From 1809548bb52979b30fa15231a1429b3621ddaeaa Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 11 Apr 2025 15:56:25 +0200 Subject: host/dwc2: cleanup transfer on device close Signed-off-by: HiFiPhile --- src/portable/synopsys/dwc2/hcd_dwc2.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/portable') diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index b13479b02..d76fdeea7 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -448,6 +448,12 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr) { hcd_endpoint_t* edpt = &_hcd_data.edpt[i]; if (edpt->hcchar_bm.enable && edpt->hcchar_bm.dev_addr == dev_addr) { tu_memclr(edpt, sizeof(hcd_endpoint_t)); + for (uint8_t j = 0; j < (uint8_t) DWC2_CHANNEL_COUNT_MAX; j++) { + hcd_xfer_t* xfer = &_hcd_data.xfer[j]; + if (xfer->allocated && xfer->ep_id == i) { + tu_memclr(xfer, sizeof(hcd_xfer_t)); + } + } } } } -- cgit v1.3.1 From 90cf575656a009cf4080742909090e219b25ae0f Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 18 Apr 2025 17:39:45 +0200 Subject: Disable channel properly. Signed-off-by: HiFiPhile --- src/portable/synopsys/dwc2/hcd_dwc2.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'src/portable') diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index d76fdeea7..50aa837d2 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -443,15 +443,17 @@ tusb_speed_t hcd_port_speed_get(uint8_t rhport) { // HCD closes all opened endpoints belong to this device void hcd_device_close(uint8_t rhport, uint8_t dev_addr) { - (void) rhport; + dwc2_regs_t* dwc2 = DWC2_REG(rhport); for (uint8_t i = 0; i < (uint8_t) CFG_TUH_DWC2_ENDPOINT_MAX; i++) { hcd_endpoint_t* edpt = &_hcd_data.edpt[i]; if (edpt->hcchar_bm.enable && edpt->hcchar_bm.dev_addr == dev_addr) { tu_memclr(edpt, sizeof(hcd_endpoint_t)); - for (uint8_t j = 0; j < (uint8_t) DWC2_CHANNEL_COUNT_MAX; j++) { - hcd_xfer_t* xfer = &_hcd_data.xfer[j]; + for (uint8_t ch_id = 0; ch_id < (uint8_t) DWC2_CHANNEL_COUNT_MAX; ch_id++) { + hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; if (xfer->allocated && xfer->ep_id == i) { - tu_memclr(xfer, sizeof(hcd_xfer_t)); + dwc2_channel_t* channel = &dwc2->channel[ch_id]; + xfer->err_count = HCD_XFER_ERROR_MAX; + channel_disable(dwc2, channel); } } } -- cgit v1.3.1 From 376c1063b7184984ae44ff5a3d225130bc470d14 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Thu, 15 May 2025 21:34:53 +0200 Subject: Fix transfer failed event still queued Signed-off-by: HiFiPhile --- src/portable/synopsys/dwc2/hcd_dwc2.c | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) (limited to 'src/portable') diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index 50aa837d2..8821361e8 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -98,6 +98,7 @@ typedef struct { uint8_t period_split_nyet_count : 3; uint8_t halted_nyet : 1; uint8_t halted_sof_schedule : 1; + uint8_t closing : 1; // closing channel }; uint8_t result; @@ -452,8 +453,12 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr) { hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; if (xfer->allocated && xfer->ep_id == i) { dwc2_channel_t* channel = &dwc2->channel[ch_id]; - xfer->err_count = HCD_XFER_ERROR_MAX; - channel_disable(dwc2, channel); + dwc2_channel_split_t hcsplt = {.value = channel->hcsplt}; + xfer->closing = 1; + // Channel disable must not be programmed for non-split periodic channels + if (!channel_is_periodic(channel->hcchar) || hcsplt.split_en) { + channel_disable(dwc2, channel); + } } } } @@ -915,6 +920,11 @@ static bool handle_channel_in_slave(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t h } else if (xfer->err_count == HCD_XFER_ERROR_MAX) { xfer->result = XFER_RESULT_FAILED; is_done = true; + } else if (xfer->closing) { + // channel is closing, de-allocate channel + channel_dealloc(dwc2, ch_id); + // don't send event + is_done = false; } else { // got here due to NAK or NYET channel_xfer_in_retry(dwc2, ch_id, hcint); @@ -969,6 +979,11 @@ static bool handle_channel_out_slave(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t } else if (xfer->err_count == HCD_XFER_ERROR_MAX) { xfer->result = XFER_RESULT_FAILED; is_done = true; + } else if (xfer->closing) { + // channel is closing, de-allocate channel + channel_dealloc(dwc2, ch_id); + // don't send event + is_done = false; } else { // Got here due to NAK or NYET TU_ASSERT(channel_xfer_start(dwc2, ch_id)); @@ -1068,6 +1083,13 @@ static bool handle_channel_in_dma(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hci // retry start-split in next binterval channel_xfer_in_retry(dwc2, ch_id, hcint); } + + if (xfer->closing) { + // channel is closing, de-allocate channel + channel_dealloc(dwc2, ch_id); + // don't send event + is_done = false; + } } return is_done; @@ -1125,6 +1147,13 @@ static bool handle_channel_out_dma(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hc channel->hcchar |= HCCHAR_CHENA; } } + + if (xfer->closing) { + // channel is closing, de-allocate channel + channel_dealloc(dwc2, ch_id); + // don't send event + is_done = false; + } } else if (hcint & HCINT_ACK) { xfer->err_count = 0; channel->hcintmsk &= ~HCINT_ACK; -- cgit v1.3.1 From 2d979ee4a9e7de6b956c373842e8c81c2e6382b4 Mon Sep 17 00:00:00 2001 From: R Date: Fri, 12 Sep 2025 22:16:15 +0100 Subject: ohci: Add functions used for explicit cache operations --- src/portable/ohci/ohci.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src/portable') diff --git a/src/portable/ohci/ohci.c b/src/portable/ohci/ohci.c index 81091c9a7..9450b8d0e 100644 --- a/src/portable/ohci/ohci.c +++ b/src/portable/ohci/ohci.c @@ -143,6 +143,15 @@ enum { PID_FROM_TD = 0, }; +//--------------------------------------------------------------------+ +// Support for explicit D-cache operations +//--------------------------------------------------------------------+ +TU_ATTR_WEAK bool hcd_dcache_clean(void const* addr, uint32_t data_size) { (void) addr; (void) data_size; return true; } +TU_ATTR_WEAK bool hcd_dcache_invalidate(void const* addr, uint32_t data_size) { (void) addr; (void) data_size; return true; } +#ifndef hcd_dcache_uncached +#define hcd_dcache_uncached(x) (x) +#endif + //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ -- cgit v1.3.1 From 839149c5c0b667a8080de39c85cdbdd291be4dc5 Mon Sep 17 00:00:00 2001 From: R Date: Fri, 12 Sep 2025 22:16:46 +0100 Subject: ohci: Align TDs to cache lines --- src/portable/ohci/ohci.h | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) (limited to 'src/portable') diff --git a/src/portable/ohci/ohci.h b/src/portable/ohci/ohci.h index 94bad5df7..12c411764 100644 --- a/src/portable/ohci/ohci.h +++ b/src/portable/ohci/ohci.h @@ -61,6 +61,31 @@ typedef struct { TU_VERIFY_STATIC( sizeof(ohci_hcca_t) == 256, "size is not correct" ); +// An OHCI host controller is controlled using data structures placed in memory (RAM). +// It needs to both read and write these data structures (as defined by the OHCI specification), +// and this can be mentally conceptualized similar to two software threads running on +// two different CPUs. In order to prevent a _data race_ where data gets corrupted, +// the CPU and the OHCI host controller need to agree on how the memory should be accessed. +// In this driver, we do this by transferring logical ownership of transfer descriptors (TDs) +// between the CPU and the OHCI host controller. Only the device which holds the logical ownership +// is allowed to read or write the TD. This ownership is not visible anywhere in the code, +// but it instead must be inferred based on the logical state of the transfer. +// +// If dcache-supporting mode is enabled, we need to do additional manual cache operations +// in order to correctly transfer this logical ownership and prevent data corruption. +// In order to do this, we also choose to align each OHCI TD so that it doesn't +// share CPU cache lines with other TDs. This is because manual cache operations +// can only be performed on cache line granularity. In other words, one cache line is +// the _smallest_ amount that can be read/written at a time. If there were to be multiple TDs +// in the same cache line, they would be required to always have the same logical ownership. +// This ends up being impossible to guarantee, so we choose a design which avoids the situation entirely. +// +// TDs have a minimum alignment requirement according to the OHCI specification. This is 16 bytes for +// a general TD but 32 bytes for an isochronous TD. It happens that typical CPU cache line sizes are usually +// a power of 2 at least 32. In order to simplify code later in this file, we assume this +// as an additional requirement. +TU_VERIFY_STATIC( (CFG_TUH_MEM_DCACHE_ENABLE ? CFG_TUH_MEM_DCACHE_LINE_SIZE : 0) % 32 == 0, "cache line not multiple of 32" ); + // common link item for gtd and itd for list travel // use as pointer only typedef struct TU_ATTR_ALIGNED(16) { @@ -69,7 +94,7 @@ typedef struct TU_ATTR_ALIGNED(16) { uint32_t reserved2; }ohci_td_item_t; -typedef struct TU_ATTR_ALIGNED(16) +typedef struct TU_ATTR_ALIGNED(CFG_TUH_MEM_DCACHE_ENABLE ? CFG_TUH_MEM_DCACHE_LINE_SIZE : 16) { // Word 0 uint32_t used : 1; @@ -92,7 +117,7 @@ typedef struct TU_ATTR_ALIGNED(16) uint8_t* buffer_end; } ohci_gtd_t; -TU_VERIFY_STATIC( sizeof(ohci_gtd_t) == 16, "size is not correct" ); +TU_VERIFY_STATIC( sizeof(ohci_gtd_t) == CFG_TUH_MEM_DCACHE_ENABLE ? CFG_TUH_MEM_DCACHE_LINE_SIZE : 16, "size is not correct" ); typedef struct TU_ATTR_ALIGNED(16) { @@ -129,7 +154,7 @@ typedef struct TU_ATTR_ALIGNED(16) TU_VERIFY_STATIC( sizeof(ohci_ed_t) == 16, "size is not correct" ); -typedef struct TU_ATTR_ALIGNED(32) +typedef struct TU_ATTR_ALIGNED(CFG_TUH_MEM_DCACHE_ENABLE ? CFG_TUH_MEM_DCACHE_LINE_SIZE : 32) { /*---------- Word 1 ----------*/ uint32_t starting_frame : 16; @@ -152,7 +177,7 @@ typedef struct TU_ATTR_ALIGNED(32) volatile uint16_t offset_packetstatus[8]; } ochi_itd_t; -TU_VERIFY_STATIC( sizeof(ochi_itd_t) == 32, "size is not correct" ); +TU_VERIFY_STATIC( sizeof(ochi_itd_t) == CFG_TUH_MEM_DCACHE_ENABLE ? CFG_TUH_MEM_DCACHE_LINE_SIZE : 32, "size is not correct" ); typedef struct { uint16_t expected_bytes; // up to 8192 bytes so max is 13 bits -- cgit v1.3.1 From 330d9d7f426b3227149e76fc7dd167e2cd3745ad Mon Sep 17 00:00:00 2001 From: R Date: Fri, 12 Sep 2025 23:33:47 +0100 Subject: ohci: Re-implement TD allocation, matching the specification The initial motivation for doing this is to remove the `used` flag in the TD. If we use this flag, we end up being required to read from TDs that the OHCI controller might be modifying (i.e. the OHCI controller logically owns the TD). This happens when we try to allocate a new, empty TD while the OHCI host controller is working on a transfer. Move the `used` flag to `gtd_extra_data_t`. This data is only used by the CPU, and the OHCI controller never accesses it. The existing allocation method for TDs does *not* put an empty TD onto each ED (i.e it does *not* do what is shown in Figure 5-6 of the OHCI specification). Instead, the NextTD field of the last TD is set to 0. The TailP field of the ED is also set to 0. This works in many cases. However, this implementation means that the CPU may end up trying to write to the NextTD field of an in-progress transfer while the OHCI host controller logically owns it. Change the implementation to use an empty TD, as suggested by the specification, for endpoints other than EP0. This avoids the above issue. It is not necessary to make the change for EP0 because only at most one TD can ever be pending at a time. The above change should also remove the need for the stall workaround. In the future, we want to modify the code to access EDs through an uncached mapping. Because uncached mappings are slow, we want to access EDs as little as possible. Currently, when a TD completes, we access an ED in order to figure out the device address and endpoint number of the TD which was completed. Because moving `used` to `gtd_extra_data_t` necessitates expanding it, we have enough room to also store the device address and endpoint number of the TD. This patch does so. With the above two changes, we no longer need to access an ED when a TD completes. Also remove the `index` field from TDs as it is no longer necessary. --- src/portable/ohci/ohci.c | 82 ++++++++++++++++++------------------------------ src/portable/ohci/ohci.h | 8 +++-- 2 files changed, 35 insertions(+), 55 deletions(-) (limited to 'src/portable') diff --git a/src/portable/ohci/ohci.c b/src/portable/ohci/ohci.c index 9450b8d0e..b297173bc 100644 --- a/src/portable/ohci/ohci.c +++ b/src/portable/ohci/ohci.c @@ -355,7 +355,6 @@ static void ed_init(ohci_ed_t *p_ed, uint8_t dev_addr, uint16_t ep_size, uint8_t static void gtd_init(ohci_gtd_t *p_td, uint8_t *data_ptr, uint16_t total_bytes) { tu_memclr(p_td, sizeof(ohci_gtd_t)); - p_td->used = 1; gtd_get_extra_data(p_td)->expected_bytes = total_bytes; p_td->buffer_rounding = 1; // less than queued length is not a error @@ -439,25 +438,15 @@ static ohci_gtd_t * gtd_find_free(void) { for(uint8_t i=0; i < GTD_MAX; i++) { - if ( !ohci_data.gtd_pool[i].used ) return &ohci_data.gtd_pool[i]; + if ( !ohci_data.gtd_extra[i].used ) { + ohci_data.gtd_extra[i].used = 1; + return &ohci_data.gtd_pool[i]; + } } return NULL; } -static void td_insert_to_ed(ohci_ed_t* p_ed, ohci_gtd_t * p_gtd) -{ - // tail is always NULL - if ( tu_align16(p_ed->td_head.address) == 0 ) - { // TD queue is empty --> head = TD - p_ed->td_head.address |= (uint32_t) _phys_addr(p_gtd); - } - else - { // TODO currently only support queue up to 2 TD each endpoint at a time - ((ohci_gtd_t*) tu_align16((uint32_t)_virt_addr((void *)p_ed->td_head.address)))->next = (uint32_t) _phys_addr(p_gtd); - } -} - //--------------------------------------------------------------------+ // Endpoint API //--------------------------------------------------------------------+ @@ -490,6 +479,16 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const return true; } + if ( tu_edpt_number(ep_desc->bEndpointAddress) != 0 ) { + // Get an empty TD and use it as the end-of-list marker. + // This marker TD will be used when a transfer is made on this EP + // (and a new, empty TD will be allocated for the next-next transfer). + ohci_gtd_t* gtd = gtd_find_free(); + TU_ASSERT(gtd); + hcd_dcache_uncached(p_ed->td_head).address = (uint32_t)_phys_addr(gtd); + hcd_dcache_uncached(p_ed->td_tail) = (uint32_t)_phys_addr(gtd); + } + ed_list_insert( p_ed_head[ep_desc->bmAttributes.xfer], p_ed ); return true; @@ -508,7 +507,8 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet ohci_gtd_t *qtd = &ohci_data.control[dev_addr].gtd; gtd_init(qtd, (uint8_t*)(uintptr_t) setup_packet, 8); - qtd->index = dev_addr; + gtd_get_extra_data(qtd)->dev_addr = dev_addr; + gtd_get_extra_data(qtd)->ep_addr = tu_edpt_addr(0, TUSB_DIR_OUT); qtd->pid = PID_SETUP; qtd->data_toggle = GTD_DT_DATA0; qtd->delay_interrupt = OHCI_INT_ON_COMPLETE_YES; @@ -534,8 +534,9 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * ohci_gtd_t* gtd = &ohci_data.control[dev_addr].gtd; gtd_init(gtd, buffer, buflen); + gtd_get_extra_data(gtd)->dev_addr = dev_addr; + gtd_get_extra_data(gtd)->ep_addr = ep_addr; - gtd->index = dev_addr; gtd->pid = dir ? PID_IN : PID_OUT; gtd->data_toggle = GTD_DT_DATA1; // Both Data and Ack stage start with DATA1 gtd->delay_interrupt = OHCI_INT_ON_COMPLETE_YES; @@ -546,15 +547,20 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * }else { ohci_ed_t * ed = ed_from_addr(dev_addr, ep_addr); - ohci_gtd_t* gtd = gtd_find_free(); - - TU_ASSERT(gtd); + ohci_gtd_t *gtd = (ohci_gtd_t *)_virt_addr((void *)hcd_dcache_uncached(ed->td_tail)); gtd_init(gtd, buffer, buflen); - gtd->index = ed-ohci_data.ed_pool; + gtd_get_extra_data(gtd)->dev_addr = dev_addr; + gtd_get_extra_data(gtd)->ep_addr = ep_addr; gtd->delay_interrupt = OHCI_INT_ON_COMPLETE_YES; - td_insert_to_ed(ed, gtd); + // Insert a new, empty TD at the tail, to be used by the next transfer + ohci_gtd_t* new_gtd = gtd_find_free(); + TU_ASSERT(new_gtd); + + gtd->next = (uint32_t)_phys_addr(new_gtd); + + hcd_dcache_uncached(ed->td_tail) = (uint32_t)_phys_addr(new_gtd); tusb_xfer_type_t xfer_type = ed_get_xfer_type( ed_from_addr(dev_addr, ep_addr) ); if (TUSB_XFER_BULK == xfer_type) OHCI_REG->command_status_bit.bulk_list_filled = 1; @@ -614,17 +620,6 @@ static inline bool gtd_is_control(ohci_gtd_t const * const p_qtd) return ((uint32_t) p_qtd) < ((uint32_t) ohci_data.gtd_pool); // check ohci_data_t for memory layout } -static inline ohci_ed_t* gtd_get_ed(ohci_gtd_t const * const p_qtd) -{ - if ( gtd_is_control(p_qtd) ) - { - return &ohci_data.control[p_qtd->index].ed; - }else - { - return &ohci_data.ed_pool[p_qtd->index]; - } -} - static gtd_extra_data_t *gtd_get_extra_data(ohci_gtd_t const * const gtd) { if ( gtd_is_control(gtd) ) { uint8_t idx = ((uintptr_t)gtd - (uintptr_t)&ohci_data.control->gtd) / sizeof(ohci_data.control[0]); @@ -661,29 +656,12 @@ static void done_queue_isr(uint8_t hostid) xfer_result_t const event = (qtd->condition_code == OHCI_CCODE_NO_ERROR) ? XFER_RESULT_SUCCESS : (qtd->condition_code == OHCI_CCODE_STALL) ? XFER_RESULT_STALLED : XFER_RESULT_FAILED; - qtd->used = 0; // free TD + gtd_get_extra_data(qtd)->used = 0; // free TD if ( (qtd->delay_interrupt == OHCI_INT_ON_COMPLETE_YES) || (event != XFER_RESULT_SUCCESS) ) { - ohci_ed_t * const ed = gtd_get_ed(qtd); uint32_t const xferred_bytes = gtd_get_extra_data(qtd)->expected_bytes - gtd_xfer_byte_left((uint32_t) qtd->buffer_end, (uint32_t) qtd->current_buffer_pointer); - // NOTE Assuming the current list is BULK and there is no other EDs in the list has queued TDs. - // When there is a error resulting this ED is halted, and this EP still has other queued TD - // --> the Bulk list only has this halted EP queueing TDs (remaining) - // --> Bulk list will be considered as not empty by HC !!! while there is no attempt transaction on this list - // --> HC will not process Control list (due to service ratio when Bulk list not empty) - // To walk-around this, the halted ED will have TailP = HeadP (empty list condition), when clearing halt - // the TailP must be set back to NULL for processing remaining TDs - if (event != XFER_RESULT_SUCCESS) - { - ed->td_tail &= 0x0Ful; - ed->td_tail |= tu_align16(ed->td_head.address); // mark halted EP as empty queue - if ( event == XFER_RESULT_STALLED ) ed->is_stalled = 1; - } - - uint8_t dir = (ed->ep_number == 0) ? (qtd->pid == PID_IN) : (ed->pid == PID_IN); - - hcd_event_xfer_complete(ed->dev_addr, tu_edpt_addr(ed->ep_number, dir), xferred_bytes, event, true); + hcd_event_xfer_complete(gtd_get_extra_data(qtd)->dev_addr, gtd_get_extra_data(qtd)->ep_addr, xferred_bytes, event, true); } td_head = (ohci_td_item_t*) _virt_addr((void *)td_head->next); diff --git a/src/portable/ohci/ohci.h b/src/portable/ohci/ohci.h index 12c411764..8483686fa 100644 --- a/src/portable/ohci/ohci.h +++ b/src/portable/ohci/ohci.h @@ -97,9 +97,7 @@ typedef struct TU_ATTR_ALIGNED(16) { typedef struct TU_ATTR_ALIGNED(CFG_TUH_MEM_DCACHE_ENABLE ? CFG_TUH_MEM_DCACHE_LINE_SIZE : 16) { // Word 0 - uint32_t used : 1; - uint32_t index : 8; // endpoint index the gtd belongs to, or device address in case of control xfer - uint32_t : 9; // can be used + uint32_t : 18; // can be used uint32_t buffer_rounding : 1; uint32_t pid : 2; uint32_t delay_interrupt : 3; @@ -181,7 +179,11 @@ TU_VERIFY_STATIC( sizeof(ochi_itd_t) == CFG_TUH_MEM_DCACHE_ENABLE ? CFG_TUH_MEM_ typedef struct { uint16_t expected_bytes; // up to 8192 bytes so max is 13 bits + uint8_t dev_addr : 7; + uint8_t used : 1; + uint8_t ep_addr; } gtd_extra_data_t; +TU_VERIFY_STATIC( sizeof(gtd_extra_data_t) == 4, "size is not correct" ); // structure with member alignment required from large to small typedef struct TU_ATTR_ALIGNED(256) { -- cgit v1.3.1 From 915d21241c265692a5bfc1cb1d96af4521eca536 Mon Sep 17 00:00:00 2001 From: R Date: Sat, 13 Sep 2025 00:18:52 +0100 Subject: ohci: Perform explicit cache operations on TDs, buffers --- src/portable/ohci/ohci.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'src/portable') diff --git a/src/portable/ohci/ohci.c b/src/portable/ohci/ohci.c index b297173bc..c5b1d78e6 100644 --- a/src/portable/ohci/ohci.c +++ b/src/portable/ohci/ohci.c @@ -225,6 +225,8 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { #endif } + hcd_dcache_clean(&ohci_data, sizeof(ohci_data)); + // reset controller OHCI_REG->command_status_bit.controller_reset = 1; while( OHCI_REG->command_status_bit.controller_reset ) {} // should not take longer than 10 us @@ -506,12 +508,15 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet ohci_ed_t* ed = &ohci_data.control[dev_addr].ed; ohci_gtd_t *qtd = &ohci_data.control[dev_addr].gtd; + hcd_dcache_clean(setup_packet, 8); + gtd_init(qtd, (uint8_t*)(uintptr_t) setup_packet, 8); gtd_get_extra_data(qtd)->dev_addr = dev_addr; gtd_get_extra_data(qtd)->ep_addr = tu_edpt_addr(0, TUSB_DIR_OUT); qtd->pid = PID_SETUP; qtd->data_toggle = GTD_DT_DATA0; qtd->delay_interrupt = OHCI_INT_ON_COMPLETE_YES; + hcd_dcache_clean(qtd, sizeof(ohci_gtd_t)); //------------- Attach TDs list to Control Endpoint -------------// ed->td_head.address = (uint32_t) _phys_addr(qtd); @@ -528,6 +533,13 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); + // IN transfer: invalidate buffer, OUT transfer: clean buffer + if (dir) { + hcd_dcache_invalidate(buffer, buflen); + } else { + hcd_dcache_clean(buffer, buflen); + } + if ( epnum == 0 ) { ohci_ed_t* ed = &ohci_data.control[dev_addr].ed; @@ -540,6 +552,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * gtd->pid = dir ? PID_IN : PID_OUT; gtd->data_toggle = GTD_DT_DATA1; // Both Data and Ack stage start with DATA1 gtd->delay_interrupt = OHCI_INT_ON_COMPLETE_YES; + hcd_dcache_clean(gtd, sizeof(ohci_gtd_t)); ed->td_head.address = (uint32_t) _phys_addr(gtd); @@ -559,6 +572,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * TU_ASSERT(new_gtd); gtd->next = (uint32_t)_phys_addr(new_gtd); + hcd_dcache_clean(gtd, sizeof(ohci_gtd_t)); hcd_dcache_uncached(ed->td_tail) = (uint32_t)_phys_addr(new_gtd); @@ -603,6 +617,12 @@ static ohci_td_item_t* list_reverse(ohci_td_item_t* td_head) while(td_head != NULL) { td_head = _virt_addr(td_head); + // FIXME: This is not the correct object size. + // However, because we have hardcoded the assumption that + // a cache line is at least 32 bytes (in ohci.h), and + // because both types of TD structs are <= 32 bytes, this + // nonetheless still works without error. + hcd_dcache_invalidate(td_head, sizeof(ohci_td_item_t)); uint32_t next = td_head->next; // make current's item become reverse's first item -- cgit v1.3.1 From b9378eb8e79691907aae40b3fc26cb57d4ffaeb4 Mon Sep 17 00:00:00 2001 From: R Date: Sat, 13 Sep 2025 00:41:15 +0100 Subject: ohci: Use uncached alias to access EDs This code is written very carefully to always use an uncached view of memory to read/write EDs. An uncached view must *always* be used, or else cache behavior can corrupt the ED. As part of this change, combine access into as few word-sized accesses as possible. This makes the code perform better. Doing this involves giving type names to the bitfields that make up the ED's data words. --- src/portable/ohci/ohci.c | 95 ++++++++++++++++++++++++++---------------------- src/portable/ohci/ohci.h | 48 ++++++++++++++---------- 2 files changed, 79 insertions(+), 64 deletions(-) (limited to 'src/portable') diff --git a/src/portable/ohci/ohci.c b/src/portable/ohci/ohci.c index c5b1d78e6..a9246e1cd 100644 --- a/src/portable/ohci/ohci.c +++ b/src/portable/ohci/ohci.c @@ -199,9 +199,9 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { ohci_data.hcca.interrupt_table[i] = (uint32_t) _phys_addr(&ohci_data.period_head_ed); } - ohci_data.control[0].ed.skip = 1; - ohci_data.bulk_head_ed.skip = 1; - ohci_data.period_head_ed.skip = 1; + ohci_data.control[0].ed.w0.skip = 1; + ohci_data.bulk_head_ed.w0.skip = 1; + ohci_data.period_head_ed.w0.skip = 1; //If OHCI hardware is in SMM mode, gain ownership (Ref OHCI spec 5.1.1.3.3) if (OHCI_REG->control_bit.interrupt_routing == 1) @@ -300,7 +300,7 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr) // addr0 serves as static head --> only set skip bit if ( dev_addr == 0 ) { - ohci_data.control[0].ed.skip = 1; + hcd_dcache_uncached(ohci_data.control[0].ed.w0).skip = 1; }else { // remove control @@ -323,11 +323,11 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr) //--------------------------------------------------------------------+ // List Helper //--------------------------------------------------------------------+ -static inline tusb_xfer_type_t ed_get_xfer_type(ohci_ed_t const * const p_ed) +static inline tusb_xfer_type_t ed_get_xfer_type(ohci_ed_word0 w0) { - return (p_ed->ep_number == 0 ) ? TUSB_XFER_CONTROL : - (p_ed->is_iso ) ? TUSB_XFER_ISOCHRONOUS : - (p_ed->is_interrupt_xfer) ? TUSB_XFER_INTERRUPT : TUSB_XFER_BULK; + return (w0.ep_number == 0 ) ? TUSB_XFER_CONTROL : + (w0.is_iso ) ? TUSB_XFER_ISOCHRONOUS : + (w0.is_interrupt_xfer) ? TUSB_XFER_INTERRUPT : TUSB_XFER_BULK; } static void ed_init(ohci_ed_t *p_ed, uint8_t dev_addr, uint16_t ep_size, uint8_t ep_addr, uint8_t xfer_type, uint8_t interval) @@ -337,21 +337,25 @@ static void ed_init(ohci_ed_t *p_ed, uint8_t dev_addr, uint16_t ep_size, uint8_t // address 0 is used as async head, which always on the list --> cannot be cleared if (dev_addr != 0) { - tu_memclr(p_ed, sizeof(ohci_ed_t)); + hcd_dcache_uncached(p_ed->td_tail) = 0; + hcd_dcache_uncached(p_ed->td_head).address = 0; + hcd_dcache_uncached(p_ed->next) = 0; } tuh_bus_info_t bus_info; tuh_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 = bus_info.speed; - p_ed->is_iso = (xfer_type == TUSB_XFER_ISOCHRONOUS) ? 1 : 0; - p_ed->max_packet_size = ep_size; - - p_ed->used = 1; - p_ed->is_interrupt_xfer = (xfer_type == TUSB_XFER_INTERRUPT ? 1 : 0); + ohci_ed_word0 w0 = {.u = 0}; + w0.dev_addr = dev_addr; + w0.ep_number = ep_addr & 0x0F; + w0.pid = (xfer_type == TUSB_XFER_CONTROL) ? PID_FROM_TD : (tu_edpt_dir(ep_addr) ? PID_IN : PID_OUT); + w0.speed = bus_info.speed; + w0.is_iso = (xfer_type == TUSB_XFER_ISOCHRONOUS) ? 1 : 0; + w0.max_packet_size = ep_size; + + w0.used = 1; + w0.is_interrupt_xfer = (xfer_type == TUSB_XFER_INTERRUPT ? 1 : 0); + hcd_dcache_uncached(p_ed->w0) = w0; } static void gtd_init(ohci_gtd_t *p_td, uint8_t *data_ptr, uint16_t total_bytes) { @@ -381,8 +385,9 @@ static ohci_ed_t * ed_from_addr(uint8_t dev_addr, uint8_t ep_addr) for(uint32_t i=0; inext = p_pre->next; - p_pre->next = (uint32_t) _phys_addr(p_ed); + hcd_dcache_uncached(p_ed->next) = hcd_dcache_uncached(p_pre->next); + hcd_dcache_uncached(p_pre->next) = (uint32_t) _phys_addr(p_ed); } static void ed_list_remove_by_addr(ohci_ed_t * p_head, uint8_t dev_addr) { ohci_ed_t* p_prev = p_head; - while( p_prev->next ) + uint32_t ed_pa; + while( (ed_pa = hcd_dcache_uncached(p_prev->next)) ) { - ohci_ed_t* ed = (ohci_ed_t*) _virt_addr((void *)p_prev->next); + ohci_ed_t* ed = (ohci_ed_t*) _virt_addr((void *)ed_pa); - if (ed->dev_addr == dev_addr) + if (hcd_dcache_uncached(ed->w0).dev_addr == dev_addr) { // Prevent Host Controller from processing this ED while we remove it - ed->skip = 1; + hcd_dcache_uncached(ed->w0).skip = 1; // unlink ed, will also move up p_prev - p_prev->next = ed->next; + hcd_dcache_uncached(p_prev->next) = hcd_dcache_uncached(ed->next); // point the removed ED's next pointer to list head to make sure HC can always safely move away from this ED - ed->next = (uint32_t) _phys_addr(p_head); - ed->used = 0; - ed->skip = 0; + hcd_dcache_uncached(ed->next) = (uint32_t) _phys_addr(p_head); + ohci_ed_word0 w0 = hcd_dcache_uncached(ed->w0); + w0.used = 0; + w0.skip = 0; + hcd_dcache_uncached(ed->w0) = w0; }else { - p_prev = (ohci_ed_t*) _virt_addr((void *)p_prev->next); + p_prev = (ohci_ed_t*) _virt_addr((void *)ed_pa); } } } @@ -477,7 +485,7 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const // control of dev0 is used as static async head if ( dev_addr == 0 ) { - p_ed->skip = 0; // only need to clear skip bit + hcd_dcache_uncached(p_ed->w0).skip = 0; // only need to clear skip bit return true; } @@ -519,7 +527,7 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet hcd_dcache_clean(qtd, sizeof(ohci_gtd_t)); //------------- Attach TDs list to Control Endpoint -------------// - ed->td_head.address = (uint32_t) _phys_addr(qtd); + hcd_dcache_uncached(ed->td_head.address) = (uint32_t) _phys_addr(qtd); OHCI_REG->command_status_bit.control_list_filled = 1; @@ -554,12 +562,13 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * gtd->delay_interrupt = OHCI_INT_ON_COMPLETE_YES; hcd_dcache_clean(gtd, sizeof(ohci_gtd_t)); - ed->td_head.address = (uint32_t) _phys_addr(gtd); + hcd_dcache_uncached(ed->td_head).address = (uint32_t) _phys_addr(gtd); OHCI_REG->command_status_bit.control_list_filled = 1; }else { ohci_ed_t * ed = ed_from_addr(dev_addr, ep_addr); + tusb_xfer_type_t xfer_type = ed_get_xfer_type( hcd_dcache_uncached(ed->w0) ); ohci_gtd_t *gtd = (ohci_gtd_t *)_virt_addr((void *)hcd_dcache_uncached(ed->td_tail)); gtd_init(gtd, buffer, buflen); @@ -576,7 +585,6 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * hcd_dcache_uncached(ed->td_tail) = (uint32_t)_phys_addr(new_gtd); - tusb_xfer_type_t xfer_type = ed_get_xfer_type( ed_from_addr(dev_addr, ep_addr) ); if (TUSB_XFER_BULK == xfer_type) OHCI_REG->command_status_bit.bulk_list_filled = 1; } @@ -595,13 +603,12 @@ bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { (void) rhport; ohci_ed_t * const p_ed = ed_from_addr(dev_addr, ep_addr); - p_ed->is_stalled = 0; - p_ed->td_tail &= 0x0Ful; // set tail pointer back to NULL - - p_ed->td_head.toggle = 0; // reset data toggle - p_ed->td_head.halted = 0; + ohci_ed_td_head td_head = hcd_dcache_uncached(p_ed->td_head); + td_head.toggle = 0; // reset data toggle + td_head.halted = 0; + hcd_dcache_uncached(p_ed->td_head) = td_head; - if ( TUSB_XFER_BULK == ed_get_xfer_type(p_ed) ) OHCI_REG->command_status_bit.bulk_list_filled = 1; + if ( TUSB_XFER_BULK == ed_get_xfer_type(hcd_dcache_uncached(p_ed->w0)) ) OHCI_REG->command_status_bit.bulk_list_filled = 1; return true; } @@ -665,8 +672,8 @@ static void done_queue_isr(uint8_t hostid) (void) hostid; // done head is written in reversed order of completion --> need to reverse the done queue first - ohci_td_item_t* td_head = list_reverse ( (ohci_td_item_t*) tu_align16(ohci_data.hcca.done_head) ); - ohci_data.hcca.done_head = 0; + ohci_td_item_t* td_head = list_reverse ( (ohci_td_item_t*) tu_align16(hcd_dcache_uncached(ohci_data.hcca).done_head) ); + hcd_dcache_uncached(ohci_data.hcca).done_head = 0; while( td_head != NULL ) { diff --git a/src/portable/ohci/ohci.h b/src/portable/ohci/ohci.h index 8483686fa..78cac664e 100644 --- a/src/portable/ohci/ohci.h +++ b/src/portable/ohci/ohci.h @@ -117,34 +117,42 @@ typedef struct TU_ATTR_ALIGNED(CFG_TUH_MEM_DCACHE_ENABLE ? CFG_TUH_MEM_DCACHE_LI TU_VERIFY_STATIC( sizeof(ohci_gtd_t) == CFG_TUH_MEM_DCACHE_ENABLE ? CFG_TUH_MEM_DCACHE_LINE_SIZE : 16, "size is not correct" ); +typedef union { + struct { + uint32_t dev_addr : 7; + uint32_t ep_number : 4; + uint32_t pid : 2; + uint32_t speed : 1; + uint32_t skip : 1; + uint32_t is_iso : 1; + uint32_t max_packet_size : 11; + // HCD: make use of 5 reserved bits + uint32_t used : 1; + uint32_t is_interrupt_xfer : 1; + uint32_t : 3; + }; + uint32_t u; +} ohci_ed_word0; + +typedef union { + uint32_t address; + struct { + uint32_t halted : 1; + uint32_t toggle : 1; + uint32_t : 30; + }; +} ohci_ed_td_head; + typedef struct TU_ATTR_ALIGNED(16) { // Word 0 - uint32_t dev_addr : 7; - uint32_t ep_number : 4; - uint32_t pid : 2; - uint32_t speed : 1; - uint32_t skip : 1; - uint32_t is_iso : 1; - uint32_t max_packet_size : 11; - // HCD: make use of 5 reserved bits - uint32_t used : 1; - uint32_t is_interrupt_xfer : 1; - uint32_t is_stalled : 1; - uint32_t : 2; + ohci_ed_word0 w0; // Word 1 uint32_t td_tail; // Word 2 - volatile union { - uint32_t address; - struct { - uint32_t halted : 1; - uint32_t toggle : 1; - uint32_t : 30; - }; - }td_head; + volatile ohci_ed_td_head td_head; // Word 3: next ED uint32_t next; -- cgit v1.3.1 From e0a589cdcae6eaf790d05712a6f2b8c0352fb5fd Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Thu, 2 Oct 2025 13:54:01 +0200 Subject: dwc2: support ISO IN transfer when bInterval > 1 dwc2 requires manually toggle Even/Odd bit manually for ISO IN transfer, that's poses a problem when bInterval > 1 mainly for audio class, as the moment the transfer is scheduled, we don't know when the host will issue IN token (bInterval vs bRefresh schenanigans). Linux driver use NAK interrupt to detect when the host is sending IN token and toggle the Even/Odd bit accordingly based on the current frame number and bInterval. However on ST's stripped down DWC2 FS controller (e.g STM32F4, STM32F7), NAK interrupt is not supported, even it's marked as always present in DWC2 databook. NAK interrupt is only supported on HS controller with external PHY. Instead I schedule all ISO IN transfer for next frame, if the transfer failed, incomplete isochronous IN transfer interrupt will be triggered and we can relaunch the transfer. Signed-off-by: HiFiPhile --- src/portable/synopsys/dwc2/dcd_dwc2.c | 41 +++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) (limited to 'src/portable') diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index f10f0bdc3..7d999e445 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -51,6 +51,7 @@ typedef struct { uint16_t total_len; uint16_t max_size; uint8_t interval; + uint8_t iso_retry; // ISO retry counter } xfer_ctl_t; // This variable is modified from ISR context, so it must be protected by critical section @@ -357,7 +358,7 @@ static void edpt_schedule_packets(uint8_t rhport, const uint8_t epnum, const uin dwc2_depctl_t depctl = {.value = dep->ctl}; depctl.clear_nak = 1; depctl.enable = 1; - if (depctl.type == DEPCTL_EPTYPE_ISOCHRONOUS && xfer->interval == 1) { + if (depctl.type == DEPCTL_EPTYPE_ISOCHRONOUS) { const dwc2_dsts_t dsts = {.value = dwc2->dsts}; const uint32_t odd_now = dsts.frame_number & 1u; if (odd_now) { @@ -597,6 +598,9 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to _dcd_data.ep0_pending[dir] = total_bytes; } + // Reset ISO retry counter to max frame interval value + xfer->iso_retry = 255; + // Schedule packets to be sent within interrupt edpt_schedule_packets(rhport, epnum, dir); ret = true; @@ -629,6 +633,9 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_t xfer->ff = ff; xfer->total_len = total_bytes; + // Reset ISO retry counter to max frame interval value + xfer->iso_retry = 255; + // Schedule packets to be sent within interrupt // TODO xfer fifo may only available for slave mode edpt_schedule_packets(rhport, epnum, dir); @@ -714,7 +721,7 @@ static void handle_bus_reset(uint8_t rhport) { dwc2->epout[0].doeptsiz |= (3 << DOEPTSIZ_STUPCNT_Pos); } - dwc2->gintmsk |= GINTMSK_OEPINT | GINTMSK_IEPINT; + dwc2->gintmsk |= GINTMSK_OEPINT | GINTMSK_IEPINT | GINTMSK_IISOIXFRM; } static void handle_enum_done(uint8_t rhport) { @@ -1100,6 +1107,36 @@ void dcd_int_handler(uint8_t rhport) { // IEPINT bit read-only, clear using DIEPINTn handle_ep_irq(rhport, TUSB_DIR_IN); } + + // Incomplete isochronous IN transfer interrupt handling. + if (gintsts & GINTSTS_IISOIXFR) { + dwc2->gintsts = GINTSTS_IISOIXFR; + // Loop over all IN endpoints + const uint8_t ep_count = dwc2_ep_count(dwc2); + for (uint8_t epnum = 0; epnum < ep_count; epnum++) { + dwc2_dep_t* epin = &dwc2->epin[epnum]; + dwc2_depctl_t depctl = {.value = epin->diepctl}; + // Find enabled ISO endpoints + if (depctl.enable && depctl.type == DEPCTL_EPTYPE_ISOCHRONOUS) { + // Disable endpoint, flush fifo and restart transfer + depctl.set_nak = 1; + epin->diepctl = depctl.value; + depctl.disable = 1; + epin->diepctl = depctl.value; + while ((epin->diepint & DIEPINT_EPDISD_Msk) == 0) {} + epin->diepint = DIEPINT_EPDISD; + dfifo_flush_tx(dwc2, epnum); + xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, TUSB_DIR_IN); + if (xfer->iso_retry) { + xfer->iso_retry--; + edpt_schedule_packets(rhport, epnum, TUSB_DIR_IN); + } else { + // too many retries, give up + dcd_event_xfer_complete(rhport, epnum | TUSB_DIR_IN_MASK, 0, XFER_RESULT_FAILED, true); + } + } + } + } } #if CFG_TUD_TEST_MODE -- cgit v1.3.1 From f272d87a3f3cce71aa2d13813a1fee94aecb9fc5 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 6 Oct 2025 10:58:58 +0700 Subject: remove dcd_esp32sx which is replaced by dwc2 --- README.rst | 2 +- src/class/audio/audio_device.c | 5 +- src/portable/espressif/esp32sx/dcd_esp32sx.c | 889 --------------------------- tools/iar_gen.py | 2 +- 4 files changed, 4 insertions(+), 894 deletions(-) delete mode 100644 src/portable/espressif/esp32sx/dcd_esp32sx.c (limited to 'src/portable') diff --git a/README.rst b/README.rst index 16de684a6..03ad3744c 100644 --- a/README.rst +++ b/README.rst @@ -122,7 +122,7 @@ Supported CPUs +--------------+-----------------------------+--------+------+-----------+------------------------+-------------------+ | Dialog | DA1469x | ✔ | ✖ | ✖ | da146xx | | +--------------+-----------------------------+--------+------+-----------+------------------------+-------------------+ -| Espressif | S2, S3 | ✔ | ✔ | ✖ | dwc2 or esp32sx | | +| Espressif | S2, S3 | ✔ | ✔ | ✖ | dwc2 | | | ESP32 +-----------------------------+--------+------+-----------+------------------------+-------------------+ | | P4 | ✔ | ✔ | ✔ | dwc2 | | | +-----------------------------+--------+------+-----------+------------------------+-------------------+ diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 701411401..7df177773 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -79,10 +79,9 @@ // 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 -// Only STM32 and dcd_transdimension use non-linear buffer for now -// dwc2 except esp32sx (since it may use dcd_esp32sx) +// Only STM32 and ChipIdea HS use non-linear buffer for now // Ring buffer is incompatible with dcache, since neither address nor size is aligned to cache line -#if (defined(TUP_USBIP_DWC2) && !TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3)) || \ +#if defined(TUP_USBIP_DWC2) || \ defined(TUP_USBIP_FSDEV) || \ CFG_TUSB_MCU == OPT_MCU_RX63X || \ CFG_TUSB_MCU == OPT_MCU_RX65X || \ diff --git a/src/portable/espressif/esp32sx/dcd_esp32sx.c b/src/portable/espressif/esp32sx/dcd_esp32sx.c deleted file mode 100644 index 1b6aae026..000000000 --- a/src/portable/espressif/esp32sx/dcd_esp32sx.c +++ /dev/null @@ -1,889 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2018 Scott Shawcroft, 2019 William D. Jones for Adafruit Industries - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * Additions Copyright (c) 2020, Espressif Systems (Shanghai) Co. Ltd. - * - * 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_TUSB_MCU == OPT_MCU_ESP32S2) || (CFG_TUSB_MCU == OPT_MCU_ESP32S3)) && CFG_TUD_ENABLED) - -// Espressif -#include "xtensa/xtensa_api.h" - -#include "esp_intr_alloc.h" -#include "esp_log.h" -#include "soc/dport_reg.h" -#include "soc/gpio_sig_map.h" -#include "soc/usb_periph.h" -#include "soc/usb_reg.h" -#include "soc/usb_struct.h" -#include "soc/periph_defs.h" // for interrupt source - -#include "device/dcd.h" - -#ifndef USB_OUT_EP_NUM -#define USB_OUT_EP_NUM ((int) (sizeof(USB0.out_ep_reg) / sizeof(USB0.out_ep_reg[0]))) -#endif - -#ifndef USB_IN_EP_NUM -#define USB_IN_EP_NUM ((int) (sizeof(USB0.in_ep_reg) / sizeof(USB0.in_ep_reg[0]))) -#endif - -// Max number of bi-directional endpoints including EP0 -// Note: ESP32S2 specs say there are only up to 5 IN active endpoints include EP0 -// We should probably prohibit enabling Endpoint IN > 4 (not done yet) -#define EP_MAX USB_OUT_EP_NUM - -// FIFO size in bytes -#define EP_FIFO_SIZE 1024 - -// Max number of IN EP FIFOs -#define EP_FIFO_NUM 5 - -typedef struct { - uint8_t *buffer; - // tu_fifo_t * ff; // TODO support dcd_edpt_xfer_fifo API - uint16_t total_len; - uint16_t queued_len; - uint16_t max_size; - bool short_packet; - uint8_t interval; -} xfer_ctl_t; - -static const char *TAG = "TUSB:DCD"; -static intr_handle_t usb_ih; - - -static uint32_t _setup_packet[2]; - -#define XFER_CTL_BASE(_ep, _dir) &xfer_status[_ep][_dir] -static xfer_ctl_t xfer_status[EP_MAX][2]; - -// Keep count of how many FIFOs are in use -static uint8_t _allocated_fifos = 1; //FIFO0 is always in use - -// Will either return an unused FIFO number, or 0 if all are used. -static uint8_t get_free_fifo(void) -{ - if (_allocated_fifos < EP_FIFO_NUM) return _allocated_fifos++; - return 0; -} - -// Setup the control endpoint 0. -static void bus_reset(void) -{ - for (int ep_num = 0; ep_num < USB_OUT_EP_NUM; ep_num++) { - USB0.out_ep_reg[ep_num].doepctl |= USB_DO_SNAK0_M; // DOEPCTL0_SNAK - } - - // clear device address - USB0.dcfg &= ~USB_DEVADDR_M; - - USB0.daintmsk = USB_OUTEPMSK0_M | USB_INEPMSK0_M; - USB0.doepmsk = USB_SETUPMSK_M | USB_XFERCOMPLMSK; - USB0.diepmsk = USB_TIMEOUTMSK_M | USB_DI_XFERCOMPLMSK_M /*| USB_INTKNTXFEMPMSK_M*/; - - // "USB Data FIFOs" section in reference manual - // Peripheral FIFO architecture - // - // --------------- 320 or 1024 ( 1280 or 4096 bytes ) - // | IN FIFO MAX | - // --------------- - // | ... | - // --------------- y + x + 16 + GRXFSIZ - // | IN FIFO 2 | - // --------------- x + 16 + GRXFSIZ - // | IN FIFO 1 | - // --------------- 16 + GRXFSIZ - // | IN FIFO 0 | - // --------------- GRXFSIZ - // | OUT FIFO | - // | ( Shared ) | - // --------------- 0 - // - // According to "FIFO RAM allocation" section in RM, FIFO RAM are allocated as follows (each word 32-bits): - // - Each EP IN needs at least max packet size, 16 words is sufficient for EP0 IN - // - // - All EP OUT shared a unique OUT FIFO which uses - // * 10 locations in hardware for setup packets + setup control words (up to 3 setup packets). - // * 2 locations for OUT endpoint control words. - // * 16 for largest packet size of 64 bytes. ( TODO Highspeed is 512 bytes) - // * 1 location for global NAK (not required/used here). - // * It is recommended to allocate 2 times the largest packet size, therefore - // Recommended value = 10 + 1 + 2 x (16+2) = 47 --> Let's make it 52 - USB0.grstctl |= 0x10 << USB_TXFNUM_S; // fifo 0x10, - USB0.grstctl |= USB_TXFFLSH_M; // Flush fifo - USB0.grxfsiz = 52; - - // Control IN uses FIFO 0 with 64 bytes ( 16 32-bit word ) - USB0.gnptxfsiz = (16 << USB_NPTXFDEP_S) | (USB0.grxfsiz & 0x0000ffffUL); - - // Ready to receive SETUP packet - USB0.out_ep_reg[0].doeptsiz |= USB_SUPCNT0_M; - - USB0.gintmsk |= USB_IEPINTMSK_M | USB_OEPINTMSK_M; -} - -static void enum_done_processing(void) -{ - ESP_EARLY_LOGV(TAG, "dcd_int_handler - Speed enumeration done! Sending DCD_EVENT_BUS_RESET then"); - // On current silicon on the Full Speed core, speed is fixed to Full Speed. - // However, keep for debugging and in case Low Speed is ever supported. - uint32_t enum_spd = (USB0.dsts >> USB_ENUMSPD_S) & (USB_ENUMSPD_V); - - // Maximum packet size for EP 0 is set for both directions by writing DIEPCTL - if (enum_spd == 0x03) { // Full-Speed (PHY on 48 MHz) - USB0.in_ep_reg[0].diepctl &= ~USB_D_MPS0_V; // 64 bytes - USB0.in_ep_reg[0].diepctl &= ~USB_D_STALL0_M; // clear Stall - xfer_status[0][TUSB_DIR_OUT].max_size = 64; - xfer_status[0][TUSB_DIR_IN].max_size = 64; - } else { - USB0.in_ep_reg[0].diepctl |= USB_D_MPS0_V; // 8 bytes - USB0.in_ep_reg[0].diepctl &= ~USB_D_STALL0_M; // clear Stall - xfer_status[0][TUSB_DIR_OUT].max_size = 8; - xfer_status[0][TUSB_DIR_IN].max_size = 8; - } -} - - -/*------------------------------------------------------------------*/ -/* Controller API - *------------------------------------------------------------------*/ -bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { - (void) rh_init; - ESP_LOGV(TAG, "DCD init - Start"); - - // A. Disconnect - ESP_LOGV(TAG, "DCD init - Soft DISCONNECT and Setting up"); - USB0.dctl |= USB_SFTDISCON_M; // Soft disconnect - - // B. Programming DCFG - /* If USB host misbehaves during status portion of control xfer - (non zero-length packet), send STALL back and discard. Full speed. */ - USB0.dcfg |= USB_NZSTSOUTHSHK_M | // NonZero .... STALL - (3 << 0); // dev speed: fullspeed 1.1 on 48 mhz // TODO no value in usb_reg.h (IDF-1476) - - USB0.gahbcfg |= USB_NPTXFEMPLVL_M | USB_GLBLLNTRMSK_M; // Global interruptions ON - USB0.gusbcfg |= USB_FORCEDEVMODE_M; // force devmode - USB0.gotgctl &= ~(USB_BVALIDOVVAL_M | USB_BVALIDOVEN_M | USB_VBVALIDOVVAL_M); //no overrides - - // C. Setting SNAKs, then connect - for (int n = 0; n < USB_OUT_EP_NUM; n++) { - USB0.out_ep_reg[n].doepctl |= USB_DO_SNAK0_M; // DOEPCTL0_SNAK - } - - // D. Interruption masking - USB0.gintmsk = 0; //mask all - USB0.gotgint = ~0U; //clear OTG ints - USB0.gintsts = ~0U; //clear pending ints - USB0.gintmsk = USB_OTGINTMSK_M | - USB_MODEMISMSK_M | - USB_RXFLVIMSK_M | - USB_ERLYSUSPMSK_M | - USB_USBSUSPMSK_M | - USB_USBRSTMSK_M | - USB_ENUMDONEMSK_M | - USB_RESETDETMSK_M | - USB_WKUPINT_M | - USB_DISCONNINTMSK_M; // host most only - - dcd_connect(rhport); - return true; -} - -void dcd_set_address(uint8_t rhport, uint8_t dev_addr) -{ - (void)rhport; - ESP_LOGV(TAG, "DCD init - Set address : %u", dev_addr); - USB0.dcfg |= ((dev_addr & USB_DEVADDR_V) << USB_DEVADDR_S); - // Response with status after changing device address - dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); -} - -void dcd_remote_wakeup(uint8_t rhport) -{ - (void)rhport; - - // set remote wakeup - USB0.dctl |= USB_RMTWKUPSIG_M; - - // enable SOF to detect bus resume - USB0.gintsts = USB_SOF_M; - USB0.gintmsk |= USB_SOFMSK_M; - - // Per specs: remote wakeup signal bit must be clear within 1-15ms - vTaskDelay(pdMS_TO_TICKS(1)); - - USB0.dctl &= ~USB_RMTWKUPSIG_M; -} - -// connect by enabling internal pull-up resistor on D+/D- -void dcd_connect(uint8_t rhport) -{ - (void) rhport; - USB0.dctl &= ~USB_SFTDISCON_M; -} - -// disconnect by disabling internal pull-up resistor on D+/D- -void dcd_disconnect(uint8_t rhport) -{ - (void) rhport; - USB0.dctl |= USB_SFTDISCON_M; -} - -void dcd_sof_enable(uint8_t rhport, bool en) -{ - (void) rhport; - (void) en; - - // TODO implement later -} - -/*------------------------------------------------------------------*/ -/* DCD Endpoint port - *------------------------------------------------------------------*/ - -bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_edpt) -{ - ESP_LOGV(TAG, "DCD endpoint opened"); - (void)rhport; - - usb_out_endpoint_t *out_ep = &(USB0.out_ep_reg[0]); - usb_in_endpoint_t *in_ep = &(USB0.in_ep_reg[0]); - - uint8_t const epnum = tu_edpt_number(desc_edpt->bEndpointAddress); - uint8_t const dir = tu_edpt_dir(desc_edpt->bEndpointAddress); - - TU_ASSERT(epnum < EP_MAX); - - xfer_ctl_t *xfer = XFER_CTL_BASE(epnum, dir); - xfer->max_size = tu_edpt_packet_size(desc_edpt); - xfer->interval = desc_edpt->bInterval; - - if (dir == TUSB_DIR_OUT) { - out_ep[epnum].doepctl |= USB_USBACTEP1_M | - desc_edpt->bmAttributes.xfer << USB_EPTYPE1_S | - (desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? USB_DO_SETD0PID1_M : 0) | - xfer->max_size << USB_MPS1_S; - USB0.daintmsk |= (1 << (16 + epnum)); - } else { - // "USB Data FIFOs" section in reference manual - // Peripheral FIFO architecture - // - // --------------- 320 or 1024 ( 1280 or 4096 bytes ) - // | IN FIFO MAX | - // --------------- - // | ... | - // --------------- y + x + 16 + GRXFSIZ - // | IN FIFO 2 | - // --------------- x + 16 + GRXFSIZ - // | IN FIFO 1 | - // --------------- 16 + GRXFSIZ - // | IN FIFO 0 | - // --------------- GRXFSIZ - // | OUT FIFO | - // | ( Shared ) | - // --------------- 0 - // - // Since OUT FIFO = GRXFSIZ, FIFO 0 = 16, for simplicity, we equally allocated for the rest of endpoints - // - Size : (FIFO_SIZE/4 - GRXFSIZ - 16) / (EP_MAX-1) - // - Offset: GRXFSIZ + 16 + Size*(epnum-1) - // - IN EP 1 gets FIFO 1, IN EP "n" gets FIFO "n". - - uint8_t fifo_num = get_free_fifo(); - TU_ASSERT(fifo_num != 0); - - in_ep[epnum].diepctl &= ~(USB_D_TXFNUM1_M | USB_D_EPTYPE1_M | USB_DI_SETD0PID1 | USB_D_MPS1_M); - in_ep[epnum].diepctl |= USB_D_USBACTEP1_M | - fifo_num << USB_D_TXFNUM1_S | - desc_edpt->bmAttributes.xfer << USB_D_EPTYPE1_S | - (desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? (1 << USB_DI_SETD0PID1_S) : 0) | - xfer->max_size << 0; - - USB0.daintmsk |= (1 << (0 + epnum)); - - // Both TXFD and TXSA are in unit of 32-bit words. - // IN FIFO 0 was configured during enumeration, hence the "+ 16". - uint16_t const allocated_size = (USB0.grxfsiz & 0x0000ffff) + 16; - uint16_t const fifo_size = (EP_FIFO_SIZE/4 - allocated_size) / (EP_FIFO_NUM-1); - uint32_t const fifo_offset = allocated_size + fifo_size*(fifo_num-1); - - // DIEPTXF starts at FIFO #1. - USB0.dieptxf[epnum - 1] = (fifo_size << USB_NPTXFDEP_S) | fifo_offset; - } - return true; -} - -void dcd_edpt_close_all(uint8_t rhport) -{ - (void) rhport; - - usb_out_endpoint_t *out_ep = &(USB0.out_ep_reg[0]); - usb_in_endpoint_t *in_ep = &(USB0.in_ep_reg[0]); - - // Disable non-control interrupt - USB0.daintmsk = USB_OUTEPMSK0_M | USB_INEPMSK0_M; - - for(uint8_t n = 1; n < EP_MAX; n++) - { - // disable OUT endpoint - out_ep[n].doepctl = 0; - xfer_status[n][TUSB_DIR_OUT].max_size = 0; - - // disable IN endpoint - in_ep[n].diepctl = 0; - xfer_status[n][TUSB_DIR_IN].max_size = 0; - } - - _allocated_fifos = 1; -} - -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes) -{ - (void)rhport; - - 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); - xfer->buffer = buffer; - // xfer->ff = NULL; // TODO support dcd_edpt_xfer_fifo API - xfer->total_len = total_bytes; - xfer->queued_len = 0; - xfer->short_packet = false; - - uint16_t num_packets = (total_bytes / xfer->max_size); - uint8_t short_packet_size = total_bytes % xfer->max_size; - - // Zero-size packet is special case. - if (short_packet_size > 0 || (total_bytes == 0)) { - num_packets++; - } - - ESP_LOGV(TAG, "Transfer <-> EP%i, %s, pkgs: %i, bytes: %i", - epnum, ((dir == TUSB_DIR_IN) ? "USB0.HOST (in)" : "HOST->DEV (out)"), - num_packets, total_bytes); - - // IN and OUT endpoint xfers are interrupt-driven, we just schedule them - // here. - if (dir == TUSB_DIR_IN) { - // A full IN transfer (multiple packets, possibly) triggers XFRC. - USB0.in_ep_reg[epnum].dieptsiz = (num_packets << USB_D_PKTCNT0_S) | total_bytes; - USB0.in_ep_reg[epnum].diepctl |= USB_D_EPENA1_M | USB_D_CNAK1_M; // Enable | CNAK - - // For ISO endpoint with interval=1 set correct DATA0/DATA1 bit for next frame - if ((USB0.in_ep_reg[epnum].diepctl & USB_D_EPTYPE0_M) == (1 << USB_D_EPTYPE1_S) && xfer->interval == 1) { - // Take odd/even bit from frame counter. - uint32_t const odd_frame_now = (USB0.dsts & (1u << USB_SOFFN_S)); - USB0.in_ep_reg[epnum].diepctl |= (odd_frame_now ? USB_DI_SETD0PID1 : USB_DI_SETD1PID1); - } - - // Enable fifo empty interrupt only if there are something to put in the fifo. - if(total_bytes != 0) { - USB0.dtknqr4_fifoemptymsk |= (1 << epnum); - } - } else { - // Each complete packet for OUT xfers triggers XFRC. - USB0.out_ep_reg[epnum].doeptsiz |= USB_PKTCNT0_M | ((xfer->max_size & USB_XFERSIZE0_V) << USB_XFERSIZE0_S); - USB0.out_ep_reg[epnum].doepctl |= USB_EPENA0_M | USB_CNAK0_M; - - // For ISO endpoint with interval=1 set correct DATA0/DATA1 bit for next frame - if ((USB0.out_ep_reg[epnum].doepctl & USB_D_EPTYPE0_M) == (1 << USB_D_EPTYPE1_S) && xfer->interval == 1) { - // Take odd/even bit from frame counter. - uint32_t const odd_frame_now = (USB0.dsts & (1u << USB_SOFFN_S)); - USB0.out_ep_reg[epnum].doepctl |= (odd_frame_now ? USB_DO_SETD0PID1 : USB_DO_SETD1PID1); - } - } - return true; -} - -#if 0 // TODO support dcd_edpt_xfer_fifo API -bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) -{ - (void)rhport; -} -#endif - -void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) -{ - (void)rhport; - - usb_out_endpoint_t *out_ep = &(USB0.out_ep_reg[0]); - usb_in_endpoint_t *in_ep = &(USB0.in_ep_reg[0]); - - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - if (dir == TUSB_DIR_IN) { - // Only disable currently enabled non-control endpoint - if ((epnum == 0) || !(in_ep[epnum].diepctl & USB_D_EPENA1_M)) { - in_ep[epnum].diepctl |= (USB_DI_SNAK1_M | USB_D_STALL1_M); - } else { - // Stop transmitting packets and NAK IN xfers. - in_ep[epnum].diepctl |= USB_DI_SNAK1_M; - while ((in_ep[epnum].diepint & USB_DI_SNAK1_M) == 0) ; - - // Disable the endpoint. Note that both SNAK and STALL are set here. - in_ep[epnum].diepctl |= (USB_DI_SNAK1_M | USB_D_STALL1_M | USB_D_EPDIS1_M); - while ((in_ep[epnum].diepint & USB_D_EPDISBLD0_M) == 0) ; - in_ep[epnum].diepint = USB_D_EPDISBLD0_M; - } - - // Flush the FIFO, and wait until we have confirmed it cleared. - uint8_t const fifo_num = ((in_ep[epnum].diepctl >> USB_D_TXFNUM1_S) & USB_D_TXFNUM1_V); - USB0.grstctl |= (fifo_num << USB_TXFNUM_S); - USB0.grstctl |= USB_TXFFLSH_M; - while ((USB0.grstctl & USB_TXFFLSH_M) != 0) ; - } else { - // Only disable currently enabled non-control endpoint - if ((epnum == 0) || !(out_ep[epnum].doepctl & USB_EPENA0_M)) { - out_ep[epnum].doepctl |= USB_STALL0_M; - } else { - // Asserting GONAK is required to STALL an OUT endpoint. - // Simpler to use polling here, we don't use the "B"OUTNAKEFF interrupt - // anyway, and it can't be cleared by user code. If this while loop never - // finishes, we have bigger problems than just the stack. - USB0.dctl |= USB_SGOUTNAK_M; - while ((USB0.gintsts & USB_GOUTNAKEFF_M) == 0) ; - - // Ditto here- disable the endpoint. Note that only STALL and not SNAK - // is set here. - out_ep[epnum].doepctl |= (USB_STALL0_M | USB_EPDIS0_M); - while ((out_ep[epnum].doepint & USB_EPDISBLD0_M) == 0) ; - out_ep[epnum].doepint = USB_EPDISBLD0_M; - - // Allow other OUT endpoints to keep receiving. - USB0.dctl |= USB_CGOUTNAK_M; - } - } -} - -void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) -{ - (void)rhport; - - usb_out_endpoint_t *out_ep = &(USB0.out_ep_reg[0]); - usb_in_endpoint_t *in_ep = &(USB0.in_ep_reg[0]); - - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - if (dir == TUSB_DIR_IN) { - in_ep[epnum].diepctl &= ~USB_D_STALL1_M; - - uint8_t eptype = (in_ep[epnum].diepctl & USB_D_EPTYPE1_M) >> USB_D_EPTYPE1_S; - // Required by USB spec to reset DATA toggle bit to DATA0 on interrupt - // and bulk endpoints. - if (eptype == 2 || eptype == 3) { - in_ep[epnum].diepctl |= USB_DI_SETD0PID1_M; - } - } else { - out_ep[epnum].doepctl &= ~USB_STALL1_M; - - uint8_t eptype = (out_ep[epnum].doepctl & USB_EPTYPE1_M) >> USB_EPTYPE1_S; - // Required by USB spec to reset DATA toggle bit to DATA0 on interrupt - // and bulk endpoints. - if (eptype == 2 || eptype == 3) { - out_ep[epnum].doepctl |= USB_DO_SETD0PID1_M; - } - } -} - -/*------------------------------------------------------------------*/ - -static void receive_packet(xfer_ctl_t *xfer, /* usb_out_endpoint_t * out_ep, */ uint16_t xfer_size) -{ - ESP_EARLY_LOGV(TAG, "USB - receive_packet"); - volatile uint32_t *rx_fifo = USB0.fifo[0]; - - // See above TODO - // uint16_t remaining = (out_ep->DOEPTSIZ & UsbDOEPTSIZ_XFRSIZ_Msk) >> UsbDOEPTSIZ_XFRSIZ_Pos; - // xfer->queued_len = xfer->total_len - remaining; - - uint16_t remaining = xfer->total_len - xfer->queued_len; - uint16_t to_recv_size; - - if (remaining <= xfer->max_size) { - // Avoid buffer overflow. - to_recv_size = (xfer_size > remaining) ? remaining : xfer_size; - } else { - // Room for full packet, choose recv_size based on what the microcontroller - // claims. - to_recv_size = (xfer_size > xfer->max_size) ? xfer->max_size : xfer_size; - } - - // Common buffer read -#if 0 // TODO support dcd_edpt_xfer_fifo API - if (xfer->ff) - { - // Ring buffer - tu_fifo_write_n_const_addr_full_words(xfer->ff, (const void *) rx_fifo, to_recv_size); - } - else -#endif - { - uint8_t to_recv_rem = to_recv_size % 4; - uint16_t to_recv_size_aligned = to_recv_size - to_recv_rem; - - // Do not assume xfer buffer is aligned. - uint8_t *base = (xfer->buffer + xfer->queued_len); - - // This for loop always runs at least once- skip if less than 4 bytes - // to collect. - if (to_recv_size >= 4) { - for (uint16_t i = 0; i < to_recv_size_aligned; i += 4) { - uint32_t tmp = (*rx_fifo); - base[i] = tmp & 0x000000FF; - base[i + 1] = (tmp & 0x0000FF00) >> 8; - base[i + 2] = (tmp & 0x00FF0000) >> 16; - base[i + 3] = (tmp & 0xFF000000) >> 24; - } - } - - // Do not read invalid bytes from RX FIFO. - if (to_recv_rem != 0) { - uint32_t tmp = (*rx_fifo); - uint8_t *last_32b_bound = base + to_recv_size_aligned; - - last_32b_bound[0] = tmp & 0x000000FF; - if (to_recv_rem > 1) { - last_32b_bound[1] = (tmp & 0x0000FF00) >> 8; - } - if (to_recv_rem > 2) { - last_32b_bound[2] = (tmp & 0x00FF0000) >> 16; - } - } - } - - xfer->queued_len += xfer_size; - - // Per USB spec, a short OUT packet (including length 0) is always - // indicative of the end of a transfer (at least for ctl, bulk, int). - xfer->short_packet = (xfer_size < xfer->max_size); -} - -static void transmit_packet(xfer_ctl_t *xfer, volatile usb_in_endpoint_t *in_ep, uint8_t fifo_num) -{ - ESP_EARLY_LOGV(TAG, "USB - transmit_packet"); - volatile uint32_t *tx_fifo = USB0.fifo[fifo_num]; - - uint16_t remaining = (in_ep->dieptsiz & 0x7FFFFU) >> USB_D_XFERSIZE0_S; - xfer->queued_len = xfer->total_len - remaining; - - uint16_t to_xfer_size = (remaining > xfer->max_size) ? xfer->max_size : remaining; - -#if 0 // TODO support dcd_edpt_xfer_fifo API - if (xfer->ff) - { - tu_fifo_read_n_const_addr_full_words(xfer->ff, (void *) tx_fifo, to_xfer_size); - } - else -#endif - { - uint8_t to_xfer_rem = to_xfer_size % 4; - uint16_t to_xfer_size_aligned = to_xfer_size - to_xfer_rem; - - // Buffer might not be aligned to 32b, so we need to force alignment - // by copying to a temp var. - uint8_t *base = (xfer->buffer + xfer->queued_len); - - // This for loop always runs at least once- skip if less than 4 bytes - // to send off. - if (to_xfer_size >= 4) { - for (uint16_t i = 0; i < to_xfer_size_aligned; i += 4) { - uint32_t tmp = base[i] | (base[i + 1] << 8) | - (base[i + 2] << 16) | (base[i + 3] << 24); - (*tx_fifo) = tmp; - } - } - - // Do not read beyond end of buffer if not divisible by 4. - if (to_xfer_rem != 0) { - uint32_t tmp = 0; - uint8_t *last_32b_bound = base + to_xfer_size_aligned; - - tmp |= last_32b_bound[0]; - if (to_xfer_rem > 1) { - tmp |= (last_32b_bound[1] << 8); - } - if (to_xfer_rem > 2) { - tmp |= (last_32b_bound[2] << 16); - } - - (*tx_fifo) = tmp; - } - } -} - -static void read_rx_fifo(void) -{ - // Pop control word off FIFO (completed xfers will have 2 control words, - // we only pop one ctl word each interrupt). - uint32_t const ctl_word = USB0.grxstsp; - uint8_t const pktsts = (ctl_word & USB_PKTSTS_M) >> USB_PKTSTS_S; - uint8_t const epnum = (ctl_word & USB_CHNUM_M ) >> USB_CHNUM_S; - uint16_t const bcnt = (ctl_word & USB_BCNT_M ) >> USB_BCNT_S; - - switch (pktsts) { - case 0x01: // Global OUT NAK (Interrupt) - ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX type : Global OUT NAK"); - break; - - case 0x02: { // Out packet recvd - ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX type : Out packet"); - xfer_ctl_t *xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); - receive_packet(xfer, bcnt); - } - break; - - case 0x03: // Out packet done (Interrupt) - ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX type : Out packet done"); - break; - - case 0x04: // Step 2: Setup transaction completed (Interrupt) - // After this event, OEPINT interrupt will occur with SETUP bit set - ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX : Setup packet done"); - USB0.out_ep_reg[epnum].doeptsiz |= USB_SUPCNT0_M; - break; - - case 0x06: { // Step1: Setup data packet received - volatile uint32_t *rx_fifo = USB0.fifo[0]; - - // We can receive up to three setup packets in succession, but - // only the last one is valid. Therefore we just overwrite it - _setup_packet[0] = (*rx_fifo); - _setup_packet[1] = (*rx_fifo); - - ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX : Setup packet : 0x%08x 0x%08x", _setup_packet[0], _setup_packet[1]); - } - break; - - default: // Invalid, do something here, like breakpoint? - TU_BREAKPOINT(); - break; - } -} - -static void handle_epout_ints(void) -{ - // GINTSTS will be cleared with DAINT == 0 - // DAINT for a given EP clears when DOEPINTx is cleared. - // DOEPINT will be cleared when DAINT's out bits are cleared. - for (int n = 0; n < USB_OUT_EP_NUM; n++) { - xfer_ctl_t *xfer = XFER_CTL_BASE(n, TUSB_DIR_OUT); - - if (USB0.daint & (1 << (16 + n))) { - // SETUP packet Setup Phase done. - if ((USB0.out_ep_reg[n].doepint & USB_SETUP0_M)) { - USB0.out_ep_reg[n].doepint = USB_STUPPKTRCVD0_M | USB_SETUP0_M; // clear - dcd_event_setup_received(0, (uint8_t *)&_setup_packet[0], true); - } - - // OUT XFER complete (single packet).q - if (USB0.out_ep_reg[n].doepint & USB_XFERCOMPL0_M) { - - ESP_EARLY_LOGV(TAG, "TUSB IRQ - EP OUT - XFER complete (single packet)"); - USB0.out_ep_reg[n].doepint = USB_XFERCOMPL0_M; - - // Transfer complete if short packet or total len is transferred - if (xfer->short_packet || (xfer->queued_len == xfer->total_len)) { - xfer->short_packet = false; - dcd_event_xfer_complete(0, n, xfer->queued_len, XFER_RESULT_SUCCESS, true); - } else { - // Schedule another packet to be received. - USB0.out_ep_reg[n].doeptsiz |= USB_PKTCNT0_M | ((xfer->max_size & USB_XFERSIZE0_V) << USB_XFERSIZE0_S); - USB0.out_ep_reg[n].doepctl |= USB_EPENA0_M | USB_CNAK0_M; - } - } - } - } -} - -static void handle_epin_ints(void) -{ - // GINTSTS will be cleared with DAINT == 0 - // DAINT for a given EP clears when DIEPINTx is cleared. - // IEPINT will be cleared when DAINT's out bits are cleared. - for (uint32_t n = 0; n < USB_IN_EP_NUM; n++) { - xfer_ctl_t *xfer = &xfer_status[n][TUSB_DIR_IN]; - - if (USB0.daint & (1 << (0 + n))) { - ESP_EARLY_LOGV(TAG, "TUSB IRQ - EP IN %u", n); - // IN XFER complete (entire xfer). - if (USB0.in_ep_reg[n].diepint & USB_D_XFERCOMPL0_M) { - ESP_EARLY_LOGV(TAG, "TUSB IRQ - IN XFER complete!"); - USB0.in_ep_reg[n].diepint = USB_D_XFERCOMPL0_M; - dcd_event_xfer_complete(0, n | TUSB_DIR_IN_MASK, xfer->total_len, XFER_RESULT_SUCCESS, true); - } - - // XFER FIFO empty - if (USB0.in_ep_reg[n].diepint & USB_D_TXFEMP0_M) { - ESP_EARLY_LOGV(TAG, "TUSB IRQ - IN XFER FIFO empty!"); - USB0.in_ep_reg[n].diepint = USB_D_TXFEMP0_M; - transmit_packet(xfer, &USB0.in_ep_reg[n], n); - - // Turn off TXFE if all bytes are written. - if (xfer->queued_len == xfer->total_len) - { - USB0.dtknqr4_fifoemptymsk &= ~(1 << n); - } - } - - // XFER Timeout - if (USB0.in_ep_reg[n].diepint & USB_D_TIMEOUT0_M) { - // Clear interrupt or endpoint will hang. - USB0.in_ep_reg[n].diepint = USB_D_TIMEOUT0_M; - // Maybe retry? - } - } - } -} - - -static void _dcd_int_handler(void* arg) -{ - (void) arg; - uint8_t const rhport = 0; - - const uint32_t int_msk = USB0.gintmsk; - const uint32_t int_status = USB0.gintsts & int_msk; - - if (int_status & USB_USBRST_M) { - // start of reset - ESP_EARLY_LOGV(TAG, "dcd_int_handler - reset"); - USB0.gintsts = USB_USBRST_M; - // FIFOs will be reassigned when the endpoints are reopen - _allocated_fifos = 1; - bus_reset(); - } - - if (int_status & USB_RESETDET_M) { - ESP_EARLY_LOGV(TAG, "dcd_int_handler - reset while suspend"); - USB0.gintsts = USB_RESETDET_M; - bus_reset(); - } - - if (int_status & USB_ENUMDONE_M) { - // ENUMDNE detects speed of the link. For full-speed, we - // always expect the same value. This interrupt is considered - // the end of reset. - USB0.gintsts = USB_ENUMDONE_M; - enum_done_processing(); - dcd_event_bus_reset(rhport, TUSB_SPEED_FULL, true); - } - - if(int_status & USB_USBSUSP_M) - { - USB0.gintsts = USB_USBSUSP_M; - dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true); - } - - if(int_status & USB_WKUPINT_M) - { - USB0.gintsts = USB_WKUPINT_M; - dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true); - } - - if (int_status & USB_OTGINT_M) - { - // OTG INT bit is read-only - ESP_EARLY_LOGV(TAG, "dcd_int_handler - disconnected"); - - uint32_t const otg_int = USB0.gotgint; - - if (otg_int & USB_SESENDDET_M) - { - dcd_event_bus_signal(rhport, DCD_EVENT_UNPLUGGED, true); - } - - USB0.gotgint = otg_int; - } - - if (int_status & USB_SOF_M) { - USB0.gintsts = USB_SOF_M; - - // Disable SOF interrupt since currently only used for remote wakeup detection - USB0.gintmsk &= ~USB_SOFMSK_M; - - dcd_event_bus_signal(rhport, DCD_EVENT_SOF, true); - } - - - if (int_status & USB_RXFLVI_M) { - // RXFLVL bit is read-only - ESP_EARLY_LOGV(TAG, "dcd_int_handler - rx!"); - - // Mask out RXFLVL while reading data from FIFO - USB0.gintmsk &= ~USB_RXFLVIMSK_M; - read_rx_fifo(); - USB0.gintmsk |= USB_RXFLVIMSK_M; - } - - // OUT endpoint interrupt handling. - if (int_status & USB_OEPINT_M) { - // OEPINT is read-only - ESP_EARLY_LOGV(TAG, "dcd_int_handler - OUT endpoint!"); - handle_epout_ints(); - } - - // IN endpoint interrupt handling. - if (int_status & USB_IEPINT_M) { - // IEPINT bit read-only - ESP_EARLY_LOGV(TAG, "dcd_int_handler - IN endpoint!"); - handle_epin_ints(); - } - - // Without handling - USB0.gintsts |= USB_CURMOD_INT_M | - USB_MODEMIS_M | - USB_OTGINT_M | - USB_NPTXFEMP_M | - USB_GINNAKEFF_M | - USB_GOUTNAKEFF | - USB_ERLYSUSP_M | - USB_USBSUSP_M | - USB_ISOOUTDROP_M | - USB_EOPF_M | - USB_EPMIS_M | - USB_INCOMPISOIN_M | - USB_INCOMPIP_M | - USB_FETSUSP_M | - USB_PTXFEMP_M; -} - -void dcd_int_enable (uint8_t rhport) -{ - (void) rhport; - esp_intr_alloc(ETS_USB_INTR_SOURCE, ESP_INTR_FLAG_LOWMED, (intr_handler_t) _dcd_int_handler, NULL, &usb_ih); -} - -void dcd_int_disable (uint8_t rhport) -{ - (void) rhport; - esp_intr_free(usb_ih); -} - -#endif // #if OPT_MCU_ESP32S2 || OPT_MCU_ESP32S3 diff --git a/tools/iar_gen.py b/tools/iar_gen.py index 8d45659db..571febb2c 100755 --- a/tools/iar_gen.py +++ b/tools/iar_gen.py @@ -74,7 +74,7 @@ def ListPath(path, blacklist=[]): print('') def List(): - ListPath('src', [ 'template.c', 'dcd_synopsys.c', 'dcd_esp32sx.c' ]) + ListPath('src', [ 'template.c' ]) ListPath('lib/SEGGER_RTT') if __name__ == "__main__": -- cgit v1.3.1 From 5ac0bed779ec43cc74f8ed990a01165139454267 Mon Sep 17 00:00:00 2001 From: Mengsk Date: Mon, 6 Oct 2025 17:12:05 +0200 Subject: dcd/dwc2: fix enumration when EP0 size=8 Signed-off-by: Mengsk --- src/portable/synopsys/dwc2/dcd_dwc2.c | 23 +++++++++++++++++------ src/portable/synopsys/dwc2/dwc2_type.h | 6 ++++++ 2 files changed, 23 insertions(+), 6 deletions(-) (limited to 'src/portable') diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index f10f0bdc3..d3f8f6b2a 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -168,7 +168,7 @@ static void dma_setup_prepare(uint8_t rhport) { - All EP OUT shared a unique OUT FIFO which uses (for Slave or Buffer DMA, Scatt/Gather DMA use different formula): - 13 for setup packets + control words (up to 3 setup packets). - 1 for global NAK (not required/used here). - - Largest-EPsize/4 + 1. ( FS: 64 bytes, HS: 512 bytes). Recommended is "2 x (Largest-EPsize/4 + 1)" + - Largest-EPsize/4 + 1. (FS: 64 bytes, HS: 512 bytes). Recommended is "2 x (Largest-EPsize/4 + 1)" - 2 for each used OUT endpoint Therefore GRXFSIZ = 13 + 1 + 2 x (Largest-EPsize/4 + 1) + 2 x EPOUTnum @@ -701,12 +701,23 @@ static void handle_bus_reset(uint8_t rhport) { dcfg.address = 0; dwc2->dcfg = dcfg.value; - // Fixed both control EP0 size to 64 bytes - dwc2->epin[0].ctl &= ~(0x03 << DIEPCTL_MPSIZ_Pos); - dwc2->epout[0].ctl &= ~(0x03 << DOEPCTL_MPSIZ_Pos); + // 6. Configure maximum packet size for EP0 + uint8_t mps = 0; + switch (CFG_TUD_ENDPOINT0_SIZE) { + case 8: mps = 3; break; + case 16: mps = 2; break; + case 32: mps = 1; break; + case 64: mps = 0; break; + default: mps = 0; break; + } + + dwc2->epin[0].ctl &= ~DIEPCTL0_MPSIZ_Msk; + dwc2->epout[0].ctl &= ~DOEPCTL0_MPSIZ_Msk; + dwc2->epin[0].ctl |= mps << DIEPCTL0_MPSIZ_Pos; + dwc2->epout[0].ctl |= mps << DOEPCTL0_MPSIZ_Pos; - xfer_status[0][TUSB_DIR_OUT].max_size = 64; - xfer_status[0][TUSB_DIR_IN].max_size = 64; + xfer_status[0][TUSB_DIR_OUT].max_size = CFG_TUD_ENDPOINT0_SIZE; + xfer_status[0][TUSB_DIR_IN].max_size = CFG_TUD_ENDPOINT0_SIZE; if(dma_device_enabled(dwc2)) { dma_setup_prepare(rhport); diff --git a/src/portable/synopsys/dwc2/dwc2_type.h b/src/portable/synopsys/dwc2/dwc2_type.h index 0a8dacf5f..75643529f 100644 --- a/src/portable/synopsys/dwc2/dwc2_type.h +++ b/src/portable/synopsys/dwc2/dwc2_type.h @@ -1847,6 +1847,9 @@ TU_VERIFY_STATIC(offsetof(dwc2_regs_t, fifo ) == 0x1000, "incorrect size"); #define HPTXFSIZ_PTXFD HPTXFSIZ_PTXFD_Msk // Host periodic TxFIFO depth /******************** Bit definition for DIEPCTL register ********************/ +#define DIEPCTL0_MPSIZ_Pos (0U) +#define DIEPCTL0_MPSIZ_Msk (0x3UL << DIEPCTL0_MPSIZ_Pos) // 0x00000003 +#define DIEPCTL0_MPSIZ DIEPCTL0_MPSIZ_Msk // Maximum packet size(endpoint 0) #define DIEPCTL_MPSIZ_Pos (0U) #define DIEPCTL_MPSIZ_Msk (0x7FFUL << DIEPCTL_MPSIZ_Pos) // 0x000007FF #define DIEPCTL_MPSIZ DIEPCTL_MPSIZ_Msk // Maximum packet size @@ -2155,6 +2158,9 @@ TU_VERIFY_STATIC(offsetof(dwc2_regs_t, fifo ) == 0x1000, "incorrect size"); #define EPCTL_EPENA EPCTL_EPENA_Msk // Endpoint enable /******************** Bit definition for DOEPCTL register ********************/ +#define DOEPCTL0_MPSIZ_Pos (0U) +#define DOEPCTL0_MPSIZ_Msk (0x3UL << DOEPCTL0_MPSIZ_Pos) // 0x00000003 +#define DOEPCTL0_MPSIZ DOEPCTL0_MPSIZ_Msk // Maximum packet size(endpoint 0) #define DOEPCTL_MPSIZ_Pos (0U) #define DOEPCTL_MPSIZ_Msk (0x7FFUL << DOEPCTL_MPSIZ_Pos) // 0x000007FF #define DOEPCTL_MPSIZ DOEPCTL_MPSIZ_Msk // Maximum packet size //Bit 1 -- cgit v1.3.1 From 16dd74912fd6627fcfa1dcd91a8e6f9150b0cced Mon Sep 17 00:00:00 2001 From: Mengsk Date: Tue, 7 Oct 2025 12:53:50 +0200 Subject: dcd/dwc2: cleanup previous pending EP0 IN transfer if a SETUP packet is received Signed-off-by: Mengsk --- src/portable/synopsys/dwc2/dcd_dwc2.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'src/portable') diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index d3f8f6b2a..9d9172b67 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -282,8 +282,7 @@ static void edpt_disable(uint8_t rhport, uint8_t ep_addr, bool stall) { dwc2_dep_t* dep = &dwc2->ep[dir == TUSB_DIR_IN ? 0 : 1][epnum]; if (dir == TUSB_DIR_IN) { - // Only disable currently enabled non-control endpoint - if ((epnum == 0) || !(dep->diepctl & DIEPCTL_EPENA)) { + if (!(dep->diepctl & DIEPCTL_EPENA)) { dep->diepctl |= DIEPCTL_SNAK | (stall ? DIEPCTL_STALL : 0); } else { // Stop transmitting packets and NAK IN xfers. @@ -841,6 +840,11 @@ static void handle_rxflvl_irq(uint8_t rhport) { static void handle_epout_slave(uint8_t rhport, uint8_t epnum, dwc2_doepint_t doepint_bm) { if (doepint_bm.setup_phase_done) { + // Cleanup previous pending EP0 IN transfer if any + dwc2_dep_t* epin0 = &DWC2_REG(rhport)->epin[0]; + if (epin0->diepctl & DIEPCTL_EPENA) { + edpt_disable(rhport, 0x80, false); + } dcd_event_setup_received(rhport, _dcd_usbbuf.setup_packet, true); return; } @@ -919,6 +923,11 @@ static void handle_epout_dma(uint8_t rhport, uint8_t epnum, dwc2_doepint_t doepi dwc2_regs_t* dwc2 = DWC2_REG(rhport); if (doepint_bm.setup_phase_done) { + // Cleanup previous pending EP0 IN transfer if any + dwc2_dep_t* epin0 = &DWC2_REG(rhport)->epin[0]; + if (epin0->diepctl & DIEPCTL_EPENA) { + edpt_disable(rhport, 0x80, false); + } dma_setup_prepare(rhport); dcd_dcache_invalidate(_dcd_usbbuf.setup_packet, 8); dcd_event_setup_received(rhport, _dcd_usbbuf.setup_packet, true); -- cgit v1.3.1 From d4374bb0dbb0e0eddd4459219f981fd8f62365a1 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 9 Oct 2025 18:18:08 +0700 Subject: centralize hcd_dcache_uncached() for ED --- src/portable/ohci/ohci.c | 359 +++++++++++++++++++++-------------------------- src/portable/ohci/ohci.h | 57 +++----- 2 files changed, 182 insertions(+), 234 deletions(-) (limited to 'src/portable') diff --git a/src/portable/ohci/ohci.c b/src/portable/ohci/ohci.c index 340d8c56a..ee85f1b6a 100644 --- a/src/portable/ohci/ohci.c +++ b/src/portable/ohci/ohci.c @@ -109,17 +109,17 @@ enum { enum { OHCI_CCODE_NO_ERROR = 0, OHCI_CCODE_CRC = 1, - OHCI_CCODE_BIT_STUFFING = 2, - OHCI_CCODE_DATA_TOGGLE_MISMATCH = 3, - OHCI_CCODE_STALL = 4, - OHCI_CCODE_DEVICE_NOT_RESPONDING = 5, - OHCI_CCODE_PID_CHECK_FAILURE = 6, - OHCI_CCODE_UNEXPECTED_PID = 7, - OHCI_CCODE_DATA_OVERRUN = 8, - OHCI_CCODE_DATA_UNDERRUN = 9, - OHCI_CCODE_BUFFER_OVERRUN = 12, - OHCI_CCODE_BUFFER_UNDERRUN = 13, - OHCI_CCODE_NOT_ACCESSED = 14, + OHCI_CCODE_BIT_STUFFING = 2, + OHCI_CCODE_DATA_TOGGLE_MISMATCH = 3, + OHCI_CCODE_STALL = 4, + OHCI_CCODE_DEVICE_NOT_RESPONDING = 5, + OHCI_CCODE_PID_CHECK_FAILURE = 6, + OHCI_CCODE_UNEXPECTED_PID = 7, + OHCI_CCODE_DATA_OVERRUN = 8, + OHCI_CCODE_DATA_UNDERRUN = 9, + OHCI_CCODE_BUFFER_OVERRUN = 12, + OHCI_CCODE_BUFFER_UNDERRUN = 13, + OHCI_CCODE_NOT_ACCESSED = 14, }; enum { @@ -148,6 +148,8 @@ enum { //--------------------------------------------------------------------+ TU_ATTR_WEAK bool hcd_dcache_clean(void const* addr, uint32_t data_size) { (void) addr; (void) data_size; return true; } TU_ATTR_WEAK bool hcd_dcache_invalidate(void const* addr, uint32_t data_size) { (void) addr; (void) data_size; return true; } + +// Optional macro to access ED in uncached way #ifndef hcd_dcache_uncached #define hcd_dcache_uncached(x) (x) #endif @@ -157,17 +159,21 @@ TU_ATTR_WEAK bool hcd_dcache_invalidate(void const* addr, uint32_t data_size) { //--------------------------------------------------------------------+ CFG_TUH_MEM_SECTION TU_ATTR_ALIGNED(256) static ohci_data_t ohci_data; -static ohci_ed_t * const p_ed_head[] = -{ - [TUSB_XFER_CONTROL] = &ohci_data.control[0].ed, - [TUSB_XFER_BULK ] = &ohci_data.bulk_head_ed, - [TUSB_XFER_INTERRUPT] = &ohci_data.period_head_ed, +static ohci_ed_t * const p_ed_head[] = { + [TUSB_XFER_CONTROL] = hcd_dcache_uncached(&ohci_data.control[0].ed), + [TUSB_XFER_BULK ] = hcd_dcache_uncached(&ohci_data.bulk_head_ed), + [TUSB_XFER_INTERRUPT] = hcd_dcache_uncached(&ohci_data.period_head_ed), [TUSB_XFER_ISOCHRONOUS] = NULL // TODO Isochronous }; static void ed_list_insert(ohci_ed_t * p_pre, ohci_ed_t * p_ed); static void ed_list_remove_by_addr(ohci_ed_t * p_head, uint8_t dev_addr); static gtd_extra_data_t *gtd_get_extra_data(ohci_gtd_t const * const gtd); +static ohci_ed_t* ed_from_addr(uint8_t dev_addr, uint8_t ep_addr); + +TU_ATTR_ALWAYS_INLINE static inline ohci_ed_t* ed_control(uint8_t daddr) { + return hcd_dcache_uncached(&ohci_data.control[daddr].ed); +} //--------------------------------------------------------------------+ // USBH-HCD API @@ -175,13 +181,11 @@ static gtd_extra_data_t *gtd_get_extra_data(ohci_gtd_t const * const gtd); // If your system requires separation of virtual and physical memory, implement // tusb_app_virt_to_phys and tusb_app_virt_to_phys in your application. -TU_ATTR_ALWAYS_INLINE static inline void *_phys_addr(void *virtual_address) -{ +TU_ATTR_ALWAYS_INLINE static inline void *_phys_addr(void *virtual_address) { return tusb_app_virt_to_phys(virtual_address); } -TU_ATTR_ALWAYS_INLINE static inline void *_virt_addr(void *physical_address) -{ +TU_ATTR_ALWAYS_INLINE static inline void *_virt_addr(void *physical_address) { return tusb_app_phys_to_virt(physical_address); } @@ -192,8 +196,8 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { //------------- Data Structure init -------------// tu_memclr(&ohci_data, sizeof(ohci_data_t)); - for(uint8_t i=0; i<32; i++) - { // assign all interrupt pointers to period head ed + // assign all interrupt pointers to period head ed + for(uint8_t i=0; i<32; i++) { ohci_data.hcca.interrupt_table[i] = (uint32_t) _phys_addr(&ohci_data.period_head_ed); } @@ -202,19 +206,14 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { ohci_data.period_head_ed.w0.skip = 1; //If OHCI hardware is in SMM mode, gain ownership (Ref OHCI spec 5.1.1.3.3) - if (OHCI_REG->control_bit.interrupt_routing == 1) - { + if (OHCI_REG->control_bit.interrupt_routing == 1) { OHCI_REG->command_status_bit.ownership_change_request = 1; while (OHCI_REG->control_bit.interrupt_routing == 1) {} - } - - //If OHCI hardware has come from warm-boot, signal resume (Ref OHCI spec 5.1.1.3.4) - else if (OHCI_REG->control_bit.hc_functional_state != OHCI_CONTROL_FUNCSTATE_RESET && - OHCI_REG->control_bit.hc_functional_state != OHCI_CONTROL_FUNCSTATE_OPERATIONAL) - { + } else if (OHCI_REG->control_bit.hc_functional_state != OHCI_CONTROL_FUNCSTATE_RESET && + OHCI_REG->control_bit.hc_functional_state != OHCI_CONTROL_FUNCSTATE_OPERATIONAL) { + //If OHCI hardware has come from warm-boot, signal resume (Ref OHCI spec 5.1.1.3.4) //Wait 20 ms. (Ref Usb spec 7.1.7.7) OHCI_REG->control_bit.hc_functional_state = OHCI_CONTROL_FUNCSTATE_RESUME; - tusb_time_delay_ms_api(20); } @@ -256,7 +255,6 @@ uint32_t hcd_frame_number(uint8_t rhport) return (ohci_data.frame_number_hi << 16) | OHCI_REG->frame_number; } - //--------------------------------------------------------------------+ // PORT API //--------------------------------------------------------------------+ @@ -282,26 +280,18 @@ tusb_speed_t hcd_port_speed_get(uint8_t hostid) // endpoints are tied to an address, which only reclaim after a long delay when enumerating // thus there is no need to make sure ED is not in HC's cahed as it will not for sure -void hcd_device_close(uint8_t rhport, uint8_t dev_addr) -{ +void hcd_device_close(uint8_t rhport, uint8_t dev_addr) { // TODO OHCI (void) rhport; // addr0 serves as static head --> only set skip bit - if ( dev_addr == 0 ) - { - hcd_dcache_uncached(ohci_data.control[0].ed.w0).skip = 1; - }else - { - // remove control - ed_list_remove_by_addr( p_ed_head[TUSB_XFER_CONTROL], dev_addr); - - // remove bulk - ed_list_remove_by_addr(p_ed_head[TUSB_XFER_BULK], dev_addr); - - // remove interrupt - ed_list_remove_by_addr(p_ed_head[TUSB_XFER_INTERRUPT], dev_addr); - + if (dev_addr == 0) { + ohci_ed_t* ed = ed_control(0); + ed->w0.skip = 1; + } else { + ed_list_remove_by_addr(p_ed_head[TUSB_XFER_CONTROL], dev_addr); // remove control + ed_list_remove_by_addr(p_ed_head[TUSB_XFER_BULK], dev_addr); // remove bulk + ed_list_remove_by_addr(p_ed_head[TUSB_XFER_INTERRUPT], dev_addr); // remove interrupt // TODO remove ISO } } @@ -313,29 +303,26 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr) //--------------------------------------------------------------------+ // List Helper //--------------------------------------------------------------------+ -static inline tusb_xfer_type_t ed_get_xfer_type(ohci_ed_word0 w0) -{ +static inline tusb_xfer_type_t ed_get_xfer_type(ohci_ed_word0_t w0) { return (w0.ep_number == 0 ) ? TUSB_XFER_CONTROL : (w0.is_iso ) ? TUSB_XFER_ISOCHRONOUS : (w0.is_interrupt_xfer) ? TUSB_XFER_INTERRUPT : TUSB_XFER_BULK; } -static void ed_init(ohci_ed_t *p_ed, uint8_t dev_addr, uint16_t ep_size, uint8_t ep_addr, uint8_t xfer_type, uint8_t interval) -{ +static void ed_init(ohci_ed_t *p_ed, uint8_t dev_addr, uint16_t ep_size, uint8_t ep_addr, uint8_t xfer_type, uint8_t interval) { (void) interval; // address 0 is used as async head, which always on the list --> cannot be cleared - if (dev_addr != 0) - { - hcd_dcache_uncached(p_ed->td_tail) = 0; - hcd_dcache_uncached(p_ed->td_head).address = 0; - hcd_dcache_uncached(p_ed->next) = 0; + if (dev_addr != 0) { + p_ed->td_tail = 0; + p_ed->td_head.address = 0; + p_ed->next = 0; } tuh_bus_info_t bus_info; tuh_bus_info_get(dev_addr, &bus_info); - ohci_ed_word0 w0 = {.u = 0}; + ohci_ed_word0_t w0 = {.value = 0}; w0.dev_addr = dev_addr; w0.ep_number = ep_addr & 0x0F; w0.pid = (xfer_type == TUSB_XFER_CONTROL) ? PID_FROM_TD : (tu_edpt_dir(ep_addr) ? PID_IN : PID_OUT); @@ -345,12 +332,13 @@ static void ed_init(ohci_ed_t *p_ed, uint8_t dev_addr, uint16_t ep_size, uint8_t w0.used = 1; w0.is_interrupt_xfer = (xfer_type == TUSB_XFER_INTERRUPT ? 1 : 0); - hcd_dcache_uncached(p_ed->w0) = w0; + p_ed->w0 = w0; } static void gtd_init(ohci_gtd_t *p_td, uint8_t *data_ptr, uint16_t total_bytes) { tu_memclr(p_td, sizeof(ohci_gtd_t)); + p_td->used = 1; gtd_get_extra_data(p_td)->expected_bytes = total_bytes; p_td->buffer_rounding = 1; // less than queued length is not a error @@ -367,130 +355,109 @@ static void gtd_init(ohci_gtd_t *p_td, uint8_t *data_ptr, uint16_t total_bytes) } } -static ohci_ed_t * ed_from_addr(uint8_t dev_addr, uint8_t ep_addr) -{ - if ( tu_edpt_number(ep_addr) == 0 ) return &ohci_data.control[dev_addr].ed; +static ohci_ed_t* ed_from_addr(uint8_t dev_addr, uint8_t ep_addr) { + if (tu_edpt_number(ep_addr) == 0) { + return ed_control(dev_addr); + } ohci_ed_t* ed_pool = ohci_data.ed_pool; - - for(uint32_t i=0; iw0.dev_addr == dev_addr) && + ep_addr == tu_edpt_addr(qhd->w0.ep_number, qhd->w0.pid == PID_IN)) { + return qhd; } } return NULL; } -static ohci_ed_t * ed_find_free(void) -{ +static ohci_ed_t* ed_find_free(void) { ohci_ed_t* ed_pool = ohci_data.ed_pool; - - for(uint8_t i = 0; i < ED_MAX; i++) - { - if ( !hcd_dcache_uncached(ed_pool[i].w0).used ) return &ed_pool[i]; + for (size_t i = 0; i < ED_MAX; i++) { + ohci_ed_t* qhd = hcd_dcache_uncached(&ed_pool[i]); + if (!qhd->w0.used) { + return qhd; + } } - return NULL; } -static void ed_list_insert(ohci_ed_t * p_pre, ohci_ed_t * p_ed) -{ - hcd_dcache_uncached(p_ed->next) = hcd_dcache_uncached(p_pre->next); - hcd_dcache_uncached(p_pre->next) = (uint32_t) _phys_addr(p_ed); +static void ed_list_insert(ohci_ed_t * p_pre, ohci_ed_t * p_ed) { + p_ed->next = p_pre->next; + p_pre->next = (uint32_t) _phys_addr(p_ed); } -static void ed_list_remove_by_addr(ohci_ed_t * p_head, uint8_t dev_addr) -{ +static void ed_list_remove_by_addr(ohci_ed_t * p_head, uint8_t dev_addr) { ohci_ed_t* p_prev = p_head; - uint32_t ed_pa; - while( (ed_pa = hcd_dcache_uncached(p_prev->next)) ) - { - ohci_ed_t* ed = (ohci_ed_t*) _virt_addr((void *)ed_pa); + while (p_prev->next) { + ohci_ed_t* ed = (ohci_ed_t*)_virt_addr((void*)p_prev->next); - if (hcd_dcache_uncached(ed->w0).dev_addr == dev_addr) - { + if (ed->w0.dev_addr == dev_addr) { // Prevent Host Controller from processing this ED while we remove it - hcd_dcache_uncached(ed->w0).skip = 1; + ed->w0.skip = 1; // unlink ed, will also move up p_prev - hcd_dcache_uncached(p_prev->next) = hcd_dcache_uncached(ed->next); + p_prev->next = ed->next; // point the removed ED's next pointer to list head to make sure HC can always safely move away from this ED - hcd_dcache_uncached(ed->next) = (uint32_t) _phys_addr(p_head); - ohci_ed_word0 w0 = hcd_dcache_uncached(ed->w0); - w0.used = 0; - w0.skip = 0; - hcd_dcache_uncached(ed->w0) = w0; - }else - { - p_prev = (ohci_ed_t*) _virt_addr((void *)ed_pa); + ed->next = (uint32_t)_phys_addr(p_head); + ed->w0.used = 0; + ed->w0.skip = 0; + } else { + p_prev = (ohci_ed_t*)_virt_addr((void*)p_prev->next); } } } -static ohci_gtd_t * gtd_find_free(void) -{ - for(uint8_t i=0; i < GTD_MAX; i++) - { - if ( !ohci_data.gtd_extra[i].used ) { - ohci_data.gtd_extra[i].used = 1; +static ohci_gtd_t* gtd_find_free(void) { + for (uint8_t i = 0; i < GTD_MAX; i++) { + if (!ohci_data.gtd_pool[i].used) { return &ohci_data.gtd_pool[i]; } } - return NULL; } //--------------------------------------------------------------------+ // 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) { + (void)rhport; // TODO iso support TU_ASSERT(ep_desc->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS); //------------- Prepare Queue Head -------------// - ohci_ed_t * p_ed; - - if ( ep_desc->bEndpointAddress == 0 ) - { - p_ed = &ohci_data.control[dev_addr].ed; - }else - { + ohci_ed_t* p_ed; + if (ep_desc->bEndpointAddress == 0) { + p_ed = ed_control(dev_addr); + } else { p_ed = ed_find_free(); } TU_ASSERT(p_ed); - ed_init( p_ed, dev_addr, tu_edpt_packet_size(ep_desc), ep_desc->bEndpointAddress, - ep_desc->bmAttributes.xfer, ep_desc->bInterval ); + ed_init(p_ed, dev_addr, tu_edpt_packet_size(ep_desc), ep_desc->bEndpointAddress, + ep_desc->bmAttributes.xfer, ep_desc->bInterval); // control of dev0 is used as static async head - if ( dev_addr == 0 ) - { - hcd_dcache_uncached(p_ed->w0).skip = 0; // only need to clear skip bit + if (dev_addr == 0) { + p_ed->w0.skip = 0; // only need to clear skip bit return true; } - if ( tu_edpt_number(ep_desc->bEndpointAddress) != 0 ) { + if (tu_edpt_number(ep_desc->bEndpointAddress) != 0) { // Get an empty TD and use it as the end-of-list marker. // This marker TD will be used when a transfer is made on this EP // (and a new, empty TD will be allocated for the next-next transfer). ohci_gtd_t* gtd = gtd_find_free(); TU_ASSERT(gtd); - hcd_dcache_uncached(p_ed->td_head).address = (uint32_t)_phys_addr(gtd); - hcd_dcache_uncached(p_ed->td_tail) = (uint32_t)_phys_addr(gtd); + p_ed->td_head.address = (uint32_t)_phys_addr(gtd); + p_ed->td_tail = (uint32_t)_phys_addr(gtd); } - ed_list_insert( p_ed_head[ep_desc->bmAttributes.xfer], p_ed ); - + ed_list_insert(p_ed_head[ep_desc->bmAttributes.xfer], p_ed); return true; } @@ -499,25 +466,23 @@ bool hcd_edpt_close(uint8_t rhport, uint8_t daddr, uint8_t 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]) -{ +bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]) { (void) rhport; - ohci_ed_t* ed = &ohci_data.control[dev_addr].ed; + ohci_ed_t* ed = ed_control(dev_addr); ohci_gtd_t *qtd = &ohci_data.control[dev_addr].gtd; hcd_dcache_clean(setup_packet, 8); gtd_init(qtd, (uint8_t*)(uintptr_t) setup_packet, 8); - gtd_get_extra_data(qtd)->dev_addr = dev_addr; - gtd_get_extra_data(qtd)->ep_addr = tu_edpt_addr(0, TUSB_DIR_OUT); + qtd->index = dev_addr; qtd->pid = PID_SETUP; qtd->data_toggle = GTD_DT_DATA0; qtd->delay_interrupt = OHCI_INT_ON_COMPLETE_YES; hcd_dcache_clean(qtd, sizeof(ohci_gtd_t)); //------------- Attach TDs list to Control Endpoint -------------// - hcd_dcache_uncached(ed->td_head.address) = (uint32_t) _phys_addr(qtd); + ed->td_head.address = (uint32_t) _phys_addr(qtd); OHCI_REG->command_status_bit.control_list_filled = 1; @@ -538,32 +503,27 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * hcd_dcache_clean(buffer, buflen); } - if ( epnum == 0 ) - { - ohci_ed_t* ed = &ohci_data.control[dev_addr].ed; + ohci_ed_t * ed = ed_from_addr(dev_addr, ep_addr); + if (epnum == 0) { ohci_gtd_t* gtd = &ohci_data.control[dev_addr].gtd; gtd_init(gtd, buffer, buflen); - gtd_get_extra_data(gtd)->dev_addr = dev_addr; - gtd_get_extra_data(gtd)->ep_addr = ep_addr; - gtd->pid = dir ? PID_IN : PID_OUT; - gtd->data_toggle = GTD_DT_DATA1; // Both Data and Ack stage start with DATA1 + gtd->index = dev_addr; + gtd->pid = dir ? PID_IN : PID_OUT; + gtd->data_toggle = GTD_DT_DATA1; // Both Data and Ack stage start with DATA1 gtd->delay_interrupt = OHCI_INT_ON_COMPLETE_YES; hcd_dcache_clean(gtd, sizeof(ohci_gtd_t)); - hcd_dcache_uncached(ed->td_head).address = (uint32_t) _phys_addr(gtd); + ed->td_head.address = (uint32_t)_phys_addr(gtd); OHCI_REG->command_status_bit.control_list_filled = 1; - }else - { - ohci_ed_t * ed = ed_from_addr(dev_addr, ep_addr); - tusb_xfer_type_t xfer_type = ed_get_xfer_type( hcd_dcache_uncached(ed->w0) ); - ohci_gtd_t *gtd = (ohci_gtd_t *)_virt_addr((void *)hcd_dcache_uncached(ed->td_tail)); + } else { + tusb_xfer_type_t xfer_type = ed_get_xfer_type(ed->w0); + ohci_gtd_t* gtd = (ohci_gtd_t*)_virt_addr((void*)ed->td_tail); gtd_init(gtd, buffer, buflen); - gtd_get_extra_data(gtd)->dev_addr = dev_addr; - gtd_get_extra_data(gtd)->ep_addr = ep_addr; + gtd->index = ed-ohci_data.ed_pool; gtd->delay_interrupt = OHCI_INT_ON_COMPLETE_YES; // Insert a new, empty TD at the tail, to be used by the next transfer @@ -573,9 +533,11 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * gtd->next = (uint32_t)_phys_addr(new_gtd); hcd_dcache_clean(gtd, sizeof(ohci_gtd_t)); - hcd_dcache_uncached(ed->td_tail) = (uint32_t)_phys_addr(new_gtd); + ed->td_tail = (uint32_t)_phys_addr(new_gtd); - if (TUSB_XFER_BULK == xfer_type) OHCI_REG->command_status_bit.bulk_list_filled = 1; + if (TUSB_XFER_BULK == xfer_type) { + OHCI_REG->command_status_bit.bulk_list_filled = 1; + } } return true; @@ -593,12 +555,14 @@ bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { (void) rhport; ohci_ed_t * const p_ed = ed_from_addr(dev_addr, ep_addr); - ohci_ed_td_head td_head = hcd_dcache_uncached(p_ed->td_head); + ohci_ed_word2_t td_head = p_ed->td_head; td_head.toggle = 0; // reset data toggle td_head.halted = 0; - hcd_dcache_uncached(p_ed->td_head) = td_head; + p_ed->td_head = td_head; - if ( TUSB_XFER_BULK == ed_get_xfer_type(hcd_dcache_uncached(p_ed->w0)) ) OHCI_REG->command_status_bit.bulk_list_filled = 1; + if (TUSB_XFER_BULK == ed_get_xfer_type(p_ed->w0)) { + OHCI_REG->command_status_bit.bulk_list_filled = 1; + } return true; } @@ -632,13 +596,22 @@ static ohci_td_item_t* list_reverse(ohci_td_item_t* td_head) return _virt_addr(td_reverse_head); } -static inline bool gtd_is_control(ohci_gtd_t const * const p_qtd) -{ +TU_ATTR_ALWAYS_INLINE static inline bool gtd_is_control(ohci_gtd_t const * const p_qtd) { return ((uint32_t) p_qtd) < ((uint32_t) ohci_data.gtd_pool); // check ohci_data_t for memory layout } +TU_ATTR_ALWAYS_INLINE static inline ohci_ed_t* gtd_get_ed(ohci_gtd_t const* const p_qtd) { + ohci_ed_t* ed; + if (gtd_is_control(p_qtd)) { + ed = &ohci_data.control[p_qtd->index].ed; + } else { + ed = &ohci_data.ed_pool[p_qtd->index]; + } + return hcd_dcache_uncached(ed); +} + static gtd_extra_data_t *gtd_get_extra_data(ohci_gtd_t const * const gtd) { - if ( gtd_is_control(gtd) ) { + if (gtd_is_control(gtd)) { uint8_t idx = ((uintptr_t)gtd - (uintptr_t)&ohci_data.control->gtd) / sizeof(ohci_data.control[0]); return &ohci_data.gtd_extra_control[idx]; }else { @@ -646,85 +619,77 @@ static gtd_extra_data_t *gtd_get_extra_data(ohci_gtd_t const * const gtd) { } } -static inline uint32_t gtd_xfer_byte_left(uint32_t buffer_end, uint32_t current_buffer) -{ +TU_ATTR_ALWAYS_INLINE static inline uint32_t gtd_xfer_byte_left(uint32_t buffer_end, uint32_t current_buffer) { // 5.2.9 OHCI sample code - // CBP is 0 mean all data is transferred - if (current_buffer == 0) return 0; + if (current_buffer == 0) { + return 0; + } return (tu_align4k(buffer_end ^ current_buffer) ? 0x1000 : 0) + - tu_offset4k(buffer_end) - tu_offset4k(current_buffer) + 1; + tu_offset4k(buffer_end) - tu_offset4k(current_buffer) + 1; } -static void done_queue_isr(uint8_t hostid) -{ - (void) hostid; +static void done_queue_isr(uint8_t hostid) { + (void)hostid; // done head is written in reversed order of completion --> need to reverse the done queue first - ohci_td_item_t* td_head = list_reverse ( (ohci_td_item_t*) tu_align16(hcd_dcache_uncached(ohci_data.hcca).done_head) ); - hcd_dcache_uncached(ohci_data.hcca).done_head = 0; + ohci_td_item_t* td_head = list_reverse((ohci_td_item_t*)tu_align16(ohci_data.hcca.done_head)); + ohci_data.hcca.done_head = 0; - while( td_head != NULL ) - { + while (td_head != NULL) { // TODO check if td_head is iso td //------------- Non ISO transfer -------------// - ohci_gtd_t * const qtd = (ohci_gtd_t *) td_head; + ohci_gtd_t* const qtd = (ohci_gtd_t*) td_head; xfer_result_t const event = (qtd->condition_code == OHCI_CCODE_NO_ERROR) ? XFER_RESULT_SUCCESS : (qtd->condition_code == OHCI_CCODE_STALL) ? XFER_RESULT_STALLED : XFER_RESULT_FAILED; - - gtd_get_extra_data(qtd)->used = 0; // free TD - if ( (qtd->delay_interrupt == OHCI_INT_ON_COMPLETE_YES) || (event != XFER_RESULT_SUCCESS) ) - { - uint32_t const xferred_bytes = gtd_get_extra_data(qtd)->expected_bytes - gtd_xfer_byte_left((uint32_t) qtd->buffer_end, (uint32_t) qtd->current_buffer_pointer); - - hcd_event_xfer_complete(gtd_get_extra_data(qtd)->dev_addr, gtd_get_extra_data(qtd)->ep_addr, xferred_bytes, event, true); + qtd->used = 0; // free TD + if ((qtd->delay_interrupt == OHCI_INT_ON_COMPLETE_YES) || (event != XFER_RESULT_SUCCESS)) { + const ohci_ed_t* ed = gtd_get_ed(qtd); + const ohci_ed_word0_t ed_w0 = ed->w0; + const uint32_t xferred_bytes = gtd_get_extra_data(qtd)->expected_bytes - gtd_xfer_byte_left((uint32_t)qtd->buffer_end, (uint32_t)qtd->current_buffer_pointer); + uint8_t dir = (ed_w0.ep_number == 0) ? (qtd->pid == PID_IN) : (ed_w0.pid == PID_IN); + const uint8_t ep_addr = tu_edpt_addr(ed_w0.ep_number, dir); + hcd_event_xfer_complete(ed_w0.dev_addr, ep_addr, xferred_bytes, event, true); } - td_head = (ohci_td_item_t*) _virt_addr((void *)td_head->next); + td_head = (ohci_td_item_t*)_virt_addr((void*)td_head->next); } } void hcd_int_handler(uint8_t hostid, bool in_isr) { - (void) in_isr; - - uint32_t const int_en = OHCI_REG->interrupt_enable; + (void)in_isr; + uint32_t const int_en = OHCI_REG->interrupt_enable; uint32_t const int_status = OHCI_REG->interrupt_status & int_en; - if (int_status == 0) return; + if (int_status == 0) { + return; + } // Disable MIE as per OHCI spec 5.3 OHCI_REG->interrupt_disable = OHCI_INT_MASTER_ENABLE_MASK; // Frame number overflow - if ( int_status & OHCI_INT_FRAME_OVERFLOW_MASK ) - { + if (int_status & OHCI_INT_FRAME_OVERFLOW_MASK) { ohci_data.frame_number_hi++; } //------------- RootHub status -------------// - if ( int_status & OHCI_INT_RHPORT_STATUS_CHANGE_MASK ) - { - for (int i = 0; i < TUP_OHCI_RHPORTS; i++) - { + if (int_status & OHCI_INT_RHPORT_STATUS_CHANGE_MASK) { + for (int i = 0; i < TUP_OHCI_RHPORTS; i++) { uint32_t const rhport_status = OHCI_REG->rhport_status[i] & RHPORT_ALL_CHANGE_MASK; - if ( rhport_status & RHPORT_CONNECT_STATUS_CHANGE_MASK ) - { + if (rhport_status & RHPORT_CONNECT_STATUS_CHANGE_MASK) { // TODO check if remote wake-up - if ( OHCI_REG->rhport_status_bit[i].current_connect_status ) - { + if (OHCI_REG->rhport_status_bit[i].current_connect_status) { // TODO reset port immediately, without this controller will got 2-3 (debouncing connection status change) OHCI_REG->rhport_status[i] = RHPORT_PORT_RESET_STATUS_MASK; hcd_event_device_attach(i, true); - }else - { + } else { hcd_event_device_remove(i, true); } } - if ( rhport_status & RHPORT_PORT_SUSPEND_CHANGE_MASK) - { - + if (rhport_status & RHPORT_PORT_SUSPEND_CHANGE_MASK) { } OHCI_REG->rhport_status[i] = rhport_status; // acknowledge all interrupt @@ -732,13 +697,11 @@ void hcd_int_handler(uint8_t hostid, bool in_isr) { } //------------- Transfer Complete -------------// - if (int_status & OHCI_INT_WRITEBACK_DONEHEAD_MASK) - { + if (int_status & OHCI_INT_WRITEBACK_DONEHEAD_MASK) { done_queue_isr(hostid); } OHCI_REG->interrupt_status = int_status; // Acknowledge handled interrupt - OHCI_REG->interrupt_enable = OHCI_INT_MASTER_ENABLE_MASK; // Enable MIE } //--------------------------------------------------------------------+ diff --git a/src/portable/ohci/ohci.h b/src/portable/ohci/ohci.h index 78cac664e..ac5d2881b 100644 --- a/src/portable/ohci/ohci.h +++ b/src/portable/ohci/ohci.h @@ -79,12 +79,6 @@ TU_VERIFY_STATIC( sizeof(ohci_hcca_t) == 256, "size is not correct" ); // the _smallest_ amount that can be read/written at a time. If there were to be multiple TDs // in the same cache line, they would be required to always have the same logical ownership. // This ends up being impossible to guarantee, so we choose a design which avoids the situation entirely. -// -// TDs have a minimum alignment requirement according to the OHCI specification. This is 16 bytes for -// a general TD but 32 bytes for an isochronous TD. It happens that typical CPU cache line sizes are usually -// a power of 2 at least 32. In order to simplify code later in this file, we assume this -// as an additional requirement. -TU_VERIFY_STATIC( (CFG_TUH_MEM_DCACHE_ENABLE ? CFG_TUH_MEM_DCACHE_LINE_SIZE : 0) % 32 == 0, "cache line not multiple of 32" ); // common link item for gtd and itd for list travel // use as pointer only @@ -94,10 +88,12 @@ typedef struct TU_ATTR_ALIGNED(16) { uint32_t reserved2; }ohci_td_item_t; -typedef struct TU_ATTR_ALIGNED(CFG_TUH_MEM_DCACHE_ENABLE ? CFG_TUH_MEM_DCACHE_LINE_SIZE : 16) +typedef struct TU_ATTR_ALIGNED(TU_MAX(CFG_TUH_MEM_DCACHE_LINE_SIZE, 16)) { // Word 0 - uint32_t : 18; // can be used + uint32_t used : 1; + uint32_t index : 8; // endpoint index the gtd belongs to, or device address in case of control xfer + uint32_t : 9; // can be used uint32_t buffer_rounding : 1; uint32_t pid : 2; uint32_t delay_interrupt : 3; @@ -114,8 +110,7 @@ typedef struct TU_ATTR_ALIGNED(CFG_TUH_MEM_DCACHE_ENABLE ? CFG_TUH_MEM_DCACHE_LI // Word 3 uint8_t* buffer_end; } ohci_gtd_t; - -TU_VERIFY_STATIC( sizeof(ohci_gtd_t) == CFG_TUH_MEM_DCACHE_ENABLE ? CFG_TUH_MEM_DCACHE_LINE_SIZE : 16, "size is not correct" ); +TU_VERIFY_STATIC(sizeof(ohci_gtd_t) == TU_MAX(CFG_TUH_MEM_DCACHE_LINE_SIZE,16), "size is not correct" ); typedef union { struct { @@ -126,13 +121,14 @@ typedef union { uint32_t skip : 1; uint32_t is_iso : 1; uint32_t max_packet_size : 11; - // HCD: make use of 5 reserved bits + // HCD: make use of 5 reserved bits uint32_t used : 1; uint32_t is_interrupt_xfer : 1; uint32_t : 3; }; - uint32_t u; -} ohci_ed_word0; + uint32_t value; +} ohci_ed_word0_t; +TU_VERIFY_STATIC(sizeof(ohci_ed_word0_t) == 4, "size is not correct" ); typedef union { uint32_t address; @@ -141,26 +137,18 @@ typedef union { uint32_t toggle : 1; uint32_t : 30; }; -} ohci_ed_td_head; - -typedef struct TU_ATTR_ALIGNED(16) -{ - // Word 0 - ohci_ed_word0 w0; - - // Word 1 - uint32_t td_tail; - - // Word 2 - volatile ohci_ed_td_head td_head; - - // Word 3: next ED - uint32_t next; +} ohci_ed_word2_t; +TU_VERIFY_STATIC(sizeof(ohci_ed_word2_t) == 4, "size is not correct" ); + +typedef struct TU_ATTR_ALIGNED(TU_MAX(CFG_TUH_MEM_DCACHE_LINE_SIZE, 16)) { + ohci_ed_word0_t w0; // Word 0 + uint32_t td_tail; // Word 1 + volatile ohci_ed_word2_t td_head; // Word 2 + uint32_t next; // Word 3 } ohci_ed_t; +TU_VERIFY_STATIC(sizeof(ohci_ed_t) == TU_MAX(CFG_TUH_MEM_DCACHE_LINE_SIZE, 16), "size is not correct" ); -TU_VERIFY_STATIC( sizeof(ohci_ed_t) == 16, "size is not correct" ); - -typedef struct TU_ATTR_ALIGNED(CFG_TUH_MEM_DCACHE_ENABLE ? CFG_TUH_MEM_DCACHE_LINE_SIZE : 32) +typedef struct TU_ATTR_ALIGNED(TU_MAX(CFG_TUH_MEM_DCACHE_LINE_SIZE, 32)) { /*---------- Word 1 ----------*/ uint32_t starting_frame : 16; @@ -183,15 +171,12 @@ typedef struct TU_ATTR_ALIGNED(CFG_TUH_MEM_DCACHE_ENABLE ? CFG_TUH_MEM_DCACHE_LI volatile uint16_t offset_packetstatus[8]; } ochi_itd_t; -TU_VERIFY_STATIC( sizeof(ochi_itd_t) == CFG_TUH_MEM_DCACHE_ENABLE ? CFG_TUH_MEM_DCACHE_LINE_SIZE : 32, "size is not correct" ); +TU_VERIFY_STATIC(sizeof(ochi_itd_t) == TU_MAX(CFG_TUH_MEM_DCACHE_LINE_SIZE, 32), "size is not correct" ); typedef struct { uint16_t expected_bytes; // up to 8192 bytes so max is 13 bits - uint8_t dev_addr : 7; - uint8_t used : 1; - uint8_t ep_addr; } gtd_extra_data_t; -TU_VERIFY_STATIC( sizeof(gtd_extra_data_t) == 4, "size is not correct" ); +TU_VERIFY_STATIC(sizeof(gtd_extra_data_t) == 2, "size is not correct" ); // structure with member alignment required from large to small typedef struct TU_ATTR_ALIGNED(256) { -- cgit v1.3.1 From a97da37424f5864a58c273037c7bd92312d81fb7 Mon Sep 17 00:00:00 2001 From: 唐皮皮 Date: Thu, 9 Oct 2025 19:44:11 +0800 Subject: Fix dcd_int_enable when remapping the USB interrupt --- src/portable/st/stm32_fsdev/fsdev_at32.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/portable') diff --git a/src/portable/st/stm32_fsdev/fsdev_at32.h b/src/portable/st/stm32_fsdev/fsdev_at32.h index f7ee89995..deb1de2a8 100644 --- a/src/portable/st/stm32_fsdev/fsdev_at32.h +++ b/src/portable/st/stm32_fsdev/fsdev_at32.h @@ -175,9 +175,9 @@ void dcd_int_enable(uint8_t rhport) { // 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); + NVIC_EnableIRQ(USBFS_MAPH_IRQn); + NVIC_EnableIRQ(USBFS_MAPL_IRQn); + NVIC_EnableIRQ(USBFSWakeUp_IRQn); } else #endif { -- cgit v1.3.1 From cc82e088b5333bae3dba8fb12965271d89cd5117 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 9 Oct 2025 18:50:04 +0700 Subject: fix todo size in list_reverse() --- src/portable/ohci/ohci.c | 22 +++++++++---------- src/portable/ohci/ohci.h | 55 ++++++++++++++++++++++++------------------------ 2 files changed, 38 insertions(+), 39 deletions(-) (limited to 'src/portable') diff --git a/src/portable/ohci/ohci.c b/src/portable/ohci/ohci.c index ee85f1b6a..ee89555a3 100644 --- a/src/portable/ohci/ohci.c +++ b/src/portable/ohci/ohci.c @@ -571,20 +571,18 @@ bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { //--------------------------------------------------------------------+ // OHCI Interrupt Handler //--------------------------------------------------------------------+ -static ohci_td_item_t* list_reverse(ohci_td_item_t* td_head) -{ - ohci_td_item_t* td_reverse_head = NULL; +TU_ATTR_ALWAYS_INLINE static inline bool is_itd(ohci_td_item_t* item) { + (void) item; + return false; // ISO not supported yet +} - while(td_head != NULL) - { +static ohci_td_item_t* list_reverse(ohci_td_item_t* td_head) { + ohci_td_item_t* td_reverse_head = NULL; + while(td_head != NULL) { td_head = _virt_addr(td_head); - // FIXME: This is not the correct object size. - // However, because we have hardcoded the assumption that - // a cache line is at least 32 bytes (in ohci.h), and - // because both types of TD structs are <= 32 bytes, this - // nonetheless still works without error. - hcd_dcache_invalidate(td_head, sizeof(ohci_td_item_t)); - uint32_t next = td_head->next; + const uint32_t item_size = is_itd(td_head) ? sizeof(ohci_itd_t) : sizeof(ohci_gtd_t); + hcd_dcache_invalidate(td_head, item_size); + const uint32_t next = td_head->next; // make current's item become reverse's first item td_head->next = (uint32_t) td_reverse_head; diff --git a/src/portable/ohci/ohci.h b/src/portable/ohci/ohci.h index ac5d2881b..a6f31c7a5 100644 --- a/src/portable/ohci/ohci.h +++ b/src/portable/ohci/ohci.h @@ -48,6 +48,10 @@ enum { // tinyUSB's OHCI implementation caps number of EDs to 8 bits TU_VERIFY_STATIC (ED_MAX <= 256, "Reduce CFG_TUH_DEVICE_MAX or CFG_TUH_ENDPOINT_MAX"); +#define GTD_ALIGN_SIZE TU_MAX(CFG_TUH_MEM_DCACHE_LINE_SIZE, 16) +#define ED_ALIGN_SIZE TU_MAX(CFG_TUH_MEM_DCACHE_LINE_SIZE, 16) +#define ITD_ALIGN_SIZE TU_MAX(CFG_TUH_MEM_DCACHE_LINE_SIZE, 32) + //--------------------------------------------------------------------+ // OHCI Data Structure //--------------------------------------------------------------------+ @@ -81,17 +85,15 @@ TU_VERIFY_STATIC( sizeof(ohci_hcca_t) == 256, "size is not correct" ); // This ends up being impossible to guarantee, so we choose a design which avoids the situation entirely. // common link item for gtd and itd for list travel -// use as pointer only typedef struct TU_ATTR_ALIGNED(16) { uint32_t reserved[2]; volatile uint32_t next; uint32_t reserved2; }ohci_td_item_t; -typedef struct TU_ATTR_ALIGNED(TU_MAX(CFG_TUH_MEM_DCACHE_LINE_SIZE, 16)) -{ - // Word 0 - uint32_t used : 1; +typedef struct TU_ATTR_ALIGNED(GTD_ALIGN_SIZE) { + // Word 0 + uint32_t used : 1; uint32_t index : 8; // endpoint index the gtd belongs to, or device address in case of control xfer uint32_t : 9; // can be used uint32_t buffer_rounding : 1; @@ -101,16 +103,16 @@ typedef struct TU_ATTR_ALIGNED(TU_MAX(CFG_TUH_MEM_DCACHE_LINE_SIZE, 16)) volatile uint32_t error_count : 2; volatile uint32_t condition_code : 4; - // Word 1 - uint8_t* volatile current_buffer_pointer; + // Word 1 + uint8_t* volatile current_buffer_pointer; - // Word 2 : next TD - volatile uint32_t next; + // Word 2 : next TD + volatile uint32_t next; - // Word 3 - uint8_t* buffer_end; + // Word 3 + uint8_t* buffer_end; } ohci_gtd_t; -TU_VERIFY_STATIC(sizeof(ohci_gtd_t) == TU_MAX(CFG_TUH_MEM_DCACHE_LINE_SIZE,16), "size is not correct" ); +TU_VERIFY_STATIC(sizeof(ohci_gtd_t) == GTD_ALIGN_SIZE, "size is not correct" ); typedef union { struct { @@ -140,17 +142,16 @@ typedef union { } ohci_ed_word2_t; TU_VERIFY_STATIC(sizeof(ohci_ed_word2_t) == 4, "size is not correct" ); -typedef struct TU_ATTR_ALIGNED(TU_MAX(CFG_TUH_MEM_DCACHE_LINE_SIZE, 16)) { +typedef struct TU_ATTR_ALIGNED(ED_ALIGN_SIZE) { ohci_ed_word0_t w0; // Word 0 uint32_t td_tail; // Word 1 volatile ohci_ed_word2_t td_head; // Word 2 uint32_t next; // Word 3 } ohci_ed_t; -TU_VERIFY_STATIC(sizeof(ohci_ed_t) == TU_MAX(CFG_TUH_MEM_DCACHE_LINE_SIZE, 16), "size is not correct" ); +TU_VERIFY_STATIC(sizeof(ohci_ed_t) == ED_ALIGN_SIZE, "size is not correct" ); -typedef struct TU_ATTR_ALIGNED(TU_MAX(CFG_TUH_MEM_DCACHE_LINE_SIZE, 32)) -{ - /*---------- Word 1 ----------*/ +typedef struct TU_ATTR_ALIGNED(ITD_ALIGN_SIZE) { + /*---------- Word 1 ----------*/ uint32_t starting_frame : 16; uint32_t : 5; // can be used uint32_t delay_interrupt : 3; @@ -158,20 +159,20 @@ typedef struct TU_ATTR_ALIGNED(TU_MAX(CFG_TUH_MEM_DCACHE_LINE_SIZE, 32)) uint32_t : 1; // can be used volatile uint32_t condition_code : 4; - /*---------- Word 2 ----------*/ - uint32_t buffer_page0; // 12 lsb bits can be used - /*---------- Word 3 ----------*/ - volatile uint32_t next; + /*---------- Word 2 ----------*/ + uint32_t buffer_page0; // 12 lsb bits can be used - /*---------- Word 4 ----------*/ - uint32_t buffer_end; + /*---------- Word 3 ----------*/ + volatile uint32_t next; - /*---------- Word 5-8 ----------*/ - volatile uint16_t offset_packetstatus[8]; -} ochi_itd_t; + /*---------- Word 4 ----------*/ + uint32_t buffer_end; -TU_VERIFY_STATIC(sizeof(ochi_itd_t) == TU_MAX(CFG_TUH_MEM_DCACHE_LINE_SIZE, 32), "size is not correct" ); + /*---------- Word 5-8 ----------*/ + volatile uint16_t offset_packetstatus[8]; +} ohci_itd_t; +TU_VERIFY_STATIC(sizeof(ohci_itd_t) == ITD_ALIGN_SIZE, "size is not correct" ); typedef struct { uint16_t expected_bytes; // up to 8192 bytes so max is 13 bits -- cgit v1.3.1 From aa0fc2e08f1c2dd6f026a431e8989357fbb4c5bf Mon Sep 17 00:00:00 2001 From: poornadharshan13-rgb Date: Fri, 10 Oct 2025 10:20:19 +0530 Subject: successfully --- src/common/tusb_common.h | 23 +++++++++++++++++++---- src/portable/synopsys/dwc2/dcd_dwc2.c | 17 +++++++++-------- 2 files changed, 28 insertions(+), 12 deletions(-) (limited to 'src/portable') diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index 2b095e238..6393652a3 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -109,20 +109,35 @@ extern void* tusb_app_phys_to_virt(void *phys_addr); // This is a backport of memset_s from c11 TU_ATTR_ALWAYS_INLINE static inline int tu_memset_s(void *dest, size_t destsz, int ch, size_t count) { - // TODO may check if desst and src is not NULL - if ( count > destsz ) { + // Validate parameters + if (dest == NULL) { return -1; } + + if (count > destsz) { + return -1; + } + memset(dest, ch, count); return 0; } // This is a backport of memcpy_s from c11 TU_ATTR_ALWAYS_INLINE static inline int tu_memcpy_s(void *dest, size_t destsz, const void *src, size_t count) { - // TODO may check if desst and src is not NULL - if ( count > destsz ) { + // Validate parameters + if (dest == NULL) { return -1; } + + // For memcpy, src may be NULL only if count == 0. Reject otherwise. + if (src == NULL && count != 0) { + return -1; + } + + if (count > destsz) { + return -1; + } + memcpy(dest, src, count); return 0; } diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index 9d9172b67..e3c21a86d 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -814,17 +814,18 @@ static void handle_rxflvl_irq(uint8_t rhport) { dfifo_read_packet(dwc2, xfer->buffer, byte_count); xfer->buffer += byte_count; } + } - // short packet, minus remaining bytes (xfer_size) - if (byte_count < xfer->max_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; - } + // short packet (including ZLP when byte_count == 0), minus remaining bytes (xfer_size) + if (byte_count < xfer->max_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; } } + break; } -- cgit v1.3.1 From 83baf13dcbde66942419c03348cc88ef22575e32 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 10 Oct 2025 12:33:41 +0700 Subject: try to enable ohci for lpc55 but not working, probably clock issue --- README.rst | 8 +-- hw/bsp/lpc17/family.cmake | 1 - hw/bsp/lpc17/family.mk | 1 - hw/bsp/lpc40/family.cmake | 1 - hw/bsp/lpc40/family.mk | 1 - hw/bsp/lpc55/boards/double_m33_express/board.cmake | 5 -- hw/bsp/lpc55/boards/lpcxpresso55s28/board.cmake | 5 -- hw/bsp/lpc55/boards/lpcxpresso55s69/board.cmake | 5 -- hw/bsp/lpc55/family.c | 74 ++++++++++++++++------ hw/bsp/lpc55/family.cmake | 46 +++++++++----- src/common/tusb_mcu.h | 5 ++ src/portable/nxp/lpc17_40/hcd_lpc17_40.c | 48 -------------- src/portable/ohci/ohci.c | 11 +++- src/portable/ohci/ohci.h | 49 +++++++------- src/portable/ohci/ohci_nxp.h | 70 ++++++++++++++++++++ 15 files changed, 196 insertions(+), 134 deletions(-) delete mode 100644 src/portable/nxp/lpc17_40/hcd_lpc17_40.c create mode 100644 src/portable/ohci/ohci_nxp.h (limited to 'src/portable') diff --git a/README.rst b/README.rst index 03ad3744c..7165b72ed 100644 --- a/README.rst +++ b/README.rst @@ -160,7 +160,7 @@ Supported CPUs | +-----------------------------+--------+------+-----------+------------------------+-------------------+ | | NUC505 | ✔ | | ✔ | nuc505 | | +--------------+---------+-------------------+--------+------+-----------+------------------------+-------------------+ -| NXP | iMXRT | RT 10xx, 11xx | ✔ | ✔ | ✔ | ci_hs | | +| NXP | iMXRT | RT 10xx, 11xx | ✔ | ✔ | ✔ | ci_hs, ehci | | | +---------+-------------------+--------+------+-----------+------------------------+-------------------+ | | Kinetis | KL | ✔ | ⚠ | ✖ | ci_fs, khci | | | | +-------------------+--------+------+-----------+------------------------+-------------------+ @@ -168,15 +168,15 @@ Supported CPUs | +---------+-------------------+--------+------+-----------+------------------------+-------------------+ | | LPC | 11u, 13, 15 | ✔ | ✖ | ✖ | lpc_ip3511 | | | | +-------------------+--------+------+-----------+------------------------+-------------------+ -| | | 17, 40 | ✔ | ⚠ | ✖ | lpc17_40 | | +| | | 17, 40 | ✔ | ⚠ | ✖ | lpc17_40, ohci | | | | +-------------------+--------+------+-----------+------------------------+-------------------+ -| | | 18, 43 | ✔ | ✔ | ✔ | ci_hs | | +| | | 18, 43 | ✔ | ✔ | ✔ | ci_hs, ehci | | | | +-------------------+--------+------+-----------+------------------------+-------------------+ | | | 51u | ✔ | ✖ | ✖ | lpc_ip3511 | | | | +-------------------+--------+------+-----------+------------------------+-------------------+ | | | 54, 55 | ✔ | | ✔ | lpc_ip3511 | | | +---------+-------------------+--------+------+-----------+------------------------+-------------------+ -| | MCX | N9 | ✔ | | ✔ | ci_fs, ci_hs | | +| | MCX | N9 | ✔ | | ✔ | ci_fs, ci_hs, ehci | | | | +-------------------+--------+------+-----------+------------------------+-------------------+ | | | A15 | ✔ | | | ci_fs | | +--------------+---------+-------------------+--------+------+-----------+------------------------+-------------------+ diff --git a/hw/bsp/lpc17/family.cmake b/hw/bsp/lpc17/family.cmake index 771a0f405..c18a10e24 100644 --- a/hw/bsp/lpc17/family.cmake +++ b/hw/bsp/lpc17/family.cmake @@ -89,7 +89,6 @@ function(family_configure_example TARGET RTOS) family_add_tinyusb(${TARGET} OPT_MCU_LPC175X_6X) target_sources(${TARGET} PUBLIC ${TOP}/src/portable/nxp/lpc17_40/dcd_lpc17_40.c - ${TOP}/src/portable/nxp/lpc17_40/hcd_lpc17_40.c ${TOP}/src/portable/ohci/ohci.c ) target_link_libraries(${TARGET} PUBLIC board_${BOARD}) diff --git a/hw/bsp/lpc17/family.mk b/hw/bsp/lpc17/family.mk index e8d707ea5..f1ed1a7d0 100644 --- a/hw/bsp/lpc17/family.mk +++ b/hw/bsp/lpc17/family.mk @@ -20,7 +20,6 @@ LDFLAGS_GCC += --specs=nosys.specs --specs=nano.specs SRC_C += \ src/portable/nxp/lpc17_40/dcd_lpc17_40.c \ - src/portable/nxp/lpc17_40/hcd_lpc17_40.c \ src/portable/ohci/ohci.c \ $(MCU_DIR)/../gcc/cr_startup_lpc175x_6x.c \ $(MCU_DIR)/src/chip_17xx_40xx.c \ diff --git a/hw/bsp/lpc40/family.cmake b/hw/bsp/lpc40/family.cmake index 3a680eae6..439b27491 100644 --- a/hw/bsp/lpc40/family.cmake +++ b/hw/bsp/lpc40/family.cmake @@ -90,7 +90,6 @@ function(family_configure_example TARGET RTOS) family_add_tinyusb(${TARGET} OPT_MCU_LPC40XX) target_sources(${TARGET} PUBLIC ${TOP}/src/portable/nxp/lpc17_40/dcd_lpc17_40.c - ${TOP}/src/portable/nxp/lpc17_40/hcd_lpc17_40.c ${TOP}/src/portable/ohci/ohci.c ) target_link_libraries(${TARGET} PUBLIC board_${BOARD}) diff --git a/hw/bsp/lpc40/family.mk b/hw/bsp/lpc40/family.mk index c72631235..c21923000 100644 --- a/hw/bsp/lpc40/family.mk +++ b/hw/bsp/lpc40/family.mk @@ -18,7 +18,6 @@ LDFLAGS_GCC += --specs=nosys.specs --specs=nano.specs # All source paths should be relative to the top level. SRC_C += \ src/portable/nxp/lpc17_40/dcd_lpc17_40.c \ - src/portable/nxp/lpc17_40/hcd_lpc17_40.c \ src/portable/ohci/ohci.c \ $(MCU_DIR)/../gcc/cr_startup_lpc40xx.c \ $(MCU_DIR)/src/chip_17xx_40xx.c \ diff --git a/hw/bsp/lpc55/boards/double_m33_express/board.cmake b/hw/bsp/lpc55/boards/double_m33_express/board.cmake index 3324ce888..186655b5a 100644 --- a/hw/bsp/lpc55/boards/double_m33_express/board.cmake +++ b/hw/bsp/lpc55/boards/double_m33_express/board.cmake @@ -7,11 +7,6 @@ set(NXPLINK_DEVICE LPC55S69:LPCXpresso55S69) set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/LPC55S69_cm33_core0_uf2.ld) -# Device port default to PORT1 Highspeed -if (NOT DEFINED PORT) - set(PORT 1) -endif() - function(update_board TARGET) target_compile_definitions(${TARGET} PUBLIC CPU_LPC55S69JBD100_cm33_core0 diff --git a/hw/bsp/lpc55/boards/lpcxpresso55s28/board.cmake b/hw/bsp/lpc55/boards/lpcxpresso55s28/board.cmake index b3d0c3349..d935b70e6 100644 --- a/hw/bsp/lpc55/boards/lpcxpresso55s28/board.cmake +++ b/hw/bsp/lpc55/boards/lpcxpresso55s28/board.cmake @@ -5,11 +5,6 @@ set(JLINK_DEVICE LPC55S28) set(PYOCD_TARGET LPC55S28) set(NXPLINK_DEVICE LPC55S28:LPCXpresso55S28) -# Device port default to PORT1 Highspeed -if (NOT DEFINED PORT) - set(PORT 1) -endif() - function(update_board TARGET) target_compile_definitions(${TARGET} PUBLIC CPU_LPC55S28JBD100 diff --git a/hw/bsp/lpc55/boards/lpcxpresso55s69/board.cmake b/hw/bsp/lpc55/boards/lpcxpresso55s69/board.cmake index b52ec2f9d..f46775b27 100644 --- a/hw/bsp/lpc55/boards/lpcxpresso55s69/board.cmake +++ b/hw/bsp/lpc55/boards/lpcxpresso55s69/board.cmake @@ -5,11 +5,6 @@ set(JLINK_DEVICE LPC55S69_M33_0) set(PYOCD_TARGET LPC55S69) set(NXPLINK_DEVICE LPC55S69:LPCXpresso55S69) -# Device port default to PORT1 Highspeed -if (NOT DEFINED PORT) - set(PORT 1) -endif() - function(update_board TARGET) target_compile_definitions(${TARGET} PUBLIC CPU_LPC55S69JBD100_cm33_core0 diff --git a/hw/bsp/lpc55/family.c b/hw/bsp/lpc55/family.c index dbf8d71b7..b2e219382 100644 --- a/hw/bsp/lpc55/family.c +++ b/hw/bsp/lpc55/family.c @@ -55,6 +55,7 @@ #define IOCON_PIO_MODE_INACT 0x00u // No addition pin function #define IOCON_PIO_OPENDRAIN_DI 0x00u // Open drain is disabled #define IOCON_PIO_SLEW_STANDARD 0x00u // Standard mode, output slew rate control is enabled +#define IOCON_PIO_MODE_PULLUP 0x20u /*!<@brief Selects pull-up function */ #define IOCON_PIO_DIG_FUNC0_EN (IOCON_PIO_DIGITAL_EN | IOCON_PIO_FUNC0) // Digital pin function 0 enabled #define IOCON_PIO_DIG_FUNC1_EN (IOCON_PIO_DIGITAL_EN | IOCON_PIO_FUNC1) // Digital pin function 1 enabled @@ -197,13 +198,14 @@ void board_init(void) { USART_Init(UART_DEV, &uart_config, 12000000); #endif - // USB VBUS +#if (CFG_TUD_ENABLED && BOARD_TUD_RHPORT == 0) || (CFG_TUH_ENABLED && BOARD_TUH_RHPORT == 0) /* PORT0 PIN22 configured as USB0_VBUS */ IOCON_PinMuxSet(IOCON, 0U, 22U, IOCON_PIO_DIG_FUNC7_EN); - -#if defined(BOARD_TUD_RHPORT) && BOARD_TUD_RHPORT == 0 // Port0 is Full Speed + NVIC_ClearPendingIRQ(USB0_IRQn); + NVIC_ClearPendingIRQ(USB0_NEEDCLK_IRQn); + /* Turn on USB0 Phy */ POWER_DisablePD(kPDRUNCFG_PD_USB0_PHY); @@ -212,21 +214,55 @@ void board_init(void) { RESET_PeripheralReset(kUSB0HSL_RST_SHIFT_RSTn); RESET_PeripheralReset(kUSB0HMR_RST_SHIFT_RSTn); - // Enable USB Clock Adjustments to trim the FRO for the full speed controller - ANACTRL->FRO192M_CTRL |= ANACTRL_FRO192M_CTRL_USBCLKADJ_MASK; - CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 1, false); - CLOCK_AttachClk(kFRO_HF_to_USB0_CLK); - - /*According to reference manual, device mode setting has to be set by access usb host register */ - CLOCK_EnableClock(kCLOCK_Usbhsl0); // enable usb0 host clock - USBFSH->PORTMODE |= USBFSH_PORTMODE_DEV_ENABLE_MASK; - CLOCK_DisableClock(kCLOCK_Usbhsl0); // disable usb0 host clock - - /* enable USB Device clock */ - CLOCK_EnableUsbfs0DeviceClock(kCLOCK_UsbfsSrcFro, CLOCK_GetFreq(kCLOCK_FroHf)); + if (BOARD_TUD_RHPORT == 0) { + // Enable USB Clock Adjustments to trim the FRO for the full speed controller + ANACTRL->FRO192M_CTRL |= ANACTRL_FRO192M_CTRL_USBCLKADJ_MASK; + CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 1, false); + CLOCK_AttachClk(kFRO_HF_to_USB0_CLK); + + /*According to reference manual, device mode setting has to be set by access usb host register */ + CLOCK_EnableClock(kCLOCK_Usbhsl0); // enable usb0 host clock + USBFSH->PORTMODE |= USBFSH_PORTMODE_DEV_ENABLE_MASK; + CLOCK_DisableClock(kCLOCK_Usbhsl0); // disable usb0 host clock + /* enable USB Device clock */ + CLOCK_EnableUsbfs0DeviceClock(kCLOCK_UsbfsSrcFro, CLOCK_GetFreq(kCLOCK_FroHf)); + } else { + const uint32_t port1_pin12_config = (/* Pin is configured as USB0_PORTPWRN */ + IOCON_PIO_FUNC4 | + /* Selects pull-up function */ + IOCON_PIO_MODE_PULLUP | + /* Standard mode, output slew rate control is enabled */ + IOCON_PIO_SLEW_STANDARD | + /* Input function is not inverted */ + IOCON_PIO_INV_DI | + /* Enables digital function */ + IOCON_PIO_DIGITAL_EN | + /* Open drain is disabled */ + IOCON_PIO_OPENDRAIN_DI); + /* PORT1 PIN12 (coords: 67) is configured as USB0_PORTPWRN */ + IOCON_PinMuxSet(IOCON, 1U, 12U, port1_pin12_config); + + const uint32_t port0_pin28_config = (/* Pin is configured as USB0_OVERCURRENTN */ + IOCON_PIO_FUNC7 | + /* Selects pull-up function */ + IOCON_PIO_MODE_PULLUP | + /* Standard mode, output slew rate control is enabled */ + IOCON_PIO_SLEW_STANDARD | + /* Input function is not inverted */ + IOCON_PIO_INV_DI | + /* Enables digital function */ + IOCON_PIO_DIGITAL_EN | + /* Open drain is disabled */ + IOCON_PIO_OPENDRAIN_DI); + /* PORT0 PIN28 (coords: 66) is configured as USB0_OVERCURRENTN */ + IOCON_PinMuxSet(IOCON, 0U, 28U, port0_pin28_config); + + CLOCK_EnableUsbfs0HostClock(kCLOCK_UsbfsSrcPll1, 48000000U); + USBFSH->PORTMODE &= ~USBFSH_PORTMODE_DEV_ENABLE_MASK; + } #endif -#if defined(BOARD_TUD_RHPORT) && BOARD_TUD_RHPORT == 1 +#if (CFG_TUD_ENABLED && BOARD_TUD_RHPORT == 1) || (CFG_TUH_ENABLED && BOARD_TUH_RHPORT == 1) // Port1 is High Speed /* Turn on USB1 Phy */ @@ -266,9 +302,9 @@ void board_init(void) { // phytx |= USBPHY_TX_D_CAL(0x0C) | USBPHY_TX_TXCAL45DP(0x06) | USBPHY_TX_TXCAL45DM(0x06); // USBPHY->TX = phytx; - ARM_MPU_SetMemAttr(0, 0x44); // Normal memory, non-cacheable (inner and outer) - ARM_MPU_SetRegion(0, ARM_MPU_RBAR(0x40100000, ARM_MPU_SH_NON, 0, 1, 1), ARM_MPU_RLAR(0x40104000, 0)); - ARM_MPU_Enable(MPU_CTRL_PRIVDEFENA_Msk | MPU_CTRL_HFNMIENA_Msk); + ARM_MPU_SetMemAttr(0, 0x44); // Normal memory, non-cacheable (inner and outer) + ARM_MPU_SetRegion(0, ARM_MPU_RBAR(0x40100000, ARM_MPU_SH_NON, 0, 1, 1), ARM_MPU_RLAR(0x40104000, 0)); + ARM_MPU_Enable(MPU_CTRL_PRIVDEFENA_Msk | MPU_CTRL_HFNMIENA_Msk); #endif } diff --git a/hw/bsp/lpc55/family.cmake b/hw/bsp/lpc55/family.cmake index a89548635..506164d9d 100644 --- a/hw/bsp/lpc55/family.cmake +++ b/hw/bsp/lpc55/family.cmake @@ -12,12 +12,29 @@ set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOL set(FAMILY_MCUS LPC55 CACHE INTERNAL "") -if (NOT DEFINED PORT) - set(PORT 0) -endif() - -# Host port will be the other port if available -set(HOST_PORT $) +# ---------------------- +# Port & Speed Selection +# ---------------------- + +# default device port to USB1 highspeed, host to USB0 fullspeed +if (NOT DEFINED RHPORT_DEVICE) + set(RHPORT_DEVICE 1) +endif () +if (NOT DEFINED RHPORT_HOST) + set(RHPORT_HOST 0) +endif () + +# port 0 is fullspeed, port 1 is highspeed +set(RHPORT_SPEED OPT_MODE_FULL_SPEED OPT_MODE_HIGH_SPEED) + +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 @@ -67,22 +84,20 @@ function(add_board_target BOARD_TARGET) ) target_compile_definitions(${BOARD_TARGET} PUBLIC CFG_TUSB_MEM_ALIGN=TU_ATTR_ALIGNED\(64\) - BOARD_TUD_RHPORT=${PORT} - BOARD_TUH_RHPORT=${HOST_PORT} + BOARD_TUD_RHPORT=${RHPORT_DEVICE} + BOARD_TUD_MAX_SPEED=${RHPORT_DEVICE_SPEED} + BOARD_TUH_RHPORT=${RHPORT_HOST} + BOARD_TUH_MAX_SPEED=${RHPORT_HOST_SPEED} __STARTUP_CLEAR_BSS ) # Port 0 is Fullspeed, Port 1 is Highspeed. Port1 controller can only access USB_SRAM - if (PORT EQUAL 1) + if (RHPORT_DEVICE EQUAL 1) target_compile_definitions(${BOARD_TARGET} PUBLIC - BOARD_TUD_MAX_SPEED=OPT_MODE_HIGH_SPEED - BOARD_TUH_MAX_SPEED=OPT_MODE_FULL_SPEED CFG_TUD_MEM_SECTION=__attribute__\(\(section\(\"m_usb_global\"\)\)\) ) - else () + elseif (RHPORT_HOST EQUAL 1) target_compile_definitions(${BOARD_TARGET} PUBLIC - BOARD_TUD_MAX_SPEED=OPT_MODE_FULL_SPEED - BOARD_TUH_MAX_SPEED=OPT_MODE_HIGH_SPEED CFG_TUH_MEM_SECTION=__attribute__\(\(section\(\"m_usb_global\"\)\)\) ) endif () @@ -143,11 +158,10 @@ function(family_configure_example TARGET RTOS) family_add_tinyusb(${TARGET} OPT_MCU_LPC55) target_sources(${TARGET} PUBLIC ${TOP}/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c + ${TOP}/src/portable/ohci/ohci.c ) target_link_libraries(${TARGET} PUBLIC board_${BOARD}) - - # Flashing family_add_bin_hex(${TARGET}) family_flash_jlink(${TARGET}) diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index 1c11df114..03062beb8 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -64,6 +64,7 @@ #elif TU_CHECK_MCU(OPT_MCU_LPC175X_6X, OPT_MCU_LPC177X_8X, OPT_MCU_LPC40XX) #define TUP_DCD_ENDPOINT_MAX 16 #define TUP_USBIP_OHCI + #define TUP_USBIP_OHCI_NXP #define TUP_OHCI_RHPORTS 2 #elif TU_CHECK_MCU(OPT_MCU_LPC51UXX) @@ -78,6 +79,10 @@ #elif TU_CHECK_MCU(OPT_MCU_LPC55) // TODO USB0 has 5, USB1 has 6 #define TUP_USBIP_IP3511 + #define TUP_USBIP_OHCI + #define TUP_USBIP_OHCI_NXP + #define TUP_OHCI_RHPORTS 1 // 1 downstream port + #define TUP_DCD_ENDPOINT_MAX 6 #elif TU_CHECK_MCU(OPT_MCU_LPC18XX, OPT_MCU_LPC43XX) diff --git a/src/portable/nxp/lpc17_40/hcd_lpc17_40.c b/src/portable/nxp/lpc17_40/hcd_lpc17_40.c deleted file mode 100644 index fea3e2a66..000000000 --- a/src/portable/nxp/lpc17_40/hcd_lpc17_40.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019, 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. - */ - -#include "tusb_option.h" - -#if CFG_TUH_ENABLED && \ - (CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX) - -#include "chip.h" -#include "host/hcd.h" -#include "host/usbh.h" - -void hcd_int_enable(uint8_t rhport) -{ - (void) rhport; - NVIC_EnableIRQ(USB_IRQn); -} - -void hcd_int_disable(uint8_t rhport) -{ - (void) rhport; - NVIC_DisableIRQ(USB_IRQn); -} - -#endif diff --git a/src/portable/ohci/ohci.c b/src/portable/ohci/ohci.c index f1689b5b4..a12f7d6ed 100644 --- a/src/portable/ohci/ohci.c +++ b/src/portable/ohci/ohci.c @@ -41,13 +41,16 @@ #include "host/usbh.h" #include "ohci.h" -// TODO remove -#include "chip.h" +#if defined(TUP_USBIP_OHCI_NXP) + #include "ohci_nxp.h" +#else + #error Unsupported OHCI IP +#endif //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ -#define OHCI_REG ((ohci_registers_t *) LPC_USB_BASE) + enum { OHCI_CONTROL_FUNCSTATE_RESET = 0, @@ -181,6 +184,8 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { (void) rhport; (void) rh_init; + ohci_phy_init(rhport); + //------------- Data Structure init -------------// tu_memclr(&ohci_data, sizeof(ohci_data_t)); for(uint8_t i=0; i<32; i++) diff --git a/src/portable/ohci/ohci.h b/src/portable/ohci/ohci.h index 94bad5df7..bddb19561 100644 --- a/src/portable/ohci/ohci.h +++ b/src/portable/ohci/ohci.h @@ -192,10 +192,10 @@ typedef struct TU_ATTR_ALIGNED(256) { //--------------------------------------------------------------------+ typedef volatile struct { - uint32_t revision; + uint32_t revision; // 0x00 union { - uint32_t control; + uint32_t control; // 0x04 struct { uint32_t control_bulk_service_ratio : 2; uint32_t periodic_list_enable : 1; @@ -211,7 +211,7 @@ typedef volatile struct }; union { - uint32_t command_status; + uint32_t command_status; // 0x08 struct { uint32_t controller_reset : 1; uint32_t control_list_filled : 1; @@ -222,26 +222,24 @@ typedef volatile struct }command_status_bit; }; - uint32_t interrupt_status; - uint32_t interrupt_enable; - uint32_t interrupt_disable; - - uint32_t hcca; - uint32_t period_current_ed; - uint32_t control_head_ed; - uint32_t control_current_ed; - uint32_t bulk_head_ed; - uint32_t bulk_current_ed; - uint32_t done_head; - - uint32_t frame_interval; - uint32_t frame_remaining; - uint32_t frame_number; - uint32_t periodic_start; - uint32_t lowspeed_threshold; + uint32_t interrupt_status; // 0x0C + uint32_t interrupt_enable; // 0x10 + uint32_t interrupt_disable; // 0x14 + uint32_t hcca; // 0x18 + uint32_t period_current_ed; // 0x1C + uint32_t control_head_ed; // 0x20 + uint32_t control_current_ed; // 0x24 + uint32_t bulk_head_ed; // 0x28 + uint32_t bulk_current_ed; // 0x2C + uint32_t done_head; // 0x30 + uint32_t frame_interval; // 0x34 + uint32_t frame_remaining; // 0x38 + uint32_t frame_number; // 0x3C + uint32_t periodic_start; // 0x40 + uint32_t lowspeed_threshold; // 0x44 union { - uint32_t rh_descriptorA; + uint32_t rh_descriptorA; // 0x48 struct { uint32_t number_downstream_ports : 8; uint32_t power_switching_mode : 1; @@ -255,7 +253,7 @@ typedef volatile struct }; union { - uint32_t rh_descriptorB; + uint32_t rh_descriptorB; // 0x4C struct { uint32_t device_removable : 16; uint32_t port_power_control_mask : 16; @@ -263,9 +261,9 @@ typedef volatile struct }; union { - uint32_t rh_status; + uint32_t rh_status; // 0x50 struct { - uint32_t local_power_status : 1; // read Local Power Status; write: Clear Global Power + uint32_t local_power_status : 1; // read Local Power Status; write: Clear Global Power uint32_t over_current_indicator : 1; uint32_t : 13; uint32_t device_remote_wakeup_enable : 1; @@ -277,7 +275,8 @@ typedef volatile struct }; union { - uint32_t rhport_status[TUP_OHCI_RHPORTS]; + uint32_t rhport_status[TUP_OHCI_RHPORTS]; // 0x54 + struct { uint32_t current_connect_status : 1; uint32_t port_enable_status : 1; diff --git a/src/portable/ohci/ohci_nxp.h b/src/portable/ohci/ohci_nxp.h new file mode 100644 index 000000000..9cba05e95 --- /dev/null +++ b/src/portable/ohci/ohci_nxp.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. + */ +#ifndef TUSB_OHCI_NXP_H +#define TUSB_OHCI_NXP_H + +#if TU_CHECK_MCU(OPT_MCU_LPC175X_6X, OPT_MCU_LPC177X_8X, OPT_MCU_LPC40XX) + +#include "chip.h" +#define OHCI_REG ((ohci_registers_t *) LPC_USB_BASE) + +void hcd_int_enable(uint8_t rhport) { + (void)rhport; + NVIC_EnableIRQ(USB_IRQn); +} + +void hcd_int_disable(uint8_t rhport) { + (void)rhport; + NVIC_DisableIRQ(USB_IRQn); +} + +static void ohci_phy_init(uint8_t rhport) { + (void) rhport; +} + +#else + +#include "fsl_device_registers.h" + +// for LPC55 USB0 controller +#define OHCI_REG ((ohci_registers_t *) USBFSH_BASE) + +static void ohci_phy_init(uint8_t rhport) { + (void) rhport; +} + +void hcd_int_enable(uint8_t rhport) { + (void)rhport; + NVIC_EnableIRQ(USB0_IRQn); +} + +void hcd_int_disable(uint8_t rhport) { + (void)rhport; + NVIC_DisableIRQ(USB0_IRQn); +} +#endif + +#endif -- cgit v1.3.1 From d4fa8912c598ec6ef020d4e46ebd33c716e24dbb Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 10 Oct 2025 13:42:53 +0200 Subject: dcd/dwc2: fix EP0 mulit-packet logic, write the packet directly if num_packets = 1 Signed-off-by: HiFiPhile --- src/portable/synopsys/dwc2/dcd_dwc2.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) (limited to 'src/portable') diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index 9d9172b67..12290b6a4 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -335,7 +335,7 @@ static void edpt_schedule_packets(uint8_t rhport, const uint8_t epnum, const uin // EP0 is limited to one packet per xfer if (epnum == 0) { - total_bytes = tu_min16(_dcd_data.ep0_pending[dir], xfer->max_size); + total_bytes = tu_min16(_dcd_data.ep0_pending[dir], CFG_TUD_ENDPOINT0_SIZE); _dcd_data.ep0_pending[dir] -= total_bytes; num_packets = 1; } else { @@ -373,12 +373,29 @@ static void edpt_schedule_packets(uint8_t rhport, const uint8_t epnum, const uin } dep->diepdma = (uintptr_t) xfer->buffer; dep->diepctl = depctl.value; // enable endpoint + // Advance buffer pointer for EP0 + if (epnum == 0) { + xfer->buffer += total_bytes; + } } else { dep->diepctl = depctl.value; // enable endpoint // Enable tx fifo empty interrupt only if there is data. Note must after depctl enable if (dir == TUSB_DIR_IN && total_bytes != 0) { - dwc2->diepempmsk |= (1 << epnum); + // For num_packets = 1 we write the packet directly + if (num_packets == 1) { + // Push packet to Tx-FIFO + if (xfer->ff) { + volatile uint32_t* tx_fifo = dwc2->fifo[epnum]; + tu_fifo_read_n_const_addr_full_words(xfer->ff, (void*)(uintptr_t)tx_fifo, total_bytes); + } else { + dfifo_write_packet(dwc2, epnum, xfer->buffer, total_bytes); + xfer->buffer += total_bytes; + } + } else { + // Enable TXFE interrupt for multi-packet transfer + dwc2->diepempmsk |= (1 << epnum); + } } } } @@ -820,7 +837,6 @@ static void handle_rxflvl_irq(uint8_t rhport) { 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; } } -- cgit v1.3.1 From ee7a7c56db8d6429e9df2bf042cbbe638210100d Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 13 Oct 2025 12:41:55 +0700 Subject: get cmake build with 54h20 not tested on actual hw, probably not running --- hw/bsp/nrf/boards/nrf52833dk/board.cmake | 4 + hw/bsp/nrf/boards/nrf52833dk/board.h | 57 ++++++++++++ hw/bsp/nrf/boards/nrf52833dk/board.mk | 7 ++ hw/bsp/nrf/boards/nrf54h20dk/board.cmake | 11 +++ hw/bsp/nrf/boards/nrf54h20dk/board.h | 65 ++++++++++++++ hw/bsp/nrf/boards/nrf54h20dk/board.mk | 16 ++++ hw/bsp/nrf/boards/pca10095/board.cmake | 3 +- hw/bsp/nrf/boards/pca10095/board.mk | 1 - hw/bsp/nrf/boards/pca10100/board.cmake | 4 - hw/bsp/nrf/boards/pca10100/board.h | 57 ------------ hw/bsp/nrf/boards/pca10100/board.mk | 7 -- hw/bsp/nrf/family.c | 90 +++++++------------ hw/bsp/nrf/family.cmake | 69 +++++++++------ hw/bsp/nrf/family.mk | 10 ++- hw/bsp/nrf/linker/nrf52833_xxaa.ld | 6 -- hw/bsp/nrf/linker/nrf52840_s140_v6.ld | 6 -- hw/bsp/nrf/linker/nrf52840_xxaa.ld | 6 -- hw/bsp/nrf/linker/nrf5340_xxaa_application.ld | 6 -- hw/bsp/nrf/linker/nrf54h20_xxaa_application.ld | 21 +++++ hw/bsp/nrf/nrfx_config/nrfx_config.h | 115 +++++++++++++++++++------ hw/bsp/nrf/nrfx_config/nrfx_config_common.h | 86 ++++++++++++++++++ hw/bsp/nrf/nrfx_config/nrfx_config_ext.h | 39 +++++++++ src/common/tusb_mcu.h | 6 ++ src/portable/synopsys/dwc2/dwc2_common.h | 2 + src/portable/synopsys/dwc2/dwc2_nrf.h | 61 +++++++++++++ src/tusb_option.h | 3 +- tools/get_deps.py | 2 +- 27 files changed, 555 insertions(+), 205 deletions(-) create mode 100644 hw/bsp/nrf/boards/nrf52833dk/board.cmake create mode 100644 hw/bsp/nrf/boards/nrf52833dk/board.h create mode 100644 hw/bsp/nrf/boards/nrf52833dk/board.mk create mode 100644 hw/bsp/nrf/boards/nrf54h20dk/board.cmake create mode 100644 hw/bsp/nrf/boards/nrf54h20dk/board.h create mode 100644 hw/bsp/nrf/boards/nrf54h20dk/board.mk delete mode 100644 hw/bsp/nrf/boards/pca10100/board.cmake delete mode 100644 hw/bsp/nrf/boards/pca10100/board.h delete mode 100644 hw/bsp/nrf/boards/pca10100/board.mk create mode 100644 hw/bsp/nrf/linker/nrf54h20_xxaa_application.ld create mode 100644 hw/bsp/nrf/nrfx_config/nrfx_config_common.h create mode 100644 hw/bsp/nrf/nrfx_config/nrfx_config_ext.h create mode 100644 src/portable/synopsys/dwc2/dwc2_nrf.h (limited to 'src/portable') diff --git a/hw/bsp/nrf/boards/nrf52833dk/board.cmake b/hw/bsp/nrf/boards/nrf52833dk/board.cmake new file mode 100644 index 000000000..a925dae80 --- /dev/null +++ b/hw/bsp/nrf/boards/nrf52833dk/board.cmake @@ -0,0 +1,4 @@ +set(MCU_VARIANT nrf52833) + +function(update_board TARGET) +endfunction() diff --git a/hw/bsp/nrf/boards/nrf52833dk/board.h b/hw/bsp/nrf/boards/nrf52833dk/board.h new file mode 100644 index 000000000..8aca6dce9 --- /dev/null +++ b/hw/bsp/nrf/boards/nrf52833dk/board.h @@ -0,0 +1,57 @@ +/* + * 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: Nordic nRF52833 DK + url: https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52833-DK +*/ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +#define _PINNUM(port, pin) ((port)*32 + (pin)) + +// LED +#define LED_PIN 13 +#define LED_STATE_ON 0 + +// Button +#define BUTTON_PIN 11 +#define BUTTON_STATE_ACTIVE 0 + +// UART +#define UART_RX_PIN 8 +#define UART_TX_PIN 6 + +#ifdef __cplusplus + } +#endif + +#endif /* BOARD_H_ */ diff --git a/hw/bsp/nrf/boards/nrf52833dk/board.mk b/hw/bsp/nrf/boards/nrf52833dk/board.mk new file mode 100644 index 000000000..5fba269b7 --- /dev/null +++ b/hw/bsp/nrf/boards/nrf52833dk/board.mk @@ -0,0 +1,7 @@ +MCU_VARIANT = nrf52833 +CFLAGS += -DNRF52833_XXAA + +LD_FILE = hw/mcu/nordic/nrfx/mdk/nrf52833_xxaa.ld + +# flash using jlink +flash: flash-jlink diff --git a/hw/bsp/nrf/boards/nrf54h20dk/board.cmake b/hw/bsp/nrf/boards/nrf54h20dk/board.cmake new file mode 100644 index 000000000..fca7a56d2 --- /dev/null +++ b/hw/bsp/nrf/boards/nrf54h20dk/board.cmake @@ -0,0 +1,11 @@ +set(MCU_VARIANT nrf54h20) + +function(update_board TARGET) + # temporarily, 54h20 has multiple sram sections + target_compile_definitions(${TARGET} PUBLIC + CFG_EXAMPLE_VIDEO_READONLY + ) + target_sources(${TARGET} PRIVATE +# ${NRFX_PATH}/drivers/src/nrfx_usbreg.c + ) +endfunction() diff --git a/hw/bsp/nrf/boards/nrf54h20dk/board.h b/hw/bsp/nrf/boards/nrf54h20dk/board.h new file mode 100644 index 000000000..1c7981049 --- /dev/null +++ b/hw/bsp/nrf/boards/nrf54h20dk/board.h @@ -0,0 +1,65 @@ +/* + * 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: Nordic nRF5340 DK + url: https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF5340-DK +*/ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +#define _PINNUM(port, pin) ((port)*32 + (pin)) + +// LED +#define LED_PIN 28 +#define LED_STATE_ON 0 + +// Button +#define BUTTON_PIN 23 +#define BUTTON_STATE_ACTIVE 0 + +// UART +#define UART_RX_PIN 22 +#define UART_TX_PIN 20 + +// SPI for USB host shield +// Pin is correct but not working probably due to signal incompatible (1.8V 3v3) with MAC3421E !? +//#define MAX3421_SCK_PIN _PINNUM(1, 15) +//#define MAX3421_MOSI_PIN _PINNUM(1, 13) +//#define MAX3421_MISO_PIN _PINNUM(1, 14) +//#define MAX3421_CS_PIN _PINNUM(1, 12) +//#define MAX3421_INTR_PIN _PINNUM(1, 11) + +#ifdef __cplusplus + } +#endif + +#endif /* BOARD_H_ */ diff --git a/hw/bsp/nrf/boards/nrf54h20dk/board.mk b/hw/bsp/nrf/boards/nrf54h20dk/board.mk new file mode 100644 index 000000000..157ba3c36 --- /dev/null +++ b/hw/bsp/nrf/boards/nrf54h20dk/board.mk @@ -0,0 +1,16 @@ +MCU_VARIANT = nrf54h20_application +CFLAGS += -DNRF54H20_XXAA + +# enable max3421 host driver for this board +MAX3421_HOST = 1 + +LD_FILE = hw/mcu/nordic/nrfx/mdk/nrf5340_xxaa_application.ld + +SRC_C += hw/mcu/nordic/nrfx/drivers/src/nrfx_usbreg.c + +# caused by void SystemStoreFICRNS() (without void) in system_nrf5340_application.c +CFLAGS += -Wno-error=strict-prototypes + +# flash using jlink +JLINK_DEVICE = nrf5340_xxaa_app +flash: flash-jlink diff --git a/hw/bsp/nrf/boards/pca10095/board.cmake b/hw/bsp/nrf/boards/pca10095/board.cmake index 6d183dde6..a2bfeec89 100644 --- a/hw/bsp/nrf/boards/pca10095/board.cmake +++ b/hw/bsp/nrf/boards/pca10095/board.cmake @@ -1,4 +1,5 @@ -set(MCU_VARIANT nrf5340_application) +#set(MCU_VARIANT nrf5340_application) +set(MCU_VARIANT nrf5340) function(update_board TARGET) target_sources(${TARGET} PRIVATE diff --git a/hw/bsp/nrf/boards/pca10095/board.mk b/hw/bsp/nrf/boards/pca10095/board.mk index 20580d619..9a973150d 100644 --- a/hw/bsp/nrf/boards/pca10095/board.mk +++ b/hw/bsp/nrf/boards/pca10095/board.mk @@ -1,4 +1,3 @@ -CPU_CORE = cortex-m33 MCU_VARIANT = nrf5340_application CFLAGS += -DNRF5340_XXAA -DNRF5340_XXAA_APPLICATION diff --git a/hw/bsp/nrf/boards/pca10100/board.cmake b/hw/bsp/nrf/boards/pca10100/board.cmake deleted file mode 100644 index a925dae80..000000000 --- a/hw/bsp/nrf/boards/pca10100/board.cmake +++ /dev/null @@ -1,4 +0,0 @@ -set(MCU_VARIANT nrf52833) - -function(update_board TARGET) -endfunction() diff --git a/hw/bsp/nrf/boards/pca10100/board.h b/hw/bsp/nrf/boards/pca10100/board.h deleted file mode 100644 index 8aca6dce9..000000000 --- a/hw/bsp/nrf/boards/pca10100/board.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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: Nordic nRF52833 DK - url: https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52833-DK -*/ - -#ifndef BOARD_H_ -#define BOARD_H_ - -#ifdef __cplusplus - extern "C" { -#endif - -#define _PINNUM(port, pin) ((port)*32 + (pin)) - -// LED -#define LED_PIN 13 -#define LED_STATE_ON 0 - -// Button -#define BUTTON_PIN 11 -#define BUTTON_STATE_ACTIVE 0 - -// UART -#define UART_RX_PIN 8 -#define UART_TX_PIN 6 - -#ifdef __cplusplus - } -#endif - -#endif /* BOARD_H_ */ diff --git a/hw/bsp/nrf/boards/pca10100/board.mk b/hw/bsp/nrf/boards/pca10100/board.mk deleted file mode 100644 index 5fba269b7..000000000 --- a/hw/bsp/nrf/boards/pca10100/board.mk +++ /dev/null @@ -1,7 +0,0 @@ -MCU_VARIANT = nrf52833 -CFLAGS += -DNRF52833_XXAA - -LD_FILE = hw/mcu/nordic/nrfx/mdk/nrf52833_xxaa.ld - -# flash using jlink -flash: flash-jlink diff --git a/hw/bsp/nrf/family.c b/hw/bsp/nrf/family.c index 298ca2302..6edeacd87 100644 --- a/hw/bsp/nrf/family.c +++ b/hw/bsp/nrf/family.c @@ -45,7 +45,9 @@ #include "nrfx.h" #include "hal/nrf_gpio.h" #include "nrfx_gpiote.h" +#if !defined(NRF54H20_XXAA) #include "nrfx_power.h" +#endif #include "nrfx_uarte.h" #include "nrfx_spim.h" @@ -58,21 +60,26 @@ #pragma GCC diagnostic pop #endif - -// There is API changes between nrfx v2 and v3 -#if 85301 >= (10000*MDK_MAJOR_VERSION + 100*MDK_MINOR_VERSION + MDK_MICRO_VERSION) - // note MDK 8.53.1 is also used by nrfx v3.0.0, just skip this version and use later 3.x - #define NRFX_VER 2 -#else - #define NRFX_VER 3 +// example only supports nrfx v3 for code simplicity +#if !(defined(NRFX_CONFIG_API_VER_MAJOR) && NRFX_CONFIG_API_VER_MAJOR >= 3) && \ + !(85301 >= (10000*MDK_MAJOR_VERSION + 100*MDK_MINOR_VERSION + MDK_MICRO_VERSION)) + #error "Example requires nrfx v3.0.0 or later" #endif //--------------------------------------------------------------------+ // Forward USB interrupt events to TinyUSB IRQ Handler //--------------------------------------------------------------------+ +#if defined(NRF54H20_XXAA) +#define USBD_IRQn USBHS_IRQn +void USBHS_IRQHandler(void) { + tusb_int_handler(0, true); +} + +#else void USBD_IRQHandler(void) { tud_int_handler(0); } +#endif /*------------------------------------------------------------------*/ /* MACRO TYPEDEF CONSTANT ENUM @@ -96,39 +103,39 @@ enum { #define OUTPUTRDY_Msk POWER_USBREGSTATUS_OUTPUTRDY_Msk #endif -static nrfx_uarte_t _uart_id = NRFX_UARTE_INSTANCE(0); +static nrfx_uarte_t _uart_id = NRFX_UARTE_INSTANCE(CFG_NRFX_UARTE_INSTANCE_ID); // tinyusb function that handles power event (detected, ready, removed) // We must call it within SD's SOC event handler, or set it as power event handler if SD is not enabled. extern void tusb_hal_nrf_power_event(uint32_t event); +#if !defined(NRF54H20_XXAA) // nrf power callback, could be unused if SD is enabled or usb is disabled (board_test example) TU_ATTR_UNUSED static void power_event_handler(nrfx_power_usb_evt_t event) { tusb_hal_nrf_power_event((uint32_t) event); } +#endif //------------- Host using MAX2341E -------------// #if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 static void max3421_init(void); static nrfx_spim_t _spi = NRFX_SPIM_INSTANCE(1); - -#if NRFX_VER > 2 static nrfx_gpiote_t _gpiote = NRFX_GPIOTE_INSTANCE(0); #endif -#endif - //--------------------------------------------------------------------+ // //--------------------------------------------------------------------+ void board_init(void) { +#if !defined(NRF54H20_XXAA) // stop LF clock just in case we jump from application without reset NRF_CLOCK->TASKS_LFCLKSTOP = 1UL; // Use Internal OSC to compatible with all boards NRF_CLOCK->LFCLKSRC = LFCLK_SRC_RC; NRF_CLOCK->TASKS_LFCLKSTART = 1UL; +#endif // LED nrf_gpio_cfg_output(LED_PIN); @@ -140,6 +147,7 @@ void board_init(void) { #if CFG_TUSB_OS == OPT_OS_NONE // 1ms tick timer SysTick_Config(SystemCoreClock / 1000); + #elif CFG_TUSB_OS == OPT_OS_ZEPHYR #ifdef CONFIG_HAS_HW_NRF_USBREG // IRQ_CONNECT(USBREGULATOR_IRQn, DT_IRQ(DT_INST(0, nordic_nrf_clock), priority), nrfx_isr, nrfx_usbreg_irq_handler, 0); @@ -153,21 +161,6 @@ void board_init(void) { #endif // UART - #if NRFX_VER <= 2 - nrfx_uarte_config_t uart_cfg = { - .pseltxd = UART_TX_PIN, - .pselrxd = UART_RX_PIN, - .pselcts = NRF_UARTE_PSEL_DISCONNECTED, - .pselrts = NRF_UARTE_PSEL_DISCONNECTED, - .p_context = NULL, - .baudrate = NRF_UARTE_BAUDRATE_115200, // CFG_BOARD_UART_BAUDRATE - .interrupt_priority = 7, - .hal_cfg = { - .hwfc = NRF_UARTE_HWFC_DISABLED, - .parity = NRF_UARTE_PARITY_EXCLUDED, - } - }; - #else nrfx_uarte_config_t uart_cfg = { .txd_pin = UART_TX_PIN, .rxd_pin = UART_RX_PIN, @@ -181,7 +174,6 @@ void board_init(void) { .parity = NRF_UARTE_PARITY_EXCLUDED, } }; - #endif nrfx_uarte_init(&_uart_id, &uart_cfg, NULL); @@ -191,6 +183,7 @@ void board_init(void) { // 2 is highest for application NVIC_SetPriority(USBD_IRQn, 2); +#if !defined(NRF54H20_XXAA) // USB power may already be ready at this time -> no event generated // We need to invoke the handler based on the status initially uint32_t usb_reg; @@ -234,6 +227,7 @@ void board_init(void) { tusb_hal_nrf_power_event(USB_EVT_READY); } #endif +#endif #if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 max3421_init(); @@ -255,7 +249,9 @@ uint32_t board_button_read(void) { size_t board_get_unique_id(uint8_t id[], size_t max_len) { (void) max_len; -#ifdef NRF5340_XXAA +#if defined(NRF54H20_XXAA) + uintptr_t did_addr = (uintptr_t) NRF_FICR->BLE.ADDR; +#elif defined(NRF5340_XXAA) uintptr_t did_addr = (uintptr_t) NRF_FICR->INFO.DEVICEID; #else uintptr_t did_addr = (uintptr_t) NRF_FICR->DEVICEID; @@ -277,11 +273,7 @@ int board_uart_read(uint8_t* buf, int len) { } int board_uart_write(void const* buf, int len) { - nrfx_err_t err = nrfx_uarte_tx(&_uart_id, (uint8_t const*) buf, (size_t) len - #if NRFX_VER > 2 - ,0 - #endif - ); + nrfx_err_t err = nrfx_uarte_tx(&_uart_id, (uint8_t const*) buf, (size_t) len ,0); return (NRFX_SUCCESS == err) ? len : 0; } @@ -352,18 +344,16 @@ void nrf_error_cb(uint32_t id, uint32_t pc, uint32_t info) { // API: SPI transfer with MAX3421E, must be implemented by application //--------------------------------------------------------------------+ #if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 - -#if NRFX_VER <= 2 -void max3421_int_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action ) { - if (action != NRF_GPIOTE_POLARITY_HITOLO) return; -#else void max3421_int_handler(nrfx_gpiote_pin_t pin, nrfx_gpiote_trigger_t action, void* p_context) { (void) p_context; - if (action != NRFX_GPIOTE_TRIGGER_HITOLO) return; -#endif + if (action != NRFX_GPIOTE_TRIGGER_HITOLO) { + return; + } + if (pin != MAX3421_INTR_PIN) { + return; + } - if (pin != MAX3421_INTR_PIN) return; - tuh_int_handler(1, true); + tusb_int_handler(1, true); } static void max3421_init(void) { @@ -378,13 +368,8 @@ static void max3421_init(void) { .sck_pin = MAX3421_SCK_PIN, .mosi_pin = MAX3421_MOSI_PIN, .miso_pin = MAX3421_MISO_PIN, - #if NRFX_VER <= 2 - .ss_pin = NRFX_SPIM_PIN_NOT_USED, - .frequency = NRF_SPIM_FREQ_4M, - #else .ss_pin = NRF_SPIM_PIN_NOT_CONNECTED, .frequency = 4000000u, - #endif .ss_active_high = false, .irq_priority = 3, .orc = 0xFF, @@ -398,14 +383,6 @@ static void max3421_init(void) { TU_ASSERT(NRFX_SUCCESS == nrfx_spim_init(&_spi, &cfg, NULL, NULL), ); // max3421e interrupt pin - #if NRFX_VER <= 2 - nrfx_gpiote_init(1); - nrfx_gpiote_in_config_t in_config = NRFX_GPIOTE_CONFIG_IN_SENSE_HITOLO(true); - in_config.pull = NRF_GPIO_PIN_PULLUP; - NVIC_SetPriority(GPIOTE_IRQn, 2); - nrfx_gpiote_in_init(MAX3421_INTR_PIN, &in_config, max3421_int_handler); - nrfx_gpiote_trigger_enable(MAX3421_INTR_PIN, true); - #else nrf_gpio_pin_pull_t intr_pull = NRF_GPIO_PIN_PULLUP; nrfx_gpiote_trigger_config_t intr_trigger = { .trigger = NRFX_GPIOTE_TRIGGER_HITOLO, @@ -426,7 +403,6 @@ static void max3421_init(void) { nrfx_gpiote_input_configure(&_gpiote, MAX3421_INTR_PIN, &intr_config); nrfx_gpiote_trigger_enable(&_gpiote, MAX3421_INTR_PIN, true); - #endif } // API to enable/disable MAX3421 INTR pin interrupt diff --git a/hw/bsp/nrf/family.cmake b/hw/bsp/nrf/family.cmake index 7d0a9f6de..67aa19db2 100644 --- a/hw/bsp/nrf/family.cmake +++ b/hw/bsp/nrf/family.cmake @@ -10,17 +10,21 @@ if (NOT board_cmake_included) endif () # toolchain set up -if (MCU_VARIANT STREQUAL "nrf5340_application") +if (MCU_VARIANT STREQUAL nrf5340 OR MCU_VARIANT STREQUAL nrf54h20) set(CMAKE_SYSTEM_CPU cortex-m33 CACHE INTERNAL "System Processor") - set(JLINK_DEVICE nrf5340_xxaa_app) + set(JLINK_DEVICE ${MCU_VARIANT}_xxaa_app) else () set(CMAKE_SYSTEM_CPU cortex-m4 CACHE INTERNAL "System Processor") set(JLINK_DEVICE ${MCU_VARIANT}_xxaa) endif () -set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake) +if (MCU_VARIANT STREQUAL "nrf54h20") + set(FAMILY_MCUS NRF54 CACHE INTERNAL "") +else () + set(FAMILY_MCUS NRF5X CACHE INTERNAL "") +endif () -set(FAMILY_MCUS NRF5X CACHE INTERNAL "") +set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake) #------------------------------------ # BOARD_TARGET @@ -31,36 +35,46 @@ function(add_board_target BOARD_TARGET) return() endif () - if (MCU_VARIANT STREQUAL "nrf5340_application") - set(MCU_VARIANT_XXAA "nrf5340_xxaa_application") - else () - set(MCU_VARIANT_XXAA "${MCU_VARIANT}_xxaa") - endif () - - if (NOT DEFINED LD_FILE_GNU) - set(LD_FILE_GNU ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/linker/${MCU_VARIANT_XXAA}.ld) - endif () - - if (NOT DEFINED STARTUP_FILE_${CMAKE_C_COMPILER_ID}) - set(STARTUP_FILE_GNU ${NRFX_PATH}/mdk/gcc_startup_${MCU_VARIANT}.S) - set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) - endif () - add_library(${BOARD_TARGET} STATIC ${NRFX_PATH}/helpers/nrfx_flag32_allocator.c ${NRFX_PATH}/drivers/src/nrfx_gpiote.c ${NRFX_PATH}/drivers/src/nrfx_power.c ${NRFX_PATH}/drivers/src/nrfx_spim.c ${NRFX_PATH}/drivers/src/nrfx_uarte.c - ${NRFX_PATH}/mdk/system_${MCU_VARIANT}.c ${NRFX_PATH}/soc/nrfx_atomic.c - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) - string(TOUPPER "${MCU_VARIANT_XXAA}" MCU_VARIANT_XXAA_UPPER) + + if (MCU_VARIANT STREQUAL nrf54h20) + set(LD_FILE_GNU_DEFAULT ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/linker/${MCU_VARIANT}_xxaa_application.ld) + target_sources(${BOARD_TARGET} PUBLIC + ${NRFX_PATH}/mdk/system_nrf54h.c + ${NRFX_PATH}/mdk/gcc_startup_${MCU_VARIANT}_application.S + ) + elseif (MCU_VARIANT STREQUAL nrf5340) + set(LD_FILE_GNU_DEFAULT ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/linker/${MCU_VARIANT}_xxaa_application.ld) + target_sources(${BOARD_TARGET} PUBLIC + ${NRFX_PATH}/mdk/system_${MCU_VARIANT}_application.c + ${NRFX_PATH}/mdk/gcc_startup_${MCU_VARIANT}_application.S + ) + target_compile_definitions(${BOARD_TARGET} PUBLIC NRF5340_XXAA_APPLICATION) + else() + set(LD_FILE_GNU_DEFAULT ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/linker/${MCU_VARIANT}_xxaa.ld) + target_sources(${BOARD_TARGET} PUBLIC + ${NRFX_PATH}/mdk/system_${MCU_VARIANT}.c + ${NRFX_PATH}/mdk/gcc_startup_${MCU_VARIANT}.S + ) + endif () + + if (NOT DEFINED LD_FILE_GNU) + set(LD_FILE_GNU ${LD_FILE_GNU_DEFAULT}) + endif () + + string(TOUPPER ${MCU_VARIANT} MCU_VARIANT_UPPER) target_compile_definitions(${BOARD_TARGET} PUBLIC __STARTUP_CLEAR_BSS CONFIG_GPIO_AS_PINRESET - ${MCU_VARIANT_XXAA_UPPER} + ${MCU_VARIANT_UPPER}_XXAA + NRF_APPLICATION ) if (TRACE_ETM STREQUAL "1") @@ -137,13 +151,16 @@ function(family_configure_example TARGET RTOS) endif () # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_NRF5X) + family_add_tinyusb(${TARGET} OPT_MCU_${FAMILY_MCUS}) target_sources(${TARGET} PRIVATE ${TOP}/src/portable/nordic/nrf5x/dcd_nrf5x.c + ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c + ${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c + ${TOP}/src/portable/synopsys/dwc2/dwc2_common.c ) # Flashing -# family_add_bin_hex(${TARGET}) + # family_add_bin_hex(${TARGET}) family_flash_jlink(${TARGET}) -# family_flash_adafruit_nrfutil(${TARGET}) + # family_flash_adafruit_nrfutil(${TARGET}) endfunction() diff --git a/hw/bsp/nrf/family.mk b/hw/bsp/nrf/family.mk index a8acb1624..f3a6e2cc1 100644 --- a/hw/bsp/nrf/family.mk +++ b/hw/bsp/nrf/family.mk @@ -5,7 +5,15 @@ NRFX_PATH = hw/mcu/nordic/nrfx include $(TOP)/$(BOARD_PATH)/board.mk # nRF52 is cortex-m4, nRF53 is cortex-m33 -CPU_CORE ?= cortex-m4 +ifeq (${MCU_VARIANT},nrf5340_application) + CPU_CORE = cortex-m33 +else +ifeq (${MCU_VARIANT},nrf54h20_application) + CPU_CORE = cortex-m33 +else + CPU_CORE = cortex-m4 +endif +endif CFLAGS += \ -DCFG_TUSB_MCU=OPT_MCU_NRF5X \ diff --git a/hw/bsp/nrf/linker/nrf52833_xxaa.ld b/hw/bsp/nrf/linker/nrf52833_xxaa.ld index ae4d0e5b3..f4c46a3f1 100644 --- a/hw/bsp/nrf/linker/nrf52833_xxaa.ld +++ b/hw/bsp/nrf/linker/nrf52833_xxaa.ld @@ -12,9 +12,3 @@ MEMORY INCLUDE "nrf_common.ld" - -/* nrfx v2 linker does not define __tbss_start/end__ __sbss_start/end__*/ -__tbss_start__ = __tbss_start; -__tbss_end__ = __tbss_end; -__sbss_start__ = __sbss_start; -__sbss_end__ = __sbss_end; diff --git a/hw/bsp/nrf/linker/nrf52840_s140_v6.ld b/hw/bsp/nrf/linker/nrf52840_s140_v6.ld index 037a14196..1a2292269 100644 --- a/hw/bsp/nrf/linker/nrf52840_s140_v6.ld +++ b/hw/bsp/nrf/linker/nrf52840_s140_v6.ld @@ -36,9 +36,3 @@ SECTIONS } INSERT AFTER .data; INCLUDE "nrf_common.ld" - -/* nrfx v2 linker does not define __tbss_start/end__ __sbss_start/end__*/ -__tbss_start__ = __tbss_start; -__tbss_end__ = __tbss_end; -__sbss_start__ = __sbss_start; -__sbss_end__ = __sbss_end; diff --git a/hw/bsp/nrf/linker/nrf52840_xxaa.ld b/hw/bsp/nrf/linker/nrf52840_xxaa.ld index 2d20ba7ac..fcfe08a60 100644 --- a/hw/bsp/nrf/linker/nrf52840_xxaa.ld +++ b/hw/bsp/nrf/linker/nrf52840_xxaa.ld @@ -12,9 +12,3 @@ MEMORY } INCLUDE "nrf_common.ld" - -/* nrfx v2 linker does not define __tbss_start/end__ __sbss_start/end__*/ -__tbss_start__ = __tbss_start; -__tbss_end__ = __tbss_end; -__sbss_start__ = __sbss_start; -__sbss_end__ = __sbss_end; diff --git a/hw/bsp/nrf/linker/nrf5340_xxaa_application.ld b/hw/bsp/nrf/linker/nrf5340_xxaa_application.ld index 31762d0b2..7fd682a40 100644 --- a/hw/bsp/nrf/linker/nrf5340_xxaa_application.ld +++ b/hw/bsp/nrf/linker/nrf5340_xxaa_application.ld @@ -13,9 +13,3 @@ MEMORY INCLUDE "nrf_common.ld" - -/* nrfx v2 linker does not define __tbss_start/end__ __sbss_start/end__*/ -__tbss_start__ = __tbss_start; -__tbss_end__ = __tbss_end; -__sbss_start__ = __sbss_start; -__sbss_end__ = __sbss_end; diff --git a/hw/bsp/nrf/linker/nrf54h20_xxaa_application.ld b/hw/bsp/nrf/linker/nrf54h20_xxaa_application.ld new file mode 100644 index 000000000..0c8d7127a --- /dev/null +++ b/hw/bsp/nrf/linker/nrf54h20_xxaa_application.ld @@ -0,0 +1,21 @@ +/* Linker script to configure memory regions. */ + +SEARCH_DIR(.) +/*GROUP(-lgcc -lc) not compatible with clang*/ + +MEMORY +{ + FLASH (rx) : ORIGIN = 0xE0A0000, LENGTH = 0x40000 /* Inside global MRAM0 */ + FLASH1 (rx) : ORIGIN = 0x2F840000, LENGTH = 0x4000 /* OTP0 */ + EXTFLASH (rx) : ORIGIN = 0x70000000, LENGTH = 0x20000000 + RAM (rwx) : ORIGIN = 0x22000000, LENGTH = 0x8000 + RAM1 (rwx) : ORIGIN = 0x2F000000, LENGTH = 0x80000 /* RAM00 */ + RAM2 (rwx) : ORIGIN = 0x2F080000, LENGTH = 0x60000 /* RAM01 */ + RAM3 (rwx) : ORIGIN = 0x2F880000, LENGTH = 0x10000 /* RAM20 */ + RAM4 (rwx) : ORIGIN = 0x2F890000, LENGTH = 0x8000 /* RAM21 */ + RAM5 (rwx) : ORIGIN = 0x2FC00000, LENGTH = 0x4000 /* RAM30 (low-speed) */ + RAM6 (rwx) : ORIGIN = 0x2FC04000, LENGTH = 0x4000 /* RAM31 (low-speed) */ +} + + +INCLUDE "nrf_common.ld" diff --git a/hw/bsp/nrf/nrfx_config/nrfx_config.h b/hw/bsp/nrf/nrfx_config/nrfx_config.h index fbec4192b..88431e42c 100644 --- a/hw/bsp/nrf/nrfx_config/nrfx_config.h +++ b/hw/bsp/nrf/nrfx_config/nrfx_config.h @@ -1,46 +1,111 @@ +/* + * Copyright (c) 2019 - 2025, Nordic Semiconductor ASA + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * 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 the copyright holder 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. + */ + #ifndef NRFX_CONFIG_H__ #define NRFX_CONFIG_H__ -#define NRFX_POWER_ENABLED 1 -#define NRFX_POWER_DEFAULT_CONFIG_IRQ_PRIORITY 7 - -#define NRFX_CLOCK_ENABLED 0 -#define NRFX_GPIOTE_ENABLED 1 -#define NRFX_GPIOTE0_ENABLED 1 - -#define NRFX_UARTE_ENABLED 1 -#define NRFX_UARTE0_ENABLED 1 - -#define NRFX_SPIM_ENABLED 1 -#define NRFX_SPIM1_ENABLED 1 // use SPI1 since nrf5340 share uart with spi - -#define NRFX_PRS_ENABLED 0 -#define NRFX_USBREG_ENABLED 1 +#include "nrfx_config_common.h" #if defined(NRF51) -#include + #include #elif defined(NRF52805_XXAA) -#include + #include #elif defined(NRF52810_XXAA) -#include + #include #elif defined(NRF52811_XXAA) -#include + #include #elif defined(NRF52820_XXAA) -#include + #include #elif defined(NRF52832_XXAA) || defined (NRF52832_XXAB) -#include + #include #elif defined(NRF52833_XXAA) -#include + #include #elif defined(NRF52840_XXAA) -#include + #include #elif defined(NRF5340_XXAA_APPLICATION) -#include + #include #elif defined(NRF5340_XXAA_NETWORK) #include +#elif defined(NRF54H20_XXAA) && defined(NRF_APPLICATION) + #include +#elif defined(NRF54H20_XXAA) && defined(NRF_RADIOCORE) + #include +#elif defined(NRF54H20_XXAA) && defined(NRF_PPR) + #include +#elif defined(NRF54H20_XXAA) && defined(NRF_FLPR) + #include +#elif defined(NRF54L05_XXAA) && defined(NRF_APPLICATION) + #include +#elif defined(NRF54L05_XXAA) && defined(NRF_FLPR) + #include +#elif defined(NRF54L10_XXAA) && defined(NRF_APPLICATION) + #include +#elif defined(NRF54L10_XXAA) && defined(NRF_FLPR) + #include +#elif defined(NRF54L15_XXAA) && defined(NRF_APPLICATION) + #include +#elif defined(NRF54L15_XXAA) && defined(NRF_FLPR) + #include +#elif defined(NRF54LM20A_ENGA_XXAA) && defined(NRF_APPLICATION) + #include +#elif defined(NRF54LM20A_ENGA_XXAA) && defined(NRF_FLPR) + #include +#elif defined(NRF54LS05B_ENGA_XXAA) && defined(NRF_APPLICATION) + #include +#elif defined(NRF54LV10A_ENGA_XXAA) && defined(NRF_APPLICATION) + #include +#elif defined(NRF54LV10A_ENGA_XXAA) && defined(NRF_FLPR) + #include +#elif defined(NRF7120_ENGA_XXAA) && defined(NRF_APPLICATION) + #include +#elif defined(NRF7120_ENGA_XXAA) && defined(NRF_FLPR) + #include +#elif defined(NRF7120_ENGA_XXAA) && defined(NRF_LMAC) + #include +#elif defined(NRF7120_ENGA_XXAA) && defined(NRF_UMAC) + #include #elif defined(NRF9120_XXAA) || defined(NRF9160_XXAA) #include +#elif defined(NRF9230_ENGB_XXAA) && defined(NRF_APPLICATION) + #include +#elif defined(NRF9230_ENGB_XXAA) && defined(NRF_RADIOCORE) + #include +#elif defined(NRF9230_ENGB_XXAA) && defined(NRF_PPR) + #include +#elif defined(NRF9230_ENGB_XXAA) && defined(NRF_FLPR) + #include #else - #error "Unknown device." + #include "nrfx_config_ext.h" #endif #endif // NRFX_CONFIG_H__ diff --git a/hw/bsp/nrf/nrfx_config/nrfx_config_common.h b/hw/bsp/nrf/nrfx_config/nrfx_config_common.h new file mode 100644 index 000000000..1d75e5a66 --- /dev/null +++ b/hw/bsp/nrf/nrfx_config/nrfx_config_common.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2022 - 2025, Nordic Semiconductor ASA + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * 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 the copyright holder 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. + */ + +#ifndef NRFX_CONFIG_COMMON_H__ +#define NRFX_CONFIG_COMMON_H__ + +#ifndef NRFX_CONFIG_H__ +#error "This file should not be included directly. Include nrfx_config.h instead." +#endif + +/** @brief Symbol specifying major version of the nrfx API to be used. */ +#ifndef NRFX_CONFIG_API_VER_MAJOR +#define NRFX_CONFIG_API_VER_MAJOR 3 +#endif + +/** @brief Symbol specifying minor version of the nrfx API to be used. */ +#ifndef NRFX_CONFIG_API_VER_MINOR +#define NRFX_CONFIG_API_VER_MINOR 12 +#endif + +/** @brief Symbol specifying micro version of the nrfx API to be used. */ +#ifndef NRFX_CONFIG_API_VER_MICRO +#define NRFX_CONFIG_API_VER_MICRO 0 +#endif + +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ +#define NRFX_CLOCK_ENABLED 0 +#define NRFX_UARTE_ENABLED 1 + +#if defined(NRF54H20_XXAA) +#define NRFX_UARTE120_ENABLED 1 +#define CFG_NRFX_UARTE_INSTANCE_ID 120 + +#else + +#define NRFX_POWER_ENABLED 1 +#define NRFX_POWER_DEFAULT_CONFIG_IRQ_PRIORITY 7 + +#define NRFX_UARTE0_ENABLED 1 +#define CFG_NRFX_UARTE_INSTANCE_ID 0 + +#define NRFX_GPIOTE_ENABLED 1 +#define NRFX_GPIOTE0_ENABLED 1 + +#define NRFX_SPIM_ENABLED 1 +#define NRFX_SPIM1_ENABLED 1 // use SPI1 since nrf5340 share uart with spi +#endif + +#define NRFX_PRS_ENABLED 0 +#define NRFX_USBREG_ENABLED 1 + +#define NRF_STATIC_INLINE static inline + +#endif /* NRFX_CONFIG_COMMON_H__ */ diff --git a/hw/bsp/nrf/nrfx_config/nrfx_config_ext.h b/hw/bsp/nrf/nrfx_config/nrfx_config_ext.h new file mode 100644 index 000000000..e503e1399 --- /dev/null +++ b/hw/bsp/nrf/nrfx_config/nrfx_config_ext.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2023 - 2025, Nordic Semiconductor ASA + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * 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 the copyright holder 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. + */ + +#ifndef NRFX_CONFIG_EXT_H__ +#define NRFX_CONFIG_EXT_H__ + +#error "Unknown device." + +#endif // NRFX_CONFIG_EXT_H__ diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index 1c11df114..1f8975e55 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -137,6 +137,12 @@ // 8 CBI + 1 ISO #define TUP_DCD_ENDPOINT_MAX 9 +#elif TU_CHECK_MCU(OPT_MCU_NRF54) + #define TUP_USBIP_DWC2 + #define TUP_USBIP_DWC2_NRF + #define TUP_DCD_ENDPOINT_MAX 16 + #define CFG_TUH_DWC2_DMA_ENABLE_DEFAULT 0 + //--------------------------------------------------------------------+ // Microchip //--------------------------------------------------------------------+ diff --git a/src/portable/synopsys/dwc2/dwc2_common.h b/src/portable/synopsys/dwc2/dwc2_common.h index 33219f786..0166b0261 100644 --- a/src/portable/synopsys/dwc2/dwc2_common.h +++ b/src/portable/synopsys/dwc2/dwc2_common.h @@ -51,6 +51,8 @@ #include "dwc2_xmc.h" #elif defined(TUP_USBIP_DWC2_AT32) #include "dwc2_at32.h" +#elif defined(TUP_USBIP_DWC2_NRF) + #include "dwc2_nrf.h" #else #error "Unsupported MCUs" #endif diff --git a/src/portable/synopsys/dwc2/dwc2_nrf.h b/src/portable/synopsys/dwc2/dwc2_nrf.h new file mode 100644 index 000000000..b93571f16 --- /dev/null +++ b/src/portable/synopsys/dwc2/dwc2_nrf.h @@ -0,0 +1,61 @@ +/* + * 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_DWC2_NRF_H +#define TUSB_DWC2_NRF_H + +#include "nrf.h" + +#define DWC2_EP_MAX 16 + +static const dwc2_controller_t _dwc2_controller[] = { + { .reg_base = NRF_USBHSCORE0_NS_BASE, .irqnum = USBHS_IRQn, .ep_count = 16, .ep_fifo_size = 12288 }, +}; + +TU_ATTR_ALWAYS_INLINE static inline void dwc2_int_set(uint8_t rhport, tusb_role_t role, bool enabled) { + (void) rhport; + (void) role; + (void) enabled; +} + +#define dwc2_dcd_int_enable(_rhport) dwc2_int_set(_rhport, TUSB_ROLE_DEVICE, true) +#define dwc2_dcd_int_disable(_rhport) dwc2_int_set(_rhport, TUSB_ROLE_DEVICE, false) + +TU_ATTR_ALWAYS_INLINE static inline void dwc2_remote_wakeup_delay(void) { +} + +// 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; + (void)hs_phy_type; +} + +// 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; +} + +#endif diff --git a/src/tusb_option.h b/src/tusb_option.h index 378b5607e..dd57f6296 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -62,7 +62,8 @@ #define OPT_MCU_LPC55XX OPT_MCU_LPC55 // NRF -#define OPT_MCU_NRF5X 100 ///< Nordic nRF5x series +#define OPT_MCU_NRF5X 100 ///< Nordic nRF 52,53 series +#define OPT_MCU_NRF54 101 ///< Nordic nRF54 series // SAM #define OPT_MCU_SAMD21 200 ///< MicroChip SAMD21 diff --git a/tools/get_deps.py b/tools/get_deps.py index 36ed98a62..c243137fa 100755 --- a/tools/get_deps.py +++ b/tools/get_deps.py @@ -47,7 +47,7 @@ deps_optional = { 'b93e856211060ae825216c6a1d6aa347ec758843', 'mm32'], 'hw/mcu/nordic/nrfx': ['https://github.com/NordicSemiconductor/nrfx.git', - '7c47cc0a56ce44658e6da2458e86cd8783ccc4a2', + '11f57e578c7feea13f21c79ea0efab2630ac68c7', 'nrf'], 'hw/mcu/nuvoton': ['https://github.com/majbthrd/nuc_driver.git', '2204191ec76283371419fbcec207da02e1bc22fa', -- cgit v1.3.1 From 367044e4873fc9ca9cdac918cee684e1e08216e0 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 14 Oct 2025 20:51:49 +0700 Subject: fix lots of warnings for missing-prototypes for irqhandler --- examples/host/msc_file_explorer/CMakeLists.txt | 4 +--- hw/bsp/at32f402_405/family.c | 1 - hw/bsp/at32f423/at32f423_int.h | 2 +- hw/bsp/broadcom_32bit/family.cmake | 4 ++++ hw/bsp/broadcom_64bit/family.cmake | 4 ++++ hw/bsp/ch32f20x/ch32f20x_it.h | 12 +++++++----- hw/bsp/ch32f20x/family.c | 1 + hw/bsp/ch32v10x/ch32v10x_it.h | 14 ++++++++++++++ hw/bsp/ch32v10x/family.c | 3 ++- hw/bsp/ch32v20x/ch32v20x_it.h | 17 +++++++++++++++++ hw/bsp/ch32v20x/family.c | 3 ++- hw/bsp/ch32v30x/ch32v30x_it.h | 14 +++++++++++++- hw/bsp/ch32v30x/debug_uart.c | 3 ++- hw/bsp/ch32v30x/family.c | 3 ++- hw/bsp/da1469x/family.cmake | 5 +++++ hw/bsp/fomu/family.c | 1 - hw/bsp/fomu/family.cmake | 4 ++++ hw/bsp/gd32vf103/family.cmake | 12 ++++++++++++ hw/bsp/imxrt/family.cmake | 5 ++++- hw/bsp/kinetis_k/family.cmake | 4 ++++ hw/bsp/kinetis_k32l2/family.cmake | 4 ++++ hw/bsp/kinetis_kl/family.cmake | 4 ++++ hw/bsp/lpc13/family.cmake | 5 +++++ hw/bsp/lpc15/family.cmake | 5 +++++ hw/bsp/lpc17/family.cmake | 5 +++++ hw/bsp/lpc40/family.cmake | 5 +++++ hw/bsp/lpc51/family.cmake | 4 ++++ hw/bsp/lpc54/family.cmake | 4 ++++ hw/bsp/lpc55/family.cmake | 9 +++++---- hw/bsp/maxim/family.c | 2 ++ hw/bsp/maxim/family.cmake | 4 ++++ hw/bsp/mcx/family.cmake | 4 ++++ hw/bsp/mm32/family.cmake | 4 ++++ hw/bsp/msp430/family.c | 9 +++++---- hw/bsp/msp432e4/family.cmake | 5 +++++ hw/bsp/nrf/family.cmake | 1 - hw/bsp/ra/family.cmake | 5 +++++ hw/bsp/samd11/family.c | 5 ++--- hw/bsp/samg/family.c | 1 + hw/bsp/saml2x/family.c | 1 + hw/bsp/stm32c0/family.cmake | 5 +++++ hw/bsp/stm32f0/family.cmake | 5 +++++ hw/bsp/stm32f1/family.cmake | 5 +++++ hw/bsp/stm32f2/family.cmake | 5 +++++ hw/bsp/stm32f3/family.cmake | 5 +++++ hw/bsp/stm32f4/family.cmake | 5 +++++ hw/bsp/stm32f7/family.cmake | 5 +++++ hw/bsp/stm32g0/family.cmake | 5 +++++ hw/bsp/stm32g4/family.cmake | 5 +++++ hw/bsp/stm32h5/family.cmake | 5 +++++ hw/bsp/stm32h7/family.cmake | 5 +++++ hw/bsp/stm32h7rs/family.cmake | 5 +++++ hw/bsp/stm32l0/family.cmake | 5 +++++ hw/bsp/stm32l4/family.cmake | 5 +++++ hw/bsp/stm32n6/boards/stm32n6570dk/board.h | 10 +++++----- hw/bsp/stm32n6/boards/stm32n657nucleo/board.h | 2 +- hw/bsp/stm32n6/family.cmake | 8 +++++++- hw/bsp/stm32u0/family.cmake | 5 +++++ hw/bsp/stm32u5/family.cmake | 5 +++++ hw/bsp/stm32wb/family.cmake | 5 +++++ hw/bsp/stm32wba/family.cmake | 5 +++++ hw/bsp/tm4c/family.cmake | 4 ++++ hw/bsp/xmc4000/family.cmake | 4 ++++ src/portable/mentor/musb/musb_max32.h | 10 ++++++++++ src/portable/sunxi/dcd_sunxi_musb.c | 4 ++-- src/portable/synopsys/dwc2/dcd_dwc2.c | 1 + src/portable/wch/hcd_ch32_usbfs.c | 10 ++++++++++ tools/get_deps.py | 6 +++--- 68 files changed, 310 insertions(+), 41 deletions(-) (limited to 'src/portable') diff --git a/examples/host/msc_file_explorer/CMakeLists.txt b/examples/host/msc_file_explorer/CMakeLists.txt index 95d532fc9..e9c15b7c1 100644 --- a/examples/host/msc_file_explorer/CMakeLists.txt +++ b/examples/host/msc_file_explorer/CMakeLists.txt @@ -28,9 +28,7 @@ target_sources(${PROJECT} PUBLIC # Suppress warnings on fatfs if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") - set_source_files_properties( - ${TOP}/lib/fatfs/source/ff.c - PROPERTIES + set_source_files_properties(${TOP}/lib/fatfs/source/ff.c PROPERTIES COMPILE_FLAGS "-Wno-conversion -Wno-cast-qual" ) endif () diff --git a/hw/bsp/at32f402_405/family.c b/hw/bsp/at32f402_405/family.c index 6f3196744..beac1a7f8 100644 --- a/hw/bsp/at32f402_405/family.c +++ b/hw/bsp/at32f402_405/family.c @@ -30,7 +30,6 @@ #include "at32f402_405_clock.h" #include "at32f402_405_int.h" -#include "at32f403a_407_usb.h" #include "bsp/board_api.h" #include "board.h" diff --git a/hw/bsp/at32f423/at32f423_int.h b/hw/bsp/at32f423/at32f423_int.h index bf73ae6c0..aa707346d 100644 --- a/hw/bsp/at32f423/at32f423_int.h +++ b/hw/bsp/at32f423/at32f423_int.h @@ -39,7 +39,7 @@ extern "C" { /* exported functions ------------------------------------------------------- */ void NMI_Handler(void); -//void HardFault_Handler(void); +void HardFault_Handler(void); void MemManage_Handler(void); void BusFault_Handler(void); void UsageFault_Handler(void); diff --git a/hw/bsp/broadcom_32bit/family.cmake b/hw/bsp/broadcom_32bit/family.cmake index 5e57d8b1e..1ec54b06f 100644 --- a/hw/bsp/broadcom_32bit/family.cmake +++ b/hw/bsp/broadcom_32bit/family.cmake @@ -86,6 +86,10 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ) + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + target_include_directories(${TARGET} PUBLIC # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} diff --git a/hw/bsp/broadcom_64bit/family.cmake b/hw/bsp/broadcom_64bit/family.cmake index 1a088c2c0..e87aaa3a4 100644 --- a/hw/bsp/broadcom_64bit/family.cmake +++ b/hw/bsp/broadcom_64bit/family.cmake @@ -93,6 +93,10 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ) + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + target_include_directories(${TARGET} PUBLIC # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} diff --git a/hw/bsp/ch32f20x/ch32f20x_it.h b/hw/bsp/ch32f20x/ch32f20x_it.h index 34f3bbf96..7daf0d76e 100644 --- a/hw/bsp/ch32f20x/ch32f20x_it.h +++ b/hw/bsp/ch32f20x/ch32f20x_it.h @@ -1,9 +1,9 @@ /********************************** (C) COPYRIGHT ******************************* -* File Name : ch32f20x_it.h -* Author : WCH -* Version : V1.0.0 -* Date : 2021/08/08 -* Description : This file contains the headers of the interrupt handlers. + * File Name : ch32f20x_it.h + * Author : WCH + * Version : V1.0.0 + * Date : 2021/08/08 + * Description : This file contains the headers of the interrupt handlers. ********************************************************************************* * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. * Attention: This software (modified or not) and binary are used for @@ -21,5 +21,7 @@ void BusFault_Handler(void); void UsageFault_Handler(void); void DebugMon_Handler(void); +void USBHS_IRQHandler(void); +void SysTick_Handler(void); #endif /* __CH32F20xIT_H */ diff --git a/hw/bsp/ch32f20x/family.c b/hw/bsp/ch32f20x/family.c index 7fef71d47..7eae62fa4 100644 --- a/hw/bsp/ch32f20x/family.c +++ b/hw/bsp/ch32f20x/family.c @@ -32,6 +32,7 @@ #include "debug_uart.h" #include "ch32f20x.h" +#include "ch32f20x_it.h" #include "bsp/board_api.h" #include "board.h" diff --git a/hw/bsp/ch32v10x/ch32v10x_it.h b/hw/bsp/ch32v10x/ch32v10x_it.h index 13afc2412..34615bb69 100644 --- a/hw/bsp/ch32v10x/ch32v10x_it.h +++ b/hw/bsp/ch32v10x/ch32v10x_it.h @@ -12,4 +12,18 @@ #ifndef __CH32V10x_IT_H #define __CH32V10x_IT_H +#ifdef __cplusplus +extern "C" { +#endif + +#include "ch32v10x.h" + +void USBHD_IRQHandler(void); +void USBWakeUp_IRQHandler(void); +void SysTick_Handler(void); + +#ifdef __cplusplus +} +#endif + #endif /* __CH32V10x_IT_H */ diff --git a/hw/bsp/ch32v10x/family.c b/hw/bsp/ch32v10x/family.c index f25102494..dfc041462 100644 --- a/hw/bsp/ch32v10x/family.c +++ b/hw/bsp/ch32v10x/family.c @@ -12,6 +12,7 @@ #endif #include "ch32v10x.h" +#include "ch32v10x_it.h" #ifdef __GNUC__ #pragma GCC diagnostic pop @@ -44,7 +45,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t SysTick_Config(uint32_t ticks) { +static uint32_t SysTick_Config(uint32_t ticks) { NVIC_EnableIRQ(SysTicK_IRQn); SysTick->CTLR = 0; SysTick->CNTL0 = SysTick->CNTL1 = SysTick->CNTL2 = SysTick->CNTL3 = 0; diff --git a/hw/bsp/ch32v20x/ch32v20x_it.h b/hw/bsp/ch32v20x/ch32v20x_it.h index e49c61ae2..d1e8db255 100644 --- a/hw/bsp/ch32v20x/ch32v20x_it.h +++ b/hw/bsp/ch32v20x/ch32v20x_it.h @@ -12,4 +12,21 @@ #ifndef __CH32V20x_IT_H #define __CH32V20x_IT_H +#ifdef __cplusplus +extern "C" { +#endif + +#include "ch32v20x.h" + +void USB_LP_CAN1_RX0_IRQHandler(void); +void USB_HP_CAN1_TX_IRQHandler(void); +void USBWakeUp_IRQHandler(void); +void USBHD_IRQHandler(void); +void USBHDWakeUp_IRQHandler(void); +void SysTick_Handler(void); + +#ifdef __cplusplus +} +#endif + #endif /* __CH32V20x_IT_H */ diff --git a/hw/bsp/ch32v20x/family.c b/hw/bsp/ch32v20x/family.c index 510f82981..690acee1e 100644 --- a/hw/bsp/ch32v20x/family.c +++ b/hw/bsp/ch32v20x/family.c @@ -12,6 +12,7 @@ manufacturer: WCH #endif #include "ch32v20x.h" +#include "ch32v20x_it.h" #ifdef __GNUC__ #pragma GCC diagnostic pop @@ -74,7 +75,7 @@ __attribute__((interrupt)) void SysTick_Handler(void) { system_ticks++; } -uint32_t SysTick_Config(uint32_t ticks) { +static uint32_t SysTick_Config(uint32_t ticks) { NVIC_EnableIRQ(SysTicK_IRQn); SysTick->CTLR = 0; SysTick->SR = 0; diff --git a/hw/bsp/ch32v30x/ch32v30x_it.h b/hw/bsp/ch32v30x/ch32v30x_it.h index f3977a8be..b9bf0b82e 100644 --- a/hw/bsp/ch32v30x/ch32v30x_it.h +++ b/hw/bsp/ch32v30x/ch32v30x_it.h @@ -10,7 +10,19 @@ #ifndef __CH32V30x_IT_H #define __CH32V30x_IT_H -// #include "debug.h" +#ifdef __cplusplus +extern "C" { +#endif + +#include "ch32v30x.h" + +void USBHS_IRQHandler(void); +void OTG_FS_IRQHandler(void); +void SysTick_Handler(void); + +#ifdef __cplusplus +} +#endif #endif /* __CH32V30x_IT_H */ diff --git a/hw/bsp/ch32v30x/debug_uart.c b/hw/bsp/ch32v30x/debug_uart.c index 2fd3a9d64..4d2992c58 100644 --- a/hw/bsp/ch32v30x/debug_uart.c +++ b/hw/bsp/ch32v30x/debug_uart.c @@ -49,7 +49,8 @@ void USART1_IRQHandler(void) { __asm volatile ("call USART1_IRQHandler_impl; mret"); } -__attribute__((used)) void USART1_IRQHandler_impl(void) +void USART1_IRQHandler_impl(void) __attribute__((used)) ; +void USART1_IRQHandler_impl(void) { if(USART_GetITStatus(USART1, USART_IT_TC) != RESET) { diff --git a/hw/bsp/ch32v30x/family.c b/hw/bsp/ch32v30x/family.c index bd01f4f46..c694f1a08 100644 --- a/hw/bsp/ch32v30x/family.c +++ b/hw/bsp/ch32v30x/family.c @@ -40,6 +40,7 @@ #include "debug_uart.h" #include "ch32v30x.h" +#include "ch32v30x_it.h" #ifdef __GNUC__ #pragma GCC diagnostic pop @@ -70,7 +71,7 @@ __attribute__((interrupt)) void OTG_FS_IRQHandler(void) { // MACRO TYPEDEF CONSTANT ENUM //--------------------------------------------------------------------+ -uint32_t SysTick_Config(uint32_t ticks) { +static uint32_t SysTick_Config(uint32_t ticks) { NVIC_EnableIRQ(SysTicK_IRQn); SysTick->CTLR = 0; SysTick->SR = 0; diff --git a/hw/bsp/da1469x/family.cmake b/hw/bsp/da1469x/family.cmake index 20d6cbc44..b5bec52c8 100644 --- a/hw/bsp/da1469x/family.cmake +++ b/hw/bsp/da1469x/family.cmake @@ -118,6 +118,11 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + target_include_directories(${TARGET} PUBLIC # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} diff --git a/hw/bsp/fomu/family.c b/hw/bsp/fomu/family.c index 61943cb01..9d7977bea 100644 --- a/hw/bsp/fomu/family.c +++ b/hw/bsp/fomu/family.c @@ -38,7 +38,6 @@ //--------------------------------------------------------------------+ // Board porting API //--------------------------------------------------------------------+ - void fomu_error(uint32_t line) { (void)line; diff --git a/hw/bsp/fomu/family.cmake b/hw/bsp/fomu/family.cmake index 639373695..0c7eae90e 100644 --- a/hw/bsp/fomu/family.cmake +++ b/hw/bsp/fomu/family.cmake @@ -69,6 +69,10 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ) + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + target_include_directories(${TARGET} PUBLIC # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} diff --git a/hw/bsp/gd32vf103/family.cmake b/hw/bsp/gd32vf103/family.cmake index a47871b38..4f5a945e8 100644 --- a/hw/bsp/gd32vf103/family.cmake +++ b/hw/bsp/gd32vf103/family.cmake @@ -97,6 +97,18 @@ function(family_configure_example TARGET RTOS) ${SOC_DIR}/Common/Source/Stubs/lseek.c ${SOC_DIR}/Common/Source/Stubs/read.c ) + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties( + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c + ${SOC_DIR}/Common/Source/Stubs/sbrk.c + ${SOC_DIR}/Common/Source/Stubs/close.c + ${SOC_DIR}/Common/Source/Stubs/isatty.c + ${SOC_DIR}/Common/Source/Stubs/fstat.c + ${SOC_DIR}/Common/Source/Stubs/lseek.c + ${SOC_DIR}/Common/Source/Stubs/read.c + PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + target_include_directories(${TARGET} PUBLIC # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} diff --git a/hw/bsp/imxrt/family.cmake b/hw/bsp/imxrt/family.cmake index feec4973f..37acab06d 100644 --- a/hw/bsp/imxrt/family.cmake +++ b/hw/bsp/imxrt/family.cmake @@ -122,10 +122,13 @@ function(family_configure_example TARGET RTOS) add_board_target(board_${BOARD}) target_sources(${TARGET} PUBLIC - # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ) + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + target_include_directories(${TARGET} PUBLIC # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} diff --git a/hw/bsp/kinetis_k/family.cmake b/hw/bsp/kinetis_k/family.cmake index ce91777c9..426004b4e 100644 --- a/hw/bsp/kinetis_k/family.cmake +++ b/hw/bsp/kinetis_k/family.cmake @@ -89,6 +89,10 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ) + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + target_include_directories(${TARGET} PUBLIC # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} diff --git a/hw/bsp/kinetis_k32l2/family.cmake b/hw/bsp/kinetis_k32l2/family.cmake index 946614a03..8e1b25a95 100644 --- a/hw/bsp/kinetis_k32l2/family.cmake +++ b/hw/bsp/kinetis_k32l2/family.cmake @@ -84,6 +84,10 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ) + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + target_include_directories(${TARGET} PUBLIC # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} diff --git a/hw/bsp/kinetis_kl/family.cmake b/hw/bsp/kinetis_kl/family.cmake index 51a646258..335e67375 100644 --- a/hw/bsp/kinetis_kl/family.cmake +++ b/hw/bsp/kinetis_kl/family.cmake @@ -88,6 +88,10 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ) + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + target_include_directories(${TARGET} PUBLIC # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} diff --git a/hw/bsp/lpc13/family.cmake b/hw/bsp/lpc13/family.cmake index e3c0b18c7..4ced216cb 100644 --- a/hw/bsp/lpc13/family.cmake +++ b/hw/bsp/lpc13/family.cmake @@ -79,6 +79,11 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + target_include_directories(${TARGET} PUBLIC # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} diff --git a/hw/bsp/lpc15/family.cmake b/hw/bsp/lpc15/family.cmake index 761c5a619..f07044c24 100644 --- a/hw/bsp/lpc15/family.cmake +++ b/hw/bsp/lpc15/family.cmake @@ -81,6 +81,11 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + target_include_directories(${TARGET} PUBLIC # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} diff --git a/hw/bsp/lpc17/family.cmake b/hw/bsp/lpc17/family.cmake index 771a0f405..2cbb261ca 100644 --- a/hw/bsp/lpc17/family.cmake +++ b/hw/bsp/lpc17/family.cmake @@ -78,6 +78,11 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + target_include_directories(${TARGET} PUBLIC # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} diff --git a/hw/bsp/lpc40/family.cmake b/hw/bsp/lpc40/family.cmake index 3a680eae6..21ed18057 100644 --- a/hw/bsp/lpc40/family.cmake +++ b/hw/bsp/lpc40/family.cmake @@ -79,6 +79,11 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + target_include_directories(${TARGET} PUBLIC # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} diff --git a/hw/bsp/lpc51/family.cmake b/hw/bsp/lpc51/family.cmake index 09d97d256..615fab6b8 100644 --- a/hw/bsp/lpc51/family.cmake +++ b/hw/bsp/lpc51/family.cmake @@ -98,6 +98,10 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ) + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + target_include_directories(${TARGET} PUBLIC # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} diff --git a/hw/bsp/lpc54/family.cmake b/hw/bsp/lpc54/family.cmake index 66320870a..3a0de4648 100644 --- a/hw/bsp/lpc54/family.cmake +++ b/hw/bsp/lpc54/family.cmake @@ -126,6 +126,10 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ) + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + # https://github.com/gsteiert/sct_neopixel/pull/1 if (CMAKE_C_COMPILER_ID STREQUAL "GNU") set_source_files_properties(${TOP}/lib/sct_neopixel/sct_neopixel.c PROPERTIES diff --git a/hw/bsp/lpc55/family.cmake b/hw/bsp/lpc55/family.cmake index a89548635..08c186ca1 100644 --- a/hw/bsp/lpc55/family.cmake +++ b/hw/bsp/lpc55/family.cmake @@ -126,10 +126,11 @@ function(family_configure_example TARGET RTOS) ${TOP}/lib/sct_neopixel/sct_neopixel.c ) - # https://github.com/gsteiert/sct_neopixel/pull/1 - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - set_source_files_properties(${TOP}/lib/sct_neopixel/sct_neopixel.c PROPERTIES - COMPILE_FLAGS "-Wno-unused-parameter") + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c + PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + set_source_files_properties(${TOP}/lib/sct_neopixel/sct_neopixel.c + PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes -Wno-unused-parameter") endif () target_include_directories(${TARGET} PUBLIC diff --git a/hw/bsp/maxim/family.c b/hw/bsp/maxim/family.c index 0ef6b8c4d..92b5adb6d 100644 --- a/hw/bsp/maxim/family.c +++ b/hw/bsp/maxim/family.c @@ -31,6 +31,7 @@ #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wstrict-prototypes" // _mxc_crit_get_state() +#pragma GCC diagnostic ignored "-Wredundant-decls" #endif #include "gpio.h" @@ -154,6 +155,7 @@ uint32_t board_button_read(void) { size_t board_get_unique_id(uint8_t id[], size_t max_len) { #if defined(MAX32650) // USN is 13 bytes on this device + (void) max_len; MXC_SYS_GetUSN(id, 13); return 13; #else diff --git a/hw/bsp/maxim/family.cmake b/hw/bsp/maxim/family.cmake index 75daec753..e4b1b2c46 100644 --- a/hw/bsp/maxim/family.cmake +++ b/hw/bsp/maxim/family.cmake @@ -160,6 +160,10 @@ endfunction() function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + # Board target add_board_target(board_${BOARD}) diff --git a/hw/bsp/mcx/family.cmake b/hw/bsp/mcx/family.cmake index f857ed31a..a8f50773d 100644 --- a/hw/bsp/mcx/family.cmake +++ b/hw/bsp/mcx/family.cmake @@ -105,6 +105,10 @@ endfunction() function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + # Board target add_board_target(board_${BOARD}) diff --git a/hw/bsp/mm32/family.cmake b/hw/bsp/mm32/family.cmake index 0561a63a0..d5e62a2da 100644 --- a/hw/bsp/mm32/family.cmake +++ b/hw/bsp/mm32/family.cmake @@ -79,6 +79,10 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ) + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + target_include_directories(${TARGET} PUBLIC # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} diff --git a/hw/bsp/msp430/family.c b/hw/bsp/msp430/family.c index a45bd5f93..390a9915e 100644 --- a/hw/bsp/msp430/family.c +++ b/hw/bsp/msp430/family.c @@ -35,8 +35,8 @@ //--------------------------------------------------------------------+ // Forward USB interrupt events to TinyUSB IRQ Handler //--------------------------------------------------------------------+ -void __attribute__ ((interrupt(USB_UBM_VECTOR))) USB_UBM_ISR(void) -{ +void USB_UBM_ISR(void) __attribute__ ((interrupt(USB_UBM_VECTOR))); +void USB_UBM_ISR(void) { tud_int_handler(0); } @@ -200,8 +200,9 @@ int board_uart_write(void const * buf, int len) #if CFG_TUSB_OS == OPT_OS_NONE volatile uint32_t system_ticks = 0; -void __attribute__ ((interrupt(TIMER0_A0_VECTOR))) TIMER0_A0_ISR (void) -{ + +void TIMER0_A0_ISR (void) __attribute__ ((interrupt(TIMER0_A0_VECTOR))); +void TIMER0_A0_ISR (void) { system_ticks++; // TAxCCR0 CCIFG resets itself as soon as interrupt is invoked. } diff --git a/hw/bsp/msp432e4/family.cmake b/hw/bsp/msp432e4/family.cmake index f6939ecfe..62ab83866 100644 --- a/hw/bsp/msp432e4/family.cmake +++ b/hw/bsp/msp432e4/family.cmake @@ -77,6 +77,11 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + target_include_directories(${TARGET} PUBLIC # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} diff --git a/hw/bsp/nrf/family.cmake b/hw/bsp/nrf/family.cmake index cc2b7a2e5..3384aeaf3 100644 --- a/hw/bsp/nrf/family.cmake +++ b/hw/bsp/nrf/family.cmake @@ -141,7 +141,6 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ) - if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") endif () diff --git a/hw/bsp/ra/family.cmake b/hw/bsp/ra/family.cmake index 42a32631c..bf6bcfb4a 100644 --- a/hw/bsp/ra/family.cmake +++ b/hw/bsp/ra/family.cmake @@ -127,6 +127,11 @@ function(family_configure_example TARGET RTOS) # Explicitly added bsp_rom_registers here, otherwise MCU can be bricked if g_bsp_rom_registers is dropped by linker ${FSP_RA}/src/bsp/mcu/all/bsp_rom_registers.c ) + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${FSP_RA}/src/bsp/mcu/all/bsp_rom_registers.c PROPERTIES COMPILE_FLAGS "-Wno-undef") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + target_include_directories(${TARGET} PUBLIC # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} diff --git a/hw/bsp/samd11/family.c b/hw/bsp/samd11/family.c index 79ca9de02..62e060c8e 100644 --- a/hw/bsp/samd11/family.c +++ b/hw/bsp/samd11/family.c @@ -155,12 +155,11 @@ uint32_t board_millis(void) return system_ticks; } -void _init(void) -{ +void _init(void); +void _init(void) { // This _init() standin makes certain GCC environments happier. // They expect the main binary to have a constructor called _init; but don't provide a weak default. // Providing an empty constructor satisfies this odd case, and doesn't harm anything. } - #endif diff --git a/hw/bsp/samg/family.c b/hw/bsp/samg/family.c index 8db429e79..234dc0ec0 100644 --- a/hw/bsp/samg/family.c +++ b/hw/bsp/samg/family.c @@ -154,6 +154,7 @@ uint32_t board_millis(void) { // 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/saml2x/family.c b/hw/bsp/saml2x/family.c index cdc65baf1..275dbbd2e 100644 --- a/hw/bsp/saml2x/family.c +++ b/hw/bsp/saml2x/family.c @@ -167,6 +167,7 @@ uint32_t board_millis(void) { #endif +void _init(void); void _init(void) { } diff --git a/hw/bsp/stm32c0/family.cmake b/hw/bsp/stm32c0/family.cmake index c6a90fff6..85562d474 100644 --- a/hw/bsp/stm32c0/family.cmake +++ b/hw/bsp/stm32c0/family.cmake @@ -94,6 +94,11 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + target_include_directories(${TARGET} PUBLIC # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} diff --git a/hw/bsp/stm32f0/family.cmake b/hw/bsp/stm32f0/family.cmake index 12c7b592c..8d584a8e1 100644 --- a/hw/bsp/stm32f0/family.cmake +++ b/hw/bsp/stm32f0/family.cmake @@ -92,6 +92,11 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + target_include_directories(${TARGET} PUBLIC # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} diff --git a/hw/bsp/stm32f1/family.cmake b/hw/bsp/stm32f1/family.cmake index cbb9c3568..72fe17482 100644 --- a/hw/bsp/stm32f1/family.cmake +++ b/hw/bsp/stm32f1/family.cmake @@ -91,6 +91,11 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + target_include_directories(${TARGET} PUBLIC # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} diff --git a/hw/bsp/stm32f2/family.cmake b/hw/bsp/stm32f2/family.cmake index dc6bc2885..30ee23eb9 100644 --- a/hw/bsp/stm32f2/family.cmake +++ b/hw/bsp/stm32f2/family.cmake @@ -91,6 +91,11 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + target_include_directories(${TARGET} PUBLIC # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} diff --git a/hw/bsp/stm32f3/family.cmake b/hw/bsp/stm32f3/family.cmake index 0ba2920d5..b708c667f 100644 --- a/hw/bsp/stm32f3/family.cmake +++ b/hw/bsp/stm32f3/family.cmake @@ -89,6 +89,11 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + target_include_directories(${TARGET} PUBLIC # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} diff --git a/hw/bsp/stm32f4/family.cmake b/hw/bsp/stm32f4/family.cmake index db5736192..18e8676c5 100644 --- a/hw/bsp/stm32f4/family.cmake +++ b/hw/bsp/stm32f4/family.cmake @@ -117,6 +117,11 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + target_include_directories(${TARGET} PUBLIC # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} diff --git a/hw/bsp/stm32f7/family.cmake b/hw/bsp/stm32f7/family.cmake index 1a3365332..48c0edae6 100644 --- a/hw/bsp/stm32f7/family.cmake +++ b/hw/bsp/stm32f7/family.cmake @@ -119,6 +119,11 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + target_include_directories(${TARGET} PUBLIC # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} diff --git a/hw/bsp/stm32g0/family.cmake b/hw/bsp/stm32g0/family.cmake index 4da26f27e..d489a40b5 100644 --- a/hw/bsp/stm32g0/family.cmake +++ b/hw/bsp/stm32g0/family.cmake @@ -93,6 +93,11 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + target_include_directories(${TARGET} PUBLIC # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} diff --git a/hw/bsp/stm32g4/family.cmake b/hw/bsp/stm32g4/family.cmake index 5ec9926fe..3a4c8ae32 100644 --- a/hw/bsp/stm32g4/family.cmake +++ b/hw/bsp/stm32g4/family.cmake @@ -89,6 +89,11 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + target_include_directories(${TARGET} PUBLIC # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} diff --git a/hw/bsp/stm32h5/family.cmake b/hw/bsp/stm32h5/family.cmake index 1df6bcb90..1240901e8 100644 --- a/hw/bsp/stm32h5/family.cmake +++ b/hw/bsp/stm32h5/family.cmake @@ -93,6 +93,11 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + target_include_directories(${TARGET} PUBLIC # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} diff --git a/hw/bsp/stm32h7/family.cmake b/hw/bsp/stm32h7/family.cmake index b4f0bebbf..a1e49d1fd 100644 --- a/hw/bsp/stm32h7/family.cmake +++ b/hw/bsp/stm32h7/family.cmake @@ -124,6 +124,11 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + target_include_directories(${TARGET} PUBLIC # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} diff --git a/hw/bsp/stm32h7rs/family.cmake b/hw/bsp/stm32h7rs/family.cmake index 40230ef12..e67cabd4b 100644 --- a/hw/bsp/stm32h7rs/family.cmake +++ b/hw/bsp/stm32h7rs/family.cmake @@ -127,6 +127,11 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + target_include_directories(${TARGET} PUBLIC # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} diff --git a/hw/bsp/stm32l0/family.cmake b/hw/bsp/stm32l0/family.cmake index 954bdb158..3278d2645 100644 --- a/hw/bsp/stm32l0/family.cmake +++ b/hw/bsp/stm32l0/family.cmake @@ -93,6 +93,11 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + target_include_directories(${TARGET} PUBLIC # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} diff --git a/hw/bsp/stm32l4/family.cmake b/hw/bsp/stm32l4/family.cmake index eebcff4f3..8d44f2506 100644 --- a/hw/bsp/stm32l4/family.cmake +++ b/hw/bsp/stm32l4/family.cmake @@ -93,6 +93,11 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + target_include_directories(${TARGET} PUBLIC # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} diff --git a/hw/bsp/stm32n6/boards/stm32n6570dk/board.h b/hw/bsp/stm32n6/boards/stm32n6570dk/board.h index a3d945f76..bbcad6340 100644 --- a/hw/bsp/stm32n6/boards/stm32n6570dk/board.h +++ b/hw/bsp/stm32n6/boards/stm32n6570dk/board.h @@ -97,7 +97,7 @@ static board_pindef_t board_pindef[] = { //--------------------------------------------------------------------+ // RCC Clock //--------------------------------------------------------------------+ -void SystemClock_Config(void) { +static void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; /* Configure the power domain */ @@ -214,7 +214,7 @@ static I2C_HandleTypeDef i2c_handle = { }}; static TCPP0203_Object_t tcpp0203_obj = {0}; -int32_t board_tcpp0203_init(void) { +static 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); @@ -231,16 +231,16 @@ int32_t board_tcpp0203_init(void) { return 0; } -int32_t board_tcpp0203_deinit(void) { +static int32_t board_tcpp0203_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; } diff --git a/hw/bsp/stm32n6/boards/stm32n657nucleo/board.h b/hw/bsp/stm32n6/boards/stm32n657nucleo/board.h index 963ecad61..33c68f7cf 100644 --- a/hw/bsp/stm32n6/boards/stm32n657nucleo/board.h +++ b/hw/bsp/stm32n6/boards/stm32n657nucleo/board.h @@ -97,7 +97,7 @@ static board_pindef_t board_pindef[] = { //--------------------------------------------------------------------+ // RCC Clock //--------------------------------------------------------------------+ -void SystemClock_Config(void) { +static void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; /* Configure the power domain */ diff --git a/hw/bsp/stm32n6/family.cmake b/hw/bsp/stm32n6/family.cmake index 76763937e..e1b8524bf 100644 --- a/hw/bsp/stm32n6/family.cmake +++ b/hw/bsp/stm32n6/family.cmake @@ -76,7 +76,7 @@ function(add_board_target BOARD_TARGET) ) target_include_directories(${BOARD_TARGET} PUBLIC ${CMAKE_CURRENT_FUNCTION_LIST_DIR} - ${CMSIS_5}/CMSIS/Core/Include + ${TOP}/lib/CMSIS_6/CMSIS/Core/Include ${ST_CMSIS}/Include ${ST_HAL_DRIVER}/Inc ) @@ -125,6 +125,12 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c + PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + target_include_directories(${TARGET} PUBLIC # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} diff --git a/hw/bsp/stm32u0/family.cmake b/hw/bsp/stm32u0/family.cmake index fefaea9de..535b4716f 100644 --- a/hw/bsp/stm32u0/family.cmake +++ b/hw/bsp/stm32u0/family.cmake @@ -94,6 +94,11 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + target_include_directories(${TARGET} PUBLIC # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} diff --git a/hw/bsp/stm32u5/family.cmake b/hw/bsp/stm32u5/family.cmake index 7a5935961..f1f9f6502 100644 --- a/hw/bsp/stm32u5/family.cmake +++ b/hw/bsp/stm32u5/family.cmake @@ -93,6 +93,11 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + target_include_directories(${TARGET} PUBLIC # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} diff --git a/hw/bsp/stm32wb/family.cmake b/hw/bsp/stm32wb/family.cmake index 0ea937257..e749e2fcc 100644 --- a/hw/bsp/stm32wb/family.cmake +++ b/hw/bsp/stm32wb/family.cmake @@ -96,6 +96,11 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + target_include_directories(${TARGET} PUBLIC # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} diff --git a/hw/bsp/stm32wba/family.cmake b/hw/bsp/stm32wba/family.cmake index 3f42879be..391989a6d 100644 --- a/hw/bsp/stm32wba/family.cmake +++ b/hw/bsp/stm32wba/family.cmake @@ -111,6 +111,11 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + target_include_directories(${TARGET} PUBLIC # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} diff --git a/hw/bsp/tm4c/family.cmake b/hw/bsp/tm4c/family.cmake index e1cf94e96..7fe256fb6 100644 --- a/hw/bsp/tm4c/family.cmake +++ b/hw/bsp/tm4c/family.cmake @@ -61,6 +61,10 @@ endfunction() function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + # Board target add_board_target(board_${BOARD}) diff --git a/hw/bsp/xmc4000/family.cmake b/hw/bsp/xmc4000/family.cmake index 6edd72caf..594bd1116 100644 --- a/hw/bsp/xmc4000/family.cmake +++ b/hw/bsp/xmc4000/family.cmake @@ -64,6 +64,10 @@ endfunction() function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + # Board target add_board_target(board_${BOARD}) diff --git a/src/portable/mentor/musb/musb_max32.h b/src/portable/mentor/musb/musb_max32.h index 35849b5f8..599de2ca1 100644 --- a/src/portable/mentor/musb/musb_max32.h +++ b/src/portable/mentor/musb/musb_max32.h @@ -31,7 +31,17 @@ extern "C" { #endif +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wredundant-decls" +#endif + #include "mxc_device.h" + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + #include "usbhs_regs.h" #define MUSB_CFG_SHARED_FIFO 1 // shared FIFO for TX and RX endpoints diff --git a/src/portable/sunxi/dcd_sunxi_musb.c b/src/portable/sunxi/dcd_sunxi_musb.c index 9801a485f..f1f4897cb 100644 --- a/src/portable/sunxi/dcd_sunxi_musb.c +++ b/src/portable/sunxi/dcd_sunxi_musb.c @@ -176,7 +176,7 @@ static void USBC_ForceVbusValidToHigh(void) USBC_Writel(reg_val, USBC_REG_ISCR(USBC0_BASE)); } -void USBC_SelectBus(u32 io_type, u32 ep_type, u32 ep_index) +static void USBC_SelectBus(u32 io_type, u32 ep_type, u32 ep_index) { u32 reg_val = 0; @@ -952,7 +952,7 @@ void dcd_remote_wakeup(uint8_t rhport) { (void)rhport; USBC_REG_set_bit_b(USBC_BP_POWER_D_RESUME, USBC_REG_PCTL(USBC0_BASE)); - delay_ms(10); + tusb_time_delay_ms_api(10); USBC_REG_clear_bit_b(USBC_BP_POWER_D_RESUME, USBC_REG_PCTL(USBC0_BASE)); } diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index e3c21a86d..f1e4dbd77 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -77,6 +77,7 @@ CFG_TUD_MEM_SECTION static struct { TU_ATTR_ALWAYS_INLINE static inline uint8_t dwc2_ep_count(const dwc2_regs_t* dwc2) { #if TU_CHECK_MCU(OPT_MCU_GD32VF103) + (void) dwc2; return DWC2_EP_MAX; #else const dwc2_ghwcfg2_t ghwcfg2 = {.value = dwc2->ghwcfg2}; diff --git a/src/portable/wch/hcd_ch32_usbfs.c b/src/portable/wch/hcd_ch32_usbfs.c index 200136906..7bbf122dd 100644 --- a/src/portable/wch/hcd_ch32_usbfs.c +++ b/src/portable/wch/hcd_ch32_usbfs.c @@ -36,7 +36,17 @@ #include "bsp/board_api.h" +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstrict-prototypes" +#endif + #include "ch32v20x.h" + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + #include "ch32v20x_usb.h" #define USBFS_RX_BUF_LEN 64 diff --git a/tools/get_deps.py b/tools/get_deps.py index c243137fa..c1e2c075d 100755 --- a/tools/get_deps.py +++ b/tools/get_deps.py @@ -246,12 +246,12 @@ 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 stm32u0 stm32u5 stm32wb stm32wba' + 'stm32h7 stm32h7rs stm32l0 stm32l1 stm32l4 stm32l5 stm32u0 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', - 'b0bbb0423b278ca632cfe1474eb227961d835fd2', - 'ra'], + '6f0a58d01aa9bd2feba212097f9afe7acd991d52', + 'ra stm32n6'], 'lib/sct_neopixel': ['https://github.com/gsteiert/sct_neopixel.git', 'e73e04ca63495672d955f9268e003cffe168fcd8', 'lpc55'], -- cgit v1.3.1 From 2a8811ebb0213297dedb34c33f29c9035a516600 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 15 Oct 2025 00:15:46 +0700 Subject: merge samd2x and saml2x bsp, add OPT_MCU_SAML2X to replace OPT_MCU_SAML21 & OPT_MCU_SAML22 --- .../device/net_lwip_webserver/src/tusb_config.h | 2 +- hw/bsp/samd21/FreeRTOSConfig/FreeRTOSConfig.h | 153 ------ hw/bsp/samd21/boards/atsamd21_xpro/board.cmake | 9 - hw/bsp/samd21/boards/atsamd21_xpro/board.h | 60 --- hw/bsp/samd21/boards/atsamd21_xpro/board.mk | 10 - .../boards/atsamd21_xpro/samd21j18a_flash.ld | 144 ------ .../boards/circuitplayground_express/board.cmake | 9 - .../boards/circuitplayground_express/board.h | 59 --- .../boards/circuitplayground_express/board.mk | 9 - .../circuitplayground_express.ld | 146 ------ hw/bsp/samd21/boards/curiosity_nano/board.cmake | 10 - hw/bsp/samd21/boards/curiosity_nano/board.h | 59 --- hw/bsp/samd21/boards/curiosity_nano/board.mk | 14 - .../boards/curiosity_nano/samd21g17a_flash.ld | 144 ------ hw/bsp/samd21/boards/cynthion_d21/board.cmake | 12 - hw/bsp/samd21/boards/cynthion_d21/board.h | 55 --- hw/bsp/samd21/boards/cynthion_d21/board.mk | 16 - .../samd21/boards/cynthion_d21/samd21g18a_flash.ld | 144 ------ .../samd21/boards/feather_m0_express/board.cmake | 9 - hw/bsp/samd21/boards/feather_m0_express/board.h | 74 --- hw/bsp/samd21/boards/feather_m0_express/board.mk | 9 - .../feather_m0_express/feather_m0_express.ld | 146 ------ hw/bsp/samd21/boards/itsybitsy_m0/board.cmake | 9 - hw/bsp/samd21/boards/itsybitsy_m0/board.h | 59 --- hw/bsp/samd21/boards/itsybitsy_m0/board.mk | 9 - hw/bsp/samd21/boards/itsybitsy_m0/itsybitsy_m0.ld | 146 ------ hw/bsp/samd21/boards/metro_m0_express/board.cmake | 9 - hw/bsp/samd21/boards/metro_m0_express/board.h | 74 --- hw/bsp/samd21/boards/metro_m0_express/board.mk | 9 - .../boards/metro_m0_express/metro_m0_express.ld | 146 ------ hw/bsp/samd21/boards/qtpy/board.cmake | 9 - hw/bsp/samd21/boards/qtpy/board.h | 55 --- hw/bsp/samd21/boards/qtpy/board.mk | 11 - hw/bsp/samd21/boards/qtpy/qtpy.ld | 146 ------ hw/bsp/samd21/boards/seeeduino_xiao/board.cmake | 9 - hw/bsp/samd21/boards/seeeduino_xiao/board.h | 59 --- hw/bsp/samd21/boards/seeeduino_xiao/board.mk | 9 - .../samd21/boards/seeeduino_xiao/seeeduino_xiao.ld | 146 ------ .../boards/sparkfun_samd21_mini_usb/board.cmake | 9 - .../samd21/boards/sparkfun_samd21_mini_usb/board.h | 62 --- .../boards/sparkfun_samd21_mini_usb/board.mk | 9 - .../sparkfun_samd21_mini_usb.ld | 146 ------ hw/bsp/samd21/boards/trinket_m0/board.cmake | 9 - hw/bsp/samd21/boards/trinket_m0/board.h | 44 -- hw/bsp/samd21/boards/trinket_m0/board.mk | 4 - hw/bsp/samd21/boards/trinket_m0/trinket_m0.ld | 146 ------ hw/bsp/samd21/family.c | 453 ----------------- hw/bsp/samd21/family.cmake | 110 ----- hw/bsp/samd21/family.mk | 53 -- hw/bsp/samd2x_l2x/FreeRTOSConfig/FreeRTOSConfig.h | 153 ++++++ hw/bsp/samd2x_l2x/boards/atsamd21_xpro/board.cmake | 10 + hw/bsp/samd2x_l2x/boards/atsamd21_xpro/board.h | 60 +++ hw/bsp/samd2x_l2x/boards/atsamd21_xpro/board.mk | 12 + .../boards/atsamd21_xpro/samd21j18a_flash.ld | 144 ++++++ hw/bsp/samd2x_l2x/boards/atsaml21_xpro/board.cmake | 9 + hw/bsp/samd2x_l2x/boards/atsaml21_xpro/board.h | 55 +++ hw/bsp/samd2x_l2x/boards/atsaml21_xpro/board.mk | 12 + .../boards/atsaml21_xpro/saml21j18b_flash.ld | 155 ++++++ .../boards/circuitplayground_express/board.cmake | 10 + .../boards/circuitplayground_express/board.h | 59 +++ .../boards/circuitplayground_express/board.mk | 11 + .../circuitplayground_express.ld | 146 ++++++ .../samd2x_l2x/boards/curiosity_nano/board.cmake | 11 + hw/bsp/samd2x_l2x/boards/curiosity_nano/board.h | 59 +++ hw/bsp/samd2x_l2x/boards/curiosity_nano/board.mk | 16 + .../boards/curiosity_nano/samd21g17a_flash.ld | 144 ++++++ hw/bsp/samd2x_l2x/boards/cynthion_d21/board.cmake | 13 + hw/bsp/samd2x_l2x/boards/cynthion_d21/board.h | 55 +++ hw/bsp/samd2x_l2x/boards/cynthion_d21/board.mk | 18 + .../boards/cynthion_d21/samd21g18a_flash.ld | 144 ++++++ .../boards/feather_m0_express/board.cmake | 10 + .../samd2x_l2x/boards/feather_m0_express/board.h | 74 +++ .../samd2x_l2x/boards/feather_m0_express/board.mk | 11 + .../feather_m0_express/feather_m0_express.ld | 146 ++++++ hw/bsp/samd2x_l2x/boards/itsybitsy_m0/board.cmake | 10 + hw/bsp/samd2x_l2x/boards/itsybitsy_m0/board.h | 59 +++ hw/bsp/samd2x_l2x/boards/itsybitsy_m0/board.mk | 11 + .../samd2x_l2x/boards/itsybitsy_m0/itsybitsy_m0.ld | 146 ++++++ .../samd2x_l2x/boards/metro_m0_express/board.cmake | 10 + hw/bsp/samd2x_l2x/boards/metro_m0_express/board.h | 74 +++ hw/bsp/samd2x_l2x/boards/metro_m0_express/board.mk | 11 + .../boards/metro_m0_express/metro_m0_express.ld | 146 ++++++ hw/bsp/samd2x_l2x/boards/qtpy/board.cmake | 10 + hw/bsp/samd2x_l2x/boards/qtpy/board.h | 55 +++ hw/bsp/samd2x_l2x/boards/qtpy/board.mk | 13 + hw/bsp/samd2x_l2x/boards/qtpy/qtpy.ld | 146 ++++++ .../samd2x_l2x/boards/saml22_feather/board.cmake | 9 + hw/bsp/samd2x_l2x/boards/saml22_feather/board.h | 52 ++ hw/bsp/samd2x_l2x/boards/saml22_feather/board.mk | 11 + .../boards/saml22_feather/saml22_feather.ld | 146 ++++++ .../samd2x_l2x/boards/seeeduino_xiao/board.cmake | 10 + hw/bsp/samd2x_l2x/boards/seeeduino_xiao/board.h | 59 +++ hw/bsp/samd2x_l2x/boards/seeeduino_xiao/board.mk | 11 + .../boards/seeeduino_xiao/seeeduino_xiao.ld | 146 ++++++ .../samd2x_l2x/boards/sensorwatch_m0/board.cmake | 9 + hw/bsp/samd2x_l2x/boards/sensorwatch_m0/board.h | 52 ++ hw/bsp/samd2x_l2x/boards/sensorwatch_m0/board.mk | 11 + .../boards/sensorwatch_m0/sensorwatch_m0.ld | 146 ++++++ .../boards/sparkfun_samd21_mini_usb/board.cmake | 10 + .../boards/sparkfun_samd21_mini_usb/board.h | 62 +++ .../boards/sparkfun_samd21_mini_usb/board.mk | 11 + .../sparkfun_samd21_mini_usb.ld | 146 ++++++ hw/bsp/samd2x_l2x/boards/trinket_m0/board.cmake | 10 + hw/bsp/samd2x_l2x/boards/trinket_m0/board.h | 44 ++ hw/bsp/samd2x_l2x/boards/trinket_m0/board.mk | 6 + hw/bsp/samd2x_l2x/boards/trinket_m0/trinket_m0.ld | 146 ++++++ hw/bsp/samd2x_l2x/family.c | 550 +++++++++++++++++++++ hw/bsp/samd2x_l2x/family.cmake | 164 ++++++ hw/bsp/samd2x_l2x/family.mk | 92 ++++ hw/bsp/saml2x/FreeRTOSConfig/FreeRTOSConfig.h | 153 ------ hw/bsp/saml2x/boards/atsaml21_xpro/board.cmake | 9 - hw/bsp/saml2x/boards/atsaml21_xpro/board.h | 55 --- hw/bsp/saml2x/boards/atsaml21_xpro/board.mk | 12 - .../boards/atsaml21_xpro/saml21j18b_flash.ld | 155 ------ hw/bsp/saml2x/boards/saml22_feather/board.cmake | 9 - hw/bsp/saml2x/boards/saml22_feather/board.h | 52 -- hw/bsp/saml2x/boards/saml22_feather/board.mk | 11 - .../saml2x/boards/saml22_feather/saml22_feather.ld | 146 ------ hw/bsp/saml2x/boards/sensorwatch_m0/board.cmake | 9 - hw/bsp/saml2x/boards/sensorwatch_m0/board.h | 52 -- hw/bsp/saml2x/boards/sensorwatch_m0/board.mk | 11 - .../saml2x/boards/sensorwatch_m0/sensorwatch_m0.ld | 146 ------ hw/bsp/saml2x/family.c | 173 ------- hw/bsp/saml2x/family.cmake | 115 ----- hw/bsp/saml2x/family.mk | 53 -- src/common/tusb_mcu.h | 4 +- src/portable/microchip/samd/dcd_samd.c | 24 +- src/portable/microchip/samd/hcd_samd.c | 12 +- src/tusb_option.h | 5 +- 129 files changed, 4148 insertions(+), 4432 deletions(-) delete mode 100644 hw/bsp/samd21/FreeRTOSConfig/FreeRTOSConfig.h delete mode 100644 hw/bsp/samd21/boards/atsamd21_xpro/board.cmake delete mode 100644 hw/bsp/samd21/boards/atsamd21_xpro/board.h delete mode 100644 hw/bsp/samd21/boards/atsamd21_xpro/board.mk delete mode 100644 hw/bsp/samd21/boards/atsamd21_xpro/samd21j18a_flash.ld delete mode 100644 hw/bsp/samd21/boards/circuitplayground_express/board.cmake delete mode 100644 hw/bsp/samd21/boards/circuitplayground_express/board.h delete mode 100644 hw/bsp/samd21/boards/circuitplayground_express/board.mk delete mode 100644 hw/bsp/samd21/boards/circuitplayground_express/circuitplayground_express.ld delete mode 100644 hw/bsp/samd21/boards/curiosity_nano/board.cmake delete mode 100644 hw/bsp/samd21/boards/curiosity_nano/board.h delete mode 100644 hw/bsp/samd21/boards/curiosity_nano/board.mk delete mode 100644 hw/bsp/samd21/boards/curiosity_nano/samd21g17a_flash.ld delete mode 100644 hw/bsp/samd21/boards/cynthion_d21/board.cmake delete mode 100644 hw/bsp/samd21/boards/cynthion_d21/board.h delete mode 100644 hw/bsp/samd21/boards/cynthion_d21/board.mk delete mode 100644 hw/bsp/samd21/boards/cynthion_d21/samd21g18a_flash.ld delete mode 100644 hw/bsp/samd21/boards/feather_m0_express/board.cmake delete mode 100644 hw/bsp/samd21/boards/feather_m0_express/board.h delete mode 100644 hw/bsp/samd21/boards/feather_m0_express/board.mk delete mode 100644 hw/bsp/samd21/boards/feather_m0_express/feather_m0_express.ld delete mode 100644 hw/bsp/samd21/boards/itsybitsy_m0/board.cmake delete mode 100644 hw/bsp/samd21/boards/itsybitsy_m0/board.h delete mode 100644 hw/bsp/samd21/boards/itsybitsy_m0/board.mk delete mode 100644 hw/bsp/samd21/boards/itsybitsy_m0/itsybitsy_m0.ld delete mode 100644 hw/bsp/samd21/boards/metro_m0_express/board.cmake delete mode 100644 hw/bsp/samd21/boards/metro_m0_express/board.h delete mode 100644 hw/bsp/samd21/boards/metro_m0_express/board.mk delete mode 100644 hw/bsp/samd21/boards/metro_m0_express/metro_m0_express.ld delete mode 100644 hw/bsp/samd21/boards/qtpy/board.cmake delete mode 100644 hw/bsp/samd21/boards/qtpy/board.h delete mode 100644 hw/bsp/samd21/boards/qtpy/board.mk delete mode 100644 hw/bsp/samd21/boards/qtpy/qtpy.ld delete mode 100644 hw/bsp/samd21/boards/seeeduino_xiao/board.cmake delete mode 100644 hw/bsp/samd21/boards/seeeduino_xiao/board.h delete mode 100644 hw/bsp/samd21/boards/seeeduino_xiao/board.mk delete mode 100644 hw/bsp/samd21/boards/seeeduino_xiao/seeeduino_xiao.ld delete mode 100644 hw/bsp/samd21/boards/sparkfun_samd21_mini_usb/board.cmake delete mode 100644 hw/bsp/samd21/boards/sparkfun_samd21_mini_usb/board.h delete mode 100644 hw/bsp/samd21/boards/sparkfun_samd21_mini_usb/board.mk delete mode 100644 hw/bsp/samd21/boards/sparkfun_samd21_mini_usb/sparkfun_samd21_mini_usb.ld delete mode 100644 hw/bsp/samd21/boards/trinket_m0/board.cmake delete mode 100644 hw/bsp/samd21/boards/trinket_m0/board.h delete mode 100644 hw/bsp/samd21/boards/trinket_m0/board.mk delete mode 100644 hw/bsp/samd21/boards/trinket_m0/trinket_m0.ld delete mode 100644 hw/bsp/samd21/family.c delete mode 100644 hw/bsp/samd21/family.cmake delete mode 100644 hw/bsp/samd21/family.mk create mode 100644 hw/bsp/samd2x_l2x/FreeRTOSConfig/FreeRTOSConfig.h create mode 100644 hw/bsp/samd2x_l2x/boards/atsamd21_xpro/board.cmake create mode 100644 hw/bsp/samd2x_l2x/boards/atsamd21_xpro/board.h create mode 100644 hw/bsp/samd2x_l2x/boards/atsamd21_xpro/board.mk create mode 100644 hw/bsp/samd2x_l2x/boards/atsamd21_xpro/samd21j18a_flash.ld create mode 100644 hw/bsp/samd2x_l2x/boards/atsaml21_xpro/board.cmake create mode 100644 hw/bsp/samd2x_l2x/boards/atsaml21_xpro/board.h create mode 100644 hw/bsp/samd2x_l2x/boards/atsaml21_xpro/board.mk create mode 100644 hw/bsp/samd2x_l2x/boards/atsaml21_xpro/saml21j18b_flash.ld create mode 100644 hw/bsp/samd2x_l2x/boards/circuitplayground_express/board.cmake create mode 100644 hw/bsp/samd2x_l2x/boards/circuitplayground_express/board.h create mode 100644 hw/bsp/samd2x_l2x/boards/circuitplayground_express/board.mk create mode 100644 hw/bsp/samd2x_l2x/boards/circuitplayground_express/circuitplayground_express.ld create mode 100644 hw/bsp/samd2x_l2x/boards/curiosity_nano/board.cmake create mode 100644 hw/bsp/samd2x_l2x/boards/curiosity_nano/board.h create mode 100644 hw/bsp/samd2x_l2x/boards/curiosity_nano/board.mk create mode 100644 hw/bsp/samd2x_l2x/boards/curiosity_nano/samd21g17a_flash.ld create mode 100644 hw/bsp/samd2x_l2x/boards/cynthion_d21/board.cmake create mode 100644 hw/bsp/samd2x_l2x/boards/cynthion_d21/board.h create mode 100644 hw/bsp/samd2x_l2x/boards/cynthion_d21/board.mk create mode 100644 hw/bsp/samd2x_l2x/boards/cynthion_d21/samd21g18a_flash.ld create mode 100644 hw/bsp/samd2x_l2x/boards/feather_m0_express/board.cmake create mode 100644 hw/bsp/samd2x_l2x/boards/feather_m0_express/board.h create mode 100644 hw/bsp/samd2x_l2x/boards/feather_m0_express/board.mk create mode 100644 hw/bsp/samd2x_l2x/boards/feather_m0_express/feather_m0_express.ld create mode 100644 hw/bsp/samd2x_l2x/boards/itsybitsy_m0/board.cmake create mode 100644 hw/bsp/samd2x_l2x/boards/itsybitsy_m0/board.h create mode 100644 hw/bsp/samd2x_l2x/boards/itsybitsy_m0/board.mk create mode 100644 hw/bsp/samd2x_l2x/boards/itsybitsy_m0/itsybitsy_m0.ld create mode 100644 hw/bsp/samd2x_l2x/boards/metro_m0_express/board.cmake create mode 100644 hw/bsp/samd2x_l2x/boards/metro_m0_express/board.h create mode 100644 hw/bsp/samd2x_l2x/boards/metro_m0_express/board.mk create mode 100644 hw/bsp/samd2x_l2x/boards/metro_m0_express/metro_m0_express.ld create mode 100644 hw/bsp/samd2x_l2x/boards/qtpy/board.cmake create mode 100644 hw/bsp/samd2x_l2x/boards/qtpy/board.h create mode 100644 hw/bsp/samd2x_l2x/boards/qtpy/board.mk create mode 100644 hw/bsp/samd2x_l2x/boards/qtpy/qtpy.ld create mode 100644 hw/bsp/samd2x_l2x/boards/saml22_feather/board.cmake create mode 100644 hw/bsp/samd2x_l2x/boards/saml22_feather/board.h create mode 100644 hw/bsp/samd2x_l2x/boards/saml22_feather/board.mk create mode 100644 hw/bsp/samd2x_l2x/boards/saml22_feather/saml22_feather.ld create mode 100644 hw/bsp/samd2x_l2x/boards/seeeduino_xiao/board.cmake create mode 100644 hw/bsp/samd2x_l2x/boards/seeeduino_xiao/board.h create mode 100644 hw/bsp/samd2x_l2x/boards/seeeduino_xiao/board.mk create mode 100644 hw/bsp/samd2x_l2x/boards/seeeduino_xiao/seeeduino_xiao.ld create mode 100644 hw/bsp/samd2x_l2x/boards/sensorwatch_m0/board.cmake create mode 100644 hw/bsp/samd2x_l2x/boards/sensorwatch_m0/board.h create mode 100644 hw/bsp/samd2x_l2x/boards/sensorwatch_m0/board.mk create mode 100644 hw/bsp/samd2x_l2x/boards/sensorwatch_m0/sensorwatch_m0.ld create mode 100644 hw/bsp/samd2x_l2x/boards/sparkfun_samd21_mini_usb/board.cmake create mode 100644 hw/bsp/samd2x_l2x/boards/sparkfun_samd21_mini_usb/board.h create mode 100644 hw/bsp/samd2x_l2x/boards/sparkfun_samd21_mini_usb/board.mk create mode 100644 hw/bsp/samd2x_l2x/boards/sparkfun_samd21_mini_usb/sparkfun_samd21_mini_usb.ld create mode 100644 hw/bsp/samd2x_l2x/boards/trinket_m0/board.cmake create mode 100644 hw/bsp/samd2x_l2x/boards/trinket_m0/board.h create mode 100644 hw/bsp/samd2x_l2x/boards/trinket_m0/board.mk create mode 100644 hw/bsp/samd2x_l2x/boards/trinket_m0/trinket_m0.ld create mode 100644 hw/bsp/samd2x_l2x/family.c create mode 100644 hw/bsp/samd2x_l2x/family.cmake create mode 100644 hw/bsp/samd2x_l2x/family.mk delete mode 100644 hw/bsp/saml2x/FreeRTOSConfig/FreeRTOSConfig.h delete mode 100644 hw/bsp/saml2x/boards/atsaml21_xpro/board.cmake delete mode 100644 hw/bsp/saml2x/boards/atsaml21_xpro/board.h delete mode 100644 hw/bsp/saml2x/boards/atsaml21_xpro/board.mk delete mode 100644 hw/bsp/saml2x/boards/atsaml21_xpro/saml21j18b_flash.ld delete mode 100644 hw/bsp/saml2x/boards/saml22_feather/board.cmake delete mode 100644 hw/bsp/saml2x/boards/saml22_feather/board.h delete mode 100644 hw/bsp/saml2x/boards/saml22_feather/board.mk delete mode 100644 hw/bsp/saml2x/boards/saml22_feather/saml22_feather.ld delete mode 100644 hw/bsp/saml2x/boards/sensorwatch_m0/board.cmake delete mode 100644 hw/bsp/saml2x/boards/sensorwatch_m0/board.h delete mode 100644 hw/bsp/saml2x/boards/sensorwatch_m0/board.mk delete mode 100644 hw/bsp/saml2x/boards/sensorwatch_m0/sensorwatch_m0.ld delete mode 100644 hw/bsp/saml2x/family.c delete mode 100644 hw/bsp/saml2x/family.cmake delete mode 100644 hw/bsp/saml2x/family.mk (limited to 'src/portable') diff --git a/examples/device/net_lwip_webserver/src/tusb_config.h b/examples/device/net_lwip_webserver/src/tusb_config.h index c774f59ff..31731ac1b 100644 --- a/examples/device/net_lwip_webserver/src/tusb_config.h +++ b/examples/device/net_lwip_webserver/src/tusb_config.h @@ -88,7 +88,7 @@ extern "C" { #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) +#elif TU_CHECK_MCU(OPT_MCU_SAMD21, OPT_MCU_SAML2X) #define USE_ECM 1 #elif TU_CHECK_MCU(OPT_MCU_STM32F0, OPT_MCU_STM32F1) #define USE_ECM 1 diff --git a/hw/bsp/samd21/FreeRTOSConfig/FreeRTOSConfig.h b/hw/bsp/samd21/FreeRTOSConfig/FreeRTOSConfig.h deleted file mode 100644 index 6c9ecae2d..000000000 --- a/hw/bsp/samd21/FreeRTOSConfig/FreeRTOSConfig.h +++ /dev/null @@ -1,153 +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 "sam.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 2 - -/* The lowest interrupt priority that can be used in a call to a "set priority" function. */ -#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1< rom - - /* .ARM.exidx is sorted, so has to go in its own output section. */ - PROVIDE_HIDDEN (__exidx_start = .); - .ARM.exidx : - { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - } > rom - PROVIDE_HIDDEN (__exidx_end = .); - - . = ALIGN(4); - _etext = .; - - .relocate : AT (_etext) - { - . = ALIGN(4); - _srelocate = .; - *(.ramfunc .ramfunc.*); - *(.data .data.*); - . = ALIGN(4); - _erelocate = .; - } > ram - - /* .bss section which is used for uninitialized data */ - .bss (NOLOAD) : - { - . = ALIGN(4); - _sbss = . ; - _szero = .; - *(.bss .bss.*) - *(COMMON) - . = ALIGN(4); - _ebss = . ; - _ezero = .; - end = .; - } > ram - - /* stack section */ - .stack (NOLOAD): - { - . = ALIGN(8); - _sstack = .; - . = . + STACK_SIZE; - . = ALIGN(8); - _estack = .; - } > ram - - . = ALIGN(4); - _end = . ; -} diff --git a/hw/bsp/samd21/boards/circuitplayground_express/board.cmake b/hw/bsp/samd21/boards/circuitplayground_express/board.cmake deleted file mode 100644 index c1a612936..000000000 --- a/hw/bsp/samd21/boards/circuitplayground_express/board.cmake +++ /dev/null @@ -1,9 +0,0 @@ -set(JLINK_DEVICE ATSAMD21G18) -set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/${BOARD}.ld) - -function(update_board TARGET) - target_compile_definitions(${TARGET} PUBLIC - __SAMD21G18A__ - CFG_EXAMPLE_VIDEO_READONLY - ) -endfunction() diff --git a/hw/bsp/samd21/boards/circuitplayground_express/board.h b/hw/bsp/samd21/boards/circuitplayground_express/board.h deleted file mode 100644 index bfe2d9951..000000000 --- a/hw/bsp/samd21/boards/circuitplayground_express/board.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * 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 Circuit Playground Express - url: https://www.adafruit.com/product/3333 -*/ - -#ifndef BOARD_H_ -#define BOARD_H_ - -#ifdef __cplusplus - extern "C" { -#endif - -// LED -#define LED_PIN 17 -#define LED_STATE_ON 1 - -// Button -#define BUTTON_PIN 28 -#define BUTTON_STATE_ACTIVE 1 - -// UART -#define UART_RX_PIN 4 -#define UART_TX_PIN 5 - -static inline void board_vbus_set(uint8_t rhport, bool state) { - (void) rhport; (void) state; -} - -#ifdef __cplusplus - } -#endif - -#endif /* BOARD_H_ */ diff --git a/hw/bsp/samd21/boards/circuitplayground_express/board.mk b/hw/bsp/samd21/boards/circuitplayground_express/board.mk deleted file mode 100644 index d6c9150b3..000000000 --- a/hw/bsp/samd21/boards/circuitplayground_express/board.mk +++ /dev/null @@ -1,9 +0,0 @@ -CFLAGS += -D__SAMD21G18A__ -DCFG_EXAMPLE_VIDEO_READONLY - -# All source paths should be relative to the top level. -LD_FILE = $(BOARD_PATH)/$(BOARD).ld - -# For flash-jlink target -JLINK_DEVICE = ATSAMD21G18 - -flash: flash-bossac diff --git a/hw/bsp/samd21/boards/circuitplayground_express/circuitplayground_express.ld b/hw/bsp/samd21/boards/circuitplayground_express/circuitplayground_express.ld deleted file mode 100644 index ce7aff80b..000000000 --- a/hw/bsp/samd21/boards/circuitplayground_express/circuitplayground_express.ld +++ /dev/null @@ -1,146 +0,0 @@ -/** - * \file - * - * \brief Linker script for running in internal FLASH on the SAMD21G18A - * - * Copyright (c) 2017 Microchip Technology Inc. - * - * \asf_license_start - * - * \page License - * - * 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 Licence 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. - * - * \asf_license_stop - * - */ - - -OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") -OUTPUT_ARCH(arm) -SEARCH_DIR(.) - -/* Memory Spaces Definitions */ -MEMORY -{ - rom (rx) : ORIGIN = 0x00000000 + 8K, LENGTH = 0x00040000 - 8K - ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000 -} - -/* The stack size used by the application. NOTE: you need to adjust according to your application. */ -STACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x2000; - -ENTRY(Reset_Handler) - -/* Section Definitions */ -SECTIONS -{ - .text : - { - . = ALIGN(4); - _sfixed = .; - KEEP(*(.vectors .vectors.*)) - *(.text .text.* .gnu.linkonce.t.*) - *(.glue_7t) *(.glue_7) - *(.rodata .rodata* .gnu.linkonce.r.*) - *(.ARM.extab* .gnu.linkonce.armextab.*) - - /* Support C constructors, and C destructors in both user code - and the C library. This also provides support for C++ code. */ - . = ALIGN(4); - KEEP(*(.init)) - . = ALIGN(4); - __preinit_array_start = .; - KEEP (*(.preinit_array)) - __preinit_array_end = .; - - . = ALIGN(4); - __init_array_start = .; - KEEP (*(SORT(.init_array.*))) - KEEP (*(.init_array)) - __init_array_end = .; - - . = ALIGN(4); - KEEP (*crtbegin.o(.ctors)) - KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) - KEEP (*(SORT(.ctors.*))) - KEEP (*crtend.o(.ctors)) - - . = ALIGN(4); - KEEP(*(.fini)) - - . = ALIGN(4); - __fini_array_start = .; - KEEP (*(.fini_array)) - KEEP (*(SORT(.fini_array.*))) - __fini_array_end = .; - - KEEP (*crtbegin.o(.dtors)) - KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) - KEEP (*(SORT(.dtors.*))) - KEEP (*crtend.o(.dtors)) - - . = ALIGN(4); - _efixed = .; /* End of text section */ - } > rom - - /* .ARM.exidx is sorted, so has to go in its own output section. */ - PROVIDE_HIDDEN (__exidx_start = .); - .ARM.exidx : - { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - } > rom - PROVIDE_HIDDEN (__exidx_end = .); - - . = ALIGN(4); - _etext = .; - - .relocate : AT (_etext) - { - . = ALIGN(4); - _srelocate = .; - *(.ramfunc .ramfunc.*); - *(.data .data.*); - . = ALIGN(4); - _erelocate = .; - } > ram - - /* .bss section which is used for uninitialized data */ - .bss (NOLOAD) : - { - . = ALIGN(4); - _sbss = . ; - _szero = .; - *(.bss .bss.*) - *(COMMON) - . = ALIGN(4); - _ebss = . ; - _ezero = .; - end = .; - } > ram - - /* stack section */ - .stack (NOLOAD): - { - . = ALIGN(8); - _sstack = .; - . = . + STACK_SIZE; - . = ALIGN(8); - _estack = .; - } > ram - - . = ALIGN(4); - _end = . ; -} diff --git a/hw/bsp/samd21/boards/curiosity_nano/board.cmake b/hw/bsp/samd21/boards/curiosity_nano/board.cmake deleted file mode 100644 index ff779c0fd..000000000 --- a/hw/bsp/samd21/boards/curiosity_nano/board.cmake +++ /dev/null @@ -1,10 +0,0 @@ -set(JLINK_DEVICE atsamd21g17a) -set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/samd21g17a_flash.ld) - -function(update_board TARGET) - target_compile_definitions(${TARGET} PUBLIC - __SAMD21G17A__ - CFG_EXAMPLE_MSC_READONLY - CFG_EXAMPLE_VIDEO_READONLY - ) -endfunction() diff --git a/hw/bsp/samd21/boards/curiosity_nano/board.h b/hw/bsp/samd21/boards/curiosity_nano/board.h deleted file mode 100644 index a2a7385a4..000000000 --- a/hw/bsp/samd21/boards/curiosity_nano/board.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * 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: SAMD21 Curiosty Nano - url: https://www.microchip.com/en-us/development-tool/dm320119 -*/ - -#ifndef BOARD_H_ -#define BOARD_H_ - -#ifdef __cplusplus - extern "C" { -#endif - -// LED -#define LED_PIN (32 + 10) // PB10 -#define LED_STATE_ON 0 - -// Button -#define BUTTON_PIN (0 + 11) // PB11 -#define BUTTON_STATE_ACTIVE 0 - -// UART -#define UART_RX_PIN 31 // CDC5_RX -#define UART_TX_PIN 37 // CDC5_TX - -static inline void board_vbus_set(uint8_t rhport, bool state) { - (void) rhport; (void) state; -} - -#ifdef __cplusplus - } -#endif - -#endif /* BOARD_H_ */ diff --git a/hw/bsp/samd21/boards/curiosity_nano/board.mk b/hw/bsp/samd21/boards/curiosity_nano/board.mk deleted file mode 100644 index 112fb6946..000000000 --- a/hw/bsp/samd21/boards/curiosity_nano/board.mk +++ /dev/null @@ -1,14 +0,0 @@ -CFLAGS += -D__SAMD21G17A__ -DCFG_EXAMPLE_MSC_READONLY -DCFG_EXAMPLE_VIDEO_READONLY - -# All source paths should be relative to the top level. -LD_FILE = $(BOARD_PATH)/samd21g17a_flash.ld - -# For flash-jlink target -JLINK_DEVICE = atsamd21g17a - -# flash using jlink (options are: jlink/cmsisdap/stlink/dfu) -#flash: flash-jlink - -PYOCD_TARGET = atsamd21g17a -PYOCD_OPTION = -O dap_protocol=swd -flash: flash-pyocd diff --git a/hw/bsp/samd21/boards/curiosity_nano/samd21g17a_flash.ld b/hw/bsp/samd21/boards/curiosity_nano/samd21g17a_flash.ld deleted file mode 100644 index e03a4ce60..000000000 --- a/hw/bsp/samd21/boards/curiosity_nano/samd21g17a_flash.ld +++ /dev/null @@ -1,144 +0,0 @@ -/** - * \file - * - * \brief Linker script for running in internal FLASH on the SAMD21G17A/D - * - * Copyright (c) 2017 Microchip Technology Inc. - * - * \asf_license_start - * - * \page License - * - * 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 Licence 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. - * - * \asf_license_stop - * - */ - - -OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") -OUTPUT_ARCH(arm) -SEARCH_DIR(.) - -/* Memory Spaces Definitions */ -MEMORY -{ - rom (rx) : ORIGIN = 0x00000000, LENGTH = 0x00020000 - ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00004000 -} - -/* The stack size used by the application. NOTE: you need to adjust according to your application. */ -STACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x1000; - -/* Section Definitions */ -SECTIONS -{ - .text : - { - . = ALIGN(4); - _sfixed = .; - KEEP(*(.vectors .vectors.*)) - *(.text .text.* .gnu.linkonce.t.*) - *(.glue_7t) *(.glue_7) - *(.rodata .rodata* .gnu.linkonce.r.*) - *(.ARM.extab* .gnu.linkonce.armextab.*) - - /* Support C constructors, and C destructors in both user code - and the C library. This also provides support for C++ code. */ - . = ALIGN(4); - KEEP(*(.init)) - . = ALIGN(4); - __preinit_array_start = .; - KEEP (*(.preinit_array)) - __preinit_array_end = .; - - . = ALIGN(4); - __init_array_start = .; - KEEP (*(SORT(.init_array.*))) - KEEP (*(.init_array)) - __init_array_end = .; - - . = ALIGN(4); - KEEP (*crtbegin.o(.ctors)) - KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) - KEEP (*(SORT(.ctors.*))) - KEEP (*crtend.o(.ctors)) - - . = ALIGN(4); - KEEP(*(.fini)) - - . = ALIGN(4); - __fini_array_start = .; - KEEP (*(.fini_array)) - KEEP (*(SORT(.fini_array.*))) - __fini_array_end = .; - - KEEP (*crtbegin.o(.dtors)) - KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) - KEEP (*(SORT(.dtors.*))) - KEEP (*crtend.o(.dtors)) - - . = ALIGN(4); - _efixed = .; /* End of text section */ - } > rom - - /* .ARM.exidx is sorted, so has to go in its own output section. */ - PROVIDE_HIDDEN (__exidx_start = .); - .ARM.exidx : - { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - } > rom - PROVIDE_HIDDEN (__exidx_end = .); - - . = ALIGN(4); - _etext = .; - - .relocate : AT (_etext) - { - . = ALIGN(4); - _srelocate = .; - *(.ramfunc .ramfunc.*); - *(.data .data.*); - . = ALIGN(4); - _erelocate = .; - } > ram - - /* .bss section which is used for uninitialized data */ - .bss (NOLOAD) : - { - . = ALIGN(4); - _sbss = . ; - _szero = .; - *(.bss .bss.*) - *(COMMON) - . = ALIGN(4); - _ebss = . ; - _ezero = .; - end = .; - } > ram - - /* stack section */ - .stack (NOLOAD): - { - . = ALIGN(8); - _sstack = .; - . = . + STACK_SIZE; - . = ALIGN(8); - _estack = .; - } > ram - - . = ALIGN(4); - _end = . ; -} diff --git a/hw/bsp/samd21/boards/cynthion_d21/board.cmake b/hw/bsp/samd21/boards/cynthion_d21/board.cmake deleted file mode 100644 index fb54b7561..000000000 --- a/hw/bsp/samd21/boards/cynthion_d21/board.cmake +++ /dev/null @@ -1,12 +0,0 @@ -set(JLINK_DEVICE ATSAMD21G18) -set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/samd21g18a_flash.ld) - -function(update_board TARGET) - target_compile_definitions(${TARGET} PUBLIC - __SAMD21G18A__ - CFG_EXAMPLE_VIDEO_READONLY - ) - target_link_options(${TARGET} PUBLIC - "LINKER:--defsym=BOOTLOADER_SIZE=0x800" - ) -endfunction() diff --git a/hw/bsp/samd21/boards/cynthion_d21/board.h b/hw/bsp/samd21/boards/cynthion_d21/board.h deleted file mode 100644 index 83782bc65..000000000 --- a/hw/bsp/samd21/boards/cynthion_d21/board.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * 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: Great Scott Gadgets Cynthion - url: https://greatscottgadgets.com/cynthion/ -*/ - -#ifndef BOARD_H_ -#define BOARD_H_ - -#ifdef __cplusplus - extern "C" { -#endif - -// LED -#define LED_PIN PIN_PA22 -#define LED_STATE_ON 1 - -// Button -#define BUTTON_PIN PIN_PB22 -#define BUTTON_STATE_ACTIVE 0 - -static inline void board_vbus_set(uint8_t rhport, bool state) { - (void) rhport; (void) state; -} - -#ifdef __cplusplus - } -#endif - -#endif /* BOARD_H_ */ diff --git a/hw/bsp/samd21/boards/cynthion_d21/board.mk b/hw/bsp/samd21/boards/cynthion_d21/board.mk deleted file mode 100644 index 52c9d60cb..000000000 --- a/hw/bsp/samd21/boards/cynthion_d21/board.mk +++ /dev/null @@ -1,16 +0,0 @@ -CFLAGS += -D__SAMD21G18A__ -DCFG_EXAMPLE_VIDEO_READONLY - -LD_FILE = $(BOARD_PATH)/samd21g18a_flash.ld - -# Default bootloader size is now 2K, allow to specify other -ifeq ($(BOOTLOADER_SIZE), ) - BOOTLOADER_SIZE := 0x800 -endif -LDFLAGS += -Wl,--defsym=BOOTLOADER_SIZE=$(BOOTLOADER_SIZE) - -# For flash-jlink target -JLINK_DEVICE = ATSAMD21G18 - -# flash using dfu-util -flash: $(BUILD)/$(PROJECT).bin - dfu-util -a 0 -d 1d50:615c -D $< || dfu-util -a 0 -d 16d0:05a5 -D $< diff --git a/hw/bsp/samd21/boards/cynthion_d21/samd21g18a_flash.ld b/hw/bsp/samd21/boards/cynthion_d21/samd21g18a_flash.ld deleted file mode 100644 index 95d71b9e3..000000000 --- a/hw/bsp/samd21/boards/cynthion_d21/samd21g18a_flash.ld +++ /dev/null @@ -1,144 +0,0 @@ -/** - * \file - * - * \brief Linker script for running in internal FLASH on the SAMD21G18A - * - * Copyright (c) 2017 Microchip Technology Inc. - * - * \asf_license_start - * - * \page License - * - * 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 Licence 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. - * - * \asf_license_stop - * - */ - - -OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") -OUTPUT_ARCH(arm) -SEARCH_DIR(.) - -/* Memory Spaces Definitions */ -MEMORY -{ - rom (rx) : ORIGIN = 0x00000000 + BOOTLOADER_SIZE, LENGTH = 0x00040000 - BOOTLOADER_SIZE - ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000 -} - -/* The stack size used by the application. NOTE: you need to adjust according to your application. */ -STACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x2000; - -/* Section Definitions */ -SECTIONS -{ - .text : - { - . = ALIGN(4); - _sfixed = .; - KEEP(*(.vectors .vectors.*)) - *(.text .text.* .gnu.linkonce.t.*) - *(.glue_7t) *(.glue_7) - *(.rodata .rodata* .gnu.linkonce.r.*) - *(.ARM.extab* .gnu.linkonce.armextab.*) - - /* Support C constructors, and C destructors in both user code - and the C library. This also provides support for C++ code. */ - . = ALIGN(4); - KEEP(*(.init)) - . = ALIGN(4); - __preinit_array_start = .; - KEEP (*(.preinit_array)) - __preinit_array_end = .; - - . = ALIGN(4); - __init_array_start = .; - KEEP (*(SORT(.init_array.*))) - KEEP (*(.init_array)) - __init_array_end = .; - - . = ALIGN(4); - KEEP (*crtbegin.o(.ctors)) - KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) - KEEP (*(SORT(.ctors.*))) - KEEP (*crtend.o(.ctors)) - - . = ALIGN(4); - KEEP(*(.fini)) - - . = ALIGN(4); - __fini_array_start = .; - KEEP (*(.fini_array)) - KEEP (*(SORT(.fini_array.*))) - __fini_array_end = .; - - KEEP (*crtbegin.o(.dtors)) - KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) - KEEP (*(SORT(.dtors.*))) - KEEP (*crtend.o(.dtors)) - - . = ALIGN(4); - _efixed = .; /* End of text section */ - } > rom - - /* .ARM.exidx is sorted, so has to go in its own output section. */ - PROVIDE_HIDDEN (__exidx_start = .); - .ARM.exidx : - { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - } > rom - PROVIDE_HIDDEN (__exidx_end = .); - - . = ALIGN(4); - _etext = .; - - .relocate : AT (_etext) - { - . = ALIGN(4); - _srelocate = .; - *(.ramfunc .ramfunc.*); - *(.data .data.*); - . = ALIGN(4); - _erelocate = .; - } > ram - - /* .bss section which is used for uninitialized data */ - .bss (NOLOAD) : - { - . = ALIGN(4); - _sbss = . ; - _szero = .; - *(.bss .bss.*) - *(COMMON) - . = ALIGN(4); - _ebss = . ; - _ezero = .; - end = .; - } > ram - - /* stack section */ - .stack (NOLOAD): - { - . = ALIGN(8); - _sstack = .; - . = . + STACK_SIZE; - . = ALIGN(8); - _estack = .; - } > ram - - . = ALIGN(4); - _end = . ; -} diff --git a/hw/bsp/samd21/boards/feather_m0_express/board.cmake b/hw/bsp/samd21/boards/feather_m0_express/board.cmake deleted file mode 100644 index c1a612936..000000000 --- a/hw/bsp/samd21/boards/feather_m0_express/board.cmake +++ /dev/null @@ -1,9 +0,0 @@ -set(JLINK_DEVICE ATSAMD21G18) -set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/${BOARD}.ld) - -function(update_board TARGET) - target_compile_definitions(${TARGET} PUBLIC - __SAMD21G18A__ - CFG_EXAMPLE_VIDEO_READONLY - ) -endfunction() diff --git a/hw/bsp/samd21/boards/feather_m0_express/board.h b/hw/bsp/samd21/boards/feather_m0_express/board.h deleted file mode 100644 index 6fe13eb30..000000000 --- a/hw/bsp/samd21/boards/feather_m0_express/board.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * 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 M0 Express - url: https://www.adafruit.com/product/3403 -*/ - -#ifndef BOARD_H_ -#define BOARD_H_ - -#ifdef __cplusplus - extern "C" { -#endif - -// LED -#define LED_PIN 17 -#define LED_STATE_ON 1 - -// Button -#define BUTTON_PIN 15 -#define BUTTON_STATE_ACTIVE 0 - -// UART -#define UART_RX_PIN 4 -#define UART_TX_PIN 5 - -// SPI for USB host shield -#define MAX3421_SERCOM_ID 4 // SERCOM4 -#define MAX3421_SERCOM_FUNCTION 3 // function D (Sercom Alt) - -#define MAX3421_SCK_PIN (32+11) -#define MAX3421_MOSI_PIN (32+10) -#define MAX3421_MISO_PIN 12 -#define MAX3421_TX_PAD 1 // MOSI = PAD_2, SCK = PAD_3 -#define MAX3421_RX_PAD 0 // MISO = PAD_2 - -#define MAX3421_CS_PIN 18 // D10 - -#define MAX3421_INTR_PIN 7 // D10 -#define MAX3421_INTR_EIC_ID 7 // EIC7 - -static inline void board_vbus_set(uint8_t rhport, bool state) { - (void) rhport; (void) state; -} - -#ifdef __cplusplus - } -#endif - -#endif /* BOARD_H_ */ diff --git a/hw/bsp/samd21/boards/feather_m0_express/board.mk b/hw/bsp/samd21/boards/feather_m0_express/board.mk deleted file mode 100644 index d6c9150b3..000000000 --- a/hw/bsp/samd21/boards/feather_m0_express/board.mk +++ /dev/null @@ -1,9 +0,0 @@ -CFLAGS += -D__SAMD21G18A__ -DCFG_EXAMPLE_VIDEO_READONLY - -# All source paths should be relative to the top level. -LD_FILE = $(BOARD_PATH)/$(BOARD).ld - -# For flash-jlink target -JLINK_DEVICE = ATSAMD21G18 - -flash: flash-bossac diff --git a/hw/bsp/samd21/boards/feather_m0_express/feather_m0_express.ld b/hw/bsp/samd21/boards/feather_m0_express/feather_m0_express.ld deleted file mode 100644 index ce7aff80b..000000000 --- a/hw/bsp/samd21/boards/feather_m0_express/feather_m0_express.ld +++ /dev/null @@ -1,146 +0,0 @@ -/** - * \file - * - * \brief Linker script for running in internal FLASH on the SAMD21G18A - * - * Copyright (c) 2017 Microchip Technology Inc. - * - * \asf_license_start - * - * \page License - * - * 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 Licence 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. - * - * \asf_license_stop - * - */ - - -OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") -OUTPUT_ARCH(arm) -SEARCH_DIR(.) - -/* Memory Spaces Definitions */ -MEMORY -{ - rom (rx) : ORIGIN = 0x00000000 + 8K, LENGTH = 0x00040000 - 8K - ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000 -} - -/* The stack size used by the application. NOTE: you need to adjust according to your application. */ -STACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x2000; - -ENTRY(Reset_Handler) - -/* Section Definitions */ -SECTIONS -{ - .text : - { - . = ALIGN(4); - _sfixed = .; - KEEP(*(.vectors .vectors.*)) - *(.text .text.* .gnu.linkonce.t.*) - *(.glue_7t) *(.glue_7) - *(.rodata .rodata* .gnu.linkonce.r.*) - *(.ARM.extab* .gnu.linkonce.armextab.*) - - /* Support C constructors, and C destructors in both user code - and the C library. This also provides support for C++ code. */ - . = ALIGN(4); - KEEP(*(.init)) - . = ALIGN(4); - __preinit_array_start = .; - KEEP (*(.preinit_array)) - __preinit_array_end = .; - - . = ALIGN(4); - __init_array_start = .; - KEEP (*(SORT(.init_array.*))) - KEEP (*(.init_array)) - __init_array_end = .; - - . = ALIGN(4); - KEEP (*crtbegin.o(.ctors)) - KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) - KEEP (*(SORT(.ctors.*))) - KEEP (*crtend.o(.ctors)) - - . = ALIGN(4); - KEEP(*(.fini)) - - . = ALIGN(4); - __fini_array_start = .; - KEEP (*(.fini_array)) - KEEP (*(SORT(.fini_array.*))) - __fini_array_end = .; - - KEEP (*crtbegin.o(.dtors)) - KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) - KEEP (*(SORT(.dtors.*))) - KEEP (*crtend.o(.dtors)) - - . = ALIGN(4); - _efixed = .; /* End of text section */ - } > rom - - /* .ARM.exidx is sorted, so has to go in its own output section. */ - PROVIDE_HIDDEN (__exidx_start = .); - .ARM.exidx : - { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - } > rom - PROVIDE_HIDDEN (__exidx_end = .); - - . = ALIGN(4); - _etext = .; - - .relocate : AT (_etext) - { - . = ALIGN(4); - _srelocate = .; - *(.ramfunc .ramfunc.*); - *(.data .data.*); - . = ALIGN(4); - _erelocate = .; - } > ram - - /* .bss section which is used for uninitialized data */ - .bss (NOLOAD) : - { - . = ALIGN(4); - _sbss = . ; - _szero = .; - *(.bss .bss.*) - *(COMMON) - . = ALIGN(4); - _ebss = . ; - _ezero = .; - end = .; - } > ram - - /* stack section */ - .stack (NOLOAD): - { - . = ALIGN(8); - _sstack = .; - . = . + STACK_SIZE; - . = ALIGN(8); - _estack = .; - } > ram - - . = ALIGN(4); - _end = . ; -} diff --git a/hw/bsp/samd21/boards/itsybitsy_m0/board.cmake b/hw/bsp/samd21/boards/itsybitsy_m0/board.cmake deleted file mode 100644 index c1a612936..000000000 --- a/hw/bsp/samd21/boards/itsybitsy_m0/board.cmake +++ /dev/null @@ -1,9 +0,0 @@ -set(JLINK_DEVICE ATSAMD21G18) -set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/${BOARD}.ld) - -function(update_board TARGET) - target_compile_definitions(${TARGET} PUBLIC - __SAMD21G18A__ - CFG_EXAMPLE_VIDEO_READONLY - ) -endfunction() diff --git a/hw/bsp/samd21/boards/itsybitsy_m0/board.h b/hw/bsp/samd21/boards/itsybitsy_m0/board.h deleted file mode 100644 index d901b2ea4..000000000 --- a/hw/bsp/samd21/boards/itsybitsy_m0/board.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * 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 ItsyBitsy M0 - url: https://www.adafruit.com/product/3727 -*/ - -#ifndef BOARD_H_ -#define BOARD_H_ - -#ifdef __cplusplus - extern "C" { -#endif - -// LED -#define LED_PIN 17 -#define LED_STATE_ON 1 - -// Button -#define BUTTON_PIN 21 -#define BUTTON_STATE_ACTIVE 0 - -// UART -#define UART_RX_PIN 4 -#define UART_TX_PIN 5 - -static inline void board_vbus_set(uint8_t rhport, bool state) { - (void) rhport; (void) state; -} - -#ifdef __cplusplus - } -#endif - -#endif /* BOARD_H_ */ diff --git a/hw/bsp/samd21/boards/itsybitsy_m0/board.mk b/hw/bsp/samd21/boards/itsybitsy_m0/board.mk deleted file mode 100644 index d6c9150b3..000000000 --- a/hw/bsp/samd21/boards/itsybitsy_m0/board.mk +++ /dev/null @@ -1,9 +0,0 @@ -CFLAGS += -D__SAMD21G18A__ -DCFG_EXAMPLE_VIDEO_READONLY - -# All source paths should be relative to the top level. -LD_FILE = $(BOARD_PATH)/$(BOARD).ld - -# For flash-jlink target -JLINK_DEVICE = ATSAMD21G18 - -flash: flash-bossac diff --git a/hw/bsp/samd21/boards/itsybitsy_m0/itsybitsy_m0.ld b/hw/bsp/samd21/boards/itsybitsy_m0/itsybitsy_m0.ld deleted file mode 100644 index ce7aff80b..000000000 --- a/hw/bsp/samd21/boards/itsybitsy_m0/itsybitsy_m0.ld +++ /dev/null @@ -1,146 +0,0 @@ -/** - * \file - * - * \brief Linker script for running in internal FLASH on the SAMD21G18A - * - * Copyright (c) 2017 Microchip Technology Inc. - * - * \asf_license_start - * - * \page License - * - * 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 Licence 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. - * - * \asf_license_stop - * - */ - - -OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") -OUTPUT_ARCH(arm) -SEARCH_DIR(.) - -/* Memory Spaces Definitions */ -MEMORY -{ - rom (rx) : ORIGIN = 0x00000000 + 8K, LENGTH = 0x00040000 - 8K - ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000 -} - -/* The stack size used by the application. NOTE: you need to adjust according to your application. */ -STACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x2000; - -ENTRY(Reset_Handler) - -/* Section Definitions */ -SECTIONS -{ - .text : - { - . = ALIGN(4); - _sfixed = .; - KEEP(*(.vectors .vectors.*)) - *(.text .text.* .gnu.linkonce.t.*) - *(.glue_7t) *(.glue_7) - *(.rodata .rodata* .gnu.linkonce.r.*) - *(.ARM.extab* .gnu.linkonce.armextab.*) - - /* Support C constructors, and C destructors in both user code - and the C library. This also provides support for C++ code. */ - . = ALIGN(4); - KEEP(*(.init)) - . = ALIGN(4); - __preinit_array_start = .; - KEEP (*(.preinit_array)) - __preinit_array_end = .; - - . = ALIGN(4); - __init_array_start = .; - KEEP (*(SORT(.init_array.*))) - KEEP (*(.init_array)) - __init_array_end = .; - - . = ALIGN(4); - KEEP (*crtbegin.o(.ctors)) - KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) - KEEP (*(SORT(.ctors.*))) - KEEP (*crtend.o(.ctors)) - - . = ALIGN(4); - KEEP(*(.fini)) - - . = ALIGN(4); - __fini_array_start = .; - KEEP (*(.fini_array)) - KEEP (*(SORT(.fini_array.*))) - __fini_array_end = .; - - KEEP (*crtbegin.o(.dtors)) - KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) - KEEP (*(SORT(.dtors.*))) - KEEP (*crtend.o(.dtors)) - - . = ALIGN(4); - _efixed = .; /* End of text section */ - } > rom - - /* .ARM.exidx is sorted, so has to go in its own output section. */ - PROVIDE_HIDDEN (__exidx_start = .); - .ARM.exidx : - { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - } > rom - PROVIDE_HIDDEN (__exidx_end = .); - - . = ALIGN(4); - _etext = .; - - .relocate : AT (_etext) - { - . = ALIGN(4); - _srelocate = .; - *(.ramfunc .ramfunc.*); - *(.data .data.*); - . = ALIGN(4); - _erelocate = .; - } > ram - - /* .bss section which is used for uninitialized data */ - .bss (NOLOAD) : - { - . = ALIGN(4); - _sbss = . ; - _szero = .; - *(.bss .bss.*) - *(COMMON) - . = ALIGN(4); - _ebss = . ; - _ezero = .; - end = .; - } > ram - - /* stack section */ - .stack (NOLOAD): - { - . = ALIGN(8); - _sstack = .; - . = . + STACK_SIZE; - . = ALIGN(8); - _estack = .; - } > ram - - . = ALIGN(4); - _end = . ; -} diff --git a/hw/bsp/samd21/boards/metro_m0_express/board.cmake b/hw/bsp/samd21/boards/metro_m0_express/board.cmake deleted file mode 100644 index c1a612936..000000000 --- a/hw/bsp/samd21/boards/metro_m0_express/board.cmake +++ /dev/null @@ -1,9 +0,0 @@ -set(JLINK_DEVICE ATSAMD21G18) -set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/${BOARD}.ld) - -function(update_board TARGET) - target_compile_definitions(${TARGET} PUBLIC - __SAMD21G18A__ - CFG_EXAMPLE_VIDEO_READONLY - ) -endfunction() diff --git a/hw/bsp/samd21/boards/metro_m0_express/board.h b/hw/bsp/samd21/boards/metro_m0_express/board.h deleted file mode 100644 index 726de3259..000000000 --- a/hw/bsp/samd21/boards/metro_m0_express/board.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * 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 Metro M0 Express - url: https://www.adafruit.com/product/3505 -*/ - -#ifndef BOARD_H_ -#define BOARD_H_ - -#ifdef __cplusplus - extern "C" { -#endif - -// LED -#define LED_PIN 17 -#define LED_STATE_ON 1 - -// Button: D5 -#define BUTTON_PIN 15 -#define BUTTON_STATE_ACTIVE 0 - -// UART -#define UART_RX_PIN 4 -#define UART_TX_PIN 5 - -// SPI for USB host shield -#define MAX3421_SERCOM_ID 4 // SERCOM4 -#define MAX3421_SERCOM_FUNCTION 3 // function D (Sercom Alt) - -#define MAX3421_SCK_PIN (32+11) -#define MAX3421_MOSI_PIN (32+10) -#define MAX3421_MISO_PIN 12 -#define MAX3421_TX_PAD 1 // MOSI = PAD_2, SCK = PAD_3 -#define MAX3421_RX_PAD 0 // MISO = PAD_2 - -#define MAX3421_CS_PIN 18 // D10 - -#define MAX3421_INTR_PIN 7 // D9 -#define MAX3421_INTR_EIC_ID 7 // EIC7 - -static inline void board_vbus_set(uint8_t rhport, bool state) { - (void) rhport; (void) state; -} - -#ifdef __cplusplus - } -#endif - -#endif /* BOARD_H_ */ diff --git a/hw/bsp/samd21/boards/metro_m0_express/board.mk b/hw/bsp/samd21/boards/metro_m0_express/board.mk deleted file mode 100644 index d6c9150b3..000000000 --- a/hw/bsp/samd21/boards/metro_m0_express/board.mk +++ /dev/null @@ -1,9 +0,0 @@ -CFLAGS += -D__SAMD21G18A__ -DCFG_EXAMPLE_VIDEO_READONLY - -# All source paths should be relative to the top level. -LD_FILE = $(BOARD_PATH)/$(BOARD).ld - -# For flash-jlink target -JLINK_DEVICE = ATSAMD21G18 - -flash: flash-bossac diff --git a/hw/bsp/samd21/boards/metro_m0_express/metro_m0_express.ld b/hw/bsp/samd21/boards/metro_m0_express/metro_m0_express.ld deleted file mode 100644 index ce7aff80b..000000000 --- a/hw/bsp/samd21/boards/metro_m0_express/metro_m0_express.ld +++ /dev/null @@ -1,146 +0,0 @@ -/** - * \file - * - * \brief Linker script for running in internal FLASH on the SAMD21G18A - * - * Copyright (c) 2017 Microchip Technology Inc. - * - * \asf_license_start - * - * \page License - * - * 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 Licence 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. - * - * \asf_license_stop - * - */ - - -OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") -OUTPUT_ARCH(arm) -SEARCH_DIR(.) - -/* Memory Spaces Definitions */ -MEMORY -{ - rom (rx) : ORIGIN = 0x00000000 + 8K, LENGTH = 0x00040000 - 8K - ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000 -} - -/* The stack size used by the application. NOTE: you need to adjust according to your application. */ -STACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x2000; - -ENTRY(Reset_Handler) - -/* Section Definitions */ -SECTIONS -{ - .text : - { - . = ALIGN(4); - _sfixed = .; - KEEP(*(.vectors .vectors.*)) - *(.text .text.* .gnu.linkonce.t.*) - *(.glue_7t) *(.glue_7) - *(.rodata .rodata* .gnu.linkonce.r.*) - *(.ARM.extab* .gnu.linkonce.armextab.*) - - /* Support C constructors, and C destructors in both user code - and the C library. This also provides support for C++ code. */ - . = ALIGN(4); - KEEP(*(.init)) - . = ALIGN(4); - __preinit_array_start = .; - KEEP (*(.preinit_array)) - __preinit_array_end = .; - - . = ALIGN(4); - __init_array_start = .; - KEEP (*(SORT(.init_array.*))) - KEEP (*(.init_array)) - __init_array_end = .; - - . = ALIGN(4); - KEEP (*crtbegin.o(.ctors)) - KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) - KEEP (*(SORT(.ctors.*))) - KEEP (*crtend.o(.ctors)) - - . = ALIGN(4); - KEEP(*(.fini)) - - . = ALIGN(4); - __fini_array_start = .; - KEEP (*(.fini_array)) - KEEP (*(SORT(.fini_array.*))) - __fini_array_end = .; - - KEEP (*crtbegin.o(.dtors)) - KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) - KEEP (*(SORT(.dtors.*))) - KEEP (*crtend.o(.dtors)) - - . = ALIGN(4); - _efixed = .; /* End of text section */ - } > rom - - /* .ARM.exidx is sorted, so has to go in its own output section. */ - PROVIDE_HIDDEN (__exidx_start = .); - .ARM.exidx : - { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - } > rom - PROVIDE_HIDDEN (__exidx_end = .); - - . = ALIGN(4); - _etext = .; - - .relocate : AT (_etext) - { - . = ALIGN(4); - _srelocate = .; - *(.ramfunc .ramfunc.*); - *(.data .data.*); - . = ALIGN(4); - _erelocate = .; - } > ram - - /* .bss section which is used for uninitialized data */ - .bss (NOLOAD) : - { - . = ALIGN(4); - _sbss = . ; - _szero = .; - *(.bss .bss.*) - *(COMMON) - . = ALIGN(4); - _ebss = . ; - _ezero = .; - end = .; - } > ram - - /* stack section */ - .stack (NOLOAD): - { - . = ALIGN(8); - _sstack = .; - . = . + STACK_SIZE; - . = ALIGN(8); - _estack = .; - } > ram - - . = ALIGN(4); - _end = . ; -} diff --git a/hw/bsp/samd21/boards/qtpy/board.cmake b/hw/bsp/samd21/boards/qtpy/board.cmake deleted file mode 100644 index f6cd446dd..000000000 --- a/hw/bsp/samd21/boards/qtpy/board.cmake +++ /dev/null @@ -1,9 +0,0 @@ -set(JLINK_DEVICE ATSAMD21E18) -set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/${BOARD}.ld) - -function(update_board TARGET) - target_compile_definitions(${TARGET} PUBLIC - __SAMD21E18A__ - CFG_EXAMPLE_VIDEO_READONLY - ) -endfunction() diff --git a/hw/bsp/samd21/boards/qtpy/board.h b/hw/bsp/samd21/boards/qtpy/board.h deleted file mode 100644 index b1cf338e4..000000000 --- a/hw/bsp/samd21/boards/qtpy/board.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * 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 QT Py - url: https://www.adafruit.com/product/4600 -*/ - -#ifndef BOARD_H_ -#define BOARD_H_ - -#ifdef __cplusplus - extern "C" { -#endif - -// LED is neopixel, leave unset for now - -// Button is wired to reset - -// UART -#define UART_RX_PIN 8 -#define UART_TX_PIN 7 - -static inline void board_vbus_set(uint8_t rhport, bool state) { - (void) rhport; (void) state; -} - -#ifdef __cplusplus - } -#endif - -#endif /* BOARD_H_ */ diff --git a/hw/bsp/samd21/boards/qtpy/board.mk b/hw/bsp/samd21/boards/qtpy/board.mk deleted file mode 100644 index 6cefa84c3..000000000 --- a/hw/bsp/samd21/boards/qtpy/board.mk +++ /dev/null @@ -1,11 +0,0 @@ -# For Adafruit QT Py board - -CFLAGS += -D__SAMD21E18A__ -DCFG_EXAMPLE_VIDEO_READONLY - -# All source paths should be relative to the top level. -LD_FILE = $(BOARD_PATH)/$(BOARD).ld - -# For flash-jlink target -JLINK_DEVICE = ATSAMD21E18 - -flash: flash-bossac diff --git a/hw/bsp/samd21/boards/qtpy/qtpy.ld b/hw/bsp/samd21/boards/qtpy/qtpy.ld deleted file mode 100644 index ce7aff80b..000000000 --- a/hw/bsp/samd21/boards/qtpy/qtpy.ld +++ /dev/null @@ -1,146 +0,0 @@ -/** - * \file - * - * \brief Linker script for running in internal FLASH on the SAMD21G18A - * - * Copyright (c) 2017 Microchip Technology Inc. - * - * \asf_license_start - * - * \page License - * - * 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 Licence 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. - * - * \asf_license_stop - * - */ - - -OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") -OUTPUT_ARCH(arm) -SEARCH_DIR(.) - -/* Memory Spaces Definitions */ -MEMORY -{ - rom (rx) : ORIGIN = 0x00000000 + 8K, LENGTH = 0x00040000 - 8K - ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000 -} - -/* The stack size used by the application. NOTE: you need to adjust according to your application. */ -STACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x2000; - -ENTRY(Reset_Handler) - -/* Section Definitions */ -SECTIONS -{ - .text : - { - . = ALIGN(4); - _sfixed = .; - KEEP(*(.vectors .vectors.*)) - *(.text .text.* .gnu.linkonce.t.*) - *(.glue_7t) *(.glue_7) - *(.rodata .rodata* .gnu.linkonce.r.*) - *(.ARM.extab* .gnu.linkonce.armextab.*) - - /* Support C constructors, and C destructors in both user code - and the C library. This also provides support for C++ code. */ - . = ALIGN(4); - KEEP(*(.init)) - . = ALIGN(4); - __preinit_array_start = .; - KEEP (*(.preinit_array)) - __preinit_array_end = .; - - . = ALIGN(4); - __init_array_start = .; - KEEP (*(SORT(.init_array.*))) - KEEP (*(.init_array)) - __init_array_end = .; - - . = ALIGN(4); - KEEP (*crtbegin.o(.ctors)) - KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) - KEEP (*(SORT(.ctors.*))) - KEEP (*crtend.o(.ctors)) - - . = ALIGN(4); - KEEP(*(.fini)) - - . = ALIGN(4); - __fini_array_start = .; - KEEP (*(.fini_array)) - KEEP (*(SORT(.fini_array.*))) - __fini_array_end = .; - - KEEP (*crtbegin.o(.dtors)) - KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) - KEEP (*(SORT(.dtors.*))) - KEEP (*crtend.o(.dtors)) - - . = ALIGN(4); - _efixed = .; /* End of text section */ - } > rom - - /* .ARM.exidx is sorted, so has to go in its own output section. */ - PROVIDE_HIDDEN (__exidx_start = .); - .ARM.exidx : - { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - } > rom - PROVIDE_HIDDEN (__exidx_end = .); - - . = ALIGN(4); - _etext = .; - - .relocate : AT (_etext) - { - . = ALIGN(4); - _srelocate = .; - *(.ramfunc .ramfunc.*); - *(.data .data.*); - . = ALIGN(4); - _erelocate = .; - } > ram - - /* .bss section which is used for uninitialized data */ - .bss (NOLOAD) : - { - . = ALIGN(4); - _sbss = . ; - _szero = .; - *(.bss .bss.*) - *(COMMON) - . = ALIGN(4); - _ebss = . ; - _ezero = .; - end = .; - } > ram - - /* stack section */ - .stack (NOLOAD): - { - . = ALIGN(8); - _sstack = .; - . = . + STACK_SIZE; - . = ALIGN(8); - _estack = .; - } > ram - - . = ALIGN(4); - _end = . ; -} diff --git a/hw/bsp/samd21/boards/seeeduino_xiao/board.cmake b/hw/bsp/samd21/boards/seeeduino_xiao/board.cmake deleted file mode 100644 index c1a612936..000000000 --- a/hw/bsp/samd21/boards/seeeduino_xiao/board.cmake +++ /dev/null @@ -1,9 +0,0 @@ -set(JLINK_DEVICE ATSAMD21G18) -set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/${BOARD}.ld) - -function(update_board TARGET) - target_compile_definitions(${TARGET} PUBLIC - __SAMD21G18A__ - CFG_EXAMPLE_VIDEO_READONLY - ) -endfunction() diff --git a/hw/bsp/samd21/boards/seeeduino_xiao/board.h b/hw/bsp/samd21/boards/seeeduino_xiao/board.h deleted file mode 100644 index 1c434c68c..000000000 --- a/hw/bsp/samd21/boards/seeeduino_xiao/board.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * 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: Seeeduino XIAO - url: https://wiki.seeedstudio.com/Seeeduino-XIAO/ -*/ - -#ifndef BOARD_H_ -#define BOARD_H_ - -#ifdef __cplusplus - extern "C" { -#endif - -// LED -#define LED_PIN 17 -#define LED_STATE_ON 0 - -// Button -#define BUTTON_PIN 9 // PA4 pin D1 on seed input -#define BUTTON_STATE_ACTIVE 0 - -// UART -#define UART_RX_PIN 4 -#define UART_TX_PIN 5 - -static inline void board_vbus_set(uint8_t rhport, bool state) { - (void) rhport; (void) state; -} - -#ifdef __cplusplus - } -#endif - -#endif /* BOARD_H_ */ diff --git a/hw/bsp/samd21/boards/seeeduino_xiao/board.mk b/hw/bsp/samd21/boards/seeeduino_xiao/board.mk deleted file mode 100644 index 1c888da3a..000000000 --- a/hw/bsp/samd21/boards/seeeduino_xiao/board.mk +++ /dev/null @@ -1,9 +0,0 @@ -CFLAGS += -D__SAMD21G18A__ -DCFG_EXAMPLE_VIDEO_READONLY - -LD_FILE = $(BOARD_PATH)/$(BOARD).ld - -# For flash-jlink target -JLINK_DEVICE = ATSAMD21G18 - -# flash using jlink -flash: flash-jlink diff --git a/hw/bsp/samd21/boards/seeeduino_xiao/seeeduino_xiao.ld b/hw/bsp/samd21/boards/seeeduino_xiao/seeeduino_xiao.ld deleted file mode 100644 index 0d0c4e6c4..000000000 --- a/hw/bsp/samd21/boards/seeeduino_xiao/seeeduino_xiao.ld +++ /dev/null @@ -1,146 +0,0 @@ -/** - * \file - * - * \brief Linker script for running in internal FLASH on the SAMD21G18A - * - * Copyright (c) 2017 Microchip Technology Inc. - * - * \asf_license_start - * - * \page License - * - * 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 Licence 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. - * - * \asf_license_stop - * - */ - - -OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") -OUTPUT_ARCH(arm) -SEARCH_DIR(.) - -/* Memory Spaces Definitions */ -MEMORY -{ - rom (rx) : ORIGIN = 0x00000000 + 8K, LENGTH = 0x00040000 - 8K /* 8K offset to preserve bootloader */ - ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000 -} - -/* The stack size used by the application. NOTE: you need to adjust according to your application. */ -STACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x2000; - -ENTRY(Reset_Handler) - -/* Section Definitions */ -SECTIONS -{ - .text : - { - . = ALIGN(4); - _sfixed = .; - KEEP(*(.vectors .vectors.*)) - *(.text .text.* .gnu.linkonce.t.*) - *(.glue_7t) *(.glue_7) - *(.rodata .rodata* .gnu.linkonce.r.*) - *(.ARM.extab* .gnu.linkonce.armextab.*) - - /* Support C constructors, and C destructors in both user code - and the C library. This also provides support for C++ code. */ - . = ALIGN(4); - KEEP(*(.init)) - . = ALIGN(4); - __preinit_array_start = .; - KEEP (*(.preinit_array)) - __preinit_array_end = .; - - . = ALIGN(4); - __init_array_start = .; - KEEP (*(SORT(.init_array.*))) - KEEP (*(.init_array)) - __init_array_end = .; - - . = ALIGN(4); - KEEP (*crtbegin.o(.ctors)) - KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) - KEEP (*(SORT(.ctors.*))) - KEEP (*crtend.o(.ctors)) - - . = ALIGN(4); - KEEP(*(.fini)) - - . = ALIGN(4); - __fini_array_start = .; - KEEP (*(.fini_array)) - KEEP (*(SORT(.fini_array.*))) - __fini_array_end = .; - - KEEP (*crtbegin.o(.dtors)) - KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) - KEEP (*(SORT(.dtors.*))) - KEEP (*crtend.o(.dtors)) - - . = ALIGN(4); - _efixed = .; /* End of text section */ - } > rom - - /* .ARM.exidx is sorted, so has to go in its own output section. */ - PROVIDE_HIDDEN (__exidx_start = .); - .ARM.exidx : - { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - } > rom - PROVIDE_HIDDEN (__exidx_end = .); - - . = ALIGN(4); - _etext = .; - - .relocate : AT (_etext) - { - . = ALIGN(4); - _srelocate = .; - *(.ramfunc .ramfunc.*); - *(.data .data.*); - . = ALIGN(4); - _erelocate = .; - } > ram - - /* .bss section which is used for uninitialized data */ - .bss (NOLOAD) : - { - . = ALIGN(4); - _sbss = . ; - _szero = .; - *(.bss .bss.*) - *(COMMON) - . = ALIGN(4); - _ebss = . ; - _ezero = .; - end = .; - } > ram - - /* stack section */ - .stack (NOLOAD): - { - . = ALIGN(8); - _sstack = .; - . = . + STACK_SIZE; - . = ALIGN(8); - _estack = .; - } > ram - - . = ALIGN(4); - _end = . ; -} diff --git a/hw/bsp/samd21/boards/sparkfun_samd21_mini_usb/board.cmake b/hw/bsp/samd21/boards/sparkfun_samd21_mini_usb/board.cmake deleted file mode 100644 index c1a612936..000000000 --- a/hw/bsp/samd21/boards/sparkfun_samd21_mini_usb/board.cmake +++ /dev/null @@ -1,9 +0,0 @@ -set(JLINK_DEVICE ATSAMD21G18) -set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/${BOARD}.ld) - -function(update_board TARGET) - target_compile_definitions(${TARGET} PUBLIC - __SAMD21G18A__ - CFG_EXAMPLE_VIDEO_READONLY - ) -endfunction() diff --git a/hw/bsp/samd21/boards/sparkfun_samd21_mini_usb/board.h b/hw/bsp/samd21/boards/sparkfun_samd21_mini_usb/board.h deleted file mode 100644 index a05cf5e4e..000000000 --- a/hw/bsp/samd21/boards/sparkfun_samd21_mini_usb/board.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * 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: SparkFun SAMD21 Mini - url: https://www.sparkfun.com/products/13664 -*/ - -#ifndef BOARD_H_ -#define BOARD_H_ - -#ifdef __cplusplus - extern "C" { -#endif - -// LED -#define LED_PIN 17 // PA17 (D13) -#define LED_STATE_ON 1 - -// Button -#define BUTTON_PIN 14 // PA14 (D2) -#define BUTTON_STATE_ACTIVE 0 - -// UART -#define UART_SERCOM 0 -#define UART_RX_PIN 11 // PA11 D0 -#define UART_TX_PIN 10 // PA10 D1 - -static inline void board_vbus_set(uint8_t rhport, bool state) { - (void) rhport; - gpio_set_pin_direction(PIN_PA28, GPIO_DIRECTION_OUT); - gpio_set_pin_level(PIN_PA28, state); -} - -#ifdef __cplusplus - } -#endif - -#endif /* BOARD_H_ */ diff --git a/hw/bsp/samd21/boards/sparkfun_samd21_mini_usb/board.mk b/hw/bsp/samd21/boards/sparkfun_samd21_mini_usb/board.mk deleted file mode 100644 index d6c9150b3..000000000 --- a/hw/bsp/samd21/boards/sparkfun_samd21_mini_usb/board.mk +++ /dev/null @@ -1,9 +0,0 @@ -CFLAGS += -D__SAMD21G18A__ -DCFG_EXAMPLE_VIDEO_READONLY - -# All source paths should be relative to the top level. -LD_FILE = $(BOARD_PATH)/$(BOARD).ld - -# For flash-jlink target -JLINK_DEVICE = ATSAMD21G18 - -flash: flash-bossac diff --git a/hw/bsp/samd21/boards/sparkfun_samd21_mini_usb/sparkfun_samd21_mini_usb.ld b/hw/bsp/samd21/boards/sparkfun_samd21_mini_usb/sparkfun_samd21_mini_usb.ld deleted file mode 100644 index 0754a8e9c..000000000 --- a/hw/bsp/samd21/boards/sparkfun_samd21_mini_usb/sparkfun_samd21_mini_usb.ld +++ /dev/null @@ -1,146 +0,0 @@ -/** - * \file - * - * \brief Linker script for running in internal FLASH on the SAMD21G18A - * - * Copyright (c) 2017 Microchip Technology Inc. - * - * \asf_license_start - * - * \page License - * - * 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 Licence 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. - * - * \asf_license_stop - * - */ - - -OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") -OUTPUT_ARCH(arm) -SEARCH_DIR(.) - -/* Memory Spaces Definitions */ -MEMORY -{ - rom (rx) : ORIGIN = 0x00000000 + 8K, LENGTH = 0x00040000 - 8K - ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000-0x0004 /* 4 bytes used by bootloader to keep data between resets */ -} - -/* The stack size used by the application. NOTE: you need to adjust according to your application. */ -STACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x2000; - -ENTRY(Reset_Handler) - -/* Section Definitions */ -SECTIONS -{ - .text : - { - . = ALIGN(4); - _sfixed = .; - KEEP(*(.vectors .vectors.*)) - *(.text .text.* .gnu.linkonce.t.*) - *(.glue_7t) *(.glue_7) - *(.rodata .rodata* .gnu.linkonce.r.*) - *(.ARM.extab* .gnu.linkonce.armextab.*) - - /* Support C constructors, and C destructors in both user code - and the C library. This also provides support for C++ code. */ - . = ALIGN(4); - KEEP(*(.init)) - . = ALIGN(4); - __preinit_array_start = .; - KEEP (*(.preinit_array)) - __preinit_array_end = .; - - . = ALIGN(4); - __init_array_start = .; - KEEP (*(SORT(.init_array.*))) - KEEP (*(.init_array)) - __init_array_end = .; - - . = ALIGN(4); - KEEP (*crtbegin.o(.ctors)) - KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) - KEEP (*(SORT(.ctors.*))) - KEEP (*crtend.o(.ctors)) - - . = ALIGN(4); - KEEP(*(.fini)) - - . = ALIGN(4); - __fini_array_start = .; - KEEP (*(.fini_array)) - KEEP (*(SORT(.fini_array.*))) - __fini_array_end = .; - - KEEP (*crtbegin.o(.dtors)) - KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) - KEEP (*(SORT(.dtors.*))) - KEEP (*crtend.o(.dtors)) - - . = ALIGN(4); - _efixed = .; /* End of text section */ - } > rom - - /* .ARM.exidx is sorted, so has to go in its own output section. */ - PROVIDE_HIDDEN (__exidx_start = .); - .ARM.exidx : - { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - } > rom - PROVIDE_HIDDEN (__exidx_end = .); - - . = ALIGN(4); - _etext = .; - - .relocate : AT (_etext) - { - . = ALIGN(4); - _srelocate = .; - *(.ramfunc .ramfunc.*); - *(.data .data.*); - . = ALIGN(4); - _erelocate = .; - } > ram - - /* .bss section which is used for uninitialized data */ - .bss (NOLOAD) : - { - . = ALIGN(4); - _sbss = . ; - _szero = .; - *(.bss .bss.*) - *(COMMON) - . = ALIGN(4); - _ebss = . ; - _ezero = .; - end = .; - } > ram - - /* stack section */ - .stack (NOLOAD): - { - . = ALIGN(8); - _sstack = .; - . = . + STACK_SIZE; - . = ALIGN(8); - _estack = .; - } > ram - - . = ALIGN(4); - _end = . ; -} diff --git a/hw/bsp/samd21/boards/trinket_m0/board.cmake b/hw/bsp/samd21/boards/trinket_m0/board.cmake deleted file mode 100644 index f6cd446dd..000000000 --- a/hw/bsp/samd21/boards/trinket_m0/board.cmake +++ /dev/null @@ -1,9 +0,0 @@ -set(JLINK_DEVICE ATSAMD21E18) -set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/${BOARD}.ld) - -function(update_board TARGET) - target_compile_definitions(${TARGET} PUBLIC - __SAMD21E18A__ - CFG_EXAMPLE_VIDEO_READONLY - ) -endfunction() diff --git a/hw/bsp/samd21/boards/trinket_m0/board.h b/hw/bsp/samd21/boards/trinket_m0/board.h deleted file mode 100644 index 01ad83089..000000000 --- a/hw/bsp/samd21/boards/trinket_m0/board.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2021 Jean Gressmann - * - * 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. - * - */ - -/* metadata: - name: Adafruit Trinket M0 - url: https://www.adafruit.com/product/3500 -*/ - -#pragma once - -// LED -#define LED_PIN 10 // PA10 -#define LED_STATE_ON 1 - -// UART -#define UART_SERCOM 0 -#define UART_RX_PIN 7 -#define UART_TX_PIN 6 - -static inline void board_vbus_set(uint8_t rhport, bool state) { - (void) rhport; (void) state; -} diff --git a/hw/bsp/samd21/boards/trinket_m0/board.mk b/hw/bsp/samd21/boards/trinket_m0/board.mk deleted file mode 100644 index 6addf13b7..000000000 --- a/hw/bsp/samd21/boards/trinket_m0/board.mk +++ /dev/null @@ -1,4 +0,0 @@ -CFLAGS += -D__SAMD21E18A__ -DCFG_EXAMPLE_VIDEO_READONLY - -# All source paths should be relative to the top level. -LD_FILE = $(BOARD_PATH)/trinket_m0.ld diff --git a/hw/bsp/samd21/boards/trinket_m0/trinket_m0.ld b/hw/bsp/samd21/boards/trinket_m0/trinket_m0.ld deleted file mode 100644 index ce7aff80b..000000000 --- a/hw/bsp/samd21/boards/trinket_m0/trinket_m0.ld +++ /dev/null @@ -1,146 +0,0 @@ -/** - * \file - * - * \brief Linker script for running in internal FLASH on the SAMD21G18A - * - * Copyright (c) 2017 Microchip Technology Inc. - * - * \asf_license_start - * - * \page License - * - * 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 Licence 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. - * - * \asf_license_stop - * - */ - - -OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") -OUTPUT_ARCH(arm) -SEARCH_DIR(.) - -/* Memory Spaces Definitions */ -MEMORY -{ - rom (rx) : ORIGIN = 0x00000000 + 8K, LENGTH = 0x00040000 - 8K - ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000 -} - -/* The stack size used by the application. NOTE: you need to adjust according to your application. */ -STACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x2000; - -ENTRY(Reset_Handler) - -/* Section Definitions */ -SECTIONS -{ - .text : - { - . = ALIGN(4); - _sfixed = .; - KEEP(*(.vectors .vectors.*)) - *(.text .text.* .gnu.linkonce.t.*) - *(.glue_7t) *(.glue_7) - *(.rodata .rodata* .gnu.linkonce.r.*) - *(.ARM.extab* .gnu.linkonce.armextab.*) - - /* Support C constructors, and C destructors in both user code - and the C library. This also provides support for C++ code. */ - . = ALIGN(4); - KEEP(*(.init)) - . = ALIGN(4); - __preinit_array_start = .; - KEEP (*(.preinit_array)) - __preinit_array_end = .; - - . = ALIGN(4); - __init_array_start = .; - KEEP (*(SORT(.init_array.*))) - KEEP (*(.init_array)) - __init_array_end = .; - - . = ALIGN(4); - KEEP (*crtbegin.o(.ctors)) - KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) - KEEP (*(SORT(.ctors.*))) - KEEP (*crtend.o(.ctors)) - - . = ALIGN(4); - KEEP(*(.fini)) - - . = ALIGN(4); - __fini_array_start = .; - KEEP (*(.fini_array)) - KEEP (*(SORT(.fini_array.*))) - __fini_array_end = .; - - KEEP (*crtbegin.o(.dtors)) - KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) - KEEP (*(SORT(.dtors.*))) - KEEP (*crtend.o(.dtors)) - - . = ALIGN(4); - _efixed = .; /* End of text section */ - } > rom - - /* .ARM.exidx is sorted, so has to go in its own output section. */ - PROVIDE_HIDDEN (__exidx_start = .); - .ARM.exidx : - { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - } > rom - PROVIDE_HIDDEN (__exidx_end = .); - - . = ALIGN(4); - _etext = .; - - .relocate : AT (_etext) - { - . = ALIGN(4); - _srelocate = .; - *(.ramfunc .ramfunc.*); - *(.data .data.*); - . = ALIGN(4); - _erelocate = .; - } > ram - - /* .bss section which is used for uninitialized data */ - .bss (NOLOAD) : - { - . = ALIGN(4); - _sbss = . ; - _szero = .; - *(.bss .bss.*) - *(COMMON) - . = ALIGN(4); - _ebss = . ; - _ezero = .; - end = .; - } > ram - - /* stack section */ - .stack (NOLOAD): - { - . = ALIGN(8); - _sstack = .; - . = . + STACK_SIZE; - . = ALIGN(8); - _estack = .; - } > ram - - . = ALIGN(4); - _end = . ; -} diff --git a/hw/bsp/samd21/family.c b/hw/bsp/samd21/family.c deleted file mode 100644 index 14e60e917..000000000 --- a/hw/bsp/samd21/family.c +++ /dev/null @@ -1,453 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 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: - manufacturer: Microchip -*/ - -#include "sam.h" -#include "bsp/board_api.h" - -// Suppress warning caused by mcu driver -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wcast-qual" -#endif - -#include "hal/include/hal_gpio.h" -#include "hal/include/hal_init.h" -#include "hri/hri_nvmctrl_d21.h" - -#include "hpl/gclk/hpl_gclk_base.h" -#include "hpl_pm_config.h" -#include "hpl/pm/hpl_pm_base.h" - -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif - -static inline void board_vbus_set(uint8_t rhport, bool state) TU_ATTR_UNUSED; -#include "board.h" - -//--------------------------------------------------------------------+ -// MACRO TYPEDEF CONSTANT ENUM DECLARATION -//--------------------------------------------------------------------+ - -/* Referenced GCLKs, should be initialized firstly */ -#define _GCLK_INIT_1ST (1 << 0 | 1 << 1) - -/* Not referenced GCLKs, initialized last */ -#define _GCLK_INIT_LAST (~_GCLK_INIT_1ST) - -//--------------------------------------------------------------------+ -// 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 && !CFG_TUH_MAX3421 - tuh_int_handler(0); -#endif -} - -//--------------------------------------------------------------------+ -// Implementation -//--------------------------------------------------------------------+ -static void uart_init(void); - -#if CFG_TUH_ENABLED && CFG_TUH_MAX3421 -#define MAX3421_SERCOM TU_XSTRCAT(SERCOM, MAX3421_SERCOM_ID) -static void max3421_init(void); -#endif - -void board_init(void) { - // Clock init ( follow hpl_init.c ) - hri_nvmctrl_set_CTRLB_RWS_bf(NVMCTRL, 2); - - _pm_init(); - _sysctrl_init_sources(); -#if _GCLK_INIT_1ST - _gclk_init_generators_by_fref(_GCLK_INIT_1ST); -#endif - _sysctrl_init_referenced_generators(); - _gclk_init_generators_by_fref(_GCLK_INIT_LAST); - - // Update SystemCoreClock since it is hard coded with asf4 and not correct - // Init 1ms tick timer (samd SystemCoreClock may not correct) - SystemCoreClock = CONF_CPU_FREQUENCY; -#if CFG_TUSB_OS == OPT_OS_NONE - SysTick_Config(CONF_CPU_FREQUENCY / 1000); -#endif - - // Led init -#ifdef LED_PIN - gpio_set_pin_direction(LED_PIN, GPIO_DIRECTION_OUT); - board_led_write(false); -#endif - - // Button init -#ifdef BUTTON_PIN - gpio_set_pin_direction(BUTTON_PIN, GPIO_DIRECTION_IN); - gpio_set_pin_pull_mode(BUTTON_PIN, BUTTON_STATE_ACTIVE ? GPIO_PULL_DOWN : GPIO_PULL_UP); -#endif - - uart_init(); - -#if 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 - - /* USB Clock init - * The USB module requires a GCLK_USB of 48 MHz ~ 0.25% clock - * for low speed and full speed operation. */ - _pm_enable_bus_clock(PM_BUS_APBB, USB); - _pm_enable_bus_clock(PM_BUS_AHB, USB); - _gclk_enable_channel(USB_GCLK_ID, GCLK_CLKCTRL_GEN_GCLK0_Val); - - // USB Pin Init - gpio_set_pin_direction(PIN_PA24, GPIO_DIRECTION_OUT); - gpio_set_pin_level(PIN_PA24, false); - gpio_set_pin_pull_mode(PIN_PA24, GPIO_PULL_OFF); - gpio_set_pin_direction(PIN_PA25, GPIO_DIRECTION_OUT); - gpio_set_pin_level(PIN_PA25, false); - gpio_set_pin_pull_mode(PIN_PA25, GPIO_PULL_OFF); - - gpio_set_pin_function(PIN_PA24, PINMUX_PA24G_USB_DM); - gpio_set_pin_function(PIN_PA25, PINMUX_PA25G_USB_DP); - - // Output 500hz PWM on D12 (PA19 - TCC0 WO[3]) so we can validate the GCLK0 clock speed with a Saleae. - _pm_enable_bus_clock(PM_BUS_APBC, TCC0); - TCC0->PER.bit.PER = 48000000 / 1000; - TCC0->CC[3].bit.CC = 48000000 / 2000; - TCC0->CTRLA.bit.ENABLE = true; - - 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 - #if CFG_TUH_MAX3421 - max3421_init(); - #else - // VBUS Power - board_vbus_set(0, true); - #endif -#endif -} - -//--------------------------------------------------------------------+ -// Board porting API -//--------------------------------------------------------------------+ - -void board_led_write(bool state) { - (void) state; -#ifdef LED_PIN - gpio_set_pin_level(LED_PIN, state ? LED_STATE_ON : (1 - LED_STATE_ON)); -#endif -} - -uint32_t board_button_read(void) { -#ifdef BUTTON_PIN - return BUTTON_STATE_ACTIVE == gpio_get_pin_level(BUTTON_PIN); -#else - return 0; -#endif -} - -#if defined(UART_SERCOM) - -#define BOARD_SERCOM2(n) SERCOM ## n -#define BOARD_SERCOM(n) BOARD_SERCOM2(n) - -static void uart_init(void) -{ -#if UART_SERCOM == 0 - #if UART_TX_PIN == 6 - gpio_set_pin_function(PIN_PA06, PINMUX_PA06D_SERCOM0_PAD2); - #elif UART_TX_PIN == 10 - gpio_set_pin_function(PIN_PA10, PINMUX_PA10C_SERCOM0_PAD2); - #else - #error "UART_TX_PIN not supported" - #endif - - #if UART_RX_PIN == 7 - gpio_set_pin_function(PIN_PA07, PINMUX_PA07D_SERCOM0_PAD3); - #elif UART_RX_PIN == 11 - gpio_set_pin_function(PIN_PA11, PINMUX_PA11C_SERCOM0_PAD3); - #else - #error "UART_RX_PIN not supported" -#endif - - // setup clock (48MHz) - _pm_enable_bus_clock(PM_BUS_APBC, SERCOM0); - _gclk_enable_channel(SERCOM0_GCLK_ID_CORE, GCLK_CLKCTRL_GEN_GCLK0_Val); - - SERCOM0->USART.CTRLA.bit.SWRST = 1; /* reset SERCOM & enable config */ - while(SERCOM0->USART.SYNCBUSY.bit.SWRST); - - SERCOM0->USART.CTRLA.reg = /* CMODE = 0 -> async, SAMPA = 0, FORM = 0 -> USART frame, SMPR = 0 -> arithmetic baud rate */ - SERCOM_USART_CTRLA_SAMPR(1) | /* 0 = 16x / arithmetic baud rate, 1 = 16x / fractional baud rate */ -// SERCOM_USART_CTRLA_FORM(0) | /* 0 = USART Frame, 2 = LIN Master */ - SERCOM_USART_CTRLA_DORD | /* LSB first */ - SERCOM_USART_CTRLA_MODE(1) | /* 0 = Asynchronous, 1 = USART with internal clock */ - SERCOM_USART_CTRLA_RXPO(3) | /* pad 3 */ - SERCOM_USART_CTRLA_TXPO(1); /* pad 2 */ - - SERCOM0->USART.CTRLB.reg = - SERCOM_USART_CTRLB_TXEN | /* tx enabled */ - SERCOM_USART_CTRLB_RXEN; /* rx enabled */ - - /* 115200 */ - SERCOM0->USART.BAUD.reg = SERCOM_USART_BAUD_FRAC_FP(0) | SERCOM_USART_BAUD_FRAC_BAUD(26); - - SERCOM0->USART.CTRLA.bit.ENABLE = 1; /* activate SERCOM */ - while(SERCOM0->USART.SYNCBUSY.bit.ENABLE); /* wait for SERCOM to be ready */ -#endif -} - -static inline void uart_send_buffer(uint8_t const *text, size_t len) -{ - for (size_t i = 0; i < len; ++i) { - BOARD_SERCOM(UART_SERCOM)->USART.DATA.reg = text[i]; - while((BOARD_SERCOM(UART_SERCOM)->USART.INTFLAG.reg & SERCOM_USART_INTFLAG_TXC) == 0); - } -} - -static inline void uart_send_str(const char* text) -{ - while (*text) { - BOARD_SERCOM(UART_SERCOM)->USART.DATA.reg = *text++; - while((BOARD_SERCOM(UART_SERCOM)->USART.INTFLAG.reg & SERCOM_USART_INTFLAG_TXC) == 0); - } -} - -int board_uart_read(uint8_t* buf, int len) -{ - (void) buf; (void) len; - return 0; -} - -int board_uart_write(void const * buf, int len) -{ - if (len < 0) { - uart_send_str(buf); - } else { - uart_send_buffer(buf, len); - } - return len; -} - -#else // ! defined(UART_SERCOM) - -static void uart_init(void) { -} - -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) 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++; -} - -uint32_t board_millis(void) { - return system_ticks; -} - -#endif - -//--------------------------------------------------------------------+ -// -//--------------------------------------------------------------------+ -#if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 - -static void max3421_init(void) { - //------------- SPI Init -------------// - // MAX3421E max SPI clock is 26MHz however SAMD can only work reliably at 12 Mhz - uint32_t const baudrate = 12000000u; - - // Enable the APB clock for SERCOM - PM->APBCMASK.reg |= 1u << (PM_APBCMASK_SERCOM0_Pos + MAX3421_SERCOM_ID); - - // Configure GCLK for SERCOM -// GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID_SERCOM4_CORE | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_CLKEN; - GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(GCLK_CLKCTRL_ID_SERCOM0_CORE_Val + MAX3421_SERCOM_ID) | - GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_CLKEN; - while (GCLK->STATUS.bit.SYNCBUSY); - - Sercom* sercom = MAX3421_SERCOM; - - // Disable the SPI module - sercom->SPI.CTRLA.bit.ENABLE = 0; - - // Reset the SPI module - sercom->SPI.CTRLA.bit.SWRST = 1; - while (sercom->SPI.SYNCBUSY.bit.SWRST); - - // Set up SPI in master mode, MSB first, SPI mode 0 - sercom->SPI.CTRLA.reg = SERCOM_SPI_CTRLA_DOPO(MAX3421_TX_PAD) | SERCOM_SPI_CTRLA_DIPO(MAX3421_RX_PAD) | - SERCOM_SPI_CTRLA_MODE(3); - - sercom->SPI.CTRLB.reg = SERCOM_SPI_CTRLB_CHSIZE(0) | SERCOM_SPI_CTRLB_RXEN; - while (sercom->SPI.SYNCBUSY.bit.CTRLB == 1); - - // Set the baud rate - sercom->SPI.BAUD.reg = (uint8_t) (SystemCoreClock / (2 * baudrate) - 1); - - // Configure PA12 as MOSI (PAD0), PA13 as SCK (PAD1), PA14 as MISO (PAD2), function C (sercom) - gpio_set_pin_direction(MAX3421_SCK_PIN, GPIO_DIRECTION_OUT); - gpio_set_pin_pull_mode(MAX3421_SCK_PIN, GPIO_PULL_OFF); - gpio_set_pin_function(MAX3421_SCK_PIN, MAX3421_SERCOM_FUNCTION); - - gpio_set_pin_direction(MAX3421_MOSI_PIN, GPIO_DIRECTION_OUT); - gpio_set_pin_pull_mode(MAX3421_MOSI_PIN, GPIO_PULL_OFF); - gpio_set_pin_function(MAX3421_MOSI_PIN, MAX3421_SERCOM_FUNCTION); - - gpio_set_pin_direction(MAX3421_MISO_PIN, GPIO_DIRECTION_IN); - gpio_set_pin_pull_mode(MAX3421_MISO_PIN, GPIO_PULL_OFF); - gpio_set_pin_function(MAX3421_MISO_PIN, MAX3421_SERCOM_FUNCTION); - - // CS pin - gpio_set_pin_direction(MAX3421_CS_PIN, GPIO_DIRECTION_OUT); - gpio_set_pin_level(MAX3421_CS_PIN, 1); - - // Enable the SPI module - sercom->SPI.CTRLA.bit.ENABLE = 1; - while (sercom->SPI.SYNCBUSY.bit.ENABLE); - - //------------- External Interrupt -------------// - - // Enable the APB clock for EIC (External Interrupt Controller) - PM->APBAMASK.reg |= PM_APBAMASK_EIC; - - // Configure GCLK for EIC - GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID_EIC | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_CLKEN; - while (GCLK->STATUS.bit.SYNCBUSY); - - // Configure PA20 as an input with function A (external interrupt) - gpio_set_pin_direction(MAX3421_INTR_PIN, GPIO_DIRECTION_IN); - gpio_set_pin_pull_mode(MAX3421_INTR_PIN, GPIO_PULL_UP); - gpio_set_pin_function(MAX3421_INTR_PIN, 0); - - // Disable EIC - EIC->CTRL.bit.ENABLE = 0; - while (EIC->STATUS.bit.SYNCBUSY); - - // Configure EIC to trigger on falling edge - uint8_t const sense_shift = MAX3421_INTR_EIC_ID * 4; - EIC->CONFIG[0].reg &= ~(7 << sense_shift); - EIC->CONFIG[0].reg |= 2 << sense_shift; - -#if CFG_TUSB_OS == OPT_OS_FREERTOS - // If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher ) - NVIC_SetPriority(EIC_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY); -#endif - - // Enable External Interrupt - EIC->INTENSET.reg = EIC_INTENSET_EXTINT(1 << MAX3421_INTR_EIC_ID); - - // Enable EIC - EIC->CTRL.bit.ENABLE = 1; - while (EIC->STATUS.bit.SYNCBUSY); -} - -void EIC_Handler(void) { - // Clear the interrupt flag - EIC->INTFLAG.reg = EIC_INTFLAG_EXTINT(1 << MAX3421_INTR_EIC_ID); - - // Call the TinyUSB interrupt handler - tuh_int_handler(1, true); -} - -// API to enable/disable MAX3421 INTR pin interrupt -void tuh_max3421_int_api(uint8_t rhport, bool enabled) { - (void) rhport; - - if (enabled) { - NVIC_EnableIRQ(EIC_IRQn); - } else { - NVIC_DisableIRQ(EIC_IRQn); - } -} - -// API to control MAX3421 SPI CS -void tuh_max3421_spi_cs_api(uint8_t rhport, bool active) { - (void) rhport; - gpio_set_pin_level(MAX3421_CS_PIN, active ? 0 : 1); -} - -// API to transfer data with MAX3421 SPI -// Either tx_buf or rx_buf can be NULL, which means transfer is write or read only -bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const* tx_buf, uint8_t* rx_buf, size_t xfer_bytes) { - (void) rhport; - - Sercom* sercom = MAX3421_SERCOM; - - for (size_t count = 0; count < xfer_bytes; count++) { - // Wait for the transmit buffer to be empty - while (!sercom->SPI.INTFLAG.bit.DRE); - - // Write data to be transmitted - uint8_t data = 0x00; - if (tx_buf) { - data = tx_buf[count]; - } - - sercom->SPI.DATA.reg = (uint32_t) data; - - // Wait for the receive buffer to be filled - while (!sercom->SPI.INTFLAG.bit.RXC); - - // Read received data - data = (uint8_t) sercom->SPI.DATA.reg; - if (rx_buf) { - rx_buf[count] = data; - } - } - - // wait for bus idle and clear flags - while (!(sercom->SPI.INTFLAG.reg & (SERCOM_SPI_INTFLAG_TXC | SERCOM_SPI_INTFLAG_DRE))); - sercom->SPI.INTFLAG.reg = SERCOM_SPI_INTFLAG_TXC | SERCOM_SPI_INTFLAG_DRE; - - return true; -} - -#endif diff --git a/hw/bsp/samd21/family.cmake b/hw/bsp/samd21/family.cmake deleted file mode 100644 index 3c600318e..000000000 --- a/hw/bsp/samd21/family.cmake +++ /dev/null @@ -1,110 +0,0 @@ -include_guard() - -set(SDK_DIR ${TOP}/hw/mcu/microchip/samd21) - -# include board specific -include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) - -# toolchain set up -set(CMAKE_SYSTEM_CPU cortex-m0plus CACHE INTERNAL "System Processor") -set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake) - -set(FAMILY_MCUS SAMD21 CACHE INTERNAL "") -set(OPENOCD_OPTION "-f interface/cmsis-dap.cfg -c \"transport select swd\" -f target/at91samdXX.cfg") - -#------------------------------------ -# BOARD_TARGET -#------------------------------------ -# only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif () - - set(LD_FILE_Clang ${LD_FILE_GNU}) - if (NOT DEFINED LD_FILE_${CMAKE_C_COMPILER_ID}) - message(FATAL_ERROR "LD_FILE_${CMAKE_C_COMPILER_ID} not defined") - endif () - - set(STARTUP_FILE_GNU ${SDK_DIR}/gcc/gcc/startup_samd21.c) - set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) - - add_library(${BOARD_TARGET} STATIC - ${SDK_DIR}/gcc/system_samd21.c - ${SDK_DIR}/hpl/gclk/hpl_gclk.c - ${SDK_DIR}/hpl/pm/hpl_pm.c - ${SDK_DIR}/hpl/sysctrl/hpl_sysctrl.c - ${SDK_DIR}/hal/src/hal_atomic.c - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} - ) - target_include_directories(${BOARD_TARGET} PUBLIC - ${SDK_DIR} - ${SDK_DIR}/config - ${SDK_DIR}/include - ${SDK_DIR}/hal/include - ${SDK_DIR}/hal/utils/include - ${SDK_DIR}/hpl/pm - ${SDK_DIR}/hpl/port - ${SDK_DIR}/hri - ${SDK_DIR}/CMSIS/Include - ) - target_compile_definitions(${BOARD_TARGET} PUBLIC - CONF_DFLL_OVERWRITE_CALIBRATION=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 - ) - 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_SAMD21) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/microchip/samd/dcd_samd.c - ${TOP}/src/portable/microchip/samd/hcd_samd.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) - - # Flashing - family_add_bin_hex(${TARGET}) - family_flash_jlink(${TARGET}) - #family_flash_openocd(${TARGET}) -endfunction() diff --git a/hw/bsp/samd21/family.mk b/hw/bsp/samd21/family.mk deleted file mode 100644 index a2c37b2b6..000000000 --- a/hw/bsp/samd21/family.mk +++ /dev/null @@ -1,53 +0,0 @@ -UF2_FAMILY_ID = 0x68ed2b88 -SDK_DIR = hw/mcu/microchip/samd21 - -include $(TOP)/$(BOARD_PATH)/board.mk -CPU_CORE ?= cortex-m0plus - -CFLAGS += \ - -flto \ - -DCONF_DFLL_OVERWRITE_CALIBRATION=0 \ - -DCFG_TUSB_MCU=OPT_MCU_SAMD21 - -# suppress warning caused by vendor mcu driver -CFLAGS += -Wno-error=redundant-decls - -# SAM driver is flooded with -Wcast-qual which slow down complication significantly -CFLAGS_SKIP += -Wcast-qual - -LDFLAGS_GCC += \ - -nostdlib -nostartfiles \ - --specs=nosys.specs --specs=nano.specs \ - -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 \ - ${SDK_DIR}/hpl/gclk/hpl_gclk.c \ - ${SDK_DIR}/hpl/pm/hpl_pm.c \ - ${SDK_DIR}/hpl/sysctrl/hpl_sysctrl.c \ - -INC += \ - $(TOP)/$(BOARD_PATH) \ - $(TOP)/${SDK_DIR} \ - $(TOP)/${SDK_DIR}/config \ - $(TOP)/${SDK_DIR}/include \ - $(TOP)/${SDK_DIR}/hal/include \ - $(TOP)/${SDK_DIR}/hal/utils/include \ - $(TOP)/${SDK_DIR}/hpl/pm/ \ - $(TOP)/${SDK_DIR}/hpl/port \ - $(TOP)/${SDK_DIR}/hri \ - $(TOP)/lib/CMSIS_5/CMSIS/Core/Include \ - -# flash using bossac at least version 1.8 -# can be found in arduino15/packages/arduino/tools/bossac/ -# Add it to your PATH or change BOSSAC variable to match your installation -BOSSAC = bossac - -flash-bossac: $(BUILD)/$(PROJECT).bin - @:$(call check_defined, SERIAL, example: SERIAL=/dev/ttyACM0) - $(BOSSAC) --port=$(SERIAL) -U -i --offset=0x2000 -e -w $^ -R diff --git a/hw/bsp/samd2x_l2x/FreeRTOSConfig/FreeRTOSConfig.h b/hw/bsp/samd2x_l2x/FreeRTOSConfig/FreeRTOSConfig.h new file mode 100644 index 000000000..6c9ecae2d --- /dev/null +++ b/hw/bsp/samd2x_l2x/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 "sam.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 2 + +/* The lowest interrupt priority that can be used in a call to a "set priority" function. */ +#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1< rom + + /* .ARM.exidx is sorted, so has to go in its own output section. */ + PROVIDE_HIDDEN (__exidx_start = .); + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > rom + PROVIDE_HIDDEN (__exidx_end = .); + + . = ALIGN(4); + _etext = .; + + .relocate : AT (_etext) + { + . = ALIGN(4); + _srelocate = .; + *(.ramfunc .ramfunc.*); + *(.data .data.*); + . = ALIGN(4); + _erelocate = .; + } > ram + + /* .bss section which is used for uninitialized data */ + .bss (NOLOAD) : + { + . = ALIGN(4); + _sbss = . ; + _szero = .; + *(.bss .bss.*) + *(COMMON) + . = ALIGN(4); + _ebss = . ; + _ezero = .; + end = .; + } > ram + + /* stack section */ + .stack (NOLOAD): + { + . = ALIGN(8); + _sstack = .; + . = . + STACK_SIZE; + . = ALIGN(8); + _estack = .; + } > ram + + . = ALIGN(4); + _end = . ; +} diff --git a/hw/bsp/samd2x_l2x/boards/atsaml21_xpro/board.cmake b/hw/bsp/samd2x_l2x/boards/atsaml21_xpro/board.cmake new file mode 100644 index 000000000..874b741cc --- /dev/null +++ b/hw/bsp/samd2x_l2x/boards/atsaml21_xpro/board.cmake @@ -0,0 +1,9 @@ +set(SAM_FAMILY saml21) +set(JLINK_DEVICE ATSAML21J18) +set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/saml21j18b_flash.ld) + +function(update_board TARGET) + target_compile_definitions(${TARGET} PUBLIC + __SAML21J18B__ + ) +endfunction() diff --git a/hw/bsp/samd2x_l2x/boards/atsaml21_xpro/board.h b/hw/bsp/samd2x_l2x/boards/atsaml21_xpro/board.h new file mode 100644 index 000000000..b93b4e591 --- /dev/null +++ b/hw/bsp/samd2x_l2x/boards/atsaml21_xpro/board.h @@ -0,0 +1,55 @@ +/* + * 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: SAML21 Xplained Pro + url: https://www.microchip.com/en-us/development-tool/atsaml21-xpro-b +*/ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +// LED +#define LED_PIN (32 + 30) // PB30 +#define LED_STATE_ON 0 + +// Button +#define BUTTON_PIN (0 + 15) // PA15 +#define BUTTON_STATE_ACTIVE 0 + +// UART +#define UART_RX_PIN 4 +#define UART_TX_PIN 5 + +#ifdef __cplusplus + } +#endif + +#endif /* BOARD_H_ */ diff --git a/hw/bsp/samd2x_l2x/boards/atsaml21_xpro/board.mk b/hw/bsp/samd2x_l2x/boards/atsaml21_xpro/board.mk new file mode 100644 index 000000000..4ebfa7e71 --- /dev/null +++ b/hw/bsp/samd2x_l2x/boards/atsaml21_xpro/board.mk @@ -0,0 +1,12 @@ +SAM_FAMILY = saml21 + +CFLAGS += -D__SAML21J18B__ + +# All source paths should be relative to the top level. +LD_FILE = $(BOARD_PATH)/saml21j18b_flash.ld + +# For flash-jlink target +JLINK_DEVICE = ATSAML21J18 + +# flash using jlink +flash: flash-jlink diff --git a/hw/bsp/samd2x_l2x/boards/atsaml21_xpro/saml21j18b_flash.ld b/hw/bsp/samd2x_l2x/boards/atsaml21_xpro/saml21j18b_flash.ld new file mode 100644 index 000000000..f9523451b --- /dev/null +++ b/hw/bsp/samd2x_l2x/boards/atsaml21_xpro/saml21j18b_flash.ld @@ -0,0 +1,155 @@ +/** + * \file + * + * \brief Linker script for running in internal FLASH on the SAML21J18B + * + * Copyright (c) 2016 Atmel Corporation, + * a wholly owned subsidiary of Microchip Technology Inc. + * + * \asf_license_start + * + * \page License + * + * 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 Licence 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. + * + * \asf_license_stop + * + */ + + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +SEARCH_DIR(.) + +ENTRY(Reset_Handler) + +/* Memory Spaces Definitions */ +MEMORY +{ + rom (rx) : ORIGIN = 0x00000000, LENGTH = 0x00040000 + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000 + lpram (rwx) : ORIGIN = 0x30000000, LENGTH = 0x00002000 +} + +/* The stack size used by the application. NOTE: you need to adjust according to your application. */ +STACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x2000; + +/* Section Definitions */ +SECTIONS +{ + .text : + { + . = ALIGN(4); + _sfixed = .; + KEEP(*(.vectors .vectors.*)) + *(.text .text.* .gnu.linkonce.t.*) + *(.glue_7t) *(.glue_7) + *(.rodata .rodata* .gnu.linkonce.r.*) + *(.ARM.extab* .gnu.linkonce.armextab.*) + + /* Support C constructors, and C destructors in both user code + and the C library. This also provides support for C++ code. */ + . = ALIGN(4); + KEEP(*(.init)) + . = ALIGN(4); + __preinit_array_start = .; + KEEP (*(.preinit_array)) + __preinit_array_end = .; + + . = ALIGN(4); + __init_array_start = .; + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + __init_array_end = .; + + . = ALIGN(4); + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*crtend.o(.ctors)) + + . = ALIGN(4); + KEEP(*(.fini)) + + . = ALIGN(4); + __fini_array_start = .; + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + __fini_array_end = .; + + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*crtend.o(.dtors)) + + . = ALIGN(4); + _efixed = .; /* End of text section */ + } > rom + + /* .ARM.exidx is sorted, so has to go in its own output section. */ + PROVIDE_HIDDEN (__exidx_start = .); + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > rom + PROVIDE_HIDDEN (__exidx_end = .); + + . = ALIGN(4); + _etext = .; + + .relocate : AT (_etext) + { + . = ALIGN(4); + _srelocate = .; + *(.ramfunc .ramfunc.*); + *(.data .data.*); + . = ALIGN(4); + _erelocate = .; + } > ram + + .lpram (NOLOAD): + { + . = ALIGN(8); + _slpram = .; + *(.lpram .lpram.*); + . = ALIGN(8); + _elpram = .; + } > lpram + + /* .bss section which is used for uninitialized data */ + .bss (NOLOAD) : + { + . = ALIGN(4); + _sbss = . ; + _szero = .; + *(.bss .bss.*) + *(COMMON) + . = ALIGN(4); + _ebss = . ; + _ezero = .; + end = .; + } > ram + + /* stack section */ + .stack (NOLOAD): + { + . = ALIGN(8); + _sstack = .; + . = . + STACK_SIZE; + . = ALIGN(8); + _estack = .; + } > ram + + . = ALIGN(4); + _end = . ; +} diff --git a/hw/bsp/samd2x_l2x/boards/circuitplayground_express/board.cmake b/hw/bsp/samd2x_l2x/boards/circuitplayground_express/board.cmake new file mode 100644 index 000000000..dedc07594 --- /dev/null +++ b/hw/bsp/samd2x_l2x/boards/circuitplayground_express/board.cmake @@ -0,0 +1,10 @@ +set(SAM_FAMILY samd21) +set(JLINK_DEVICE ATSAMD21G18) +set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/${BOARD}.ld) + +function(update_board TARGET) + target_compile_definitions(${TARGET} PUBLIC + __SAMD21G18A__ + CFG_EXAMPLE_VIDEO_READONLY + ) +endfunction() diff --git a/hw/bsp/samd2x_l2x/boards/circuitplayground_express/board.h b/hw/bsp/samd2x_l2x/boards/circuitplayground_express/board.h new file mode 100644 index 000000000..bfe2d9951 --- /dev/null +++ b/hw/bsp/samd2x_l2x/boards/circuitplayground_express/board.h @@ -0,0 +1,59 @@ +/* + * 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 Circuit Playground Express + url: https://www.adafruit.com/product/3333 +*/ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +// LED +#define LED_PIN 17 +#define LED_STATE_ON 1 + +// Button +#define BUTTON_PIN 28 +#define BUTTON_STATE_ACTIVE 1 + +// UART +#define UART_RX_PIN 4 +#define UART_TX_PIN 5 + +static inline void board_vbus_set(uint8_t rhport, bool state) { + (void) rhport; (void) state; +} + +#ifdef __cplusplus + } +#endif + +#endif /* BOARD_H_ */ diff --git a/hw/bsp/samd2x_l2x/boards/circuitplayground_express/board.mk b/hw/bsp/samd2x_l2x/boards/circuitplayground_express/board.mk new file mode 100644 index 000000000..f4211e6c8 --- /dev/null +++ b/hw/bsp/samd2x_l2x/boards/circuitplayground_express/board.mk @@ -0,0 +1,11 @@ +SAM_FAMILY = samd21 + +CFLAGS += -D__SAMD21G18A__ -DCFG_EXAMPLE_VIDEO_READONLY + +# All source paths should be relative to the top level. +LD_FILE = $(BOARD_PATH)/$(BOARD).ld + +# For flash-jlink target +JLINK_DEVICE = ATSAMD21G18 + +flash: flash-bossac diff --git a/hw/bsp/samd2x_l2x/boards/circuitplayground_express/circuitplayground_express.ld b/hw/bsp/samd2x_l2x/boards/circuitplayground_express/circuitplayground_express.ld new file mode 100644 index 000000000..ce7aff80b --- /dev/null +++ b/hw/bsp/samd2x_l2x/boards/circuitplayground_express/circuitplayground_express.ld @@ -0,0 +1,146 @@ +/** + * \file + * + * \brief Linker script for running in internal FLASH on the SAMD21G18A + * + * Copyright (c) 2017 Microchip Technology Inc. + * + * \asf_license_start + * + * \page License + * + * 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 Licence 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. + * + * \asf_license_stop + * + */ + + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +SEARCH_DIR(.) + +/* Memory Spaces Definitions */ +MEMORY +{ + rom (rx) : ORIGIN = 0x00000000 + 8K, LENGTH = 0x00040000 - 8K + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000 +} + +/* The stack size used by the application. NOTE: you need to adjust according to your application. */ +STACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x2000; + +ENTRY(Reset_Handler) + +/* Section Definitions */ +SECTIONS +{ + .text : + { + . = ALIGN(4); + _sfixed = .; + KEEP(*(.vectors .vectors.*)) + *(.text .text.* .gnu.linkonce.t.*) + *(.glue_7t) *(.glue_7) + *(.rodata .rodata* .gnu.linkonce.r.*) + *(.ARM.extab* .gnu.linkonce.armextab.*) + + /* Support C constructors, and C destructors in both user code + and the C library. This also provides support for C++ code. */ + . = ALIGN(4); + KEEP(*(.init)) + . = ALIGN(4); + __preinit_array_start = .; + KEEP (*(.preinit_array)) + __preinit_array_end = .; + + . = ALIGN(4); + __init_array_start = .; + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + __init_array_end = .; + + . = ALIGN(4); + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*crtend.o(.ctors)) + + . = ALIGN(4); + KEEP(*(.fini)) + + . = ALIGN(4); + __fini_array_start = .; + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + __fini_array_end = .; + + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*crtend.o(.dtors)) + + . = ALIGN(4); + _efixed = .; /* End of text section */ + } > rom + + /* .ARM.exidx is sorted, so has to go in its own output section. */ + PROVIDE_HIDDEN (__exidx_start = .); + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > rom + PROVIDE_HIDDEN (__exidx_end = .); + + . = ALIGN(4); + _etext = .; + + .relocate : AT (_etext) + { + . = ALIGN(4); + _srelocate = .; + *(.ramfunc .ramfunc.*); + *(.data .data.*); + . = ALIGN(4); + _erelocate = .; + } > ram + + /* .bss section which is used for uninitialized data */ + .bss (NOLOAD) : + { + . = ALIGN(4); + _sbss = . ; + _szero = .; + *(.bss .bss.*) + *(COMMON) + . = ALIGN(4); + _ebss = . ; + _ezero = .; + end = .; + } > ram + + /* stack section */ + .stack (NOLOAD): + { + . = ALIGN(8); + _sstack = .; + . = . + STACK_SIZE; + . = ALIGN(8); + _estack = .; + } > ram + + . = ALIGN(4); + _end = . ; +} diff --git a/hw/bsp/samd2x_l2x/boards/curiosity_nano/board.cmake b/hw/bsp/samd2x_l2x/boards/curiosity_nano/board.cmake new file mode 100644 index 000000000..be744a130 --- /dev/null +++ b/hw/bsp/samd2x_l2x/boards/curiosity_nano/board.cmake @@ -0,0 +1,11 @@ +set(SAM_FAMILY samd21) +set(JLINK_DEVICE atsamd21g17a) +set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/samd21g17a_flash.ld) + +function(update_board TARGET) + target_compile_definitions(${TARGET} PUBLIC + __SAMD21G17A__ + CFG_EXAMPLE_MSC_READONLY + CFG_EXAMPLE_VIDEO_READONLY + ) +endfunction() diff --git a/hw/bsp/samd2x_l2x/boards/curiosity_nano/board.h b/hw/bsp/samd2x_l2x/boards/curiosity_nano/board.h new file mode 100644 index 000000000..a2a7385a4 --- /dev/null +++ b/hw/bsp/samd2x_l2x/boards/curiosity_nano/board.h @@ -0,0 +1,59 @@ +/* + * 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: SAMD21 Curiosty Nano + url: https://www.microchip.com/en-us/development-tool/dm320119 +*/ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +// LED +#define LED_PIN (32 + 10) // PB10 +#define LED_STATE_ON 0 + +// Button +#define BUTTON_PIN (0 + 11) // PB11 +#define BUTTON_STATE_ACTIVE 0 + +// UART +#define UART_RX_PIN 31 // CDC5_RX +#define UART_TX_PIN 37 // CDC5_TX + +static inline void board_vbus_set(uint8_t rhport, bool state) { + (void) rhport; (void) state; +} + +#ifdef __cplusplus + } +#endif + +#endif /* BOARD_H_ */ diff --git a/hw/bsp/samd2x_l2x/boards/curiosity_nano/board.mk b/hw/bsp/samd2x_l2x/boards/curiosity_nano/board.mk new file mode 100644 index 000000000..b7ebc867e --- /dev/null +++ b/hw/bsp/samd2x_l2x/boards/curiosity_nano/board.mk @@ -0,0 +1,16 @@ +SAM_FAMILY = samd21 + +CFLAGS += -D__SAMD21G17A__ -DCFG_EXAMPLE_MSC_READONLY -DCFG_EXAMPLE_VIDEO_READONLY + +# All source paths should be relative to the top level. +LD_FILE = $(BOARD_PATH)/samd21g17a_flash.ld + +# For flash-jlink target +JLINK_DEVICE = atsamd21g17a + +# flash using jlink (options are: jlink/cmsisdap/stlink/dfu) +#flash: flash-jlink + +PYOCD_TARGET = atsamd21g17a +PYOCD_OPTION = -O dap_protocol=swd +flash: flash-pyocd diff --git a/hw/bsp/samd2x_l2x/boards/curiosity_nano/samd21g17a_flash.ld b/hw/bsp/samd2x_l2x/boards/curiosity_nano/samd21g17a_flash.ld new file mode 100644 index 000000000..e03a4ce60 --- /dev/null +++ b/hw/bsp/samd2x_l2x/boards/curiosity_nano/samd21g17a_flash.ld @@ -0,0 +1,144 @@ +/** + * \file + * + * \brief Linker script for running in internal FLASH on the SAMD21G17A/D + * + * Copyright (c) 2017 Microchip Technology Inc. + * + * \asf_license_start + * + * \page License + * + * 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 Licence 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. + * + * \asf_license_stop + * + */ + + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +SEARCH_DIR(.) + +/* Memory Spaces Definitions */ +MEMORY +{ + rom (rx) : ORIGIN = 0x00000000, LENGTH = 0x00020000 + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00004000 +} + +/* The stack size used by the application. NOTE: you need to adjust according to your application. */ +STACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x1000; + +/* Section Definitions */ +SECTIONS +{ + .text : + { + . = ALIGN(4); + _sfixed = .; + KEEP(*(.vectors .vectors.*)) + *(.text .text.* .gnu.linkonce.t.*) + *(.glue_7t) *(.glue_7) + *(.rodata .rodata* .gnu.linkonce.r.*) + *(.ARM.extab* .gnu.linkonce.armextab.*) + + /* Support C constructors, and C destructors in both user code + and the C library. This also provides support for C++ code. */ + . = ALIGN(4); + KEEP(*(.init)) + . = ALIGN(4); + __preinit_array_start = .; + KEEP (*(.preinit_array)) + __preinit_array_end = .; + + . = ALIGN(4); + __init_array_start = .; + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + __init_array_end = .; + + . = ALIGN(4); + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*crtend.o(.ctors)) + + . = ALIGN(4); + KEEP(*(.fini)) + + . = ALIGN(4); + __fini_array_start = .; + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + __fini_array_end = .; + + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*crtend.o(.dtors)) + + . = ALIGN(4); + _efixed = .; /* End of text section */ + } > rom + + /* .ARM.exidx is sorted, so has to go in its own output section. */ + PROVIDE_HIDDEN (__exidx_start = .); + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > rom + PROVIDE_HIDDEN (__exidx_end = .); + + . = ALIGN(4); + _etext = .; + + .relocate : AT (_etext) + { + . = ALIGN(4); + _srelocate = .; + *(.ramfunc .ramfunc.*); + *(.data .data.*); + . = ALIGN(4); + _erelocate = .; + } > ram + + /* .bss section which is used for uninitialized data */ + .bss (NOLOAD) : + { + . = ALIGN(4); + _sbss = . ; + _szero = .; + *(.bss .bss.*) + *(COMMON) + . = ALIGN(4); + _ebss = . ; + _ezero = .; + end = .; + } > ram + + /* stack section */ + .stack (NOLOAD): + { + . = ALIGN(8); + _sstack = .; + . = . + STACK_SIZE; + . = ALIGN(8); + _estack = .; + } > ram + + . = ALIGN(4); + _end = . ; +} diff --git a/hw/bsp/samd2x_l2x/boards/cynthion_d21/board.cmake b/hw/bsp/samd2x_l2x/boards/cynthion_d21/board.cmake new file mode 100644 index 000000000..ae739b215 --- /dev/null +++ b/hw/bsp/samd2x_l2x/boards/cynthion_d21/board.cmake @@ -0,0 +1,13 @@ +set(SAM_FAMILY samd21) +set(JLINK_DEVICE ATSAMD21G18) +set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/samd21g18a_flash.ld) + +function(update_board TARGET) + target_compile_definitions(${TARGET} PUBLIC + __SAMD21G18A__ + CFG_EXAMPLE_VIDEO_READONLY + ) + target_link_options(${TARGET} PUBLIC + "LINKER:--defsym=BOOTLOADER_SIZE=0x800" + ) +endfunction() diff --git a/hw/bsp/samd2x_l2x/boards/cynthion_d21/board.h b/hw/bsp/samd2x_l2x/boards/cynthion_d21/board.h new file mode 100644 index 000000000..83782bc65 --- /dev/null +++ b/hw/bsp/samd2x_l2x/boards/cynthion_d21/board.h @@ -0,0 +1,55 @@ +/* + * 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: Great Scott Gadgets Cynthion + url: https://greatscottgadgets.com/cynthion/ +*/ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +// LED +#define LED_PIN PIN_PA22 +#define LED_STATE_ON 1 + +// Button +#define BUTTON_PIN PIN_PB22 +#define BUTTON_STATE_ACTIVE 0 + +static inline void board_vbus_set(uint8_t rhport, bool state) { + (void) rhport; (void) state; +} + +#ifdef __cplusplus + } +#endif + +#endif /* BOARD_H_ */ diff --git a/hw/bsp/samd2x_l2x/boards/cynthion_d21/board.mk b/hw/bsp/samd2x_l2x/boards/cynthion_d21/board.mk new file mode 100644 index 000000000..05ca9cb5d --- /dev/null +++ b/hw/bsp/samd2x_l2x/boards/cynthion_d21/board.mk @@ -0,0 +1,18 @@ +SAM_FAMILY = samd21 + +CFLAGS += -D__SAMD21G18A__ -DCFG_EXAMPLE_VIDEO_READONLY + +LD_FILE = $(BOARD_PATH)/samd21g18a_flash.ld + +# Default bootloader size is now 2K, allow to specify other +ifeq ($(BOOTLOADER_SIZE), ) + BOOTLOADER_SIZE := 0x800 +endif +LDFLAGS += -Wl,--defsym=BOOTLOADER_SIZE=$(BOOTLOADER_SIZE) + +# For flash-jlink target +JLINK_DEVICE = ATSAMD21G18 + +# flash using dfu-util +flash: $(BUILD)/$(PROJECT).bin + dfu-util -a 0 -d 1d50:615c -D $< || dfu-util -a 0 -d 16d0:05a5 -D $< diff --git a/hw/bsp/samd2x_l2x/boards/cynthion_d21/samd21g18a_flash.ld b/hw/bsp/samd2x_l2x/boards/cynthion_d21/samd21g18a_flash.ld new file mode 100644 index 000000000..95d71b9e3 --- /dev/null +++ b/hw/bsp/samd2x_l2x/boards/cynthion_d21/samd21g18a_flash.ld @@ -0,0 +1,144 @@ +/** + * \file + * + * \brief Linker script for running in internal FLASH on the SAMD21G18A + * + * Copyright (c) 2017 Microchip Technology Inc. + * + * \asf_license_start + * + * \page License + * + * 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 Licence 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. + * + * \asf_license_stop + * + */ + + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +SEARCH_DIR(.) + +/* Memory Spaces Definitions */ +MEMORY +{ + rom (rx) : ORIGIN = 0x00000000 + BOOTLOADER_SIZE, LENGTH = 0x00040000 - BOOTLOADER_SIZE + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000 +} + +/* The stack size used by the application. NOTE: you need to adjust according to your application. */ +STACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x2000; + +/* Section Definitions */ +SECTIONS +{ + .text : + { + . = ALIGN(4); + _sfixed = .; + KEEP(*(.vectors .vectors.*)) + *(.text .text.* .gnu.linkonce.t.*) + *(.glue_7t) *(.glue_7) + *(.rodata .rodata* .gnu.linkonce.r.*) + *(.ARM.extab* .gnu.linkonce.armextab.*) + + /* Support C constructors, and C destructors in both user code + and the C library. This also provides support for C++ code. */ + . = ALIGN(4); + KEEP(*(.init)) + . = ALIGN(4); + __preinit_array_start = .; + KEEP (*(.preinit_array)) + __preinit_array_end = .; + + . = ALIGN(4); + __init_array_start = .; + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + __init_array_end = .; + + . = ALIGN(4); + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*crtend.o(.ctors)) + + . = ALIGN(4); + KEEP(*(.fini)) + + . = ALIGN(4); + __fini_array_start = .; + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + __fini_array_end = .; + + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*crtend.o(.dtors)) + + . = ALIGN(4); + _efixed = .; /* End of text section */ + } > rom + + /* .ARM.exidx is sorted, so has to go in its own output section. */ + PROVIDE_HIDDEN (__exidx_start = .); + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > rom + PROVIDE_HIDDEN (__exidx_end = .); + + . = ALIGN(4); + _etext = .; + + .relocate : AT (_etext) + { + . = ALIGN(4); + _srelocate = .; + *(.ramfunc .ramfunc.*); + *(.data .data.*); + . = ALIGN(4); + _erelocate = .; + } > ram + + /* .bss section which is used for uninitialized data */ + .bss (NOLOAD) : + { + . = ALIGN(4); + _sbss = . ; + _szero = .; + *(.bss .bss.*) + *(COMMON) + . = ALIGN(4); + _ebss = . ; + _ezero = .; + end = .; + } > ram + + /* stack section */ + .stack (NOLOAD): + { + . = ALIGN(8); + _sstack = .; + . = . + STACK_SIZE; + . = ALIGN(8); + _estack = .; + } > ram + + . = ALIGN(4); + _end = . ; +} diff --git a/hw/bsp/samd2x_l2x/boards/feather_m0_express/board.cmake b/hw/bsp/samd2x_l2x/boards/feather_m0_express/board.cmake new file mode 100644 index 000000000..dedc07594 --- /dev/null +++ b/hw/bsp/samd2x_l2x/boards/feather_m0_express/board.cmake @@ -0,0 +1,10 @@ +set(SAM_FAMILY samd21) +set(JLINK_DEVICE ATSAMD21G18) +set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/${BOARD}.ld) + +function(update_board TARGET) + target_compile_definitions(${TARGET} PUBLIC + __SAMD21G18A__ + CFG_EXAMPLE_VIDEO_READONLY + ) +endfunction() diff --git a/hw/bsp/samd2x_l2x/boards/feather_m0_express/board.h b/hw/bsp/samd2x_l2x/boards/feather_m0_express/board.h new file mode 100644 index 000000000..6fe13eb30 --- /dev/null +++ b/hw/bsp/samd2x_l2x/boards/feather_m0_express/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: Adafruit Feather M0 Express + url: https://www.adafruit.com/product/3403 +*/ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +// LED +#define LED_PIN 17 +#define LED_STATE_ON 1 + +// Button +#define BUTTON_PIN 15 +#define BUTTON_STATE_ACTIVE 0 + +// UART +#define UART_RX_PIN 4 +#define UART_TX_PIN 5 + +// SPI for USB host shield +#define MAX3421_SERCOM_ID 4 // SERCOM4 +#define MAX3421_SERCOM_FUNCTION 3 // function D (Sercom Alt) + +#define MAX3421_SCK_PIN (32+11) +#define MAX3421_MOSI_PIN (32+10) +#define MAX3421_MISO_PIN 12 +#define MAX3421_TX_PAD 1 // MOSI = PAD_2, SCK = PAD_3 +#define MAX3421_RX_PAD 0 // MISO = PAD_2 + +#define MAX3421_CS_PIN 18 // D10 + +#define MAX3421_INTR_PIN 7 // D10 +#define MAX3421_INTR_EIC_ID 7 // EIC7 + +static inline void board_vbus_set(uint8_t rhport, bool state) { + (void) rhport; (void) state; +} + +#ifdef __cplusplus + } +#endif + +#endif /* BOARD_H_ */ diff --git a/hw/bsp/samd2x_l2x/boards/feather_m0_express/board.mk b/hw/bsp/samd2x_l2x/boards/feather_m0_express/board.mk new file mode 100644 index 000000000..f4211e6c8 --- /dev/null +++ b/hw/bsp/samd2x_l2x/boards/feather_m0_express/board.mk @@ -0,0 +1,11 @@ +SAM_FAMILY = samd21 + +CFLAGS += -D__SAMD21G18A__ -DCFG_EXAMPLE_VIDEO_READONLY + +# All source paths should be relative to the top level. +LD_FILE = $(BOARD_PATH)/$(BOARD).ld + +# For flash-jlink target +JLINK_DEVICE = ATSAMD21G18 + +flash: flash-bossac diff --git a/hw/bsp/samd2x_l2x/boards/feather_m0_express/feather_m0_express.ld b/hw/bsp/samd2x_l2x/boards/feather_m0_express/feather_m0_express.ld new file mode 100644 index 000000000..ce7aff80b --- /dev/null +++ b/hw/bsp/samd2x_l2x/boards/feather_m0_express/feather_m0_express.ld @@ -0,0 +1,146 @@ +/** + * \file + * + * \brief Linker script for running in internal FLASH on the SAMD21G18A + * + * Copyright (c) 2017 Microchip Technology Inc. + * + * \asf_license_start + * + * \page License + * + * 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 Licence 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. + * + * \asf_license_stop + * + */ + + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +SEARCH_DIR(.) + +/* Memory Spaces Definitions */ +MEMORY +{ + rom (rx) : ORIGIN = 0x00000000 + 8K, LENGTH = 0x00040000 - 8K + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000 +} + +/* The stack size used by the application. NOTE: you need to adjust according to your application. */ +STACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x2000; + +ENTRY(Reset_Handler) + +/* Section Definitions */ +SECTIONS +{ + .text : + { + . = ALIGN(4); + _sfixed = .; + KEEP(*(.vectors .vectors.*)) + *(.text .text.* .gnu.linkonce.t.*) + *(.glue_7t) *(.glue_7) + *(.rodata .rodata* .gnu.linkonce.r.*) + *(.ARM.extab* .gnu.linkonce.armextab.*) + + /* Support C constructors, and C destructors in both user code + and the C library. This also provides support for C++ code. */ + . = ALIGN(4); + KEEP(*(.init)) + . = ALIGN(4); + __preinit_array_start = .; + KEEP (*(.preinit_array)) + __preinit_array_end = .; + + . = ALIGN(4); + __init_array_start = .; + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + __init_array_end = .; + + . = ALIGN(4); + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*crtend.o(.ctors)) + + . = ALIGN(4); + KEEP(*(.fini)) + + . = ALIGN(4); + __fini_array_start = .; + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + __fini_array_end = .; + + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*crtend.o(.dtors)) + + . = ALIGN(4); + _efixed = .; /* End of text section */ + } > rom + + /* .ARM.exidx is sorted, so has to go in its own output section. */ + PROVIDE_HIDDEN (__exidx_start = .); + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > rom + PROVIDE_HIDDEN (__exidx_end = .); + + . = ALIGN(4); + _etext = .; + + .relocate : AT (_etext) + { + . = ALIGN(4); + _srelocate = .; + *(.ramfunc .ramfunc.*); + *(.data .data.*); + . = ALIGN(4); + _erelocate = .; + } > ram + + /* .bss section which is used for uninitialized data */ + .bss (NOLOAD) : + { + . = ALIGN(4); + _sbss = . ; + _szero = .; + *(.bss .bss.*) + *(COMMON) + . = ALIGN(4); + _ebss = . ; + _ezero = .; + end = .; + } > ram + + /* stack section */ + .stack (NOLOAD): + { + . = ALIGN(8); + _sstack = .; + . = . + STACK_SIZE; + . = ALIGN(8); + _estack = .; + } > ram + + . = ALIGN(4); + _end = . ; +} diff --git a/hw/bsp/samd2x_l2x/boards/itsybitsy_m0/board.cmake b/hw/bsp/samd2x_l2x/boards/itsybitsy_m0/board.cmake new file mode 100644 index 000000000..dedc07594 --- /dev/null +++ b/hw/bsp/samd2x_l2x/boards/itsybitsy_m0/board.cmake @@ -0,0 +1,10 @@ +set(SAM_FAMILY samd21) +set(JLINK_DEVICE ATSAMD21G18) +set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/${BOARD}.ld) + +function(update_board TARGET) + target_compile_definitions(${TARGET} PUBLIC + __SAMD21G18A__ + CFG_EXAMPLE_VIDEO_READONLY + ) +endfunction() diff --git a/hw/bsp/samd2x_l2x/boards/itsybitsy_m0/board.h b/hw/bsp/samd2x_l2x/boards/itsybitsy_m0/board.h new file mode 100644 index 000000000..d901b2ea4 --- /dev/null +++ b/hw/bsp/samd2x_l2x/boards/itsybitsy_m0/board.h @@ -0,0 +1,59 @@ +/* + * 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 ItsyBitsy M0 + url: https://www.adafruit.com/product/3727 +*/ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +// LED +#define LED_PIN 17 +#define LED_STATE_ON 1 + +// Button +#define BUTTON_PIN 21 +#define BUTTON_STATE_ACTIVE 0 + +// UART +#define UART_RX_PIN 4 +#define UART_TX_PIN 5 + +static inline void board_vbus_set(uint8_t rhport, bool state) { + (void) rhport; (void) state; +} + +#ifdef __cplusplus + } +#endif + +#endif /* BOARD_H_ */ diff --git a/hw/bsp/samd2x_l2x/boards/itsybitsy_m0/board.mk b/hw/bsp/samd2x_l2x/boards/itsybitsy_m0/board.mk new file mode 100644 index 000000000..f4211e6c8 --- /dev/null +++ b/hw/bsp/samd2x_l2x/boards/itsybitsy_m0/board.mk @@ -0,0 +1,11 @@ +SAM_FAMILY = samd21 + +CFLAGS += -D__SAMD21G18A__ -DCFG_EXAMPLE_VIDEO_READONLY + +# All source paths should be relative to the top level. +LD_FILE = $(BOARD_PATH)/$(BOARD).ld + +# For flash-jlink target +JLINK_DEVICE = ATSAMD21G18 + +flash: flash-bossac diff --git a/hw/bsp/samd2x_l2x/boards/itsybitsy_m0/itsybitsy_m0.ld b/hw/bsp/samd2x_l2x/boards/itsybitsy_m0/itsybitsy_m0.ld new file mode 100644 index 000000000..ce7aff80b --- /dev/null +++ b/hw/bsp/samd2x_l2x/boards/itsybitsy_m0/itsybitsy_m0.ld @@ -0,0 +1,146 @@ +/** + * \file + * + * \brief Linker script for running in internal FLASH on the SAMD21G18A + * + * Copyright (c) 2017 Microchip Technology Inc. + * + * \asf_license_start + * + * \page License + * + * 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 Licence 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. + * + * \asf_license_stop + * + */ + + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +SEARCH_DIR(.) + +/* Memory Spaces Definitions */ +MEMORY +{ + rom (rx) : ORIGIN = 0x00000000 + 8K, LENGTH = 0x00040000 - 8K + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000 +} + +/* The stack size used by the application. NOTE: you need to adjust according to your application. */ +STACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x2000; + +ENTRY(Reset_Handler) + +/* Section Definitions */ +SECTIONS +{ + .text : + { + . = ALIGN(4); + _sfixed = .; + KEEP(*(.vectors .vectors.*)) + *(.text .text.* .gnu.linkonce.t.*) + *(.glue_7t) *(.glue_7) + *(.rodata .rodata* .gnu.linkonce.r.*) + *(.ARM.extab* .gnu.linkonce.armextab.*) + + /* Support C constructors, and C destructors in both user code + and the C library. This also provides support for C++ code. */ + . = ALIGN(4); + KEEP(*(.init)) + . = ALIGN(4); + __preinit_array_start = .; + KEEP (*(.preinit_array)) + __preinit_array_end = .; + + . = ALIGN(4); + __init_array_start = .; + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + __init_array_end = .; + + . = ALIGN(4); + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*crtend.o(.ctors)) + + . = ALIGN(4); + KEEP(*(.fini)) + + . = ALIGN(4); + __fini_array_start = .; + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + __fini_array_end = .; + + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*crtend.o(.dtors)) + + . = ALIGN(4); + _efixed = .; /* End of text section */ + } > rom + + /* .ARM.exidx is sorted, so has to go in its own output section. */ + PROVIDE_HIDDEN (__exidx_start = .); + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > rom + PROVIDE_HIDDEN (__exidx_end = .); + + . = ALIGN(4); + _etext = .; + + .relocate : AT (_etext) + { + . = ALIGN(4); + _srelocate = .; + *(.ramfunc .ramfunc.*); + *(.data .data.*); + . = ALIGN(4); + _erelocate = .; + } > ram + + /* .bss section which is used for uninitialized data */ + .bss (NOLOAD) : + { + . = ALIGN(4); + _sbss = . ; + _szero = .; + *(.bss .bss.*) + *(COMMON) + . = ALIGN(4); + _ebss = . ; + _ezero = .; + end = .; + } > ram + + /* stack section */ + .stack (NOLOAD): + { + . = ALIGN(8); + _sstack = .; + . = . + STACK_SIZE; + . = ALIGN(8); + _estack = .; + } > ram + + . = ALIGN(4); + _end = . ; +} diff --git a/hw/bsp/samd2x_l2x/boards/metro_m0_express/board.cmake b/hw/bsp/samd2x_l2x/boards/metro_m0_express/board.cmake new file mode 100644 index 000000000..dedc07594 --- /dev/null +++ b/hw/bsp/samd2x_l2x/boards/metro_m0_express/board.cmake @@ -0,0 +1,10 @@ +set(SAM_FAMILY samd21) +set(JLINK_DEVICE ATSAMD21G18) +set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/${BOARD}.ld) + +function(update_board TARGET) + target_compile_definitions(${TARGET} PUBLIC + __SAMD21G18A__ + CFG_EXAMPLE_VIDEO_READONLY + ) +endfunction() diff --git a/hw/bsp/samd2x_l2x/boards/metro_m0_express/board.h b/hw/bsp/samd2x_l2x/boards/metro_m0_express/board.h new file mode 100644 index 000000000..726de3259 --- /dev/null +++ b/hw/bsp/samd2x_l2x/boards/metro_m0_express/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: Adafruit Metro M0 Express + url: https://www.adafruit.com/product/3505 +*/ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +// LED +#define LED_PIN 17 +#define LED_STATE_ON 1 + +// Button: D5 +#define BUTTON_PIN 15 +#define BUTTON_STATE_ACTIVE 0 + +// UART +#define UART_RX_PIN 4 +#define UART_TX_PIN 5 + +// SPI for USB host shield +#define MAX3421_SERCOM_ID 4 // SERCOM4 +#define MAX3421_SERCOM_FUNCTION 3 // function D (Sercom Alt) + +#define MAX3421_SCK_PIN (32+11) +#define MAX3421_MOSI_PIN (32+10) +#define MAX3421_MISO_PIN 12 +#define MAX3421_TX_PAD 1 // MOSI = PAD_2, SCK = PAD_3 +#define MAX3421_RX_PAD 0 // MISO = PAD_2 + +#define MAX3421_CS_PIN 18 // D10 + +#define MAX3421_INTR_PIN 7 // D9 +#define MAX3421_INTR_EIC_ID 7 // EIC7 + +static inline void board_vbus_set(uint8_t rhport, bool state) { + (void) rhport; (void) state; +} + +#ifdef __cplusplus + } +#endif + +#endif /* BOARD_H_ */ diff --git a/hw/bsp/samd2x_l2x/boards/metro_m0_express/board.mk b/hw/bsp/samd2x_l2x/boards/metro_m0_express/board.mk new file mode 100644 index 000000000..f4211e6c8 --- /dev/null +++ b/hw/bsp/samd2x_l2x/boards/metro_m0_express/board.mk @@ -0,0 +1,11 @@ +SAM_FAMILY = samd21 + +CFLAGS += -D__SAMD21G18A__ -DCFG_EXAMPLE_VIDEO_READONLY + +# All source paths should be relative to the top level. +LD_FILE = $(BOARD_PATH)/$(BOARD).ld + +# For flash-jlink target +JLINK_DEVICE = ATSAMD21G18 + +flash: flash-bossac diff --git a/hw/bsp/samd2x_l2x/boards/metro_m0_express/metro_m0_express.ld b/hw/bsp/samd2x_l2x/boards/metro_m0_express/metro_m0_express.ld new file mode 100644 index 000000000..ce7aff80b --- /dev/null +++ b/hw/bsp/samd2x_l2x/boards/metro_m0_express/metro_m0_express.ld @@ -0,0 +1,146 @@ +/** + * \file + * + * \brief Linker script for running in internal FLASH on the SAMD21G18A + * + * Copyright (c) 2017 Microchip Technology Inc. + * + * \asf_license_start + * + * \page License + * + * 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 Licence 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. + * + * \asf_license_stop + * + */ + + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +SEARCH_DIR(.) + +/* Memory Spaces Definitions */ +MEMORY +{ + rom (rx) : ORIGIN = 0x00000000 + 8K, LENGTH = 0x00040000 - 8K + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000 +} + +/* The stack size used by the application. NOTE: you need to adjust according to your application. */ +STACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x2000; + +ENTRY(Reset_Handler) + +/* Section Definitions */ +SECTIONS +{ + .text : + { + . = ALIGN(4); + _sfixed = .; + KEEP(*(.vectors .vectors.*)) + *(.text .text.* .gnu.linkonce.t.*) + *(.glue_7t) *(.glue_7) + *(.rodata .rodata* .gnu.linkonce.r.*) + *(.ARM.extab* .gnu.linkonce.armextab.*) + + /* Support C constructors, and C destructors in both user code + and the C library. This also provides support for C++ code. */ + . = ALIGN(4); + KEEP(*(.init)) + . = ALIGN(4); + __preinit_array_start = .; + KEEP (*(.preinit_array)) + __preinit_array_end = .; + + . = ALIGN(4); + __init_array_start = .; + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + __init_array_end = .; + + . = ALIGN(4); + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*crtend.o(.ctors)) + + . = ALIGN(4); + KEEP(*(.fini)) + + . = ALIGN(4); + __fini_array_start = .; + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + __fini_array_end = .; + + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*crtend.o(.dtors)) + + . = ALIGN(4); + _efixed = .; /* End of text section */ + } > rom + + /* .ARM.exidx is sorted, so has to go in its own output section. */ + PROVIDE_HIDDEN (__exidx_start = .); + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > rom + PROVIDE_HIDDEN (__exidx_end = .); + + . = ALIGN(4); + _etext = .; + + .relocate : AT (_etext) + { + . = ALIGN(4); + _srelocate = .; + *(.ramfunc .ramfunc.*); + *(.data .data.*); + . = ALIGN(4); + _erelocate = .; + } > ram + + /* .bss section which is used for uninitialized data */ + .bss (NOLOAD) : + { + . = ALIGN(4); + _sbss = . ; + _szero = .; + *(.bss .bss.*) + *(COMMON) + . = ALIGN(4); + _ebss = . ; + _ezero = .; + end = .; + } > ram + + /* stack section */ + .stack (NOLOAD): + { + . = ALIGN(8); + _sstack = .; + . = . + STACK_SIZE; + . = ALIGN(8); + _estack = .; + } > ram + + . = ALIGN(4); + _end = . ; +} diff --git a/hw/bsp/samd2x_l2x/boards/qtpy/board.cmake b/hw/bsp/samd2x_l2x/boards/qtpy/board.cmake new file mode 100644 index 000000000..958944620 --- /dev/null +++ b/hw/bsp/samd2x_l2x/boards/qtpy/board.cmake @@ -0,0 +1,10 @@ +set(SAM_FAMILY samd21) +set(JLINK_DEVICE ATSAMD21E18) +set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/${BOARD}.ld) + +function(update_board TARGET) + target_compile_definitions(${TARGET} PUBLIC + __SAMD21E18A__ + CFG_EXAMPLE_VIDEO_READONLY + ) +endfunction() diff --git a/hw/bsp/samd2x_l2x/boards/qtpy/board.h b/hw/bsp/samd2x_l2x/boards/qtpy/board.h new file mode 100644 index 000000000..b1cf338e4 --- /dev/null +++ b/hw/bsp/samd2x_l2x/boards/qtpy/board.h @@ -0,0 +1,55 @@ +/* + * 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 QT Py + url: https://www.adafruit.com/product/4600 +*/ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +// LED is neopixel, leave unset for now + +// Button is wired to reset + +// UART +#define UART_RX_PIN 8 +#define UART_TX_PIN 7 + +static inline void board_vbus_set(uint8_t rhport, bool state) { + (void) rhport; (void) state; +} + +#ifdef __cplusplus + } +#endif + +#endif /* BOARD_H_ */ diff --git a/hw/bsp/samd2x_l2x/boards/qtpy/board.mk b/hw/bsp/samd2x_l2x/boards/qtpy/board.mk new file mode 100644 index 000000000..4009c8a38 --- /dev/null +++ b/hw/bsp/samd2x_l2x/boards/qtpy/board.mk @@ -0,0 +1,13 @@ +SAM_FAMILY = samd21 + +# For Adafruit QT Py board + +CFLAGS += -D__SAMD21E18A__ -DCFG_EXAMPLE_VIDEO_READONLY + +# All source paths should be relative to the top level. +LD_FILE = $(BOARD_PATH)/$(BOARD).ld + +# For flash-jlink target +JLINK_DEVICE = ATSAMD21E18 + +flash: flash-bossac diff --git a/hw/bsp/samd2x_l2x/boards/qtpy/qtpy.ld b/hw/bsp/samd2x_l2x/boards/qtpy/qtpy.ld new file mode 100644 index 000000000..ce7aff80b --- /dev/null +++ b/hw/bsp/samd2x_l2x/boards/qtpy/qtpy.ld @@ -0,0 +1,146 @@ +/** + * \file + * + * \brief Linker script for running in internal FLASH on the SAMD21G18A + * + * Copyright (c) 2017 Microchip Technology Inc. + * + * \asf_license_start + * + * \page License + * + * 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 Licence 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. + * + * \asf_license_stop + * + */ + + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +SEARCH_DIR(.) + +/* Memory Spaces Definitions */ +MEMORY +{ + rom (rx) : ORIGIN = 0x00000000 + 8K, LENGTH = 0x00040000 - 8K + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000 +} + +/* The stack size used by the application. NOTE: you need to adjust according to your application. */ +STACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x2000; + +ENTRY(Reset_Handler) + +/* Section Definitions */ +SECTIONS +{ + .text : + { + . = ALIGN(4); + _sfixed = .; + KEEP(*(.vectors .vectors.*)) + *(.text .text.* .gnu.linkonce.t.*) + *(.glue_7t) *(.glue_7) + *(.rodata .rodata* .gnu.linkonce.r.*) + *(.ARM.extab* .gnu.linkonce.armextab.*) + + /* Support C constructors, and C destructors in both user code + and the C library. This also provides support for C++ code. */ + . = ALIGN(4); + KEEP(*(.init)) + . = ALIGN(4); + __preinit_array_start = .; + KEEP (*(.preinit_array)) + __preinit_array_end = .; + + . = ALIGN(4); + __init_array_start = .; + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + __init_array_end = .; + + . = ALIGN(4); + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*crtend.o(.ctors)) + + . = ALIGN(4); + KEEP(*(.fini)) + + . = ALIGN(4); + __fini_array_start = .; + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + __fini_array_end = .; + + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*crtend.o(.dtors)) + + . = ALIGN(4); + _efixed = .; /* End of text section */ + } > rom + + /* .ARM.exidx is sorted, so has to go in its own output section. */ + PROVIDE_HIDDEN (__exidx_start = .); + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > rom + PROVIDE_HIDDEN (__exidx_end = .); + + . = ALIGN(4); + _etext = .; + + .relocate : AT (_etext) + { + . = ALIGN(4); + _srelocate = .; + *(.ramfunc .ramfunc.*); + *(.data .data.*); + . = ALIGN(4); + _erelocate = .; + } > ram + + /* .bss section which is used for uninitialized data */ + .bss (NOLOAD) : + { + . = ALIGN(4); + _sbss = . ; + _szero = .; + *(.bss .bss.*) + *(COMMON) + . = ALIGN(4); + _ebss = . ; + _ezero = .; + end = .; + } > ram + + /* stack section */ + .stack (NOLOAD): + { + . = ALIGN(8); + _sstack = .; + . = . + STACK_SIZE; + . = ALIGN(8); + _estack = .; + } > ram + + . = ALIGN(4); + _end = . ; +} diff --git a/hw/bsp/samd2x_l2x/boards/saml22_feather/board.cmake b/hw/bsp/samd2x_l2x/boards/saml22_feather/board.cmake new file mode 100644 index 000000000..7fd79d2ce --- /dev/null +++ b/hw/bsp/samd2x_l2x/boards/saml22_feather/board.cmake @@ -0,0 +1,9 @@ +set(SAM_FAMILY saml22) +set(JLINK_DEVICE ATSAML22J18) +set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/${BOARD}.ld) + +function(update_board TARGET) + target_compile_definitions(${TARGET} PUBLIC + __SAML22J18A__ + ) +endfunction() diff --git a/hw/bsp/samd2x_l2x/boards/saml22_feather/board.h b/hw/bsp/samd2x_l2x/boards/saml22_feather/board.h new file mode 100644 index 000000000..f8660c3f8 --- /dev/null +++ b/hw/bsp/samd2x_l2x/boards/saml22_feather/board.h @@ -0,0 +1,52 @@ +/* + * 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: SAML22 Feather + url: https://github.com/joeycastillo/Feather-Projects/tree/main/SAML22%20Feather +*/ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +// LED +#define LED_PIN PIN_PA08 +#define LED_STATE_ON 1 + +// Button +#define BUTTON_PIN PIN_PA06 +#define BUTTON_STATE_ACTIVE 0 + + +#ifdef __cplusplus + } +#endif + +#endif /* BOARD_H_ */ diff --git a/hw/bsp/samd2x_l2x/boards/saml22_feather/board.mk b/hw/bsp/samd2x_l2x/boards/saml22_feather/board.mk new file mode 100644 index 000000000..c7817ff70 --- /dev/null +++ b/hw/bsp/samd2x_l2x/boards/saml22_feather/board.mk @@ -0,0 +1,11 @@ +SAM_FAMILY = saml22 + +CFLAGS += -D__SAML22J18A__ + +# All source paths should be relative to the top level. +LD_FILE = $(BOARD_PATH)/$(BOARD).ld + +# For flash-jlink target +JLINK_DEVICE = ATSAML22J18 + +flash: flash-bossac diff --git a/hw/bsp/samd2x_l2x/boards/saml22_feather/saml22_feather.ld b/hw/bsp/samd2x_l2x/boards/saml22_feather/saml22_feather.ld new file mode 100644 index 000000000..a04305be7 --- /dev/null +++ b/hw/bsp/samd2x_l2x/boards/saml22_feather/saml22_feather.ld @@ -0,0 +1,146 @@ +/** + * \file + * + * \brief Linker script for running in internal FLASH on the SAML22J18A + * + * Copyright (c) 2018 Microchip Technology Inc. + * + * \asf_license_start + * + * \page License + * + * 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 Licence 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. + * + * \asf_license_stop + * + */ + + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +SEARCH_DIR(.) + +ENTRY(Reset_Handler) + +/* Memory Spaces Definitions */ +MEMORY +{ + rom (rx) : ORIGIN = 0x00000000, LENGTH = 0x00040000 + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000 +} + +/* The stack size used by the application. NOTE: you need to adjust according to your application. */ +STACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x2000; + +/* Section Definitions */ +SECTIONS +{ + .text : + { + . = ALIGN(4); + _sfixed = .; + KEEP(*(.vectors .vectors.*)) + *(.text .text.* .gnu.linkonce.t.*) + *(.glue_7t) *(.glue_7) + *(.rodata .rodata* .gnu.linkonce.r.*) + *(.ARM.extab* .gnu.linkonce.armextab.*) + + /* Support C constructors, and C destructors in both user code + and the C library. This also provides support for C++ code. */ + . = ALIGN(4); + KEEP(*(.init)) + . = ALIGN(4); + __preinit_array_start = .; + KEEP (*(.preinit_array)) + __preinit_array_end = .; + + . = ALIGN(4); + __init_array_start = .; + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + __init_array_end = .; + + . = ALIGN(4); + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*crtend.o(.ctors)) + + . = ALIGN(4); + KEEP(*(.fini)) + + . = ALIGN(4); + __fini_array_start = .; + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + __fini_array_end = .; + + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*crtend.o(.dtors)) + + . = ALIGN(4); + _efixed = .; /* End of text section */ + } > rom + + /* .ARM.exidx is sorted, so has to go in its own output section. */ + PROVIDE_HIDDEN (__exidx_start = .); + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > rom + PROVIDE_HIDDEN (__exidx_end = .); + + . = ALIGN(4); + _etext = .; + + .relocate : AT (_etext) + { + . = ALIGN(4); + _srelocate = .; + *(.ramfunc .ramfunc.*); + *(.data .data.*); + . = ALIGN(4); + _erelocate = .; + } > ram + + /* .bss section which is used for uninitialized data */ + .bss (NOLOAD) : + { + . = ALIGN(4); + _sbss = . ; + _szero = .; + *(.bss .bss.*) + *(COMMON) + . = ALIGN(4); + _ebss = . ; + _ezero = .; + end = .; + } > ram + + /* stack section */ + .stack (NOLOAD): + { + . = ALIGN(8); + _sstack = .; + . = . + STACK_SIZE; + . = ALIGN(8); + _estack = .; + } > ram + + . = ALIGN(4); + _end = . ; +} diff --git a/hw/bsp/samd2x_l2x/boards/seeeduino_xiao/board.cmake b/hw/bsp/samd2x_l2x/boards/seeeduino_xiao/board.cmake new file mode 100644 index 000000000..dedc07594 --- /dev/null +++ b/hw/bsp/samd2x_l2x/boards/seeeduino_xiao/board.cmake @@ -0,0 +1,10 @@ +set(SAM_FAMILY samd21) +set(JLINK_DEVICE ATSAMD21G18) +set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/${BOARD}.ld) + +function(update_board TARGET) + target_compile_definitions(${TARGET} PUBLIC + __SAMD21G18A__ + CFG_EXAMPLE_VIDEO_READONLY + ) +endfunction() diff --git a/hw/bsp/samd2x_l2x/boards/seeeduino_xiao/board.h b/hw/bsp/samd2x_l2x/boards/seeeduino_xiao/board.h new file mode 100644 index 000000000..1c434c68c --- /dev/null +++ b/hw/bsp/samd2x_l2x/boards/seeeduino_xiao/board.h @@ -0,0 +1,59 @@ +/* + * 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: Seeeduino XIAO + url: https://wiki.seeedstudio.com/Seeeduino-XIAO/ +*/ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +// LED +#define LED_PIN 17 +#define LED_STATE_ON 0 + +// Button +#define BUTTON_PIN 9 // PA4 pin D1 on seed input +#define BUTTON_STATE_ACTIVE 0 + +// UART +#define UART_RX_PIN 4 +#define UART_TX_PIN 5 + +static inline void board_vbus_set(uint8_t rhport, bool state) { + (void) rhport; (void) state; +} + +#ifdef __cplusplus + } +#endif + +#endif /* BOARD_H_ */ diff --git a/hw/bsp/samd2x_l2x/boards/seeeduino_xiao/board.mk b/hw/bsp/samd2x_l2x/boards/seeeduino_xiao/board.mk new file mode 100644 index 000000000..0afe37f12 --- /dev/null +++ b/hw/bsp/samd2x_l2x/boards/seeeduino_xiao/board.mk @@ -0,0 +1,11 @@ +SAM_FAMILY = samd21 + +CFLAGS += -D__SAMD21G18A__ -DCFG_EXAMPLE_VIDEO_READONLY + +LD_FILE = $(BOARD_PATH)/$(BOARD).ld + +# For flash-jlink target +JLINK_DEVICE = ATSAMD21G18 + +# flash using jlink +flash: flash-jlink diff --git a/hw/bsp/samd2x_l2x/boards/seeeduino_xiao/seeeduino_xiao.ld b/hw/bsp/samd2x_l2x/boards/seeeduino_xiao/seeeduino_xiao.ld new file mode 100644 index 000000000..0d0c4e6c4 --- /dev/null +++ b/hw/bsp/samd2x_l2x/boards/seeeduino_xiao/seeeduino_xiao.ld @@ -0,0 +1,146 @@ +/** + * \file + * + * \brief Linker script for running in internal FLASH on the SAMD21G18A + * + * Copyright (c) 2017 Microchip Technology Inc. + * + * \asf_license_start + * + * \page License + * + * 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 Licence 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. + * + * \asf_license_stop + * + */ + + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +SEARCH_DIR(.) + +/* Memory Spaces Definitions */ +MEMORY +{ + rom (rx) : ORIGIN = 0x00000000 + 8K, LENGTH = 0x00040000 - 8K /* 8K offset to preserve bootloader */ + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000 +} + +/* The stack size used by the application. NOTE: you need to adjust according to your application. */ +STACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x2000; + +ENTRY(Reset_Handler) + +/* Section Definitions */ +SECTIONS +{ + .text : + { + . = ALIGN(4); + _sfixed = .; + KEEP(*(.vectors .vectors.*)) + *(.text .text.* .gnu.linkonce.t.*) + *(.glue_7t) *(.glue_7) + *(.rodata .rodata* .gnu.linkonce.r.*) + *(.ARM.extab* .gnu.linkonce.armextab.*) + + /* Support C constructors, and C destructors in both user code + and the C library. This also provides support for C++ code. */ + . = ALIGN(4); + KEEP(*(.init)) + . = ALIGN(4); + __preinit_array_start = .; + KEEP (*(.preinit_array)) + __preinit_array_end = .; + + . = ALIGN(4); + __init_array_start = .; + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + __init_array_end = .; + + . = ALIGN(4); + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*crtend.o(.ctors)) + + . = ALIGN(4); + KEEP(*(.fini)) + + . = ALIGN(4); + __fini_array_start = .; + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + __fini_array_end = .; + + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*crtend.o(.dtors)) + + . = ALIGN(4); + _efixed = .; /* End of text section */ + } > rom + + /* .ARM.exidx is sorted, so has to go in its own output section. */ + PROVIDE_HIDDEN (__exidx_start = .); + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > rom + PROVIDE_HIDDEN (__exidx_end = .); + + . = ALIGN(4); + _etext = .; + + .relocate : AT (_etext) + { + . = ALIGN(4); + _srelocate = .; + *(.ramfunc .ramfunc.*); + *(.data .data.*); + . = ALIGN(4); + _erelocate = .; + } > ram + + /* .bss section which is used for uninitialized data */ + .bss (NOLOAD) : + { + . = ALIGN(4); + _sbss = . ; + _szero = .; + *(.bss .bss.*) + *(COMMON) + . = ALIGN(4); + _ebss = . ; + _ezero = .; + end = .; + } > ram + + /* stack section */ + .stack (NOLOAD): + { + . = ALIGN(8); + _sstack = .; + . = . + STACK_SIZE; + . = ALIGN(8); + _estack = .; + } > ram + + . = ALIGN(4); + _end = . ; +} diff --git a/hw/bsp/samd2x_l2x/boards/sensorwatch_m0/board.cmake b/hw/bsp/samd2x_l2x/boards/sensorwatch_m0/board.cmake new file mode 100644 index 000000000..67d26475f --- /dev/null +++ b/hw/bsp/samd2x_l2x/boards/sensorwatch_m0/board.cmake @@ -0,0 +1,9 @@ +set(SAM_FAMILY saml22) +set(JLINK_DEVICE ATSAML21J18) +set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/${BOARD}.ld) + +function(update_board TARGET) + target_compile_definitions(${TARGET} PUBLIC + __SAML22J18A__ + ) +endfunction() diff --git a/hw/bsp/samd2x_l2x/boards/sensorwatch_m0/board.h b/hw/bsp/samd2x_l2x/boards/sensorwatch_m0/board.h new file mode 100644 index 000000000..502c799db --- /dev/null +++ b/hw/bsp/samd2x_l2x/boards/sensorwatch_m0/board.h @@ -0,0 +1,52 @@ +/* + * 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: SensorWatch + url: https://github.com/joeycastillo/Sensor-Watch +*/ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +// LED +#define LED_PIN PIN_PA21 +#define LED_STATE_ON 1 + +// Button +#define BUTTON_PIN PIN_PA22 +#define BUTTON_STATE_ACTIVE 1 + + +#ifdef __cplusplus + } +#endif + +#endif /* BOARD_H_ */ diff --git a/hw/bsp/samd2x_l2x/boards/sensorwatch_m0/board.mk b/hw/bsp/samd2x_l2x/boards/sensorwatch_m0/board.mk new file mode 100644 index 000000000..c7817ff70 --- /dev/null +++ b/hw/bsp/samd2x_l2x/boards/sensorwatch_m0/board.mk @@ -0,0 +1,11 @@ +SAM_FAMILY = saml22 + +CFLAGS += -D__SAML22J18A__ + +# All source paths should be relative to the top level. +LD_FILE = $(BOARD_PATH)/$(BOARD).ld + +# For flash-jlink target +JLINK_DEVICE = ATSAML22J18 + +flash: flash-bossac diff --git a/hw/bsp/samd2x_l2x/boards/sensorwatch_m0/sensorwatch_m0.ld b/hw/bsp/samd2x_l2x/boards/sensorwatch_m0/sensorwatch_m0.ld new file mode 100644 index 000000000..a04305be7 --- /dev/null +++ b/hw/bsp/samd2x_l2x/boards/sensorwatch_m0/sensorwatch_m0.ld @@ -0,0 +1,146 @@ +/** + * \file + * + * \brief Linker script for running in internal FLASH on the SAML22J18A + * + * Copyright (c) 2018 Microchip Technology Inc. + * + * \asf_license_start + * + * \page License + * + * 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 Licence 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. + * + * \asf_license_stop + * + */ + + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +SEARCH_DIR(.) + +ENTRY(Reset_Handler) + +/* Memory Spaces Definitions */ +MEMORY +{ + rom (rx) : ORIGIN = 0x00000000, LENGTH = 0x00040000 + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000 +} + +/* The stack size used by the application. NOTE: you need to adjust according to your application. */ +STACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x2000; + +/* Section Definitions */ +SECTIONS +{ + .text : + { + . = ALIGN(4); + _sfixed = .; + KEEP(*(.vectors .vectors.*)) + *(.text .text.* .gnu.linkonce.t.*) + *(.glue_7t) *(.glue_7) + *(.rodata .rodata* .gnu.linkonce.r.*) + *(.ARM.extab* .gnu.linkonce.armextab.*) + + /* Support C constructors, and C destructors in both user code + and the C library. This also provides support for C++ code. */ + . = ALIGN(4); + KEEP(*(.init)) + . = ALIGN(4); + __preinit_array_start = .; + KEEP (*(.preinit_array)) + __preinit_array_end = .; + + . = ALIGN(4); + __init_array_start = .; + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + __init_array_end = .; + + . = ALIGN(4); + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*crtend.o(.ctors)) + + . = ALIGN(4); + KEEP(*(.fini)) + + . = ALIGN(4); + __fini_array_start = .; + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + __fini_array_end = .; + + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*crtend.o(.dtors)) + + . = ALIGN(4); + _efixed = .; /* End of text section */ + } > rom + + /* .ARM.exidx is sorted, so has to go in its own output section. */ + PROVIDE_HIDDEN (__exidx_start = .); + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > rom + PROVIDE_HIDDEN (__exidx_end = .); + + . = ALIGN(4); + _etext = .; + + .relocate : AT (_etext) + { + . = ALIGN(4); + _srelocate = .; + *(.ramfunc .ramfunc.*); + *(.data .data.*); + . = ALIGN(4); + _erelocate = .; + } > ram + + /* .bss section which is used for uninitialized data */ + .bss (NOLOAD) : + { + . = ALIGN(4); + _sbss = . ; + _szero = .; + *(.bss .bss.*) + *(COMMON) + . = ALIGN(4); + _ebss = . ; + _ezero = .; + end = .; + } > ram + + /* stack section */ + .stack (NOLOAD): + { + . = ALIGN(8); + _sstack = .; + . = . + STACK_SIZE; + . = ALIGN(8); + _estack = .; + } > ram + + . = ALIGN(4); + _end = . ; +} diff --git a/hw/bsp/samd2x_l2x/boards/sparkfun_samd21_mini_usb/board.cmake b/hw/bsp/samd2x_l2x/boards/sparkfun_samd21_mini_usb/board.cmake new file mode 100644 index 000000000..dedc07594 --- /dev/null +++ b/hw/bsp/samd2x_l2x/boards/sparkfun_samd21_mini_usb/board.cmake @@ -0,0 +1,10 @@ +set(SAM_FAMILY samd21) +set(JLINK_DEVICE ATSAMD21G18) +set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/${BOARD}.ld) + +function(update_board TARGET) + target_compile_definitions(${TARGET} PUBLIC + __SAMD21G18A__ + CFG_EXAMPLE_VIDEO_READONLY + ) +endfunction() diff --git a/hw/bsp/samd2x_l2x/boards/sparkfun_samd21_mini_usb/board.h b/hw/bsp/samd2x_l2x/boards/sparkfun_samd21_mini_usb/board.h new file mode 100644 index 000000000..a05cf5e4e --- /dev/null +++ b/hw/bsp/samd2x_l2x/boards/sparkfun_samd21_mini_usb/board.h @@ -0,0 +1,62 @@ +/* + * 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: SparkFun SAMD21 Mini + url: https://www.sparkfun.com/products/13664 +*/ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +// LED +#define LED_PIN 17 // PA17 (D13) +#define LED_STATE_ON 1 + +// Button +#define BUTTON_PIN 14 // PA14 (D2) +#define BUTTON_STATE_ACTIVE 0 + +// UART +#define UART_SERCOM 0 +#define UART_RX_PIN 11 // PA11 D0 +#define UART_TX_PIN 10 // PA10 D1 + +static inline void board_vbus_set(uint8_t rhport, bool state) { + (void) rhport; + gpio_set_pin_direction(PIN_PA28, GPIO_DIRECTION_OUT); + gpio_set_pin_level(PIN_PA28, state); +} + +#ifdef __cplusplus + } +#endif + +#endif /* BOARD_H_ */ diff --git a/hw/bsp/samd2x_l2x/boards/sparkfun_samd21_mini_usb/board.mk b/hw/bsp/samd2x_l2x/boards/sparkfun_samd21_mini_usb/board.mk new file mode 100644 index 000000000..f4211e6c8 --- /dev/null +++ b/hw/bsp/samd2x_l2x/boards/sparkfun_samd21_mini_usb/board.mk @@ -0,0 +1,11 @@ +SAM_FAMILY = samd21 + +CFLAGS += -D__SAMD21G18A__ -DCFG_EXAMPLE_VIDEO_READONLY + +# All source paths should be relative to the top level. +LD_FILE = $(BOARD_PATH)/$(BOARD).ld + +# For flash-jlink target +JLINK_DEVICE = ATSAMD21G18 + +flash: flash-bossac diff --git a/hw/bsp/samd2x_l2x/boards/sparkfun_samd21_mini_usb/sparkfun_samd21_mini_usb.ld b/hw/bsp/samd2x_l2x/boards/sparkfun_samd21_mini_usb/sparkfun_samd21_mini_usb.ld new file mode 100644 index 000000000..0754a8e9c --- /dev/null +++ b/hw/bsp/samd2x_l2x/boards/sparkfun_samd21_mini_usb/sparkfun_samd21_mini_usb.ld @@ -0,0 +1,146 @@ +/** + * \file + * + * \brief Linker script for running in internal FLASH on the SAMD21G18A + * + * Copyright (c) 2017 Microchip Technology Inc. + * + * \asf_license_start + * + * \page License + * + * 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 Licence 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. + * + * \asf_license_stop + * + */ + + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +SEARCH_DIR(.) + +/* Memory Spaces Definitions */ +MEMORY +{ + rom (rx) : ORIGIN = 0x00000000 + 8K, LENGTH = 0x00040000 - 8K + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000-0x0004 /* 4 bytes used by bootloader to keep data between resets */ +} + +/* The stack size used by the application. NOTE: you need to adjust according to your application. */ +STACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x2000; + +ENTRY(Reset_Handler) + +/* Section Definitions */ +SECTIONS +{ + .text : + { + . = ALIGN(4); + _sfixed = .; + KEEP(*(.vectors .vectors.*)) + *(.text .text.* .gnu.linkonce.t.*) + *(.glue_7t) *(.glue_7) + *(.rodata .rodata* .gnu.linkonce.r.*) + *(.ARM.extab* .gnu.linkonce.armextab.*) + + /* Support C constructors, and C destructors in both user code + and the C library. This also provides support for C++ code. */ + . = ALIGN(4); + KEEP(*(.init)) + . = ALIGN(4); + __preinit_array_start = .; + KEEP (*(.preinit_array)) + __preinit_array_end = .; + + . = ALIGN(4); + __init_array_start = .; + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + __init_array_end = .; + + . = ALIGN(4); + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*crtend.o(.ctors)) + + . = ALIGN(4); + KEEP(*(.fini)) + + . = ALIGN(4); + __fini_array_start = .; + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + __fini_array_end = .; + + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*crtend.o(.dtors)) + + . = ALIGN(4); + _efixed = .; /* End of text section */ + } > rom + + /* .ARM.exidx is sorted, so has to go in its own output section. */ + PROVIDE_HIDDEN (__exidx_start = .); + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > rom + PROVIDE_HIDDEN (__exidx_end = .); + + . = ALIGN(4); + _etext = .; + + .relocate : AT (_etext) + { + . = ALIGN(4); + _srelocate = .; + *(.ramfunc .ramfunc.*); + *(.data .data.*); + . = ALIGN(4); + _erelocate = .; + } > ram + + /* .bss section which is used for uninitialized data */ + .bss (NOLOAD) : + { + . = ALIGN(4); + _sbss = . ; + _szero = .; + *(.bss .bss.*) + *(COMMON) + . = ALIGN(4); + _ebss = . ; + _ezero = .; + end = .; + } > ram + + /* stack section */ + .stack (NOLOAD): + { + . = ALIGN(8); + _sstack = .; + . = . + STACK_SIZE; + . = ALIGN(8); + _estack = .; + } > ram + + . = ALIGN(4); + _end = . ; +} diff --git a/hw/bsp/samd2x_l2x/boards/trinket_m0/board.cmake b/hw/bsp/samd2x_l2x/boards/trinket_m0/board.cmake new file mode 100644 index 000000000..958944620 --- /dev/null +++ b/hw/bsp/samd2x_l2x/boards/trinket_m0/board.cmake @@ -0,0 +1,10 @@ +set(SAM_FAMILY samd21) +set(JLINK_DEVICE ATSAMD21E18) +set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/${BOARD}.ld) + +function(update_board TARGET) + target_compile_definitions(${TARGET} PUBLIC + __SAMD21E18A__ + CFG_EXAMPLE_VIDEO_READONLY + ) +endfunction() diff --git a/hw/bsp/samd2x_l2x/boards/trinket_m0/board.h b/hw/bsp/samd2x_l2x/boards/trinket_m0/board.h new file mode 100644 index 000000000..01ad83089 --- /dev/null +++ b/hw/bsp/samd2x_l2x/boards/trinket_m0/board.h @@ -0,0 +1,44 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021 Jean Gressmann + * + * 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. + * + */ + +/* metadata: + name: Adafruit Trinket M0 + url: https://www.adafruit.com/product/3500 +*/ + +#pragma once + +// LED +#define LED_PIN 10 // PA10 +#define LED_STATE_ON 1 + +// UART +#define UART_SERCOM 0 +#define UART_RX_PIN 7 +#define UART_TX_PIN 6 + +static inline void board_vbus_set(uint8_t rhport, bool state) { + (void) rhport; (void) state; +} diff --git a/hw/bsp/samd2x_l2x/boards/trinket_m0/board.mk b/hw/bsp/samd2x_l2x/boards/trinket_m0/board.mk new file mode 100644 index 000000000..201259288 --- /dev/null +++ b/hw/bsp/samd2x_l2x/boards/trinket_m0/board.mk @@ -0,0 +1,6 @@ +SAM_FAMILY = samd21 + +CFLAGS += -D__SAMD21E18A__ -DCFG_EXAMPLE_VIDEO_READONLY + +# All source paths should be relative to the top level. +LD_FILE = $(BOARD_PATH)/trinket_m0.ld diff --git a/hw/bsp/samd2x_l2x/boards/trinket_m0/trinket_m0.ld b/hw/bsp/samd2x_l2x/boards/trinket_m0/trinket_m0.ld new file mode 100644 index 000000000..ce7aff80b --- /dev/null +++ b/hw/bsp/samd2x_l2x/boards/trinket_m0/trinket_m0.ld @@ -0,0 +1,146 @@ +/** + * \file + * + * \brief Linker script for running in internal FLASH on the SAMD21G18A + * + * Copyright (c) 2017 Microchip Technology Inc. + * + * \asf_license_start + * + * \page License + * + * 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 Licence 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. + * + * \asf_license_stop + * + */ + + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +SEARCH_DIR(.) + +/* Memory Spaces Definitions */ +MEMORY +{ + rom (rx) : ORIGIN = 0x00000000 + 8K, LENGTH = 0x00040000 - 8K + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000 +} + +/* The stack size used by the application. NOTE: you need to adjust according to your application. */ +STACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x2000; + +ENTRY(Reset_Handler) + +/* Section Definitions */ +SECTIONS +{ + .text : + { + . = ALIGN(4); + _sfixed = .; + KEEP(*(.vectors .vectors.*)) + *(.text .text.* .gnu.linkonce.t.*) + *(.glue_7t) *(.glue_7) + *(.rodata .rodata* .gnu.linkonce.r.*) + *(.ARM.extab* .gnu.linkonce.armextab.*) + + /* Support C constructors, and C destructors in both user code + and the C library. This also provides support for C++ code. */ + . = ALIGN(4); + KEEP(*(.init)) + . = ALIGN(4); + __preinit_array_start = .; + KEEP (*(.preinit_array)) + __preinit_array_end = .; + + . = ALIGN(4); + __init_array_start = .; + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + __init_array_end = .; + + . = ALIGN(4); + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*crtend.o(.ctors)) + + . = ALIGN(4); + KEEP(*(.fini)) + + . = ALIGN(4); + __fini_array_start = .; + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + __fini_array_end = .; + + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*crtend.o(.dtors)) + + . = ALIGN(4); + _efixed = .; /* End of text section */ + } > rom + + /* .ARM.exidx is sorted, so has to go in its own output section. */ + PROVIDE_HIDDEN (__exidx_start = .); + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > rom + PROVIDE_HIDDEN (__exidx_end = .); + + . = ALIGN(4); + _etext = .; + + .relocate : AT (_etext) + { + . = ALIGN(4); + _srelocate = .; + *(.ramfunc .ramfunc.*); + *(.data .data.*); + . = ALIGN(4); + _erelocate = .; + } > ram + + /* .bss section which is used for uninitialized data */ + .bss (NOLOAD) : + { + . = ALIGN(4); + _sbss = . ; + _szero = .; + *(.bss .bss.*) + *(COMMON) + . = ALIGN(4); + _ebss = . ; + _ezero = .; + end = .; + } > ram + + /* stack section */ + .stack (NOLOAD): + { + . = ALIGN(8); + _sstack = .; + . = . + STACK_SIZE; + . = ALIGN(8); + _estack = .; + } > ram + + . = ALIGN(4); + _end = . ; +} diff --git a/hw/bsp/samd2x_l2x/family.c b/hw/bsp/samd2x_l2x/family.c new file mode 100644 index 000000000..67da1294e --- /dev/null +++ b/hw/bsp/samd2x_l2x/family.c @@ -0,0 +1,550 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 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: + manufacturer: Microchip +*/ + +#include "sam.h" +#include "bsp/board_api.h" + +// Suppress warning caused by mcu driver +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-qual" +#endif + +#include "hal/include/hal_gpio.h" +#include "hal/include/hal_init.h" +#include "hpl/gclk/hpl_gclk_base.h" + +// SAMD21 specific includes +#if defined(__SAMD21E15A__) || defined(__SAMD21E16A__) || defined(__SAMD21E17A__) || defined(__SAMD21E18A__) || \ + defined(__SAMD21G15A__) || defined(__SAMD21G16A__) || defined(__SAMD21G17A__) || defined(__SAMD21G18A__) || \ + defined(__SAMD21J15A__) || defined(__SAMD21J16A__) || defined(__SAMD21J17A__) || defined(__SAMD21J18A__) + #define SAMD21_FAMILY + #include "hri/hri_nvmctrl_d21.h" + #include "hpl_pm_config.h" + #include "hpl/pm/hpl_pm_base.h" +#endif + +// SAML21/22 specific includes +#if defined(__SAML21E15B__) || defined(__SAML21E16B__) || defined(__SAML21E17B__) || defined(__SAML21E18B__) || \ + defined(__SAML21G16B__) || defined(__SAML21G17B__) || defined(__SAML21G18B__) || \ + defined(__SAML21J16B__) || defined(__SAML21J17B__) || defined(__SAML21J18B__) || \ + defined(__SAML22G16A__) || defined(__SAML22G17A__) || defined(__SAML22G18A__) || \ + defined(__SAML22J16A__) || defined(__SAML22J17A__) || defined(__SAML22J18A__) || \ + defined(__SAML22N16A__) || defined(__SAML22N17A__) || defined(__SAML22N18A__) + #define SAML2X_FAMILY + #include "hpl_mclk_config.h" +#endif + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + +#include "board.h" + +// board_vbus_set is defined in board.h for boards that support it +#if !defined(board_vbus_set) + #define board_vbus_set(rhport, state) do { (void)(rhport); (void)(state); } while(0) +#endif + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM DECLARATION +//--------------------------------------------------------------------+ + +#ifdef SAMD21_FAMILY +/* Referenced GCLKs, should be initialized firstly */ +#define _GCLK_INIT_1ST (1 << 0 | 1 << 1) +/* Not referenced GCLKs, initialized last */ +#define _GCLK_INIT_LAST (~_GCLK_INIT_1ST) +#endif + +#ifdef SAML2X_FAMILY +/* Referenced GCLKs (out of 0~4), should be initialized firstly */ +#define _GCLK_INIT_1ST 0x00000000 +/* Not referenced GCLKs, initialized last */ +#define _GCLK_INIT_LAST 0x0000001F +#endif + +//--------------------------------------------------------------------+ +// 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 && !CFG_TUH_MAX3421 + tuh_int_handler(0); +#endif +} + +//--------------------------------------------------------------------+ +// Implementation +//--------------------------------------------------------------------+ +static void uart_init(void); + +#if CFG_TUH_ENABLED && CFG_TUH_MAX3421 +#define MAX3421_SERCOM TU_XSTRCAT(SERCOM, MAX3421_SERCOM_ID) +static void max3421_init(void); +#endif + +void board_init(void) { +#ifdef SAMD21_FAMILY + // Clock init for SAMD21 ( follow hpl_init.c ) + hri_nvmctrl_set_CTRLB_RWS_bf(NVMCTRL, 2); + + _pm_init(); + _sysctrl_init_sources(); +#if _GCLK_INIT_1ST + _gclk_init_generators_by_fref(_GCLK_INIT_1ST); +#endif + _sysctrl_init_referenced_generators(); + _gclk_init_generators_by_fref(_GCLK_INIT_LAST); +#endif + +#ifdef SAML2X_FAMILY + // Clock init for SAML2x ( follow hpl_init.c ) + hri_nvmctrl_set_CTRLB_RWS_bf(NVMCTRL, CONF_NVM_WAIT_STATE); + + _set_performance_level(2); + + _osc32kctrl_init_sources(); + _oscctrl_init_sources(); + _mclk_init(); +#if _GCLK_INIT_1ST + _gclk_init_generators_by_fref(_GCLK_INIT_1ST); +#endif + _oscctrl_init_referenced_generators(); + _gclk_init_generators_by_fref(_GCLK_INIT_LAST); + +#if (CONF_PORT_EVCTRL_PORT_0 | CONF_PORT_EVCTRL_PORT_1 | CONF_PORT_EVCTRL_PORT_2 | CONF_PORT_EVCTRL_PORT_3) + hri_port_set_EVCTRL_reg(PORT, 0, CONF_PORTA_EVCTRL); + hri_port_set_EVCTRL_reg(PORT, 1, CONF_PORTB_EVCTRL); +#endif +#endif + + // Update SystemCoreClock since it is hard coded with asf4 and not correct + // Init 1ms tick timer (samd SystemCoreClock may not correct) + SystemCoreClock = CONF_CPU_FREQUENCY; +#if CFG_TUSB_OS == OPT_OS_NONE + SysTick_Config(CONF_CPU_FREQUENCY / 1000); +#endif + + // Led init +#ifdef LED_PIN + gpio_set_pin_direction(LED_PIN, GPIO_DIRECTION_OUT); + board_led_write(false); +#endif + + // Button init +#ifdef BUTTON_PIN + gpio_set_pin_direction(BUTTON_PIN, GPIO_DIRECTION_IN); + gpio_set_pin_pull_mode(BUTTON_PIN, BUTTON_STATE_ACTIVE ? GPIO_PULL_DOWN : GPIO_PULL_UP); +#endif + + uart_init(); + +#if 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 + + /* USB Clock init + * The USB module requires a GCLK_USB of 48 MHz ~ 0.25% clock + * for low speed and full speed operation. */ +#ifdef SAMD21_FAMILY + _pm_enable_bus_clock(PM_BUS_APBB, USB); + _pm_enable_bus_clock(PM_BUS_AHB, USB); + _gclk_enable_channel(USB_GCLK_ID, GCLK_CLKCTRL_GEN_GCLK0_Val); +#endif + +#ifdef SAML2X_FAMILY + hri_gclk_write_PCHCTRL_reg(GCLK, USB_GCLK_ID, GCLK_PCHCTRL_GEN_GCLK1_Val | GCLK_PCHCTRL_CHEN); + hri_mclk_set_AHBMASK_USB_bit(MCLK); + hri_mclk_set_APBBMASK_USB_bit(MCLK); +#endif + + // USB Pin Init + gpio_set_pin_direction(PIN_PA24, GPIO_DIRECTION_OUT); + gpio_set_pin_level(PIN_PA24, false); + gpio_set_pin_pull_mode(PIN_PA24, GPIO_PULL_OFF); + gpio_set_pin_direction(PIN_PA25, GPIO_DIRECTION_OUT); + gpio_set_pin_level(PIN_PA25, false); + gpio_set_pin_pull_mode(PIN_PA25, GPIO_PULL_OFF); + + gpio_set_pin_function(PIN_PA24, PINMUX_PA24G_USB_DM); + gpio_set_pin_function(PIN_PA25, PINMUX_PA25G_USB_DP); + +#ifdef SAMD21_FAMILY + // Output 500hz PWM on D12 (PA19 - TCC0 WO[3]) so we can validate the GCLK0 clock speed with a Saleae. + _pm_enable_bus_clock(PM_BUS_APBC, TCC0); + TCC0->PER.bit.PER = 48000000 / 1000; + TCC0->CC[3].bit.CC = 48000000 / 2000; + TCC0->CTRLA.bit.ENABLE = true; + + gpio_set_pin_function(PIN_PA19, PINMUX_PA19F_TCC0_WO3); + _gclk_enable_channel(TCC0_GCLK_ID, GCLK_CLKCTRL_GEN_GCLK0_Val); +#endif + +#if CFG_TUH_ENABLED + #if CFG_TUH_MAX3421 + max3421_init(); + #else + // VBUS Power + board_vbus_set(0, true); + #endif +#endif +} + +//--------------------------------------------------------------------+ +// Board porting API +//--------------------------------------------------------------------+ + +void board_led_write(bool state) { + (void) state; +#ifdef LED_PIN + gpio_set_pin_level(LED_PIN, state ? LED_STATE_ON : (1 - LED_STATE_ON)); +#endif +} + +uint32_t board_button_read(void) { +#ifdef BUTTON_PIN + return BUTTON_STATE_ACTIVE == gpio_get_pin_level(BUTTON_PIN); +#else + return 0; +#endif +} + +#if defined(UART_SERCOM) + +#define BOARD_SERCOM2(n) SERCOM ## n +#define BOARD_SERCOM(n) BOARD_SERCOM2(n) + +static void uart_init(void) +{ +#if UART_SERCOM == 0 + #if UART_TX_PIN == 6 + gpio_set_pin_function(PIN_PA06, PINMUX_PA06D_SERCOM0_PAD2); + #elif UART_TX_PIN == 10 + gpio_set_pin_function(PIN_PA10, PINMUX_PA10C_SERCOM0_PAD2); + #else + #error "UART_TX_PIN not supported" + #endif + + #if UART_RX_PIN == 7 + gpio_set_pin_function(PIN_PA07, PINMUX_PA07D_SERCOM0_PAD3); + #elif UART_RX_PIN == 11 + gpio_set_pin_function(PIN_PA11, PINMUX_PA11C_SERCOM0_PAD3); + #else + #error "UART_RX_PIN not supported" +#endif + +#ifdef SAMD21_FAMILY + // setup clock (48MHz) + _pm_enable_bus_clock(PM_BUS_APBC, SERCOM0); + _gclk_enable_channel(SERCOM0_GCLK_ID_CORE, GCLK_CLKCTRL_GEN_GCLK0_Val); +#endif + +#ifdef SAML2X_FAMILY + // setup clock (48MHz) + hri_gclk_write_PCHCTRL_reg(GCLK, SERCOM0_GCLK_ID_CORE, GCLK_PCHCTRL_GEN_GCLK1_Val | GCLK_PCHCTRL_CHEN); + hri_mclk_set_APBCMASK_SERCOM0_bit(MCLK); +#endif + + SERCOM0->USART.CTRLA.bit.SWRST = 1; /* reset SERCOM & enable config */ + while(SERCOM0->USART.SYNCBUSY.bit.SWRST); + + SERCOM0->USART.CTRLA.reg = /* CMODE = 0 -> async, SAMPA = 0, FORM = 0 -> USART frame, SMPR = 0 -> arithmetic baud rate */ + SERCOM_USART_CTRLA_SAMPR(1) | /* 0 = 16x / arithmetic baud rate, 1 = 16x / fractional baud rate */ +// SERCOM_USART_CTRLA_FORM(0) | /* 0 = USART Frame, 2 = LIN Master */ + SERCOM_USART_CTRLA_DORD | /* LSB first */ + SERCOM_USART_CTRLA_MODE(1) | /* 0 = Asynchronous, 1 = USART with internal clock */ + SERCOM_USART_CTRLA_RXPO(3) | /* pad 3 */ + SERCOM_USART_CTRLA_TXPO(1); /* pad 2 */ + + SERCOM0->USART.CTRLB.reg = + SERCOM_USART_CTRLB_TXEN | /* tx enabled */ + SERCOM_USART_CTRLB_RXEN; /* rx enabled */ + + /* 115200 */ + SERCOM0->USART.BAUD.reg = SERCOM_USART_BAUD_FRAC_FP(0) | SERCOM_USART_BAUD_FRAC_BAUD(26); + + SERCOM0->USART.CTRLA.bit.ENABLE = 1; /* activate SERCOM */ + while(SERCOM0->USART.SYNCBUSY.bit.ENABLE); /* wait for SERCOM to be ready */ +#endif +} + +static inline void uart_send_buffer(uint8_t const *text, size_t len) +{ + for (size_t i = 0; i < len; ++i) { + BOARD_SERCOM(UART_SERCOM)->USART.DATA.reg = text[i]; + while((BOARD_SERCOM(UART_SERCOM)->USART.INTFLAG.reg & SERCOM_USART_INTFLAG_TXC) == 0); + } +} + +static inline void uart_send_str(const char* text) +{ + while (*text) { + BOARD_SERCOM(UART_SERCOM)->USART.DATA.reg = *text++; + while((BOARD_SERCOM(UART_SERCOM)->USART.INTFLAG.reg & SERCOM_USART_INTFLAG_TXC) == 0); + } +} + +int board_uart_read(uint8_t* buf, int len) +{ + (void) buf; (void) len; + return 0; +} + +int board_uart_write(void const * buf, int len) +{ + if (len < 0) { + uart_send_str(buf); + } else { + uart_send_buffer(buf, len); + } + return len; +} + +#else // ! defined(UART_SERCOM) + +static void uart_init(void) { +} + +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) 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++; +} + +uint32_t board_millis(void) { + return system_ticks; +} + +#endif + +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ +#if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 + +static void max3421_init(void) { + //------------- SPI Init -------------// + // MAX3421E max SPI clock is 26MHz however SAMD can only work reliably at 12 Mhz + uint32_t const baudrate = 12000000u; + +#ifdef SAMD21_FAMILY + // Enable the APB clock for SERCOM + PM->APBCMASK.reg |= 1u << (PM_APBCMASK_SERCOM0_Pos + MAX3421_SERCOM_ID); + + // Configure GCLK for SERCOM + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(GCLK_CLKCTRL_ID_SERCOM0_CORE_Val + MAX3421_SERCOM_ID) | + GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_CLKEN; + while (GCLK->STATUS.bit.SYNCBUSY); +#endif + +#ifdef SAML2X_FAMILY + // Enable the APB clock for SERCOM + hri_mclk_set_APBCMASK_reg(MCLK, 1u << (MCLK_APBCMASK_SERCOM0_Pos + MAX3421_SERCOM_ID)); + + // Configure GCLK for SERCOM + hri_gclk_write_PCHCTRL_reg(GCLK, SERCOM0_GCLK_ID_CORE + MAX3421_SERCOM_ID, + GCLK_PCHCTRL_GEN_GCLK1_Val | GCLK_PCHCTRL_CHEN); +#endif + + Sercom* sercom = MAX3421_SERCOM; + + // Disable the SPI module + sercom->SPI.CTRLA.bit.ENABLE = 0; + + // Reset the SPI module + sercom->SPI.CTRLA.bit.SWRST = 1; + while (sercom->SPI.SYNCBUSY.bit.SWRST); + + // Set up SPI in master mode, MSB first, SPI mode 0 + sercom->SPI.CTRLA.reg = SERCOM_SPI_CTRLA_DOPO(MAX3421_TX_PAD) | SERCOM_SPI_CTRLA_DIPO(MAX3421_RX_PAD) | + SERCOM_SPI_CTRLA_MODE(3); + + sercom->SPI.CTRLB.reg = SERCOM_SPI_CTRLB_CHSIZE(0) | SERCOM_SPI_CTRLB_RXEN; + while (sercom->SPI.SYNCBUSY.bit.CTRLB == 1); + + // Set the baud rate + sercom->SPI.BAUD.reg = (uint8_t) (SystemCoreClock / (2 * baudrate) - 1); + + // Configure SPI pins + gpio_set_pin_direction(MAX3421_SCK_PIN, GPIO_DIRECTION_OUT); + gpio_set_pin_pull_mode(MAX3421_SCK_PIN, GPIO_PULL_OFF); + gpio_set_pin_function(MAX3421_SCK_PIN, MAX3421_SERCOM_FUNCTION); + + gpio_set_pin_direction(MAX3421_MOSI_PIN, GPIO_DIRECTION_OUT); + gpio_set_pin_pull_mode(MAX3421_MOSI_PIN, GPIO_PULL_OFF); + gpio_set_pin_function(MAX3421_MOSI_PIN, MAX3421_SERCOM_FUNCTION); + + gpio_set_pin_direction(MAX3421_MISO_PIN, GPIO_DIRECTION_IN); + gpio_set_pin_pull_mode(MAX3421_MISO_PIN, GPIO_PULL_OFF); + gpio_set_pin_function(MAX3421_MISO_PIN, MAX3421_SERCOM_FUNCTION); + + // CS pin + gpio_set_pin_direction(MAX3421_CS_PIN, GPIO_DIRECTION_OUT); + gpio_set_pin_level(MAX3421_CS_PIN, 1); + + // Enable the SPI module + sercom->SPI.CTRLA.bit.ENABLE = 1; + while (sercom->SPI.SYNCBUSY.bit.ENABLE); + + //------------- External Interrupt -------------// + +#ifdef SAMD21_FAMILY + // Enable the APB clock for EIC (External Interrupt Controller) + PM->APBAMASK.reg |= PM_APBAMASK_EIC; + + // Configure GCLK for EIC + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID_EIC | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_CLKEN; + while (GCLK->STATUS.bit.SYNCBUSY); +#endif + +#ifdef SAML2X_FAMILY + // Enable the APB clock for EIC + hri_mclk_set_APBAMASK_EIC_bit(MCLK); + + // Configure GCLK for EIC + hri_gclk_write_PCHCTRL_reg(GCLK, EIC_GCLK_ID, GCLK_PCHCTRL_GEN_GCLK1_Val | GCLK_PCHCTRL_CHEN); +#endif + + // Configure interrupt pin as an input with function A (external interrupt) + gpio_set_pin_direction(MAX3421_INTR_PIN, GPIO_DIRECTION_IN); + gpio_set_pin_pull_mode(MAX3421_INTR_PIN, GPIO_PULL_UP); + gpio_set_pin_function(MAX3421_INTR_PIN, 0); + + // Disable EIC + EIC->CTRL.bit.ENABLE = 0; + while (EIC->STATUS.bit.SYNCBUSY); + + // Configure EIC to trigger on falling edge + uint8_t const sense_shift = MAX3421_INTR_EIC_ID * 4; + EIC->CONFIG[0].reg &= ~(7 << sense_shift); + EIC->CONFIG[0].reg |= 2 << sense_shift; + +#if CFG_TUSB_OS == OPT_OS_FREERTOS + // If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher ) + NVIC_SetPriority(EIC_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY); +#endif + + // Enable External Interrupt + EIC->INTENSET.reg = EIC_INTENSET_EXTINT(1 << MAX3421_INTR_EIC_ID); + + // Enable EIC + EIC->CTRL.bit.ENABLE = 1; + while (EIC->STATUS.bit.SYNCBUSY); +} + +void EIC_Handler(void) { + // Clear the interrupt flag + EIC->INTFLAG.reg = EIC_INTFLAG_EXTINT(1 << MAX3421_INTR_EIC_ID); + + // Call the TinyUSB interrupt handler + tuh_int_handler(1, true); +} + +// API to enable/disable MAX3421 INTR pin interrupt +void tuh_max3421_int_api(uint8_t rhport, bool enabled) { + (void) rhport; + + if (enabled) { + NVIC_EnableIRQ(EIC_IRQn); + } else { + NVIC_DisableIRQ(EIC_IRQn); + } +} + +// API to control MAX3421 SPI CS +void tuh_max3421_spi_cs_api(uint8_t rhport, bool active) { + (void) rhport; + gpio_set_pin_level(MAX3421_CS_PIN, active ? 0 : 1); +} + +// API to transfer data with MAX3421 SPI +// Either tx_buf or rx_buf can be NULL, which means transfer is write or read only +bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const* tx_buf, uint8_t* rx_buf, size_t xfer_bytes) { + (void) rhport; + + Sercom* sercom = MAX3421_SERCOM; + + for (size_t count = 0; count < xfer_bytes; count++) { + // Wait for the transmit buffer to be empty + while (!sercom->SPI.INTFLAG.bit.DRE); + + // Write data to be transmitted + uint8_t data = 0x00; + if (tx_buf) { + data = tx_buf[count]; + } + + sercom->SPI.DATA.reg = (uint32_t) data; + + // Wait for the receive buffer to be filled + while (!sercom->SPI.INTFLAG.bit.RXC); + + // Read received data + data = (uint8_t) sercom->SPI.DATA.reg; + if (rx_buf) { + rx_buf[count] = data; + } + } + + // wait for bus idle and clear flags + while (!(sercom->SPI.INTFLAG.reg & (SERCOM_SPI_INTFLAG_TXC | SERCOM_SPI_INTFLAG_DRE))); + sercom->SPI.INTFLAG.reg = SERCOM_SPI_INTFLAG_TXC | SERCOM_SPI_INTFLAG_DRE; + + return true; +} + +#endif + +// Stub for libc init array (required by SAML21/SAML22) +#ifdef SAML2X_FAMILY +void _init(void); +void _init(void) { +} +#endif diff --git a/hw/bsp/samd2x_l2x/family.cmake b/hw/bsp/samd2x_l2x/family.cmake new file mode 100644 index 000000000..9f1b20800 --- /dev/null +++ b/hw/bsp/samd2x_l2x/family.cmake @@ -0,0 +1,164 @@ +include_guard() + +# include board specific +include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) + +# Determine which SAM family based on board configuration +# SAM_FAMILY should be set by board.cmake (samd21, saml21, or saml22) +if(NOT DEFINED SAM_FAMILY) + # Default to samd21 if not specified for backward compatibility + set(SAM_FAMILY samd21) +endif() + +set(SDK_DIR ${TOP}/hw/mcu/microchip/${SAM_FAMILY}) +set(CMSIS_5 ${TOP}/lib/CMSIS_5) + +# toolchain set up +set(CMAKE_SYSTEM_CPU cortex-m0plus CACHE INTERNAL "System Processor") +set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake) + +set(FAMILY_MCUS SAMD21 SAML2X CACHE INTERNAL "") +set(OPENOCD_OPTION "-f interface/cmsis-dap.cfg -c \"transport select swd\" -f target/at91samdXX.cfg") + +#------------------------------------ +# BOARD_TARGET +#------------------------------------ +# only need to be built ONCE for all examples +function(add_board_target BOARD_TARGET) + if (TARGET ${BOARD_TARGET}) + return() + endif () + + set(LD_FILE_Clang ${LD_FILE_GNU}) + if (NOT DEFINED LD_FILE_${CMAKE_C_COMPILER_ID}) + message(FATAL_ERROR "LD_FILE_${CMAKE_C_COMPILER_ID} not defined") + endif () + + set(STARTUP_FILE_GNU ${SDK_DIR}/gcc/gcc/startup_${SAM_FAMILY}.c) + set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) + + # Common sources for all SAM families + set(COMMON_SOURCES + ${SDK_DIR}/gcc/system_${SAM_FAMILY}.c + ${SDK_DIR}/hal/src/hal_atomic.c + ${SDK_DIR}/hpl/gclk/hpl_gclk.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} + ) + + # Family-specific sources + if(SAM_FAMILY STREQUAL "samd21") + list(APPEND COMMON_SOURCES + ${SDK_DIR}/hpl/pm/hpl_pm.c + ${SDK_DIR}/hpl/sysctrl/hpl_sysctrl.c + ) + else() + # SAML21/SAML22 + list(APPEND COMMON_SOURCES + ${SDK_DIR}/hpl/mclk/hpl_mclk.c + ${SDK_DIR}/hpl/osc32kctrl/hpl_osc32kctrl.c + ${SDK_DIR}/hpl/oscctrl/hpl_oscctrl.c + ${SDK_DIR}/hpl/pm/hpl_pm.c + ) + endif() + + add_library(${BOARD_TARGET} STATIC ${COMMON_SOURCES}) + + target_include_directories(${BOARD_TARGET} PUBLIC + ${SDK_DIR} + ${SDK_DIR}/config + ${SDK_DIR}/include + ${SDK_DIR}/hal/include + ${SDK_DIR}/hal/utils/include + ${SDK_DIR}/hpl/pm + ${SDK_DIR}/hpl/port + ${SDK_DIR}/hri + ${CMSIS_5}/CMSIS/Core/Include + ) + + # Family-specific compile definitions + if(SAM_FAMILY STREQUAL "samd21") + target_compile_definitions(${BOARD_TARGET} PUBLIC + CONF_DFLL_OVERWRITE_CALIBRATION=0 + ) + else() + # SAML21/SAML22 + target_compile_definitions(${BOARD_TARGET} PUBLIC + CONF_OSC32K_CALIB_ENABLE=0 + CFG_EXAMPLE_VIDEO_READONLY + ) + endif() + + 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} + ) + + # Determine MCU option based on SAM_FAMILY + if(SAM_FAMILY STREQUAL "samd21") + set(MCU_OPTION OPT_MCU_SAMD21) + elseif(SAM_FAMILY STREQUAL "saml21") + set(MCU_OPTION OPT_MCU_SAML21) + elseif(SAM_FAMILY STREQUAL "saml22") + set(MCU_OPTION OPT_MCU_SAML22) + else() + message(FATAL_ERROR "Unknown SAM_FAMILY: ${SAM_FAMILY}") + endif() + + # Add TinyUSB target and port source + family_add_tinyusb(${TARGET} ${MCU_OPTION}) + target_sources(${TARGET} PUBLIC + ${TOP}/src/portable/microchip/samd/dcd_samd.c + ) + + # Add HCD support for SAMD21 (has host capability) + if(SAM_FAMILY STREQUAL "samd21") + target_sources(${TARGET} PUBLIC + ${TOP}/src/portable/microchip/samd/hcd_samd.c + ) + endif() + + target_link_libraries(${TARGET} PUBLIC board_${BOARD}) + + # Flashing + family_add_bin_hex(${TARGET}) + family_flash_jlink(${TARGET}) + #family_flash_openocd(${TARGET}) +endfunction() diff --git a/hw/bsp/samd2x_l2x/family.mk b/hw/bsp/samd2x_l2x/family.mk new file mode 100644 index 000000000..dca440ddd --- /dev/null +++ b/hw/bsp/samd2x_l2x/family.mk @@ -0,0 +1,92 @@ +UF2_FAMILY_ID = 0x68ed2b88 + +include $(TOP)/$(BOARD_PATH)/board.mk + +# SAM_FAMILY should be set by board.mk (samd21, saml21, or saml22) +ifeq ($(SAM_FAMILY),) + # Default to samd21 if not specified for backward compatibility + SAM_FAMILY = samd21 +endif + +SDK_DIR = hw/mcu/microchip/$(SAM_FAMILY) +CPU_CORE ?= cortex-m0plus + +# Common CFLAGS +CFLAGS += \ + -flto \ + +# Family-specific CFLAGS +ifeq ($(SAM_FAMILY),samd21) + CFLAGS += \ + -DCONF_DFLL_OVERWRITE_CALIBRATION=0 \ + -DCFG_TUSB_MCU=OPT_MCU_SAMD21 +else + # SAML21/SAML22 + CFLAGS += \ + -DCONF_OSC32K_CALIB_ENABLE=0 \ + -DCFG_EXAMPLE_VIDEO_READONLY \ + + ifeq ($(SAM_FAMILY),saml21) + CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_SAML21 + else ifeq ($(SAM_FAMILY),saml22) + CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_SAML22 + endif +endif + +# suppress warning caused by vendor mcu driver +CFLAGS += -Wno-error=redundant-decls + +# SAM driver is flooded with -Wcast-qual which slow down complication significantly +CFLAGS_SKIP += -Wcast-qual + +LDFLAGS_GCC += \ + -nostdlib -nostartfiles \ + --specs=nosys.specs --specs=nano.specs \ + +LDFLAGS_CLANG += + +# Common source files +SRC_C += \ + src/portable/microchip/samd/dcd_samd.c \ + ${SDK_DIR}/gcc/gcc/startup_$(SAM_FAMILY).c \ + ${SDK_DIR}/gcc/system_$(SAM_FAMILY).c \ + ${SDK_DIR}/hal/src/hal_atomic.c \ + ${SDK_DIR}/hpl/gclk/hpl_gclk.c \ + +# Family-specific source files +ifeq ($(SAM_FAMILY),samd21) + SRC_C += \ + src/portable/microchip/samd/hcd_samd.c \ + ${SDK_DIR}/hpl/pm/hpl_pm.c \ + ${SDK_DIR}/hpl/sysctrl/hpl_sysctrl.c \ + +else + # SAML21/SAML22 + SRC_C += \ + ${SDK_DIR}/hpl/mclk/hpl_mclk.c \ + ${SDK_DIR}/hpl/osc32kctrl/hpl_osc32kctrl.c \ + ${SDK_DIR}/hpl/oscctrl/hpl_oscctrl.c \ + ${SDK_DIR}/hpl/pm/hpl_pm.c \ + +endif + +INC += \ + $(TOP)/$(BOARD_PATH) \ + $(TOP)/${SDK_DIR} \ + $(TOP)/${SDK_DIR}/config \ + $(TOP)/${SDK_DIR}/include \ + $(TOP)/${SDK_DIR}/hal/include \ + $(TOP)/${SDK_DIR}/hal/utils/include \ + $(TOP)/${SDK_DIR}/hpl/pm/ \ + $(TOP)/${SDK_DIR}/hpl/port \ + $(TOP)/${SDK_DIR}/hri \ + $(TOP)/lib/CMSIS_5/CMSIS/Core/Include \ + +# flash using bossac at least version 1.8 +# can be found in arduino15/packages/arduino/tools/bossac/ +# Add it to your PATH or change BOSSAC variable to match your installation +BOSSAC = bossac + +flash-bossac: $(BUILD)/$(PROJECT).bin + @:$(call check_defined, SERIAL, example: SERIAL=/dev/ttyACM0) + $(BOSSAC) --port=$(SERIAL) -U -i --offset=0x2000 -e -w $^ -R diff --git a/hw/bsp/saml2x/FreeRTOSConfig/FreeRTOSConfig.h b/hw/bsp/saml2x/FreeRTOSConfig/FreeRTOSConfig.h deleted file mode 100644 index 6c9ecae2d..000000000 --- a/hw/bsp/saml2x/FreeRTOSConfig/FreeRTOSConfig.h +++ /dev/null @@ -1,153 +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 "sam.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 2 - -/* The lowest interrupt priority that can be used in a call to a "set priority" function. */ -#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1< rom - - /* .ARM.exidx is sorted, so has to go in its own output section. */ - PROVIDE_HIDDEN (__exidx_start = .); - .ARM.exidx : - { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - } > rom - PROVIDE_HIDDEN (__exidx_end = .); - - . = ALIGN(4); - _etext = .; - - .relocate : AT (_etext) - { - . = ALIGN(4); - _srelocate = .; - *(.ramfunc .ramfunc.*); - *(.data .data.*); - . = ALIGN(4); - _erelocate = .; - } > ram - - .lpram (NOLOAD): - { - . = ALIGN(8); - _slpram = .; - *(.lpram .lpram.*); - . = ALIGN(8); - _elpram = .; - } > lpram - - /* .bss section which is used for uninitialized data */ - .bss (NOLOAD) : - { - . = ALIGN(4); - _sbss = . ; - _szero = .; - *(.bss .bss.*) - *(COMMON) - . = ALIGN(4); - _ebss = . ; - _ezero = .; - end = .; - } > ram - - /* stack section */ - .stack (NOLOAD): - { - . = ALIGN(8); - _sstack = .; - . = . + STACK_SIZE; - . = ALIGN(8); - _estack = .; - } > ram - - . = ALIGN(4); - _end = . ; -} diff --git a/hw/bsp/saml2x/boards/saml22_feather/board.cmake b/hw/bsp/saml2x/boards/saml22_feather/board.cmake deleted file mode 100644 index 7fd79d2ce..000000000 --- a/hw/bsp/saml2x/boards/saml22_feather/board.cmake +++ /dev/null @@ -1,9 +0,0 @@ -set(SAM_FAMILY saml22) -set(JLINK_DEVICE ATSAML22J18) -set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/${BOARD}.ld) - -function(update_board TARGET) - target_compile_definitions(${TARGET} PUBLIC - __SAML22J18A__ - ) -endfunction() diff --git a/hw/bsp/saml2x/boards/saml22_feather/board.h b/hw/bsp/saml2x/boards/saml22_feather/board.h deleted file mode 100644 index f8660c3f8..000000000 --- a/hw/bsp/saml2x/boards/saml22_feather/board.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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: SAML22 Feather - url: https://github.com/joeycastillo/Feather-Projects/tree/main/SAML22%20Feather -*/ - -#ifndef BOARD_H_ -#define BOARD_H_ - -#ifdef __cplusplus - extern "C" { -#endif - -// LED -#define LED_PIN PIN_PA08 -#define LED_STATE_ON 1 - -// Button -#define BUTTON_PIN PIN_PA06 -#define BUTTON_STATE_ACTIVE 0 - - -#ifdef __cplusplus - } -#endif - -#endif /* BOARD_H_ */ diff --git a/hw/bsp/saml2x/boards/saml22_feather/board.mk b/hw/bsp/saml2x/boards/saml22_feather/board.mk deleted file mode 100644 index c7817ff70..000000000 --- a/hw/bsp/saml2x/boards/saml22_feather/board.mk +++ /dev/null @@ -1,11 +0,0 @@ -SAM_FAMILY = saml22 - -CFLAGS += -D__SAML22J18A__ - -# All source paths should be relative to the top level. -LD_FILE = $(BOARD_PATH)/$(BOARD).ld - -# For flash-jlink target -JLINK_DEVICE = ATSAML22J18 - -flash: flash-bossac diff --git a/hw/bsp/saml2x/boards/saml22_feather/saml22_feather.ld b/hw/bsp/saml2x/boards/saml22_feather/saml22_feather.ld deleted file mode 100644 index a04305be7..000000000 --- a/hw/bsp/saml2x/boards/saml22_feather/saml22_feather.ld +++ /dev/null @@ -1,146 +0,0 @@ -/** - * \file - * - * \brief Linker script for running in internal FLASH on the SAML22J18A - * - * Copyright (c) 2018 Microchip Technology Inc. - * - * \asf_license_start - * - * \page License - * - * 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 Licence 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. - * - * \asf_license_stop - * - */ - - -OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") -OUTPUT_ARCH(arm) -SEARCH_DIR(.) - -ENTRY(Reset_Handler) - -/* Memory Spaces Definitions */ -MEMORY -{ - rom (rx) : ORIGIN = 0x00000000, LENGTH = 0x00040000 - ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000 -} - -/* The stack size used by the application. NOTE: you need to adjust according to your application. */ -STACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x2000; - -/* Section Definitions */ -SECTIONS -{ - .text : - { - . = ALIGN(4); - _sfixed = .; - KEEP(*(.vectors .vectors.*)) - *(.text .text.* .gnu.linkonce.t.*) - *(.glue_7t) *(.glue_7) - *(.rodata .rodata* .gnu.linkonce.r.*) - *(.ARM.extab* .gnu.linkonce.armextab.*) - - /* Support C constructors, and C destructors in both user code - and the C library. This also provides support for C++ code. */ - . = ALIGN(4); - KEEP(*(.init)) - . = ALIGN(4); - __preinit_array_start = .; - KEEP (*(.preinit_array)) - __preinit_array_end = .; - - . = ALIGN(4); - __init_array_start = .; - KEEP (*(SORT(.init_array.*))) - KEEP (*(.init_array)) - __init_array_end = .; - - . = ALIGN(4); - KEEP (*crtbegin.o(.ctors)) - KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) - KEEP (*(SORT(.ctors.*))) - KEEP (*crtend.o(.ctors)) - - . = ALIGN(4); - KEEP(*(.fini)) - - . = ALIGN(4); - __fini_array_start = .; - KEEP (*(.fini_array)) - KEEP (*(SORT(.fini_array.*))) - __fini_array_end = .; - - KEEP (*crtbegin.o(.dtors)) - KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) - KEEP (*(SORT(.dtors.*))) - KEEP (*crtend.o(.dtors)) - - . = ALIGN(4); - _efixed = .; /* End of text section */ - } > rom - - /* .ARM.exidx is sorted, so has to go in its own output section. */ - PROVIDE_HIDDEN (__exidx_start = .); - .ARM.exidx : - { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - } > rom - PROVIDE_HIDDEN (__exidx_end = .); - - . = ALIGN(4); - _etext = .; - - .relocate : AT (_etext) - { - . = ALIGN(4); - _srelocate = .; - *(.ramfunc .ramfunc.*); - *(.data .data.*); - . = ALIGN(4); - _erelocate = .; - } > ram - - /* .bss section which is used for uninitialized data */ - .bss (NOLOAD) : - { - . = ALIGN(4); - _sbss = . ; - _szero = .; - *(.bss .bss.*) - *(COMMON) - . = ALIGN(4); - _ebss = . ; - _ezero = .; - end = .; - } > ram - - /* stack section */ - .stack (NOLOAD): - { - . = ALIGN(8); - _sstack = .; - . = . + STACK_SIZE; - . = ALIGN(8); - _estack = .; - } > ram - - . = ALIGN(4); - _end = . ; -} diff --git a/hw/bsp/saml2x/boards/sensorwatch_m0/board.cmake b/hw/bsp/saml2x/boards/sensorwatch_m0/board.cmake deleted file mode 100644 index 67d26475f..000000000 --- a/hw/bsp/saml2x/boards/sensorwatch_m0/board.cmake +++ /dev/null @@ -1,9 +0,0 @@ -set(SAM_FAMILY saml22) -set(JLINK_DEVICE ATSAML21J18) -set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/${BOARD}.ld) - -function(update_board TARGET) - target_compile_definitions(${TARGET} PUBLIC - __SAML22J18A__ - ) -endfunction() diff --git a/hw/bsp/saml2x/boards/sensorwatch_m0/board.h b/hw/bsp/saml2x/boards/sensorwatch_m0/board.h deleted file mode 100644 index 502c799db..000000000 --- a/hw/bsp/saml2x/boards/sensorwatch_m0/board.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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: SensorWatch - url: https://github.com/joeycastillo/Sensor-Watch -*/ - -#ifndef BOARD_H_ -#define BOARD_H_ - -#ifdef __cplusplus - extern "C" { -#endif - -// LED -#define LED_PIN PIN_PA21 -#define LED_STATE_ON 1 - -// Button -#define BUTTON_PIN PIN_PA22 -#define BUTTON_STATE_ACTIVE 1 - - -#ifdef __cplusplus - } -#endif - -#endif /* BOARD_H_ */ diff --git a/hw/bsp/saml2x/boards/sensorwatch_m0/board.mk b/hw/bsp/saml2x/boards/sensorwatch_m0/board.mk deleted file mode 100644 index c7817ff70..000000000 --- a/hw/bsp/saml2x/boards/sensorwatch_m0/board.mk +++ /dev/null @@ -1,11 +0,0 @@ -SAM_FAMILY = saml22 - -CFLAGS += -D__SAML22J18A__ - -# All source paths should be relative to the top level. -LD_FILE = $(BOARD_PATH)/$(BOARD).ld - -# For flash-jlink target -JLINK_DEVICE = ATSAML22J18 - -flash: flash-bossac diff --git a/hw/bsp/saml2x/boards/sensorwatch_m0/sensorwatch_m0.ld b/hw/bsp/saml2x/boards/sensorwatch_m0/sensorwatch_m0.ld deleted file mode 100644 index a04305be7..000000000 --- a/hw/bsp/saml2x/boards/sensorwatch_m0/sensorwatch_m0.ld +++ /dev/null @@ -1,146 +0,0 @@ -/** - * \file - * - * \brief Linker script for running in internal FLASH on the SAML22J18A - * - * Copyright (c) 2018 Microchip Technology Inc. - * - * \asf_license_start - * - * \page License - * - * 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 Licence 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. - * - * \asf_license_stop - * - */ - - -OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") -OUTPUT_ARCH(arm) -SEARCH_DIR(.) - -ENTRY(Reset_Handler) - -/* Memory Spaces Definitions */ -MEMORY -{ - rom (rx) : ORIGIN = 0x00000000, LENGTH = 0x00040000 - ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000 -} - -/* The stack size used by the application. NOTE: you need to adjust according to your application. */ -STACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x2000; - -/* Section Definitions */ -SECTIONS -{ - .text : - { - . = ALIGN(4); - _sfixed = .; - KEEP(*(.vectors .vectors.*)) - *(.text .text.* .gnu.linkonce.t.*) - *(.glue_7t) *(.glue_7) - *(.rodata .rodata* .gnu.linkonce.r.*) - *(.ARM.extab* .gnu.linkonce.armextab.*) - - /* Support C constructors, and C destructors in both user code - and the C library. This also provides support for C++ code. */ - . = ALIGN(4); - KEEP(*(.init)) - . = ALIGN(4); - __preinit_array_start = .; - KEEP (*(.preinit_array)) - __preinit_array_end = .; - - . = ALIGN(4); - __init_array_start = .; - KEEP (*(SORT(.init_array.*))) - KEEP (*(.init_array)) - __init_array_end = .; - - . = ALIGN(4); - KEEP (*crtbegin.o(.ctors)) - KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) - KEEP (*(SORT(.ctors.*))) - KEEP (*crtend.o(.ctors)) - - . = ALIGN(4); - KEEP(*(.fini)) - - . = ALIGN(4); - __fini_array_start = .; - KEEP (*(.fini_array)) - KEEP (*(SORT(.fini_array.*))) - __fini_array_end = .; - - KEEP (*crtbegin.o(.dtors)) - KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) - KEEP (*(SORT(.dtors.*))) - KEEP (*crtend.o(.dtors)) - - . = ALIGN(4); - _efixed = .; /* End of text section */ - } > rom - - /* .ARM.exidx is sorted, so has to go in its own output section. */ - PROVIDE_HIDDEN (__exidx_start = .); - .ARM.exidx : - { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - } > rom - PROVIDE_HIDDEN (__exidx_end = .); - - . = ALIGN(4); - _etext = .; - - .relocate : AT (_etext) - { - . = ALIGN(4); - _srelocate = .; - *(.ramfunc .ramfunc.*); - *(.data .data.*); - . = ALIGN(4); - _erelocate = .; - } > ram - - /* .bss section which is used for uninitialized data */ - .bss (NOLOAD) : - { - . = ALIGN(4); - _sbss = . ; - _szero = .; - *(.bss .bss.*) - *(COMMON) - . = ALIGN(4); - _ebss = . ; - _ezero = .; - end = .; - } > ram - - /* stack section */ - .stack (NOLOAD): - { - . = ALIGN(8); - _sstack = .; - . = . + STACK_SIZE; - . = ALIGN(8); - _estack = .; - } > ram - - . = ALIGN(4); - _end = . ; -} diff --git a/hw/bsp/saml2x/family.c b/hw/bsp/saml2x/family.c deleted file mode 100644 index 275dbbd2e..000000000 --- a/hw/bsp/saml2x/family.c +++ /dev/null @@ -1,173 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 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: - manufacturer: Microchip -*/ - -#include "sam.h" - -// Suppress warning caused by mcu driver -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wcast-qual" -#endif - -#include "hal/include/hal_gpio.h" -#include "hal/include/hal_init.h" -#include "hpl/gclk/hpl_gclk_base.h" -#include "hpl_mclk_config.h" - -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif - -#include "bsp/board_api.h" -#include "board.h" - -//--------------------------------------------------------------------+ -// Forward USB interrupt events to TinyUSB IRQ Handler -//--------------------------------------------------------------------+ -void USB_Handler(void) { - tud_int_handler(0); -} - -//--------------------------------------------------------------------+ -// MACRO TYPEDEF CONSTANT ENUM DECLARATION -//--------------------------------------------------------------------+ - -/* Referenced GCLKs (out of 0~4), should be initialized firstly */ -#define _GCLK_INIT_1ST 0x00000000 -/* Not referenced GCLKs, initialized last */ -#define _GCLK_INIT_LAST 0x0000001F - -void board_init(void) { - // Clock init ( follow hpl_init.c ) - hri_nvmctrl_set_CTRLB_RWS_bf(NVMCTRL, CONF_NVM_WAIT_STATE); - - _set_performance_level(2); - - _osc32kctrl_init_sources(); - _oscctrl_init_sources(); - _mclk_init(); -#if _GCLK_INIT_1ST - _gclk_init_generators_by_fref(_GCLK_INIT_1ST); -#endif - _oscctrl_init_referenced_generators(); - _gclk_init_generators_by_fref(_GCLK_INIT_LAST); - -#if (CONF_PORT_EVCTRL_PORT_0 | CONF_PORT_EVCTRL_PORT_1 | CONF_PORT_EVCTRL_PORT_2 | CONF_PORT_EVCTRL_PORT_3) - hri_port_set_EVCTRL_reg(PORT, 0, CONF_PORTA_EVCTRL); - hri_port_set_EVCTRL_reg(PORT, 1, CONF_PORTB_EVCTRL); -#endif - - // Update SystemCoreClock since it is hard coded with asf4 and not correct - // Init 1ms tick timer (samd SystemCoreClock may not correct) - SystemCoreClock = CONF_CPU_FREQUENCY; - SysTick_Config(CONF_CPU_FREQUENCY / 1000); - - // Led init - gpio_set_pin_direction(LED_PIN, GPIO_DIRECTION_OUT); - gpio_set_pin_level(LED_PIN, !LED_STATE_ON); - - // Button init - gpio_set_pin_direction(BUTTON_PIN, GPIO_DIRECTION_IN); - gpio_set_pin_pull_mode(BUTTON_PIN, BUTTON_STATE_ACTIVE ? GPIO_PULL_DOWN : GPIO_PULL_UP); - -#if 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 - - /* USB Clock init - * The USB module requires a GCLK_USB of 48 MHz ~ 0.25% clock - * for low speed and full speed operation. */ - hri_gclk_write_PCHCTRL_reg(GCLK, USB_GCLK_ID, GCLK_PCHCTRL_GEN_GCLK1_Val | GCLK_PCHCTRL_CHEN); - hri_mclk_set_AHBMASK_USB_bit(MCLK); - hri_mclk_set_APBBMASK_USB_bit(MCLK); - - // USB Pin Init - gpio_set_pin_direction(PIN_PA24, GPIO_DIRECTION_OUT); - gpio_set_pin_level(PIN_PA24, false); - gpio_set_pin_pull_mode(PIN_PA24, GPIO_PULL_OFF); - gpio_set_pin_direction(PIN_PA25, GPIO_DIRECTION_OUT); - gpio_set_pin_level(PIN_PA25, false); - gpio_set_pin_pull_mode(PIN_PA25, GPIO_PULL_OFF); - - gpio_set_pin_function(PIN_PA24, PINMUX_PA24G_USB_DM); - gpio_set_pin_function(PIN_PA25, PINMUX_PA25G_USB_DP); - - // Output 500hz PWM on PB23 (TCC0 WO[3]) so we can validate the GCLK1 clock speed -// hri_mclk_set_APBCMASK_TCC0_bit(MCLK); -// TCC0->PER.bit.PER = 48000000 / 1000; -// TCC0->CC[3].bit.CC = 48000000 / 2000; -// TCC0->CTRLA.bit.ENABLE = true; -// -// gpio_set_pin_function(PIN_PB23, PINMUX_PB23F_TCC0_WO3); -// hri_gclk_write_PCHCTRL_reg(GCLK, TCC0_GCLK_ID, GCLK_PCHCTRL_GEN_GCLK1_Val | GCLK_PCHCTRL_CHEN); -} - -//--------------------------------------------------------------------+ -// Board porting API -//--------------------------------------------------------------------+ - -void board_led_write(bool state) { - gpio_set_pin_level(LED_PIN, state); -} - -uint32_t board_button_read(void) { - // button is active low - return gpio_get_pin_level(BUTTON_PIN) ? 0 : 1; -} - -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) buf; - (void) len; - return 0; -} - -#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 _init(void); -void _init(void) { - -} diff --git a/hw/bsp/saml2x/family.cmake b/hw/bsp/saml2x/family.cmake deleted file mode 100644 index 49f2e3e75..000000000 --- a/hw/bsp/saml2x/family.cmake +++ /dev/null @@ -1,115 +0,0 @@ -include_guard() - -# include board specific -include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) - -set(SDK_DIR ${TOP}/hw/mcu/microchip/${SAM_FAMILY}) -set(CMSIS_5 ${TOP}/lib/CMSIS_5) - -# toolchain set up -set(CMAKE_SYSTEM_CPU cortex-m0plus CACHE INTERNAL "System Processor") -set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake) - -set(FAMILY_MCUS SAML21 SAML22 CACHE INTERNAL "") -set(OPENOCD_OPTION "-f interface/cmsis-dap.cfg -c \"transport select swd\" -f target/at91samdXX.cfg") - -#------------------------------------ -# BOARD_TARGET -#------------------------------------ -# only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif () - - set(LD_FILE_Clang ${LD_FILE_GNU}) - if (NOT DEFINED LD_FILE_${CMAKE_C_COMPILER_ID}) - message(FATAL_ERROR "LD_FILE_${CMAKE_C_COMPILER_ID} not defined") - endif () - - set(STARTUP_FILE_GNU ${SDK_DIR}/gcc/gcc/startup_${SAM_FAMILY}.c) - set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) - - add_library(${BOARD_TARGET} STATIC - ${SDK_DIR}/gcc/system_${SAM_FAMILY}.c - ${SDK_DIR}/hal/src/hal_atomic.c - ${SDK_DIR}/hpl/gclk/hpl_gclk.c - ${SDK_DIR}/hpl/mclk/hpl_mclk.c - ${SDK_DIR}/hpl/osc32kctrl/hpl_osc32kctrl.c - ${SDK_DIR}/hpl/oscctrl/hpl_oscctrl.c - ${SDK_DIR}/hpl/pm/hpl_pm.c - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} - ) - target_include_directories(${BOARD_TARGET} PUBLIC - ${SDK_DIR} - ${SDK_DIR}/config - ${SDK_DIR}/include - ${SDK_DIR}/hal/include - ${SDK_DIR}/hal/utils/include - ${SDK_DIR}/hpl/pm - ${SDK_DIR}/hpl/port - ${SDK_DIR}/hri - ${CMSIS_5}/CMSIS/Core/Include - ) - target_compile_definitions(${BOARD_TARGET} PUBLIC - CONF_OSC32K_CALIB_ENABLE=0 - CFG_EXAMPLE_VIDEO_READONLY - ) - - 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_SAML22) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/microchip/samd/dcd_samd.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) - - - - # Flashing - family_add_bin_hex(${TARGET}) - family_flash_jlink(${TARGET}) - #family_flash_openocd(${TARGET}) -endfunction() diff --git a/hw/bsp/saml2x/family.mk b/hw/bsp/saml2x/family.mk deleted file mode 100644 index 65dfe5032..000000000 --- a/hw/bsp/saml2x/family.mk +++ /dev/null @@ -1,53 +0,0 @@ -UF2_FAMILY_ID = 0x68ed2b88 -SDK_DIR = hw/mcu/microchip/$(SAM_FAMILY) - -include $(TOP)/$(BOARD_PATH)/board.mk -CPU_CORE ?= cortex-m0plus - -CFLAGS += \ - -flto \ - -DCONF_OSC32K_CALIB_ENABLE=0 \ - -DCFG_TUSB_MCU=OPT_MCU_SAML22 \ - -DCFG_EXAMPLE_VIDEO_READONLY \ - -# suppress warning caused by vendor mcu driver -CFLAGS += -Wno-error=redundant-decls - -# SAM driver is flooded with -Wcast-qual which slow down complication significantly -CFLAGS_SKIP += -Wcast-qual - -LDFLAGS_GCC += \ - -nostdlib -nostartfiles \ - --specs=nosys.specs --specs=nano.specs \ - -SRC_C += \ - src/portable/microchip/samd/dcd_samd.c \ - $(SDK_DIR)/gcc/gcc/startup_$(SAM_FAMILY).c \ - $(SDK_DIR)/gcc/system_$(SAM_FAMILY).c \ - $(SDK_DIR)/hal/src/hal_atomic.c \ - $(SDK_DIR)/hpl/gclk/hpl_gclk.c \ - $(SDK_DIR)/hpl/mclk/hpl_mclk.c \ - $(SDK_DIR)/hpl/osc32kctrl/hpl_osc32kctrl.c \ - $(SDK_DIR)/hpl/oscctrl/hpl_oscctrl.c \ - $(SDK_DIR)/hpl/pm/hpl_pm.c \ - -INC += \ - $(TOP)/$(BOARD_PATH) \ - $(TOP)/${SDK_DIR} \ - $(TOP)/${SDK_DIR}/config \ - $(TOP)/${SDK_DIR}/include \ - $(TOP)/${SDK_DIR}/hal/include \ - $(TOP)/${SDK_DIR}/hal/utils/include \ - $(TOP)/${SDK_DIR}/hpl/pm/ \ - $(TOP)/${SDK_DIR}/hpl/port \ - $(TOP)/${SDK_DIR}/hri \ - $(TOP)/lib/CMSIS_5/CMSIS/Core/Include \ - -# flash using bossac at least version 1.8 -# can be found in arduino15/packages/arduino/tools/bossac/ -# Add it to your PATH or change BOSSAC variable to match your installation -BOSSAC = bossac - -flash-bossac: $(BUILD)/$(PROJECT).bin - @:$(call check_defined, SERIAL, example: SERIAL=/dev/ttyACM0) - $(BOSSAC) --port=$(SERIAL) -U -i --offset=0x2000 -e -w $^ -R diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index 1f8975e55..bb3ac4d76 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -146,8 +146,8 @@ //--------------------------------------------------------------------+ // Microchip //--------------------------------------------------------------------+ -#elif TU_CHECK_MCU(OPT_MCU_SAMD21, OPT_MCU_SAMD51, OPT_MCU_SAME5X) || \ - TU_CHECK_MCU(OPT_MCU_SAMD11, OPT_MCU_SAML21, OPT_MCU_SAML22) +#elif TU_CHECK_MCU(OPT_MCU_SAMD11, OPT_MCU_SAML2X, OPT_MCU_SAMD21) || \ + TU_CHECK_MCU(OPT_MCU_SAMD51, OPT_MCU_SAME5X) #define TUP_DCD_ENDPOINT_MAX 8 #elif TU_CHECK_MCU(OPT_MCU_SAMG) diff --git a/src/portable/microchip/samd/dcd_samd.c b/src/portable/microchip/samd/dcd_samd.c index 357aa1549..e43439f2a 100644 --- a/src/portable/microchip/samd/dcd_samd.c +++ b/src/portable/microchip/samd/dcd_samd.c @@ -26,10 +26,7 @@ #include "tusb_option.h" -#if CFG_TUD_ENABLED && \ - (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) +#if CFG_TUD_ENABLED && TU_CHECK_MCU(OPT_MCU_SAMD11, OPT_MCU_SAMD21, OPT_MCU_SAML2X, OPT_MCU_SAMD51, OPT_MCU_SAME5X) #include "sam.h" #include "device/dcd.h" @@ -106,10 +103,8 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { return true; } -#if CFG_TUSB_MCU == OPT_MCU_SAMD51 || CFG_TUSB_MCU == OPT_MCU_SAME5X - -void dcd_int_enable(uint8_t rhport) -{ +#if TU_CHECK_MCU(OPT_MCU_SAMD51, OPT_MCU_SAME5X) +void dcd_int_enable(uint8_t rhport) { (void) rhport; NVIC_EnableIRQ(USB_0_IRQn); NVIC_EnableIRQ(USB_1_IRQn); @@ -117,8 +112,7 @@ void dcd_int_enable(uint8_t rhport) NVIC_EnableIRQ(USB_3_IRQn); } -void dcd_int_disable(uint8_t rhport) -{ +void dcd_int_disable(uint8_t rhport) { (void) rhport; NVIC_DisableIRQ(USB_3_IRQn); NVIC_DisableIRQ(USB_2_IRQn); @@ -126,17 +120,13 @@ void dcd_int_disable(uint8_t rhport) 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 - -void dcd_int_enable(uint8_t rhport) -{ +#elif TU_CHECK_MCU(OPT_MCU_SAMD11, OPT_MCU_SAMD21, OPT_MCU_SAML2X) +void dcd_int_enable(uint8_t rhport) { (void) rhport; NVIC_EnableIRQ(USB_IRQn); } -void dcd_int_disable(uint8_t rhport) -{ +void dcd_int_disable(uint8_t rhport) { (void) rhport; NVIC_DisableIRQ(USB_IRQn); } diff --git a/src/portable/microchip/samd/hcd_samd.c b/src/portable/microchip/samd/hcd_samd.c index 1f4b2b233..0de7ddeb6 100644 --- a/src/portable/microchip/samd/hcd_samd.c +++ b/src/portable/microchip/samd/hcd_samd.c @@ -26,11 +26,8 @@ #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) +#if CFG_TUH_ENABLED && !(defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421) && \ + TU_CHECK_MCU(OPT_MCU_SAMD11, OPT_MCU_SAMD21, OPT_MCU_SAML2X, OPT_MCU_SAMD51, OPT_MCU_SAME5X) #include "host/hcd.h" #include "sam.h" @@ -428,7 +425,7 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { return true; } -#if CFG_TUSB_MCU == OPT_MCU_SAMD51 || CFG_TUSB_MCU == OPT_MCU_SAME5X +#if TU_CHECK_MCU(OPT_MCU_SAMD51, OPT_MCU_SAME5X) // Enable USB interrupt void hcd_int_enable(uint8_t rhport) @@ -450,8 +447,7 @@ void hcd_int_disable(uint8_t rhport) 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 +#elif TU_CHECK_MCU(OPT_MCU_SAMD11, OPT_MCU_SAMD21, OPT_MCU_SAML2X) // Enable USB interrupt void hcd_int_enable(uint8_t rhport) diff --git a/src/tusb_option.h b/src/tusb_option.h index dd57f6296..9d5aed252 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -71,8 +71,9 @@ #define OPT_MCU_SAMG 202 ///< MicroChip SAMDG series #define OPT_MCU_SAME5X 203 ///< MicroChip SAM E5x #define OPT_MCU_SAMD11 204 ///< MicroChip SAMD11 -#define OPT_MCU_SAML22 205 ///< MicroChip SAML22 -#define OPT_MCU_SAML21 206 ///< MicroChip SAML21 +#define OPT_MCU_SAML2X 205 ///< MicroChip SAML2x +#define OPT_MCU_SAML21 OPT_MCU_SAML2X ///< SAML21 backward compatibility +#define OPT_MCU_SAML22 OPT_MCU_SAML2X ///< SAML22 backward compatibility #define OPT_MCU_SAMX7X 207 ///< MicroChip SAME70, S70, V70, V71 family // STM32 -- cgit v1.3.1 From 4efb17130b96cb213cad79121397c7fb1b78c202 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 15 Oct 2025 09:33:23 +0700 Subject: fix unused warnings --- src/portable/synopsys/dwc2/hcd_dwc2.c | 1 - 1 file changed, 1 deletion(-) (limited to 'src/portable') diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index 257fa2833..e4ab16d9d 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -1131,7 +1131,6 @@ 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; -- cgit v1.3.1 From 0d690c8b801da36b0d06490648c1110da06edc19 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 15 Oct 2025 12:49:36 +0700 Subject: update nuc121/125 --- .../device/audio_4_channel_mic_freertos/skip.txt | 1 + examples/device/audio_test_freertos/skip.txt | 1 + examples/device/cdc_msc_freertos/skip.txt | 1 + hw/bsp/nuc121_125/FreeRTOSConfig/FreeRTOSConfig.h | 150 +++++++++++++++++++++ .../boards/nutiny_sdk_nuc121/board.cmake | 7 - .../nuc121_125/boards/nutiny_sdk_nuc121/board.mk | 11 -- .../nuc121_125/boards/nutiny_sdk_nuc125/board.mk | 5 - hw/bsp/nuc121_125/family.cmake | 14 +- hw/bsp/nuc121_125/family.mk | 11 +- src/common/tusb_mcu.h | 1 + src/portable/nuvoton/nuc121/dcd_nuc121.c | 16 ++- 11 files changed, 184 insertions(+), 34 deletions(-) create mode 100644 hw/bsp/nuc121_125/FreeRTOSConfig/FreeRTOSConfig.h (limited to 'src/portable') diff --git a/examples/device/audio_4_channel_mic_freertos/skip.txt b/examples/device/audio_4_channel_mic_freertos/skip.txt index 30cd46e7e..65925b32c 100644 --- a/examples/device/audio_4_channel_mic_freertos/skip.txt +++ b/examples/device/audio_4_channel_mic_freertos/skip.txt @@ -17,3 +17,4 @@ board:lpcxpresso11u37 board:lpcxpresso1347 family:broadcom_32bit family:broadcom_64bit +family:nuc121_125 diff --git a/examples/device/audio_test_freertos/skip.txt b/examples/device/audio_test_freertos/skip.txt index 1f3d4281a..c9cdacad7 100644 --- a/examples/device/audio_test_freertos/skip.txt +++ b/examples/device/audio_test_freertos/skip.txt @@ -15,3 +15,4 @@ mcu:RAXXX family:broadcom_32bit family:broadcom_64bit board:stm32l0538disco +family:nuc121_125 diff --git a/examples/device/cdc_msc_freertos/skip.txt b/examples/device/cdc_msc_freertos/skip.txt index b73a6d8dd..69fc883e6 100644 --- a/examples/device/cdc_msc_freertos/skip.txt +++ b/examples/device/cdc_msc_freertos/skip.txt @@ -15,3 +15,4 @@ mcu:RAXXX mcu:STM32L0 family:broadcom_32bit family:broadcom_64bit +family:nuc121_125 diff --git a/hw/bsp/nuc121_125/FreeRTOSConfig/FreeRTOSConfig.h b/hw/bsp/nuc121_125/FreeRTOSConfig/FreeRTOSConfig.h new file mode 100644 index 000000000..e8f120553 --- /dev/null +++ b/hw/bsp/nuc121_125/FreeRTOSConfig/FreeRTOSConfig.h @@ -0,0 +1,150 @@ +/* + * 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 "NuMicro.h" +#endif + +/* Cortex-M0 port configuration. */ +#define configENABLE_MPU 0 +#define configENABLE_FPU 0 +#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 +// NUC121/125 has 2 priority bits +#define configPRIO_BITS 2 + +/* The lowest interrupt priority that can be used in a call to a "set priority" function. */ +#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1<bEndpointAddress); cfg |= (TUSB_DIR_IN == dir) ? USBD_CFG_EPMODE_IN : USBD_CFG_EPMODE_OUT; - if (TUSB_XFER_ISOCHRONOUS == type) + if (TUSB_XFER_ISOCHRONOUS == type) { cfg |= USBD_CFG_TYPE_ISO; + } ep->CFG = cfg; /* make a note of the endpoint size */ @@ -303,6 +304,19 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) return true; } +bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { + (void) rhport; + (void) ep_addr; + (void) largest_packet_size; + return false; // TODO not implemented yet +} + +bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) { + (void) rhport; + (void) desc_ep; + return false; // TODO not implemented yet +} + void dcd_edpt_close_all (uint8_t rhport) { (void) rhport; -- cgit v1.3.1 From 8199ed6fd0329e63c45352816973a6632d635c69 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 15 Oct 2025 13:37:21 +0700 Subject: refactor all nuc to family --- examples/device/net_lwip_webserver/skip.txt | 1 + hw/bsp/board.c | 2 +- hw/bsp/nuc100_120/FreeRTOSConfig/FreeRTOSConfig.h | 150 ++++++++++++++++ .../boards/nutiny_sdk_nuc120/board.cmake | 7 + hw/bsp/nuc100_120/boards/nutiny_sdk_nuc120/board.h | 43 +++++ .../nuc100_120/boards/nutiny_sdk_nuc120/board.mk | 2 + .../boards/nutiny_sdk_nuc120/nuc120_flash.ld | 195 ++++++++++++++++++++ hw/bsp/nuc100_120/family.c | 127 +++++++++++++ hw/bsp/nuc100_120/family.cmake | 87 +++++++++ hw/bsp/nuc100_120/family.mk | 39 ++++ hw/bsp/nuc121_125/family.mk | 3 - hw/bsp/nuc126/FreeRTOSConfig/FreeRTOSConfig.h | 150 ++++++++++++++++ hw/bsp/nuc126/boards/nutiny_nuc126v/board.cmake | 7 + hw/bsp/nuc126/boards/nutiny_nuc126v/board.h | 46 +++++ hw/bsp/nuc126/boards/nutiny_nuc126v/board.mk | 2 + .../nuc126/boards/nutiny_nuc126v/nuc126_flash.ld | 195 ++++++++++++++++++++ hw/bsp/nuc126/family.c | 144 +++++++++++++++ hw/bsp/nuc126/family.cmake | 104 +++++++++++ hw/bsp/nuc126/family.mk | 48 +++++ hw/bsp/nuc505/FreeRTOSConfig/FreeRTOSConfig.h | 150 ++++++++++++++++ hw/bsp/nuc505/boards/nutiny_sdk_nuc505/board.cmake | 7 + hw/bsp/nuc505/boards/nutiny_sdk_nuc505/board.h | 42 +++++ hw/bsp/nuc505/boards/nutiny_sdk_nuc505/board.mk | 2 + .../boards/nutiny_sdk_nuc505/nuc505_flashtoram.ld | 199 +++++++++++++++++++++ hw/bsp/nuc505/family.c | 127 +++++++++++++ hw/bsp/nuc505/family.cmake | 91 ++++++++++ hw/bsp/nuc505/family.mk | 55 ++++++ hw/bsp/nutiny_nuc126v/board.mk | 48 ----- hw/bsp/nutiny_nuc126v/nuc126_flash.ld | 195 -------------------- hw/bsp/nutiny_nuc126v/nutiny_nuc126.c | 153 ---------------- hw/bsp/nutiny_sdk_nuc120/board.mk | 41 ----- hw/bsp/nutiny_sdk_nuc120/nuc120_flash.ld | 195 -------------------- hw/bsp/nutiny_sdk_nuc120/nutiny_sdk_nuc120.c | 133 -------------- hw/bsp/nutiny_sdk_nuc505/board.mk | 63 ------- hw/bsp/nutiny_sdk_nuc505/nuc505_flashtoram.ld | 199 --------------------- hw/bsp/nutiny_sdk_nuc505/nutiny_sdk_nuc505.c | 129 ------------- src/common/tusb_mcu.h | 2 + src/portable/nuvoton/nuc505/dcd_nuc505.c | 13 ++ 38 files changed, 2036 insertions(+), 1160 deletions(-) create mode 100644 hw/bsp/nuc100_120/FreeRTOSConfig/FreeRTOSConfig.h create mode 100644 hw/bsp/nuc100_120/boards/nutiny_sdk_nuc120/board.cmake create mode 100644 hw/bsp/nuc100_120/boards/nutiny_sdk_nuc120/board.h create mode 100644 hw/bsp/nuc100_120/boards/nutiny_sdk_nuc120/board.mk create mode 100644 hw/bsp/nuc100_120/boards/nutiny_sdk_nuc120/nuc120_flash.ld create mode 100644 hw/bsp/nuc100_120/family.c create mode 100644 hw/bsp/nuc100_120/family.cmake create mode 100644 hw/bsp/nuc100_120/family.mk create mode 100644 hw/bsp/nuc126/FreeRTOSConfig/FreeRTOSConfig.h create mode 100644 hw/bsp/nuc126/boards/nutiny_nuc126v/board.cmake create mode 100644 hw/bsp/nuc126/boards/nutiny_nuc126v/board.h create mode 100644 hw/bsp/nuc126/boards/nutiny_nuc126v/board.mk create mode 100644 hw/bsp/nuc126/boards/nutiny_nuc126v/nuc126_flash.ld create mode 100644 hw/bsp/nuc126/family.c create mode 100644 hw/bsp/nuc126/family.cmake create mode 100644 hw/bsp/nuc126/family.mk create mode 100644 hw/bsp/nuc505/FreeRTOSConfig/FreeRTOSConfig.h create mode 100644 hw/bsp/nuc505/boards/nutiny_sdk_nuc505/board.cmake create mode 100644 hw/bsp/nuc505/boards/nutiny_sdk_nuc505/board.h create mode 100644 hw/bsp/nuc505/boards/nutiny_sdk_nuc505/board.mk create mode 100644 hw/bsp/nuc505/boards/nutiny_sdk_nuc505/nuc505_flashtoram.ld create mode 100644 hw/bsp/nuc505/family.c create mode 100644 hw/bsp/nuc505/family.cmake create mode 100644 hw/bsp/nuc505/family.mk delete mode 100644 hw/bsp/nutiny_nuc126v/board.mk delete mode 100644 hw/bsp/nutiny_nuc126v/nuc126_flash.ld delete mode 100644 hw/bsp/nutiny_nuc126v/nutiny_nuc126.c delete mode 100644 hw/bsp/nutiny_sdk_nuc120/board.mk delete mode 100644 hw/bsp/nutiny_sdk_nuc120/nuc120_flash.ld delete mode 100644 hw/bsp/nutiny_sdk_nuc120/nutiny_sdk_nuc120.c delete mode 100644 hw/bsp/nutiny_sdk_nuc505/board.mk delete mode 100644 hw/bsp/nutiny_sdk_nuc505/nuc505_flashtoram.ld delete mode 100644 hw/bsp/nutiny_sdk_nuc505/nutiny_sdk_nuc505.c (limited to 'src/portable') diff --git a/examples/device/net_lwip_webserver/skip.txt b/examples/device/net_lwip_webserver/skip.txt index 6121f1f9d..1b5482a57 100644 --- a/examples/device/net_lwip_webserver/skip.txt +++ b/examples/device/net_lwip_webserver/skip.txt @@ -20,3 +20,4 @@ board:curiosity_nano board:frdm_kl25z # lpc55 has weird error 'ncm_interface' causes a section type conflict with 'ntb_parameters' family:lpc55 +family:nuc126 diff --git a/hw/bsp/board.c b/hw/bsp/board.c index 03d09c353..41e6eb1b8 100644 --- a/hw/bsp/board.c +++ b/hw/bsp/board.c @@ -31,7 +31,7 @@ #ifdef __ICCARM__ #define sys_write __write #define sys_read __read -#elif defined(__MSP430__) || defined(__RX__) || TU_CHECK_MCU(OPT_MCU_NUC121) +#elif defined(__MSP430__) || defined(__RX__) || TU_CHECK_MCU(OPT_MCU_NUC120, OPT_MCU_NUC121, OPT_MCU_NUC126, OPT_MCU_NUC505) #define sys_write write #define sys_read read #else diff --git a/hw/bsp/nuc100_120/FreeRTOSConfig/FreeRTOSConfig.h b/hw/bsp/nuc100_120/FreeRTOSConfig/FreeRTOSConfig.h new file mode 100644 index 000000000..e8f120553 --- /dev/null +++ b/hw/bsp/nuc100_120/FreeRTOSConfig/FreeRTOSConfig.h @@ -0,0 +1,150 @@ +/* + * 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 "NuMicro.h" +#endif + +/* Cortex-M0 port configuration. */ +#define configENABLE_MPU 0 +#define configENABLE_FPU 0 +#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 +// NUC121/125 has 2 priority bits +#define configPRIO_BITS 2 + +/* The lowest interrupt priority that can be used in a call to a "set priority" function. */ +#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1< FLASH + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > FLASH + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > FLASH + __exidx_end = .; + + /* To copy multiple ROM to RAM sections, + * uncomment .copy.table section and, + * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */ + /* + .copy.table : + { + . = ALIGN(4); + __copy_table_start__ = .; + LONG (__etext) + LONG (__data_start__) + LONG (__data_end__ - __data_start__) + LONG (__etext2) + LONG (__data2_start__) + LONG (__data2_end__ - __data2_start__) + __copy_table_end__ = .; + } > FLASH + */ + + /* To clear multiple BSS sections, + * uncomment .zero.table section and, + * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */ + /* + .zero.table : + { + . = ALIGN(4); + __zero_table_start__ = .; + LONG (__bss_start__) + LONG (__bss_end__ - __bss_start__) + LONG (__bss2_start__) + LONG (__bss2_end__ - __bss2_start__) + __zero_table_end__ = .; + } > FLASH + */ + + __etext = .; + + .data : AT (__etext) + { + __data_start__ = .; + *(vtable) + *(.data*) + + . = 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 = .); + + KEEP(*(.jcr*)) + . = ALIGN(4); + /* All data end */ + __data_end__ = .; + + } > RAM + + .bss : + { + . = ALIGN(4); + __bss_start__ = .; + *(.bss*) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + } > RAM + + .heap (COPY): + { + __HeapBase = .; + __end__ = .; + end = __end__; + KEEP(*(.heap*)) + __HeapLimit = .; + } > RAM + + /* .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): + { + KEEP(*(.stack*)) + } > RAM + + /* Set stack top to end of RAM, and stack limit move down by + * size of stack_dummy section */ + __StackTop = ORIGIN(RAM) + LENGTH(RAM); + __StackLimit = __StackTop - SIZEOF(.stack_dummy); + PROVIDE(__stack = __StackTop); + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") +} diff --git a/hw/bsp/nuc100_120/family.c b/hw/bsp/nuc100_120/family.c new file mode 100644 index 000000000..d04dc6657 --- /dev/null +++ b/hw/bsp/nuc100_120/family.c @@ -0,0 +1,127 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 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. + */ + +#include "bsp/board_api.h" +#include "board.h" + +#include "NUC100Series.h" +#include "clk.h" +#include "sys.h" + +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USBD_IRQHandler(void) +{ + tud_int_handler(0); +} + +void board_init(void) +{ + SYS_UnlockReg(); + + /* Enable Internal RC 22.1184 MHz clock */ + CLK_EnableXtalRC(CLK_PWRCON_OSC22M_EN_Msk); + + /* Waiting for Internal RC clock ready */ + CLK_WaitClockReady(CLK_CLKSTATUS_OSC22M_STB_Msk); + + /* Switch HCLK clock source to Internal RC and HCLK source divide 1 */ + CLK_SetHCLK(CLK_CLKSEL0_HCLK_S_HIRC, CLK_CLKDIV_HCLK(1)); + + /* Enable external XTAL 12 MHz clock */ + CLK_EnableXtalRC(CLK_PWRCON_XTL12M_EN_Msk); + + /* Waiting for external XTAL clock ready */ + CLK_WaitClockReady(CLK_CLKSTATUS_XTL12M_STB_Msk); + + /* Set core clock */ + CLK_SetCoreClock(48000000); + + /* Enable module clock */ + CLK_EnableModuleClock(USBD_MODULE); + + /* Select module clock source */ + CLK_SetModuleClock(USBD_MODULE, 0, CLK_CLKDIV_USB(1)); + + SYS_LockReg(); + +#if CFG_TUSB_OS == OPT_OS_NONE + // 1ms tick timer + SysTick_Config(48000000 / 1000); +#endif + + GPIO_SetMode(LED_PORT, 1UL << LED_PIN, GPIO_PMD_OUTPUT); +} + +#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 + +//--------------------------------------------------------------------+ +// Board porting API +//--------------------------------------------------------------------+ + +void board_led_write(bool state) +{ +#if 0 + /* this would be the simplest solution... *IF* the part supported the pin data interface */ + LED_PIN_IO = (state) ? LED_STATE_ON : (1-LED_STATE_ON); +#else + /* if the part's *PDIO pin data registers don't work, a more elaborate approach is needed */ + uint32_t irq_state = __get_PRIMASK(); + __disable_irq(); + uint32_t current = LED_PORT->DOUT & ~(1UL << LED_PIN); + LED_PORT->DOUT = current | (((state) ? LED_STATE_ON : (1UL-LED_STATE_ON)) << LED_PIN); + __set_PRIMASK(irq_state); +#endif +} + +uint32_t board_button_read(void) +{ + return 0; +} + +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) buf; (void) len; + return 0; +} diff --git a/hw/bsp/nuc100_120/family.cmake b/hw/bsp/nuc100_120/family.cmake new file mode 100644 index 000000000..06501b526 --- /dev/null +++ b/hw/bsp/nuc100_120/family.cmake @@ -0,0 +1,87 @@ +include_guard() + +include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) + +set(SDK_DIR ${TOP}/hw/mcu/nuvoton/nuc100_120) +set(CMSIS_5 ${TOP}/lib/CMSIS_5) + +set(CMAKE_SYSTEM_CPU cortex-m0 CACHE INTERNAL "System Processor") +set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake) +set(OPENOCD_OPTION "-f interface/nulink.cfg -f target/numicroM0.cfg") + +set(FAMILY_MCUS NUC100 NUC120 CACHE INTERNAL "") + +function(add_board_target BOARD_TARGET) + if (TARGET ${BOARD_TARGET}) + return() + endif () + + set(LD_FILE_Clang ${LD_FILE_GNU}) + if (NOT DEFINED LD_FILE_${CMAKE_C_COMPILER_ID}) + message(FATAL_ERROR "LD_FILE_${CMAKE_C_COMPILER_ID} not defined") + endif () + + set(STARTUP_FILE_GNU ${SDK_DIR}/Device/Nuvoton/NUC100Series/Source/GCC/startup_NUC100Series.S) + set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) + + add_library(${BOARD_TARGET} STATIC + ${SDK_DIR}/Device/Nuvoton/NUC100Series/Source/system_NUC100Series.c + ${SDK_DIR}/StdDriver/src/clk.c + ${SDK_DIR}/StdDriver/src/gpio.c + ${SDK_DIR}/StdDriver/src/sys.c + ${SDK_DIR}/StdDriver/src/timer.c + ${SDK_DIR}/StdDriver/src/uart.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} + ) + + target_include_directories(${BOARD_TARGET} PUBLIC + ${SDK_DIR}/Device/Nuvoton/NUC100Series/Include + ${SDK_DIR}/StdDriver/inc + ${SDK_DIR}/CMSIS/Include + ) + + target_compile_definitions(${BOARD_TARGET} PUBLIC + CFG_EXAMPLE_MSC_READONLY + CFG_EXAMPLE_VIDEO_READONLY + ) + + update_board(${BOARD_TARGET}) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + --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() + +function(family_configure_example TARGET RTOS) + family_configure_common(${TARGET} ${RTOS}) + add_board_target(board_${BOARD}) + + target_sources(${TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ) + target_include_directories(${TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} + ) + + family_add_tinyusb(${TARGET} OPT_MCU_NUC120) + target_sources(${TARGET} PUBLIC + ${TOP}/src/portable/nuvoton/nuc120/dcd_nuc120.c + ) + target_link_libraries(${TARGET} PUBLIC board_${BOARD}) + + family_flash_openocd_nuvoton(${TARGET}) +endfunction() diff --git a/hw/bsp/nuc100_120/family.mk b/hw/bsp/nuc100_120/family.mk new file mode 100644 index 000000000..f9afb4f72 --- /dev/null +++ b/hw/bsp/nuc100_120/family.mk @@ -0,0 +1,39 @@ +include $(TOP)/$(BOARD_PATH)/board.mk + +CFLAGS += \ + -flto \ + -DCFG_EXAMPLE_MSC_READONLY \ + -DCFG_EXAMPLE_VIDEO_READONLY \ + -DCFG_TUSB_MCU=OPT_MCU_NUC120 + +CPU_CORE ?= cortex-m0 + +LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs + +# LD_FILE is defined in board.mk + +SRC_C += \ + src/portable/nuvoton/nuc120/dcd_nuc120.c \ + hw/mcu/nuvoton/nuc100_120/Device/Nuvoton/NUC100Series/Source/system_NUC100Series.c \ + hw/mcu/nuvoton/nuc100_120/StdDriver/src/clk.c \ + hw/mcu/nuvoton/nuc100_120/StdDriver/src/gpio.c \ + hw/mcu/nuvoton/nuc100_120/StdDriver/src/sys.c \ + hw/mcu/nuvoton/nuc100_120/StdDriver/src/timer.c \ + hw/mcu/nuvoton/nuc100_120/StdDriver/src/uart.c + +SRC_S += \ + hw/mcu/nuvoton/nuc100_120/Device/Nuvoton/NUC100Series/Source/GCC/startup_NUC100Series.S + +INC += \ + $(TOP)/hw/mcu/nuvoton/nuc100_120/Device/Nuvoton/NUC100Series/Include \ + $(TOP)/hw/mcu/nuvoton/nuc100_120/StdDriver/inc \ + $(TOP)/hw/mcu/nuvoton/nuc100_120/CMSIS/Include \ + $(TOP)/$(BOARD_PATH) + +FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/ARM_CM0 + +# Flash using Nuvoton's openocd fork at https://github.com/OpenNuvoton/OpenOCD-Nuvoton +# Please compile and install it from github source +OPENOCD_NUVOTON_PATH ?= $(HOME)/app/OpenOCD-Nuvoton +flash: $(BUILD)/$(PROJECT).elf + $(OPENOCD_NUVOTON_PATH)/src/openocd -s $(OPENOCD_NUVOTON_PATH)/tcl -f interface/nulink.cfg -f target/numicroM0.cfg -c "program $< reset exit" diff --git a/hw/bsp/nuc121_125/family.mk b/hw/bsp/nuc121_125/family.mk index 9e2430d13..f46dac6e4 100644 --- a/hw/bsp/nuc121_125/family.mk +++ b/hw/bsp/nuc121_125/family.mk @@ -2,9 +2,6 @@ include $(TOP)/$(BOARD_PATH)/board.mk CFLAGS += \ -flto \ - -mthumb \ - -mabi=aapcs-linux \ - -mcpu=cortex-m0 \ -D__ARM_FEATURE_DSP=0 \ -DUSE_ASSERT=0 \ -DCFG_EXAMPLE_MSC_READONLY \ diff --git a/hw/bsp/nuc126/FreeRTOSConfig/FreeRTOSConfig.h b/hw/bsp/nuc126/FreeRTOSConfig/FreeRTOSConfig.h new file mode 100644 index 000000000..e8f120553 --- /dev/null +++ b/hw/bsp/nuc126/FreeRTOSConfig/FreeRTOSConfig.h @@ -0,0 +1,150 @@ +/* + * 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 "NuMicro.h" +#endif + +/* Cortex-M0 port configuration. */ +#define configENABLE_MPU 0 +#define configENABLE_FPU 0 +#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 +// NUC121/125 has 2 priority bits +#define configPRIO_BITS 2 + +/* The lowest interrupt priority that can be used in a call to a "set priority" function. */ +#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1< FLASH + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > FLASH + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > FLASH + __exidx_end = .; + + /* To copy multiple ROM to RAM sections, + * uncomment .copy.table section and, + * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */ + /* + .copy.table : + { + . = ALIGN(4); + __copy_table_start__ = .; + LONG (__etext) + LONG (__data_start__) + LONG (__data_end__ - __data_start__) + LONG (__etext2) + LONG (__data2_start__) + LONG (__data2_end__ - __data2_start__) + __copy_table_end__ = .; + } > FLASH + */ + + /* To clear multiple BSS sections, + * uncomment .zero.table section and, + * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */ + /* + .zero.table : + { + . = ALIGN(4); + __zero_table_start__ = .; + LONG (__bss_start__) + LONG (__bss_end__ - __bss_start__) + LONG (__bss2_start__) + LONG (__bss2_end__ - __bss2_start__) + __zero_table_end__ = .; + } > FLASH + */ + + __etext = .; + + .data : AT (__etext) + { + __data_start__ = .; + *(vtable) + *(.data*) + + . = 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 = .); + + KEEP(*(.jcr*)) + . = ALIGN(4); + /* All data end */ + __data_end__ = .; + + } > RAM + + .bss : + { + . = ALIGN(4); + __bss_start__ = .; + *(.bss*) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + } > RAM + + .heap (COPY): + { + __HeapBase = .; + __end__ = .; + end = __end__; + KEEP(*(.heap*)) + __HeapLimit = .; + } > RAM + + /* .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): + { + KEEP(*(.stack*)) + } > RAM + + /* Set stack top to end of RAM, and stack limit move down by + * size of stack_dummy section */ + __StackTop = ORIGIN(RAM) + LENGTH(RAM); + __StackLimit = __StackTop - SIZEOF(.stack_dummy); + PROVIDE(__stack = __StackTop); + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") +} diff --git a/hw/bsp/nuc126/family.c b/hw/bsp/nuc126/family.c new file mode 100644 index 000000000..f992fcab4 --- /dev/null +++ b/hw/bsp/nuc126/family.c @@ -0,0 +1,144 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 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. + */ + +#include "bsp/board_api.h" +#include "board.h" + +#include "NuMicro.h" +#include "clk.h" +#include "sys.h" + + +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USBD_IRQHandler(void) +{ + tud_int_handler(0); +} +#define TRIM_INIT (SYS_BASE+0x118) + +void board_init(void) +{ + /* Unlock protected registers */ + SYS_UnlockReg(); + + /*---------------------------------------------------------------------------------------------------------*/ + /* Init System Clock */ + /*---------------------------------------------------------------------------------------------------------*/ + + /* Enable Internal RC 22.1184 MHz clock */ + CLK_EnableXtalRC(CLK_PWRCTL_HIRCEN_Msk); + + /* Waiting for Internal RC clock ready */ + CLK_WaitClockReady(CLK_STATUS_HIRCSTB_Msk); + + /* Switch HCLK clock source to Internal RC and HCLK source divide 1 */ + CLK_SetHCLK(CLK_CLKSEL0_HCLKSEL_HIRC, CLK_CLKDIV0_HCLK(1)); + +#ifndef CRYSTAL_LESS + /* Enable external XTAL 12 MHz clock */ + CLK_EnableXtalRC(CLK_PWRCTL_HXTEN_Msk); + + /* Waiting for external XTAL clock ready */ + CLK_WaitClockReady(CLK_STATUS_HXTSTB_Msk); + + /* Set core clock */ + CLK_SetCoreClock(72000000); + + /* Use HIRC as UART clock source */ + CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL1_UARTSEL_HIRC, CLK_CLKDIV0_UART(1)); + + /* Use PLL as USB clock source */ + CLK_SetModuleClock(USBD_MODULE, CLK_CLKSEL3_USBDSEL_PLL, CLK_CLKDIV0_USB(3)); + +#else + /* Enable Internal RC 48MHz clock */ + CLK_EnableXtalRC(CLK_PWRCTL_HIRC48EN_Msk); + + /* Waiting for Internal RC clock ready */ + CLK_WaitClockReady(CLK_STATUS_HIRC48STB_Msk); + + /* Switch HCLK clock source to Internal RC and HCLK source divide 1 */ + CLK_SetHCLK(CLK_CLKSEL0_HCLKSEL_HIRC48, CLK_CLKDIV0_HCLK(1)); + + /* Use HIRC as UART clock source */ + CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL1_UARTSEL_HIRC, CLK_CLKDIV0_UART(1)); + + /* Use HIRC48 as USB clock source */ + CLK_SetModuleClock(USBD_MODULE, CLK_CLKSEL3_USBDSEL_HIRC48, CLK_CLKDIV0_USB(1)); +#endif + + /* Enable module clock */ + CLK_EnableModuleClock(USBD_MODULE); + +#if CFG_TUSB_OS == OPT_OS_NONE + // 1ms tick timer + SysTick_Config(48000000 / 1000); +#endif + + // LED + GPIO_SetMode(LED_PORT, 1 << LED_PIN, GPIO_MODE_OUTPUT); +} + +#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 + +//--------------------------------------------------------------------+ +// Board porting API +//--------------------------------------------------------------------+ + +void board_led_write(bool state) +{ + LED_PIN_IO = (state ? LED_STATE_ON : (1-LED_STATE_ON)); +} + +uint32_t board_button_read(void) +{ + return 0; +} + +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) buf; (void) len; + return 0; +} diff --git a/hw/bsp/nuc126/family.cmake b/hw/bsp/nuc126/family.cmake new file mode 100644 index 000000000..00725d725 --- /dev/null +++ b/hw/bsp/nuc126/family.cmake @@ -0,0 +1,104 @@ +include_guard() + +# include board specific +include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) + +set(SDK_DIR ${TOP}/hw/mcu/nuvoton/nuc126) +set(CMSIS_5 ${TOP}/lib/CMSIS_5) + +# toolchain set up +set(CMAKE_SYSTEM_CPU cortex-m0 CACHE INTERNAL "System Processor") +set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake) +set(OPENOCD_OPTION "-f interface/nulink.cfg -f target/numicroM0.cfg") + +set(FAMILY_MCUS NUC126 CACHE INTERNAL "") + +#------------------------------------ +# BOARD_TARGET +#------------------------------------ +function(add_board_target BOARD_TARGET) + if (TARGET ${BOARD_TARGET}) + return() + endif () + + set(LD_FILE_Clang ${LD_FILE_GNU}) + if (NOT DEFINED LD_FILE_${CMAKE_C_COMPILER_ID}) + message(FATAL_ERROR "LD_FILE_${CMAKE_C_COMPILER_ID} not defined") + endif () + + set(STARTUP_FILE_GNU ${SDK_DIR}/Device/Nuvoton/NUC126/Source/GCC/startup_NUC126.S) + set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) + + add_library(${BOARD_TARGET} STATIC + ${SDK_DIR}/Device/Nuvoton/NUC126/Source/system_NUC126.c + ${SDK_DIR}/StdDriver/src/clk.c + ${SDK_DIR}/StdDriver/src/crc.c + ${SDK_DIR}/StdDriver/src/gpio.c + ${SDK_DIR}/StdDriver/src/rtc.c + ${SDK_DIR}/StdDriver/src/sys.c + ${SDK_DIR}/StdDriver/src/timer.c + ${SDK_DIR}/StdDriver/src/uart.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} + ) + + target_include_directories(${BOARD_TARGET} PUBLIC + ${SDK_DIR}/Device/Nuvoton/NUC126/Include + ${SDK_DIR}/StdDriver/inc + ${SDK_DIR}/CMSIS/Include + ) + + target_compile_definitions(${BOARD_TARGET} PUBLIC + __ARM_FEATURE_DSP=0 + USE_ASSERT=0 + CFG_EXAMPLE_VIDEO_READONLY + __CORTEX_SC=0 + ) + + update_board(${BOARD_TARGET}) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + --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 ---------- + target_sources(${TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ) + target_include_directories(${TARGET} PUBLIC + ${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_NUC126) + target_sources(${TARGET} PUBLIC + ${TOP}/src/portable/nuvoton/nuc121/dcd_nuc121.c + ) + target_link_libraries(${TARGET} PUBLIC board_${BOARD}) + + family_flash_openocd_nuvoton(${TARGET}) +endfunction() diff --git a/hw/bsp/nuc126/family.mk b/hw/bsp/nuc126/family.mk new file mode 100644 index 000000000..37df7aaab --- /dev/null +++ b/hw/bsp/nuc126/family.mk @@ -0,0 +1,48 @@ +include $(TOP)/$(BOARD_PATH)/board.mk + +CFLAGS += \ + -flto \ + -D__ARM_FEATURE_DSP=0 \ + -DUSE_ASSERT=0 \ + -DCFG_EXAMPLE_VIDEO_READONLY \ + -D__CORTEX_SC=0 \ + -DCFG_TUSB_MCU=OPT_MCU_NUC126 + +CPU_CORE ?= cortex-m0 + +# mcu driver cause following warnings +CFLAGS += -Wno-error=redundant-decls + +LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs + +# All source paths should be relative to the top level. +# LD_FILE is defined in board.mk + +SRC_C += \ + src/portable/nuvoton/nuc121/dcd_nuc121.c \ + hw/mcu/nuvoton/nuc126/Device/Nuvoton/NUC126/Source/system_NUC126.c \ + hw/mcu/nuvoton/nuc126/StdDriver/src/clk.c \ + hw/mcu/nuvoton/nuc126/StdDriver/src/crc.c \ + hw/mcu/nuvoton/nuc126/StdDriver/src/gpio.c \ + hw/mcu/nuvoton/nuc126/StdDriver/src/rtc.c \ + hw/mcu/nuvoton/nuc126/StdDriver/src/sys.c \ + hw/mcu/nuvoton/nuc126/StdDriver/src/timer.c \ + hw/mcu/nuvoton/nuc126/StdDriver/src/uart.c + +SRC_S += \ + hw/mcu/nuvoton/nuc126/Device/Nuvoton/NUC126/Source/GCC/startup_NUC126.S + +INC += \ + $(TOP)/hw/mcu/nuvoton/nuc126/Device/Nuvoton/NUC126/Include \ + $(TOP)/hw/mcu/nuvoton/nuc126/StdDriver/inc \ + $(TOP)/hw/mcu/nuvoton/nuc126/CMSIS/Include \ + $(TOP)/$(BOARD_PATH) + +# For freeRTOS port source +FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/ARM_CM0 + +# Flash using Nuvoton's openocd fork at https://github.com/OpenNuvoton/OpenOCD-Nuvoton +# Please compile and install it from github source +OPENOCD_NUVOTON_PATH ?= $(HOME)/app/OpenOCD-Nuvoton +flash: $(BUILD)/$(PROJECT).elf + $(OPENOCD_NUVOTON_PATH)/src/openocd -s $(OPENOCD_NUVOTON_PATH)/tcl -f interface/nulink.cfg -f target/numicroM0.cfg -c "program $< reset exit" diff --git a/hw/bsp/nuc505/FreeRTOSConfig/FreeRTOSConfig.h b/hw/bsp/nuc505/FreeRTOSConfig/FreeRTOSConfig.h new file mode 100644 index 000000000..a44beb767 --- /dev/null +++ b/hw/bsp/nuc505/FreeRTOSConfig/FreeRTOSConfig.h @@ -0,0 +1,150 @@ +/* + * 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 "NUC505Series.h" +#endif + +/* Cortex-M4F 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 +// NUC505 has 3 priority bits +#define configPRIO_BITS 3 + +/* The lowest interrupt priority that can be used in a call to a "set priority" function. */ +#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1< FLASH + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > FLASH + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > FLASH + __exidx_end = .; + + /* To copy multiple ROM to RAM sections, + * uncomment .copy.table section and, + * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */ + /* + .copy.table : + { + . = ALIGN(4); + __copy_table_start__ = .; + LONG (__etext) + LONG (__data_start__) + LONG (__data_end__ - __data_start__) + LONG (__etext2) + LONG (__data2_start__) + LONG (__data2_end__ - __data2_start__) + __copy_table_end__ = .; + } > FLASH + */ + + /* To clear multiple BSS sections, + * uncomment .zero.table section and, + * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */ + /* + .zero.table : + { + . = ALIGN(4); + __zero_table_start__ = .; + LONG (__bss_start__) + LONG (__bss_end__ - __bss_start__) + LONG (__bss2_start__) + LONG (__bss2_end__ - __bss2_start__) + __zero_table_end__ = .; + } > FLASH + */ + + __etext = .; + + .data : AT (__etext) + { + __data_start__ = .; + + *(.text*) + + /* .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) + + *(.rodata*) + + KEEP(*(.eh_frame*)) + + *(vtable) + *(.data*) + + . = 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 = .); + + KEEP(*(.jcr*)) + . = ALIGN(4); + /* All data end */ + __data_end__ = .; + + } > RAM + + .bss : + { + . = ALIGN(4); + __bss_start__ = .; + *(.bss*) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + } > RAM + + .heap (COPY): + { + __HeapBase = .; + __end__ = .; + end = __end__; + KEEP(*(.heap*)) + __HeapLimit = .; + } > RAM + + /* .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): + { + KEEP(*(.stack*)) + } > RAM + + /* Set stack top to end of RAM, and stack limit move down by + * size of stack_dummy section */ + __StackTop = ORIGIN(RAM) + LENGTH(RAM); + __StackLimit = __StackTop - SIZEOF(.stack_dummy); + PROVIDE(__stack = __StackTop); + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") +} diff --git a/hw/bsp/nuc505/family.c b/hw/bsp/nuc505/family.c new file mode 100644 index 000000000..00ed92310 --- /dev/null +++ b/hw/bsp/nuc505/family.c @@ -0,0 +1,127 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 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. + */ + +#include "bsp/board_api.h" +#include "board.h" +#include "NUC505Series.h" + +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USBD_IRQHandler(void) +{ + tud_int_handler(0); +} + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM +//--------------------------------------------------------------------+ + +void board_init(void) +{ + /* Enable XTAL */ + CLK->PWRCTL |= CLK_PWRCTL_HXTEN_Msk; + + CLK_SetCoreClock(96000000); + + /* Set PCLK divider */ + CLK_SetModuleClock(PCLK_MODULE, 0, 1); + + /* Update System Core Clock */ + SystemCoreClockUpdate(); + + /* Enable USB IP clock */ + CLK_EnableModuleClock(USBD_MODULE); + + /* Select USB IP clock source */ + CLK_SetModuleClock(USBD_MODULE, CLK_USBD_SRC_EXT, 0); + + CLK_SetModuleClock(PCLK_MODULE, 0, 1); + + /* Enable PHY */ + USBD_ENABLE_PHY(); + /* wait PHY clock ready */ + while (1) { + USBD->EP[EPA].EPMPS = 0x20; + if (USBD->EP[EPA].EPMPS == 0x20) + break; + } + + /* Force SE0, and then clear it to connect*/ + USBD_SET_SE0(); + +#if CFG_TUSB_OS == OPT_OS_NONE + // 1ms tick timer + SysTick_Config(96000000 / 1000); +#endif + + GPIO_SetMode(LED_PORT, 1UL << LED_PIN, GPIO_MODE_OUTPUT); +} + +#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 + +//--------------------------------------------------------------------+ +// Board porting API +//--------------------------------------------------------------------+ + +void board_led_write(bool state) +{ + uint32_t current = (state) ? LED_STATE_ON : (1-LED_STATE_ON); + current <<= LED_PIN; + uint32_t irq_state = __get_PRIMASK(); + __disable_irq(); + current |= LED_PORT->DOUT & ~(1UL << LED_PIN); + LED_PORT->DOUT = current; + __set_PRIMASK(irq_state); +} + +uint32_t board_button_read(void) +{ + return 0; +} + +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) buf; (void) len; + return 0; +} diff --git a/hw/bsp/nuc505/family.cmake b/hw/bsp/nuc505/family.cmake new file mode 100644 index 000000000..8816ddbae --- /dev/null +++ b/hw/bsp/nuc505/family.cmake @@ -0,0 +1,91 @@ +include_guard() + +include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) + +set(SDK_DIR ${TOP}/hw/mcu/nuvoton/nuc505) +set(CMSIS_5 ${TOP}/lib/CMSIS_5) + +set(CMAKE_SYSTEM_CPU cortex-m4 CACHE INTERNAL "System Processor") +set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake) +set(OPENOCD_OPTION "-f interface/nulink.cfg -f target/numicroM4.cfg") + +set(FAMILY_MCUS NUC505 CACHE INTERNAL "") + +function(add_board_target BOARD_TARGET) + if (TARGET ${BOARD_TARGET}) + return() + endif () + + set(LD_FILE_Clang ${LD_FILE_GNU}) + if (NOT DEFINED LD_FILE_${CMAKE_C_COMPILER_ID}) + message(FATAL_ERROR "LD_FILE_${CMAKE_C_COMPILER_ID} not defined") + endif () + + set(STARTUP_FILE_GNU ${SDK_DIR}/Device/Nuvoton/NUC505Series/Source/GCC/startup_NUC505Series.S) + set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) + + add_library(${BOARD_TARGET} STATIC + ${SDK_DIR}/Device/Nuvoton/NUC505Series/Source/system_NUC505Series.c + ${SDK_DIR}/StdDriver/src/adc.c + ${SDK_DIR}/StdDriver/src/clk.c + ${SDK_DIR}/StdDriver/src/gpio.c + ${SDK_DIR}/StdDriver/src/i2c.c + ${SDK_DIR}/StdDriver/src/i2s.c + ${SDK_DIR}/StdDriver/src/pwm.c + ${SDK_DIR}/StdDriver/src/rtc.c + ${SDK_DIR}/StdDriver/src/spi.c + ${SDK_DIR}/StdDriver/src/spim.c + ${SDK_DIR}/StdDriver/src/sys.c + ${SDK_DIR}/StdDriver/src/timer.c + ${SDK_DIR}/StdDriver/src/uart.c + ${SDK_DIR}/StdDriver/src/wdt.c + ${SDK_DIR}/StdDriver/src/wwdt.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} + ) + + target_include_directories(${BOARD_TARGET} PUBLIC + ${SDK_DIR}/Device/Nuvoton/NUC505Series/Include + ${SDK_DIR}/StdDriver/inc + ${SDK_DIR}/CMSIS/Include + ) + + update_board(${BOARD_TARGET}) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + --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() + +function(family_configure_example TARGET RTOS) + family_configure_common(${TARGET} ${RTOS}) + add_board_target(board_${BOARD}) + + target_sources(${TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ) + target_include_directories(${TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} + ) + + family_add_tinyusb(${TARGET} OPT_MCU_NUC505) + target_sources(${TARGET} PUBLIC + ${TOP}/src/portable/nuvoton/nuc505/dcd_nuc505.c + ) + target_link_libraries(${TARGET} PUBLIC board_${BOARD}) + + family_flash_openocd_nuvoton(${TARGET}) +endfunction() diff --git a/hw/bsp/nuc505/family.mk b/hw/bsp/nuc505/family.mk new file mode 100644 index 000000000..e1f25e2db --- /dev/null +++ b/hw/bsp/nuc505/family.mk @@ -0,0 +1,55 @@ +include $(TOP)/$(BOARD_PATH)/board.mk + +CFLAGS += \ + -flto \ + -DCFG_TUSB_MCU=OPT_MCU_NUC505 + +CPU_CORE ?= cortex-m4 + +# mcu driver cause following warnings +CFLAGS += -Wno-error=redundant-decls + +LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs + +# LD_FILE is defined in board.mk + +SRC_C += \ + src/portable/nuvoton/nuc505/dcd_nuc505.c \ + hw/mcu/nuvoton/nuc505/Device/Nuvoton/NUC505Series/Source/system_NUC505Series.c \ + hw/mcu/nuvoton/nuc505/StdDriver/src/adc.c \ + hw/mcu/nuvoton/nuc505/StdDriver/src/clk.c \ + hw/mcu/nuvoton/nuc505/StdDriver/src/gpio.c \ + hw/mcu/nuvoton/nuc505/StdDriver/src/i2c.c \ + hw/mcu/nuvoton/nuc505/StdDriver/src/i2s.c \ + hw/mcu/nuvoton/nuc505/StdDriver/src/pwm.c \ + hw/mcu/nuvoton/nuc505/StdDriver/src/rtc.c \ + hw/mcu/nuvoton/nuc505/StdDriver/src/spi.c \ + hw/mcu/nuvoton/nuc505/StdDriver/src/spim.c \ + hw/mcu/nuvoton/nuc505/StdDriver/src/sys.c \ + hw/mcu/nuvoton/nuc505/StdDriver/src/timer.c \ + hw/mcu/nuvoton/nuc505/StdDriver/src/uart.c \ + hw/mcu/nuvoton/nuc505/StdDriver/src/wdt.c \ + hw/mcu/nuvoton/nuc505/StdDriver/src/wwdt.c + +SRC_S += \ + hw/mcu/nuvoton/nuc505/Device/Nuvoton/NUC505Series/Source/GCC/startup_NUC505Series.S + +INC += \ + $(TOP)/hw/mcu/nuvoton/nuc505/Device/Nuvoton/NUC505Series/Include \ + $(TOP)/hw/mcu/nuvoton/nuc505/StdDriver/inc \ + $(TOP)/hw/mcu/nuvoton/nuc505/CMSIS/Include \ + $(TOP)/$(BOARD_PATH) + +FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/ARM_CM4F + +# Note +# To be able to program the SPI flash, it need to boot with ICP mode "1011". +# However, in ICP mode, opencod cannot establish connection to the mcu. +# Therefore, there is no easy command line flash for NUC505 +# It is probably better to just use Nuvoton NuMicro ICP programming on windows to program the board + +# Flash using Nuvoton's openocd fork at https://github.com/OpenNuvoton/OpenOCD-Nuvoton +# Please compile and install it from github source +OPENOCD_NUVOTON_PATH ?= $(HOME)/app/OpenOCD-Nuvoton +flash: $(BUILD)/$(PROJECT).elf + $(OPENOCD_NUVOTON_PATH)/src/openocd -s $(OPENOCD_NUVOTON_PATH)/tcl -f interface/nulink.cfg -f target/numicroM4.cfg -c "program $< reset exit" diff --git a/hw/bsp/nutiny_nuc126v/board.mk b/hw/bsp/nutiny_nuc126v/board.mk deleted file mode 100644 index e87d1aad0..000000000 --- a/hw/bsp/nutiny_nuc126v/board.mk +++ /dev/null @@ -1,48 +0,0 @@ -CFLAGS += \ - -flto \ - -mthumb \ - -mabi=aapcs-linux \ - -mcpu=cortex-m0 \ - -D__ARM_FEATURE_DSP=0 \ - -DUSE_ASSERT=0 \ - -DCFG_EXAMPLE_VIDEO_READONLY \ - -D__CORTEX_SC=0 \ - -DCFG_TUSB_MCU=OPT_MCU_NUC126 - -# mcu driver cause following warnings -CFLAGS += -Wno-error=redundant-decls - -LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs - -# All source paths should be relative to the top level. -LD_FILE = hw/bsp/$(BOARD)/nuc126_flash.ld - -SRC_C += \ - src/portable/nuvoton/nuc121/dcd_nuc121.c \ - hw/mcu/nuvoton/nuc126/Device/Nuvoton/NUC126/Source/system_NUC126.c \ - hw/mcu/nuvoton/nuc126/StdDriver/src/clk.c \ - hw/mcu/nuvoton/nuc126/StdDriver/src/crc.c \ - hw/mcu/nuvoton/nuc126/StdDriver/src/gpio.c \ - hw/mcu/nuvoton/nuc126/StdDriver/src/rtc.c \ - hw/mcu/nuvoton/nuc126/StdDriver/src/sys.c \ - hw/mcu/nuvoton/nuc126/StdDriver/src/timer.c \ - hw/mcu/nuvoton/nuc126/StdDriver/src/uart.c - -SRC_S += \ - hw/mcu/nuvoton/nuc126/Device/Nuvoton/NUC126/Source/GCC/startup_NUC126.S - -INC += \ - $(TOP)/hw/mcu/nuvoton/nuc126/Device/Nuvoton/NUC126/Include \ - $(TOP)/hw/mcu/nuvoton/nuc126/StdDriver/inc \ - $(TOP)/hw/mcu/nuvoton/nuc126/CMSIS/Include - -# For freeRTOS port source -FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/ARM_CM0 - -# For flash-jlink target -JLINK_DEVICE = NUC126VG4AE - -# Flash using Nuvoton's openocd fork at https://github.com/OpenNuvoton/OpenOCD-Nuvoton -# Please compile and install it from github source -flash: $(BUILD)/$(PROJECT).elf - openocd -f interface/nulink.cfg -f target/numicroM0.cfg -c "program $< reset exit" diff --git a/hw/bsp/nutiny_nuc126v/nuc126_flash.ld b/hw/bsp/nutiny_nuc126v/nuc126_flash.ld deleted file mode 100644 index b23890b4b..000000000 --- a/hw/bsp/nutiny_nuc126v/nuc126_flash.ld +++ /dev/null @@ -1,195 +0,0 @@ -/* Linker script to configure memory regions. */ -MEMORY -{ - FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x40000 /* 256k */ - RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x5000 /* 20k */ -} - -/* Library configurations */ -GROUP(libgcc.a libc.a libm.a libnosys.a) - -/* Linker script to place sections and symbol values. Should be used together - * with other linker script that defines memory regions FLASH and RAM. - * It references following symbols, which must be defined in code: - * Reset_Handler : Entry of reset handler - * - * It defines following symbols, which code can use without definition: - * __exidx_start - * __exidx_end - * __copy_table_start__ - * __copy_table_end__ - * __zero_table_start__ - * __zero_table_end__ - * __etext - * __data_start__ - * __preinit_array_start - * __preinit_array_end - * __init_array_start - * __init_array_end - * __fini_array_start - * __fini_array_end - * __data_end__ - * __bss_start__ - * __bss_end__ - * __end__ - * end - * __HeapLimit - * __StackLimit - * __StackTop - * __stack - * __Vectors_End - * __Vectors_Size - */ -ENTRY(Reset_Handler) - -SECTIONS -{ - .text : - { - KEEP(*(.vectors)) - __Vectors_End = .; - __Vectors_Size = __Vectors_End - __Vectors; - __end__ = .; - - *(.text*) - - 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) - - *(.rodata*) - - KEEP(*(.eh_frame*)) - } > FLASH - - .ARM.extab : - { - *(.ARM.extab* .gnu.linkonce.armextab.*) - } > FLASH - - __exidx_start = .; - .ARM.exidx : - { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - } > FLASH - __exidx_end = .; - - /* To copy multiple ROM to RAM sections, - * uncomment .copy.table section and, - * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */ - /* - .copy.table : - { - . = ALIGN(4); - __copy_table_start__ = .; - LONG (__etext) - LONG (__data_start__) - LONG (__data_end__ - __data_start__) - LONG (__etext2) - LONG (__data2_start__) - LONG (__data2_end__ - __data2_start__) - __copy_table_end__ = .; - } > FLASH - */ - - /* To clear multiple BSS sections, - * uncomment .zero.table section and, - * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */ - /* - .zero.table : - { - . = ALIGN(4); - __zero_table_start__ = .; - LONG (__bss_start__) - LONG (__bss_end__ - __bss_start__) - LONG (__bss2_start__) - LONG (__bss2_end__ - __bss2_start__) - __zero_table_end__ = .; - } > FLASH - */ - - __etext = .; - - .data : AT (__etext) - { - __data_start__ = .; - *(vtable) - *(.data*) - - . = 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 = .); - - KEEP(*(.jcr*)) - . = ALIGN(4); - /* All data end */ - __data_end__ = .; - - } > RAM - - .bss : - { - . = ALIGN(4); - __bss_start__ = .; - *(.bss*) - *(COMMON) - . = ALIGN(4); - __bss_end__ = .; - } > RAM - - .heap (COPY): - { - __HeapBase = .; - __end__ = .; - end = __end__; - KEEP(*(.heap*)) - __HeapLimit = .; - } > RAM - - /* .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): - { - KEEP(*(.stack*)) - } > RAM - - /* Set stack top to end of RAM, and stack limit move down by - * size of stack_dummy section */ - __StackTop = ORIGIN(RAM) + LENGTH(RAM); - __StackLimit = __StackTop - SIZEOF(.stack_dummy); - PROVIDE(__stack = __StackTop); - - /* Check if data + heap + stack exceeds RAM limit */ - ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") -} diff --git a/hw/bsp/nutiny_nuc126v/nutiny_nuc126.c b/hw/bsp/nutiny_nuc126v/nutiny_nuc126.c deleted file mode 100644 index 9974127a8..000000000 --- a/hw/bsp/nutiny_nuc126v/nutiny_nuc126.c +++ /dev/null @@ -1,153 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 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. - */ - -#include "bsp/board_api.h" -#include "NuMicro.h" -#include "clk.h" -#include "sys.h" - - -//--------------------------------------------------------------------+ -// Forward USB interrupt events to TinyUSB IRQ Handler -//--------------------------------------------------------------------+ -void USBD_IRQHandler(void) -{ - tud_int_handler(0); -} - -//--------------------------------------------------------------------+ -// MACRO TYPEDEF CONSTANT ENUM -//--------------------------------------------------------------------+ -#define LED_PORT PC -#define LED_PIN 9 -#define LED_PIN_IO PC9 -#define LED_STATE_ON 0 - -#define CRYSTAL_LESS /* system will be 48MHz when defined, otherwise, system is 72MHz */ -#define HIRC48_AUTO_TRIM SYS_IRCTCTL1_REFCKSEL_Msk | (1UL << SYS_IRCTCTL1_LOOPSEL_Pos) | (2UL << SYS_IRCTCTL1_FREQSEL_Pos) -#define TRIM_INIT (SYS_BASE+0x118) - -void board_init(void) -{ - /* Unlock protected registers */ - SYS_UnlockReg(); - - /*---------------------------------------------------------------------------------------------------------*/ - /* Init System Clock */ - /*---------------------------------------------------------------------------------------------------------*/ - - /* Enable Internal RC 22.1184 MHz clock */ - CLK_EnableXtalRC(CLK_PWRCTL_HIRCEN_Msk); - - /* Waiting for Internal RC clock ready */ - CLK_WaitClockReady(CLK_STATUS_HIRCSTB_Msk); - - /* Switch HCLK clock source to Internal RC and HCLK source divide 1 */ - CLK_SetHCLK(CLK_CLKSEL0_HCLKSEL_HIRC, CLK_CLKDIV0_HCLK(1)); - -#ifndef CRYSTAL_LESS - /* Enable external XTAL 12 MHz clock */ - CLK_EnableXtalRC(CLK_PWRCTL_HXTEN_Msk); - - /* Waiting for external XTAL clock ready */ - CLK_WaitClockReady(CLK_STATUS_HXTSTB_Msk); - - /* Set core clock */ - CLK_SetCoreClock(72000000); - - /* Use HIRC as UART clock source */ - CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL1_UARTSEL_HIRC, CLK_CLKDIV0_UART(1)); - - /* Use PLL as USB clock source */ - CLK_SetModuleClock(USBD_MODULE, CLK_CLKSEL3_USBDSEL_PLL, CLK_CLKDIV0_USB(3)); - -#else - /* Enable Internal RC 48MHz clock */ - CLK_EnableXtalRC(CLK_PWRCTL_HIRC48EN_Msk); - - /* Waiting for Internal RC clock ready */ - CLK_WaitClockReady(CLK_STATUS_HIRC48STB_Msk); - - /* Switch HCLK clock source to Internal RC and HCLK source divide 1 */ - CLK_SetHCLK(CLK_CLKSEL0_HCLKSEL_HIRC48, CLK_CLKDIV0_HCLK(1)); - - /* Use HIRC as UART clock source */ - CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL1_UARTSEL_HIRC, CLK_CLKDIV0_UART(1)); - - /* Use HIRC48 as USB clock source */ - CLK_SetModuleClock(USBD_MODULE, CLK_CLKSEL3_USBDSEL_HIRC48, CLK_CLKDIV0_USB(1)); -#endif - - /* Enable module clock */ - CLK_EnableModuleClock(USBD_MODULE); - -#if CFG_TUSB_OS == OPT_OS_NONE - // 1ms tick timer - SysTick_Config(48000000 / 1000); -#endif - - // LED - GPIO_SetMode(LED_PORT, 1 << LED_PIN, GPIO_MODE_OUTPUT); -} - -#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 - -//--------------------------------------------------------------------+ -// Board porting API -//--------------------------------------------------------------------+ - -void board_led_write(bool state) -{ - LED_PIN_IO = (state ? LED_STATE_ON : (1-LED_STATE_ON)); -} - -uint32_t board_button_read(void) -{ - return 0; -} - -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) buf; (void) len; - return 0; -} diff --git a/hw/bsp/nutiny_sdk_nuc120/board.mk b/hw/bsp/nutiny_sdk_nuc120/board.mk deleted file mode 100644 index d982bdc06..000000000 --- a/hw/bsp/nutiny_sdk_nuc120/board.mk +++ /dev/null @@ -1,41 +0,0 @@ -CFLAGS += \ - -flto \ - -mthumb \ - -mabi=aapcs-linux \ - -mcpu=cortex-m0 \ - -DCFG_EXAMPLE_MSC_READONLY \ - -DCFG_EXAMPLE_VIDEO_READONLY \ - -DCFG_TUSB_MCU=OPT_MCU_NUC120 - -LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs - -# All source paths should be relative to the top level. -LD_FILE = hw/bsp/nutiny_sdk_nuc120/nuc120_flash.ld - -SRC_C += \ - src/portable/nuvoton/nuc120/dcd_nuc120.c \ - hw/mcu/nuvoton/nuc100_120/Device/Nuvoton/NUC100Series/Source/system_NUC100Series.c \ - hw/mcu/nuvoton/nuc100_120/StdDriver/src/clk.c \ - hw/mcu/nuvoton/nuc100_120/StdDriver/src/gpio.c \ - hw/mcu/nuvoton/nuc100_120/StdDriver/src/sys.c \ - hw/mcu/nuvoton/nuc100_120/StdDriver/src/timer.c \ - hw/mcu/nuvoton/nuc100_120/StdDriver/src/uart.c - -SRC_S += \ - hw/mcu/nuvoton/nuc100_120/Device/Nuvoton/NUC100Series/Source/GCC/startup_NUC100Series.S - -INC += \ - $(TOP)/hw/mcu/nuvoton/nuc100_120/Device/Nuvoton/NUC100Series/Include \ - $(TOP)/hw/mcu/nuvoton/nuc100_120/StdDriver/inc \ - $(TOP)/hw/mcu/nuvoton/nuc100_120/CMSIS/Include - -# For freeRTOS port source -FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/ARM_CM0 - -# For flash-jlink target -JLINK_DEVICE = NUC120LE3 - -# Flash using Nuvoton's openocd fork at https://github.com/OpenNuvoton/OpenOCD-Nuvoton -# Please compile and install it from github source -flash: $(BUILD)/$(PROJECT).elf - openocd -f interface/nulink.cfg -f target/numicroM0.cfg -c "program $< reset exit" diff --git a/hw/bsp/nutiny_sdk_nuc120/nuc120_flash.ld b/hw/bsp/nutiny_sdk_nuc120/nuc120_flash.ld deleted file mode 100644 index cab12c8b9..000000000 --- a/hw/bsp/nutiny_sdk_nuc120/nuc120_flash.ld +++ /dev/null @@ -1,195 +0,0 @@ -/* Linker script to configure memory regions. */ -MEMORY -{ - FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x20000 /* 128k */ - RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x4000 /* 16k */ -} - -/* Library configurations */ -GROUP(libgcc.a libc.a libm.a libnosys.a) - -/* Linker script to place sections and symbol values. Should be used together - * with other linker script that defines memory regions FLASH and RAM. - * It references following symbols, which must be defined in code: - * Reset_Handler : Entry of reset handler - * - * It defines following symbols, which code can use without definition: - * __exidx_start - * __exidx_end - * __copy_table_start__ - * __copy_table_end__ - * __zero_table_start__ - * __zero_table_end__ - * __etext - * __data_start__ - * __preinit_array_start - * __preinit_array_end - * __init_array_start - * __init_array_end - * __fini_array_start - * __fini_array_end - * __data_end__ - * __bss_start__ - * __bss_end__ - * __end__ - * end - * __HeapLimit - * __StackLimit - * __StackTop - * __stack - * __Vectors_End - * __Vectors_Size - */ -ENTRY(Reset_Handler) - -SECTIONS -{ - .text : - { - KEEP(*(.vectors)) - __Vectors_End = .; - __Vectors_Size = __Vectors_End - __Vectors; - __end__ = .; - - *(.text*) - - 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) - - *(.rodata*) - - KEEP(*(.eh_frame*)) - } > FLASH - - .ARM.extab : - { - *(.ARM.extab* .gnu.linkonce.armextab.*) - } > FLASH - - __exidx_start = .; - .ARM.exidx : - { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - } > FLASH - __exidx_end = .; - - /* To copy multiple ROM to RAM sections, - * uncomment .copy.table section and, - * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */ - /* - .copy.table : - { - . = ALIGN(4); - __copy_table_start__ = .; - LONG (__etext) - LONG (__data_start__) - LONG (__data_end__ - __data_start__) - LONG (__etext2) - LONG (__data2_start__) - LONG (__data2_end__ - __data2_start__) - __copy_table_end__ = .; - } > FLASH - */ - - /* To clear multiple BSS sections, - * uncomment .zero.table section and, - * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */ - /* - .zero.table : - { - . = ALIGN(4); - __zero_table_start__ = .; - LONG (__bss_start__) - LONG (__bss_end__ - __bss_start__) - LONG (__bss2_start__) - LONG (__bss2_end__ - __bss2_start__) - __zero_table_end__ = .; - } > FLASH - */ - - __etext = .; - - .data : AT (__etext) - { - __data_start__ = .; - *(vtable) - *(.data*) - - . = 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 = .); - - KEEP(*(.jcr*)) - . = ALIGN(4); - /* All data end */ - __data_end__ = .; - - } > RAM - - .bss : - { - . = ALIGN(4); - __bss_start__ = .; - *(.bss*) - *(COMMON) - . = ALIGN(4); - __bss_end__ = .; - } > RAM - - .heap (COPY): - { - __HeapBase = .; - __end__ = .; - end = __end__; - KEEP(*(.heap*)) - __HeapLimit = .; - } > RAM - - /* .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): - { - KEEP(*(.stack*)) - } > RAM - - /* Set stack top to end of RAM, and stack limit move down by - * size of stack_dummy section */ - __StackTop = ORIGIN(RAM) + LENGTH(RAM); - __StackLimit = __StackTop - SIZEOF(.stack_dummy); - PROVIDE(__stack = __StackTop); - - /* Check if data + heap + stack exceeds RAM limit */ - ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") -} diff --git a/hw/bsp/nutiny_sdk_nuc120/nutiny_sdk_nuc120.c b/hw/bsp/nutiny_sdk_nuc120/nutiny_sdk_nuc120.c deleted file mode 100644 index 18a189d8c..000000000 --- a/hw/bsp/nutiny_sdk_nuc120/nutiny_sdk_nuc120.c +++ /dev/null @@ -1,133 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 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. - */ - -#include "bsp/board_api.h" -#include "NUC100Series.h" -#include "clk.h" -#include "sys.h" - -//--------------------------------------------------------------------+ -// Forward USB interrupt events to TinyUSB IRQ Handler -//--------------------------------------------------------------------+ -void USBD_IRQHandler(void) -{ - tud_int_handler(0); -} - -//--------------------------------------------------------------------+ -// MACRO TYPEDEF CONSTANT ENUM -//--------------------------------------------------------------------+ -#define LED_PORT PB -#define LED_PIN 0 -#define LED_PIN_IO PB0 -#define LED_STATE_ON 0 - -void board_init(void) -{ - SYS_UnlockReg(); - - /* Enable Internal RC 22.1184 MHz clock */ - CLK_EnableXtalRC(CLK_PWRCON_OSC22M_EN_Msk); - - /* Waiting for Internal RC clock ready */ - CLK_WaitClockReady(CLK_CLKSTATUS_OSC22M_STB_Msk); - - /* Switch HCLK clock source to Internal RC and HCLK source divide 1 */ - CLK_SetHCLK(CLK_CLKSEL0_HCLK_S_HIRC, CLK_CLKDIV_HCLK(1)); - - /* Enable external XTAL 12 MHz clock */ - CLK_EnableXtalRC(CLK_PWRCON_XTL12M_EN_Msk); - - /* Waiting for external XTAL clock ready */ - CLK_WaitClockReady(CLK_CLKSTATUS_XTL12M_STB_Msk); - - /* Set core clock */ - CLK_SetCoreClock(48000000); - - /* Enable module clock */ - CLK_EnableModuleClock(USBD_MODULE); - - /* Select module clock source */ - CLK_SetModuleClock(USBD_MODULE, 0, CLK_CLKDIV_USB(1)); - - SYS_LockReg(); - -#if CFG_TUSB_OS == OPT_OS_NONE - // 1ms tick timer - SysTick_Config(48000000 / 1000); -#endif - - GPIO_SetMode(LED_PORT, 1UL << LED_PIN, GPIO_PMD_OUTPUT); -} - -#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 - -//--------------------------------------------------------------------+ -// Board porting API -//--------------------------------------------------------------------+ - -void board_led_write(bool state) -{ -#if 0 - /* this would be the simplest solution... *IF* the part supported the pin data interface */ - LED_PIN_IO = (state) ? LED_STATE_ON : (1-LED_STATE_ON); -#else - /* if the part's *PDIO pin data registers don't work, a more elaborate approach is needed */ - uint32_t irq_state = __get_PRIMASK(); - __disable_irq(); - uint32_t current = LED_PORT->DOUT & ~(1UL << LED_PIN); - LED_PORT->DOUT = current | (((state) ? LED_STATE_ON : (1UL-LED_STATE_ON)) << LED_PIN); - __set_PRIMASK(irq_state); -#endif -} - -uint32_t board_button_read(void) -{ - return 0; -} - -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) buf; (void) len; - return 0; -} diff --git a/hw/bsp/nutiny_sdk_nuc505/board.mk b/hw/bsp/nutiny_sdk_nuc505/board.mk deleted file mode 100644 index 1dc8b244e..000000000 --- a/hw/bsp/nutiny_sdk_nuc505/board.mk +++ /dev/null @@ -1,63 +0,0 @@ -CFLAGS += \ - -flto \ - -mthumb \ - -mabi=aapcs-linux \ - -mcpu=cortex-m4 \ - -mfloat-abi=hard \ - -mfpu=fpv4-sp-d16 \ - -DCFG_TUSB_MCU=OPT_MCU_NUC505 - -# mcu driver cause following warnings -CFLAGS += -Wno-error=redundant-decls - -LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs - -# All source paths should be relative to the top level. -LD_FILE = hw/bsp/$(BOARD)/nuc505_flashtoram.ld - -SRC_C += \ - src/portable/nuvoton/nuc505/dcd_nuc505.c \ - hw/mcu/nuvoton/nuc505/Device/Nuvoton/NUC505Series/Source/system_NUC505Series.c \ - hw/mcu/nuvoton/nuc505/StdDriver/src/adc.c \ - hw/mcu/nuvoton/nuc505/StdDriver/src/clk.c \ - hw/mcu/nuvoton/nuc505/StdDriver/src/gpio.c \ - hw/mcu/nuvoton/nuc505/StdDriver/src/i2c.c \ - hw/mcu/nuvoton/nuc505/StdDriver/src/i2s.c \ - hw/mcu/nuvoton/nuc505/StdDriver/src/pwm.c \ - hw/mcu/nuvoton/nuc505/StdDriver/src/rtc.c \ - hw/mcu/nuvoton/nuc505/StdDriver/src/spi.c \ - hw/mcu/nuvoton/nuc505/StdDriver/src/spim.c \ - hw/mcu/nuvoton/nuc505/StdDriver/src/sys.c \ - hw/mcu/nuvoton/nuc505/StdDriver/src/timer.c \ - hw/mcu/nuvoton/nuc505/StdDriver/src/uart.c \ - hw/mcu/nuvoton/nuc505/StdDriver/src/wdt.c \ - hw/mcu/nuvoton/nuc505/StdDriver/src/wwdt.c - -SRC_S += \ - hw/mcu/nuvoton/nuc505/Device/Nuvoton/NUC505Series/Source/GCC/startup_NUC505Series.S - -INC += \ - $(TOP)/hw/mcu/nuvoton/nuc505/Device/Nuvoton/NUC505Series/Include \ - $(TOP)/hw/mcu/nuvoton/nuc505/StdDriver/inc \ - $(TOP)/hw/mcu/nuvoton/nuc505/CMSIS/Include - -# For freeRTOS port source -FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/ARM_CM4F - -# For flash-jlink target -JLINK_DEVICE = NUC505YO13Y - -# Note -# To be able to program the SPI flash, it need to boot with ICP mode "1011". -# However, in ICP mode, opencod cannot establish connection to the mcu. -# Therefore, there is no easy command line flash for NUC505 -# It is probably better to just use Nuvoton NuMicro ICP programming on windows to program the board -# - 1111 "SPI" (run from internal flash) -# - 1110 "USB" (mass storage emulator that accepts a .bin file) -# - 0111 "ICE-SPI" (allow external debugger access, but may not be programmable) -# - 1011 ICP mode (programmable via NuMicro ICP programming tool) - -# Flash using Nuvoton's openocd fork at https://github.com/OpenNuvoton/OpenOCD-Nuvoton -# Please compile and install it from github source -flash: $(BUILD)/$(PROJECT).elf - openocd -f interface/nulink.cfg -f target/numicroM4.cfg -c "program $< reset exit" diff --git a/hw/bsp/nutiny_sdk_nuc505/nuc505_flashtoram.ld b/hw/bsp/nutiny_sdk_nuc505/nuc505_flashtoram.ld deleted file mode 100644 index 53d385cd0..000000000 --- a/hw/bsp/nutiny_sdk_nuc505/nuc505_flashtoram.ld +++ /dev/null @@ -1,199 +0,0 @@ -/* Linker script to configure memory regions. */ -MEMORY -{ - FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x80000 /* 512k */ - RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x20000 /* 128k */ -} - -/* Library configurations */ -GROUP(libgcc.a libc.a libm.a libnosys.a) - -/* Linker script to place sections and symbol values. Should be used together - * with other linker script that defines memory regions FLASH and RAM. - * It references following symbols, which must be defined in code: - * Reset_Handler : Entry of reset handler - * - * It defines following symbols, which code can use without definition: - * __exidx_start - * __exidx_end - * __copy_table_start__ - * __copy_table_end__ - * __zero_table_start__ - * __zero_table_end__ - * __etext - * __data_start__ - * __preinit_array_start - * __preinit_array_end - * __init_array_start - * __init_array_end - * __fini_array_start - * __fini_array_end - * __data_end__ - * __bss_start__ - * __bss_end__ - * __end__ - * end - * __HeapLimit - * __StackLimit - * __StackTop - * __stack - * __Vectors_End - * __Vectors_Size - */ -ENTRY(Reset_Handler) - -SECTIONS -{ - .startup : - { - KEEP(*(.vectors)) - __Vectors_End = .; - __Vectors_Size = __Vectors_End - __Vectors; - __end__ = .; - - KEEP(*(.preinit)) - - KEEP(*(.init)) - KEEP(*(.fini)) - - } > FLASH - - .ARM.extab : - { - *(.ARM.extab* .gnu.linkonce.armextab.*) - } > FLASH - - __exidx_start = .; - .ARM.exidx : - { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - } > FLASH - __exidx_end = .; - - /* To copy multiple ROM to RAM sections, - * uncomment .copy.table section and, - * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */ - /* - .copy.table : - { - . = ALIGN(4); - __copy_table_start__ = .; - LONG (__etext) - LONG (__data_start__) - LONG (__data_end__ - __data_start__) - LONG (__etext2) - LONG (__data2_start__) - LONG (__data2_end__ - __data2_start__) - __copy_table_end__ = .; - } > FLASH - */ - - /* To clear multiple BSS sections, - * uncomment .zero.table section and, - * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */ - /* - .zero.table : - { - . = ALIGN(4); - __zero_table_start__ = .; - LONG (__bss_start__) - LONG (__bss_end__ - __bss_start__) - LONG (__bss2_start__) - LONG (__bss2_end__ - __bss2_start__) - __zero_table_end__ = .; - } > FLASH - */ - - __etext = .; - - .data : AT (__etext) - { - __data_start__ = .; - - *(.text*) - - /* .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) - - *(.rodata*) - - KEEP(*(.eh_frame*)) - - *(vtable) - *(.data*) - - . = 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 = .); - - KEEP(*(.jcr*)) - . = ALIGN(4); - /* All data end */ - __data_end__ = .; - - } > RAM - - .bss : - { - . = ALIGN(4); - __bss_start__ = .; - *(.bss*) - *(COMMON) - . = ALIGN(4); - __bss_end__ = .; - } > RAM - - .heap (COPY): - { - __HeapBase = .; - __end__ = .; - end = __end__; - KEEP(*(.heap*)) - __HeapLimit = .; - } > RAM - - /* .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): - { - KEEP(*(.stack*)) - } > RAM - - /* Set stack top to end of RAM, and stack limit move down by - * size of stack_dummy section */ - __StackTop = ORIGIN(RAM) + LENGTH(RAM); - __StackLimit = __StackTop - SIZEOF(.stack_dummy); - PROVIDE(__stack = __StackTop); - - /* Check if data + heap + stack exceeds RAM limit */ - ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") -} diff --git a/hw/bsp/nutiny_sdk_nuc505/nutiny_sdk_nuc505.c b/hw/bsp/nutiny_sdk_nuc505/nutiny_sdk_nuc505.c deleted file mode 100644 index 3ec0066a3..000000000 --- a/hw/bsp/nutiny_sdk_nuc505/nutiny_sdk_nuc505.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 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. - */ - -#include "bsp/board_api.h" -#include "NUC505Series.h" - -//--------------------------------------------------------------------+ -// Forward USB interrupt events to TinyUSB IRQ Handler -//--------------------------------------------------------------------+ -void USBD_IRQHandler(void) -{ - tud_int_handler(0); -} - -//--------------------------------------------------------------------+ -// MACRO TYPEDEF CONSTANT ENUM -//--------------------------------------------------------------------+ -#define LED_PORT PC -#define LED_PIN 3 -#define LED_STATE_ON 0 - -void board_init(void) -{ - /* Enable XTAL */ - CLK->PWRCTL |= CLK_PWRCTL_HXTEN_Msk; - - CLK_SetCoreClock(96000000); - - /* Set PCLK divider */ - CLK_SetModuleClock(PCLK_MODULE, 0, 1); - - /* Update System Core Clock */ - SystemCoreClockUpdate(); - - /* Enable USB IP clock */ - CLK_EnableModuleClock(USBD_MODULE); - - /* Select USB IP clock source */ - CLK_SetModuleClock(USBD_MODULE, CLK_USBD_SRC_EXT, 0); - - CLK_SetModuleClock(PCLK_MODULE, 0, 1); - - /* Enable PHY */ - USBD_ENABLE_PHY(); - /* wait PHY clock ready */ - while (1) { - USBD->EP[EPA].EPMPS = 0x20; - if (USBD->EP[EPA].EPMPS == 0x20) - break; - } - - /* Force SE0, and then clear it to connect*/ - USBD_SET_SE0(); - -#if CFG_TUSB_OS == OPT_OS_NONE - // 1ms tick timer - SysTick_Config(96000000 / 1000); -#endif - - GPIO_SetMode(LED_PORT, 1UL << LED_PIN, GPIO_MODE_OUTPUT); -} - -#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 - -//--------------------------------------------------------------------+ -// Board porting API -//--------------------------------------------------------------------+ - -void board_led_write(bool state) -{ - uint32_t current = (state) ? LED_STATE_ON : (1-LED_STATE_ON); - current <<= LED_PIN; - uint32_t irq_state = __get_PRIMASK(); - __disable_irq(); - current |= LED_PORT->DOUT & ~(1UL << LED_PIN); - LED_PORT->DOUT = current; - __set_PRIMASK(irq_state); -} - -uint32_t board_button_read(void) -{ - return 0; -} - -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) buf; (void) len; - return 0; -} diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index 5e1a6aafd..d0a502367 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -386,10 +386,12 @@ #elif TU_CHECK_MCU(OPT_MCU_NUC120) #define TUP_DCD_ENDPOINT_MAX 6 + #define TUP_DCD_EDPT_ISO_ALLOC #elif TU_CHECK_MCU(OPT_MCU_NUC505) #define TUP_DCD_ENDPOINT_MAX 12 #define TUP_RHPORT_HIGHSPEED 1 + #define TUP_DCD_EDPT_ISO_ALLOC //--------------------------------------------------------------------+ // Espressif diff --git a/src/portable/nuvoton/nuc505/dcd_nuc505.c b/src/portable/nuvoton/nuc505/dcd_nuc505.c index 1c98a0a49..fa457d861 100644 --- a/src/portable/nuvoton/nuc505/dcd_nuc505.c +++ b/src/portable/nuvoton/nuc505/dcd_nuc505.c @@ -357,6 +357,19 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) return true; } +bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { + (void) rhport; + (void) ep_addr; + (void) largest_packet_size; + return false; // TODO not implemented yet +} + +bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) { + (void) rhport; + (void) desc_ep; + return false; // TODO not implemented yet +} + void dcd_edpt_close_all (uint8_t rhport) { (void) rhport; -- cgit v1.3.1 From 53deb6cc6cf97055fb66f25509b2cdce0b17a3c7 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 15 Oct 2025 15:43:08 +0700 Subject: fix more warnings --- hw/bsp/nuc100_120/FreeRTOSConfig/FreeRTOSConfig.h | 2 +- src/portable/nuvoton/nuc120/dcd_nuc120.c | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) (limited to 'src/portable') diff --git a/hw/bsp/nuc100_120/FreeRTOSConfig/FreeRTOSConfig.h b/hw/bsp/nuc100_120/FreeRTOSConfig/FreeRTOSConfig.h index e8f120553..dfac55a91 100644 --- a/hw/bsp/nuc100_120/FreeRTOSConfig/FreeRTOSConfig.h +++ b/hw/bsp/nuc100_120/FreeRTOSConfig/FreeRTOSConfig.h @@ -44,7 +44,7 @@ // skip if included from IAR assembler #ifndef __IASMARM__ - #include "NuMicro.h" +#include "NUC100Series.h" #endif /* Cortex-M0 port configuration. */ diff --git a/src/portable/nuvoton/nuc120/dcd_nuc120.c b/src/portable/nuvoton/nuc120/dcd_nuc120.c index b0b6fe857..0edebf159 100644 --- a/src/portable/nuvoton/nuc120/dcd_nuc120.c +++ b/src/portable/nuvoton/nuc120/dcd_nuc120.c @@ -275,6 +275,19 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) return true; } +bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { + (void) rhport; + (void) ep_addr; + (void) largest_packet_size; + return false; // TODO not implemented yet +} + +bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) { + (void) rhport; + (void) desc_ep; + return false; // TODO not implemented yet +} + void dcd_edpt_close_all (uint8_t rhport) { (void) rhport; -- cgit v1.3.1 From fd9d43d7c5785f4d5337bce1e5d5cede86b709c7 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 15 Oct 2025 19:31:16 +0700 Subject: refactor spresense into cxd56. there is no orphan board in bsp. --- examples/device/uac2_headset/src/usb_descriptors.c | 6 +- hw/bsp/cxd56/FreeRTOSConfig/FreeRTOSConfig.h | 150 +++++++++++++++++++++ hw/bsp/cxd56/boards/spresense/board.cmake | 6 + hw/bsp/cxd56/boards/spresense/board.h | 43 ++++++ hw/bsp/cxd56/boards/spresense/board.mk | 7 + hw/bsp/cxd56/family.c | 112 +++++++++++++++ hw/bsp/cxd56/family.cmake | 135 +++++++++++++++++++ hw/bsp/cxd56/family.mk | 70 ++++++++++ hw/bsp/family_support.mk | 28 +--- hw/bsp/fomu/family.mk | 2 +- hw/bsp/spresense/board.mk | 75 ----------- hw/bsp/spresense/board_spresense.c | 105 --------------- src/common/tusb_mcu.h | 1 + src/portable/sony/cxd56/dcd_cxd56.c | 13 ++ 14 files changed, 548 insertions(+), 205 deletions(-) create mode 100644 hw/bsp/cxd56/FreeRTOSConfig/FreeRTOSConfig.h create mode 100644 hw/bsp/cxd56/boards/spresense/board.cmake create mode 100644 hw/bsp/cxd56/boards/spresense/board.h create mode 100644 hw/bsp/cxd56/boards/spresense/board.mk create mode 100644 hw/bsp/cxd56/family.c create mode 100644 hw/bsp/cxd56/family.cmake create mode 100644 hw/bsp/cxd56/family.mk delete mode 100644 hw/bsp/spresense/board.mk delete mode 100644 hw/bsp/spresense/board_spresense.c (limited to 'src/portable') diff --git a/examples/device/uac2_headset/src/usb_descriptors.c b/examples/device/uac2_headset/src/usb_descriptors.c index bc9160d5e..fc12c122e 100644 --- a/examples/device/uac2_headset/src/usb_descriptors.c +++ b/examples/device/uac2_headset/src/usb_descriptors.c @@ -87,9 +87,9 @@ uint8_t const * tud_descriptor_device_cb(void) #elif CFG_TUSB_MCU == OPT_MCU_CXD56 // CXD56 USB driver has fixed endpoint type (bulk/interrupt/iso) and direction (IN/OUT) by its number // 0 control (IN/OUT), 1 Bulk (IN), 2 Bulk (OUT), 3 In (IN), 4 Bulk (IN), 5 Bulk (OUT), 6 In (IN) - // #define EPNUM_AUDIO_IN 0x01 - // #define EPNUM_AUDIO_OUT 0x02 - // #define EPNUM_AUDIO_INT 0x03 + #define EPNUM_AUDIO_IN 0x01 + #define EPNUM_AUDIO_OUT 0x02 + #define EPNUM_AUDIO_INT 0x03 #elif CFG_TUSB_MCU == OPT_MCU_NRF5X // ISO endpoints for NRF5x are fixed to 0x08 (0x88) diff --git a/hw/bsp/cxd56/FreeRTOSConfig/FreeRTOSConfig.h b/hw/bsp/cxd56/FreeRTOSConfig/FreeRTOSConfig.h new file mode 100644 index 000000000..57b9d7dba --- /dev/null +++ b/hw/bsp/cxd56/FreeRTOSConfig/FreeRTOSConfig.h @@ -0,0 +1,150 @@ +/* + * 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 "nuttx/config.h" +#endif + +/* Cortex-M4F 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 +// CXD56 (Cortex-M4F) has 3 priority bits +#define configPRIO_BITS 3 + +/* The lowest interrupt priority that can be used in a call to a "set priority" function. */ +#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1< + +#define LED_PIN PIN_I2S1_BCK +#define BUTTON_PIN PIN_HIF_IRQ_OUT + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/hw/bsp/cxd56/boards/spresense/board.mk b/hw/bsp/cxd56/boards/spresense/board.mk new file mode 100644 index 000000000..6c31c9d9d --- /dev/null +++ b/hw/bsp/cxd56/boards/spresense/board.mk @@ -0,0 +1,7 @@ +# Spresense board configuration +SERIAL ?= /dev/ttyUSB0 + +# flash +flash: $(BUILD)/$(PROJECT).spk + @echo FLASH $< + @$(PYTHON) $(TOP)/hw/mcu/sony/cxd56/tools/flash_writer.py -s -c $(SERIAL) -d -b 115200 -n $< diff --git a/hw/bsp/cxd56/family.c b/hw/bsp/cxd56/family.c new file mode 100644 index 000000000..a8e2fd52b --- /dev/null +++ b/hw/bsp/cxd56/family.c @@ -0,0 +1,112 @@ +/* + * The MIT License (MIT) + * + * Copyright 2019 Sony Semiconductor Solutions Corporation + * + * 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 + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +#include +#include + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + +#include "bsp/board_api.h" +#include "board.h" + +// Initialize on-board peripherals : led, button, uart and USB +void board_init(void) +{ + boardctl(BOARDIOC_INIT, 0); + + board_gpio_write(PIN_I2S1_BCK, -1); + board_gpio_config(PIN_I2S1_BCK, 0, false, true, PIN_FLOAT); + + board_gpio_write(PIN_HIF_IRQ_OUT, -1); + board_gpio_config(PIN_HIF_IRQ_OUT, 0, true, true, PIN_FLOAT); +}; + +void board_late_initialize(void) { + +} + +//--------------------------------------------------------------------+ +// Board porting API +//--------------------------------------------------------------------+ + +// Turn LED on or off +void board_led_write(bool state) +{ + board_gpio_write(LED_PIN, state); +} + +// Get the current state of button +// a '1' means active (pressed), a '0' means inactive. +uint32_t board_button_read(void) +{ + if (board_gpio_read(BUTTON_PIN)) + { + return 0; + } + + return 1; +} + +// Get characters from UART +int board_uart_read(uint8_t *buf, int len) +{ + int r = read(0, buf, len); + + return r; +} + +// Send characters to UART +int board_uart_write(void const *buf, int len) +{ + int r = write(1, buf, len); + + return r; +} + +// Get current milliseconds +uint32_t board_millis(void) +{ + struct timespec tp; + + /* Wait until RTC is available */ + while (g_rtc_enabled == false); + + if (clock_gettime(CLOCK_MONOTONIC, &tp)) + { + return 0; + } + + return (((uint64_t)tp.tv_sec) * 1000 + tp.tv_nsec / 1000000); +} diff --git a/hw/bsp/cxd56/family.cmake b/hw/bsp/cxd56/family.cmake new file mode 100644 index 000000000..993f8f456 --- /dev/null +++ b/hw/bsp/cxd56/family.cmake @@ -0,0 +1,135 @@ +include_guard() + +# include board specific +include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) + +set(SDK_DIR ${TOP}/hw/mcu/sony/cxd56/spresense-exported-sdk) + +# 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 CXD56 CACHE INTERNAL "") + +# Detect platform for mkspk tool +set(PLATFORM ${CMAKE_SYSTEM_NAME}) +if(PLATFORM STREQUAL "Darwin") + set(MKSPK ${TOP}/hw/mcu/sony/cxd56/mkspk/mkspk) +elseif(PLATFORM STREQUAL "Linux") + set(MKSPK ${TOP}/hw/mcu/sony/cxd56/mkspk/mkspk) +else() + set(MKSPK ${TOP}/hw/mcu/sony/cxd56/mkspk/mkspk.exe) +endif() + +#------------------------------------ +# BOARD_TARGET +#------------------------------------ +function(add_board_target BOARD_TARGET) + if (TARGET ${BOARD_TARGET}) + return() + endif () + + set(LD_FILE_GNU ${SDK_DIR}/nuttx/scripts/ramconfig.ld) + set(LD_FILE_Clang ${LD_FILE_GNU}) + + if (NOT DEFINED LD_FILE_${CMAKE_C_COMPILER_ID}) + message(FATAL_ERROR "LD_FILE_${CMAKE_C_COMPILER_ID} not defined") + endif () + + # Spresense uses NuttX libraries + add_library(${BOARD_TARGET} INTERFACE) + + target_include_directories(${BOARD_TARGET} INTERFACE + ${SDK_DIR}/nuttx/include + ${SDK_DIR}/nuttx/arch + ${SDK_DIR}/nuttx/arch/chip + ${SDK_DIR}/nuttx/arch/os + ${SDK_DIR}/sdk/include + ) + + target_compile_definitions(${BOARD_TARGET} INTERFACE + CONFIG_HAVE_DOUBLE + main=spresense_main + ) + + target_compile_options(${BOARD_TARGET} INTERFACE + -pipe + -fno-builtin + -fno-strength-reduce + -fomit-frame-pointer + -Wno-error=undef + -Wno-error=cast-align + -Wno-error=unused-parameter + -Wno-error=shadow + -Wno-error=redundant-decls + ) + + update_board(${BOARD_TARGET}) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${BOARD_TARGET} INTERFACE + "LINKER:--script=${LD_FILE_GNU}" + -Xlinker --entry=__start + -nostartfiles + -nodefaultlibs + -Wl,--gc-sections + -u spresense_main + --specs=nosys.specs --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${BOARD_TARGET} INTERFACE + "LINKER:--script=${LD_FILE_Clang}" + -Xlinker --entry=__start + -nostartfiles + -nodefaultlibs + -u spresense_main + ) + endif () +endfunction() + + +#------------------------------------ +# Functions +#------------------------------------ +function(family_configure_example TARGET RTOS) + family_configure_common(${TARGET} ${RTOS}) + + # Board target + add_board_target(board_${BOARD}) + + #---------- Port Specific ---------- + target_sources(${TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ) + target_include_directories(${TARGET} PUBLIC + ${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_CXD56) + target_sources(${TARGET} PUBLIC + ${TOP}/src/portable/sony/cxd56/dcd_cxd56.c + ) + target_link_libraries(${TARGET} PUBLIC + board_${BOARD} + ${SDK_DIR}/nuttx/libs/libapps.a + ${SDK_DIR}/nuttx/libs/libnuttx.a + gcc # Compiler runtime support for FP operations like __aeabi_dmul + ) + + # Build mkspk tool + add_custom_command(OUTPUT ${MKSPK} + COMMAND $(MAKE) -C ${TOP}/hw/mcu/sony/cxd56/mkspk + COMMENT "Building mkspk tool" + ) + + # Create .spk file + add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}.spk + COMMAND ${MKSPK} -c 2 $ nuttx ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}.spk + DEPENDS ${TARGET} ${MKSPK} + COMMENT "Creating ${TARGET}.spk" + ) +endfunction() diff --git a/hw/bsp/cxd56/family.mk b/hw/bsp/cxd56/family.mk new file mode 100644 index 000000000..adfe9ee82 --- /dev/null +++ b/hw/bsp/cxd56/family.mk @@ -0,0 +1,70 @@ +include $(TOP)/$(BOARD_PATH)/board.mk + +# Platforms are: Linux, Darwin, MSYS, CYGWIN +PLATFORM := $(firstword $(subst _, ,$(shell uname -s 2>/dev/null))) + +ifeq ($(PLATFORM),Darwin) + # macOS + MKSPK = $(TOP)/hw/mcu/sony/cxd56/mkspk/mkspk +else ifeq ($(PLATFORM),Linux) + # Linux + MKSPK = $(TOP)/hw/mcu/sony/cxd56/mkspk/mkspk +else + # Cygwin/MSYS2 + MKSPK = $(TOP)/hw/mcu/sony/cxd56/mkspk/mkspk.exe +endif + +CFLAGS += \ + -DCONFIG_HAVE_DOUBLE \ + -Dmain=spresense_main \ + -pipe \ + -std=gnu11 \ + -fno-strength-reduce \ + -fomit-frame-pointer \ + -Wno-error=undef \ + -Wno-error=cast-align \ + -Wno-error=unused-parameter \ + -DCFG_TUSB_MCU=OPT_MCU_CXD56 \ + +CPU_CORE ?= cortex-m4 + +# suppress following warnings from mcu driver +# lwip/src/core/raw.c:334:43: error: declaration of 'recv' shadows a global declaration +CFLAGS += -Wno-error=shadow -Wno-error=redundant-decls + +LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs + +SPRESENSE_SDK = $(TOP)/hw/mcu/sony/cxd56/spresense-exported-sdk + +SRC_C += src/portable/sony/cxd56/dcd_cxd56.c + +INC += \ + $(SPRESENSE_SDK)/nuttx/include \ + $(SPRESENSE_SDK)/nuttx/arch \ + $(SPRESENSE_SDK)/nuttx/arch/chip \ + $(SPRESENSE_SDK)/nuttx/arch/os \ + $(SPRESENSE_SDK)/sdk/include \ + $(TOP)/$(BOARD_PATH) + +LIBS += \ + $(SPRESENSE_SDK)/nuttx/libs/libapps.a \ + $(SPRESENSE_SDK)/nuttx/libs/libnuttx.a \ + +LD_FILE = hw/mcu/sony/cxd56/spresense-exported-sdk/nuttx/scripts/ramconfig.ld + +LDFLAGS += \ + -Xlinker --entry=__start \ + -nostartfiles \ + -nodefaultlibs \ + -Wl,--gc-sections \ + -u spresense_main + +$(MKSPK): $(BUILD)/$(PROJECT).elf + $(MAKE) -C $(TOP)/hw/mcu/sony/cxd56/mkspk + +$(BUILD)/$(PROJECT).spk: $(MKSPK) + @echo CREATE $@ + @$(MKSPK) -c 2 $(BUILD)/$(PROJECT).elf nuttx $@ + +# For freeRTOS port source +FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/ARM_CM4F diff --git a/hw/bsp/family_support.mk b/hw/bsp/family_support.mk index 2e236dc4a..db410a657 100644 --- a/hw/bsp/family_support.mk +++ b/hw/bsp/family_support.mk @@ -64,34 +64,20 @@ BUILD := _build/$(BOARD) PROJECT := $(notdir $(CURDIR)) #------------------------------------------------------------- -# Board / Family +# Family and Board #------------------------------------------------------------- - -# Board without family -ifneq ($(wildcard $(TOP)/hw/bsp/$(BOARD)/board.mk),) - BOARD_PATH := hw/bsp/$(BOARD) - FAMILY := -endif - -# Board within family -ifeq ($(BOARD_PATH),) - BOARD_PATH := $(subst $(TOP)/,,$(wildcard $(TOP)/hw/bsp/*/boards/$(BOARD))) - FAMILY := $(word 3, $(subst /, ,$(BOARD_PATH))) - FAMILY_PATH = hw/bsp/$(FAMILY) -endif +BOARD_PATH := $(subst $(TOP)/,,$(wildcard $(TOP)/hw/bsp/*/boards/$(BOARD))) +FAMILY := $(word 3, $(subst /, ,$(BOARD_PATH))) +FAMILY_PATH = hw/bsp/$(FAMILY) ifeq ($(BOARD_PATH),) $(info You must provide a BOARD parameter with 'BOARD=') $(error Invalid BOARD specified) endif -ifeq ($(FAMILY),) - include $(TOP)/hw/bsp/$(BOARD)/board.mk -else - # Include Family and Board specific defs - include $(TOP)/$(FAMILY_PATH)/family.mk - SRC_C += $(subst $(TOP)/,,$(wildcard $(TOP)/$(FAMILY_PATH)/*.c)) -endif +# Include Family and Board specific defs +include $(TOP)/$(FAMILY_PATH)/family.mk +SRC_C += $(subst $(TOP)/,,$(wildcard $(TOP)/$(FAMILY_PATH)/*.c)) #------------------------------------------------------------- # Source files and compiler flags diff --git a/hw/bsp/fomu/family.mk b/hw/bsp/fomu/family.mk index 69a546964..c29b1c70f 100644 --- a/hw/bsp/fomu/family.mk +++ b/hw/bsp/fomu/family.mk @@ -27,7 +27,7 @@ FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/RISC-V # flash using dfu-util $(BUILD)/$(PROJECT).dfu: $(BUILD)/$(PROJECT).bin @echo "Create $@" - python $(TOP)/hw/bsp/$(BOARD)/dfu.py -b $^ -D 0x1209:0x5bf0 $@ + python $(TOP)/$(FAMILY_PATH)/dfu.py -b $^ -D 0x1209:0x5bf0 $@ flash: $(BUILD)/$(PROJECT).dfu dfu-util -D $^ diff --git a/hw/bsp/spresense/board.mk b/hw/bsp/spresense/board.mk deleted file mode 100644 index 24f39d2b6..000000000 --- a/hw/bsp/spresense/board.mk +++ /dev/null @@ -1,75 +0,0 @@ -# Platforms are: Linux, Darwin, MSYS, CYGWIN -PLATFORM := $(firstword $(subst _, ,$(shell uname -s 2>/dev/null))) - -ifeq ($(PLATFORM),Darwin) - # macOS - MKSPK = $(TOP)/hw/mcu/sony/cxd56/mkspk/mkspk -else ifeq ($(PLATFORM),Linux) - # Linux - MKSPK = $(TOP)/hw/mcu/sony/cxd56/mkspk/mkspk -else - # Cygwin/MSYS2 - MKSPK = $(TOP)/hw/mcu/sony/cxd56/mkspk/mkspk.exe -endif - -SERIAL ?= /dev/ttyUSB0 - -CFLAGS += \ - -DCONFIG_HAVE_DOUBLE \ - -Dmain=spresense_main \ - -pipe \ - -std=gnu11 \ - -mcpu=cortex-m4 \ - -mthumb \ - -mfpu=fpv4-sp-d16 \ - -mfloat-abi=hard \ - -mabi=aapcs \ - -fno-builtin \ - -fno-strength-reduce \ - -fomit-frame-pointer \ - -Wno-error=undef \ - -Wno-error=cast-align \ - -Wno-error=unused-parameter \ - -DCFG_TUSB_MCU=OPT_MCU_CXD56 \ - -# suppress following warnings from mcu driver -# lwip/src/core/raw.c:334:43: error: declaration of 'recv' shadows a global declaration -CFLAGS += -Wno-error=shadow -Wno-error=redundant-decls - -LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs - -SPRESENSE_SDK = $(TOP)/hw/mcu/sony/cxd56/spresense-exported-sdk - -SRC_C += src/portable/sony/cxd56/dcd_cxd56.c - -INC += \ - $(SPRESENSE_SDK)/nuttx/include \ - $(SPRESENSE_SDK)/nuttx/arch \ - $(SPRESENSE_SDK)/nuttx/arch/chip \ - $(SPRESENSE_SDK)/nuttx/arch/os \ - $(SPRESENSE_SDK)/sdk/include \ - -LIBS += \ - $(SPRESENSE_SDK)/nuttx/libs/libapps.a \ - $(SPRESENSE_SDK)/nuttx/libs/libnuttx.a \ - -LD_FILE = hw/mcu/sony/cxd56/spresense-exported-sdk/nuttx/scripts/ramconfig.ld - -LDFLAGS += \ - -Xlinker --entry=__start \ - -nostartfiles \ - -nodefaultlibs \ - -Wl,--gc-sections \ - -u spresense_main - -$(MKSPK): $(BUILD)/$(PROJECT).elf - $(MAKE) -C $(TOP)/hw/mcu/sony/cxd56/mkspk - -$(BUILD)/$(PROJECT).spk: $(MKSPK) - @echo CREATE $@ - @$(MKSPK) -c 2 $(BUILD)/$(PROJECT).elf nuttx $@ - -# flash -flash: $(BUILD)/$(PROJECT).spk - @echo FLASH $< - @$(PYTHON) $(TOP)/hw/mcu/sony/cxd56/tools/flash_writer.py -s -c $(SERIAL) -d -b 115200 -n $< diff --git a/hw/bsp/spresense/board_spresense.c b/hw/bsp/spresense/board_spresense.c deleted file mode 100644 index 8cd04a49d..000000000 --- a/hw/bsp/spresense/board_spresense.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright 2019 Sony Semiconductor Solutions Corporation - * - * 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 -#include -#include -#include - -#include "bsp/board_api.h" - -/*------------------------------------------------------------------*/ -/* MACRO TYPEDEF CONSTANT ENUM - *------------------------------------------------------------------*/ -#define LED_PIN PIN_I2S1_BCK - -#define BUTTON_PIN PIN_HIF_IRQ_OUT - -// Initialize on-board peripherals : led, button, uart and USB -void board_init(void) -{ - boardctl(BOARDIOC_INIT, 0); - - board_gpio_write(PIN_I2S1_BCK, -1); - board_gpio_config(PIN_I2S1_BCK, 0, false, true, PIN_FLOAT); - - board_gpio_write(PIN_HIF_IRQ_OUT, -1); - board_gpio_config(PIN_HIF_IRQ_OUT, 0, true, true, PIN_FLOAT); -}; - -//--------------------------------------------------------------------+ -// Board porting API -//--------------------------------------------------------------------+ - -// Turn LED on or off -void board_led_write(bool state) -{ - board_gpio_write(LED_PIN, state); -} - -// Get the current state of button -// a '1' means active (pressed), a '0' means inactive. -uint32_t board_button_read(void) -{ - if (board_gpio_read(BUTTON_PIN)) - { - return 0; - } - - return 1; -} - -// Get characters from UART -int board_uart_read(uint8_t *buf, int len) -{ - int r = read(0, buf, len); - - return r; -} - -// Send characters to UART -int board_uart_write(void const *buf, int len) -{ - int r = write(1, buf, len); - - return r; -} - -// Get current milliseconds -uint32_t board_millis(void) -{ - struct timespec tp; - - /* Wait until RTC is available */ - while (g_rtc_enabled == false); - - if (clock_gettime(CLOCK_MONOTONIC, &tp)) - { - return 0; - } - - return (((uint64_t)tp.tv_sec) * 1000 + tp.tv_nsec / 1000000); -} diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index d0a502367..0b8ed1059 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -359,6 +359,7 @@ #define TUP_DCD_ENDPOINT_MAX 7 #define TUP_RHPORT_HIGHSPEED 1 #define TUD_ENDPOINT_ONE_DIRECTION_ONLY + #define TUP_DCD_EDPT_ISO_ALLOC //--------------------------------------------------------------------+ // TI diff --git a/src/portable/sony/cxd56/dcd_cxd56.c b/src/portable/sony/cxd56/dcd_cxd56.c index b16509c6f..a13cd152c 100644 --- a/src/portable/sony/cxd56/dcd_cxd56.c +++ b/src/portable/sony/cxd56/dcd_cxd56.c @@ -339,6 +339,19 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *p_endpoint_desc) return true; } +bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { + (void) rhport; + (void) ep_addr; + (void) largest_packet_size; + return false; // TODO not implemented yet +} + +bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) { + (void) rhport; + (void) desc_ep; + return false; // TODO not implemented yet +} + void dcd_edpt_close_all (uint8_t rhport) { (void) rhport; -- cgit v1.3.1 From 31bd4fc169eb002ded3f23e8a6a0b95f3f591efb Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 22 Oct 2025 05:28:31 +0000 Subject: Add is_isr parameter to dcd_edpt_xfer and dcd_edpt_xfer_fifo Co-authored-by: HiFiPhile <4375114+HiFiPhile@users.noreply.github.com> --- src/device/dcd.h | 4 ++-- src/device/usbd.c | 8 ++++---- src/portable/bridgetek/ft9xx/dcd_ft9xx.c | 9 ++++++--- src/portable/chipidea/ci_fs/dcd_ci_fs.c | 6 ++++-- src/portable/chipidea/ci_hs/dcd_ci_hs.c | 9 ++++++--- src/portable/dialog/da146xx/dcd_da146xx.c | 6 ++++-- src/portable/mentor/musb/dcd_musb.c | 7 +++++-- src/portable/microchip/pic/dcd_pic.c | 6 ++++-- src/portable/microchip/pic32mz/dcd_pic32mz.c | 4 +++- src/portable/microchip/samd/dcd_samd.c | 6 ++++-- src/portable/microchip/samg/dcd_samg.c | 9 ++++++--- src/portable/microchip/samx7x/dcd_samx7x.c | 9 ++++++--- src/portable/mindmotion/mm32/dcd_mm32f327x_otg.c | 6 ++++-- src/portable/nordic/nrf5x/dcd_nrf5x.c | 4 +++- src/portable/nuvoton/nuc120/dcd_nuc120.c | 7 +++++-- src/portable/nuvoton/nuc121/dcd_nuc121.c | 7 +++++-- src/portable/nuvoton/nuc505/dcd_nuc505.c | 7 +++++-- src/portable/nxp/khci/dcd_khci.c | 6 ++++-- src/portable/nxp/lpc17_40/dcd_lpc17_40.c | 6 ++++-- src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c | 7 +++++-- src/portable/raspberrypi/pio_usb/dcd_pio_usb.c | 8 +++++--- src/portable/raspberrypi/rp2040/dcd_rp2040.c | 4 +++- src/portable/renesas/rusb2/dcd_rusb2.c | 7 +++++-- src/portable/sony/cxd56/dcd_cxd56.c | 4 +++- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 9 ++++++--- src/portable/sunxi/dcd_sunxi_musb.c | 7 +++++-- src/portable/synopsys/dwc2/dcd_dwc2.c | 17 ++++++++++------- src/portable/template/dcd_template.c | 7 +++++-- src/portable/ti/msp430x5xx/dcd_msp430x5xx.c | 9 ++++++--- src/portable/valentyusb/eptri/dcd_eptri.c | 6 ++++-- src/portable/wch/dcd_ch32_usbfs.c | 6 ++++-- src/portable/wch/dcd_ch32_usbhs.c | 6 ++++-- test/unit-test/test/device/msc/test_msc_device.c | 10 +++++----- test/unit-test/test/device/usbd/test_usbd.c | 16 ++++++++-------- 34 files changed, 162 insertions(+), 87 deletions(-) (limited to 'src/portable') diff --git a/src/device/dcd.h b/src/device/dcd.h index 400f62bff..f90156235 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -158,11 +158,11 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc void dcd_edpt_close_all (uint8_t rhport); // Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack -bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); +bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr); // Submit an transfer using fifo, When complete dcd_event_xfer_complete() is invoked to notify the stack // This API is optional, may be useful for register-based for transferring data. -bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes); +bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes, bool is_isr); // Stall endpoint, any queuing transfer should be removed from endpoint void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr); diff --git a/src/device/usbd.c b/src/device/usbd.c index 339ccf4b4..d5ebcc66b 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -415,8 +415,8 @@ TU_ATTR_WEAK usbd_class_driver_t const* usbd_app_driver_get_cb(uint8_t* driver_c return NULL; } -TU_ATTR_WEAK bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) { - (void) rhport; (void) ep_addr; (void) ff; (void) total_bytes; +TU_ATTR_WEAK bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes, bool is_isr) { + (void) rhport; (void) ep_addr; (void) ff; (void) total_bytes; (void) is_isr; return false; } @@ -1433,7 +1433,7 @@ bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t t // could return and USBD task can preempt and clear the busy _usbd_dev.ep_status[epnum][dir].busy = 1; - if (dcd_edpt_xfer(rhport, ep_addr, buffer, total_bytes)) { + if (dcd_edpt_xfer(rhport, ep_addr, buffer, total_bytes, false)) { return true; } else { // DCD error, mark endpoint as ready to allow next transfer @@ -1464,7 +1464,7 @@ bool usbd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_ // and usbd task can preempt and clear the busy _usbd_dev.ep_status[epnum][dir].busy = 1; - if (dcd_edpt_xfer_fifo(rhport, ep_addr, ff, total_bytes)) { + if (dcd_edpt_xfer_fifo(rhport, ep_addr, ff, total_bytes, false)) { TU_LOG_USBD("OK\r\n"); return true; } else { diff --git a/src/portable/bridgetek/ft9xx/dcd_ft9xx.c b/src/portable/bridgetek/ft9xx/dcd_ft9xx.c index 34a8be3b6..f6def44ab 100644 --- a/src/portable/bridgetek/ft9xx/dcd_ft9xx.c +++ b/src/portable/bridgetek/ft9xx/dcd_ft9xx.c @@ -1,3 +1,4 @@ + /* * The MIT License (MIT) * @@ -556,7 +557,7 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) (void)dev_addr; // Respond with status. There is no checking that the address is in range. - dcd_edpt_xfer(rhport, tu_edpt_addr(USBD_EP_0, TUSB_DIR_IN), NULL, 0); + dcd_edpt_xfer(rhport, tu_edpt_addr(USBD_EP_0, TUSB_DIR_IN), NULL, 0, false); // Set the update bit for the address register. dev_addr |= 0x80; @@ -807,8 +808,9 @@ void dcd_edpt_close_all(uint8_t rhport) } // Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes) +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) { + (void) is_isr; (void)rhport; uint8_t ep_number = tu_edpt_number(ep_addr); uint8_t ep_dir = tu_edpt_dir(ep_addr); @@ -891,8 +893,9 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to } // Submit a transfer where is managed by FIFO, When complete dcd_event_xfer_complete() is invoked to notify the stack - optional, however, must be listed in usbd.c -bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t *ff, uint16_t total_bytes) +bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes, bool is_isr) { + (void) is_isr; (void)rhport; (void)ep_addr; (void)ff; diff --git a/src/portable/chipidea/ci_fs/dcd_ci_fs.c b/src/portable/chipidea/ci_fs/dcd_ci_fs.c index 11ddb683f..6bf3450ed 100644 --- a/src/portable/chipidea/ci_fs/dcd_ci_fs.c +++ b/src/portable/chipidea/ci_fs/dcd_ci_fs.c @@ -1,3 +1,4 @@ + /* * The MIT License (MIT) * @@ -303,7 +304,7 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) { _dcd.addr = dev_addr & 0x7F; /* Response with status first before changing device address */ - dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); + dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0, false); } void dcd_remote_wakeup(uint8_t rhport) @@ -419,8 +420,9 @@ void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) dcd_int_enable(rhport); } -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) { + (void) is_isr; const unsigned epn = tu_edpt_number(ep_addr); const unsigned dir = tu_edpt_dir(ep_addr); endpoint_state_t *ep = &_dcd.endpoint[epn][dir]; diff --git a/src/portable/chipidea/ci_hs/dcd_ci_hs.c b/src/portable/chipidea/ci_hs/dcd_ci_hs.c index 244f5a2d4..a11d2bbd1 100644 --- a/src/portable/chipidea/ci_hs/dcd_ci_hs.c +++ b/src/portable/chipidea/ci_hs/dcd_ci_hs.c @@ -1,3 +1,4 @@ + /* * The MIT License (MIT) * @@ -277,7 +278,7 @@ void dcd_int_disable(uint8_t rhport) void dcd_set_address(uint8_t rhport, uint8_t dev_addr) { // Response with status first before changing device address - dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); + dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0, false); ci_hs_regs_t* dcd_reg = CI_HS_REG(rhport); dcd_reg->DEVICEADDR = (dev_addr << 25) | TU_BIT(24); @@ -465,8 +466,9 @@ static void qhd_start_xfer(uint8_t rhport, uint8_t epnum, uint8_t dir) dcd_reg->ENDPTPRIME = TU_BIT(epnum + (dir ? 16 : 0)); } -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) { + (void) is_isr; uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); @@ -486,8 +488,9 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t t #if !CFG_TUD_MEM_DCACHE_ENABLE // fifo has to be aligned to 4k boundary // It's incompatible with dcache enabled transfer, since neither address nor size is aligned to cache line -bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes, bool is_isr) { + (void) is_isr; uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); diff --git a/src/portable/dialog/da146xx/dcd_da146xx.c b/src/portable/dialog/da146xx/dcd_da146xx.c index 56ecb7575..8666992aa 100644 --- a/src/portable/dialog/da146xx/dcd_da146xx.c +++ b/src/portable/dialog/da146xx/dcd_da146xx.c @@ -1,3 +1,4 @@ + /* * The MIT License (MIT) * @@ -837,7 +838,7 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) // Set default address for one ZLP USB->USB_EPC0_REG = USB_USB_EPC0_REG_USB_DEF_Msk; USB->USB_FAR_REG = (dev_addr & USB_USB_FAR_REG_USB_AD_Msk) | USB_USB_FAR_REG_USB_AD_EN_Msk; - dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); + dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0, false); } void dcd_remote_wakeup(uint8_t rhport) @@ -1025,8 +1026,9 @@ void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) tu_memclr(xfer, sizeof(*xfer)); } -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) { + (void) is_isr; 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); diff --git a/src/portable/mentor/musb/dcd_musb.c b/src/portable/mentor/musb/dcd_musb.c index 4fce08dd9..acb35fcee 100644 --- a/src/portable/mentor/musb/dcd_musb.c +++ b/src/portable/mentor/musb/dcd_musb.c @@ -1,3 +1,4 @@ + /* * The MIT License (MIT) * @@ -772,8 +773,9 @@ void dcd_edpt_close_all(uint8_t rhport) } // Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) { + (void) is_isr; (void)rhport; bool ret; // TU_LOG1("X %x %d\r\n", ep_addr, total_bytes); @@ -794,8 +796,9 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t t // Submit a transfer where is managed by FIFO, When complete dcd_event_xfer_complete() is invoked to notify the stack // - optional, however, must be listed in usbd.c -bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes, bool is_isr) { + (void) is_isr; (void)rhport; bool ret; // TU_LOG1("X %x %d\r\n", ep_addr, total_bytes); diff --git a/src/portable/microchip/pic/dcd_pic.c b/src/portable/microchip/pic/dcd_pic.c index b4a698199..7d92056e8 100644 --- a/src/portable/microchip/pic/dcd_pic.c +++ b/src/portable/microchip/pic/dcd_pic.c @@ -1,3 +1,4 @@ + /* * The MIT License (MIT) * @@ -545,7 +546,7 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) { _dcd.addr = dev_addr & 0x7F; /* Response with status first before changing device address */ - dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); + dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0, false); } void dcd_remote_wakeup(uint8_t rhport) @@ -687,8 +688,9 @@ void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) if (ie) intr_enable(rhport); } -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) { + (void) is_isr; const unsigned epn = tu_edpt_number(ep_addr); const unsigned dir = tu_edpt_dir(ep_addr); diff --git a/src/portable/microchip/pic32mz/dcd_pic32mz.c b/src/portable/microchip/pic32mz/dcd_pic32mz.c index cbd157d6b..ce53893ec 100644 --- a/src/portable/microchip/pic32mz/dcd_pic32mz.c +++ b/src/portable/microchip/pic32mz/dcd_pic32mz.c @@ -1,3 +1,4 @@ + /* * The MIT License (MIT) * @@ -444,8 +445,9 @@ void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) (void) ep_addr; } -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) { + (void) is_isr; 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); diff --git a/src/portable/microchip/samd/dcd_samd.c b/src/portable/microchip/samd/dcd_samd.c index e43439f2a..1ff314d39 100644 --- a/src/portable/microchip/samd/dcd_samd.c +++ b/src/portable/microchip/samd/dcd_samd.c @@ -1,3 +1,4 @@ + /* * The MIT License (MIT) * @@ -142,7 +143,7 @@ void dcd_set_address (uint8_t rhport, uint8_t dev_addr) (void) dev_addr; // Response with zlp status - dcd_edpt_xfer(rhport, 0x80, NULL, 0); + dcd_edpt_xfer(rhport, 0x80, NULL, 0, false); // DCD can only set address after status for this request is complete // do it at dcd_edpt0_status_complete() @@ -258,8 +259,9 @@ void dcd_edpt_close_all (uint8_t rhport) // TODO implement dcd_edpt_close_all() } -bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) { + (void) is_isr; (void) rhport; uint8_t const epnum = tu_edpt_number(ep_addr); diff --git a/src/portable/microchip/samg/dcd_samg.c b/src/portable/microchip/samg/dcd_samg.c index a5c768839..3ba538639 100644 --- a/src/portable/microchip/samg/dcd_samg.c +++ b/src/portable/microchip/samg/dcd_samg.c @@ -1,3 +1,4 @@ + /* * The MIT License (MIT) * @@ -175,7 +176,7 @@ void dcd_set_address (uint8_t rhport, uint8_t dev_addr) (void) dev_addr; // Response with zlp status - dcd_edpt_xfer(rhport, 0x80, NULL, 0); + dcd_edpt_xfer(rhport, 0x80, NULL, 0, false); // DCD can only set address after status for this request is complete. // do it at dcd_edpt0_status_complete() @@ -282,8 +283,9 @@ void dcd_edpt_close_all (uint8_t rhport) } // Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack -bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) { + (void) is_isr; (void) rhport; uint8_t const epnum = tu_edpt_number(ep_addr); @@ -309,8 +311,9 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t } #if 0 // TODO support dcd_edpt_xfer_fifo API -bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes, bool is_isr) { + (void) is_isr; (void) rhport; return true; } diff --git a/src/portable/microchip/samx7x/dcd_samx7x.c b/src/portable/microchip/samx7x/dcd_samx7x.c index 8aec1568d..494c83fde 100644 --- a/src/portable/microchip/samx7x/dcd_samx7x.c +++ b/src/portable/microchip/samx7x/dcd_samx7x.c @@ -1,3 +1,4 @@ + /* * The MIT License (MIT) * @@ -132,7 +133,7 @@ void dcd_set_address (uint8_t rhport, uint8_t dev_addr) // do it at dcd_edpt0_status_complete() // Response with zlp status - dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); + dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0, false); } // Wake up host @@ -605,8 +606,9 @@ static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix) } // Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack -bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) { + (void) is_isr; (void) rhport; uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); @@ -666,8 +668,9 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t // bytes should be written and second to keep the return value free to give back a boolean // success message. If total_bytes is too big, the FIFO will copy only what is available // into the USB buffer! -bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes, bool is_isr) { + (void) is_isr; (void) rhport; uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); diff --git a/src/portable/mindmotion/mm32/dcd_mm32f327x_otg.c b/src/portable/mindmotion/mm32/dcd_mm32f327x_otg.c index 1ce3da27e..5cec4defb 100644 --- a/src/portable/mindmotion/mm32/dcd_mm32f327x_otg.c +++ b/src/portable/mindmotion/mm32/dcd_mm32f327x_otg.c @@ -1,3 +1,4 @@ + /* * The MIT License (MIT) * @@ -282,7 +283,7 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) (void) rhport; _dcd.addr = dev_addr & 0x7F; /* Response with status first before changing device address */ - dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); + dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0, false); } #ifdef __GNUC__ // caused by extra declaration of SystemCoreClock in freeRTOSConfig.h @@ -381,8 +382,9 @@ void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) bd->head = 0; } -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) { + (void) is_isr; (void) rhport; NVIC_DisableIRQ(USB_FS_IRQn); const unsigned epn = ep_addr & 0xFu; diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c index 9e5f5117f..a2d634fe6 100644 --- a/src/portable/nordic/nrf5x/dcd_nrf5x.c +++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c @@ -1,3 +1,4 @@ + /* * The MIT License (MIT) * @@ -426,7 +427,8 @@ void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) { __DSB(); } -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) { +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) { + (void) is_isr; (void) rhport; uint8_t const epnum = tu_edpt_number(ep_addr); diff --git a/src/portable/nuvoton/nuc120/dcd_nuc120.c b/src/portable/nuvoton/nuc120/dcd_nuc120.c index 0edebf159..bb1d11355 100644 --- a/src/portable/nuvoton/nuc120/dcd_nuc120.c +++ b/src/portable/nuvoton/nuc120/dcd_nuc120.c @@ -1,3 +1,4 @@ + /* * The MIT License (MIT) * @@ -294,8 +295,9 @@ void dcd_edpt_close_all (uint8_t rhport) // TODO implement dcd_edpt_close_all() } -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes) +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) { + (void) is_isr; (void) rhport; /* mine the data for the information we need */ @@ -326,8 +328,9 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to } #if 0 // TODO support dcd_edpt_xfer_fifo API -bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes, bool is_isr) { + (void) is_isr; (void) rhport; /* mine the data for the information we need */ diff --git a/src/portable/nuvoton/nuc121/dcd_nuc121.c b/src/portable/nuvoton/nuc121/dcd_nuc121.c index 37210ea34..067d455c6 100644 --- a/src/portable/nuvoton/nuc121/dcd_nuc121.c +++ b/src/portable/nuvoton/nuc121/dcd_nuc121.c @@ -1,3 +1,4 @@ + /* * The MIT License (MIT) * @@ -323,8 +324,9 @@ void dcd_edpt_close_all (uint8_t rhport) // TODO implement dcd_edpt_close_all() } -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes) +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) { + (void) is_isr; (void) rhport; /* mine the data for the information we need */ @@ -355,8 +357,9 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to } #if 0 // TODO support dcd_edpt_xfer_fifo API -bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes, bool is_isr) { + (void) is_isr; (void) rhport; /* mine the data for the information we need */ diff --git a/src/portable/nuvoton/nuc505/dcd_nuc505.c b/src/portable/nuvoton/nuc505/dcd_nuc505.c index fa457d861..f7593cf25 100644 --- a/src/portable/nuvoton/nuc505/dcd_nuc505.c +++ b/src/portable/nuvoton/nuc505/dcd_nuc505.c @@ -1,3 +1,4 @@ + /* * The MIT License (MIT) * @@ -376,8 +377,9 @@ void dcd_edpt_close_all (uint8_t rhport) // TODO implement dcd_edpt_close_all() } -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes) +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) { + (void) is_isr; (void) rhport; if (0x80 == ep_addr) /* control EP0 IN */ @@ -437,8 +439,9 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to } #if 0 // TODO support dcd_edpt_xfer_fifo API -bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes, bool is_isr) { + (void) is_isr; (void) rhport; TU_ASSERT(0x80 != ep_addr && 0x00 != ep_addr); // Must not be used for control stuff diff --git a/src/portable/nxp/khci/dcd_khci.c b/src/portable/nxp/khci/dcd_khci.c index 3d5e195a9..395bf0d3d 100644 --- a/src/portable/nxp/khci/dcd_khci.c +++ b/src/portable/nxp/khci/dcd_khci.c @@ -1,3 +1,4 @@ + /* * The MIT License (MIT) * @@ -314,7 +315,7 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) { _dcd.addr = dev_addr & 0x7F; /* Response with status first before changing device address */ - dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); + dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0, false); } void dcd_remote_wakeup(uint8_t rhport) @@ -428,8 +429,9 @@ void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) if (ie) NVIC_EnableIRQ(USB0_IRQn); } -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) { + (void) is_isr; (void) rhport; const unsigned epn = tu_edpt_number(ep_addr); const unsigned dir = tu_edpt_dir(ep_addr); diff --git a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c index 855c59cd1..81220e850 100644 --- a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c +++ b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c @@ -1,3 +1,4 @@ + /* * The MIT License (MIT) * @@ -205,7 +206,7 @@ void dcd_int_disable(uint8_t rhport) void dcd_set_address(uint8_t rhport, uint8_t dev_addr) { // Response with status first before changing device address - dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); + dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0, false); sie_write(SIE_CMDCODE_SET_ADDRESS, 1, 0x80 | dev_addr); // 7th bit is : device_enable @@ -399,8 +400,9 @@ static bool control_xact(uint8_t rhport, uint8_t dir, uint8_t * buffer, uint8_t return true; } -bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) { + (void) is_isr; // Control transfer is not DMA support, and must be done in slave mode if ( tu_edpt_number(ep_addr) == 0 ) { diff --git a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c index 7c637ce0c..6e889b473 100644 --- a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c +++ b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c @@ -1,3 +1,4 @@ + /* * The MIT License (MIT) * @@ -322,7 +323,7 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs; // Response with status first before changing device address - dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); + dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0, false); dcd_reg->DEVCMDSTAT &= ~DEVCMDSTAT_DEVICE_ADDR_MASK; dcd_reg->DEVCMDSTAT |= dev_addr; @@ -464,7 +465,8 @@ static void prepare_ep_xfer(uint8_t rhport, uint8_t ep_id, uint16_t buf_offset, ep_cs[0].cmd_sts.active = 1; } -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) { +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) { + (void) is_isr; uint8_t const ep_id = ep_addr2id(ep_addr); if (!buffer || total_bytes == 0) { @@ -486,6 +488,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to //--------------------------------------------------------------------+ static void bus_reset(uint8_t rhport) { + (void) is_isr; tu_memclr(&_dcd, sizeof(dcd_data_t)); edpt_reset_all(rhport); diff --git a/src/portable/raspberrypi/pio_usb/dcd_pio_usb.c b/src/portable/raspberrypi/pio_usb/dcd_pio_usb.c index 60afbd435..3653544d9 100644 --- a/src/portable/raspberrypi/pio_usb/dcd_pio_usb.c +++ b/src/portable/raspberrypi/pio_usb/dcd_pio_usb.c @@ -1,3 +1,4 @@ + /* * The MIT License (MIT) * @@ -76,7 +77,7 @@ void dcd_set_address (uint8_t rhport, uint8_t dev_addr) { // must be called before queuing status pio_usb_device_set_address(dev_addr); - dcd_edpt_xfer(rhport, 0x80, NULL, 0); + dcd_edpt_xfer(rhport, 0x80, NULL, 0, false); } // Wake up host @@ -114,15 +115,16 @@ void dcd_edpt_close_all (uint8_t rhport) } // Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack -bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) { + (void) is_isr; (void) rhport; endpoint_t *ep = pio_usb_device_get_endpoint_by_address(ep_addr); return pio_usb_ll_transfer_start(ep, buffer, total_bytes); } // Submit a transfer where is managed by FIFO, When complete dcd_event_xfer_complete() is invoked to notify the stack - optional, however, must be listed in usbd.c -//bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +//bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes, bool is_isr) //{ // (void) rhport; // (void) ep_addr; diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index a89c2f42b..0a7c250c2 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -1,3 +1,4 @@ + /* * The MIT License (MIT) * @@ -526,7 +527,8 @@ void dcd_edpt_close_all(uint8_t rhport) { reset_non_control_endpoints(); } -bool dcd_edpt_xfer(__unused uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) { +bool dcd_edpt_xfer(__unused uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes, bool is_isr) { + (void) is_isr; assert(rhport == 0); hw_endpoint_xfer(ep_addr, buffer, total_bytes); return true; diff --git a/src/portable/renesas/rusb2/dcd_rusb2.c b/src/portable/renesas/rusb2/dcd_rusb2.c index ecd28973c..9b875f0d1 100644 --- a/src/portable/renesas/rusb2/dcd_rusb2.c +++ b/src/portable/renesas/rusb2/dcd_rusb2.c @@ -1,3 +1,4 @@ + /* * The MIT License (MIT) * @@ -859,8 +860,9 @@ void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) _dcd.ep[dir][epn] = 0; } -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) { + (void) is_isr; rusb2_reg_t* rusb = RUSB2_REG(rhport); dcd_int_disable(rhport); @@ -870,8 +872,9 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to return r; } -bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes, bool is_isr) { + (void) is_isr; // USB buffers always work in bytes so to avoid unnecessary divisions we demand item_size = 1 TU_ASSERT(ff->item_size == 1); rusb2_reg_t* rusb = RUSB2_REG(rhport); diff --git a/src/portable/sony/cxd56/dcd_cxd56.c b/src/portable/sony/cxd56/dcd_cxd56.c index a13cd152c..664952b83 100644 --- a/src/portable/sony/cxd56/dcd_cxd56.c +++ b/src/portable/sony/cxd56/dcd_cxd56.c @@ -1,3 +1,4 @@ + /* * The MIT License (MIT) * @@ -358,8 +359,9 @@ void dcd_edpt_close_all (uint8_t rhport) // TODO implement dcd_edpt_close_all() } -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes) +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) { + (void) is_isr; (void) rhport; bool ret = true; diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index ed823a832..640481442 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -1,3 +1,4 @@ + /* * The MIT License (MIT) * @@ -246,7 +247,7 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) { (void)dev_addr; // Respond with status - dcd_edpt_xfer(rhport, TUSB_DIR_IN_MASK | 0x00, NULL, 0); + dcd_edpt_xfer(rhport, TUSB_DIR_IN_MASK | 0x00, NULL, 0, false); // DCD can only set address after status for this request is complete. // do it at dcd_edpt0_status_complete() @@ -788,7 +789,8 @@ static bool edpt_xfer(uint8_t rhport, uint8_t ep_num, tusb_dir_t dir) { return true; } -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes) { +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) { + (void) is_isr; uint8_t const ep_num = tu_edpt_number(ep_addr); tusb_dir_t const dir = tu_edpt_dir(ep_addr); xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, dir); @@ -801,7 +803,8 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to return edpt_xfer(rhport, ep_num, dir); } -bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t *ff, uint16_t total_bytes) { +bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes, bool is_isr) { + (void) is_isr; uint8_t const ep_num = tu_edpt_number(ep_addr); tusb_dir_t const dir = tu_edpt_dir(ep_addr); xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, dir); diff --git a/src/portable/sunxi/dcd_sunxi_musb.c b/src/portable/sunxi/dcd_sunxi_musb.c index f1f4897cb..52d69ad01 100644 --- a/src/portable/sunxi/dcd_sunxi_musb.c +++ b/src/portable/sunxi/dcd_sunxi_musb.c @@ -1,3 +1,4 @@ + /* * The MIT License (MIT) * @@ -1083,8 +1084,9 @@ void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) } // Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) { + (void) is_isr; (void)rhport; bool ret; // TU_LOG1("X %x %d\r\n", ep_addr, total_bytes); @@ -1102,8 +1104,9 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t t } // Submit a transfer where is managed by FIFO, When complete dcd_event_xfer_complete() is invoked to notify the stack - optional, however, must be listed in usbd.c -bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes, bool is_isr) { + (void) is_isr; (void)rhport; bool ret; // TU_LOG1("X %x %d\r\n", ep_addr, total_bytes); diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index f1e4dbd77..f3a0ee7fc 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -1,3 +1,4 @@ + /* * The MIT License (MIT) * @@ -456,7 +457,7 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) { dwc2->dcfg = (dwc2->dcfg & ~DCFG_DAD_Msk) | (dev_addr << DCFG_DAD_Pos); // Response with status after changing device address - dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); + dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0, false, false); } void dcd_remote_wakeup(uint8_t rhport) { @@ -577,13 +578,14 @@ bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * p_endpo return true; } -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) { +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes, bool is_isr) { + (void) is_isr; 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; - usbd_spin_lock(false); + usbd_spin_lock(is_isr); if (xfer->max_size == 0) { ret = false; // Endpoint is closed @@ -602,7 +604,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to ret = true; } - usbd_spin_unlock(false); + usbd_spin_unlock(is_isr); return ret; } @@ -611,7 +613,8 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to // bytes should be written and second to keep the return value free to give back a boolean // success message. If total_bytes is too big, the FIFO will copy only what is available // into the USB buffer! -bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_t total_bytes) { +bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_t total_bytes, bool is_isr) { + (void) is_isr; // USB buffers always work in bytes so to avoid unnecessary divisions we demand item_size = 1 TU_ASSERT(ff->item_size == 1); @@ -620,7 +623,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; - usbd_spin_lock(false); + usbd_spin_lock(is_isr); if (xfer->max_size == 0) { ret = false; // Endpoint is closed @@ -635,7 +638,7 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_t ret = true; } - usbd_spin_unlock(false); + usbd_spin_unlock(is_isr); return ret; } diff --git a/src/portable/template/dcd_template.c b/src/portable/template/dcd_template.c index 3738ac0cb..ff7995c11 100644 --- a/src/portable/template/dcd_template.c +++ b/src/portable/template/dcd_template.c @@ -1,3 +1,4 @@ + /* * The MIT License (MIT) * @@ -113,7 +114,8 @@ void dcd_edpt_close_all (uint8_t rhport) { } // Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack -bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) { +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) { + (void) is_isr; (void) rhport; (void) ep_addr; (void) buffer; @@ -122,7 +124,8 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t } // Submit a transfer where is managed by FIFO, When complete dcd_event_xfer_complete() is invoked to notify the stack - optional, however, must be listed in usbd.c -bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) { +bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes, bool is_isr) { + (void) is_isr; (void) rhport; (void) ep_addr; (void) ff; diff --git a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c index 64cbc5087..def55b59b 100644 --- a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c +++ b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c @@ -1,3 +1,4 @@ + /* * The MIT License (MIT) * @@ -219,7 +220,7 @@ void dcd_set_address (uint8_t rhport, uint8_t dev_addr) USBFUNADR = dev_addr; // Response with status after changing device address - dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); + dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0, false); } void dcd_remote_wakeup(uint8_t rhport) @@ -344,8 +345,9 @@ void dcd_edpt_close_all (uint8_t rhport) // TODO implement dcd_edpt_close_all() } -bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) { + (void) is_isr; (void) rhport; uint8_t const epnum = tu_edpt_number(ep_addr); @@ -393,8 +395,9 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t } #if 0 // TODO support dcd_edpt_xfer_fifo API -bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes, bool is_isr) { + (void) is_isr; (void) rhport; uint8_t const epnum = tu_edpt_number(ep_addr); diff --git a/src/portable/valentyusb/eptri/dcd_eptri.c b/src/portable/valentyusb/eptri/dcd_eptri.c index a03c94558..a389aa761 100644 --- a/src/portable/valentyusb/eptri/dcd_eptri.c +++ b/src/portable/valentyusb/eptri/dcd_eptri.c @@ -1,3 +1,4 @@ + /* * The MIT License (MIT) * @@ -375,7 +376,7 @@ void dcd_int_disable(uint8_t rhport) void dcd_set_address(uint8_t rhport, uint8_t dev_addr) { // Respond with ACK status first before changing device address - dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); + dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0, false); // Wait for the response packet to get sent while (tx_active) @@ -475,8 +476,9 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) // IN endpoints will get un-stalled when more data is written. } -bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) { + (void) is_isr; (void)rhport; uint8_t ep_num = tu_edpt_number(ep_addr); uint8_t ep_dir = tu_edpt_dir(ep_addr); diff --git a/src/portable/wch/dcd_ch32_usbfs.c b/src/portable/wch/dcd_ch32_usbfs.c index c248ba14e..c5b610b82 100644 --- a/src/portable/wch/dcd_ch32_usbfs.c +++ b/src/portable/wch/dcd_ch32_usbfs.c @@ -1,3 +1,4 @@ + /* * The MIT License (MIT) * @@ -218,7 +219,7 @@ void dcd_int_disable(uint8_t rhport) { void dcd_set_address(uint8_t rhport, uint8_t dev_addr) { (void) dev_addr; - dcd_edpt_xfer(rhport, 0x80, NULL, 0); // zlp status response + dcd_edpt_xfer(rhport, 0x80, NULL, 0, false); // zlp status response } void dcd_remote_wakeup(uint8_t rhport) { @@ -289,7 +290,8 @@ void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) { // TODO optional } -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) { +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) { + (void) is_isr; (void) rhport; uint8_t ep = tu_edpt_number(ep_addr); uint8_t dir = tu_edpt_dir(ep_addr); diff --git a/src/portable/wch/dcd_ch32_usbhs.c b/src/portable/wch/dcd_ch32_usbhs.c index 4a208b9df..cf2deab78 100644 --- a/src/portable/wch/dcd_ch32_usbhs.c +++ b/src/portable/wch/dcd_ch32_usbhs.c @@ -1,3 +1,4 @@ + /* * The MIT License (MIT) * @@ -203,7 +204,7 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) { (void) dev_addr; // Response with zlp status - dcd_edpt_xfer(rhport, 0x80, NULL, 0); + dcd_edpt_xfer(rhport, 0x80, NULL, 0, false); } void dcd_remote_wakeup(uint8_t rhport) { @@ -315,7 +316,8 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { } } -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) { +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) { + (void) is_isr; (void) rhport; uint8_t const ep_num = tu_edpt_number(ep_addr); tusb_dir_t const dir = tu_edpt_dir(ep_addr); 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 49843a921..ea02b7050 100644 --- a/test/unit-test/test/device/msc/test_msc_device.c +++ b/test/unit-test/test/device/msc/test_msc_device.c @@ -256,7 +256,7 @@ void test_msc(void) dcd_edpt_open_ExpectAndReturn(rhport, (tusb_desc_endpoint_t const *) tu_desc_next(desc_ep), true); // Prepare SCSI command - dcd_edpt_xfer_ExpectAndReturn(rhport, EDPT_MSC_OUT, NULL, sizeof(msc_cbw_t), true); + dcd_edpt_xfer_ExpectAndReturn(rhport, EDPT_MSC_OUT, NULL, sizeof(msc_cbw_t), false, true); dcd_edpt_xfer_IgnoreArg_buffer(); dcd_edpt_xfer_ReturnMemThruPtr_buffer( (uint8_t*) &cbw_read10, sizeof(msc_cbw_t)); @@ -264,20 +264,20 @@ void test_msc(void) dcd_event_xfer_complete(rhport, EDPT_MSC_OUT, sizeof(msc_cbw_t), 0, true); // control status - dcd_edpt_xfer_ExpectAndReturn(rhport, EDPT_CTRL_IN, NULL, 0, true); + dcd_edpt_xfer_ExpectAndReturn(rhport, EDPT_CTRL_IN, NULL, 0, false, true); // SCSI Data transfer - dcd_edpt_xfer_ExpectAndReturn(rhport, EDPT_MSC_IN, NULL, 512, true); + dcd_edpt_xfer_ExpectAndReturn(rhport, EDPT_MSC_IN, NULL, 512, false, true); dcd_edpt_xfer_IgnoreArg_buffer(); dcd_event_xfer_complete(rhport, EDPT_MSC_IN, 512, 0, true); // complete // SCSI Status - dcd_edpt_xfer_ExpectAndReturn(rhport, EDPT_MSC_IN, NULL, 13, true); + dcd_edpt_xfer_ExpectAndReturn(rhport, EDPT_MSC_IN, NULL, 13, false, true); dcd_edpt_xfer_IgnoreArg_buffer(); dcd_event_xfer_complete(rhport, EDPT_MSC_IN, 13, 0, true); // Prepare for next command - dcd_edpt_xfer_ExpectAndReturn(rhport, EDPT_MSC_OUT, NULL, sizeof(msc_cbw_t), true); + dcd_edpt_xfer_ExpectAndReturn(rhport, EDPT_MSC_OUT, NULL, sizeof(msc_cbw_t), false, true); dcd_edpt_xfer_IgnoreArg_buffer(); tud_task(); diff --git a/test/unit-test/test/device/usbd/test_usbd.c b/test/unit-test/test/device/usbd/test_usbd.c index f0153da3f..3a2cf3217 100644 --- a/test/unit-test/test/device/usbd/test_usbd.c +++ b/test/unit-test/test/device/usbd/test_usbd.c @@ -151,11 +151,11 @@ void test_usbd_get_device_descriptor(void) dcd_event_setup_received(rhport, (uint8_t*) &req_get_desc_device, false); // data - dcd_edpt_xfer_ExpectWithArrayAndReturn(rhport, 0x80, (uint8_t*)&data_desc_device, sizeof(tusb_desc_device_t), sizeof(tusb_desc_device_t), true); + dcd_edpt_xfer_ExpectWithArrayAndReturn(rhport, 0x80, (uint8_t*)&data_desc_device, sizeof(tusb_desc_device_t), sizeof(tusb_desc_device_t), false, true); dcd_event_xfer_complete(rhport, EDPT_CTRL_IN, sizeof(tusb_desc_device_t), 0, false); // status - dcd_edpt_xfer_ExpectAndReturn(rhport, EDPT_CTRL_OUT, NULL, 0, true); + dcd_edpt_xfer_ExpectAndReturn(rhport, EDPT_CTRL_OUT, NULL, 0, false, true); dcd_event_xfer_complete(rhport, EDPT_CTRL_OUT, 0, 0, false); dcd_edpt0_status_complete_ExpectWithArray(rhport, &req_get_desc_device, 1); @@ -184,11 +184,11 @@ void test_usbd_get_configuration_descriptor(void) dcd_event_setup_received(rhport, (uint8_t*) &req_get_desc_configuration, false); // data - dcd_edpt_xfer_ExpectWithArrayAndReturn(rhport, 0x80, (uint8_t*) data_desc_configuration, total_len, total_len, true); + dcd_edpt_xfer_ExpectWithArrayAndReturn(rhport, 0x80, (uint8_t*) data_desc_configuration, total_len, total_len, false, true); dcd_event_xfer_complete(rhport, EDPT_CTRL_IN, total_len, 0, false); // status - dcd_edpt_xfer_ExpectAndReturn(rhport, EDPT_CTRL_OUT, NULL, 0, true); + dcd_edpt_xfer_ExpectAndReturn(rhport, EDPT_CTRL_OUT, NULL, 0, false, true); dcd_event_xfer_complete(rhport, EDPT_CTRL_OUT, 0, 0, false); dcd_edpt0_status_complete_ExpectWithArray(rhport, &req_get_desc_configuration, 1); @@ -227,20 +227,20 @@ void test_usbd_control_in_zlp(void) // 1st transaction dcd_edpt_xfer_ExpectWithArrayAndReturn(rhport, EDPT_CTRL_IN, - zlp_desc_configuration, CFG_TUD_ENDPOINT0_SIZE, CFG_TUD_ENDPOINT0_SIZE, true); + zlp_desc_configuration, CFG_TUD_ENDPOINT0_SIZE, CFG_TUD_ENDPOINT0_SIZE, false, true); dcd_event_xfer_complete(rhport, EDPT_CTRL_IN, CFG_TUD_ENDPOINT0_SIZE, 0, false); // 2nd transaction dcd_edpt_xfer_ExpectWithArrayAndReturn(rhport, EDPT_CTRL_IN, - zlp_desc_configuration + CFG_TUD_ENDPOINT0_SIZE, CFG_TUD_ENDPOINT0_SIZE, CFG_TUD_ENDPOINT0_SIZE, true); + zlp_desc_configuration + CFG_TUD_ENDPOINT0_SIZE, CFG_TUD_ENDPOINT0_SIZE, CFG_TUD_ENDPOINT0_SIZE, false, true); dcd_event_xfer_complete(rhport, EDPT_CTRL_IN, CFG_TUD_ENDPOINT0_SIZE, 0, false); // Expect Zero length Packet - dcd_edpt_xfer_ExpectAndReturn(rhport, EDPT_CTRL_IN, NULL, 0, true); + dcd_edpt_xfer_ExpectAndReturn(rhport, EDPT_CTRL_IN, NULL, 0, false, true); dcd_event_xfer_complete(rhport, EDPT_CTRL_IN, 0, 0, false); // Status - dcd_edpt_xfer_ExpectAndReturn(rhport, EDPT_CTRL_OUT, NULL, 0, true); + dcd_edpt_xfer_ExpectAndReturn(rhport, EDPT_CTRL_OUT, NULL, 0, false, true); dcd_event_xfer_complete(rhport, EDPT_CTRL_OUT, 0, 0, false); dcd_edpt0_status_complete_ExpectWithArray(rhport, &req_get_desc_configuration, 1); -- cgit v1.3.1 From 16cfe6895a4ee6d6b196e99a033a7326908f8d8a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 22 Oct 2025 05:32:08 +0000 Subject: Fix duplicate is_isr parameter in dcd_dwc2.c Co-authored-by: HiFiPhile <4375114+HiFiPhile@users.noreply.github.com> --- hw/mcu/raspberry_pi/Pico-PIO-USB | 1 + hw/mcu/st/cmsis_device_f4 | 1 + hw/mcu/st/stm32f4xx_hal_driver | 1 + lib/CMSIS_5 | 1 + src/portable/synopsys/dwc2/dcd_dwc2.c | 2 +- 5 files changed, 5 insertions(+), 1 deletion(-) create mode 160000 hw/mcu/raspberry_pi/Pico-PIO-USB create mode 160000 hw/mcu/st/cmsis_device_f4 create mode 160000 hw/mcu/st/stm32f4xx_hal_driver create mode 160000 lib/CMSIS_5 (limited to 'src/portable') diff --git a/hw/mcu/raspberry_pi/Pico-PIO-USB b/hw/mcu/raspberry_pi/Pico-PIO-USB new file mode 160000 index 000000000..675543bcc --- /dev/null +++ b/hw/mcu/raspberry_pi/Pico-PIO-USB @@ -0,0 +1 @@ +Subproject commit 675543bcc9baa8170f868ab7ba316d418dbcf41f diff --git a/hw/mcu/st/cmsis_device_f4 b/hw/mcu/st/cmsis_device_f4 new file mode 160000 index 000000000..3c77349ce --- /dev/null +++ b/hw/mcu/st/cmsis_device_f4 @@ -0,0 +1 @@ +Subproject commit 3c77349ce04c8af401454cc51f85ea9a50e34fc1 diff --git a/hw/mcu/st/stm32f4xx_hal_driver b/hw/mcu/st/stm32f4xx_hal_driver new file mode 160000 index 000000000..b6f0ed382 --- /dev/null +++ b/hw/mcu/st/stm32f4xx_hal_driver @@ -0,0 +1 @@ +Subproject commit b6f0ed3829f3829eb358a2e7417d80bba1a42db7 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/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index f3a0ee7fc..ab30a06e8 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -457,7 +457,7 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) { dwc2->dcfg = (dwc2->dcfg & ~DCFG_DAD_Msk) | (dev_addr << DCFG_DAD_Pos); // Response with status after changing device address - dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0, false, false); + dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0, false); } void dcd_remote_wakeup(uint8_t rhport) { -- cgit v1.3.1 From 30132e8e6d39447c0633f96594ff4bdac06d6bc8 Mon Sep 17 00:00:00 2001 From: Mengsk Date: Wed, 22 Oct 2025 16:57:11 +0200 Subject: Fix copilot issues Signed-off-by: Mengsk --- hw/mcu/raspberry_pi/Pico-PIO-USB | 1 - hw/mcu/st/cmsis_device_f4 | 1 - hw/mcu/st/stm32f4xx_hal_driver | 1 - lib/CMSIS_5 | 1 - lib/FreeRTOS-Kernel | 1 - lib/lwip | 1 - src/class/audio/audio_device.c | 22 +++++++++++----------- src/class/cdc/cdc_device.c | 4 ++-- src/class/mtp/mtp_device.c | 2 +- src/class/net/ncm_device.c | 4 ++-- src/class/usbtmc/usbtmc_device.c | 2 +- src/portable/chipidea/ci_fs/dcd_ci_fs.c | 2 +- src/portable/mindmotion/mm32/dcd_mm32f327x_otg.c | 2 +- src/portable/nxp/khci/dcd_khci.c | 2 +- src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c | 1 - test/fuzz/dcd_fuzz.cc | 5 +++-- tools/uf2 | 1 - 17 files changed, 23 insertions(+), 30 deletions(-) delete mode 160000 hw/mcu/raspberry_pi/Pico-PIO-USB delete mode 160000 hw/mcu/st/cmsis_device_f4 delete mode 160000 hw/mcu/st/stm32f4xx_hal_driver delete mode 160000 lib/CMSIS_5 delete mode 160000 lib/FreeRTOS-Kernel delete mode 160000 lib/lwip delete mode 160000 tools/uf2 (limited to 'src/portable') diff --git a/hw/mcu/raspberry_pi/Pico-PIO-USB b/hw/mcu/raspberry_pi/Pico-PIO-USB deleted file mode 160000 index 675543bcc..000000000 --- a/hw/mcu/raspberry_pi/Pico-PIO-USB +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 675543bcc9baa8170f868ab7ba316d418dbcf41f diff --git a/hw/mcu/st/cmsis_device_f4 b/hw/mcu/st/cmsis_device_f4 deleted file mode 160000 index 3c77349ce..000000000 --- a/hw/mcu/st/cmsis_device_f4 +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 3c77349ce04c8af401454cc51f85ea9a50e34fc1 diff --git a/hw/mcu/st/stm32f4xx_hal_driver b/hw/mcu/st/stm32f4xx_hal_driver deleted file mode 160000 index b6f0ed382..000000000 --- a/hw/mcu/st/stm32f4xx_hal_driver +++ /dev/null @@ -1 +0,0 @@ -Subproject commit b6f0ed3829f3829eb358a2e7417d80bba1a42db7 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/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index af0be903f..6c972ca7a 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -520,10 +520,10 @@ static bool audiod_rx_xfer_isr(uint8_t rhport, audiod_function_t* audio, uint16_ 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, true), false); + TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->lin_buf_out, audio->ep_out_sz, true)); #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, true), false); + TU_VERIFY(usbd_edpt_xfer_fifo(rhport, audio->ep_out, &audio->ep_out_ff, audio->ep_out_sz, true)); #endif #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP @@ -607,7 +607,7 @@ bool tud_audio_int_n_write(uint8_t func_id, const audio_interrupt_data_t *data) // Check length if (tu_memcpy_s(int_ep_buf[func_id].buf, sizeof(int_ep_buf[func_id].buf), data, sizeof(audio_interrupt_data_t)) == 0) { // Schedule transmit - TU_ASSERT(usbd_edpt_xfer(_audiod_fct[func_id].rhport, _audiod_fct[func_id].ep_int, int_ep_buf[func_id].buf, sizeof(int_ep_buf[func_id].buf)), 0); + TU_ASSERT(usbd_edpt_xfer(_audiod_fct[func_id].rhport, _audiod_fct[func_id].ep_int, int_ep_buf[func_id].buf, sizeof(int_ep_buf[func_id].buf), false)); } else { // Release endpoint since we don't make any transfer usbd_edpt_release(_audiod_fct[func_id].rhport, _audiod_fct[func_id].ep_int); @@ -619,7 +619,7 @@ bool tud_audio_int_n_write(uint8_t func_id, const audio_interrupt_data_t *data) #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) { +static inline bool audiod_fb_send(audiod_function_t *audio, bool is_isr) { bool apply_correction = (TUSB_SPEED_FULL == tud_speed_get()) && audio->feedback.format_correction; // Format the feedback value if (apply_correction) { @@ -647,7 +647,7 @@ static inline bool audiod_fb_send(audiod_function_t *audio) { // 10.14 3 3 Linux, OSX // // We send 3 bytes since sending packet larger than wMaxPacketSize is pretty ugly - return usbd_edpt_xfer(audio->rhport, audio->ep_fb, (uint8_t *) audio->fb_buf, apply_correction ? 3 : 4); + return usbd_edpt_xfer(audio->rhport, audio->ep_fb, (uint8_t *) audio->fb_buf, apply_correction ? 3 : 4, is_isr); } #endif @@ -1133,10 +1133,10 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *p #endif // 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)); + TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->lin_buf_in, 0, false)); #else // Send everything in ISO EP FIFO - TU_VERIFY(usbd_edpt_xfer_fifo(rhport, audio->ep_in, &audio->ep_in_ff, 0)); + TU_VERIFY(usbd_edpt_xfer_fifo(rhport, audio->ep_in, &audio->ep_in_ff, 0, false)); #endif } #endif// CFG_TUD_AUDIO_ENABLE_EP_IN @@ -1152,9 +1152,9 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *p // 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); + TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->lin_buf_out, audio->ep_out_sz, false)); #else - TU_VERIFY(usbd_edpt_xfer_fifo(rhport, audio->ep_out, &audio->ep_out_ff, audio->ep_out_sz), false); + TU_VERIFY(usbd_edpt_xfer_fifo(rhport, audio->ep_out, &audio->ep_out_ff, audio->ep_out_sz, false)); #endif } @@ -1164,7 +1164,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *p audio->ep_fb = ep_addr; audio->feedback.frame_shift = desc_ep->bInterval - 1; // Schedule first feedback transmit - audiod_fb_send(audio); + audiod_fb_send(audio, false); } #endif #endif// CFG_TUD_AUDIO_ENABLE_EP_OUT @@ -1472,7 +1472,7 @@ bool audiod_xfer_isr(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint if (audio->ep_fb == ep_addr) { // Schedule a transmit with the new value if EP is not busy // Schedule next transmission - value is changed bytud_audio_n_fb_set() in the meantime or the old value gets sent - audiod_fb_send(audio); + audiod_fb_send(audio, true); return true; } #endif diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index bef430a5d..94c82cc77 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -196,7 +196,7 @@ bool tud_cdc_n_notify_uart_state (uint8_t itf, const cdc_notify_uart_state_t *st notify_msg->request.wLength = sizeof(cdc_notify_uart_state_t); notify_msg->serial_state = *state; - return usbd_edpt_xfer(p_cdc->rhport, p_cdc->ep_notify, (uint8_t *, false)notify_msg, 8 + sizeof(cdc_notify_uart_state_t)); + return usbd_edpt_xfer(p_cdc->rhport, p_cdc->ep_notify, (uint8_t *)notify_msg, 8 + sizeof(cdc_notify_uart_state_t), false); } bool tud_cdc_n_notify_conn_speed_change(uint8_t itf, const cdc_notify_conn_speed_change_t* conn_speed_change) { @@ -213,7 +213,7 @@ bool tud_cdc_n_notify_conn_speed_change(uint8_t itf, const cdc_notify_conn_speed 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 *, false)notify_msg, 8 + sizeof(cdc_notify_conn_speed_change_t)); + return usbd_edpt_xfer(p_cdc->rhport, p_cdc->ep_notify, (uint8_t *)notify_msg, 8 + sizeof(cdc_notify_conn_speed_change_t), false); } #endif diff --git a/src/class/mtp/mtp_device.c b/src/class/mtp/mtp_device.c index 0499f2dda..764019e42 100644 --- a/src/class/mtp/mtp_device.c +++ b/src/class/mtp/mtp_device.c @@ -251,7 +251,7 @@ bool tud_mtp_event_send(mtp_event_t* event) { TU_VERIFY(p_mtp->ep_event != 0); _mtpd_epbuf.buf_event = *event; TU_VERIFY(usbd_edpt_claim(p_mtp->rhport, p_mtp->ep_event)); // Claim the endpoint - return usbd_edpt_xfer(p_mtp->rhport, p_mtp->ep_event, (uint8_t*, false) &_mtpd_epbuf.buf_event, sizeof(mtp_event_t)); + return usbd_edpt_xfer(p_mtp->rhport, p_mtp->ep_event, (uint8_t*) &_mtpd_epbuf.buf_event, sizeof(mtp_event_t), false); } //--------------------------------------------------------------------+ diff --git a/src/class/net/ncm_device.c b/src/class/net/ncm_device.c index 5e6dc5610..335f6ad09 100644 --- a/src/class/net/ncm_device.c +++ b/src/class/net/ncm_device.c @@ -205,7 +205,7 @@ static void notification_xmit(uint8_t rhport, bool force_next) { uint16_t notif_len = sizeof(notify_speed_change.header) + notify_speed_change.header.wLength; ncm_epbuf.epnotif = notify_speed_change; - usbd_edpt_xfer(rhport, ncm_interface.ep_notif, (uint8_t*, false) &ncm_epbuf.epnotif, notif_len); + usbd_edpt_xfer(rhport, ncm_interface.ep_notif, (uint8_t*) &ncm_epbuf.epnotif, notif_len, false); ncm_interface.notification_xmit_state = NOTIFICATION_CONNECTED; ncm_interface.notification_xmit_is_running = true; @@ -227,7 +227,7 @@ static void notification_xmit(uint8_t rhport, bool force_next) { uint16_t notif_len = sizeof(notify_connected.header) + notify_connected.header.wLength; ncm_epbuf.epnotif = notify_connected; - usbd_edpt_xfer(rhport, ncm_interface.ep_notif, (uint8_t *, false) &ncm_epbuf.epnotif, notif_len); + usbd_edpt_xfer(rhport, ncm_interface.ep_notif, (uint8_t *) &ncm_epbuf.epnotif, notif_len, false); ncm_interface.notification_xmit_state = NOTIFICATION_DONE; ncm_interface.notification_xmit_is_running = true; diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index e97740079..4b0bb01ec 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -841,7 +841,7 @@ bool usbtmcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request }, .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 *, false) &intMsg, sizeof(intMsg)); + usbd_edpt_xfer(rhport, usbtmc_state.ep_int_in, (void *) &intMsg, sizeof(intMsg), false); } } else { rsp.statusByte = tud_usbtmc_get_stb_cb(&(rsp.USBTMC_status)); diff --git a/src/portable/chipidea/ci_fs/dcd_ci_fs.c b/src/portable/chipidea/ci_fs/dcd_ci_fs.c index 6bf3450ed..283baf645 100644 --- a/src/portable/chipidea/ci_fs/dcd_ci_fs.c +++ b/src/portable/chipidea/ci_fs/dcd_ci_fs.c @@ -132,7 +132,7 @@ static void prepare_next_setup_packet(uint8_t rhport) _dcd.bdt[0][1][in_odd].data = 1; _dcd.bdt[0][1][in_odd ^ 1].data = 0; dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_OUT), - _dcd.setup_packet, sizeof(_dcd.setup_packet)); + _dcd.setup_packet, sizeof(_dcd.setup_packet), false); } static void process_stall(uint8_t rhport) diff --git a/src/portable/mindmotion/mm32/dcd_mm32f327x_otg.c b/src/portable/mindmotion/mm32/dcd_mm32f327x_otg.c index 5cec4defb..6c0302031 100644 --- a/src/portable/mindmotion/mm32/dcd_mm32f327x_otg.c +++ b/src/portable/mindmotion/mm32/dcd_mm32f327x_otg.c @@ -128,7 +128,7 @@ static void prepare_next_setup_packet(uint8_t rhport) _dcd.bdt[0][1][in_odd].data = 1; _dcd.bdt[0][1][in_odd ^ 1].data = 0; dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_OUT), - _dcd.setup_packet, sizeof(_dcd.setup_packet)); + _dcd.setup_packet, sizeof(_dcd.setup_packet), false); } static void process_stall(uint8_t rhport) diff --git a/src/portable/nxp/khci/dcd_khci.c b/src/portable/nxp/khci/dcd_khci.c index 395bf0d3d..3b0de47f4 100644 --- a/src/portable/nxp/khci/dcd_khci.c +++ b/src/portable/nxp/khci/dcd_khci.c @@ -130,7 +130,7 @@ static void prepare_next_setup_packet(uint8_t rhport) _dcd.bdt[0][1][in_odd].data = 1; _dcd.bdt[0][1][in_odd ^ 1].data = 0; dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_OUT), - _dcd.setup_packet, sizeof(_dcd.setup_packet)); + _dcd.setup_packet, sizeof(_dcd.setup_packet), false); } static void process_stall(uint8_t rhport) diff --git a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c index 6e889b473..2257d0368 100644 --- a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c +++ b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c @@ -488,7 +488,6 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t t //--------------------------------------------------------------------+ static void bus_reset(uint8_t rhport) { - (void) is_isr; tu_memclr(&_dcd, sizeof(dcd_data_t)); edpt_reset_all(rhport); diff --git a/test/fuzz/dcd_fuzz.cc b/test/fuzz/dcd_fuzz.cc index 046a90555..7a5d51623 100644 --- a/test/fuzz/dcd_fuzz.cc +++ b/test/fuzz/dcd_fuzz.cc @@ -104,7 +104,7 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) { UNUSED(rhport); state.address = dev_addr; // Respond with status. - dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); + dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0, false); return; } @@ -160,10 +160,11 @@ void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) { // Submit a transfer, When complete dcd_event_xfer_complete() is invoked to // notify the stack bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, - uint16_t total_bytes) { + uint16_t total_bytes, bool is_isr) { UNUSED(rhport); UNUSED(buffer); UNUSED(total_bytes); + UNUSED(is_isr); uint8_t const dir = tu_edpt_dir(ep_addr); 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 -- cgit v1.3.1 From 925ba123dac77b1675abeb2455762b52fffdc29b Mon Sep 17 00:00:00 2001 From: Zixun LI Date: Wed, 22 Oct 2025 21:08:09 +0200 Subject: Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/portable/bridgetek/ft9xx/dcd_ft9xx.c | 1 - src/portable/chipidea/ci_fs/dcd_ci_fs.c | 1 - src/portable/chipidea/ci_hs/dcd_ci_hs.c | 1 - src/portable/dialog/da146xx/dcd_da146xx.c | 1 - src/portable/mentor/musb/dcd_musb.c | 1 - src/portable/microchip/pic/dcd_pic.c | 1 - src/portable/microchip/pic32mz/dcd_pic32mz.c | 1 - src/portable/microchip/samd/dcd_samd.c | 1 - src/portable/microchip/samg/dcd_samg.c | 1 - src/portable/microchip/samx7x/dcd_samx7x.c | 1 - src/portable/mindmotion/mm32/dcd_mm32f327x_otg.c | 1 - src/portable/nordic/nrf5x/dcd_nrf5x.c | 1 - src/portable/nuvoton/nuc120/dcd_nuc120.c | 1 - src/portable/nuvoton/nuc121/dcd_nuc121.c | 1 - src/portable/nuvoton/nuc505/dcd_nuc505.c | 1 - src/portable/nxp/khci/dcd_khci.c | 1 - src/portable/nxp/lpc17_40/dcd_lpc17_40.c | 1 - src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c | 1 - src/portable/raspberrypi/pio_usb/dcd_pio_usb.c | 1 - src/portable/raspberrypi/rp2040/dcd_rp2040.c | 1 - src/portable/renesas/rusb2/dcd_rusb2.c | 1 - src/portable/sony/cxd56/dcd_cxd56.c | 1 - src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 1 - src/portable/sunxi/dcd_sunxi_musb.c | 1 - src/portable/synopsys/dwc2/dcd_dwc2.c | 1 - src/portable/template/dcd_template.c | 1 - src/portable/ti/msp430x5xx/dcd_msp430x5xx.c | 1 - src/portable/valentyusb/eptri/dcd_eptri.c | 1 - src/portable/wch/dcd_ch32_usbfs.c | 1 - src/portable/wch/dcd_ch32_usbhs.c | 1 - 30 files changed, 30 deletions(-) (limited to 'src/portable') diff --git a/src/portable/bridgetek/ft9xx/dcd_ft9xx.c b/src/portable/bridgetek/ft9xx/dcd_ft9xx.c index f6def44ab..76a54e62e 100644 --- a/src/portable/bridgetek/ft9xx/dcd_ft9xx.c +++ b/src/portable/bridgetek/ft9xx/dcd_ft9xx.c @@ -1,4 +1,3 @@ - /* * The MIT License (MIT) * diff --git a/src/portable/chipidea/ci_fs/dcd_ci_fs.c b/src/portable/chipidea/ci_fs/dcd_ci_fs.c index 283baf645..558d64b57 100644 --- a/src/portable/chipidea/ci_fs/dcd_ci_fs.c +++ b/src/portable/chipidea/ci_fs/dcd_ci_fs.c @@ -1,4 +1,3 @@ - /* * The MIT License (MIT) * diff --git a/src/portable/chipidea/ci_hs/dcd_ci_hs.c b/src/portable/chipidea/ci_hs/dcd_ci_hs.c index a11d2bbd1..808c293a5 100644 --- a/src/portable/chipidea/ci_hs/dcd_ci_hs.c +++ b/src/portable/chipidea/ci_hs/dcd_ci_hs.c @@ -1,4 +1,3 @@ - /* * The MIT License (MIT) * diff --git a/src/portable/dialog/da146xx/dcd_da146xx.c b/src/portable/dialog/da146xx/dcd_da146xx.c index 8666992aa..5beb62b4d 100644 --- a/src/portable/dialog/da146xx/dcd_da146xx.c +++ b/src/portable/dialog/da146xx/dcd_da146xx.c @@ -1,4 +1,3 @@ - /* * The MIT License (MIT) * diff --git a/src/portable/mentor/musb/dcd_musb.c b/src/portable/mentor/musb/dcd_musb.c index acb35fcee..1e4ec0015 100644 --- a/src/portable/mentor/musb/dcd_musb.c +++ b/src/portable/mentor/musb/dcd_musb.c @@ -1,4 +1,3 @@ - /* * The MIT License (MIT) * diff --git a/src/portable/microchip/pic/dcd_pic.c b/src/portable/microchip/pic/dcd_pic.c index 7d92056e8..3114295de 100644 --- a/src/portable/microchip/pic/dcd_pic.c +++ b/src/portable/microchip/pic/dcd_pic.c @@ -1,4 +1,3 @@ - /* * The MIT License (MIT) * diff --git a/src/portable/microchip/pic32mz/dcd_pic32mz.c b/src/portable/microchip/pic32mz/dcd_pic32mz.c index ce53893ec..a903c3ae2 100644 --- a/src/portable/microchip/pic32mz/dcd_pic32mz.c +++ b/src/portable/microchip/pic32mz/dcd_pic32mz.c @@ -1,4 +1,3 @@ - /* * The MIT License (MIT) * diff --git a/src/portable/microchip/samd/dcd_samd.c b/src/portable/microchip/samd/dcd_samd.c index 1ff314d39..8293273e5 100644 --- a/src/portable/microchip/samd/dcd_samd.c +++ b/src/portable/microchip/samd/dcd_samd.c @@ -1,4 +1,3 @@ - /* * The MIT License (MIT) * diff --git a/src/portable/microchip/samg/dcd_samg.c b/src/portable/microchip/samg/dcd_samg.c index 3ba538639..c6c7f15d1 100644 --- a/src/portable/microchip/samg/dcd_samg.c +++ b/src/portable/microchip/samg/dcd_samg.c @@ -1,4 +1,3 @@ - /* * The MIT License (MIT) * diff --git a/src/portable/microchip/samx7x/dcd_samx7x.c b/src/portable/microchip/samx7x/dcd_samx7x.c index 494c83fde..57c0fcb4d 100644 --- a/src/portable/microchip/samx7x/dcd_samx7x.c +++ b/src/portable/microchip/samx7x/dcd_samx7x.c @@ -1,4 +1,3 @@ - /* * The MIT License (MIT) * diff --git a/src/portable/mindmotion/mm32/dcd_mm32f327x_otg.c b/src/portable/mindmotion/mm32/dcd_mm32f327x_otg.c index 6c0302031..929cb40c4 100644 --- a/src/portable/mindmotion/mm32/dcd_mm32f327x_otg.c +++ b/src/portable/mindmotion/mm32/dcd_mm32f327x_otg.c @@ -1,4 +1,3 @@ - /* * The MIT License (MIT) * diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c index a2d634fe6..89dff4995 100644 --- a/src/portable/nordic/nrf5x/dcd_nrf5x.c +++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c @@ -1,4 +1,3 @@ - /* * The MIT License (MIT) * diff --git a/src/portable/nuvoton/nuc120/dcd_nuc120.c b/src/portable/nuvoton/nuc120/dcd_nuc120.c index bb1d11355..d9a0e3fa8 100644 --- a/src/portable/nuvoton/nuc120/dcd_nuc120.c +++ b/src/portable/nuvoton/nuc120/dcd_nuc120.c @@ -1,4 +1,3 @@ - /* * The MIT License (MIT) * diff --git a/src/portable/nuvoton/nuc121/dcd_nuc121.c b/src/portable/nuvoton/nuc121/dcd_nuc121.c index 067d455c6..a4dfe24fa 100644 --- a/src/portable/nuvoton/nuc121/dcd_nuc121.c +++ b/src/portable/nuvoton/nuc121/dcd_nuc121.c @@ -1,4 +1,3 @@ - /* * The MIT License (MIT) * diff --git a/src/portable/nuvoton/nuc505/dcd_nuc505.c b/src/portable/nuvoton/nuc505/dcd_nuc505.c index f7593cf25..25e3f2203 100644 --- a/src/portable/nuvoton/nuc505/dcd_nuc505.c +++ b/src/portable/nuvoton/nuc505/dcd_nuc505.c @@ -1,4 +1,3 @@ - /* * The MIT License (MIT) * diff --git a/src/portable/nxp/khci/dcd_khci.c b/src/portable/nxp/khci/dcd_khci.c index 3b0de47f4..8941ca766 100644 --- a/src/portable/nxp/khci/dcd_khci.c +++ b/src/portable/nxp/khci/dcd_khci.c @@ -1,4 +1,3 @@ - /* * The MIT License (MIT) * diff --git a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c index 81220e850..364cf8de4 100644 --- a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c +++ b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c @@ -1,4 +1,3 @@ - /* * The MIT License (MIT) * diff --git a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c index 2257d0368..143b0277c 100644 --- a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c +++ b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c @@ -1,4 +1,3 @@ - /* * The MIT License (MIT) * diff --git a/src/portable/raspberrypi/pio_usb/dcd_pio_usb.c b/src/portable/raspberrypi/pio_usb/dcd_pio_usb.c index 3653544d9..5e3dd7faf 100644 --- a/src/portable/raspberrypi/pio_usb/dcd_pio_usb.c +++ b/src/portable/raspberrypi/pio_usb/dcd_pio_usb.c @@ -1,4 +1,3 @@ - /* * The MIT License (MIT) * diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index 0a7c250c2..15852f29f 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -1,4 +1,3 @@ - /* * The MIT License (MIT) * diff --git a/src/portable/renesas/rusb2/dcd_rusb2.c b/src/portable/renesas/rusb2/dcd_rusb2.c index 9b875f0d1..6ac1c5ee4 100644 --- a/src/portable/renesas/rusb2/dcd_rusb2.c +++ b/src/portable/renesas/rusb2/dcd_rusb2.c @@ -1,4 +1,3 @@ - /* * The MIT License (MIT) * diff --git a/src/portable/sony/cxd56/dcd_cxd56.c b/src/portable/sony/cxd56/dcd_cxd56.c index 664952b83..be694edfa 100644 --- a/src/portable/sony/cxd56/dcd_cxd56.c +++ b/src/portable/sony/cxd56/dcd_cxd56.c @@ -1,4 +1,3 @@ - /* * The MIT License (MIT) * diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 640481442..381aa0b40 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -1,4 +1,3 @@ - /* * The MIT License (MIT) * diff --git a/src/portable/sunxi/dcd_sunxi_musb.c b/src/portable/sunxi/dcd_sunxi_musb.c index 52d69ad01..46d05e3e6 100644 --- a/src/portable/sunxi/dcd_sunxi_musb.c +++ b/src/portable/sunxi/dcd_sunxi_musb.c @@ -1,4 +1,3 @@ - /* * The MIT License (MIT) * diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index ab30a06e8..ad78708b6 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -1,4 +1,3 @@ - /* * The MIT License (MIT) * diff --git a/src/portable/template/dcd_template.c b/src/portable/template/dcd_template.c index ff7995c11..90c672d19 100644 --- a/src/portable/template/dcd_template.c +++ b/src/portable/template/dcd_template.c @@ -1,4 +1,3 @@ - /* * The MIT License (MIT) * diff --git a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c index def55b59b..10c7d78c5 100644 --- a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c +++ b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c @@ -1,4 +1,3 @@ - /* * The MIT License (MIT) * diff --git a/src/portable/valentyusb/eptri/dcd_eptri.c b/src/portable/valentyusb/eptri/dcd_eptri.c index a389aa761..760f3c90a 100644 --- a/src/portable/valentyusb/eptri/dcd_eptri.c +++ b/src/portable/valentyusb/eptri/dcd_eptri.c @@ -1,4 +1,3 @@ - /* * The MIT License (MIT) * diff --git a/src/portable/wch/dcd_ch32_usbfs.c b/src/portable/wch/dcd_ch32_usbfs.c index c5b610b82..eb2ebd868 100644 --- a/src/portable/wch/dcd_ch32_usbfs.c +++ b/src/portable/wch/dcd_ch32_usbfs.c @@ -1,4 +1,3 @@ - /* * The MIT License (MIT) * diff --git a/src/portable/wch/dcd_ch32_usbhs.c b/src/portable/wch/dcd_ch32_usbhs.c index cf2deab78..a18eb3e81 100644 --- a/src/portable/wch/dcd_ch32_usbhs.c +++ b/src/portable/wch/dcd_ch32_usbhs.c @@ -1,4 +1,3 @@ - /* * The MIT License (MIT) * -- cgit v1.3.1 From 55c6d07af314627c55d595cc74d0d7694ce6f091 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 24 Oct 2025 14:28:59 +0700 Subject: fix more warnings --- hw/bsp/board_api.h | 6 ++++-- hw/bsp/samd5x_e5x/family.c | 2 +- hw/bsp/stm32f4/family.c | 2 +- hw/bsp/stm32f7/family.c | 2 +- hw/bsp/stm32h7/family.c | 4 ++-- hw/bsp/stm32h7rs/family.c | 2 +- hw/bsp/stm32n6/family.c | 2 +- src/common/tusb_types.h | 8 ++++---- src/device/dcd.h | 2 +- src/osal/osal.h | 2 +- src/osal/osal_none.h | 4 ++-- src/portable/synopsys/dwc2/dcd_dwc2.c | 6 +++--- src/tusb.c | 8 ++++++-- src/tusb_option.h | 10 +++++----- 14 files changed, 33 insertions(+), 27 deletions(-) (limited to 'src/portable') diff --git a/hw/bsp/board_api.h b/hw/bsp/board_api.h index 5ecd7797a..80d86a4aa 100644 --- a/hw/bsp/board_api.h +++ b/hw/bsp/board_api.h @@ -154,11 +154,13 @@ static inline size_t board_usb_get_serial(uint16_t desc_str1[], size_t max_chars // TODO work with make, but not working with esp32s3 cmake uid_len = board_get_unique_id(uid, sizeof(uid)); - if ( uid_len > max_chars / 2 ) uid_len = max_chars / 2; + if ( uid_len > max_chars / 2u ) { + uid_len = max_chars / 2u; + } for ( size_t i = 0; i < uid_len; i++ ) { for ( size_t j = 0; j < 2; j++ ) { - const char nibble_to_hex[16] = { + const unsigned char nibble_to_hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; diff --git a/hw/bsp/samd5x_e5x/family.c b/hw/bsp/samd5x_e5x/family.c index d53aa00d6..df6f19d0f 100644 --- a/hw/bsp/samd5x_e5x/family.c +++ b/hw/bsp/samd5x_e5x/family.c @@ -179,7 +179,7 @@ size_t board_get_unique_id(uint8_t id[], size_t max_len) { for (int i = 0; i < 4; i++) { uint32_t did = *((uint32_t const*) did_addr[i]); did = TU_BSWAP32(did); // swap endian to match samd51 uf2 bootloader - memcpy(id + i * 4, &did, 4); + memcpy(id + i * 4, &did, sizeof(uint32_t)); } return 16; diff --git a/hw/bsp/stm32f4/family.c b/hw/bsp/stm32f4/family.c index 260927903..6e02b0575 100644 --- a/hw/bsp/stm32f4/family.c +++ b/hw/bsp/stm32f4/family.c @@ -54,7 +54,7 @@ void OTG_HS_IRQHandler(void) { // MACRO TYPEDEF CONSTANT ENUM //--------------------------------------------------------------------+ #ifdef UART_DEV -UART_HandleTypeDef UartHandle = { +static UART_HandleTypeDef UartHandle = { .Instance = UART_DEV, .Init = { .BaudRate = CFG_BOARD_UART_BAUDRATE, diff --git a/hw/bsp/stm32f7/family.c b/hw/bsp/stm32f7/family.c index bf2d28e42..38dfaa3bc 100644 --- a/hw/bsp/stm32f7/family.c +++ b/hw/bsp/stm32f7/family.c @@ -46,7 +46,7 @@ typedef struct { //--------------------------------------------------------------------+ #ifdef UART_DEV -UART_HandleTypeDef UartHandle = { +static UART_HandleTypeDef UartHandle = { .Instance = UART_DEV, .Init = { .BaudRate = CFG_BOARD_UART_BAUDRATE, diff --git a/hw/bsp/stm32h7/family.c b/hw/bsp/stm32h7/family.c index 4f80b15ff..7b618b2e4 100644 --- a/hw/bsp/stm32h7/family.c +++ b/hw/bsp/stm32h7/family.c @@ -49,7 +49,7 @@ typedef struct { //--------------------------------------------------------------------+ #ifdef UART_DEV -UART_HandleTypeDef UartHandle = { +static UART_HandleTypeDef UartHandle = { .Instance = UART_DEV, .Init = { .BaudRate = CFG_BOARD_UART_BAUDRATE, @@ -127,7 +127,7 @@ void board_init(void) { #if CFG_TUSB_OS == OPT_OS_NONE // 1ms tick timer - SysTick_Config(SystemCoreClock / 1000); + SysTick_Config(SystemCoreClock / 1000u); #elif CFG_TUSB_OS == OPT_OS_FREERTOS // Explicitly disable systick to prevent its ISR runs before scheduler start diff --git a/hw/bsp/stm32h7rs/family.c b/hw/bsp/stm32h7rs/family.c index 80ac81125..6192f7a40 100644 --- a/hw/bsp/stm32h7rs/family.c +++ b/hw/bsp/stm32h7rs/family.c @@ -49,7 +49,7 @@ typedef struct { //--------------------------------------------------------------------+ #ifdef UART_DEV -UART_HandleTypeDef UartHandle = { +static UART_HandleTypeDef UartHandle = { .Instance = UART_DEV, .Init = { .BaudRate = CFG_BOARD_UART_BAUDRATE, diff --git a/hw/bsp/stm32n6/family.c b/hw/bsp/stm32n6/family.c index 1d0616d8e..58be4867d 100644 --- a/hw/bsp/stm32n6/family.c +++ b/hw/bsp/stm32n6/family.c @@ -62,7 +62,7 @@ typedef struct { //--------------------------------------------------------------------+ #ifdef UART_DEV -UART_HandleTypeDef UartHandle = { +static UART_HandleTypeDef UartHandle = { .Instance = UART_DEV, .Init = { .BaudRate = CFG_BOARD_UART_BAUDRATE, diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index ec01bbf0f..c0b7469ed 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -77,9 +77,9 @@ *------------------------------------------------------------------*/ typedef enum { - TUSB_ROLE_INVALID = 0, - TUSB_ROLE_DEVICE = 0x1, - TUSB_ROLE_HOST = 0x2, + TUSB_ROLE_INVALID = 0u, + TUSB_ROLE_DEVICE = 0x1u, + TUSB_ROLE_HOST = 0x2u, } tusb_role_t; /// defined base on EHCI specs value for Endpoint Speed @@ -178,7 +178,7 @@ typedef enum { } tusb_request_feature_selector_t; typedef enum { - TUSB_REQ_TYPE_STANDARD = 0, + TUSB_REQ_TYPE_STANDARD = 0u, TUSB_REQ_TYPE_CLASS, TUSB_REQ_TYPE_VENDOR, TUSB_REQ_TYPE_INVALID diff --git a/src/device/dcd.h b/src/device/dcd.h index 400f62bff..436c4555f 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -79,7 +79,7 @@ typedef struct TU_ATTR_ALIGNED(4) { // FUNC_CALL struct { - void (*func) (void*); + void (*func) (void* param); void* param; }func_call; }; diff --git a/src/osal/osal.h b/src/osal/osal.h index 8faa81b07..658b18584 100644 --- a/src/osal/osal.h +++ b/src/osal/osal.h @@ -33,7 +33,7 @@ #include "common/tusb_common.h" -typedef void (*osal_task_func_t)( void * ); +typedef void (*osal_task_func_t)(void* param); // Timeout #define OSAL_TIMEOUT_NOTIMEOUT (0) // Return immediately diff --git a/src/osal/osal_none.h b/src/osal/osal_none.h index 3e397ef35..6f9b8b0dc 100644 --- a/src/osal/osal_none.h +++ b/src/osal/osal_none.h @@ -35,7 +35,7 @@ extern "C" { // Spinlock API //--------------------------------------------------------------------+ typedef struct { - void (* interrupt_set)(bool); + void (* interrupt_set)(bool enabled); } osal_spinlock_t; // For SMP, spinlock must be locked by hardware, cannot just use interrupt @@ -141,7 +141,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hd #include "common/tusb_fifo.h" typedef struct { - void (* interrupt_set)(bool); + void (* interrupt_set)(bool enabled); tu_fifo_t ff; } osal_queue_def_t; diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index f1e4dbd77..8560b2109 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -379,7 +379,7 @@ static void edpt_schedule_packets(uint8_t rhport, const uint8_t epnum, const uin // Enable tx fifo empty interrupt only if there is data. Note must after depctl enable if (dir == TUSB_DIR_IN && total_bytes != 0) { - dwc2->diepempmsk |= (1 << epnum); + dwc2->diepempmsk |= (1u << epnum); } } } @@ -402,7 +402,7 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { // Set device max speed uint32_t dcfg = dwc2->dcfg & ~DCFG_DSPD_Msk; if (is_highspeed) { - dcfg |= DCFG_DSPD_HS << DCFG_DSPD_Pos; + // dcfg Highspeed's mask is 0 // 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) @@ -914,7 +914,7 @@ static void handle_epin_slave(uint8_t rhport, uint8_t epnum, dwc2_diepint_t diep // Turn off TXFE if all bytes are written. tsiz.value = epin->tsiz; if (tsiz.xfer_size == 0) { - dwc2->diepempmsk &= ~(1 << epnum); + dwc2->diepempmsk &= ~(1u << epnum); } } } diff --git a/src/tusb.c b/src/tusb.c index 083e6d861..d52c156ab 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -576,8 +576,12 @@ void tu_print_mem(void const* buf, uint32_t count, uint8_t indent) { if (i % item_per_line == 0) { // Print Ascii - if (i != 0) dump_str_line(buf8 - 16, 16); - for (uint8_t s = 0; s < indent; s++) tu_printf(" "); + if (i != 0) { + dump_str_line(buf8 - 16, 16); + } + for (uint8_t s = 0; s < indent; s++) { + tu_printf(" "); + } // print offset or absolute address tu_printf("%04X: ", 16 * i / item_per_line); } diff --git a/src/tusb_option.h b/src/tusb_option.h index 9d5aed252..14404c59c 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -244,11 +244,11 @@ #define OPT_MODE_HOST 0x0002 ///< Host Mode // High byte is max operational speed (corresponding to tusb_speed_t) -#define OPT_MODE_DEFAULT_SPEED 0x0000 ///< Default (max) speed supported by MCU -#define OPT_MODE_LOW_SPEED 0x0100 ///< Low Speed -#define OPT_MODE_FULL_SPEED 0x0200 ///< Full Speed -#define OPT_MODE_HIGH_SPEED 0x0400 ///< High Speed -#define OPT_MODE_SPEED_MASK 0xff00 +#define OPT_MODE_DEFAULT_SPEED 0x0000u ///< Default (max) speed supported by MCU +#define OPT_MODE_LOW_SPEED 0x0100u ///< Low Speed +#define OPT_MODE_FULL_SPEED 0x0200u ///< Full Speed +#define OPT_MODE_HIGH_SPEED 0x0400u ///< High Speed +#define OPT_MODE_SPEED_MASK 0xff00u //--------------------------------------------------------------------+ // Include tusb_config.h -- cgit v1.3.1 From 80309e4d13b10acba40ef4bccec139cecdffe9cf Mon Sep 17 00:00:00 2001 From: peppapighs Date: Sat, 25 Oct 2025 08:53:38 +0800 Subject: dcd/dwc2: clear pending suspend interrupt before usb reset --- src/portable/synopsys/dwc2/dcd_dwc2.c | 2 + src/portable/synopsys/dwc2/dwc2_at32.h | 79 +++++++++++++++++----------------- 2 files changed, 42 insertions(+), 39 deletions(-) (limited to 'src/portable') diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index f1e4dbd77..e560a1e19 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -1054,6 +1054,8 @@ void dcd_int_handler(uint8_t rhport) { if (gintsts & GINTSTS_ENUMDNE) { // ENUMDNE is the end of reset where speed of the link is detected dwc2->gintsts = GINTSTS_ENUMDNE; + // There may be a pending suspend event, so we clear it first + dwc2->gintsts = GINTSTS_USBSUSP; dwc2->gintmsk |= GINTMSK_USBSUSPM; handle_enum_done(rhport); } diff --git a/src/portable/synopsys/dwc2/dwc2_at32.h b/src/portable/synopsys/dwc2/dwc2_at32.h index 37b6592c4..513495eb1 100644 --- a/src/portable/synopsys/dwc2/dwc2_at32.h +++ b/src/portable/synopsys/dwc2/dwc2_at32.h @@ -64,58 +64,59 @@ #endif #ifdef __cplusplus - extern "C" { +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}, +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} + {.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); +} - 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"); - } +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 - 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) { - } - } +// 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) { + } +} - // 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 +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; - 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 } #endif -#endif /* DWC2_GD32_H_ */ +#endif /* DWC2_AT32_H_ */ -- cgit v1.3.1 From d55e074a36de0331006fca1a19a241e98f9bd7e1 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 27 Oct 2025 17:11:42 +0700 Subject: improve warnings with rp2040 family --- hw/bsp/family_support.cmake | 55 ++------------------- hw/bsp/rp2040/family.c | 2 +- hw/bsp/rp2040/family.cmake | 66 +++++++++++++++----------- src/portable/raspberrypi/pio_usb/hcd_pio_usb.c | 11 +++++ 4 files changed, 54 insertions(+), 80 deletions(-) (limited to 'src/portable') diff --git a/hw/bsp/family_support.cmake b/hw/bsp/family_support.cmake index 912e0f4d7..16c0d48d7 100644 --- a/hw/bsp/family_support.cmake +++ b/hw/bsp/family_support.cmake @@ -63,8 +63,9 @@ set(WARN_FLAGS_GNU -Wunused -Wunused-function -Wreturn-type - #-Wredundant-decls - #-Wmissing-prototypes + -Wredundant-decls + -Wmissing-prototypes +# -Wconversion ) set(WARN_FLAGS_Clang ${WARN_FLAGS_GNU}) @@ -391,56 +392,6 @@ function(family_example_missing_dependency TARGET DEPENDENCY) message(WARNING "${DEPENDENCY} submodule needed by ${TARGET} not found, please run 'python tools/get_deps.py ${DEPENDENCY}' to fetch it") endfunction() -#---------------------------------- -# RPI specific: refactor later -#---------------------------------- -function(family_add_default_example_warnings TARGET) - target_compile_options(${TARGET} PUBLIC - -Wall - -Wextra - -Werror - -Wfatal-errors - -Wdouble-promotion - -Wfloat-equal - # FIXME commented out because of https://github.com/raspberrypi/pico-sdk/issues/1468 - #-Wshadow - -Wwrite-strings - -Wsign-compare - -Wmissing-format-attribute - -Wunreachable-code - -Wcast-align - -Wcast-qual - -Wnull-dereference - -Wuninitialized - -Wunused - -Wredundant-decls - #-Wstrict-prototypes - #-Werror-implicit-function-declaration - #-Wundef - ) - - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 12.0 AND NO_WARN_RWX_SEGMENTS_SUPPORTED) - target_link_options(${TARGET} PUBLIC "LINKER:--no-warn-rwx-segments") - endif() - - # GCC 10 - if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 10.0) - target_compile_options(${TARGET} PUBLIC -Wconversion) - endif() - - # GCC 8 - if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 8.0) - target_compile_options(${TARGET} PUBLIC -Wcast-function-type -Wstrict-overflow) - endif() - - # GCC 6 - if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 6.0) - target_compile_options(${TARGET} PUBLIC -Wno-strict-aliasing) - endif() - endif() -endfunction() - #---------------------------------- # Flashing target #---------------------------------- diff --git a/hw/bsp/rp2040/family.c b/hw/bsp/rp2040/family.c index 989140e02..35e5fc923 100644 --- a/hw/bsp/rp2040/family.c +++ b/hw/bsp/rp2040/family.c @@ -92,7 +92,7 @@ static uart_inst_t *uart_inst; // // This doesn't work if others are trying to access flash at the same time, // e.g. XIP streamer, or the other core. -bool __no_inline_not_in_flash_func(get_bootsel_button)(void) { +static bool __no_inline_not_in_flash_func(get_bootsel_button)(void) { const uint CS_PIN_INDEX = 1; // Must disable interrupts, as interrupt handlers may be in flash, and we diff --git a/hw/bsp/rp2040/family.cmake b/hw/bsp/rp2040/family.cmake index 3bec5bf70..5d6d8b40e 100644 --- a/hw/bsp/rp2040/family.cmake +++ b/hw/bsp/rp2040/family.cmake @@ -184,6 +184,43 @@ endif() #------------------------------------ # Functions #------------------------------------ +function(family_add_default_example_warnings TARGET) + # Apply warnings to all TinyUSB interface library sources as well as examples sources + # we cannot set compile options for target since it will not propagate to INTERFACE sources then picosdk files + foreach(TINYUSB_TARGET IN ITEMS tinyusb_common_base tinyusb_device_base tinyusb_host_base tinyusb_host_max3421 tinyusb_bsp) + get_target_property(TINYUSB_SOURCES ${TINYUSB_TARGET} INTERFACE_SOURCES) + set_source_files_properties(${TINYUSB_SOURCES} PROPERTIES COMPILE_OPTIONS "${WARN_FLAGS_${CMAKE_C_COMPILER_ID}}") + endforeach() + + # Also apply to example sources, but filter out any source files from lib/ (e.g. fatfs) + get_target_property(EXAMPLE_SOURCES ${TARGET} SOURCES) + set(FILTERED_SOURCES "") + foreach(SOURCE_FILE IN LISTS EXAMPLE_SOURCES) + string(FIND "${SOURCE_FILE}" "${TOP}/lib" FOUND_POS) + if(FOUND_POS EQUAL -1) + list(APPEND FILTERED_SOURCES ${SOURCE_FILE}) + endif() + endforeach() + set_source_files_properties(${FILTERED_SOURCES} PROPERTIES COMPILE_OPTIONS "${WARN_FLAGS_${CMAKE_C_COMPILER_ID}}") + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 12.0 AND NO_WARN_RWX_SEGMENTS_SUPPORTED) + target_link_options(${TARGET} PRIVATE "LINKER:--no-warn-rwx-segments") + endif() + + if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 10.0) + target_compile_options(${TARGET} PRIVATE -Wconversion) + endif() + + if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 8.0) + target_compile_options(${TARGET} PRIVATE -Wcast-function-type -Wstrict-overflow) + endif() + + if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 6.0) + target_compile_options(${TARGET} PRIVATE -Wno-strict-aliasing) + endif() + endif() +endfunction() function(family_configure_target TARGET RTOS) if (RTOS STREQUAL noos OR RTOS STREQUAL "") @@ -204,7 +241,7 @@ function(family_configure_target TARGET RTOS) pico_enable_stdio_uart(${TARGET} 1) target_link_libraries(${TARGET} PUBLIC pico_stdlib tinyusb_board${RTOS_SUFFIX} tinyusb_additions) - family_flash_openocd(${TARGET}) + family_flash_openocd(${TARGET}) family_flash_jlink(${TARGET}) endfunction() @@ -359,34 +396,9 @@ function(suppress_tinyusb_warnings) ${PICO_TINYUSB_PATH}/src/portable/raspberrypi/rp2040/hcd_rp2040.c ) foreach(SOURCE_FILE IN LISTS CONVERSION_WARNING_FILES) - set_source_files_properties( - ${SOURCE_FILE} - PROPERTIES - COMPILE_FLAGS "-Wno-conversion") + set_source_files_properties(${SOURCE_FILE} PROPERTIES COMPILE_FLAGS "-Wno-conversion") endforeach() endif() - if (CMAKE_C_COMPILER_ID STREQUAL "GNU" AND CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 11.0) - set_source_files_properties( - ${PICO_TINYUSB_PATH}/lib/fatfs/source/ff.c - COMPILE_FLAGS "-Wno-stringop-overflow -Wno-array-bounds") - endif() - set_source_files_properties( - ${PICO_TINYUSB_PATH}/lib/fatfs/source/ff.c - PROPERTIES - COMPILE_FLAGS "-Wno-conversion -Wno-cast-qual") - - set_source_files_properties( - ${PICO_TINYUSB_PATH}/lib/lwip/src/core/tcp_in.c - ${PICO_TINYUSB_PATH}/lib/lwip/src/core/tcp_out.c - PROPERTIES - COMPILE_FLAGS "-Wno-conversion") - - set_source_files_properties( - ${PICO_TINYUSB_PATH}/lib/networking/dnserver.c - ${PICO_TINYUSB_PATH}/lib/networking/dhserver.c - ${PICO_TINYUSB_PATH}/lib/networking/rndis_reports.c - PROPERTIES - COMPILE_FLAGS "-Wno-conversion -Wno-sign-conversion") if (TARGET tinyusb_pico_pio_usb) set_source_files_properties( diff --git a/src/portable/raspberrypi/pio_usb/hcd_pio_usb.c b/src/portable/raspberrypi/pio_usb/hcd_pio_usb.c index d59a2b4ee..90eb920e0 100644 --- a/src/portable/raspberrypi/pio_usb/hcd_pio_usb.c +++ b/src/portable/raspberrypi/pio_usb/hcd_pio_usb.c @@ -29,9 +29,20 @@ #if CFG_TUH_ENABLED && (CFG_TUSB_MCU == OPT_MCU_RP2040) && CFG_TUH_RPI_PIO_USB #include "pico.h" + #include "pio_usb.h" + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wsign-conversion" +#endif + #include "pio_usb_ll.h" +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + //--------------------------------------------------------------------+ // INCLUDE //--------------------------------------------------------------------+ -- cgit v1.3.1 From 113a763bc3fe861ac7c20075b2ad29bb51f6fd01 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 28 Oct 2025 00:38:34 +0700 Subject: fix warning with strict prototypes warnings --- hw/bsp/at32f402_405/family.cmake | 4 ++-- hw/bsp/at32f403a_407/family.cmake | 4 ++-- hw/bsp/at32f413/family.cmake | 2 +- hw/bsp/at32f415/family.cmake | 2 +- hw/bsp/at32f423/family.cmake | 2 +- hw/bsp/at32f425/family.cmake | 2 +- hw/bsp/at32f435_437/family.cmake | 2 +- hw/bsp/broadcom_32bit/family.cmake | 4 ++-- hw/bsp/broadcom_64bit/family.cmake | 4 ++-- hw/bsp/ch32v10x/family.cmake | 3 ++- hw/bsp/ch32v20x/family.cmake | 3 +-- hw/bsp/ch32v30x/family.cmake | 3 ++- hw/bsp/cxd56/family.cmake | 2 +- hw/bsp/da1469x/family.cmake | 4 ++-- hw/bsp/efm32/family.cmake | 4 ++-- hw/bsp/f1c100s/family.cmake | 3 ++- hw/bsp/fomu/family.cmake | 4 ++-- hw/bsp/gd32vf103/family.cmake | 16 ++++++++++++++-- hw/bsp/imxrt/family.cmake | 4 ++-- hw/bsp/kinetis_k/family.cmake | 4 ++-- hw/bsp/kinetis_k32l2/family.cmake | 4 ++-- hw/bsp/kinetis_kl/family.cmake | 4 ++-- hw/bsp/lpc51/family.cmake | 4 ++-- hw/bsp/lpc54/family.cmake | 4 ++-- hw/bsp/lpc55/family.cmake | 4 ++-- hw/bsp/maxim/family.cmake | 4 ++-- hw/bsp/mcx/family.cmake | 4 ++-- hw/bsp/mm32/family.cmake | 4 ++-- hw/bsp/msp432e4/family.cmake | 4 ++-- hw/bsp/nrf/family.cmake | 4 ++-- hw/bsp/nuc100_120/family.cmake | 7 ++++++- hw/bsp/nuc121_125/family.cmake | 8 ++++++-- hw/bsp/nuc126/family.cmake | 8 ++++++-- hw/bsp/nuc505/family.cmake | 8 ++++++-- hw/bsp/samd11/family.cmake | 4 ++-- hw/bsp/samd2x_l2x/family.cmake | 4 ++-- hw/bsp/samd5x_e5x/family.cmake | 4 ++-- hw/bsp/same7x/family.cmake | 4 ++-- hw/bsp/samg/family.cmake | 4 ++-- hw/bsp/stm32c0/family.cmake | 4 ++-- hw/bsp/stm32f0/family.cmake | 4 ++-- hw/bsp/stm32f1/family.cmake | 4 ++-- hw/bsp/stm32f2/family.cmake | 4 ++-- hw/bsp/stm32f3/family.cmake | 4 ++-- hw/bsp/stm32f4/family.cmake | 4 ++-- hw/bsp/stm32f7/family.cmake | 4 ++-- hw/bsp/stm32g0/family.cmake | 4 ++-- hw/bsp/stm32g4/family.cmake | 4 ++-- hw/bsp/stm32h5/family.cmake | 4 ++-- hw/bsp/stm32h7/family.cmake | 4 ++-- hw/bsp/stm32h7rs/family.cmake | 4 ++-- hw/bsp/stm32l0/family.cmake | 4 ++-- hw/bsp/stm32l4/family.cmake | 4 ++-- hw/bsp/stm32n6/family.cmake | 4 ++-- hw/bsp/stm32u0/family.cmake | 4 ++-- hw/bsp/stm32u5/family.cmake | 4 ++-- hw/bsp/stm32wb/family.cmake | 4 ++-- hw/bsp/stm32wba/family.cmake | 4 ++-- hw/bsp/tm4c/family.cmake | 4 +--- hw/bsp/xmc4000/family.cmake | 4 ++-- src/portable/nuvoton/nuc121/dcd_nuc121.c | 10 ++++++++++ src/portable/nuvoton/nuc505/dcd_nuc505.c | 10 ++++++++++ 62 files changed, 160 insertions(+), 111 deletions(-) (limited to 'src/portable') diff --git a/hw/bsp/at32f402_405/family.cmake b/hw/bsp/at32f402_405/family.cmake index fa29fd2ed..87869cfe9 100644 --- a/hw/bsp/at32f402_405/family.cmake +++ b/hw/bsp/at32f402_405/family.cmake @@ -110,10 +110,10 @@ function(family_configure_example TARGET RTOS) ) endif () - - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES SKIP_LINTING ON COMPILE_OPTIONS -w) + # Flashing family_add_bin_hex(${TARGET}) family_flash_jlink(${TARGET}) diff --git a/hw/bsp/at32f403a_407/family.cmake b/hw/bsp/at32f403a_407/family.cmake index 953f2ca49..498b89c1a 100644 --- a/hw/bsp/at32f403a_407/family.cmake +++ b/hw/bsp/at32f403a_407/family.cmake @@ -84,10 +84,10 @@ function(family_configure_example TARGET RTOS) "LINKER:--config=${LD_FILE_IAR}" ) endif () - - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES SKIP_LINTING ON COMPILE_OPTIONS -w) + # Flashing family_add_bin_hex(${TARGET}) family_flash_jlink(${TARGET}) diff --git a/hw/bsp/at32f413/family.cmake b/hw/bsp/at32f413/family.cmake index 5e41a1621..02692daf5 100644 --- a/hw/bsp/at32f413/family.cmake +++ b/hw/bsp/at32f413/family.cmake @@ -85,7 +85,7 @@ function(family_configure_example TARGET RTOS) ) endif () - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES SKIP_LINTING ON COMPILE_OPTIONS -w) diff --git a/hw/bsp/at32f415/family.cmake b/hw/bsp/at32f415/family.cmake index 3c1b6b80c..f28da6f47 100644 --- a/hw/bsp/at32f415/family.cmake +++ b/hw/bsp/at32f415/family.cmake @@ -85,7 +85,7 @@ function(family_configure_example TARGET RTOS) ) endif () - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES SKIP_LINTING ON COMPILE_OPTIONS -w) diff --git a/hw/bsp/at32f423/family.cmake b/hw/bsp/at32f423/family.cmake index 8294914b6..3c666b132 100644 --- a/hw/bsp/at32f423/family.cmake +++ b/hw/bsp/at32f423/family.cmake @@ -87,7 +87,7 @@ function(family_configure_example TARGET RTOS) ) endif () - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES SKIP_LINTING ON COMPILE_OPTIONS -w) diff --git a/hw/bsp/at32f425/family.cmake b/hw/bsp/at32f425/family.cmake index ef1ca5a83..39d98a220 100644 --- a/hw/bsp/at32f425/family.cmake +++ b/hw/bsp/at32f425/family.cmake @@ -85,7 +85,7 @@ function(family_configure_example TARGET RTOS) ) endif () - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES SKIP_LINTING ON COMPILE_OPTIONS -w) diff --git a/hw/bsp/at32f435_437/family.cmake b/hw/bsp/at32f435_437/family.cmake index 191a850aa..32a401bb6 100644 --- a/hw/bsp/at32f435_437/family.cmake +++ b/hw/bsp/at32f435_437/family.cmake @@ -94,7 +94,7 @@ function(family_configure_example TARGET RTOS) ) endif () - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES SKIP_LINTING ON COMPILE_OPTIONS -w) diff --git a/hw/bsp/broadcom_32bit/family.cmake b/hw/bsp/broadcom_32bit/family.cmake index c92d79de8..3f327861b 100644 --- a/hw/bsp/broadcom_32bit/family.cmake +++ b/hw/bsp/broadcom_32bit/family.cmake @@ -88,10 +88,10 @@ function(family_configure_example TARGET RTOS) if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") endif () - - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES SKIP_LINTING ON COMPILE_OPTIONS -w) + # Flashing family_add_bin_hex(${TARGET}) family_flash_jlink(${TARGET}) diff --git a/hw/bsp/broadcom_64bit/family.cmake b/hw/bsp/broadcom_64bit/family.cmake index 5fabda524..6294ebafd 100644 --- a/hw/bsp/broadcom_64bit/family.cmake +++ b/hw/bsp/broadcom_64bit/family.cmake @@ -93,10 +93,10 @@ function(family_configure_example TARGET RTOS) if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") endif () - - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES SKIP_LINTING ON COMPILE_OPTIONS -w) + # Flashing family_add_bin_hex(${TARGET}) family_flash_jlink(${TARGET}) diff --git a/hw/bsp/ch32v10x/family.cmake b/hw/bsp/ch32v10x/family.cmake index 0e4a38066..fb9ccb3a3 100644 --- a/hw/bsp/ch32v10x/family.cmake +++ b/hw/bsp/ch32v10x/family.cmake @@ -87,9 +87,10 @@ function(family_configure_example TARGET RTOS) ) endif () - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES SKIP_LINTING ON COMPILE_OPTIONS -w) + # Flashing family_add_bin_hex(${TARGET}) family_flash_openocd_wch(${TARGET}) diff --git a/hw/bsp/ch32v20x/family.cmake b/hw/bsp/ch32v20x/family.cmake index b65a39f0a..d8c7c5327 100644 --- a/hw/bsp/ch32v20x/family.cmake +++ b/hw/bsp/ch32v20x/family.cmake @@ -117,8 +117,7 @@ function(family_configure_example TARGET RTOS) ) endif () - - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES SKIP_LINTING ON COMPILE_OPTIONS -w) diff --git a/hw/bsp/ch32v30x/family.cmake b/hw/bsp/ch32v30x/family.cmake index d32666429..b974bd5e7 100644 --- a/hw/bsp/ch32v30x/family.cmake +++ b/hw/bsp/ch32v30x/family.cmake @@ -109,9 +109,10 @@ function(family_configure_example TARGET RTOS) ) endif () - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES SKIP_LINTING ON COMPILE_OPTIONS -w) + # Flashing family_add_bin_hex(${TARGET}) family_flash_openocd_wch(${TARGET}) diff --git a/hw/bsp/cxd56/family.cmake b/hw/bsp/cxd56/family.cmake index 5bc01c1dd..7cd2f51f8 100644 --- a/hw/bsp/cxd56/family.cmake +++ b/hw/bsp/cxd56/family.cmake @@ -107,7 +107,7 @@ function(family_configure_example TARGET RTOS) ) endif () - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES SKIP_LINTING ON COMPILE_OPTIONS -w) diff --git a/hw/bsp/da1469x/family.cmake b/hw/bsp/da1469x/family.cmake index 120a078d4..40070ba10 100644 --- a/hw/bsp/da1469x/family.cmake +++ b/hw/bsp/da1469x/family.cmake @@ -116,10 +116,10 @@ function(family_configure_example TARGET RTOS) if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") endif () - - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES SKIP_LINTING ON COMPILE_OPTIONS -w) + # Flashing family_add_bin_hex(${TARGET}) family_flash_jlink_dialog(${TARGET}) diff --git a/hw/bsp/efm32/family.cmake b/hw/bsp/efm32/family.cmake index 2cd62612c..8c521eee0 100644 --- a/hw/bsp/efm32/family.cmake +++ b/hw/bsp/efm32/family.cmake @@ -81,10 +81,10 @@ function(family_configure_example TARGET RTOS) ) endif () - - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES SKIP_LINTING ON COMPILE_OPTIONS -w) + # Flashing family_add_bin_hex(${TARGET}) family_flash_jlink(${TARGET}) diff --git a/hw/bsp/f1c100s/family.cmake b/hw/bsp/f1c100s/family.cmake index ad4915f39..5522eeec7 100644 --- a/hw/bsp/f1c100s/family.cmake +++ b/hw/bsp/f1c100s/family.cmake @@ -100,9 +100,10 @@ function(family_configure_example TARGET RTOS) ) endif () - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES SKIP_LINTING ON COMPILE_OPTIONS -w) + # Flashing family_add_bin_hex(${TARGET}) family_flash_jlink(${TARGET}) diff --git a/hw/bsp/fomu/family.cmake b/hw/bsp/fomu/family.cmake index 41c8239fa..ac3c0c446 100644 --- a/hw/bsp/fomu/family.cmake +++ b/hw/bsp/fomu/family.cmake @@ -69,10 +69,10 @@ function(family_configure_example TARGET RTOS) if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") endif () - - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES SKIP_LINTING ON COMPILE_OPTIONS -w) + # Flashing family_add_bin_hex(${TARGET}) endfunction() diff --git a/hw/bsp/gd32vf103/family.cmake b/hw/bsp/gd32vf103/family.cmake index fb292c28e..76f520ea8 100644 --- a/hw/bsp/gd32vf103/family.cmake +++ b/hw/bsp/gd32vf103/family.cmake @@ -100,10 +100,22 @@ function(family_configure_example TARGET RTOS) ) endif () - - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties( + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c + ${SOC_DIR}/Common/Source/Stubs/sbrk.c + ${SOC_DIR}/Common/Source/Stubs/close.c + ${SOC_DIR}/Common/Source/Stubs/isatty.c + ${SOC_DIR}/Common/Source/Stubs/fstat.c + ${SOC_DIR}/Common/Source/Stubs/lseek.c + ${SOC_DIR}/Common/Source/Stubs/read.c + PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes" + ) + endif () + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES SKIP_LINTING ON COMPILE_OPTIONS -w) + # Flashing family_add_bin_hex(${TARGET}) family_flash_jlink(${TARGET}) diff --git a/hw/bsp/imxrt/family.cmake b/hw/bsp/imxrt/family.cmake index f07ac249f..100deba1f 100644 --- a/hw/bsp/imxrt/family.cmake +++ b/hw/bsp/imxrt/family.cmake @@ -131,10 +131,10 @@ function(family_configure_example TARGET RTOS) if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") endif () - - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES SKIP_LINTING ON COMPILE_OPTIONS -w) + # Flashing family_add_bin_hex(${TARGET}) family_flash_jlink(${TARGET}) diff --git a/hw/bsp/kinetis_k/family.cmake b/hw/bsp/kinetis_k/family.cmake index ef078836e..e1b5c221e 100644 --- a/hw/bsp/kinetis_k/family.cmake +++ b/hw/bsp/kinetis_k/family.cmake @@ -91,10 +91,10 @@ function(family_configure_example TARGET RTOS) if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") endif () - - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES SKIP_LINTING ON COMPILE_OPTIONS -w) + # Flashing family_add_bin_hex(${TARGET}) family_flash_jlink(${TARGET}) diff --git a/hw/bsp/kinetis_k32l2/family.cmake b/hw/bsp/kinetis_k32l2/family.cmake index 75619b316..110335ab2 100644 --- a/hw/bsp/kinetis_k32l2/family.cmake +++ b/hw/bsp/kinetis_k32l2/family.cmake @@ -86,10 +86,10 @@ function(family_configure_example TARGET RTOS) if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") endif () - - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES SKIP_LINTING ON COMPILE_OPTIONS -w) + # Flashing family_flash_jlink(${TARGET}) family_add_bin_hex(${TARGET}) diff --git a/hw/bsp/kinetis_kl/family.cmake b/hw/bsp/kinetis_kl/family.cmake index 9e27106fe..230a3057d 100644 --- a/hw/bsp/kinetis_kl/family.cmake +++ b/hw/bsp/kinetis_kl/family.cmake @@ -90,10 +90,10 @@ function(family_configure_example TARGET RTOS) if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") endif () - - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES SKIP_LINTING ON COMPILE_OPTIONS -w) + # Flashing family_add_bin_hex(${TARGET}) family_flash_jlink(${TARGET}) diff --git a/hw/bsp/lpc51/family.cmake b/hw/bsp/lpc51/family.cmake index 8a35af416..1823b64fc 100644 --- a/hw/bsp/lpc51/family.cmake +++ b/hw/bsp/lpc51/family.cmake @@ -98,10 +98,10 @@ function(family_configure_example TARGET RTOS) if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") endif () - - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES SKIP_LINTING ON COMPILE_OPTIONS -w) + # Flashing family_add_bin_hex(${TARGET}) family_flash_jlink(${TARGET}) diff --git a/hw/bsp/lpc54/family.cmake b/hw/bsp/lpc54/family.cmake index efa6fd346..c6145bd41 100644 --- a/hw/bsp/lpc54/family.cmake +++ b/hw/bsp/lpc54/family.cmake @@ -126,10 +126,10 @@ function(family_configure_example TARGET RTOS) if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") endif () - - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES SKIP_LINTING ON COMPILE_OPTIONS -w) + # Flashing family_add_bin_hex(${TARGET}) family_flash_jlink(${TARGET}) diff --git a/hw/bsp/lpc55/family.cmake b/hw/bsp/lpc55/family.cmake index 9dab57113..3477d9f10 100644 --- a/hw/bsp/lpc55/family.cmake +++ b/hw/bsp/lpc55/family.cmake @@ -128,10 +128,10 @@ function(family_configure_example TARGET RTOS) set_source_files_properties(${TOP}/lib/sct_neopixel/sct_neopixel.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes -Wno-unused-parameter") endif () - - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES SKIP_LINTING ON COMPILE_OPTIONS -w) + # Flashing family_add_bin_hex(${TARGET}) family_flash_jlink(${TARGET}) diff --git a/hw/bsp/maxim/family.cmake b/hw/bsp/maxim/family.cmake index 7785598b8..d890113e6 100644 --- a/hw/bsp/maxim/family.cmake +++ b/hw/bsp/maxim/family.cmake @@ -175,11 +175,11 @@ function(family_configure_example TARGET RTOS) endif () set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") endif () - - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES SKIP_LINTING ON COMPILE_OPTIONS -w) + # Flashing family_add_bin_hex(${TARGET}) family_flash_jlink(${TARGET}) diff --git a/hw/bsp/mcx/family.cmake b/hw/bsp/mcx/family.cmake index 8e7cc9fc8..d062cec16 100644 --- a/hw/bsp/mcx/family.cmake +++ b/hw/bsp/mcx/family.cmake @@ -115,10 +115,10 @@ function(family_configure_example TARGET RTOS) if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") endif () - - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES SKIP_LINTING ON COMPILE_OPTIONS -w) + # Flashing family_add_bin_hex(${TARGET}) family_flash_jlink(${TARGET}) diff --git a/hw/bsp/mm32/family.cmake b/hw/bsp/mm32/family.cmake index a08398bec..04961d6c3 100644 --- a/hw/bsp/mm32/family.cmake +++ b/hw/bsp/mm32/family.cmake @@ -79,10 +79,10 @@ function(family_configure_example TARGET RTOS) if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") endif () - - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES SKIP_LINTING ON COMPILE_OPTIONS -w) + # Flashing family_add_bin_hex(${TARGET}) family_flash_jlink(${TARGET}) diff --git a/hw/bsp/msp432e4/family.cmake b/hw/bsp/msp432e4/family.cmake index a7f2ff2ac..6725eedac 100644 --- a/hw/bsp/msp432e4/family.cmake +++ b/hw/bsp/msp432e4/family.cmake @@ -79,10 +79,10 @@ function(family_configure_example TARGET RTOS) if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") endif () - - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES SKIP_LINTING ON COMPILE_OPTIONS -w) + # Flashing family_add_bin_hex(${TARGET}) family_flash_msp430flasher(${TARGET}) diff --git a/hw/bsp/nrf/family.cmake b/hw/bsp/nrf/family.cmake index ea19e79e7..4e999b636 100644 --- a/hw/bsp/nrf/family.cmake +++ b/hw/bsp/nrf/family.cmake @@ -152,10 +152,10 @@ function(family_configure_example TARGET RTOS) if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") endif () - - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES SKIP_LINTING ON COMPILE_OPTIONS -w) + # Flashing # family_add_bin_hex(${TARGET}) family_flash_jlink(${TARGET}) diff --git a/hw/bsp/nuc100_120/family.cmake b/hw/bsp/nuc100_120/family.cmake index fe2ac7b54..f81447596 100644 --- a/hw/bsp/nuc100_120/family.cmake +++ b/hw/bsp/nuc100_120/family.cmake @@ -79,8 +79,13 @@ function(family_configure_example TARGET RTOS) ) endif () - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES + COMPILE_FLAGS "-Wno-missing-prototypes -Wno-redundant-decls") + endif () + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES SKIP_LINTING ON COMPILE_OPTIONS -w) + family_flash_openocd_nuvoton(${TARGET}) endfunction() diff --git a/hw/bsp/nuc121_125/family.cmake b/hw/bsp/nuc121_125/family.cmake index 22968510f..718f8db9a 100644 --- a/hw/bsp/nuc121_125/family.cmake +++ b/hw/bsp/nuc121_125/family.cmake @@ -82,9 +82,13 @@ function(family_configure_example TARGET RTOS) ) endif () - - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES + COMPILE_FLAGS "-Wno-missing-prototypes -Wno-redundant-decls") + endif () + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES SKIP_LINTING ON COMPILE_OPTIONS -w) + family_flash_openocd_nuvoton(${TARGET}) endfunction() diff --git a/hw/bsp/nuc126/family.cmake b/hw/bsp/nuc126/family.cmake index f7f75442c..3fc670cf0 100644 --- a/hw/bsp/nuc126/family.cmake +++ b/hw/bsp/nuc126/family.cmake @@ -85,9 +85,13 @@ function(family_configure_example TARGET RTOS) ) endif () - - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES + COMPILE_FLAGS "-Wno-missing-prototypes -Wno-redundant-decls") + endif () + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES SKIP_LINTING ON COMPILE_OPTIONS -w) + family_flash_openocd_nuvoton(${TARGET}) endfunction() diff --git a/hw/bsp/nuc505/family.cmake b/hw/bsp/nuc505/family.cmake index 5fe48e03c..a31f5ff73 100644 --- a/hw/bsp/nuc505/family.cmake +++ b/hw/bsp/nuc505/family.cmake @@ -81,9 +81,13 @@ function(family_configure_example TARGET RTOS) ) endif () - - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES + COMPILE_FLAGS "-Wno-missing-prototypes -Wno-redundant-decls") + endif () + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES SKIP_LINTING ON COMPILE_OPTIONS -w) + family_flash_openocd_nuvoton(${TARGET}) endfunction() diff --git a/hw/bsp/samd11/family.cmake b/hw/bsp/samd11/family.cmake index b4fe26e4d..982cef792 100644 --- a/hw/bsp/samd11/family.cmake +++ b/hw/bsp/samd11/family.cmake @@ -87,10 +87,10 @@ function(family_configure_example TARGET RTOS) "LINKER:--config=${LD_FILE_IAR}" ) endif () - - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES SKIP_LINTING ON COMPILE_OPTIONS -w) + # Flashing family_add_bin_hex(${TARGET}) family_flash_jlink(${TARGET}) diff --git a/hw/bsp/samd2x_l2x/family.cmake b/hw/bsp/samd2x_l2x/family.cmake index 74766ddc8..76371ccdc 100644 --- a/hw/bsp/samd2x_l2x/family.cmake +++ b/hw/bsp/samd2x_l2x/family.cmake @@ -137,10 +137,10 @@ function(family_configure_example TARGET RTOS) "LINKER:--config=${LD_FILE_IAR}" ) endif () - - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES SKIP_LINTING ON COMPILE_OPTIONS -w) + # Flashing family_add_bin_hex(${TARGET}) family_flash_jlink(${TARGET}) diff --git a/hw/bsp/samd5x_e5x/family.cmake b/hw/bsp/samd5x_e5x/family.cmake index a92e79630..bb022ab76 100644 --- a/hw/bsp/samd5x_e5x/family.cmake +++ b/hw/bsp/samd5x_e5x/family.cmake @@ -80,10 +80,10 @@ function(family_configure_example TARGET RTOS) "LINKER:--config=${LD_FILE_IAR}" ) endif () - - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES SKIP_LINTING ON COMPILE_OPTIONS -w) + # Flashing family_add_bin_hex(${TARGET}) family_flash_jlink(${TARGET}) diff --git a/hw/bsp/same7x/family.cmake b/hw/bsp/same7x/family.cmake index 67df075dc..a9c9de413 100644 --- a/hw/bsp/same7x/family.cmake +++ b/hw/bsp/same7x/family.cmake @@ -89,10 +89,10 @@ function(family_configure_example TARGET RTOS) "LINKER:--config=${LD_FILE_IAR}" ) endif () - - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES SKIP_LINTING ON COMPILE_OPTIONS -w) + family_add_bin_hex(${TARGET}) family_flash_jlink(${TARGET}) endfunction() diff --git a/hw/bsp/samg/family.cmake b/hw/bsp/samg/family.cmake index 8d3af4143..c07e20b90 100644 --- a/hw/bsp/samg/family.cmake +++ b/hw/bsp/samg/family.cmake @@ -82,11 +82,11 @@ function(family_configure_example TARGET RTOS) "LINKER:--config=${LD_FILE_IAR}" ) endif () - - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES SKIP_LINTING ON COMPILE_OPTIONS -w) + # Flashing family_add_bin_hex(${TARGET}) family_flash_jlink(${TARGET}) diff --git a/hw/bsp/stm32c0/family.cmake b/hw/bsp/stm32c0/family.cmake index 78c921ae5..90d5322b7 100644 --- a/hw/bsp/stm32c0/family.cmake +++ b/hw/bsp/stm32c0/family.cmake @@ -95,11 +95,11 @@ function(family_configure_example TARGET RTOS) if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") endif () - - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES SKIP_LINTING ON COMPILE_OPTIONS -w) + # Flashing family_add_bin_hex(${TARGET}) family_flash_jlink(${TARGET}) diff --git a/hw/bsp/stm32f0/family.cmake b/hw/bsp/stm32f0/family.cmake index fd2791ffe..ee73ae872 100644 --- a/hw/bsp/stm32f0/family.cmake +++ b/hw/bsp/stm32f0/family.cmake @@ -92,11 +92,11 @@ function(family_configure_example TARGET RTOS) if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") endif () - - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES SKIP_LINTING ON COMPILE_OPTIONS -w) + # Flashing family_add_bin_hex(${TARGET}) family_flash_stlink(${TARGET}) diff --git a/hw/bsp/stm32f1/family.cmake b/hw/bsp/stm32f1/family.cmake index c95664c39..064f32096 100644 --- a/hw/bsp/stm32f1/family.cmake +++ b/hw/bsp/stm32f1/family.cmake @@ -89,11 +89,11 @@ function(family_configure_example TARGET RTOS) if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") endif () - - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES SKIP_LINTING ON COMPILE_OPTIONS -w) + # Flashing family_add_bin_hex(${TARGET}) family_flash_stlink(${TARGET}) diff --git a/hw/bsp/stm32f2/family.cmake b/hw/bsp/stm32f2/family.cmake index 18d2339e7..7152a0679 100644 --- a/hw/bsp/stm32f2/family.cmake +++ b/hw/bsp/stm32f2/family.cmake @@ -91,11 +91,11 @@ function(family_configure_example TARGET RTOS) if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") endif () - - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES SKIP_LINTING ON COMPILE_OPTIONS -w) + # Flashing family_add_bin_hex(${TARGET}) family_flash_stlink(${TARGET}) diff --git a/hw/bsp/stm32f3/family.cmake b/hw/bsp/stm32f3/family.cmake index c2896ff90..7c9e97e62 100644 --- a/hw/bsp/stm32f3/family.cmake +++ b/hw/bsp/stm32f3/family.cmake @@ -89,11 +89,11 @@ function(family_configure_example TARGET RTOS) if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") endif () - - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES SKIP_LINTING ON COMPILE_OPTIONS -w) + # Flashing family_add_bin_hex(${TARGET}) family_flash_stlink(${TARGET}) diff --git a/hw/bsp/stm32f4/family.cmake b/hw/bsp/stm32f4/family.cmake index b37196cfc..0d3d9ec93 100644 --- a/hw/bsp/stm32f4/family.cmake +++ b/hw/bsp/stm32f4/family.cmake @@ -119,11 +119,11 @@ function(family_configure_example TARGET RTOS) if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") endif () - - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES SKIP_LINTING ON COMPILE_OPTIONS -w) + # Flashing family_add_bin_hex(${TARGET}) family_flash_stlink(${TARGET}) diff --git a/hw/bsp/stm32f7/family.cmake b/hw/bsp/stm32f7/family.cmake index 29b235669..d405753d4 100644 --- a/hw/bsp/stm32f7/family.cmake +++ b/hw/bsp/stm32f7/family.cmake @@ -121,11 +121,11 @@ function(family_configure_example TARGET RTOS) if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") endif () - - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES SKIP_LINTING ON COMPILE_OPTIONS -w) + # Flashing family_add_bin_hex(${TARGET}) family_flash_stlink(${TARGET}) diff --git a/hw/bsp/stm32g0/family.cmake b/hw/bsp/stm32g0/family.cmake index ade644f60..572f0e644 100644 --- a/hw/bsp/stm32g0/family.cmake +++ b/hw/bsp/stm32g0/family.cmake @@ -92,11 +92,11 @@ function(family_configure_example TARGET RTOS) if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") endif () - - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES SKIP_LINTING ON COMPILE_OPTIONS -w) + # Flashing family_add_bin_hex(${TARGET}) family_flash_jlink(${TARGET}) diff --git a/hw/bsp/stm32g4/family.cmake b/hw/bsp/stm32g4/family.cmake index 16f8ead79..7e8b319b8 100644 --- a/hw/bsp/stm32g4/family.cmake +++ b/hw/bsp/stm32g4/family.cmake @@ -90,11 +90,11 @@ function(family_configure_example TARGET RTOS) if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") endif () - - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES SKIP_LINTING ON COMPILE_OPTIONS -w) + # Flashing family_add_bin_hex(${TARGET}) family_flash_stlink(${TARGET}) diff --git a/hw/bsp/stm32h5/family.cmake b/hw/bsp/stm32h5/family.cmake index bbed6aafc..6e63c4072 100644 --- a/hw/bsp/stm32h5/family.cmake +++ b/hw/bsp/stm32h5/family.cmake @@ -94,11 +94,11 @@ function(family_configure_example TARGET RTOS) if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") endif () - - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES SKIP_LINTING ON COMPILE_OPTIONS -w) + # Flashing family_add_bin_hex(${TARGET}) family_flash_stlink(${TARGET}) diff --git a/hw/bsp/stm32h7/family.cmake b/hw/bsp/stm32h7/family.cmake index b55f2f575..8b6086356 100644 --- a/hw/bsp/stm32h7/family.cmake +++ b/hw/bsp/stm32h7/family.cmake @@ -120,11 +120,11 @@ function(family_configure_example TARGET RTOS) elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") target_link_options(${TARGET} PUBLIC "LINKER:--config=${LD_FILE_IAR}") endif () - - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES SKIP_LINTING ON COMPILE_OPTIONS -w) + # Flashing family_add_bin_hex(${TARGET}) family_flash_stlink(${TARGET}) diff --git a/hw/bsp/stm32h7rs/family.cmake b/hw/bsp/stm32h7rs/family.cmake index da26b0b72..1fd1cb057 100644 --- a/hw/bsp/stm32h7rs/family.cmake +++ b/hw/bsp/stm32h7rs/family.cmake @@ -129,11 +129,11 @@ function(family_configure_example TARGET RTOS) if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") endif () - - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES SKIP_LINTING ON COMPILE_OPTIONS -w) + # Flashing family_add_bin_hex(${TARGET}) family_flash_stlink(${TARGET}) diff --git a/hw/bsp/stm32l0/family.cmake b/hw/bsp/stm32l0/family.cmake index 2030516e1..b6b0139a0 100644 --- a/hw/bsp/stm32l0/family.cmake +++ b/hw/bsp/stm32l0/family.cmake @@ -93,11 +93,11 @@ function(family_configure_example TARGET RTOS) if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") endif () - - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES SKIP_LINTING ON COMPILE_OPTIONS -w) + # Flashing family_add_bin_hex(${TARGET}) family_flash_stlink(${TARGET}) diff --git a/hw/bsp/stm32l4/family.cmake b/hw/bsp/stm32l4/family.cmake index 00f4bba3e..5bc28dd5d 100644 --- a/hw/bsp/stm32l4/family.cmake +++ b/hw/bsp/stm32l4/family.cmake @@ -94,11 +94,11 @@ function(family_configure_example TARGET RTOS) if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") endif () - - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES SKIP_LINTING ON COMPILE_OPTIONS -w) + # Flashing family_add_bin_hex(${TARGET}) family_flash_stlink(${TARGET}) diff --git a/hw/bsp/stm32n6/family.cmake b/hw/bsp/stm32n6/family.cmake index a76ec50e2..6aec26f99 100644 --- a/hw/bsp/stm32n6/family.cmake +++ b/hw/bsp/stm32n6/family.cmake @@ -128,11 +128,11 @@ function(family_configure_example TARGET RTOS) set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") endif () - - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES SKIP_LINTING ON COMPILE_OPTIONS -w) + # Flashing family_add_bin_hex(${TARGET}) family_flash_stlink(${TARGET}) diff --git a/hw/bsp/stm32u0/family.cmake b/hw/bsp/stm32u0/family.cmake index 2d640c997..4f9b03109 100644 --- a/hw/bsp/stm32u0/family.cmake +++ b/hw/bsp/stm32u0/family.cmake @@ -94,11 +94,11 @@ function(family_configure_example TARGET RTOS) if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") endif () - - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES SKIP_LINTING ON COMPILE_OPTIONS -w) + # Flashing family_add_bin_hex(${TARGET}) family_flash_stlink(${TARGET}) diff --git a/hw/bsp/stm32u5/family.cmake b/hw/bsp/stm32u5/family.cmake index 4de861706..70e0c313c 100644 --- a/hw/bsp/stm32u5/family.cmake +++ b/hw/bsp/stm32u5/family.cmake @@ -96,11 +96,11 @@ function(family_configure_example TARGET RTOS) if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") endif () - - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES SKIP_LINTING ON COMPILE_OPTIONS -w) + # Flashing family_add_bin_hex(${TARGET}) family_flash_stlink(${TARGET}) diff --git a/hw/bsp/stm32wb/family.cmake b/hw/bsp/stm32wb/family.cmake index 90f3cd6d8..1a96e3d7e 100644 --- a/hw/bsp/stm32wb/family.cmake +++ b/hw/bsp/stm32wb/family.cmake @@ -94,11 +94,11 @@ function(family_configure_example TARGET RTOS) if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") endif () - - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES SKIP_LINTING ON COMPILE_OPTIONS -w) + # Flashing family_add_bin_hex(${TARGET}) family_flash_stlink(${TARGET}) diff --git a/hw/bsp/stm32wba/family.cmake b/hw/bsp/stm32wba/family.cmake index 0bc5578a0..9628913cc 100644 --- a/hw/bsp/stm32wba/family.cmake +++ b/hw/bsp/stm32wba/family.cmake @@ -109,11 +109,11 @@ function(family_configure_example TARGET RTOS) if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") endif () - - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES SKIP_LINTING ON COMPILE_OPTIONS -w) + # Flashing family_add_bin_hex(${TARGET}) family_flash_stlink(${TARGET}) diff --git a/hw/bsp/tm4c/family.cmake b/hw/bsp/tm4c/family.cmake index 936dcffa1..12f0448a3 100644 --- a/hw/bsp/tm4c/family.cmake +++ b/hw/bsp/tm4c/family.cmake @@ -72,11 +72,9 @@ function(family_configure_example TARGET RTOS) if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") endif () - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES SKIP_LINTING ON - COMPILE_FLAGS "-Wno-cast-qual" - ) + COMPILE_OPTIONS -w) # Flashing family_add_bin_hex(${TARGET}) diff --git a/hw/bsp/xmc4000/family.cmake b/hw/bsp/xmc4000/family.cmake index 54b582b1f..a8fa5351c 100644 --- a/hw/bsp/xmc4000/family.cmake +++ b/hw/bsp/xmc4000/family.cmake @@ -78,10 +78,10 @@ function(family_configure_example TARGET RTOS) if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") endif () - - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES SKIP_LINTING ON COMPILE_OPTIONS -w) + # Flashing family_add_bin_hex(${TARGET}) family_flash_jlink(${TARGET}) diff --git a/src/portable/nuvoton/nuc121/dcd_nuc121.c b/src/portable/nuvoton/nuc121/dcd_nuc121.c index 37210ea34..804a35565 100644 --- a/src/portable/nuvoton/nuc121/dcd_nuc121.c +++ b/src/portable/nuvoton/nuc121/dcd_nuc121.c @@ -38,8 +38,18 @@ #if CFG_TUD_ENABLED && ( (CFG_TUSB_MCU == OPT_MCU_NUC121) || (CFG_TUSB_MCU == OPT_MCU_NUC126) ) #include "device/dcd.h" + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wredundant-decls" +#endif + #include "NuMicro.h" +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + // Since TinyUSB doesn't use SOF for now, and this interrupt too often (1ms interval) // We disable SOF for now until needed later on #ifndef USE_SOF diff --git a/src/portable/nuvoton/nuc505/dcd_nuc505.c b/src/portable/nuvoton/nuc505/dcd_nuc505.c index fa457d861..6195015ae 100644 --- a/src/portable/nuvoton/nuc505/dcd_nuc505.c +++ b/src/portable/nuvoton/nuc505/dcd_nuc505.c @@ -38,8 +38,18 @@ #if CFG_TUD_ENABLED && (CFG_TUSB_MCU == OPT_MCU_NUC505) #include "device/dcd.h" + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wredundant-decls" +#endif + #include "NUC505Series.h" +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + /* * The DMA functionality of the USBD peripheral does not appear to succeed with * transfer lengths that are longer (> 64 bytes) and are not a multiple of 4. -- cgit v1.3.1 From d92b810df7670aae0e195fd02abef5014470c2f7 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 28 Oct 2025 13:21:38 +0700 Subject: fix Identifiers that start with '__' or '_[A-Z]' are reserved. fix compiling with nuc family --- .github/actions/setup_toolchain/action.yml | 2 +- .../device/audio_4_channel_mic/src/tusb_config.h | 6 +- .../audio_4_channel_mic/src/usb_descriptors.c | 6 +- .../audio_4_channel_mic_freertos/src/tusb_config.h | 6 +- .../src/usb_descriptors.c | 6 +- examples/device/audio_test/src/tusb_config.h | 6 +- examples/device/audio_test/src/usb_descriptors.c | 6 +- .../device/audio_test_freertos/src/tusb_config.h | 6 +- .../audio_test_freertos/src/usb_descriptors.c | 6 +- .../device/audio_test_multi_rate/src/tusb_config.h | 6 +- .../audio_test_multi_rate/src/usb_descriptors.c | 6 +- examples/device/board_test/src/tusb_config.h | 6 +- examples/device/cdc_dual_ports/src/tusb_config.h | 6 +- .../device/cdc_dual_ports/src/usb_descriptors.c | 6 +- examples/device/cdc_msc/src/msc_disk.c | 99 +++++++++++----------- examples/device/cdc_msc/src/tusb_config.h | 6 +- examples/device/cdc_msc/src/usb_descriptors.c | 6 +- examples/device/cdc_msc_freertos/src/tusb_config.h | 6 +- .../device/cdc_msc_freertos/src/usb_descriptors.c | 6 +- examples/device/cdc_uac2/src/tusb_config.h | 6 +- examples/device/cdc_uac2/src/usb_descriptors.c | 6 +- examples/device/dfu/src/usb_descriptors.c | 6 +- examples/device/dfu_runtime/src/usb_descriptors.c | 6 +- .../device/dynamic_configuration/src/tusb_config.h | 6 +- .../dynamic_configuration/src/usb_descriptors.c | 6 +- .../device/hid_boot_interface/src/tusb_config.h | 6 +- .../hid_boot_interface/src/usb_descriptors.c | 6 +- examples/device/hid_composite/src/tusb_config.h | 6 +- .../device/hid_composite/src/usb_descriptors.c | 6 +- .../hid_composite_freertos/src/tusb_config.h | 6 +- .../hid_composite_freertos/src/usb_descriptors.c | 6 +- .../device/hid_generic_inout/src/tusb_config.h | 6 +- .../device/hid_generic_inout/src/usb_descriptors.c | 6 +- .../hid_multiple_interface/src/tusb_config.h | 6 +- .../hid_multiple_interface/src/usb_descriptors.c | 6 +- examples/device/midi_test/src/tusb_config.h | 6 +- examples/device/midi_test/src/usb_descriptors.c | 6 +- .../device/midi_test_freertos/src/tusb_config.h | 6 +- .../midi_test_freertos/src/usb_descriptors.c | 6 +- examples/device/msc_dual_lun/src/tusb_config.h | 6 +- examples/device/msc_dual_lun/src/usb_descriptors.c | 6 +- examples/device/mtp/src/tusb_config.h | 6 +- examples/device/mtp/src/usb_descriptors.c | 6 +- .../device/net_lwip_webserver/src/tusb_config.h | 6 +- .../net_lwip_webserver/src/usb_descriptors.c | 6 +- examples/device/uac2_headset/src/tusb_config.h | 6 +- examples/device/uac2_headset/src/usb_descriptors.c | 6 +- examples/device/uac2_speaker_fb/src/tusb_config.h | 6 +- .../device/uac2_speaker_fb/src/usb_descriptors.c | 6 +- examples/device/usbtmc/src/usb_descriptors.c | 6 +- examples/device/video_capture/src/tusb_config.h | 6 +- .../device/video_capture/src/usb_descriptors.c | 6 +- .../device/video_capture_2ch/src/tusb_config.h | 6 +- .../device/video_capture_2ch/src/usb_descriptors.c | 6 +- examples/device/webusb_serial/src/tusb_config.h | 6 +- .../device/webusb_serial/src/usb_descriptors.c | 6 +- .../host_hid_to_device_cdc/src/usb_descriptors.c | 6 +- .../host_info_to_device_cdc/src/usb_descriptors.c | 6 +- examples/host/cdc_msc_hid/src/tusb_config.h | 6 +- .../host/cdc_msc_hid_freertos/src/tusb_config.h | 6 +- examples/host/hid_controller/src/tusb_config.h | 6 +- examples/host/msc_file_explorer/src/tusb_config.h | 6 +- examples/typec/power_delivery/src/tusb_config.h | 6 +- hw/bsp/ansi_escape.h | 6 +- hw/bsp/nuc100_120/family.cmake | 12 ++- hw/bsp/nuc121_125/family.cmake | 12 +-- hw/bsp/nuc126/family.cmake | 12 +-- hw/bsp/nuc505/family.cmake | 12 +-- lib/rt-thread/tusb_config.h | 6 +- src/class/audio/audio.h | 4 +- src/class/audio/audio_device.h | 2 +- src/class/bth/bth_device.h | 6 +- src/class/cdc/cdc.h | 4 +- src/class/cdc/cdc_device.h | 2 +- src/class/cdc/cdc_host.h | 6 +- src/class/cdc/cdc_rndis.h | 6 +- src/class/cdc/cdc_rndis_host.h | 6 +- src/class/dfu/dfu.h | 6 +- src/class/dfu/dfu_device.h | 6 +- src/class/dfu/dfu_rt_device.h | 6 +- src/class/hid/hid.h | 6 +- src/class/hid/hid_host.h | 6 +- src/class/midi/midi_device.h | 6 +- src/class/msc/msc.h | 6 +- src/class/msc/msc_device.h | 6 +- src/class/net/ncm.h | 4 +- src/class/net/net_device.h | 6 +- src/class/usbtmc/usbtmc.h | 4 +- src/class/vendor/vendor_device.h | 6 +- src/class/vendor/vendor_host.h | 6 +- src/common/tusb_common.h | 6 +- src/common/tusb_compiler.h | 18 ++-- src/common/tusb_debug.h | 6 +- src/common/tusb_fifo.h | 6 +- src/device/usbd.h | 6 +- src/host/hcd.h | 4 +- src/host/usbh.h | 6 +- src/host/usbh_pvt.h | 4 +- src/osal/osal.h | 6 +- src/osal/osal_none.h | 2 +- src/portable/ehci/ehci.h | 6 +- src/portable/ehci/ehci_api.h | 4 +- src/portable/nxp/lpc17_40/dcd_lpc17_40.h | 4 +- src/portable/ohci/ohci.h | 6 +- src/portable/renesas/rusb2/rusb2_type.h | 6 +- src/portable/sunxi/musb_def.h | 4 +- src/portable/synopsys/dwc2/dwc2_bcm.h | 4 +- src/portable/valentyusb/eptri/dcd_eptri.h | 6 +- src/tusb.h | 6 +- src/tusb_option.h | 6 +- src/typec/pd_types.h | 4 +- src/typec/tcd.h | 4 +- src/typec/usbc.h | 6 +- test/fuzz/device/cdc/src/tusb_config.h | 6 +- test/fuzz/device/cdc/src/usb_descriptors.cc | 6 +- test/fuzz/device/msc/src/tusb_config.h | 6 +- test/fuzz/device/msc/src/usb_descriptors.cc | 6 +- test/fuzz/device/net/src/tusb_config.h | 6 +- test/fuzz/device/net/src/usb_descriptors.cc | 6 +- test/unit-test/test/support/tusb_config.h | 6 +- 120 files changed, 404 insertions(+), 405 deletions(-) (limited to 'src/portable') diff --git a/.github/actions/setup_toolchain/action.yml b/.github/actions/setup_toolchain/action.yml index 292fd172d..d15a29f20 100644 --- a/.github/actions/setup_toolchain/action.yml +++ b/.github/actions/setup_toolchain/action.yml @@ -33,7 +33,7 @@ runs: env: TOOLCHAIN: ${{ inputs.toolchain }} run: | - TOOLCHAIN_URL=$(jq -r '."$TOOLCHAIN"' .github/actions/setup_toolchain/toolchain.json) + TOOLCHAIN_URL=$(jq -r --arg tc "$TOOLCHAIN" '.[$tc]' .github/actions/setup_toolchain/toolchain.json) echo "toolchain_url=$TOOLCHAIN_URL" echo "toolchain_url=$TOOLCHAIN_URL" >> $GITHUB_OUTPUT shell: bash 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 0ee3ba2d0..8ead5c8b0 100644 --- a/examples/device/audio_4_channel_mic/src/tusb_config.h +++ b/examples/device/audio_4_channel_mic/src/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -123,4 +123,4 @@ extern "C" { } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/device/audio_4_channel_mic/src/usb_descriptors.c b/examples/device/audio_4_channel_mic/src/usb_descriptors.c index d48ee0d08..73f856fc8 100644 --- a/examples/device/audio_4_channel_mic/src/usb_descriptors.c +++ b/examples/device/audio_4_channel_mic/src/usb_descriptors.c @@ -32,9 +32,9 @@ * Auto ProductID layout's Bitmap: * [MSB] AUDIO | MIDI | HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(AUDIO, 4) | _PID_MAP(VENDOR, 5) ) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) +#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \ + PID_MAP(MIDI, 3) | PID_MAP(AUDIO, 4) | PID_MAP(VENDOR, 5) ) //--------------------------------------------------------------------+ // Device Descriptors 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 d973be2af..dd7cc7eff 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 @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -129,4 +129,4 @@ extern "C" { } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/device/audio_4_channel_mic_freertos/src/usb_descriptors.c b/examples/device/audio_4_channel_mic_freertos/src/usb_descriptors.c index d48ee0d08..73f856fc8 100644 --- a/examples/device/audio_4_channel_mic_freertos/src/usb_descriptors.c +++ b/examples/device/audio_4_channel_mic_freertos/src/usb_descriptors.c @@ -32,9 +32,9 @@ * Auto ProductID layout's Bitmap: * [MSB] AUDIO | MIDI | HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(AUDIO, 4) | _PID_MAP(VENDOR, 5) ) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) +#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \ + PID_MAP(MIDI, 3) | PID_MAP(AUDIO, 4) | PID_MAP(VENDOR, 5) ) //--------------------------------------------------------------------+ // Device Descriptors diff --git a/examples/device/audio_test/src/tusb_config.h b/examples/device/audio_test/src/tusb_config.h index 10bf53809..2efec5124 100644 --- a/examples/device/audio_test/src/tusb_config.h +++ b/examples/device/audio_test/src/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -122,4 +122,4 @@ extern "C" { } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/device/audio_test/src/usb_descriptors.c b/examples/device/audio_test/src/usb_descriptors.c index 52ddc1bb2..5f0f587b3 100644 --- a/examples/device/audio_test/src/usb_descriptors.c +++ b/examples/device/audio_test/src/usb_descriptors.c @@ -32,9 +32,9 @@ * Auto ProductID layout's Bitmap: * [MSB] AUDIO | MIDI | HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(AUDIO, 4) | _PID_MAP(VENDOR, 5) ) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) +#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \ + PID_MAP(MIDI, 3) | PID_MAP(AUDIO, 4) | PID_MAP(VENDOR, 5) ) //--------------------------------------------------------------------+ // Device Descriptors diff --git a/examples/device/audio_test_freertos/src/tusb_config.h b/examples/device/audio_test_freertos/src/tusb_config.h index c9dc50082..4dad6c2b9 100644 --- a/examples/device/audio_test_freertos/src/tusb_config.h +++ b/examples/device/audio_test_freertos/src/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -128,4 +128,4 @@ extern "C" { } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/device/audio_test_freertos/src/usb_descriptors.c b/examples/device/audio_test_freertos/src/usb_descriptors.c index 52ddc1bb2..5f0f587b3 100644 --- a/examples/device/audio_test_freertos/src/usb_descriptors.c +++ b/examples/device/audio_test_freertos/src/usb_descriptors.c @@ -32,9 +32,9 @@ * Auto ProductID layout's Bitmap: * [MSB] AUDIO | MIDI | HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(AUDIO, 4) | _PID_MAP(VENDOR, 5) ) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) +#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \ + PID_MAP(MIDI, 3) | PID_MAP(AUDIO, 4) | PID_MAP(VENDOR, 5) ) //--------------------------------------------------------------------+ // Device Descriptors 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 b48c0a0be..7ce235df0 100644 --- a/examples/device/audio_test_multi_rate/src/tusb_config.h +++ b/examples/device/audio_test_multi_rate/src/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -138,4 +138,4 @@ extern "C" { } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/device/audio_test_multi_rate/src/usb_descriptors.c b/examples/device/audio_test_multi_rate/src/usb_descriptors.c index d1e801120..11e5d2127 100644 --- a/examples/device/audio_test_multi_rate/src/usb_descriptors.c +++ b/examples/device/audio_test_multi_rate/src/usb_descriptors.c @@ -34,9 +34,9 @@ * Auto ProductID layout's Bitmap: * [MSB] AUDIO | MIDI | HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(AUDIO, 4) | _PID_MAP(VENDOR, 5) ) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) +#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \ + PID_MAP(MIDI, 3) | PID_MAP(AUDIO, 4) | PID_MAP(VENDOR, 5) ) //--------------------------------------------------------------------+ // Device Descriptors diff --git a/examples/device/board_test/src/tusb_config.h b/examples/device/board_test/src/tusb_config.h index 81829d450..97ec65f66 100644 --- a/examples/device/board_test/src/tusb_config.h +++ b/examples/device/board_test/src/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -74,4 +74,4 @@ } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/device/cdc_dual_ports/src/tusb_config.h b/examples/device/cdc_dual_ports/src/tusb_config.h index 7f7df3909..0da4032a7 100644 --- a/examples/device/cdc_dual_ports/src/tusb_config.h +++ b/examples/device/cdc_dual_ports/src/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -110,4 +110,4 @@ } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/device/cdc_dual_ports/src/usb_descriptors.c b/examples/device/cdc_dual_ports/src/usb_descriptors.c index 34cdbfafb..dd0aefaea 100644 --- a/examples/device/cdc_dual_ports/src/usb_descriptors.c +++ b/examples/device/cdc_dual_ports/src/usb_descriptors.c @@ -32,9 +32,9 @@ * Auto ProductID layout's Bitmap: * [MSB] HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) ) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) +#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \ + PID_MAP(MIDI, 3) | PID_MAP(VENDOR, 4) ) #define USB_VID 0xCafe #define USB_BCD 0x0200 diff --git a/examples/device/cdc_msc/src/msc_disk.c b/examples/device/cdc_msc/src/msc_disk.c index b39f5efa1..1a95f7f8b 100644 --- a/examples/device/cdc_msc/src/msc_disk.c +++ b/examples/device/cdc_msc/src/msc_disk.c @@ -58,63 +58,64 @@ 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, - - // 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, 0x55, 0xAA}, + { + 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, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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 -------------// - README_CONTENTS + {README_CONTENTS} }; // Invoked when received SCSI_CMD_INQUIRY, v2 with full inquiry response diff --git a/examples/device/cdc_msc/src/tusb_config.h b/examples/device/cdc_msc/src/tusb_config.h index 811d464e9..fdb2ddf18 100644 --- a/examples/device/cdc_msc/src/tusb_config.h +++ b/examples/device/cdc_msc/src/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -113,4 +113,4 @@ } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/device/cdc_msc/src/usb_descriptors.c b/examples/device/cdc_msc/src/usb_descriptors.c index c9b9a133a..c668ea3a7 100644 --- a/examples/device/cdc_msc/src/usb_descriptors.c +++ b/examples/device/cdc_msc/src/usb_descriptors.c @@ -32,9 +32,9 @@ * Auto ProductID layout's Bitmap: * [MSB] HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) ) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) +#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \ + PID_MAP(MIDI, 3) | PID_MAP(VENDOR, 4) ) #define USB_VID 0xCafe #define USB_BCD 0x0200 diff --git a/examples/device/cdc_msc_freertos/src/tusb_config.h b/examples/device/cdc_msc_freertos/src/tusb_config.h index 9cc3a18d1..6b1937a8d 100644 --- a/examples/device/cdc_msc_freertos/src/tusb_config.h +++ b/examples/device/cdc_msc_freertos/src/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -120,4 +120,4 @@ } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/device/cdc_msc_freertos/src/usb_descriptors.c b/examples/device/cdc_msc_freertos/src/usb_descriptors.c index 58b39a2dd..4950f02e0 100644 --- a/examples/device/cdc_msc_freertos/src/usb_descriptors.c +++ b/examples/device/cdc_msc_freertos/src/usb_descriptors.c @@ -32,9 +32,9 @@ * Auto ProductID layout's Bitmap: * [MSB] HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) ) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) +#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \ + PID_MAP(MIDI, 3) | PID_MAP(VENDOR, 4) ) #define USB_VID 0xCafe #define USB_BCD 0x0200 diff --git a/examples/device/cdc_uac2/src/tusb_config.h b/examples/device/cdc_uac2/src/tusb_config.h index 2e744f8d2..bd1dfc688 100644 --- a/examples/device/cdc_uac2/src/tusb_config.h +++ b/examples/device/cdc_uac2/src/tusb_config.h @@ -24,8 +24,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -171,4 +171,4 @@ extern "C" { } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/device/cdc_uac2/src/usb_descriptors.c b/examples/device/cdc_uac2/src/usb_descriptors.c index 19ed63b51..252b602ac 100644 --- a/examples/device/cdc_uac2/src/usb_descriptors.c +++ b/examples/device/cdc_uac2/src/usb_descriptors.c @@ -35,9 +35,9 @@ * Auto ProductID layout's Bitmap: * [MSB] AUDIO | MIDI | HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(AUDIO, 4) | _PID_MAP(VENDOR, 5) ) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) +#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \ + PID_MAP(MIDI, 3) | PID_MAP(AUDIO, 4) | PID_MAP(VENDOR, 5) ) //--------------------------------------------------------------------+ // Device Descriptors diff --git a/examples/device/dfu/src/usb_descriptors.c b/examples/device/dfu/src/usb_descriptors.c index a7fca87cd..14ec315ea 100644 --- a/examples/device/dfu/src/usb_descriptors.c +++ b/examples/device/dfu/src/usb_descriptors.c @@ -33,9 +33,9 @@ * Auto ProductID layout's Bitmap: * [MSB] HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) ) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) +#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \ + PID_MAP(MIDI, 3) | PID_MAP(VENDOR, 4) ) //--------------------------------------------------------------------+ // Device Descriptors diff --git a/examples/device/dfu_runtime/src/usb_descriptors.c b/examples/device/dfu_runtime/src/usb_descriptors.c index d64ad151f..1d46ee252 100644 --- a/examples/device/dfu_runtime/src/usb_descriptors.c +++ b/examples/device/dfu_runtime/src/usb_descriptors.c @@ -33,9 +33,9 @@ * Auto ProductID layout's Bitmap: * [MSB] HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) ) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) +#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \ + PID_MAP(MIDI, 3) | PID_MAP(VENDOR, 4) ) //--------------------------------------------------------------------+ // Device Descriptors diff --git a/examples/device/dynamic_configuration/src/tusb_config.h b/examples/device/dynamic_configuration/src/tusb_config.h index b9b3878cc..7309d97c9 100644 --- a/examples/device/dynamic_configuration/src/tusb_config.h +++ b/examples/device/dynamic_configuration/src/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -112,4 +112,4 @@ } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/device/dynamic_configuration/src/usb_descriptors.c b/examples/device/dynamic_configuration/src/usb_descriptors.c index 4599c6f82..083279938 100644 --- a/examples/device/dynamic_configuration/src/usb_descriptors.c +++ b/examples/device/dynamic_configuration/src/usb_descriptors.c @@ -32,9 +32,9 @@ * Auto ProductID layout's Bitmap: * [MSB] HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) ) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) +#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \ + PID_MAP(MIDI, 3) | PID_MAP(VENDOR, 4) ) // Configuration mode // 0 : enumerated as CDC/MIDI. Board button is not pressed when enumerating diff --git a/examples/device/hid_boot_interface/src/tusb_config.h b/examples/device/hid_boot_interface/src/tusb_config.h index 52723e09f..5d6fd62e1 100644 --- a/examples/device/hid_boot_interface/src/tusb_config.h +++ b/examples/device/hid_boot_interface/src/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -104,4 +104,4 @@ } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/device/hid_boot_interface/src/usb_descriptors.c b/examples/device/hid_boot_interface/src/usb_descriptors.c index a830dfea8..9b4becc85 100644 --- a/examples/device/hid_boot_interface/src/usb_descriptors.c +++ b/examples/device/hid_boot_interface/src/usb_descriptors.c @@ -33,9 +33,9 @@ * Auto ProductID layout's Bitmap: * [MSB] HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) ) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) +#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \ + PID_MAP(MIDI, 3) | PID_MAP(VENDOR, 4) ) //--------------------------------------------------------------------+ // Device Descriptors diff --git a/examples/device/hid_composite/src/tusb_config.h b/examples/device/hid_composite/src/tusb_config.h index 6bd32c427..895745ed2 100644 --- a/examples/device/hid_composite/src/tusb_config.h +++ b/examples/device/hid_composite/src/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -104,4 +104,4 @@ } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/device/hid_composite/src/usb_descriptors.c b/examples/device/hid_composite/src/usb_descriptors.c index 168f3f325..46e4b63f9 100644 --- a/examples/device/hid_composite/src/usb_descriptors.c +++ b/examples/device/hid_composite/src/usb_descriptors.c @@ -33,9 +33,9 @@ * Auto ProductID layout's Bitmap: * [MSB] HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) ) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) +#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \ + PID_MAP(MIDI, 3) | PID_MAP(VENDOR, 4) ) #define USB_VID 0xCafe #define USB_BCD 0x0200 diff --git a/examples/device/hid_composite_freertos/src/tusb_config.h b/examples/device/hid_composite_freertos/src/tusb_config.h index b28033a0c..ad067ac82 100644 --- a/examples/device/hid_composite_freertos/src/tusb_config.h +++ b/examples/device/hid_composite_freertos/src/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -111,4 +111,4 @@ } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/device/hid_composite_freertos/src/usb_descriptors.c b/examples/device/hid_composite_freertos/src/usb_descriptors.c index dd8682e64..a745c17b5 100644 --- a/examples/device/hid_composite_freertos/src/usb_descriptors.c +++ b/examples/device/hid_composite_freertos/src/usb_descriptors.c @@ -33,9 +33,9 @@ * Auto ProductID layout's Bitmap: * [MSB] HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) ) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) +#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \ + PID_MAP(MIDI, 3) | PID_MAP(VENDOR, 4) ) #define USB_VID 0xCafe #define USB_BCD 0x0200 diff --git a/examples/device/hid_generic_inout/src/tusb_config.h b/examples/device/hid_generic_inout/src/tusb_config.h index 98143ac4d..58dc52afc 100644 --- a/examples/device/hid_generic_inout/src/tusb_config.h +++ b/examples/device/hid_generic_inout/src/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -104,4 +104,4 @@ } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/device/hid_generic_inout/src/usb_descriptors.c b/examples/device/hid_generic_inout/src/usb_descriptors.c index b8bcda30e..f26333d50 100644 --- a/examples/device/hid_generic_inout/src/usb_descriptors.c +++ b/examples/device/hid_generic_inout/src/usb_descriptors.c @@ -32,9 +32,9 @@ * Auto ProductID layout's Bitmap: * [MSB] HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) ) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) +#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \ + PID_MAP(MIDI, 3) | PID_MAP(VENDOR, 4) ) //--------------------------------------------------------------------+ // Device Descriptors diff --git a/examples/device/hid_multiple_interface/src/tusb_config.h b/examples/device/hid_multiple_interface/src/tusb_config.h index 49dc962fe..e1805017d 100644 --- a/examples/device/hid_multiple_interface/src/tusb_config.h +++ b/examples/device/hid_multiple_interface/src/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -104,4 +104,4 @@ } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/device/hid_multiple_interface/src/usb_descriptors.c b/examples/device/hid_multiple_interface/src/usb_descriptors.c index 0c5645247..cd2d93c44 100644 --- a/examples/device/hid_multiple_interface/src/usb_descriptors.c +++ b/examples/device/hid_multiple_interface/src/usb_descriptors.c @@ -32,9 +32,9 @@ * Auto ProductID layout's Bitmap: * [MSB] HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) ) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) +#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \ + PID_MAP(MIDI, 3) | PID_MAP(VENDOR, 4) ) //--------------------------------------------------------------------+ // Device Descriptors diff --git a/examples/device/midi_test/src/tusb_config.h b/examples/device/midi_test/src/tusb_config.h index 314dde438..f4282b2d7 100644 --- a/examples/device/midi_test/src/tusb_config.h +++ b/examples/device/midi_test/src/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -105,4 +105,4 @@ } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/device/midi_test/src/usb_descriptors.c b/examples/device/midi_test/src/usb_descriptors.c index da873479e..e969f33a3 100644 --- a/examples/device/midi_test/src/usb_descriptors.c +++ b/examples/device/midi_test/src/usb_descriptors.c @@ -32,9 +32,9 @@ * Auto ProductID layout's Bitmap: * [MSB] HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) ) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) +#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \ + PID_MAP(MIDI, 3) | PID_MAP(VENDOR, 4) ) //--------------------------------------------------------------------+ // Device Descriptors diff --git a/examples/device/midi_test_freertos/src/tusb_config.h b/examples/device/midi_test_freertos/src/tusb_config.h index 0ffdc37fb..c158f5197 100644 --- a/examples/device/midi_test_freertos/src/tusb_config.h +++ b/examples/device/midi_test_freertos/src/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -105,4 +105,4 @@ } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/device/midi_test_freertos/src/usb_descriptors.c b/examples/device/midi_test_freertos/src/usb_descriptors.c index da873479e..e969f33a3 100644 --- a/examples/device/midi_test_freertos/src/usb_descriptors.c +++ b/examples/device/midi_test_freertos/src/usb_descriptors.c @@ -32,9 +32,9 @@ * Auto ProductID layout's Bitmap: * [MSB] HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) ) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) +#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \ + PID_MAP(MIDI, 3) | PID_MAP(VENDOR, 4) ) //--------------------------------------------------------------------+ // Device Descriptors diff --git a/examples/device/msc_dual_lun/src/tusb_config.h b/examples/device/msc_dual_lun/src/tusb_config.h index 9cbbbade9..4fb6816c6 100644 --- a/examples/device/msc_dual_lun/src/tusb_config.h +++ b/examples/device/msc_dual_lun/src/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -104,4 +104,4 @@ } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/device/msc_dual_lun/src/usb_descriptors.c b/examples/device/msc_dual_lun/src/usb_descriptors.c index 8fbbf0d90..f73935ee0 100644 --- a/examples/device/msc_dual_lun/src/usb_descriptors.c +++ b/examples/device/msc_dual_lun/src/usb_descriptors.c @@ -32,9 +32,9 @@ * Auto ProductID layout's Bitmap: * [MSB] HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) ) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) +#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \ + PID_MAP(MIDI, 3) | PID_MAP(VENDOR, 4) ) //--------------------------------------------------------------------+ // Device Descriptors diff --git a/examples/device/mtp/src/tusb_config.h b/examples/device/mtp/src/tusb_config.h index 4d166aa63..95cc048ee 100644 --- a/examples/device/mtp/src/tusb_config.h +++ b/examples/device/mtp/src/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -136,4 +136,4 @@ } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/device/mtp/src/usb_descriptors.c b/examples/device/mtp/src/usb_descriptors.c index db8b32a4d..f0aa3de6b 100644 --- a/examples/device/mtp/src/usb_descriptors.c +++ b/examples/device/mtp/src/usb_descriptors.c @@ -32,9 +32,9 @@ * Auto ProductID layout's Bitmap: * [MSB] MTP | VENDOR | MIDI | HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) | _PID_MAP(MTP, 5)) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) +#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \ + PID_MAP(MIDI, 3) | PID_MAP(VENDOR, 4) | PID_MAP(MTP, 5)) #define USB_VID 0xCafe #define USB_BCD 0x0200 diff --git a/examples/device/net_lwip_webserver/src/tusb_config.h b/examples/device/net_lwip_webserver/src/tusb_config.h index 31731ac1b..3285ea52c 100644 --- a/examples/device/net_lwip_webserver/src/tusb_config.h +++ b/examples/device/net_lwip_webserver/src/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -141,4 +141,4 @@ extern "C" { } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/device/net_lwip_webserver/src/usb_descriptors.c b/examples/device/net_lwip_webserver/src/usb_descriptors.c index 5bd9ff0f3..1bc568983 100644 --- a/examples/device/net_lwip_webserver/src/usb_descriptors.c +++ b/examples/device/net_lwip_webserver/src/usb_descriptors.c @@ -32,9 +32,9 @@ * Auto ProductID layout's Bitmap: * [MSB] NET | VENDOR | MIDI | HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) | _PID_MAP(ECM_RNDIS, 5) | _PID_MAP(NCM, 5) ) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) +#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \ + PID_MAP(MIDI, 3) | PID_MAP(VENDOR, 4) | PID_MAP(ECM_RNDIS, 5) | PID_MAP(NCM, 5) ) // String Descriptor Index enum diff --git a/examples/device/uac2_headset/src/tusb_config.h b/examples/device/uac2_headset/src/tusb_config.h index e9165163b..2678054e1 100644 --- a/examples/device/uac2_headset/src/tusb_config.h +++ b/examples/device/uac2_headset/src/tusb_config.h @@ -24,8 +24,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -165,4 +165,4 @@ extern "C" { } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/device/uac2_headset/src/usb_descriptors.c b/examples/device/uac2_headset/src/usb_descriptors.c index 7aa0b17fc..7b1a41161 100644 --- a/examples/device/uac2_headset/src/usb_descriptors.c +++ b/examples/device/uac2_headset/src/usb_descriptors.c @@ -34,9 +34,9 @@ * Auto ProductID layout's Bitmap: * [MSB] AUDIO | MIDI | HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(AUDIO, 4) | _PID_MAP(VENDOR, 5) ) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) +#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \ + PID_MAP(MIDI, 3) | PID_MAP(AUDIO, 4) | PID_MAP(VENDOR, 5) ) //--------------------------------------------------------------------+ // Device Descriptors diff --git a/examples/device/uac2_speaker_fb/src/tusb_config.h b/examples/device/uac2_speaker_fb/src/tusb_config.h index 18ab2ff96..153b056bf 100644 --- a/examples/device/uac2_speaker_fb/src/tusb_config.h +++ b/examples/device/uac2_speaker_fb/src/tusb_config.h @@ -24,8 +24,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -162,4 +162,4 @@ extern "C" { } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/device/uac2_speaker_fb/src/usb_descriptors.c b/examples/device/uac2_speaker_fb/src/usb_descriptors.c index 29f7ea6d6..c74eb90dc 100644 --- a/examples/device/uac2_speaker_fb/src/usb_descriptors.c +++ b/examples/device/uac2_speaker_fb/src/usb_descriptors.c @@ -38,9 +38,9 @@ * Auto ProductID layout's Bitmap: * [MSB] AUDIO | MIDI | HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(AUDIO, 4) | _PID_MAP(VENDOR, 5) ) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) +#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \ + PID_MAP(MIDI, 3) | PID_MAP(AUDIO, 4) | PID_MAP(VENDOR, 5) ) //--------------------------------------------------------------------+ // Device Descriptors diff --git a/examples/device/usbtmc/src/usb_descriptors.c b/examples/device/usbtmc/src/usb_descriptors.c index 747850593..16bd176f8 100644 --- a/examples/device/usbtmc/src/usb_descriptors.c +++ b/examples/device/usbtmc/src/usb_descriptors.c @@ -34,9 +34,9 @@ * Auto ProductID layout's Bitmap: * [MSB] HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) ) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) +#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \ + PID_MAP(MIDI, 3) | PID_MAP(VENDOR, 4) ) #define USB_VID 0xcafe #define USB_BCD 0x0200 diff --git a/examples/device/video_capture/src/tusb_config.h b/examples/device/video_capture/src/tusb_config.h index 4ba86ca65..390152e16 100644 --- a/examples/device/video_capture/src/tusb_config.h +++ b/examples/device/video_capture/src/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -115,4 +115,4 @@ } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/device/video_capture/src/usb_descriptors.c b/examples/device/video_capture/src/usb_descriptors.c index 2fd1860c3..114dd5722 100644 --- a/examples/device/video_capture/src/usb_descriptors.c +++ b/examples/device/video_capture/src/usb_descriptors.c @@ -33,9 +33,9 @@ * Auto ProductID layout's Bitmap: * [MSB] VIDEO | AUDIO | MIDI | HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(AUDIO, 4) | _PID_MAP(VIDEO, 5) | _PID_MAP(VENDOR, 6) ) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) +#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \ + PID_MAP(MIDI, 3) | PID_MAP(AUDIO, 4) | PID_MAP(VIDEO, 5) | PID_MAP(VENDOR, 6) ) #define USB_VID 0xCafe #define USB_BCD 0x0200 diff --git a/examples/device/video_capture_2ch/src/tusb_config.h b/examples/device/video_capture_2ch/src/tusb_config.h index e84e49879..48ab4d20a 100644 --- a/examples/device/video_capture_2ch/src/tusb_config.h +++ b/examples/device/video_capture_2ch/src/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -117,4 +117,4 @@ } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/device/video_capture_2ch/src/usb_descriptors.c b/examples/device/video_capture_2ch/src/usb_descriptors.c index 0d19c53cf..024d16e07 100644 --- a/examples/device/video_capture_2ch/src/usb_descriptors.c +++ b/examples/device/video_capture_2ch/src/usb_descriptors.c @@ -33,9 +33,9 @@ * Auto ProductID layout's Bitmap: * [MSB] VIDEO | AUDIO | MIDI | HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(AUDIO, 4) | _PID_MAP(VIDEO, 5) | _PID_MAP(VENDOR, 6) ) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) +#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \ + PID_MAP(MIDI, 3) | PID_MAP(AUDIO, 4) | PID_MAP(VIDEO, 5) | PID_MAP(VENDOR, 6) ) #define USB_VID 0xCafe #define USB_BCD 0x0200 diff --git a/examples/device/webusb_serial/src/tusb_config.h b/examples/device/webusb_serial/src/tusb_config.h index b86ad3752..b6cdf7e56 100644 --- a/examples/device/webusb_serial/src/tusb_config.h +++ b/examples/device/webusb_serial/src/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -111,4 +111,4 @@ } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/device/webusb_serial/src/usb_descriptors.c b/examples/device/webusb_serial/src/usb_descriptors.c index 8579190be..0ef41a68e 100644 --- a/examples/device/webusb_serial/src/usb_descriptors.c +++ b/examples/device/webusb_serial/src/usb_descriptors.c @@ -33,9 +33,9 @@ * Auto ProductID layout's Bitmap: * [MSB] MIDI | HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) ) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) +#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \ + PID_MAP(MIDI, 3) | PID_MAP(VENDOR, 4) ) //--------------------------------------------------------------------+ // Device Descriptors diff --git a/examples/dual/host_hid_to_device_cdc/src/usb_descriptors.c b/examples/dual/host_hid_to_device_cdc/src/usb_descriptors.c index ca515b36e..3efa30e20 100644 --- a/examples/dual/host_hid_to_device_cdc/src/usb_descriptors.c +++ b/examples/dual/host_hid_to_device_cdc/src/usb_descriptors.c @@ -32,9 +32,9 @@ * Auto ProductID layout's Bitmap: * [MSB] HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) ) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) +#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \ + PID_MAP(MIDI, 3) | PID_MAP(VENDOR, 4) ) #define USB_VID 0xCafe #define USB_BCD 0x0200 diff --git a/examples/dual/host_info_to_device_cdc/src/usb_descriptors.c b/examples/dual/host_info_to_device_cdc/src/usb_descriptors.c index ca515b36e..3efa30e20 100644 --- a/examples/dual/host_info_to_device_cdc/src/usb_descriptors.c +++ b/examples/dual/host_info_to_device_cdc/src/usb_descriptors.c @@ -32,9 +32,9 @@ * Auto ProductID layout's Bitmap: * [MSB] HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) ) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) +#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \ + PID_MAP(MIDI, 3) | PID_MAP(VENDOR, 4) ) #define USB_VID 0xCafe #define USB_BCD 0x0200 diff --git a/examples/host/cdc_msc_hid/src/tusb_config.h b/examples/host/cdc_msc_hid/src/tusb_config.h index 2f8cb5e03..75de3511c 100644 --- a/examples/host/cdc_msc_hid/src/tusb_config.h +++ b/examples/host/cdc_msc_hid/src/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -134,4 +134,4 @@ } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ 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 3cdb227e2..8583e7176 100644 --- a/examples/host/cdc_msc_hid_freertos/src/tusb_config.h +++ b/examples/host/cdc_msc_hid_freertos/src/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -139,4 +139,4 @@ } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/host/hid_controller/src/tusb_config.h b/examples/host/hid_controller/src/tusb_config.h index 351fe0178..a5c202fda 100644 --- a/examples/host/hid_controller/src/tusb_config.h +++ b/examples/host/hid_controller/src/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -119,4 +119,4 @@ } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/host/msc_file_explorer/src/tusb_config.h b/examples/host/msc_file_explorer/src/tusb_config.h index c1829c300..a9d24c89f 100644 --- a/examples/host/msc_file_explorer/src/tusb_config.h +++ b/examples/host/msc_file_explorer/src/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -118,4 +118,4 @@ } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/typec/power_delivery/src/tusb_config.h b/examples/typec/power_delivery/src/tusb_config.h index f7cb3cc04..ee013d056 100644 --- a/examples/typec/power_delivery/src/tusb_config.h +++ b/examples/typec/power_delivery/src/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -80,4 +80,4 @@ } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/hw/bsp/ansi_escape.h b/hw/bsp/ansi_escape.h index 15af2f3ab..0b72bea17 100644 --- a/hw/bsp/ansi_escape.h +++ b/hw/bsp/ansi_escape.h @@ -28,8 +28,8 @@ * \defgroup group_ansi_esc ANSI Escape Code * @{ */ -#ifndef _TUSB_ANSI_ESC_CODE_H_ -#define _TUSB_ANSI_ESC_CODE_H_ +#ifndef TUSB_ANSI_ESC_CODE_H_ +#define TUSB_ANSI_ESC_CODE_H_ #ifdef __cplusplus @@ -92,6 +92,6 @@ } #endif -#endif /* _TUSB_ANSI_ESC_CODE_H_ */ +#endif /* TUSB_ANSI_ESC_CODE_H_ */ /** @} */ diff --git a/hw/bsp/nuc100_120/family.cmake b/hw/bsp/nuc100_120/family.cmake index f81447596..b8f36bb9b 100644 --- a/hw/bsp/nuc100_120/family.cmake +++ b/hw/bsp/nuc100_120/family.cmake @@ -69,19 +69,17 @@ function(family_configure_example TARGET RTOS) "LINKER:--script=${LD_FILE_GNU}" --specs=nosys.specs --specs=nano.specs ) + target_compile_options(${TARGET} PRIVATE -Wno-redundant-decls) elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - target_link_options(${TARGET} PUBLIC - "LINKER:--script=${LD_FILE_Clang}" - ) + target_link_options(${TARGET} PUBLIC "LINKER:--script=${LD_FILE_Clang}") + target_compile_options(${TARGET} PRIVATE -Wno-redundant-decls) elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) + target_link_options(${TARGET} PUBLIC "LINKER:--config=${LD_FILE_IAR}") endif () if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES - COMPILE_FLAGS "-Wno-missing-prototypes -Wno-redundant-decls") + COMPILE_FLAGS "-Wno-missing-prototypes") endif () set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES SKIP_LINTING ON diff --git a/hw/bsp/nuc121_125/family.cmake b/hw/bsp/nuc121_125/family.cmake index 718f8db9a..ee52e9ce4 100644 --- a/hw/bsp/nuc121_125/family.cmake +++ b/hw/bsp/nuc121_125/family.cmake @@ -72,14 +72,14 @@ function(family_configure_example TARGET RTOS) "LINKER:--script=${LD_FILE_GNU}" --specs=nosys.specs --specs=nano.specs ) + target_compile_options(${TARGET} PRIVATE -Wno-redundant-decls) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - target_link_options(${TARGET} PUBLIC - "LINKER:--script=${LD_FILE_Clang}" - ) + target_link_options(${TARGET} PUBLIC "LINKER:--script=${LD_FILE_Clang}") + target_compile_options(${TARGET} PRIVATE -Wno-redundant-decls) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) + target_link_options(${TARGET} PUBLIC "LINKER:--config=${LD_FILE_IAR}") endif () if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") diff --git a/hw/bsp/nuc126/family.cmake b/hw/bsp/nuc126/family.cmake index 3fc670cf0..d0f99ba1a 100644 --- a/hw/bsp/nuc126/family.cmake +++ b/hw/bsp/nuc126/family.cmake @@ -75,14 +75,14 @@ function(family_configure_example TARGET RTOS) "LINKER:--script=${LD_FILE_GNU}" --specs=nosys.specs --specs=nano.specs ) + target_compile_options(${TARGET} PRIVATE -Wno-redundant-decls) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - target_link_options(${TARGET} PUBLIC - "LINKER:--script=${LD_FILE_Clang}" - ) + target_link_options(${TARGET} PUBLIC "LINKER:--script=${LD_FILE_Clang}") + target_compile_options(${TARGET} PRIVATE -Wno-redundant-decls) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) + target_link_options(${TARGET} PUBLIC "LINKER:--config=${LD_FILE_IAR}") endif () if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") diff --git a/hw/bsp/nuc505/family.cmake b/hw/bsp/nuc505/family.cmake index a31f5ff73..581cad4d0 100644 --- a/hw/bsp/nuc505/family.cmake +++ b/hw/bsp/nuc505/family.cmake @@ -71,14 +71,14 @@ function(family_configure_example TARGET RTOS) "LINKER:--script=${LD_FILE_GNU}" --specs=nosys.specs --specs=nano.specs ) + target_compile_options(${TARGET} PRIVATE -Wno-redundant-decls) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - target_link_options(${TARGET} PUBLIC - "LINKER:--script=${LD_FILE_Clang}" - ) + target_link_options(${TARGET} PUBLIC "LINKER:--script=${LD_FILE_Clang}") + target_compile_options(${TARGET} PRIVATE -Wno-redundant-decls) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) + target_link_options(${TARGET} PUBLIC "LINKER:--config=${LD_FILE_IAR}") endif () if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") diff --git a/lib/rt-thread/tusb_config.h b/lib/rt-thread/tusb_config.h index 11dc21983..6f794dc41 100644 --- a/lib/rt-thread/tusb_config.h +++ b/lib/rt-thread/tusb_config.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __RTTHREAD__ #include @@ -215,4 +215,4 @@ extern "C" { #endif #endif /*__RTTHREAD__*/ -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/src/class/audio/audio.h b/src/class/audio/audio.h index 0d1acadcc..fc352a1af 100644 --- a/src/class/audio/audio.h +++ b/src/class/audio/audio.h @@ -30,8 +30,8 @@ * Currently only MIDI subclass is supported * @{ */ -#ifndef _TUSB_AUDIO_H__ -#define _TUSB_AUDIO_H__ +#ifndef TUSB_AUDIO_H__ +#define TUSB_AUDIO_H__ #include "common/tusb_common.h" diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index 00948767e..b22a918f4 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -462,7 +462,7 @@ void audiod_sof_isr (uint8_t rhport, uint32_t frame_count); } #endif -#endif /* _TUSB_AUDIO_DEVICE_H_ */ +#endif /* TUSB_AUDIO_DEVICE_H_ */ /** @} */ /** @} */ diff --git a/src/class/bth/bth_device.h b/src/class/bth/bth_device.h index 68f073bff..89a056dc8 100755 --- a/src/class/bth/bth_device.h +++ b/src/class/bth/bth_device.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_BTH_DEVICE_H_ -#define _TUSB_BTH_DEVICE_H_ +#ifndef TUSB_BTH_DEVICE_H_ +#define TUSB_BTH_DEVICE_H_ #include #include @@ -114,4 +114,4 @@ bool btd_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t r } #endif -#endif /* _TUSB_BTH_DEVICE_H_ */ +#endif /* TUSB_BTH_DEVICE_H_ */ diff --git a/src/class/cdc/cdc.h b/src/class/cdc/cdc.h index 10ba16a7c..6d207c717 100644 --- a/src/class/cdc/cdc.h +++ b/src/class/cdc/cdc.h @@ -29,8 +29,8 @@ * Currently only Abstract Control Model subclass is supported * @{ */ -#ifndef _TUSB_CDC_H__ -#define _TUSB_CDC_H__ +#ifndef TUSB_CDC_H__ +#define TUSB_CDC_H__ #include "common/tusb_common.h" diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 9673b9807..c321f3d16 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -257,4 +257,4 @@ bool cdcd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t re } #endif -#endif /* _TUSB_CDC_DEVICE_H_ */ +#endif /* TUSB_CDC_DEVICE_H_ */ diff --git a/src/class/cdc/cdc_host.h b/src/class/cdc/cdc_host.h index bf6711d7e..e8637beac 100644 --- a/src/class/cdc/cdc_host.h +++ b/src/class/cdc/cdc_host.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_CDC_HOST_H_ -#define _TUSB_CDC_HOST_H_ +#ifndef TUSB_CDC_HOST_H_ +#define TUSB_CDC_HOST_H_ #include "cdc.h" @@ -255,4 +255,4 @@ void cdch_close (uint8_t dev_addr); } #endif -#endif /* _TUSB_CDC_HOST_H_ */ +#endif /* TUSB_CDC_HOST_H_ */ diff --git a/src/class/cdc/cdc_rndis.h b/src/class/cdc/cdc_rndis.h index ad153e0ac..fbbd43206 100644 --- a/src/class/cdc/cdc_rndis.h +++ b/src/class/cdc/cdc_rndis.h @@ -30,8 +30,8 @@ * \defgroup CDC_RNDIS_Common Common Definitions * @{ */ -#ifndef _TUSB_CDC_RNDIS_H_ -#define _TUSB_CDC_RNDIS_H_ +#ifndef TUSB_CDC_RNDIS_H_ +#define TUSB_CDC_RNDIS_H_ #include "cdc.h" @@ -295,7 +295,7 @@ typedef enum } #endif -#endif /* _TUSB_CDC_RNDIS_H_ */ +#endif /* TUSB_CDC_RNDIS_H_ */ /** @} */ /** @} */ diff --git a/src/class/cdc/cdc_rndis_host.h b/src/class/cdc/cdc_rndis_host.h index bb431ec1f..e70d27f79 100644 --- a/src/class/cdc/cdc_rndis_host.h +++ b/src/class/cdc/cdc_rndis_host.h @@ -28,8 +28,8 @@ * \defgroup CDC_RNSID_Host Host * @{ */ -#ifndef _TUSB_CDC_RNDIS_HOST_H_ -#define _TUSB_CDC_RNDIS_HOST_H_ +#ifndef TUSB_CDC_RNDIS_HOST_H_ +#define TUSB_CDC_RNDIS_HOST_H_ #include "common/tusb_common.h" #include "host/usbh.h" @@ -58,6 +58,6 @@ void rndish_close(uint8_t dev_addr); } #endif -#endif /* _TUSB_CDC_RNDIS_HOST_H_ */ +#endif /* TUSB_CDC_RNDIS_HOST_H_ */ /** @} */ diff --git a/src/class/dfu/dfu.h b/src/class/dfu/dfu.h index 114c827b8..8cd63656a 100644 --- a/src/class/dfu/dfu.h +++ b/src/class/dfu/dfu.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_DFU_H_ -#define _TUSB_DFU_H_ +#ifndef TUSB_DFU_H_ +#define TUSB_DFU_H_ #include "common/tusb_common.h" @@ -116,4 +116,4 @@ TU_VERIFY_STATIC( sizeof(dfu_status_response_t) == 6, "size is not correct"); } #endif -#endif /* _TUSB_DFU_H_ */ +#endif /* TUSB_DFU_H_ */ diff --git a/src/class/dfu/dfu_device.h b/src/class/dfu/dfu_device.h index e59e61ce9..b22b4c450 100644 --- a/src/class/dfu/dfu_device.h +++ b/src/class/dfu/dfu_device.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_DFU_DEVICE_H_ -#define _TUSB_DFU_DEVICE_H_ +#ifndef TUSB_DFU_DEVICE_H_ +#define TUSB_DFU_DEVICE_H_ #include "dfu.h" @@ -96,4 +96,4 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_r } #endif -#endif /* _TUSB_DFU_MODE_DEVICE_H_ */ +#endif /* TUSB_DFU_MODE_DEVICE_H_ */ diff --git a/src/class/dfu/dfu_rt_device.h b/src/class/dfu/dfu_rt_device.h index 67eb26d95..c4116d8fe 100644 --- a/src/class/dfu/dfu_rt_device.h +++ b/src/class/dfu/dfu_rt_device.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_DFU_RT_DEVICE_H_ -#define _TUSB_DFU_RT_DEVICE_H_ +#ifndef TUSB_DFU_RT_DEVICE_H_ +#define TUSB_DFU_RT_DEVICE_H_ #include "dfu.h" @@ -52,4 +52,4 @@ bool dfu_rtd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_req } #endif -#endif /* _TUSB_DFU_RT_DEVICE_H_ */ +#endif /* TUSB_DFU_RT_DEVICE_H_ */ diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h index b69f623a0..0883d95ac 100644 --- a/src/class/hid/hid.h +++ b/src/class/hid/hid.h @@ -28,8 +28,8 @@ * \defgroup ClassDriver_HID Human Interface Device (HID) * @{ */ -#ifndef _TUSB_HID_H_ -#define _TUSB_HID_H_ +#ifndef TUSB_HID_H_ +#define TUSB_HID_H_ #include "common/tusb_common.h" @@ -2071,6 +2071,6 @@ enum { } #endif -#endif /* _TUSB_HID_H__ */ +#endif /* TUSB_HID_H__ */ /// @} diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index 032827af1..87f0e7dc9 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_HID_HOST_H_ -#define _TUSB_HID_HOST_H_ +#ifndef TUSB_HID_HOST_H_ +#define TUSB_HID_HOST_H_ #include "hid.h" @@ -182,4 +182,4 @@ void hidh_close(uint8_t dev_addr); } #endif -#endif /* _TUSB_HID_HOST_H_ */ +#endif /* TUSB_HID_HOST_H_ */ diff --git a/src/class/midi/midi_device.h b/src/class/midi/midi_device.h index c2c6e9859..d23516cec 100644 --- a/src/class/midi/midi_device.h +++ b/src/class/midi/midi_device.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_MIDI_DEVICE_H_ -#define _TUSB_MIDI_DEVICE_H_ +#ifndef TUSB_MIDI_DEVICE_H_ +#define TUSB_MIDI_DEVICE_H_ #include "class/audio/audio.h" #include "midi.h" @@ -168,7 +168,7 @@ bool midid_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t } #endif -#endif /* _TUSB_MIDI_DEVICE_H_ */ +#endif /* TUSB_MIDI_DEVICE_H_ */ /** @} */ /** @} */ diff --git a/src/class/msc/msc.h b/src/class/msc/msc.h index b2b44eac4..3b5d4a855 100644 --- a/src/class/msc/msc.h +++ b/src/class/msc/msc.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_MSC_H_ -#define _TUSB_MSC_H_ +#ifndef TUSB_MSC_H_ +#define TUSB_MSC_H_ #include "common/tusb_common.h" @@ -398,4 +398,4 @@ TU_VERIFY_STATIC(sizeof(scsi_write10_t) == 10, "size is not correct"); } #endif -#endif /* _TUSB_MSC_H_ */ +#endif /* TUSB_MSC_H_ */ diff --git a/src/class/msc/msc_device.h b/src/class/msc/msc_device.h index 7d898e988..21e24971b 100644 --- a/src/class/msc/msc_device.h +++ b/src/class/msc/msc_device.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_MSC_DEVICE_H_ -#define _TUSB_MSC_DEVICE_H_ +#ifndef TUSB_MSC_DEVICE_H_ +#define TUSB_MSC_DEVICE_H_ #include "common/tusb_common.h" #include "msc.h" @@ -167,4 +167,4 @@ bool mscd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t ev } #endif -#endif /* _TUSB_MSC_DEVICE_H_ */ +#endif /* TUSB_MSC_DEVICE_H_ */ diff --git a/src/class/net/ncm.h b/src/class/net/ncm.h index 0245a87f2..8989fe0b4 100644 --- a/src/class/net/ncm.h +++ b/src/class/net/ncm.h @@ -25,8 +25,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_NCM_H_ -#define _TUSB_NCM_H_ +#ifndef TUSB_NCM_H_ +#define TUSB_NCM_H_ #include "common/tusb_common.h" diff --git a/src/class/net/net_device.h b/src/class/net/net_device.h index ef5ecffc8..96c03fd61 100644 --- a/src/class/net/net_device.h +++ b/src/class/net/net_device.h @@ -25,8 +25,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_NET_DEVICE_H_ -#define _TUSB_NET_DEVICE_H_ +#ifndef TUSB_NET_DEVICE_H_ +#define TUSB_NET_DEVICE_H_ #include #include "class/cdc/cdc.h" @@ -114,4 +114,4 @@ void netd_report (uint8_t *buf, uint16_t len); } #endif -#endif /* _TUSB_NET_DEVICE_H_ */ +#endif /* TUSB_NET_DEVICE_H_ */ diff --git a/src/class/usbtmc/usbtmc.h b/src/class/usbtmc/usbtmc.h index 327de087c..3bf5e1a17 100644 --- a/src/class/usbtmc/usbtmc.h +++ b/src/class/usbtmc/usbtmc.h @@ -25,8 +25,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_USBTMC_H__ -#define _TUSB_USBTMC_H__ +#ifndef TUSB_USBTMC_H__ +#define TUSB_USBTMC_H__ #include "common/tusb_common.h" diff --git a/src/class/vendor/vendor_device.h b/src/class/vendor/vendor_device.h index 5fe4fc9ff..5376f3917 100644 --- a/src/class/vendor/vendor_device.h +++ b/src/class/vendor/vendor_device.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_VENDOR_DEVICE_H_ -#define _TUSB_VENDOR_DEVICE_H_ +#ifndef TUSB_VENDOR_DEVICE_H_ +#define TUSB_VENDOR_DEVICE_H_ #include "common/tusb_common.h" @@ -141,4 +141,4 @@ bool vendord_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, u } #endif -#endif /* _TUSB_VENDOR_DEVICE_H_ */ +#endif /* TUSB_VENDOR_DEVICE_H_ */ diff --git a/src/class/vendor/vendor_host.h b/src/class/vendor/vendor_host.h index acfebe7a4..00e3c3402 100644 --- a/src/class/vendor/vendor_host.h +++ b/src/class/vendor/vendor_host.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_VENDOR_HOST_H_ -#define _TUSB_VENDOR_HOST_H_ +#ifndef TUSB_VENDOR_HOST_H_ +#define TUSB_VENDOR_HOST_H_ #include "common/tusb_common.h" @@ -64,4 +64,4 @@ void cush_close(uint8_t dev_addr); } #endif -#endif /* _TUSB_VENDOR_HOST_H_ */ +#endif /* TUSB_VENDOR_HOST_H_ */ diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index dfa9299c1..04149da71 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_COMMON_H_ -#define _TUSB_COMMON_H_ +#ifndef TUSB_COMMON_H_ +#define TUSB_COMMON_H_ #ifdef __cplusplus extern "C" { @@ -391,4 +391,4 @@ uint8_t const * tu_desc_find3(uint8_t const* desc, uint8_t const* end, uint8_t b } #endif -#endif /* _TUSB_COMMON_H_ */ +#endif /* TUSB_COMMON_H_ */ diff --git a/src/common/tusb_compiler.h b/src/common/tusb_compiler.h index 9b33a6f61..55950fb45 100644 --- a/src/common/tusb_compiler.h +++ b/src/common/tusb_compiler.h @@ -29,8 +29,8 @@ * \brief Group_Compiler brief * @{ */ -#ifndef _TUSB_COMPILER_H_ -#define _TUSB_COMPILER_H_ +#ifndef TUSB_COMPILER_H_ +#define TUSB_COMPILER_H_ #define TU_TOKEN(x) x #define TU_STRING(x) #x ///< stringify without expand @@ -45,9 +45,9 @@ #define TU_INCLUDE_PATH(_dir,_file) TU_XSTRING( TU_TOKEN(_dir)TU_TOKEN(_file) ) #if defined __COUNTER__ && __COUNTER__ != __COUNTER__ - #define _TU_COUNTER_ __COUNTER__ + #define TU_COUNTER __COUNTER__ #else - #define _TU_COUNTER_ __LINE__ + #define TU_COUNTER __LINE__ #endif // Compile-time Assert @@ -56,9 +56,9 @@ #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112L #define TU_VERIFY_STATIC _Static_assert #elif defined(__CCRX__) - #define TU_VERIFY_STATIC(const_expr, _mess) typedef char TU_XSTRCAT(_verify_static_, _TU_COUNTER_)[(const_expr) ? 1 : 0]; + #define TU_VERIFY_STATIC(const_expr, _mess) typedef char TU_XSTRCAT(_verify_static_, TU_COUNTER)[(const_expr) ? 1 : 0]; #else - #define TU_VERIFY_STATIC(const_expr, _mess) enum { TU_XSTRCAT(_verify_static_, _TU_COUNTER_) = 1/(!!(const_expr)) } + #define TU_VERIFY_STATIC(const_expr, _mess) enum { TU_XSTRCAT(_verify_static_, TU_COUNTER) = 1/(!!(const_expr)) } #endif /* --------------------- Fuzzing types -------------------------------------- */ @@ -68,8 +68,8 @@ #define tu_static static #endif -// for declaration of reserved field, make use of _TU_COUNTER_ -#define TU_RESERVED TU_XSTRCAT(reserved, _TU_COUNTER_) +// for declaration of reserved field, make use of TU_COUNTER +#define TU_RESERVED TU_XSTRCAT(reserved, TU_COUNTER) #define TU_LITTLE_ENDIAN (0x12u) #define TU_BIG_ENDIAN (0x21u) @@ -305,6 +305,6 @@ #error Byte order is undefined #endif -#endif /* _TUSB_COMPILER_H_ */ +#endif /* TUSB_COMPILER_H_ */ /// @} diff --git a/src/common/tusb_debug.h b/src/common/tusb_debug.h index 86517b9c9..e3f9d3f18 100644 --- a/src/common/tusb_debug.h +++ b/src/common/tusb_debug.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_DEBUG_H_ -#define _TUSB_DEBUG_H_ +#ifndef TUSB_DEBUG_H_ +#define TUSB_DEBUG_H_ #ifdef __cplusplus extern "C" { @@ -168,4 +168,4 @@ static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint3 } #endif -#endif /* _TUSB_DEBUG_H_ */ +#endif diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 879acda4f..f2a6c5469 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -25,8 +25,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_FIFO_H_ -#define _TUSB_FIFO_H_ +#ifndef TUSB_FIFO_H_ +#define TUSB_FIFO_H_ #ifdef __cplusplus extern "C" { @@ -196,4 +196,4 @@ void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info); } #endif -#endif /* _TUSB_FIFO_H_ */ +#endif diff --git a/src/device/usbd.h b/src/device/usbd.h index c62986150..f75803b14 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_USBD_H_ -#define _TUSB_USBD_H_ +#ifndef TUSB_USBD_H_ +#define TUSB_USBD_H_ #include "common/tusb_common.h" @@ -904,6 +904,6 @@ bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_requ } #endif -#endif /* _TUSB_USBD_H_ */ +#endif /* TUSB_USBD_H_ */ /** @} */ diff --git a/src/host/hcd.h b/src/host/hcd.h index d3551bf5b..4a17326ec 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_HCD_H_ -#define _TUSB_HCD_H_ +#ifndef TUSB_HCD_H_ +#define TUSB_HCD_H_ #include "common/tusb_common.h" #include "osal/osal.h" diff --git a/src/host/usbh.h b/src/host/usbh.h index 8d48bf90d..4b6747848 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_USBH_H_ -#define _TUSB_USBH_H_ +#ifndef TUSB_USBH_H_ +#define TUSB_USBH_H_ #ifdef __cplusplus extern "C" { @@ -179,7 +179,7 @@ TU_ATTR_ALWAYS_INLINE static inline void tuh_task(void) { // Check if there is pending events need processing by tuh_task() bool tuh_task_event_ready(void); -#ifndef _TUSB_HCD_H_ +#ifndef TUSB_HCD_H_ extern void hcd_int_handler(uint8_t rhport, bool in_isr); #endif diff --git a/src/host/usbh_pvt.h b/src/host/usbh_pvt.h index 9d91e52e8..d722bb7e8 100644 --- a/src/host/usbh_pvt.h +++ b/src/host/usbh_pvt.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_USBH_PVT_H_ -#define _TUSB_USBH_PVT_H_ +#ifndef TUSB_USBH_PVT_H_ +#define TUSB_USBH_PVT_H_ #include "osal/osal.h" #include "common/tusb_fifo.h" diff --git a/src/osal/osal.h b/src/osal/osal.h index 658b18584..44521620f 100644 --- a/src/osal/osal.h +++ b/src/osal/osal.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_OSAL_H_ -#define _TUSB_OSAL_H_ +#ifndef TUSB_OSAL_H_ +#define TUSB_OSAL_H_ #ifdef __cplusplus extern "C" { @@ -101,4 +101,4 @@ typedef void (*osal_task_func_t)(void* param); } #endif -#endif /* _TUSB_OSAL_H_ */ +#endif diff --git a/src/osal/osal_none.h b/src/osal/osal_none.h index 6f9b8b0dc..bc86dcb28 100644 --- a/src/osal/osal_none.h +++ b/src/osal/osal_none.h @@ -156,7 +156,7 @@ typedef osal_queue_def_t* osal_queue_t; } TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) { - tu_fifo_clear(&qdef->ff); + (void) tu_fifo_clear(&qdef->ff); return (osal_queue_t) qdef; } diff --git a/src/portable/ehci/ehci.h b/src/portable/ehci/ehci.h index 87659701b..719bdeafc 100644 --- a/src/portable/ehci/ehci.h +++ b/src/portable/ehci/ehci.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_EHCI_H_ -#define _TUSB_EHCI_H_ +#ifndef TUSB_EHCI_H_ +#define TUSB_EHCI_H_ /* Abbreviation @@ -458,4 +458,4 @@ TU_VERIFY_STATIC(sizeof(ehci_cap_registers_t) == 16, "size is not correct"); } #endif -#endif /* _TUSB_EHCI_H_ */ +#endif /* TUSB_EHCI_H_ */ diff --git a/src/portable/ehci/ehci_api.h b/src/portable/ehci/ehci_api.h index 12e0a73d7..79fbe702a 100644 --- a/src/portable/ehci/ehci_api.h +++ b/src/portable/ehci/ehci_api.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_EHCI_API_H_ -#define _TUSB_EHCI_API_H_ +#ifndef TUSB_EHCI_API_H_ +#define TUSB_EHCI_API_H_ #ifdef __cplusplus extern "C" { diff --git a/src/portable/nxp/lpc17_40/dcd_lpc17_40.h b/src/portable/nxp/lpc17_40/dcd_lpc17_40.h index 654b80866..25c9f9985 100644 --- a/src/portable/nxp/lpc17_40/dcd_lpc17_40.h +++ b/src/portable/nxp/lpc17_40/dcd_lpc17_40.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_DCD_LPC17_40_H_ -#define _TUSB_DCD_LPC17_40_H_ +#ifndef TUSB_DCD_LPC17_40_H_ +#define TUSB_DCD_LPC17_40_H_ #include "common/tusb_common.h" diff --git a/src/portable/ohci/ohci.h b/src/portable/ohci/ohci.h index 94bad5df7..3366f15f7 100644 --- a/src/portable/ohci/ohci.h +++ b/src/portable/ohci/ohci.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_OHCI_H_ -#define _TUSB_OHCI_H_ +#ifndef TUSB_OHCI_H_ +#define TUSB_OHCI_H_ #ifdef __cplusplus extern "C" { @@ -304,4 +304,4 @@ TU_VERIFY_STATIC( sizeof(ohci_registers_t) == (0x54 + (4 * TUP_OHCI_RHPORTS)), " } #endif -#endif /* _TUSB_OHCI_H_ */ +#endif /* TUSB_OHCI_H_ */ diff --git a/src/portable/renesas/rusb2/rusb2_type.h b/src/portable/renesas/rusb2/rusb2_type.h index dd88f66a7..71837d03c 100644 --- a/src/portable/renesas/rusb2/rusb2_type.h +++ b/src/portable/renesas/rusb2/rusb2_type.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_RUSB2_TYPE_H_ -#define _TUSB_RUSB2_TYPE_H_ +#ifndef TUSB_RUSB2_TYPE_H_ +#define TUSB_RUSB2_TYPE_H_ #include #include @@ -1777,4 +1777,4 @@ TU_VERIFY_STATIC(offsetof(rusb2_reg_t, DPUSR1R_FS ) == 0x0404, "incorrect offset } #endif -#endif /* _TUSB_RUSB2_TYPE_H_ */ +#endif /* TUSB_RUSB2_TYPE_H_ */ diff --git a/src/portable/sunxi/musb_def.h b/src/portable/sunxi/musb_def.h index 53da5ded2..ce9b89d55 100644 --- a/src/portable/sunxi/musb_def.h +++ b/src/portable/sunxi/musb_def.h @@ -26,8 +26,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_MUSB_DEF -#define _TUSB_MUSB_DEF +#ifndef TUSB_MUSB_DEF +#define TUSB_MUSB_DEF #define USBC_Readb(reg) (*(volatile unsigned char *)(reg)) diff --git a/src/portable/synopsys/dwc2/dwc2_bcm.h b/src/portable/synopsys/dwc2/dwc2_bcm.h index e5824606a..df6d4a852 100644 --- a/src/portable/synopsys/dwc2/dwc2_bcm.h +++ b/src/portable/synopsys/dwc2/dwc2_bcm.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_DWC2_BCM_H_ -#define _TUSB_DWC2_BCM_H_ +#ifndef TUSB_DWC2_BCM_H_ +#define TUSB_DWC2_BCM_H_ #ifdef __cplusplus extern "C" { diff --git a/src/portable/valentyusb/eptri/dcd_eptri.h b/src/portable/valentyusb/eptri/dcd_eptri.h index d67635d7c..2fe74a712 100644 --- a/src/portable/valentyusb/eptri/dcd_eptri.h +++ b/src/portable/valentyusb/eptri/dcd_eptri.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_DCD_VALENTYUSB_EPTRI_H_ -#define _TUSB_DCD_VALENTYUSB_EPTRI_H_ +#ifndef TUSB_DCD_VALENTYUSB_EPTRI_H_ +#define TUSB_DCD_VALENTYUSB_EPTRI_H_ #include "common/tusb_common.h" #ifdef __cplusplus @@ -36,4 +36,4 @@ } #endif -#endif /* _TUSB_DCD_VALENTYUSB_EPTRI_H_ */ +#endif /* TUSB_DCD_VALENTYUSB_EPTRI_H_ */ diff --git a/src/tusb.h b/src/tusb.h index 6a469eef4..62b3b9783 100644 --- a/src/tusb.h +++ b/src/tusb.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_H_ -#define _TUSB_H_ +#ifndef TUSB_H_ +#define TUSB_H_ #ifdef __cplusplus extern "C" { @@ -178,4 +178,4 @@ bool tusb_deinit(uint8_t rhport); } #endif -#endif /* _TUSB_H_ */ +#endif /* TUSB_H_ */ diff --git a/src/tusb_option.h b/src/tusb_option.h index 14404c59c..e00311039 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_OPTION_H_ -#define _TUSB_OPTION_H_ +#ifndef TUSB_OPTION_H_ +#define TUSB_OPTION_H_ #include "common/tusb_compiler.h" @@ -727,6 +727,6 @@ // To avoid GCC compiler warnings when -pedantic option is used (strict ISO C) typedef int make_iso_compilers_happy; -#endif /* _TUSB_OPTION_H_ */ +#endif /* TUSB_OPTION_H_ */ /** @} */ diff --git a/src/typec/pd_types.h b/src/typec/pd_types.h index 1b2968f65..950f4d488 100644 --- a/src/typec/pd_types.h +++ b/src/typec/pd_types.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_PD_TYPES_H_ -#define _TUSB_PD_TYPES_H_ +#ifndef TUSB_PD_TYPES_H_ +#define TUSB_PD_TYPES_H_ #ifdef __cplusplus extern "C" { diff --git a/src/typec/tcd.h b/src/typec/tcd.h index bcbdab8ed..da7ab4b13 100644 --- a/src/typec/tcd.h +++ b/src/typec/tcd.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_TCD_H_ -#define _TUSB_TCD_H_ +#ifndef TUSB_TCD_H_ +#define TUSB_TCD_H_ #include "common/tusb_common.h" #include "pd_types.h" diff --git a/src/typec/usbc.h b/src/typec/usbc.h index 448542aab..711119596 100644 --- a/src/typec/usbc.h +++ b/src/typec/usbc.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_UTCD_H_ -#define _TUSB_UTCD_H_ +#ifndef TUSB_UTCD_H_ +#define TUSB_UTCD_H_ #include "common/tusb_common.h" #include "pd_types.h" @@ -63,7 +63,7 @@ void tuc_task (void) { tuc_task_ext(UINT32_MAX, false); } -#ifndef _TUSB_TCD_H_ +#ifndef TUSB_TCD_H_ extern void tcd_int_handler(uint8_t rhport); #endif diff --git a/test/fuzz/device/cdc/src/tusb_config.h b/test/fuzz/device/cdc/src/tusb_config.h index 10a8a825a..76f44619e 100644 --- a/test/fuzz/device/cdc/src/tusb_config.h +++ b/test/fuzz/device/cdc/src/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -111,4 +111,4 @@ } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/test/fuzz/device/cdc/src/usb_descriptors.cc b/test/fuzz/device/cdc/src/usb_descriptors.cc index c26bd18c3..0d7d17b4b 100644 --- a/test/fuzz/device/cdc/src/usb_descriptors.cc +++ b/test/fuzz/device/cdc/src/usb_descriptors.cc @@ -30,10 +30,10 @@ * Auto ProductID layout's Bitmap: * [MSB] HID | CDC [LSB] */ -#define _PID_MAP(itf, n) ((CFG_TUD_##itf) << (n)) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) << (n)) #define USB_PID \ - (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(HID, 2) | _PID_MAP(MIDI, 3) | \ - _PID_MAP(VENDOR, 4)) + (0x4000 | PID_MAP(CDC, 0) | PID_MAP(HID, 2) | PID_MAP(MIDI, 3) | \ + PID_MAP(VENDOR, 4)) #define USB_VID 0xCafe #define USB_BCD 0x0200 diff --git a/test/fuzz/device/msc/src/tusb_config.h b/test/fuzz/device/msc/src/tusb_config.h index ca39c6b0a..abd8cd4ce 100644 --- a/test/fuzz/device/msc/src/tusb_config.h +++ b/test/fuzz/device/msc/src/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -111,4 +111,4 @@ } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/test/fuzz/device/msc/src/usb_descriptors.cc b/test/fuzz/device/msc/src/usb_descriptors.cc index 6d9c4cd96..55c113ad7 100644 --- a/test/fuzz/device/msc/src/usb_descriptors.cc +++ b/test/fuzz/device/msc/src/usb_descriptors.cc @@ -30,10 +30,10 @@ * Auto ProductID layout's Bitmap: * [MSB] HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ((CFG_TUD_##itf) << (n)) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) << (n)) #define USB_PID \ - (0x4000 | _PID_MAP(MSC, 0) | _PID_MAP(HID, 1) | _PID_MAP(MIDI, 2) | \ - _PID_MAP(VENDOR, 3)) + (0x4000 | PID_MAP(MSC, 0) | PID_MAP(HID, 1) | PID_MAP(MIDI, 2) | \ + PID_MAP(VENDOR, 3)) #define USB_VID 0xCafe #define USB_BCD 0x0200 diff --git a/test/fuzz/device/net/src/tusb_config.h b/test/fuzz/device/net/src/tusb_config.h index 6ad859337..4fe98e043 100644 --- a/test/fuzz/device/net/src/tusb_config.h +++ b/test/fuzz/device/net/src/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -119,4 +119,4 @@ } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/test/fuzz/device/net/src/usb_descriptors.cc b/test/fuzz/device/net/src/usb_descriptors.cc index e57a791b6..301f23829 100644 --- a/test/fuzz/device/net/src/usb_descriptors.cc +++ b/test/fuzz/device/net/src/usb_descriptors.cc @@ -30,10 +30,10 @@ * Auto ProductID layout's Bitmap: * [MSB] HID | CDC [LSB] */ -#define _PID_MAP(itf, n) ((CFG_TUD_##itf) << (n)) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) << (n)) #define USB_PID \ - (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(HID, 2) | _PID_MAP(MIDI, 3) | \ - _PID_MAP(VENDOR, 4)) + (0x4000 | PID_MAP(CDC, 0) | PID_MAP(HID, 2) | PID_MAP(MIDI, 3) | \ + PID_MAP(VENDOR, 4)) #define USB_VID 0xCafe #define USB_BCD 0x0200 diff --git a/test/unit-test/test/support/tusb_config.h b/test/unit-test/test/support/tusb_config.h index 00818fae5..dee24f65d 100644 --- a/test/unit-test/test/support/tusb_config.h +++ b/test/unit-test/test/support/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ // testing framework #include "unity.h" @@ -103,4 +103,4 @@ } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ -- cgit v1.3.1 From 7c4cc0f7c8f72a9f55a8b301dfab6fc1d0125018 Mon Sep 17 00:00:00 2001 From: Mengsk Date: Thu, 30 Oct 2025 13:57:40 +0100 Subject: Refactor IN fifo write Signed-off-by: Mengsk --- src/portable/synopsys/dwc2/dcd_dwc2.c | 79 ++++++++++++++++++----------------- 1 file changed, 41 insertions(+), 38 deletions(-) (limited to 'src/portable') diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index 493fafe2e..13431ee1d 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -323,6 +323,40 @@ static void edpt_disable(uint8_t rhport, uint8_t ep_addr, bool stall) { } } +static uint16_t epin_write_tx_fifo(uint8_t rhport, uint8_t epnum) { + dwc2_regs_t* dwc2 = DWC2_REG(rhport); + dwc2_dep_t* const epin = &dwc2->ep[0][epnum]; + xfer_ctl_t* const xfer = XFER_CTL_BASE(epnum, TUSB_DIR_IN); + + dwc2_ep_tsize_t tsiz = {.value = epin->tsiz}; + const uint16_t remain_packets = tsiz.packet_count; + + uint16_t total_bytes_written = 0; + // Process every single packet (only whole packets can be written to fifo) + for (uint16_t i = 0; i < remain_packets; i++) { + 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 + if (xact_bytes > ((epin->dtxfsts & DTXFSTS_INEPTFSAV_Msk) << 2)) { + break; + } + + // Push packet to Tx-FIFO + if (xfer->ff) { + volatile uint32_t* tx_fifo = dwc2->fifo[epnum]; + tu_fifo_read_n_const_addr_full_words(xfer->ff, (void*)(uintptr_t)tx_fifo, xact_bytes); + total_bytes_written += xact_bytes; + } else { + dfifo_write_packet(dwc2, epnum, xfer->buffer, xact_bytes); + xfer->buffer += xact_bytes; + total_bytes_written += xact_bytes; + } + } + return total_bytes_written; +} + // 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 @@ -381,21 +415,12 @@ static void edpt_schedule_packets(uint8_t rhport, const uint8_t epnum, const uin } else { dep->diepctl = depctl.value; // enable endpoint - // Enable tx fifo empty interrupt only if there is data. Note must after depctl enable if (dir == TUSB_DIR_IN && total_bytes != 0) { - // For num_packets = 1 we write the packet directly - if (num_packets == 1) { - // Push packet to Tx-FIFO - if (xfer->ff) { - volatile uint32_t* tx_fifo = dwc2->fifo[epnum]; - tu_fifo_read_n_const_addr_full_words(xfer->ff, (void*)(uintptr_t)tx_fifo, total_bytes); - } else { - dfifo_write_packet(dwc2, epnum, xfer->buffer, total_bytes); - xfer->buffer += total_bytes; - } - } else { - // Enable TXFE interrupt for multi-packet transfer - dwc2->diepempmsk |= (1u << epnum); + const uint16_t xferred_bytes = epin_write_tx_fifo(rhport, epnum); + + // Enable TXFE interrupt if there are still data to be sent + if (xfer->total_len - xferred_bytes > 0) { + dwc2->diepempmsk |= (1u << epnum); } } } @@ -902,32 +927,10 @@ 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))) { - 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++) { - 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 - if (xact_bytes > ((epin->dtxfsts & DTXFSTS_INEPTFSAV_Msk) << 2)) { - break; - } - - // Push packet to Tx-FIFO - if (xfer->ff) { - volatile uint32_t* tx_fifo = dwc2->fifo[epnum]; - tu_fifo_read_n_const_addr_full_words(xfer->ff, (void*)(uintptr_t)tx_fifo, xact_bytes); - } else { - dfifo_write_packet(dwc2, epnum, xfer->buffer, xact_bytes); - xfer->buffer += xact_bytes; - } - } + epin_write_tx_fifo(rhport, epnum); // Turn off TXFE if all bytes are written. - tsiz.value = epin->tsiz; + dwc2_ep_tsize_t tsiz = {.value = epin->tsiz}; if (tsiz.xfer_size == 0) { dwc2->diepempmsk &= ~(1u << epnum); } -- cgit v1.3.1 From 82b0e2d0066ef1eea3b2bdeee0651c7519bc7f0a Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Thu, 30 Oct 2025 21:44:53 +0100 Subject: Retry until bInterval Signed-off-by: HiFiPhile --- src/portable/synopsys/dwc2/dcd_dwc2.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'src/portable') diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index 0f59f3f79..9419f88b3 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -255,7 +255,13 @@ static void edpt_activate(uint8_t rhport, const tusb_desc_endpoint_t* p_endpoint xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, dir); xfer->max_size = tu_edpt_packet_size(p_endpoint_desc); - xfer->interval = p_endpoint_desc->bInterval; + + const dwc2_dsts_t dsts = {.value = dwc2->dsts}; + if (dsts.enum_speed == DCFG_SPEED_HIGH) { + xfer->interval = 1 << (p_endpoint_desc->bInterval - 1); + } else { + xfer->interval = p_endpoint_desc->bInterval; + } // Endpoint control dwc2_depctl_t depctl = {.value = 0}; @@ -597,8 +603,8 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to _dcd_data.ep0_pending[dir] = total_bytes; } - // Reset ISO retry counter to max frame interval value - xfer->iso_retry = 255; + // Reset ISO retry counter to interval value + xfer->iso_retry = xfer->interval; // Schedule packets to be sent within interrupt edpt_schedule_packets(rhport, epnum, dir); @@ -632,8 +638,8 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_t xfer->ff = ff; xfer->total_len = total_bytes; - // Reset ISO retry counter to max frame interval value - xfer->iso_retry = 255; + // Reset ISO retry counter to interval value + xfer->iso_retry = xfer->interval; // Schedule packets to be sent within interrupt // TODO xfer fifo may only available for slave mode -- cgit v1.3.1 From beea882c6bcee352b5ff69446aef9fc43237bab0 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Thu, 30 Oct 2025 21:45:36 +0100 Subject: Simply restart the transfer Signed-off-by: HiFiPhile --- src/portable/synopsys/dwc2/dcd_dwc2.c | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) (limited to 'src/portable') diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index 9419f88b3..e72fcda5b 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -1138,27 +1138,34 @@ void dcd_int_handler(uint8_t rhport) { // Incomplete isochronous IN transfer interrupt handling. if (gintsts & GINTSTS_IISOIXFR) { dwc2->gintsts = GINTSTS_IISOIXFR; + const dwc2_dsts_t dsts = {.value = dwc2->dsts}; + const uint32_t odd_now = dsts.frame_number & 1u; // Loop over all IN endpoints const uint8_t ep_count = dwc2_ep_count(dwc2); for (uint8_t epnum = 0; epnum < ep_count; epnum++) { dwc2_dep_t* epin = &dwc2->epin[epnum]; dwc2_depctl_t depctl = {.value = epin->diepctl}; - // Find enabled ISO endpoints - if (depctl.enable && depctl.type == DEPCTL_EPTYPE_ISOCHRONOUS) { - // Disable endpoint, flush fifo and restart transfer - depctl.set_nak = 1; - epin->diepctl = depctl.value; - depctl.disable = 1; - epin->diepctl = depctl.value; - while ((epin->diepint & DIEPINT_EPDISD_Msk) == 0) {} - epin->diepint = DIEPINT_EPDISD; - dfifo_flush_tx(dwc2, epnum); + // Read DSTS and DIEPCTLn for all isochronous endpoints. If the current EP is enabled + // and the read value of DSTS.SOFFN is the targeted uframe number for this EP, then + // this EP has an incomplete transfer. + if (depctl.enable && depctl.type == DEPCTL_EPTYPE_ISOCHRONOUS && depctl.dpid_iso_odd == odd_now) { xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, TUSB_DIR_IN); if (xfer->iso_retry) { xfer->iso_retry--; - edpt_schedule_packets(rhport, epnum, TUSB_DIR_IN); + // Restart ISO transfer + dwc2_ep_tsize_t deptsiz = {.value = 0}; + deptsiz.xfer_size = xfer->total_len; + deptsiz.packet_count = tu_div_ceil(xfer->total_len, xfer->max_size); + epin->tsiz = deptsiz.value; + if (odd_now) { + depctl.set_data0_iso_even = 1; + } else { + depctl.set_data1_iso_odd = 1; + } + epin->diepctl = depctl.value; } else { // too many retries, give up + edpt_disable(rhport, epnum | TUSB_DIR_IN_MASK, false); dcd_event_xfer_complete(rhport, epnum | TUSB_DIR_IN_MASK, 0, XFER_RESULT_FAILED, true); } } -- cgit v1.3.1 From be4b38c54dc4e23af322ae04eda1f30e5ced0289 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 31 Oct 2025 10:25:43 +0100 Subject: Skip TXFE for EP0 Signed-off-by: HiFiPhile --- src/portable/synopsys/dwc2/dcd_dwc2.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/portable') diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index 13431ee1d..cb4768a5e 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -419,7 +419,8 @@ static void edpt_schedule_packets(uint8_t rhport, const uint8_t epnum, const uin const uint16_t xferred_bytes = epin_write_tx_fifo(rhport, epnum); // Enable TXFE interrupt if there are still data to be sent - if (xfer->total_len - xferred_bytes > 0) { + // EP0 only sends one packet at a time, so no need to check for EP0 + if ((epnum != 0) && (xfer->total_len - xferred_bytes > 0)) { dwc2->diepempmsk |= (1u << epnum); } } -- cgit v1.3.1 From 9d46cca57637cfd086499970a8f5d5669ba9bfa0 Mon Sep 17 00:00:00 2001 From: tswan22 Date: Sat, 1 Nov 2025 12:51:31 -0400 Subject: add STM32U3 device (adjusted from STM32U0) --- README.rst | 2 ++ src/common/tusb_mcu.h | 5 +++++ src/portable/st/stm32_fsdev/fsdev_stm32.h | 28 ++++++++++++++++++++++++++++ src/tusb_option.h | 1 + 4 files changed, 36 insertions(+) (limited to 'src/portable') diff --git a/README.rst b/README.rst index 3ea1bd018..23e427ec9 100644 --- a/README.rst +++ b/README.rst @@ -212,6 +212,8 @@ Supported CPUs | +----+------------------------+--------+------+-----------+------------------------+-------------------+ | | U0 | ✔ | ✖ | ✖ | stm32_fsdev | | | +----+------------------------+--------+------+-----------+------------------------+-------------------+ +| | U3 | ✔ | | ✖ | stm32_fsdev | | +| +----+------------------------+--------+------+-----------+------------------------+-------------------+ | | U5 | 535, 545 | ✔ | | ✖ | stm32_fsdev | | | | +------------------------+--------+------+-----------+------------------------+-------------------+ | | | 575, 585 | ✔ | ✔ | ✖ | dwc2 | | diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index 0b8ed1059..6941e1a31 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -337,6 +337,11 @@ #define TUP_USBIP_FSDEV_STM32 #define TUP_DCD_ENDPOINT_MAX 8 +#elif TU_CHECK_MCU(OPT_MCU_STM32U3) + #define TUP_USBIP_FSDEV + #define TUP_USBIP_FSDEV_STM32 + #define TUP_DCD_ENDPOINT_MAX 8 + #elif TU_CHECK_MCU(OPT_MCU_STM32H7RS, OPT_MCU_STM32N6) #define TUP_USBIP_DWC2 #define TUP_USBIP_DWC2_STM32 diff --git a/src/portable/st/stm32_fsdev/fsdev_stm32.h b/src/portable/st/stm32_fsdev/fsdev_stm32.h index 63b50f13d..30ffadc35 100644 --- a/src/portable/st/stm32_fsdev/fsdev_stm32.h +++ b/src/portable/st/stm32_fsdev/fsdev_stm32.h @@ -225,6 +225,32 @@ #define USB_CNTR_LPMODE USB_CNTR_SUSPRDY #define USB_CNTR_FSUSP USB_CNTR_SUSPEN +#elif CFG_TUSB_MCU == OPT_MCU_STM32U3 + #include "stm32u3xx.h" + #define FSDEV_PMA_SIZE (2048u) + #define FSDEV_BUS_32BIT + #define FSDEV_HAS_SBUF_ISO 1 // This is assumed to work but has not been tested... + #define USB USB_DRD_FS + + #define USB_EP_CTR_RX USB_EP_VTRX + #define USB_EP_CTR_TX USB_EP_VTTX + #define USB_EP_T_FIELD USB_CHEP_UTYPE + #define USB_EPREG_MASK USB_CHEP_REG_MASK + #define USB_EPTX_DTOGMASK USB_CHEP_TX_DTOGMASK + #define USB_EPRX_DTOGMASK USB_CHEP_RX_DTOGMASK + #define USB_EPTX_DTOG1 USB_CHEP_TX_DTOG1 + #define USB_EPTX_DTOG2 USB_CHEP_TX_DTOG2 + #define USB_EPRX_DTOG1 USB_CHEP_RX_DTOG1 + #define USB_EPRX_DTOG2 USB_CHEP_RX_DTOG2 + #define USB_EPRX_STAT USB_CH_RX_VALID + #define USB_EPKIND_MASK USB_EP_KIND_MASK + #define USB_CNTR_FRES USB_CNTR_USBRST + #define USB_CNTR_RESUME USB_CNTR_L2RES + #define USB_ISTR_EP_ID USB_ISTR_IDN + #define USB_EPADDR_FIELD USB_CHEP_ADDR + #define USB_CNTR_LPMODE USB_CNTR_SUSPRDY + #define USB_CNTR_FSUSP USB_CNTR_SUSPEN + #else #error You are using an untested or unimplemented STM32 variant. Please update the driver. // This includes U0 @@ -338,6 +364,8 @@ static const IRQn_Type fsdev_irq[] = { USB_IRQn, #elif CFG_TUSB_MCU == OPT_MCU_STM32U0 USB_DRD_FS_IRQn, + #elif CFG_TUSB_MCU == OPT_MCU_STM32U3 + USB_FS_IRQn, #else #error Unknown arch in USB driver #endif diff --git a/src/tusb_option.h b/src/tusb_option.h index 14404c59c..b78fbca30 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -98,6 +98,7 @@ #define OPT_MCU_STM32C0 318 ///< ST C0 #define OPT_MCU_STM32N6 319 ///< ST N6 #define OPT_MCU_STM32WBA 320 ///< ST WBA +#define OPT_MCU_STM32U3 321 ///< ST U3 // Sony #define OPT_MCU_CXD56 400 ///< SONY CXD56 -- cgit v1.3.1 From 67b2a5c2e1dacd305015ae4a6329c8db8f198e81 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 3 Nov 2025 11:17:39 +0700 Subject: remove binary prefix for portability --- src/common/tusb_common.h | 42 ++++-------------------------------------- src/portable/ehci/ehci.c | 6 +++--- src/portable/ohci/ohci.c | 2 +- 3 files changed, 8 insertions(+), 42 deletions(-) (limited to 'src/portable') diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index 6d7adc3a1..ac1c6457f 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -278,14 +278,12 @@ TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write16(void *mem, uint16_ // We have to manually pick up bytes since tu_unaligned_uint32_t will still generate unaligned code // NOTE: volatile cast to memory to prevent compiler to optimize and generate unaligned code // TODO Big Endian may need minor changes -TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_unaligned_read32(const void* mem) -{ +TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_unaligned_read32(const void* mem) { volatile uint8_t const* buf8 = (uint8_t const*) mem; return tu_u32(buf8[3], buf8[2], buf8[1], buf8[0]); } -TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write32(void* mem, uint32_t value) -{ +TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write32(void* mem, uint32_t value) { volatile uint8_t* buf8 = (uint8_t*) mem; buf8[0] = tu_u32_byte0(value); buf8[1] = tu_u32_byte1(value); @@ -293,20 +291,17 @@ TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write32(void* mem, uint32_ buf8[3] = tu_u32_byte3(value); } -TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_unaligned_read16(const void* mem) -{ +TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_unaligned_read16(const void* mem) { volatile uint8_t const* buf8 = (uint8_t const*) mem; return tu_u16(buf8[1], buf8[0]); } -TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write16(void* mem, uint16_t value) -{ +TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write16(void* mem, uint16_t value) { volatile uint8_t* buf8 = (uint8_t*) mem; buf8[0] = tu_u16_low(value); buf8[1] = tu_u16_high(value); } - #else // MCU that could access unaligned memory natively @@ -328,35 +323,6 @@ TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write16(void *mem, uint16_ #endif -// To be removed -//------------- Binary constant -------------// -#if defined(__GNUC__) && !defined(__CC_ARM) - -#define TU_BIN8(x) ((uint8_t) (0b##x)) -#define TU_BIN16(b1, b2) ((uint16_t) (0b##b1##b2)) -#define TU_BIN32(b1, b2, b3, b4) ((uint32_t) (0b##b1##b2##b3##b4)) - -#else - -// internal macro of B8, B16, B32 -#define _B8__(x) (((x&0x0000000FUL)?1:0) \ - +((x&0x000000F0UL)?2:0) \ - +((x&0x00000F00UL)?4:0) \ - +((x&0x0000F000UL)?8:0) \ - +((x&0x000F0000UL)?16:0) \ - +((x&0x00F00000UL)?32:0) \ - +((x&0x0F000000UL)?64:0) \ - +((x&0xF0000000UL)?128:0)) - -#define TU_BIN8(d) ((uint8_t) _B8__(0x##d##UL)) -#define TU_BIN16(dmsb,dlsb) (((uint16_t)TU_BIN8(dmsb)<<8) + TU_BIN8(dlsb)) -#define TU_BIN32(dmsb,db2,db3,dlsb) \ - (((uint32_t)TU_BIN8(dmsb)<<24) \ - + ((uint32_t)TU_BIN8(db2)<<16) \ - + ((uint32_t)TU_BIN8(db3)<<8) \ - + TU_BIN8(dlsb)) -#endif - //--------------------------------------------------------------------+ // Descriptor helper //--------------------------------------------------------------------+ diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c index 953483583..973bb43cc 100644 --- a/src/portable/ehci/ehci.c +++ b/src/portable/ehci/ehci.c @@ -919,8 +919,8 @@ static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, tusb_desc_endpoint_t c 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); + p_qhd->int_smask = (interval == 1) ? 0xff : // 0b11111111 + (interval == 2) ? 0xaa /* 0b10101010 */ : 0x44 /* 01000100 */; } else { p_qhd->interval_ms = (uint8_t) tu_min16(1 << (interval - 4), 255); p_qhd->int_smask = TU_BIT(interval % 8); @@ -929,7 +929,7 @@ static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, tusb_desc_endpoint_t c 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->fl_int_cmask = 0x1c; // 0b11100 p_qhd->interval_ms = interval; } break; diff --git a/src/portable/ohci/ohci.c b/src/portable/ohci/ohci.c index 6d4594450..f6ee7e764 100644 --- a/src/portable/ohci/ohci.c +++ b/src/portable/ohci/ohci.c @@ -127,7 +127,7 @@ enum { enum { OHCI_INT_ON_COMPLETE_YES = 0, - OHCI_INT_ON_COMPLETE_NO = TU_BIN8(111) + OHCI_INT_ON_COMPLETE_NO = 0x7 // 0b111 }; enum { -- cgit v1.3.1 From 22f01aea0d31b5a54532877d02d61f51041aeb6f Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 3 Nov 2025 15:14:52 +0700 Subject: fix more warnings/alerts --- .PVS-Studio/.pvsconfig | 4 +- src/class/video/video_device.c | 180 ++++++++++++++++++++++++++--------------- src/common/tusb_verify.h | 2 +- src/host/usbh.c | 18 ++--- src/portable/ohci/ohci.c | 6 +- 5 files changed, 130 insertions(+), 80 deletions(-) (limited to 'src/portable') diff --git a/.PVS-Studio/.pvsconfig b/.PVS-Studio/.pvsconfig index b722c6d10..32125c2f7 100644 --- a/.PVS-Studio/.pvsconfig +++ b/.PVS-Studio/.pvsconfig @@ -1 +1,3 @@ -//-V::2506,2514 +//-V::2506 +//-V::2514 +//-V::2614 diff --git a/src/class/video/video_device.c b/src/class/video/video_device.c index 5c00cc358..087292e56 100644 --- a/src/class/video/video_device.c +++ b/src/class/video/video_device.c @@ -103,7 +103,7 @@ typedef struct TU_ATTR_PACKED { uint8_t index_vc; /* index of bound video control interface */ uint8_t index_vs; /* index from the video control interface */ struct { - uint16_t beg; /* Offset of the begging of video streaming interface descriptor */ + uint16_t beg; /* Offset of the beginning of video streaming interface descriptor */ uint16_t end; /* Offset of the end of video streaming interface descriptor */ uint16_t cur; /* Offset of the current settings */ uint16_t ep[2]; /* Offset of endpoint descriptors. 0: streaming, 1: still capture */ @@ -244,9 +244,13 @@ static inline uint8_t _desc_ep_addr(void const *desc) { * @return instance */ static videod_streaming_interface_t* _get_instance_streaming(uint_fast8_t ctl_idx, uint_fast8_t stm_idx) { videod_interface_t *ctl = &_videod_itf[ctl_idx]; - if (!ctl->beg) return NULL; + if (!ctl->beg) { + return NULL; + } videod_streaming_interface_t *stm = &_videod_streaming_itf[ctl->stm[stm_idx]]; - if (!stm->desc.beg) return NULL; + if (!stm->desc.beg) { + return NULL; + } return stm; } @@ -255,7 +259,9 @@ static tusb_desc_vc_itf_t const* _get_desc_vc(videod_interface_t const *self) { } static tusb_desc_vs_itf_t const* _get_desc_vs(videod_streaming_interface_t const *self) { - if (!self->desc.cur) return NULL; + if (!self->desc.cur) { + return NULL; + } uint8_t const *desc = _videod_itf[self->index_vc].beg; return (tusb_desc_vs_itf_t const*)(desc + self->desc.cur); } @@ -366,8 +372,12 @@ static void const* _find_desc_ep(void const *beg, void const *end) { for (void const *cur = beg; cur < end; cur = tu_desc_next(cur)) { uint_fast8_t desc_type = tu_desc_type(cur); - if (TUSB_DESC_ENDPOINT == desc_type) return cur; - if (TUSB_DESC_INTERFACE == desc_type) break; + if (TUSB_DESC_ENDPOINT == desc_type) { + return cur; + } + if (TUSB_DESC_INTERFACE == desc_type) { + break; + } } return end; } @@ -453,7 +463,7 @@ static bool _update_streaming_parameters(videod_streaming_interface_t const *stm tusb_desc_vs_itf_t const *vs = _get_desc_vs(stm); uint_fast8_t fmtnum = param->bFormatIndex; TU_ASSERT(vs && fmtnum <= vs->stm.bNumFormats); - if (!fmtnum) { + if (0 == fmtnum) { if (1 < vs->stm.bNumFormats) return true; /* Need to negotiate all variables. */ fmtnum = 1; param->bFormatIndex = 1; @@ -492,8 +502,10 @@ static bool _update_streaming_parameters(videod_streaming_interface_t const *stm uint_fast8_t frmnum = param->bFrameIndex; TU_ASSERT(frmnum <= fmt->bNumFrameDescriptors); - if (!frmnum) { - if (1 < fmt->bNumFrameDescriptors) return true; + if (0 == frmnum) { + if (1 < fmt->bNumFrameDescriptors) { + return true; + } frmnum = 1; param->bFrameIndex = 1; } @@ -502,7 +514,7 @@ static bool _update_streaming_parameters(videod_streaming_interface_t const *stm /* Set the parameters determined by the frame */ uint_fast32_t frame_size = param->dwMaxVideoFrameSize; - if (!frame_size) { + if (0 == frame_size) { switch (fmt->bDescriptorSubType) { case VIDEO_CS_ITF_VS_FORMAT_UNCOMPRESSED: frame_size = (uint_fast32_t)frm->wWidth * frm->wHeight * fmt->uncompressed.bBitsPerPixel / 8; @@ -522,7 +534,7 @@ static bool _update_streaming_parameters(videod_streaming_interface_t const *stm } uint_fast32_t interval = param->dwFrameInterval; - if (!interval) { + if (0 == interval) { if ((1 < frm->uncompressed.bFrameIntervalType) || ((0 == frm->uncompressed.bFrameIntervalType) && (frm->uncompressed.dwFrameInterval[1] != frm->uncompressed.dwFrameInterval[0]))) { @@ -532,7 +544,7 @@ static bool _update_streaming_parameters(videod_streaming_interface_t const *stm param->dwFrameInterval = interval; } uint_fast32_t interval_ms = interval / 10000; - TU_ASSERT(interval_ms); + TU_ASSERT(interval_ms != 0); uint_fast32_t payload_size = (frame_size + interval_ms - 1) / interval_ms + 2; if (CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE < payload_size) { payload_size = CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE; @@ -550,7 +562,7 @@ static bool _negotiate_streaming_parameters(videod_streaming_interface_t const * video_probe_and_commit_control_t *param) { uint_fast8_t const fmtnum = param->bFormatIndex; - if (!fmtnum) { + if (0 == fmtnum) { switch (request) { case VIDEO_REQUEST_GET_MAX: if (_get_desc_vs(stm)) @@ -581,7 +593,7 @@ static bool _negotiate_streaming_parameters(videod_streaming_interface_t const * } uint_fast8_t frmnum = param->bFrameIndex; - if (!frmnum) { + if (0 == frmnum) { tusb_desc_vs_itf_t const *vs = _get_desc_vs(stm); TU_ASSERT(vs); void const *end = _end_of_streaming_descriptor(vs); @@ -637,7 +649,7 @@ static bool _negotiate_streaming_parameters(videod_streaming_interface_t const * return true; } - if (!param->dwFrameInterval) { + if (0 == param->dwFrameInterval) { tusb_desc_vs_itf_t const *vs = _get_desc_vs(stm); TU_ASSERT(vs); void const *end = _end_of_streaming_descriptor(vs); @@ -686,12 +698,12 @@ static bool _negotiate_streaming_parameters(videod_streaming_interface_t const * default: return false; } param->dwFrameInterval = interval; - if (!interval) { + if (0 == interval) { param->dwMaxPayloadTransferSize = 0; } else { uint_fast32_t frame_size = param->dwMaxVideoFrameSize; uint_fast32_t payload_size; - if (!interval_ms) { + if (0 == interval_ms) { payload_size = frame_size + 2; } else { payload_size = (frame_size + interval_ms - 1) / interval_ms + 2; @@ -719,7 +731,7 @@ static bool _close_vc_itf(uint8_t rhport, videod_interface_t *self) /* The end of the video control interface descriptor. */ void const *end = _end_of_control_descriptor(vc); - if (vc->std.bNumEndpoints) { + if (vc->std.bNumEndpoints != 0) { /* Find the notification endpoint descriptor. */ cur = _find_desc(cur, end, TUSB_DESC_ENDPOINT); TU_ASSERT(cur < end); @@ -757,7 +769,7 @@ static bool _open_vc_itf(uint8_t rhport, videod_interface_t *self, uint_fast8_t cur += vc->std.bLength + vc->ctl.bLength; TU_LOG_DRV(" bNumEndpoints %d\r\n", vc->std.bNumEndpoints); /* Open the notification endpoint if it exist. */ - if (vc->std.bNumEndpoints) { + if (vc->std.bNumEndpoints != 0) { /* Support for 1 endpoint only. */ TU_VERIFY(1 == vc->std.bNumEndpoints); /* Find the notification endpoint descriptor. */ @@ -843,7 +855,7 @@ static bool _open_vs_itf(uint8_t rhport, videod_streaming_interface_t *stm, uint stm->desc.ep[i] = (uint16_t) (cur - desc); TU_LOG_DRV(" open EP%02x\r\n", _desc_ep_addr(cur)); } - if (altnum) { + if (altnum != 0) { stm->state = VS_STATE_STREAMING; } TU_LOG_DRV(" done\r\n"); @@ -929,16 +941,14 @@ static int handle_video_ctl_cs_req(uint8_t rhport, uint8_t stage, return VIDEO_ERROR_NONE; case VIDEO_REQUEST_GET_CUR: - if (stage == CONTROL_STAGE_SETUP) - { + if (stage == CONTROL_STAGE_SETUP) { TU_VERIFY(1 == request->wLength, VIDEO_ERROR_UNKNOWN); TU_VERIFY(tud_control_xfer(rhport, request, &self->power_mode, sizeof(self->power_mode)), VIDEO_ERROR_UNKNOWN); } return VIDEO_ERROR_NONE; case VIDEO_REQUEST_GET_INFO: - if (stage == CONTROL_STAGE_SETUP) - { + if (stage == CONTROL_STAGE_SETUP) { TU_VERIFY(1 == request->wLength, VIDEO_ERROR_UNKNOWN); TU_VERIFY(tud_control_xfer(rhport, request, (uint8_t*)(uintptr_t) &_cap_get_set, sizeof(_cap_get_set)), VIDEO_ERROR_UNKNOWN); } @@ -951,15 +961,13 @@ static int handle_video_ctl_cs_req(uint8_t rhport, uint8_t stage, case VIDEO_VC_CTL_REQUEST_ERROR_CODE: switch (request->bRequest) { case VIDEO_REQUEST_GET_CUR: - if (stage == CONTROL_STAGE_SETUP) - { + if (stage == CONTROL_STAGE_SETUP) { TU_VERIFY(tud_control_xfer(rhport, request, &self->error_code, sizeof(uint8_t)), VIDEO_ERROR_UNKNOWN); } return VIDEO_ERROR_NONE; case VIDEO_REQUEST_GET_INFO: - if (stage == CONTROL_STAGE_SETUP) - { + if (stage == CONTROL_STAGE_SETUP) { TU_VERIFY(tud_control_xfer(rhport, request, (uint8_t*)(uintptr_t) &_cap_get, sizeof(_cap_get)), VIDEO_ERROR_UNKNOWN); } return VIDEO_ERROR_NONE; @@ -986,7 +994,7 @@ static int handle_video_ctl_req(uint8_t rhport, uint8_t stage, case TUSB_REQ_TYPE_CLASS: { uint_fast8_t entity_id = TU_U16_HIGH(request->wIndex); - if (!entity_id) { + if (0 == entity_id) { return handle_video_ctl_cs_req(rhport, stage, request, ctl_idx); } else { TU_VERIFY(_find_desc_entity(_get_desc_vc(&_videod_itf[ctl_idx]), entity_id), VIDEO_ERROR_INVALID_REQUEST); @@ -1001,14 +1009,12 @@ static int handle_video_ctl_req(uint8_t rhport, uint8_t stage, static int handle_video_stm_std_req(uint8_t rhport, uint8_t stage, tusb_control_request_t const *request, - uint_fast8_t stm_idx) -{ + uint_fast8_t stm_idx) { TU_LOG_DRV("\r\n"); videod_streaming_interface_t *self = &_videod_streaming_itf[stm_idx]; switch (request->bRequest) { case TUSB_REQ_GET_INTERFACE: - if (stage == CONTROL_STAGE_SETUP) - { + if (stage == CONTROL_STAGE_SETUP) { TU_VERIFY(1 == request->wLength, VIDEO_ERROR_UNKNOWN); tusb_desc_vs_itf_t const *vs = _get_desc_vs(self); TU_VERIFY(vs, VIDEO_ERROR_UNKNOWN); @@ -1075,12 +1081,14 @@ static int handle_video_stm_cs_req(uint8_t rhport, uint8_t stage, } else if (stage == CONTROL_STAGE_DATA) { TU_VERIFY(_update_streaming_parameters(stm, &stm->probe_commit_payload), VIDEO_ERROR_INVALID_VALUE_WITHIN_RANGE); + } else { + // nothing to do } return VIDEO_ERROR_NONE; case VIDEO_REQUEST_GET_CUR: if (stage == CONTROL_STAGE_SETUP) { - TU_VERIFY(request->wLength, VIDEO_ERROR_UNKNOWN); + TU_VERIFY(request->wLength != 0, VIDEO_ERROR_UNKNOWN); TU_VERIFY(tud_control_xfer(rhport, request, &stm->probe_commit_payload, sizeof(video_probe_and_commit_control_t)), VIDEO_ERROR_UNKNOWN); } return VIDEO_ERROR_NONE; @@ -1090,7 +1098,7 @@ static int handle_video_stm_cs_req(uint8_t rhport, uint8_t stage, case VIDEO_REQUEST_GET_RES: case VIDEO_REQUEST_GET_DEF: if (stage == CONTROL_STAGE_SETUP) { - TU_VERIFY(request->wLength, VIDEO_ERROR_UNKNOWN); + TU_VERIFY(request->wLength != 0, VIDEO_ERROR_UNKNOWN); video_probe_and_commit_control_t tmp = stm->probe_commit_payload; TU_VERIFY(_negotiate_streaming_parameters(stm, request->bRequest, &tmp), VIDEO_ERROR_INVALID_VALUE_WITHIN_RANGE); TU_VERIFY(tud_control_xfer(rhport, request, &tmp, sizeof(tmp)), VIDEO_ERROR_UNKNOWN); @@ -1137,12 +1145,14 @@ static int handle_video_stm_cs_req(uint8_t rhport, uint8_t stage, hdr->bHeaderLength = sizeof(*hdr); hdr->bmHeaderInfo = 0; } + } else { + // nothing to do } return VIDEO_ERROR_NONE; case VIDEO_REQUEST_GET_CUR: if (stage == CONTROL_STAGE_SETUP) { - TU_VERIFY(request->wLength, VIDEO_ERROR_UNKNOWN); + TU_VERIFY(request->wLength != 0, VIDEO_ERROR_UNKNOWN); TU_VERIFY(tud_control_xfer(rhport, request, &stm->probe_commit_payload, sizeof(video_probe_and_commit_control_t)), VIDEO_ERROR_UNKNOWN); } return VIDEO_ERROR_NONE; @@ -1185,14 +1195,15 @@ static int handle_video_stm_cs_req(uint8_t rhport, uint8_t stage, static int handle_video_stm_req(uint8_t rhport, uint8_t stage, tusb_control_request_t const *request, - uint_fast8_t stm_idx) -{ + uint_fast8_t stm_idx) { switch (request->bmRequestType_bit.type) { case TUSB_REQ_TYPE_STANDARD: return handle_video_stm_std_req(rhport, stage, request, stm_idx); case TUSB_REQ_TYPE_CLASS: - if (TU_U16_HIGH(request->wIndex)) return VIDEO_ERROR_INVALID_REQUEST; + if (0 != TU_U16_HIGH(request->wIndex)) { + return VIDEO_ERROR_INVALID_REQUEST; + } return handle_video_stm_cs_req(rhport, stage, request, stm_idx); default: return VIDEO_ERROR_INVALID_REQUEST; @@ -1203,11 +1214,12 @@ static int handle_video_stm_req(uint8_t rhport, uint8_t stage, // APPLICATION API //--------------------------------------------------------------------+ -bool tud_video_n_connected(uint_fast8_t ctl_idx) -{ +bool tud_video_n_connected(uint_fast8_t ctl_idx) { TU_ASSERT(ctl_idx < CFG_TUD_VIDEO); videod_streaming_interface_t *stm = _get_instance_streaming(ctl_idx, 0); - if (stm) return true; + if (stm != NULL) { + return true; + } return false; } @@ -1216,15 +1228,21 @@ bool tud_video_n_streaming(uint_fast8_t ctl_idx, uint_fast8_t stm_idx) TU_ASSERT(ctl_idx < CFG_TUD_VIDEO); TU_ASSERT(stm_idx < CFG_TUD_VIDEO_STREAMING); videod_streaming_interface_t *stm = _get_instance_streaming(ctl_idx, stm_idx); - if (!stm || !stm->desc.ep[0]) return false; - if (stm->state == VS_STATE_PROBING) return false; + if (NULL == stm || 0 == stm->desc.ep[0]) { + return false; + } + if (stm->state == VS_STATE_PROBING) { + return false; + } -#ifdef TUP_DCD_EDPT_ISO_ALLOC + #ifdef TUP_DCD_EDPT_ISO_ALLOC uint8_t const *desc = _videod_itf[stm->index_vc].beg; uint_fast16_t ofs_ep = stm->desc.ep[0]; tusb_desc_endpoint_t const *ep = (tusb_desc_endpoint_t const*)(desc + ofs_ep); if (ep->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS) { - if (stm->state == VS_STATE_COMMITTED) return false; + if (stm->state == VS_STATE_COMMITTED) { + return false; + } } #endif @@ -1235,25 +1253,35 @@ bool tud_video_n_frame_xfer(uint_fast8_t ctl_idx, uint_fast8_t stm_idx, void *bu TU_ASSERT(ctl_idx < CFG_TUD_VIDEO); TU_ASSERT(stm_idx < CFG_TUD_VIDEO_STREAMING); - if (!buffer || !bufsize) return false; + if (NULL == buffer || 0 == bufsize) { + return false; + } videod_streaming_interface_t *stm = _get_instance_streaming(ctl_idx, stm_idx); videod_streaming_epbuf_t *stm_epbuf = &_videod_streaming_epbuf[ctl_idx]; - if (!stm || !stm->desc.ep[0] || stm->buffer) return false; - if (stm->state == VS_STATE_PROBING) return false; + if ( NULL == stm || 0 == stm->desc.ep[0] || stm->buffer) { + return false; + } + if (stm->state == VS_STATE_PROBING) { + return false; + } /* Find EP address */ uint8_t const *desc = _videod_itf[stm->index_vc].beg; uint8_t ep_addr = 0; for (uint_fast8_t i = 0; i < CFG_TUD_VIDEO_STREAMING; ++i) { uint_fast16_t ofs_ep = stm->desc.ep[i]; - if (!ofs_ep) continue; + if (0 == ofs_ep) { + continue; + } ep_addr = _desc_ep_addr(desc + ofs_ep); break; } - if (!ep_addr) return false; + if (0 == ep_addr) { + return false; + } - TU_VERIFY( usbd_edpt_claim(0, ep_addr) ); + TU_VERIFY(usbd_edpt_claim(0, ep_addr)); /* update the packet header */ tusb_video_payload_header_t *hdr = (tusb_video_payload_header_t*)stm_epbuf->buf; hdr->FrameID ^= 1; @@ -1305,7 +1333,9 @@ uint16_t videod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin videod_interface_t *self = NULL; uint8_t ctl_idx; for (ctl_idx = 0; ctl_idx < CFG_TUD_VIDEO; ++ctl_idx) { - if (_videod_itf[ctl_idx].beg) continue; + if (NULL != _videod_itf[ctl_idx].beg) { + continue; + } self = &_videod_itf[ctl_idx]; break; } @@ -1326,7 +1356,9 @@ uint16_t videod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin videod_streaming_interface_t *stm = NULL; /* find free streaming interface handle */ for (uint8_t i = 0; i < CFG_TUD_VIDEO_STREAMING; ++i) { - if (_videod_streaming_itf[i].desc.beg) continue; + if (0 != _videod_streaming_itf[i].desc.beg) { + continue; + } stm = &_videod_streaming_itf[i]; self->stm[stm_idx] = i; break; @@ -1354,7 +1386,9 @@ uint16_t videod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin } p_desc = tu_desc_next(p_desc); } - if(ep_addr > 0 && ep_size > 0) usbd_edpt_iso_alloc(rhport, ep_addr, ep_size); + if(ep_addr > 0 && ep_size > 0) { + usbd_edpt_iso_alloc(rhport, ep_addr, ep_size); + } #endif if (0 == stm_idx && 1 == bInCollection) { /* If there is only one streaming interface and no alternate settings, @@ -1381,31 +1415,43 @@ bool videod_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_ uint_fast8_t itf; for (itf = 0; itf < CFG_TUD_VIDEO; ++itf) { void const *desc = _videod_itf[itf].beg; - if (!desc) continue; - if (itfnum == _desc_itfnum(desc)) break; + if (!desc) { + continue; + } + if (itfnum == _desc_itfnum(desc)) { + break; + } } if (itf < CFG_TUD_VIDEO) { TU_LOG_DRV(" VC[%d]: ", itf); err = handle_video_ctl_req(rhport, stage, request, itf); _videod_itf[itf].error_code = (uint8_t)err; - if (err) return false; + if (0 != err) { + return false; + } return true; } /* Identify which streaming interface to use */ for (itf = 0; itf < CFG_TUD_VIDEO_STREAMING; ++itf) { videod_streaming_interface_t *stm = &_videod_streaming_itf[itf]; - if (!stm->desc.beg) continue; + if (0 == stm->desc.beg) { + continue; + } uint8_t const *desc = _videod_itf[stm->index_vc].beg; - if (itfnum == _desc_itfnum(desc + stm->desc.beg)) break; + if (itfnum == _desc_itfnum(desc + stm->desc.beg)) { + break; + } } if (itf < CFG_TUD_VIDEO_STREAMING) { TU_LOG_DRV(" VS[%d]: ", itf); err = handle_video_stm_req(rhport, stage, request, itf); _videod_streaming_itf[itf].error_code = (uint8_t)err; - if (err) return false; + if (err != 0) { + return false; + } return true; } return false; @@ -1421,19 +1467,23 @@ bool videod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 for (itf = 0; itf < CFG_TUD_VIDEO_STREAMING; ++itf) { stm = &_videod_streaming_itf[itf]; uint_fast16_t const ep_ofs = stm->desc.ep[0]; - if (!ep_ofs) continue; + if (0 == ep_ofs) { + continue; + } ctl = &_videod_itf[stm->index_vc]; uint8_t const *desc = ctl->beg; - if (ep_addr == _desc_ep_addr(desc + ep_ofs)) break; + if (ep_addr == _desc_ep_addr(desc + ep_ofs)) { + break; + } } TU_ASSERT(itf < CFG_TUD_VIDEO_STREAMING); videod_streaming_epbuf_t *stm_epbuf = &_videod_streaming_epbuf[itf]; if (stm->offset < stm->bufsize) { /* Claim the endpoint */ - TU_VERIFY( usbd_edpt_claim(rhport, ep_addr), 0); + TU_VERIFY(usbd_edpt_claim(rhport, ep_addr), 0); uint_fast16_t pkt_len = _prepare_in_payload(stm, stm_epbuf->buf); - TU_ASSERT( usbd_edpt_xfer(rhport, ep_addr, stm_epbuf->buf, (uint16_t) pkt_len), 0); + TU_ASSERT(usbd_edpt_xfer(rhport, ep_addr, stm_epbuf->buf, (uint16_t) pkt_len), 0); } else { stm->buffer = NULL; stm->bufsize = 0; diff --git a/src/common/tusb_verify.h b/src/common/tusb_verify.h index 9dc73aa60..d6806d44a 100644 --- a/src/common/tusb_verify.h +++ b/src/common/tusb_verify.h @@ -78,7 +78,7 @@ defined(__ARM7M__) || defined (__ARM7EM__) || defined(__ARM8M_MAINLINE__) || defined(__ARM8EM_MAINLINE__) #define TU_BREAKPOINT() do { \ volatile uint32_t* ARM_CM_DHCSR = ((volatile uint32_t*) 0xE000EDF0UL); /* Cortex M CoreDebug->DHCSR */ \ - if ( (*ARM_CM_DHCSR) & 1UL ) __asm("BKPT #0\n"); /* Only halt mcu if debugger is attached */ \ + if (0 != ((*ARM_CM_DHCSR) & 1UL)) {__asm("BKPT #0\n");} /* Only halt mcu if debugger is attached */ \ } while(0) #elif defined(__riscv) && !TUSB_MCU_VENDOR_ESPRESSIF diff --git a/src/host/usbh.c b/src/host/usbh.c index 6bafde368..0330320f8 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -1314,7 +1314,7 @@ static void process_removed_device(uint8_t rhport, uint8_t hub_addr, uint8_t hub do { 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; + uint8_t const daddr = dev_id + 1u; // hub_addr = 0 means roothub, hub_port = 0 means all devices of downstream hub if (dev->bus_info.rhport == rhport && dev->connected && @@ -1336,7 +1336,7 @@ static void process_removed_device(uint8_t rhport, uint8_t hub_addr, uint8_t hub // Close class driver 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) { + if (driver != NULL) { driver->close(daddr); } } @@ -1354,7 +1354,7 @@ static void process_removed_device(uint8_t rhport, uint8_t hub_addr, uint8_t hub // find a marked hub to process for (uint8_t h_id = 0; h_id < CFG_TUH_HUB; h_id++) { - if (removing_hubs[h_id]) { + if (0 != removing_hubs[h_id]) { removing_hubs[h_id] = 0; // update hub_addr and hub_port for next loop @@ -1513,7 +1513,7 @@ static void process_enumeration(tuh_xfer_t* xfer) { 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) { + if (0 == port_status.status.connection) { TU_LOG_USBH("Device unplugged from hub while debouncing\r\n"); enum_full_complete(); return; @@ -1535,7 +1535,7 @@ static void process_enumeration(tuh_xfer_t* xfer) { 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.change.reset) { + if (1 == 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_HUB_CLEAR_RESET_COMPLETE),); } else { @@ -1550,7 +1550,7 @@ static void process_enumeration(tuh_xfer_t* xfer) { 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) { + if (0 == port_status.status.connection) { TU_LOG_USBH("Device unplugged from hub (not addressed yet)\r\n"); enum_full_complete(); return; @@ -1748,7 +1748,7 @@ static void process_enumeration(tuh_xfer_t* xfer) { 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),); + TU_ASSERT(tuh_configuration_set(daddr, config_idx+1u, process_enumeration, ENUM_CONFIG_DRIVER),); } else { config_idx++; TU_ASSERT(config_idx < dev->bNumConfigurations,); @@ -1794,7 +1794,7 @@ static uint8_t enum_get_new_address(bool is_hub) { } for (uint8_t idx = start; idx < end; idx++) { - if (!_usbh_devices[idx].connected) { + if (0 == _usbh_devices[idx].connected) { return (idx + 1); } } @@ -1904,7 +1904,7 @@ void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num) { // with usbh_driver_set_config_complete() uint8_t const drv_id = dev->itf2drv[itf_num]; usbh_class_driver_t const * driver = get_driver(drv_id); - if (driver) { + if (driver != NULL) { TU_LOG_USBH("%s set config: itf = %u\r\n", driver->name, itf_num); driver->set_config(dev_addr, itf_num); break; diff --git a/src/portable/ohci/ohci.c b/src/portable/ohci/ohci.c index f6ee7e764..5ca093506 100644 --- a/src/portable/ohci/ohci.c +++ b/src/portable/ohci/ohci.c @@ -494,8 +494,7 @@ 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); @@ -509,11 +508,10 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * } ohci_ed_t * ed = ed_from_addr(dev_addr, ep_addr); + TU_ASSERT(ed); if (epnum == 0) { ohci_gtd_t* gtd = &ohci_data.control[dev_addr].gtd; - gtd_init(gtd, buffer, buflen); - gtd->index = dev_addr; gtd->pid = dir ? PID_IN : PID_OUT; gtd->data_toggle = GTD_DT_DATA1; // Both Data and Ack stage start with DATA1 -- cgit v1.3.1 From 8979af34c0e5b97520070bcfdffe5280de9ac24c Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 3 Nov 2025 16:36:07 +0700 Subject: Fixed more alert found by PVS-Studio --- .../audio_test_multi_rate/src/usb_descriptors.h | 4 +- examples/device/cdc_msc/src/main.c | 2 +- examples/device/cdc_uac2/src/cdc_app.c | 19 ++-- examples/device/cdc_uac2/src/usb_descriptors.h | 4 +- examples/device/net_lwip_webserver/src/lwipopts.h | 4 +- examples/device/uac2_headset/src/usb_descriptors.h | 4 +- .../device/uac2_speaker_fb/src/usb_descriptors.h | 4 +- examples/host/cdc_msc_hid_freertos/src/cdc_app.c | 8 +- hw/bsp/board.c | 5 +- hw/bsp/board_api.h | 2 +- src/class/cdc/cdc.h | 18 ++-- src/class/video/video_device.c | 6 +- src/common/tusb_common.h | 16 ++- src/common/tusb_compiler.h | 16 +-- src/common/tusb_fifo.c | 42 ++++---- src/common/tusb_private.h | 4 +- src/common/tusb_types.h | 2 +- src/common/tusb_verify.h | 4 +- src/device/dcd.h | 2 +- src/device/usbd.c | 120 ++++++++++----------- src/device/usbd.h | 60 ++++++----- src/device/usbd_pvt.h | 4 +- src/portable/synopsys/dwc2/dcd_dwc2.c | 76 +++++++------ src/portable/synopsys/dwc2/dwc2_stm32.h | 4 +- src/portable/synopsys/dwc2/dwc2_type.h | 2 +- 25 files changed, 224 insertions(+), 208 deletions(-) (limited to 'src/portable') diff --git a/examples/device/audio_test_multi_rate/src/usb_descriptors.h b/examples/device/audio_test_multi_rate/src/usb_descriptors.h index c02f40cd9..948a7f4ae 100644 --- a/examples/device/audio_test_multi_rate/src/usb_descriptors.h +++ b/examples/device/audio_test_multi_rate/src/usb_descriptors.h @@ -23,8 +23,8 @@ * */ -#ifndef _USB_DESCRIPTORS_H_ -#define _USB_DESCRIPTORS_H_ +#ifndef USB_DESCRIPTORS_H_ +#define USB_DESCRIPTORS_H_ // #include "tusb.h" diff --git a/examples/device/cdc_msc/src/main.c b/examples/device/cdc_msc/src/main.c index 5d70903bc..ff998a13d 100644 --- a/examples/device/cdc_msc/src/main.c +++ b/examples/device/cdc_msc/src/main.c @@ -123,7 +123,7 @@ void cdc_task(void) { 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 == 0) && btn) { + if ((btn_prev == 0u) && btn) { uart_state.dsr ^= 1; tud_cdc_notify_uart_state(&uart_state); } diff --git a/examples/device/cdc_uac2/src/cdc_app.c b/examples/device/cdc_uac2/src/cdc_app.c index 2166c1d6b..e3ad8a9ac 100644 --- a/examples/device/cdc_uac2/src/cdc_app.c +++ b/examples/device/cdc_uac2/src/cdc_app.c @@ -29,33 +29,26 @@ #include "common.h" // Invoked when cdc when line state changed e.g connected/disconnected -void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) -{ +void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) { (void) itf; (void) rts; - if (dtr) - { + if (dtr) { // Terminal connected - } - else - { + } else { // Terminal disconnected } } // Invoked when CDC interface received data from host -void tud_cdc_rx_cb(uint8_t itf) -{ +void tud_cdc_rx_cb(uint8_t itf) { uint8_t buf[64]; uint32_t count; // connected() check for DTR bit // Most but not all terminal client set this when making connection - if (tud_cdc_connected()) - { - if (tud_cdc_available()) // data is available - { + if (tud_cdc_connected()) { + if (tud_cdc_available()) { count = tud_cdc_n_read(itf, buf, sizeof(buf)); (void) count; diff --git a/examples/device/cdc_uac2/src/usb_descriptors.h b/examples/device/cdc_uac2/src/usb_descriptors.h index 95d8da5c3..139384d3e 100644 --- a/examples/device/cdc_uac2/src/usb_descriptors.h +++ b/examples/device/cdc_uac2/src/usb_descriptors.h @@ -24,8 +24,8 @@ * */ -#ifndef _USB_DESCRIPTORS_H_ -#define _USB_DESCRIPTORS_H_ +#ifndef USB_DESCRIPTORS_H_ +#define USB_DESCRIPTORS_H_ // #include "tusb.h" diff --git a/examples/device/net_lwip_webserver/src/lwipopts.h b/examples/device/net_lwip_webserver/src/lwipopts.h index 04949cef9..11686ce2a 100644 --- a/examples/device/net_lwip_webserver/src/lwipopts.h +++ b/examples/device/net_lwip_webserver/src/lwipopts.h @@ -29,8 +29,8 @@ * Author: Simon Goldschmidt * */ -#ifndef __LWIPOPTS_H__ -#define __LWIPOPTS_H__ +#ifndef LWIPOPTS_H__ +#define LWIPOPTS_H__ /* Prevent having to link sys_arch.c (we don't test the API layers in unit tests) */ #define NO_SYS 1 diff --git a/examples/device/uac2_headset/src/usb_descriptors.h b/examples/device/uac2_headset/src/usb_descriptors.h index d673beace..47154626e 100644 --- a/examples/device/uac2_headset/src/usb_descriptors.h +++ b/examples/device/uac2_headset/src/usb_descriptors.h @@ -23,8 +23,8 @@ * */ -#ifndef _USB_DESCRIPTORS_H_ -#define _USB_DESCRIPTORS_H_ +#ifndef USB_DESCRIPTORS_H_ +#define USB_DESCRIPTORS_H_ enum { diff --git a/examples/device/uac2_speaker_fb/src/usb_descriptors.h b/examples/device/uac2_speaker_fb/src/usb_descriptors.h index b0ec60ea1..79f25bbfa 100644 --- a/examples/device/uac2_speaker_fb/src/usb_descriptors.h +++ b/examples/device/uac2_speaker_fb/src/usb_descriptors.h @@ -23,8 +23,8 @@ * */ -#ifndef _USB_DESCRIPTORS_H_ -#define _USB_DESCRIPTORS_H_ +#ifndef USB_DESCRIPTORS_H_ +#define USB_DESCRIPTORS_H_ //--------------------------------------------------------------------+ // UAC2 DESCRIPTOR TEMPLATES 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 279efe7b7..0e0105980 100644 --- a/examples/host/cdc_msc_hid_freertos/src/cdc_app.c +++ b/examples/host/cdc_msc_hid_freertos/src/cdc_app.c @@ -46,9 +46,9 @@ static void cdc_app_task(void* param); void cdc_app_init(void) { #if configSUPPORT_STATIC_ALLOCATION - xTaskCreateStatic(cdc_app_task, "cdc", CDC_STACK_SZIE, NULL, configMAX_PRIORITIES-2, cdc_stack, &cdc_taskdef); + (void) xTaskCreateStatic(cdc_app_task, "cdc", CDC_STACK_SZIE, NULL, configMAX_PRIORITIES-2, cdc_stack, &cdc_taskdef); #else - xTaskCreate(cdc_app_task, "cdc", CDC_STACK_SZIE, NULL, configMAX_PRIORITIES-2, NULL); + (void) xTaskCreate(cdc_app_task, "cdc", CDC_STACK_SZIE, NULL, configMAX_PRIORITIES-2, NULL); #endif } @@ -57,7 +57,9 @@ 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++; diff --git a/hw/bsp/board.c b/hw/bsp/board.c index 476ec6733..483d9dc28 100644 --- a/hw/bsp/board.c +++ b/hw/bsp/board.c @@ -51,8 +51,7 @@ int sys_read(int fhdl, char *buf, size_t count) TU_ATTR_USED; int sys_write(int fhdl, const char *buf, size_t count) { (void) fhdl; - SEGGER_RTT_Write(0, buf, (int) count); - return (int) count; + return (int) SEGGER_RTT_Write(0, buf, (int) count); } int sys_read(int fhdl, char *buf, size_t count) { @@ -159,7 +158,7 @@ int board_getchar(void) { } void board_putchar(int c) { - sys_write(0, (const char*)&c, 1); + (void) sys_write(0, (const char*)&c, 1); } uint32_t tusb_time_millis_api(void) { diff --git a/hw/bsp/board_api.h b/hw/bsp/board_api.h index 088c5fec4..606ac484f 100644 --- a/hw/bsp/board_api.h +++ b/hw/bsp/board_api.h @@ -165,7 +165,7 @@ static inline size_t board_usb_get_serial(uint16_t desc_str1[], size_t max_chars '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; - const uint8_t nibble = (uint8_t) ((uid[i] >> (j * 4)) & 0xf); + const uint8_t nibble = (uint8_t) ((uid[i] >> (j * 4u)) & 0xfu); desc_str1[i * 2 + (1 - j)] = nibble_to_hex[nibble]; // UTF-16-LE } } diff --git a/src/class/cdc/cdc.h b/src/class/cdc/cdc.h index 6d207c717..679723ba6 100644 --- a/src/class/cdc/cdc.h +++ b/src/class/cdc/cdc.h @@ -192,10 +192,10 @@ 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" : "?" ) +#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 @@ -211,11 +211,11 @@ typedef enum { } 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' : '?' ) + (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/video/video_device.c b/src/class/video/video_device.c index 087292e56..14eba86fb 100644 --- a/src/class/video/video_device.c +++ b/src/class/video/video_device.c @@ -464,7 +464,9 @@ static bool _update_streaming_parameters(videod_streaming_interface_t const *stm uint_fast8_t fmtnum = param->bFormatIndex; TU_ASSERT(vs && fmtnum <= vs->stm.bNumFormats); if (0 == fmtnum) { - if (1 < vs->stm.bNumFormats) return true; /* Need to negotiate all variables. */ + if (1 < vs->stm.bNumFormats) { + return true; /* Need to negotiate all variables. */ + } fmtnum = 1; param->bFormatIndex = 1; } @@ -1259,7 +1261,7 @@ bool tud_video_n_frame_xfer(uint_fast8_t ctl_idx, uint_fast8_t stm_idx, void *bu videod_streaming_interface_t *stm = _get_instance_streaming(ctl_idx, stm_idx); videod_streaming_epbuf_t *stm_epbuf = &_videod_streaming_epbuf[ctl_idx]; - if ( NULL == stm || 0 == stm->desc.ep[0] || stm->buffer) { + if (NULL == stm || 0 == stm->desc.ep[0] || stm->buffer) { return false; } if (stm->state == VS_STATE_PROBING) { diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index ac1c6457f..5f659eb95 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -111,7 +111,7 @@ extern void* tusb_app_phys_to_virt(void *phys_addr); //--------------------------------------------------------------------+ //------------- Mem -------------// -#define tu_memclr(buffer, size) memset((buffer), 0, (size)) +#define tu_memclr(buffer, size) (void) memset((buffer), 0, (size)) #define tu_varclr(_var) tu_memclr(_var, sizeof(*(_var))) // This is a backport of memset_s from c11 @@ -121,6 +121,10 @@ TU_ATTR_ALWAYS_INLINE static inline int tu_memset_s(void *dest, size_t destsz, i return -1; } + if (count == 0u) { + return 0; + } + if (count > destsz) { return -1; } @@ -131,13 +135,15 @@ TU_ATTR_ALWAYS_INLINE static inline int tu_memset_s(void *dest, size_t destsz, i // This is a backport of memcpy_s from c11 TU_ATTR_ALWAYS_INLINE static inline int tu_memcpy_s(void *dest, size_t destsz, const void *src, size_t count) { - // Validate parameters if (dest == NULL) { return -1; } - // For memcpy, src may be NULL only if count == 0. Reject otherwise. - if (src == NULL && count != 0u) { + if (count == 0u) { + return 0; + } + + if (src == NULL) { return -1; } @@ -230,7 +236,7 @@ TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_round_up(uint32_t v, uint32_t f) // TODO use clz TODO remove TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_log2(uint32_t value) { uint8_t result = 0; - while ((value >>= 1) != 0) { + while (value >>= 1) { result++; } return result; diff --git a/src/common/tusb_compiler.h b/src/common/tusb_compiler.h index 49421e865..167385d13 100644 --- a/src/common/tusb_compiler.h +++ b/src/common/tusb_compiler.h @@ -77,19 +77,19 @@ /*------------------------------------------------------------------*/ /* Count number of arguments of __VA_ARGS__ * - reference www.stackoverflow.com/questions/2124339/c-preprocessor-va-args-number-of-arguments - * - _GET_NTH_ARG() takes args >= N (64) but only expand to Nth one (64th) - * - _RSEQ_N() is reverse sequential to N to add padding to have + * - TU_GET_NTH_ARG() takes args >= N (64) but only expand to Nth one (64th) + * - TU_NARG_RSEQ_N() is reverse sequential to N to add padding to have * Nth position is the same as the number of arguments * - ##__VA_ARGS__ is used to deal with 0 paramerter (swallows comma) *------------------------------------------------------------------*/ -#if !defined(__CCRX__) -#define TU_ARGS_NUM(...) _TU_NARG(_0, ##__VA_ARGS__, _RSEQ_N()) +#if defined(__CCRX__) +#define TU_ARGS_NUM(...) TU_NARG_IMPL(_0, __VA_ARGS__, TU_NARG_RSEQ_N()) #else -#define TU_ARGS_NUM(...) _TU_NARG(_0, __VA_ARGS__, _RSEQ_N()) +#define TU_ARGS_NUM(...) TU_NARG_IMPL(_0, ##__VA_ARGS__, TU_NARG_RSEQ_N()) #endif -#define _TU_NARG(...) _GET_NTH_ARG(__VA_ARGS__) -#define _GET_NTH_ARG( \ +#define TU_NARG_IMPL(...) TU_GET_NTH_ARG(__VA_ARGS__) +#define TU_GET_NTH_ARG( \ _1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \ _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \ _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \ @@ -97,7 +97,7 @@ _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \ _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \ _61,_62,_63,N,...) N -#define _RSEQ_N() \ +#define TU_NARG_RSEQ_N() \ 62,61,60, \ 59,58,57,56,55,54,53,52,51,50, \ 49,48,47,46,45,44,43,42,41,40, \ diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index f7679556f..3b8920c01 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -38,14 +38,16 @@ #if OSAL_MUTEX_REQUIRED -TU_ATTR_ALWAYS_INLINE static inline void _ff_lock(osal_mutex_t mutex) -{ - if (mutex) osal_mutex_lock(mutex, OSAL_TIMEOUT_WAIT_FOREVER); +TU_ATTR_ALWAYS_INLINE static inline void _ff_lock(osal_mutex_t mutex) { + if (mutex) { + osal_mutex_lock(mutex, OSAL_TIMEOUT_WAIT_FOREVER); + } } -TU_ATTR_ALWAYS_INLINE static inline void _ff_unlock(osal_mutex_t mutex) -{ - if (mutex) osal_mutex_unlock(mutex); +TU_ATTR_ALWAYS_INLINE static inline void _ff_unlock(osal_mutex_t mutex) { + if (mutex) { + osal_mutex_unlock(mutex); + } } #else @@ -59,8 +61,7 @@ TU_ATTR_ALWAYS_INLINE static inline void _ff_unlock(osal_mutex_t mutex) * \brief Write modes intended to allow special read and write functions to be able to * copy data to and from USB hardware FIFOs as needed for e.g. STM32s and others */ -typedef enum -{ +typedef enum { TU_FIFO_COPY_INC, ///< Copy from/to an increasing source/destination address - default mode #ifdef TUP_MEM_CONST_ADDR TU_FIFO_COPY_CST_FULL_WORDS, ///< Copy from/to a constant source/destination address - required for e.g. STM32 to write into USB hardware FIFO @@ -72,7 +73,9 @@ bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_si // Limit index space to 2*depth - this allows for a fast "modulo" calculation // but limits the maximum depth to 2^16/2 = 2^15 and buffer overflows are detectable // only if overflow happens once (important for unsupervised DMA applications) - if (depth > 0x8000) return false; + if (depth > 0x8000) { + return false; + } _ff_lock(f->mutex_wr); _ff_lock(f->mutex_rd); @@ -98,22 +101,19 @@ bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_si // Intended to be used to read from hardware USB FIFO in e.g. STM32 where all data is read from a constant address // Code adapted from dcd_synopsys.c // TODO generalize with configurable 1 byte or 4 byte each read -static void _ff_push_const_addr(uint8_t * ff_buf, const void * app_buf, uint16_t len) -{ +static void _ff_push_const_addr(uint8_t * ff_buf, const void * app_buf, uint16_t len) { volatile const uint32_t * reg_rx = (volatile const uint32_t *) app_buf; // Reading full available 32 bit words from const app address uint16_t full_words = len >> 2; - while(full_words--) - { + while(full_words--) { tu_unaligned_write32(ff_buf, *reg_rx); ff_buf += 4; } // Read the remaining 1-3 bytes from const app address uint8_t const bytes_rem = len & 0x03; - if ( bytes_rem ) - { + if (bytes_rem) { uint32_t tmp32 = *reg_rx; memcpy(ff_buf, &tmp32, bytes_rem); } @@ -121,22 +121,19 @@ static void _ff_push_const_addr(uint8_t * ff_buf, const void * app_buf, uint16_t // Intended to be used to write to hardware USB FIFO in e.g. STM32 // where all data is written to a constant address in full word copies -static void _ff_pull_const_addr(void * app_buf, const uint8_t * ff_buf, uint16_t len) -{ +static void _ff_pull_const_addr(void * app_buf, const uint8_t * ff_buf, uint16_t len) { volatile uint32_t * reg_tx = (volatile uint32_t *) app_buf; // Write full available 32 bit words to const address uint16_t full_words = len >> 2; - while(full_words--) - { + while(full_words--) { *reg_tx = tu_unaligned_read32(ff_buf); ff_buf += 4; } // Write the remaining 1-3 bytes into const address uint8_t const bytes_rem = len & 0x03; - if ( bytes_rem ) - { + if (bytes_rem) { uint32_t tmp32 = 0; memcpy(&tmp32, ff_buf, bytes_rem); @@ -146,8 +143,7 @@ static void _ff_pull_const_addr(void * app_buf, const uint8_t * ff_buf, uint16_t #endif // send one item to fifo WITHOUT updating write pointer -static inline void _ff_push(tu_fifo_t* f, void const * app_buf, uint16_t rel) -{ +static inline void _ff_push(tu_fifo_t* f, void const * app_buf, uint16_t rel) { memcpy(f->buffer + (rel * f->item_size), app_buf, f->item_size); } diff --git a/src/common/tusb_private.h b/src/common/tusb_private.h index 31aca8a31..37d5e89f1 100644 --- a/src/common/tusb_private.h +++ b/src/common/tusb_private.h @@ -141,7 +141,7 @@ uint32_t tu_edpt_stream_read_xfer(uint8_t hwid, tu_edpt_stream_t* s); // Complete read transfer by writing EP -> FIFO. Must be called in the transfer complete callback TU_ATTR_ALWAYS_INLINE static inline void tu_edpt_stream_read_xfer_complete(tu_edpt_stream_t* s, uint32_t xferred_bytes) { - if (tu_fifo_depth(&s->ff)) { + if (0 != tu_fifo_depth(&s->ff)) { tu_fifo_write_n(&s->ff, s->ep_buf, (uint16_t) xferred_bytes); } } @@ -149,7 +149,7 @@ void tu_edpt_stream_read_xfer_complete(tu_edpt_stream_t* s, uint32_t xferred_byt // Complete read transfer with provided buffer TU_ATTR_ALWAYS_INLINE static inline void tu_edpt_stream_read_xfer_complete_with_buf(tu_edpt_stream_t* s, const void * buf, uint32_t xferred_bytes) { - if (tu_fifo_depth(&s->ff)) { + if (0 != tu_fifo_depth(&s->ff)) { tu_fifo_write_n(&s->ff, buf, (uint16_t) xferred_bytes); } } diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index 9197381cf..a3a660d3b 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -548,7 +548,7 @@ TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_edpt_number(uint8_t addr) { } TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_edpt_addr(uint8_t num, uint8_t dir) { - return (uint8_t) (num | (dir ? TUSB_DIR_IN_MASK : 0)); + return (uint8_t) (num | (dir == TUSB_DIR_IN ? TUSB_DIR_IN_MASK : 0u)); } TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_edpt_packet_size(tusb_desc_endpoint_t const* desc_ep) { diff --git a/src/common/tusb_verify.h b/src/common/tusb_verify.h index d6806d44a..ffd785384 100644 --- a/src/common/tusb_verify.h +++ b/src/common/tusb_verify.h @@ -78,7 +78,7 @@ defined(__ARM7M__) || defined (__ARM7EM__) || defined(__ARM8M_MAINLINE__) || defined(__ARM8EM_MAINLINE__) #define TU_BREAKPOINT() do { \ volatile uint32_t* ARM_CM_DHCSR = ((volatile uint32_t*) 0xE000EDF0UL); /* Cortex M CoreDebug->DHCSR */ \ - if (0 != ((*ARM_CM_DHCSR) & 1UL)) {__asm("BKPT #0\n");} /* Only halt mcu if debugger is attached */ \ + if (0 != ((*ARM_CM_DHCSR) & 1UL)) { __asm("BKPT #0\n"); } /* Only halt mcu if debugger is attached */ \ } while(0) #elif defined(__riscv) && !TUSB_MCU_VENDOR_ESPRESSIF @@ -98,7 +98,7 @@ *------------------------------------------------------------------*/ #define TU_VERIFY_DEFINE(_cond, _ret) \ do { \ - if ( !(_cond) ) { return _ret; } \ + if (!(_cond)) { return _ret; } \ } while(0) #define TU_VERIFY_1ARGS(_cond) TU_VERIFY_DEFINE(_cond, false) diff --git a/src/device/dcd.h b/src/device/dcd.h index 436c4555f..1b0289280 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -214,7 +214,7 @@ TU_ATTR_ALWAYS_INLINE static inline void dcd_event_setup_received(uint8_t rhport dcd_event_t event; event.rhport = rhport; event.event_id = DCD_EVENT_SETUP_RECEIVED; - memcpy(&event.setup_received, setup, sizeof(tusb_control_request_t)); + (void) memcpy(&event.setup_received, setup, sizeof(tusb_control_request_t)); dcd_event_handler(&event, in_isr); } diff --git a/src/device/usbd.c b/src/device/usbd.c index 05fc752af..9d0bc0f3f 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -354,6 +354,8 @@ TU_ATTR_ALWAYS_INLINE static inline usbd_class_driver_t const * get_driver(uint8 driver = &_app_driver[drvid]; } else if (drvid < TOTAL_DRIVER_COUNT && BUILTIN_DRIVER_COUNT > 0) { driver = &_usbd_driver[drvid - _app_driver_count]; + } else { + // nothing to do } return driver; } @@ -572,7 +574,7 @@ bool tud_deinit(uint8_t rhport) { // Deinit device controller driver dcd_int_disable(rhport); dcd_disconnect(rhport); - dcd_deinit(rhport); + TU_VERIFY(dcd_deinit(rhport)); // Deinit class drivers for (uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++) { @@ -594,7 +596,6 @@ bool tud_deinit(uint8_t rhport) { #endif _usbd_rhport = RHPORT_INVALID; - return true; } @@ -606,8 +607,8 @@ static void configuration_reset(uint8_t rhport) { } tu_varclr(&_usbd_dev); - memset(_usbd_dev.itf2drv, DRVID_INVALID, sizeof(_usbd_dev.itf2drv)); // invalid mapping - memset(_usbd_dev.ep2drv, DRVID_INVALID, sizeof(_usbd_dev.ep2drv)); // invalid mapping + (void) memset(_usbd_dev.itf2drv, DRVID_INVALID, sizeof(_usbd_dev.itf2drv)); // invalid mapping + (void) memset(_usbd_dev.ep2drv, DRVID_INVALID, sizeof(_usbd_dev.ep2drv)); // invalid mapping } static void usbd_reset(uint8_t rhport) { @@ -638,12 +639,16 @@ void tud_task_ext(uint32_t timeout_ms, bool in_isr) { (void) in_isr; // not implemented yet // Skip if stack is not initialized - if (!tud_inited()) return; + if (!tud_inited()) { + return; + } // Loop until there is no more events in the queue while (1) { dcd_event_t event; - if (!osal_queue_receive(_usbd_q, &event, timeout_ms)) return; + if (!osal_queue_receive(_usbd_q, &event, timeout_ms)) { + return; + } #if CFG_TUSB_DEBUG >= CFG_TUD_LOG_LEVEL if (event.event_id == DCD_EVENT_SETUP_RECEIVED) TU_LOG_USBD("\r\n"); // extra line for setup @@ -667,7 +672,7 @@ void tud_task_ext(uint32_t timeout_ms, bool in_isr) { TU_ASSERT(_usbd_queued_setup > 0,); _usbd_queued_setup--; TU_LOG_BUF(CFG_TUD_LOG_LEVEL, &event.setup_received, 8); - if (_usbd_queued_setup) { + if (_usbd_queued_setup != 0) { TU_LOG_USBD(" Skipped since there is other SETUP in queue\r\n"); break; } @@ -703,8 +708,7 @@ void tud_task_ext(uint32_t timeout_ms, bool in_isr) { _usbd_dev.ep_status[epnum][ep_dir].claimed = 0; if (0 == epnum) { - usbd_control_xfer_cb(event.rhport, ep_addr, (xfer_result_t) event.xfer_complete.result, - event.xfer_complete.len); + usbd_control_xfer_cb(event.rhport, ep_addr, (xfer_result_t) event.xfer_complete.result, event.xfer_complete.len); } else { usbd_class_driver_t const* driver = get_driver(_usbd_dev.ep2drv[epnum][ep_dir]); TU_ASSERT(driver,); @@ -738,7 +742,7 @@ 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) { + if (event.func_call.func != NULL) { event.func_call.func(event.func_call.param); } break; @@ -792,7 +796,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const } #endif - switch ( p_request->bmRequestType_bit.recipient ) { + switch (p_request->bmRequestType_bit.recipient) { //-V2520 //------------- Device Requests e.g in enumeration -------------// case TUSB_REQ_RCPT_DEVICE: if ( TUSB_REQ_TYPE_CLASS == p_request->bmRequestType_bit.type ) { @@ -806,13 +810,13 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const return invoke_class_control(rhport, driver, p_request); } - if ( TUSB_REQ_TYPE_STANDARD != p_request->bmRequestType_bit.type ) { + if (TUSB_REQ_TYPE_STANDARD != p_request->bmRequestType_bit.type) { // Non-standard request is not supported TU_BREAKPOINT(); return false; } - switch ( p_request->bRequest ) { + switch (p_request->bRequest) { //-V2520 case TUSB_REQ_SET_ADDRESS: // Depending on mcu, status phase could be sent either before or after changing device address, // or even require stack to not response with status at all @@ -834,18 +838,15 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const // Only process if new configure is different if (_usbd_dev.cfg_num != cfg_num) { - if ( _usbd_dev.cfg_num ) { + if (_usbd_dev.cfg_num != 0) { // already configured: need to clear all endpoints and driver first TU_LOG_USBD(" Clear current Configuration (%u) before switching\r\n", _usbd_dev.cfg_num); - // disable SOF dcd_sof_enable(rhport, false); - - // close all non-control endpoints, cancel all pending transfers if any dcd_edpt_close_all(rhport); // close all drivers and current configured state except bus speed - uint8_t const speed = _usbd_dev.speed; + const uint8_t speed = _usbd_dev.speed; configuration_reset(rhport); _usbd_dev.speed = speed; // restore speed @@ -853,18 +854,15 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const _usbd_dev.cfg_num = cfg_num; - // Handle the new configuration and execute the corresponding callback - if ( cfg_num ) { - // switch to new configuration if not zero + // Handle the new configuration + if (cfg_num == 0) { + tud_umount_cb(); + } else { if (!process_set_config(rhport, cfg_num)) { - TU_MESS_FAILED(); - TU_BREAKPOINT(); _usbd_dev.cfg_num = 0; - return false; + TU_ASSERT(false); } tud_mount_cb(); - } else { - tud_umount_cb(); } } @@ -873,17 +871,17 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const break; case TUSB_REQ_GET_DESCRIPTOR: - TU_VERIFY( process_get_descriptor(rhport, p_request) ); + TU_VERIFY(process_get_descriptor(rhport, p_request)); break; case TUSB_REQ_SET_FEATURE: - switch(p_request->wValue) { + switch(p_request->wValue) { //-V2520 case TUSB_REQ_FEATURE_REMOTE_WAKEUP: TU_LOG_USBD(" Enable Remote Wakeup\r\n"); // Host may enable remote wake up before suspending especially HID device _usbd_dev.remote_wakeup_en = true; tud_control_status(rhport, p_request); - break; + break; #if CFG_TUD_TEST_MODE case TUSB_REQ_FEATURE_TEST_MODE: { @@ -897,7 +895,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const tud_control_status(rhport, p_request); break; } - #endif /* CFG_TUD_TEST_MODE */ + #endif // Stall unsupported feature selector default: return false; @@ -907,13 +905,12 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const case TUSB_REQ_CLEAR_FEATURE: // Only support remote wakeup for device feature TU_VERIFY(TUSB_REQ_FEATURE_REMOTE_WAKEUP == p_request->wValue); - TU_LOG_USBD(" Disable Remote Wakeup\r\n"); // Host may disable remote wake up after resuming _usbd_dev.remote_wakeup_en = false; tud_control_status(rhport, p_request); - break; + break; case TUSB_REQ_GET_STATUS: { // Device status bit mask @@ -939,24 +936,24 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const // all requests to Interface (STD or Class) is forwarded to class driver. // notable requests are: GET HID REPORT DESCRIPTOR, SET_INTERFACE, GET_INTERFACE - if ( !invoke_class_control(rhport, driver, p_request) ) { + if (!invoke_class_control(rhport, driver, p_request)) { // For GET_INTERFACE and SET_INTERFACE, it is mandatory to respond even if the class // driver doesn't use alternate settings or implement this TU_VERIFY(TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type); - switch(p_request->bRequest) { - case TUSB_REQ_GET_INTERFACE: - case TUSB_REQ_SET_INTERFACE: - // Clear complete callback if driver set since it can also stall the request. - usbd_control_set_complete_callback(NULL); + // Clear complete callback if driver set since it can also stall the request. + usbd_control_set_complete_callback(NULL); - if (TUSB_REQ_GET_INTERFACE == p_request->bRequest) { - uint8_t alternate = 0; - tud_control_xfer(rhport, p_request, &alternate, 1); - }else { - tud_control_status(rhport, p_request); - } - break; + switch (p_request->bRequest) { //-V2520 + case TUSB_REQ_GET_INTERFACE: { + uint8_t alternate = 0; + tud_control_xfer(rhport, p_request, &alternate, 1); + break; + } + + case TUSB_REQ_SET_INTERFACE: + tud_control_status(rhport, p_request); + break; default: return false; } @@ -973,15 +970,15 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const TU_ASSERT(ep_num < TU_ARRAY_SIZE(_usbd_dev.ep2drv) ); usbd_class_driver_t const * driver = get_driver(_usbd_dev.ep2drv[ep_num][ep_dir]); - if ( TUSB_REQ_TYPE_STANDARD != p_request->bmRequestType_bit.type ) { + if (TUSB_REQ_TYPE_STANDARD != p_request->bmRequestType_bit.type) { // Forward class request to its driver TU_VERIFY(driver); return invoke_class_control(rhport, driver, p_request); } else { // Handle STD request to endpoint - switch ( p_request->bRequest ) { + switch (p_request->bRequest) { //-V2520 case TUSB_REQ_GET_STATUS: { - uint16_t status = usbd_edpt_stalled(rhport, ep_addr) ? 0x0001 : 0x0000; + uint16_t status = usbd_edpt_stalled(rhport, ep_addr) ? 0x0001u : 0x0000u; tud_control_xfer(rhport, p_request, &status, 2); } break; @@ -996,7 +993,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const } } - if (driver) { + if (driver != NULL) { // Some classes such as USBTMC needs to clear/re-init its buffer when receiving CLEAR_FEATURE request // We will also forward std request targeted endpoint to class drivers as well @@ -1006,7 +1003,9 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const usbd_control_set_complete_callback(NULL); // skip ZLP status if driver already did that - if ( !_usbd_dev.ep_status[0][TUSB_DIR_IN].busy ) tud_control_status(rhport, p_request); + if (!_usbd_dev.ep_status[0][TUSB_DIR_IN].busy) { + tud_control_status(rhport, p_request); + } } } break; @@ -1017,8 +1016,8 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const return false; } } + break; } - break; // Unknown recipient default: @@ -1081,10 +1080,11 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) // Some drivers use 2 or more interfaces but may not have IAD e.g MIDI (always) or // BTH (even CDC) with class in device descriptor (single interface) - if ( assoc_itf_count == 1) - { + if (assoc_itf_count == 1) { #if CFG_TUD_CDC - if ( driver->open == cdcd_open ) assoc_itf_count = 2; + if ( driver->open == cdcd_open ) { + assoc_itf_count = 2; + } #endif #if CFG_TUD_MIDI @@ -1158,8 +1158,7 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const tusb_desc_type_t const desc_type = (tusb_desc_type_t) tu_u16_high(p_request->wValue); uint8_t const desc_index = tu_u16_low( p_request->wValue ); - switch(desc_type) - { + switch(desc_type) { //-V2520 case TUSB_DESC_DEVICE: { TU_LOG_USBD(" Device\r\n"); @@ -1187,7 +1186,7 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const // requested by host if USB > 2.0 ( i.e 2.1 or 3.x ) uintptr_t desc_bos = (uintptr_t) tud_descriptor_bos_cb(); - TU_VERIFY(desc_bos); + TU_VERIFY(desc_bos != 0); // Use offsetof to avoid pointer to the odd/misaligned address uint16_t const total_len = tu_le16toh( tu_unaligned_read16((const void*) (desc_bos + offsetof(tusb_desc_bos_t, wTotalLength))) ); @@ -1203,12 +1202,12 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const if ( desc_type == TUSB_DESC_CONFIGURATION ) { TU_LOG_USBD(" Configuration[%u]\r\n", desc_index); desc_config = (uintptr_t) tud_descriptor_configuration_cb(desc_index); - TU_ASSERT(desc_config); + TU_ASSERT(desc_config != 0); }else { // Host only request this after getting Device Qualifier descriptor TU_LOG_USBD(" Other Speed Configuration\r\n"); desc_config = (uintptr_t) tud_descriptor_other_speed_configuration_cb(desc_index); - TU_VERIFY(desc_config); + TU_VERIFY(desc_config != 0); } // Use offsetof to avoid pointer to the odd/misaligned address @@ -1218,8 +1217,7 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const } // break; // unreachable - case TUSB_DESC_STRING: - { + case TUSB_DESC_STRING: { TU_LOG_USBD(" String[%u]\r\n", desc_index); // String Descriptor always uses the desc set from user diff --git a/src/device/usbd.h b/src/device/usbd.h index bfff23399..c446638c3 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -95,7 +95,9 @@ bool tud_suspended(void); // Check if device is ready to transfer TU_ATTR_ALWAYS_INLINE static inline bool tud_ready(void) { - return tud_mounted() && !tud_suspended(); + const bool is_mounted = tud_mounted(); + const bool is_suspended = tud_suspended(); + return is_mounted && !is_suspended; } // Remote wake up host, only if suspended and enabled by host @@ -421,7 +423,7 @@ bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_requ TUD_AUDIO10_DESC_SELECTOR_UNIT_ONE_PIN_LEN, TUSB_DESC_CS_INTERFACE, AUDIO10_CS_AC_INTERFACE_SELECTOR_UNIT, _unitid, 1, _srcid, _stridx /* Feature Unit Descriptor UAC1 (4.3.2.5) - Variable Channels */ -#define TUD_AUDIO10_DESC_FEATURE_UNIT_LEN(_nchannels) (7 + (_nchannels + 1) * 2) +#define TUD_AUDIO10_DESC_FEATURE_UNIT_LEN(_nchannels) (7 + ((_nchannels) + 1) * 2) // Feature Unit descriptor, take list of control bitmaps for master channel + each channel as variable arguments #define TUD_AUDIO10_DESC_FEATURE_UNIT(_unitid, _srcid, _stridx, ...) \ TUD_AUDIO10_DESC_FEATURE_UNIT_LEN(TU_ARGS_NUM(__VA_ARGS__) - 1), TUSB_DESC_CS_INTERFACE, AUDIO10_CS_AC_INTERFACE_FEATURE_UNIT, _unitid, _srcid, 2, TU_ARGS_APPLY_EXPAND(U16_TO_U8S_LE, __VA_ARGS__), _stridx @@ -539,7 +541,7 @@ bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_requ TUD_AUDIO20_DESC_OUTPUT_TERM_LEN, TUSB_DESC_CS_INTERFACE, AUDIO20_CS_AC_INTERFACE_OUTPUT_TERMINAL, _termid, U16_TO_U8S_LE(_termtype), _assocTerm, _srcid, _clkid, U16_TO_U8S_LE(_ctrl), _stridx /* Feature Unit Descriptor(4.7.2.8) */ -#define TUD_AUDIO20_DESC_FEATURE_UNIT_LEN(_nchannels) (6 + (_nchannels + 1) * 4) +#define TUD_AUDIO20_DESC_FEATURE_UNIT_LEN(_nchannels) (6 + ((_nchannels) + 1) * 4) #define TUD_AUDIO20_DESC_FEATURE_UNIT(_unitid, _srcid, _stridx, ...) \ TUD_AUDIO20_DESC_FEATURE_UNIT_LEN(TU_ARGS_NUM(__VA_ARGS__) - 1), TUSB_DESC_CS_INTERFACE, AUDIO20_CS_AC_INTERFACE_FEATURE_UNIT, _unitid, _srcid, TU_ARGS_APPLY_EXPAND(U32_TO_U8S_LE, __VA_ARGS__), _stridx @@ -728,7 +730,7 @@ bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_requ // Calculate wMaxPacketSize of Endpoints #define TUD_AUDIO_EP_SIZE(_is_highspeed, _maxFrequency, _nBytesPerSample, _nChannels) \ - ((((_maxFrequency + (_is_highspeed ? 7999 : 999)) / (_is_highspeed ? 8000 : 1000)) + 1) * _nBytesPerSample * _nChannels) + (((((_maxFrequency) + ((_is_highspeed) ? 7999 : 999)) / ((_is_highspeed) ? 8000 : 1000)) + 1) * (_nBytesPerSample) * (_nChannels)) //--------------------------------------------------------------------+ @@ -807,44 +809,44 @@ bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_requ // Interface number, Alternate count, starting string index, attributes, detach timeout, transfer size // Note: Alternate count must be numeric or macro, string index is increased by one for each Alt interface #define TUD_DFU_DESCRIPTOR(_itfnum, _alt_count, _stridx, _attr, _timeout, _xfer_size) \ - TU_XSTRCAT(_TUD_DFU_ALT_,_alt_count)(_itfnum, 0, _stridx), \ + TU_XSTRCAT(TUD_DFU_ALT_,_alt_count)(_itfnum, 0, _stridx), \ /* Function */ \ 9, DFU_DESC_FUNCTIONAL, _attr, U16_TO_U8S_LE(_timeout), U16_TO_U8S_LE(_xfer_size), U16_TO_U8S_LE(0x0101) -#define _TUD_DFU_ALT(_itfnum, _alt, _stridx) \ +#define TUD_DFU_ALT(_itfnum, _alt, _stridx) \ /* Interface */ \ 9, TUSB_DESC_INTERFACE, _itfnum, _alt, 0, TUD_DFU_APP_CLASS, TUD_DFU_APP_SUBCLASS, DFU_PROTOCOL_DFU, _stridx -#define _TUD_DFU_ALT_1(_itfnum, _alt_count, _stridx) \ - _TUD_DFU_ALT(_itfnum, _alt_count, _stridx) +#define TUD_DFU_ALT_1(_itfnum, _alt_count, _stridx) \ + TUD_DFU_ALT(_itfnum, _alt_count, _stridx) -#define _TUD_DFU_ALT_2(_itfnum, _alt_count, _stridx) \ - _TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ - _TUD_DFU_ALT_1(_itfnum, _alt_count+1, _stridx+1) +#define TUD_DFU_ALT_2(_itfnum, _alt_count, _stridx) \ + TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ + TUD_DFU_ALT_1(_itfnum, _alt_count+1, _stridx+1) -#define _TUD_DFU_ALT_3(_itfnum, _alt_count, _stridx) \ - _TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ - _TUD_DFU_ALT_2(_itfnum, _alt_count+1, _stridx+1) +#define TUD_DFU_ALT_3(_itfnum, _alt_count, _stridx) \ + TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ + TUD_DFU_ALT_2(_itfnum, _alt_count+1, _stridx+1) -#define _TUD_DFU_ALT_4(_itfnum, _alt_count, _stridx) \ - _TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ - _TUD_DFU_ALT_3(_itfnum, _alt_count+1, _stridx+1) +#define TUD_DFU_ALT_4(_itfnum, _alt_count, _stridx) \ + TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ + TUD_DFU_ALT_3(_itfnum, _alt_count+1, _stridx+1) -#define _TUD_DFU_ALT_5(_itfnum, _alt_count, _stridx) \ - _TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ - _TUD_DFU_ALT_4(_itfnum, _alt_count+1, _stridx+1) +#define TUD_DFU_ALT_5(_itfnum, _alt_count, _stridx) \ + TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ + TUD_DFU_ALT_4(_itfnum, _alt_count+1, _stridx+1) -#define _TUD_DFU_ALT_6(_itfnum, _alt_count, _stridx) \ - _TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ - _TUD_DFU_ALT_5(_itfnum, _alt_count+1, _stridx+1) +#define TUD_DFU_ALT_6(_itfnum, _alt_count, _stridx) \ + TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ + TUD_DFU_ALT_5(_itfnum, _alt_count+1, _stridx+1) -#define _TUD_DFU_ALT_7(_itfnum, _alt_count, _stridx) \ - _TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ - _TUD_DFU_ALT_6(_itfnum, _alt_count+1, _stridx+1) +#define TUD_DFU_ALT_7(_itfnum, _alt_count, _stridx) \ + TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ + TUD_DFU_ALT_6(_itfnum, _alt_count+1, _stridx+1) -#define _TUD_DFU_ALT_8(_itfnum, _alt_count, _stridx) \ - _TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ - _TUD_DFU_ALT_7(_itfnum, _alt_count+1, _stridx+1) +#define TUD_DFU_ALT_8(_itfnum, _alt_count, _stridx) \ + TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ + TUD_DFU_ALT_7(_itfnum, _alt_count+1, _stridx+1) //--------------------------------------------------------------------+ // CDC-ECM Descriptor Templates diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index a688cf497..2894d3023 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -117,7 +117,9 @@ bool usbd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * p_endp // Check if endpoint is ready (not busy and not stalled) TU_ATTR_ALWAYS_INLINE static inline bool usbd_edpt_ready(uint8_t rhport, uint8_t ep_addr) { - return !usbd_edpt_busy(rhport, ep_addr) && !usbd_edpt_stalled(rhport, ep_addr); + const bool is_busy = usbd_edpt_busy(rhport, ep_addr); + const bool is_stalled = usbd_edpt_stalled(rhport, ep_addr); + return !is_busy && !is_stalled; } // Enable SOF interrupt diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index 1b43b9ac4..b2531426a 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -85,6 +85,12 @@ TU_ATTR_ALWAYS_INLINE static inline uint8_t dwc2_ep_count(const dwc2_regs_t* dwc #endif } +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ +TU_ATTR_ALWAYS_INLINE static inline bool edpt_is_enabled(dwc2_dep_t* dep) { + return (dep->ctl & EPCTL_EPENA) != 0; +} //-------------------------------------------------------------------- // DMA @@ -117,7 +123,7 @@ static void dma_setup_prepare(uint8_t rhport) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); if (dwc2->gsnpsid >= DWC2_CORE_REV_3_00a) { - if(dwc2->epout[0].doepctl & DOEPCTL_EPENA) { + if(edpt_is_enabled(&dwc2->epout[0])) { return; } } @@ -200,7 +206,7 @@ static bool dfifo_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t packet_size) { } } else { // Check IN endpoints concurrently active limit - if(dwc2_controller->ep_in_count) { + if(0 != dwc2_controller->ep_in_count) { TU_ASSERT(_dcd_data.allocated_epin_count < dwc2_controller->ep_in_count); _dcd_data.allocated_epin_count++; } @@ -217,10 +223,10 @@ static bool dfifo_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t packet_size) { // Both TXFD and TXSA are in unit of 32-bit words. if (epnum == 0) { - dwc2->dieptxf0 = (fifo_size << DIEPTXF0_TX0FD_Pos) | _dcd_data.dfifo_top; + dwc2->dieptxf0 = ((uint32_t) fifo_size << DIEPTXF0_TX0FD_Pos) | _dcd_data.dfifo_top; } else { // DIEPTXF starts at FIFO #1. - dwc2->dieptxf[epnum - 1] = (fifo_size << DIEPTXF_INEPTXFD_Pos) | _dcd_data.dfifo_top; + dwc2->dieptxf[epnum - 1] = ((uint32_t) fifo_size << DIEPTXF_INEPTXFD_Pos) | _dcd_data.dfifo_top; } } @@ -238,10 +244,10 @@ static void dfifo_device_init(uint8_t rhport) { if (is_dma) { _dcd_data.dfifo_top -= 2 * dwc2_controller->ep_count; } - dwc2->gdfifocfg = (_dcd_data.dfifo_top << GDFIFOCFG_EPINFOBASE_SHIFT) | _dcd_data.dfifo_top; + dwc2->gdfifocfg = ((uint32_t) _dcd_data.dfifo_top << GDFIFOCFG_EPINFOBASE_SHIFT) | _dcd_data.dfifo_top; // Allocate FIFO for EP0 IN - dfifo_alloc(rhport, 0x80, CFG_TUD_ENDPOINT0_SIZE); + (void) dfifo_alloc(rhport, 0x80, CFG_TUD_ENDPOINT0_SIZE); } @@ -282,16 +288,18 @@ static void edpt_disable(uint8_t rhport, uint8_t ep_addr, bool stall) { const uint8_t dir = tu_edpt_dir(ep_addr); dwc2_dep_t* dep = &dwc2->ep[dir == TUSB_DIR_IN ? 0 : 1][epnum]; + const uint32_t stall_mask = (stall ? EPCTL_STALL : 0); + if (dir == TUSB_DIR_IN) { - if (!(dep->diepctl & DIEPCTL_EPENA)) { - dep->diepctl |= DIEPCTL_SNAK | (stall ? DIEPCTL_STALL : 0); + if (!edpt_is_enabled(dep)) { + dep->diepctl |= DIEPCTL_SNAK | stall_mask; } else { // Stop transmitting packets and NAK IN xfers. dep->diepctl |= DIEPCTL_SNAK; while ((dep->diepint & DIEPINT_INEPNE) == 0) {} // Disable the endpoint. - dep->diepctl |= DIEPCTL_EPDIS | (stall ? DIEPCTL_STALL : 0); + dep->diepctl |= DIEPCTL_EPDIS | stall_mask; while ((dep->diepint & DIEPINT_EPDISD_Msk) == 0) {} dep->diepint = DIEPINT_EPDISD; @@ -300,9 +308,10 @@ static void edpt_disable(uint8_t rhport, uint8_t ep_addr, bool stall) { // Flush the FIFO, and wait until we have confirmed it cleared. dfifo_flush_tx(dwc2, epnum); } else { - // Only disable currently enabled non-control endpoint - if ((epnum == 0) || !(dep->doepctl & DOEPCTL_EPENA)) { - dep->doepctl |= stall ? DOEPCTL_STALL : 0; + if (!edpt_is_enabled(dep) || epnum == 0) { + // non-control not-enabled: stall if set + // For EP0 Out, keep it enabled to receive SETUP packets + dep->doepctl |= stall_mask; } else { // Asserting GONAK is required to STALL an OUT endpoint. // Simpler to use polling here, we don't use the "B"OUTNAKEFF interrupt @@ -312,7 +321,7 @@ static void edpt_disable(uint8_t rhport, uint8_t ep_addr, bool stall) { while ((dwc2->gintsts & GINTSTS_BOUTNAKEFF_Msk) == 0) {} // Ditto here disable the endpoint. - dep->doepctl |= DOEPCTL_EPDIS | (stall ? DOEPCTL_STALL : 0); + dep->doepctl |= DOEPCTL_EPDIS | stall_mask; while ((dep->doepint & DOEPINT_EPDISD_Msk) == 0) {} dep->doepint = DOEPINT_EPDISD; @@ -360,7 +369,7 @@ static void edpt_schedule_packets(uint8_t rhport, const uint8_t epnum, const uin 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) { + if (odd_now != 0) { depctl.set_data0_iso_even = 1; } else { depctl.set_data1_iso_odd = 1; @@ -379,7 +388,7 @@ static void edpt_schedule_packets(uint8_t rhport, const uint8_t epnum, const uin // Enable tx fifo empty interrupt only if there is data. Note must after depctl enable if (dir == TUSB_DIR_IN && total_bytes != 0) { - dwc2->diepempmsk |= (1u << epnum); + dwc2->diepempmsk |= (1u << epnum); //-V629 } } } @@ -551,7 +560,7 @@ void dcd_edpt_close_all(uint8_t rhport) { for (uint8_t n = 1; n < ep_count; n++) { for (uint8_t d = 0; d < 2; d++) { dwc2_dep_t* dep = &dwc2->ep[d][n]; - if (dep->ctl & EPCTL_EPENA) { + if (edpt_is_enabled(dep)) { dep->ctl |= EPCTL_SNAK | EPCTL_EPDIS; } xfer_status[n][1-d].max_size = 0; @@ -643,8 +652,12 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_t void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); edpt_disable(rhport, ep_addr, true); - if((tu_edpt_number(ep_addr) == 0) && dma_device_enabled(dwc2)) { - dma_setup_prepare(rhport); + + // For control endpoint, prepare to receive SETUP packet + if (tu_edpt_number(ep_addr) == 0) { + if (dma_device_enabled(dwc2)) { + dma_setup_prepare(rhport); + } } } @@ -681,8 +694,9 @@ static void handle_bus_reset(uint8_t rhport) { // Disable all IN endpoints for (uint8_t n = 0; n < ep_count; n++) { - if (dwc2->epin[n].diepctl & DIEPCTL_EPENA) { - dwc2->epin[n].diepctl |= DIEPCTL_SNAK | DIEPCTL_EPDIS; + dwc2_dep_t* dep = &dwc2->epin[n]; + if (edpt_is_enabled(dep)) { + dep->diepctl |= DIEPCTL_SNAK | DIEPCTL_EPDIS; } } @@ -807,9 +821,9 @@ static void handle_rxflvl_irq(uint8_t rhport) { const uint16_t byte_count = grxstsp.byte_count; xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); - if (byte_count) { + if (byte_count != 0) { // Read packet off RxFIFO - if (xfer->ff) { + if (xfer->ff != NULL) { tu_fifo_write_n_const_addr_full_words(xfer->ff, (const void*) (uintptr_t) rx_fifo, byte_count); } else { dfifo_read_packet(dwc2, xfer->buffer, byte_count); @@ -836,7 +850,7 @@ static void handle_rxflvl_irq(uint8_t rhport) { // the specified OUT endpoint which will be handled by handle_epout_irq() break; - default: break; + default: break; // nothing to do } } @@ -844,7 +858,7 @@ static void handle_epout_slave(uint8_t rhport, uint8_t epnum, dwc2_doepint_t doe if (doepint_bm.setup_phase_done) { // Cleanup previous pending EP0 IN transfer if any dwc2_dep_t* epin0 = &DWC2_REG(rhport)->epin[0]; - if (epin0->diepctl & DIEPCTL_EPENA) { + if (edpt_is_enabled(epin0)) { edpt_disable(rhport, 0x80, false); } dcd_event_setup_received(rhport, _dcd_usbbuf.setup_packet, true); @@ -858,7 +872,6 @@ static void handle_epout_slave(uint8_t rhport, uint8_t epnum, dwc2_doepint_t doe // can is set when GRXSTS_PKTSTS_SETUP_RX is popped therefore they can bet set before/together with setup_phase_done if (!doepint_bm.status_phase_rx && !doepint_bm.setup_packet_rx) { xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); - if ((epnum == 0) && _dcd_data.ep0_pending[TUSB_DIR_OUT]) { // EP0 can only handle one packet, Schedule another packet to be received. edpt_schedule_packets(rhport, epnum, TUSB_DIR_OUT); @@ -875,7 +888,7 @@ static void handle_epin_slave(uint8_t rhport, uint8_t epnum, dwc2_diepint_t diep xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, TUSB_DIR_IN); if (diepint_bm.xfer_complete) { - if ((epnum == 0) && _dcd_data.ep0_pending[TUSB_DIR_IN]) { + if ((epnum == 0) && (0 != _dcd_data.ep0_pending[TUSB_DIR_IN])) { // EP0 can only handle one packet. Schedule another packet to be transmitted. edpt_schedule_packets(rhport, epnum, TUSB_DIR_IN); } else { @@ -886,7 +899,7 @@ static void handle_epin_slave(uint8_t rhport, uint8_t epnum, dwc2_diepint_t diep // TX FIFO empty bit is read-only. It will only be cleared by hardware when written bytes is more than // - 64 bytes or // - Half/Empty of TX FIFO size (configured by GAHBCFG.TXFELVL) - if (diepint_bm.txfifo_empty && (dwc2->diepempmsk & (1 << epnum))) { + if (diepint_bm.txfifo_empty && tu_bit_test(dwc2->diepempmsk, epnum)) { dwc2_ep_tsize_t tsiz = {.value = epin->tsiz}; const uint16_t remain_packets = tsiz.packet_count; @@ -902,7 +915,7 @@ static void handle_epin_slave(uint8_t rhport, uint8_t epnum, dwc2_diepint_t diep } // Push packet to Tx-FIFO - if (xfer->ff) { + if (xfer->ff != NULL) { volatile uint32_t* tx_fifo = dwc2->fifo[epnum]; tu_fifo_read_n_const_addr_full_words(xfer->ff, (void*)(uintptr_t)tx_fifo, xact_bytes); } else { @@ -927,7 +940,7 @@ static void handle_epout_dma(uint8_t rhport, uint8_t epnum, dwc2_doepint_t doepi if (doepint_bm.setup_phase_done) { // Cleanup previous pending EP0 IN transfer if any dwc2_dep_t* epin0 = &DWC2_REG(rhport)->epin[0]; - if (epin0->diepctl & DIEPCTL_EPENA) { + if (edpt_is_enabled(epin0)) { edpt_disable(rhport, 0x80, false); } dma_setup_prepare(rhport); @@ -993,7 +1006,7 @@ static void handle_ep_irq(uint8_t rhport, uint8_t dir) { // DAINT for a given EP clears when DEPINTx is cleared. // EPINT will be cleared when DAINT bits are cleared. for (uint8_t epnum = 0; epnum < ep_count; epnum++) { - if (dwc2->daint & TU_BIT(daint_offset + epnum)) { + if (tu_bit_test(dwc2->daint,daint_offset + epnum)) { dwc2_dep_t* epout = &ep_base[epnum]; union { uint32_t value; @@ -1002,7 +1015,7 @@ static void handle_ep_irq(uint8_t rhport, uint8_t dir) { } intr; intr.value = epout->intr; - epout->intr = intr.value; // Clear interrupt + epout->intr = intr.value; // Clear interrupt //-V::2584::{otg_int} if (is_dma) { #if CFG_TUD_DWC2_DMA_ENABLE @@ -1037,6 +1050,7 @@ static void handle_ep_irq(uint8_t rhport, uint8_t dir) { Note: when OTG_MULTI_PROC_INTRPT = 1, Device Each endpoint interrupt deachint/deachmsk/diepeachmsk/doepeachmsk are combined to generate dedicated interrupt line for each endpoint. */ +//-V::2584::{gintsts} PVS-Studio suppression void dcd_int_handler(uint8_t rhport) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); const uint32_t gintmask = dwc2->gintmsk; diff --git a/src/portable/synopsys/dwc2/dwc2_stm32.h b/src/portable/synopsys/dwc2/dwc2_stm32.h index 08950ccc0..9da8de41f 100644 --- a/src/portable/synopsys/dwc2/dwc2_stm32.h +++ b/src/portable/synopsys/dwc2/dwc2_stm32.h @@ -176,7 +176,9 @@ TU_ATTR_ALWAYS_INLINE static inline void dwc2_int_set(uint8_t rhport, tusb_role_ TU_ATTR_ALWAYS_INLINE static inline void dwc2_remote_wakeup_delay(void) { // try to delay for 1 ms uint32_t count = SystemCoreClock / 1000; - while (count--) __NOP(); + while (count--) { + __NOP(); + } } // MCU specific PHY init, called BEFORE core reset diff --git a/src/portable/synopsys/dwc2/dwc2_type.h b/src/portable/synopsys/dwc2/dwc2_type.h index 75643529f..adcc579e3 100644 --- a/src/portable/synopsys/dwc2/dwc2_type.h +++ b/src/portable/synopsys/dwc2/dwc2_type.h @@ -1435,7 +1435,7 @@ TU_VERIFY_STATIC(offsetof(dwc2_regs_t, fifo ) == 0x1000, "incorrect size"); #define DAINTMSK_OEPM_Msk (0xFFFFUL << DAINTMSK_OEPM_Pos) // 0xFFFF0000 #define DAINTMSK_OEPM DAINTMSK_OEPM_Msk // OUT EP interrupt mask bits -#define DAINT_SHIFT(_dir) ((_dir == TUSB_DIR_IN) ? 0 : 16) +#define DAINT_SHIFT(_dir) (((_dir) == TUSB_DIR_IN) ? 0 : 16) #if 0 /******************** Bit definition for OTG register ********************/ -- cgit v1.3.1 From 1f84dd595a511c82d766b39c2659869bc259be8f Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 6 Nov 2025 18:22:37 +0700 Subject: fix compile issue when enable both host and device for dwc2 --- src/portable/synopsys/dwc2/dcd_dwc2.c | 1 - src/portable/synopsys/dwc2/dwc2_common.c | 10 ---------- src/portable/synopsys/dwc2/dwc2_common.h | 8 ++++++++ 3 files changed, 8 insertions(+), 11 deletions(-) (limited to 'src/portable') diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index b2531426a..06579fbb3 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -1050,7 +1050,6 @@ static void handle_ep_irq(uint8_t rhport, uint8_t dir) { Note: when OTG_MULTI_PROC_INTRPT = 1, Device Each endpoint interrupt deachint/deachmsk/diepeachmsk/doepeachmsk are combined to generate dedicated interrupt line for each endpoint. */ -//-V::2584::{gintsts} PVS-Studio suppression void dcd_int_handler(uint8_t rhport) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); const uint32_t gintmask = dwc2->gintmsk; diff --git a/src/portable/synopsys/dwc2/dwc2_common.c b/src/portable/synopsys/dwc2/dwc2_common.c index 5ff18ab94..980574e12 100644 --- a/src/portable/synopsys/dwc2/dwc2_common.c +++ b/src/portable/synopsys/dwc2/dwc2_common.c @@ -29,16 +29,6 @@ #define DWC2_COMMON_DEBUG 2 #if defined(TUP_USBIP_DWC2) && (CFG_TUH_ENABLED || CFG_TUD_ENABLED) - -#if CFG_TUD_ENABLED -#include "device/dcd.h" -#endif - -#if CFG_TUH_ENABLED -#include "host/hcd.h" -#include "host/usbh.h" -#endif - #include "dwc2_common.h" //-------------------------------------------------------------------- diff --git a/src/portable/synopsys/dwc2/dwc2_common.h b/src/portable/synopsys/dwc2/dwc2_common.h index 0166b0261..dc204f578 100644 --- a/src/portable/synopsys/dwc2/dwc2_common.h +++ b/src/portable/synopsys/dwc2/dwc2_common.h @@ -30,6 +30,14 @@ #include "common/tusb_common.h" #include "dwc2_type.h" +#if CFG_TUD_ENABLED +#include "device/dcd.h" +#endif + +#if CFG_TUH_ENABLED +#include "host/hcd.h" +#endif + // Following symbols must be defined by port header // - _dwc2_controller[]: array of controllers // - DWC2_EP_MAX: largest EP counts of all controllers -- cgit v1.3.1 From 86a4990b96eafb5904f946fa061b310f155a7d51 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 5 Nov 2025 19:56:54 +0700 Subject: fix more alerts --- examples/device/cdc_msc/src/main.c | 35 +++++++++++++++++------------------ src/common/tusb_compiler.h | 2 +- src/common/tusb_private.h | 4 ++-- src/common/tusb_verify.h | 2 +- src/portable/ehci/ehci.c | 2 +- 5 files changed, 22 insertions(+), 23 deletions(-) (limited to 'src/portable') diff --git a/examples/device/cdc_msc/src/main.c b/examples/device/cdc_msc/src/main.c index ff998a13d..e4a205533 100644 --- a/examples/device/cdc_msc/src/main.c +++ b/examples/device/cdc_msc/src/main.c @@ -37,12 +37,12 @@ */ enum { BLINK_NOT_MOUNTED = 250, - BLINK_MOUNTED = 1000, - BLINK_SUSPENDED = 2500, + BLINK_MOUNTED = 1000, + BLINK_SUSPENDED = 2500, }; static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; -static bool blink_enable = true; +static bool blink_enable = true; void led_blinking_task(void); void cdc_task(void); @@ -52,10 +52,7 @@ 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 - }; + tusb_rhport_init_t dev_init = {.role = TUSB_ROLE_DEVICE, .speed = TUSB_SPEED_AUTO}; tusb_init(BOARD_TUD_RHPORT, &dev_init); board_init_after_tusb(); @@ -86,7 +83,7 @@ void tud_umount_cb(void) { // 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)remote_wakeup_en; blink_interval_ms = BLINK_SUSPENDED; } @@ -107,9 +104,9 @@ void cdc_task(void) { // connected and there are data available if (tud_cdc_available()) { // read data - char buf[64]; + char buf[64]; uint32_t count = tud_cdc_read(buf, sizeof(buf)); - (void) count; + (void)count; // Echo back // Note: Skip echo by commenting out write() and write_flush() @@ -120,10 +117,12 @@ void cdc_task(void) { } // Press on-board button to send Uart status notification + static cdc_notify_uart_state_t uart_state = {.value = 0}; + 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 == 0u) && btn) { + const uint32_t btn = board_button_read(); + + if ((btn_prev == 0u) && (btn != 0u)) { uart_state.dsr ^= 1; tud_cdc_notify_uart_state(&uart_state); } @@ -133,8 +132,8 @@ void cdc_task(void) { // Invoked when cdc when line state changed e.g connected/disconnected void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) { - (void) itf; - (void) rts; + (void)itf; + (void)rts; if (dtr) { // Terminal connected @@ -148,15 +147,15 @@ void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) { // Invoked when CDC interface received data from host void tud_cdc_rx_cb(uint8_t itf) { - (void) itf; + (void)itf; } //--------------------------------------------------------------------+ // BLINKING TASK //--------------------------------------------------------------------+ void led_blinking_task(void) { - static uint32_t start_ms = 0; - static bool led_state = false; + static uint32_t start_ms = 0; + static bool led_state = false; if (blink_enable) { // Blink every interval ms diff --git a/src/common/tusb_compiler.h b/src/common/tusb_compiler.h index 167385d13..7719790d1 100644 --- a/src/common/tusb_compiler.h +++ b/src/common/tusb_compiler.h @@ -106,7 +106,7 @@ 19,18,17,16,15,14,13,12,11,10, \ 9,8,7,6,5,4,3,2,1,0 -// Apply a macro X to each of the arguments with a selected separation/delimiter +// Apply a macro X to each of the arguments with a separation/delimiter #define TU_ARGS_APPLY(_X, _s, ...) TU_XSTRCAT(TU_ARGS_APPLY_, TU_ARGS_NUM(__VA_ARGS__))(_X, _s, __VA_ARGS__) #define TU_ARGS_APPLY_1(_X, _s, _a1) _X(_a1) diff --git a/src/common/tusb_private.h b/src/common/tusb_private.h index 37d5e89f1..5e1d59233 100644 --- a/src/common/tusb_private.h +++ b/src/common/tusb_private.h @@ -141,7 +141,7 @@ uint32_t tu_edpt_stream_read_xfer(uint8_t hwid, tu_edpt_stream_t* s); // Complete read transfer by writing EP -> FIFO. Must be called in the transfer complete callback TU_ATTR_ALWAYS_INLINE static inline void tu_edpt_stream_read_xfer_complete(tu_edpt_stream_t* s, uint32_t xferred_bytes) { - if (0 != tu_fifo_depth(&s->ff)) { + if (0u != tu_fifo_depth(&s->ff)) { tu_fifo_write_n(&s->ff, s->ep_buf, (uint16_t) xferred_bytes); } } @@ -149,7 +149,7 @@ void tu_edpt_stream_read_xfer_complete(tu_edpt_stream_t* s, uint32_t xferred_byt // Complete read transfer with provided buffer TU_ATTR_ALWAYS_INLINE static inline void tu_edpt_stream_read_xfer_complete_with_buf(tu_edpt_stream_t* s, const void * buf, uint32_t xferred_bytes) { - if (0 != tu_fifo_depth(&s->ff)) { + if (0u != tu_fifo_depth(&s->ff)) { tu_fifo_write_n(&s->ff, buf, (uint16_t) xferred_bytes); } } diff --git a/src/common/tusb_verify.h b/src/common/tusb_verify.h index ffd785384..587554e7f 100644 --- a/src/common/tusb_verify.h +++ b/src/common/tusb_verify.h @@ -78,7 +78,7 @@ defined(__ARM7M__) || defined (__ARM7EM__) || defined(__ARM8M_MAINLINE__) || defined(__ARM8EM_MAINLINE__) #define TU_BREAKPOINT() do { \ volatile uint32_t* ARM_CM_DHCSR = ((volatile uint32_t*) 0xE000EDF0UL); /* Cortex M CoreDebug->DHCSR */ \ - if (0 != ((*ARM_CM_DHCSR) & 1UL)) { __asm("BKPT #0\n"); } /* Only halt mcu if debugger is attached */ \ + if (0u != ((*ARM_CM_DHCSR) & 1UL)) { __asm("BKPT #0\n"); } /* Only halt mcu if debugger is attached */ \ } while(0) #elif defined(__riscv) && !TUSB_MCU_VENDOR_ESPRESSIF diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c index 973bb43cc..c33c970e4 100644 --- a/src/portable/ehci/ehci.c +++ b/src/portable/ehci/ehci.c @@ -920,7 +920,7 @@ static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, tusb_desc_endpoint_t c // sub millisecond interval p_qhd->interval_ms = 0; p_qhd->int_smask = (interval == 1) ? 0xff : // 0b11111111 - (interval == 2) ? 0xaa /* 0b10101010 */ : 0x44 /* 01000100 */; + (interval == 2) ? 0xaa /* 0b10101010 */ : 0x44 /* 0b01000100 */; } else { p_qhd->interval_ms = (uint8_t) tu_min16(1 << (interval - 4), 255); p_qhd->int_smask = TU_BIT(interval % 8); -- cgit v1.3.1 From 6b28a4478c9f8fa3993d593360eb5574bbdeda22 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 15 Nov 2025 19:46:14 +0700 Subject: make TUP_DCD_EDPT_ISO_ALLOC i.e dcd_edpt_iso_alloc()/dcd_edpt_iso_activate() as default driver implementation. dcd_edpt_close() is deprecated and will be removed from all driver in the future. --- docs/porting.rst | 10 + src/common/tusb_mcu.h | 335 ++++++++++++----------- src/device/dcd.h | 11 +- src/portable/bridgetek/ft9xx/dcd_ft9xx.c | 15 +- src/portable/chipidea/ci_fs/dcd_ci_fs.c | 18 +- src/portable/chipidea/ci_hs/dcd_ci_hs.c | 196 +++++++------ src/portable/dialog/da146xx/dcd_da146xx.c | 16 +- src/portable/microchip/pic/dcd_pic.c | 16 +- src/portable/microchip/pic32mz/dcd_pic32mz.c | 13 +- src/portable/microchip/samd/dcd_samd.c | 11 +- src/portable/microchip/samg/dcd_samg.c | 15 +- src/portable/microchip/samx7x/dcd_samx7x.c | 17 +- src/portable/mindmotion/mm32/dcd_mm32f327x_otg.c | 299 ++++++++++---------- src/portable/nordic/nrf5x/dcd_nrf5x.c | 16 +- src/portable/nxp/khci/dcd_khci.c | 16 +- src/portable/nxp/lpc17_40/dcd_lpc17_40.c | 15 +- src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c | 16 +- src/portable/raspberrypi/pio_usb/dcd_pio_usb.c | 14 +- src/portable/renesas/rusb2/dcd_rusb2.c | 16 +- src/portable/sunxi/dcd_sunxi_musb.c | 16 +- src/portable/ti/msp430x5xx/dcd_msp430x5xx.c | 16 +- src/portable/valentyusb/eptri/dcd_eptri.c | 15 +- src/portable/wch/dcd_ch32_usbfs.c | 13 +- src/portable/wch/dcd_ch32_usbhs.c | 27 +- 24 files changed, 702 insertions(+), 450 deletions(-) (limited to 'src/portable') diff --git a/docs/porting.rst b/docs/porting.rst index c3076354c..9b60ec5a2 100644 --- a/docs/porting.rst +++ b/docs/porting.rst @@ -173,12 +173,22 @@ Also make sure to enable endpoint specific interrupts. ``dcd_edpt_close()`` """""""""""""""""""" +.. warning:: + This function is deprecated, ISO transfer should implement dcd_edpt_iso_alloc() and dcd_edpt_iso_activate() instead. + Close an endpoint. his function is used for implementing alternate settings. After calling this, the device should not respond to any packets directed towards this endpoint. When called, this function must abort any transfers in progress through this endpoint, before returning. Implementation is optional. Must be called from the USB task. Interrupts could be disabled or enabled during the call. +``dcd_edpt_iso_alloc() / dcd_edpt_iso_activate()`` +"""""""""""""""""""""""""""""""""""""""""""""""""" + +dcd_edpt_iso_alloc() is used to allocate largest buffer (for all alternative interfaces) for ISO endpoints when device is enumerated. This allows DCD to allocate necessary resources for ISO endpoints in the future. + +dcd_edpt_iso_activate() is used to activate or deactivate ISO endpoint when alternate setting is set with active max packet size. + ``dcd_edpt_xfer()`` """"""""""""""""""" diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index fd922ee56..05ae6929c 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -37,14 +37,14 @@ #ifdef __ARM_ARCH // ARM Architecture set __ARM_FEATURE_UNALIGNED to 1 for mcu supports unaligned access #if defined(__ARM_FEATURE_UNALIGNED) && __ARM_FEATURE_UNALIGNED == 1 - #define TUP_ARCH_STRICT_ALIGN 0 + #define TUP_ARCH_STRICT_ALIGN 0 #else - #define TUP_ARCH_STRICT_ALIGN 1 + #define TUP_ARCH_STRICT_ALIGN 1 #endif #else // TODO default to strict align for others // Should investigate other architecture such as risv, xtensa, mips for optimal setting - #define TUP_ARCH_STRICT_ALIGN 1 + #define TUP_ARCH_STRICT_ALIGN 1 #endif /* USB Controller Attributes for Device, Host or MCU (both) @@ -57,41 +57,41 @@ //--------------------------------------------------------------------+ // NXP //--------------------------------------------------------------------+ -#if TU_CHECK_MCU(OPT_MCU_LPC11UXX, OPT_MCU_LPC13XX, OPT_MCU_LPC15XX) +#if TU_CHECK_MCU(OPT_MCU_LPC11UXX, OPT_MCU_LPC13XX, OPT_MCU_LPC15XX) #define TUP_USBIP_IP3511 - #define TUP_DCD_ENDPOINT_MAX 5 + #define TUP_DCD_ENDPOINT_MAX 5 #elif TU_CHECK_MCU(OPT_MCU_LPC175X_6X, OPT_MCU_LPC177X_8X, OPT_MCU_LPC40XX) - #define TUP_DCD_ENDPOINT_MAX 16 + #define TUP_DCD_ENDPOINT_MAX 16 #define TUP_USBIP_OHCI #define TUP_USBIP_OHCI_NXP - #define TUP_OHCI_RHPORTS 2 + #define TUP_OHCI_RHPORTS 2 #elif TU_CHECK_MCU(OPT_MCU_LPC51UXX) - #define TUP_USBIP_IP3511 - #define TUP_DCD_ENDPOINT_MAX 5 + #define TUP_USBIP_IP3511 + #define TUP_DCD_ENDPOINT_MAX 5 #elif TU_CHECK_MCU(OPT_MCU_LPC54) // TODO USB0 has 5, USB1 has 6 #define TUP_USBIP_IP3511 - #define TUP_DCD_ENDPOINT_MAX 6 + #define TUP_DCD_ENDPOINT_MAX 6 #elif TU_CHECK_MCU(OPT_MCU_LPC55) // TODO USB0 has 5, USB1 has 6 #define TUP_USBIP_IP3511 #define TUP_USBIP_OHCI #define TUP_USBIP_OHCI_NXP - #define TUP_OHCI_RHPORTS 1 // 1 downstream port + #define TUP_OHCI_RHPORTS 1 // 1 downstream port - #define TUP_DCD_ENDPOINT_MAX 6 + #define TUP_DCD_ENDPOINT_MAX 6 #elif TU_CHECK_MCU(OPT_MCU_LPC18XX, OPT_MCU_LPC43XX) // USB0 has 6 with HS PHY, USB1 has 4 only FS #define TUP_USBIP_CHIPIDEA_HS #define TUP_USBIP_EHCI - #define TUP_DCD_ENDPOINT_MAX 6 - #define TUP_RHPORT_HIGHSPEED 1 + #define TUP_DCD_ENDPOINT_MAX 6 + #define TUP_RHPORT_HIGHSPEED 1 #elif TU_CHECK_MCU(OPT_MCU_MCXN9) // USB0 is chipidea FS @@ -102,15 +102,15 @@ #define TUP_USBIP_CHIPIDEA_HS #define TUP_USBIP_EHCI - #define TUP_DCD_ENDPOINT_MAX 8 - #define TUP_RHPORT_HIGHSPEED 1 + #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_RHPORT_HIGHSPEED 1 #elif TU_CHECK_MCU(OPT_MCU_MCXA15) // USB0 is chipidea FS #define TUP_USBIP_CHIPIDEA_FS #define TUP_USBIP_CHIPIDEA_FS_MCX - #define TUP_DCD_ENDPOINT_MAX 16 + #define TUP_DCD_ENDPOINT_MAX 16 #elif TU_CHECK_MCU(OPT_MCU_MIMXRT1XXX) #include "fsl_device_registers.h" @@ -118,60 +118,61 @@ #define TUP_USBIP_CHIPIDEA_HS #define TUP_USBIP_EHCI - #define TUP_DCD_ENDPOINT_MAX 8 - #define TUP_RHPORT_HIGHSPEED 1 + #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_RHPORT_HIGHSPEED 1 #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_DEFAULT 32 + #define CFG_TUD_MEM_DCACHE_ENABLE_DEFAULT 1 + #define CFG_TUH_MEM_DCACHE_ENABLE_DEFAULT 1 + #define CFG_TUSB_MEM_DCACHE_LINE_SIZE_DEFAULT 32 #endif #elif TU_CHECK_MCU(OPT_MCU_KINETIS_KL, OPT_MCU_KINETIS_K32L, OPT_MCU_KINETIS_K) #define TUP_USBIP_CHIPIDEA_FS #define TUP_USBIP_CHIPIDEA_FS_KINETIS - #define TUP_DCD_ENDPOINT_MAX 16 + #define TUP_DCD_ENDPOINT_MAX 16 #elif TU_CHECK_MCU(OPT_MCU_MM32F327X) - #define TUP_DCD_ENDPOINT_MAX 16 + #define TUP_DCD_ENDPOINT_MAX 16 + #define TUP_DCD_EDPT_CLOSE_API //--------------------------------------------------------------------+ // Nordic //--------------------------------------------------------------------+ #elif TU_CHECK_MCU(OPT_MCU_NRF5X) // 8 CBI + 1 ISO - #define TUP_DCD_ENDPOINT_MAX 9 + #define TUP_DCD_ENDPOINT_MAX 9 + #define TUP_DCD_EDPT_CLOSE_API #elif TU_CHECK_MCU(OPT_MCU_NRF54) #define TUP_USBIP_DWC2 #define TUP_USBIP_DWC2_NRF - #define TUP_DCD_ENDPOINT_MAX 16 + #define TUP_DCD_ENDPOINT_MAX 16 #define CFG_TUH_DWC2_DMA_ENABLE_DEFAULT 0 //--------------------------------------------------------------------+ // Microchip //--------------------------------------------------------------------+ -#elif TU_CHECK_MCU(OPT_MCU_SAMD11, OPT_MCU_SAML2X, OPT_MCU_SAMD21) || \ - TU_CHECK_MCU(OPT_MCU_SAMD51, OPT_MCU_SAME5X) - #define TUP_DCD_ENDPOINT_MAX 8 +#elif TU_CHECK_MCU(OPT_MCU_SAMD11, OPT_MCU_SAML2X, OPT_MCU_SAMD21) || TU_CHECK_MCU(OPT_MCU_SAMD51, OPT_MCU_SAME5X) + #define TUP_DCD_ENDPOINT_MAX 8 #elif TU_CHECK_MCU(OPT_MCU_SAMG) - #define TUP_DCD_ENDPOINT_MAX 6 + #define TUP_DCD_ENDPOINT_MAX 6 #define TUD_ENDPOINT_ONE_DIRECTION_ONLY #elif TU_CHECK_MCU(OPT_MCU_SAMX7X) - #define TUP_DCD_ENDPOINT_MAX 10 - #define TUP_RHPORT_HIGHSPEED 1 + #define TUP_DCD_ENDPOINT_MAX 10 + #define TUP_RHPORT_HIGHSPEED 1 #define TUD_ENDPOINT_ONE_DIRECTION_ONLY #elif TU_CHECK_MCU(OPT_MCU_PIC32MZ) - #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_DCD_ENDPOINT_MAX 8 #define TUD_ENDPOINT_ONE_DIRECTION_ONLY -#elif TU_CHECK_MCU(OPT_MCU_PIC32MX, OPT_MCU_PIC32MM, OPT_MCU_PIC32MK) || \ - TU_CHECK_MCU(OPT_MCU_PIC24, OPT_MCU_DSPIC33) - #define TUP_DCD_ENDPOINT_MAX 16 +#elif TU_CHECK_MCU(OPT_MCU_PIC32MX, OPT_MCU_PIC32MM, OPT_MCU_PIC32MK) || TU_CHECK_MCU(OPT_MCU_PIC24, OPT_MCU_DSPIC33) + #define TUP_DCD_ENDPOINT_MAX 16 #define TUD_ENDPOINT_ONE_DIRECTION_ONLY + #define TUP_DCD_EDPT_CLOSE_API //--------------------------------------------------------------------+ // ST @@ -179,23 +180,23 @@ #elif TU_CHECK_MCU(OPT_MCU_STM32F0) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_DCD_ENDPOINT_MAX 8 #elif TU_CHECK_MCU(OPT_MCU_STM32F1) // - F102, F103 use fsdev // - F105, F107 use dwc2 - #if defined (STM32F105x8) || defined (STM32F105xB) || defined (STM32F105xC) || \ - defined (STM32F107xB) || defined (STM32F107xC) + #if defined(STM32F105x8) || defined(STM32F105xB) || defined(STM32F105xC) || defined(STM32F107xB) || \ + defined(STM32F107xC) #define TUP_USBIP_DWC2 #define TUP_USBIP_DWC2_STM32 #define CFG_TUH_DWC2_DMA_ENABLE_DEFAULT 0 - #define TUP_DCD_ENDPOINT_MAX 4 - #elif defined(STM32F102x6) || defined(STM32F102xB) || \ - defined(STM32F103x6) || defined(STM32F103xB) || defined(STM32F103xE) || defined(STM32F103xG) + #define TUP_DCD_ENDPOINT_MAX 4 + #elif defined(STM32F102x6) || defined(STM32F102xB) || defined(STM32F103x6) || defined(STM32F103xB) || \ + defined(STM32F103xE) || defined(STM32F103xG) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_DCD_ENDPOINT_MAX 8 #else #error "Unsupported STM32F1 mcu" #endif @@ -205,55 +206,55 @@ #define TUP_USBIP_DWC2_STM32 // FS has 4 ep, HS has 5 ep - #define TUP_DCD_ENDPOINT_MAX 6 + #define TUP_DCD_ENDPOINT_MAX 6 #elif TU_CHECK_MCU(OPT_MCU_STM32F3) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_DCD_ENDPOINT_MAX 8 #elif TU_CHECK_MCU(OPT_MCU_STM32F4) #define TUP_USBIP_DWC2 #define TUP_USBIP_DWC2_STM32 // For most mcu, FS has 4, HS has 6. TODO 446/469/479 HS has 9 - #define TUP_DCD_ENDPOINT_MAX 6 + #define TUP_DCD_ENDPOINT_MAX 6 #elif TU_CHECK_MCU(OPT_MCU_STM32F7) #define TUP_USBIP_DWC2 #define TUP_USBIP_DWC2_STM32 // FS has 6, HS has 9 - #define TUP_DCD_ENDPOINT_MAX 9 + #define TUP_DCD_ENDPOINT_MAX 9 // MCU with on-chip HS Phy #if defined(STM32F723xx) || defined(STM32F730xx) || defined(STM32F733xx) - #define TUP_RHPORT_HIGHSPEED 1 // Port0: FS, Port1: HS + #define TUP_RHPORT_HIGHSPEED 1 // Port0: FS, Port1: HS #endif // 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_DEFAULT 32 + #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_DEFAULT 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 + #define TUP_DCD_ENDPOINT_MAX 9 #if __CORTEX_M == 7 // 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_DEFAULT 32 + #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_DEFAULT 32 #endif #elif TU_CHECK_MCU(OPT_MCU_STM32H5) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_DCD_ENDPOINT_MAX 8 #elif TU_CHECK_MCU(OPT_MCU_STM32G4) // Device controller @@ -262,41 +263,40 @@ // TypeC controller #define TUP_USBIP_TYPEC_STM32 - #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_DCD_ENDPOINT_MAX 8 #define TUP_TYPEC_RHPORTS_NUM 1 #elif TU_CHECK_MCU(OPT_MCU_STM32G0) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_DCD_ENDPOINT_MAX 8 #elif TU_CHECK_MCU(OPT_MCU_STM32C0) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_DCD_ENDPOINT_MAX 8 #elif TU_CHECK_MCU(OPT_MCU_STM32L0, OPT_MCU_STM32L1) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_DCD_ENDPOINT_MAX 8 #elif TU_CHECK_MCU(OPT_MCU_STM32L4) // - L4x2, L4x3 use fsdev // - L4x4, L4x6, L4x7, L4x9 use dwc2 - #if defined (STM32L475xx) || defined (STM32L476xx) || \ - defined (STM32L485xx) || defined (STM32L486xx) || defined (STM32L496xx) || \ - defined (STM32L4A6xx) || defined (STM32L4P5xx) || defined (STM32L4Q5xx) || \ - defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || \ - defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + #if defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) || \ + defined(STM32L496xx) || defined(STM32L4A6xx) || defined(STM32L4P5xx) || defined(STM32L4Q5xx) || \ + defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || \ + defined(STM32L4S7xx) || defined(STM32L4S9xx) #define TUP_USBIP_DWC2 #define TUP_USBIP_DWC2_STM32 - #define TUP_DCD_ENDPOINT_MAX 6 + #define TUP_DCD_ENDPOINT_MAX 6 #elif defined(STM32L412xx) || defined(STM32L422xx) || defined(STM32L432xx) || defined(STM32L433xx) || \ - defined(STM32L442xx) || defined(STM32L443xx) || defined(STM32L452xx) || defined(STM32L462xx) + defined(STM32L442xx) || defined(STM32L443xx) || defined(STM32L452xx) || defined(STM32L462xx) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_DCD_ENDPOINT_MAX 8 #else #error "Unsupported STM32L4 mcu" #endif @@ -304,19 +304,19 @@ #elif TU_CHECK_MCU(OPT_MCU_STM32WB) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define TUP_DCD_ENDPOINT_MAX 8 + #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 + #define TUP_DCD_ENDPOINT_MAX 9 + #define TUP_RHPORT_HIGHSPEED 1 #elif TU_CHECK_MCU(OPT_MCU_STM32U5) - #if defined (STM32U535xx) || defined (STM32U545xx) + #if defined(STM32U535xx) || defined(STM32U545xx) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_DCD_ENDPOINT_MAX 8 #else #define TUP_USBIP_DWC2 @@ -324,38 +324,38 @@ // U59x/5Ax/5Fx/5Gx are highspeed with built-in HS PHY #if defined(STM32U595xx) || defined(STM32U599xx) || defined(STM32U5A5xx) || defined(STM32U5A9xx) || \ - defined(STM32U5F7xx) || defined(STM32U5F9xx) || defined(STM32U5G7xx) || defined(STM32U5G9xx) - #define TUP_DCD_ENDPOINT_MAX 9 - #define TUP_RHPORT_HIGHSPEED 1 + defined(STM32U5F7xx) || defined(STM32U5F9xx) || defined(STM32U5G7xx) || defined(STM32U5G9xx) + #define TUP_DCD_ENDPOINT_MAX 9 + #define TUP_RHPORT_HIGHSPEED 1 #else - #define TUP_DCD_ENDPOINT_MAX 6 + #define TUP_DCD_ENDPOINT_MAX 6 #endif #endif #elif TU_CHECK_MCU(OPT_MCU_STM32L5) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_DCD_ENDPOINT_MAX 8 #elif TU_CHECK_MCU(OPT_MCU_STM32U0) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_DCD_ENDPOINT_MAX 8 #elif TU_CHECK_MCU(OPT_MCU_STM32U3) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_DCD_ENDPOINT_MAX 8 #elif TU_CHECK_MCU(OPT_MCU_STM32H7RS, OPT_MCU_STM32N6) #define TUP_USBIP_DWC2 #define TUP_USBIP_DWC2_STM32 // FS has 6, HS has 9 - #define TUP_DCD_ENDPOINT_MAX 9 + #define TUP_DCD_ENDPOINT_MAX 9 // MCU with on-chip HS Phy - #define TUP_RHPORT_HIGHSPEED 1 + #define TUP_RHPORT_HIGHSPEED 1 // Enable dcache if DMA is enabled #define CFG_TUD_MEM_DCACHE_ENABLE_DEFAULT CFG_TUD_DWC2_DMA_ENABLE @@ -366,43 +366,39 @@ // Sony //--------------------------------------------------------------------+ #elif TU_CHECK_MCU(OPT_MCU_CXD56) - #define TUP_DCD_ENDPOINT_MAX 7 - #define TUP_RHPORT_HIGHSPEED 1 + #define TUP_DCD_ENDPOINT_MAX 7 + #define TUP_RHPORT_HIGHSPEED 1 #define TUD_ENDPOINT_ONE_DIRECTION_ONLY - #define TUP_DCD_EDPT_ISO_ALLOC //--------------------------------------------------------------------+ // TI //--------------------------------------------------------------------+ #elif TU_CHECK_MCU(OPT_MCU_MSP430x5xx) - #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_DCD_ENDPOINT_MAX 8 #elif TU_CHECK_MCU(OPT_MCU_MSP432E4, OPT_MCU_TM4C123, OPT_MCU_TM4C129) #define TUP_USBIP_MUSB #define TUP_USBIP_MUSB_TI - #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_DCD_ENDPOINT_MAX 8 //--------------------------------------------------------------------+ // ValentyUSB (Litex) //--------------------------------------------------------------------+ #elif TU_CHECK_MCU(OPT_MCU_VALENTYUSB_EPTRI) - #define TUP_DCD_ENDPOINT_MAX 16 + #define TUP_DCD_ENDPOINT_MAX 16 //--------------------------------------------------------------------+ // Nuvoton //--------------------------------------------------------------------+ #elif TU_CHECK_MCU(OPT_MCU_NUC121, OPT_MCU_NUC126) - #define TUP_DCD_ENDPOINT_MAX 8 - #define TUP_DCD_EDPT_ISO_ALLOC + #define TUP_DCD_ENDPOINT_MAX 8 #elif TU_CHECK_MCU(OPT_MCU_NUC120) - #define TUP_DCD_ENDPOINT_MAX 6 - #define TUP_DCD_EDPT_ISO_ALLOC + #define TUP_DCD_ENDPOINT_MAX 6 #elif TU_CHECK_MCU(OPT_MCU_NUC505) - #define TUP_DCD_ENDPOINT_MAX 12 - #define TUP_RHPORT_HIGHSPEED 1 - #define TUP_DCD_EDPT_ISO_ALLOC + #define TUP_DCD_ENDPOINT_MAX 12 + #define TUP_RHPORT_HIGHSPEED 1 //--------------------------------------------------------------------+ // Espressif @@ -410,114 +406,124 @@ #elif TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3, OPT_MCU_ESP32H4) #define TUP_USBIP_DWC2 #define TUP_USBIP_DWC2_ESP32 - #define TUP_DCD_ENDPOINT_MAX 7 // only 5 TX FIFO for endpoint IN - #define CFG_TUSB_OS_INC_PATH_DEFAULT freertos/ + #define TUP_DCD_ENDPOINT_MAX 7 // only 5 TX FIFO for endpoint IN + + // clang-format off + #define CFG_TUSB_OS_INC_PATH_DEFAULT freertos/ + // clang-format on #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 + #define CFG_TUD_DWC2_SLAVE_ENABLE_DEFAULT !CFG_TUD_DWC2_DMA_ENABLE + #define CFG_TUH_DWC2_SLAVE_ENABLE_DEFAULT !CFG_TUH_DWC2_DMA_ENABLE #elif TU_CHECK_MCU(OPT_MCU_ESP32P4) #define TUP_USBIP_DWC2 #define TUP_USBIP_DWC2_ESP32 - #define TUP_RHPORT_HIGHSPEED 1 // port0 FS, port1 HS - #define TUP_DCD_ENDPOINT_MAX 16 // FS 7 ep, HS 16 ep + #define TUP_RHPORT_HIGHSPEED 1 // port0 FS, port1 HS + #define TUP_DCD_ENDPOINT_MAX 16 // FS 7 ep, HS 16 ep - #define CFG_TUSB_OS_INC_PATH_DEFAULT freertos/ + // clang-format off + #define CFG_TUSB_OS_INC_PATH_DEFAULT freertos/ + // clang-format on - #define TUP_MCU_MULTIPLE_CORE 1 + #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 + #define CFG_TUD_DWC2_SLAVE_ENABLE_DEFAULT !CFG_TUD_DWC2_DMA_ENABLE + #define CFG_TUH_DWC2_SLAVE_ENABLE_DEFAULT !CFG_TUH_DWC2_DMA_ENABLE // 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_DEFAULT 64 + #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_DEFAULT 64 -#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) +#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" + #error "MCUs are only supported with CFG_TUH_MAX3421 enabled" #endif - #define TUP_DCD_ENDPOINT_MAX 0 - #define CFG_TUSB_OS_INC_PATH_DEFAULT freertos/ + #define TUP_DCD_ENDPOINT_MAX 0 + + // clang-format off + #define CFG_TUSB_OS_INC_PATH_DEFAULT freertos/ + // clang-format on + //--------------------------------------------------------------------+ // Dialog //--------------------------------------------------------------------+ #elif TU_CHECK_MCU(OPT_MCU_DA1469X) - #define TUP_DCD_ENDPOINT_MAX 4 + #define TUP_DCD_ENDPOINT_MAX 4 + #define TUP_DCD_EDPT_CLOSE_API //--------------------------------------------------------------------+ // Raspberry Pi //--------------------------------------------------------------------+ #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 TUP_DCD_ENDPOINT_MAX 16 + #define TUP_MCU_MULTIPLE_CORE 1 - #define TU_ATTR_FAST_FUNC __not_in_flash("tinyusb") + #define TU_ATTR_FAST_FUNC __not_in_flash("tinyusb") //--------------------------------------------------------------------+ // Silabs //--------------------------------------------------------------------+ #elif TU_CHECK_MCU(OPT_MCU_EFM32GG) #define TUP_USBIP_DWC2 - #define TUP_DCD_ENDPOINT_MAX 7 + #define TUP_DCD_ENDPOINT_MAX 7 //--------------------------------------------------------------------+ // Renesas //--------------------------------------------------------------------+ #elif TU_CHECK_MCU(OPT_MCU_RX63X, OPT_MCU_RX65X, OPT_MCU_RX72N, OPT_MCU_RAXXX) #define TUP_USBIP_RUSB2 - #define TUP_DCD_ENDPOINT_MAX 10 + #define TUP_DCD_ENDPOINT_MAX 10 //--------------------------------------------------------------------+ // GigaDevice //--------------------------------------------------------------------+ #elif TU_CHECK_MCU(OPT_MCU_GD32VF103) #define TUP_USBIP_DWC2 - #define TUP_DCD_ENDPOINT_MAX 4 + #define TUP_DCD_ENDPOINT_MAX 4 //--------------------------------------------------------------------+ // Broadcom //--------------------------------------------------------------------+ #elif TU_CHECK_MCU(OPT_MCU_BCM2711, OPT_MCU_BCM2835, OPT_MCU_BCM2837) #define TUP_USBIP_DWC2 - #define TUP_DCD_ENDPOINT_MAX 8 - #define TUP_RHPORT_HIGHSPEED 1 + #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_RHPORT_HIGHSPEED 1 //--------------------------------------------------------------------+ // Infineon //--------------------------------------------------------------------+ #elif TU_CHECK_MCU(OPT_MCU_XMC4000) #define TUP_USBIP_DWC2 - #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_DCD_ENDPOINT_MAX 8 //--------------------------------------------------------------------+ // BridgeTek //--------------------------------------------------------------------+ #elif TU_CHECK_MCU(OPT_MCU_FT90X) - #define TUP_DCD_ENDPOINT_MAX 8 - #define TUP_RHPORT_HIGHSPEED 1 + #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_RHPORT_HIGHSPEED 1 #define TUD_ENDPOINT_ONE_DIRECTION_ONLY #elif TU_CHECK_MCU(OPT_MCU_FT93X) - #define TUP_DCD_ENDPOINT_MAX 16 - #define TUP_RHPORT_HIGHSPEED 1 + #define TUP_DCD_ENDPOINT_MAX 16 + #define TUP_RHPORT_HIGHSPEED 1 #define TUD_ENDPOINT_ONE_DIRECTION_ONLY //--------------------------------------------------------------------+ // Allwinner //--------------------------------------------------------------------+ #elif TU_CHECK_MCU(OPT_MCU_F1C100S) - #define TUP_DCD_ENDPOINT_MAX 4 + #define TUP_DCD_ENDPOINT_MAX 4 //--------------------------------------------------------------------+ // WCH @@ -527,31 +533,31 @@ #define TUP_USBIP_WCH_USBFS #if !defined(CFG_TUD_WCH_USBIP_USBFS) - #define CFG_TUD_WCH_USBIP_USBFS 0 + #define CFG_TUD_WCH_USBIP_USBFS 0 #endif #if !defined(CFG_TUD_WCH_USBIP_USBHS) - #define CFG_TUD_WCH_USBIP_USBHS (CFG_TUD_WCH_USBIP_USBFS ? 0 : 1) + #define CFG_TUD_WCH_USBIP_USBHS (CFG_TUD_WCH_USBIP_USBFS ? 0 : 1) #endif - #define TUP_RHPORT_HIGHSPEED CFG_TUD_WCH_USBIP_USBHS - #define TUP_DCD_ENDPOINT_MAX (CFG_TUD_WCH_USBIP_USBHS ? 16 : 8) + #define TUP_RHPORT_HIGHSPEED CFG_TUD_WCH_USBIP_USBHS + #define TUP_DCD_ENDPOINT_MAX (CFG_TUD_WCH_USBIP_USBHS ? 16 : 8) #elif TU_CHECK_MCU(OPT_MCU_CH32V103) #define TUP_USBIP_WCH_USBFS #if !defined(CFG_TUD_WCH_USBIP_USBFS) - #define CFG_TUD_WCH_USBIP_USBFS 1 + #define CFG_TUD_WCH_USBIP_USBFS 1 #endif - #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_DCD_ENDPOINT_MAX 8 #elif TU_CHECK_MCU(OPT_MCU_CH32V20X) // 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 + #define CFG_TUH_WCH_USBIP_USBFS 1 #endif #define TUP_USBIP_FSDEV @@ -559,14 +565,14 @@ // default to FSDEV for device #if !defined(CFG_TUD_WCH_USBIP_USBFS) - #define CFG_TUD_WCH_USBIP_USBFS 0 + #define CFG_TUD_WCH_USBIP_USBFS 0 #endif #if !defined(CFG_TUD_WCH_USBIP_FSDEV) - #define CFG_TUD_WCH_USBIP_FSDEV (CFG_TUD_WCH_USBIP_USBFS ? 0 : 1) + #define CFG_TUD_WCH_USBIP_FSDEV (CFG_TUD_WCH_USBIP_USBFS ? 0 : 1) #endif - #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_DCD_ENDPOINT_MAX 8 #elif TU_CHECK_MCU(OPT_MCU_CH32V307) // v307 support both FS and HS, default to HS @@ -574,15 +580,15 @@ #define TUP_USBIP_WCH_USBFS #if !defined(CFG_TUD_WCH_USBIP_USBFS) - #define CFG_TUD_WCH_USBIP_USBFS 0 + #define CFG_TUD_WCH_USBIP_USBFS 0 #endif #if !defined(CFG_TUD_WCH_USBIP_USBHS) - #define CFG_TUD_WCH_USBIP_USBHS (CFG_TUD_WCH_USBIP_USBFS ? 0 : 1) + #define CFG_TUD_WCH_USBIP_USBHS (CFG_TUD_WCH_USBIP_USBFS ? 0 : 1) #endif - #define TUP_RHPORT_HIGHSPEED CFG_TUD_WCH_USBIP_USBHS - #define TUP_DCD_ENDPOINT_MAX (CFG_TUD_WCH_USBIP_USBHS ? 16 : 8) + #define TUP_RHPORT_HIGHSPEED CFG_TUD_WCH_USBIP_USBHS + #define TUP_DCD_ENDPOINT_MAX (CFG_TUD_WCH_USBIP_USBHS ? 16 : 8) //--------------------------------------------------------------------+ // Analog Devices @@ -590,8 +596,8 @@ #elif TU_CHECK_MCU(OPT_MCU_MAX32650, OPT_MCU_MAX32666, OPT_MCU_MAX32690, OPT_MCU_MAX78002) #define TUP_USBIP_MUSB #define TUP_USBIP_MUSB_ADI - #define TUP_DCD_ENDPOINT_MAX 12 - #define TUP_RHPORT_HIGHSPEED 1 + #define TUP_DCD_ENDPOINT_MAX 12 + #define TUP_RHPORT_HIGHSPEED 1 #define TUD_ENDPOINT_ONE_DIRECTION_ONLY //--------------------------------------------------------------------+ @@ -600,46 +606,44 @@ #elif TU_CHECK_MCU(OPT_MCU_AT32F403A_407) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_AT32 - #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_DCD_ENDPOINT_MAX 8 #elif TU_CHECK_MCU(OPT_MCU_AT32F413) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_AT32 - #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_DCD_ENDPOINT_MAX 8 #elif TU_CHECK_MCU(OPT_MCU_AT32F415) #define TUP_USBIP_DWC2 #define TUP_USBIP_DWC2_AT32 - #define TUP_DCD_ENDPOINT_MAX 4 + #define TUP_DCD_ENDPOINT_MAX 4 #elif TU_CHECK_MCU(OPT_MCU_AT32F435_437) #define TUP_USBIP_DWC2 #define TUP_USBIP_DWC2_AT32 - #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_DCD_ENDPOINT_MAX 8 #elif TU_CHECK_MCU(OPT_MCU_AT32F423) #define TUP_USBIP_DWC2 #define TUP_USBIP_DWC2_AT32 - #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_DCD_ENDPOINT_MAX 8 #elif TU_CHECK_MCU(OPT_MCU_AT32F402_405) #define TUP_USBIP_DWC2 #define TUP_USBIP_DWC2_AT32 - #define TUP_DCD_ENDPOINT_MAX 8 + #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 + #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 - #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_DCD_ENDPOINT_MAX 8 #endif @@ -649,7 +653,7 @@ #if defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 #ifndef CFG_TUH_MAX3421_ENDPOINT_TOTAL - #define CFG_TUH_MAX3421_ENDPOINT_TOTAL (8 + 4*(CFG_TUH_DEVICE_MAX-1)) + #define CFG_TUH_MAX3421_ENDPOINT_TOTAL (8 + 4 * (CFG_TUH_DEVICE_MAX - 1)) #endif #endif @@ -659,17 +663,17 @@ //--------------------------------------------------------------------+ #ifndef TUP_MCU_MULTIPLE_CORE -#define TUP_MCU_MULTIPLE_CORE 0 + #define TUP_MCU_MULTIPLE_CORE 0 #endif #if !defined(TUP_DCD_ENDPOINT_MAX) && defined(CFG_TUD_ENABLED) && CFG_TUD_ENABLED #warning "TUP_DCD_ENDPOINT_MAX is not defined for this MCU, default to 8" - #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_DCD_ENDPOINT_MAX 8 #endif // Default to fullspeed if not defined #ifndef TUP_RHPORT_HIGHSPEED - #define TUP_RHPORT_HIGHSPEED 0 + #define TUP_RHPORT_HIGHSPEED 0 #endif // fast function, normally mean placing function in SRAM @@ -677,8 +681,13 @@ #define TU_ATTR_FAST_FUNC #endif -// USBIP that support ISO alloc & activate API -#if defined(TUP_USBIP_DWC2) || defined(TUP_USBIP_FSDEV) || defined(TUP_USBIP_MUSB) +#if defined(TUP_USBIP_CHIPIDEA_FS) || defined(TUP_USBIP_IP3511) || defined(TUP_USBIP_RUSB2) || \ + (defined(TUP_USBIP_WCH_USBFS) && CFG_TUD_WCH_USBIP_USBFS) + #define TUP_DCD_EDPT_CLOSE_API +#endif + +// USBIP implement dcd_edpt_close() and does not support ISO alloc & activate API +#ifndef TUP_DCD_EDPT_CLOSE_API #define TUP_DCD_EDPT_ISO_ALLOC #endif diff --git a/src/device/dcd.h b/src/device/dcd.h index 1b0289280..353f836ee 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -171,7 +171,12 @@ void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr); // This API never calls with control endpoints, since it is auto cleared when receiving setup packet void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr); -#ifdef TUP_DCD_EDPT_ISO_ALLOC +#ifdef TUP_DCD_EDPT_CLOSE_API +// Close an endpoint. +void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr); + +#else + // Allocate packet buffer used by ISO endpoints // Some MCU need manual packet buffer allocation, we allocate the largest size to avoid clustering bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size); @@ -179,10 +184,6 @@ bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet // Configure and enable an ISO endpoint according to descriptor bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep); -#else -// Close an endpoint. -void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr); - #endif //--------------------------------------------------------------------+ diff --git a/src/portable/bridgetek/ft9xx/dcd_ft9xx.c b/src/portable/bridgetek/ft9xx/dcd_ft9xx.c index 34a8be3b6..6ed4be410 100644 --- a/src/portable/bridgetek/ft9xx/dcd_ft9xx.c +++ b/src/portable/bridgetek/ft9xx/dcd_ft9xx.c @@ -806,6 +806,20 @@ void dcd_edpt_close_all(uint8_t rhport) _ft9xx_reset_edpts(); } +bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { + (void)rhport; + (void)ep_addr; + (void)largest_packet_size; + return false; +} + +bool dcd_edpt_iso_activate(uint8_t rhport, const tusb_desc_endpoint_t *desc_ep) { + (void)rhport; + (void)desc_ep; + return false; +} + + // Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes) { @@ -1200,5 +1214,4 @@ void ft9xx_usbd_pm_ISR(void) } } } - #endif diff --git a/src/portable/chipidea/ci_fs/dcd_ci_fs.c b/src/portable/chipidea/ci_fs/dcd_ci_fs.c index 11ddb683f..8b5c42aa2 100644 --- a/src/portable/chipidea/ci_fs/dcd_ci_fs.c +++ b/src/portable/chipidea/ci_fs/dcd_ci_fs.c @@ -399,6 +399,7 @@ void dcd_edpt_close_all(uint8_t rhport) } } +#ifdef TUP_DCD_EDPT_CLOSE_API void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) { const unsigned epn = tu_edpt_number(ep_addr); @@ -419,6 +420,22 @@ void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) dcd_int_enable(rhport); } +#else + +bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { + (void) rhport; + (void) ep_addr; + (void) largest_packet_size; + return false; +} + +bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep) { + (void) rhport; + (void) desc_ep; + return false; +} +#endif + bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) { const unsigned epn = tu_edpt_number(ep_addr); @@ -564,5 +581,4 @@ void dcd_int_handler(uint8_t rhport) process_tokdne(rhport); } } - #endif diff --git a/src/portable/chipidea/ci_hs/dcd_ci_hs.c b/src/portable/chipidea/ci_hs/dcd_ci_hs.c index 244f5a2d4..8c5253eb9 100644 --- a/src/portable/chipidea/ci_hs/dcd_ci_hs.c +++ b/src/portable/chipidea/ci_hs/dcd_ci_hs.c @@ -64,16 +64,19 @@ bool dcd_dcache_clean_invalidate(void const* addr, uint32_t data_size) { //--------------------------------------------------------------------+ // ENDPTCTRL +enum { + ENDPTCTRL_TYPE_POS = 2, // Endpoint type is 2-bit field +}; + enum { ENDPTCTRL_STALL = TU_BIT(0), ENDPTCTRL_TOGGLE_INHIBIT = TU_BIT(5), // used for test only ENDPTCTRL_TOGGLE_RESET = TU_BIT(6), - ENDPTCTRL_ENABLE = TU_BIT(7) + ENDPTCTRL_ENABLE = TU_BIT(7), }; -enum { - ENDPTCTRL_TYPE_POS = 2, // Endpoint type is 2-bit field -}; +#define ENDPTCTRL_TYPE(_type) ((_type) << ENDPTCTRL_TYPE_POS) + #define ENDPTCTRL_RESET_MASK (ENDPTCTRL_TYPE(TUSB_XFER_BULK) | (ENDPTCTRL_TYPE(TUSB_XFER_BULK) << 16u)) // USBSTS, USBINTR enum { @@ -170,9 +173,7 @@ static dcd_data_t _dcd_data; // Prototypes and Helper Functions //--------------------------------------------------------------------+ -TU_ATTR_ALWAYS_INLINE -static inline uint8_t ci_ep_count(ci_hs_regs_t const* dcd_reg) -{ +TU_ATTR_ALWAYS_INLINE static inline uint8_t ci_ep_count(const ci_hs_regs_t *dcd_reg) { return dcd_reg->DCCPARAMS & DCCPARAMS_DEN_MASK; } @@ -191,9 +192,8 @@ static void bus_reset(uint8_t rhport) // type (e.g. bulk). Leaving an un-configured endpoint control will cause undefined behavior // for the data PID tracking on the active endpoint. uint8_t const ep_count = ci_ep_count(dcd_reg); - for( uint8_t i=1; i < ep_count; i++) - { - dcd_reg->ENDPTCTRL[i] = (TUSB_XFER_BULK << ENDPTCTRL_TYPE_POS) | (TUSB_XFER_BULK << (16+ENDPTCTRL_TYPE_POS)); + for (uint8_t i = 1; i < ep_count; i++) { + dcd_reg->ENDPTCTRL[i] = ENDPTCTRL_RESET_MASK; } //------------- Clear All Registers -------------// @@ -315,26 +315,25 @@ void dcd_sof_enable(uint8_t rhport, bool en) // HELPER //--------------------------------------------------------------------+ -static void qtd_init(dcd_qtd_t* p_qtd, void * data_ptr, uint16_t total_bytes) -{ - dcd_dcache_clean_invalidate((uint32_t*) tu_align((uint32_t) data_ptr, 4), total_bytes); +static void qtd_init(dcd_qtd_t *p_qtd, void *data_ptr, uint16_t total_bytes) { + dcd_dcache_clean_invalidate((uint32_t *)tu_align((uint32_t)data_ptr, 4), total_bytes); tu_memclr(p_qtd, sizeof(dcd_qtd_t)); - p_qtd->next = QTD_NEXT_INVALID; - p_qtd->active = 1; - p_qtd->total_bytes = p_qtd->expected_bytes = total_bytes; - p_qtd->int_on_complete = true; + p_qtd->next = QTD_NEXT_INVALID; + p_qtd->active = 1; + p_qtd->total_bytes = p_qtd->expected_bytes = total_bytes; + p_qtd->int_on_complete = true; - if (data_ptr != NULL) - { - p_qtd->buffer[0] = (uint32_t) data_ptr; + if (data_ptr != NULL) { + p_qtd->buffer[0] = (uint32_t)data_ptr; - uint32_t const bufend = p_qtd->buffer[0] + total_bytes; - for(uint8_t i=1; i<5; i++) - { - uint32_t const next_page = tu_align4k( p_qtd->buffer[i-1] ) + 4096; - if ( bufend <= next_page ) break; + const uint32_t bufend = p_qtd->buffer[0] + total_bytes; + for (uint8_t i = 1; i < 5; i++) { + const uint32_t next_page = tu_align4k(p_qtd->buffer[i - 1]) + 4096; + if (bufend <= next_page) { + break; + } p_qtd->buffer[i] = next_page; @@ -346,6 +345,35 @@ static void qtd_init(dcd_qtd_t* p_qtd, void * data_ptr, uint16_t total_bytes) //--------------------------------------------------------------------+ // DCD Endpoint Port //--------------------------------------------------------------------+ +TU_ATTR_ALWAYS_INLINE static inline void ep_ctrl_write(volatile uint32_t *epctrl, uint8_t dir, uint32_t value) { + if (dir == TUSB_DIR_OUT) { + *epctrl = (*epctrl & 0xFFFF0000u) | value; + } else { + *epctrl = (*epctrl & 0x0000FFFFu) | (value << 16); + } +} + +TU_ATTR_ALWAYS_INLINE static inline void ep_ctrl_mask(volatile uint32_t *epctrl, uint8_t dir, uint32_t and_mask, + uint32_t or_mask) { + uint32_t value = *epctrl; + if (and_mask != 0) { + value &= (dir == TUSB_DIR_OUT) ? and_mask : (and_mask << 16u); + } + if (or_mask != 0) { + value |= (dir == TUSB_DIR_OUT) ? or_mask : (or_mask << 16u); + } + + *epctrl = value; +} + +TU_ATTR_ALWAYS_INLINE static inline void ep_ctrl_set(volatile uint32_t *epctrl, uint8_t dir, uint32_t mask) { + ep_ctrl_mask(epctrl, dir, 0, mask); +} + +TU_ATTR_ALWAYS_INLINE static inline void ep_ctrl_clear(volatile uint32_t *epctrl, uint8_t dir, uint32_t mask) { + ep_ctrl_mask(epctrl, dir, ~mask, 0); +} + void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { uint8_t const epnum = tu_edpt_number(ep_addr); @@ -366,80 +394,91 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) // data toggle also need to be reset ci_hs_regs_t* dcd_reg = CI_HS_REG(rhport); dcd_reg->ENDPTCTRL[epnum] |= ENDPTCTRL_TOGGLE_RESET << ( dir ? 16 : 0 ); - dcd_reg->ENDPTCTRL[epnum] &= ~(ENDPTCTRL_STALL << ( dir ? 16 : 0)); + dcd_reg->ENDPTCTRL[epnum] &= ~(ENDPTCTRL_STALL << (dir ? 16 : 0)); } -bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) -{ - uint8_t const epnum = tu_edpt_number(p_endpoint_desc->bEndpointAddress); - uint8_t const dir = tu_edpt_dir(p_endpoint_desc->bEndpointAddress); - - ci_hs_regs_t* dcd_reg = CI_HS_REG(rhport); - - // Must not exceed max endpoint number - TU_ASSERT(epnum < ci_ep_count(dcd_reg)); - - //------------- Prepare Queue Head -------------// - dcd_qhd_t * p_qhd = &_dcd_data.qhd[epnum][dir]; +static void qhd_init(dcd_qhd_t *p_qhd, uint16_t max_packet_size, uint8_t iso_mult) { tu_memclr(p_qhd, sizeof(dcd_qhd_t)); - p_qhd->zero_length_termination = 1; - p_qhd->max_packet_size = tu_edpt_packet_size(p_endpoint_desc); - if (p_endpoint_desc->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS) - { - p_qhd->iso_mult = 1; - } - + p_qhd->max_packet_size = max_packet_size; + p_qhd->iso_mult = iso_mult; p_qhd->qtd_overlay.next = QTD_NEXT_INVALID; - dcd_dcache_clean_invalidate(&_dcd_data, sizeof(dcd_data_t)); +} - // Enable EP Control - uint32_t const epctrl = (p_endpoint_desc->bmAttributes.xfer << ENDPTCTRL_TYPE_POS) | ENDPTCTRL_ENABLE | ENDPTCTRL_TOGGLE_RESET; +bool dcd_edpt_open(uint8_t rhport, const tusb_desc_endpoint_t *endpoint_desc) { + ci_hs_regs_t *dcd_reg = CI_HS_REG(rhport); + const uint8_t epnum = tu_edpt_number(endpoint_desc->bEndpointAddress); + const uint8_t dir = tu_edpt_dir(endpoint_desc->bEndpointAddress); + const uint8_t xfer_type = endpoint_desc->bmAttributes.xfer; + TU_ASSERT(epnum < ci_ep_count(dcd_reg)); - if ( dir == TUSB_DIR_OUT ) - { - dcd_reg->ENDPTCTRL[epnum] = (dcd_reg->ENDPTCTRL[epnum] & 0xFFFF0000u) | epctrl; - }else - { - dcd_reg->ENDPTCTRL[epnum] = (dcd_reg->ENDPTCTRL[epnum] & 0x0000FFFFu) | (epctrl << 16); - } + dcd_qhd_t *p_qhd = &_dcd_data.qhd[epnum][dir]; + qhd_init(p_qhd, tu_edpt_packet_size(endpoint_desc), 0u); + + // EP Control + const uint32_t epctrl = ENDPTCTRL_TYPE(xfer_type) | ENDPTCTRL_ENABLE | ENDPTCTRL_TOGGLE_RESET; + ep_ctrl_write(&dcd_reg->ENDPTCTRL[epnum], dir, epctrl); return true; } -void dcd_edpt_close_all (uint8_t rhport) -{ - ci_hs_regs_t* dcd_reg = CI_HS_REG(rhport); +bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { + (void)rhport; + (void)ep_addr; + (void)largest_packet_size; - // Disable all non-control endpoints - uint8_t const ep_count = ci_ep_count(dcd_reg); - for (uint8_t epnum = 1; epnum < ep_count; epnum++) - { - _dcd_data.qhd[epnum][TUSB_DIR_OUT].qtd_overlay.halted = 1; - _dcd_data.qhd[epnum][TUSB_DIR_IN ].qtd_overlay.halted = 1; + ci_hs_regs_t *dcd_reg = CI_HS_REG(rhport); + const uint8_t epnum = tu_edpt_number(ep_addr); + const uint8_t dir = tu_edpt_dir(ep_addr); + TU_ASSERT(epnum < ci_ep_count(dcd_reg)); - dcd_reg->ENDPTFLUSH = TU_BIT(epnum) | TU_BIT(epnum+16); - dcd_reg->ENDPTCTRL[epnum] = (TUSB_XFER_BULK << ENDPTCTRL_TYPE_POS) | (TUSB_XFER_BULK << (16+ENDPTCTRL_TYPE_POS)); - } + // EP Control: set type but not enabled yet + const uint32_t epctrl = ENDPTCTRL_TYPE(TUSB_XFER_ISOCHRONOUS) | ENDPTCTRL_TOGGLE_RESET; + ep_ctrl_write(&dcd_reg->ENDPTCTRL[epnum], dir, epctrl); + + return true; } -void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) -{ - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); +bool dcd_edpt_iso_activate(uint8_t rhport, const tusb_desc_endpoint_t *desc_ep) { + const uint8_t epnum = tu_edpt_number(desc_ep->bEndpointAddress); + const uint8_t dir = tu_edpt_dir(desc_ep->bEndpointAddress); + ci_hs_regs_t *dcd_reg = CI_HS_REG(rhport); + TU_ASSERT(epnum < ci_ep_count(dcd_reg)); - ci_hs_regs_t* dcd_reg = CI_HS_REG(rhport); + dcd_qhd_t *p_qhd = &_dcd_data.qhd[epnum][dir]; + volatile uint32_t *endptctrl = &dcd_reg->ENDPTCTRL[epnum]; - _dcd_data.qhd[epnum][dir].qtd_overlay.halted = 1; + // _dcd_data.qhd[epnum][dir].qtd_overlay.halted = 1; + // dcd_dcache_clean_invalidate(&_dcd_data, sizeof(dcd_data_t)); // Flush EP - uint32_t const flush_mask = TU_BIT(epnum + (dir ? 16 : 0)); - dcd_reg->ENDPTFLUSH = flush_mask; - while(dcd_reg->ENDPTFLUSH & flush_mask); + const uint32_t flush_mask = TU_BIT(epnum + (dir ? 16 : 0)); + dcd_reg->ENDPTFLUSH = flush_mask; + while (dcd_reg->ENDPTFLUSH & flush_mask) {} + + // disable to change max packet size + ep_ctrl_clear(endptctrl, dir, ENDPTCTRL_ENABLE); - // Clear EP enable - dcd_reg->ENDPTCTRL[epnum] &=~(ENDPTCTRL_ENABLE << (dir ? 16 : 0)); + qhd_init(p_qhd, tu_edpt_packet_size(desc_ep), 1u); + + ep_ctrl_set(endptctrl, dir, ENDPTCTRL_ENABLE); + + return true; +} + +void dcd_edpt_close_all(uint8_t rhport) { + ci_hs_regs_t *dcd_reg = CI_HS_REG(rhport); + + // Disable all non-control endpoints + uint8_t const ep_count = ci_ep_count(dcd_reg); + for (uint8_t epnum = 1; epnum < ep_count; epnum++) { + _dcd_data.qhd[epnum][TUSB_DIR_OUT].qtd_overlay.halted = 1; + _dcd_data.qhd[epnum][TUSB_DIR_IN].qtd_overlay.halted = 1; + + dcd_reg->ENDPTFLUSH = TU_BIT(epnum) | TU_BIT(epnum + 16); + dcd_reg->ENDPTCTRL[epnum] = ENDPTCTRL_RESET_MASK; + } } static void qhd_start_xfer(uint8_t rhport, uint8_t epnum, uint8_t dir) @@ -678,5 +717,4 @@ void dcd_int_handler(uint8_t rhport) dcd_event_sof(rhport, frame, true); } } - #endif diff --git a/src/portable/dialog/da146xx/dcd_da146xx.c b/src/portable/dialog/da146xx/dcd_da146xx.c index 56ecb7575..868a10dd9 100644 --- a/src/portable/dialog/da146xx/dcd_da146xx.c +++ b/src/portable/dialog/da146xx/dcd_da146xx.c @@ -1025,6 +1025,21 @@ void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) tu_memclr(xfer, sizeof(*xfer)); } +#if 0 +bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { + (void) rhport; + (void) ep_addr; + (void) largest_packet_size; + return false; +} + +bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep) { + (void) rhport; + (void) desc_ep; + return false; +} +#endif + 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); @@ -1218,5 +1233,4 @@ void dcd_int_handler(uint8_t rhport) handle_alt_ev(); } } - #endif diff --git a/src/portable/microchip/pic/dcd_pic.c b/src/portable/microchip/pic/dcd_pic.c index b4a698199..8413a7ddd 100644 --- a/src/portable/microchip/pic/dcd_pic.c +++ b/src/portable/microchip/pic/dcd_pic.c @@ -687,6 +687,21 @@ void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) if (ie) intr_enable(rhport); } +#if 0 +bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { + (void) rhport; + (void) ep_addr; + (void) largest_packet_size; + return false; +} + +bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep) { + (void) rhport; + (void) desc_ep; + return false; +} +#endif + bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) { @@ -866,5 +881,4 @@ void dcd_int_handler(uint8_t rhport) intr_clear(rhport); } - #endif diff --git a/src/portable/microchip/pic32mz/dcd_pic32mz.c b/src/portable/microchip/pic32mz/dcd_pic32mz.c index cbd157d6b..b039bb505 100644 --- a/src/portable/microchip/pic32mz/dcd_pic32mz.c +++ b/src/portable/microchip/pic32mz/dcd_pic32mz.c @@ -438,12 +438,20 @@ void dcd_edpt_close_all (uint8_t rhport) } } -void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) -{ +bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { (void) rhport; (void) ep_addr; + (void)largest_packet_size; + return false; +} + +bool dcd_edpt_iso_activate(uint8_t rhport, const tusb_desc_endpoint_t *desc_ep) { + (void)rhport; + (void)desc_ep; + return false; } + 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); @@ -744,5 +752,4 @@ void dcd_int_handler(uint8_t rhport) } } } - #endif diff --git a/src/portable/microchip/samd/dcd_samd.c b/src/portable/microchip/samd/dcd_samd.c index e43439f2a..383cf60e5 100644 --- a/src/portable/microchip/samd/dcd_samd.c +++ b/src/portable/microchip/samd/dcd_samd.c @@ -245,11 +245,17 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) return true; } -void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) { +bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { (void) rhport; (void) ep_addr; + (void)largest_packet_size; + return false; +} - // TODO: implement if necessary? +bool dcd_edpt_iso_activate(uint8_t rhport, const tusb_desc_endpoint_t *desc_ep) { + (void)rhport; + (void)desc_ep; + return false; } void dcd_edpt_close_all (uint8_t rhport) @@ -427,5 +433,4 @@ void dcd_int_handler (uint8_t rhport) // Handle complete transfer maybe_transfer_complete(); } - #endif diff --git a/src/portable/microchip/samg/dcd_samg.c b/src/portable/microchip/samg/dcd_samg.c index a5c768839..879b2eb2b 100644 --- a/src/portable/microchip/samg/dcd_samg.c +++ b/src/portable/microchip/samg/dcd_samg.c @@ -270,9 +270,17 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) return true; } -void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) { - (void) rhport; (void) ep_addr; - // TODO implement dcd_edpt_close() +bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { + (void)rhport; + (void)ep_addr; + (void)largest_packet_size; + return false; +} + +bool dcd_edpt_iso_activate(uint8_t rhport, const tusb_desc_endpoint_t *desc_ep) { + (void)rhport; + (void)desc_ep; + return false; } void dcd_edpt_close_all (uint8_t rhport) @@ -494,5 +502,4 @@ void dcd_int_handler(uint8_t rhport) } } } - #endif diff --git a/src/portable/microchip/samx7x/dcd_samx7x.c b/src/portable/microchip/samx7x/dcd_samx7x.c index 8aec1568d..51308f7a2 100644 --- a/src/portable/microchip/samx7x/dcd_samx7x.c +++ b/src/portable/microchip/samx7x/dcd_samx7x.c @@ -559,15 +559,17 @@ void dcd_edpt_close_all (uint8_t rhport) // TODO implement dcd_edpt_close_all() } -void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) -{ +bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { (void) rhport; - uint8_t const epnum = tu_edpt_number(ep_addr); + (void) ep_addr; + (void) largest_packet_size; + return false; +} - // Disable endpoint interrupt - USB_REG->DEVIDR = 1 << (DEVIDR_PEP_0_Pos + epnum); - // Disable EP - USB_REG->DEVEPT &=~(1 << (DEVEPT_EPEN0_Pos + epnum)); +bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep) { + (void) rhport; + (void) desc_ep; + return false; } static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix) @@ -773,5 +775,4 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) USB_REG->DEVEPTIDR[epnum] = DEVEPTIDR_CTRL_STALLRQC; USB_REG->DEVEPTIER[epnum] = HSTPIPIER_RSTDTS; } - #endif diff --git a/src/portable/mindmotion/mm32/dcd_mm32f327x_otg.c b/src/portable/mindmotion/mm32/dcd_mm32f327x_otg.c index 1ce3da27e..a232810a2 100644 --- a/src/portable/mindmotion/mm32/dcd_mm32f327x_otg.c +++ b/src/portable/mindmotion/mm32/dcd_mm32f327x_otg.c @@ -26,7 +26,7 @@ #include "tusb_option.h" -#if CFG_TUD_ENABLED && ( CFG_TUSB_MCU == OPT_MCU_MM32F327X ) +#if CFG_TUD_ENABLED && (CFG_TUSB_MCU == OPT_MCU_MM32F327X) #include "reg_usb_otg_fs.h" #include "mm32_device.h" @@ -43,56 +43,53 @@ enum { TOK_PID_SETUP = 0xDu, }; -typedef struct TU_ATTR_PACKED -{ +typedef struct TU_ATTR_PACKED { union { uint32_t head; struct { union { struct { - uint16_t : 2; - uint16_t tok_pid : 4; - uint16_t data : 1; - uint16_t own : 1; - uint16_t : 8; + uint16_t : 2; + uint16_t tok_pid : 4; + uint16_t data : 1; + uint16_t own : 1; + uint16_t : 8; }; struct { - uint16_t : 2; - uint16_t bdt_stall: 1; - uint16_t dts : 1; - uint16_t ninc : 1; - uint16_t keep : 1; - uint16_t : 10; + uint16_t : 2; + uint16_t bdt_stall : 1; + uint16_t dts : 1; + uint16_t ninc : 1; + uint16_t keep : 1; + uint16_t : 10; }; }; - uint16_t bc : 10; - uint16_t : 6; + uint16_t bc : 10; + uint16_t : 6; }; }; uint8_t *addr; -}buffer_descriptor_t; +} buffer_descriptor_t; -TU_VERIFY_STATIC( sizeof(buffer_descriptor_t) == 8, "size is not correct" ); +TU_VERIFY_STATIC(sizeof(buffer_descriptor_t) == 8, "size is not correct"); -typedef struct TU_ATTR_PACKED -{ +typedef struct TU_ATTR_PACKED { union { uint32_t state; struct { - uint32_t max_packet_size :11; + uint32_t max_packet_size : 11; uint32_t : 5; uint32_t odd : 1; - uint32_t :15; + uint32_t : 15; }; }; uint16_t length; uint16_t remaining; -}endpoint_state_t; +} endpoint_state_t; -TU_VERIFY_STATIC( sizeof(endpoint_state_t) == 8, "size is not correct" ); +TU_VERIFY_STATIC(sizeof(endpoint_state_t) == 8, "size is not correct"); -typedef struct -{ +typedef struct { union { /* [#EP][OUT,IN][EVEN,ODD] */ buffer_descriptor_t bdt[16][2][2]; @@ -104,7 +101,7 @@ typedef struct }; uint8_t setup_packet[8]; uint8_t addr; -}dcd_data_t; +} dcd_data_t; //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION @@ -112,10 +109,9 @@ typedef struct // BDT(Buffer Descriptor Table) must be 256-byte aligned CFG_TUD_MEM_SECTION TU_ATTR_ALIGNED(512) static dcd_data_t _dcd; -TU_VERIFY_STATIC( sizeof(_dcd.bdt) == 512, "size is not correct" ); +TU_VERIFY_STATIC(sizeof(_dcd.bdt) == 512, "size is not correct"); -static void prepare_next_setup_packet(uint8_t rhport) -{ +static void prepare_next_setup_packet(uint8_t rhport) { const unsigned out_odd = _dcd.endpoint[0][0].odd; const unsigned in_odd = _dcd.endpoint[0][1].odd; if (_dcd.bdt[0][0][out_odd].own) { @@ -126,12 +122,10 @@ static void prepare_next_setup_packet(uint8_t rhport) _dcd.bdt[0][0][out_odd ^ 1].data = 1; _dcd.bdt[0][1][in_odd].data = 1; _dcd.bdt[0][1][in_odd ^ 1].data = 0; - dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_OUT), - _dcd.setup_packet, sizeof(_dcd.setup_packet)); + dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_OUT), _dcd.setup_packet, sizeof(_dcd.setup_packet)); } -static void process_stall(uint8_t rhport) -{ +static void process_stall(uint8_t rhport) { if (USB_OTG_FS->EP_CTL[0] & USB_ENDPT_EPSTALL_MASK) { /* clear stall condition of the control pipe */ prepare_next_setup_packet(rhport); @@ -139,13 +133,12 @@ static void process_stall(uint8_t rhport) } } -static void process_tokdne(uint8_t rhport) -{ - const unsigned s = USB_OTG_FS->STAT; - USB_OTG_FS->INT_STAT = USB_ISTAT_TOKDNE_MASK; /* fetch the next token if received */ - buffer_descriptor_t *bd = (buffer_descriptor_t *)&_dcd.bda[s]; - endpoint_state_t *ep = &_dcd.endpoint_unified[s >> 3]; - unsigned odd = (s & USB_STAT_ODD_MASK) ? 1 : 0; +static void process_tokdne(uint8_t rhport) { + const unsigned s = USB_OTG_FS->STAT; + USB_OTG_FS->INT_STAT = USB_ISTAT_TOKDNE_MASK; /* fetch the next token if received */ + buffer_descriptor_t *bd = (buffer_descriptor_t *)&_dcd.bda[s]; + endpoint_state_t *ep = &_dcd.endpoint_unified[s >> 3]; + unsigned odd = (s & USB_STAT_ODD_MASK) ? 1 : 0; /* fetch pid before discarded by the next steps */ const unsigned pid = bd->tok_pid; @@ -155,7 +148,7 @@ static void process_tokdne(uint8_t rhport) bd->ninc = 0; bd->keep = 0; /* update the odd variable to prepare for the next transfer */ - ep->odd = odd ^ 1; + ep->odd = odd ^ 1; if (pid == TOK_PID_SETUP) { dcd_event_setup_received(rhport, bd->addr, true); USB_OTG_FS->CTL &= ~USB_CTL_TXSUSPENDTOKENBUSY_MASK; @@ -165,25 +158,24 @@ static void process_tokdne(uint8_t rhport) TU_LOG1("TKDNE %x\r\n", s); } - const unsigned bc = bd->bc; + const unsigned bc = bd->bc; const unsigned remaining = ep->remaining - bc; if (remaining && bc == ep->max_packet_size) { /* continue the transferring consecutive data */ - ep->remaining = remaining; + ep->remaining = remaining; const int next_remaining = remaining - ep->max_packet_size; if (next_remaining > 0) { /* prepare to the after next transfer */ bd->addr += ep->max_packet_size * 2; - bd->bc = next_remaining > ep->max_packet_size ? ep->max_packet_size: next_remaining; + bd->bc = next_remaining > ep->max_packet_size ? ep->max_packet_size : next_remaining; __DSB(); - bd->own = 1; /* the own bit must set after addr */ + bd->own = 1; /* the own bit must set after addr */ } return; } const unsigned length = ep->length; - dcd_event_xfer_complete(rhport, - ((s & USB_STAT_TX_MASK) << 4) | (s >> USB_STAT_ENDP_SHIFT), - length - remaining, XFER_RESULT_SUCCESS, true); + dcd_event_xfer_complete(rhport, ((s & USB_STAT_TX_MASK) << 4) | (s >> USB_STAT_ENDP_SHIFT), length - remaining, + XFER_RESULT_SUCCESS, true); if (0 == (s & USB_STAT_ENDP_MASK) && 0 == length) { /* After completion a ZLP of control transfer, * it prepares for the next steup transfer. */ @@ -191,24 +183,23 @@ static void process_tokdne(uint8_t rhport) /* When the transfer was the SetAddress, * the device address should be updated here. */ USB_OTG_FS->ADDR = _dcd.addr; - _dcd.addr = 0; + _dcd.addr = 0; } prepare_next_setup_packet(rhport); } } -static void process_bus_reset(uint8_t rhport) -{ - USB_OTG_FS->CTL |= USB_CTL_ODDRST_MASK; - USB_OTG_FS->ADDR = 0; - USB_OTG_FS->INT_ENB = (USB_OTG_FS->INT_ENB & ~USB_INTEN_RESUMEEN_MASK) | USB_INTEN_SLEEPEN_MASK; +static void process_bus_reset(uint8_t rhport) { + USB_OTG_FS->CTL |= USB_CTL_ODDRST_MASK; + USB_OTG_FS->ADDR = 0; + USB_OTG_FS->INT_ENB = (USB_OTG_FS->INT_ENB & ~USB_INTEN_RESUMEEN_MASK) | USB_INTEN_SLEEPEN_MASK; USB_OTG_FS->EP_CTL[0] = USB_ENDPT_EPHSHK_MASK | USB_ENDPT_EPRXEN_MASK | USB_ENDPT_EPTXEN_MASK; for (unsigned i = 1; i < 16; ++i) { USB_OTG_FS->EP_CTL[i] = 0; } buffer_descriptor_t *bd = _dcd.bdt[0][0]; - for (unsigned i = 0; i < sizeof(_dcd.bdt)/sizeof(*bd); ++i, ++bd) { + for (unsigned i = 0; i < sizeof(_dcd.bdt) / sizeof(*bd); ++i, ++bd) { bd->head = 0; } const endpoint_state_t ep0 = { @@ -226,31 +217,29 @@ static void process_bus_reset(uint8_t rhport) dcd_event_bus_reset(rhport, TUSB_SPEED_FULL, true); } -static void process_bus_inactive(uint8_t rhport) -{ - (void) rhport; +static void process_bus_inactive(uint8_t rhport) { + (void)rhport; const unsigned inten = USB_OTG_FS->INT_ENB; - USB_OTG_FS->INT_ENB = (inten & ~USB_INTEN_SLEEPEN_MASK) | USB_INTEN_RESUMEEN_MASK; + USB_OTG_FS->INT_ENB = (inten & ~USB_INTEN_SLEEPEN_MASK) | USB_INTEN_RESUMEEN_MASK; dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true); } -static void process_bus_active(uint8_t rhport) -{ - (void) rhport; +static void process_bus_active(uint8_t rhport) { + (void)rhport; const unsigned inten = USB_OTG_FS->INT_ENB; - USB_OTG_FS->INT_ENB = (inten & ~USB_INTEN_RESUMEEN_MASK) | USB_INTEN_SLEEPEN_MASK; + USB_OTG_FS->INT_ENB = (inten & ~USB_INTEN_RESUMEEN_MASK) | USB_INTEN_SLEEPEN_MASK; dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true); } /*------------------------------------------------------------------*/ /* Device API *------------------------------------------------------------------*/ -bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { - (void) rhport; - (void) rh_init; +bool dcd_init(uint8_t rhport, const tusb_rhport_init_t *rh_init) { + (void)rhport; + (void)rh_init; tu_memclr(&_dcd, sizeof(_dcd)); - USB_OTG_FS->BDT_PAGE_01 = (uint8_t)((uintptr_t)_dcd.bdt >> 8); + USB_OTG_FS->BDT_PAGE_01 = (uint8_t)((uintptr_t)_dcd.bdt >> 8); USB_OTG_FS->BDT_PAGE_02 = (uint8_t)((uintptr_t)_dcd.bdt >> 16); USB_OTG_FS->BDT_PAGE_03 = (uint8_t)((uintptr_t)_dcd.bdt >> 24); @@ -259,27 +248,24 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { return true; } #define USB_DEVICE_INTERRUPT_PRIORITY (3U) -void dcd_int_enable(uint8_t rhport) -{ +void dcd_int_enable(uint8_t rhport) { uint8_t irqNumber; irqNumber = USB_FS_IRQn; - (void) rhport; - USB_OTG_FS->INT_ENB = USB_INTEN_USBRSTEN_MASK | USB_INTEN_TOKDNEEN_MASK | - USB_INTEN_SLEEPEN_MASK | USB_INTEN_ERROREN_MASK | USB_INTEN_STALLEN_MASK; + (void)rhport; + USB_OTG_FS->INT_ENB = USB_INTEN_USBRSTEN_MASK | USB_INTEN_TOKDNEEN_MASK | USB_INTEN_SLEEPEN_MASK | + USB_INTEN_ERROREN_MASK | USB_INTEN_STALLEN_MASK; NVIC_SetPriority((IRQn_Type)irqNumber, USB_DEVICE_INTERRUPT_PRIORITY); NVIC_EnableIRQ(USB_FS_IRQn); } -void dcd_int_disable(uint8_t rhport) -{ - (void) rhport; +void dcd_int_disable(uint8_t rhport) { + (void)rhport; NVIC_DisableIRQ(USB_FS_IRQn); USB_OTG_FS->INT_ENB = 0; } -void dcd_set_address(uint8_t rhport, uint8_t dev_addr) -{ - (void) rhport; +void dcd_set_address(uint8_t rhport, uint8_t dev_addr) { + (void)rhport; _dcd.addr = dev_addr & 0x7F; /* Response with status first before changing device address */ dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); @@ -296,31 +282,29 @@ extern u32 SystemCoreClock; #pragma GCC diagnostic pop #endif -void dcd_remote_wakeup(uint8_t rhport) -{ - (void) rhport; +void dcd_remote_wakeup(uint8_t rhport) { + (void)rhport; unsigned cnt = SystemCoreClock / 100; USB_OTG_FS->CTL |= USB_CTL_RESUME_MASK; - while (cnt--) __NOP(); + while (cnt--) { + __NOP(); + } USB_OTG_FS->CTL &= ~USB_CTL_RESUME_MASK; } -void dcd_connect(uint8_t rhport) -{ - (void) rhport; - USB_OTG_FS->CTL |= USB_CTL_USBENSOFEN_MASK; +void dcd_connect(uint8_t rhport) { + (void)rhport; + USB_OTG_FS->CTL |= USB_CTL_USBENSOFEN_MASK; } -void dcd_disconnect(uint8_t rhport) -{ - (void) rhport; - USB_OTG_FS->CTL = 0; +void dcd_disconnect(uint8_t rhport) { + (void)rhport; + USB_OTG_FS->CTL = 0; } -void dcd_sof_enable(uint8_t rhport, bool en) -{ - (void) rhport; - (void) en; +void dcd_sof_enable(uint8_t rhport, bool en) { + (void)rhport; + (void)en; // TODO implement later } @@ -328,24 +312,23 @@ void dcd_sof_enable(uint8_t rhport, bool en) //--------------------------------------------------------------------+ // Endpoint API //--------------------------------------------------------------------+ -bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) -{ - (void) rhport; - - const unsigned ep_addr = ep_desc->bEndpointAddress; - const unsigned epn = ep_addr & 0xFu; - const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; - const unsigned xfer = ep_desc->bmAttributes.xfer; - endpoint_state_t *ep = &_dcd.endpoint[epn][dir]; - const unsigned odd = ep->odd; - buffer_descriptor_t *bd = &_dcd.bdt[epn][dir][0]; +bool dcd_edpt_open(uint8_t rhport, const tusb_desc_endpoint_t *ep_desc) { + (void)rhport; + + const unsigned ep_addr = ep_desc->bEndpointAddress; + const unsigned epn = ep_addr & 0xFu; + const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; + const unsigned xfer = ep_desc->bmAttributes.xfer; + endpoint_state_t *ep = &_dcd.endpoint[epn][dir]; + const unsigned odd = ep->odd; + buffer_descriptor_t *bd = &_dcd.bdt[epn][dir][0]; /* No support for control transfer */ TU_ASSERT(epn && (xfer != TUSB_XFER_CONTROL)); ep->max_packet_size = tu_edpt_packet_size(ep_desc); - unsigned val = USB_ENDPT_EPCTLDIS_MASK; - val |= (xfer != TUSB_XFER_ISOCHRONOUS) ? USB_ENDPT_EPHSHK_MASK: 0; + unsigned val = USB_ENDPT_EPCTLDIS_MASK; + val |= (xfer != TUSB_XFER_ISOCHRONOUS) ? USB_ENDPT_EPHSHK_MASK : 0; val |= dir ? USB_ENDPT_EPTXEN_MASK : USB_ENDPT_EPRXEN_MASK; USB_OTG_FS->EP_CTL[epn] |= val; @@ -359,21 +342,19 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) return true; } -void dcd_edpt_close_all (uint8_t rhport) -{ - (void) rhport; +void dcd_edpt_close_all(uint8_t rhport) { + (void)rhport; // TODO implement dcd_edpt_close_all() } -void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) -{ - (void) rhport; +void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) { + (void)rhport; - const unsigned epn = ep_addr & 0xFu; - const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; - endpoint_state_t *ep = &_dcd.endpoint[epn][dir]; - buffer_descriptor_t *bd = &_dcd.bdt[epn][dir][0]; - const unsigned msk = dir ? USB_ENDPT_EPTXEN_MASK : USB_ENDPT_EPRXEN_MASK; + const unsigned epn = ep_addr & 0xFu; + const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; + endpoint_state_t *ep = &_dcd.endpoint[epn][dir]; + buffer_descriptor_t *bd = &_dcd.bdt[epn][dir][0]; + const unsigned msk = dir ? USB_ENDPT_EPTXEN_MASK : USB_ENDPT_EPRXEN_MASK; USB_OTG_FS->EP_CTL[epn] &= ~msk; ep->max_packet_size = 0; ep->length = 0; @@ -381,14 +362,28 @@ void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) bd->head = 0; } -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) -{ - (void) rhport; + #if 0 +bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { + (void)rhport; + (void)ep_addr; + (void)largest_packet_size; + return false; +} + +bool dcd_edpt_iso_activate(uint8_t rhport, const tusb_desc_endpoint_t *desc_ep) { + (void)rhport; + (void)desc_ep; + return false; +} + #endif + +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes) { + (void)rhport; NVIC_DisableIRQ(USB_FS_IRQn); - const unsigned epn = ep_addr & 0xFu; - const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; - endpoint_state_t *ep = &_dcd.endpoint[epn][dir]; - buffer_descriptor_t *bd = &_dcd.bdt[epn][dir][ep->odd]; + const unsigned epn = ep_addr & 0xFu; + const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; + endpoint_state_t *ep = &_dcd.endpoint[epn][dir]; + buffer_descriptor_t *bd = &_dcd.bdt[epn][dir][ep->odd]; if (bd->own) { TU_LOG1("DCD XFER fail %x %d %lx %lx\r\n", ep_addr, total_bytes, ep->state, bd->head); @@ -399,42 +394,40 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to const unsigned mps = ep->max_packet_size; if (total_bytes > mps) { - buffer_descriptor_t *next = ep->odd ? bd - 1: bd + 1; + buffer_descriptor_t *next = ep->odd ? bd - 1 : bd + 1; /* When total_bytes is greater than the max packet size, * it prepares to the next transfer to avoid NAK in advance. */ - next->bc = total_bytes >= 2 * mps ? mps: total_bytes - mps; + next->bc = total_bytes >= 2 * mps ? mps : total_bytes - mps; next->addr = buffer + mps; next->own = 1; } - bd->bc = total_bytes >= mps ? mps: total_bytes; - bd->addr = buffer; + bd->bc = total_bytes >= mps ? mps : total_bytes; + bd->addr = buffer; __DSB(); - bd->own = 1; /* the own bit must set after addr */ + bd->own = 1; /* the own bit must set after addr */ NVIC_EnableIRQ(USB_FS_IRQn); return true; } -void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) -{ - (void) rhport; +void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { + (void)rhport; const unsigned epn = ep_addr & 0xFu; if (0 == epn) { - USB_OTG_FS->EP_CTL[epn] |= USB_ENDPT_EPSTALL_MASK; + USB_OTG_FS->EP_CTL[epn] |= USB_ENDPT_EPSTALL_MASK; } else { - const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; - buffer_descriptor_t *bd = _dcd.bdt[epn][dir]; - bd[0].bdt_stall = 1; - bd[1].bdt_stall = 1; + const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; + buffer_descriptor_t *bd = _dcd.bdt[epn][dir]; + bd[0].bdt_stall = 1; + bd[1].bdt_stall = 1; } } -void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) -{ - (void) rhport; - const unsigned epn = ep_addr & 0xFu; - const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; - const unsigned odd = _dcd.endpoint[epn][dir].odd; - buffer_descriptor_t *bd = _dcd.bdt[epn][dir]; +void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { + (void)rhport; + const unsigned epn = ep_addr & 0xFu; + const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; + const unsigned odd = _dcd.endpoint[epn][dir].odd; + buffer_descriptor_t *bd = _dcd.bdt[epn][dir]; bd[odd ^ 1].own = 0; bd[odd ^ 1].data = 1; @@ -447,19 +440,18 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) //--------------------------------------------------------------------+ // ISR //--------------------------------------------------------------------+ -void dcd_int_handler(uint8_t rhport) -{ - (void) rhport; +void dcd_int_handler(uint8_t rhport) { + (void)rhport; - uint32_t is = USB_OTG_FS->INT_STAT; - uint32_t msk = USB_OTG_FS->INT_ENB; + uint32_t is = USB_OTG_FS->INT_STAT; + uint32_t msk = USB_OTG_FS->INT_ENB; USB_OTG_FS->INT_STAT = is & ~msk; is &= msk; if (is & USB_ISTAT_ERROR_MASK) { /* TODO: */ - uint32_t es = USB_OTG_FS->ERR_STAT; + uint32_t es = USB_OTG_FS->ERR_STAT; USB_OTG_FS->ERR_STAT = es; - USB_OTG_FS->INT_STAT = is; /* discard any pending events */ + USB_OTG_FS->INT_STAT = is; /* discard any pending events */ return; } @@ -493,5 +485,4 @@ void dcd_int_handler(uint8_t rhport) return; } } - #endif diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c index 9e5f5117f..730ca7fb1 100644 --- a/src/portable/nordic/nrf5x/dcd_nrf5x.c +++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c @@ -426,6 +426,21 @@ void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) { __DSB(); } +#if 0 +bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { + (void)rhport; + (void)ep_addr; + (void)largest_packet_size; + return false; +} + +bool dcd_edpt_iso_activate(uint8_t rhport, const tusb_desc_endpoint_t *desc_ep) { + (void)rhport; + (void)desc_ep; + return false; +} +#endif + bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) { (void) rhport; @@ -1062,5 +1077,4 @@ void tusb_hal_nrf_power_event(uint32_t event) { break; } } - #endif diff --git a/src/portable/nxp/khci/dcd_khci.c b/src/portable/nxp/khci/dcd_khci.c index 3d5e195a9..da1c5c888 100644 --- a/src/portable/nxp/khci/dcd_khci.c +++ b/src/portable/nxp/khci/dcd_khci.c @@ -428,6 +428,21 @@ void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) if (ie) NVIC_EnableIRQ(USB0_IRQn); } +#if 0 +bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { + (void) rhport; + (void) ep_addr; + (void) largest_packet_size; + return false; +} + +bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep) { + (void) rhport; + (void) desc_ep; + return false; +} + #endif + bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) { (void) rhport; @@ -577,5 +592,4 @@ void dcd_int_handler(uint8_t rhport) process_tokdne(rhport); } } - #endif diff --git a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c index 855c59cd1..5516e1ba6 100644 --- a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c +++ b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c @@ -337,9 +337,17 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) return true; } -void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) { - (void) rhport; (void) ep_addr; - // TODO implement dcd_edpt_close() +bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { + (void)rhport; + (void)ep_addr; + (void)largest_packet_size; + return false; +} + +bool dcd_edpt_iso_activate(uint8_t rhport, const tusb_desc_endpoint_t *desc_ep) { + (void)rhport; + (void)desc_ep; + return false; } void dcd_edpt_close_all (uint8_t rhport) @@ -600,5 +608,4 @@ void dcd_int_handler(uint8_t rhport) TU_BREAKPOINT(); } } - #endif diff --git a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c index 7c637ce0c..1c135f3be 100644 --- a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c +++ b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c @@ -432,6 +432,21 @@ void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) _dcd.ep[ep_id][0].cmd_sts.disable = _dcd.ep[ep_id][1].cmd_sts.disable = 1; } +#if 0 +bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { + (void)rhport; + (void)ep_addr; + (void)largest_packet_size; + return false; +} + +bool dcd_edpt_iso_activate(uint8_t rhport, const tusb_desc_endpoint_t *desc_ep) { + (void)rhport; + (void)desc_ep; + return false; +} +#endif + static void prepare_ep_xfer(uint8_t rhport, uint8_t ep_id, uint16_t buf_offset, uint16_t total_bytes) { uint16_t nbytes; ep_cmd_sts_t* ep_cs = get_ep_cs(ep_id); @@ -631,5 +646,4 @@ void dcd_int_handler(uint8_t rhport) // Endpoint transfer complete interrupt process_xfer_isr(rhport, int_status); } - #endif diff --git a/src/portable/raspberrypi/pio_usb/dcd_pio_usb.c b/src/portable/raspberrypi/pio_usb/dcd_pio_usb.c index 60afbd435..25ef117c2 100644 --- a/src/portable/raspberrypi/pio_usb/dcd_pio_usb.c +++ b/src/portable/raspberrypi/pio_usb/dcd_pio_usb.c @@ -113,6 +113,19 @@ void dcd_edpt_close_all (uint8_t rhport) (void) rhport; } +bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { + (void)rhport; + (void)ep_addr; + (void)largest_packet_size; + return false; +} + +bool dcd_edpt_iso_activate(uint8_t rhport, const tusb_desc_endpoint_t *desc_ep) { + (void)rhport; + (void)desc_ep; + return false; +} + // Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) { @@ -207,5 +220,4 @@ void __no_inline_not_in_flash_func(pio_usb_device_irq_handler)(uint8_t root_id) // clear all rport->ints &= ~ints; } - #endif diff --git a/src/portable/renesas/rusb2/dcd_rusb2.c b/src/portable/renesas/rusb2/dcd_rusb2.c index ecd28973c..2cc79aa74 100644 --- a/src/portable/renesas/rusb2/dcd_rusb2.c +++ b/src/portable/renesas/rusb2/dcd_rusb2.c @@ -859,6 +859,21 @@ void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) _dcd.ep[dir][epn] = 0; } +#if 0 +bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { + (void)rhport; + (void)ep_addr; + (void)largest_packet_size; + return false; +} + +bool dcd_edpt_iso_activate(uint8_t rhport, const tusb_desc_endpoint_t *desc_ep) { + (void)rhport; + (void)desc_ep; + return false; +} +#endif + bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) { rusb2_reg_t* rusb = RUSB2_REG(rhport); @@ -1028,5 +1043,4 @@ void dcd_int_handler(uint8_t rhport) } } } - #endif diff --git a/src/portable/sunxi/dcd_sunxi_musb.c b/src/portable/sunxi/dcd_sunxi_musb.c index f1f4897cb..8e6dc8c63 100644 --- a/src/portable/sunxi/dcd_sunxi_musb.c +++ b/src/portable/sunxi/dcd_sunxi_musb.c @@ -1082,6 +1082,21 @@ void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) musb_int_unmask(); } + #if 0 +bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { + (void)rhport; + (void)ep_addr; + (void)largest_packet_size; + return false; +} + +bool dcd_edpt_iso_activate(uint8_t rhport, const tusb_desc_endpoint_t *desc_ep) { + (void)rhport; + (void)desc_ep; + return false; +} + #endif + // Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) { @@ -1210,5 +1225,4 @@ void dcd_int_handler(uint8_t rhport) rxis &= ~TU_BIT(num); } } - #endif diff --git a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c index 64cbc5087..e4c28a56f 100644 --- a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c +++ b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c @@ -333,11 +333,20 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) return true; } -void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) { - (void) rhport; (void) ep_addr; - // TODO implement dcd_edpt_close() +bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { + (void)rhport; + (void)ep_addr; + (void)largest_packet_size; + return false; } +bool dcd_edpt_iso_activate(uint8_t rhport, const tusb_desc_endpoint_t *desc_ep) { + (void)rhport; + (void)desc_ep; + return false; +} + + void dcd_edpt_close_all (uint8_t rhport) { (void) rhport; @@ -821,5 +830,4 @@ void dcd_int_handler(uint8_t rhport) } } - #endif diff --git a/src/portable/valentyusb/eptri/dcd_eptri.c b/src/portable/valentyusb/eptri/dcd_eptri.c index a03c94558..f0e52ae47 100644 --- a/src/portable/valentyusb/eptri/dcd_eptri.c +++ b/src/portable/valentyusb/eptri/dcd_eptri.c @@ -438,9 +438,17 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) return true; } -void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) { - (void) rhport; (void) ep_addr; - // TODO implement dcd_edpt_close() +bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { + (void)rhport; + (void)ep_addr; + (void)largest_packet_size; + return false; +} + +bool dcd_edpt_iso_activate(uint8_t rhport, const tusb_desc_endpoint_t *desc_ep) { + (void)rhport; + (void)desc_ep; + return false; } void dcd_edpt_close_all (uint8_t rhport) @@ -659,5 +667,4 @@ void dcd_int_handler(uint8_t rhport) } } } - #endif diff --git a/src/portable/wch/dcd_ch32_usbfs.c b/src/portable/wch/dcd_ch32_usbfs.c index c248ba14e..f8c3b05c3 100644 --- a/src/portable/wch/dcd_ch32_usbfs.c +++ b/src/portable/wch/dcd_ch32_usbfs.c @@ -283,12 +283,20 @@ void dcd_edpt_close_all(uint8_t rhport) { // TODO optional } -void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) { +bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { (void) rhport; (void) ep_addr; - // TODO optional + (void)largest_packet_size; + return false; +} + +bool dcd_edpt_iso_activate(uint8_t rhport, const tusb_desc_endpoint_t *desc_ep) { + (void)rhport; + (void)desc_ep; + return false; } + bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) { (void) rhport; uint8_t ep = tu_edpt_number(ep_addr); @@ -344,5 +352,4 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { } } } - #endif diff --git a/src/portable/wch/dcd_ch32_usbhs.c b/src/portable/wch/dcd_ch32_usbhs.c index 4a208b9df..36fdc89ef 100644 --- a/src/portable/wch/dcd_ch32_usbhs.c +++ b/src/portable/wch/dcd_ch32_usbhs.c @@ -27,13 +27,14 @@ #include "tusb_option.h" -#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" +#if CFG_TUD_ENABLED && defined(TUP_USBIP_WCH_USBHS) && defined(CFG_TUD_WCH_USBIP_USBHS) && \ + (CFG_TUD_WCH_USBIP_USBHS == 1) + #include "ch32_usbhs_reg.h" -#include "device/dcd.h" + #include "device/dcd.h" -// Max number of bi-directional endpoints including EP0 -#define EP_MAX 16 + // Max number of bi-directional endpoints including EP0 + #define EP_MAX 16 typedef struct { uint8_t* buffer; @@ -288,6 +289,21 @@ void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) { } } + #if 0 +bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { + (void) rhport; + (void) ep_addr; + (void) largest_packet_size; + return false; +} + +bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep) { + (void) rhport; + (void) desc_ep; + return false; +} + #endif + void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { (void) rhport; @@ -419,5 +435,4 @@ void dcd_int_handler(uint8_t rhport) { USBHSD->INT_FG = USBHS_SUSPEND_FLAG; /* Clear flag */ } } - #endif -- cgit v1.3.1 From be9d1973ac4c30fedd24b8199fd4dee5c842e2ef Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 17 Nov 2025 17:45:38 +0700 Subject: make TUP_DCD_EDPT_ISO_ALLOC i.e dcd_edpt_iso_alloc()/dcd_edpt_iso_activate() as default driver implementation. dcd_edpt_close() is deprecated and will be removed from all driver in the future. --- examples/device/video_capture/skip.txt | 1 - examples/device/video_capture_2ch/skip.txt | 1 - hw/bsp/family_support.cmake | 3 + hw/bsp/mcx/boards/frdm_mcxa153/board.cmake | 9 +- hw/bsp/mcx/boards/frdm_mcxa153/board.mk | 8 + .../mcx/boards/frdm_mcxa153/board/clock_config.c | 559 ++++++++++++++++++++ .../mcx/boards/frdm_mcxa153/board/clock_config.h | 385 ++++++++++++++ hw/bsp/mcx/boards/frdm_mcxa153/board/pin_mux.c | 492 ++++++++++++++++++ hw/bsp/mcx/boards/frdm_mcxa153/board/pin_mux.h | 211 ++++++++ hw/bsp/mcx/boards/frdm_mcxa153/clock_config.c | 466 ----------------- hw/bsp/mcx/boards/frdm_mcxa153/clock_config.h | 170 ------ hw/bsp/mcx/boards/frdm_mcxa153/frdm_mcxa153.mex | 573 +++++++++++++++++++++ hw/bsp/mcx/boards/frdm_mcxa153/pin_mux.c | 130 ----- hw/bsp/mcx/boards/frdm_mcxa153/pin_mux.h | 51 -- hw/bsp/mcx/family.c | 7 +- hw/bsp/mcx/family.mk | 13 +- src/common/tusb_mcu.h | 11 +- src/portable/chipidea/ci_fs/dcd_ci_fs.c | 83 ++- src/portable/nxp/khci/dcd_khci.c | 78 ++- 19 files changed, 2313 insertions(+), 938 deletions(-) create mode 100644 hw/bsp/mcx/boards/frdm_mcxa153/board/clock_config.c create mode 100644 hw/bsp/mcx/boards/frdm_mcxa153/board/clock_config.h create mode 100644 hw/bsp/mcx/boards/frdm_mcxa153/board/pin_mux.c create mode 100644 hw/bsp/mcx/boards/frdm_mcxa153/board/pin_mux.h delete mode 100644 hw/bsp/mcx/boards/frdm_mcxa153/clock_config.c delete mode 100644 hw/bsp/mcx/boards/frdm_mcxa153/clock_config.h create mode 100644 hw/bsp/mcx/boards/frdm_mcxa153/frdm_mcxa153.mex delete mode 100644 hw/bsp/mcx/boards/frdm_mcxa153/pin_mux.c delete mode 100644 hw/bsp/mcx/boards/frdm_mcxa153/pin_mux.h (limited to 'src/portable') diff --git a/examples/device/video_capture/skip.txt b/examples/device/video_capture/skip.txt index 50302c544..cb0c7d2e6 100644 --- a/examples/device/video_capture/skip.txt +++ b/examples/device/video_capture/skip.txt @@ -1,6 +1,5 @@ mcu:CH32V103 mcu:CH32V20X -mcu:MCXA15 mcu:MSP430x5xx mcu:NUC121 mcu:SAMD11 diff --git a/examples/device/video_capture_2ch/skip.txt b/examples/device/video_capture_2ch/skip.txt index 0f6508226..af3b0de04 100644 --- a/examples/device/video_capture_2ch/skip.txt +++ b/examples/device/video_capture_2ch/skip.txt @@ -6,7 +6,6 @@ mcu:CH32V103 mcu:CH32V20X mcu:CH32V307 mcu:STM32L0 -mcu:MCXA15 family:espressif board:curiosity_nano board:kuiic diff --git a/hw/bsp/family_support.cmake b/hw/bsp/family_support.cmake index 23dfb9d80..2b9612186 100644 --- a/hw/bsp/family_support.cmake +++ b/hw/bsp/family_support.cmake @@ -264,6 +264,9 @@ function(family_configure_common TARGET RTOS) ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib SKIP_LINTING ON # need cmake 4.2 ) + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_target_properties(${BOARD_TARGET} PROPERTIES COMPILE_OPTIONS -w) + endif () endif () target_link_libraries(${TARGET} PUBLIC ${BOARD_TARGET}) endif () diff --git a/hw/bsp/mcx/boards/frdm_mcxa153/board.cmake b/hw/bsp/mcx/boards/frdm_mcxa153/board.cmake index 7cd8991e6..e6619992f 100644 --- a/hw/bsp/mcx/boards/frdm_mcxa153/board.cmake +++ b/hw/bsp/mcx/boards/frdm_mcxa153/board.cmake @@ -14,8 +14,11 @@ function(update_board TARGET) 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 + target_sources(${TARGET} PRIVATE + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/board/clock_config.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/board/pin_mux.c + ) + target_include_directories(${TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/board ) endfunction() diff --git a/hw/bsp/mcx/boards/frdm_mcxa153/board.mk b/hw/bsp/mcx/boards/frdm_mcxa153/board.mk index af8416d8e..34558b43e 100644 --- a/hw/bsp/mcx/boards/frdm_mcxa153/board.mk +++ b/hw/bsp/mcx/boards/frdm_mcxa153/board.mk @@ -6,6 +6,14 @@ CPU_CORE = cortex-m33-nodsp-nofp CFLAGS += \ -DCPU_MCXA153VLH \ -DCFG_TUSB_MCU=OPT_MCU_MCXA15 \ + -DCFG_EXAMPLE_VIDEO_READONLY + +SRC_C += \ + ${BOARD_PATH}/board/clock_config.c \ + ${BOARD_PATH}/board/pin_mux.c + +INC += \ + $(TOP)/$(BOARD_PATH)/board JLINK_DEVICE = MCXA153 PYOCD_TARGET = MCXA153 diff --git a/hw/bsp/mcx/boards/frdm_mcxa153/board/clock_config.c b/hw/bsp/mcx/boards/frdm_mcxa153/board/clock_config.c new file mode 100644 index 000000000..599110d7a --- /dev/null +++ b/hw/bsp/mcx/boards/frdm_mcxa153/board/clock_config.c @@ -0,0 +1,559 @@ +/* + * Copyright 2025 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. + **********************************************************************************************************************/ +/* + * 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 v18.0 +processor: MCXA153 +package_id: MCXA153VLH +mcu_data: ksdk2_0 +processor_version: 25.09.10 +board: FRDM-MCXA153 + * 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: TRACE_clock.outFreq, value: 12 MHz} +- {id: UTICK_clock.outFreq, value: 1 MHz} +- {id: WWDT0_clock.outFreq, value: 1 MHz} +settings: +- {id: SCGMode, value: SIRC} +- {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); + } + + + /*!< Set up system dividers */ + CLOCK_SetClockDiv(kCLOCK_DivAHBCLK, 1U); /* !< Set AHBCLKDIV divider to value 1 */ + 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 */ + CLOCK_AttachClk(kCPU_CLK_to_TRACE); /* !< Switch TRACE to CPU_CLK */ + + /*!< Set up dividers */ + CLOCK_SetClockDiv(kCLOCK_DivTRACE, 1U); /* !< Set TRACECLKDIV divider to value 1 */ + CLOCK_SetClockDiv(kCLOCK_DivWWDT0, 1U); /* !< Set WWDT0CLKDIV 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: TRACE_clock.outFreq, value: 24 MHz} +- {id: UTICK_clock.outFreq, value: 1 MHz} +- {id: WWDT0_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'} + * 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); + } + + + /*!< Set up system 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 */ + + 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 */ + CLOCK_AttachClk(kCPU_CLK_to_TRACE); /* !< Switch TRACE to CPU_CLK */ + CLOCK_AttachClk(kFRO_HF_DIV_to_LPSPI0); /* !< Switch LPSPI0 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_LPSPI1); /* !< Switch LPSPI1 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_LPI2C0); /* !< Switch LPI2C0 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_LPUART0); /* !< Switch LPUART0 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_LPUART1); /* !< Switch LPUART1 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_LPUART2); /* !< Switch LPUART2 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_LPTMR0); /* !< Switch LPTMR0 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_I3C0FCLK); /* !< Switch I3C0FCLK to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_CMP0); /* !< Switch CMP0 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_CMP1); /* !< Switch CMP1 to FRO_HF_DIV */ + + /*!< Set up dividers */ + CLOCK_SetClockDiv(kCLOCK_DivTRACE, 1U); /* !< Set TRACECLKDIV divider to value 1 */ + CLOCK_SetClockDiv(kCLOCK_DivWWDT0, 1U); /* !< Set WWDT0CLKDIV 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: TRACE_clock.outFreq, value: 48 MHz} +- {id: UTICK_clock.outFreq, value: 1 MHz} +- {id: WWDT0_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); + } + + + /*!< Set up system 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 */ + + 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 */ + CLOCK_AttachClk(kCPU_CLK_to_TRACE); /* !< Switch TRACE to CPU_CLK */ + CLOCK_AttachClk(kFRO_HF_DIV_to_LPSPI0); /* !< Switch LPSPI0 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_LPSPI1); /* !< Switch LPSPI1 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_LPI2C0); /* !< Switch LPI2C0 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_LPUART0); /* !< Switch LPUART0 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_LPUART1); /* !< Switch LPUART1 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_LPUART2); /* !< Switch LPUART2 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_LPTMR0); /* !< Switch LPTMR0 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_I3C0FCLK); /* !< Switch I3C0FCLK to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_CMP0); /* !< Switch CMP0 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_CMP1); /* !< Switch CMP1 to FRO_HF_DIV */ + + /*!< Set up dividers */ + CLOCK_SetClockDiv(kCLOCK_DivTRACE, 1U); /* !< Set TRACECLKDIV divider to value 1 */ + CLOCK_SetClockDiv(kCLOCK_DivWWDT0, 1U); /* !< Set WWDT0CLKDIV 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: TRACE_clock.outFreq, value: 64 MHz} +- {id: UTICK_clock.outFreq, value: 1 MHz} +- {id: WWDT0_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); + } + + + /*!< Set up system 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 */ + + 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 */ + CLOCK_AttachClk(kCPU_CLK_to_TRACE); /* !< Switch TRACE to CPU_CLK */ + CLOCK_AttachClk(kFRO_HF_DIV_to_LPSPI0); /* !< Switch LPSPI0 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_LPSPI1); /* !< Switch LPSPI1 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_LPI2C0); /* !< Switch LPI2C0 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_LPUART0); /* !< Switch LPUART0 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_LPUART1); /* !< Switch LPUART1 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_LPUART2); /* !< Switch LPUART2 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_LPTMR0); /* !< Switch LPTMR0 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_I3C0FCLK); /* !< Switch I3C0FCLK to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_CMP0); /* !< Switch CMP0 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_CMP1); /* !< Switch CMP1 to FRO_HF_DIV */ + + /*!< Set up dividers */ + CLOCK_SetClockDiv(kCLOCK_DivTRACE, 1U); /* !< Set TRACECLKDIV divider to value 1 */ + CLOCK_SetClockDiv(kCLOCK_DivWWDT0, 1U); /* !< Set WWDT0CLKDIV 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: TRACE_clock.outFreq, value: 96 MHz} +- {id: UTICK_clock.outFreq, value: 1 MHz} +- {id: WWDT0_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.OSTIMERCLKSEL.sel, value: VBAT.CLK16K_1} +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); + } + + + /*!< Set up system 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 */ + + 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 */ + CLOCK_AttachClk(kCPU_CLK_to_TRACE); /* !< Switch TRACE to CPU_CLK */ + CLOCK_AttachClk(kFRO_HF_DIV_to_LPSPI0); /* !< Switch LPSPI0 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_LPSPI1); /* !< Switch LPSPI1 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_LPI2C0); /* !< Switch LPI2C0 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_LPUART0); /* !< Switch LPUART0 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_LPUART1); /* !< Switch LPUART1 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_LPUART2); /* !< Switch LPUART2 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_LPTMR0); /* !< Switch LPTMR0 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_I3C0FCLK); /* !< Switch I3C0FCLK to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_CMP0); /* !< Switch CMP0 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_CMP1); /* !< Switch CMP1 to FRO_HF_DIV */ + + /*!< Set up dividers */ + CLOCK_SetClockDiv(kCLOCK_DivTRACE, 1U); /* !< Set TRACECLKDIV divider to value 1 */ + CLOCK_SetClockDiv(kCLOCK_DivWWDT0, 1U); /* !< Set WWDT0CLKDIV divider to value 1 */ + + /* Set SystemCoreClock variable */ + SystemCoreClock = BOARD_BOOTCLOCKFRO96M_CORE_CLOCK; +} diff --git a/hw/bsp/mcx/boards/frdm_mcxa153/board/clock_config.h b/hw/bsp/mcx/boards/frdm_mcxa153/board/clock_config.h new file mode 100644 index 000000000..d609eb468 --- /dev/null +++ b/hw/bsp/mcx/boards/frdm_mcxa153/board/clock_config.h @@ -0,0 +1,385 @@ +/* + * Copyright 2025 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 _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 */ + +/* Clock outputs (values are in Hz): */ +#define BOARD_BOOTCLOCKFRO12M_ADC0_CLOCK 0UL /* Clock consumers of ADC0_clock output : ADC0 */ +#define BOARD_BOOTCLOCKFRO12M_CLK16K_0_CLOCK 0UL /* Clock consumers of CLK16K_0_clock output : CMP0, WAKETIMER0, WUU0 */ +#define BOARD_BOOTCLOCKFRO12M_CLK16K_1_CLOCK 0UL /* Clock consumers of CLK16K_1_clock output : CMP1, LPTMR0, WAKETIMER0 */ +#define BOARD_BOOTCLOCKFRO12M_CLKOUT_CLOCK 0UL /* Clock consumers of CLKOUT_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO12M_CLK_1M_CLOCK 1000000UL /* Clock consumers of CLK_1M_clock output : CMC */ +#define BOARD_BOOTCLOCKFRO12M_CLK_48M_CLOCK 0UL /* Clock consumers of CLK_48M_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO12M_CLK_IN_CLOCK 0UL /* Clock consumers of CLK_IN_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO12M_CMP0FDIV_CLOCK 0UL /* Clock consumers of CMP0FDIV_clock output : CMP0 */ +#define BOARD_BOOTCLOCKFRO12M_CMP0RRDIV_CLOCK 0UL /* Clock consumers of CMP0RRDIV_clock output : CMP0 */ +#define BOARD_BOOTCLOCKFRO12M_CMP1FDIV_CLOCK 0UL /* Clock consumers of CMP1FDIV_clock output : CMP1 */ +#define BOARD_BOOTCLOCKFRO12M_CMP1RRDIV_CLOCK 0UL /* Clock consumers of CMP1RRDIV_clock output : CMP1 */ +#define BOARD_BOOTCLOCKFRO12M_CPU_CLOCK 12000000UL /* Clock consumers of CPU_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO12M_CTIMER0_CLOCK 0UL /* Clock consumers of CTIMER0_clock output : CTIMER0 */ +#define BOARD_BOOTCLOCKFRO12M_CTIMER1_CLOCK 0UL /* Clock consumers of CTIMER1_clock output : CTIMER1 */ +#define BOARD_BOOTCLOCKFRO12M_CTIMER2_CLOCK 0UL /* Clock consumers of CTIMER2_clock output : CTIMER2 */ +#define BOARD_BOOTCLOCKFRO12M_FREQME_REFERENCE_CLOCK 0UL /* Clock consumers of FREQME_reference_clock output : FREQME0 */ +#define BOARD_BOOTCLOCKFRO12M_FREQME_TARGET_CLOCK 0UL /* Clock consumers of FREQME_target_clock output : FREQME0 */ +#define BOARD_BOOTCLOCKFRO12M_FRO_12M_CLOCK 12000000UL /* Clock consumers of FRO_12M_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO12M_FRO_HF_DIV_CLOCK 0UL /* Clock consumers of FRO_HF_DIV_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO12M_FRO_HF_CLOCK 0UL /* Clock consumers of FRO_HF_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO12M_I3C_FCLK_CLOCK 0UL /* Clock consumers of I3C_FCLK_clock output : I3C0 */ +#define BOARD_BOOTCLOCKFRO12M_I3C_SLOW_TC_CLOCK 0UL /* Clock consumers of I3C_SLOW_TC_clock output : I3C0 */ +#define BOARD_BOOTCLOCKFRO12M_I3C_SLOW_CLOCK 0UL /* Clock consumers of I3C_SLOW_clock output : I3C0 */ +#define BOARD_BOOTCLOCKFRO12M_LPI2C0_CLOCK 0UL /* Clock consumers of LPI2C0_clock output : LPI2C0 */ +#define BOARD_BOOTCLOCKFRO12M_LPSPI0_CLOCK 0UL /* Clock consumers of LPSPI0_clock output : LPSPI0 */ +#define BOARD_BOOTCLOCKFRO12M_LPSPI1_CLOCK 0UL /* Clock consumers of LPSPI1_clock output : LPSPI1 */ +#define BOARD_BOOTCLOCKFRO12M_LPTMR0_CLOCK 0UL /* Clock consumers of LPTMR0_clock output : LPTMR0 */ +#define BOARD_BOOTCLOCKFRO12M_LPUART0_CLOCK 0UL /* Clock consumers of LPUART0_clock output : LPUART0 */ +#define BOARD_BOOTCLOCKFRO12M_LPUART1_CLOCK 0UL /* Clock consumers of LPUART1_clock output : LPUART1 */ +#define BOARD_BOOTCLOCKFRO12M_LPUART2_CLOCK 0UL /* Clock consumers of LPUART2_clock output : LPUART2 */ +#define BOARD_BOOTCLOCKFRO12M_MAIN_CLOCK 12000000UL /* Clock consumers of MAIN_clock output : FLEXPWM0 */ +#define BOARD_BOOTCLOCKFRO12M_OSTIMER_CLOCK 0UL /* Clock consumers of OSTIMER_clock output : OSTIMER0 */ +#define BOARD_BOOTCLOCKFRO12M_FIRC_TRIM_CLOCK 0UL /* Clock consumers of SCG.FIRC_TRIM_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO12M_SIRC_TRIM_CLOCK 0UL /* Clock consumers of SCG.SIRC_TRIM_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO12M_SLOW_CLOCK 3000000UL /* Clock consumers of Slow_clock output : AOI0, CMC, CMP0, LPTMR0, WAKETIMER0, WUU0 */ +#define BOARD_BOOTCLOCKFRO12M_SYSTEM_CLOCK 12000000UL /* Clock consumers of System_clock output : ADC0, CMP1, CTIMER0, CTIMER1, CTIMER2, DMA0, FLEXPWM0, FREQME0, GPIO0, GPIO1, GPIO2, GPIO3, I3C0, INPUTMUX0, LPI2C0, LPSPI0, LPSPI1, LPUART0, LPUART1, LPUART2, OSTIMER0, PORT0, PORT1, PORT2, PORT3, QDC0, SWD, SysTick, USB0, UTICK0, WWDT0 */ +#define BOARD_BOOTCLOCKFRO12M_TRACE_CLOCK 12000000UL /* Clock consumers of TRACE_clock output : SWD */ +#define BOARD_BOOTCLOCKFRO12M_USB0_CLOCK 0UL /* Clock consumers of USB0_clock output : USB0 */ +#define BOARD_BOOTCLOCKFRO12M_UTICK_CLOCK 1000000UL /* Clock consumers of UTICK_clock output : UTICK0 */ +#define BOARD_BOOTCLOCKFRO12M_WUU_CLOCK 0UL /* Clock consumers of WUU_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO12M_WWDT0_CLOCK 1000000UL /* Clock consumers of WWDT0_clock output : WWDT0 */ + + +/******************************************************************************* + * 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 */ + +/* Clock outputs (values are in Hz): */ +#define BOARD_BOOTCLOCKFRO24M_ADC0_CLOCK 0UL /* Clock consumers of ADC0_clock output : ADC0 */ +#define BOARD_BOOTCLOCKFRO24M_CLK16K_0_CLOCK 0UL /* Clock consumers of CLK16K_0_clock output : CMP0, WAKETIMER0, WUU0 */ +#define BOARD_BOOTCLOCKFRO24M_CLK16K_1_CLOCK 0UL /* Clock consumers of CLK16K_1_clock output : CMP1, LPTMR0, WAKETIMER0 */ +#define BOARD_BOOTCLOCKFRO24M_CLKOUT_CLOCK 0UL /* Clock consumers of CLKOUT_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO24M_CLK_1M_CLOCK 1000000UL /* Clock consumers of CLK_1M_clock output : CMC */ +#define BOARD_BOOTCLOCKFRO24M_CLK_48M_CLOCK 48000000UL /* Clock consumers of CLK_48M_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO24M_CLK_IN_CLOCK 0UL /* Clock consumers of CLK_IN_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO24M_CMP0FDIV_CLOCK 0UL /* Clock consumers of CMP0FDIV_clock output : CMP0 */ +#define BOARD_BOOTCLOCKFRO24M_CMP0RRDIV_CLOCK 0UL /* Clock consumers of CMP0RRDIV_clock output : CMP0 */ +#define BOARD_BOOTCLOCKFRO24M_CMP1FDIV_CLOCK 0UL /* Clock consumers of CMP1FDIV_clock output : CMP1 */ +#define BOARD_BOOTCLOCKFRO24M_CMP1RRDIV_CLOCK 0UL /* Clock consumers of CMP1RRDIV_clock output : CMP1 */ +#define BOARD_BOOTCLOCKFRO24M_CPU_CLOCK 24000000UL /* Clock consumers of CPU_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO24M_CTIMER0_CLOCK 0UL /* Clock consumers of CTIMER0_clock output : CTIMER0 */ +#define BOARD_BOOTCLOCKFRO24M_CTIMER1_CLOCK 0UL /* Clock consumers of CTIMER1_clock output : CTIMER1 */ +#define BOARD_BOOTCLOCKFRO24M_CTIMER2_CLOCK 0UL /* Clock consumers of CTIMER2_clock output : CTIMER2 */ +#define BOARD_BOOTCLOCKFRO24M_FREQME_REFERENCE_CLOCK 0UL /* Clock consumers of FREQME_reference_clock output : FREQME0 */ +#define BOARD_BOOTCLOCKFRO24M_FREQME_TARGET_CLOCK 0UL /* Clock consumers of FREQME_target_clock output : FREQME0 */ +#define BOARD_BOOTCLOCKFRO24M_FRO_12M_CLOCK 12000000UL /* Clock consumers of FRO_12M_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO24M_FRO_HF_DIV_CLOCK 48000000UL /* Clock consumers of FRO_HF_DIV_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO24M_FRO_HF_CLOCK 48000000UL /* Clock consumers of FRO_HF_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO24M_I3C_FCLK_CLOCK 0UL /* Clock consumers of I3C_FCLK_clock output : I3C0 */ +#define BOARD_BOOTCLOCKFRO24M_I3C_SLOW_TC_CLOCK 0UL /* Clock consumers of I3C_SLOW_TC_clock output : I3C0 */ +#define BOARD_BOOTCLOCKFRO24M_I3C_SLOW_CLOCK 0UL /* Clock consumers of I3C_SLOW_clock output : I3C0 */ +#define BOARD_BOOTCLOCKFRO24M_LPI2C0_CLOCK 0UL /* Clock consumers of LPI2C0_clock output : LPI2C0 */ +#define BOARD_BOOTCLOCKFRO24M_LPSPI0_CLOCK 0UL /* Clock consumers of LPSPI0_clock output : LPSPI0 */ +#define BOARD_BOOTCLOCKFRO24M_LPSPI1_CLOCK 0UL /* Clock consumers of LPSPI1_clock output : LPSPI1 */ +#define BOARD_BOOTCLOCKFRO24M_LPTMR0_CLOCK 0UL /* Clock consumers of LPTMR0_clock output : LPTMR0 */ +#define BOARD_BOOTCLOCKFRO24M_LPUART0_CLOCK 0UL /* Clock consumers of LPUART0_clock output : LPUART0 */ +#define BOARD_BOOTCLOCKFRO24M_LPUART1_CLOCK 0UL /* Clock consumers of LPUART1_clock output : LPUART1 */ +#define BOARD_BOOTCLOCKFRO24M_LPUART2_CLOCK 0UL /* Clock consumers of LPUART2_clock output : LPUART2 */ +#define BOARD_BOOTCLOCKFRO24M_MAIN_CLOCK 48000000UL /* Clock consumers of MAIN_clock output : FLEXPWM0 */ +#define BOARD_BOOTCLOCKFRO24M_OSTIMER_CLOCK 0UL /* Clock consumers of OSTIMER_clock output : OSTIMER0 */ +#define BOARD_BOOTCLOCKFRO24M_FIRC_TRIM_CLOCK 0UL /* Clock consumers of SCG.FIRC_TRIM_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO24M_SIRC_TRIM_CLOCK 0UL /* Clock consumers of SCG.SIRC_TRIM_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO24M_SLOW_CLOCK 6000000UL /* Clock consumers of Slow_clock output : AOI0, CMC, CMP0, LPTMR0, WAKETIMER0, WUU0 */ +#define BOARD_BOOTCLOCKFRO24M_SYSTEM_CLOCK 24000000UL /* Clock consumers of System_clock output : ADC0, CMP1, CTIMER0, CTIMER1, CTIMER2, DMA0, FLEXPWM0, FREQME0, GPIO0, GPIO1, GPIO2, GPIO3, I3C0, INPUTMUX0, LPI2C0, LPSPI0, LPSPI1, LPUART0, LPUART1, LPUART2, OSTIMER0, PORT0, PORT1, PORT2, PORT3, QDC0, SWD, SysTick, USB0, UTICK0, WWDT0 */ +#define BOARD_BOOTCLOCKFRO24M_TRACE_CLOCK 24000000UL /* Clock consumers of TRACE_clock output : SWD */ +#define BOARD_BOOTCLOCKFRO24M_USB0_CLOCK 0UL /* Clock consumers of USB0_clock output : USB0 */ +#define BOARD_BOOTCLOCKFRO24M_UTICK_CLOCK 1000000UL /* Clock consumers of UTICK_clock output : UTICK0 */ +#define BOARD_BOOTCLOCKFRO24M_WUU_CLOCK 0UL /* Clock consumers of WUU_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO24M_WWDT0_CLOCK 1000000UL /* Clock consumers of WWDT0_clock output : WWDT0 */ + + +/******************************************************************************* + * 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 */ + +/* Clock outputs (values are in Hz): */ +#define BOARD_BOOTCLOCKFRO48M_ADC0_CLOCK 0UL /* Clock consumers of ADC0_clock output : ADC0 */ +#define BOARD_BOOTCLOCKFRO48M_CLK16K_0_CLOCK 0UL /* Clock consumers of CLK16K_0_clock output : CMP0, WAKETIMER0, WUU0 */ +#define BOARD_BOOTCLOCKFRO48M_CLK16K_1_CLOCK 0UL /* Clock consumers of CLK16K_1_clock output : CMP1, LPTMR0, WAKETIMER0 */ +#define BOARD_BOOTCLOCKFRO48M_CLKOUT_CLOCK 0UL /* Clock consumers of CLKOUT_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO48M_CLK_1M_CLOCK 1000000UL /* Clock consumers of CLK_1M_clock output : CMC */ +#define BOARD_BOOTCLOCKFRO48M_CLK_48M_CLOCK 48000000UL /* Clock consumers of CLK_48M_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO48M_CLK_IN_CLOCK 0UL /* Clock consumers of CLK_IN_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO48M_CMP0FDIV_CLOCK 0UL /* Clock consumers of CMP0FDIV_clock output : CMP0 */ +#define BOARD_BOOTCLOCKFRO48M_CMP0RRDIV_CLOCK 0UL /* Clock consumers of CMP0RRDIV_clock output : CMP0 */ +#define BOARD_BOOTCLOCKFRO48M_CMP1FDIV_CLOCK 0UL /* Clock consumers of CMP1FDIV_clock output : CMP1 */ +#define BOARD_BOOTCLOCKFRO48M_CMP1RRDIV_CLOCK 0UL /* Clock consumers of CMP1RRDIV_clock output : CMP1 */ +#define BOARD_BOOTCLOCKFRO48M_CPU_CLOCK 48000000UL /* Clock consumers of CPU_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO48M_CTIMER0_CLOCK 0UL /* Clock consumers of CTIMER0_clock output : CTIMER0 */ +#define BOARD_BOOTCLOCKFRO48M_CTIMER1_CLOCK 0UL /* Clock consumers of CTIMER1_clock output : CTIMER1 */ +#define BOARD_BOOTCLOCKFRO48M_CTIMER2_CLOCK 0UL /* Clock consumers of CTIMER2_clock output : CTIMER2 */ +#define BOARD_BOOTCLOCKFRO48M_FREQME_REFERENCE_CLOCK 0UL /* Clock consumers of FREQME_reference_clock output : FREQME0 */ +#define BOARD_BOOTCLOCKFRO48M_FREQME_TARGET_CLOCK 0UL /* Clock consumers of FREQME_target_clock output : FREQME0 */ +#define BOARD_BOOTCLOCKFRO48M_FRO_12M_CLOCK 12000000UL /* Clock consumers of FRO_12M_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO48M_FRO_HF_DIV_CLOCK 48000000UL /* Clock consumers of FRO_HF_DIV_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO48M_FRO_HF_CLOCK 48000000UL /* Clock consumers of FRO_HF_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO48M_I3C_FCLK_CLOCK 0UL /* Clock consumers of I3C_FCLK_clock output : I3C0 */ +#define BOARD_BOOTCLOCKFRO48M_I3C_SLOW_TC_CLOCK 0UL /* Clock consumers of I3C_SLOW_TC_clock output : I3C0 */ +#define BOARD_BOOTCLOCKFRO48M_I3C_SLOW_CLOCK 0UL /* Clock consumers of I3C_SLOW_clock output : I3C0 */ +#define BOARD_BOOTCLOCKFRO48M_LPI2C0_CLOCK 0UL /* Clock consumers of LPI2C0_clock output : LPI2C0 */ +#define BOARD_BOOTCLOCKFRO48M_LPSPI0_CLOCK 0UL /* Clock consumers of LPSPI0_clock output : LPSPI0 */ +#define BOARD_BOOTCLOCKFRO48M_LPSPI1_CLOCK 0UL /* Clock consumers of LPSPI1_clock output : LPSPI1 */ +#define BOARD_BOOTCLOCKFRO48M_LPTMR0_CLOCK 0UL /* Clock consumers of LPTMR0_clock output : LPTMR0 */ +#define BOARD_BOOTCLOCKFRO48M_LPUART0_CLOCK 0UL /* Clock consumers of LPUART0_clock output : LPUART0 */ +#define BOARD_BOOTCLOCKFRO48M_LPUART1_CLOCK 0UL /* Clock consumers of LPUART1_clock output : LPUART1 */ +#define BOARD_BOOTCLOCKFRO48M_LPUART2_CLOCK 0UL /* Clock consumers of LPUART2_clock output : LPUART2 */ +#define BOARD_BOOTCLOCKFRO48M_MAIN_CLOCK 48000000UL /* Clock consumers of MAIN_clock output : FLEXPWM0 */ +#define BOARD_BOOTCLOCKFRO48M_OSTIMER_CLOCK 0UL /* Clock consumers of OSTIMER_clock output : OSTIMER0 */ +#define BOARD_BOOTCLOCKFRO48M_FIRC_TRIM_CLOCK 0UL /* Clock consumers of SCG.FIRC_TRIM_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO48M_SIRC_TRIM_CLOCK 0UL /* Clock consumers of SCG.SIRC_TRIM_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO48M_SLOW_CLOCK 12000000UL /* Clock consumers of Slow_clock output : AOI0, CMC, CMP0, LPTMR0, WAKETIMER0, WUU0 */ +#define BOARD_BOOTCLOCKFRO48M_SYSTEM_CLOCK 48000000UL /* Clock consumers of System_clock output : ADC0, CMP1, CTIMER0, CTIMER1, CTIMER2, DMA0, FLEXPWM0, FREQME0, GPIO0, GPIO1, GPIO2, GPIO3, I3C0, INPUTMUX0, LPI2C0, LPSPI0, LPSPI1, LPUART0, LPUART1, LPUART2, OSTIMER0, PORT0, PORT1, PORT2, PORT3, QDC0, SWD, SysTick, USB0, UTICK0, WWDT0 */ +#define BOARD_BOOTCLOCKFRO48M_TRACE_CLOCK 48000000UL /* Clock consumers of TRACE_clock output : SWD */ +#define BOARD_BOOTCLOCKFRO48M_USB0_CLOCK 0UL /* Clock consumers of USB0_clock output : USB0 */ +#define BOARD_BOOTCLOCKFRO48M_UTICK_CLOCK 1000000UL /* Clock consumers of UTICK_clock output : UTICK0 */ +#define BOARD_BOOTCLOCKFRO48M_WUU_CLOCK 0UL /* Clock consumers of WUU_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO48M_WWDT0_CLOCK 1000000UL /* Clock consumers of WWDT0_clock output : WWDT0 */ + + +/******************************************************************************* + * 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 */ + +/* Clock outputs (values are in Hz): */ +#define BOARD_BOOTCLOCKFRO64M_ADC0_CLOCK 0UL /* Clock consumers of ADC0_clock output : ADC0 */ +#define BOARD_BOOTCLOCKFRO64M_CLK16K_0_CLOCK 0UL /* Clock consumers of CLK16K_0_clock output : CMP0, WAKETIMER0, WUU0 */ +#define BOARD_BOOTCLOCKFRO64M_CLK16K_1_CLOCK 0UL /* Clock consumers of CLK16K_1_clock output : CMP1, LPTMR0, WAKETIMER0 */ +#define BOARD_BOOTCLOCKFRO64M_CLKOUT_CLOCK 0UL /* Clock consumers of CLKOUT_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO64M_CLK_1M_CLOCK 1000000UL /* Clock consumers of CLK_1M_clock output : CMC */ +#define BOARD_BOOTCLOCKFRO64M_CLK_48M_CLOCK 48000000UL /* Clock consumers of CLK_48M_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO64M_CLK_IN_CLOCK 0UL /* Clock consumers of CLK_IN_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO64M_CMP0FDIV_CLOCK 0UL /* Clock consumers of CMP0FDIV_clock output : CMP0 */ +#define BOARD_BOOTCLOCKFRO64M_CMP0RRDIV_CLOCK 0UL /* Clock consumers of CMP0RRDIV_clock output : CMP0 */ +#define BOARD_BOOTCLOCKFRO64M_CMP1FDIV_CLOCK 0UL /* Clock consumers of CMP1FDIV_clock output : CMP1 */ +#define BOARD_BOOTCLOCKFRO64M_CMP1RRDIV_CLOCK 0UL /* Clock consumers of CMP1RRDIV_clock output : CMP1 */ +#define BOARD_BOOTCLOCKFRO64M_CPU_CLOCK 64000000UL /* Clock consumers of CPU_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO64M_CTIMER0_CLOCK 0UL /* Clock consumers of CTIMER0_clock output : CTIMER0 */ +#define BOARD_BOOTCLOCKFRO64M_CTIMER1_CLOCK 0UL /* Clock consumers of CTIMER1_clock output : CTIMER1 */ +#define BOARD_BOOTCLOCKFRO64M_CTIMER2_CLOCK 0UL /* Clock consumers of CTIMER2_clock output : CTIMER2 */ +#define BOARD_BOOTCLOCKFRO64M_FREQME_REFERENCE_CLOCK 0UL /* Clock consumers of FREQME_reference_clock output : FREQME0 */ +#define BOARD_BOOTCLOCKFRO64M_FREQME_TARGET_CLOCK 0UL /* Clock consumers of FREQME_target_clock output : FREQME0 */ +#define BOARD_BOOTCLOCKFRO64M_FRO_12M_CLOCK 12000000UL /* Clock consumers of FRO_12M_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO64M_FRO_HF_DIV_CLOCK 64000000UL /* Clock consumers of FRO_HF_DIV_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO64M_FRO_HF_CLOCK 64000000UL /* Clock consumers of FRO_HF_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO64M_I3C_FCLK_CLOCK 0UL /* Clock consumers of I3C_FCLK_clock output : I3C0 */ +#define BOARD_BOOTCLOCKFRO64M_I3C_SLOW_TC_CLOCK 0UL /* Clock consumers of I3C_SLOW_TC_clock output : I3C0 */ +#define BOARD_BOOTCLOCKFRO64M_I3C_SLOW_CLOCK 0UL /* Clock consumers of I3C_SLOW_clock output : I3C0 */ +#define BOARD_BOOTCLOCKFRO64M_LPI2C0_CLOCK 0UL /* Clock consumers of LPI2C0_clock output : LPI2C0 */ +#define BOARD_BOOTCLOCKFRO64M_LPSPI0_CLOCK 0UL /* Clock consumers of LPSPI0_clock output : LPSPI0 */ +#define BOARD_BOOTCLOCKFRO64M_LPSPI1_CLOCK 0UL /* Clock consumers of LPSPI1_clock output : LPSPI1 */ +#define BOARD_BOOTCLOCKFRO64M_LPTMR0_CLOCK 0UL /* Clock consumers of LPTMR0_clock output : LPTMR0 */ +#define BOARD_BOOTCLOCKFRO64M_LPUART0_CLOCK 0UL /* Clock consumers of LPUART0_clock output : LPUART0 */ +#define BOARD_BOOTCLOCKFRO64M_LPUART1_CLOCK 0UL /* Clock consumers of LPUART1_clock output : LPUART1 */ +#define BOARD_BOOTCLOCKFRO64M_LPUART2_CLOCK 0UL /* Clock consumers of LPUART2_clock output : LPUART2 */ +#define BOARD_BOOTCLOCKFRO64M_MAIN_CLOCK 64000000UL /* Clock consumers of MAIN_clock output : FLEXPWM0 */ +#define BOARD_BOOTCLOCKFRO64M_OSTIMER_CLOCK 0UL /* Clock consumers of OSTIMER_clock output : OSTIMER0 */ +#define BOARD_BOOTCLOCKFRO64M_FIRC_TRIM_CLOCK 0UL /* Clock consumers of SCG.FIRC_TRIM_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO64M_SIRC_TRIM_CLOCK 0UL /* Clock consumers of SCG.SIRC_TRIM_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO64M_SLOW_CLOCK 16000000UL /* Clock consumers of Slow_clock output : AOI0, CMC, CMP0, LPTMR0, WAKETIMER0, WUU0 */ +#define BOARD_BOOTCLOCKFRO64M_SYSTEM_CLOCK 64000000UL /* Clock consumers of System_clock output : ADC0, CMP1, CTIMER0, CTIMER1, CTIMER2, DMA0, FLEXPWM0, FREQME0, GPIO0, GPIO1, GPIO2, GPIO3, I3C0, INPUTMUX0, LPI2C0, LPSPI0, LPSPI1, LPUART0, LPUART1, LPUART2, OSTIMER0, PORT0, PORT1, PORT2, PORT3, QDC0, SWD, SysTick, USB0, UTICK0, WWDT0 */ +#define BOARD_BOOTCLOCKFRO64M_TRACE_CLOCK 64000000UL /* Clock consumers of TRACE_clock output : SWD */ +#define BOARD_BOOTCLOCKFRO64M_USB0_CLOCK 0UL /* Clock consumers of USB0_clock output : USB0 */ +#define BOARD_BOOTCLOCKFRO64M_UTICK_CLOCK 1000000UL /* Clock consumers of UTICK_clock output : UTICK0 */ +#define BOARD_BOOTCLOCKFRO64M_WUU_CLOCK 0UL /* Clock consumers of WUU_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO64M_WWDT0_CLOCK 1000000UL /* Clock consumers of WWDT0_clock output : WWDT0 */ + + +/******************************************************************************* + * 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 */ + +/* Clock outputs (values are in Hz): */ +#define BOARD_BOOTCLOCKFRO96M_ADC0_CLOCK 0UL /* Clock consumers of ADC0_clock output : ADC0 */ +#define BOARD_BOOTCLOCKFRO96M_CLK16K_0_CLOCK 0UL /* Clock consumers of CLK16K_0_clock output : CMP0, WAKETIMER0, WUU0 */ +#define BOARD_BOOTCLOCKFRO96M_CLK16K_1_CLOCK 0UL /* Clock consumers of CLK16K_1_clock output : CMP1, LPTMR0, WAKETIMER0 */ +#define BOARD_BOOTCLOCKFRO96M_CLKOUT_CLOCK 0UL /* Clock consumers of CLKOUT_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO96M_CLK_1M_CLOCK 1000000UL /* Clock consumers of CLK_1M_clock output : CMC */ +#define BOARD_BOOTCLOCKFRO96M_CLK_48M_CLOCK 48000000UL /* Clock consumers of CLK_48M_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO96M_CLK_IN_CLOCK 0UL /* Clock consumers of CLK_IN_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO96M_CMP0FDIV_CLOCK 0UL /* Clock consumers of CMP0FDIV_clock output : CMP0 */ +#define BOARD_BOOTCLOCKFRO96M_CMP0RRDIV_CLOCK 0UL /* Clock consumers of CMP0RRDIV_clock output : CMP0 */ +#define BOARD_BOOTCLOCKFRO96M_CMP1FDIV_CLOCK 0UL /* Clock consumers of CMP1FDIV_clock output : CMP1 */ +#define BOARD_BOOTCLOCKFRO96M_CMP1RRDIV_CLOCK 0UL /* Clock consumers of CMP1RRDIV_clock output : CMP1 */ +#define BOARD_BOOTCLOCKFRO96M_CPU_CLOCK 96000000UL /* Clock consumers of CPU_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO96M_CTIMER0_CLOCK 0UL /* Clock consumers of CTIMER0_clock output : CTIMER0 */ +#define BOARD_BOOTCLOCKFRO96M_CTIMER1_CLOCK 0UL /* Clock consumers of CTIMER1_clock output : CTIMER1 */ +#define BOARD_BOOTCLOCKFRO96M_CTIMER2_CLOCK 0UL /* Clock consumers of CTIMER2_clock output : CTIMER2 */ +#define BOARD_BOOTCLOCKFRO96M_FREQME_REFERENCE_CLOCK 0UL /* Clock consumers of FREQME_reference_clock output : FREQME0 */ +#define BOARD_BOOTCLOCKFRO96M_FREQME_TARGET_CLOCK 0UL /* Clock consumers of FREQME_target_clock output : FREQME0 */ +#define BOARD_BOOTCLOCKFRO96M_FRO_12M_CLOCK 12000000UL /* Clock consumers of FRO_12M_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO96M_FRO_HF_DIV_CLOCK 96000000UL /* Clock consumers of FRO_HF_DIV_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO96M_FRO_HF_CLOCK 96000000UL /* Clock consumers of FRO_HF_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO96M_I3C_FCLK_CLOCK 0UL /* Clock consumers of I3C_FCLK_clock output : I3C0 */ +#define BOARD_BOOTCLOCKFRO96M_I3C_SLOW_TC_CLOCK 0UL /* Clock consumers of I3C_SLOW_TC_clock output : I3C0 */ +#define BOARD_BOOTCLOCKFRO96M_I3C_SLOW_CLOCK 0UL /* Clock consumers of I3C_SLOW_clock output : I3C0 */ +#define BOARD_BOOTCLOCKFRO96M_LPI2C0_CLOCK 0UL /* Clock consumers of LPI2C0_clock output : LPI2C0 */ +#define BOARD_BOOTCLOCKFRO96M_LPSPI0_CLOCK 0UL /* Clock consumers of LPSPI0_clock output : LPSPI0 */ +#define BOARD_BOOTCLOCKFRO96M_LPSPI1_CLOCK 0UL /* Clock consumers of LPSPI1_clock output : LPSPI1 */ +#define BOARD_BOOTCLOCKFRO96M_LPTMR0_CLOCK 0UL /* Clock consumers of LPTMR0_clock output : LPTMR0 */ +#define BOARD_BOOTCLOCKFRO96M_LPUART0_CLOCK 0UL /* Clock consumers of LPUART0_clock output : LPUART0 */ +#define BOARD_BOOTCLOCKFRO96M_LPUART1_CLOCK 0UL /* Clock consumers of LPUART1_clock output : LPUART1 */ +#define BOARD_BOOTCLOCKFRO96M_LPUART2_CLOCK 0UL /* Clock consumers of LPUART2_clock output : LPUART2 */ +#define BOARD_BOOTCLOCKFRO96M_MAIN_CLOCK 96000000UL /* Clock consumers of MAIN_clock output : FLEXPWM0 */ +#define BOARD_BOOTCLOCKFRO96M_OSTIMER_CLOCK 0UL /* Clock consumers of OSTIMER_clock output : OSTIMER0 */ +#define BOARD_BOOTCLOCKFRO96M_FIRC_TRIM_CLOCK 0UL /* Clock consumers of SCG.FIRC_TRIM_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO96M_SIRC_TRIM_CLOCK 0UL /* Clock consumers of SCG.SIRC_TRIM_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO96M_SLOW_CLOCK 24000000UL /* Clock consumers of Slow_clock output : AOI0, CMC, CMP0, LPTMR0, WAKETIMER0, WUU0 */ +#define BOARD_BOOTCLOCKFRO96M_SYSTEM_CLOCK 96000000UL /* Clock consumers of System_clock output : ADC0, CMP1, CTIMER0, CTIMER1, CTIMER2, DMA0, FLEXPWM0, FREQME0, GPIO0, GPIO1, GPIO2, GPIO3, I3C0, INPUTMUX0, LPI2C0, LPSPI0, LPSPI1, LPUART0, LPUART1, LPUART2, OSTIMER0, PORT0, PORT1, PORT2, PORT3, QDC0, SWD, SysTick, USB0, UTICK0, WWDT0 */ +#define BOARD_BOOTCLOCKFRO96M_TRACE_CLOCK 96000000UL /* Clock consumers of TRACE_clock output : SWD */ +#define BOARD_BOOTCLOCKFRO96M_USB0_CLOCK 0UL /* Clock consumers of USB0_clock output : USB0 */ +#define BOARD_BOOTCLOCKFRO96M_UTICK_CLOCK 1000000UL /* Clock consumers of UTICK_clock output : UTICK0 */ +#define BOARD_BOOTCLOCKFRO96M_WUU_CLOCK 0UL /* Clock consumers of WUU_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO96M_WWDT0_CLOCK 1000000UL /* Clock consumers of WWDT0_clock output : WWDT0 */ + + +/******************************************************************************* + * 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_mcxa153/board/pin_mux.c b/hw/bsp/mcx/boards/frdm_mcxa153/board/pin_mux.c new file mode 100644 index 000000000..58b0f47e9 --- /dev/null +++ b/hw/bsp/mcx/boards/frdm_mcxa153/board/pin_mux.c @@ -0,0 +1,492 @@ +/* + * Copyright 2025 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. + **********************************************************************************************************************/ + +/* clang-format off */ +/* + * TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* +!!GlobalInfo +product: Pins v17.0 +processor: MCXA153 +package_id: MCXA153VLH +mcu_data: ksdk2_0 +processor_version: 25.09.10 +board: FRDM-MCXA153 +external_user_signals: {} + * 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 ************************************************************************************************************ + * + * Function Name : BOARD_InitBootPins + * Description : Calls initialization functions. + * + * END ****************************************************************************************************************/ +void BOARD_InitBootPins(void) +{ + BOARD_InitDEBUG_UARTPins(); + BOARD_InitLEDsPins(); + BOARD_InitBUTTONsPins(); +} + +/* clang-format off */ +/* + * TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* +BOARD_InitDEBUG_UARTPins: +- options: {callFromInitBoot: 'true', coreID: cm33_core0, enableClock: 'true'} +- pin_list: + - {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: high, pull_select: down, pull_enable: disable, 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 */ + +/* FUNCTION ************************************************************************************************************ + * + * Function Name : BOARD_InitDEBUG_UARTPins + * Description : Configures pin routing and optionally pin electrical features. + * + * END ****************************************************************************************************************/ +void BOARD_InitDEBUG_UARTPins(void) +{ + /* 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 DEBUG_UART_RX = {/* Internal pull-up/down resistor is disabled */ + .pullSelect = kPORT_PullDisable, + /* Low internal pull resistor value is selected. */ + .pullValueSelect = kPORT_LowPullResistor, + /* Fast slew rate is configured */ + .slewRate = kPORT_FastSlewRate, + /* Passive input filter is disabled */ + .passiveFilterEnable = kPORT_PassiveFilterDisable, + /* Open drain output is disabled */ + .openDrainEnable = kPORT_OpenDrainDisable, + /* High drive strength is configured */ + .driveStrength = kPORT_HighDriveStrength, + /* Normal drive strength is configured */ + .driveStrength1 = kPORT_NormalDriveStrength, + /* Pin is configured as LPUART0_RXD */ + .mux = kPORT_MuxAlt2, + /* Digital input enabled */ + .inputBuffer = kPORT_InputBufferEnable, + /* Digital input is not inverted */ + .invertInput = kPORT_InputNormal, + /* Pin Control Register fields [15:0] are not locked */ + .lockRegister = kPORT_UnlockRegister}; + /* PORT0_2 (pin 51) is configured as LPUART0_RXD */ + PORT_SetPinConfig(BOARD_INITDEBUG_UARTPINS_DEBUG_UART_RX_PORT, BOARD_INITDEBUG_UARTPINS_DEBUG_UART_RX_PIN, &DEBUG_UART_RX); + + const port_pin_config_t DEBUG_UART_TX = {/* Internal pull-up resistor is enabled */ + .pullSelect = kPORT_PullUp, + /* Low internal pull resistor value is selected. */ + .pullValueSelect = kPORT_LowPullResistor, + /* Fast slew rate is configured */ + .slewRate = kPORT_FastSlewRate, + /* Passive input filter is disabled */ + .passiveFilterEnable = kPORT_PassiveFilterDisable, + /* Open drain output is disabled */ + .openDrainEnable = kPORT_OpenDrainDisable, + /* Low drive strength is configured */ + .driveStrength = kPORT_LowDriveStrength, + /* Normal drive strength is configured */ + .driveStrength1 = kPORT_NormalDriveStrength, + /* Pin is configured as LPUART0_TXD */ + .mux = kPORT_MuxAlt2, + /* Digital input enabled */ + .inputBuffer = kPORT_InputBufferEnable, + /* Digital input is not inverted */ + .invertInput = kPORT_InputNormal, + /* Pin Control Register fields [15:0] are not locked */ + .lockRegister = kPORT_UnlockRegister}; + /* PORT0_3 (pin 52) is configured as LPUART0_TXD */ + PORT_SetPinConfig(BOARD_INITDEBUG_UARTPINS_DEBUG_UART_TX_PORT, BOARD_INITDEBUG_UARTPINS_DEBUG_UART_TX_PIN, &DEBUG_UART_TX); +} + +/* clang-format off */ +/* + * TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* +BOARD_InitSWD_DEBUGPins: +- options: {callFromInitBoot: 'false', coreID: cm33_core0, enableClock: 'true'} +- pin_list: + - {pin_num: '50', peripheral: SWD, signal: SWCLK, pin_signal: P0_1/TCLK/SWCLK/LPUART0_CTS_B/LPSPI0_SDI/CT_INP1, slew_rate: fast, open_drain: disable, drive_strength: low, + pull_select: down, pull_enable: enable, input_buffer: enable, invert_input: normal} + - {pin_num: '49', peripheral: SWD, signal: SWDIO, pin_signal: P0_0/TMS/SWDIO/LPUART0_RTS_B/LPSPI0_PCS0/CT_INP0, slew_rate: fast, open_drain: disable, drive_strength: high, + pull_select: up, pull_enable: enable, input_buffer: enable, invert_input: normal} + - {pin_num: '51', peripheral: SWD, signal: SWO, pin_signal: P0_2/TDO/SWO/LPUART0_RXD/LPSPI0_SCK/CT0_MAT0/UTICK_CAP0/I3C0_PUR, slew_rate: fast, open_drain: disable, + drive_strength: high, pull_select: down, pull_enable: disable, input_buffer: enable, invert_input: normal} + * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS *********** + */ +/* clang-format on */ + +/* FUNCTION ************************************************************************************************************ + * + * Function Name : BOARD_InitSWD_DEBUGPins + * Description : Configures pin routing and optionally pin electrical features. + * + * END ****************************************************************************************************************/ +void BOARD_InitSWD_DEBUGPins(void) +{ + /* Write to PORT0: Peripheral clock is enabled */ + CLOCK_EnableClock(kCLOCK_GatePORT0); + /* PORT0 peripheral is released from reset */ + RESET_ReleasePeripheralReset(kPORT0_RST_SHIFT_RSTn); + /* LPUART0 peripheral is released from reset */ + RESET_ReleasePeripheralReset(kLPUART0_RST_SHIFT_RSTn); + + const port_pin_config_t DEBUG_SWD_SWDIO = {/* Internal pull-up resistor is enabled */ + .pullSelect = kPORT_PullUp, + /* Low internal pull resistor value is selected. */ + .pullValueSelect = kPORT_LowPullResistor, + /* Fast slew rate is configured */ + .slewRate = kPORT_FastSlewRate, + /* Passive input filter is disabled */ + .passiveFilterEnable = kPORT_PassiveFilterDisable, + /* Open drain output is disabled */ + .openDrainEnable = kPORT_OpenDrainDisable, + /* High drive strength is configured */ + .driveStrength = kPORT_HighDriveStrength, + /* Normal drive strength is configured */ + .driveStrength1 = kPORT_NormalDriveStrength, + /* Pin is configured as SWDIO */ + .mux = kPORT_MuxAlt1, + /* Digital input enabled */ + .inputBuffer = kPORT_InputBufferEnable, + /* Digital input is not inverted */ + .invertInput = kPORT_InputNormal, + /* Pin Control Register fields [15:0] are not locked */ + .lockRegister = kPORT_UnlockRegister}; + /* PORT0_0 (pin 49) is configured as SWDIO */ + PORT_SetPinConfig(BOARD_INITSWD_DEBUGPINS_DEBUG_SWD_SWDIO_PORT, BOARD_INITSWD_DEBUGPINS_DEBUG_SWD_SWDIO_PIN, &DEBUG_SWD_SWDIO); + + const port_pin_config_t DEBUG_SWD_SWDCLK = {/* Internal pull-down resistor is enabled */ + .pullSelect = kPORT_PullDown, + /* Low internal pull resistor value is selected. */ + .pullValueSelect = kPORT_LowPullResistor, + /* Fast slew rate is configured */ + .slewRate = kPORT_FastSlewRate, + /* Passive input filter is disabled */ + .passiveFilterEnable = kPORT_PassiveFilterDisable, + /* Open drain output is disabled */ + .openDrainEnable = kPORT_OpenDrainDisable, + /* Low drive strength is configured */ + .driveStrength = kPORT_LowDriveStrength, + /* Normal drive strength is configured */ + .driveStrength1 = kPORT_NormalDriveStrength, + /* Pin is configured as SWCLK */ + .mux = kPORT_MuxAlt1, + /* Digital input enabled */ + .inputBuffer = kPORT_InputBufferEnable, + /* Digital input is not inverted */ + .invertInput = kPORT_InputNormal, + /* Pin Control Register fields [15:0] are not locked */ + .lockRegister = kPORT_UnlockRegister}; + /* PORT0_1 (pin 50) is configured as SWCLK */ + PORT_SetPinConfig(BOARD_INITSWD_DEBUGPINS_DEBUG_SWD_SWDCLK_PORT, BOARD_INITSWD_DEBUGPINS_DEBUG_SWD_SWDCLK_PIN, &DEBUG_SWD_SWDCLK); + + const port_pin_config_t DEBUG_UART_RX = {/* Internal pull-up/down resistor is disabled */ + .pullSelect = kPORT_PullDisable, + /* Low internal pull resistor value is selected. */ + .pullValueSelect = kPORT_LowPullResistor, + /* Fast slew rate is configured */ + .slewRate = kPORT_FastSlewRate, + /* Passive input filter is disabled */ + .passiveFilterEnable = kPORT_PassiveFilterDisable, + /* Open drain output is disabled */ + .openDrainEnable = kPORT_OpenDrainDisable, + /* High drive strength is configured */ + .driveStrength = kPORT_HighDriveStrength, + /* Normal drive strength is configured */ + .driveStrength1 = kPORT_NormalDriveStrength, + /* Pin is configured as SWO */ + .mux = kPORT_MuxAlt1, + /* Digital input enabled */ + .inputBuffer = kPORT_InputBufferEnable, + /* Digital input is not inverted */ + .invertInput = kPORT_InputNormal, + /* Pin Control Register fields [15:0] are not locked */ + .lockRegister = kPORT_UnlockRegister}; + /* PORT0_2 (pin 51) is configured as SWO */ + PORT_SetPinConfig(BOARD_INITSWD_DEBUGPINS_DEBUG_UART_RX_PORT, BOARD_INITSWD_DEBUGPINS_DEBUG_UART_RX_PIN, &DEBUG_UART_RX); +} + +/* clang-format off */ +/* + * TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* +BOARD_InitLEDsPins: +- options: {callFromInitBoot: 'true', coreID: cm33_core0, enableClock: 'true'} +- pin_list: + - {pin_num: '37', peripheral: GPIO3, signal: 'GPIO, 13', pin_signal: P3_13/LPUART2_CTS_B/CT1_MAT3/PWM0_X1, direction: OUTPUT, gpio_init_state: 'true', slew_rate: fast, + open_drain: disable, drive_strength: low, pull_select: up, pull_enable: disable, input_buffer: enable, invert_input: normal} + - {pin_num: '38', peripheral: GPIO3, signal: 'GPIO, 12', pin_signal: P3_12/LPUART2_RTS_B/CT1_MAT2/PWM0_X0, direction: OUTPUT, gpio_init_state: 'true', slew_rate: fast, + open_drain: disable, drive_strength: low, pull_select: up, pull_enable: disable, input_buffer: enable, invert_input: normal} + - {pin_num: '46', peripheral: GPIO3, signal: 'GPIO, 0', pin_signal: P3_0/WUU0_IN22/TRIG_IN0/CT_INP16/PWM0_A0, direction: OUTPUT, gpio_init_state: 'true', slew_rate: fast, + open_drain: disable, drive_strength: low, pull_select: up, pull_enable: disable, passive_filter: disable, input_buffer: enable, invert_input: normal} + * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS *********** + */ +/* clang-format on */ + +/* FUNCTION ************************************************************************************************************ + * + * Function Name : BOARD_InitLEDsPins + * Description : Configures pin routing and optionally pin electrical features. + * + * END ****************************************************************************************************************/ +void BOARD_InitLEDsPins(void) +{ + /* Write to GPIO3: Peripheral clock is enabled */ + CLOCK_EnableClock(kCLOCK_GateGPIO3); + /* Write to 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); + + gpio_pin_config_t LED_BLUE_config = { + .pinDirection = kGPIO_DigitalOutput, + .outputLogic = 1U + }; + /* Initialize GPIO functionality on pin PIO3_0 (pin 46) */ + GPIO_PinInit(BOARD_INITLEDSPINS_LED_BLUE_GPIO, BOARD_INITLEDSPINS_LED_BLUE_PIN, &LED_BLUE_config); + + gpio_pin_config_t LED_RED_config = { + .pinDirection = kGPIO_DigitalOutput, + .outputLogic = 1U + }; + /* Initialize GPIO functionality on pin PIO3_12 (pin 38) */ + GPIO_PinInit(BOARD_INITLEDSPINS_LED_RED_GPIO, BOARD_INITLEDSPINS_LED_RED_PIN, &LED_RED_config); + + gpio_pin_config_t LED_GREEN_config = { + .pinDirection = kGPIO_DigitalOutput, + .outputLogic = 1U + }; + /* Initialize GPIO functionality on pin PIO3_13 (pin 37) */ + GPIO_PinInit(BOARD_INITLEDSPINS_LED_GREEN_GPIO, BOARD_INITLEDSPINS_LED_GREEN_PIN, &LED_GREEN_config); + + /* PORT3_0 (pin 46) is configured as P3_0 */ + PORT_SetPinMux(BOARD_INITLEDSPINS_LED_BLUE_PORT, BOARD_INITLEDSPINS_LED_BLUE_PIN, kPORT_MuxAlt0); + + PORT3->PCR[0] = + ((PORT3->PCR[0] & + /* Mask bits to zero which are setting */ + (~(PORT_PCR_PS_MASK | PORT_PCR_PE_MASK | PORT_PCR_SRE_MASK | PORT_PCR_PFE_MASK | PORT_PCR_ODE_MASK | PORT_PCR_DSE_MASK | PORT_PCR_IBE_MASK | PORT_PCR_INV_MASK))) + + /* Pull Select: Enables internal pullup resistor. */ + | PORT_PCR_PS(PCR_PS_ps1) + + /* Pull Enable: Disables. */ + | PORT_PCR_PE(PCR_PE_pe0) + + /* Slew Rate Enable: Fast. */ + | PORT_PCR_SRE(PCR_SRE_sre0) + + /* Passive Filter Enable: Disables. */ + | PORT_PCR_PFE(PCR_PFE_pfe0) + + /* Open Drain Enable: Disables. */ + | PORT_PCR_ODE(PCR_ODE_ode0) + + /* Drive Strength Enable: Low. */ + | PORT_PCR_DSE(PCR_DSE_dse0) + + /* Input Buffer Enable: Enables. */ + | PORT_PCR_IBE(PCR_IBE_ibe1) + + /* Invert Input: Does not invert. */ + | PORT_PCR_INV(PCR_INV_inv0)); + + /* PORT3_12 (pin 38) is configured as P3_12 */ + PORT_SetPinMux(BOARD_INITLEDSPINS_LED_RED_PORT, BOARD_INITLEDSPINS_LED_RED_PIN, kPORT_MuxAlt0); + + PORT3->PCR[12] = + ((PORT3->PCR[12] & + /* Mask bits to zero which are setting */ + (~(PORT_PCR_PS_MASK | PORT_PCR_PE_MASK | PORT_PCR_SRE_MASK | PORT_PCR_ODE_MASK | PORT_PCR_DSE_MASK | PORT_PCR_IBE_MASK | PORT_PCR_INV_MASK))) + + /* Pull Select: Enables internal pullup resistor. */ + | PORT_PCR_PS(PCR_PS_ps1) + + /* Pull Enable: Disables. */ + | PORT_PCR_PE(PCR_PE_pe0) + + /* Slew Rate Enable: Fast. */ + | PORT_PCR_SRE(PCR_SRE_sre0) + + /* Open Drain Enable: Disables. */ + | PORT_PCR_ODE(PCR_ODE_ode0) + + /* Drive Strength Enable: Low. */ + | PORT_PCR_DSE(PCR_DSE_dse0) + + /* Input Buffer Enable: Enables. */ + | PORT_PCR_IBE(PCR_IBE_ibe1) + + /* Invert Input: Does not invert. */ + | PORT_PCR_INV(PCR_INV_inv0)); + + /* PORT3_13 (pin 37) is configured as P3_13 */ + PORT_SetPinMux(BOARD_INITLEDSPINS_LED_GREEN_PORT, BOARD_INITLEDSPINS_LED_GREEN_PIN, kPORT_MuxAlt0); + + PORT3->PCR[13] = + ((PORT3->PCR[13] & + /* Mask bits to zero which are setting */ + (~(PORT_PCR_PS_MASK | PORT_PCR_PE_MASK | PORT_PCR_SRE_MASK | PORT_PCR_ODE_MASK | PORT_PCR_DSE_MASK | PORT_PCR_IBE_MASK | PORT_PCR_INV_MASK))) + + /* Pull Select: Enables internal pullup resistor. */ + | PORT_PCR_PS(PCR_PS_ps1) + + /* Pull Enable: Disables. */ + | PORT_PCR_PE(PCR_PE_pe0) + + /* Slew Rate Enable: Fast. */ + | PORT_PCR_SRE(PCR_SRE_sre0) + + /* Open Drain Enable: Disables. */ + | PORT_PCR_ODE(PCR_ODE_ode0) + + /* Drive Strength Enable: Low. */ + | PORT_PCR_DSE(PCR_DSE_dse0) + + /* Input Buffer Enable: Enables. */ + | PORT_PCR_IBE(PCR_IBE_ibe1) + + /* Invert Input: Does not invert. */ + | PORT_PCR_INV(PCR_INV_inv0)); +} + +/* clang-format off */ +/* + * TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* +BOARD_InitBUTTONsPins: +- options: {callFromInitBoot: 'true', coreID: cm33_core0, enableClock: 'true'} +- pin_list: + - {pin_num: '1', peripheral: GPIO1, signal: 'GPIO, 7', pin_signal: P1_7/WUU0_IN9/TRIG_OUT2/LPUART2_CTS_B/CT_INP7/ADC0_A23, slew_rate: fast, open_drain: disable, + drive_strength: low, pull_select: down, pull_enable: disable, input_buffer: enable, invert_input: normal} + - {pin_num: '8', peripheral: GPIO1, signal: 'GPIO, 29', pin_signal: P1_29/RESET_B/SPC_LPREQ, slew_rate: fast, open_drain: enable, drive_strength: low, pull_select: up, + pull_enable: enable, passive_filter: enable, pull_value: low, input_buffer: enable, invert_input: normal} + - {pin_num: '32', peripheral: GPIO3, signal: 'GPIO, 29', pin_signal: P3_29/WUU0_IN27/ISPMODE_N/CT_INP3/ADC0_A14, 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_InitBUTTONsPins + * Description : Configures pin routing and optionally pin electrical features. + * + * END ****************************************************************************************************************/ +void BOARD_InitBUTTONsPins(void) +{ + /* Write to PORT1: Peripheral clock is enabled */ + CLOCK_EnableClock(kCLOCK_GatePORT1); + /* Write to PORT3: Peripheral clock is enabled */ + CLOCK_EnableClock(kCLOCK_GatePORT3); + /* GPIO1 peripheral is released from reset */ + RESET_ReleasePeripheralReset(kGPIO1_RST_SHIFT_RSTn); + /* PORT1 peripheral is released from reset */ + RESET_ReleasePeripheralReset(kPORT1_RST_SHIFT_RSTn); + /* GPIO3 peripheral is released from reset */ + RESET_ReleasePeripheralReset(kGPIO3_RST_SHIFT_RSTn); + /* PORT3 peripheral is released from reset */ + RESET_ReleasePeripheralReset(kPORT3_RST_SHIFT_RSTn); + + const port_pin_config_t SW1 = {/* Internal pull-up resistor is enabled */ + .pullSelect = kPORT_PullUp, + /* Low internal pull resistor value is selected. */ + .pullValueSelect = kPORT_LowPullResistor, + /* Fast slew rate is configured */ + .slewRate = kPORT_FastSlewRate, + /* Passive input filter is enabled */ + .passiveFilterEnable = kPORT_PassiveFilterEnable, + /* Open drain output is enabled */ + .openDrainEnable = kPORT_OpenDrainEnable, + /* Low drive strength is configured */ + .driveStrength = kPORT_LowDriveStrength, + /* Normal drive strength is configured */ + .driveStrength1 = kPORT_NormalDriveStrength, + /* Pin is configured as P1_29 */ + .mux = kPORT_MuxAlt0, + /* Digital input enabled */ + .inputBuffer = kPORT_InputBufferEnable, + /* Digital input is not inverted */ + .invertInput = kPORT_InputNormal, + /* Pin Control Register fields [15:0] are not locked */ + .lockRegister = kPORT_UnlockRegister}; + /* PORT1_29 (pin 8) is configured as P1_29 */ + PORT_SetPinConfig(BOARD_INITBUTTONSPINS_SW1_PORT, BOARD_INITBUTTONSPINS_SW1_PIN, &SW1); + + const port_pin_config_t SW3 = {/* Internal pull-up/down resistor is disabled */ + .pullSelect = kPORT_PullDisable, + /* Low internal pull resistor value is selected. */ + .pullValueSelect = kPORT_LowPullResistor, + /* Fast slew rate is configured */ + .slewRate = kPORT_FastSlewRate, + /* Passive input filter is disabled */ + .passiveFilterEnable = kPORT_PassiveFilterDisable, + /* Open drain output is disabled */ + .openDrainEnable = kPORT_OpenDrainDisable, + /* Low drive strength is configured */ + .driveStrength = kPORT_LowDriveStrength, + /* Normal drive strength is configured */ + .driveStrength1 = kPORT_NormalDriveStrength, + /* Pin is configured as P1_7 */ + .mux = kPORT_MuxAlt0, + /* Digital input enabled */ + .inputBuffer = kPORT_InputBufferEnable, + /* Digital input is not inverted */ + .invertInput = kPORT_InputNormal, + /* Pin Control Register fields [15:0] are not locked */ + .lockRegister = kPORT_UnlockRegister}; + /* PORT1_7 (pin 1) is configured as P1_7 */ + PORT_SetPinConfig(BOARD_INITBUTTONSPINS_SW3_PORT, BOARD_INITBUTTONSPINS_SW3_PIN, &SW3); + + const port_pin_config_t ISP = {/* Internal pull-up resistor is enabled */ + .pullSelect = kPORT_PullUp, + /* Low internal pull resistor value is selected. */ + .pullValueSelect = kPORT_LowPullResistor, + /* Fast slew rate is configured */ + .slewRate = kPORT_FastSlewRate, + /* Passive input filter is disabled */ + .passiveFilterEnable = kPORT_PassiveFilterDisable, + /* Open drain output is disabled */ + .openDrainEnable = kPORT_OpenDrainDisable, + /* Low drive strength is configured */ + .driveStrength = kPORT_LowDriveStrength, + /* Normal drive strength is configured */ + .driveStrength1 = kPORT_NormalDriveStrength, + /* Pin is configured as P3_29 */ + .mux = kPORT_MuxAlt0, + /* Digital input enabled */ + .inputBuffer = kPORT_InputBufferEnable, + /* Digital input is not inverted */ + .invertInput = kPORT_InputNormal, + /* Pin Control Register fields [15:0] are not locked */ + .lockRegister = kPORT_UnlockRegister}; + /* PORT3_29 (pin 32) is configured as P3_29 */ + PORT_SetPinConfig(BOARD_INITBUTTONSPINS_ISP_PORT, BOARD_INITBUTTONSPINS_ISP_PIN, &ISP); +} +/*********************************************************************************************************************** + * EOF + **********************************************************************************************************************/ diff --git a/hw/bsp/mcx/boards/frdm_mcxa153/board/pin_mux.h b/hw/bsp/mcx/boards/frdm_mcxa153/board/pin_mux.h new file mode 100644 index 000000000..4a42f266d --- /dev/null +++ b/hw/bsp/mcx/boards/frdm_mcxa153/board/pin_mux.h @@ -0,0 +1,211 @@ +/* + * Copyright 2025 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_ + +/*! + * @addtogroup pin_mux + * @{ + */ + +/*********************************************************************************************************************** + * API + **********************************************************************************************************************/ + +#if defined(__cplusplus) +extern "C" { +#endif + +/*! + * @brief Calls initialization functions. + * + */ +void BOARD_InitBootPins(void); + +/*! @name PORT0_2 (number 51), P0_2/SWO/J25[3]/J18[6] + @{ */ + +/* Symbols to be used with PORT driver */ +#define BOARD_INITDEBUG_UARTPINS_DEBUG_UART_RX_PORT PORT0 /*!<@brief PORT peripheral base pointer */ +#define BOARD_INITDEBUG_UARTPINS_DEBUG_UART_RX_PIN 2U /*!<@brief PORT pin number */ +#define BOARD_INITDEBUG_UARTPINS_DEBUG_UART_RX_PIN_MASK (1U << 2U) /*!<@brief PORT pin mask */ + /* @} */ + +/*! @name PORT0_3 (number 52), P0_3/J25[1]/J18[8] + @{ */ + +/* Symbols to be used with PORT driver */ +#define BOARD_INITDEBUG_UARTPINS_DEBUG_UART_TX_PORT PORT0 /*!<@brief PORT peripheral base pointer */ +#define BOARD_INITDEBUG_UARTPINS_DEBUG_UART_TX_PIN 3U /*!<@brief PORT pin number */ +#define BOARD_INITDEBUG_UARTPINS_DEBUG_UART_TX_PIN_MASK (1U << 3U) /*!<@brief PORT pin mask */ + /* @} */ + +/*! + * @brief Configures pin routing and optionally pin electrical features. + * + */ +void BOARD_InitDEBUG_UARTPins(void); + +/*! @name PORT0_1 (number 50), P0_1/SWCLK/JP10[2]/J18[4] + @{ */ + +/* Symbols to be used with PORT driver */ +#define BOARD_INITSWD_DEBUGPINS_DEBUG_SWD_SWDCLK_PORT PORT0 /*!<@brief PORT peripheral base pointer */ +#define BOARD_INITSWD_DEBUGPINS_DEBUG_SWD_SWDCLK_PIN 1U /*!<@brief PORT pin number */ +#define BOARD_INITSWD_DEBUGPINS_DEBUG_SWD_SWDCLK_PIN_MASK (1U << 1U) /*!<@brief PORT pin mask */ + /* @} */ + +/*! @name PORT0_0 (number 49), P0_0/SWDIO/J18[2] + @{ */ + +/* Symbols to be used with PORT driver */ +#define BOARD_INITSWD_DEBUGPINS_DEBUG_SWD_SWDIO_PORT PORT0 /*!<@brief PORT peripheral base pointer */ +#define BOARD_INITSWD_DEBUGPINS_DEBUG_SWD_SWDIO_PIN 0U /*!<@brief PORT pin number */ +#define BOARD_INITSWD_DEBUGPINS_DEBUG_SWD_SWDIO_PIN_MASK (1U << 0U) /*!<@brief PORT pin mask */ + /* @} */ + +/*! @name PORT0_2 (number 51), P0_2/SWO/J25[3]/J18[6] + @{ */ + +/* Symbols to be used with PORT driver */ +#define BOARD_INITSWD_DEBUGPINS_DEBUG_UART_RX_PORT PORT0 /*!<@brief PORT peripheral base pointer */ +#define BOARD_INITSWD_DEBUGPINS_DEBUG_UART_RX_PIN 2U /*!<@brief PORT pin number */ +#define BOARD_INITSWD_DEBUGPINS_DEBUG_UART_RX_PIN_MASK (1U << 2U) /*!<@brief PORT pin mask */ + /* @} */ + +/*! + * @brief Configures pin routing and optionally pin electrical features. + * + */ +void BOARD_InitSWD_DEBUGPins(void); + +#define PCR_DSE_dse0 0x00u /*!<@brief Drive Strength Enable: Low */ +#define PCR_IBE_ibe1 0x01u /*!<@brief Input Buffer Enable: Enables */ +#define PCR_INV_inv0 0x00u /*!<@brief Invert Input: Does not invert */ +#define PCR_ODE_ode0 0x00u /*!<@brief Open Drain Enable: Disables */ +#define PCR_PE_pe0 0x00u /*!<@brief Pull Enable: Disables */ +#define PCR_PFE_pfe0 0x00u /*!<@brief Passive Filter Enable: Disables */ +#define PCR_PS_ps1 0x01u /*!<@brief Pull Select: Enables internal pullup resistor */ +#define PCR_SRE_sre0 0x00u /*!<@brief Slew Rate Enable: Fast */ + +/*! @name PORT3_13 (number 37), P3_13/J1[14] + @{ */ + +/* Symbols to be used with GPIO driver */ +#define BOARD_INITLEDSPINS_LED_GREEN_GPIO GPIO3 /*!<@brief GPIO peripheral base pointer */ +#define BOARD_INITLEDSPINS_LED_GREEN_INIT_GPIO_VALUE 1U /*!<@brief GPIO output initial state */ +#define BOARD_INITLEDSPINS_LED_GREEN_GPIO_PIN 13U /*!<@brief GPIO pin number */ +#define BOARD_INITLEDSPINS_LED_GREEN_GPIO_PIN_MASK (1U << 13U) /*!<@brief GPIO pin mask */ + +/* Symbols to be used with PORT driver */ +#define BOARD_INITLEDSPINS_LED_GREEN_PORT PORT3 /*!<@brief PORT peripheral base pointer */ +#define BOARD_INITLEDSPINS_LED_GREEN_PIN 13U /*!<@brief PORT pin number */ +#define BOARD_INITLEDSPINS_LED_GREEN_PIN_MASK (1U << 13U) /*!<@brief PORT pin mask */ + /* @} */ + +/*! @name PORT3_12 (number 38), P3_12/J1[12]/J5[1] + @{ */ + +/* Symbols to be used with GPIO driver */ +#define BOARD_INITLEDSPINS_LED_RED_GPIO GPIO3 /*!<@brief GPIO peripheral base pointer */ +#define BOARD_INITLEDSPINS_LED_RED_INIT_GPIO_VALUE 1U /*!<@brief GPIO output initial state */ +#define BOARD_INITLEDSPINS_LED_RED_GPIO_PIN 12U /*!<@brief GPIO pin number */ +#define BOARD_INITLEDSPINS_LED_RED_GPIO_PIN_MASK (1U << 12U) /*!<@brief GPIO pin mask */ + +/* Symbols to be used with PORT driver */ +#define BOARD_INITLEDSPINS_LED_RED_PORT PORT3 /*!<@brief PORT peripheral base pointer */ +#define BOARD_INITLEDSPINS_LED_RED_PIN 12U /*!<@brief PORT pin number */ +#define BOARD_INITLEDSPINS_LED_RED_PIN_MASK (1U << 12U) /*!<@brief PORT pin mask */ + /* @} */ + +/*! @name PORT3_0 (number 46), P3_0/J1[8] + @{ */ + +/* Symbols to be used with GPIO driver */ +#define BOARD_INITLEDSPINS_LED_BLUE_GPIO GPIO3 /*!<@brief GPIO peripheral base pointer */ +#define BOARD_INITLEDSPINS_LED_BLUE_INIT_GPIO_VALUE 1U /*!<@brief GPIO output initial state */ +#define BOARD_INITLEDSPINS_LED_BLUE_GPIO_PIN 0U /*!<@brief GPIO pin number */ +#define BOARD_INITLEDSPINS_LED_BLUE_GPIO_PIN_MASK (1U << 0U) /*!<@brief GPIO pin mask */ + +/* Symbols to be used with PORT driver */ +#define BOARD_INITLEDSPINS_LED_BLUE_PORT PORT3 /*!<@brief PORT peripheral base pointer */ +#define BOARD_INITLEDSPINS_LED_BLUE_PIN 0U /*!<@brief PORT pin number */ +#define BOARD_INITLEDSPINS_LED_BLUE_PIN_MASK (1U << 0U) /*!<@brief PORT pin mask */ + /* @} */ + +/*! + * @brief Configures pin routing and optionally pin electrical features. + * + */ +void BOARD_InitLEDsPins(void); + +/*! @name PORT1_7 (number 1), P1_7/J1[1] + @{ */ + +/* Symbols to be used with GPIO driver */ +#define BOARD_INITBUTTONSPINS_SW3_GPIO GPIO1 /*!<@brief GPIO peripheral base pointer */ +#define BOARD_INITBUTTONSPINS_SW3_GPIO_PIN 7U /*!<@brief GPIO pin number */ +#define BOARD_INITBUTTONSPINS_SW3_GPIO_PIN_MASK (1U << 7U) /*!<@brief GPIO pin mask */ + +/* Symbols to be used with PORT driver */ +#define BOARD_INITBUTTONSPINS_SW3_PORT PORT1 /*!<@brief PORT peripheral base pointer */ +#define BOARD_INITBUTTONSPINS_SW3_PIN 7U /*!<@brief PORT pin number */ +#define BOARD_INITBUTTONSPINS_SW3_PIN_MASK (1U << 7U) /*!<@brief PORT pin mask */ + /* @} */ + +/*! @name PORT1_29 (number 8), P1_29/J3[6]/J18[10] + @{ */ + +/* Symbols to be used with GPIO driver */ +#define BOARD_INITBUTTONSPINS_SW1_GPIO GPIO1 /*!<@brief GPIO peripheral base pointer */ +#define BOARD_INITBUTTONSPINS_SW1_GPIO_PIN 29U /*!<@brief GPIO pin number */ +#define BOARD_INITBUTTONSPINS_SW1_GPIO_PIN_MASK (1U << 29U) /*!<@brief GPIO pin mask */ + +/* Symbols to be used with PORT driver */ +#define BOARD_INITBUTTONSPINS_SW1_PORT PORT1 /*!<@brief PORT peripheral base pointer */ +#define BOARD_INITBUTTONSPINS_SW1_PIN 29U /*!<@brief PORT pin number */ +#define BOARD_INITBUTTONSPINS_SW1_PIN_MASK (1U << 29U) /*!<@brief PORT pin mask */ + /* @} */ + +/*! @name PORT3_29 (number 32), P3_29/J18[7]/J4[11] + @{ */ + +/* Symbols to be used with GPIO driver */ +#define BOARD_INITBUTTONSPINS_ISP_GPIO GPIO3 /*!<@brief GPIO peripheral base pointer */ +#define BOARD_INITBUTTONSPINS_ISP_GPIO_PIN 29U /*!<@brief GPIO pin number */ +#define BOARD_INITBUTTONSPINS_ISP_GPIO_PIN_MASK (1U << 29U) /*!<@brief GPIO pin mask */ + +/* Symbols to be used with PORT driver */ +#define BOARD_INITBUTTONSPINS_ISP_PORT PORT3 /*!<@brief PORT peripheral base pointer */ +#define BOARD_INITBUTTONSPINS_ISP_PIN 29U /*!<@brief PORT pin number */ +#define BOARD_INITBUTTONSPINS_ISP_PIN_MASK (1U << 29U) /*!<@brief PORT pin mask */ + /* @} */ + +/*! + * @brief Configures pin routing and optionally pin electrical features. + * + */ +void BOARD_InitBUTTONsPins(void); + +#if defined(__cplusplus) +} +#endif + +/*! + * @} + */ +#endif /* _PIN_MUX_H_ */ + +/*********************************************************************************************************************** + * EOF + **********************************************************************************************************************/ diff --git a/hw/bsp/mcx/boards/frdm_mcxa153/clock_config.c b/hw/bsp/mcx/boards/frdm_mcxa153/clock_config.c deleted file mode 100644 index 5a132dc67..000000000 --- a/hw/bsp/mcx/boards/frdm_mcxa153/clock_config.c +++ /dev/null @@ -1,466 +0,0 @@ -/* - * 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. - **********************************************************************************************************************/ -/* - * 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 v12.0 -processor: MCXA153 -package_id: MCXA153VLH -mcu_data: ksdk2_0 -processor_version: 0.13.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) -{ -} - -/******************************************************************************* - ******************** 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} -settings: -- {id: SCGMode, value: SIRC} -- {id: FRO_HF_PERIPHERALS_EN_CFG, value: Disabled} -- {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} -settings: -- {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} -settings: -- {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} -settings: -- {id: VDD_CORE, value: voltage_1v1} -- {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 -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} -settings: -- {id: VDD_CORE, value: voltage_1v1} -- {id: CLKOUTDIV_HALT, value: Enable} -- {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_mcxa153/clock_config.h b/hw/bsp/mcx/boards/frdm_mcxa153/clock_config.h deleted file mode 100644 index aae811052..000000000 --- a/hw/bsp/mcx/boards/frdm_mcxa153/clock_config.h +++ /dev/null @@ -1,170 +0,0 @@ -/* - * 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 _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_mcxa153/frdm_mcxa153.mex b/hw/bsp/mcx/boards/frdm_mcxa153/frdm_mcxa153.mex new file mode 100644 index 000000000..43fea73db --- /dev/null +++ b/hw/bsp/mcx/boards/frdm_mcxa153/frdm_mcxa153.mex @@ -0,0 +1,573 @@ + + + + MCXA153 + MCXA153VLH + FRDM-MCXA153 + ksdk2_0 + + + + + + + true + false + + /* + * Copyright 2025 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + true + + true + true + false + + + + + + + + + 25.09.10 + + + + + + + Configures pin routing and optionally pin electrical features. + + true + cm33_core0 + true + + + + + true + + + + + true + + + + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Configures pin routing and optionally pin electrical features. + + false + cm33_core0 + true + + + + + true + + + + + true + + + + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Configures pin routing and optionally pin electrical features. + + true + cm33_core0 + true + + + + + true + + + + + true + + + + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Configures pin routing and optionally pin electrical features. + + true + cm33_core0 + true + + + + + true + + + + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 25.09.10 + + + + + + + + + true + + + + + true + + + + + true + + + + + + + + + + + + + + + + + + + + + + + + false + + + + + + + + true + + + + + true + + + + + true + + + + + + + + + + + + + + + + + + + + + + + + + false + + + + + + + + true + + + + + true + + + + + true + + + + + + + + + + + + + + + + + + + + + + + + false + + + + + + + + true + + + + + true + + + + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + + + + + + + + true + + + + + true + + + + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + true + + + + + + + N/A + + + + + + + + + + 25.09.10 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + N/A + + + + diff --git a/hw/bsp/mcx/boards/frdm_mcxa153/pin_mux.c b/hw/bsp/mcx/boards/frdm_mcxa153/pin_mux.c deleted file mode 100644 index 47709951b..000000000 --- a/hw/bsp/mcx/boards/frdm_mcxa153/pin_mux.c +++ /dev/null @@ -1,130 +0,0 @@ -/* - * 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. - **********************************************************************************************************************/ - -/* clang-format off */ -/* - * TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* -!!GlobalInfo -product: Pins v14.0 -processor: MCXA153 -package_id: MCXA153VLH -mcu_data: ksdk2_0 -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 "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: '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 */ - -/* FUNCTION ************************************************************************************************************ - * - * Function Name : BOARD_InitPins - * Description : Configures pin routing and optionally pin electrical features. - * - * END ****************************************************************************************************************/ -void BOARD_InitPins(void) -{ - CLOCK_EnableClock(kCLOCK_GateGPIO3); - /* Write to 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); - - - /* 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, - /* 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 51) is configured as LPUART0_RXD */ - PORT_SetPinConfig(PORT0, 2U, &port0_2_pin51_config); - - const port_pin_config_t port0_3_pin52_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 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 deleted file mode 100644 index 2c0e617a5..000000000 --- a/hw/bsp/mcx/boards/frdm_mcxa153/pin_mux.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * 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_ - -/*! - * @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/family.c b/hw/bsp/mcx/family.c index 2dfefeb92..e1accf941 100644 --- a/hw/bsp/mcx/family.c +++ b/hw/bsp/mcx/family.c @@ -61,14 +61,9 @@ void USB0_IRQHandler(void) { void board_init(void) { - BOARD_InitPins(); - + BOARD_InitBootPins(); BOARD_InitBootClocks(); - #ifdef XTAL0_CLK_HZ - CLOCK_SetupExtClocking(XTAL0_CLK_HZ); - #endif - #if CFG_TUSB_OS == OPT_OS_NONE // 1ms tick timer SysTick_Config(SystemCoreClock / 1000); diff --git a/hw/bsp/mcx/family.mk b/hw/bsp/mcx/family.mk index a16f4b6c0..4321e654a 100644 --- a/hw/bsp/mcx/family.mk +++ b/hw/bsp/mcx/family.mk @@ -11,7 +11,7 @@ CFLAGS += \ -DBOARD_TUD_RHPORT=$(PORT) \ # mcu driver cause following warnings -CFLAGS += -Wno-error=unused-parameter -Wno-error=old-style-declaration +CFLAGS += -Wno-error=unused-parameter -Wno-error=old-style-declaration -Wno-error=redundant-decls LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs @@ -56,12 +56,9 @@ INC += \ $(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 - - - + $(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/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index 05ae6929c..002cd3a0e 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -543,6 +543,10 @@ #define TUP_RHPORT_HIGHSPEED CFG_TUD_WCH_USBIP_USBHS #define TUP_DCD_ENDPOINT_MAX (CFG_TUD_WCH_USBIP_USBHS ? 16 : 8) + #if CFG_TUD_WCH_USBIP_USBHS + #define TUP_DCD_EDPT_CLOSE_API + #endif + #elif TU_CHECK_MCU(OPT_MCU_CH32V103) #define TUP_USBIP_WCH_USBFS @@ -590,6 +594,10 @@ #define TUP_RHPORT_HIGHSPEED CFG_TUD_WCH_USBIP_USBHS #define TUP_DCD_ENDPOINT_MAX (CFG_TUD_WCH_USBIP_USBHS ? 16 : 8) + #if CFG_TUD_WCH_USBIP_USBHS + #define TUP_DCD_EDPT_CLOSE_API + #endif + //--------------------------------------------------------------------+ // Analog Devices //--------------------------------------------------------------------+ @@ -681,8 +689,7 @@ #define TU_ATTR_FAST_FUNC #endif -#if defined(TUP_USBIP_CHIPIDEA_FS) || defined(TUP_USBIP_IP3511) || defined(TUP_USBIP_RUSB2) || \ - (defined(TUP_USBIP_WCH_USBFS) && CFG_TUD_WCH_USBIP_USBFS) +#if defined(TUP_USBIP_IP3511) || defined(TUP_USBIP_RUSB2) #define TUP_DCD_EDPT_CLOSE_API #endif diff --git a/src/portable/chipidea/ci_fs/dcd_ci_fs.c b/src/portable/chipidea/ci_fs/dcd_ci_fs.c index 8b5c42aa2..40ad4cf82 100644 --- a/src/portable/chipidea/ci_fs/dcd_ci_fs.c +++ b/src/portable/chipidea/ci_fs/dcd_ci_fs.c @@ -344,24 +344,21 @@ void dcd_sof_enable(uint8_t rhport, bool en) //--------------------------------------------------------------------+ // Endpoint API //--------------------------------------------------------------------+ -bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) -{ - (void) rhport; - - const unsigned ep_addr = ep_desc->bEndpointAddress; - const unsigned epn = tu_edpt_number(ep_addr); - const unsigned dir = tu_edpt_dir(ep_addr); - const unsigned xfer = ep_desc->bmAttributes.xfer; - endpoint_state_t *ep = &_dcd.endpoint[epn][dir]; - const unsigned odd = ep->odd; - buffer_descriptor_t *bd = _dcd.bdt[epn][dir]; +static bool edpt_open(uint8_t rhport, uint8_t ep_addr, uint16_t max_packet_size, tusb_xfer_type_t xfer) { + (void)rhport; + const unsigned epn = tu_edpt_number(ep_addr); + const unsigned dir = tu_edpt_dir(ep_addr); + endpoint_state_t *ep = &_dcd.endpoint[epn][dir]; + const unsigned odd = ep->odd; + buffer_descriptor_t *bd = _dcd.bdt[epn][dir]; /* No support for control transfer */ TU_ASSERT(epn && (xfer != TUSB_XFER_CONTROL)); - ep->max_packet_size = tu_edpt_packet_size(ep_desc); + ep->max_packet_size = max_packet_size; + unsigned val = USB_ENDPT_EPCTLDIS_MASK; - val |= (xfer != TUSB_XFER_ISOCHRONOUS) ? USB_ENDPT_EPHSHK_MASK: 0; + val |= (xfer != TUSB_XFER_ISOCHRONOUS) ? USB_ENDPT_EPHSHK_MASK : 0; val |= dir ? USB_ENDPT_EPTXEN_MASK : USB_ENDPT_EPRXEN_MASK; CI_REG->EP[epn].CTL |= val; @@ -375,8 +372,27 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) return true; } -void dcd_edpt_close_all(uint8_t rhport) -{ +bool dcd_edpt_open(uint8_t rhport, const tusb_desc_endpoint_t *ep_desc) { + return edpt_open(rhport, ep_desc->bEndpointAddress, tu_edpt_packet_size(ep_desc), ep_desc->bmAttributes.xfer); +} + +bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { + return edpt_open(rhport, ep_addr, largest_packet_size, TUSB_XFER_ISOCHRONOUS); +} + +bool dcd_edpt_iso_activate(uint8_t rhport, const tusb_desc_endpoint_t *ep_desc) { + const unsigned epn = tu_edpt_number(ep_desc->bEndpointAddress); + const unsigned dir = tu_edpt_dir(ep_desc->bEndpointAddress); + endpoint_state_t *ep = &_dcd.endpoint[epn][dir]; + + dcd_int_disable(rhport); + ep->max_packet_size = tu_edpt_packet_size(ep_desc); + dcd_int_enable(rhport); + + return true; +} + +void dcd_edpt_close_all(uint8_t rhport) { dcd_int_disable(rhport); for (unsigned i = 1; i < 16; ++i) { @@ -399,43 +415,6 @@ void dcd_edpt_close_all(uint8_t rhport) } } -#ifdef TUP_DCD_EDPT_CLOSE_API -void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) -{ - const unsigned epn = tu_edpt_number(ep_addr); - const unsigned dir = tu_edpt_dir(ep_addr); - endpoint_state_t *ep = &_dcd.endpoint[epn][dir]; - buffer_descriptor_t *bd = _dcd.bdt[epn][dir]; - const unsigned msk = dir ? USB_ENDPT_EPTXEN_MASK : USB_ENDPT_EPRXEN_MASK; - - dcd_int_disable(rhport); - - CI_REG->EP[epn].CTL &= ~msk; - ep->max_packet_size = 0; - ep->length = 0; - ep->remaining = 0; - bd[0].head = 0; - bd[1].head = 0; - - dcd_int_enable(rhport); -} - -#else - -bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { - (void) rhport; - (void) ep_addr; - (void) largest_packet_size; - return false; -} - -bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep) { - (void) rhport; - (void) desc_ep; - return false; -} -#endif - bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) { const unsigned epn = tu_edpt_number(ep_addr); diff --git a/src/portable/nxp/khci/dcd_khci.c b/src/portable/nxp/khci/dcd_khci.c index da1c5c888..9edaadf58 100644 --- a/src/portable/nxp/khci/dcd_khci.c +++ b/src/portable/nxp/khci/dcd_khci.c @@ -355,24 +355,21 @@ void dcd_sof_enable(uint8_t rhport, bool en) //--------------------------------------------------------------------+ // Endpoint API //--------------------------------------------------------------------+ -bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) -{ - (void) rhport; +static bool edpt_open(uint8_t rhport, uint8_t ep_addr, uint16_t max_packet_size, tusb_xfer_type_t xfer) { + (void)rhport; - const unsigned ep_addr = ep_desc->bEndpointAddress; - const unsigned epn = tu_edpt_number(ep_addr); - const unsigned dir = tu_edpt_dir(ep_addr); - const unsigned xfer = ep_desc->bmAttributes.xfer; - endpoint_state_t *ep = &_dcd.endpoint[epn][dir]; - const unsigned odd = ep->odd; - buffer_descriptor_t *bd = _dcd.bdt[epn][dir]; + const unsigned epn = tu_edpt_number(ep_addr); + const unsigned dir = tu_edpt_dir(ep_addr); + endpoint_state_t *ep = &_dcd.endpoint[epn][dir]; + const unsigned odd = ep->odd; + buffer_descriptor_t *bd = _dcd.bdt[epn][dir]; /* No support for control transfer */ TU_ASSERT(epn && (xfer != TUSB_XFER_CONTROL)); - ep->max_packet_size = tu_edpt_packet_size(ep_desc); - unsigned val = USB_ENDPT_EPCTLDIS_MASK; - val |= (xfer != TUSB_XFER_ISOCHRONOUS) ? USB_ENDPT_EPHSHK_MASK: 0; + ep->max_packet_size = max_packet_size; + unsigned val = USB_ENDPT_EPCTLDIS_MASK; + val |= (xfer != TUSB_XFER_ISOCHRONOUS) ? USB_ENDPT_EPHSHK_MASK : 0; val |= dir ? USB_ENDPT_EPTXEN_MASK : USB_ENDPT_EPRXEN_MASK; KHCI->ENDPOINT[epn].ENDPT |= val; @@ -386,6 +383,26 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) return true; } +bool dcd_edpt_open(uint8_t rhport, const tusb_desc_endpoint_t *ep_desc) { + return edpt_open(rhport, ep_desc->bEndpointAddress, tu_edpt_packet_size(ep_desc), ep_desc->bmAttributes.xfer); +} + +bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { + return edpt_open(rhport, ep_addr, largest_packet_size, TUSB_XFER_ISOCHRONOUS); +} + +bool dcd_edpt_iso_activate(uint8_t rhport, const tusb_desc_endpoint_t *ep_desc) { + const unsigned epn = tu_edpt_number(ep_desc->bEndpointAddress); + const unsigned dir = tu_edpt_dir(ep_desc->bEndpointAddress); + endpoint_state_t *ep = &_dcd.endpoint[epn][dir]; + + dcd_int_disable(rhport); + ep->max_packet_size = tu_edpt_packet_size(ep_desc); + dcd_int_enable(rhport); + + return true; +} + void dcd_edpt_close_all(uint8_t rhport) { (void) rhport; @@ -408,41 +425,6 @@ void dcd_edpt_close_all(uint8_t rhport) } } -void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) -{ - (void) rhport; - - const unsigned epn = tu_edpt_number(ep_addr); - const unsigned dir = tu_edpt_dir(ep_addr); - endpoint_state_t *ep = &_dcd.endpoint[epn][dir]; - buffer_descriptor_t *bd = _dcd.bdt[epn][dir]; - const unsigned msk = dir ? USB_ENDPT_EPTXEN_MASK : USB_ENDPT_EPRXEN_MASK; - const unsigned ie = NVIC_GetEnableIRQ(USB0_IRQn); - NVIC_DisableIRQ(USB0_IRQn); - KHCI->ENDPOINT[epn].ENDPT &= ~msk; - ep->max_packet_size = 0; - ep->length = 0; - ep->remaining = 0; - bd[0].head = 0; - bd[1].head = 0; - if (ie) NVIC_EnableIRQ(USB0_IRQn); -} - -#if 0 -bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { - (void) rhport; - (void) ep_addr; - (void) largest_packet_size; - return false; -} - -bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep) { - (void) rhport; - (void) desc_ep; - return false; -} - #endif - bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) { (void) rhport; -- cgit v1.3.1 From e4a04b2a4b7e3b7f3186bf4f12868ce6de36204b Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 18 Nov 2025 23:39:45 +0700 Subject: improve closing endpoint and channel --- src/portable/synopsys/dwc2/hcd_dwc2.c | 159 ++++++++++++++++++++-------------- 1 file changed, 94 insertions(+), 65 deletions(-) (limited to 'src/portable') diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index 2b2bfc91a..fa4e22629 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -32,19 +32,19 @@ #error DWC2 require either CFG_TUH_DWC2_SLAVE_ENABLE or CFG_TUH_DWC2_DMA_ENABLE to be enabled #endif -// Debug level for DWC2 -#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 -#ifndef CFG_TUH_DWC2_ENDPOINT_MAX -#define CFG_TUH_DWC2_ENDPOINT_MAX 16 -#endif + // Debug level for DWC2 + #define DWC2_DEBUG 2 + + // Max number of endpoints application can open, can be larger than DWC2_CHANNEL_COUNT_MAX + #ifndef CFG_TUH_DWC2_ENDPOINT_MAX + #define CFG_TUH_DWC2_ENDPOINT_MAX 16u + #endif -#define DWC2_CHANNEL_COUNT_MAX 16 // absolute max channel count + #define DWC2_CHANNEL_COUNT_MAX 16u // absolute max channel count TU_VERIFY_STATIC(CFG_TUH_DWC2_ENDPOINT_MAX <= 255, "currently only use 8-bit for index"); enum { @@ -79,7 +79,8 @@ typedef struct { 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; + uint32_t closing : 1; // endpoint is closing + // uint32_t : 8; }; uint32_t uframe_countdown; // micro-frame count down to transfer for periodic, only need 18-bit @@ -196,8 +197,21 @@ 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, channel_is_periodic(channel->hcchar))); + const bool is_period = channel_is_periodic(channel->hcchar); + if (dma_host_enabled(dwc2)) { + // In buffer DMA or external DMA mode: + // - Channel disable must not be programmed for non-split periodic channels. At the end of the next uframe/frame (in + // the worst case), the controller generates a channel halted and disables the channel automatically. + // - For split enabled channels (both non-periodic and periodic), channel disable must not be programmed randomly. + // However, channel disable can be programmed for specific scenarios such as NAK and FrmOvrn. + if (is_period && (channel->hcsplt & HCSPLT_SPLITEN)) { + return true; + } + } else { + while (0 == req_queue_avail(dwc2, is_period)) { + // blocking wait for request queue available + } + } channel->hcintmsk |= HCINT_HALTED; channel->hcchar |= HCCHAR_CHDIS | HCCHAR_CHENA; // must set both CHDIS and CHENA return true; @@ -205,7 +219,9 @@ 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, channel_is_periodic(channel->hcchar))); + while (0 == req_queue_avail(dwc2, channel_is_periodic(channel->hcchar))) { + // blocking wait for request queue available + } channel->hcchar |= HCCHAR_CHENA; return true; } @@ -238,13 +254,37 @@ TU_ATTR_ALWAYS_INLINE static inline uint8_t edpt_alloc(void) { return TUSB_INDEX_INVALID_8; } -// Find a endpoint that is opened previously with hcd_edpt_open() +TU_ATTR_ALWAYS_INLINE static inline void edpt_dealloc(hcd_endpoint_t *edpt) { + edpt->hcchar_bm.enable = 0; +} + +// close an opened endpoint +static void edpt_close(dwc2_regs_t *dwc2, uint8_t ep_id) { + hcd_endpoint_t *edpt = &_hcd_data.edpt[ep_id]; + edpt->closing = 1; // mark endpoint as closing + + // disable active channel belong to this endpoint + for (uint8_t ch_id = 0; ch_id < DWC2_CHANNEL_COUNT_MAX; ch_id++) { + hcd_xfer_t *xfer = &_hcd_data.xfer[ch_id]; + if (xfer->allocated && xfer->ep_id == ep_id) { + dwc2_channel_t *channel = &dwc2->channel[ch_id]; + xfer->closing = 1; + channel_disable(dwc2, channel); + return; // only 1 active channel per endpoint + } + } + + edpt_dealloc(edpt); // no active channel, safe to de-alloc now +} + +// Find an endpoint that is opened previously with hcd_edpt_open() // Note: EP0 is bidirectional TU_ATTR_ALWAYS_INLINE static inline uint8_t edpt_find_opened(uint8_t dev_addr, uint8_t ep_num, uint8_t ep_dir) { for (uint8_t i = 0; i < (uint8_t)CFG_TUH_DWC2_ENDPOINT_MAX; i++) { - const dwc2_channel_char_t* hcchar_bm = &_hcd_data.edpt[i].hcchar_bm; - if (hcchar_bm->enable && hcchar_bm->dev_addr == dev_addr && - hcchar_bm->ep_num == ep_num && (ep_num == 0 || hcchar_bm->ep_dir == ep_dir)) { + const hcd_endpoint_t *edpt = &_hcd_data.edpt[i]; + const dwc2_channel_char_t hcchar_bm = edpt->hcchar_bm; + if (hcchar_bm.enable && hcchar_bm.dev_addr == dev_addr && hcchar_bm.ep_num == ep_num && + (ep_num == 0 || hcchar_bm.ep_dir == ep_dir)) { return i; } } @@ -458,22 +498,10 @@ tusb_speed_t hcd_port_speed_get(uint8_t rhport) { // HCD closes all opened endpoints belong to this device void hcd_device_close(uint8_t rhport, uint8_t dev_addr) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); - for (uint8_t i = 0; i < (uint8_t) CFG_TUH_DWC2_ENDPOINT_MAX; i++) { - hcd_endpoint_t* edpt = &_hcd_data.edpt[i]; + for (uint8_t ep_id = 0; ep_id < CFG_TUH_DWC2_ENDPOINT_MAX; ep_id++) { + const hcd_endpoint_t *edpt = &_hcd_data.edpt[ep_id]; if (edpt->hcchar_bm.enable && edpt->hcchar_bm.dev_addr == dev_addr) { - tu_memclr(edpt, sizeof(hcd_endpoint_t)); - for (uint8_t ch_id = 0; ch_id < (uint8_t) DWC2_CHANNEL_COUNT_MAX; ch_id++) { - hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; - if (xfer->allocated && xfer->ep_id == i) { - dwc2_channel_t* channel = &dwc2->channel[ch_id]; - dwc2_channel_split_t hcsplt = {.value = channel->hcsplt}; - xfer->closing = 1; - // Channel disable must not be programmed for non-split periodic channels - if (!channel_is_periodic(channel->hcchar) || hcsplt.split_en) { - channel_disable(dwc2, channel); - } - } - } + edpt_close(dwc2, ep_id); } } } @@ -533,8 +561,15 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, const tusb_desc_endpoint_t* } 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 + dwc2_regs_t *dwc2 = DWC2_REG(rhport); + const uint8_t ep_num = tu_edpt_number(ep_addr); + const uint8_t ep_dir = tu_edpt_dir(ep_addr); + const uint8_t ep_id = edpt_find_opened(daddr, ep_num, ep_dir); + TU_ASSERT(ep_id < CFG_TUH_DWC2_ENDPOINT_MAX); + + edpt_close(dwc2, ep_id); + + return true; } // clean up channel after part of transfer is done but the whole urb is not complete @@ -603,8 +638,7 @@ static bool channel_xfer_start(dwc2_regs_t* dwc2, uint8_t ch_id) { channel->hcint = 0xFFFFFFFFU; // clear all channel interrupts if (dma_host_enabled(dwc2)) { - uint32_t hcintmsk = HCINT_HALTED; - channel->hcintmsk = hcintmsk; + channel->hcintmsk = HCINT_HALTED; dwc2->haintmsk |= TU_BIT(ch_id); channel->hcdma = (uint32_t) edpt->buffer; @@ -659,7 +693,6 @@ static bool edpt_xfer_kickoff(dwc2_regs_t* dwc2, uint8_t ep_id) { return channel_xfer_start(dwc2, ch_id); } -// 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) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); const uint8_t ep_num = tu_edpt_number(ep_addr); @@ -667,7 +700,8 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * uint8_t ep_id = edpt_find_opened(dev_addr, ep_num, ep_dir); TU_ASSERT(ep_id < CFG_TUH_DWC2_ENDPOINT_MAX); - hcd_endpoint_t* edpt = &_hcd_data.edpt[ep_id]; + hcd_endpoint_t *edpt = &_hcd_data.edpt[ep_id]; + TU_VERIFY(edpt->closing == 0); // skip if endpoint is closing edpt->buffer = buffer; edpt->buflen = buflen; @@ -958,12 +992,9 @@ static bool handle_channel_in_slave(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t h is_done = true; } else if (xfer->err_count == HCD_XFER_ERROR_MAX) { xfer->result = XFER_RESULT_FAILED; - is_done = true; + is_done = true; } else if (xfer->closing) { - // channel is closing, de-allocate channel - channel_dealloc(dwc2, ch_id); - // don't send event - is_done = false; + is_done = true; } else { // got here due to NAK or NYET channel_xfer_in_retry(dwc2, ch_id, hcint); @@ -1025,10 +1056,7 @@ static bool handle_channel_out_slave(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t xfer->result = XFER_RESULT_FAILED; is_done = true; } else if (xfer->closing) { - // channel is closing, de-allocate channel - channel_dealloc(dwc2, ch_id); - // don't send event - is_done = false; + is_done = true; } else { // Got here due to NAK or NYET TU_ASSERT(channel_xfer_start(dwc2, ch_id)); @@ -1147,10 +1175,7 @@ static bool handle_channel_in_dma(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hci } if (xfer->closing) { - // channel is closing, de-allocate channel - channel_dealloc(dwc2, ch_id); - // don't send event - is_done = false; + is_done = true; } } @@ -1214,10 +1239,7 @@ static bool handle_channel_out_dma(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hc } if (xfer->closing) { - // channel is closing, de-allocate channel - channel_dealloc(dwc2, ch_id); - // don't send event - is_done = false; + is_done = true; } } else if (hcint & HCINT_ACK) { xfer->err_count = 0; @@ -1263,12 +1285,17 @@ static void handle_channel_irq(uint8_t rhport, bool in_isr) { } else { is_done = handle_channel_in_slave(dwc2, ch_id, hcint); } - #endif + #endif } if (is_done) { - 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); + if (xfer->closing) { + hcd_endpoint_t *edpt = &_hcd_data.edpt[xfer->ep_id]; + edpt_dealloc(edpt); + } else { + 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); } } @@ -1287,16 +1314,18 @@ static bool handle_sof_irq(uint8_t rhport, bool in_isr) { const uint32_t ucount = (hprt_speed_get(dwc2) == TUSB_SPEED_HIGH ? 1 : 8); 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 && 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)) { - edpt->uframe_countdown = ucount; // failed to start, try again next frame + hcd_endpoint_t *edpt = &_hcd_data.edpt[ep_id]; + if (edpt->closing == 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)) { + edpt->uframe_countdown = ucount; // failed to start, try again next frame + } } - } - more_isr = true; + more_isr = true; + } } } -- cgit v1.3.1 From 39c78085cc6ab04b4097031b3260b738cc5dcec2 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 19 Nov 2025 16:24:39 +0700 Subject: extract to handle_incomplete_iso_in() for readability --- src/portable/synopsys/dwc2/dcd_dwc2.c | 78 ++++++++++++++++++----------------- 1 file changed, 40 insertions(+), 38 deletions(-) (limited to 'src/portable') diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index 013830963..53b6821fa 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -650,15 +650,13 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to xfer->buffer = buffer; xfer->ff = NULL; xfer->total_len = total_bytes; + xfer->iso_retry = xfer->interval; // Reset ISO retry counter to interval value // EP0 can only handle one packet if (epnum == 0) { _dcd_data.ep0_pending[dir] = total_bytes; } - // Reset ISO retry counter to interval value - xfer->iso_retry = xfer->interval; - // Schedule packets to be sent within interrupt edpt_schedule_packets(rhport, epnum, dir); ret = true; @@ -690,9 +688,7 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_t xfer->buffer = NULL; xfer->ff = ff; xfer->total_len = total_bytes; - - // Reset ISO retry counter to interval value - xfer->iso_retry = xfer->interval; + xfer->iso_retry = xfer->interval; // Reset ISO retry counter to interval value // Schedule packets to be sent within interrupt // TODO xfer fifo may only available for slave mode @@ -1070,6 +1066,43 @@ static void handle_ep_irq(uint8_t rhport, uint8_t dir) { } } +static void handle_incomplete_iso_in(uint8_t rhport) { + dwc2_regs_t *dwc2 = DWC2_REG(rhport); + const dwc2_dsts_t dsts = {.value = dwc2->dsts}; + const uint32_t odd_now = dsts.frame_number & 1u; + + // Loop over all IN endpoints + const uint8_t ep_count = dwc2_ep_count(dwc2); + for (uint8_t epnum = 0; epnum < ep_count; epnum++) { + dwc2_dep_t *epin = &dwc2->epin[epnum]; + dwc2_depctl_t depctl = {.value = epin->diepctl}; + // Read DSTS and DIEPCTLn for all isochronous endpoints. If the current EP is enabled and the read value of + // DSTS.SOFFN is the targeted uframe number for this EP, then this EP has an incomplete transfer. + if (depctl.enable && depctl.type == DEPCTL_EPTYPE_ISOCHRONOUS && depctl.dpid_iso_odd == odd_now) { + xfer_ctl_t *xfer = XFER_CTL_BASE(epnum, TUSB_DIR_IN); + if (xfer->iso_retry > 0) { + xfer->iso_retry--; + // Restart ISO transfe: re-write TSIZ and CTL + dwc2_ep_tsize_t deptsiz = {.value = 0}; + deptsiz.xfer_size = xfer->total_len; + deptsiz.packet_count = tu_div_ceil(xfer->total_len, xfer->max_size); + epin->tsiz = deptsiz.value; + + if (odd_now) { + depctl.set_data0_iso_even = 1; + } else { + depctl.set_data1_iso_odd = 1; + } + epin->diepctl = depctl.value; + } else { + // too many retries, give up + edpt_disable(rhport, epnum | TUSB_DIR_IN_MASK, false); + dcd_event_xfer_complete(rhport, epnum | TUSB_DIR_IN_MASK, 0, XFER_RESULT_FAILED, true); + } + } + } +} + /* Interrupt Hierarchy DIEPINT DIEPINT \ / @@ -1173,38 +1206,7 @@ void dcd_int_handler(uint8_t rhport) { // Incomplete isochronous IN transfer interrupt handling. if (gintsts & GINTSTS_IISOIXFR) { dwc2->gintsts = GINTSTS_IISOIXFR; - const dwc2_dsts_t dsts = {.value = dwc2->dsts}; - const uint32_t odd_now = dsts.frame_number & 1u; - // Loop over all IN endpoints - const uint8_t ep_count = dwc2_ep_count(dwc2); - for (uint8_t epnum = 0; epnum < ep_count; epnum++) { - dwc2_dep_t* epin = &dwc2->epin[epnum]; - dwc2_depctl_t depctl = {.value = epin->diepctl}; - // Read DSTS and DIEPCTLn for all isochronous endpoints. If the current EP is enabled - // and the read value of DSTS.SOFFN is the targeted uframe number for this EP, then - // this EP has an incomplete transfer. - if (depctl.enable && depctl.type == DEPCTL_EPTYPE_ISOCHRONOUS && depctl.dpid_iso_odd == odd_now) { - xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, TUSB_DIR_IN); - if (xfer->iso_retry) { - xfer->iso_retry--; - // Restart ISO transfer - dwc2_ep_tsize_t deptsiz = {.value = 0}; - deptsiz.xfer_size = xfer->total_len; - deptsiz.packet_count = tu_div_ceil(xfer->total_len, xfer->max_size); - epin->tsiz = deptsiz.value; - if (odd_now) { - depctl.set_data0_iso_even = 1; - } else { - depctl.set_data1_iso_odd = 1; - } - epin->diepctl = depctl.value; - } else { - // too many retries, give up - edpt_disable(rhport, epnum | TUSB_DIR_IN_MASK, false); - dcd_event_xfer_complete(rhport, epnum | TUSB_DIR_IN_MASK, 0, XFER_RESULT_FAILED, true); - } - } - } + handle_incomplete_iso_in(rhport); } } -- cgit v1.3.1 From e0155eb1d2170d8448e422a6f75f8bc65b476cec Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 19 Nov 2025 18:37:15 +0700 Subject: fix more alerts --- .PVS-Studio/.pvsconfig | 3 +- AGENTS.md | 221 ++++++++++++++++++++++++++++++- src/portable/synopsys/dwc2/dwc2_common.h | 4 +- src/portable/synopsys/dwc2/dwc2_stm32.h | 2 +- src/portable/synopsys/dwc2/dwc2_type.h | 10 ++ src/portable/synopsys/dwc2/hcd_dwc2.c | 87 ++++++------ 6 files changed, 280 insertions(+), 47 deletions(-) (limited to 'src/portable') diff --git a/.PVS-Studio/.pvsconfig b/.PVS-Studio/.pvsconfig index c9e60c996..c098fc375 100644 --- a/.PVS-Studio/.pvsconfig +++ b/.PVS-Studio/.pvsconfig @@ -11,7 +11,8 @@ //-V:memcpy:2547 [MISRA-C-17.7] The return value of non-void function 'memcpy' should be used. //-V:memmove:2547 [MISRA-C-17.7] The return value of non-void function 'memmove' should be used. //-V:printf:2547 [MISRA-C-17.7] -//-V::2584::{gintsts} dwc2 +//-V::2584::{gintsts} dwc2 interrupt handler +//-V::2584::{hcint} dwc2 interrupt handler //-V::2600 [MISRA-C-21.6] The function with the 'printf' name should not be used. //+V2614 DISABLE_LENGHT_LIMIT_CHECK:YES //-V:memcpy:2628 Pointer arguments to the 'memcpy' function should be pointers to qualified or unqualified versions of compatible types. diff --git a/AGENTS.md b/AGENTS.md index 7d727ef8a..3e085cf03 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -20,12 +20,221 @@ 2. Build at least one representative example (e.g., `examples/device/cdc_msc`) via CMake+Ninja or Make. 3. Run unit tests relevant to touched modules; add fuzz/HIL coverage when modifying parsers or protocol state machines. -## Copilot Agent Notes (`.github/copilot-instructions.md`) -- Treat this handbook as authoritative before searching or executing speculative shell commands; unexpected conflicts justify additional probing. -- Respect build timing guidance: allow ≥5 minutes for single example builds and ≥30 minutes for bulk runs; never cancel dependency fetches or builds mid-flight. -- Support optional switches: `-DRHPORT_DEVICE[_SPEED]`, logging toggles (`LOG=2`, `LOGGER=rtt`), and board selection helpers from `tools/get_deps.py`. -- Flashing shortcuts: `ninja -jlink|openocd|uf2` or `make BOARD= flash-{jlink,openocd}`; list Ninja targets with `ninja -t targets`. -- Keep Ceedling installed (`sudo gem install ceedling`) and available for per-test or full suite runs triggered from `test/unit-test`. +## Copilot Agent Notes (`./github/copilot-instruction.md`) +# 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=raspberry_pi_pico -DCMAKE_BUILD_TYPE=MinSizeRel .. +cmake --build . -j4 +``` +-- takes 1-2 seconds. NEVER CANCEL. Set timeout to 5+ minutes. + +**CMake with Ninja (Alternative)** +```bash +cd examples/device/cdc_msc +mkdir build && cd build +cmake -G Ninja -DBOARD=raspberry_pi_pico .. +ninja +``` + +**Option 2: Individual Example with Make** +```bash +cd examples/device/cdc_msc +make BOARD=raspberry_pi_pico 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. + +#### Build Options +- **Debug build**: + - CMake: `-DCMAKE_BUILD_TYPE=Debug` + - Make: `DEBUG=1` +- **With logging**: + - CMake: `-DLOG=2` + - Make: `LOG=2` +- **With RTT logger**: + - CMake: `-DLOG=2 -DLOGGER=rtt` + - Make: `LOG=2 LOGGER=rtt` +- **RootHub port selection**: + - CMake: `-DRHPORT_DEVICE=1` + - Make: `RHPORT_DEVICE=1` +- **Port speed**: + - CMake: `-DRHPORT_DEVICE_SPEED=OPT_MODE_FULL_SPEED` + - Make: `RHPORT_DEVICE_SPEED=OPT_MODE_FULL_SPEED` + +#### Flashing and Deployment +- **Flash with JLink**: + - CMake: `ninja cdc_msc-jlink` + - Make: `make BOARD=raspberry_pi_pico flash-jlink` +- **Flash with OpenOCD**: + - CMake: `ninja cdc_msc-openocd` + - Make: `make BOARD=raspberry_pi_pico flash-openocd` +- **Generate UF2**: + - CMake: `ninja cdc_msc-uf2` + - Make: `make BOARD=raspberry_pi_pico all uf2` +- **List all targets** (CMake/Ninja): `ninja -t targets` + +#### Unit Testing +- Install Ceedling: `sudo gem install ceedling` +- Run all unit tests: `cd test/unit-test && ceedling` or `cd test/unit-test && ceedling test:all` -- takes 4 seconds. NEVER CANCEL. Set timeout to 10+ minutes. +- Run specific test: `cd test/unit-test && ceedling test:test_fifo` +- 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 + +#### Static Analysis with PVS-Studio +- **Analyze whole project**: + ```bash + pvs-studio-analyzer analyze -f examples/cmake-build-raspberry_pi_pico/compile_commands.json -R .PVS-Studio/.pvsconfig -o pvs-report.log -j12 --dump-files --misra-cpp-version 2008 --misra-c-version 2023 --use-old-parser + ``` +- **Analyze specific source files**: + ```bash + pvs-studio-analyzer analyze -f examples/cmake-build-raspberry_pi_pico/compile_commands.json -R .PVS-Studio/.pvsconfig -S path/to/file.c -o pvs-report.log -j12 --dump-files --misra-cpp-version 2008 --misra-c-version 2023 --use-old-parser + ``` +- **Multiple specific files**: + ```bash + pvs-studio-analyzer analyze -f examples/cmake-build-raspberry_pi_pico/compile_commands.json -R .PVS-Studio/.pvsconfig -S src/file1.c -S src/file2.c -o pvs-report.log -j12 --dump-files --misra-cpp-version 2008 --misra-c-version 2023 --use-old-parser + ``` +- Requires `compile_commands.json` in the build directory (generated by CMake with `-DCMAKE_EXPORT_COMPILE_COMMANDS=ON`) +- Use `-f` option to specify path to `compile_commands.json` +- Use `-R .PVS-Studio/.pvsconfig` to specify rule configuration file +- Use `-j12` for parallel analysis with 12 threads +- `--dump-files` saves preprocessed files for debugging +- `--misra-c-version 2023` enables MISRA C:2023 checks +- `--misra-cpp-version 2008` enables MISRA C++:2008 checks +- `--use-old-parser` uses legacy parser for compatibility +- Analysis takes ~10-30 seconds depending on project size. Set timeout to 5+ minutes. +- View results: `plog-converter -a GA:1,2 -t errorfile pvs-report.log` or open in PVS-Studio GUI + +### 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=raspberry_pi_pico 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**: `raspberry_pi_pico` - 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 + +### Code Style Guidelines + +#### General Coding Standards +- Use C99 standard +- Memory-safe: no dynamic allocation +- Thread-safe: defer all interrupt events to non-ISR task functions +- 2-space indentation, no tabs +- Use snake_case for variables/functions +- Use UPPER_CASE for macros and constants +- Follow existing variable naming patterns in files you're modifying +- Include proper header comments with MIT license +- Add descriptive comments for non-obvious functions + +#### Best Practices +- When including headers, group in order: C stdlib, tusb common, drivers, classes +- Always check return values from functions that can fail +- Use TU_ASSERT() for error checking with return statements +- Follow the existing code patterns in the files you're modifying + +Remember: TinyUSB is designed for embedded systems - builds are fast, tests are focused, and the codebase is optimized for resource-constrained environments. ## Claude Agent Notes (`CLAUDE.md`) - Default to CMake+Ninja for builds, but align with Make workflows when users rely on legacy scripts; provide DEBUG/LOG/LOGGER knobs consistently. diff --git a/src/portable/synopsys/dwc2/dwc2_common.h b/src/portable/synopsys/dwc2/dwc2_common.h index dc204f578..428304ba9 100644 --- a/src/portable/synopsys/dwc2/dwc2_common.h +++ b/src/portable/synopsys/dwc2/dwc2_common.h @@ -94,13 +94,13 @@ void dwc2_core_handle_common_irq(uint8_t rhport, bool in_isr); TU_ATTR_ALWAYS_INLINE static inline void dfifo_flush_tx(dwc2_regs_t* dwc2, uint8_t fnum) { // flush TX fifo and wait for it cleared dwc2->grstctl = GRSTCTL_TXFFLSH | (fnum << GRSTCTL_TXFNUM_Pos); - while (dwc2->grstctl & GRSTCTL_TXFFLSH_Msk) {} + while (0 != (dwc2->grstctl & GRSTCTL_TXFFLSH_Msk)) {} } TU_ATTR_ALWAYS_INLINE static inline void dfifo_flush_rx(dwc2_regs_t* dwc2) { // flush RX fifo and wait for it cleared dwc2->grstctl = GRSTCTL_RXFFLSH; - while (dwc2->grstctl & GRSTCTL_RXFFLSH_Msk) {} + while (0 != (dwc2->grstctl & GRSTCTL_RXFFLSH_Msk)) {} } void dfifo_read_packet(dwc2_regs_t* dwc2, uint8_t* dst, uint16_t len); diff --git a/src/portable/synopsys/dwc2/dwc2_stm32.h b/src/portable/synopsys/dwc2/dwc2_stm32.h index 9da8de41f..62629334e 100644 --- a/src/portable/synopsys/dwc2/dwc2_stm32.h +++ b/src/portable/synopsys/dwc2/dwc2_stm32.h @@ -176,7 +176,7 @@ TU_ATTR_ALWAYS_INLINE static inline void dwc2_int_set(uint8_t rhport, tusb_role_ TU_ATTR_ALWAYS_INLINE static inline void dwc2_remote_wakeup_delay(void) { // try to delay for 1 ms uint32_t count = SystemCoreClock / 1000; - while (count--) { + while ((count--) > 0) { __NOP(); } } diff --git a/src/portable/synopsys/dwc2/dwc2_type.h b/src/portable/synopsys/dwc2/dwc2_type.h index adcc579e3..7693ce02a 100644 --- a/src/portable/synopsys/dwc2/dwc2_type.h +++ b/src/portable/synopsys/dwc2/dwc2_type.h @@ -91,6 +91,16 @@ enum { GOTGCTL_OTG_VERSION_2_0 = 1, }; +enum { + GUSBCFG_PHYSEL_HIGHSPEED = 0, + GUSBCFG_PHYSEL_FULLSPEED = 1, +}; + +enum { + GUSBCFG_PHYHS_UTMI = 0, + GUSBCFG_PHYHS_ULPI = 1, +}; + enum { GHWCFG2_OPMODE_HNP_SRP = 0, GHWCFG2_OPMODE_SRP = 1, diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index fa4e22629..b92448685 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -300,8 +300,8 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t cal_packet_count(uint16_t len, uint } TU_ATTR_ALWAYS_INLINE static inline uint8_t cal_next_pid(uint8_t pid, uint8_t packet_count) { - if (packet_count & 0x01) { - return pid ^ 0x02; // toggle DATA0 and DATA1 + if (packet_count & 0x01u) { + return pid ^ 0x02u; // toggle DATA0 and DATA1 } else { return pid; } @@ -544,17 +544,24 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, const tusb_desc_endpoint_t* 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 (bus_info.speed == TUSB_SPEED_FULL) { - edpt->uframe_interval <<= 3; - } - } else if (desc_ep->bmAttributes.xfer == TUSB_XFER_INTERRUPT) { - if (bus_info.speed == TUSB_SPEED_HIGH) { + switch (desc_ep->bmAttributes.xfer) { + case TUSB_XFER_ISOCHRONOUS: edpt->uframe_interval = 1 << (desc_ep->bInterval - 1); - } else { - edpt->uframe_interval = desc_ep->bInterval << 3; - } + if (bus_info.speed == TUSB_SPEED_FULL) { + edpt->uframe_interval <<= 3; + } + break; + + case TUSB_XFER_INTERRUPT: + if (bus_info.speed == TUSB_SPEED_HIGH) { + edpt->uframe_interval = 1 << (desc_ep->bInterval - 1); + } else { + edpt->uframe_interval = desc_ep->bInterval << 3; + } + break; + + default: + break; } return true; @@ -801,7 +808,7 @@ static void channel_xfer_in_retry(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hci edpt->next_pid = hctsiz.pid; // save PID edpt->uframe_countdown = edpt->uframe_interval - ucount; // enable SOF interrupt if not already enabled - if (!(dwc2->gintmsk & GINTMSK_SOFM)) { + if (0 == (dwc2->gintmsk & GINTMSK_SOFM)) { dwc2->gintsts = GINTSTS_SOF; dwc2->gintmsk |= GINTMSK_SOFM; } @@ -848,7 +855,7 @@ static void handle_rxflvl_irq(uint8_t rhport) { TU_ASSERT(xfer->ep_id < CFG_TUH_DWC2_ENDPOINT_MAX,); hcd_endpoint_t* edpt = &_hcd_data.edpt[xfer->ep_id]; - if (byte_count) { + if (byte_count > 0) { dfifo_read_packet(dwc2, edpt->buffer + xfer->xferred_bytes, byte_count); xfer->xferred_bytes += byte_count; xfer->fifo_bytes = byte_count; @@ -884,8 +891,8 @@ static bool handle_txfifo_empty(dwc2_regs_t* dwc2, bool is_periodic) { 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) && (hcchar.ep_dir == TUSB_DIR_OUT)) { - hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; + if (0 == (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 dwc2_channel_tsize_t hctsiz = {.value = channel->hctsiz}; @@ -946,6 +953,8 @@ static bool handle_channel_in_slave(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t h } else if (hcint & HCINT_XACT_ERR) { xfer->err_count++; channel->hcintmsk |= HCINT_ACK; + } else { + // nothing to do } channel_disable(dwc2, channel); @@ -957,7 +966,7 @@ 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_NAK) { // NAK received, disable channel to flush all posted request and try again - if (hcsplt.split_en) { + if (hcsplt.split_en == 1u) { hcsplt.split_compl = 0; // restart with start-split channel->hcsplt = hcsplt.value; } @@ -966,8 +975,8 @@ static bool handle_channel_in_slave(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t h } else if (hcint & HCINT_ACK) { xfer->err_count = 0; - if (hcsplt.split_en) { - if (!hcsplt.split_compl) { + if (hcsplt.split_en == 1u) { + if (hcsplt.split_compl == 0) { // start split is ACK --> do complete split channel->hcintmsk |= HCINT_NYET; hcsplt.split_compl = 1; @@ -979,7 +988,7 @@ static bool handle_channel_in_slave(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t h } else { // ACK with data const uint16_t remain_packets = hctsiz.packet_count; - if (remain_packets) { + if (remain_packets > 0) { // still more packet to receive, also reset to start split hcsplt.split_compl = 0; channel->hcsplt = hcsplt.value; @@ -993,7 +1002,7 @@ static bool handle_channel_in_slave(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t h } else if (xfer->err_count == HCD_XFER_ERROR_MAX) { xfer->result = XFER_RESULT_FAILED; is_done = true; - } else if (xfer->closing) { + } else if (xfer->closing == 1) { is_done = true; } else { // got here due to NAK or NYET @@ -1002,6 +1011,8 @@ static bool handle_channel_in_slave(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t h } else if (hcint & HCINT_DATATOGGLE_ERR) { xfer->err_count = 0; TU_ASSERT(false); + } else { + // nothing to do } return is_done; } @@ -1026,7 +1037,7 @@ 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 (hcsplt.split_en) { + if (hcsplt.split_en == 1u) { // retry complete split hcsplt.split_compl = 1; channel->hcsplt = hcsplt.value; @@ -1054,8 +1065,8 @@ static bool handle_channel_out_slave(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t is_done = true; } else if (xfer->err_count == HCD_XFER_ERROR_MAX) { xfer->result = XFER_RESULT_FAILED; - is_done = true; - } else if (xfer->closing) { + is_done = true; + } else if (xfer->closing == 1) { is_done = true; } else { // Got here due to NAK or NYET @@ -1064,8 +1075,8 @@ 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 (hcsplt.split_en) { - if (!hcsplt.split_compl) { + if (hcsplt.split_en == 1u) { + if (hcsplt.split_compl == 0) { // ACK for start split --> do complete split hcsplt.split_compl = 1; channel->hcsplt = hcsplt.value; @@ -1077,6 +1088,8 @@ static bool handle_channel_out_slave(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t channel->hctsiz &= ~HCTSIZ_DOPING; // HC already cleared PING bit, but we clear anyway channel->hcchar |= HCCHAR_CHENA; } + } else { + // nothing to do } if (is_done) { @@ -1174,7 +1187,7 @@ static bool handle_channel_in_dma(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hci channel_xfer_in_retry(dwc2, ch_id, hcint); } - if (xfer->closing) { + if (xfer->closing == 1) { is_done = true; } } @@ -1238,7 +1251,7 @@ static bool handle_channel_out_dma(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hc } } - if (xfer->closing) { + if (xfer->closing == 1) { is_done = true; } } else if (hcint & HCINT_ACK) { @@ -1289,7 +1302,7 @@ static void handle_channel_irq(uint8_t rhport, bool in_isr) { } if (is_done) { - if (xfer->closing) { + if (xfer->closing == 1) { hcd_endpoint_t *edpt = &_hcd_data.edpt[xfer->ep_id]; edpt_dealloc(edpt); } else { @@ -1337,9 +1350,9 @@ 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 = {.value = dwc2->gusbcfg}; - uint32_t phy_clock; + uint32_t phy_clock; - if (gusbcfg.phy_sel) { + if (gusbcfg.phy_sel == GUSBCFG_PHYSEL_FULLSPEED) { phy_clock = 48; // dedicated FS is 48Mhz if (speed == TUSB_SPEED_LOW) { hcfg |= HCFG_FSLS_PHYCLK_SEL_6MHZ; @@ -1347,7 +1360,7 @@ static void port0_enable(dwc2_regs_t* dwc2, tusb_speed_t speed) { hcfg |= HCFG_FSLS_PHYCLK_SEL_48MHZ; } } else { - if (gusbcfg.ulpi_utmi_sel) { + if (gusbcfg.ulpi_utmi_sel == GUSBCFG_PHYHS_ULPI) { phy_clock = 60; // ULPI 8-bit is 60Mhz } else { // UTMI+ 16-bit is 30Mhz, 8-bit is 60Mhz @@ -1386,20 +1399,20 @@ static void handle_hprt_irq(uint8_t rhport, bool in_isr) { const dwc2_hprt_t hprt_bm = {.value = dwc2->hprt}; uint32_t hprt = hprt_bm.value & ~HPRT_W1_MASK; - if (hprt_bm.conn_detected) { + if (hprt_bm.conn_detected == 1u) { // Port Connect Detect hprt |= HPRT_CONN_DETECT; - if (hprt_bm.conn_status) { + if (hprt_bm.conn_status == 1u) { hcd_event_device_attach(rhport, in_isr); } } - if (hprt_bm.enable_change) { + if (hprt_bm.enable_change == 1u) { // Port enable change hprt |= HPRT_ENABLE_CHANGE; - if (hprt_bm.enable) { + if (hprt_bm.enable == 1u) { // Port enable const tusb_speed_t speed = hprt_speed_get(dwc2); port0_enable(dwc2, speed); @@ -1458,7 +1471,7 @@ void hcd_int_handler(uint8_t rhport, bool in_isr) { // Device disconnected dwc2->gintsts = GINTSTS_DISCINT; - if (!(dwc2->hprt & HPRT_CONN_STATUS)) { + if (0 == (dwc2->hprt & HPRT_CONN_STATUS)) { hcd_event_device_remove(rhport, in_isr); } } -- cgit v1.3.1 From 19fd61603f49e0130f65cdf404c9d4424bda70e3 Mon Sep 17 00:00:00 2001 From: Ha Thach Date: Wed, 19 Nov 2025 19:20:53 +0700 Subject: Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- AGENTS.md | 2 +- src/portable/synopsys/dwc2/dwc2_stm32.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/portable') diff --git a/AGENTS.md b/AGENTS.md index 3e085cf03..27bc60515 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -20,7 +20,7 @@ 2. Build at least one representative example (e.g., `examples/device/cdc_msc`) via CMake+Ninja or Make. 3. Run unit tests relevant to touched modules; add fuzz/HIL coverage when modifying parsers or protocol state machines. -## Copilot Agent Notes (`./github/copilot-instruction.md`) +## Copilot Agent Notes (`.github/copilot-instructions.md`) # 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. diff --git a/src/portable/synopsys/dwc2/dwc2_stm32.h b/src/portable/synopsys/dwc2/dwc2_stm32.h index 62629334e..9da8de41f 100644 --- a/src/portable/synopsys/dwc2/dwc2_stm32.h +++ b/src/portable/synopsys/dwc2/dwc2_stm32.h @@ -176,7 +176,7 @@ TU_ATTR_ALWAYS_INLINE static inline void dwc2_int_set(uint8_t rhport, tusb_role_ TU_ATTR_ALWAYS_INLINE static inline void dwc2_remote_wakeup_delay(void) { // try to delay for 1 ms uint32_t count = SystemCoreClock / 1000; - while ((count--) > 0) { + while (count--) { __NOP(); } } -- cgit v1.3.1 From 30198b2ab9e69c120e5b49c063dad3d2d3889d79 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 20 Nov 2025 18:35:28 +0700 Subject: refactor tu_fifo, add tu_fifo_write/read/peek_n_access() --- .clang-format | 1 - src/common/tusb_fifo.c | 162 +++++-------------------------- src/common/tusb_fifo.h | 32 ++++-- src/device/usbd.c | 20 ++-- src/portable/microchip/samg/dcd_samg.c | 10 +- src/portable/nuvoton/nuc505/dcd_nuc505.c | 14 ++- src/portable/synopsys/dwc2/dcd_dwc2.c | 4 +- src/tusb_option.h | 41 ++++---- 8 files changed, 94 insertions(+), 190 deletions(-) (limited to 'src/portable') diff --git a/.clang-format b/.clang-format index f15c26c9e..924516e13 100644 --- a/.clang-format +++ b/.clang-format @@ -86,7 +86,6 @@ PenaltyBreakBeforeFirstCallParameter: 1000000 PenaltyBreakOpenParenthesis: 1000000 QualifierAlignment: Custom QualifierOrder: ['static', 'const', 'volatile', 'restrict', 'type'] -ReflowComments: false SpaceAfterTemplateKeyword: false SpaceBeforeRangeBasedForLoopColon: false SpaceInEmptyParentheses: false diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 5c9e586fb..a3e89bbc2 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -57,17 +57,6 @@ TU_ATTR_ALWAYS_INLINE static inline void _ff_unlock(osal_mutex_t mutex) { #endif -/** \enum tu_fifo_copy_mode_t - * \brief Write modes intended to allow special read and write functions to be able to - * copy data to and from USB hardware FIFOs as needed for e.g. STM32s and others - */ -typedef enum { - TU_FIFO_COPY_INC, ///< Copy from/to an increasing source/destination address - default mode -#ifdef TUP_MEM_CONST_ADDR - TU_FIFO_COPY_CST_FULL_WORDS, ///< Copy from/to a constant source/destination address - required for e.g. STM32 to write into USB hardware FIFO -#endif -} tu_fifo_copy_mode_t; - bool tu_fifo_config(tu_fifo_t *f, void *buffer, uint16_t depth, uint16_t item_size, bool overwritable) { // Limit index space to 2*depth - this allows for a fast "modulo" calculation // but limits the maximum depth to 2^16/2 = 2^15 and buffer overflows are detectable @@ -147,7 +136,8 @@ static inline void _ff_push(tu_fifo_t *f, const void *app_buf, uint16_t rel) { } // send n items to fifo WITHOUT updating write pointer -static void _ff_push_n(tu_fifo_t *f, const void *app_buf, uint16_t n, uint16_t wr_ptr, tu_fifo_copy_mode_t copy_mode) { +static void _ff_push_n(tu_fifo_t *f, const void *app_buf, uint16_t n, uint16_t wr_ptr, + tu_fifo_access_mode_t copy_mode) { const uint16_t lin_count = f->depth - wr_ptr; const uint16_t wrap_count = n - lin_count; @@ -158,7 +148,7 @@ static void _ff_push_n(tu_fifo_t *f, const void *app_buf, uint16_t n, uint16_t w uint8_t *ff_buf = f->buffer + (wr_ptr * f->item_size); switch (copy_mode) { - case TU_FIFO_COPY_INC: + case TU_FIFO_INC_ADDR_RW8: if (n <= lin_count) { // Linear only memcpy(ff_buf, app_buf, n * f->item_size); @@ -175,7 +165,7 @@ static void _ff_push_n(tu_fifo_t *f, const void *app_buf, uint16_t n, uint16_t w break; #ifdef TUP_MEM_CONST_ADDR - case TU_FIFO_COPY_CST_FULL_WORDS: + case TU_FIFO_FIXED_ADDR_RW32: // Intended for hardware buffers from which it can be read word by word only if (n <= lin_count) { // Linear only @@ -232,7 +222,7 @@ static inline void _ff_pull(tu_fifo_t *f, void *app_buf, uint16_t rel) { } // get n items from fifo WITHOUT updating read pointer -static void _ff_pull_n(tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t rd_ptr, tu_fifo_copy_mode_t copy_mode) { +static void _ff_pull_n(tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t rd_ptr, tu_fifo_access_mode_t copy_mode) { const uint16_t lin_count = f->depth - rd_ptr; const uint16_t wrap_count = n - lin_count; // only used if wrapped @@ -243,23 +233,19 @@ static void _ff_pull_n(tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t rd_ptr, uint8_t *ff_buf = f->buffer + (rd_ptr * f->item_size); switch (copy_mode) { - case TU_FIFO_COPY_INC: + case TU_FIFO_INC_ADDR_RW8: if (n <= lin_count) { // Linear only memcpy(app_buf, ff_buf, n * f->item_size); } else { // Wrap around - - // Read data from linear part of buffer - memcpy(app_buf, ff_buf, lin_bytes); - - // Read data wrapped part - memcpy((uint8_t *)app_buf + lin_bytes, f->buffer, wrap_bytes); + memcpy(app_buf, ff_buf, lin_bytes); // linear part + memcpy((uint8_t *)app_buf + lin_bytes, f->buffer, wrap_bytes); // wrapped part } break; #ifdef TUP_MEM_CONST_ADDR - case TU_FIFO_COPY_CST_FULL_WORDS: + case TU_FIFO_FIXED_ADDR_RW32: if (n <= lin_count) { // Linear only _ff_pull_const_addr(app_buf, ff_buf, n * f->item_size); @@ -337,7 +323,7 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t _ff_remaining(uint16_t depth, uint1 // Advance an absolute index // "absolute" index is only in the range of [0..2*depth) -static uint16_t advance_index(uint16_t depth, uint16_t idx, uint16_t offset) { +TU_ATTR_ALWAYS_INLINE static inline uint16_t advance_index(uint16_t depth, uint16_t idx, uint16_t offset) { // We limit the index space of p such that a correct wrap around happens // Check for a wrap around or if we are in unused index space - This has to be checked first!! // We are exploiting the wrap around to the correct index @@ -350,23 +336,7 @@ static uint16_t advance_index(uint16_t depth, uint16_t idx, uint16_t offset) { return new_idx; } -#if 0 // not used but -// Backward an absolute index -static uint16_t backward_index(uint16_t depth, uint16_t idx, uint16_t offset) { - // We limit the index space of p such that a correct wrap around happens - // Check for a wrap around or if we are in unused index space - This has to be checked first!! - // We are exploiting the wrap around to the correct index - uint16_t new_idx = (uint16_t) (idx - offset); - if ( (idx < new_idx) || (new_idx >= 2*depth) ) { - uint16_t const non_used_index_space = (uint16_t) (UINT16_MAX - (2*depth-1)); - new_idx = (uint16_t) (new_idx - non_used_index_space); - } - - return new_idx; -} -#endif - -// index to pointer, simply an modulo with minus. +// index to pointer, simply a modulo with minus. TU_ATTR_ALWAYS_INLINE static inline uint16_t idx2ptr(uint16_t depth, uint16_t idx) { // Only run at most 3 times since index is limit in the range of [0..2*depth) while (idx >= depth) { @@ -416,13 +386,12 @@ static bool _tu_fifo_peek(tu_fifo_t *f, void *p_buffer, uint16_t wr_idx, uint16_ // Works on local copies of w and r // Must be protected by mutexes since in case of an overflow read pointer gets modified -static uint16_t _tu_fifo_peek_n( - tu_fifo_t *f, void *p_buffer, uint16_t n, uint16_t wr_idx, uint16_t rd_idx, tu_fifo_copy_mode_t copy_mode) { +uint16_t tu_fifo_peek_n_access(tu_fifo_t *f, void *p_buffer, uint16_t n, uint16_t wr_idx, uint16_t rd_idx, + tu_fifo_access_mode_t access_mode) { uint16_t cnt = _ff_count(f->depth, wr_idx, rd_idx); - // nothing to peek if (cnt == 0) { - return 0; + return 0; // nothing to peek } // Check overflow and correct if required @@ -431,20 +400,17 @@ static uint16_t _tu_fifo_peek_n( cnt = f->depth; } - // Check if we can read something at and after offset - if too less is available we read what remains if (cnt < n) { - n = cnt; + n = cnt; // limit to available count } - uint16_t rd_ptr = idx2ptr(f->depth, rd_idx); - - // Peek data - _ff_pull_n(f, p_buffer, n, rd_ptr, copy_mode); + const uint16_t rd_ptr = idx2ptr(f->depth, rd_idx); + _ff_pull_n(f, p_buffer, n, rd_ptr, access_mode); return n; } -static uint16_t _tu_fifo_write_n(tu_fifo_t *f, const void *data, uint16_t n, tu_fifo_copy_mode_t copy_mode) { +uint16_t tu_fifo_write_n_access(tu_fifo_t *f, const void *data, uint16_t n, tu_fifo_access_mode_t access_mode) { if (n == 0) { return 0; } @@ -471,7 +437,7 @@ static uint16_t _tu_fifo_write_n(tu_fifo_t *f, const void *data, uint16_t n, tu_ // Since it would end up in a race condition with read functions! if (n >= f->depth) { // Only copy last part - if (copy_mode == TU_FIFO_COPY_INC) { + if (access_mode == TU_FIFO_INC_ADDR_RW8) { buf8 += (n - f->depth) * f->item_size; } else { // TODO should read from hw fifo to discard data, however reading an odd number could @@ -507,7 +473,7 @@ static uint16_t _tu_fifo_write_n(tu_fifo_t *f, const void *data, uint16_t n, tu_ uint16_t wr_ptr = idx2ptr(f->depth, wr_idx); TU_LOG(TU_FIFO_DBG, "actual_n = %u, wr_ptr = %u", n, wr_ptr); - _ff_push_n(f, buf8, n, wr_ptr, copy_mode); + _ff_push_n(f, buf8, n, wr_ptr, access_mode); f->wr_idx = advance_index(f->depth, wr_idx, n); TU_LOG(TU_FIFO_DBG, "\tnew_wr = %u\r\n", f->wr_idx); @@ -518,12 +484,12 @@ static uint16_t _tu_fifo_write_n(tu_fifo_t *f, const void *data, uint16_t n, tu_ return n; } -static uint16_t _tu_fifo_read_n(tu_fifo_t *f, void *buffer, uint16_t n, tu_fifo_copy_mode_t copy_mode) { +uint16_t tu_fifo_read_n_access(tu_fifo_t *f, void *buffer, uint16_t n, tu_fifo_access_mode_t access_mode) { _ff_lock(f->mutex_rd); // Peek the data // f->rd_idx might get modified in case of an overflow so we can not use a local variable - n = _tu_fifo_peek_n(f, buffer, n, f->wr_idx, f->rd_idx, copy_mode); + n = tu_fifo_peek_n_access(f, buffer, n, f->wr_idx, f->rd_idx, access_mode); // Advance read pointer f->rd_idx = advance_index(f->depth, f->rd_idx, n); @@ -651,49 +617,6 @@ bool tu_fifo_read(tu_fifo_t *f, void *buffer) { return ret; } -/******************************************************************************/ -/*! - @brief This function will read n elements from the array index specified by - the read pointer and increment the read index. - This function checks for an overflow and corrects read pointer if required. - - @param[in] f - Pointer to the FIFO buffer to manipulate - @param[in] buffer - The pointer to data location - @param[in] n - Number of element that buffer can afford - - @returns number of items read from the FIFO - */ -/******************************************************************************/ -uint16_t tu_fifo_read_n(tu_fifo_t *f, void *buffer, uint16_t n) { - return _tu_fifo_read_n(f, buffer, n, TU_FIFO_COPY_INC); -} - -#ifdef TUP_MEM_CONST_ADDR -/******************************************************************************/ -/*! - @brief This function will read n elements from the array index specified by - the read pointer and increment the read index. - This function checks for an overflow and corrects read pointer if required. - The dest address will not be incremented which is useful for writing to registers. - - @param[in] f - Pointer to the FIFO buffer to manipulate - @param[in] buffer - The pointer to data location - @param[in] n - Number of element that buffer can afford - - @returns number of items read from the FIFO - */ -/******************************************************************************/ -uint16_t tu_fifo_read_n_const_addr_full_words(tu_fifo_t *f, void *buffer, uint16_t n) { - return _tu_fifo_read_n(f, buffer, n, TU_FIFO_COPY_CST_FULL_WORDS); -} -#endif - /******************************************************************************/ /*! @brief Read one item without removing it from the FIFO. @@ -731,7 +654,7 @@ bool tu_fifo_peek(tu_fifo_t *f, void *p_buffer) { /******************************************************************************/ uint16_t tu_fifo_peek_n(tu_fifo_t *f, void *p_buffer, uint16_t n) { _ff_lock(f->mutex_rd); - uint16_t ret = _tu_fifo_peek_n(f, p_buffer, n, f->wr_idx, f->rd_idx, TU_FIFO_COPY_INC); + uint16_t ret = tu_fifo_peek_n_access(f, p_buffer, n, f->wr_idx, f->rd_idx, TU_FIFO_INC_ADDR_RW8); _ff_unlock(f->mutex_rd); return ret; } @@ -772,45 +695,6 @@ bool tu_fifo_write(tu_fifo_t *f, const void *data) { return ret; } -/******************************************************************************/ -/*! - @brief This function will write n elements into the array index specified by - the write pointer and increment the write index. - - @param[in] f - Pointer to the FIFO buffer to manipulate - @param[in] data - The pointer to data to add to the FIFO - @param[in] count - Number of element - @return Number of written elements - */ -/******************************************************************************/ -uint16_t tu_fifo_write_n(tu_fifo_t *f, const void *data, uint16_t n) { - return _tu_fifo_write_n(f, data, n, TU_FIFO_COPY_INC); -} - -#ifdef TUP_MEM_CONST_ADDR -/******************************************************************************/ -/*! - @brief This function will write n elements into the array index specified by - the write pointer and increment the write index. The source address will - not be incremented which is useful for reading from registers. - - @param[in] f - Pointer to the FIFO buffer to manipulate - @param[in] data - The pointer to data to add to the FIFO - @param[in] count - Number of element - @return Number of written elements - */ -/******************************************************************************/ -uint16_t tu_fifo_write_n_const_addr_full_words(tu_fifo_t *f, const void *data, uint16_t n) { - return _tu_fifo_write_n(f, data, n, TU_FIFO_COPY_CST_FULL_WORDS); -} -#endif - /******************************************************************************/ /*! @brief Clear the fifo read and write pointers diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 9d8b864e9..5cf45b2a7 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -141,6 +141,16 @@ typedef struct { uint8_t _name##_buf[_depth*sizeof(_type)]; \ tu_fifo_t _name = TU_FIFO_INIT(_name##_buf, _depth, _type, _overwritable) +// Write modes intended to allow special read and write functions to be able to +// copy data to and from USB hardware FIFOs as needed for e.g. STM32s and others +typedef enum { + TU_FIFO_INC_ADDR_RW8, // increased address read/write by bytes - normal (default) mode + TU_FIFO_FIXED_ADDR_RW32, // fixed address read/write by 4 bytes (word). Used for STM32 access into USB hardware FIFO +} tu_fifo_access_mode_t; + +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ bool tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable); bool tu_fifo_clear(tu_fifo_t *f); bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_size, bool overwritable); @@ -155,17 +165,23 @@ void tu_fifo_config_mutex(tu_fifo_t *f, osal_mutex_t wr_mutex, osal_mutex_t rd_m #define tu_fifo_config_mutex(_f, _wr_mutex, _rd_mutex) #endif -bool tu_fifo_write(tu_fifo_t *f, void const *data); -uint16_t tu_fifo_write_n(tu_fifo_t *f, const void *data, uint16_t n); +// Write API +uint16_t tu_fifo_write_n_access(tu_fifo_t *f, const void *data, uint16_t n, tu_fifo_access_mode_t access_mode); +bool tu_fifo_write(tu_fifo_t *f, const void *data); +TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_write_n(tu_fifo_t *f, const void *data, uint16_t n) { + return tu_fifo_write_n_access(f, data, n, TU_FIFO_INC_ADDR_RW8); +} +// Read API +uint16_t tu_fifo_read_n_access(tu_fifo_t *f, void *buffer, uint16_t n, tu_fifo_access_mode_t access_mode); bool tu_fifo_read(tu_fifo_t *f, void *buffer); -uint16_t tu_fifo_read_n(tu_fifo_t *f, void *buffer, uint16_t n); - -#ifdef TUP_MEM_CONST_ADDR -uint16_t tu_fifo_write_n_const_addr_full_words(tu_fifo_t *f, const void *data, uint16_t n); -uint16_t tu_fifo_read_n_const_addr_full_words(tu_fifo_t *f, void *buffer, uint16_t n); -#endif +TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_read_n(tu_fifo_t *f, void *buffer, uint16_t n) { + return tu_fifo_read_n_access(f, buffer, n, TU_FIFO_INC_ADDR_RW8); +} +// Peek API +uint16_t tu_fifo_peek_n_access(tu_fifo_t *f, void *p_buffer, uint16_t n, uint16_t wr_idx, uint16_t rd_idx, + tu_fifo_access_mode_t access_mode); bool tu_fifo_peek(tu_fifo_t *f, void *p_buffer); uint16_t tu_fifo_peek_n(tu_fifo_t *f, void *p_buffer, uint16_t n); diff --git a/src/device/usbd.c b/src/device/usbd.c index d4dfae4b4..a65d14daf 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -140,7 +140,7 @@ typedef struct { }usbd_device_t; -tu_static usbd_device_t _usbd_dev; +static usbd_device_t _usbd_dev; static volatile uint8_t _usbd_queued_setup; //--------------------------------------------------------------------+ @@ -153,8 +153,8 @@ static volatile uint8_t _usbd_queued_setup; #endif // Built-in class drivers -tu_static usbd_class_driver_t const _usbd_driver[] = { - #if CFG_TUD_CDC +static const usbd_class_driver_t _usbd_driver[] = { + #if CFG_TUD_CDC { .name = DRIVER_NAME("CDC"), .init = cdcd_init, @@ -340,10 +340,10 @@ tu_static usbd_class_driver_t const _usbd_driver[] = { enum { BUILTIN_DRIVER_COUNT = TU_ARRAY_SIZE(_usbd_driver) }; // Additional class drivers implemented by application -tu_static usbd_class_driver_t const * _app_driver = NULL; -tu_static uint8_t _app_driver_count = 0; +static const usbd_class_driver_t *_app_driver = NULL; +static uint8_t _app_driver_count = 0; -#define TOTAL_DRIVER_COUNT ((uint8_t) (_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. @@ -365,8 +365,10 @@ TU_ATTR_ALWAYS_INLINE static inline usbd_class_driver_t const * get_driver(uint8 //--------------------------------------------------------------------+ // DCD Event //--------------------------------------------------------------------+ -enum { RHPORT_INVALID = 0xFFu }; -tu_static uint8_t _usbd_rhport = RHPORT_INVALID; +enum { + RHPORT_INVALID = 0xFFu +}; +static uint8_t _usbd_rhport = RHPORT_INVALID; static OSAL_SPINLOCK_DEF(_usbd_spin, usbd_int_set); @@ -428,7 +430,7 @@ TU_ATTR_WEAK bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t // Debug //--------------------------------------------------------------------+ #if CFG_TUSB_DEBUG >= CFG_TUD_LOG_LEVEL -tu_static char const* const _usbd_event_str[DCD_EVENT_COUNT] = { +static char const *const _usbd_event_str[DCD_EVENT_COUNT] = { "Invalid", "Bus Reset", "Unplugged", diff --git a/src/portable/microchip/samg/dcd_samg.c b/src/portable/microchip/samg/dcd_samg.c index 149eee794..fad39c6c5 100644 --- a/src/portable/microchip/samg/dcd_samg.c +++ b/src/portable/microchip/samg/dcd_samg.c @@ -436,9 +436,8 @@ void dcd_int_handler(uint8_t rhport) { // write to EP fifo #if 0 // TODO support dcd_edpt_xfer_fifo - if (xfer->ff) - { - tu_fifo_read_n_const_addr_full_words(xfer->ff, (void *) &UDP->UDP_FDR[epnum], xact_len); + if (xfer->ff) { + tu_fifo_read_n_access(xfer->ff, (void *) &UDP->UDP_FDR[epnum], xact_len, TU_FIFO_FIXED_ADDR_RW32); } else #endif @@ -471,9 +470,8 @@ void dcd_int_handler(uint8_t rhport) // Read from EP fifo #if 0 // TODO support dcd_edpt_xfer_fifo API - if (xfer->ff) - { - tu_fifo_write_n_const_addr_full_words(xfer->ff, (const void *) &UDP->UDP_FDR[epnum], xact_len); + if (xfer->ff) { + tu_fifo_write_n_access(xfer->ff, (const void *) &UDP->UDP_FDR[epnum], xact_len, TU_FIFO_FIXED_ADDR_RW32); } else #endif diff --git a/src/portable/nuvoton/nuc505/dcd_nuc505.c b/src/portable/nuvoton/nuc505/dcd_nuc505.c index 7c80f06d9..12f8cbd09 100644 --- a/src/portable/nuvoton/nuc505/dcd_nuc505.c +++ b/src/portable/nuvoton/nuc505/dcd_nuc505.c @@ -193,9 +193,8 @@ static void dcd_userEP_in_xfer(struct xfer_ctl_t *xfer, USBD_EP_T *ep) /* provided buffers are thankfully 32-bit aligned, allowing most data to be transferred as 32-bit */ #if 0 // TODO support dcd_edpt_xfer_fifo API - if (xfer->ff) - { - tu_fifo_read_n_const_addr_full_words(xfer->ff, (void *) (&ep->EPDAT_BYTE), bytes_now); + if (xfer->ff) { + tu_fifo_read_n_access(xfer->ff, (void *) (&ep->EPDAT_BYTE), bytes_now, TU_FIFO_FIXED_ADDR_RW32); } else #endif @@ -696,15 +695,14 @@ void dcd_int_handler(uint8_t rhport) uint16_t const available_bytes = ep->EPDATCNT & USBD_EPDATCNT_DATCNT_Msk; /* copy the data from the PC to the previously provided buffer */ #if 0 // TODO support dcd_edpt_xfer_fifo API - if (xfer->ff) - { - tu_fifo_write_n_const_addr_full_words(xfer->ff, (const void *) &ep->EPDAT_BYTE, tu_min16(available_bytes, xfer->total_bytes - xfer->out_bytes_so_far)); + if (xfer->ff) { + tu_fifo_write_n_access(xfer->ff, (const void *) &ep->EPDAT_BYTE, tu_min16(available_bytes, xfer->total_bytes - xfer->out_bytes_so_far), TU_FIFO_FIXED_ADDR_RW32); } else #endif { - for (int count = 0; (count < available_bytes) && (xfer->out_bytes_so_far < xfer->total_bytes); count++, xfer->out_bytes_so_far++) - { + for (int count = 0; (count < available_bytes) && (xfer->out_bytes_so_far < xfer->total_bytes); + count++, xfer->out_bytes_so_far++) { *xfer->data_ptr++ = ep->EPDAT_BYTE; } } diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index e99cd29c6..1629b1d56 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -362,7 +362,7 @@ static uint16_t epin_write_tx_fifo(uint8_t rhport, uint8_t epnum) { // Push packet to Tx-FIFO if (xfer->ff) { volatile uint32_t* tx_fifo = dwc2->fifo[epnum]; - tu_fifo_read_n_const_addr_full_words(xfer->ff, (void*)(uintptr_t)tx_fifo, xact_bytes); + tu_fifo_read_n_access(xfer->ff, (void *)(uintptr_t)tx_fifo, xact_bytes, TU_FIFO_FIXED_ADDR_RW32); total_bytes_written += xact_bytes; } else { dfifo_write_packet(dwc2, epnum, xfer->buffer, xact_bytes); @@ -878,7 +878,7 @@ static void handle_rxflvl_irq(uint8_t rhport) { if (byte_count != 0) { // Read packet off RxFIFO if (xfer->ff != NULL) { - tu_fifo_write_n_const_addr_full_words(xfer->ff, (const void*) (uintptr_t) rx_fifo, byte_count); + tu_fifo_write_n_access(xfer->ff, (const void *)(uintptr_t)rx_fifo, byte_count, TU_FIFO_FIXED_ADDR_RW32); } else { dfifo_read_packet(dwc2, xfer->buffer, byte_count); xfer->buffer += byte_count; diff --git a/src/tusb_option.h b/src/tusb_option.h index c8265f898..dd5f17dfc 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -268,15 +268,17 @@ // USBIP //--------------------------------------------------------------------+ +//------------- DWC2 -------------// +// Slave mode for device #ifndef CFG_TUD_DWC2_SLAVE_ENABLE #ifndef CFG_TUD_DWC2_SLAVE_ENABLE_DEFAULT - #define CFG_TUD_DWC2_SLAVE_ENABLE_DEFAULT 1 + #define CFG_TUD_DWC2_SLAVE_ENABLE_DEFAULT 1 #endif #define CFG_TUD_DWC2_SLAVE_ENABLE CFG_TUD_DWC2_SLAVE_ENABLE_DEFAULT #endif -// Enable DWC2 DMA for device +// DMA for device #ifndef CFG_TUD_DWC2_DMA_ENABLE #ifndef CFG_TUD_DWC2_DMA_ENABLE_DEFAULT #define CFG_TUD_DWC2_DMA_ENABLE_DEFAULT 0 @@ -285,33 +287,39 @@ #define CFG_TUD_DWC2_DMA_ENABLE CFG_TUD_DWC2_DMA_ENABLE_DEFAULT #endif -// 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 - #endif - - #define CFG_TUD_CI_HS_VBUS_CHARGE CFG_TUD_CI_HS_VBUS_CHARGE_DEFAULT -#endif - -// Enable DWC2 Slave mode for host +// Slave mode for host #ifndef CFG_TUH_DWC2_SLAVE_ENABLE #ifndef CFG_TUH_DWC2_SLAVE_ENABLE_DEFAULT - #define CFG_TUH_DWC2_SLAVE_ENABLE_DEFAULT 1 + #define CFG_TUH_DWC2_SLAVE_ENABLE_DEFAULT 1 #endif #define CFG_TUH_DWC2_SLAVE_ENABLE CFG_TUH_DWC2_SLAVE_ENABLE_DEFAULT #endif -// Enable DWC2 DMA for host +// DMA for host #ifndef CFG_TUH_DWC2_DMA_ENABLE #ifndef CFG_TUH_DWC2_DMA_ENABLE_DEFAULT - #define CFG_TUH_DWC2_DMA_ENABLE_DEFAULT 0 + #define CFG_TUH_DWC2_DMA_ENABLE_DEFAULT 0 #endif - #define CFG_TUH_DWC2_DMA_ENABLE CFG_TUH_DWC2_DMA_ENABLE_DEFAULT + #define CFG_TUH_DWC2_DMA_ENABLE CFG_TUH_DWC2_DMA_ENABLE_DEFAULT +#endif + +#if defined(TUP_USBIP_DWC2) && CFG_TUD_DWC2_SLAVE_ENABLE == 1 +#define TUP_DCD_EDPT_DEDICATED_FIFO #endif +//------------- ChipIdea -------------// +// 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 + #endif + + #define CFG_TUD_CI_HS_VBUS_CHARGE CFG_TUD_CI_HS_VBUS_CHARGE_DEFAULT +#endif + +//------------- pio-usb -------------// // Enable PIO-USB software host controller #ifndef CFG_TUH_RPI_PIO_USB #define CFG_TUH_RPI_PIO_USB 0 @@ -326,7 +334,6 @@ #define CFG_TUH_MAX3421 0 #endif - //-------------------------------------------------------------------- // RootHub Mode detection //-------------------------------------------------------------------- -- cgit v1.3.1 From a6df41d895bb19eecbd16cab9471c82681785d11 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 21 Nov 2025 15:44:07 +0100 Subject: dcd/dwc2: add IN fifo configure Signed-off-by: HiFiPhile --- src/device/usbd.h | 14 ++++++++++++++ src/portable/synopsys/dwc2/dcd_dwc2.c | 21 +++++++++++++++++---- 2 files changed, 31 insertions(+), 4 deletions(-) (limited to 'src/portable') diff --git a/src/device/usbd.h b/src/device/usbd.h index b40ef6277..781688a8a 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -33,6 +33,20 @@ extern "C" { #endif +// ConfigID for tuh_configure() +enum { + TUD_CFGID_INVALID = 0, + TUD_CFGID_DWC2 = 100, +}; + +typedef struct { + uint16_t bm_double_buffered; // bitmap of IN endpoints to be double buffered, only effective for bulk endpoints +} tud_configure_dwc2_t; + +typedef union { + tud_configure_dwc2_t dwc2; +} tud_configure_param_t; + //--------------------------------------------------------------------+ // Application API //--------------------------------------------------------------------+ diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index e99cd29c6..477341791 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.h" #include "device/usbd_pvt.h" #include "dwc2_common.h" @@ -76,6 +77,10 @@ CFG_TUD_MEM_SECTION static struct { TUD_EPBUF_DEF(setup_packet, 8); } _dcd_usbbuf; +static tud_configure_dwc2_t _tud_cfg = { + .bm_double_buffered = 0 +}; + TU_ATTR_ALWAYS_INLINE static inline uint8_t dwc2_ep_count(const dwc2_regs_t* dwc2) { #if TU_CHECK_MCU(OPT_MCU_GD32VF103) (void) dwc2; @@ -212,8 +217,8 @@ static bool dfifo_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t packet_size) { _dcd_data.allocated_epin_count++; } - // If The TXFELVL is configured as half empty, the fifo must be twice the max_size. - if ((dwc2->gahbcfg & GAHBCFG_TX_FIFO_EPMTY_LVL) == 0) { + // Enable double buffering if configured + if (((_tud_cfg.bm_double_buffered & (1 << epnum)) != 0) && (epnum > 0)) { fifo_size *= 2; } @@ -446,6 +451,16 @@ static void edpt_schedule_packets(uint8_t rhport, const uint8_t epnum, const uin //-------------------------------------------------------------------- // Controller API //-------------------------------------------------------------------- +// optional dcd configuration, called by tud_configure() +bool dcd_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param) { + (void) rhport; + TU_VERIFY(cfg_id == TUD_CFGID_DWC2 && cfg_param != NULL); + + const tud_configure_param_t* const cfg = (const tud_configure_param_t*) cfg_param; + _tud_cfg = cfg->dwc2; + return true; +} + bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { (void) rh_init; dwc2_regs_t* dwc2 = DWC2_REG(rhport); @@ -492,9 +507,7 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { // Enable required interrupts dwc2->gintmsk |= GINTMSK_OTGINT | GINTMSK_USBRST | GINTMSK_ENUMDNEM | GINTMSK_WUIM; - // TX FIFO empty level for interrupt is complete empty uint32_t gahbcfg = dwc2->gahbcfg; - gahbcfg |= GAHBCFG_TX_FIFO_EPMTY_LVL; gahbcfg |= GAHBCFG_GINT; // Enable global interrupt dwc2->gahbcfg = gahbcfg; -- cgit v1.3.1 From 50a7d923dd66cbb996c5587db4821fc52a307902 Mon Sep 17 00:00:00 2001 From: milek7 Date: Sun, 23 Nov 2025 00:00:10 +0100 Subject: stm32_fsdev: Fix missed cases in single-buffered isochronous endpoint support. --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'src/portable') diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 381aa0b40..6276f0f07 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -293,7 +293,11 @@ static void handle_ctr_tx(uint32_t ep_id) { return; } xfer->iso_in_sending = false; +#if FSDEV_USE_SBUF_ISO == 0 uint8_t buf_id = (ep_reg & USB_EP_DTOG_TX) ? 0 : 1; +#else + uint8_t buf_id = BTABLE_BUF_TX; +#endif btable_set_count(ep_id, buf_id, 0); } @@ -774,7 +778,12 @@ static bool edpt_xfer(uint8_t rhport, uint8_t ep_num, tusb_dir_t dir) { uint16_t cnt = tu_min16(xfer->total_len, xfer->max_packet_size); - if (ep_is_iso(ep_reg)) { +#if FSDEV_USE_SBUF_ISO == 0 + bool const dbl_buf = ep_is_iso(ep_reg); +#else + bool const dbl_buf = false; +#endif + if (dbl_buf) { btable_set_rx_bufsize(ep_idx, 0, cnt); btable_set_rx_bufsize(ep_idx, 1, cnt); } else { -- cgit v1.3.1 From 4632a78883daeb0d6355542c2daa008bfc4d4cc3 Mon Sep 17 00:00:00 2001 From: Zixun LI Date: Tue, 25 Nov 2025 16:03:21 +0100 Subject: dcd/fsdev: re-enable SBUF for STM32U0, no more issue --- src/portable/st/stm32_fsdev/fsdev_stm32.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/portable') diff --git a/src/portable/st/stm32_fsdev/fsdev_stm32.h b/src/portable/st/stm32_fsdev/fsdev_stm32.h index 30ffadc35..e7a57aca0 100644 --- a/src/portable/st/stm32_fsdev/fsdev_stm32.h +++ b/src/portable/st/stm32_fsdev/fsdev_stm32.h @@ -202,8 +202,7 @@ #include "stm32u0xx.h" #define FSDEV_PMA_SIZE (1024u) #define FSDEV_BUS_32BIT - // Disable SBUF_ISO on U0 for now due to bad performance (audio glitching) - #define FSDEV_HAS_SBUF_ISO 0 + #define FSDEV_HAS_SBUF_ISO 1 #define USB USB_DRD_FS #define USB_EP_CTR_RX USB_EP_VTRX -- cgit v1.3.1 From fb631c9a402478702fcce7168a5f1cc3b231e959 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Mon, 24 Nov 2025 00:26:05 +0100 Subject: hcd: add fsdev driver Signed-off-by: HiFiPhile --- examples/host/device_info/only.txt | 1 + examples/host/msc_file_explorer/only.txt | 1 + hw/bsp/stm32c0/family.c | 4 +- hw/bsp/stm32c0/family.cmake | 1 + hw/bsp/stm32c0/family.mk | 1 + src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 20 +- src/portable/st/stm32_fsdev/fsdev_at32.h | 16 +- src/portable/st/stm32_fsdev/fsdev_ch32.h | 9 +- src/portable/st/stm32_fsdev/fsdev_stm32.h | 15 +- src/portable/st/stm32_fsdev/fsdev_type.h | 41 +- src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c | 833 ++++++++++++++++++++++++++ 11 files changed, 917 insertions(+), 25 deletions(-) create mode 100644 src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c (limited to 'src/portable') diff --git a/examples/host/device_info/only.txt b/examples/host/device_info/only.txt index 61a08f68d..069f92d83 100644 --- a/examples/host/device_info/only.txt +++ b/examples/host/device_info/only.txt @@ -13,6 +13,7 @@ mcu:MSP432E4 mcu:RP2040 mcu:RX65X mcu:RAXXX +mcu:STM32C0 mcu:STM32F4 mcu:STM32F7 mcu:STM32H7 diff --git a/examples/host/msc_file_explorer/only.txt b/examples/host/msc_file_explorer/only.txt index cba58f8e8..a7bebf1d9 100644 --- a/examples/host/msc_file_explorer/only.txt +++ b/examples/host/msc_file_explorer/only.txt @@ -13,6 +13,7 @@ mcu:MSP432E4 mcu:RX65X mcu:RAXXX mcu:MAX3421 +mcu:STM32C0 mcu:STM32F4 mcu:STM32F7 mcu:STM32H7 diff --git a/hw/bsp/stm32c0/family.c b/hw/bsp/stm32c0/family.c index 09704b527..b04a9cea5 100644 --- a/hw/bsp/stm32c0/family.c +++ b/hw/bsp/stm32c0/family.c @@ -37,13 +37,13 @@ // Forward USB interrupt events to TinyUSB IRQ Handler //--------------------------------------------------------------------+ void USB_DRD_FS_IRQHandler(void) { - tud_int_handler(0); + tusb_int_handler(0, true); } // Startup code generated by STM32CubeIDE uses USB_IRQHandler, while // stm32c071xx.s from cmsis_device_c0 uses USB_DRD_FS_IRQHandler. void USB_IRQHandler(void) { - USB_DRD_FS_IRQHandler(); + tusb_int_handler(0, true); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/stm32c0/family.cmake b/hw/bsp/stm32c0/family.cmake index f68e80895..6e04b20f4 100644 --- a/hw/bsp/stm32c0/family.cmake +++ b/hw/bsp/stm32c0/family.cmake @@ -66,6 +66,7 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c + ${TOP}/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c ${TOP}/src/portable/st/typec/typec_stm32.c ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) diff --git a/hw/bsp/stm32c0/family.mk b/hw/bsp/stm32c0/family.mk index bdb34454e..fd03ad537 100644 --- a/hw/bsp/stm32c0/family.mk +++ b/hw/bsp/stm32c0/family.mk @@ -29,6 +29,7 @@ LDFLAGS_GCC += \ SRC_C += \ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ + src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c \ $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \ diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 381aa0b40..db1a5784a 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -123,8 +123,6 @@ #error "Unknown USB IP" #endif -#include "fsdev_type.h" - //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ @@ -848,6 +846,24 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { ep_write(ep_idx, ep_reg, true); } +void dcd_int_enable(uint8_t rhport) { + fsdev_int_enable(rhport); +} + +void dcd_int_disable(uint8_t rhport) { + fsdev_int_disable(rhport); +} + +#if defined(USB_BCDR_DPPU) || defined(SYSCFG_PMC_USB_PU) +void dcd_connect(uint8_t rhport) { + fsdev_connect(rhport); +} + +void dcd_disconnect(uint8_t rhport) { + fsdev_disconnect(rhport); +} +#endif + //--------------------------------------------------------------------+ // PMA read/write //--------------------------------------------------------------------+ diff --git a/src/portable/st/stm32_fsdev/fsdev_at32.h b/src/portable/st/stm32_fsdev/fsdev_at32.h index deb1de2a8..03490ee24 100644 --- a/src/portable/st/stm32_fsdev/fsdev_at32.h +++ b/src/portable/st/stm32_fsdev/fsdev_at32.h @@ -168,7 +168,7 @@ enum { FSDEV_IRQ_NUM = TU_ARRAY_SIZE(fsdev_irq) }; #error "Unsupported MCU" #endif -void dcd_int_enable(uint8_t rhport) { +void fsdev_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 @@ -187,7 +187,7 @@ void dcd_int_enable(uint8_t rhport) { } } -void dcd_int_disable(uint8_t rhport) { +void fsdev_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 @@ -206,20 +206,20 @@ void dcd_int_disable(uint8_t rhport) { } } -void dcd_disconnect(uint8_t rhport) { +void fsdev_disconnect(uint8_t rhport) { (void) rhport; /* disable usb phy */ - FSDEV_REG->CNTR |= USB_CNTR_PDWN; + *(volatile uint32_t*)(FSDEV_REG_BASE + 0x40) |= USB_CNTR_PDWN; /* D+ 1.5k pull-up disable, USB->cfg_bit.puo = TRUE; */ - *(uint32_t *)(FSDEV_REG_BASE+0x60) |= (1u<<1); + *(volatile uint32_t *)(FSDEV_REG_BASE+0x60) |= (1u<<1); } -void dcd_connect(uint8_t rhport) { +void fsdev_connect(uint8_t rhport) { (void) rhport; /* enable usb phy */ - FSDEV_REG->CNTR &= ~USB_CNTR_PDWN; + *(volatile uint32_t*)(FSDEV_REG_BASE + 0x40) &= ~USB_CNTR_PDWN; /* Dp 1.5k pull-up enable, USB->cfg_bit.puo = 0; */ - *(uint32_t *)(FSDEV_REG_BASE+0x60) &= ~(1u<<1); + *(volatile uint32_t *)(FSDEV_REG_BASE+0x60) &= ~(1u<<1); } #endif diff --git a/src/portable/st/stm32_fsdev/fsdev_ch32.h b/src/portable/st/stm32_fsdev/fsdev_ch32.h index ceebb6dab..547f3bd1b 100644 --- a/src/portable/st/stm32_fsdev/fsdev_ch32.h +++ b/src/portable/st/stm32_fsdev/fsdev_ch32.h @@ -168,6 +168,7 @@ #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" //--------------------------------------------------------------------+ // @@ -184,26 +185,26 @@ enum { FSDEV_IRQ_NUM = TU_ARRAY_SIZE(fsdev_irq) }; #error "Unsupported MCU" #endif -void dcd_int_enable(uint8_t rhport) { +void fsdev_int_enable(uint8_t rhport) { (void)rhport; for(uint8_t i=0; i < FSDEV_IRQ_NUM; i++) { NVIC_EnableIRQ(fsdev_irq[i]); } } -void dcd_int_disable(uint8_t rhport) { +void fsdev_int_disable(uint8_t rhport) { (void)rhport; for(uint8_t i=0; i < FSDEV_IRQ_NUM; i++) { NVIC_DisableIRQ(fsdev_irq[i]); } } -void dcd_disconnect(uint8_t rhport) { +void fsdev_disconnect(uint8_t rhport) { (void) rhport; EXTEN->EXTEN_CTR &= ~EXTEN_USBD_PU_EN; } -void dcd_connect(uint8_t rhport) { +void fsdev_connect(uint8_t rhport) { (void) rhport; EXTEN->EXTEN_CTR |= EXTEN_USBD_PU_EN; } diff --git a/src/portable/st/stm32_fsdev/fsdev_stm32.h b/src/portable/st/stm32_fsdev/fsdev_stm32.h index 30ffadc35..d47d23f14 100644 --- a/src/portable/st/stm32_fsdev/fsdev_stm32.h +++ b/src/portable/st/stm32_fsdev/fsdev_stm32.h @@ -321,6 +321,8 @@ #define FSDEV_USE_SBUF_ISO 0 #endif +#include "fsdev_type.h" + //--------------------------------------------------------------------+ // //--------------------------------------------------------------------+ @@ -372,7 +374,7 @@ static const IRQn_Type fsdev_irq[] = { }; enum { FSDEV_IRQ_NUM = TU_ARRAY_SIZE(fsdev_irq) }; -void dcd_int_enable(uint8_t rhport) { +void fsdev_int_enable(uint8_t rhport) { (void)rhport; // forces write to RAM before allowing ISR to execute @@ -395,7 +397,7 @@ void dcd_int_enable(uint8_t rhport) { } } -void dcd_int_disable(uint8_t rhport) { +void fsdev_int_disable(uint8_t rhport) { (void)rhport; #if CFG_TUSB_MCU == OPT_MCU_STM32F3 && defined(SYSCFG_CFGR1_USB_IT_RMP) @@ -420,28 +422,27 @@ void dcd_int_disable(uint8_t rhport) { // Define only on MCU with internal pull-up. BSP can define on MCU without internal PU. #if defined(USB_BCDR_DPPU) -void dcd_disconnect(uint8_t rhport) { +void fsdev_disconnect(uint8_t rhport) { (void)rhport; USB->BCDR &= ~(USB_BCDR_DPPU); } -void dcd_connect(uint8_t rhport) { +void fsdev_connect(uint8_t rhport) { (void)rhport; USB->BCDR |= USB_BCDR_DPPU; } #elif defined(SYSCFG_PMC_USB_PU) // works e.g. on STM32L151 -void dcd_disconnect(uint8_t rhport) { +void fsdev_disconnect(uint8_t rhport) { (void)rhport; SYSCFG->PMC &= ~(SYSCFG_PMC_USB_PU); } -void dcd_connect(uint8_t rhport) { +void fsdev_connect(uint8_t rhport) { (void)rhport; SYSCFG->PMC |= SYSCFG_PMC_USB_PU; } #endif - #endif /* TUSB_FSDEV_STM32_H */ diff --git a/src/portable/st/stm32_fsdev/fsdev_type.h b/src/portable/st/stm32_fsdev/fsdev_type.h index cf36576bb..2b340d64a 100644 --- a/src/portable/st/stm32_fsdev/fsdev_type.h +++ b/src/portable/st/stm32_fsdev/fsdev_type.h @@ -174,6 +174,14 @@ typedef enum { #define EP_STAT_MASK(_dir) (3u << (USB_EPTX_STAT_Pos + ((_dir) == TUSB_DIR_IN ? 0 : 8))) #define EP_DTOG_MASK(_dir) (1u << (USB_EP_DTOG_TX_Pos + ((_dir) == TUSB_DIR_IN ? 0 : 8))) +#define CH_STAT_MASK(_dir) (3u << (USB_EPTX_STAT_Pos + ((_dir) == TUSB_DIR_IN ? 8 : 0))) +#define CH_DTOG_MASK(_dir) (1u << (USB_EP_DTOG_TX_Pos + ((_dir) == TUSB_DIR_IN ? 8 : 0))) + +void fsdev_int_enable(uint8_t rhport); +void fsdev_int_disable(uint8_t rhport); +void fsdev_connect(uint8_t rhport); +void fsdev_disconnect(uint8_t rhport); + //--------------------------------------------------------------------+ // Endpoint Helper // - CTR is write 0 to clear @@ -186,13 +194,13 @@ TU_ATTR_ALWAYS_INLINE static inline uint32_t ep_read(uint32_t ep_id) { TU_ATTR_ALWAYS_INLINE static inline void ep_write(uint32_t ep_id, uint32_t value, bool need_exclusive) { if (need_exclusive) { - dcd_int_disable(0); + fsdev_int_disable(0); } FSDEV_REG->ep[ep_id].reg = (fsdev_bus_t) value; if (need_exclusive) { - dcd_int_enable(0); + fsdev_int_enable(0); } } @@ -216,6 +224,35 @@ TU_ATTR_ALWAYS_INLINE static inline bool ep_is_iso(uint32_t reg) { return (reg & USB_EP_TYPE_MASK) == USB_EP_ISOCHRONOUS; } +//--------------------------------------------------------------------+ +// Channel Helper +// - Direction is opposite to endpoint direction +//--------------------------------------------------------------------+ + +TU_ATTR_ALWAYS_INLINE static inline uint32_t ch_read(uint32_t ch_id) { + return ep_read(ch_id); +} + +TU_ATTR_ALWAYS_INLINE static inline void ch_write(uint32_t ch_id, uint32_t value, bool need_exclusive) { + ep_write(ch_id, value, need_exclusive); +} + +TU_ATTR_ALWAYS_INLINE static inline void ch_write_clear_ctr(uint32_t ch_id, tusb_dir_t dir) { + uint32_t reg = FSDEV_REG->ep[ch_id].reg; + reg |= USB_EP_CTR_TX | USB_EP_CTR_RX; + reg &= USB_EPREG_MASK; + reg &= ~(1 << (USB_EP_CTR_TX_Pos + (dir == TUSB_DIR_IN ? 8 : 0))); + ep_write(ch_id, reg, false); +} + +TU_ATTR_ALWAYS_INLINE static inline void ch_change_status(uint32_t* reg, tusb_dir_t dir, ep_stat_t state) { + *reg ^= (state << (USB_EPTX_STAT_Pos + (dir == TUSB_DIR_IN ? 8 : 0))); +} + +TU_ATTR_ALWAYS_INLINE static inline void ch_change_dtog(uint32_t* reg, tusb_dir_t dir, uint8_t state) { + *reg ^= (state << (USB_EP_DTOG_TX_Pos + (dir == TUSB_DIR_IN ? 8 : 0))); +} + //--------------------------------------------------------------------+ // BTable Helper //--------------------------------------------------------------------+ diff --git a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c new file mode 100644 index 000000000..1c08f64d6 --- /dev/null +++ b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c @@ -0,0 +1,833 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2025 HiFiPhile (Zixun LI) + * + * 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. + */ + +/********************************************** + * This driver provides USB Host controller support for STM32 MCUs with "USB A"/"PCD"/"HCD" peripheral. + * This covers these MCU families: + * + * C0 2048 byte buffer; 32-bit bus; host mode + * G0 2048 byte buffer; 32-bit bus; host mode + * H5 2048 byte buffer; 32-bit bus; host mode + * U535, U545 2048 byte buffer; 32-bit bus; host mode + * + */ + +#include "tusb_option.h" + +#if CFG_TUH_ENABLED && defined(TUP_USBIP_FSDEV) && \ + TU_CHECK_MCU(OPT_MCU_STM32C0, OPT_MCU_STM32G0, OPT_MCU_STM32H5, OPT_MCU_STM32U5) + +#include "host/hcd.h" +#include "host/usbh.h" + +#if defined(TUP_USBIP_FSDEV_STM32) + #include "fsdev_stm32.h" +#else + #error "Unknown USB IP" +#endif + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ + +// Debug level for FSDEV +#define FSDEV_DEBUG 1 + +// Max number of endpoints application can open, can be larger than FSDEV_EP_COUNT +#ifndef CFG_TUH_FSDEV_ENDPOINT_MAX + #define CFG_TUH_FSDEV_ENDPOINT_MAX 16u +#endif + +TU_VERIFY_STATIC(CFG_TUH_FSDEV_ENDPOINT_MAX <= 255, "currently only use 8-bit for index"); + +enum { + HCD_XFER_ERROR_MAX = 3 +}; + +// Host driver struct for each opened endpoint +typedef struct { + uint8_t *buffer; + uint16_t buflen; + uint16_t max_packet_size; + uint8_t dev_addr; + uint8_t ep_addr; + uint8_t ep_type; + uint8_t interval; + bool low_speed; + bool allocated; + bool next_setup; +} hcd_endpoint_t; + +// Additional info for each channel when it is active +typedef struct { + hcd_endpoint_t* edpt[2]; // OUT/IN + uint16_t queued_len[2]; + uint8_t dev_addr; + uint8_t ep_num; + uint8_t ep_type; + bool allocated[2]; + uint8_t retry[2]; + uint8_t result; +} hcd_xfer_t; + +// Root hub port state +static struct { + bool connected; +} _hcd_port; + +typedef struct { + hcd_xfer_t xfer[FSDEV_EP_COUNT]; + hcd_endpoint_t edpt[CFG_TUH_FSDEV_ENDPOINT_MAX]; +} hcd_data_t; + +hcd_data_t _hcd_data; + +//--------------------------------------------------------------------+ +// Prototypes +//--------------------------------------------------------------------+ + +static uint8_t endpoint_alloc(void); +static uint8_t endpoint_find(uint8_t dev_addr, uint8_t ep_addr); +static uint32_t hcd_pma_alloc(uint8_t channel, tusb_dir_t dir, uint16_t len); +static uint8_t channel_alloc(uint8_t dev_addr, uint8_t ep_addr, uint8_t ep_type); +static bool hcd_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t nbytes); +static bool hcd_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t nbytes); +static bool edpt_xfer_kickoff(uint8_t ep_id); +static bool channel_xfer_start(uint8_t ch_id, tusb_dir_t dir); +static void edpoint_close(uint8_t ep_id); +static void port_status_handler(uint8_t rhport, bool in_isr); +//--------------------------------------------------------------------+ +// Inline Functions +//--------------------------------------------------------------------+ + +static inline void endpoint_dealloc(hcd_endpoint_t* edpt) { + edpt->allocated = false; +} + +static inline void channel_dealloc(hcd_xfer_t* xfer, tusb_dir_t dir) { + xfer->allocated[dir] = false; +} + +//--------------------------------------------------------------------+ +// Controller API +//--------------------------------------------------------------------+ + +// 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; + return false; +} + +// Initialize controller to host mode +bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { + (void) rh_init; + + // Follow the RM mentions to use a special ordering of PDWN and FRES + for (volatile uint32_t i = 0; i < 200; i++) { + asm("NOP"); + } + + // Perform USB peripheral reset + FSDEV_REG->CNTR = USB_CNTR_FRES | USB_CNTR_PDWN; + for (volatile uint32_t i = 0; i < 200; i++) { + asm("NOP"); + } + + FSDEV_REG->CNTR &= ~USB_CNTR_PDWN; + + // Wait startup time + for (volatile uint32_t i = 0; i < 200; i++) { + asm("NOP"); + } + + FSDEV_REG->CNTR = USB_CNTR_HOST; // Enable USB in Host mode + +#if !defined(FSDEV_BUS_32BIT) + // BTABLE register does not exist on 32-bit bus devices + FSDEV_REG->BTABLE = FSDEV_BTABLE_BASE; +#endif + + FSDEV_REG->ISTR = 0; // Clear pending interrupts + + // Reset channels to disabled + for (uint32_t i = 0; i < FSDEV_EP_COUNT; i++) { + ch_write(i, 0u, false); + } + + tu_memclr(&_hcd_data, sizeof(_hcd_data)); + + // Enable interrupts for host mode + FSDEV_REG->CNTR |= USB_CNTR_RESETM | USB_CNTR_CTRM | USB_CNTR_SUSPM | + USB_CNTR_WKUPM | USB_CNTR_ERRM | USB_CNTR_PMAOVRM; + + // Initialize port state + _hcd_port.connected = false; + + fsdev_connect(rhport); + + return true; +} + +static void port_status_handler(uint8_t rhport, bool in_isr) { + uint32_t const fnr_reg = FSDEV_REG->FNR; + uint32_t const istr_reg = FSDEV_REG->ISTR; + // SE0 detected USB Disconnected state + if ((fnr_reg & (USB_FNR_RXDP | USB_FNR_RXDM)) == 0U) { + _hcd_port.connected = false; + hcd_event_device_remove(rhport, in_isr); + return; + } + + if (!_hcd_port.connected) { + // J-state or K-state detected & LastState=Disconnected + if (((fnr_reg & USB_FNR_RXDP) != 0U) || ((istr_reg & USB_ISTR_LS_DCONN) != 0U)) { + _hcd_port.connected = true; + hcd_event_device_attach(rhport, in_isr); + } + } else { + // J-state or K-state detected & lastState=Connected: a Missed disconnection is detected + if (((fnr_reg & USB_FNR_RXDP) != 0U) || ((istr_reg & USB_ISTR_LS_DCONN) != 0U)) { + _hcd_port.connected = false; + hcd_event_device_remove(rhport, in_isr); + } + } +} + +// Handle CTR interrupt for the TX/OUT direction +static void handle_ctr_tx(uint32_t ch_id) { + uint32_t ch_reg = ch_read(ch_id) | USB_EP_CTR_TX | USB_EP_CTR_RX; + + uint8_t const ep_num = ch_reg & USB_EPADDR_FIELD; + uint8_t const daddr = (ch_reg & USB_CHEP_DEVADDR_Msk) >> USB_CHEP_DEVADDR_Pos; + + uint8_t ep_id = endpoint_find(daddr, ep_num); + TU_VERIFY(ep_id != TUSB_INDEX_INVALID_8, ); + + hcd_endpoint_t* edpt = &_hcd_data.edpt[ep_id]; + hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; + TU_VERIFY(xfer->allocated[TUSB_DIR_OUT],); + + // Manage Correct Transaction + if ((ch_reg & USB_CH_ERRTX) == 0U) { + // Acked + if ((ch_reg & USB_CH_TX_STTX) == USB_CH_TX_ACK_SBUF) { + if (edpt->buflen != xfer->queued_len[TUSB_DIR_OUT]) { + uint16_t const len = tu_min16(edpt->buflen - xfer->queued_len[TUSB_DIR_OUT], edpt->max_packet_size); + uint16_t pma_addr = (uint16_t) btable_get_addr(ch_id, BTABLE_BUF_TX); + hcd_write_packet_memory(pma_addr, &(edpt->buffer[xfer->queued_len[TUSB_DIR_OUT]]), len); + btable_set_count(ch_id, BTABLE_BUF_TX, len); + xfer->queued_len[TUSB_DIR_OUT] += len; + + ch_change_status(&ch_reg, TUSB_DIR_OUT, EP_STAT_VALID); + ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(TUSB_DIR_OUT); // only change TX Status, reserve other toggle bits + ch_write(ch_id, ch_reg, false); + } else { + channel_dealloc(xfer, TUSB_DIR_OUT); + hcd_event_xfer_complete(daddr, ep_num, xfer->queued_len[TUSB_DIR_OUT], XFER_RESULT_SUCCESS, true); + } + } else if ((ch_reg & USB_CH_TX_STTX) == USB_CH_TX_NAK) { + // NAKed + if (edpt->ep_type != TUSB_XFER_INTERRUPT) { + ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(TUSB_DIR_OUT); // will change TX Status, reserved other toggle bits + ch_change_status(&ch_reg, TUSB_DIR_OUT, EP_STAT_VALID); + ch_write(ch_id, ch_reg, false); + } + } else if ((ch_reg & USB_CH_TX_STTX) == USB_CH_TX_STALL) { + // STALLed + channel_dealloc(xfer, TUSB_DIR_OUT); + ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(TUSB_DIR_OUT); // will change TX Status, reserved other toggle bits + ch_change_status(&ch_reg, TUSB_DIR_OUT, EP_STAT_DISABLED); + ch_write(ch_id, ch_reg, false); + hcd_event_xfer_complete(daddr, ep_num, xfer->queued_len[TUSB_DIR_OUT], XFER_RESULT_STALLED, true); + } + } else { + // Error + TU_LOG(FSDEV_DEBUG, "handle_ctr_tx error epreg=0x%08X ch=%u ep=0x%02X daddr=%u queued=%u/%u\r\n", + ch_reg, ch_id, ep_num, daddr, xfer->queued_len[TUSB_DIR_OUT], edpt->buflen); + ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(TUSB_DIR_OUT); // will change TX Status, reserved other toggle bits + ch_reg &=~USB_CH_ERRTX; + if (xfer->retry[TUSB_DIR_OUT] < HCD_XFER_ERROR_MAX) { + // Retry + xfer->retry[TUSB_DIR_OUT]++; + } else { + // Failed after retries + channel_dealloc(xfer, TUSB_DIR_OUT); + ch_change_status(&ch_reg, TUSB_DIR_OUT, EP_STAT_DISABLED); + hcd_event_xfer_complete(daddr, ep_num, xfer->queued_len[TUSB_DIR_OUT], XFER_RESULT_FAILED, true); + } + ch_write(ch_id, ch_reg, false); + } +} + +// Handle CTR interrupt for the RX/IN direction +static void handle_ctr_rx(uint32_t ch_id) { + uint32_t ch_reg = ch_read(ch_id) | USB_EP_CTR_TX | USB_EP_CTR_RX; + uint8_t const ep_num = ch_reg & USB_EPADDR_FIELD; + + uint8_t const daddr = (ch_reg & USB_CHEP_DEVADDR_Msk) >> USB_CHEP_DEVADDR_Pos; + + uint8_t ep_id = endpoint_find(daddr, ep_num | TUSB_DIR_IN_MASK); + TU_VERIFY(ep_id != TUSB_INDEX_INVALID_8, ); + + hcd_endpoint_t* edpt = &_hcd_data.edpt[ep_id]; + hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; + TU_VERIFY(xfer->allocated[TUSB_DIR_IN],); + + // Manage Correct Transaction + if ((ch_reg & USB_CH_ERRRX) == 0U) { + // Acked + if ((ch_reg & USB_CH_RX_STRX) == USB_CH_RX_ACK_SBUF) { + uint16_t const rx_count = btable_get_count(ch_id, BTABLE_BUF_RX); + uint16_t pma_addr = (uint16_t) btable_get_addr(ch_id, BTABLE_BUF_RX); + + hcd_read_packet_memory(edpt->buffer + xfer->queued_len[TUSB_DIR_IN], pma_addr, rx_count); + xfer->queued_len[TUSB_DIR_IN] += rx_count; + + if ((rx_count < edpt->max_packet_size) || (xfer->queued_len[TUSB_DIR_IN] >= edpt->buflen)) { + // all bytes received or short packet + channel_dealloc(xfer, TUSB_DIR_IN); + hcd_event_xfer_complete(daddr, ep_num | TUSB_DIR_IN_MASK, xfer->queued_len[TUSB_DIR_IN], XFER_RESULT_SUCCESS, true); + } else { + // Set endpoint active again for receiving more data. Note that isochronous endpoints stay active always + uint16_t const cnt = tu_min16(edpt->buflen - xfer->queued_len[TUSB_DIR_IN], edpt->max_packet_size); + btable_set_rx_bufsize(ch_id, BTABLE_BUF_RX, cnt); + ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(TUSB_DIR_IN); // will change RX Status, reserved other toggle bits + ch_change_status(&ch_reg, TUSB_DIR_IN, EP_STAT_VALID); + ch_write(ch_id, ch_reg, false); + } + } else if ((ch_reg & USB_CH_RX_STRX) == USB_CH_RX_NAK) { + // NAKed + if (edpt->ep_type != TUSB_XFER_INTERRUPT) { + ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(TUSB_DIR_IN); // will change TX Status, reserved other toggle bits + ch_change_status(&ch_reg, TUSB_DIR_IN, EP_STAT_VALID); + ch_write(ch_id, ch_reg, false); + } + } else { + // STALLed + channel_dealloc(xfer, TUSB_DIR_IN); + ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(TUSB_DIR_IN); // will change TX Status, reserved other toggle bits + ch_change_status(&ch_reg, TUSB_DIR_IN, EP_STAT_DISABLED); + ch_write(ch_id, ch_reg, false); + hcd_event_xfer_complete(daddr, ep_num | TUSB_DIR_IN_MASK, xfer->queued_len[TUSB_DIR_IN], XFER_RESULT_STALLED, true); + } + } else { + // Error + TU_LOG(FSDEV_DEBUG, "handle_ctr_tx error epreg=0x%08X ch=%u ep=0x%02X daddr=%u queued=%u/%u\r\n", + ch_reg, ch_id, ep_num, daddr, xfer->queued_len[TUSB_DIR_IN], edpt->buflen); + ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(TUSB_DIR_IN); // will change RX Status, reserved other toggle bits + ch_reg &=~USB_CH_ERRRX; + if (xfer->retry[TUSB_DIR_IN] < HCD_XFER_ERROR_MAX) { + // Retry + xfer->retry[TUSB_DIR_IN]++; + } else { + // Failed after retries + channel_dealloc(xfer, TUSB_DIR_IN); + ch_change_status(&ch_reg, TUSB_DIR_IN, EP_STAT_DISABLED); + hcd_event_xfer_complete(daddr, ep_num | TUSB_DIR_IN_MASK, xfer->queued_len[TUSB_DIR_IN], XFER_RESULT_FAILED, true); + } + ch_write(ch_id, ch_reg, false); + } +} + +// Interrupt Handler +void hcd_int_handler(uint8_t rhport, bool in_isr) { + uint32_t int_status = FSDEV_REG->ISTR; + + /* Port Change Detected (Connection/Disconnection) */ + if (int_status & USB_ISTR_DCON) { + FSDEV_REG->ISTR = (fsdev_bus_t)~USB_ISTR_DCON; + port_status_handler(rhport, in_isr); + } + + // Handle transfer complete (CTR) + while (FSDEV_REG->ISTR & USB_ISTR_CTR) { + uint32_t const ch_id = FSDEV_REG->ISTR & USB_ISTR_EP_ID; + uint32_t const ch_reg = ch_read(ch_id); + + if (ch_reg & USB_EP_CTR_RX) { + #ifdef FSDEV_BUS_32BIT + /* https://www.st.com/resource/en/errata_sheet/es0561-stm32h503cbebkbrb-device-errata-stmicroelectronics.pdf + * https://www.st.com/resource/en/errata_sheet/es0587-stm32u535xx-and-stm32u545xx-device-errata-stmicroelectronics.pdf + * From H503/U535 errata: Buffer description table update completes after CTR interrupt triggers + * Description: + * - During OUT transfers, the correct transfer interrupt (CTR) is triggered a little before the last USB SRAM accesses + * have completed. If the software responds quickly to the interrupt, the full buffer contents may not be correct. + * Workaround: + * - Software should ensure that a small delay is included before accessing the SRAM contents. This delay + * should be 800 ns in Full Speed mode and 6.4 μs in Low Speed mode + * - Since H5 can run up to 250Mhz -> 1 cycle = 4ns. Per errata, we need to wait 200 cycles. Though executing code + * also takes time, so we'll wait 60 cycles (count = 20). + * - Since Low Speed mode is not supported/popular, we will ignore it for now. + * + * Note: this errata may also apply to G0, U5, H5 etc. + */ + volatile uint32_t cycle_count = 20; // defined as PCD_RX_PMA_CNT in stm32 hal_driver + while (cycle_count > 0U) { + cycle_count--; // each count take 3 cycles (1 for sub, jump, and compare) + } + #endif + + ch_write_clear_ctr(ch_id, TUSB_DIR_IN); + handle_ctr_rx(ch_id); + } + + if (ch_reg & USB_EP_CTR_TX) { + ch_write_clear_ctr(ch_id, TUSB_DIR_OUT); + handle_ctr_tx(ch_id); + } + } + + if (int_status & USB_ISTR_ERR) { + FSDEV_REG->ISTR = (fsdev_bus_t)~USB_ISTR_ERR; + // TODO: Handle error + } + + if (int_status & USB_ISTR_PMAOVR) { + TU_BREAKPOINT(); + FSDEV_REG->ISTR = (fsdev_bus_t)~USB_ISTR_PMAOVR; + } +} + +// Enable USB interrupt +void hcd_int_enable(uint8_t rhport) { + fsdev_int_enable(rhport); +} + +// Disable USB interrupt +void hcd_int_disable(uint8_t rhport) { + fsdev_int_disable(rhport); +} + +// Get frame number (1ms) +uint32_t hcd_frame_number(uint8_t rhport) { + (void) rhport; + return FSDEV_REG->FNR & USB_FNR_FN; +} + +//--------------------------------------------------------------------+ +// Port API +//--------------------------------------------------------------------+ + +// Get the current connect status of roothub port +bool hcd_port_connect_status(uint8_t rhport) { + (void) rhport; + return _hcd_port.connected; +} + +// Reset USB bus on the port +void hcd_port_reset(uint8_t rhport) { + (void) rhport; + FSDEV_REG->CNTR |= USB_CNTR_FRES; +} + +// Complete bus reset sequence +void hcd_port_reset_end(uint8_t rhport) { + (void) rhport; + FSDEV_REG->CNTR &= ~USB_CNTR_FRES; +} + +// Get port link speed +tusb_speed_t hcd_port_speed_get(uint8_t rhport) { + (void) rhport; + if ((FSDEV_REG->ISTR & USB_ISTR_LS_DCONN) != 0U) { + return TUSB_SPEED_LOW; + } else { + return TUSB_SPEED_FULL; + } +} + +// HCD closes all opened endpoints belonging to this device +void hcd_device_close(uint8_t rhport, uint8_t dev_addr) { + (void) rhport; + + // Close all endpoints for this device + for(uint32_t i = 0; i < CFG_TUH_FSDEV_ENDPOINT_MAX; i++) { + hcd_endpoint_t* edpt = &_hcd_data.edpt[i]; + if (edpt->allocated && edpt->dev_addr == dev_addr) { + edpoint_close(i); + } + } + +} + +//--------------------------------------------------------------------+ +// Endpoints API +//--------------------------------------------------------------------+ + +// Open an endpoint +bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const *ep_desc) { + (void) rhport; + + uint8_t const ep_addr = ep_desc->bEndpointAddress; + uint16_t const packet_size = tu_edpt_packet_size(ep_desc); + uint8_t const ep_type = ep_desc->bmAttributes.xfer; + + uint8_t const ep_id = endpoint_alloc(); + TU_ASSERT(ep_id < CFG_TUH_FSDEV_ENDPOINT_MAX); + + hcd_endpoint_t* edpt = &_hcd_data.edpt[ep_id]; + edpt->dev_addr = dev_addr; + edpt->ep_addr = ep_addr; + edpt->ep_type = ep_type; + edpt->max_packet_size = packet_size; + edpt->interval = ep_desc->bInterval; + edpt->low_speed = (hcd_port_speed_get(rhport) == TUSB_SPEED_FULL && tuh_speed_get(dev_addr) == TUSB_SPEED_LOW); + + // EP0 is bi-directional, so we need to open both OUT and IN channels + if (ep_addr == 0) { + uint8_t const ep_id_in = endpoint_alloc(); + TU_ASSERT(ep_id_in < CFG_TUH_FSDEV_ENDPOINT_MAX); + + _hcd_data.edpt[ep_id_in] = *edpt; // copy from OUT endpoint + _hcd_data.edpt[ep_id_in].ep_addr = 0 | TUSB_DIR_IN_MASK; + } + + return true; +} + +bool hcd_edpt_close(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { + (void) rhport; + + uint8_t const ep_id = endpoint_find(dev_addr, ep_addr); + TU_ASSERT(ep_id < CFG_TUH_FSDEV_ENDPOINT_MAX); + + edpoint_close(ep_id); + + if (ep_addr == 0) { + uint8_t const ep_id_in = endpoint_find(dev_addr, 0 | TUSB_DIR_IN_MASK); + TU_ASSERT(ep_id_in < CFG_TUH_FSDEV_ENDPOINT_MAX); + + edpoint_close(ep_id_in); + } + + return false; +} + +// Submit a transfer +bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *buffer, uint16_t buflen) { + (void) rhport; + + TU_LOG(FSDEV_DEBUG, "hcd_edpt_xfer addr=%u ep=0x%02X len=%u\r\n", dev_addr, ep_addr, buflen); + + uint8_t const ep_id = endpoint_find(dev_addr, ep_addr); + TU_ASSERT(ep_id < CFG_TUH_FSDEV_ENDPOINT_MAX); + + hcd_endpoint_t *edpt = &_hcd_data.edpt[ep_id]; + + edpt->buffer = buffer; + edpt->buflen = buflen; + + return edpt_xfer_kickoff(ep_id); +} + +// Abort a queued transfer +bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { + (void) rhport; + + uint8_t const ep_id = endpoint_find(dev_addr, ep_addr); + TU_ASSERT(ep_id < CFG_TUH_FSDEV_ENDPOINT_MAX); + tusb_dir_t const dir = tu_edpt_dir(ep_addr); + + for (uint8_t i = 0; i < FSDEV_EP_COUNT; i++) { + hcd_xfer_t* xfer = &_hcd_data.xfer[i]; + + if (xfer->allocated[dir] && + xfer->dev_addr == dev_addr && + xfer->ep_num == tu_edpt_number(ep_addr)) { + + channel_dealloc(xfer, dir); + + uint32_t ch_reg = ch_read(i) | USB_EP_CTR_TX | USB_EP_CTR_RX; // reserve CTR bits + ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(dir); // will change Status, reserved other toggle bits + ch_change_status(&ch_reg, dir, EP_STAT_DISABLED); + ch_write(i, ch_reg, true); + + } + } + + return true; +} + +// Submit a special transfer to send 8-byte Setup Packet +bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]) { + (void) rhport; + + uint8_t const ep_id = endpoint_find(dev_addr, 0); + TU_ASSERT(ep_id < CFG_TUH_FSDEV_ENDPOINT_MAX); + + hcd_endpoint_t *edpt = &_hcd_data.edpt[ep_id]; + edpt->next_setup = true; + + return hcd_edpt_xfer(rhport, dev_addr, 0, (uint8_t*)(uintptr_t) setup_packet, 8); +} + +// 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; + + return true; +} + +//--------------------------------------------------------------------+ +// Helper Functions +//--------------------------------------------------------------------+ + +static uint8_t endpoint_alloc(void) { + for (uint32_t i = 0; i < CFG_TUH_FSDEV_ENDPOINT_MAX; i++) { + hcd_endpoint_t* edpt = &_hcd_data.edpt[i]; + if (!edpt->allocated) { + edpt->allocated = true; + return i; + } + } + return TUSB_INDEX_INVALID_8; +} + +static uint8_t endpoint_find(uint8_t dev_addr, uint8_t ep_addr) { + for (uint32_t i = 0; i < (uint32_t)CFG_TUH_FSDEV_ENDPOINT_MAX; i++) { + hcd_endpoint_t* edpt = &_hcd_data.edpt[i]; + if (edpt->allocated && edpt->dev_addr == dev_addr && edpt->ep_addr == ep_addr) { + return i; + } + } + return TUSB_INDEX_INVALID_8; +} + +// close an opened endpoint +static void edpoint_close(uint8_t ep_id) { + hcd_endpoint_t* edpt = &_hcd_data.edpt[ep_id]; + endpoint_dealloc(edpt); + + // disable active channel belong to this endpoint + for (uint8_t i = 0; i < FSDEV_EP_COUNT; i++) { + hcd_xfer_t* xfer = &_hcd_data.xfer[i]; + + if (xfer->allocated[TUSB_DIR_OUT] && xfer->edpt[TUSB_DIR_OUT] == edpt) { + channel_dealloc(xfer, TUSB_DIR_OUT); + + uint32_t ch_reg = ch_read(i) | USB_EP_CTR_TX | USB_EP_CTR_RX; // reserve CTR bits + ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(TUSB_DIR_OUT); // will change RX Status, reserved other toggle bits + ch_change_status(&ch_reg, TUSB_DIR_OUT, EP_STAT_DISABLED); + ch_write(i, ch_reg, true); + + } + if (xfer->allocated[TUSB_DIR_IN] && xfer->edpt[TUSB_DIR_IN] == edpt) { + channel_dealloc(xfer, TUSB_DIR_IN); + + uint32_t ch_reg = ch_read(i) | USB_EP_CTR_TX | USB_EP_CTR_RX; // reserve CTR bits + ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(TUSB_DIR_IN); // will change TX Status, reserved other toggle bits + ch_change_status(&ch_reg, TUSB_DIR_IN, EP_STAT_DISABLED); + ch_write(i, ch_reg, true); + + } + } +} + +// Allocate PMA buffer +static uint32_t hcd_pma_alloc(uint8_t channel, tusb_dir_t dir, uint16_t len) { + (void) len; + // Simple static allocation as we are unlikely to handle ISO endpoints in host mode + // We just give each channel a buffer of max packet size (64 bytes) + + uint16_t addr = FSDEV_BTABLE_BASE + 8 * FSDEV_EP_COUNT; + addr += channel * 64 * 2 + (dir == TUSB_DIR_IN ? 64 : 0); + + TU_ASSERT(addr <= FSDEV_PMA_SIZE, 0xFFFF); + + return addr; +} + +// Allocate hardware channel +static uint8_t channel_alloc(uint8_t dev_addr, uint8_t ep_addr, uint8_t ep_type) { + uint8_t const ep_num = tu_edpt_number(ep_addr); + tusb_dir_t const dir = tu_edpt_dir(ep_addr); + + // Find channel allocate for same ep_num but other direction + tusb_dir_t const other_dir = (dir == TUSB_DIR_IN) ? TUSB_DIR_OUT : TUSB_DIR_IN; + for (uint8_t i = 0; i < FSDEV_EP_COUNT; i++) { + if (!_hcd_data.xfer[i].allocated[dir] && + _hcd_data.xfer[i].allocated[other_dir] && + _hcd_data.xfer[i].dev_addr == dev_addr && + _hcd_data.xfer[i].ep_num == ep_num && + _hcd_data.xfer[i].ep_type == ep_type) { + _hcd_data.xfer[i].allocated[dir] = true; + _hcd_data.xfer[i].queued_len[dir] = 0; + _hcd_data.xfer[i].retry[dir] = 0; + return i; + } + } + + // Find free channel + for (uint8_t i = 0; i < FSDEV_EP_COUNT; i++) { + if (!_hcd_data.xfer[i].allocated[0] && !_hcd_data.xfer[i].allocated[1]) { + _hcd_data.xfer[i].dev_addr = dev_addr; + _hcd_data.xfer[i].ep_num = ep_num; + _hcd_data.xfer[i].ep_type = ep_type; + _hcd_data.xfer[i].allocated[dir] = true; + _hcd_data.xfer[i].queued_len[dir] = 0; + _hcd_data.xfer[i].retry[dir] = 0; + return i; + } + } + + // Allocation failed + return TUSB_INDEX_INVALID_8; +} + +// kick-off transfer with an endpoint +static bool edpt_xfer_kickoff(uint8_t ep_id) { + hcd_endpoint_t* edpt = &_hcd_data.edpt[ep_id]; + uint8_t ch_id = channel_alloc(edpt->dev_addr, edpt->ep_addr, edpt->ep_type); + TU_ASSERT(ch_id != TUSB_INDEX_INVALID_8); // all channel are in used + + tusb_dir_t const dir = tu_edpt_dir(edpt->ep_addr); + + hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; + xfer->edpt[dir] = edpt; + + return channel_xfer_start(ch_id, dir); +} + +static bool channel_xfer_start(uint8_t ch_id, tusb_dir_t dir) { + hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; + hcd_endpoint_t* edpt = xfer->edpt[dir]; + + uint32_t ch_reg = ch_read(ch_id) & ~USB_EPREG_MASK; + ch_reg |= tu_edpt_number(edpt->ep_addr) | edpt->dev_addr << USB_CHEP_DEVADDR_Pos | + USB_EP_CTR_TX | USB_EP_CTR_RX; + + // Set type + switch (edpt->ep_type) { + case TUSB_XFER_BULK: + ch_reg |= USB_EP_BULK; + break; + case TUSB_XFER_INTERRUPT: + ch_reg |= USB_EP_INTERRUPT; + break; + + case TUSB_XFER_CONTROL: + ch_reg |= USB_EP_CONTROL; + break; + + default: + // Note: ISO endpoint is unsupported + TU_ASSERT(false); + } + + /* Create a packet memory buffer area. */ + uint16_t pma_addr = hcd_pma_alloc(ch_id, dir, edpt->max_packet_size); + btable_set_addr(ch_id, dir == TUSB_DIR_OUT ? BTABLE_BUF_TX : BTABLE_BUF_RX, pma_addr); + + if (dir == TUSB_DIR_OUT) { + uint16_t const len = tu_min16(edpt->buflen - xfer->queued_len[TUSB_DIR_OUT], edpt->max_packet_size); + + hcd_write_packet_memory(pma_addr, &(edpt->buffer[xfer->queued_len[TUSB_DIR_OUT]]), len); + btable_set_count(ch_id, BTABLE_BUF_TX, len); + + xfer->queued_len[TUSB_DIR_OUT] += len; + if (edpt->next_setup) { + // Setup packet uses IN token + edpt->next_setup = false; + ch_reg |= USB_EP_SETUP; + } + + ch_change_status(&ch_reg, TUSB_DIR_OUT, EP_STAT_VALID); + ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(TUSB_DIR_OUT); // only change TX Status, reserve other toggle bits + + } else { + btable_set_rx_bufsize(ch_id, BTABLE_BUF_RX, edpt->max_packet_size); + ch_change_status(&ch_reg, TUSB_DIR_IN, EP_STAT_VALID); + ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(TUSB_DIR_IN); // will change RX Status, reserved other toggle bits + } + + ch_write(ch_id, ch_reg, true); + + return true; +} + +//--------------------------------------------------------------------+ +// PMA read/write +//--------------------------------------------------------------------+ + +// Write to packet memory area (PMA) from user memory +static bool hcd_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t nbytes) { + if (nbytes == 0) return true; + uint32_t n_write = nbytes / FSDEV_BUS_SIZE; + + fsdev_pma_buf_t *pma_buf = PMA_BUF_AT(dst); + const uint8_t *src8 = src; + + while (n_write--) { + pma_buf->value = fsdevbus_unaligned_read(src8); + src8 += FSDEV_BUS_SIZE; + pma_buf++; + } + + // Handle odd bytes + uint16_t odd = nbytes & (FSDEV_BUS_SIZE - 1); + if (odd) { + fsdev_bus_t temp = 0; + for (uint16_t i = 0; i < odd; i++) { + temp |= *src8++ << (i * 8); + } + pma_buf->value = temp; + } + + return true; +} + +// Read from packet memory area (PMA) to user memory +static bool hcd_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t nbytes) { + if (nbytes == 0) return true; + uint32_t n_read = nbytes / FSDEV_BUS_SIZE; + + fsdev_pma_buf_t *pma_buf = PMA_BUF_AT(src); + uint8_t *dst8 = (uint8_t *)dst; + + while (n_read--) { + fsdevbus_unaligned_write(dst8, (fsdev_bus_t) pma_buf->value); + dst8 += FSDEV_BUS_SIZE; + pma_buf++; + } + + // Handle odd bytes + uint16_t odd = nbytes & (FSDEV_BUS_SIZE - 1); + if (odd) { + fsdev_bus_t temp = pma_buf->value; + while (odd--) { + *dst8++ = (uint8_t)(temp & 0xfful); + temp >>= 8; + } + } + + return true; +} + +#endif -- cgit v1.3.1 From 03bd8c26d6b72b5e53c0d4b9787a6396ee295927 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Mon, 24 Nov 2025 21:03:04 +0100 Subject: fsdev: reorganize functions 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 + hw/bsp/at32f403a_407/family.cmake | 1 + hw/bsp/at32f403a_407/family.mk | 1 + hw/bsp/at32f413/family.cmake | 1 + hw/bsp/at32f413/family.mk | 1 + hw/bsp/ch32v20x/family.cmake | 1 + hw/bsp/ch32v20x/family.mk | 1 + hw/bsp/stm32c0/family.cmake | 1 + hw/bsp/stm32c0/family.mk | 1 + hw/bsp/stm32f0/family.cmake | 1 + hw/bsp/stm32f0/family.mk | 1 + hw/bsp/stm32f1/family.cmake | 1 + hw/bsp/stm32f1/family.mk | 1 + hw/bsp/stm32f3/family.cmake | 1 + hw/bsp/stm32f3/family.mk | 1 + hw/bsp/stm32g0/family.cmake | 1 + hw/bsp/stm32g0/family.mk | 2 + hw/bsp/stm32g4/family.cmake | 1 + hw/bsp/stm32g4/family.mk | 1 + hw/bsp/stm32h5/family.cmake | 1 + hw/bsp/stm32h5/family.mk | 2 + hw/bsp/stm32l0/family.cmake | 1 + hw/bsp/stm32l0/family.mk | 1 + hw/bsp/stm32l4/family.cmake | 1 + hw/bsp/stm32l4/family.mk | 1 + hw/bsp/stm32u0/family.cmake | 1 + hw/bsp/stm32u0/family.mk | 1 + hw/bsp/stm32u5/family.cmake | 2 + hw/bsp/stm32u5/family.mk | 6 +- hw/bsp/stm32wb/family.cmake | 1 + hw/bsp/stm32wb/family.mk | 1 + lib/rt-thread/SConscript | 3 +- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 190 +----------- src/portable/st/stm32_fsdev/fsdev_at32.h | 10 +- src/portable/st/stm32_fsdev/fsdev_ch32.h | 10 +- src/portable/st/stm32_fsdev/fsdev_common.c | 241 +++++++++++++++ src/portable/st/stm32_fsdev/fsdev_common.h | 343 +++++++++++++++++++++ src/portable/st/stm32_fsdev/fsdev_stm32.h | 14 +- src/portable/st/stm32_fsdev/fsdev_type.h | 344 --------------------- src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c | 412 ++++++++++++-------------- tools/iar_template.ipcf | 4 +- 43 files changed, 838 insertions(+), 774 deletions(-) create mode 100644 src/portable/st/stm32_fsdev/fsdev_common.c create mode 100644 src/portable/st/stm32_fsdev/fsdev_common.h delete mode 100644 src/portable/st/stm32_fsdev/fsdev_type.h (limited to 'src/portable') diff --git a/examples/host/bare_api/only.txt b/examples/host/bare_api/only.txt index cba58f8e8..a7bebf1d9 100644 --- a/examples/host/bare_api/only.txt +++ b/examples/host/bare_api/only.txt @@ -13,6 +13,7 @@ mcu:MSP432E4 mcu:RX65X mcu:RAXXX mcu:MAX3421 +mcu:STM32C0 mcu:STM32F4 mcu:STM32F7 mcu:STM32H7 diff --git a/examples/host/cdc_msc_hid/only.txt b/examples/host/cdc_msc_hid/only.txt index cba58f8e8..a7bebf1d9 100644 --- a/examples/host/cdc_msc_hid/only.txt +++ b/examples/host/cdc_msc_hid/only.txt @@ -13,6 +13,7 @@ mcu:MSP432E4 mcu:RX65X mcu:RAXXX mcu:MAX3421 +mcu:STM32C0 mcu:STM32F4 mcu:STM32F7 mcu:STM32H7 diff --git a/examples/host/cdc_msc_hid_freertos/only.txt b/examples/host/cdc_msc_hid_freertos/only.txt index ef0a1ac96..8da7a47d6 100644 --- a/examples/host/cdc_msc_hid_freertos/only.txt +++ b/examples/host/cdc_msc_hid_freertos/only.txt @@ -9,6 +9,7 @@ mcu:MIMXRT11XX mcu:MSP432E4 mcu:RX65X mcu:MAX3421 +mcu:STM32C0 mcu:STM32F4 mcu:STM32F7 mcu:STM32H7 diff --git a/hw/bsp/at32f403a_407/family.cmake b/hw/bsp/at32f403a_407/family.cmake index 498b89c1a..7aaa9ede8 100644 --- a/hw/bsp/at32f403a_407/family.cmake +++ b/hw/bsp/at32f403a_407/family.cmake @@ -61,6 +61,7 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_clock.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_int.c ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c + ${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC diff --git a/hw/bsp/at32f403a_407/family.mk b/hw/bsp/at32f403a_407/family.mk index c82d402ca..f458881a3 100644 --- a/hw/bsp/at32f403a_407/family.mk +++ b/hw/bsp/at32f403a_407/family.mk @@ -16,6 +16,7 @@ LDFLAGS_GCC += \ SRC_C += \ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ + src/portable/st/stm32_fsdev/fsdev_common.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 \ diff --git a/hw/bsp/at32f413/family.cmake b/hw/bsp/at32f413/family.cmake index 02692daf5..33718bd1c 100644 --- a/hw/bsp/at32f413/family.cmake +++ b/hw/bsp/at32f413/family.cmake @@ -61,6 +61,7 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_clock.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_int.c ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c + ${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC diff --git a/hw/bsp/at32f413/family.mk b/hw/bsp/at32f413/family.mk index 9c5d867de..abcd15d11 100644 --- a/hw/bsp/at32f413/family.mk +++ b/hw/bsp/at32f413/family.mk @@ -16,6 +16,7 @@ LDFLAGS_GCC += \ SRC_C += \ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ + src/portable/st/stm32_fsdev/fsdev_common.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 \ diff --git a/hw/bsp/ch32v20x/family.cmake b/hw/bsp/ch32v20x/family.cmake index d8c7c5327..59a96f70d 100644 --- a/hw/bsp/ch32v20x/family.cmake +++ b/hw/bsp/ch32v20x/family.cmake @@ -93,6 +93,7 @@ function(family_configure_example TARGET RTOS) ${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 + ${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC diff --git a/hw/bsp/ch32v20x/family.mk b/hw/bsp/ch32v20x/family.mk index 16fc537ac..7042ecbb7 100644 --- a/hw/bsp/ch32v20x/family.mk +++ b/hw/bsp/ch32v20x/family.mk @@ -47,6 +47,7 @@ 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 \ + src/portable/st/stm32_fsdev/fsdev_common.c \ $(SDK_SRC_DIR)/Core/core_riscv.c \ $(SDK_SRC_DIR)/Peripheral/src/${CH32_FAMILY}_gpio.c \ $(SDK_SRC_DIR)/Peripheral/src/${CH32_FAMILY}_misc.c \ diff --git a/hw/bsp/stm32c0/family.cmake b/hw/bsp/stm32c0/family.cmake index 6e04b20f4..dc1a2bb13 100644 --- a/hw/bsp/stm32c0/family.cmake +++ b/hw/bsp/stm32c0/family.cmake @@ -67,6 +67,7 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c ${TOP}/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c + ${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c ${TOP}/src/portable/st/typec/typec_stm32.c ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) diff --git a/hw/bsp/stm32c0/family.mk b/hw/bsp/stm32c0/family.mk index fd03ad537..71209bf2e 100644 --- a/hw/bsp/stm32c0/family.mk +++ b/hw/bsp/stm32c0/family.mk @@ -30,6 +30,7 @@ LDFLAGS_GCC += \ SRC_C += \ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c \ + src/portable/st/stm32_fsdev/fsdev_common.c \ $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \ diff --git a/hw/bsp/stm32f0/family.cmake b/hw/bsp/stm32f0/family.cmake index ee73ae872..a926a9739 100644 --- a/hw/bsp/stm32f0/family.cmake +++ b/hw/bsp/stm32f0/family.cmake @@ -65,6 +65,7 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c + ${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC diff --git a/hw/bsp/stm32f0/family.mk b/hw/bsp/stm32f0/family.mk index 9b8305874..b5efdcb8d 100644 --- a/hw/bsp/stm32f0/family.mk +++ b/hw/bsp/stm32f0/family.mk @@ -30,6 +30,7 @@ LDFLAGS_GCC += \ SRC_C += \ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ + src/portable/st/stm32_fsdev/fsdev_common.c \ $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \ diff --git a/hw/bsp/stm32f1/family.cmake b/hw/bsp/stm32f1/family.cmake index 064f32096..9e94d86c6 100644 --- a/hw/bsp/stm32f1/family.cmake +++ b/hw/bsp/stm32f1/family.cmake @@ -62,6 +62,7 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c + ${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC diff --git a/hw/bsp/stm32f1/family.mk b/hw/bsp/stm32f1/family.mk index ca95f2315..d4b6dfa6c 100644 --- a/hw/bsp/stm32f1/family.mk +++ b/hw/bsp/stm32f1/family.mk @@ -27,6 +27,7 @@ LDFLAGS_GCC += \ # ------------------------ SRC_C += \ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ + src/portable/st/stm32_fsdev/fsdev_common.c \ ${ST_CMSIS}/Source/Templates/system_stm32${ST_FAMILY}xx.c \ ${ST_HAL_DRIVER}/Src/stm32${ST_FAMILY}xx_hal.c \ ${ST_HAL_DRIVER}/Src/stm32${ST_FAMILY}xx_hal_cortex.c \ diff --git a/hw/bsp/stm32f3/family.cmake b/hw/bsp/stm32f3/family.cmake index 7c9e97e62..3cbb4e1cd 100644 --- a/hw/bsp/stm32f3/family.cmake +++ b/hw/bsp/stm32f3/family.cmake @@ -62,6 +62,7 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c + ${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC diff --git a/hw/bsp/stm32f3/family.mk b/hw/bsp/stm32f3/family.mk index 13734583a..eb4a4e186 100644 --- a/hw/bsp/stm32f3/family.mk +++ b/hw/bsp/stm32f3/family.mk @@ -19,6 +19,7 @@ LDFLAGS_GCC += \ SRC_C += \ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ + src/portable/st/stm32_fsdev/fsdev_common.c \ $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \ diff --git a/hw/bsp/stm32g0/family.cmake b/hw/bsp/stm32g0/family.cmake index 572f0e644..0ce85168e 100644 --- a/hw/bsp/stm32g0/family.cmake +++ b/hw/bsp/stm32g0/family.cmake @@ -64,6 +64,7 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c + ${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c ${TOP}/src/portable/st/typec/typec_stm32.c ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) diff --git a/hw/bsp/stm32g0/family.mk b/hw/bsp/stm32g0/family.mk index d735ca92d..e376f7f06 100644 --- a/hw/bsp/stm32g0/family.mk +++ b/hw/bsp/stm32g0/family.mk @@ -29,6 +29,8 @@ LDFLAGS_GCC += \ SRC_C += \ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ + src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c \ + src/portable/st/stm32_fsdev/fsdev_common.c \ $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \ diff --git a/hw/bsp/stm32g4/family.cmake b/hw/bsp/stm32g4/family.cmake index 7e8b319b8..85201ce61 100644 --- a/hw/bsp/stm32g4/family.cmake +++ b/hw/bsp/stm32g4/family.cmake @@ -62,6 +62,7 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c + ${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c ${TOP}/src/portable/st/typec/typec_stm32.c ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) diff --git a/hw/bsp/stm32g4/family.mk b/hw/bsp/stm32g4/family.mk index 0abd73532..a153194ce 100644 --- a/hw/bsp/stm32g4/family.mk +++ b/hw/bsp/stm32g4/family.mk @@ -29,6 +29,7 @@ LDFLAGS_GCC += \ SRC_C += \ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ + src/portable/st/stm32_fsdev/fsdev_common.c \ src/portable/st/typec/typec_stm32.c \ $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ diff --git a/hw/bsp/stm32h5/family.cmake b/hw/bsp/stm32h5/family.cmake index 6e63c4072..d6f356ddf 100644 --- a/hw/bsp/stm32h5/family.cmake +++ b/hw/bsp/stm32h5/family.cmake @@ -66,6 +66,7 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c + ${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c ${TOP}/src/portable/st/typec/typec_stm32.c ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) diff --git a/hw/bsp/stm32h5/family.mk b/hw/bsp/stm32h5/family.mk index 792edb2bb..ec5f82d61 100644 --- a/hw/bsp/stm32h5/family.mk +++ b/hw/bsp/stm32h5/family.mk @@ -36,6 +36,8 @@ LDFLAGS_GCC += \ SRC_C += \ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ + src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c \ + src/portable/st/stm32_fsdev/fsdev_common.c \ $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \ diff --git a/hw/bsp/stm32l0/family.cmake b/hw/bsp/stm32l0/family.cmake index b6b0139a0..3f6622f71 100644 --- a/hw/bsp/stm32l0/family.cmake +++ b/hw/bsp/stm32l0/family.cmake @@ -66,6 +66,7 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c + ${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC diff --git a/hw/bsp/stm32l0/family.mk b/hw/bsp/stm32l0/family.mk index 921b1b413..0ae881fdf 100644 --- a/hw/bsp/stm32l0/family.mk +++ b/hw/bsp/stm32l0/family.mk @@ -27,6 +27,7 @@ LDFLAGS_GCC += \ SRC_C += \ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ + src/portable/st/stm32_fsdev/fsdev_common.c \ $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \ diff --git a/hw/bsp/stm32l4/family.cmake b/hw/bsp/stm32l4/family.cmake index 5bc28dd5d..b1659d47a 100644 --- a/hw/bsp/stm32l4/family.cmake +++ b/hw/bsp/stm32l4/family.cmake @@ -67,6 +67,7 @@ function(family_configure_example TARGET RTOS) ${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c ${TOP}/src/portable/synopsys/dwc2/dwc2_common.c ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c + ${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC diff --git a/hw/bsp/stm32l4/family.mk b/hw/bsp/stm32l4/family.mk index 01d059236..fd11fd226 100644 --- a/hw/bsp/stm32l4/family.mk +++ b/hw/bsp/stm32l4/family.mk @@ -34,6 +34,7 @@ SRC_C += \ src/portable/synopsys/dwc2/hcd_dwc2.c \ src/portable/synopsys/dwc2/dwc2_common.c \ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ + src/portable/st/stm32_fsdev/fsdev_common.c \ $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \ diff --git a/hw/bsp/stm32u0/family.cmake b/hw/bsp/stm32u0/family.cmake index 4f9b03109..2d3819cba 100644 --- a/hw/bsp/stm32u0/family.cmake +++ b/hw/bsp/stm32u0/family.cmake @@ -67,6 +67,7 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c + ${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC diff --git a/hw/bsp/stm32u0/family.mk b/hw/bsp/stm32u0/family.mk index d5a850050..5f25906d3 100644 --- a/hw/bsp/stm32u0/family.mk +++ b/hw/bsp/stm32u0/family.mk @@ -27,6 +27,7 @@ LDFLAGS_GCC += \ SRC_C += \ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ + src/portable/st/stm32_fsdev/fsdev_common.c \ $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \ diff --git a/hw/bsp/stm32u5/family.cmake b/hw/bsp/stm32u5/family.cmake index 70e0c313c..58dc63ae3 100644 --- a/hw/bsp/stm32u5/family.cmake +++ b/hw/bsp/stm32u5/family.cmake @@ -66,6 +66,8 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c + ${TOP}/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c + ${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c ${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c ${TOP}/src/portable/synopsys/dwc2/dwc2_common.c diff --git a/hw/bsp/stm32u5/family.mk b/hw/bsp/stm32u5/family.mk index 3694b1ca0..79f181a68 100644 --- a/hw/bsp/stm32u5/family.mk +++ b/hw/bsp/stm32u5/family.mk @@ -39,10 +39,12 @@ SRC_C += \ ifeq ($(MCU_VARIANT),stm32u545xx) SRC_C += \ - src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c + src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ + src/portable/st/stm32_fsdev/fsdev_common.c else ifeq ($(MCU_VARIANT),stm32u535xx) SRC_C += \ - src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c + src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ + src/portable/st/stm32_fsdev/fsdev_common.c else SRC_C += \ src/portable/synopsys/dwc2/dcd_dwc2.c \ diff --git a/hw/bsp/stm32wb/family.cmake b/hw/bsp/stm32wb/family.cmake index 1a96e3d7e..6703a9b19 100644 --- a/hw/bsp/stm32wb/family.cmake +++ b/hw/bsp/stm32wb/family.cmake @@ -67,6 +67,7 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c + ${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC diff --git a/hw/bsp/stm32wb/family.mk b/hw/bsp/stm32wb/family.mk index a80ff6f5b..0b1a51cec 100644 --- a/hw/bsp/stm32wb/family.mk +++ b/hw/bsp/stm32wb/family.mk @@ -20,6 +20,7 @@ LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs SRC_C += \ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ + src/portable/st/stm32_fsdev/fsdev_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 \ diff --git a/lib/rt-thread/SConscript b/lib/rt-thread/SConscript index 99517a090..e7b6f2dc4 100644 --- a/lib/rt-thread/SConscript +++ b/lib/rt-thread/SConscript @@ -18,7 +18,8 @@ if GetDepend(["PKG_TINYUSB_DEVICE_ENABLE"]): # BSP if GetDepend(["SOC_FAMILY_STM32"]): src += ["../../src/portable/synopsys/dwc2/dcd_dwc2.c", - "../../src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c"] + "../../src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c", + "../../src/portable/st/stm32_fsdev/fsdev_common.c"] if GetDepend(["SOC_NRF52840"]): src += ["../../src/portable/nordic/nrf5x/dcd_nrf5x.c"] diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index db1a5784a..3762b33f9 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -112,16 +112,7 @@ !(defined(TUP_USBIP_FSDEV_CH32) && CFG_TUD_WCH_USBIP_FSDEV == 0) #include "device/dcd.h" - -#if defined(TUP_USBIP_FSDEV_STM32) - #include "fsdev_stm32.h" -#elif defined(TUP_USBIP_FSDEV_CH32) - #include "fsdev_ch32.h" -#elif defined(TUP_USBIP_FSDEV_AT32) - #include "fsdev_at32.h" -#else - #error "Unknown USB IP" -#endif +#include "fsdev_common.h" //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF @@ -162,11 +153,6 @@ static bool edpt_xfer(uint8_t rhport, uint8_t ep_num, tusb_dir_t dir); static uint16_t ep_buf_ptr; ///< Points to first free memory location static uint32_t dcd_pma_alloc(uint16_t len, bool dbuf); static uint8_t dcd_ep_alloc(uint8_t ep_addr, uint8_t ep_type); -static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t nbytes); -static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t nbytes); - -static bool dcd_write_packet_memory_ff(tu_fifo_t *ff, uint16_t dst, uint16_t wNBytes); -static bool dcd_read_packet_memory_ff(tu_fifo_t *ff, uint16_t src, uint16_t wNBytes); static void edpt0_open(uint8_t rhport); @@ -307,7 +293,7 @@ static void handle_ctr_setup(uint32_t ep_id) { uint16_t rx_addr = btable_get_addr(ep_id, BTABLE_BUF_RX); uint8_t setup_packet[8] TU_ATTR_ALIGNED(4); - dcd_read_packet_memory(setup_packet, rx_addr, rx_count); + fsdev_read_packet_memory(setup_packet, rx_addr, rx_count); // Clear CTR RX if another setup packet arrived before this, it will be discarded ep_write_clear_ctr(ep_id, TUSB_DIR_OUT); @@ -345,9 +331,9 @@ static void handle_ctr_rx(uint32_t ep_id) { uint16_t pma_addr = (uint16_t) btable_get_addr(ep_id, buf_id); if (xfer->ff) { - dcd_read_packet_memory_ff(xfer->ff, pma_addr, rx_count); + fsdev_read_packet_memory_ff(xfer->ff, pma_addr, rx_count); } else { - dcd_read_packet_memory(xfer->buffer + xfer->queued_len, pma_addr, rx_count); + fsdev_read_packet_memory(xfer->buffer + xfer->queued_len, pma_addr, rx_count); } xfer->queued_len += rx_count; @@ -742,9 +728,9 @@ static void dcd_transmit_packet(xfer_ctl_t *xfer, uint16_t ep_ix) { uint16_t addr_ptr = (uint16_t) btable_get_addr(ep_ix, buf_id); if (xfer->ff) { - dcd_write_packet_memory_ff(xfer->ff, addr_ptr, len); + fsdev_write_packet_memory_ff(xfer->ff, addr_ptr, len); } else { - dcd_write_packet_memory(addr_ptr, &(xfer->buffer[xfer->queued_len]), len); + fsdev_write_packet_memory(addr_ptr, &(xfer->buffer[xfer->queued_len]), len); } xfer->queued_len += len; @@ -864,168 +850,4 @@ void dcd_disconnect(uint8_t rhport) { } #endif -//--------------------------------------------------------------------+ -// PMA read/write -//--------------------------------------------------------------------+ - -// Write to packet memory area (PMA) from user memory -// - Packet memory must be either strictly 16-bit or 32-bit depending on FSDEV_BUS_32BIT -// - Uses unaligned for RAM (since M0 cannot access unaligned address) -static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t nbytes) { - if (nbytes == 0) return true; - uint32_t n_write = nbytes / FSDEV_BUS_SIZE; - - fsdev_pma_buf_t* pma_buf = PMA_BUF_AT(dst); - const uint8_t *src8 = src; - - while (n_write--) { - pma_buf->value = fsdevbus_unaligned_read(src8); - src8 += FSDEV_BUS_SIZE; - pma_buf++; - } - - // odd bytes e.g 1 for 16-bit or 1-3 for 32-bit - uint16_t odd = nbytes & (FSDEV_BUS_SIZE - 1); - if (odd) { - fsdev_bus_t temp = 0; - for(uint16_t i = 0; i < odd; i++) { - temp |= *src8++ << (i * 8); - } - pma_buf->value = temp; - } - - return true; -} - -// Read from packet memory area (PMA) to user memory. -// - Packet memory must be either strictly 16-bit or 32-bit depending on FSDEV_BUS_32BIT -// - Uses unaligned for RAM (since M0 cannot access unaligned address) -static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t nbytes) { - if (nbytes == 0) return true; - uint32_t n_read = nbytes / FSDEV_BUS_SIZE; - - fsdev_pma_buf_t* pma_buf = PMA_BUF_AT(src); - uint8_t *dst8 = (uint8_t *)dst; - - while (n_read--) { - fsdevbus_unaligned_write(dst8, (fsdev_bus_t ) pma_buf->value); - dst8 += FSDEV_BUS_SIZE; - pma_buf++; - } - - // odd bytes e.g 1 for 16-bit or 1-3 for 32-bit - uint16_t odd = nbytes & (FSDEV_BUS_SIZE - 1); - if (odd) { - fsdev_bus_t temp = pma_buf->value; - while (odd--) { - *dst8++ = (uint8_t) (temp & 0xfful); - temp >>= 8; - } - } - - return true; -} - -// Write to PMA from FIFO -static bool dcd_write_packet_memory_ff(tu_fifo_t *ff, uint16_t dst, uint16_t wNBytes) { - if (wNBytes == 0) return true; - - // Since we copy from a ring buffer FIFO, a wrap might occur making it necessary to conduct two copies - tu_fifo_buffer_info_t info; - tu_fifo_get_read_info(ff, &info); - - uint16_t cnt_lin = tu_min16(wNBytes, info.len_lin); - uint16_t cnt_wrap = tu_min16(wNBytes - cnt_lin, info.len_wrap); - uint16_t const cnt_total = cnt_lin + cnt_wrap; - - // We want to read from the FIFO and write it into the PMA, if LIN part is ODD and has WRAPPED part, - // last lin byte will be combined with wrapped part To ensure PMA is always access aligned - uint16_t lin_even = cnt_lin & ~(FSDEV_BUS_SIZE - 1); - uint16_t lin_odd = cnt_lin & (FSDEV_BUS_SIZE - 1); - uint8_t const *src8 = (uint8_t const*) info.ptr_lin; - - // write even linear part - dcd_write_packet_memory(dst, src8, lin_even); - dst += lin_even; - src8 += lin_even; - - if (lin_odd == 0) { - src8 = (uint8_t const*) info.ptr_wrap; - } else { - // Combine last linear bytes + first wrapped bytes to form fsdev bus width data - fsdev_bus_t temp = 0; - uint16_t i; - for(i = 0; i < lin_odd; i++) { - temp |= *src8++ << (i * 8); - } - - src8 = (uint8_t const*) info.ptr_wrap; - for(; i < FSDEV_BUS_SIZE && cnt_wrap > 0; i++, cnt_wrap--) { - temp |= *src8++ << (i * 8); - } - - dcd_write_packet_memory(dst, &temp, FSDEV_BUS_SIZE); - dst += FSDEV_BUS_SIZE; - } - - // write the rest of the wrapped part - dcd_write_packet_memory(dst, src8, cnt_wrap); - - tu_fifo_advance_read_pointer(ff, cnt_total); - return true; -} - -// Read from PMA to FIFO -static bool dcd_read_packet_memory_ff(tu_fifo_t *ff, uint16_t src, uint16_t wNBytes) { - if (wNBytes == 0) return true; - - // Since we copy into a ring buffer FIFO, a wrap might occur making it necessary to conduct two copies - // Check for first linear part - tu_fifo_buffer_info_t info; - tu_fifo_get_write_info(ff, &info); // We want to read from the FIFO - - uint16_t cnt_lin = tu_min16(wNBytes, info.len_lin); - uint16_t cnt_wrap = tu_min16(wNBytes - cnt_lin, info.len_wrap); - uint16_t cnt_total = cnt_lin + cnt_wrap; - - // We want to read from the FIFO and write it into the PMA, if LIN part is ODD and has WRAPPED part, - // last lin byte will be combined with wrapped part To ensure PMA is always access aligned - - uint16_t lin_even = cnt_lin & ~(FSDEV_BUS_SIZE - 1); - uint16_t lin_odd = cnt_lin & (FSDEV_BUS_SIZE - 1); - uint8_t *dst8 = (uint8_t *) info.ptr_lin; - - // read even linear part - dcd_read_packet_memory(dst8, src, lin_even); - dst8 += lin_even; - src += lin_even; - - if (lin_odd == 0) { - dst8 = (uint8_t *) info.ptr_wrap; - } else { - // Combine last linear bytes + first wrapped bytes to form fsdev bus width data - fsdev_bus_t temp; - dcd_read_packet_memory(&temp, src, FSDEV_BUS_SIZE); - src += FSDEV_BUS_SIZE; - - uint16_t i; - for (i = 0; i < lin_odd; i++) { - *dst8++ = (uint8_t) (temp & 0xfful); - temp >>= 8; - } - - dst8 = (uint8_t *) info.ptr_wrap; - for (; i < FSDEV_BUS_SIZE && cnt_wrap > 0; i++, cnt_wrap--) { - *dst8++ = (uint8_t) (temp & 0xfful); - temp >>= 8; - } - } - - // read the rest of the wrapped part - dcd_read_packet_memory(dst8, src, cnt_wrap); - - tu_fifo_advance_write_pointer(ff, cnt_total); - return true; -} - #endif diff --git a/src/portable/st/stm32_fsdev/fsdev_at32.h b/src/portable/st/stm32_fsdev/fsdev_at32.h index 03490ee24..6877dc131 100644 --- a/src/portable/st/stm32_fsdev/fsdev_at32.h +++ b/src/portable/st/stm32_fsdev/fsdev_at32.h @@ -150,8 +150,6 @@ #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" - //--------------------------------------------------------------------+ // //--------------------------------------------------------------------+ @@ -168,7 +166,7 @@ enum { FSDEV_IRQ_NUM = TU_ARRAY_SIZE(fsdev_irq) }; #error "Unsupported MCU" #endif -void fsdev_int_enable(uint8_t rhport) { +TU_ATTR_ALWAYS_INLINE static inline void fsdev_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 @@ -187,7 +185,7 @@ void fsdev_int_enable(uint8_t rhport) { } } -void fsdev_int_disable(uint8_t rhport) { +TU_ATTR_ALWAYS_INLINE static inline void fsdev_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 @@ -206,7 +204,7 @@ void fsdev_int_disable(uint8_t rhport) { } } -void fsdev_disconnect(uint8_t rhport) { +TU_ATTR_ALWAYS_INLINE static inline void fsdev_disconnect(uint8_t rhport) { (void) rhport; /* disable usb phy */ *(volatile uint32_t*)(FSDEV_REG_BASE + 0x40) |= USB_CNTR_PDWN; @@ -214,7 +212,7 @@ void fsdev_disconnect(uint8_t rhport) { *(volatile uint32_t *)(FSDEV_REG_BASE+0x60) |= (1u<<1); } -void fsdev_connect(uint8_t rhport) { +TU_ATTR_ALWAYS_INLINE static inline void fsdev_connect(uint8_t rhport) { (void) rhport; /* enable usb phy */ *(volatile uint32_t*)(FSDEV_REG_BASE + 0x40) &= ~USB_CNTR_PDWN; diff --git a/src/portable/st/stm32_fsdev/fsdev_ch32.h b/src/portable/st/stm32_fsdev/fsdev_ch32.h index 547f3bd1b..ee0057cb4 100644 --- a/src/portable/st/stm32_fsdev/fsdev_ch32.h +++ b/src/portable/st/stm32_fsdev/fsdev_ch32.h @@ -168,8 +168,6 @@ #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" - //--------------------------------------------------------------------+ // //--------------------------------------------------------------------+ @@ -185,26 +183,26 @@ enum { FSDEV_IRQ_NUM = TU_ARRAY_SIZE(fsdev_irq) }; #error "Unsupported MCU" #endif -void fsdev_int_enable(uint8_t rhport) { +TU_ATTR_ALWAYS_INLINE static inline void fsdev_int_enable(uint8_t rhport) { (void)rhport; for(uint8_t i=0; i < FSDEV_IRQ_NUM; i++) { NVIC_EnableIRQ(fsdev_irq[i]); } } -void fsdev_int_disable(uint8_t rhport) { +TU_ATTR_ALWAYS_INLINE static inline void fsdev_int_disable(uint8_t rhport) { (void)rhport; for(uint8_t i=0; i < FSDEV_IRQ_NUM; i++) { NVIC_DisableIRQ(fsdev_irq[i]); } } -void fsdev_disconnect(uint8_t rhport) { +TU_ATTR_ALWAYS_INLINE static inline void fsdev_disconnect(uint8_t rhport) { (void) rhport; EXTEN->EXTEN_CTR &= ~EXTEN_USBD_PU_EN; } -void fsdev_connect(uint8_t rhport) { +TU_ATTR_ALWAYS_INLINE static inline void fsdev_connect(uint8_t rhport) { (void) rhport; EXTEN->EXTEN_CTR |= EXTEN_USBD_PU_EN; } diff --git a/src/portable/st/stm32_fsdev/fsdev_common.c b/src/portable/st/stm32_fsdev/fsdev_common.c new file mode 100644 index 000000000..d021a6abf --- /dev/null +++ b/src/portable/st/stm32_fsdev/fsdev_common.c @@ -0,0 +1,241 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2024 Ha Thach (tinyusb.org) + * Copyright (c) 2025, HiFiPhile (Zixun LI) + * + * 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 defined(TUP_USBIP_FSDEV) && (CFG_TUH_ENABLED || CFG_TUD_ENABLED) + +#include "fsdev_common.h" + +//--------------------------------------------------------------------+ +// PMA read/write +//--------------------------------------------------------------------+ + +// Write to packet memory area (PMA) from user memory +// - Packet memory must be either strictly 16-bit or 32-bit depending on FSDEV_BUS_32BIT +// - Uses unaligned for RAM (since M0 cannot access unaligned address) +bool fsdev_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t nbytes) { + if (nbytes == 0) return true; + uint32_t n_write = nbytes / FSDEV_BUS_SIZE; + + fsdev_pma_buf_t* pma_buf = PMA_BUF_AT(dst); + const uint8_t *src8 = src; + + while (n_write--) { + pma_buf->value = fsdevbus_unaligned_read(src8); + src8 += FSDEV_BUS_SIZE; + pma_buf++; + } + + // odd bytes e.g 1 for 16-bit or 1-3 for 32-bit + uint16_t odd = nbytes & (FSDEV_BUS_SIZE - 1); + if (odd) { + fsdev_bus_t temp = 0; + for(uint16_t i = 0; i < odd; i++) { + temp |= *src8++ << (i * 8); + } + pma_buf->value = temp; + } + + return true; +} + +// Read from packet memory area (PMA) to user memory. +// - Packet memory must be either strictly 16-bit or 32-bit depending on FSDEV_BUS_32BIT +// - Uses unaligned for RAM (since M0 cannot access unaligned address) +bool fsdev_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t nbytes) { + if (nbytes == 0) return true; + uint32_t n_read = nbytes / FSDEV_BUS_SIZE; + + fsdev_pma_buf_t* pma_buf = PMA_BUF_AT(src); + uint8_t *dst8 = (uint8_t *)dst; + + while (n_read--) { + fsdevbus_unaligned_write(dst8, (fsdev_bus_t ) pma_buf->value); + dst8 += FSDEV_BUS_SIZE; + pma_buf++; + } + + // odd bytes e.g 1 for 16-bit or 1-3 for 32-bit + uint16_t odd = nbytes & (FSDEV_BUS_SIZE - 1); + if (odd) { + fsdev_bus_t temp = pma_buf->value; + while (odd--) { + *dst8++ = (uint8_t) (temp & 0xfful); + temp >>= 8; + } + } + + return true; +} + +// Write to PMA from FIFO +bool fsdev_write_packet_memory_ff(tu_fifo_t *ff, uint16_t dst, uint16_t wNBytes) { + if (wNBytes == 0) return true; + + // Since we copy from a ring buffer FIFO, a wrap might occur making it necessary to conduct two copies + tu_fifo_buffer_info_t info; + tu_fifo_get_read_info(ff, &info); + + uint16_t cnt_lin = tu_min16(wNBytes, info.len_lin); + uint16_t cnt_wrap = tu_min16(wNBytes - cnt_lin, info.len_wrap); + uint16_t const cnt_total = cnt_lin + cnt_wrap; + + // We want to read from the FIFO and write it into the PMA, if LIN part is ODD and has WRAPPED part, + // last lin byte will be combined with wrapped part To ensure PMA is always access aligned + uint16_t lin_even = cnt_lin & ~(FSDEV_BUS_SIZE - 1); + uint16_t lin_odd = cnt_lin & (FSDEV_BUS_SIZE - 1); + uint8_t const *src8 = (uint8_t const*) info.ptr_lin; + + // write even linear part + fsdev_write_packet_memory(dst, src8, lin_even); + dst += lin_even; + src8 += lin_even; + + if (lin_odd == 0) { + src8 = (uint8_t const*) info.ptr_wrap; + } else { + // Combine last linear bytes + first wrapped bytes to form fsdev bus width data + fsdev_bus_t temp = 0; + uint16_t i; + for(i = 0; i < lin_odd; i++) { + temp |= *src8++ << (i * 8); + } + + src8 = (uint8_t const*) info.ptr_wrap; + for(; i < FSDEV_BUS_SIZE && cnt_wrap > 0; i++, cnt_wrap--) { + temp |= *src8++ << (i * 8); + } + + fsdev_write_packet_memory(dst, &temp, FSDEV_BUS_SIZE); + dst += FSDEV_BUS_SIZE; + } + + // write the rest of the wrapped part + fsdev_write_packet_memory(dst, src8, cnt_wrap); + + tu_fifo_advance_read_pointer(ff, cnt_total); + return true; +} + +// Read from PMA to FIFO +bool fsdev_read_packet_memory_ff(tu_fifo_t *ff, uint16_t src, uint16_t wNBytes) { + if (wNBytes == 0) return true; + + // Since we copy into a ring buffer FIFO, a wrap might occur making it necessary to conduct two copies + // Check for first linear part + tu_fifo_buffer_info_t info; + tu_fifo_get_write_info(ff, &info); // We want to read from the FIFO + + uint16_t cnt_lin = tu_min16(wNBytes, info.len_lin); + uint16_t cnt_wrap = tu_min16(wNBytes - cnt_lin, info.len_wrap); + uint16_t cnt_total = cnt_lin + cnt_wrap; + + // We want to read from the FIFO and write it into the PMA, if LIN part is ODD and has WRAPPED part, + // last lin byte will be combined with wrapped part To ensure PMA is always access aligned + + uint16_t lin_even = cnt_lin & ~(FSDEV_BUS_SIZE - 1); + uint16_t lin_odd = cnt_lin & (FSDEV_BUS_SIZE - 1); + uint8_t *dst8 = (uint8_t *) info.ptr_lin; + + // read even linear part + fsdev_read_packet_memory(dst8, src, lin_even); + dst8 += lin_even; + src += lin_even; + + if (lin_odd == 0) { + dst8 = (uint8_t *) info.ptr_wrap; + } else { + // Combine last linear bytes + first wrapped bytes to form fsdev bus width data + fsdev_bus_t temp; + fsdev_read_packet_memory(&temp, src, FSDEV_BUS_SIZE); + src += FSDEV_BUS_SIZE; + + uint16_t i; + for (i = 0; i < lin_odd; i++) { + *dst8++ = (uint8_t) (temp & 0xfful); + temp >>= 8; + } + + dst8 = (uint8_t *) info.ptr_wrap; + for (; i < FSDEV_BUS_SIZE && cnt_wrap > 0; i++, cnt_wrap--) { + *dst8++ = (uint8_t) (temp & 0xfful); + temp >>= 8; + } + } + + // read the rest of the wrapped part + fsdev_read_packet_memory(dst8, src, cnt_wrap); + + tu_fifo_advance_write_pointer(ff, cnt_total); + return true; +} + +//--------------------------------------------------------------------+ +// BTable Helper +//--------------------------------------------------------------------+ + +/* Aligned buffer size according to hardware */ +uint16_t pma_align_buffer_size(uint16_t size, uint8_t* blsize, uint8_t* num_block) { + /* The STM32 full speed USB peripheral supports only a limited set of + * buffer sizes given by the RX buffer entry format in the USB_BTABLE. */ + uint16_t block_in_bytes; + if (size > 62) { + block_in_bytes = 32; + *blsize = 1; + *num_block = tu_div_ceil(size, 32); + } else { + block_in_bytes = 2; + *blsize = 0; + *num_block = tu_div_ceil(size, 2); + } + + return (*num_block) * block_in_bytes; +} + +void btable_set_rx_bufsize(uint32_t ep_id, uint8_t buf_id, uint16_t wCount) { + uint8_t blsize, num_block; + (void) pma_align_buffer_size(wCount, &blsize, &num_block); + + /* Encode into register. When BLSIZE==1, we need to subtract 1 block count */ + uint16_t bl_nb = (blsize << 15) | ((num_block - blsize) << 10); + if (bl_nb == 0) { + // zlp but 0 is invalid value, set blsize to 1 (32 bytes) + // Note: lower value can cause PMAOVR on setup with ch32v203 + bl_nb = 1 << 15; + } + +#ifdef FSDEV_BUS_32BIT + uint32_t count_addr = FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr; + count_addr = (bl_nb << 16) | (count_addr & 0x0000FFFFu); + FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr = count_addr; +#else + FSDEV_BTABLE->ep16[ep_id][buf_id].count = bl_nb; +#endif +} + +#endif diff --git a/src/portable/st/stm32_fsdev/fsdev_common.h b/src/portable/st/stm32_fsdev/fsdev_common.h new file mode 100644 index 000000000..e363245ec --- /dev/null +++ b/src/portable/st/stm32_fsdev/fsdev_common.h @@ -0,0 +1,343 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) N Conrad + * Copyright (c) 2024, hathach (tinyusb.org) + * Copyright (c) 2025, HiFiPhile (Zixun LI) + * + * 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_FSDEV_COMMON_H +#define TUSB_FSDEV_COMMON_H + +#include "common/tusb_common.h" + +#if CFG_TUD_ENABLED +#include "device/dcd.h" +#endif + +#if CFG_TUH_ENABLED +#include "host/hcd.h" +#endif + +#if defined(TUP_USBIP_FSDEV_STM32) + #include "fsdev_stm32.h" +#elif defined(TUP_USBIP_FSDEV_CH32) + #include "fsdev_ch32.h" +#elif defined(TUP_USBIP_FSDEV_AT32) + #include "fsdev_at32.h" +#else + #error "Unknown USB IP" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +// If sharing with CAN, one can set this to be non-zero to give CAN space where it wants it +// Both of these MUST be a multiple of 2, and are in byte units. +#ifndef FSDEV_BTABLE_BASE +#define FSDEV_BTABLE_BASE 0U +#endif + +TU_VERIFY_STATIC(FSDEV_BTABLE_BASE % 8 == 0, "BTABLE base must be aligned to 8 bytes"); + +// FSDEV_PMA_SIZE is PMA buffer size in bytes. +// - 512-byte devices, access with a stride of two words (use every other 16-bit address) +// - 1024-byte devices, access with a stride of one word (use every 16-bit address) +// - 2048-byte devices, access with 32-bit address + +// For purposes of accessing the packet +#if FSDEV_PMA_SIZE == 512 + // 1x16 bit / word access scheme + #define FSDEV_PMA_STRIDE 2 + #define pma_access_scheme TU_ATTR_ALIGNED(4) +#elif FSDEV_PMA_SIZE == 1024 + // 2x16 bit / word access scheme + #define FSDEV_PMA_STRIDE 1 + #define pma_access_scheme +#elif FSDEV_PMA_SIZE == 2048 + // 32 bit access scheme + #define FSDEV_BUS_32BIT + #define FSDEV_PMA_STRIDE 1 + #define pma_access_scheme +#endif + +// The fsdev_bus_t type can be used for both register and PMA access necessities +#ifdef FSDEV_BUS_32BIT + typedef uint32_t fsdev_bus_t; + #define fsdevbus_unaligned_read(_addr) tu_unaligned_read32(_addr) + #define fsdevbus_unaligned_write(_addr, _value) tu_unaligned_write32(_addr, _value) +#else + typedef uint16_t fsdev_bus_t; + #define fsdevbus_unaligned_read(_addr) tu_unaligned_read16(_addr) + #define fsdevbus_unaligned_write(_addr, _value) tu_unaligned_write16(_addr, _value) +#endif + +enum { + FSDEV_BUS_SIZE = sizeof(fsdev_bus_t), +}; + +//--------------------------------------------------------------------+ +// BTable Typedef +//--------------------------------------------------------------------+ +enum { + BTABLE_BUF_TX = 0, + BTABLE_BUF_RX = 1 +}; + +// hardware limit endpoint +#define FSDEV_EP_COUNT 8 + +// Buffer Table is located in Packet Memory Area (PMA) and therefore its address access is forced to either +// 16-bit or 32-bit depending on FSDEV_BUS_32BIT. +// 0: TX (IN), 1: RX (OUT) +typedef union { + // data is strictly 16-bit access (address could be 32-bit aligned) + struct { + volatile pma_access_scheme uint16_t addr; + volatile pma_access_scheme uint16_t count; + } ep16[FSDEV_EP_COUNT][2]; + + // strictly 32-bit access + struct { + volatile uint32_t count_addr; + } ep32[FSDEV_EP_COUNT][2]; +} fsdev_btable_t; + +TU_VERIFY_STATIC(sizeof(fsdev_btable_t) == FSDEV_EP_COUNT*8*FSDEV_PMA_STRIDE, "size is not correct"); +TU_VERIFY_STATIC(FSDEV_BTABLE_BASE + FSDEV_EP_COUNT*8 <= FSDEV_PMA_SIZE, "BTABLE does not fit in PMA RAM"); + +#define FSDEV_BTABLE ((volatile fsdev_btable_t*) (FSDEV_PMA_BASE + FSDEV_PMA_STRIDE*(FSDEV_BTABLE_BASE))) + +typedef struct { + volatile pma_access_scheme fsdev_bus_t value; +} fsdev_pma_buf_t; + +#define PMA_BUF_AT(_addr) ((fsdev_pma_buf_t*) (FSDEV_PMA_BASE + FSDEV_PMA_STRIDE*(_addr))) + +//--------------------------------------------------------------------+ +// Registers Typedef +//--------------------------------------------------------------------+ + +// volatile 32-bit aligned +#define _va32 volatile TU_ATTR_ALIGNED(4) + +typedef struct { + struct { + _va32 fsdev_bus_t reg; + }ep[FSDEV_EP_COUNT]; + + _va32 uint32_t RESERVED7[8]; // Reserved + _va32 fsdev_bus_t CNTR; // 40: Control register + _va32 fsdev_bus_t ISTR; // 44: Interrupt status register + _va32 fsdev_bus_t FNR; // 48: Frame number register + _va32 fsdev_bus_t DADDR; // 4C: Device address register + _va32 fsdev_bus_t BTABLE; // 50: Buffer Table address register (16-bit only) + _va32 fsdev_bus_t LPMCSR; // 54: LPM Control and Status Register (32-bit only) + _va32 fsdev_bus_t BCDR; // 58: Battery Charging Detector Register (32-bit only) +} fsdev_regs_t; + +TU_VERIFY_STATIC(offsetof(fsdev_regs_t, CNTR) == 0x40, "Wrong offset"); +TU_VERIFY_STATIC(sizeof(fsdev_regs_t) == 0x5C, "Size is not correct"); + +#define FSDEV_REG ((fsdev_regs_t*) FSDEV_REG_BASE) + + +#ifndef USB_EPTX_STAT +#define USB_EPTX_STAT 0x0030U +#endif + +#ifndef USB_EPRX_STAT +#define USB_EPRX_STAT 0x3000U +#endif + +#ifndef USB_EPTX_STAT_Pos +#define USB_EPTX_STAT_Pos 4u +#endif + +#ifndef USB_EP_DTOG_TX_Pos +#define USB_EP_DTOG_TX_Pos 6u +#endif + +#ifndef USB_EP_CTR_TX_Pos +#define USB_EP_CTR_TX_Pos 7u +#endif + +typedef enum { + EP_STAT_DISABLED = 0, + EP_STAT_STALL = 1, + EP_STAT_NAK = 2, + EP_STAT_VALID = 3 +}ep_stat_t; + +#define EP_STAT_MASK(_dir) (3u << (USB_EPTX_STAT_Pos + ((_dir) == TUSB_DIR_IN ? 0 : 8))) +#define EP_DTOG_MASK(_dir) (1u << (USB_EP_DTOG_TX_Pos + ((_dir) == TUSB_DIR_IN ? 0 : 8))) + +#define CH_STAT_MASK(_dir) (3u << (USB_EPTX_STAT_Pos + ((_dir) == TUSB_DIR_IN ? 8 : 0))) +#define CH_DTOG_MASK(_dir) (1u << (USB_EP_DTOG_TX_Pos + ((_dir) == TUSB_DIR_IN ? 8 : 0))) + +//--------------------------------------------------------------------+ +// Endpoint Helper +// - CTR is write 0 to clear +// - DTOG and STAT are write 1 to toggle +//--------------------------------------------------------------------+ + +TU_ATTR_ALWAYS_INLINE static inline uint32_t ep_read(uint32_t ep_id) { + return FSDEV_REG->ep[ep_id].reg; +} + +TU_ATTR_ALWAYS_INLINE static inline void ep_write(uint32_t ep_id, uint32_t value, bool need_exclusive) { + if (need_exclusive) { + fsdev_int_disable(0); + } + + FSDEV_REG->ep[ep_id].reg = (fsdev_bus_t) value; + + if (need_exclusive) { + fsdev_int_enable(0); + } +} + +TU_ATTR_ALWAYS_INLINE static inline void ep_write_clear_ctr(uint32_t ep_id, tusb_dir_t dir) { + uint32_t reg = FSDEV_REG->ep[ep_id].reg; + reg |= USB_EP_CTR_TX | USB_EP_CTR_RX; + reg &= USB_EPREG_MASK; + reg &= ~(1 << (USB_EP_CTR_TX_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); + ep_write(ep_id, reg, false); +} + +TU_ATTR_ALWAYS_INLINE static inline void ep_change_status(uint32_t* reg, tusb_dir_t dir, ep_stat_t state) { + *reg ^= (state << (USB_EPTX_STAT_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); +} + +TU_ATTR_ALWAYS_INLINE static inline void ep_change_dtog(uint32_t* reg, tusb_dir_t dir, uint8_t state) { + *reg ^= (state << (USB_EP_DTOG_TX_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); +} + +TU_ATTR_ALWAYS_INLINE static inline bool ep_is_iso(uint32_t reg) { + return (reg & USB_EP_TYPE_MASK) == USB_EP_ISOCHRONOUS; +} + +//--------------------------------------------------------------------+ +// Channel Helper +// - Direction is opposite to endpoint direction +//--------------------------------------------------------------------+ + +TU_ATTR_ALWAYS_INLINE static inline uint32_t ch_read(uint32_t ch_id) { + return ep_read(ch_id); +} + +TU_ATTR_ALWAYS_INLINE static inline void ch_write(uint32_t ch_id, uint32_t value, bool need_exclusive) { + ep_write(ch_id, value, need_exclusive); +} + +TU_ATTR_ALWAYS_INLINE static inline void ch_write_clear_ctr(uint32_t ch_id, tusb_dir_t dir) { + uint32_t reg = FSDEV_REG->ep[ch_id].reg; + reg |= USB_EP_CTR_TX | USB_EP_CTR_RX; + reg &= USB_EPREG_MASK; + reg &= ~(1 << (USB_EP_CTR_TX_Pos + (dir == TUSB_DIR_IN ? 8 : 0))); + ep_write(ch_id, reg, false); +} + +TU_ATTR_ALWAYS_INLINE static inline void ch_change_status(uint32_t* reg, tusb_dir_t dir, ep_stat_t state) { + *reg ^= (state << (USB_EPTX_STAT_Pos + (dir == TUSB_DIR_IN ? 8 : 0))); +} + +TU_ATTR_ALWAYS_INLINE static inline void ch_change_dtog(uint32_t* reg, tusb_dir_t dir, uint8_t state) { + *reg ^= (state << (USB_EP_DTOG_TX_Pos + (dir == TUSB_DIR_IN ? 8 : 0))); +} + +//--------------------------------------------------------------------+ +// BTable Helper +//--------------------------------------------------------------------+ + +TU_ATTR_ALWAYS_INLINE static inline uint32_t btable_get_addr(uint32_t ep_id, uint8_t buf_id) { +#ifdef FSDEV_BUS_32BIT + return FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr & 0x0000FFFFu; +#else + return FSDEV_BTABLE->ep16[ep_id][buf_id].addr; +#endif +} + +TU_ATTR_ALWAYS_INLINE static inline void btable_set_addr(uint32_t ep_id, uint8_t buf_id, uint16_t addr) { +#ifdef FSDEV_BUS_32BIT + uint32_t count_addr = FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr; + count_addr = (count_addr & 0xFFFF0000u) | (addr & 0x0000FFFCu); + FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr = count_addr; +#else + FSDEV_BTABLE->ep16[ep_id][buf_id].addr = addr; +#endif +} + +TU_ATTR_ALWAYS_INLINE static inline uint16_t btable_get_count(uint32_t ep_id, uint8_t buf_id) { + uint16_t count; +#ifdef FSDEV_BUS_32BIT + count = (FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr >> 16); +#else + count = FSDEV_BTABLE->ep16[ep_id][buf_id].count; +#endif + return count & 0x3FFU; +} + +TU_ATTR_ALWAYS_INLINE static inline void btable_set_count(uint32_t ep_id, uint8_t buf_id, uint16_t byte_count) { +#ifdef FSDEV_BUS_32BIT + uint32_t count_addr = FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr; + count_addr = (count_addr & ~0x03FF0000u) | ((byte_count & 0x3FFu) << 16); + FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr = count_addr; +#else + uint16_t cnt = FSDEV_BTABLE->ep16[ep_id][buf_id].count; + cnt = (cnt & ~0x3FFU) | (byte_count & 0x3FFU); + FSDEV_BTABLE->ep16[ep_id][buf_id].count = cnt; +#endif +} + +/* Aligned buffer size according to hardware */ +uint16_t pma_align_buffer_size(uint16_t size, uint8_t* blsize, uint8_t* num_block); + +void btable_set_rx_bufsize(uint32_t ep_id, uint8_t buf_id, uint16_t wCount); + +//--------------------------------------------------------------------+ +// PMA (Packet Memory Area) Access +//--------------------------------------------------------------------+ + +// Write to packet memory area (PMA) from user memory +// - Packet memory must be either strictly 16-bit or 32-bit depending on FSDEV_BUS_32BIT +// - Uses unaligned for RAM (since M0 cannot access unaligned address) +bool fsdev_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t nbytes); + +// Read from packet memory area (PMA) to user memory. +// - Packet memory must be either strictly 16-bit or 32-bit depending on FSDEV_BUS_32BIT +// - Uses unaligned for RAM (since M0 cannot access unaligned address) +bool fsdev_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t nbytes); + +// Write to PMA from FIFO +bool fsdev_write_packet_memory_ff(tu_fifo_t *ff, uint16_t dst, uint16_t wNBytes); + +// Read from PMA to FIFO +bool fsdev_read_packet_memory_ff(tu_fifo_t *ff, uint16_t src, uint16_t wNBytes); + +#ifdef __cplusplus +} +#endif + +#endif /* TUSB_FSDEV_COMMON_H */ diff --git a/src/portable/st/stm32_fsdev/fsdev_stm32.h b/src/portable/st/stm32_fsdev/fsdev_stm32.h index d47d23f14..71370b189 100644 --- a/src/portable/st/stm32_fsdev/fsdev_stm32.h +++ b/src/portable/st/stm32_fsdev/fsdev_stm32.h @@ -321,8 +321,6 @@ #define FSDEV_USE_SBUF_ISO 0 #endif -#include "fsdev_type.h" - //--------------------------------------------------------------------+ // //--------------------------------------------------------------------+ @@ -374,7 +372,7 @@ static const IRQn_Type fsdev_irq[] = { }; enum { FSDEV_IRQ_NUM = TU_ARRAY_SIZE(fsdev_irq) }; -void fsdev_int_enable(uint8_t rhport) { +TU_ATTR_ALWAYS_INLINE static inline void fsdev_int_enable(uint8_t rhport) { (void)rhport; // forces write to RAM before allowing ISR to execute @@ -397,7 +395,7 @@ void fsdev_int_enable(uint8_t rhport) { } } -void fsdev_int_disable(uint8_t rhport) { +TU_ATTR_ALWAYS_INLINE static inline void fsdev_int_disable(uint8_t rhport) { (void)rhport; #if CFG_TUSB_MCU == OPT_MCU_STM32F3 && defined(SYSCFG_CFGR1_USB_IT_RMP) @@ -422,24 +420,24 @@ void fsdev_int_disable(uint8_t rhport) { // Define only on MCU with internal pull-up. BSP can define on MCU without internal PU. #if defined(USB_BCDR_DPPU) -void fsdev_disconnect(uint8_t rhport) { +TU_ATTR_ALWAYS_INLINE static inline void fsdev_disconnect(uint8_t rhport) { (void)rhport; USB->BCDR &= ~(USB_BCDR_DPPU); } -void fsdev_connect(uint8_t rhport) { +TU_ATTR_ALWAYS_INLINE static inline void fsdev_connect(uint8_t rhport) { (void)rhport; USB->BCDR |= USB_BCDR_DPPU; } #elif defined(SYSCFG_PMC_USB_PU) // works e.g. on STM32L151 -void fsdev_disconnect(uint8_t rhport) { +TU_ATTR_ALWAYS_INLINE static inline void fsdev_disconnect(uint8_t rhport) { (void)rhport; SYSCFG->PMC &= ~(SYSCFG_PMC_USB_PU); } -void fsdev_connect(uint8_t rhport) { +TU_ATTR_ALWAYS_INLINE static inline void fsdev_connect(uint8_t rhport) { (void)rhport; SYSCFG->PMC |= SYSCFG_PMC_USB_PU; } diff --git a/src/portable/st/stm32_fsdev/fsdev_type.h b/src/portable/st/stm32_fsdev/fsdev_type.h deleted file mode 100644 index 2b340d64a..000000000 --- a/src/portable/st/stm32_fsdev/fsdev_type.h +++ /dev/null @@ -1,344 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright(c) N Conrad - * Copyright(c) 2024, hathach (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_FSDEV_TYPE_H -#define TUSB_FSDEV_TYPE_H - -#ifdef __cplusplus - extern "C" { -#endif - -#include "stdint.h" - -// If sharing with CAN, one can set this to be non-zero to give CAN space where it wants it -// Both of these MUST be a multiple of 2, and are in byte units. -#ifndef FSDEV_BTABLE_BASE -#define FSDEV_BTABLE_BASE 0U -#endif - -TU_VERIFY_STATIC(FSDEV_BTABLE_BASE % 8 == 0, "BTABLE base must be aligned to 8 bytes"); - -// FSDEV_PMA_SIZE is PMA buffer size in bytes. -// - 512-byte devices, access with a stride of two words (use every other 16-bit address) -// - 1024-byte devices, access with a stride of one word (use every 16-bit address) -// - 2048-byte devices, access with 32-bit address - -// For purposes of accessing the packet -#if FSDEV_PMA_SIZE == 512 - // 1x16 bit / word access scheme - #define FSDEV_PMA_STRIDE 2 - #define pma_access_scheme TU_ATTR_ALIGNED(4) -#elif FSDEV_PMA_SIZE == 1024 - // 2x16 bit / word access scheme - #define FSDEV_PMA_STRIDE 1 - #define pma_access_scheme -#elif FSDEV_PMA_SIZE == 2048 - // 32 bit access scheme - #define FSDEV_BUS_32BIT - #define FSDEV_PMA_STRIDE 1 - #define pma_access_scheme -#endif - -// The fsdev_bus_t type can be used for both register and PMA access necessities -#ifdef FSDEV_BUS_32BIT - typedef uint32_t fsdev_bus_t; - #define fsdevbus_unaligned_read(_addr) tu_unaligned_read32(_addr) - #define fsdevbus_unaligned_write(_addr, _value) tu_unaligned_write32(_addr, _value) -#else - typedef uint16_t fsdev_bus_t; - #define fsdevbus_unaligned_read(_addr) tu_unaligned_read16(_addr) - #define fsdevbus_unaligned_write(_addr, _value) tu_unaligned_write16(_addr, _value) -#endif - -enum { - FSDEV_BUS_SIZE = sizeof(fsdev_bus_t), -}; - -//--------------------------------------------------------------------+ -// BTable Typedef -//--------------------------------------------------------------------+ -enum { - BTABLE_BUF_TX = 0, - BTABLE_BUF_RX = 1 -}; - -// hardware limit endpoint -#define FSDEV_EP_COUNT 8 - -// Buffer Table is located in Packet Memory Area (PMA) and therefore its address access is forced to either -// 16-bit or 32-bit depending on FSDEV_BUS_32BIT. -// 0: TX (IN), 1: RX (OUT) -typedef union { - // data is strictly 16-bit access (address could be 32-bit aligned) - struct { - volatile pma_access_scheme uint16_t addr; - volatile pma_access_scheme uint16_t count; - } ep16[FSDEV_EP_COUNT][2]; - - // strictly 32-bit access - struct { - volatile uint32_t count_addr; - } ep32[FSDEV_EP_COUNT][2]; -} fsdev_btable_t; - -TU_VERIFY_STATIC(sizeof(fsdev_btable_t) == FSDEV_EP_COUNT*8*FSDEV_PMA_STRIDE, "size is not correct"); -TU_VERIFY_STATIC(FSDEV_BTABLE_BASE + FSDEV_EP_COUNT*8 <= FSDEV_PMA_SIZE, "BTABLE does not fit in PMA RAM"); - -#define FSDEV_BTABLE ((volatile fsdev_btable_t*) (FSDEV_PMA_BASE + FSDEV_PMA_STRIDE*(FSDEV_BTABLE_BASE))) - -typedef struct { - volatile pma_access_scheme fsdev_bus_t value; -} fsdev_pma_buf_t; - -#define PMA_BUF_AT(_addr) ((fsdev_pma_buf_t*) (FSDEV_PMA_BASE + FSDEV_PMA_STRIDE*(_addr))) - -//--------------------------------------------------------------------+ -// Registers Typedef -//--------------------------------------------------------------------+ - -// volatile 32-bit aligned -#define _va32 volatile TU_ATTR_ALIGNED(4) - -typedef struct { - struct { - _va32 fsdev_bus_t reg; - }ep[FSDEV_EP_COUNT]; - - _va32 uint32_t RESERVED7[8]; // Reserved - _va32 fsdev_bus_t CNTR; // 40: Control register - _va32 fsdev_bus_t ISTR; // 44: Interrupt status register - _va32 fsdev_bus_t FNR; // 48: Frame number register - _va32 fsdev_bus_t DADDR; // 4C: Device address register - _va32 fsdev_bus_t BTABLE; // 50: Buffer Table address register (16-bit only) - _va32 fsdev_bus_t LPMCSR; // 54: LPM Control and Status Register (32-bit only) - _va32 fsdev_bus_t BCDR; // 58: Battery Charging Detector Register (32-bit only) -} fsdev_regs_t; - -TU_VERIFY_STATIC(offsetof(fsdev_regs_t, CNTR) == 0x40, "Wrong offset"); -TU_VERIFY_STATIC(sizeof(fsdev_regs_t) == 0x5C, "Size is not correct"); - -#define FSDEV_REG ((fsdev_regs_t*) FSDEV_REG_BASE) - - -#ifndef USB_EPTX_STAT -#define USB_EPTX_STAT 0x0030U -#endif - -#ifndef USB_EPRX_STAT -#define USB_EPRX_STAT 0x3000U -#endif - -#ifndef USB_EPTX_STAT_Pos -#define USB_EPTX_STAT_Pos 4u -#endif - -#ifndef USB_EP_DTOG_TX_Pos -#define USB_EP_DTOG_TX_Pos 6u -#endif - -#ifndef USB_EP_CTR_TX_Pos -#define USB_EP_CTR_TX_Pos 7u -#endif - -typedef enum { - EP_STAT_DISABLED = 0, - EP_STAT_STALL = 1, - EP_STAT_NAK = 2, - EP_STAT_VALID = 3 -}ep_stat_t; - -#define EP_STAT_MASK(_dir) (3u << (USB_EPTX_STAT_Pos + ((_dir) == TUSB_DIR_IN ? 0 : 8))) -#define EP_DTOG_MASK(_dir) (1u << (USB_EP_DTOG_TX_Pos + ((_dir) == TUSB_DIR_IN ? 0 : 8))) - -#define CH_STAT_MASK(_dir) (3u << (USB_EPTX_STAT_Pos + ((_dir) == TUSB_DIR_IN ? 8 : 0))) -#define CH_DTOG_MASK(_dir) (1u << (USB_EP_DTOG_TX_Pos + ((_dir) == TUSB_DIR_IN ? 8 : 0))) - -void fsdev_int_enable(uint8_t rhport); -void fsdev_int_disable(uint8_t rhport); -void fsdev_connect(uint8_t rhport); -void fsdev_disconnect(uint8_t rhport); - -//--------------------------------------------------------------------+ -// Endpoint Helper -// - CTR is write 0 to clear -// - DTOG and STAT are write 1 to toggle -//--------------------------------------------------------------------+ - -TU_ATTR_ALWAYS_INLINE static inline uint32_t ep_read(uint32_t ep_id) { - return FSDEV_REG->ep[ep_id].reg; -} - -TU_ATTR_ALWAYS_INLINE static inline void ep_write(uint32_t ep_id, uint32_t value, bool need_exclusive) { - if (need_exclusive) { - fsdev_int_disable(0); - } - - FSDEV_REG->ep[ep_id].reg = (fsdev_bus_t) value; - - if (need_exclusive) { - fsdev_int_enable(0); - } -} - -TU_ATTR_ALWAYS_INLINE static inline void ep_write_clear_ctr(uint32_t ep_id, tusb_dir_t dir) { - uint32_t reg = FSDEV_REG->ep[ep_id].reg; - reg |= USB_EP_CTR_TX | USB_EP_CTR_RX; - reg &= USB_EPREG_MASK; - reg &= ~(1 << (USB_EP_CTR_TX_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); - ep_write(ep_id, reg, false); -} - -TU_ATTR_ALWAYS_INLINE static inline void ep_change_status(uint32_t* reg, tusb_dir_t dir, ep_stat_t state) { - *reg ^= (state << (USB_EPTX_STAT_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); -} - -TU_ATTR_ALWAYS_INLINE static inline void ep_change_dtog(uint32_t* reg, tusb_dir_t dir, uint8_t state) { - *reg ^= (state << (USB_EP_DTOG_TX_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); -} - -TU_ATTR_ALWAYS_INLINE static inline bool ep_is_iso(uint32_t reg) { - return (reg & USB_EP_TYPE_MASK) == USB_EP_ISOCHRONOUS; -} - -//--------------------------------------------------------------------+ -// Channel Helper -// - Direction is opposite to endpoint direction -//--------------------------------------------------------------------+ - -TU_ATTR_ALWAYS_INLINE static inline uint32_t ch_read(uint32_t ch_id) { - return ep_read(ch_id); -} - -TU_ATTR_ALWAYS_INLINE static inline void ch_write(uint32_t ch_id, uint32_t value, bool need_exclusive) { - ep_write(ch_id, value, need_exclusive); -} - -TU_ATTR_ALWAYS_INLINE static inline void ch_write_clear_ctr(uint32_t ch_id, tusb_dir_t dir) { - uint32_t reg = FSDEV_REG->ep[ch_id].reg; - reg |= USB_EP_CTR_TX | USB_EP_CTR_RX; - reg &= USB_EPREG_MASK; - reg &= ~(1 << (USB_EP_CTR_TX_Pos + (dir == TUSB_DIR_IN ? 8 : 0))); - ep_write(ch_id, reg, false); -} - -TU_ATTR_ALWAYS_INLINE static inline void ch_change_status(uint32_t* reg, tusb_dir_t dir, ep_stat_t state) { - *reg ^= (state << (USB_EPTX_STAT_Pos + (dir == TUSB_DIR_IN ? 8 : 0))); -} - -TU_ATTR_ALWAYS_INLINE static inline void ch_change_dtog(uint32_t* reg, tusb_dir_t dir, uint8_t state) { - *reg ^= (state << (USB_EP_DTOG_TX_Pos + (dir == TUSB_DIR_IN ? 8 : 0))); -} - -//--------------------------------------------------------------------+ -// BTable Helper -//--------------------------------------------------------------------+ - -TU_ATTR_ALWAYS_INLINE static inline uint32_t btable_get_addr(uint32_t ep_id, uint8_t buf_id) { -#ifdef FSDEV_BUS_32BIT - return FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr & 0x0000FFFFu; -#else - return FSDEV_BTABLE->ep16[ep_id][buf_id].addr; -#endif -} - -TU_ATTR_ALWAYS_INLINE static inline void btable_set_addr(uint32_t ep_id, uint8_t buf_id, uint16_t addr) { -#ifdef FSDEV_BUS_32BIT - uint32_t count_addr = FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr; - count_addr = (count_addr & 0xFFFF0000u) | (addr & 0x0000FFFCu); - FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr = count_addr; -#else - FSDEV_BTABLE->ep16[ep_id][buf_id].addr = addr; -#endif -} - -TU_ATTR_ALWAYS_INLINE static inline uint16_t btable_get_count(uint32_t ep_id, uint8_t buf_id) { - uint16_t count; -#ifdef FSDEV_BUS_32BIT - count = (FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr >> 16); -#else - count = FSDEV_BTABLE->ep16[ep_id][buf_id].count; -#endif - return count & 0x3FFU; -} - -TU_ATTR_ALWAYS_INLINE static inline void btable_set_count(uint32_t ep_id, uint8_t buf_id, uint16_t byte_count) { -#ifdef FSDEV_BUS_32BIT - uint32_t count_addr = FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr; - count_addr = (count_addr & ~0x03FF0000u) | ((byte_count & 0x3FFu) << 16); - FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr = count_addr; -#else - uint16_t cnt = FSDEV_BTABLE->ep16[ep_id][buf_id].count; - cnt = (cnt & ~0x3FFU) | (byte_count & 0x3FFU); - FSDEV_BTABLE->ep16[ep_id][buf_id].count = cnt; -#endif -} - -/* Aligned buffer size according to hardware */ -TU_ATTR_ALWAYS_INLINE static inline uint16_t pma_align_buffer_size(uint16_t size, uint8_t* blsize, uint8_t* num_block) { - /* The STM32 full speed USB peripheral supports only a limited set of - * buffer sizes given by the RX buffer entry format in the USB_BTABLE. */ - uint16_t block_in_bytes; - if (size > 62) { - block_in_bytes = 32; - *blsize = 1; - *num_block = tu_div_ceil(size, 32); - } else { - block_in_bytes = 2; - *blsize = 0; - *num_block = tu_div_ceil(size, 2); - } - - return (*num_block) * block_in_bytes; -} - -TU_ATTR_ALWAYS_INLINE static inline void btable_set_rx_bufsize(uint32_t ep_id, uint8_t buf_id, uint16_t wCount) { - uint8_t blsize, num_block; - (void) pma_align_buffer_size(wCount, &blsize, &num_block); - - /* Encode into register. When BLSIZE==1, we need to subtract 1 block count */ - uint16_t bl_nb = (blsize << 15) | ((num_block - blsize) << 10); - if (bl_nb == 0) { - // zlp but 0 is invalid value, set blsize to 1 (32 bytes) - // Note: lower value can cause PMAOVR on setup with ch32v203 - bl_nb = 1 << 15; - } - -#ifdef FSDEV_BUS_32BIT - uint32_t count_addr = FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr; - count_addr = (bl_nb << 16) | (count_addr & 0x0000FFFFu); - FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr = count_addr; -#else - FSDEV_BTABLE->ep16[ep_id][buf_id].count = bl_nb; -#endif - -} - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c index 1c08f64d6..b3c08ba23 100644 --- a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c @@ -30,6 +30,7 @@ * * C0 2048 byte buffer; 32-bit bus; host mode * G0 2048 byte buffer; 32-bit bus; host mode + * U3 2048 byte buffer; 32-bit bus; host mode * H5 2048 byte buffer; 32-bit bus; host mode * U535, U545 2048 byte buffer; 32-bit bus; host mode * @@ -42,19 +43,14 @@ #include "host/hcd.h" #include "host/usbh.h" - -#if defined(TUP_USBIP_FSDEV_STM32) - #include "fsdev_stm32.h" -#else - #error "Unknown USB IP" -#endif +#include "fsdev_common.h" //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ // Debug level for FSDEV -#define FSDEV_DEBUG 1 +#define FSDEV_DEBUG 3 // Max number of endpoints application can open, can be larger than FSDEV_EP_COUNT #ifndef CFG_TUH_FSDEV_ENDPOINT_MAX @@ -76,9 +72,12 @@ typedef struct { uint8_t ep_addr; uint8_t ep_type; uint8_t interval; - bool low_speed; - bool allocated; - bool next_setup; + struct TU_ATTR_PACKED { + uint8_t low_speed : 1; + uint8_t allocated : 1; + uint8_t next_setup : 1; + uint8_t pid : 1; + }; } hcd_endpoint_t; // Additional info for each channel when it is active @@ -88,7 +87,7 @@ typedef struct { uint8_t dev_addr; uint8_t ep_num; uint8_t ep_type; - bool allocated[2]; + uint8_t allocated[2]; uint8_t retry[2]; uint8_t result; } hcd_xfer_t; @@ -113,24 +112,35 @@ static uint8_t endpoint_alloc(void); static uint8_t endpoint_find(uint8_t dev_addr, uint8_t ep_addr); static uint32_t hcd_pma_alloc(uint8_t channel, tusb_dir_t dir, uint16_t len); static uint8_t channel_alloc(uint8_t dev_addr, uint8_t ep_addr, uint8_t ep_type); -static bool hcd_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t nbytes); -static bool hcd_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t nbytes); static bool edpt_xfer_kickoff(uint8_t ep_id); static bool channel_xfer_start(uint8_t ch_id, tusb_dir_t dir); static void edpoint_close(uint8_t ep_id); static void port_status_handler(uint8_t rhport, bool in_isr); +static void ch_handle_ack(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir); +static void ch_handle_nak(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir); +static void ch_handle_stall(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir); +static void ch_handle_error(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir); + //--------------------------------------------------------------------+ // Inline Functions //--------------------------------------------------------------------+ static inline void endpoint_dealloc(hcd_endpoint_t* edpt) { - edpt->allocated = false; + edpt->allocated = 0; } static inline void channel_dealloc(hcd_xfer_t* xfer, tusb_dir_t dir) { - xfer->allocated[dir] = false; + xfer->allocated[dir] = 0; } +// Write channel state in specified direction +static inline void channel_write_status(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir, ep_stat_t state, bool need_exclusive) { + ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(dir); + ch_change_status(&ch_reg, dir, state); + ch_write(ch_id, ch_reg, need_exclusive); +} + + //--------------------------------------------------------------------+ // Controller API //--------------------------------------------------------------------+ @@ -218,139 +228,153 @@ static void port_status_handler(uint8_t rhport, bool in_isr) { } } -// Handle CTR interrupt for the TX/OUT direction -static void handle_ctr_tx(uint32_t ch_id) { - uint32_t ch_reg = ch_read(ch_id) | USB_EP_CTR_TX | USB_EP_CTR_RX; +//--------------------------------------------------------------------+ +// Interrupt Helper Functions +//--------------------------------------------------------------------+ +// Handle ACK response +static void ch_handle_ack(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) { uint8_t const ep_num = ch_reg & USB_EPADDR_FIELD; uint8_t const daddr = (ch_reg & USB_CHEP_DEVADDR_Msk) >> USB_CHEP_DEVADDR_Pos; - uint8_t ep_id = endpoint_find(daddr, ep_num); - TU_VERIFY(ep_id != TUSB_INDEX_INVALID_8, ); + uint8_t ep_id = endpoint_find(daddr, ep_num | (dir == TUSB_DIR_IN ? TUSB_DIR_IN_MASK : 0)); + if (ep_id == TUSB_INDEX_INVALID_8) return; hcd_endpoint_t* edpt = &_hcd_data.edpt[ep_id]; hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; - TU_VERIFY(xfer->allocated[TUSB_DIR_OUT],); - // Manage Correct Transaction - if ((ch_reg & USB_CH_ERRTX) == 0U) { - // Acked - if ((ch_reg & USB_CH_TX_STTX) == USB_CH_TX_ACK_SBUF) { - if (edpt->buflen != xfer->queued_len[TUSB_DIR_OUT]) { - uint16_t const len = tu_min16(edpt->buflen - xfer->queued_len[TUSB_DIR_OUT], edpt->max_packet_size); - uint16_t pma_addr = (uint16_t) btable_get_addr(ch_id, BTABLE_BUF_TX); - hcd_write_packet_memory(pma_addr, &(edpt->buffer[xfer->queued_len[TUSB_DIR_OUT]]), len); - btable_set_count(ch_id, BTABLE_BUF_TX, len); - xfer->queued_len[TUSB_DIR_OUT] += len; - - ch_change_status(&ch_reg, TUSB_DIR_OUT, EP_STAT_VALID); - ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(TUSB_DIR_OUT); // only change TX Status, reserve other toggle bits - ch_write(ch_id, ch_reg, false); - } else { - channel_dealloc(xfer, TUSB_DIR_OUT); - hcd_event_xfer_complete(daddr, ep_num, xfer->queued_len[TUSB_DIR_OUT], XFER_RESULT_SUCCESS, true); - } - } else if ((ch_reg & USB_CH_TX_STTX) == USB_CH_TX_NAK) { - // NAKed - if (edpt->ep_type != TUSB_XFER_INTERRUPT) { - ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(TUSB_DIR_OUT); // will change TX Status, reserved other toggle bits - ch_change_status(&ch_reg, TUSB_DIR_OUT, EP_STAT_VALID); - ch_write(ch_id, ch_reg, false); - } - } else if ((ch_reg & USB_CH_TX_STTX) == USB_CH_TX_STALL) { - // STALLed + if (dir == TUSB_DIR_OUT) { + // OUT/TX direction + if (edpt->buflen != xfer->queued_len[TUSB_DIR_OUT]) { + // More data to send + uint16_t const len = tu_min16(edpt->buflen - xfer->queued_len[TUSB_DIR_OUT], edpt->max_packet_size); + uint16_t pma_addr = (uint16_t) btable_get_addr(ch_id, BTABLE_BUF_TX); + fsdev_write_packet_memory(pma_addr, &(edpt->buffer[xfer->queued_len[TUSB_DIR_OUT]]), len); + btable_set_count(ch_id, BTABLE_BUF_TX, len); + xfer->queued_len[TUSB_DIR_OUT] += len; + channel_write_status(ch_id, ch_reg, TUSB_DIR_OUT, EP_STAT_VALID, false); + } else { + // Transfer complete channel_dealloc(xfer, TUSB_DIR_OUT); - ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(TUSB_DIR_OUT); // will change TX Status, reserved other toggle bits - ch_change_status(&ch_reg, TUSB_DIR_OUT, EP_STAT_DISABLED); - ch_write(ch_id, ch_reg, false); - hcd_event_xfer_complete(daddr, ep_num, xfer->queued_len[TUSB_DIR_OUT], XFER_RESULT_STALLED, true); + edpt->pid = (ch_reg & USB_CHEP_DTOG_TX) ? 1 : 0; + hcd_event_xfer_complete(daddr, ep_num, xfer->queued_len[TUSB_DIR_OUT], XFER_RESULT_SUCCESS, true); } } else { - // Error - TU_LOG(FSDEV_DEBUG, "handle_ctr_tx error epreg=0x%08X ch=%u ep=0x%02X daddr=%u queued=%u/%u\r\n", - ch_reg, ch_id, ep_num, daddr, xfer->queued_len[TUSB_DIR_OUT], edpt->buflen); - ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(TUSB_DIR_OUT); // will change TX Status, reserved other toggle bits - ch_reg &=~USB_CH_ERRTX; - if (xfer->retry[TUSB_DIR_OUT] < HCD_XFER_ERROR_MAX) { - // Retry - xfer->retry[TUSB_DIR_OUT]++; + // IN/RX direction + uint16_t const rx_count = btable_get_count(ch_id, BTABLE_BUF_RX); + uint16_t pma_addr = (uint16_t) btable_get_addr(ch_id, BTABLE_BUF_RX); + + fsdev_read_packet_memory(edpt->buffer + xfer->queued_len[TUSB_DIR_IN], pma_addr, rx_count); + xfer->queued_len[TUSB_DIR_IN] += rx_count; + + if ((rx_count < edpt->max_packet_size) || (xfer->queued_len[TUSB_DIR_IN] >= edpt->buflen)) { + // Transfer complete (short packet or all bytes received) + channel_dealloc(xfer, TUSB_DIR_IN); + edpt->pid = (ch_reg & USB_CHEP_DTOG_RX) ? 1 : 0; + hcd_event_xfer_complete(daddr, ep_num | TUSB_DIR_IN_MASK, xfer->queued_len[TUSB_DIR_IN], XFER_RESULT_SUCCESS, true); } else { - // Failed after retries - channel_dealloc(xfer, TUSB_DIR_OUT); - ch_change_status(&ch_reg, TUSB_DIR_OUT, EP_STAT_DISABLED); - hcd_event_xfer_complete(daddr, ep_num, xfer->queued_len[TUSB_DIR_OUT], XFER_RESULT_FAILED, true); + // More data expected + uint16_t const cnt = tu_min16(edpt->buflen - xfer->queued_len[TUSB_DIR_IN], edpt->max_packet_size); + btable_set_rx_bufsize(ch_id, BTABLE_BUF_RX, cnt); + channel_write_status(ch_id, ch_reg, TUSB_DIR_IN, EP_STAT_VALID, false); } - ch_write(ch_id, ch_reg, false); } } -// Handle CTR interrupt for the RX/IN direction -static void handle_ctr_rx(uint32_t ch_id) { - uint32_t ch_reg = ch_read(ch_id) | USB_EP_CTR_TX | USB_EP_CTR_RX; +// Handle NAK response +static void ch_handle_nak(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) { uint8_t const ep_num = ch_reg & USB_EPADDR_FIELD; - uint8_t const daddr = (ch_reg & USB_CHEP_DEVADDR_Msk) >> USB_CHEP_DEVADDR_Pos; - uint8_t ep_id = endpoint_find(daddr, ep_num | TUSB_DIR_IN_MASK); - TU_VERIFY(ep_id != TUSB_INDEX_INVALID_8, ); + uint8_t ep_id = endpoint_find(daddr, ep_num | (dir == TUSB_DIR_IN ? TUSB_DIR_IN_MASK : 0)); + if (ep_id == TUSB_INDEX_INVALID_8) return; hcd_endpoint_t* edpt = &_hcd_data.edpt[ep_id]; - hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; - TU_VERIFY(xfer->allocated[TUSB_DIR_IN],); + // Retry non-periodic transfer immediately, + // Periodic transfer will be retried by next frame automatically + if (edpt->ep_type == TUSB_XFER_CONTROL || edpt->ep_type == TUSB_XFER_BULK) { + channel_write_status(ch_id, ch_reg, dir, EP_STAT_VALID, false); + } +} + +// Handle STALL response +static void ch_handle_stall(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) { + uint8_t const ep_num = ch_reg & USB_EPADDR_FIELD; + uint8_t const daddr = (ch_reg & USB_CHEP_DEVADDR_Msk) >> USB_CHEP_DEVADDR_Pos; + + hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; + channel_dealloc(xfer, dir); + + channel_write_status(ch_id, ch_reg, dir, EP_STAT_DISABLED, false); + + hcd_event_xfer_complete(daddr, ep_num | (dir == TUSB_DIR_IN ? TUSB_DIR_IN_MASK : 0), + xfer->queued_len[dir], XFER_RESULT_STALLED, true); +} + +// Handle error response +static void ch_handle_error(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) { + uint8_t const ep_num = ch_reg & USB_EPADDR_FIELD; + uint8_t const daddr = (ch_reg & USB_CHEP_DEVADDR_Msk) >> USB_CHEP_DEVADDR_Pos; + + uint8_t ep_id = endpoint_find(daddr, ep_num | (dir == TUSB_DIR_IN ? TUSB_DIR_IN_MASK : 0)); + if (ep_id == TUSB_INDEX_INVALID_8) return; + + hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; + + ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(dir); + ch_reg &= ~(dir == TUSB_DIR_OUT ? USB_CH_ERRTX : USB_CH_ERRRX); + + if (xfer->retry[dir] < HCD_XFER_ERROR_MAX) { + // Retry + xfer->retry[dir]++; + ch_change_status(&ch_reg, dir, EP_STAT_VALID); + } else { + // Failed after retries + channel_dealloc(xfer, dir); + ch_change_status(&ch_reg, dir, EP_STAT_DISABLED); + hcd_event_xfer_complete(daddr, ep_num | (dir == TUSB_DIR_IN ? TUSB_DIR_IN_MASK : 0), + xfer->queued_len[dir], XFER_RESULT_FAILED, true); + } + ch_write(ch_id, ch_reg, false); +} + +// Handle CTR interrupt for the TX/OUT direction +static void handle_ctr_tx(uint32_t ch_id) { + uint32_t ch_reg = ch_read(ch_id) | USB_EP_CTR_TX | USB_EP_CTR_RX; + hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; + TU_VERIFY(xfer->allocated[TUSB_DIR_OUT] == 1,); + + if ((ch_reg & USB_CH_ERRTX) == 0U) { + // No error + if ((ch_reg & USB_CH_TX_STTX) == USB_CH_TX_ACK_SBUF) { + ch_handle_ack(ch_id, ch_reg, TUSB_DIR_OUT); + } else if ((ch_reg & USB_CH_TX_STTX) == USB_CH_TX_NAK) { + ch_handle_nak(ch_id, ch_reg, TUSB_DIR_OUT); + } else if ((ch_reg & USB_CH_TX_STTX) == USB_CH_TX_STALL) { + ch_handle_stall(ch_id, ch_reg, TUSB_DIR_OUT); + } + } else { + ch_handle_error(ch_id, ch_reg, TUSB_DIR_OUT); + } +} + +// Handle CTR interrupt for the RX/IN direction +static void handle_ctr_rx(uint32_t ch_id) { + uint32_t ch_reg = ch_read(ch_id) | USB_EP_CTR_TX | USB_EP_CTR_RX; + hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; + TU_VERIFY(xfer->allocated[TUSB_DIR_IN] == 1,); - // Manage Correct Transaction if ((ch_reg & USB_CH_ERRRX) == 0U) { - // Acked + // No error if ((ch_reg & USB_CH_RX_STRX) == USB_CH_RX_ACK_SBUF) { - uint16_t const rx_count = btable_get_count(ch_id, BTABLE_BUF_RX); - uint16_t pma_addr = (uint16_t) btable_get_addr(ch_id, BTABLE_BUF_RX); - - hcd_read_packet_memory(edpt->buffer + xfer->queued_len[TUSB_DIR_IN], pma_addr, rx_count); - xfer->queued_len[TUSB_DIR_IN] += rx_count; - - if ((rx_count < edpt->max_packet_size) || (xfer->queued_len[TUSB_DIR_IN] >= edpt->buflen)) { - // all bytes received or short packet - channel_dealloc(xfer, TUSB_DIR_IN); - hcd_event_xfer_complete(daddr, ep_num | TUSB_DIR_IN_MASK, xfer->queued_len[TUSB_DIR_IN], XFER_RESULT_SUCCESS, true); - } else { - // Set endpoint active again for receiving more data. Note that isochronous endpoints stay active always - uint16_t const cnt = tu_min16(edpt->buflen - xfer->queued_len[TUSB_DIR_IN], edpt->max_packet_size); - btable_set_rx_bufsize(ch_id, BTABLE_BUF_RX, cnt); - ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(TUSB_DIR_IN); // will change RX Status, reserved other toggle bits - ch_change_status(&ch_reg, TUSB_DIR_IN, EP_STAT_VALID); - ch_write(ch_id, ch_reg, false); - } + ch_handle_ack(ch_id, ch_reg, TUSB_DIR_IN); } else if ((ch_reg & USB_CH_RX_STRX) == USB_CH_RX_NAK) { - // NAKed - if (edpt->ep_type != TUSB_XFER_INTERRUPT) { - ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(TUSB_DIR_IN); // will change TX Status, reserved other toggle bits - ch_change_status(&ch_reg, TUSB_DIR_IN, EP_STAT_VALID); - ch_write(ch_id, ch_reg, false); - } - } else { - // STALLed - channel_dealloc(xfer, TUSB_DIR_IN); - ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(TUSB_DIR_IN); // will change TX Status, reserved other toggle bits - ch_change_status(&ch_reg, TUSB_DIR_IN, EP_STAT_DISABLED); - ch_write(ch_id, ch_reg, false); - hcd_event_xfer_complete(daddr, ep_num | TUSB_DIR_IN_MASK, xfer->queued_len[TUSB_DIR_IN], XFER_RESULT_STALLED, true); + ch_handle_nak(ch_id, ch_reg, TUSB_DIR_IN); + } else if ((ch_reg & USB_CH_RX_STRX) == USB_CH_RX_STALL){ + ch_handle_stall(ch_id, ch_reg, TUSB_DIR_IN); } } else { - // Error - TU_LOG(FSDEV_DEBUG, "handle_ctr_tx error epreg=0x%08X ch=%u ep=0x%02X daddr=%u queued=%u/%u\r\n", - ch_reg, ch_id, ep_num, daddr, xfer->queued_len[TUSB_DIR_IN], edpt->buflen); - ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(TUSB_DIR_IN); // will change RX Status, reserved other toggle bits - ch_reg &=~USB_CH_ERRRX; - if (xfer->retry[TUSB_DIR_IN] < HCD_XFER_ERROR_MAX) { - // Retry - xfer->retry[TUSB_DIR_IN]++; - } else { - // Failed after retries - channel_dealloc(xfer, TUSB_DIR_IN); - ch_change_status(&ch_reg, TUSB_DIR_IN, EP_STAT_DISABLED); - hcd_event_xfer_complete(daddr, ep_num | TUSB_DIR_IN_MASK, xfer->queued_len[TUSB_DIR_IN], XFER_RESULT_FAILED, true); - } - ch_write(ch_id, ch_reg, false); + ch_handle_error(ch_id, ch_reg, TUSB_DIR_IN); } } @@ -468,7 +492,7 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr) { // Close all endpoints for this device for(uint32_t i = 0; i < CFG_TUH_FSDEV_ENDPOINT_MAX; i++) { hcd_endpoint_t* edpt = &_hcd_data.edpt[i]; - if (edpt->allocated && edpt->dev_addr == dev_addr) { + if (edpt->allocated == 1 && edpt->dev_addr == dev_addr) { edpoint_close(i); } } @@ -496,7 +520,8 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const edpt->ep_type = ep_type; edpt->max_packet_size = packet_size; edpt->interval = ep_desc->bInterval; - edpt->low_speed = (hcd_port_speed_get(rhport) == TUSB_SPEED_FULL && tuh_speed_get(dev_addr) == TUSB_SPEED_LOW); + edpt->pid = 0; + edpt->low_speed = (hcd_port_speed_get(rhport) == TUSB_SPEED_FULL && tuh_speed_get(dev_addr) == TUSB_SPEED_LOW) ? 1 : 0; // EP0 is bi-directional, so we need to open both OUT and IN channels if (ep_addr == 0) { @@ -525,7 +550,7 @@ bool hcd_edpt_close(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { edpoint_close(ep_id_in); } - return false; + return true; } // Submit a transfer @@ -556,17 +581,12 @@ bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { for (uint8_t i = 0; i < FSDEV_EP_COUNT; i++) { hcd_xfer_t* xfer = &_hcd_data.xfer[i]; - if (xfer->allocated[dir] && + if (xfer->allocated[dir] == 1 && xfer->dev_addr == dev_addr && xfer->ep_num == tu_edpt_number(ep_addr)) { - channel_dealloc(xfer, dir); - - uint32_t ch_reg = ch_read(i) | USB_EP_CTR_TX | USB_EP_CTR_RX; // reserve CTR bits - ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(dir); // will change Status, reserved other toggle bits - ch_change_status(&ch_reg, dir, EP_STAT_DISABLED); - ch_write(i, ch_reg, true); - + uint32_t ch_reg = ch_read(i) | USB_EP_CTR_TX | USB_EP_CTR_RX; + channel_write_status(i, ch_reg, dir, EP_STAT_DISABLED, true); } } @@ -582,6 +602,7 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet hcd_endpoint_t *edpt = &_hcd_data.edpt[ep_id]; edpt->next_setup = true; + edpt->pid = 0; return hcd_edpt_xfer(rhport, dev_addr, 0, (uint8_t*)(uintptr_t) setup_packet, 8); } @@ -592,6 +613,12 @@ bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { (void) dev_addr; (void) ep_addr; + uint8_t const ep_id = endpoint_find(dev_addr, 0); + TU_ASSERT(ep_id < CFG_TUH_FSDEV_ENDPOINT_MAX); + + hcd_endpoint_t *edpt = &_hcd_data.edpt[ep_id]; + edpt->pid = 0; + return true; } @@ -602,8 +629,8 @@ bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { static uint8_t endpoint_alloc(void) { for (uint32_t i = 0; i < CFG_TUH_FSDEV_ENDPOINT_MAX; i++) { hcd_endpoint_t* edpt = &_hcd_data.edpt[i]; - if (!edpt->allocated) { - edpt->allocated = true; + if (edpt->allocated == 0) { + edpt->allocated = 1; return i; } } @@ -613,7 +640,7 @@ static uint8_t endpoint_alloc(void) { static uint8_t endpoint_find(uint8_t dev_addr, uint8_t ep_addr) { for (uint32_t i = 0; i < (uint32_t)CFG_TUH_FSDEV_ENDPOINT_MAX; i++) { hcd_endpoint_t* edpt = &_hcd_data.edpt[i]; - if (edpt->allocated && edpt->dev_addr == dev_addr && edpt->ep_addr == ep_addr) { + if (edpt->allocated == 1 && edpt->dev_addr == dev_addr && edpt->ep_addr == ep_addr) { return i; } } @@ -628,24 +655,14 @@ static void edpoint_close(uint8_t ep_id) { // disable active channel belong to this endpoint for (uint8_t i = 0; i < FSDEV_EP_COUNT; i++) { hcd_xfer_t* xfer = &_hcd_data.xfer[i]; - - if (xfer->allocated[TUSB_DIR_OUT] && xfer->edpt[TUSB_DIR_OUT] == edpt) { + uint32_t ch_reg = ch_read(i) | USB_EP_CTR_TX | USB_EP_CTR_RX; + if (xfer->allocated[TUSB_DIR_OUT] == 1 && xfer->edpt[TUSB_DIR_OUT] == edpt) { channel_dealloc(xfer, TUSB_DIR_OUT); - - uint32_t ch_reg = ch_read(i) | USB_EP_CTR_TX | USB_EP_CTR_RX; // reserve CTR bits - ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(TUSB_DIR_OUT); // will change RX Status, reserved other toggle bits - ch_change_status(&ch_reg, TUSB_DIR_OUT, EP_STAT_DISABLED); - ch_write(i, ch_reg, true); - + channel_write_status(i, ch_reg, TUSB_DIR_OUT, EP_STAT_DISABLED, true); } - if (xfer->allocated[TUSB_DIR_IN] && xfer->edpt[TUSB_DIR_IN] == edpt) { + if (xfer->allocated[TUSB_DIR_IN] == 1 && xfer->edpt[TUSB_DIR_IN] == edpt) { channel_dealloc(xfer, TUSB_DIR_IN); - - uint32_t ch_reg = ch_read(i) | USB_EP_CTR_TX | USB_EP_CTR_RX; // reserve CTR bits - ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(TUSB_DIR_IN); // will change TX Status, reserved other toggle bits - ch_change_status(&ch_reg, TUSB_DIR_IN, EP_STAT_DISABLED); - ch_write(i, ch_reg, true); - + channel_write_status(i, ch_reg, TUSB_DIR_IN, EP_STAT_DISABLED, true); } } } @@ -654,10 +671,10 @@ static void edpoint_close(uint8_t ep_id) { static uint32_t hcd_pma_alloc(uint8_t channel, tusb_dir_t dir, uint16_t len) { (void) len; // Simple static allocation as we are unlikely to handle ISO endpoints in host mode - // We just give each channel a buffer of max packet size (64 bytes) + // We just give each channel two buffers of max packet size (64 bytes) for IN and OUT uint16_t addr = FSDEV_BTABLE_BASE + 8 * FSDEV_EP_COUNT; - addr += channel * 64 * 2 + (dir == TUSB_DIR_IN ? 64 : 0); + addr += channel * TUSB_EPSIZE_BULK_FS * 2 + (dir == TUSB_DIR_IN ? TUSB_EPSIZE_BULK_FS : 0); TU_ASSERT(addr <= FSDEV_PMA_SIZE, 0xFFFF); @@ -672,12 +689,12 @@ static uint8_t channel_alloc(uint8_t dev_addr, uint8_t ep_addr, uint8_t ep_type) // Find channel allocate for same ep_num but other direction tusb_dir_t const other_dir = (dir == TUSB_DIR_IN) ? TUSB_DIR_OUT : TUSB_DIR_IN; for (uint8_t i = 0; i < FSDEV_EP_COUNT; i++) { - if (!_hcd_data.xfer[i].allocated[dir] && - _hcd_data.xfer[i].allocated[other_dir] && + if (_hcd_data.xfer[i].allocated[dir] == 0 && + _hcd_data.xfer[i].allocated[other_dir] == 1 && _hcd_data.xfer[i].dev_addr == dev_addr && _hcd_data.xfer[i].ep_num == ep_num && _hcd_data.xfer[i].ep_type == ep_type) { - _hcd_data.xfer[i].allocated[dir] = true; + _hcd_data.xfer[i].allocated[dir] = 1; _hcd_data.xfer[i].queued_len[dir] = 0; _hcd_data.xfer[i].retry[dir] = 0; return i; @@ -686,11 +703,11 @@ static uint8_t channel_alloc(uint8_t dev_addr, uint8_t ep_addr, uint8_t ep_type) // Find free channel for (uint8_t i = 0; i < FSDEV_EP_COUNT; i++) { - if (!_hcd_data.xfer[i].allocated[0] && !_hcd_data.xfer[i].allocated[1]) { + if (_hcd_data.xfer[i].allocated[0] == 0 && _hcd_data.xfer[i].allocated[1] == 0) { _hcd_data.xfer[i].dev_addr = dev_addr; _hcd_data.xfer[i].ep_num = ep_num; _hcd_data.xfer[i].ep_type = ep_type; - _hcd_data.xfer[i].allocated[dir] = true; + _hcd_data.xfer[i].allocated[dir] = 1; _hcd_data.xfer[i].queued_len[dir] = 0; _hcd_data.xfer[i].retry[dir] = 0; return i; @@ -748,84 +765,35 @@ static bool channel_xfer_start(uint8_t ch_id, tusb_dir_t dir) { if (dir == TUSB_DIR_OUT) { uint16_t const len = tu_min16(edpt->buflen - xfer->queued_len[TUSB_DIR_OUT], edpt->max_packet_size); - hcd_write_packet_memory(pma_addr, &(edpt->buffer[xfer->queued_len[TUSB_DIR_OUT]]), len); + fsdev_write_packet_memory(pma_addr, &(edpt->buffer[xfer->queued_len[TUSB_DIR_OUT]]), len); btable_set_count(ch_id, BTABLE_BUF_TX, len); xfer->queued_len[TUSB_DIR_OUT] += len; - if (edpt->next_setup) { - // Setup packet uses IN token - edpt->next_setup = false; - ch_reg |= USB_EP_SETUP; - } - - ch_change_status(&ch_reg, TUSB_DIR_OUT, EP_STAT_VALID); - ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(TUSB_DIR_OUT); // only change TX Status, reserve other toggle bits - } else { btable_set_rx_bufsize(ch_id, BTABLE_BUF_RX, edpt->max_packet_size); - ch_change_status(&ch_reg, TUSB_DIR_IN, EP_STAT_VALID); - ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(TUSB_DIR_IN); // will change RX Status, reserved other toggle bits } - ch_write(ch_id, ch_reg, true); - - return true; -} - -//--------------------------------------------------------------------+ -// PMA read/write -//--------------------------------------------------------------------+ - -// Write to packet memory area (PMA) from user memory -static bool hcd_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t nbytes) { - if (nbytes == 0) return true; - uint32_t n_write = nbytes / FSDEV_BUS_SIZE; - - fsdev_pma_buf_t *pma_buf = PMA_BUF_AT(dst); - const uint8_t *src8 = src; - - while (n_write--) { - pma_buf->value = fsdevbus_unaligned_read(src8); - src8 += FSDEV_BUS_SIZE; - pma_buf++; + if (edpt->low_speed == 1) { + ch_reg |= USB_CHEP_LSEP; + } else { + ch_reg &= ~USB_CHEP_LSEP; } - // Handle odd bytes - uint16_t odd = nbytes & (FSDEV_BUS_SIZE - 1); - if (odd) { - fsdev_bus_t temp = 0; - for (uint16_t i = 0; i < odd; i++) { - temp |= *src8++ << (i * 8); - } - pma_buf->value = temp; + if (tu_edpt_number(edpt->ep_addr) == 0) { + edpt->pid = 1; } - return true; -} - -// Read from packet memory area (PMA) to user memory -static bool hcd_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t nbytes) { - if (nbytes == 0) return true; - uint32_t n_read = nbytes / FSDEV_BUS_SIZE; - - fsdev_pma_buf_t *pma_buf = PMA_BUF_AT(src); - uint8_t *dst8 = (uint8_t *)dst; - - while (n_read--) { - fsdevbus_unaligned_write(dst8, (fsdev_bus_t) pma_buf->value); - dst8 += FSDEV_BUS_SIZE; - pma_buf++; + if (edpt->next_setup) { + // Setup packet uses IN token + edpt->next_setup = false; + ch_reg |= USB_EP_SETUP; + edpt->pid = 0; } - // Handle odd bytes - uint16_t odd = nbytes & (FSDEV_BUS_SIZE - 1); - if (odd) { - fsdev_bus_t temp = pma_buf->value; - while (odd--) { - *dst8++ = (uint8_t)(temp & 0xfful); - temp >>= 8; - } - } + ch_change_status(&ch_reg, dir, EP_STAT_VALID); + ch_change_dtog(&ch_reg, dir, edpt->pid); + ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(dir) | CH_DTOG_MASK(dir); + ch_write(ch_id, ch_reg, true); return true; } diff --git a/tools/iar_template.ipcf b/tools/iar_template.ipcf index 2581a4702..caddda826 100644 --- a/tools/iar_template.ipcf +++ b/tools/iar_template.ipcf @@ -217,7 +217,9 @@ $TUSB_DIR$/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c - $TUSB_DIR$/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.h + $TUSB_DIR$/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c + $TUSB_DIR$/src/portable/st/stm32_fsdev/fsdev_common.c + $TUSB_DIR$/src/portable/st/stm32_fsdev/fsdev_common.h $TUSB_DIR$/src/portable/st/typec/typec_stm32.c -- cgit v1.3.1 From a445e8c3b31629f2d14b3380c15bceb667d546b6 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Tue, 25 Nov 2025 23:02:17 +0100 Subject: hcd/fsdev: more refactor Signed-off-by: HiFiPhile --- src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c | 123 +++++++++++++------------- 1 file changed, 61 insertions(+), 62 deletions(-) (limited to 'src/portable') diff --git a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c index b3c08ba23..2d05b2633 100644 --- a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c @@ -89,8 +89,7 @@ typedef struct { uint8_t ep_type; uint8_t allocated[2]; uint8_t retry[2]; - uint8_t result; -} hcd_xfer_t; +} hcd_channel_t; // Root hub port state static struct { @@ -98,7 +97,7 @@ static struct { } _hcd_port; typedef struct { - hcd_xfer_t xfer[FSDEV_EP_COUNT]; + hcd_channel_t channel[FSDEV_EP_COUNT]; hcd_endpoint_t edpt[CFG_TUH_FSDEV_ENDPOINT_MAX]; } hcd_data_t; @@ -129,8 +128,8 @@ static inline void endpoint_dealloc(hcd_endpoint_t* edpt) { edpt->allocated = 0; } -static inline void channel_dealloc(hcd_xfer_t* xfer, tusb_dir_t dir) { - xfer->allocated[dir] = 0; +static inline void channel_dealloc(hcd_channel_t* ch, tusb_dir_t dir) { + ch->allocated[dir] = 0; } // Write channel state in specified direction @@ -241,40 +240,40 @@ static void ch_handle_ack(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) { if (ep_id == TUSB_INDEX_INVALID_8) return; hcd_endpoint_t* edpt = &_hcd_data.edpt[ep_id]; - hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; + hcd_channel_t* channel = &_hcd_data.channel[ch_id]; if (dir == TUSB_DIR_OUT) { // OUT/TX direction - if (edpt->buflen != xfer->queued_len[TUSB_DIR_OUT]) { + if (edpt->buflen != channel->queued_len[TUSB_DIR_OUT]) { // More data to send - uint16_t const len = tu_min16(edpt->buflen - xfer->queued_len[TUSB_DIR_OUT], edpt->max_packet_size); + uint16_t const len = tu_min16(edpt->buflen - channel->queued_len[TUSB_DIR_OUT], edpt->max_packet_size); uint16_t pma_addr = (uint16_t) btable_get_addr(ch_id, BTABLE_BUF_TX); - fsdev_write_packet_memory(pma_addr, &(edpt->buffer[xfer->queued_len[TUSB_DIR_OUT]]), len); + fsdev_write_packet_memory(pma_addr, &(edpt->buffer[channel->queued_len[TUSB_DIR_OUT]]), len); btable_set_count(ch_id, BTABLE_BUF_TX, len); - xfer->queued_len[TUSB_DIR_OUT] += len; + channel->queued_len[TUSB_DIR_OUT] += len; channel_write_status(ch_id, ch_reg, TUSB_DIR_OUT, EP_STAT_VALID, false); } else { // Transfer complete - channel_dealloc(xfer, TUSB_DIR_OUT); + channel_dealloc(channel, TUSB_DIR_OUT); edpt->pid = (ch_reg & USB_CHEP_DTOG_TX) ? 1 : 0; - hcd_event_xfer_complete(daddr, ep_num, xfer->queued_len[TUSB_DIR_OUT], XFER_RESULT_SUCCESS, true); + hcd_event_xfer_complete(daddr, ep_num, channel->queued_len[TUSB_DIR_OUT], XFER_RESULT_SUCCESS, true); } } else { // IN/RX direction uint16_t const rx_count = btable_get_count(ch_id, BTABLE_BUF_RX); uint16_t pma_addr = (uint16_t) btable_get_addr(ch_id, BTABLE_BUF_RX); - fsdev_read_packet_memory(edpt->buffer + xfer->queued_len[TUSB_DIR_IN], pma_addr, rx_count); - xfer->queued_len[TUSB_DIR_IN] += rx_count; + fsdev_read_packet_memory(edpt->buffer + channel->queued_len[TUSB_DIR_IN], pma_addr, rx_count); + channel->queued_len[TUSB_DIR_IN] += rx_count; - if ((rx_count < edpt->max_packet_size) || (xfer->queued_len[TUSB_DIR_IN] >= edpt->buflen)) { + if ((rx_count < edpt->max_packet_size) || (channel->queued_len[TUSB_DIR_IN] >= edpt->buflen)) { // Transfer complete (short packet or all bytes received) - channel_dealloc(xfer, TUSB_DIR_IN); + channel_dealloc(channel, TUSB_DIR_IN); edpt->pid = (ch_reg & USB_CHEP_DTOG_RX) ? 1 : 0; - hcd_event_xfer_complete(daddr, ep_num | TUSB_DIR_IN_MASK, xfer->queued_len[TUSB_DIR_IN], XFER_RESULT_SUCCESS, true); + hcd_event_xfer_complete(daddr, ep_num | TUSB_DIR_IN_MASK, channel->queued_len[TUSB_DIR_IN], XFER_RESULT_SUCCESS, true); } else { // More data expected - uint16_t const cnt = tu_min16(edpt->buflen - xfer->queued_len[TUSB_DIR_IN], edpt->max_packet_size); + uint16_t const cnt = tu_min16(edpt->buflen - channel->queued_len[TUSB_DIR_IN], edpt->max_packet_size); btable_set_rx_bufsize(ch_id, BTABLE_BUF_RX, cnt); channel_write_status(ch_id, ch_reg, TUSB_DIR_IN, EP_STAT_VALID, false); } @@ -302,13 +301,13 @@ static void ch_handle_stall(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) { uint8_t const ep_num = ch_reg & USB_EPADDR_FIELD; uint8_t const daddr = (ch_reg & USB_CHEP_DEVADDR_Msk) >> USB_CHEP_DEVADDR_Pos; - hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; - channel_dealloc(xfer, dir); + hcd_channel_t* channel = &_hcd_data.channel[ch_id]; + channel_dealloc(channel, dir); channel_write_status(ch_id, ch_reg, dir, EP_STAT_DISABLED, false); hcd_event_xfer_complete(daddr, ep_num | (dir == TUSB_DIR_IN ? TUSB_DIR_IN_MASK : 0), - xfer->queued_len[dir], XFER_RESULT_STALLED, true); + channel->queued_len[dir], XFER_RESULT_STALLED, true); } // Handle error response @@ -319,21 +318,21 @@ static void ch_handle_error(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) { uint8_t ep_id = endpoint_find(daddr, ep_num | (dir == TUSB_DIR_IN ? TUSB_DIR_IN_MASK : 0)); if (ep_id == TUSB_INDEX_INVALID_8) return; - hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; + hcd_channel_t* channel = &_hcd_data.channel[ch_id]; ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(dir); ch_reg &= ~(dir == TUSB_DIR_OUT ? USB_CH_ERRTX : USB_CH_ERRRX); - if (xfer->retry[dir] < HCD_XFER_ERROR_MAX) { + if (channel->retry[dir] < HCD_XFER_ERROR_MAX) { // Retry - xfer->retry[dir]++; + channel->retry[dir]++; ch_change_status(&ch_reg, dir, EP_STAT_VALID); } else { // Failed after retries - channel_dealloc(xfer, dir); + channel_dealloc(channel, dir); ch_change_status(&ch_reg, dir, EP_STAT_DISABLED); hcd_event_xfer_complete(daddr, ep_num | (dir == TUSB_DIR_IN ? TUSB_DIR_IN_MASK : 0), - xfer->queued_len[dir], XFER_RESULT_FAILED, true); + channel->queued_len[dir], XFER_RESULT_FAILED, true); } ch_write(ch_id, ch_reg, false); } @@ -341,8 +340,8 @@ static void ch_handle_error(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) { // Handle CTR interrupt for the TX/OUT direction static void handle_ctr_tx(uint32_t ch_id) { uint32_t ch_reg = ch_read(ch_id) | USB_EP_CTR_TX | USB_EP_CTR_RX; - hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; - TU_VERIFY(xfer->allocated[TUSB_DIR_OUT] == 1,); + hcd_channel_t* channel = &_hcd_data.channel[ch_id]; + TU_VERIFY(channel->allocated[TUSB_DIR_OUT] == 1,); if ((ch_reg & USB_CH_ERRTX) == 0U) { // No error @@ -361,8 +360,8 @@ static void handle_ctr_tx(uint32_t ch_id) { // Handle CTR interrupt for the RX/IN direction static void handle_ctr_rx(uint32_t ch_id) { uint32_t ch_reg = ch_read(ch_id) | USB_EP_CTR_TX | USB_EP_CTR_RX; - hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; - TU_VERIFY(xfer->allocated[TUSB_DIR_IN] == 1,); + hcd_channel_t* channel = &_hcd_data.channel[ch_id]; + TU_VERIFY(channel->allocated[TUSB_DIR_IN] == 1,); if ((ch_reg & USB_CH_ERRRX) == 0U) { // No error @@ -579,12 +578,12 @@ bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { tusb_dir_t const dir = tu_edpt_dir(ep_addr); for (uint8_t i = 0; i < FSDEV_EP_COUNT; i++) { - hcd_xfer_t* xfer = &_hcd_data.xfer[i]; + hcd_channel_t* channel = &_hcd_data.channel[i]; - if (xfer->allocated[dir] == 1 && - xfer->dev_addr == dev_addr && - xfer->ep_num == tu_edpt_number(ep_addr)) { - channel_dealloc(xfer, dir); + if (channel->allocated[dir] == 1 && + channel->dev_addr == dev_addr && + channel->ep_num == tu_edpt_number(ep_addr)) { + channel_dealloc(channel, dir); uint32_t ch_reg = ch_read(i) | USB_EP_CTR_TX | USB_EP_CTR_RX; channel_write_status(i, ch_reg, dir, EP_STAT_DISABLED, true); } @@ -654,14 +653,14 @@ static void edpoint_close(uint8_t ep_id) { // disable active channel belong to this endpoint for (uint8_t i = 0; i < FSDEV_EP_COUNT; i++) { - hcd_xfer_t* xfer = &_hcd_data.xfer[i]; + hcd_channel_t* channel = &_hcd_data.channel[i]; uint32_t ch_reg = ch_read(i) | USB_EP_CTR_TX | USB_EP_CTR_RX; - if (xfer->allocated[TUSB_DIR_OUT] == 1 && xfer->edpt[TUSB_DIR_OUT] == edpt) { - channel_dealloc(xfer, TUSB_DIR_OUT); + if (channel->allocated[TUSB_DIR_OUT] == 1 && channel->edpt[TUSB_DIR_OUT] == edpt) { + channel_dealloc(channel, TUSB_DIR_OUT); channel_write_status(i, ch_reg, TUSB_DIR_OUT, EP_STAT_DISABLED, true); } - if (xfer->allocated[TUSB_DIR_IN] == 1 && xfer->edpt[TUSB_DIR_IN] == edpt) { - channel_dealloc(xfer, TUSB_DIR_IN); + if (channel->allocated[TUSB_DIR_IN] == 1 && channel->edpt[TUSB_DIR_IN] == edpt) { + channel_dealloc(channel, TUSB_DIR_IN); channel_write_status(i, ch_reg, TUSB_DIR_IN, EP_STAT_DISABLED, true); } } @@ -689,27 +688,27 @@ static uint8_t channel_alloc(uint8_t dev_addr, uint8_t ep_addr, uint8_t ep_type) // Find channel allocate for same ep_num but other direction tusb_dir_t const other_dir = (dir == TUSB_DIR_IN) ? TUSB_DIR_OUT : TUSB_DIR_IN; for (uint8_t i = 0; i < FSDEV_EP_COUNT; i++) { - if (_hcd_data.xfer[i].allocated[dir] == 0 && - _hcd_data.xfer[i].allocated[other_dir] == 1 && - _hcd_data.xfer[i].dev_addr == dev_addr && - _hcd_data.xfer[i].ep_num == ep_num && - _hcd_data.xfer[i].ep_type == ep_type) { - _hcd_data.xfer[i].allocated[dir] = 1; - _hcd_data.xfer[i].queued_len[dir] = 0; - _hcd_data.xfer[i].retry[dir] = 0; + if (_hcd_data.channel[i].allocated[dir] == 0 && + _hcd_data.channel[i].allocated[other_dir] == 1 && + _hcd_data.channel[i].dev_addr == dev_addr && + _hcd_data.channel[i].ep_num == ep_num && + _hcd_data.channel[i].ep_type == ep_type) { + _hcd_data.channel[i].allocated[dir] = 1; + _hcd_data.channel[i].queued_len[dir] = 0; + _hcd_data.channel[i].retry[dir] = 0; return i; } } // Find free channel for (uint8_t i = 0; i < FSDEV_EP_COUNT; i++) { - if (_hcd_data.xfer[i].allocated[0] == 0 && _hcd_data.xfer[i].allocated[1] == 0) { - _hcd_data.xfer[i].dev_addr = dev_addr; - _hcd_data.xfer[i].ep_num = ep_num; - _hcd_data.xfer[i].ep_type = ep_type; - _hcd_data.xfer[i].allocated[dir] = 1; - _hcd_data.xfer[i].queued_len[dir] = 0; - _hcd_data.xfer[i].retry[dir] = 0; + if (_hcd_data.channel[i].allocated[0] == 0 && _hcd_data.channel[i].allocated[1] == 0) { + _hcd_data.channel[i].dev_addr = dev_addr; + _hcd_data.channel[i].ep_num = ep_num; + _hcd_data.channel[i].ep_type = ep_type; + _hcd_data.channel[i].allocated[dir] = 1; + _hcd_data.channel[i].queued_len[dir] = 0; + _hcd_data.channel[i].retry[dir] = 0; return i; } } @@ -726,15 +725,15 @@ static bool edpt_xfer_kickoff(uint8_t ep_id) { tusb_dir_t const dir = tu_edpt_dir(edpt->ep_addr); - hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; - xfer->edpt[dir] = edpt; + hcd_channel_t* channel = &_hcd_data.channel[ch_id]; + channel->edpt[dir] = edpt; return channel_xfer_start(ch_id, dir); } static bool channel_xfer_start(uint8_t ch_id, tusb_dir_t dir) { - hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; - hcd_endpoint_t* edpt = xfer->edpt[dir]; + hcd_channel_t* channel = &_hcd_data.channel[ch_id]; + hcd_endpoint_t* edpt = channel->edpt[dir]; uint32_t ch_reg = ch_read(ch_id) & ~USB_EPREG_MASK; ch_reg |= tu_edpt_number(edpt->ep_addr) | edpt->dev_addr << USB_CHEP_DEVADDR_Pos | @@ -763,12 +762,12 @@ static bool channel_xfer_start(uint8_t ch_id, tusb_dir_t dir) { btable_set_addr(ch_id, dir == TUSB_DIR_OUT ? BTABLE_BUF_TX : BTABLE_BUF_RX, pma_addr); if (dir == TUSB_DIR_OUT) { - uint16_t const len = tu_min16(edpt->buflen - xfer->queued_len[TUSB_DIR_OUT], edpt->max_packet_size); + uint16_t const len = tu_min16(edpt->buflen - channel->queued_len[TUSB_DIR_OUT], edpt->max_packet_size); - fsdev_write_packet_memory(pma_addr, &(edpt->buffer[xfer->queued_len[TUSB_DIR_OUT]]), len); + fsdev_write_packet_memory(pma_addr, &(edpt->buffer[channel->queued_len[TUSB_DIR_OUT]]), len); btable_set_count(ch_id, BTABLE_BUF_TX, len); - xfer->queued_len[TUSB_DIR_OUT] += len; + channel->queued_len[TUSB_DIR_OUT] += len; } else { btable_set_rx_bufsize(ch_id, BTABLE_BUF_RX, edpt->max_packet_size); } -- cgit v1.3.1 From c925277e24e6743b311199d87461befe8b590187 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 26 Nov 2025 15:26:42 +0700 Subject: change tu_fifo_buffer_info_t layout --- src/class/cdc/cdc_device.c | 14 ++--- src/common/tusb_fifo.c | 58 +++++++++--------- src/common/tusb_fifo.h | 9 ++- src/common/tusb_mcu.h | 1 + src/portable/chipidea/ci_hs/dcd_ci_hs.c | 10 +-- src/portable/mentor/musb/dcd_musb.c | 8 +-- src/portable/microchip/samx7x/dcd_samx7x.c | 16 ++--- src/portable/renesas/rusb2/dcd_rusb2.c | 16 ++--- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 20 +++--- src/portable/sunxi/dcd_sunxi_musb.c | 8 +-- test/unit-test/test/test_fifo.c | 88 +++++++++++++-------------- 11 files changed, 124 insertions(+), 124 deletions(-) (limited to 'src/portable') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 2ab592bca..fbca5b574 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -501,10 +501,10 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ // find backward uint8_t *ptr; - if (buf_info.len_wrap > 0) { - ptr = buf_info.ptr_wrap + buf_info.len_wrap - 1; // last byte of wrap buffer - } else if (buf_info.len_lin > 0) { - ptr = buf_info.ptr_lin + buf_info.len_lin - 1; // last byte of linear buffer + if (buf_info.wrapped.len > 0) { + ptr = buf_info.wrapped.ptr + buf_info.wrapped.len - 1; // last byte of wrap buffer + } else if (buf_info.linear.len > 0) { + ptr = buf_info.linear.ptr + buf_info.linear.len - 1; // last byte of linear buffer } else { ptr = NULL; // no data } @@ -516,9 +516,9 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ break; // only invoke once per transfer, even if multiple wanted chars are present } - if (ptr == buf_info.ptr_wrap) { - ptr = buf_info.ptr_lin + buf_info.len_lin - 1; // last byte of linear buffer - } else if (ptr == buf_info.ptr_lin) { + if (ptr == buf_info.wrapped.ptr) { + ptr = buf_info.linear.ptr + buf_info.linear.len - 1; // last byte of linear buffer + } else if (ptr == buf_info.linear.ptr) { break; // reached the beginning } else { ptr--; diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 0c44cbd76..6bc384be3 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -82,8 +82,8 @@ bool tu_fifo_config(tu_fifo_t *f, void *buffer, uint16_t depth, uint16_t item_si //--------------------------------------------------------------------+ // Pull & Push +// copy data to/from fifo without updating read/write pointers //--------------------------------------------------------------------+ - #ifdef CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_RW32 // Intended to be used to read from hardware USB FIFO in e.g. STM32 where all data is read from a constant address // Code adapted from dcd_synopsys.c @@ -216,7 +216,7 @@ static void _ff_push_n(tu_fifo_t *f, const void *app_buf, uint16_t n, uint16_t w } // get one item from fifo WITHOUT updating read pointer -TU_ATTR_ALWAYS_INLINE static inline void _ff_pull(tu_fifo_t *f, void *buf, uint16_t ptr) { +TU_ATTR_ALWAYS_INLINE static inline void _ff_pull(const tu_fifo_t *f, void *buf, uint16_t ptr) { memcpy(buf, f->buffer + (ptr * f->item_size), f->item_size); } @@ -326,7 +326,7 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t idx2ptr(uint16_t depth, uint16_t id // Works on local copies of w // When an overwritable fifo is overflowed, rd_idx will be re-index so that it forms a full fifo -TU_ATTR_ALWAYS_INLINE static inline uint16_t ff_correct_read_index(tu_fifo_t *f, uint16_t wr_idx) { +TU_ATTR_ALWAYS_INLINE static inline uint16_t correct_read_index(tu_fifo_t *f, uint16_t wr_idx) { uint16_t rd_idx; if (wr_idx >= f->depth) { rd_idx = wr_idx - f->depth; @@ -349,7 +349,7 @@ static bool ff_peek_local(tu_fifo_t *f, void *p_buffer, uint16_t wr_idx, uint16_ // Correct read index if overflow if (ovf_count > f->depth) { ff_lock(f->mutex_rd); - rd_idx = ff_correct_read_index(f, wr_idx); + rd_idx = correct_read_index(f, wr_idx); ff_unlock(f->mutex_rd); } @@ -373,7 +373,7 @@ uint16_t tu_fifo_peek_n_access(tu_fifo_t *f, void *p_buffer, uint16_t n, uint16_ // Check overflow and correct if required if (cnt > f->depth) { - rd_idx = ff_correct_read_index(f, wr_idx); + rd_idx = correct_read_index(f, wr_idx); cnt = f->depth; } @@ -477,7 +477,7 @@ uint16_t tu_fifo_read_n_access(tu_fifo_t *f, void *buffer, uint16_t n, tu_fifo_a // Only use in case tu_fifo_overflow() returned true! void tu_fifo_correct_read_pointer(tu_fifo_t *f) { ff_lock(f->mutex_rd); - ff_correct_read_index(f, f->wr_idx); + correct_read_index(f, f->wr_idx); ff_unlock(f->mutex_rd); } @@ -696,7 +696,7 @@ void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info) { // Check overflow and correct if required - may happen in case a DMA wrote too fast if (cnt > f->depth) { ff_lock(f->mutex_rd); - rd_idx = ff_correct_read_index(f, wr_idx); + rd_idx = correct_read_index(f, wr_idx); ff_unlock(f->mutex_rd); cnt = f->depth; @@ -704,10 +704,10 @@ void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info) { // Check if fifo is empty if (cnt == 0) { - info->len_lin = 0; - info->len_wrap = 0; - info->ptr_lin = NULL; - info->ptr_wrap = NULL; + info->linear.len = 0; + info->wrapped.len = 0; + info->linear.ptr = NULL; + info->wrapped.ptr = NULL; return; } @@ -716,20 +716,20 @@ void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info) { uint16_t rd_ptr = idx2ptr(f->depth, rd_idx); // Copy pointer to buffer to start reading from - info->ptr_lin = &f->buffer[rd_ptr]; + info->linear.ptr = &f->buffer[rd_ptr]; // Check if there is a wrap around necessary if (wr_ptr > rd_ptr) { // Non wrapping case - info->len_lin = cnt; + info->linear.len = cnt; - info->len_wrap = 0; - info->ptr_wrap = NULL; + info->wrapped.len = 0; + info->wrapped.ptr = NULL; } else { - info->len_lin = f->depth - rd_ptr; // Also the case if FIFO was full + info->linear.len = f->depth - rd_ptr; // Also the case if FIFO was full - info->len_wrap = cnt - info->len_lin; - info->ptr_wrap = f->buffer; + info->wrapped.len = cnt - info->linear.len; + info->wrapped.ptr = f->buffer; } } @@ -754,10 +754,10 @@ void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info) { uint16_t remain = tu_ff_remaining_local(f->depth, wr_idx, rd_idx); if (remain == 0) { - info->len_lin = 0; - info->len_wrap = 0; - info->ptr_lin = NULL; - info->ptr_wrap = NULL; + info->linear.len = 0; + info->wrapped.len = 0; + info->linear.ptr = NULL; + info->wrapped.ptr = NULL; return; } @@ -766,16 +766,16 @@ void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info) { uint16_t rd_ptr = idx2ptr(f->depth, rd_idx); // Copy pointer to buffer to start writing to - info->ptr_lin = &f->buffer[wr_ptr]; + info->linear.ptr = &f->buffer[wr_ptr]; if (wr_ptr < rd_ptr) { // Non wrapping case - info->len_lin = rd_ptr - wr_ptr; - info->len_wrap = 0; - info->ptr_wrap = NULL; + info->linear.len = rd_ptr - wr_ptr; + info->wrapped.len = 0; + info->wrapped.ptr = NULL; } else { - info->len_lin = f->depth - wr_ptr; - info->len_wrap = remain - info->len_lin; // Remaining length - n already was limited to remain or FIFO depth - info->ptr_wrap = f->buffer; // Always start of buffer + info->linear.len = f->depth - wr_ptr; + info->wrapped.len = remain - info->linear.len; // Remaining length - n already was limited to remain or FIFO depth + info->wrapped.ptr = f->buffer; // Always start of buffer } } diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 005282824..d40fc4401 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -128,10 +128,10 @@ typedef struct { } tu_fifo_t; typedef struct { - uint16_t len_lin; ///< linear length in item size - uint16_t len_wrap; ///< wrapped length in item size - uint8_t *ptr_lin; ///< linear part start pointer - uint8_t *ptr_wrap; ///< wrapped part start pointer + struct { + uint16_t len; // length + uint8_t *ptr; // buffer pointer + } linear, wrapped; } tu_fifo_buffer_info_t; #define TU_FIFO_INIT(_buffer, _depth, _type, _overwritable) \ @@ -198,7 +198,6 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_write_n(tu_fifo_t *f, const return tu_fifo_write_n_access(f, data, n, TU_FIFO_INC_ADDR_RW8); } - //--------------------------------------------------------------------+ // Index API //--------------------------------------------------------------------+ diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index 34977378c..1e773bf96 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -523,6 +523,7 @@ //--------------------------------------------------------------------+ #elif TU_CHECK_MCU(OPT_MCU_F1C100S) #define TUP_DCD_ENDPOINT_MAX 4 + #define TUP_DCD_EDPT_CLOSE_API //--------------------------------------------------------------------+ // WCH diff --git a/src/portable/chipidea/ci_hs/dcd_ci_hs.c b/src/portable/chipidea/ci_hs/dcd_ci_hs.c index c6d405e98..4a5e5c91f 100644 --- a/src/portable/chipidea/ci_hs/dcd_ci_hs.c +++ b/src/portable/chipidea/ci_hs/dcd_ci_hs.c @@ -545,19 +545,19 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_ tu_fifo_get_write_info(ff, &fifo_info); } - if ( fifo_info.len_lin >= total_bytes ) + if ( fifo_info.linear.len >= total_bytes ) { // Linear length is enough for this transfer - qtd_init(p_qtd, fifo_info.ptr_lin, total_bytes); + qtd_init(p_qtd, fifo_info.linear.ptr, total_bytes); } else { // linear part is not enough // prepare TD up to linear length - qtd_init(p_qtd, fifo_info.ptr_lin, fifo_info.len_lin); + qtd_init(p_qtd, fifo_info.linear.ptr, fifo_info.linear.len); - if ( !tu_offset4k((uint32_t) fifo_info.ptr_wrap) && !tu_offset4k(tu_fifo_depth(ff)) ) + if ( !tu_offset4k((uint32_t) fifo_info.wrapped.ptr) && !tu_offset4k(tu_fifo_depth(ff)) ) { // If buffer is aligned to 4K & buffer size is multiple of 4K // We can make use of buffer page array to also combine the linear + wrapped length @@ -568,7 +568,7 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_ // pick up buffer array where linear ends if (p_qtd->buffer[i] == 0) { - p_qtd->buffer[i] = (uint32_t) fifo_info.ptr_wrap + 4096 * page; + p_qtd->buffer[i] = (uint32_t) fifo_info.wrapped.ptr + 4096 * page; page++; } } diff --git a/src/portable/mentor/musb/dcd_musb.c b/src/portable/mentor/musb/dcd_musb.c index 1e4ec0015..ad20d64bd 100644 --- a/src/portable/mentor/musb/dcd_musb.c +++ b/src/portable/mentor/musb/dcd_musb.c @@ -221,12 +221,12 @@ static void pipe_read_write_packet_ff(tu_fifo_t *f, volatile void *fifo, unsigne tu_fifo_buffer_info_t info; ops[dir].tu_fifo_get_info(f, &info); unsigned total_len = len; - len = TU_MIN(total_len, info.len_lin); - ops[dir].pipe_read_write(info.ptr_lin, fifo, len); + len = TU_MIN(total_len, info.linear.len); + ops[dir].pipe_read_write(info.linear.ptr, fifo, len); unsigned rem = total_len - len; if (rem) { - len = TU_MIN(rem, info.len_wrap); - ops[dir].pipe_read_write(info.ptr_wrap, fifo, len); + len = TU_MIN(rem, info.wrapped.len); + ops[dir].pipe_read_write(info.wrapped.ptr, fifo, len); rem -= len; } ops[dir].tu_fifo_advance(f, total_len - rem); diff --git a/src/portable/microchip/samx7x/dcd_samx7x.c b/src/portable/microchip/samx7x/dcd_samx7x.c index 4d54f9057..b0a053c01 100644 --- a/src/portable/microchip/samx7x/dcd_samx7x.c +++ b/src/portable/microchip/samx7x/dcd_samx7x.c @@ -697,7 +697,7 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_ udd_dma_ctrl_wrap |= DEVDMACONTROL_END_TR_IT | DEVDMACONTROL_END_TR_EN; } else { tu_fifo_get_read_info(ff, &info); - if(info.len_wrap == 0) + if(info.wrapped.len == 0) { udd_dma_ctrl_lin |= DEVDMACONTROL_END_B_EN; } @@ -705,18 +705,18 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_ } // Clean invalidate cache of linear part - CleanInValidateCache((uint32_t*) tu_align((uint32_t) info.ptr_lin, 4), info.len_lin + 31); + CleanInValidateCache((uint32_t*) tu_align((uint32_t) info.linear.ptr, 4), info.linear.len + 31); - USB_REG->DEVDMA[epnum - 1].DEVDMAADDRESS = (uint32_t)info.ptr_lin; - if (info.len_wrap) + USB_REG->DEVDMA[epnum - 1].DEVDMAADDRESS = (uint32_t)info.linear.ptr; + if (info.wrapped.len) { // Clean invalidate cache of wrapped part - CleanInValidateCache((uint32_t*) tu_align((uint32_t) info.ptr_wrap, 4), info.len_wrap + 31); + CleanInValidateCache((uint32_t*) tu_align((uint32_t) info.wrapped.ptr, 4), info.wrapped.len + 31); dma_desc[epnum - 1].next_desc = 0; - dma_desc[epnum - 1].buff_addr = (uint32_t)info.ptr_wrap; + dma_desc[epnum - 1].buff_addr = (uint32_t)info.wrapped.ptr; dma_desc[epnum - 1].chnl_ctrl = - udd_dma_ctrl_wrap | (info.len_wrap << DEVDMACONTROL_BUFF_LENGTH_Pos); + udd_dma_ctrl_wrap | (info.wrapped.len << DEVDMACONTROL_BUFF_LENGTH_Pos); // Clean cache of wrapped DMA descriptor CleanInValidateCache((uint32_t*)&dma_desc[epnum - 1], sizeof(dma_desc_t)); @@ -725,7 +725,7 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_ } else { udd_dma_ctrl_lin |= DEVDMACONTROL_END_BUFFIT; } - udd_dma_ctrl_lin |= (info.len_lin << DEVDMACONTROL_BUFF_LENGTH_Pos); + udd_dma_ctrl_lin |= (info.linear.len << DEVDMACONTROL_BUFF_LENGTH_Pos); // Disable IRQs to have a short sequence // between read of EOT_STA and DMA enable uint32_t irq_state = __get_PRIMASK(); diff --git a/src/portable/renesas/rusb2/dcd_rusb2.c b/src/portable/renesas/rusb2/dcd_rusb2.c index 7caf5d68a..786b8d980 100644 --- a/src/portable/renesas/rusb2/dcd_rusb2.c +++ b/src/portable/renesas/rusb2/dcd_rusb2.c @@ -213,13 +213,13 @@ static void pipe_write_packet_ff(rusb2_reg_t * rusb, tu_fifo_t *f, volatile void tu_fifo_buffer_info_t info; tu_fifo_get_read_info(f, &info); - uint16_t count = tu_min16(total_len, info.len_lin); - pipe_write_packet(rusb, info.ptr_lin, fifo, count); + uint16_t count = tu_min16(total_len, info.linear.len); + pipe_write_packet(rusb, info.linear.ptr, fifo, count); uint16_t rem = total_len - count; if (rem) { - rem = tu_min16(rem, info.len_wrap); - pipe_write_packet(rusb, info.ptr_wrap, fifo, rem); + rem = tu_min16(rem, info.wrapped.len); + pipe_write_packet(rusb, info.wrapped.ptr, fifo, rem); count += rem; } @@ -231,13 +231,13 @@ static void pipe_read_packet_ff(rusb2_reg_t * rusb, tu_fifo_t *f, volatile void tu_fifo_buffer_info_t info; tu_fifo_get_write_info(f, &info); - uint16_t count = tu_min16(total_len, info.len_lin); - pipe_read_packet(rusb, info.ptr_lin, fifo, count); + uint16_t count = tu_min16(total_len, info.linear.len); + pipe_read_packet(rusb, info.linear.ptr, fifo, count); uint16_t rem = total_len - count; if (rem) { - rem = tu_min16(rem, info.len_wrap); - pipe_read_packet(rusb, info.ptr_wrap, fifo, rem); + rem = tu_min16(rem, info.wrapped.len); + pipe_read_packet(rusb, info.wrapped.ptr, fifo, rem); count += rem; } diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 6276f0f07..64046ce17 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -927,15 +927,15 @@ static bool dcd_write_packet_memory_ff(tu_fifo_t *ff, uint16_t dst, uint16_t wNB tu_fifo_buffer_info_t info; tu_fifo_get_read_info(ff, &info); - uint16_t cnt_lin = tu_min16(wNBytes, info.len_lin); - uint16_t cnt_wrap = tu_min16(wNBytes - cnt_lin, info.len_wrap); + uint16_t cnt_lin = tu_min16(wNBytes, info.linear.len); + uint16_t cnt_wrap = tu_min16(wNBytes - cnt_lin, info.wrapped.len); uint16_t const cnt_total = cnt_lin + cnt_wrap; // We want to read from the FIFO and write it into the PMA, if LIN part is ODD and has WRAPPED part, // last lin byte will be combined with wrapped part To ensure PMA is always access aligned uint16_t lin_even = cnt_lin & ~(FSDEV_BUS_SIZE - 1); uint16_t lin_odd = cnt_lin & (FSDEV_BUS_SIZE - 1); - uint8_t const *src8 = (uint8_t const*) info.ptr_lin; + uint8_t const *src8 = (uint8_t const*) info.linear.ptr; // write even linear part dcd_write_packet_memory(dst, src8, lin_even); @@ -943,7 +943,7 @@ static bool dcd_write_packet_memory_ff(tu_fifo_t *ff, uint16_t dst, uint16_t wNB src8 += lin_even; if (lin_odd == 0) { - src8 = (uint8_t const*) info.ptr_wrap; + src8 = (uint8_t const*) info.wrapped.ptr; } else { // Combine last linear bytes + first wrapped bytes to form fsdev bus width data fsdev_bus_t temp = 0; @@ -952,7 +952,7 @@ static bool dcd_write_packet_memory_ff(tu_fifo_t *ff, uint16_t dst, uint16_t wNB temp |= *src8++ << (i * 8); } - src8 = (uint8_t const*) info.ptr_wrap; + src8 = (uint8_t const*) info.wrapped.ptr; for(; i < FSDEV_BUS_SIZE && cnt_wrap > 0; i++, cnt_wrap--) { temp |= *src8++ << (i * 8); } @@ -977,8 +977,8 @@ static bool dcd_read_packet_memory_ff(tu_fifo_t *ff, uint16_t src, uint16_t wNBy tu_fifo_buffer_info_t info; tu_fifo_get_write_info(ff, &info); // We want to read from the FIFO - uint16_t cnt_lin = tu_min16(wNBytes, info.len_lin); - uint16_t cnt_wrap = tu_min16(wNBytes - cnt_lin, info.len_wrap); + uint16_t cnt_lin = tu_min16(wNBytes, info.linear.len); + uint16_t cnt_wrap = tu_min16(wNBytes - cnt_lin, info.wrapped.len); uint16_t cnt_total = cnt_lin + cnt_wrap; // We want to read from the FIFO and write it into the PMA, if LIN part is ODD and has WRAPPED part, @@ -986,7 +986,7 @@ static bool dcd_read_packet_memory_ff(tu_fifo_t *ff, uint16_t src, uint16_t wNBy uint16_t lin_even = cnt_lin & ~(FSDEV_BUS_SIZE - 1); uint16_t lin_odd = cnt_lin & (FSDEV_BUS_SIZE - 1); - uint8_t *dst8 = (uint8_t *) info.ptr_lin; + uint8_t *dst8 = (uint8_t *) info.linear.ptr; // read even linear part dcd_read_packet_memory(dst8, src, lin_even); @@ -994,7 +994,7 @@ static bool dcd_read_packet_memory_ff(tu_fifo_t *ff, uint16_t src, uint16_t wNBy src += lin_even; if (lin_odd == 0) { - dst8 = (uint8_t *) info.ptr_wrap; + dst8 = (uint8_t *) info.wrapped.ptr; } else { // Combine last linear bytes + first wrapped bytes to form fsdev bus width data fsdev_bus_t temp; @@ -1007,7 +1007,7 @@ static bool dcd_read_packet_memory_ff(tu_fifo_t *ff, uint16_t src, uint16_t wNBy temp >>= 8; } - dst8 = (uint8_t *) info.ptr_wrap; + dst8 = (uint8_t *) info.wrapped.ptr; for (; i < FSDEV_BUS_SIZE && cnt_wrap > 0; i++, cnt_wrap--) { *dst8++ = (uint8_t) (temp & 0xfful); temp >>= 8; diff --git a/src/portable/sunxi/dcd_sunxi_musb.c b/src/portable/sunxi/dcd_sunxi_musb.c index d43ea1dc3..b413121a5 100644 --- a/src/portable/sunxi/dcd_sunxi_musb.c +++ b/src/portable/sunxi/dcd_sunxi_musb.c @@ -535,12 +535,12 @@ static void pipe_read_write_packet_ff(tu_fifo_t *f, volatile void *fifo, unsigne tu_fifo_buffer_info_t info; ops[dir].tu_fifo_get_info(f, &info); unsigned total_len = len; - len = TU_MIN(total_len, info.len_lin); - ops[dir].pipe_read_write(info.ptr_lin, fifo, len); + len = TU_MIN(total_len, info.linear.len); + ops[dir].pipe_read_write(info.linear.ptr, fifo, len); unsigned rem = total_len - len; if (rem) { - len = TU_MIN(rem, info.len_wrap); - ops[dir].pipe_read_write(info.ptr_wrap, fifo, len); + len = TU_MIN(rem, info.wrapped.len); + ops[dir].pipe_read_write(info.wrapped.ptr, fifo, len); rem -= len; } ops[dir].tu_fifo_advance(f, total_len - rem); diff --git a/test/unit-test/test/test_fifo.c b/test/unit-test/test/test_fifo.c index d1049b81d..ac93e7e38 100644 --- a/test/unit-test/test/test_fifo.c +++ b/test/unit-test/test/test_fifo.c @@ -236,11 +236,11 @@ void test_get_read_info_when_no_wrap() { tu_fifo_get_read_info(ff, &info); - TEST_ASSERT_EQUAL(4, info.len_lin); - TEST_ASSERT_EQUAL(0, info.len_wrap); + TEST_ASSERT_EQUAL(4, info.linear.len); + TEST_ASSERT_EQUAL(0, info.wrapped.len); - TEST_ASSERT_EQUAL_PTR(ff->buffer + 2, info.ptr_lin); - TEST_ASSERT_NULL(info.ptr_wrap); + TEST_ASSERT_EQUAL_PTR(ff->buffer + 2, info.linear.ptr); + TEST_ASSERT_NULL(info.wrapped.ptr); } void test_get_read_info_when_wrapped() { @@ -262,11 +262,11 @@ void test_get_read_info_when_wrapped() { tu_fifo_get_read_info(ff, &info); - TEST_ASSERT_EQUAL(FIFO_SIZE - 6, info.len_lin); - TEST_ASSERT_EQUAL(2, info.len_wrap); + TEST_ASSERT_EQUAL(FIFO_SIZE - 6, info.linear.len); + TEST_ASSERT_EQUAL(2, info.wrapped.len); - TEST_ASSERT_EQUAL_PTR(ff->buffer + 6, info.ptr_lin); - TEST_ASSERT_EQUAL_PTR(ff->buffer, info.ptr_wrap); + TEST_ASSERT_EQUAL_PTR(ff->buffer + 6, info.linear.ptr); + TEST_ASSERT_EQUAL_PTR(ff->buffer, info.wrapped.ptr); } void test_get_write_info_when_no_wrap() { @@ -278,12 +278,12 @@ void test_get_write_info_when_no_wrap() { tu_fifo_get_write_info(ff, &info); - TEST_ASSERT_EQUAL(FIFO_SIZE - 2, info.len_lin); - TEST_ASSERT_EQUAL(0, info.len_wrap); + TEST_ASSERT_EQUAL(FIFO_SIZE - 2, info.linear.len); + TEST_ASSERT_EQUAL(0, info.wrapped.len); - TEST_ASSERT_EQUAL_PTR(ff->buffer + 2, info.ptr_lin); + TEST_ASSERT_EQUAL_PTR(ff->buffer + 2, info.linear.ptr); // application should check len instead of ptr. - // TEST_ASSERT_NULL(info.ptr_wrap); + // TEST_ASSERT_NULL(info.wrapped.ptr); } void test_get_write_info_when_wrapped() { @@ -300,11 +300,11 @@ void test_get_write_info_when_wrapped() { tu_fifo_get_write_info(ff, &info); - TEST_ASSERT_EQUAL(FIFO_SIZE - 6, info.len_lin); - TEST_ASSERT_EQUAL(2, info.len_wrap); + TEST_ASSERT_EQUAL(FIFO_SIZE - 6, info.linear.len); + TEST_ASSERT_EQUAL(2, info.wrapped.len); - TEST_ASSERT_EQUAL_PTR(ff->buffer + 6, info.ptr_lin); - TEST_ASSERT_EQUAL_PTR(ff->buffer, info.ptr_wrap); + TEST_ASSERT_EQUAL_PTR(ff->buffer + 6, info.linear.ptr); + TEST_ASSERT_EQUAL_PTR(ff->buffer, info.wrapped.ptr); } void test_empty(void) { @@ -314,21 +314,21 @@ void test_empty(void) { // read info tu_fifo_get_read_info(ff, &info); - TEST_ASSERT_EQUAL(0, info.len_lin); - TEST_ASSERT_EQUAL(0, info.len_wrap); + TEST_ASSERT_EQUAL(0, info.linear.len); + TEST_ASSERT_EQUAL(0, info.wrapped.len); - TEST_ASSERT_NULL(info.ptr_lin); - TEST_ASSERT_NULL(info.ptr_wrap); + TEST_ASSERT_NULL(info.linear.ptr); + TEST_ASSERT_NULL(info.wrapped.ptr); // write info tu_fifo_get_write_info(ff, &info); - TEST_ASSERT_EQUAL(FIFO_SIZE, info.len_lin); - TEST_ASSERT_EQUAL(0, info.len_wrap); + TEST_ASSERT_EQUAL(FIFO_SIZE, info.linear.len); + TEST_ASSERT_EQUAL(0, info.wrapped.len); - TEST_ASSERT_EQUAL_PTR(ff->buffer, info.ptr_lin); + TEST_ASSERT_EQUAL_PTR(ff->buffer, info.linear.ptr); // application should check len instead of ptr. - // TEST_ASSERT_NULL(info.ptr_wrap); + // TEST_ASSERT_NULL(info.wrapped.ptr); // write 1 then re-check empty tu_fifo_write(ff, &temp); @@ -347,12 +347,12 @@ void test_full(void) { // read info tu_fifo_get_read_info(ff, &info); - TEST_ASSERT_EQUAL(FIFO_SIZE, info.len_lin); - TEST_ASSERT_EQUAL(0, info.len_wrap); + TEST_ASSERT_EQUAL(FIFO_SIZE, info.linear.len); + TEST_ASSERT_EQUAL(0, info.wrapped.len); - TEST_ASSERT_EQUAL_PTR(ff->buffer, info.ptr_lin); + TEST_ASSERT_EQUAL_PTR(ff->buffer, info.linear.ptr); // skip this, application must check len instead of buffer - // TEST_ASSERT_NULL(info.ptr_wrap); + // TEST_ASSERT_NULL(info.wrapped.ptr); // write info } @@ -511,18 +511,18 @@ void test_get_read_info_advanced_cases(void) { ff->wr_idx = 20; ff->rd_idx = 2; tu_fifo_get_read_info(ff, &info); - TEST_ASSERT_EQUAL(18, info.len_lin); - TEST_ASSERT_EQUAL(0, info.len_wrap); - TEST_ASSERT_EQUAL_PTR(ff->buffer + 2, info.ptr_lin); - TEST_ASSERT_NULL(info.ptr_wrap); + TEST_ASSERT_EQUAL(18, info.linear.len); + TEST_ASSERT_EQUAL(0, info.wrapped.len); + TEST_ASSERT_EQUAL_PTR(ff->buffer + 2, info.linear.ptr); + TEST_ASSERT_NULL(info.wrapped.ptr); ff->wr_idx = 68; // ptr = 4 ff->rd_idx = 56; // ptr = 56 tu_fifo_get_read_info(ff, &info); - TEST_ASSERT_EQUAL(8, info.len_lin); - TEST_ASSERT_EQUAL(4, info.len_wrap); - TEST_ASSERT_EQUAL_PTR(ff->buffer + 56, info.ptr_lin); - TEST_ASSERT_EQUAL_PTR(ff->buffer, info.ptr_wrap); + TEST_ASSERT_EQUAL(8, info.linear.len); + TEST_ASSERT_EQUAL(4, info.wrapped.len); + TEST_ASSERT_EQUAL_PTR(ff->buffer + 56, info.linear.ptr); + TEST_ASSERT_EQUAL_PTR(ff->buffer, info.wrapped.ptr); } void test_get_write_info_advanced_cases(void) { @@ -531,18 +531,18 @@ void test_get_write_info_advanced_cases(void) { ff->wr_idx = 10; ff->rd_idx = 104; // ptr = 40 tu_fifo_get_write_info(ff, &info); - TEST_ASSERT_EQUAL(30, info.len_lin); - TEST_ASSERT_EQUAL(0, info.len_wrap); - TEST_ASSERT_EQUAL_PTR(ff->buffer + 10, info.ptr_lin); - TEST_ASSERT_NULL(info.ptr_wrap); + TEST_ASSERT_EQUAL(30, info.linear.len); + TEST_ASSERT_EQUAL(0, info.wrapped.len); + TEST_ASSERT_EQUAL_PTR(ff->buffer + 10, info.linear.ptr); + TEST_ASSERT_NULL(info.wrapped.ptr); ff->wr_idx = 60; ff->rd_idx = 20; tu_fifo_get_write_info(ff, &info); - TEST_ASSERT_EQUAL(4, info.len_lin); - TEST_ASSERT_EQUAL(20, info.len_wrap); - TEST_ASSERT_EQUAL_PTR(ff->buffer + 60, info.ptr_lin); - TEST_ASSERT_EQUAL_PTR(ff->buffer, info.ptr_wrap); + TEST_ASSERT_EQUAL(4, info.linear.len); + TEST_ASSERT_EQUAL(20, info.wrapped.len); + TEST_ASSERT_EQUAL_PTR(ff->buffer + 60, info.linear.ptr); + TEST_ASSERT_EQUAL_PTR(ff->buffer, info.wrapped.ptr); } void test_correct_read_pointer_cases(void) { -- cgit v1.3.1 From f63b67211b808fa370c51f3ab8eb201b64d3d1d2 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 26 Nov 2025 16:15:12 +0700 Subject: dwc2 stm32 check if dcache enabled before calling SCB DCache function --- src/portable/synopsys/dwc2/dwc2_stm32.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/portable') diff --git a/src/portable/synopsys/dwc2/dwc2_stm32.h b/src/portable/synopsys/dwc2/dwc2_stm32.h index 9da8de41f..516eb021b 100644 --- a/src/portable/synopsys/dwc2/dwc2_stm32.h +++ b/src/portable/synopsys/dwc2/dwc2_stm32.h @@ -337,6 +337,9 @@ TU_ATTR_ALWAYS_INLINE static inline uint32_t round_up_to_cache_line_size(uint32_ } TU_ATTR_ALWAYS_INLINE static inline bool is_cache_mem(uintptr_t addr) { + if (0 == (SCB->CCR & SCB_CCR_DC_Msk)) { + return false; // D-Cache is disabled + } for (unsigned int i = 0; i < TU_ARRAY_SIZE(uncached_regions); i++) { if (uncached_regions[i].start <= addr && addr <= uncached_regions[i].end) { return false; } } -- cgit v1.3.1 From 270e1492764959c278f1b154b8e42aef4dcd98d8 Mon Sep 17 00:00:00 2001 From: Zixun LI Date: Wed, 26 Nov 2025 14:25:06 +0100 Subject: reorganize ctr_rx workaround Signed-off-by: Zixun LI --- src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c | 81 +++++++++++++++++---------- 1 file changed, 50 insertions(+), 31 deletions(-) (limited to 'src/portable') diff --git a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c index 2d05b2633..362d7df7b 100644 --- a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c @@ -139,6 +139,53 @@ static inline void channel_write_status(uint8_t ch_id, uint32_t ch_reg, tusb_dir ch_write(ch_id, ch_reg, need_exclusive); } +static inline uint16_t channel_get_rx_count(uint8_t ch_id) { + /* https://www.st.com/resource/en/errata_sheet/es0561-stm32h503cbebkbrb-device-errata-stmicroelectronics.pdf + * https://www.st.com/resource/en/errata_sheet/es0587-stm32u535xx-and-stm32u545xx-device-errata-stmicroelectronics.pdf + * From H503/U535 errata: Buffer description table update completes after CTR interrupt triggers + * Description: + * - During OUT transfers, the correct transfer interrupt (CTR) is triggered a little before the last USB SRAM accesses + * have completed. If the software responds quickly to the interrupt, the full buffer contents may not be correct. + * Workaround: + * - Software should ensure that a small delay is included before accessing the SRAM contents. This delay + * should be 800 ns in Full Speed mode and 6.4 μs in Low Speed mode + * + * Note: this errata may also apply to G0, U5, H5 etc. + * + * We choose the delay count based on max CPU frequency (in MHz) to ensure the delay is at least the required time. + */ + +#if CFG_TUSB_MCU == OPT_MCU_STM32H5 + #define FREQUENCY_MHZ 250U +#elif CFG_TUSB_MCU == OPT_MCU_STM32U5 + #define FREQUENCY_MHZ 160U +#elif CFG_TUSB_MCU == OPT_MCU_STM32U3 + #define FREQUENCY_MHZ 96U +#elif CFG_TUSB_MCU == OPT_MCU_STM32G0 + #define FREQUENCY_MHZ 64U +#elif CFG_TUSB_MCU == OPT_MCU_STM32C0 + #define FREQUENCY_MHZ 48U +#else + #error "FREQUENCY_MHZ not defined for this STM32 MCU" +#endif + + uint32_t ch_reg = ch_read(ch_id); + if (FSDEV_REG->ISTR & USB_ISTR_LS_DCONN || ch_reg & USB_CHEP_LSEP) { + // Low speed mode: 6.4 us delay -> about 2 cycles per MHz + volatile uint32_t cycle_count = FREQUENCY_MHZ * 2U; + while (cycle_count > 0U) { + cycle_count--; // each count take 3 cycles (1 for sub, jump, and compare) + } + } else { + // Full speed mode: 800 ns delay -> about 0.25 cycles per MHz + volatile uint32_t cycle_count = FREQUENCY_MHZ / 4U; + while (cycle_count > 0U) { + cycle_count--; // each count take 3 cycles (1 for sub, jump, and compare) + } + } + + return btable_get_count(ch_id, BTABLE_BUF_RX); +} //--------------------------------------------------------------------+ // Controller API @@ -175,12 +222,6 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { } FSDEV_REG->CNTR = USB_CNTR_HOST; // Enable USB in Host mode - -#if !defined(FSDEV_BUS_32BIT) - // BTABLE register does not exist on 32-bit bus devices - FSDEV_REG->BTABLE = FSDEV_BTABLE_BASE; -#endif - FSDEV_REG->ISTR = 0; // Clear pending interrupts // Reset channels to disabled @@ -260,7 +301,7 @@ static void ch_handle_ack(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) { } } else { // IN/RX direction - uint16_t const rx_count = btable_get_count(ch_id, BTABLE_BUF_RX); + uint16_t const rx_count = channel_get_rx_count(ch_id); uint16_t pma_addr = (uint16_t) btable_get_addr(ch_id, BTABLE_BUF_RX); fsdev_read_packet_memory(edpt->buffer + channel->queued_len[TUSB_DIR_IN], pma_addr, rx_count); @@ -338,7 +379,7 @@ static void ch_handle_error(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) { } // Handle CTR interrupt for the TX/OUT direction -static void handle_ctr_tx(uint32_t ch_id) { +static inline void handle_ctr_tx(uint32_t ch_id) { uint32_t ch_reg = ch_read(ch_id) | USB_EP_CTR_TX | USB_EP_CTR_RX; hcd_channel_t* channel = &_hcd_data.channel[ch_id]; TU_VERIFY(channel->allocated[TUSB_DIR_OUT] == 1,); @@ -358,7 +399,7 @@ static void handle_ctr_tx(uint32_t ch_id) { } // Handle CTR interrupt for the RX/IN direction -static void handle_ctr_rx(uint32_t ch_id) { +static inline void handle_ctr_rx(uint32_t ch_id) { uint32_t ch_reg = ch_read(ch_id) | USB_EP_CTR_TX | USB_EP_CTR_RX; hcd_channel_t* channel = &_hcd_data.channel[ch_id]; TU_VERIFY(channel->allocated[TUSB_DIR_IN] == 1,); @@ -393,28 +434,6 @@ void hcd_int_handler(uint8_t rhport, bool in_isr) { uint32_t const ch_reg = ch_read(ch_id); if (ch_reg & USB_EP_CTR_RX) { - #ifdef FSDEV_BUS_32BIT - /* https://www.st.com/resource/en/errata_sheet/es0561-stm32h503cbebkbrb-device-errata-stmicroelectronics.pdf - * https://www.st.com/resource/en/errata_sheet/es0587-stm32u535xx-and-stm32u545xx-device-errata-stmicroelectronics.pdf - * From H503/U535 errata: Buffer description table update completes after CTR interrupt triggers - * Description: - * - During OUT transfers, the correct transfer interrupt (CTR) is triggered a little before the last USB SRAM accesses - * have completed. If the software responds quickly to the interrupt, the full buffer contents may not be correct. - * Workaround: - * - Software should ensure that a small delay is included before accessing the SRAM contents. This delay - * should be 800 ns in Full Speed mode and 6.4 μs in Low Speed mode - * - Since H5 can run up to 250Mhz -> 1 cycle = 4ns. Per errata, we need to wait 200 cycles. Though executing code - * also takes time, so we'll wait 60 cycles (count = 20). - * - Since Low Speed mode is not supported/popular, we will ignore it for now. - * - * Note: this errata may also apply to G0, U5, H5 etc. - */ - volatile uint32_t cycle_count = 20; // defined as PCD_RX_PMA_CNT in stm32 hal_driver - while (cycle_count > 0U) { - cycle_count--; // each count take 3 cycles (1 for sub, jump, and compare) - } - #endif - ch_write_clear_ctr(ch_id, TUSB_DIR_IN); handle_ctr_rx(ch_id); } -- cgit v1.3.1 From 4affbc1f7b493ff9cbcdd9258ddec8bb34e6e56d Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 27 Nov 2025 09:40:50 +0700 Subject: more rename --- src/common/tusb_fifo.c | 12 ++++++------ src/common/tusb_fifo.h | 12 ++++++------ src/portable/microchip/samg/dcd_samg.c | 4 ++-- src/portable/nuvoton/nuc505/dcd_nuc505.c | 4 ++-- src/portable/synopsys/dwc2/dcd_dwc2.c | 4 ++-- test/unit-test/test/test_fifo.c | 8 ++++---- 6 files changed, 22 insertions(+), 22 deletions(-) (limited to 'src/portable') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 535ed73a5..27b97310a 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -322,8 +322,8 @@ static bool ff_peek_local(tu_fifo_t *f, void *buf, uint16_t wr_idx, uint16_t rd_ // Works on local copies of w and r // Must be protected by mutexes since in case of an overflow read pointer gets modified -uint16_t tu_fifo_peek_n_access(tu_fifo_t *f, void *p_buffer, uint16_t n, uint16_t wr_idx, uint16_t rd_idx, - tu_fifo_access_mode_t access_mode) { +uint16_t tu_fifo_peek_n_access_mode(tu_fifo_t *f, void *p_buffer, uint16_t n, uint16_t wr_idx, uint16_t rd_idx, + tu_fifo_access_mode_t access_mode) { uint16_t ovf_cnt = tu_ff_overflow_count(f->depth, wr_idx, rd_idx); if (ovf_cnt == 0) { @@ -346,7 +346,7 @@ uint16_t tu_fifo_peek_n_access(tu_fifo_t *f, void *p_buffer, uint16_t n, uint16_ return n; } -uint16_t tu_fifo_write_n_access(tu_fifo_t *f, const void *data, uint16_t n, tu_fifo_access_mode_t access_mode) { +uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n, tu_fifo_access_mode_t access_mode) { if (n == 0) { return 0; } @@ -419,11 +419,11 @@ uint16_t tu_fifo_write_n_access(tu_fifo_t *f, const void *data, uint16_t n, tu_f return n; } -uint16_t tu_fifo_read_n_access(tu_fifo_t *f, void *buffer, uint16_t n, tu_fifo_access_mode_t access_mode) { +uint16_t tu_fifo_read_n_access_mode(tu_fifo_t *f, void *buffer, uint16_t n, tu_fifo_access_mode_t access_mode) { ff_lock(f->mutex_rd); // Peek the data: f->rd_idx might get modified in case of an overflow so we can not use a local variable - n = tu_fifo_peek_n_access(f, buffer, n, f->wr_idx, f->rd_idx, access_mode); + n = tu_fifo_peek_n_access_mode(f, buffer, n, f->wr_idx, f->rd_idx, access_mode); f->rd_idx = advance_index(f->depth, f->rd_idx, n); ff_unlock(f->mutex_rd); @@ -500,7 +500,7 @@ bool tu_fifo_peek(tu_fifo_t *f, void *p_buffer) { /******************************************************************************/ uint16_t tu_fifo_peek_n(tu_fifo_t *f, void *p_buffer, uint16_t n) { ff_lock(f->mutex_rd); - const uint16_t ret = tu_fifo_peek_n_access(f, p_buffer, n, f->wr_idx, f->rd_idx, TU_FIFO_INC_ADDR_RW8); + const uint16_t ret = tu_fifo_peek_n_access_mode(f, p_buffer, n, f->wr_idx, f->rd_idx, TU_FIFO_INC_ADDR_RW8); ff_unlock(f->mutex_rd); return ret; } diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index d40fc4401..4d8448c44 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -174,8 +174,8 @@ void tu_fifo_config_mutex(tu_fifo_t *f, osal_mutex_t wr_mutex, osal_mutex_t rd_m // Peek API // peek() will correct/re-index read pointer in case of an overflowed fifo to form a full fifo //--------------------------------------------------------------------+ -uint16_t tu_fifo_peek_n_access(tu_fifo_t *f, void *p_buffer, uint16_t n, uint16_t wr_idx, uint16_t rd_idx, - tu_fifo_access_mode_t access_mode); +uint16_t tu_fifo_peek_n_access_mode(tu_fifo_t *f, void *p_buffer, uint16_t n, uint16_t wr_idx, uint16_t rd_idx, + tu_fifo_access_mode_t access_mode); bool tu_fifo_peek(tu_fifo_t *f, void *p_buffer); uint16_t tu_fifo_peek_n(tu_fifo_t *f, void *p_buffer, uint16_t n); @@ -183,19 +183,19 @@ uint16_t tu_fifo_peek_n(tu_fifo_t *f, void *p_buffer, uint16_t n); // Read API // peek() + advance read index //--------------------------------------------------------------------+ -uint16_t tu_fifo_read_n_access(tu_fifo_t *f, void *buffer, uint16_t n, tu_fifo_access_mode_t access_mode); +uint16_t tu_fifo_read_n_access_mode(tu_fifo_t *f, void *buffer, uint16_t n, tu_fifo_access_mode_t access_mode); bool tu_fifo_read(tu_fifo_t *f, void *buffer); TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_read_n(tu_fifo_t *f, void *buffer, uint16_t n) { - return tu_fifo_read_n_access(f, buffer, n, TU_FIFO_INC_ADDR_RW8); + return tu_fifo_read_n_access_mode(f, buffer, n, TU_FIFO_INC_ADDR_RW8); } //--------------------------------------------------------------------+ // Write API //--------------------------------------------------------------------+ -uint16_t tu_fifo_write_n_access(tu_fifo_t *f, const void *data, uint16_t n, tu_fifo_access_mode_t access_mode); +uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n, tu_fifo_access_mode_t access_mode); bool tu_fifo_write(tu_fifo_t *f, const void *data); TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_write_n(tu_fifo_t *f, const void *data, uint16_t n) { - return tu_fifo_write_n_access(f, data, n, TU_FIFO_INC_ADDR_RW8); + return tu_fifo_write_n_access_mode(f, data, n, TU_FIFO_INC_ADDR_RW8); } //--------------------------------------------------------------------+ diff --git a/src/portable/microchip/samg/dcd_samg.c b/src/portable/microchip/samg/dcd_samg.c index fad39c6c5..1faac2aa8 100644 --- a/src/portable/microchip/samg/dcd_samg.c +++ b/src/portable/microchip/samg/dcd_samg.c @@ -437,7 +437,7 @@ void dcd_int_handler(uint8_t rhport) // write to EP fifo #if 0 // TODO support dcd_edpt_xfer_fifo if (xfer->ff) { - tu_fifo_read_n_access(xfer->ff, (void *) &UDP->UDP_FDR[epnum], xact_len, TU_FIFO_FIXED_ADDR_RW32); + tu_fifo_read_n_access_mode(xfer->ff, (void *) &UDP->UDP_FDR[epnum], xact_len, TU_FIFO_FIXED_ADDR_RW32); } else #endif @@ -471,7 +471,7 @@ void dcd_int_handler(uint8_t rhport) // Read from EP fifo #if 0 // TODO support dcd_edpt_xfer_fifo API if (xfer->ff) { - tu_fifo_write_n_access(xfer->ff, (const void *) &UDP->UDP_FDR[epnum], xact_len, TU_FIFO_FIXED_ADDR_RW32); + tu_fifo_write_n_access_mode(xfer->ff, (const void *) &UDP->UDP_FDR[epnum], xact_len, TU_FIFO_FIXED_ADDR_RW32); } else #endif diff --git a/src/portable/nuvoton/nuc505/dcd_nuc505.c b/src/portable/nuvoton/nuc505/dcd_nuc505.c index 12f8cbd09..91b876718 100644 --- a/src/portable/nuvoton/nuc505/dcd_nuc505.c +++ b/src/portable/nuvoton/nuc505/dcd_nuc505.c @@ -194,7 +194,7 @@ static void dcd_userEP_in_xfer(struct xfer_ctl_t *xfer, USBD_EP_T *ep) /* provided buffers are thankfully 32-bit aligned, allowing most data to be transferred as 32-bit */ #if 0 // TODO support dcd_edpt_xfer_fifo API if (xfer->ff) { - tu_fifo_read_n_access(xfer->ff, (void *) (&ep->EPDAT_BYTE), bytes_now, TU_FIFO_FIXED_ADDR_RW32); + tu_fifo_read_n_access_mode(xfer->ff, (void *) (&ep->EPDAT_BYTE), bytes_now, TU_FIFO_FIXED_ADDR_RW32); } else #endif @@ -696,7 +696,7 @@ void dcd_int_handler(uint8_t rhport) /* copy the data from the PC to the previously provided buffer */ #if 0 // TODO support dcd_edpt_xfer_fifo API if (xfer->ff) { - tu_fifo_write_n_access(xfer->ff, (const void *) &ep->EPDAT_BYTE, tu_min16(available_bytes, xfer->total_bytes - xfer->out_bytes_so_far), TU_FIFO_FIXED_ADDR_RW32); + tu_fifo_write_n_access_mode(xfer->ff, (const void *) &ep->EPDAT_BYTE, tu_min16(available_bytes, xfer->total_bytes - xfer->out_bytes_so_far), TU_FIFO_FIXED_ADDR_RW32); } else #endif diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index 1629b1d56..00e81217b 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -362,7 +362,7 @@ static uint16_t epin_write_tx_fifo(uint8_t rhport, uint8_t epnum) { // Push packet to Tx-FIFO if (xfer->ff) { volatile uint32_t* tx_fifo = dwc2->fifo[epnum]; - tu_fifo_read_n_access(xfer->ff, (void *)(uintptr_t)tx_fifo, xact_bytes, TU_FIFO_FIXED_ADDR_RW32); + tu_fifo_read_n_access_mode(xfer->ff, (void *)(uintptr_t)tx_fifo, xact_bytes, TU_FIFO_FIXED_ADDR_RW32); total_bytes_written += xact_bytes; } else { dfifo_write_packet(dwc2, epnum, xfer->buffer, xact_bytes); @@ -878,7 +878,7 @@ static void handle_rxflvl_irq(uint8_t rhport) { if (byte_count != 0) { // Read packet off RxFIFO if (xfer->ff != NULL) { - tu_fifo_write_n_access(xfer->ff, (const void *)(uintptr_t)rx_fifo, byte_count, TU_FIFO_FIXED_ADDR_RW32); + tu_fifo_write_n_access_mode(xfer->ff, (const void *)(uintptr_t)rx_fifo, byte_count, TU_FIFO_FIXED_ADDR_RW32); } else { dfifo_read_packet(dwc2, xfer->buffer, byte_count); xfer->buffer += byte_count; diff --git a/test/unit-test/test/test_fifo.c b/test/unit-test/test/test_fifo.c index ac93e7e38..35bbeaa62 100644 --- a/test/unit-test/test/test_fifo.c +++ b/test/unit-test/test/test_fifo.c @@ -431,7 +431,7 @@ void test_write_n_fixed_addr_rw32_nowrap(void) { for (uint8_t n = 1; n <= 8; n++) { tu_fifo_clear(ff); - uint16_t written = tu_fifo_write_n_access(ff, (const void *)®, n, TU_FIFO_FIXED_ADDR_RW32); + uint16_t written = tu_fifo_write_n_access_mode(ff, (const void *)®, n, TU_FIFO_FIXED_ADDR_RW32); TEST_ASSERT_EQUAL(n, written); TEST_ASSERT_EQUAL(n, tu_fifo_count(ff)); @@ -453,7 +453,7 @@ void test_write_n_fixed_addr_rw32_wrapped(void) { ff->wr_idx = FIFO_SIZE - 3; ff->rd_idx = FIFO_SIZE - 3; - uint16_t written = tu_fifo_write_n_access(ff, (const void *)®, n, TU_FIFO_FIXED_ADDR_RW32); + uint16_t written = tu_fifo_write_n_access_mode(ff, (const void *)®, n, TU_FIFO_FIXED_ADDR_RW32); TEST_ASSERT_EQUAL(n, written); TEST_ASSERT_EQUAL(n, tu_fifo_count(ff)); @@ -473,7 +473,7 @@ void test_read_n_fixed_addr_rw32_nowrap(void) { tu_fifo_write_n(ff, pattern, 8); uint32_t reg = 0; - uint16_t read_cnt = tu_fifo_read_n_access(ff, ®, n, TU_FIFO_FIXED_ADDR_RW32); + uint16_t read_cnt = tu_fifo_read_n_access_mode(ff, ®, n, TU_FIFO_FIXED_ADDR_RW32); TEST_ASSERT_EQUAL(n, read_cnt); TEST_ASSERT_EQUAL(8 - n, tu_fifo_count(ff)); @@ -497,7 +497,7 @@ void test_read_n_fixed_addr_rw32_wrapped(void) { } uint32_t reg = 0; - uint16_t read_cnt = tu_fifo_read_n_access(ff, ®, n, TU_FIFO_FIXED_ADDR_RW32); + uint16_t read_cnt = tu_fifo_read_n_access_mode(ff, ®, n, TU_FIFO_FIXED_ADDR_RW32); TEST_ASSERT_EQUAL(n, read_cnt); TEST_ASSERT_EQUAL(0, tu_fifo_count(ff)); -- cgit v1.3.1 From 5d56828e43ef5f894c4586e7e7a61c3fbbbbfaf9 Mon Sep 17 00:00:00 2001 From: Zixun LI Date: Thu, 27 Nov 2025 11:02:49 +0100 Subject: extract core reset Signed-off-by: Zixun LI --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 18 +-------------- src/portable/st/stm32_fsdev/fsdev_common.c | 32 ++++++++++++++++++++++++++- src/portable/st/stm32_fsdev/fsdev_common.h | 6 ++++- src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c | 19 +--------------- 4 files changed, 38 insertions(+), 37 deletions(-) (limited to 'src/portable') diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index a6c8d2453..3c4e4fc9b 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -173,23 +173,9 @@ TU_ATTR_ALWAYS_INLINE static inline xfer_ctl_t *xfer_ctl_ptr(uint8_t epnum, uint //--------------------------------------------------------------------+ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { (void) rh_init; - // Follow the RM mentions to use a special ordering of PDWN and FRES - for (volatile uint32_t i = 0; i < 200; i++) { // should be a few us - asm("NOP"); - } - - // Perform USB peripheral reset - FSDEV_REG->CNTR = USB_CNTR_FRES | USB_CNTR_PDWN; - for (volatile uint32_t i = 0; i < 200; i++) { // should be a few us - asm("NOP"); - } - FSDEV_REG->CNTR &= ~USB_CNTR_PDWN; + fsdev_core_reset(); - // Wait startup time, for F042 and F070, this is <= 1 us. - for (volatile uint32_t i = 0; i < 200; i++) { // should be a few us - asm("NOP"); - } FSDEV_REG->CNTR = 0; // Enable USB #if !defined(FSDEV_BUS_32BIT) @@ -197,8 +183,6 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { FSDEV_REG->BTABLE = FSDEV_BTABLE_BASE; #endif - FSDEV_REG->ISTR = 0; // Clear pending interrupts - // Reset endpoints to disabled for (uint32_t i = 0; i < FSDEV_EP_COUNT; i++) { // This doesn't clear all bits since some bits are "toggle", but does set the type to DISABLED. diff --git a/src/portable/st/stm32_fsdev/fsdev_common.c b/src/portable/st/stm32_fsdev/fsdev_common.c index d021a6abf..5c7df6809 100644 --- a/src/portable/st/stm32_fsdev/fsdev_common.c +++ b/src/portable/st/stm32_fsdev/fsdev_common.c @@ -31,6 +31,35 @@ #include "fsdev_common.h" +//--------------------------------------------------------------------+ +// Global +//--------------------------------------------------------------------+ + +// Reset the USB Core +void fsdev_core_reset(void) { + // Follow the RM mentions to use a special ordering of PDWN and FRES + for (volatile uint32_t i = 0; i < 200; i++) { // should be a few us + asm("NOP"); + } + + // Perform USB peripheral reset + FSDEV_REG->CNTR = USB_CNTR_FRES | USB_CNTR_PDWN; + for (volatile uint32_t i = 0; i < 200; i++) { // should be a few us + asm("NOP"); + } + + FSDEV_REG->CNTR &= ~USB_CNTR_PDWN; + + // Wait startup time, for F042 and F070, this is <= 1 us. + for (volatile uint32_t i = 0; i < 200; i++) { // should be a few us + asm("NOP"); + } + + // Clear pending interrupts + FSDEV_REG->ISTR = 0; +} + + //--------------------------------------------------------------------+ // PMA read/write //--------------------------------------------------------------------+ @@ -199,7 +228,7 @@ bool fsdev_read_packet_memory_ff(tu_fifo_t *ff, uint16_t src, uint16_t wNBytes) // BTable Helper //--------------------------------------------------------------------+ -/* Aligned buffer size according to hardware */ +// Aligned buffer size according to hardware uint16_t pma_align_buffer_size(uint16_t size, uint8_t* blsize, uint8_t* num_block) { /* The STM32 full speed USB peripheral supports only a limited set of * buffer sizes given by the RX buffer entry format in the USB_BTABLE. */ @@ -217,6 +246,7 @@ uint16_t pma_align_buffer_size(uint16_t size, uint8_t* blsize, uint8_t* num_bloc return (*num_block) * block_in_bytes; } +// Set RX buffer size void btable_set_rx_bufsize(uint32_t ep_id, uint8_t buf_id, uint16_t wCount) { uint8_t blsize, num_block; (void) pma_align_buffer_size(wCount, &blsize, &num_block); diff --git a/src/portable/st/stm32_fsdev/fsdev_common.h b/src/portable/st/stm32_fsdev/fsdev_common.h index e363245ec..9cf61031d 100644 --- a/src/portable/st/stm32_fsdev/fsdev_common.h +++ b/src/portable/st/stm32_fsdev/fsdev_common.h @@ -311,9 +311,13 @@ TU_ATTR_ALWAYS_INLINE static inline void btable_set_count(uint32_t ep_id, uint8_ #endif } -/* Aligned buffer size according to hardware */ +// Reset the USB Core +void fsdev_core_reset(void); + +// Aligned buffer size according to hardware uint16_t pma_align_buffer_size(uint16_t size, uint8_t* blsize, uint8_t* num_block); +// Set RX buffer size void btable_set_rx_bufsize(uint32_t ep_id, uint8_t buf_id, uint16_t wCount); //--------------------------------------------------------------------+ diff --git a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c index 362d7df7b..168366058 100644 --- a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c @@ -203,26 +203,9 @@ bool hcd_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param) { bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { (void) rh_init; - // Follow the RM mentions to use a special ordering of PDWN and FRES - for (volatile uint32_t i = 0; i < 200; i++) { - asm("NOP"); - } - - // Perform USB peripheral reset - FSDEV_REG->CNTR = USB_CNTR_FRES | USB_CNTR_PDWN; - for (volatile uint32_t i = 0; i < 200; i++) { - asm("NOP"); - } - - FSDEV_REG->CNTR &= ~USB_CNTR_PDWN; - - // Wait startup time - for (volatile uint32_t i = 0; i < 200; i++) { - asm("NOP"); - } + fsdev_core_reset(); FSDEV_REG->CNTR = USB_CNTR_HOST; // Enable USB in Host mode - FSDEV_REG->ISTR = 0; // Clear pending interrupts // Reset channels to disabled for (uint32_t i = 0; i < FSDEV_EP_COUNT; i++) { -- cgit v1.3.1 From 9742ba734f8ef780fb2b4c94848c4bd534afdafe Mon Sep 17 00:00:00 2001 From: Zixun LI Date: Thu, 27 Nov 2025 11:34:37 +0100 Subject: Add fsdev_deinit Signed-off-by: Zixun LI --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 8 ++++++++ src/portable/st/stm32_fsdev/fsdev_common.c | 15 +++++++++++++++ src/portable/st/stm32_fsdev/fsdev_common.h | 3 +++ src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c | 8 ++++++++ 4 files changed, 34 insertions(+) (limited to 'src/portable') diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 3c4e4fc9b..351916147 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -199,6 +199,14 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { return true; } +bool dcd_deinit(uint8_t rhport) { + (void)rhport; + + fsdev_deinit(); + + return true; +} + void dcd_sof_enable(uint8_t rhport, bool en) { (void)rhport; diff --git a/src/portable/st/stm32_fsdev/fsdev_common.c b/src/portable/st/stm32_fsdev/fsdev_common.c index 5c7df6809..d0f3460b6 100644 --- a/src/portable/st/stm32_fsdev/fsdev_common.c +++ b/src/portable/st/stm32_fsdev/fsdev_common.c @@ -59,6 +59,21 @@ void fsdev_core_reset(void) { FSDEV_REG->ISTR = 0; } +// De-initialize the USB Core +void fsdev_deinit(void) { + // Disable all interrupts and force USB reset + FSDEV_REG->CNTR = USB_CNTR_FRES; + + // Clear pending interrupts + FSDEV_REG->ISTR = 0; + + // Put USB peripheral in power down mode + FSDEV_REG->CNTR = USB_CNTR_FRES | USB_CNTR_PDWN; + for (volatile uint32_t i = 0; i < 200; i++) { // should be a few us + asm("NOP"); + } +} + //--------------------------------------------------------------------+ // PMA read/write diff --git a/src/portable/st/stm32_fsdev/fsdev_common.h b/src/portable/st/stm32_fsdev/fsdev_common.h index 9cf61031d..0c67ee0c7 100644 --- a/src/portable/st/stm32_fsdev/fsdev_common.h +++ b/src/portable/st/stm32_fsdev/fsdev_common.h @@ -314,6 +314,9 @@ TU_ATTR_ALWAYS_INLINE static inline void btable_set_count(uint32_t ep_id, uint8_ // Reset the USB Core void fsdev_core_reset(void); +// De-initialize the USB Core +void fsdev_deinit(void); + // Aligned buffer size according to hardware uint16_t pma_align_buffer_size(uint16_t size, uint8_t* blsize, uint8_t* num_block); diff --git a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c index 168366058..39b9ac2d3 100644 --- a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c @@ -226,6 +226,14 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { return true; } +bool hcd_deinit(uint8_t rhport) { + (void)rhport; + + fsdev_deinit(); + + return true; +} + static void port_status_handler(uint8_t rhport, bool in_isr) { uint32_t const fnr_reg = FSDEV_REG->FNR; uint32_t const istr_reg = FSDEV_REG->ISTR; -- cgit v1.3.1 From a25e9e86c83785e8ce91b1c7b485a106195d368a Mon Sep 17 00:00:00 2001 From: Zixun LI Date: Thu, 27 Nov 2025 11:35:25 +0100 Subject: Remove redundant EP reg clear Signed-off-by: Zixun LI --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 10 +++------- src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c | 5 ----- 2 files changed, 3 insertions(+), 12 deletions(-) (limited to 'src/portable') diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 351916147..087639d4b 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -183,14 +183,10 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { FSDEV_REG->BTABLE = FSDEV_BTABLE_BASE; #endif - // Reset endpoints to disabled - for (uint32_t i = 0; i < FSDEV_EP_COUNT; i++) { - // This doesn't clear all bits since some bits are "toggle", but does set the type to DISABLED. - ep_write(i, 0u, false); - } - + // Enable interrupts for device mode FSDEV_REG->CNTR |= USB_CNTR_RESETM | USB_CNTR_ESOFM | USB_CNTR_CTRM | - USB_CNTR_SUSPM | USB_CNTR_WKUPM | USB_CNTR_PMAOVRM; + USB_CNTR_SUSPM | USB_CNTR_WKUPM | USB_CNTR_PMAOVRM; + handle_bus_reset(rhport); // Enable pull-up if supported diff --git a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c index 39b9ac2d3..00c71ce6c 100644 --- a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c @@ -207,11 +207,6 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { FSDEV_REG->CNTR = USB_CNTR_HOST; // Enable USB in Host mode - // Reset channels to disabled - for (uint32_t i = 0; i < FSDEV_EP_COUNT; i++) { - ch_write(i, 0u, false); - } - tu_memclr(&_hcd_data, sizeof(_hcd_data)); // Enable interrupts for host mode -- cgit v1.3.1 From 8914f402e5cdf372ade2ed1f4053ce14feffbeda Mon Sep 17 00:00:00 2001 From: Zixun LI Date: Thu, 27 Nov 2025 12:10:27 +0100 Subject: free previously allocated OUT endpoint if IN allocation failed Signed-off-by: Zixun LI --- src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'src/portable') diff --git a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c index 00c71ce6c..7d3deba34 100644 --- a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c @@ -516,7 +516,7 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const uint8_t const ep_type = ep_desc->bmAttributes.xfer; uint8_t const ep_id = endpoint_alloc(); - TU_ASSERT(ep_id < CFG_TUH_FSDEV_ENDPOINT_MAX); + TU_ASSERT(ep_id != TUSB_INDEX_INVALID_8); hcd_endpoint_t* edpt = &_hcd_data.edpt[ep_id]; edpt->dev_addr = dev_addr; @@ -530,7 +530,11 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const // EP0 is bi-directional, so we need to open both OUT and IN channels if (ep_addr == 0) { uint8_t const ep_id_in = endpoint_alloc(); - TU_ASSERT(ep_id_in < CFG_TUH_FSDEV_ENDPOINT_MAX); + if (ep_id_in == TUSB_INDEX_INVALID_8) { + // free previously allocated OUT endpoint + endpoint_dealloc(edpt); + TU_ASSERT(false); + } _hcd_data.edpt[ep_id_in] = *edpt; // copy from OUT endpoint _hcd_data.edpt[ep_id_in].ep_addr = 0 | TUSB_DIR_IN_MASK; @@ -543,13 +547,13 @@ bool hcd_edpt_close(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { (void) rhport; uint8_t const ep_id = endpoint_find(dev_addr, ep_addr); - TU_ASSERT(ep_id < CFG_TUH_FSDEV_ENDPOINT_MAX); + TU_ASSERT(ep_id != TUSB_INDEX_INVALID_8); edpoint_close(ep_id); if (ep_addr == 0) { uint8_t const ep_id_in = endpoint_find(dev_addr, 0 | TUSB_DIR_IN_MASK); - TU_ASSERT(ep_id_in < CFG_TUH_FSDEV_ENDPOINT_MAX); + TU_ASSERT(ep_id_in != TUSB_INDEX_INVALID_8); edpoint_close(ep_id_in); } @@ -564,7 +568,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *b TU_LOG(FSDEV_DEBUG, "hcd_edpt_xfer addr=%u ep=0x%02X len=%u\r\n", dev_addr, ep_addr, buflen); uint8_t const ep_id = endpoint_find(dev_addr, ep_addr); - TU_ASSERT(ep_id < CFG_TUH_FSDEV_ENDPOINT_MAX); + TU_ASSERT(ep_id != TUSB_INDEX_INVALID_8); hcd_endpoint_t *edpt = &_hcd_data.edpt[ep_id]; @@ -579,7 +583,7 @@ bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { (void) rhport; uint8_t const ep_id = endpoint_find(dev_addr, ep_addr); - TU_ASSERT(ep_id < CFG_TUH_FSDEV_ENDPOINT_MAX); + TU_ASSERT(ep_id != TUSB_INDEX_INVALID_8); tusb_dir_t const dir = tu_edpt_dir(ep_addr); for (uint8_t i = 0; i < FSDEV_EP_COUNT; i++) { @@ -602,7 +606,7 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet (void) rhport; uint8_t const ep_id = endpoint_find(dev_addr, 0); - TU_ASSERT(ep_id < CFG_TUH_FSDEV_ENDPOINT_MAX); + TU_ASSERT(ep_id != TUSB_INDEX_INVALID_8); hcd_endpoint_t *edpt = &_hcd_data.edpt[ep_id]; edpt->next_setup = true; @@ -618,7 +622,7 @@ bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { (void) ep_addr; uint8_t const ep_id = endpoint_find(dev_addr, 0); - TU_ASSERT(ep_id < CFG_TUH_FSDEV_ENDPOINT_MAX); + TU_ASSERT(ep_id != TUSB_INDEX_INVALID_8); hcd_endpoint_t *edpt = &_hcd_data.edpt[ep_id]; edpt->pid = 0; -- cgit v1.3.1 From 07ff25eb1e9871082b92161296725c5d312d3558 Mon Sep 17 00:00:00 2001 From: Zixun LI Date: Thu, 27 Nov 2025 17:17:03 +0100 Subject: Add max nak config Signed-off-by: Zixun LI --- src/host/usbh.h | 9 +- src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c | 203 +++++++++++++++++--------- 2 files changed, 140 insertions(+), 72 deletions(-) (limited to 'src/portable') diff --git a/src/host/usbh.h b/src/host/usbh.h index 4b6747848..697c911ff 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -95,18 +95,23 @@ enum { TUH_CFGID_INVALID = 0, TUH_CFGID_RPI_PIO_USB_CONFIGURATION = 100, // cfg_param: pio_usb_configuration_t TUH_CFGID_MAX3421 = 200, + TUH_CFGID_FSDEV = 300, }; typedef struct { - uint8_t max_nak; // max NAK per endpoint per frame to save CPU/SPI bus usage + uint8_t max_nak; // max NAK per endpoint per frame to save CPU/SPI bus usage (0=unlimited) uint8_t cpuctl; // R16: CPU Control Register uint8_t pinctl; // R17: Pin Control Register. FDUPSPI bit is ignored } tuh_configure_max3421_t; +typedef struct { + uint8_t max_nak; // max NAK per endpoint per frame to save CPU usage (0=unlimited) +} tuh_configure_fsdev_t; + typedef union { // For TUH_CFGID_RPI_PIO_USB_CONFIGURATION use pio_usb_configuration_t - tuh_configure_max3421_t max3421; + tuh_configure_fsdev_t fsdev; } tuh_configure_param_t; //--------------------------------------------------------------------+ diff --git a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c index 7d3deba34..ff2f2946e 100644 --- a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c @@ -60,48 +60,56 @@ TU_VERIFY_STATIC(CFG_TUH_FSDEV_ENDPOINT_MAX <= 255, "currently only use 8-bit for index"); enum { - HCD_XFER_ERROR_MAX = 3 + HCD_XFER_ERROR_MAX = 3, + HCD_XFER_NAK_MAX = 15, + HCD_XFER_NAK_DEFAULT = 3, }; // Host driver struct for each opened endpoint typedef struct { uint8_t *buffer; uint16_t buflen; + uint16_t queued_len; uint16_t max_packet_size; uint8_t dev_addr; uint8_t ep_addr; uint8_t ep_type; uint8_t interval; struct TU_ATTR_PACKED { - uint8_t low_speed : 1; + uint8_t ls_pre : 1; uint8_t allocated : 1; uint8_t next_setup : 1; uint8_t pid : 1; }; } hcd_endpoint_t; +// Channel direction state +typedef struct { + hcd_endpoint_t* edpt; + struct TU_ATTR_PACKED { + uint8_t allocated : 1; + uint8_t retry : 3; + uint8_t nak : 4; // Max NAK count in current frame + }; +} hcd_channel_dir_t; + // Additional info for each channel when it is active typedef struct { - hcd_endpoint_t* edpt[2]; // OUT/IN - uint16_t queued_len[2]; uint8_t dev_addr; uint8_t ep_num; uint8_t ep_type; - uint8_t allocated[2]; - uint8_t retry[2]; + hcd_channel_dir_t out, in; } hcd_channel_t; -// Root hub port state static struct { - bool connected; -} _hcd_port; - -typedef struct { hcd_channel_t channel[FSDEV_EP_COUNT]; hcd_endpoint_t edpt[CFG_TUH_FSDEV_ENDPOINT_MAX]; -} hcd_data_t; + bool connected; +} _hcd_data; -hcd_data_t _hcd_data; +static tuh_configure_fsdev_t _tuh_cfg = { + .max_nak = HCD_XFER_NAK_DEFAULT, +}; //--------------------------------------------------------------------+ // Prototypes @@ -114,7 +122,6 @@ static uint8_t channel_alloc(uint8_t dev_addr, uint8_t ep_addr, uint8_t ep_type) static bool edpt_xfer_kickoff(uint8_t ep_id); static bool channel_xfer_start(uint8_t ch_id, tusb_dir_t dir); static void edpoint_close(uint8_t ep_id); -static void port_status_handler(uint8_t rhport, bool in_isr); static void ch_handle_ack(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir); static void ch_handle_nak(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir); static void ch_handle_stall(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir); @@ -129,7 +136,11 @@ static inline void endpoint_dealloc(hcd_endpoint_t* edpt) { } static inline void channel_dealloc(hcd_channel_t* ch, tusb_dir_t dir) { - ch->allocated[dir] = 0; + if (dir == TUSB_DIR_OUT) { + ch->out.allocated = 0; + } else { + ch->in.allocated = 0; + } } // Write channel state in specified direction @@ -194,9 +205,11 @@ static inline uint16_t channel_get_rx_count(uint8_t ch_id) { // 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; - return false; + TU_VERIFY(cfg_id == TUH_CFGID_FSDEV && cfg_param != NULL); + + tuh_configure_param_t const* cfg = (tuh_configure_param_t const*) cfg_param; + _tuh_cfg.max_nak = tu_min8(cfg->fsdev.max_nak, HCD_XFER_NAK_MAX); + return true; } // Initialize controller to host mode @@ -210,11 +223,11 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { tu_memclr(&_hcd_data, sizeof(_hcd_data)); // Enable interrupts for host mode - FSDEV_REG->CNTR |= USB_CNTR_RESETM | USB_CNTR_CTRM | USB_CNTR_SUSPM | + FSDEV_REG->CNTR |= USB_CNTR_RESETM | USB_CNTR_CTRM | USB_CNTR_SOFM | USB_CNTR_SUSPM | USB_CNTR_WKUPM | USB_CNTR_ERRM | USB_CNTR_PMAOVRM; // Initialize port state - _hcd_port.connected = false; + _hcd_data.connected = false; fsdev_connect(rhport); @@ -229,35 +242,48 @@ bool hcd_deinit(uint8_t rhport) { return true; } -static void port_status_handler(uint8_t rhport, bool in_isr) { +//--------------------------------------------------------------------+ +// Interrupt Helper Functions +//--------------------------------------------------------------------+ + +static inline void sof_handler(void) { + // Reset NAK counters for all active channels + for (uint8_t ch_id = 0; ch_id < FSDEV_EP_COUNT; ch_id++) { + hcd_channel_t* channel = &_hcd_data.channel[ch_id]; + if (channel->out.allocated) { + channel->out.nak = 0; + } + if (channel->in.allocated) { + channel->in.nak = 0; + } + } +} + +static inline void port_status_handler(uint8_t rhport, bool in_isr) { uint32_t const fnr_reg = FSDEV_REG->FNR; uint32_t const istr_reg = FSDEV_REG->ISTR; // SE0 detected USB Disconnected state if ((fnr_reg & (USB_FNR_RXDP | USB_FNR_RXDM)) == 0U) { - _hcd_port.connected = false; + _hcd_data.connected = false; hcd_event_device_remove(rhport, in_isr); return; } - if (!_hcd_port.connected) { + if (!_hcd_data.connected) { // J-state or K-state detected & LastState=Disconnected if (((fnr_reg & USB_FNR_RXDP) != 0U) || ((istr_reg & USB_ISTR_LS_DCONN) != 0U)) { - _hcd_port.connected = true; + _hcd_data.connected = true; hcd_event_device_attach(rhport, in_isr); } } else { // J-state or K-state detected & lastState=Connected: a Missed disconnection is detected if (((fnr_reg & USB_FNR_RXDP) != 0U) || ((istr_reg & USB_ISTR_LS_DCONN) != 0U)) { - _hcd_port.connected = false; + _hcd_data.connected = false; hcd_event_device_remove(rhport, in_isr); } } } -//--------------------------------------------------------------------+ -// Interrupt Helper Functions -//--------------------------------------------------------------------+ - // Handle ACK response static void ch_handle_ack(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) { uint8_t const ep_num = ch_reg & USB_EPADDR_FIELD; @@ -271,38 +297,40 @@ static void ch_handle_ack(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) { if (dir == TUSB_DIR_OUT) { // OUT/TX direction - if (edpt->buflen != channel->queued_len[TUSB_DIR_OUT]) { + if (edpt->buflen != edpt->queued_len) { // More data to send - uint16_t const len = tu_min16(edpt->buflen - channel->queued_len[TUSB_DIR_OUT], edpt->max_packet_size); + uint16_t const len = tu_min16(edpt->buflen - edpt->queued_len, edpt->max_packet_size); uint16_t pma_addr = (uint16_t) btable_get_addr(ch_id, BTABLE_BUF_TX); - fsdev_write_packet_memory(pma_addr, &(edpt->buffer[channel->queued_len[TUSB_DIR_OUT]]), len); + fsdev_write_packet_memory(pma_addr, &(edpt->buffer[edpt->queued_len]), len); btable_set_count(ch_id, BTABLE_BUF_TX, len); - channel->queued_len[TUSB_DIR_OUT] += len; + edpt->queued_len += len; channel_write_status(ch_id, ch_reg, TUSB_DIR_OUT, EP_STAT_VALID, false); + channel->out.nak = 0; } else { // Transfer complete channel_dealloc(channel, TUSB_DIR_OUT); edpt->pid = (ch_reg & USB_CHEP_DTOG_TX) ? 1 : 0; - hcd_event_xfer_complete(daddr, ep_num, channel->queued_len[TUSB_DIR_OUT], XFER_RESULT_SUCCESS, true); + hcd_event_xfer_complete(daddr, ep_num, edpt->queued_len, XFER_RESULT_SUCCESS, true); } } else { // IN/RX direction uint16_t const rx_count = channel_get_rx_count(ch_id); uint16_t pma_addr = (uint16_t) btable_get_addr(ch_id, BTABLE_BUF_RX); - fsdev_read_packet_memory(edpt->buffer + channel->queued_len[TUSB_DIR_IN], pma_addr, rx_count); - channel->queued_len[TUSB_DIR_IN] += rx_count; + fsdev_read_packet_memory(edpt->buffer + edpt->queued_len, pma_addr, rx_count); + edpt->queued_len += rx_count; - if ((rx_count < edpt->max_packet_size) || (channel->queued_len[TUSB_DIR_IN] >= edpt->buflen)) { + if ((rx_count < edpt->max_packet_size) || (edpt->queued_len >= edpt->buflen)) { // Transfer complete (short packet or all bytes received) channel_dealloc(channel, TUSB_DIR_IN); edpt->pid = (ch_reg & USB_CHEP_DTOG_RX) ? 1 : 0; - hcd_event_xfer_complete(daddr, ep_num | TUSB_DIR_IN_MASK, channel->queued_len[TUSB_DIR_IN], XFER_RESULT_SUCCESS, true); + hcd_event_xfer_complete(daddr, ep_num | TUSB_DIR_IN_MASK, edpt->queued_len, XFER_RESULT_SUCCESS, true); } else { // More data expected - uint16_t const cnt = tu_min16(edpt->buflen - channel->queued_len[TUSB_DIR_IN], edpt->max_packet_size); + uint16_t const cnt = tu_min16(edpt->buflen - edpt->queued_len, edpt->max_packet_size); btable_set_rx_bufsize(ch_id, BTABLE_BUF_RX, cnt); channel_write_status(ch_id, ch_reg, TUSB_DIR_IN, EP_STAT_VALID, false); + channel->in.nak = 0; } } } @@ -316,10 +344,17 @@ static void ch_handle_nak(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) { if (ep_id == TUSB_INDEX_INVALID_8) return; hcd_endpoint_t* edpt = &_hcd_data.edpt[ep_id]; - // Retry non-periodic transfer immediately, + // Retry non-periodic transfer immediately if NAK count not exceeded // Periodic transfer will be retried by next frame automatically if (edpt->ep_type == TUSB_XFER_CONTROL || edpt->ep_type == TUSB_XFER_BULK) { - channel_write_status(ch_id, ch_reg, dir, EP_STAT_VALID, false); + hcd_channel_dir_t* channel_dir = + (dir == TUSB_DIR_OUT) ? &(_hcd_data.channel[ch_id].out) : &(_hcd_data.channel[ch_id].in); + if (channel_dir->nak < HCD_XFER_NAK_MAX) { + channel_dir->nak++; + } + if (channel_dir->nak < _tuh_cfg.max_nak || _tuh_cfg.max_nak == 0) { + channel_write_status(ch_id, ch_reg, dir, EP_STAT_VALID, false); + } } } @@ -328,13 +363,17 @@ static void ch_handle_stall(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) { uint8_t const ep_num = ch_reg & USB_EPADDR_FIELD; uint8_t const daddr = (ch_reg & USB_CHEP_DEVADDR_Msk) >> USB_CHEP_DEVADDR_Pos; + uint8_t ep_id = endpoint_find(daddr, ep_num | (dir == TUSB_DIR_IN ? TUSB_DIR_IN_MASK : 0)); + if (ep_id == TUSB_INDEX_INVALID_8) return; + + hcd_endpoint_t* edpt = &_hcd_data.edpt[ep_id]; hcd_channel_t* channel = &_hcd_data.channel[ch_id]; channel_dealloc(channel, dir); channel_write_status(ch_id, ch_reg, dir, EP_STAT_DISABLED, false); hcd_event_xfer_complete(daddr, ep_num | (dir == TUSB_DIR_IN ? TUSB_DIR_IN_MASK : 0), - channel->queued_len[dir], XFER_RESULT_STALLED, true); + edpt->queued_len, XFER_RESULT_STALLED, true); } // Handle error response @@ -345,21 +384,24 @@ static void ch_handle_error(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) { uint8_t ep_id = endpoint_find(daddr, ep_num | (dir == TUSB_DIR_IN ? TUSB_DIR_IN_MASK : 0)); if (ep_id == TUSB_INDEX_INVALID_8) return; + hcd_endpoint_t* edpt = &_hcd_data.edpt[ep_id]; hcd_channel_t* channel = &_hcd_data.channel[ch_id]; ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(dir); ch_reg &= ~(dir == TUSB_DIR_OUT ? USB_CH_ERRTX : USB_CH_ERRRX); - if (channel->retry[dir] < HCD_XFER_ERROR_MAX) { + hcd_channel_dir_t* channel_dir = + (dir == TUSB_DIR_OUT) ? &(_hcd_data.channel[ch_id].out) : &(_hcd_data.channel[ch_id].in); + if (channel_dir->retry < HCD_XFER_ERROR_MAX) { // Retry - channel->retry[dir]++; + channel_dir->retry++; ch_change_status(&ch_reg, dir, EP_STAT_VALID); } else { // Failed after retries channel_dealloc(channel, dir); ch_change_status(&ch_reg, dir, EP_STAT_DISABLED); hcd_event_xfer_complete(daddr, ep_num | (dir == TUSB_DIR_IN ? TUSB_DIR_IN_MASK : 0), - channel->queued_len[dir], XFER_RESULT_FAILED, true); + edpt->queued_len, XFER_RESULT_FAILED, true); } ch_write(ch_id, ch_reg, false); } @@ -368,7 +410,7 @@ static void ch_handle_error(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) { static inline void handle_ctr_tx(uint32_t ch_id) { uint32_t ch_reg = ch_read(ch_id) | USB_EP_CTR_TX | USB_EP_CTR_RX; hcd_channel_t* channel = &_hcd_data.channel[ch_id]; - TU_VERIFY(channel->allocated[TUSB_DIR_OUT] == 1,); + TU_VERIFY(channel->out.allocated == 1,); if ((ch_reg & USB_CH_ERRTX) == 0U) { // No error @@ -388,7 +430,7 @@ static inline void handle_ctr_tx(uint32_t ch_id) { static inline void handle_ctr_rx(uint32_t ch_id) { uint32_t ch_reg = ch_read(ch_id) | USB_EP_CTR_TX | USB_EP_CTR_RX; hcd_channel_t* channel = &_hcd_data.channel[ch_id]; - TU_VERIFY(channel->allocated[TUSB_DIR_IN] == 1,); + TU_VERIFY(channel->in.allocated == 1,); if ((ch_reg & USB_CH_ERRRX) == 0U) { // No error @@ -408,7 +450,13 @@ static inline void handle_ctr_rx(uint32_t ch_id) { void hcd_int_handler(uint8_t rhport, bool in_isr) { uint32_t int_status = FSDEV_REG->ISTR; - /* Port Change Detected (Connection/Disconnection) */ + // Start of Frame + if (int_status & USB_ISTR_SOF) { + FSDEV_REG->ISTR = (fsdev_bus_t)~USB_ISTR_SOF; + sof_handler(); + } + + // Port Change Detected (Connection/Disconnection) if (int_status & USB_ISTR_DCON) { FSDEV_REG->ISTR = (fsdev_bus_t)~USB_ISTR_DCON; port_status_handler(rhport, in_isr); @@ -464,7 +512,7 @@ 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 _hcd_port.connected; + return _hcd_data.connected; } // Reset USB bus on the port @@ -525,7 +573,7 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const edpt->max_packet_size = packet_size; edpt->interval = ep_desc->bInterval; edpt->pid = 0; - edpt->low_speed = (hcd_port_speed_get(rhport) == TUSB_SPEED_FULL && tuh_speed_get(dev_addr) == TUSB_SPEED_LOW) ? 1 : 0; + edpt->ls_pre = (hcd_port_speed_get(rhport) == TUSB_SPEED_FULL && tuh_speed_get(dev_addr) == TUSB_SPEED_LOW) ? 1 : 0; // EP0 is bi-directional, so we need to open both OUT and IN channels if (ep_addr == 0) { @@ -574,6 +622,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *b edpt->buffer = buffer; edpt->buflen = buflen; + edpt->queued_len = 0; return edpt_xfer_kickoff(ep_id); } @@ -588,8 +637,9 @@ bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { for (uint8_t i = 0; i < FSDEV_EP_COUNT; i++) { hcd_channel_t* channel = &_hcd_data.channel[i]; + uint8_t const allocated = (dir == TUSB_DIR_OUT) ? channel->out.allocated : channel->in.allocated; - if (channel->allocated[dir] == 1 && + if (allocated == 1 && channel->dev_addr == dev_addr && channel->ep_num == tu_edpt_number(ep_addr)) { channel_dealloc(channel, dir); @@ -664,11 +714,11 @@ static void edpoint_close(uint8_t ep_id) { for (uint8_t i = 0; i < FSDEV_EP_COUNT; i++) { hcd_channel_t* channel = &_hcd_data.channel[i]; uint32_t ch_reg = ch_read(i) | USB_EP_CTR_TX | USB_EP_CTR_RX; - if (channel->allocated[TUSB_DIR_OUT] == 1 && channel->edpt[TUSB_DIR_OUT] == edpt) { + if (channel->out.allocated == 1 && channel->out.edpt == edpt) { channel_dealloc(channel, TUSB_DIR_OUT); channel_write_status(i, ch_reg, TUSB_DIR_OUT, EP_STAT_DISABLED, true); } - if (channel->allocated[TUSB_DIR_IN] == 1 && channel->edpt[TUSB_DIR_IN] == edpt) { + if (channel->in.allocated == 1 && channel->in.edpt == edpt) { channel_dealloc(channel, TUSB_DIR_IN); channel_write_status(i, ch_reg, TUSB_DIR_IN, EP_STAT_DISABLED, true); } @@ -697,27 +747,37 @@ static uint8_t channel_alloc(uint8_t dev_addr, uint8_t ep_addr, uint8_t ep_type) // Find channel allocate for same ep_num but other direction tusb_dir_t const other_dir = (dir == TUSB_DIR_IN) ? TUSB_DIR_OUT : TUSB_DIR_IN; for (uint8_t i = 0; i < FSDEV_EP_COUNT; i++) { - if (_hcd_data.channel[i].allocated[dir] == 0 && - _hcd_data.channel[i].allocated[other_dir] == 1 && + uint8_t const allocated_dir = (dir == TUSB_DIR_OUT) ? _hcd_data.channel[i].out.allocated : _hcd_data.channel[i].in.allocated; + uint8_t const allocated_other = (other_dir == TUSB_DIR_OUT) ? _hcd_data.channel[i].out.allocated : _hcd_data.channel[i].in.allocated; + if (allocated_dir == 0 && + allocated_other == 1 && _hcd_data.channel[i].dev_addr == dev_addr && _hcd_data.channel[i].ep_num == ep_num && _hcd_data.channel[i].ep_type == ep_type) { - _hcd_data.channel[i].allocated[dir] = 1; - _hcd_data.channel[i].queued_len[dir] = 0; - _hcd_data.channel[i].retry[dir] = 0; + if (dir == TUSB_DIR_OUT) { + _hcd_data.channel[i].out.allocated = 1; + _hcd_data.channel[i].out.retry = 0; + } else { + _hcd_data.channel[i].in.allocated = 1; + _hcd_data.channel[i].in.retry = 0; + } return i; } } // Find free channel for (uint8_t i = 0; i < FSDEV_EP_COUNT; i++) { - if (_hcd_data.channel[i].allocated[0] == 0 && _hcd_data.channel[i].allocated[1] == 0) { + if (_hcd_data.channel[i].out.allocated == 0 && _hcd_data.channel[i].in.allocated == 0) { _hcd_data.channel[i].dev_addr = dev_addr; _hcd_data.channel[i].ep_num = ep_num; _hcd_data.channel[i].ep_type = ep_type; - _hcd_data.channel[i].allocated[dir] = 1; - _hcd_data.channel[i].queued_len[dir] = 0; - _hcd_data.channel[i].retry[dir] = 0; + if (dir == TUSB_DIR_OUT) { + _hcd_data.channel[i].out.allocated = 1; + _hcd_data.channel[i].out.retry = 0; + } else { + _hcd_data.channel[i].in.allocated = 1; + _hcd_data.channel[i].in.retry = 0; + } return i; } } @@ -733,16 +793,19 @@ static bool edpt_xfer_kickoff(uint8_t ep_id) { TU_ASSERT(ch_id != TUSB_INDEX_INVALID_8); // all channel are in used tusb_dir_t const dir = tu_edpt_dir(edpt->ep_addr); - hcd_channel_t* channel = &_hcd_data.channel[ch_id]; - channel->edpt[dir] = edpt; + if (dir == TUSB_DIR_OUT) { + channel->out.edpt = edpt; + } else { + channel->in.edpt = edpt; + } return channel_xfer_start(ch_id, dir); } static bool channel_xfer_start(uint8_t ch_id, tusb_dir_t dir) { hcd_channel_t* channel = &_hcd_data.channel[ch_id]; - hcd_endpoint_t* edpt = channel->edpt[dir]; + hcd_endpoint_t* edpt = (dir == TUSB_DIR_OUT) ? channel->out.edpt : channel->in.edpt; uint32_t ch_reg = ch_read(ch_id) & ~USB_EPREG_MASK; ch_reg |= tu_edpt_number(edpt->ep_addr) | edpt->dev_addr << USB_CHEP_DEVADDR_Pos | @@ -771,28 +834,28 @@ static bool channel_xfer_start(uint8_t ch_id, tusb_dir_t dir) { btable_set_addr(ch_id, dir == TUSB_DIR_OUT ? BTABLE_BUF_TX : BTABLE_BUF_RX, pma_addr); if (dir == TUSB_DIR_OUT) { - uint16_t const len = tu_min16(edpt->buflen - channel->queued_len[TUSB_DIR_OUT], edpt->max_packet_size); + uint16_t const len = tu_min16(edpt->buflen - edpt->queued_len, edpt->max_packet_size); - fsdev_write_packet_memory(pma_addr, &(edpt->buffer[channel->queued_len[TUSB_DIR_OUT]]), len); + fsdev_write_packet_memory(pma_addr, &(edpt->buffer[edpt->queued_len]), len); btable_set_count(ch_id, BTABLE_BUF_TX, len); - channel->queued_len[TUSB_DIR_OUT] += len; + edpt->queued_len += len; } else { btable_set_rx_bufsize(ch_id, BTABLE_BUF_RX, edpt->max_packet_size); } - if (edpt->low_speed == 1) { + if (edpt->ls_pre == 1) { ch_reg |= USB_CHEP_LSEP; } else { ch_reg &= ~USB_CHEP_LSEP; } + // Setup DATA/STATUS phase start with DATA1 if (tu_edpt_number(edpt->ep_addr) == 0) { edpt->pid = 1; } if (edpt->next_setup) { - // Setup packet uses IN token edpt->next_setup = false; ch_reg |= USB_EP_SETUP; edpt->pid = 0; -- cgit v1.3.1 From c6b94db2990bf9975650c2879f4aabdade6f90d0 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 28 Nov 2025 00:11:08 +0100 Subject: Use one endpoint for EP0 Signed-off-by: HiFiPhile --- src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c | 35 +++++++++++---------------- 1 file changed, 14 insertions(+), 21 deletions(-) (limited to 'src/portable') diff --git a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c index ff2f2946e..22a74efbe 100644 --- a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c @@ -575,19 +575,6 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const edpt->pid = 0; edpt->ls_pre = (hcd_port_speed_get(rhport) == TUSB_SPEED_FULL && tuh_speed_get(dev_addr) == TUSB_SPEED_LOW) ? 1 : 0; - // EP0 is bi-directional, so we need to open both OUT and IN channels - if (ep_addr == 0) { - uint8_t const ep_id_in = endpoint_alloc(); - if (ep_id_in == TUSB_INDEX_INVALID_8) { - // free previously allocated OUT endpoint - endpoint_dealloc(edpt); - TU_ASSERT(false); - } - - _hcd_data.edpt[ep_id_in] = *edpt; // copy from OUT endpoint - _hcd_data.edpt[ep_id_in].ep_addr = 0 | TUSB_DIR_IN_MASK; - } - return true; } @@ -599,13 +586,6 @@ bool hcd_edpt_close(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { edpoint_close(ep_id); - if (ep_addr == 0) { - uint8_t const ep_id_in = endpoint_find(dev_addr, 0 | TUSB_DIR_IN_MASK); - TU_ASSERT(ep_id_in != TUSB_INDEX_INVALID_8); - - edpoint_close(ep_id_in); - } - return true; } @@ -624,6 +604,12 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *b edpt->buflen = buflen; edpt->queued_len = 0; + uint8_t const ep_num = tu_edpt_number(ep_addr); + if (ep_num == 0) { + // update ep_dir since control endpoint can switch direction + edpt->ep_addr = ep_addr; + } + return edpt_xfer_kickoff(ep_id); } @@ -696,9 +682,16 @@ static uint8_t endpoint_alloc(void) { } static uint8_t endpoint_find(uint8_t dev_addr, uint8_t ep_addr) { + uint8_t const ep_num = tu_edpt_number(ep_addr); + tusb_dir_t const ep_dir = tu_edpt_dir(ep_addr); + for (uint32_t i = 0; i < (uint32_t)CFG_TUH_FSDEV_ENDPOINT_MAX; i++) { hcd_endpoint_t* edpt = &_hcd_data.edpt[i]; - if (edpt->allocated == 1 && edpt->dev_addr == dev_addr && edpt->ep_addr == ep_addr) { + tusb_dir_t const dir = tu_edpt_dir(edpt->ep_addr); + uint8_t const num = tu_edpt_number(edpt->ep_addr); + // Match both ep_num and ep_dir, or match ep_num 0 (control endpoint) + if (edpt->allocated == 1 && edpt->dev_addr == dev_addr && num == ep_num && + (dir == ep_dir || ep_num == 0)) { return i; } } -- cgit v1.3.1 From 7d012b014eb27de9a5f34da543c707109c653045 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 28 Nov 2025 12:55:56 +0700 Subject: fix build with zephyr with latest nrfx v4 --- examples/device/cdc_msc/prj.conf | 1 - examples/device/msc_dual_lun/prj.conf | 1 - hw/bsp/nrf/family.c | 9 +++++++ hw/bsp/nrf/family.cmake | 4 ++- src/portable/nordic/nrf5x/dcd_nrf5x.c | 47 ++++++++++++++++++++--------------- 5 files changed, 39 insertions(+), 23 deletions(-) (limited to 'src/portable') diff --git a/examples/device/cdc_msc/prj.conf b/examples/device/cdc_msc/prj.conf index 2f5139d9d..9e86a118d 100644 --- a/examples/device/cdc_msc/prj.conf +++ b/examples/device/cdc_msc/prj.conf @@ -3,4 +3,3 @@ CONFIG_FPU=y CONFIG_NO_OPTIMIZATIONS=y CONFIG_UART_INTERRUPT_DRIVEN=y CONFIG_NRFX_POWER=y -CONFIG_NRFX_UARTE0=y diff --git a/examples/device/msc_dual_lun/prj.conf b/examples/device/msc_dual_lun/prj.conf index 2f5139d9d..9e86a118d 100644 --- a/examples/device/msc_dual_lun/prj.conf +++ b/examples/device/msc_dual_lun/prj.conf @@ -3,4 +3,3 @@ CONFIG_FPU=y CONFIG_NO_OPTIMIZATIONS=y CONFIG_UART_INTERRUPT_DRIVEN=y CONFIG_NRFX_POWER=y -CONFIG_NRFX_UARTE0=y diff --git a/hw/bsp/nrf/family.c b/hw/bsp/nrf/family.c index 25062b18f..ee3ac61e2 100644 --- a/hw/bsp/nrf/family.c +++ b/hw/bsp/nrf/family.c @@ -100,7 +100,9 @@ static nrfx_uarte_t _uart_id = NRFX_UARTE_INSTANCE(120); #define OUTPUTRDY_Msk POWER_USBREGSTATUS_OUTPUTRDY_Msk #endif +#if CFG_TUSB_OS != OPT_OS_ZEPHYR static nrfx_uarte_t _uart_id = NRFX_UARTE_INSTANCE(0); +#endif void USBD_IRQHandler(void) { tud_int_handler(0); @@ -163,6 +165,7 @@ void board_init(void) { irq_enable(DT_INST_IRQN(0)); #endif +#if CFG_TUSB_OS != OPT_OS_ZEPHYR // UART nrfx_uarte_config_t uart_cfg = { .txd_pin = UART_TX_PIN, @@ -179,6 +182,7 @@ void board_init(void) { }; nrfx_uarte_init(&_uart_id, &uart_cfg, NULL); +#endif //------------- USB -------------// #if CFG_TUD_ENABLED @@ -276,8 +280,13 @@ int board_uart_read(uint8_t* buf, int len) { } int board_uart_write(void const* buf, int len) { +#if CFG_TUSB_OS == OPT_OS_ZEPHYR + (void) buf; + return len; +#else nrfx_err_t err = nrfx_uarte_tx(&_uart_id, (uint8_t const*) buf, (size_t) len ,0); return (NRFX_SUCCESS == err) ? len : 0; +#endif } #if CFG_TUSB_OS == OPT_OS_NONE diff --git a/hw/bsp/nrf/family.cmake b/hw/bsp/nrf/family.cmake index 4e999b636..3a6e7cc8b 100644 --- a/hw/bsp/nrf/family.cmake +++ b/hw/bsp/nrf/family.cmake @@ -127,7 +127,9 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - if (NOT RTOS STREQUAL zephyr) + if (RTOS STREQUAL zephyr) + target_include_directories(${TARGET} PUBLIC ${ZEPHYR_HAL_NORDIC_MODULE_DIR}/nrfx/bsp/stable/mdk) + else () target_sources(${TARGET} PRIVATE ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}) if (CMAKE_C_COMPILER_ID STREQUAL "GNU") diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c index 82b6db5fd..8a41c4790 100644 --- a/src/portable/nordic/nrf5x/dcd_nrf5x.c +++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c @@ -59,21 +59,26 @@ /* Try to detect nrfx version if not configured with CFG_TUD_NRF_NRFX_VERSION * nrfx v1 and v2 are concurrently developed. There is no NRFX_VERSION only MDK VERSION which is as follows: * - v3.0.0: 8.53.1 (conflict with v2.11.0), v3.1.0: 8.55.0 ... - * - v2.11.0: 8.53.1, v2.6.0: 8.44.1, v2.5.0: 8.40.2, v2.4.0: 8.37.0, v2.3.0: 8.35.0, v2.2.0: 8.32.1, v2.1.0: 8.30.2, v2.0.0: 8.29.0 + * - v2.11.0: 8.53.1, v2.6.0: 8.44.1, v2.5.0: 8.40.2, v2.4.0: 8.37.0, v2.3.0: 8.35.0, v2.2.0: 8.32.1, v2.1.0: 8.30.2, + * v2.0.0: 8.29.0 * - v1.9.0: 8.40.3, v1.8.6: 8.35.0 (conflict with v2.3.0), v1.8.5: 8.32.3, v1.8.4: 8.32.1 (conflict with v2.2.0), * v1.8.2: 8.32.1 (conflict with v2.2.0), v1.8.1: 8.27.1 * Therefore the check for v1 would be: * - MDK < 8.29.0 (v2.0), MDK == 8.32.3, 8.40.3 * - in case of conflict User of those version must upgrade to other 1.x version or set CFG_TUD_NRF_NRFX_VERSION -*/ + */ #ifndef CFG_TUD_NRF_NRFX_VERSION - #define _MDK_VERSION (10000*MDK_MAJOR_VERSION + 100*MDK_MINOR_VERSION + MDK_MICRO_VERSION) + #define MDK_VERSION (10000 * MDK_MAJOR_VERSION + 100 * MDK_MINOR_VERSION + MDK_MICRO_VERSION) - #if _MDK_VERSION < 82900 || _MDK_VERSION == 83203 || _MDK_VERSION == 84003 + #if MDK_VERSION < 82900 || MDK_VERSION == 83203 || MDK_VERSION == 84003 // nrfx <= 1.8.1, or 1.8.5 or 1.9.0 #define CFG_TUD_NRF_NRFX_VERSION 1 - #else + #elif MDK_VERSION < 85301 #define CFG_TUD_NRF_NRFX_VERSION 2 + #elif MDK_VERSION < 87300 + #define CFG_TUD_NRF_NRFX_VERSION 3 + #else + #define CFG_TUD_NRF_NRFX_VERSION 4 #endif #endif @@ -845,19 +850,19 @@ TU_ATTR_ALWAYS_INLINE static inline bool is_sd_enabled(void) { #endif static bool hfclk_running(void) { -#ifdef SOFTDEVICE_PRESENT - if ( is_sd_enabled() ) { + #ifdef SOFTDEVICE_PRESENT + if (is_sd_enabled()) { uint32_t is_running = 0; - (void) sd_clock_hfclk_is_running(&is_running); + (void)sd_clock_hfclk_is_running(&is_running); return (is_running ? true : false); } -#endif + #endif -#if CFG_TUD_NRF_NRFX_VERSION == 1 + #if CFG_TUD_NRF_NRFX_VERSION == 1 return nrf_clock_hf_is_running(NRF_CLOCK_HFCLK_HIGH_ACCURACY); -#else - return nrf_clock_hf_is_running(NRF_CLOCK, NRF_CLOCK_HFCLK_HIGH_ACCURACY); -#endif + #else + return nrf_clock_is_running(NRF_CLOCK, NRF_CLOCK_DOMAIN_HFCLK, NULL); + #endif } static void hfclk_enable(void) { @@ -867,22 +872,24 @@ static void hfclk_enable(void) { #else // already running, nothing to do - if (hfclk_running()) return; + if (hfclk_running()) { + return; + } -#ifdef SOFTDEVICE_PRESENT - if ( is_sd_enabled() ) { + #ifdef SOFTDEVICE_PRESENT + if (is_sd_enabled()) { (void)sd_clock_hfclk_request(); return; } -#endif + #endif -#if CFG_TUD_NRF_NRFX_VERSION == 1 + #if CFG_TUD_NRF_NRFX_VERSION == 1 nrf_clock_event_clear(NRF_CLOCK_EVENT_HFCLKSTARTED); nrf_clock_task_trigger(NRF_CLOCK_TASK_HFCLKSTART); -#else + #else nrf_clock_event_clear(NRF_CLOCK, NRF_CLOCK_EVENT_HFCLKSTARTED); nrf_clock_task_trigger(NRF_CLOCK, NRF_CLOCK_TASK_HFCLKSTART); -#endif + #endif #endif } -- cgit v1.3.1 From 1ffe00b4363fc2d76751270118091fc3a3a1b92b Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 28 Nov 2025 13:18:10 +0100 Subject: Fix deinit glitch Signed-off-by: HiFiPhile --- src/portable/st/stm32_fsdev/fsdev_common.c | 5 --- src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c | 47 +++++++++++++++++---------- 2 files changed, 30 insertions(+), 22 deletions(-) (limited to 'src/portable') diff --git a/src/portable/st/stm32_fsdev/fsdev_common.c b/src/portable/st/stm32_fsdev/fsdev_common.c index 4f95d9d7f..60ef339a6 100644 --- a/src/portable/st/stm32_fsdev/fsdev_common.c +++ b/src/portable/st/stm32_fsdev/fsdev_common.c @@ -37,11 +37,6 @@ // Reset the USB Core void fsdev_core_reset(void) { - // Follow the RM mentions to use a special ordering of PDWN and FRES - for (volatile uint32_t i = 0; i < 200; i++) { // should be a few us - asm("NOP"); - } - // Perform USB peripheral reset FSDEV_REG->CNTR = USB_CNTR_FRES | USB_CNTR_PDWN; for (volatile uint32_t i = 0; i < 200; i++) { // should be a few us diff --git a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c index 22a74efbe..212f620ac 100644 --- a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c @@ -59,6 +59,20 @@ TU_VERIFY_STATIC(CFG_TUH_FSDEV_ENDPOINT_MAX <= 255, "currently only use 8-bit for index"); +#if CFG_TUSB_MCU == OPT_MCU_STM32H5 + #define CPU_FREQUENCY_MHZ 250U +#elif CFG_TUSB_MCU == OPT_MCU_STM32U5 + #define CPU_FREQUENCY_MHZ 160U +#elif CFG_TUSB_MCU == OPT_MCU_STM32U3 + #define CPU_FREQUENCY_MHZ 96U +#elif CFG_TUSB_MCU == OPT_MCU_STM32G0 + #define CPU_FREQUENCY_MHZ 64U +#elif CFG_TUSB_MCU == OPT_MCU_STM32C0 + #define CPU_FREQUENCY_MHZ 48U +#else + #error "CPU_FREQUENCY_MHZ not defined for this STM32 MCU" +#endif + enum { HCD_XFER_ERROR_MAX = 3, HCD_XFER_NAK_MAX = 15, @@ -122,6 +136,7 @@ static uint8_t channel_alloc(uint8_t dev_addr, uint8_t ep_addr, uint8_t ep_type) static bool edpt_xfer_kickoff(uint8_t ep_id); static bool channel_xfer_start(uint8_t ch_id, tusb_dir_t dir); static void edpoint_close(uint8_t ep_id); +static void port_status_handler(uint8_t rhport, bool in_isr); static void ch_handle_ack(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir); static void ch_handle_nak(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir); static void ch_handle_stall(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir); @@ -166,30 +181,16 @@ static inline uint16_t channel_get_rx_count(uint8_t ch_id) { * We choose the delay count based on max CPU frequency (in MHz) to ensure the delay is at least the required time. */ -#if CFG_TUSB_MCU == OPT_MCU_STM32H5 - #define FREQUENCY_MHZ 250U -#elif CFG_TUSB_MCU == OPT_MCU_STM32U5 - #define FREQUENCY_MHZ 160U -#elif CFG_TUSB_MCU == OPT_MCU_STM32U3 - #define FREQUENCY_MHZ 96U -#elif CFG_TUSB_MCU == OPT_MCU_STM32G0 - #define FREQUENCY_MHZ 64U -#elif CFG_TUSB_MCU == OPT_MCU_STM32C0 - #define FREQUENCY_MHZ 48U -#else - #error "FREQUENCY_MHZ not defined for this STM32 MCU" -#endif - uint32_t ch_reg = ch_read(ch_id); if (FSDEV_REG->ISTR & USB_ISTR_LS_DCONN || ch_reg & USB_CHEP_LSEP) { // Low speed mode: 6.4 us delay -> about 2 cycles per MHz - volatile uint32_t cycle_count = FREQUENCY_MHZ * 2U; + volatile uint32_t cycle_count = CPU_FREQUENCY_MHZ * 2U; while (cycle_count > 0U) { cycle_count--; // each count take 3 cycles (1 for sub, jump, and compare) } } else { // Full speed mode: 800 ns delay -> about 0.25 cycles per MHz - volatile uint32_t cycle_count = FREQUENCY_MHZ / 4U; + volatile uint32_t cycle_count = CPU_FREQUENCY_MHZ / 4U; while (cycle_count > 0U) { cycle_count--; // each count take 3 cycles (1 for sub, jump, and compare) } @@ -231,12 +232,24 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { fsdev_connect(rhport); + // If DCON_STAT is already set, the controller sometimes misses the initial connection interrupt + if (FSDEV_REG->ISTR & USB_ISTR_DCON_STAT) { + // Wait DP/DM stabilize time + volatile uint32_t cycle_count = CPU_FREQUENCY_MHZ / 4U; + while (cycle_count > 0U) { + cycle_count--; + } + port_status_handler(rhport, false); + } + return true; } bool hcd_deinit(uint8_t rhport) { (void)rhport; + fsdev_disconnect(rhport); + fsdev_deinit(); return true; @@ -259,7 +272,7 @@ static inline void sof_handler(void) { } } -static inline void port_status_handler(uint8_t rhport, bool in_isr) { +static void port_status_handler(uint8_t rhport, bool in_isr) { uint32_t const fnr_reg = FSDEV_REG->FNR; uint32_t const istr_reg = FSDEV_REG->ISTR; // SE0 detected USB Disconnected state -- cgit v1.3.1 From df6f13600324b42710ae71d5320a9f2eae8303a5 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 1 Dec 2025 14:39:45 +0700 Subject: add linkermap to deps and linkermap taget --- .gitignore | 1 + .idea/cmake.xml | 1 + examples/build_system/cmake/toolchain/arm_iar.cmake | 3 ++- hw/bsp/family_support.cmake | 15 +++++++++++++++ src/portable/synopsys/dwc2/dwc2_info.py | 1 - test/hil/hil_test.py | 2 +- tools/get_deps.py | 3 +++ 7 files changed, 23 insertions(+), 3 deletions(-) (limited to 'src/portable') diff --git a/.gitignore b/.gitignore index 977911dff..93d13503f 100644 --- a/.gitignore +++ b/.gitignore @@ -42,6 +42,7 @@ cov-int *-build-dir /_bin/ __pycache__ +cmake-build/ cmake-build-* sdkconfig .PVS-Studio diff --git a/.idea/cmake.xml b/.idea/cmake.xml index 677aaa662..0754253ad 100644 --- a/.idea/cmake.xml +++ b/.idea/cmake.xml @@ -124,6 +124,7 @@ + diff --git a/examples/build_system/cmake/toolchain/arm_iar.cmake b/examples/build_system/cmake/toolchain/arm_iar.cmake index 0b7e0b585..67d100bbc 100644 --- a/examples/build_system/cmake/toolchain/arm_iar.cmake +++ b/examples/build_system/cmake/toolchain/arm_iar.cmake @@ -24,7 +24,8 @@ set(CMAKE_C_ICSTAT ${CMAKE_IAR_CSTAT} --checks=${CMAKE_CURRENT_LIST_DIR}/cstat_sel_checks.txt --db=${CMAKE_BINARY_DIR}/cstat.db --sarif_dir=${CMAKE_BINARY_DIR}/cstat_sarif - --exclude ${TOP}/hw/mcu --exclude ${TOP}/lib + --exclude=${TOP}/hw/mcu + --exclude=${TOP}/lib ) endif () diff --git a/hw/bsp/family_support.cmake b/hw/bsp/family_support.cmake index 2b9612186..5afec32c2 100644 --- a/hw/bsp/family_support.cmake +++ b/hw/bsp/family_support.cmake @@ -9,6 +9,7 @@ set(TOP "${CMAKE_CURRENT_LIST_DIR}/../..") get_filename_component(TOP ${TOP} ABSOLUTE) set(UF2CONV_PY ${TOP}/tools/uf2/utils/uf2conv.py) +set(LINKERMAP_PY ${TOP}/tools/linkermap/linkermap.py) function(family_resolve_board BOARD_NAME BOARD_PATH_OUT) if ("${BOARD_NAME}" STREQUAL "") @@ -223,6 +224,18 @@ function(family_initialize_project PROJECT DIR) endif() endfunction() +# Add linkermap target (https://github.com/hathach/linkermap) +function(family_add_linkermap TARGET) + set(LINKERMAP_OPTION "") + if (ARGC GREATER 1) + set(LINKERMAP_OPTION "${ARGV1}") + endif () + add_custom_target(${TARGET}-linkermap + COMMAND python ${LINKERMAP_PY} -j -m ${LINKERMAP_OPTION} $.map + VERBATIM + ) +endfunction() + #------------------------------------------------------------- # Common Target Configure # Most families use these settings except rp2040 and espressif @@ -332,6 +345,8 @@ function(family_configure_common TARGET RTOS) endif () endif () + family_add_linkermap(${TARGET}) + # run size after build # find_program(SIZE_EXE ${CMAKE_SIZE}) # if(NOT ${SIZE_EXE} STREQUAL SIZE_EXE-NOTFOUND) diff --git a/src/portable/synopsys/dwc2/dwc2_info.py b/src/portable/synopsys/dwc2/dwc2_info.py index f6bd2785a..8fbbc00a0 100755 --- a/src/portable/synopsys/dwc2/dwc2_info.py +++ b/src/portable/synopsys/dwc2/dwc2_info.py @@ -2,7 +2,6 @@ import ctypes import argparse -import click import pandas as pd # hex value for register: guid, gsnpsid, ghwcfg1, ghwcfg2, ghwcfg3, ghwcfg4 diff --git a/test/hil/hil_test.py b/test/hil/hil_test.py index ba0826bd3..b2e883119 100755 --- a/test/hil/hil_test.py +++ b/test/hil/hil_test.py @@ -662,7 +662,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 = 1 + max_rety = 3 start_s = time.time() for i in range(max_rety): ret = globals()[f'flash_{board["flasher"]["name"].lower()}'](board, fw_name) diff --git a/tools/get_deps.py b/tools/get_deps.py index d749e4c84..c60766e50 100755 --- a/tools/get_deps.py +++ b/tools/get_deps.py @@ -14,6 +14,9 @@ deps_mandatory = { 'lib/lwip': ['https://github.com/lwip-tcpip/lwip.git', '159e31b689577dbf69cf0683bbaffbd71fa5ee10', 'all'], + 'tools/linkermap': ['https://github.com/hathach/linkermap.git', + 'e1a7a990fcd6eb1dbae13c2eb9fb0ca9db7ac483', + 'all'], 'tools/uf2': ['https://github.com/microsoft/uf2.git', 'c594542b2faa01cc33a2b97c9fbebc38549df80a', 'all'], -- cgit v1.3.1 From 06f1597c0e55a862bce2eac0b2058cb6f6cea54b Mon Sep 17 00:00:00 2001 From: Zixun LI Date: Tue, 2 Dec 2025 11:51:08 +0100 Subject: limit to bulk ep Signed-off-by: Zixun LI --- src/portable/synopsys/dwc2/dcd_dwc2.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'src/portable') diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index 8a8600301..ba40498e6 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -191,7 +191,7 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t calc_device_grxfsiz(uint16_t larges return 13 + 1 + 2 * ((largest_ep_size / 4) + 1) + 2 * ep_count; } -static bool dfifo_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t packet_size) { +static bool dfifo_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t packet_size, bool is_bulk) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); const dwc2_controller_t* dwc2_controller = &_dwc2_controller[rhport]; const uint8_t ep_count = dwc2_controller->ep_count; @@ -217,8 +217,9 @@ static bool dfifo_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t packet_size) { _dcd_data.allocated_epin_count++; } - // Enable double buffering if configured - if (((_tud_cfg.bm_double_buffered & (1 << epnum)) != 0) && (epnum > 0)) { + // Enable double buffering if configured, only effective for non-periodic endpoints + // Since we queue only 1 control transfer at a time, it's only applicable for bulk IN endpoints + if (((_tud_cfg.bm_double_buffered & (1 << epnum)) != 0) && epnum > 0 && is_bulk) { fifo_size *= 2; } @@ -253,7 +254,7 @@ static void dfifo_device_init(uint8_t rhport) { dwc2->gdfifocfg = ((uint32_t) _dcd_data.dfifo_top << GDFIFOCFG_EPINFOBASE_SHIFT) | _dcd_data.dfifo_top; // Allocate FIFO for EP0 IN - (void) dfifo_alloc(rhport, 0x80, CFG_TUD_ENDPOINT0_SIZE); + (void) dfifo_alloc(rhport, 0x80, CFG_TUD_ENDPOINT0_SIZE, false); } @@ -603,7 +604,8 @@ void dcd_sof_enable(uint8_t rhport, bool en) { *------------------------------------------------------------------*/ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const* desc_edpt) { - TU_ASSERT(dfifo_alloc(rhport, desc_edpt->bEndpointAddress, tu_edpt_packet_size(desc_edpt))); + TU_ASSERT(dfifo_alloc(rhport, desc_edpt->bEndpointAddress, tu_edpt_packet_size(desc_edpt), + desc_edpt->bmAttributes.xfer == TUSB_XFER_BULK)); edpt_activate(rhport, desc_edpt); return true; } @@ -638,7 +640,7 @@ void dcd_edpt_close_all(uint8_t rhport) { } bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { - TU_ASSERT(dfifo_alloc(rhport, ep_addr, largest_packet_size)); + TU_ASSERT(dfifo_alloc(rhport, ep_addr, largest_packet_size, false)); return true; } -- cgit v1.3.1 From 919ee4b1527469e327710cff936366328f97294a Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 9 Dec 2025 20:11:18 +0700 Subject: update metrics to support bloaty csv --- .circleci/config2.yml | 1 - .github/workflows/build.yml | 3 +- .../build_system/cmake/toolchain/arm_clang.cmake | 1 - examples/build_system/cmake/toolchain/common.cmake | 41 +++--- hw/bsp/family_support.cmake | 33 ++--- src/common/tusb_compiler.h | 6 +- src/portable/synopsys/dwc2/hcd_dwc2.c | 2 +- tools/get_deps.py | 2 +- tools/metrics.py | 152 ++++++++++++--------- 9 files changed, 124 insertions(+), 117 deletions(-) (limited to 'src/portable') diff --git a/.circleci/config2.yml b/.circleci/config2.yml index a39682067..352d0f4fa 100644 --- a/.circleci/config2.yml +++ b/.circleci/config2.yml @@ -227,7 +227,6 @@ jobs: name: Aggregate Code Metrics command: | python tools/get_deps.py - pip install tools/linkermap/ # Combine all metrics files from all toolchain subdirectories ls -R /tmp/metrics if ls /tmp/metrics/*/*.json 1> /dev/null 2>&1; then diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5017cb3cd..9d94a3b9b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -100,7 +100,6 @@ jobs: - name: Aggregate Code Metrics run: | python tools/get_deps.py - pip install tools/linkermap/ python tools/metrics.py combine -j -m -f tinyusb/src cmake-build/*/metrics.json - name: Upload Metrics Artifact @@ -124,7 +123,7 @@ jobs: if: github.event_name != 'push' run: | if [ -f base-metrics/metrics.json ]; then - python tools/metrics.py compare -f tinyusb/src base-metrics/metrics.json metrics.json + python tools/metrics.py compare -m -f tinyusb/src base-metrics/metrics.json metrics.json cat metrics_compare.md else echo "No base metrics found, skipping comparison" diff --git a/examples/build_system/cmake/toolchain/arm_clang.cmake b/examples/build_system/cmake/toolchain/arm_clang.cmake index dba637367..e5ca82fab 100644 --- a/examples/build_system/cmake/toolchain/arm_clang.cmake +++ b/examples/build_system/cmake/toolchain/arm_clang.cmake @@ -7,7 +7,6 @@ if (NOT DEFINED CMAKE_CXX_COMPILER) endif () set(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER}) -set(TOOLCHAIN_ASM_FLAGS "-x assembler-with-cpp") find_program(CMAKE_SIZE llvm-size) find_program(CMAKE_OBJCOPY llvm-objcopy) diff --git a/examples/build_system/cmake/toolchain/common.cmake b/examples/build_system/cmake/toolchain/common.cmake index 1ef04bc00..e610a349b 100644 --- a/examples/build_system/cmake/toolchain/common.cmake +++ b/examples/build_system/cmake/toolchain/common.cmake @@ -20,41 +20,32 @@ include(${CMAKE_CURRENT_LIST_DIR}/../cpu/${CMAKE_SYSTEM_CPU}.cmake) # ---------------------------------------------------------------------------- # Compile flags # ---------------------------------------------------------------------------- +set(TOOLCHAIN_C_FLAGS) +set(TOOLCHAIN_ASM_FLAGS) +set(TOOLCHAIN_EXE_LINKER_FLAGS) + if (TOOLCHAIN STREQUAL "gcc" OR TOOLCHAIN STREQUAL "clang") list(APPEND TOOLCHAIN_COMMON_FLAGS -fdata-sections -ffunction-sections # -fsingle-precision-constant # not supported by clang -fno-strict-aliasing - -g - ) - list(APPEND TOOLCHAIN_EXE_LINKER_FLAGS - -Wl,--print-memory-usage - -Wl,--gc-sections - -Wl,--cref + -g # include debug info for bloaty ) + set(TOOLCHAIN_EXE_LINKER_FLAGS "-Wl,--print-memory-usage -Wl,--gc-sections -Wl,--cref") + + if (TOOLCHAIN STREQUAL clang) + set(TOOLCHAIN_ASM_FLAGS "-x assembler-with-cpp") + endif () elseif (TOOLCHAIN STREQUAL "iar") - list(APPEND TOOLCHAIN_COMMON_FLAGS - --debug - ) - list(APPEND TOOLCHAIN_EXE_LINKER_FLAGS - --diag_suppress=Li065 - ) + set(TOOLCHAIN_C_FLAGS --debug) + set(TOOLCHAIN_EXE_LINKER_FLAGS --diag_suppress=Li065) endif () # join the toolchain flags into a single string list(JOIN TOOLCHAIN_COMMON_FLAGS " " TOOLCHAIN_COMMON_FLAGS) -foreach (LANG IN ITEMS C CXX ASM) - set(CMAKE_${LANG}_FLAGS_INIT ${TOOLCHAIN_COMMON_FLAGS}) - # optimization flags for LOG, LOGGER ? - #set(CMAKE_${LANG}_FLAGS_RELEASE_INIT "-Os") - #set(CMAKE_${LANG}_FLAGS_DEBUG_INIT "-O0") -endforeach () - -# Assembler -if (DEFINED TOOLCHAIN_ASM_FLAGS) - set(CMAKE_ASM_FLAGS_INIT "${CMAKE_ASM_FLAGS_INIT} ${TOOLCHAIN_ASM_FLAGS}") -endif () -# Linker -list(JOIN TOOLCHAIN_EXE_LINKER_FLAGS " " CMAKE_EXE_LINKER_FLAGS_INIT) +set(CMAKE_C_FLAGS_INIT "${TOOLCHAIN_COMMON_FLAGS} ${TOOLCHAIN_C_FLAGS}") +set(CMAKE_CXX_FLAGS_INIT "${TOOLCHAIN_COMMON_FLAGS} ${TOOLCHAIN_C_FLAGS}") +set(CMAKE_ASM_FLAGS_INIT "${TOOLCHAIN_COMMON_FLAGS} ${TOOLCHAIN_ASM_FLAGS}") +set(CMAKE_EXE_LINKER_FLAGS_INIT ${TOOLCHAIN_EXE_LINKER_FLAGS}) diff --git a/hw/bsp/family_support.cmake b/hw/bsp/family_support.cmake index 62ec412e6..5eadcdaa9 100644 --- a/hw/bsp/family_support.cmake +++ b/hw/bsp/family_support.cmake @@ -232,7 +232,7 @@ function(family_add_bloaty TARGET) return() endif () - set(OPTION "--domain=vm -d compileunits") # add -d symbol if needed + set(OPTION "--domain=vm -d compileunits,sections,symbols") if (DEFINED BLOATY_OPTION) string(APPEND OPTION " ${BLOATY_OPTION}") endif () @@ -240,36 +240,33 @@ function(family_add_bloaty TARGET) add_custom_target(${TARGET}-bloaty DEPENDS ${TARGET} - COMMAND ${BLOATY_EXE} ${OPTION_LIST} $ > $.bloaty.txt - COMMAND cat $.bloaty.txt + COMMAND ${BLOATY_EXE} ${OPTION_LIST} $ VERBATIM) # post build - add_custom_command(TARGET ${TARGET} POST_BUILD - COMMAND ${BLOATY_EXE} ${OPTION_LIST} $ > $.bloaty.txt - COMMAND cat $.bloaty.txt - VERBATIM - ) + # add_custom_command(TARGET ${TARGET} POST_BUILD + # COMMAND ${BLOATY_EXE} --csv ${OPTION_LIST} $ > ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}_bloaty.csv + # VERBATIM + # ) endfunction() # Add linkermap target (https://github.com/hathach/linkermap) function(family_add_linkermap TARGET) - set(LINKERMAP_OPTION_LIST) + set(OPTION "-j") if (DEFINED LINKERMAP_OPTION) - separate_arguments(LINKERMAP_OPTION_LIST UNIX_COMMAND ${LINKERMAP_OPTION}) + string(APPEND OPTION " ${LINKERMAP_OPTION}") endif () + separate_arguments(OPTION_LIST UNIX_COMMAND ${OPTION}) add_custom_target(${TARGET}-linkermap - COMMAND python ${LINKERMAP_PY} ${LINKERMAP_OPTION_LIST} $.map + COMMAND python ${LINKERMAP_PY} ${OPTION_LIST} $.map VERBATIM ) - # post build if bloaty not exist - if (NOT TARGET ${TARGET}-bloaty) - add_custom_command(TARGET ${TARGET} POST_BUILD - COMMAND python ${LINKERMAP_PY} ${LINKERMAP_OPTION_LIST} $.map - VERBATIM) - endif () + # post build + add_custom_command(TARGET ${TARGET} POST_BUILD + COMMAND python ${LINKERMAP_PY} ${OPTION_LIST} $.map + VERBATIM) endfunction() #------------------------------------------------------------- @@ -384,7 +381,7 @@ function(family_configure_common TARGET RTOS) if (NOT RTOS STREQUAL zephyr) # Analyze size with bloaty and linkermap family_add_bloaty(${TARGET}) - family_add_linkermap(${TARGET}) # fall back to linkermap if bloaty not found + family_add_linkermap(${TARGET}) endif () # run size after build diff --git a/src/common/tusb_compiler.h b/src/common/tusb_compiler.h index c8108264f..f20834cea 100644 --- a/src/common/tusb_compiler.h +++ b/src/common/tusb_compiler.h @@ -183,11 +183,11 @@ #define TU_BSWAP32(u32) (__builtin_bswap32(u32)) #endif - #ifndef __ARMCC_VERSION // List of obsolete callback function that is renamed and should not be defined. // Put it here since only gcc support this pragma - #pragma GCC poison tud_vendor_control_request_cb - #endif + #if !defined(__ARMCC_VERSION) && !defined(__ICCARM__) + #pragma GCC poison tud_vendor_control_request_cb + #endif #elif defined(__ICCARM__) #include diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index b92448685..fc748c85f 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -821,7 +821,7 @@ static void channel_xfer_in_retry(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hci } } -#if CFG_TUSB_DEBUG +#if CFG_TUSB_DEBUG && 0 TU_ATTR_ALWAYS_INLINE static inline void print_hcint(uint32_t hcint) { const char* str[] = { "XFRC", "HALTED", "AHBERR", "STALL", diff --git a/tools/get_deps.py b/tools/get_deps.py index f11d8d51e..0d9c1a8f1 100755 --- a/tools/get_deps.py +++ b/tools/get_deps.py @@ -15,7 +15,7 @@ deps_mandatory = { '159e31b689577dbf69cf0683bbaffbd71fa5ee10', 'all'], 'tools/linkermap': ['https://github.com/hathach/linkermap.git', - '23d1c4c84c4866b84cb821fb368bb9991633871d', + '8e1f440fa15c567aceb5aa0d14f6d18c329cc67f', 'all'], 'tools/uf2': ['https://github.com/microsoft/uf2.git', 'c594542b2faa01cc33a2b97c9fbebc38549df80a', diff --git a/tools/metrics.py b/tools/metrics.py index f879a0d34..50709d5ba 100644 --- a/tools/metrics.py +++ b/tools/metrics.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -"""Calculate average sizes using bloaty output.""" +"""Calculate average sizes from bloaty CSV or TinyUSB metrics JSON outputs.""" import argparse import csv @@ -85,7 +85,7 @@ def parse_bloaty_csv(csv_text, filters=None): def combine_files(input_files, filters=None): - """Combine multiple bloaty outputs into a single data set.""" + """Combine multiple metrics inputs (bloaty CSV or metrics JSON) into a single data set.""" filters = filters or [] all_json_data = {"file_list": [], "data": []} @@ -168,12 +168,6 @@ def compute_avg(all_json_data): continue file_accumulator[fname]["symbols"][name].append(sym.get("size", 0)) sections_map = f.get("sections") or {} - if isinstance(sections_map, list): - sections_map = { - s.get("name"): s.get("size", 0) - for s in sections_map - if isinstance(s, dict) and s.get("name") - } for sname, ssize in sections_map.items(): file_accumulator[fname]["sections"][sname].append(ssize) @@ -240,6 +234,8 @@ def compare_files(base_file, new_file, filters=None): n = new_files.get(fname, {}) b_size = b.get("size", 0) n_size = n.get("size", 0) + base_sections = b.get("sections") or {} + new_sections = n.get("sections") or {} # Symbol diffs b_syms = {s["name"]: s for s in b.get("symbols", [])} @@ -256,6 +252,14 @@ def compare_files(base_file, new_file, filters=None): "file": fname, "size": {"base": b_size, "new": n_size, "diff": n_size - b_size}, "symbols": symbols, + "sections": { + name: { + "base": base_sections.get(name, 0), + "new": new_sections.get(name, 0), + "diff": new_sections.get(name, 0) - base_sections.get(name, 0), + } + for name in sorted(set(base_sections) | set(new_sections)) + }, }) total = { @@ -299,6 +303,17 @@ def get_sort_key(sort_order): return lambda x: x.get('file', ''), False +def format_diff(base, new, diff): + """Format a diff value with percentage.""" + if diff == 0: + return f"{new}" + if base == 0 or new == 0: + return f"{base} ➙ {new}" + pct = (diff / base) * 100 + sign = "+" if diff > 0 else "" + return f"{base} ➙ {new} ({sign}{diff}, {sign}{pct:.1f}%)" + + def write_json_output(json_data, path): """Write JSON output with indentation.""" @@ -315,7 +330,7 @@ def render_combine_table(json_data, sort_order='name+'): key_func, reverse = get_sort_key(sort_order) files_sorted = sorted(files, key=key_func, reverse=reverse) - total_size = json_data.get("TOTAL") or (sum(f.get("size", 0) for f in files_sorted) or 1) + total_size = json_data.get("TOTAL") or sum(f.get("size", 0) for f in files_sorted) pct_strings = [ f"{(f.get('percent') if f.get('percent') is not None else (f.get('size', 0) / total_size * 100 if total_size else 0)):.1f}%" @@ -357,12 +372,6 @@ def render_combine_table(json_data, sort_order='name+'): parts = [f"| {f.get('file', ''):<{file_width}} |"] if section_names: sections_map = f.get("sections") or {} - if isinstance(sections_map, list): - sections_map = { - s.get("name"): s.get("size", 0) - for s in sections_map - if isinstance(s, dict) and s.get("name") - } for name in section_names: parts.append(f" {sections_map.get(name, 0):>{section_widths[name]}} |") parts.append(f" {size_val:>{size_width}} | {pct_str:>{pct_width}} |") @@ -469,6 +478,7 @@ def _build_rows(files, sort_order): "new": sd['new'], "diff": diff_val, "pct": pct_str, + "sections": f.get("sections", {}), }) return rows @@ -506,59 +516,68 @@ def render_compare_table(rows, include_sum): if not rows: return ["No entries.", ""] + # collect section columns (reverse alpha) + section_names = sorted( + {name for r in rows for name in (r.get("sections") or {})}, + reverse=True, + ) + + def fmt_abs(val_old, val_new): + diff = val_new - val_old + if diff == 0: + return f"{val_new}" + sign = "+" if diff > 0 else "" + return f"{val_old} ➙ {val_new} ({sign}{diff})" + sum_base = sum(r["base"] for r in rows) sum_new = sum(r["new"] for r in rows) total_diff = sum_new - sum_base total_pct = "n/a" if sum_base == 0 else f"{(total_diff / sum_base) * 100:+.1f}%" - base_width = max(len("base"), *(len(str(r["base"])) for r in rows)) - new_width = max(len("new"), *(len(str(r["new"])) for r in rows)) - diff_width = max(len("diff"), *(len(f"{r['diff']:+}") for r in rows)) - pct_width = max(len("% diff"), *(len(r["pct"]) for r in rows)) - name_width = max(len("file"), *(len(r["file"]) for r in rows)) - - if include_sum: - base_width = max(base_width, len(str(sum_base))) - new_width = max(new_width, len(str(sum_new))) - diff_width = max(diff_width, len(f"{total_diff:+}")) - pct_width = max(pct_width, len(total_pct)) - name_width = max(name_width, len("TOTAL")) - - header = ( - f"| {'file':<{name_width}} | " - f"{'base':>{base_width}} | " - f"{'new':>{new_width}} | " - f"{'diff':>{diff_width}} | " - f"{'% diff':>{pct_width}} |" - ) - separator = ( - f"| :{'-' * (name_width - 1)} | " - f"{'-' * base_width}:| " - f"{'-' * new_width}:| " - f"{'-' * diff_width}:| " - f"{'-' * pct_width}:|" + file_width = max(len("file"), *(len(r["file"]) for r in rows), len("TOTAL")) + size_width = max( + len("size"), + *(len(fmt_abs(r["base"], r["new"])) for r in rows), + len(fmt_abs(sum_base, sum_new)), ) + pct_width = max(len("% diff"), *(len(r["pct"]) for r in rows), len(total_pct)) + section_widths = {} + for name in section_names: + max_val_len = 0 + for r in rows: + sec_entry = (r.get("sections") or {}).get(name, {"base": 0, "new": 0}) + max_val_len = max(max_val_len, len(fmt_abs(sec_entry.get("base", 0), sec_entry.get("new", 0)))) + section_widths[name] = max(len(name), max_val_len, 1) + + header_parts = [f"| {'file':<{file_width}} |"] + sep_parts = [f"| :{'-' * (file_width - 1)} |"] + for name in section_names: + header_parts.append(f" {name:>{section_widths[name]}} |") + sep_parts.append(f" {'-' * (section_widths[name] - 1)}: |") + header_parts.append(f" {'size':>{size_width}} | {'% diff':>{pct_width}} |") + sep_parts.append(f" {'-' * (size_width - 1)}: | {'-' * (pct_width - 1)}: |") + header = "".join(header_parts) + separator = "".join(sep_parts) lines = [header, separator] for r in rows: - diff_str = f"{r['diff']:+}" - lines.append( - f"| {r['file']:<{name_width}} | " - f"{str(r['base']):>{base_width}} | " - f"{str(r['new']):>{new_width}} | " - f"{diff_str:>{diff_width}} | " - f"{r['pct']:>{pct_width}} |" - ) + parts = [f"| {r['file']:<{file_width}} |"] + sections_map = r.get("sections") or {} + for name in section_names: + sec_entry = sections_map.get(name, {"base": 0, "new": 0}) + parts.append(f" {fmt_abs(sec_entry.get('base', 0), sec_entry.get('new', 0)):>{section_widths[name]}} |") + parts.append(f" {fmt_abs(r['base'], r['new']):>{size_width}} | {r['pct']:>{pct_width}} |") + lines.append("".join(parts)) if include_sum: - lines.append( - f"| {'TOTAL':<{name_width}} | " - f"{sum_base:>{base_width}} | " - f"{sum_new:>{new_width}} | " - f"{total_diff:+{diff_width}d} | " - f"{total_pct:>{pct_width}} |" - ) + total_parts = [f"| {'TOTAL':<{file_width}} |"] + for name in section_names: + total_base = sum((r.get("sections") or {}).get(name, {}).get("base", 0) for r in rows) + total_new = sum((r.get("sections") or {}).get(name, {}).get("new", 0) for r in rows) + total_parts.append(f" {fmt_abs(total_base, total_new):>{section_widths[name]}} |") + total_parts.append(f" {fmt_abs(sum_base, sum_new):>{size_width}} | {total_pct:>{pct_width}} |") + lines.append("".join(total_parts)) return lines @@ -592,9 +611,10 @@ def cmd_compare(args): if not args.quiet: print_compare_summary(comparison, args.sort) - write_compare_markdown(comparison, args.out + '.md', args.sort) - if not args.quiet: - print(f"Comparison written to {args.out}.md") + if args.markdown_out: + write_compare_markdown(comparison, args.out + '.md', args.sort) + if not args.quiet: + print(f"Comparison written to {args.out}.md") def main(argv=None): @@ -602,9 +622,9 @@ def main(argv=None): subparsers = parser.add_subparsers(dest='command', required=True, help='Available commands') # Combine subcommand - combine_parser = subparsers.add_parser('combine', help='Combine and average multiple bloaty outputs') + combine_parser = subparsers.add_parser('combine', help='Combine and average bloaty CSV outputs or metrics JSON files') combine_parser.add_argument('files', nargs='+', - help='Path to bloaty CSV output or JSON file(s) or glob pattern(s)') + help='Path to bloaty CSV output or TinyUSB metrics JSON file(s) (including linkermap-generated) or glob pattern(s)') combine_parser.add_argument('-f', '--filter', dest='filters', action='append', default=[], help='Only include compile units whose path contains this substring (can be repeated)') combine_parser.add_argument('-o', '--out', dest='out', default='metrics', @@ -620,13 +640,15 @@ def main(argv=None): help='Sort order: size/size- (descending), size+ (ascending), name/name+ (ascending), name- (descending). Default: size-') # Compare subcommand - compare_parser = subparsers.add_parser('compare', help='Compare two bloaty outputs (CSV) or JSON inputs') - compare_parser.add_argument('base', help='Base CSV/JSON file') - compare_parser.add_argument('new', help='New CSV/JSON file') + compare_parser = subparsers.add_parser('compare', help='Compare two metrics inputs (bloaty CSV or metrics JSON)') + compare_parser.add_argument('base', help='Base CSV/metrics JSON file') + compare_parser.add_argument('new', help='New CSV/metrics JSON file') compare_parser.add_argument('-f', '--filter', dest='filters', action='append', default=[], help='Only include compile units whose path contains this substring (can be repeated)') compare_parser.add_argument('-o', '--out', dest='out', default='metrics_compare', - help='Output path basename for Markdown file (default: metrics_compare)') + help='Output path basename for Markdown/JSON files (default: metrics_compare)') + compare_parser.add_argument('-m', '--markdown', dest='markdown_out', action='store_true', + help='Write Markdown output file') compare_parser.add_argument('-S', '--sort', dest='sort', default='name+', choices=['size', 'size-', 'size+', 'name', 'name-', 'name+'], help='Sort order: size/size- (descending), size+ (ascending), name/name+ (ascending), name- (descending). Default: name+') -- cgit v1.3.1 From a412a8e50d07fc789ea598f101a94570b1f33fc4 Mon Sep 17 00:00:00 2001 From: gab-k Date: Wed, 10 Dec 2025 23:04:39 +0100 Subject: hw/mcu: add support for NXP RW612 --- README.rst | 4 ++- src/common/tusb_mcu.h | 8 ++++++ src/portable/chipidea/ci_hs/ci_hs_rw61x.h | 48 +++++++++++++++++++++++++++++++ src/portable/chipidea/ci_hs/dcd_ci_hs.c | 3 ++ src/portable/ehci/ehci.c | 2 +- src/tusb_option.h | 1 + 6 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 src/portable/chipidea/ci_hs/ci_hs_rw61x.h (limited to 'src/portable') diff --git a/README.rst b/README.rst index 6a6f07825..463cc8b42 100644 --- a/README.rst +++ b/README.rst @@ -208,7 +208,9 @@ Supported CPUs | | MCX | N9 | ✔ | | ✔ | ci_fs, ci_hs, ehci | | | | +-------------------+--------+------+-----------+------------------------+-------------------+ | | | A15 | ✔ | | | ci_fs | | -+--------------+---------+-------------------+--------+------+-----------+------------------------+-------------------+ +| +---------+-------------------+--------+------+-----------+------------------------+-------------------+ +| | RW61x | ✔ | | ✔ | ci_hs, ehci | | ++--------------+-----------------------------+--------+------+-----------+------------------------+-------------------+ | Raspberry Pi | RP2040, RP2350 | ✔ | ✔ | ✖ | rp2040, pio_usb | | +--------------+-----+-----------------------+--------+------+-----------+------------------------+-------------------+ | Renesas | RX | 63N, 65N, 72N | ✔ | ✔ | ✖ | rusb2 | | diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index 1e773bf96..89316ee77 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -111,6 +111,14 @@ #define TUP_DCD_ENDPOINT_MAX 16 +#elif TU_CHECK_MCU(OPT_MCU_RW61X) + // USB0 is chipidea HS + #define TUP_USBIP_CHIPIDEA_HS + #define TUP_USBIP_EHCI + + #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_RHPORT_HIGHSPEED 1 + #elif TU_CHECK_MCU(OPT_MCU_MIMXRT1XXX) #include "fsl_device_registers.h" diff --git a/src/portable/chipidea/ci_hs/ci_hs_rw61x.h b/src/portable/chipidea/ci_hs/ci_hs_rw61x.h new file mode 100644 index 000000000..114fe26c3 --- /dev/null +++ b/src/portable/chipidea/ci_hs/ci_hs_rw61x.h @@ -0,0 +1,48 @@ +/* + * 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. + */ + +#ifndef _CI_HS_RW61X_H_ +#define _CI_HS_RW61X_H_ + +#include "fsl_device_registers.h" + +static const ci_hs_controller_t _ci_controller[] = { + {.reg_base = USBOTG_BASE, .irqnum = USB_IRQn} +}; + +TU_ATTR_ALWAYS_INLINE static inline ci_hs_regs_t* CI_HS_REG(uint8_t port) { + (void) port; + return ((ci_hs_regs_t*) _ci_controller[0].reg_base); +} + +#define CI_DCD_INT_ENABLE(_p) do { (void) _p; NVIC_EnableIRQ (_ci_controller[0].irqnum); } while (0) +#define CI_DCD_INT_DISABLE(_p) do { (void) _p; NVIC_DisableIRQ(_ci_controller[0].irqnum); } while (0) + +#define CI_HCD_INT_ENABLE(_p) NVIC_EnableIRQ (_ci_controller[_p].irqnum) +#define CI_HCD_INT_DISABLE(_p) NVIC_DisableIRQ(_ci_controller[_p].irqnum) + + +#endif diff --git a/src/portable/chipidea/ci_hs/dcd_ci_hs.c b/src/portable/chipidea/ci_hs/dcd_ci_hs.c index 4a5e5c91f..27298989c 100644 --- a/src/portable/chipidea/ci_hs/dcd_ci_hs.c +++ b/src/portable/chipidea/ci_hs/dcd_ci_hs.c @@ -55,6 +55,9 @@ bool dcd_dcache_clean_invalidate(void const* addr, uint32_t data_size) { // MCX N9 only port 1 use this controller #include "ci_hs_mcx.h" +#elif TU_CHECK_MCU(OPT_MCU_RW61X) + #include "ci_hs_rw61x.h" + #else #error "Unsupported MCUs" #endif diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c index c33c970e4..e604a0360 100644 --- a/src/portable/ehci/ehci.c +++ b/src/portable/ehci/ehci.c @@ -40,7 +40,7 @@ #include "ehci.h" // NXP specific fixes -#if TU_CHECK_MCU(OPT_MCU_MIMXRT1XXX, OPT_MCU_LPC55, OPT_MCU_MCXN9) +#if TU_CHECK_MCU(OPT_MCU_MIMXRT1XXX, OPT_MCU_LPC55, OPT_MCU_MCXN9, OPT_MCU_RW61X) #include "fsl_device_registers.h" #endif diff --git a/src/tusb_option.h b/src/tusb_option.h index be954e01a..68f2d3598 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -199,6 +199,7 @@ // NXP LPC MCX #define OPT_MCU_MCXN9 2300 ///< NXP MCX N9 Series #define OPT_MCU_MCXA15 2301 ///< NXP MCX A15 Series +#define OPT_MCU_RW61X 2302 ///< NXP RW61x Series // Analog Devices #define OPT_MCU_MAX32690 2400 ///< ADI MAX32690 -- cgit v1.3.1 From fa74d1a6e10b8a3d05f94ca876a5cccf515b5c34 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Thu, 11 Dec 2025 23:18:34 +0100 Subject: dcd/rusb2: fix fifo write Signed-off-by: HiFiPhile --- src/portable/renesas/rusb2/dcd_rusb2.c | 27 ++++++++++++++++++--------- src/tusb_option.h | 2 +- 2 files changed, 19 insertions(+), 10 deletions(-) (limited to 'src/portable') diff --git a/src/portable/renesas/rusb2/dcd_rusb2.c b/src/portable/renesas/rusb2/dcd_rusb2.c index 786b8d980..779c7bc3d 100644 --- a/src/portable/renesas/rusb2/dcd_rusb2.c +++ b/src/portable/renesas/rusb2/dcd_rusb2.c @@ -213,17 +213,26 @@ static void pipe_write_packet_ff(rusb2_reg_t * rusb, tu_fifo_t *f, volatile void tu_fifo_buffer_info_t info; tu_fifo_get_read_info(f, &info); - uint16_t count = tu_min16(total_len, info.linear.len); - pipe_write_packet(rusb, info.linear.ptr, fifo, count); + uint16_t cnt_lin = tu_min16(total_len, info.linear.len); + uint16_t cnt_wrap = tu_min16(total_len - cnt_lin, info.wrapped.len); + uint16_t const cnt_written = cnt_lin + cnt_wrap; - uint16_t rem = total_len - count; - if (rem) { - rem = tu_min16(rem, info.wrapped.len); - pipe_write_packet(rusb, info.wrapped.ptr, fifo, rem); - count += rem; - } + // Ensure only the last write is odd if total_len is odd + if (cnt_wrap == 0) { + pipe_write_packet(rusb, info.linear.ptr, fifo, cnt_lin); + } else { + pipe_write_packet(rusb, info.linear.ptr, fifo, cnt_lin & ~1); - tu_fifo_advance_read_pointer(f, count); + if (cnt_lin & 1) { + uint8_t glue[2] = {info.linear.ptr[cnt_lin & ~1], info.wrapped.ptr[0]}; + pipe_write_packet(rusb, glue, fifo, 2); + cnt_wrap--; + info.wrapped.ptr++; + } + + pipe_write_packet(rusb, info.wrapped.ptr, fifo, cnt_wrap); + } + tu_fifo_advance_read_pointer(f, cnt_written); } // Read data sw fifo <-- hw fifo diff --git a/src/tusb_option.h b/src/tusb_option.h index be954e01a..b4acee035 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -361,7 +361,7 @@ //------------ RUSB2 --------------// #if defined(TUP_USBIP_RUSB2) - #define CFG_TUD_EDPT_DEDICATED_HWFIFO 0 // need testing to enable + #define CFG_TUD_EDPT_DEDICATED_HWFIFO 1 #endif //-------------------------------------------------------------------- -- cgit v1.3.1 From 132bcd0b5e808837113206743035f0e85dd1dc9c Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Wed, 10 Dec 2025 21:37:00 +0100 Subject: hcd: add NXP IP3516 Signed-off-by: HiFiPhile --- src/common/tusb_mcu.h | 2 + src/portable/nxp/lpc_ip3516/hcd_lpc_ip3516.c | 787 +++++++++++++++++++++++++++ src/portable/nxp/lpc_ip3516/hcd_lpc_ip3516.h | 188 +++++++ 3 files changed, 977 insertions(+) create mode 100644 src/portable/nxp/lpc_ip3516/hcd_lpc_ip3516.c create mode 100644 src/portable/nxp/lpc_ip3516/hcd_lpc_ip3516.h (limited to 'src/portable') diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index 1e773bf96..c4b1155f3 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -73,11 +73,13 @@ #elif TU_CHECK_MCU(OPT_MCU_LPC54) // TODO USB0 has 5, USB1 has 6 #define TUP_USBIP_IP3511 + #define TUP_USBIP_IP3516 #define TUP_DCD_ENDPOINT_MAX 6 #elif TU_CHECK_MCU(OPT_MCU_LPC55) // TODO USB0 has 5, USB1 has 6 #define TUP_USBIP_IP3511 + #define TUP_USBIP_IP3516 #define TUP_USBIP_OHCI #define TUP_USBIP_OHCI_NXP #define TUP_OHCI_RHPORTS 1 // 1 downstream port diff --git a/src/portable/nxp/lpc_ip3516/hcd_lpc_ip3516.c b/src/portable/nxp/lpc_ip3516/hcd_lpc_ip3516.c new file mode 100644 index 000000000..16936e2c1 --- /dev/null +++ b/src/portable/nxp/lpc_ip3516/hcd_lpc_ip3516.c @@ -0,0 +1,787 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2025 HiFiPhile (Zixun LI) + * + * 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_IP3516) + +//--------------------------------------------------------------------+ +// INCLUDE +//--------------------------------------------------------------------+ +#include "common/tusb_common.h" +#include "host/hcd.h" +#include "host/usbh.h" +#include "hcd_lpc_ip3516.h" + +#if CFG_TUSB_MCU == OPT_MCU_LPC55 + #include "fsl_device_registers.h" +#else + #error "Unsupported MCUs" +#endif + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ + +#define USBHSH_PORTSC1_W1C_MASK (USBHSH_PORTSC1_CSC_MASK | USBHSH_PORTSC1_PEDC_MASK | USBHSH_PORTSC1_OCC_MASK) + +//--------------------------------------------------------------------+ +// Proprietary Transfer Descriptor +//--------------------------------------------------------------------+ + +CFG_TUD_MEM_SECTION TU_ATTR_ALIGNED(1024) static ip3516_ptd_t _ptd; + +static struct { + uint32_t uframe_number; + uint32_t uframe_length; + bool attached; // Track attachment state to avoid duplicate events, sometimes high-speed disconnection detector is not reliable +} _hcd_data; + +//--------------------------------------------------------------------+ +// Helper Functions +//--------------------------------------------------------------------+ + +static inline bool is_ptd_free(const ptd_ctrl1_t ctrl1) { + return ctrl1.mps == 0; +} + +static inline bool is_xfer_asyc(tusb_xfer_type_t xfer_type) { + return (xfer_type == TUSB_XFER_CONTROL || xfer_type == TUSB_XFER_BULK); +} + +static inline void ptd_clear_state(ptd_state_t *state) { + ptd_state_t local = {.value = 0}; + local.ep_type = state->ep_type; // preserve ep_type + local.token = state->token; // preserve token + local.data_toggle = state->data_toggle; // preserve data_toggle + *state = local; +} + +static inline uint8_t ptd_find_free(tusb_xfer_type_t xfer_type) { + uint8_t max_count; + intptr_t ptd_array; + + switch (xfer_type) { + case TUSB_XFER_CONTROL: + case TUSB_XFER_BULK: + max_count = IP3516_ATL_NUM; + ptd_array = (intptr_t)&_ptd.atl; + break; + + case TUSB_XFER_INTERRUPT: + max_count = IP3516_PTL_NUM; + ptd_array = (intptr_t)&_ptd.intr; + break; + + case TUSB_XFER_ISOCHRONOUS: + max_count = IP3516_PTL_NUM; + ptd_array = (intptr_t)&_ptd.iso; + break; + + default: + return TUSB_INDEX_INVALID_8; + } + + for (uint8_t i = 0; i < max_count; i++) { + // For ATL: stride is sizeof(ip3516_atl_t) = 16 bytes = 4 words + // For PTL: stride is sizeof(ip3516_ptl_t) = 32 bytes = 8 words + uint8_t stride = is_xfer_asyc(xfer_type) ? sizeof(ip3516_atl_t) : sizeof(ip3516_ptl_t); + ptd_ctrl1_t *ctrl1 = (ptd_ctrl1_t *)(ptd_array + i * stride); + + if (is_ptd_free(*ctrl1)) { + return i; + } + } + + return TUSB_INDEX_INVALID_8; // No free PTD found +} + +// Close all PTDs associated with a specific device address +static void close_ptds_by_device(uint8_t dev_addr, intptr_t ptd_array, uint8_t max_count, uint8_t stride, + volatile uint32_t *skip_reg) { + + uint32_t skip_mask = 0; + + for (uint8_t i = 0; i < max_count; i++) { + intptr_t ptd_ptr = ptd_array + i * stride; + ptd_ctrl1_t *ptd_ctrl1 = (ptd_ctrl1_t *)(ptd_ptr + offsetof(ip3516_atl_t, ctrl1)); + ptd_ctrl2_t *ptd_ctrl2 = (ptd_ctrl2_t *)(ptd_ptr + offsetof(ip3516_atl_t, ctrl2)); + + if (!is_ptd_free(*ptd_ctrl1) && ptd_ctrl2->dev_addr == dev_addr) { + *skip_reg |= (1 << i); + skip_mask |= (1 << i); + } + } + + if (skip_mask) { + // Wait 1 uframe for PTDs to be inactive + uint32_t start_uframe = + (USBHSH->FLADJ_FRINDEX & USBHSH_FLADJ_FRINDEX_FRINDEX_MASK) >> USBHSH_FLADJ_FRINDEX_FRINDEX_SHIFT; + while (((USBHSH->FLADJ_FRINDEX & USBHSH_FLADJ_FRINDEX_FRINDEX_MASK) >> USBHSH_FLADJ_FRINDEX_FRINDEX_SHIFT) == + start_uframe) {} + + // Clear PTDs + for (uint8_t i = 0; i < max_count; i++) { + if (skip_mask & (1 << i)) { + intptr_t ptd_ptr = ptd_array + i * stride; + tu_memclr((void *)ptd_ptr, stride); + } + } + + // Clear skip bits + *skip_reg &= ~skip_mask; + } +} + +// Check if a PTD matches the given endpoint criteria +static bool ptd_matches(intptr_t ptd_ptr, uint8_t dev_addr, uint8_t ep_num, uint8_t ep_dir) { + ptd_ctrl1_t *ptd_ctrl1 = (ptd_ctrl1_t *)(ptd_ptr + offsetof(ip3516_atl_t, ctrl1)); + if (is_ptd_free(*ptd_ctrl1)) { + return false; + } + + ptd_ctrl2_t *ptd_ctrl2 = (ptd_ctrl2_t *)(ptd_ptr + offsetof(ip3516_atl_t, ctrl2)); + if (ptd_ctrl2->dev_addr != dev_addr || ptd_ctrl2->ep_num != ep_num) { + return false; + } + + ptd_state_t *ptd_state = (ptd_state_t *)(ptd_ptr + offsetof(ip3516_atl_t, state)); + bool is_control = (ptd_state->ep_type == TUSB_XFER_CONTROL); + + // For control endpoint, match both IN and OUT directions + if (is_control) { + return true; + } + + if (ep_dir == TUSB_DIR_IN && ptd_state->token == IP3516_PTD_TOKEN_IN) { + return true; + } + + if (ep_dir == TUSB_DIR_OUT && ptd_state->token == IP3516_PTD_TOKEN_OUT) { + return true; + } + + return false; +} + +// Find and close a specific PTD +static bool find_and_close_ptd(uint8_t dev_addr, uint8_t ep_num, uint8_t ep_dir, intptr_t ptd_array, uint8_t max_count, + uint8_t stride, volatile uint32_t *skip_reg) { + for (uint8_t i = 0; i < max_count; i++) { + intptr_t ptd_ptr = ptd_array + i * stride; + if (ptd_matches(ptd_ptr, dev_addr, ep_num, ep_dir)) { + if (skip_reg) { + *skip_reg |= (1 << i); + + // Wait 1 uframe for PTD to be inactive + uint32_t start_uframe = + (USBHSH->FLADJ_FRINDEX & USBHSH_FLADJ_FRINDEX_FRINDEX_MASK) >> USBHSH_FLADJ_FRINDEX_FRINDEX_SHIFT; + while (((USBHSH->FLADJ_FRINDEX & USBHSH_FLADJ_FRINDEX_FRINDEX_MASK) >> USBHSH_FLADJ_FRINDEX_FRINDEX_SHIFT) == + start_uframe) {} + + // Just clear state + ptd_ctrl1_t *ptd_ctrl1 = (ptd_ctrl1_t *)(ptd_ptr + offsetof(ip3516_atl_t, ctrl1)); + ptd_state_t *ptd_state = (ptd_state_t *)(ptd_ptr + offsetof(ip3516_atl_t, state)); + ptd_clear_state(ptd_state); + ptd_ctrl1->valid = 0; + + *skip_reg &= ~(1 << i); + } else { + // Clear PTD + tu_memclr((void *)ptd_ptr, stride); + } + return true; + } + } + return false; +} + +// Find an opened PTD +static intptr_t find_opened_ptd(uint8_t dev_addr, uint8_t ep_addr) { + const uint8_t ep_num = tu_edpt_number(ep_addr); + const uint8_t ep_dir = tu_edpt_dir(ep_addr); + + // Search in ATL + for (uint8_t i = 0; i < IP3516_ATL_NUM; i++) { + intptr_t ptd_ptr = (intptr_t)&_ptd.atl[i]; + if (ptd_matches(ptd_ptr, dev_addr, ep_num, ep_dir)) { + return ptd_ptr; + } + } + + // Search in INT + for (uint8_t i = 0; i < IP3516_PTL_NUM; i++) { + intptr_t ptd_ptr = (intptr_t)&_ptd.intr[i]; + if (ptd_matches(ptd_ptr, dev_addr, ep_num, ep_dir)) { + return ptd_ptr; + } + } + + // Search in ISO + for (uint8_t i = 0; i < IP3516_PTL_NUM; i++) { + intptr_t ptd_ptr = (intptr_t)&_ptd.iso[i]; + if (ptd_matches(ptd_ptr, dev_addr, ep_num, ep_dir)) { + return ptd_ptr; + } + } + + return TUSB_INDEX_INVALID_8; +} + +static bool edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t *buffer, uint16_t buflen, bool is_setup) { + const uint8_t ep_num = tu_edpt_number(ep_addr); + const uint8_t ep_dir = tu_edpt_dir(ep_addr); + + intptr_t ptd_ptr = find_opened_ptd(dev_addr, ep_addr); + TU_ASSERT(ptd_ptr != TUSB_INDEX_INVALID_8); + + ptd_ctrl1_t *ptd_ctrl1 = (ptd_ctrl1_t *)(ptd_ptr + offsetof(ip3516_atl_t, ctrl1)); + ptd_ctrl2_t *ptd_ctrl2 = (ptd_ctrl2_t *)(ptd_ptr + offsetof(ip3516_atl_t, ctrl2)); + ptd_data_t *ptd_data = (ptd_data_t *)(ptd_ptr + offsetof(ip3516_atl_t, data)); + ptd_state_t *ptd_state = (ptd_state_t *)(ptd_ptr + offsetof(ip3516_atl_t, state)); + + // Setup data buffer and length + ptd_data->data_addr = (uint32_t)(uintptr_t)buffer & IP3516_PTD_DATA_ADDR_MASK; + ptd_data->xfer_len = buflen; + + // Clear previous state + ptd_clear_state(ptd_state); + + // Set token for EP0 + if (ep_num == 0) { + if (is_setup) { + ptd_state->token = IP3516_PTD_TOKEN_SETUP; + ptd_state->data_toggle = 0; + } else { + ptd_state->token = (ep_dir == TUSB_DIR_IN) ? IP3516_PTD_TOKEN_IN : IP3516_PTD_TOKEN_OUT; + ptd_state->data_toggle = 1; + } + } + + // Interrupt split transfer needs to be relauched manually if NAKed + if (ptd_ctrl2->split && ptd_state->ep_type == TUSB_XFER_INTERRUPT) { + ptd_ctrl2->reload = 0x0f; + ptd_state->nak_cnt = 0x0f; + } + + // Activate PTD + ptd_ctrl1->valid = 1; + ptd_state->active = 1; + + return true; +} + +//--------------------------------------------------------------------+ +// Controller API +//--------------------------------------------------------------------+ + +// Initialize controller to host mode +bool hcd_init(uint8_t rhport, const tusb_rhport_init_t *rh_init) { + (void)rh_init; + (void)rhport; + + // Reset controller + USBHSH->USBCMD |= USBHSH_USBCMD_HCRESET_MASK; + while (USBHSH->USBCMD & USBHSH_USBCMD_HCRESET_MASK) {} + + USBHSH->PORTMODE = USBHSH_PORTMODE_SW_CTRL_PDCOM_MASK; + + tu_memclr(&_ptd, sizeof(_ptd)); + tu_varclr(&_hcd_data); + + // Set base addresses + USBHSH->ATLPTD = (uint32_t)&_ptd.atl & USBHSH_ATLPTD_ATL_BASE_MASK; + USBHSH->INTPTD = (uint32_t)&_ptd.intr & USBHSH_INTPTD_INT_BASE_MASK; + USBHSH->ISOPTD = (uint32_t)&_ptd.iso & USBHSH_ISOPTD_ISO_BASE_MASK; + USBHSH->DATAPAYLOAD = (uint32_t)&_ptd & USBHSH_DATAPAYLOAD_DAT_BASE_MASK; + + // Turn on power switch + if (USBHSH->HCSPARAMS & USBHSH_HCSPARAMS_PPC_MASK) { + USBHSH->PORTSC1 |= USBHSH_PORTSC1_PP_MASK; + } + + // Get frame list size + uint32_t fls = (USBHSH->USBCMD & USBHSH_USBCMD_FLS_MASK) >> USBHSH_USBCMD_FLS_SHIFT; + _hcd_data.uframe_length = 8192 >> fls; + + // Clear pending interrupts + USBHSH->USBSTS = 0xFFFFFFFF; + + // Enable interrupts + USBHSH->USBINTR = USBHSH_USBINTR_ATL_IRQ_E_MASK | USBHSH_USBINTR_INT_IRQ_E_MASK | USBHSH_USBINTR_ISO_IRQ_E_MASK | + USBHSH_USBINTR_PCDE_MASK | USBHSH_USBINTR_FLRE_MASK; + + + // Enable all PTDs + USBHSH->LASTPTD = USBHSH_LASTPTD_ATL_LAST(IP3516_ATL_NUM - 1) | USBHSH_LASTPTD_INT_LAST(IP3516_PTL_NUM - 1) | + USBHSH_LASTPTD_ISO_LAST(IP3516_PTL_NUM - 1); + + // Enable controller + USBHSH->USBCMD = USBHSH_USBCMD_ATL_EN_MASK | USBHSH_USBCMD_INT_EN_MASK | USBHSH_USBCMD_ISO_EN_MASK | USBHSH_USBCMD_RS_MASK; + + return true; +} + +// Enable USB interrupt +void hcd_int_enable(uint8_t rhport) { + (void)rhport; + NVIC_EnableIRQ(USB1_IRQn); +} + +// Disable USB interrupt +void hcd_int_disable(uint8_t rhport) { + (void)rhport; + NVIC_DisableIRQ(USB1_IRQn); +} + +bool hcd_deinit(uint8_t rhport) { + (void)rhport; + + // Disable interrupts + USBHSH->USBINTR = 0; + USBHSH->USBSTS = 0xFFFFFFFF; + + // Disable controller + USBHSH->USBCMD &= ~(USBHSH_USBCMD_ATL_EN_MASK | USBHSH_USBCMD_INT_EN_MASK | USBHSH_USBCMD_ISO_EN_MASK | USBHSH_USBCMD_RS_MASK); + + // Turn off power switch + if (USBHSH->HCSPARAMS & USBHSH_HCSPARAMS_PPC_MASK) { + USBHSH->PORTSC1 &= ~USBHSH_PORTSC1_PP_MASK; + } + + // Connect PHY to device mode + USBHSH->PORTMODE = USBHSH_PORTMODE_SW_CTRL_PDCOM_MASK | USBHSH_PORTMODE_DEV_ENABLE_MASK; + + return true; +} + +//--------------------------------------------------------------------+ +// Port API +//--------------------------------------------------------------------+ + +// 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) { + (void)rhport; + uint32_t status = USBHSH->PORTSC1 & ~USBHSH_PORTSC1_W1C_MASK; + USBHSH->PORTSC1 = status | USBHSH_PORTSC1_PR_MASK; +} + +// Complete bus reset sequence, may be required by some controllers +void hcd_port_reset_end(uint8_t rhport) { + (void)rhport; + uint32_t status = USBHSH->PORTSC1 & ~USBHSH_PORTSC1_W1C_MASK; + USBHSH->PORTSC1 = status & ~USBHSH_PORTSC1_PR_MASK; + while (USBHSH->PORTSC1 & USBHSH_PORTSC1_PR_MASK) {} +#if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U)) + uint32_t pspd = (USBHSH->PORTSC1 & USBHSH_PORTSC1_PSPD_MASK) >> USBHSH_PORTSC1_PSPD_SHIFT; + if (pspd == 2) { + // enable phy disconnection for high speed + USBPHY->CTRL |= USBPHY_CTRL_ENHOSTDISCONDETECT_MASK; + } +#endif +} + +// Get the current connect status of roothub port +bool hcd_port_connect_status(uint8_t rhport) { + (void)rhport; + return (USBHSH->PORTSC1 & USBHSH_PORTSC1_CCS_MASK) ? true : false; +} + +// Get port link speed +tusb_speed_t hcd_port_speed_get(uint8_t rhport) { + (void)rhport; + uint32_t pspd = (USBHSH->PORTSC1 & USBHSH_PORTSC1_PSPD_MASK) >> USBHSH_PORTSC1_PSPD_SHIFT; + switch (pspd) { + case 0: + return TUSB_SPEED_LOW; + case 1: + return TUSB_SPEED_FULL; + case 2: + return TUSB_SPEED_HIGH; + default: + return TUSB_SPEED_INVALID; + } +} + +// Get frame number (1ms) +uint32_t hcd_frame_number(uint8_t rhport) { + (void)rhport; + uint32_t uframe = (USBHSH->FLADJ_FRINDEX & USBHSH_FLADJ_FRINDEX_FRINDEX_MASK) >> USBHSH_FLADJ_FRINDEX_FRINDEX_SHIFT; + uframe &= (_hcd_data.uframe_length - 1); + return (uframe + _hcd_data.uframe_number) >> 3; +} + +// HCD closes all opened endpoints belong to this device +void hcd_device_close(uint8_t rhport, uint8_t dev_addr) { + (void)rhport; + + close_ptds_by_device(dev_addr, (intptr_t)&_ptd.atl, IP3516_ATL_NUM, sizeof(ip3516_atl_t), &USBHSH->ATLPTDS); + close_ptds_by_device(dev_addr, (intptr_t)&_ptd.intr, IP3516_PTL_NUM, sizeof(ip3516_ptl_t), &USBHSH->INTPTDS); + close_ptds_by_device(dev_addr, (intptr_t)&_ptd.iso, IP3516_PTL_NUM, sizeof(ip3516_ptl_t), &USBHSH->ISOPTDS); +} + +//--------------------------------------------------------------------+ +// Endpoints API +//--------------------------------------------------------------------+ + +static inline intptr_t get_ptd_from_index(tusb_xfer_type_t xfer_type, uint8_t ptd_index) { + if (is_xfer_asyc(xfer_type)) { + return (intptr_t)&_ptd.atl[ptd_index]; + } else { + if (xfer_type == TUSB_XFER_INTERRUPT) { + return (intptr_t)&_ptd.intr[ptd_index]; + } else { + return (intptr_t)&_ptd.iso[ptd_index]; + } + } +} + + +// Open an endpoint +bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, const tusb_desc_endpoint_t *ep_desc) { + (void)rhport; + + const uint8_t ep_num = tu_edpt_number(ep_desc->bEndpointAddress); + const tusb_xfer_type_t xfer_type = (tusb_xfer_type_t)ep_desc->bmAttributes.xfer; + + tuh_bus_info_t bus_info; + tuh_bus_info_get(dev_addr, &bus_info); + + // Find a free PTD + uint8_t ptd_index = ptd_find_free(xfer_type); + TU_ASSERT(ptd_index != TUSB_INDEX_INVALID_8); + + // Configure PTD + intptr_t ptd_ptr = get_ptd_from_index(xfer_type, ptd_index); + volatile ptd_ctrl1_t *ctrl1 = (volatile ptd_ctrl1_t *)(ptd_ptr + offsetof(ip3516_atl_t, ctrl1)); + volatile ptd_ctrl2_t *ctrl2 = (volatile ptd_ctrl2_t *)(ptd_ptr + offsetof(ip3516_atl_t, ctrl2)); + volatile ptd_data_t *data = (volatile ptd_data_t *)(ptd_ptr + offsetof(ip3516_atl_t, data)); + volatile ptd_state_t *state = (volatile ptd_state_t *)(ptd_ptr + offsetof(ip3516_atl_t, state)); + + // Initialize PTD fields + ctrl1->mps = ep_desc->wMaxPacketSize; + ctrl1->mult = 1; + + ctrl2->dev_addr = dev_addr; + ctrl2->ep_num = ep_num; + ctrl2->speed = bus_info.speed == TUSB_SPEED_LOW ? 2 : 0; + ctrl2->hub_addr = bus_info.hub_addr; + ctrl2->hub_port = bus_info.hub_port; + ctrl2->split = (hcd_port_speed_get(rhport) == TUSB_SPEED_HIGH) && (bus_info.speed != TUSB_SPEED_HIGH) ? 1 : 0; + + data->intr = 1; + + state->ep_type = (uint32_t)xfer_type; + state->token = tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN ? IP3516_PTD_TOKEN_IN : IP3516_PTD_TOKEN_OUT; + + if (!is_xfer_asyc(xfer_type)) { + ip3516_ptl_t *ptd = (ip3516_ptl_t *)ptd_ptr; + + uint32_t uframe_interval; + if (bus_info.speed == TUSB_SPEED_HIGH) { + uframe_interval = 1 << (ep_desc->bInterval - 1); + } else { + uframe_interval = ep_desc->bInterval << 3; + // round down to nearest power of 2 + uframe_interval = 1 << tu_log2(uframe_interval); + } + uframe_interval = tu_min32(uframe_interval, IP3516_MAX_UFRAME); + + // uframe_active is an 8-bit mask, where each bit corresponds to a micro-frame within a 1ms frame. + // A '1' indicates the endpoint should be polled in that micro-frame. + // For example: + // Interval 1 (poll every u-frame) -> mask is 0b11111111 (0xFF) + // Interval 2 (poll every 2nd u-frame, e.g., 0, 2, 4, 6) -> mask is 0b10101010 (0xAA) + // Interval 4 (poll every 4th u-frame, e.g., 0, 4) -> mask is 0b10001000 (0x88) + // Interval 8 (poll every 8th u-frame, e.g., 0) -> mask is 0b10000000 (0x80) + switch (uframe_interval) { + case 1: + ptd->status.uframe_active = 0xFF; + break; + case 2: + ptd->status.uframe_active = 0xAA; + break; + case 4: + ptd->status.uframe_active = 0x11; + break; + case 8: + ptd->status.uframe_active = 0x01; + break; + default: + // For intervals > 8, we poll once per frame (every 8 u-frames) and use ctrl1.uframe to skip frames. + ptd->status.uframe_active = 0x01; + if (uframe_interval >= 16) { + ctrl1->uframe = tu_log2(uframe_interval) - 3; + } + break; + } + + if (ctrl2->split) { + // 11.18.1 Best Case Full-Speed Budget + // + // A microframe of time allows at most 187.5 raw bytes of signaling on a full-speed bus. + // The best case full-speed budget assumes that 188 full-speed bytes occur in each microframe. + // + // A 1 ms frame subdivided into microframes of budget time: + // + // Microframes Y_0 Y_1 Y_2 Y_3 Y_4 Y_5 Y_6 Y_7 + // Max wire time 187.5 187.5 187.5 187.5 187.5 187.5 32 + // Best case wire budget 188 188 188 188 188 188 29 + // + // 11.18.4 Host Split Transaction Scheduling Requirements + // + // 1. The host must never schedule a start-split in microframe Y_6. + // 2. For isochronous OUT full-speed transactions, for each microframe in which the transaction is + // budgeted, the host must schedule a 188 (or the remaining data size) data byte start-split transaction. + // For isochronous IN and interrupt IN/OUT full-/low-speed transactions, a single start-split must be + // scheduled in the microframe before the transaction is budgeted to start on the full-/low-speed bus. + // 3. For isochronous OUT full-speed transactions, the host must never schedule a complete-split. The + // TT response to a complete-split for an isochronous OUT is undefined. + // For interrupt IN/OUT full-/low-speed transactions, the host must schedule a complete-split + // transaction in each of the two microframes following the first microframe in which the full-/low- + // speed transaction is budgeted. An additional complete-split must also be scheduled in the third + // following microframe unless the full-/low-speed transaction was budgeted to start in microframe Y_6 + // For isochronous IN full-speed transactions, for each microframe in which the full-speed transaction + // is budgeted, a complete-split must be scheduled for each following microframe. + // Also, determine the last microframe in which a complete-split is scheduled, call it L. + // If L is less than Y_6, schedule additional complete-splits in microframe L+1 and L+2. + // If L is equal to Y_6, schedule one complete-split in microframe Y_7. + // + // TODO: Implement budget check scheduling + // Otherwise, it may cause bus contention with other split transfers + // Here we simply start interrupt transfers for Y_0 and Y1 and isochronous transfers for Y_2 + if (xfer_type == TUSB_XFER_ISOCHRONOUS) { + const uint8_t ss_slot = 2; // Start-split slot + const uint8_t slots = (ep_desc->wMaxPacketSize + 187) / 188; + const tusb_dir_t ep_dir = tu_edpt_dir(ep_desc->bEndpointAddress); + if (ep_dir == TUSB_DIR_IN) { + if (ep_desc->wMaxPacketSize > 192) { + ctrl1->mps = 192; + } + ptd->status.uframe_active = 1 << ss_slot; + for (uint8_t i = 0; i < slots; i++) { + ptd->iso_in_0.uframe_complete |= 1 << (2 + ss_slot + i); + } + // Schedule additional complete-splits if needed + uint8_t last_complete = ss_slot + slots + 1; + if (last_complete < 6) { + ptd->iso_in_0.uframe_complete |= 1 << (ss_slot + last_complete + 1); + ptd->iso_in_0.uframe_complete |= 1 << (ss_slot + last_complete + 2); + } else if (last_complete == 6) { + ptd->iso_in_0.uframe_complete |= 1 << 7; + } + } else { + if (ep_desc->wMaxPacketSize > 188) { + ctrl1->mps = 188; + } + for (uint8_t i = 0; i < slots; i++) { + ptd->status.uframe_active |= 1 << (ss_slot + i); + } + } + } else { + // Start-split slot, jigging to avoid bus contention: EP odd -> Y_1, EP even -> Y_0 + const uint8_t ss_slot = ep_num & 0x01; + ptd->status.uframe_active = 1 << ss_slot; + // Complete-split slots: next 3 u-frames + ptd->iso_in_0.uframe_complete = 0x1c << ss_slot; + } + } + } + + return true; +} + +// Close an opened endpoint +bool hcd_edpt_close(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { + (void)rhport; + const uint8_t ep_num = tu_edpt_number(ep_addr); + const uint8_t ep_dir = tu_edpt_dir(ep_addr); + + // Search in ATL + if (find_and_close_ptd(dev_addr, ep_num, ep_dir, (intptr_t)&_ptd.atl, IP3516_ATL_NUM, sizeof(ip3516_atl_t), NULL)) { + return true; + } + + // Search in INT + if (find_and_close_ptd(dev_addr, ep_num, ep_dir, (intptr_t)&_ptd.intr, IP3516_PTL_NUM, sizeof(ip3516_ptl_t), NULL)) { + return true; + } + + // Search in ISO + if (find_and_close_ptd(dev_addr, ep_num, ep_dir, (intptr_t)&_ptd.iso, IP3516_PTL_NUM, sizeof(ip3516_ptl_t), NULL)) { + return true; + } + + return false; +} + +// Submit a transfer on an endpoint +bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *buffer, uint16_t buflen) { + (void)rhport; + + return edpt_xfer(dev_addr, ep_addr, buffer, buflen, 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; + + const uint8_t ep_num = tu_edpt_number(ep_addr); + const uint8_t ep_dir = tu_edpt_dir(ep_addr); + + // Search in ATL + if (find_and_close_ptd(dev_addr, ep_num, ep_dir, (intptr_t)&_ptd.atl, IP3516_ATL_NUM, sizeof(ip3516_atl_t), + &USBHSH->ATLPTDS)) { + return true; + } + + // Search in INT + if (find_and_close_ptd(dev_addr, ep_num, ep_dir, (intptr_t)&_ptd.intr, IP3516_PTL_NUM, sizeof(ip3516_ptl_t), + &USBHSH->INTPTDS)) { + return true; + } + + // Search in ISO + if (find_and_close_ptd(dev_addr, ep_num, ep_dir, (intptr_t)&_ptd.iso, IP3516_PTL_NUM, sizeof(ip3516_ptl_t), + &USBHSH->ISOPTDS)) { + return true; + } + + return false; +} + +bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, const uint8_t setup_packet[8]) { + (void)rhport; + + return edpt_xfer(dev_addr, 0x00, (uint8_t *)(uintptr_t)setup_packet, 8, true); +} + +bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { + (void)rhport; + + intptr_t ptd_ptr = find_opened_ptd(dev_addr, ep_addr); + TU_ASSERT(ptd_ptr != TUSB_INDEX_INVALID_8); + + ptd_state_t *ptd_state = (ptd_state_t *)(ptd_ptr + offsetof(ip3516_atl_t, state)); + ptd_clear_state(ptd_state); + ptd_state->data_toggle = 0; // reset data toggle to DATA0 + + return true; +} + +//--------------------------------------------------------------------+ +// Interrupt Handler +//--------------------------------------------------------------------+ + +// Handle port status change event +static inline void handle_port_status_change(uint8_t rhport) { + const uint32_t status = USBHSH->PORTSC1; + + if (status & USBHSH_PORTSC1_CSC_MASK) { + if (status & USBHSH_PORTSC1_CCS_MASK && !_hcd_data.attached) { + _hcd_data.attached = true; + hcd_event_device_attach(rhport, true); + } else { + _hcd_data.attached = false; + hcd_event_device_remove(rhport, true); + #if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U)) + // disable phy disconnection for high speed + USBPHY->CTRL &= ~USBPHY_CTRL_ENHOSTDISCONDETECT_MASK; + #endif + } + } + + USBHSH->PORTSC1 |= status & USBHSH_PORTSC1_W1C_MASK; +} + +// Handle PTD done interrupt +static inline void handle_ptd_done(uint32_t done_status, intptr_t ptd_array, bool is_async) { + uint8_t max_count = is_async ? IP3516_ATL_NUM : IP3516_PTL_NUM; + uint8_t stride = is_async ? sizeof(ip3516_atl_t) : sizeof(ip3516_ptl_t); + + for (uint8_t i = 0; i < max_count; i++) { + if (done_status & (1 << i)) { + intptr_t ptd_ptr = ptd_array + i * stride; + ptd_ctrl2_t *ptd_ctrl2 = (ptd_ctrl2_t *)(ptd_ptr + offsetof(ip3516_atl_t, ctrl2)); + ptd_state_t *ptd_state = (ptd_state_t *)(ptd_ptr + offsetof(ip3516_atl_t, state)); + + xfer_result_t result; + if (ptd_state->halt) { + result = XFER_RESULT_STALLED; + } else if (ptd_state->error || ptd_state->babble) { + result = XFER_RESULT_FAILED; + } else { + result = XFER_RESULT_SUCCESS; + } + + uint8_t ep_addr = ptd_ctrl2->ep_num | (ptd_state->token == IP3516_PTD_TOKEN_IN ? 0x80 : 0x00); + + hcd_event_xfer_complete(ptd_ctrl2->dev_addr, ep_addr, ptd_state->xferred_len, result, true); + } + } +} + +void hcd_int_handler(uint8_t rhport, bool in_isr) { + (void)in_isr; + + uint32_t int_status = USBHSH->USBSTS; + USBHSH->USBSTS = int_status; // clear interrupt status + + // Port Change Detect + if (int_status & USBHSH_USBSTS_PCD_MASK) { + handle_port_status_change(rhport); + } + + // Frame List Rollover + if (int_status & USBHSH_USBSTS_FLR_MASK) { + _hcd_data.uframe_number += _hcd_data.uframe_length; + } + + // ATL done + if (int_status & USBHSH_USBSTS_ATL_IRQ_MASK) { + uint32_t done_status = USBHSH->ATLPTDD; + handle_ptd_done(done_status, (intptr_t)&_ptd.atl, true); + USBHSH->ATLPTDD = done_status; + } + + // INT done + if (int_status & USBHSH_USBSTS_INT_IRQ_MASK) { + uint32_t done_status = USBHSH->INTPTDD; + handle_ptd_done(done_status, (intptr_t)&_ptd.intr, false); + USBHSH->INTPTDD = done_status; + } + + // ISO done + if (int_status & USBHSH_USBSTS_ISO_IRQ_MASK) { + uint32_t done_status = USBHSH->ISOPTDD; + handle_ptd_done(done_status, (intptr_t)&_ptd.iso, false); + USBHSH->ISOPTDD = done_status; + } +} + +#endif diff --git a/src/portable/nxp/lpc_ip3516/hcd_lpc_ip3516.h b/src/portable/nxp/lpc_ip3516/hcd_lpc_ip3516.h new file mode 100644 index 000000000..38c3a3224 --- /dev/null +++ b/src/portable/nxp/lpc_ip3516/hcd_lpc_ip3516.h @@ -0,0 +1,188 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2025 HiFiPhile (Zixun LI) + * + * 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_IP3516_H_ +#define TUSB_HCD_IP3516_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +//--------------------------------------------------------------------+ +// IP3516 CONFIGURATION & CONSTANTS +//--------------------------------------------------------------------+ + +#define IP3516_ATL_NUM 32 +#define IP3516_PTL_NUM 32 + +#define IP3516_PTD_TOKEN_OUT 0x00U +#define IP3516_PTD_TOKEN_IN 0x01U +#define IP3516_PTD_TOKEN_SETUP 0x02U + +#define IP3516_PTD_EPTYPE_OUT 0x00U +#define IP3516_PTD_EPTYPE_IN 0x01U +#define IP3516_PTD_EPTYPE_SETUP 0x02U + +#define IP3516_PTD_MAX_TRANSFER_LENGTH 0x7FFFU + +#define IP3516_PTD_DATA_ADDR_MASK 0xFFFFU + +#define IP3516_MAX_UFRAME (1UL << 8) + +#define IP3516_PERIODIC_TRANSFER_GAP (3U) +#define IP3516_ISO_MULTIPLE_TRANSFER (8U) + + +//--------------------------------------------------------------------+ +// OHCI Data Structure +//--------------------------------------------------------------------+ + +// Control Word 1 +typedef union { + uint32_t value; + struct { + uint32_t valid : 1; + uint32_t next_ptd : 5; + uint32_t : 1; + uint32_t jump : 1; + uint32_t uframe : 8; + uint32_t mps : 11; + uint32_t : 1; + uint32_t mult : 2; + uint32_t : 2; + }; +} ptd_ctrl1_t; + +TU_VERIFY_STATIC(sizeof(ptd_ctrl1_t) == 4, "size is not correct"); + +// Control Word 2 +typedef union { + uint32_t value; + struct { + uint32_t ep_num : 4; + uint32_t dev_addr : 7; + uint32_t split : 1; + uint32_t reload : 4; + uint32_t speed : 2; + uint32_t hub_port : 7; + uint32_t hub_addr : 7; + }; +} ptd_ctrl2_t; + +TU_VERIFY_STATIC(sizeof(ptd_ctrl2_t) == 4, "size is not correct"); + +// Data Word +typedef union { + uint32_t value; + struct { + uint32_t xfer_len : 15; + uint32_t intr : 1; + uint32_t data_addr : 16; + }; +} ptd_data_t; + +TU_VERIFY_STATIC(sizeof(ptd_data_t) == 4, "size is not correct"); + +// State Word +typedef union { + uint32_t value; + struct { + uint32_t xferred_len : 15; + uint32_t token : 2; + uint32_t ep_type : 2; + uint32_t nak_cnt : 4; + uint32_t err_cnt : 2; + uint32_t data_toggle : 1; + uint32_t ping : 1; + uint32_t start_complete : 1; + uint32_t error : 1; + uint32_t babble : 1; + uint32_t halt : 1; + uint32_t active : 1; + }; +} ptd_state_t; + +TU_VERIFY_STATIC(sizeof(ptd_state_t) == 4, "size is not correct"); + +// Status Word +typedef union { + uint32_t value; + struct { + uint32_t uframe_active : 8; + uint32_t iso_status0 : 3; + uint32_t iso_status1 : 3; + uint32_t iso_status2 : 3; + uint32_t iso_status3 : 3; + uint32_t iso_status4 : 3; + uint32_t iso_status5 : 3; + uint32_t iso_status6 : 3; + uint32_t iso_status7 : 3; + }; +} ptd_status_t; + +TU_VERIFY_STATIC(sizeof(ptd_status_t) == 4, "size is not correct"); + +// ATL (Asynchronous Transfer List) structure +typedef volatile struct { + ptd_ctrl1_t ctrl1; + ptd_ctrl2_t ctrl2; + ptd_data_t data; + ptd_state_t state; +} ip3516_atl_t; + +TU_VERIFY_STATIC(sizeof(ip3516_atl_t) == 16, "size is not correct"); + +// PTL (Periodic Transfer List) structure +typedef volatile struct { + ptd_ctrl1_t ctrl1; + ptd_ctrl2_t ctrl2; + ptd_data_t data; + ptd_state_t state; + ptd_status_t status; + union { + uint32_t value; + struct { + uint32_t uframe_complete : 8; + uint32_t spl_iso_in_0 : 24; + }; + } iso_in_0; + uint32_t iso_in_1; + uint32_t iso_in_2; +} ip3516_ptl_t; + +TU_VERIFY_STATIC(sizeof(ip3516_ptl_t) == 32, "size is not correct"); + +// Proprietary Transfer Descriptor +typedef struct { + ip3516_ptl_t intr[IP3516_PTL_NUM]; + ip3516_ptl_t iso[IP3516_PTL_NUM]; + ip3516_atl_t atl[IP3516_ATL_NUM]; +} ip3516_ptd_t; + +#ifdef __cplusplus +} +#endif +#endif /* TUSB_HCD_IP3516_H_ */ -- cgit v1.3.1 From 32dafcccc79cb96df7e91a5cf600f14562f779c3 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Wed, 10 Dec 2025 21:39:48 +0100 Subject: hcd/ohci: fix warnings Signed-off-by: HiFiPhile --- src/portable/ohci/ohci.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/portable') diff --git a/src/portable/ohci/ohci.c b/src/portable/ohci/ohci.c index 5ca093506..4b248d9e6 100644 --- a/src/portable/ohci/ohci.c +++ b/src/portable/ohci/ohci.c @@ -243,7 +243,7 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { OHCI_CONTROL_LIST_BULK_ENABLE_MASK | OHCI_CONTROL_LIST_PERIODIC_ENABLE_MASK; // TODO Isochronous OHCI_REG->frame_interval = (OHCI_FMINTERVAL_FSMPS << 16) | OHCI_FMINTERVAL_FI; - OHCI_REG->frame_interval ^= (1 << 31); //Must toggle when frame_interval is updated. + OHCI_REG->frame_interval ^= (1ul << 31); //Must toggle when frame_interval is updated. OHCI_REG->periodic_start = (OHCI_FMINTERVAL_FI * 9) / 10; // Periodic start is 90% of frame interval OHCI_REG->control_bit.hc_functional_state = OHCI_CONTROL_FUNCSTATE_OPERATIONAL; // make HC's state to operational state TODO use this to suspend (save power) @@ -557,6 +557,7 @@ bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { (void) rhport; ohci_ed_t * const p_ed = ed_from_addr(dev_addr, ep_addr); + TU_ASSERT(p_ed); ohci_ed_word2_t td_head = p_ed->td_head; td_head.toggle = 0; // reset data toggle -- cgit v1.3.1 From ba9bc1a79d2c00290e64a93907f37cd3db7140f8 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 12 Dec 2025 12:30:36 +0100 Subject: update LPC54 Signed-off-by: HiFiPhile --- README.rst | 4 +- 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 + hw/bsp/lpc54/boards/lpcxpresso54114/board.h | 12 + hw/bsp/lpc54/boards/lpcxpresso54608/board.h | 21 + hw/bsp/lpc54/boards/lpcxpresso54628/board.h | 12 + hw/bsp/lpc54/family.c | 78 ++-- hw/bsp/lpc54/family.cmake | 72 ++- hw/bsp/lpc54/iar/LPC54608_flash.icf | 85 ++++ hw/bsp/lpc54/iar/LPC54628_flash.icf | 83 ++++ hw/bsp/lpc54/iar/startup_LPC54608.s | 654 +++++++++++++++++++++++++++ hw/bsp/lpc54/iar/startup_LPC54628.s | 654 +++++++++++++++++++++++++++ src/common/tusb_mcu.h | 4 + src/portable/nxp/lpc_ip3516/hcd_lpc_ip3516.c | 26 +- 19 files changed, 1665 insertions(+), 47 deletions(-) create mode 100644 hw/bsp/lpc54/iar/LPC54608_flash.icf create mode 100644 hw/bsp/lpc54/iar/LPC54628_flash.icf create mode 100644 hw/bsp/lpc54/iar/startup_LPC54608.s create mode 100644 hw/bsp/lpc54/iar/startup_LPC54628.s (limited to 'src/portable') diff --git a/README.rst b/README.rst index 6a6f07825..64583f2cc 100644 --- a/README.rst +++ b/README.rst @@ -203,7 +203,9 @@ Supported CPUs | | +-------------------+--------+------+-----------+------------------------+-------------------+ | | | 51u | ✔ | ✖ | ✖ | lpc_ip3511 | | | | +-------------------+--------+------+-----------+------------------------+-------------------+ -| | | 54, 55 | ✔ | | ✔ | lpc_ip3511 | | +| | | 54 | ⚠ | ⚠ | ✔ | lpc_ip3511, lpc_ip3516 | NRND, read errata | +| | +-------------------+--------+------+-----------+------------------------+-------------------+ +| | | 55 | ✔ | ✔ | ✔ | lpc_ip3511, lpc_ip3516 | | | +---------+-------------------+--------+------+-----------+------------------------+-------------------+ | | MCX | N9 | ✔ | | ✔ | ci_fs, ci_hs, ehci | | | | +-------------------+--------+------+-----------+------------------------+-------------------+ diff --git a/examples/host/bare_api/only.txt b/examples/host/bare_api/only.txt index b39a23e40..31b35f7b9 100644 --- a/examples/host/bare_api/only.txt +++ b/examples/host/bare_api/only.txt @@ -5,6 +5,7 @@ mcu:LPC177X_8X mcu:LPC18XX mcu:LPC40XX mcu:LPC43XX +mcu:LPC54 mcu:LPC55 mcu:MIMXRT1XXX mcu:MIMXRT10XX diff --git a/examples/host/cdc_msc_hid/only.txt b/examples/host/cdc_msc_hid/only.txt index b39a23e40..31b35f7b9 100644 --- a/examples/host/cdc_msc_hid/only.txt +++ b/examples/host/cdc_msc_hid/only.txt @@ -5,6 +5,7 @@ mcu:LPC177X_8X mcu:LPC18XX mcu:LPC40XX mcu:LPC43XX +mcu:LPC54 mcu:LPC55 mcu:MIMXRT1XXX mcu:MIMXRT10XX diff --git a/examples/host/cdc_msc_hid_freertos/only.txt b/examples/host/cdc_msc_hid_freertos/only.txt index b755df825..54a9fee51 100644 --- a/examples/host/cdc_msc_hid_freertos/only.txt +++ b/examples/host/cdc_msc_hid_freertos/only.txt @@ -3,6 +3,7 @@ mcu:LPC177X_8X mcu:LPC18XX mcu:LPC40XX mcu:LPC43XX +mcu:LPC54 mcu:LPC55 mcu:MIMXRT1XXX mcu:MIMXRT10XX diff --git a/examples/host/device_info/only.txt b/examples/host/device_info/only.txt index 2a3c5c583..36be2124d 100644 --- a/examples/host/device_info/only.txt +++ b/examples/host/device_info/only.txt @@ -5,6 +5,7 @@ mcu:LPC177X_8X mcu:LPC18XX mcu:LPC40XX mcu:LPC43XX +mcu:LPC54 mcu:LPC55 mcu:MAX3421 mcu:MIMXRT1XXX diff --git a/examples/host/hid_controller/only.txt b/examples/host/hid_controller/only.txt index b39a23e40..31b35f7b9 100644 --- a/examples/host/hid_controller/only.txt +++ b/examples/host/hid_controller/only.txt @@ -5,6 +5,7 @@ mcu:LPC177X_8X mcu:LPC18XX mcu:LPC40XX mcu:LPC43XX +mcu:LPC54 mcu:LPC55 mcu:MIMXRT1XXX mcu:MIMXRT10XX diff --git a/examples/host/midi_rx/only.txt b/examples/host/midi_rx/only.txt index b0afa4fc3..9c4771de0 100644 --- a/examples/host/midi_rx/only.txt +++ b/examples/host/midi_rx/only.txt @@ -8,6 +8,7 @@ mcu:LPC177X_8X mcu:LPC18XX mcu:LPC40XX mcu:LPC43XX +mcu:LPC54 mcu:LPC55 mcu:MAX3421 mcu:MIMXRT1XXX diff --git a/examples/host/msc_file_explorer/only.txt b/examples/host/msc_file_explorer/only.txt index b39a23e40..31b35f7b9 100644 --- a/examples/host/msc_file_explorer/only.txt +++ b/examples/host/msc_file_explorer/only.txt @@ -5,6 +5,7 @@ mcu:LPC177X_8X mcu:LPC18XX mcu:LPC40XX mcu:LPC43XX +mcu:LPC54 mcu:LPC55 mcu:MIMXRT1XXX mcu:MIMXRT10XX diff --git a/hw/bsp/lpc54/boards/lpcxpresso54114/board.h b/hw/bsp/lpc54/boards/lpcxpresso54114/board.h index c43ca9d7d..1158d0675 100644 --- a/hw/bsp/lpc54/boards/lpcxpresso54114/board.h +++ b/hw/bsp/lpc54/boards/lpcxpresso54114/board.h @@ -36,6 +36,18 @@ extern "C" { #endif +// IOCON pin mux +#define IOCON_PIO_DIGITAL_EN 0x80u // Enables digital function +#define IOCON_PIO_FUNC0 0x00u +#define IOCON_PIO_FUNC1 0x01u // Selects pin function 1 +#define IOCON_PIO_FUNC7 0x07u // Selects pin function 7 +#define IOCON_PIO_INPFILT_OFF 0x0100u // Input filter disabled +#define IOCON_PIO_INV_DI 0x00u // Input function is not inverted +#define IOCON_PIO_MODE_INACT 0x00u // No addition pin function +#define IOCON_PIO_MODE_PULLUP 0x10u +#define IOCON_PIO_OPENDRAIN_DI 0x00u // Open drain is disabled +#define IOCON_PIO_SLEW_STANDARD 0x00u // Standard mode, output slew rate control is enabled + // LED #define LED_PORT 0 #define LED_PIN 29 diff --git a/hw/bsp/lpc54/boards/lpcxpresso54608/board.h b/hw/bsp/lpc54/boards/lpcxpresso54608/board.h index e985e97e0..7a5cbea87 100644 --- a/hw/bsp/lpc54/boards/lpcxpresso54608/board.h +++ b/hw/bsp/lpc54/boards/lpcxpresso54608/board.h @@ -36,6 +36,18 @@ extern "C" { #endif +// IOCON pin mux +#define IOCON_PIO_DIGITAL_EN 0x0100u // Enables digital function +#define IOCON_PIO_FUNC0 0x00u +#define IOCON_PIO_FUNC1 0x01u // Selects pin function 1 +#define IOCON_PIO_FUNC7 0x07u // Selects pin function 7 +#define IOCON_PIO_INPFILT_OFF 0x0200u // Input filter disabled +#define IOCON_PIO_INV_DI 0x00u // Input function is not inverted +#define IOCON_PIO_MODE_INACT 0x00u // No addition pin function +#define IOCON_PIO_MODE_PULLUP 0x10u +#define IOCON_PIO_OPENDRAIN_DI 0x00u // Open drain is disabled +#define IOCON_PIO_SLEW_STANDARD 0x00u // Standard mode, output slew rate control is enabled + // LED #define LED_PORT 2 #define LED_PIN 2 @@ -54,6 +66,15 @@ // USB0 VBUS #define USB0_VBUS_PINMUX 0, 22, IOCON_PIO_DIG_FUNC7_EN +// Power switch +#define USBFS_POWER_PORT 4 +#define USBFS_POWER_PIN 7 +#define USBFS_POWER_STATE_ON 0 + +#define USBHS_POWER_PORT 4 +#define USBHS_POWER_PIN 9 +#define USBHS_POWER_STATE_ON 0 + // XTAL //#define XTAL0_CLK_HZ (16 * 1000 * 1000U) diff --git a/hw/bsp/lpc54/boards/lpcxpresso54628/board.h b/hw/bsp/lpc54/boards/lpcxpresso54628/board.h index 837d26aef..5c858ed99 100644 --- a/hw/bsp/lpc54/boards/lpcxpresso54628/board.h +++ b/hw/bsp/lpc54/boards/lpcxpresso54628/board.h @@ -36,6 +36,18 @@ extern "C" { #endif +// IOCON pin mux +#define IOCON_PIO_DIGITAL_EN 0x0100u // Enables digital function +#define IOCON_PIO_FUNC0 0x00u +#define IOCON_PIO_FUNC1 0x01u // Selects pin function 1 +#define IOCON_PIO_FUNC7 0x07u // Selects pin function 7 +#define IOCON_PIO_INPFILT_OFF 0x0200u // Input filter disabled +#define IOCON_PIO_INV_DI 0x00u // Input function is not inverted +#define IOCON_PIO_MODE_INACT 0x00u // No addition pin function +#define IOCON_PIO_MODE_PULLUP 0x10u +#define IOCON_PIO_OPENDRAIN_DI 0x00u // Open drain is disabled +#define IOCON_PIO_SLEW_STANDARD 0x00u // Standard mode, output slew rate control is enabled + // LED #define LED_PORT 2 #define LED_PIN 2 diff --git a/hw/bsp/lpc54/family.c b/hw/bsp/lpc54/family.c index 7bb73afbc..3d5bb8d5a 100644 --- a/hw/bsp/lpc54/family.c +++ b/hw/bsp/lpc54/family.c @@ -41,18 +41,6 @@ // MACRO TYPEDEF CONSTANT ENUM //--------------------------------------------------------------------+ -// IOCON pin mux -#define IOCON_PIO_DIGITAL_EN 0x80u // Enables digital function -#define IOCON_PIO_FUNC0 0x00u -#define IOCON_PIO_FUNC1 0x01u // Selects pin function 1 -#define IOCON_PIO_FUNC7 0x07u // Selects pin function 7 -#define IOCON_PIO_INPFILT_OFF 0x0100u // Input filter disabled -#define IOCON_PIO_INV_DI 0x00u // Input function is not inverted -#define IOCON_PIO_MODE_INACT 0x00u // No addition pin function -#define IOCON_PIO_MODE_PULLUP 0x10u -#define IOCON_PIO_OPENDRAIN_DI 0x00u // Open drain is disabled -#define IOCON_PIO_SLEW_STANDARD 0x00u // Standard mode, output slew rate control is enabled - // Digital pin function n enabled #define IOCON_PIO_DIG_FUNC0_EN (IOCON_PIO_DIGITAL_EN | IOCON_PIO_INPFILT_OFF | IOCON_PIO_FUNC0) #define IOCON_PIO_DIG_FUNC1_EN (IOCON_PIO_DIGITAL_EN | IOCON_PIO_INPFILT_OFF | IOCON_PIO_FUNC1) @@ -149,37 +137,71 @@ void board_init(void) { USART_Init(UART_DEV, &uart_config, 12000000); #endif - // USB - IOCON_PinMuxSet(IOCON, USB0_VBUS_PINMUX); - #if defined(FSL_FEATURE_SOC_USBHSD_COUNT) && FSL_FEATURE_SOC_USBHSD_COUNT // LPC546xx and LPC540xx has OTG 1 FS + 1 HS rhports - #if defined(BOARD_TUD_RHPORT) && BOARD_TUD_RHPORT == 0 + #if (CFG_TUD_ENABLED && BOARD_TUD_RHPORT == 0) || (CFG_TUH_ENABLED && BOARD_TUH_RHPORT == 0) + /* PORT0 PIN22 configured as USB0_VBUS */ + IOCON_PinMuxSet(IOCON, USB0_VBUS_PINMUX); + // Port0 is Full Speed POWER_DisablePD(kPDRUNCFG_PD_USB0_PHY); /*< Turn on USB Phy */ CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 1, false); CLOCK_AttachClk(kFRO_HF_to_USB0_CLK); - /*According to reference manual, device mode setting has to be set by access usb host register */ - CLOCK_EnableClock(kCLOCK_Usbhsl0); /* enable usb0 host clock */ - USBFSH->PORTMODE |= USBFSH_PORTMODE_DEV_ENABLE_MASK; - CLOCK_DisableClock(kCLOCK_Usbhsl0); /* disable usb0 host clock */ - - CLOCK_EnableUsbfs0DeviceClock(kCLOCK_UsbSrcFro, CLOCK_GetFroHfFreq()); + if (CFG_TUD_ENABLED && BOARD_TUD_RHPORT == 0) { + /*According to reference manual, device mode setting has to be set by access usb host register */ + CLOCK_EnableClock(kCLOCK_Usbhsl0); /* enable usb0 host clock */ + USBFSH->PORTMODE |= USBFSH_PORTMODE_DEV_ENABLE_MASK; + CLOCK_DisableClock(kCLOCK_Usbhsl0); /* disable usb0 host clock */ + + CLOCK_EnableUsbfs0DeviceClock(kCLOCK_UsbSrcFro, CLOCK_GetFroHfFreq()); + } else { + #ifdef USBFS_POWER_PORT + /* Configure USB0 Power Switch Pin */ + IOCON_PinMuxSet(IOCON, USBFS_POWER_PORT, USBFS_POWER_PIN, IOCON_PIO_DIG_FUNC0_EN); + + gpio_pin_config_t const power_pin_config = {kGPIO_DigitalOutput, USBFS_POWER_STATE_ON}; + GPIO_PinInit(GPIO, USBFS_POWER_PORT, USBFS_POWER_PIN, &power_pin_config); + #endif + CLOCK_EnableUsbfs0HostClock(kCLOCK_UsbSrcFro, CLOCK_GetFroHfFreq()); + USBFSH->PORTMODE &= ~USBFSH_PORTMODE_DEV_ENABLE_MASK; + } #endif - #if defined(BOARD_TUD_RHPORT) && BOARD_TUD_RHPORT == 1 - // Port1 is High Speed - POWER_DisablePD(kPDRUNCFG_PD_USB1_PHY); + #if (CFG_TUD_ENABLED && BOARD_TUD_RHPORT == 1) || (CFG_TUH_ENABLED && BOARD_TUH_RHPORT == 1) + // Port1 is High Speed + + /* Turn on USB1 Phy */ + POWER_DisablePD(kPDRUNCFG_PD_USB1_PHY); - /*According to reference manual, device mode setting has to be set by access usb host register */ - CLOCK_EnableClock(kCLOCK_Usbh1); /* enable usb1 host clock */ + /* reset the IP to make sure it's in reset state. */ + RESET_PeripheralReset(kUSB1H_RST_SHIFT_RSTn); + RESET_PeripheralReset(kUSB1D_RST_SHIFT_RSTn); + RESET_PeripheralReset(kUSB1RAM_RST_SHIFT_RSTn); + + if (CFG_TUD_ENABLED && BOARD_TUD_RHPORT == 1) { + /* According to reference manual, device mode setting has to be set by access usb host register */ + CLOCK_EnableClock(kCLOCK_Usbh1); // enable usb0 host clock + + USBHSH->PORTMODE = USBHSH_PORTMODE_SW_PDCOM_MASK; // Put PHY powerdown under software control USBHSH->PORTMODE |= USBHSH_PORTMODE_DEV_ENABLE_MASK; - CLOCK_DisableClock(kCLOCK_Usbh1); /* enable usb1 host clock */ + CLOCK_DisableClock(kCLOCK_Usbh1); // disable usb0 host clock + /* enable USB Device clock */ CLOCK_EnableUsbhs0DeviceClock(kCLOCK_UsbSrcUsbPll, 0U); + } else { + #ifdef USBHS_POWER_PORT + /* Configure USB1 Power Switch Pin */ + IOCON_PinMuxSet(IOCON, USBHS_POWER_PORT, USBHS_POWER_PIN, IOCON_PIO_DIG_FUNC0_EN); + + gpio_pin_config_t const power_pin_config = {kGPIO_DigitalOutput, USBHS_POWER_STATE_ON}; + GPIO_PinInit(GPIO, USBHS_POWER_PORT, USBHS_POWER_PIN, &power_pin_config); + #endif + CLOCK_EnableUsbhs0HostClock(kCLOCK_UsbSrcUsbPll, 0U); + } #endif #else + IOCON_PinMuxSet(IOCON, USB0_VBUS_PINMUX); // LPC5411x series only has full speed device POWER_DisablePD(kPDRUNCFG_PD_USB0_PHY); // Turn on USB Phy CLOCK_EnableUsbfs0Clock(kCLOCK_UsbSrcFro, CLOCK_GetFreq(kCLOCK_FroHf)); /* enable USB IP clock */ diff --git a/hw/bsp/lpc54/family.cmake b/hw/bsp/lpc54/family.cmake index c6145bd41..ebc0689fd 100644 --- a/hw/bsp/lpc54/family.cmake +++ b/hw/bsp/lpc54/family.cmake @@ -12,13 +12,29 @@ set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOL set(FAMILY_MCUS LPC54 CACHE INTERNAL "") -if (NOT DEFINED PORT) - set(PORT 0) -endif() +# ---------------------- +# Port & Speed Selection +# ---------------------- -# Host port will be the other port if available -set(HOST_PORT $) +# default device port to USB1 highspeed, host to USB0 fullspeed +if (NOT DEFINED RHPORT_DEVICE) + set(RHPORT_DEVICE 1) +endif () +if (NOT DEFINED RHPORT_HOST) + set(RHPORT_HOST 1) +endif () + +# port 0 is fullspeed, port 1 is highspeed +set(RHPORT_SPEED OPT_MODE_FULL_SPEED OPT_MODE_HIGH_SPEED) + +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) #------------------------------------ # Startup & Linker script #------------------------------------ @@ -26,11 +42,20 @@ if (NOT DEFINED LD_FILE_GNU) set(LD_FILE_GNU ${SDK_DIR}/devices/${MCU_VARIANT}/gcc/${MCU_CORE}_flash.ld) endif () set(LD_FILE_Clang ${LD_FILE_GNU}) + if (NOT DEFINED STARTUP_FILE_GNU) set(STARTUP_FILE_GNU ${SDK_DIR}/devices/${MCU_VARIANT}/gcc/startup_${MCU_CORE}.S) endif () set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +if (NOT DEFINED LD_FILE_IAR) + set(LD_FILE_IAR ${CMAKE_CURRENT_LIST_DIR}/iar/${MCU_CORE}_flash.icf) +endif () + +if (NOT DEFINED STARTUP_FILE_IAR) + set(STARTUP_FILE_IAR ${CMAKE_CURRENT_LIST_DIR}/iar/startup_${MCU_CORE}.s) +endif () + #------------------------------------ # Board Target #------------------------------------ @@ -64,24 +89,23 @@ function(family_add_board BOARD_TARGET) ) target_compile_definitions(${BOARD_TARGET} PUBLIC CFG_TUSB_MEM_ALIGN=TU_ATTR_ALIGNED\(64\) - BOARD_TUD_RHPORT=${PORT} - BOARD_TUH_RHPORT=${HOST_PORT} + BOARD_TUD_RHPORT=${RHPORT_DEVICE} + BOARD_TUD_MAX_SPEED=${RHPORT_DEVICE_SPEED} + BOARD_TUH_RHPORT=${RHPORT_HOST} + BOARD_TUH_MAX_SPEED=${RHPORT_HOST_SPEED} __STARTUP_CLEAR_BSS ) - # Port 0 is Fullspeed, Port 1 is Highspeed. Port1 controller can only access USB_SRAM - if (PORT EQUAL 1) + # Port 0 is Fullspeed, Port 1 is Highspeed. Port1 controller can only access USB_SRAM + if (RHPORT_DEVICE EQUAL 1) target_compile_definitions(${BOARD_TARGET} PUBLIC - BOARD_TUD_MAX_SPEED=OPT_MODE_HIGH_SPEED - BOARD_TUH_MAX_SPEED=OPT_MODE_FULL_SPEED - CFG_TUD_MEM_SECTION=__attribute__\(\(section\(\"m_usb_global\"\)\)\) + [=[CFG_TUD_MEM_SECTION=__attribute__((section("m_usb_global")))]=] ) - else () + endif () + if (RHPORT_HOST EQUAL 1) target_compile_definitions(${BOARD_TARGET} PUBLIC - BOARD_TUD_MAX_SPEED=OPT_MODE_FULL_SPEED - BOARD_TUH_MAX_SPEED=OPT_MODE_HIGH_SPEED - CFG_TUH_MEM_SECTION=__attribute__\(\(section\(\"m_usb_global\"\)\)\) - #CFG_TUD_MEM_SECTION=__attribute__\(\(section\(\"m_usb_global\"\)\)\) + [=[CFG_TUH_MEM_SECTION=__attribute__((section("m_usb_global")))]=] + CFG_TUH_USBIP_IP3516=1 ) endif () @@ -107,11 +131,23 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) + if (RHPORT_HOST EQUAL 0) + target_sources(${TARGET} PUBLIC + ${TOP}/src/portable/ohci/ohci.c + ) + elseif (RHPORT_HOST EQUAL 1) + target_sources(${TARGET} PUBLIC + ${TOP}/src/portable/nxp/lpc_ip3516/hcd_lpc_ip3516.c + ) + endif () + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") target_link_options(${TARGET} PUBLIC "LINKER:--script=${LD_FILE_GNU}" --specs=nosys.specs --specs=nano.specs -nostartfiles + "LINKER:--defsym=__stack_size__=0x1000" + "LINKER:--defsym=__heap_size__=0" ) elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") target_link_options(${TARGET} PUBLIC @@ -120,6 +156,8 @@ function(family_configure_example TARGET RTOS) elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") target_link_options(${TARGET} PUBLIC "LINKER:--config=${LD_FILE_IAR}" + "LINKER:--config_def=__stack_size__=0x1000" + "LINKER:--config_def=__heap_size__=0" ) endif () diff --git a/hw/bsp/lpc54/iar/LPC54608_flash.icf b/hw/bsp/lpc54/iar/LPC54608_flash.icf new file mode 100644 index 000000000..2a7885541 --- /dev/null +++ b/hw/bsp/lpc54/iar/LPC54608_flash.icf @@ -0,0 +1,85 @@ +/* +** ################################################################### +** Processors: LPC54608J512BD208 +** LPC54608J512ET180 +** +** Compiler: IAR ANSI C/C++ Compiler for ARM +** Reference manual: LPC546xx User manual Rev.1.9 5 June 2017 +** Version: rev. 1.2, 2017-06-08 +** Build: b241125 +** +** Abstract: +** Linker file for the IAR ANSI C/C++ Compiler for ARM +** +** Copyright 2016 Freescale Semiconductor, Inc. +** Copyright 2016-2024 NXP +** SPDX-License-Identifier: BSD-3-Clause +** +** http: www.nxp.com +** mail: support@nxp.com +** +** ################################################################### +*/ + +define symbol m_interrupts_start = 0x00000000; +define symbol m_interrupts_end = 0x000003FF; + +define symbol m_text_start = 0x00000400; +define symbol m_text_end = 0x0007FFFF; + +define symbol m_data_start = 0x20000000; +define symbol m_data_end = 0x20027FFF; + +define symbol m_usb_sram_start = 0x40100000; +define symbol m_usb_sram_end = 0x40101FFF; + +/* USB BDT size */ +define symbol usb_bdt_size = 0x0; +/* Sizes */ +if (isdefinedsymbol(__stack_size__)) { + define symbol __size_cstack__ = __stack_size__; +} else { + define symbol __size_cstack__ = 0x0400; +} + +if (isdefinedsymbol(__heap_size__)) { + define symbol __size_heap__ = __heap_size__; +} else { + define symbol __size_heap__ = 0x0400; +} + + +define memory mem with size = 4G; +define region TEXT_region = mem:[from m_interrupts_start to m_interrupts_end] + | mem:[from m_text_start to m_text_end]; +define region DATA_region = mem:[from m_data_start to m_data_end-__size_cstack__]; +define region CSTACK_region = mem:[from m_data_end-__size_cstack__+1 to m_data_end]; + +define block CSTACK with alignment = 8, size = __size_cstack__ { }; +define block HEAP with alignment = 8, size = __size_heap__ { }; +define block RW { readwrite }; +define block ZI { zi }; + +/* regions for USB */ +define region USB_BDT_region = mem:[from m_usb_sram_start to m_usb_sram_start + usb_bdt_size - 1]; +define region USB_SRAM_region = mem:[from m_usb_sram_start + usb_bdt_size to m_usb_sram_end]; +place in USB_BDT_region { section m_usb_bdt }; +place in USB_SRAM_region { section m_usb_global }; + +initialize by copy { readwrite, section .textrw }; + +if (isdefinedsymbol(__USE_DLIB_PERTHREAD)) +{ + /* Required in a multi-threaded application */ + initialize by copy with packing = none { section __DLIB_PERTHREAD }; +} + +do not initialize { section .noinit, section m_usb_bdt, section m_usb_global }; + +place at address mem: m_interrupts_start { readonly section .intvec }; +place in TEXT_region { readonly }; +place in DATA_region { block RW }; +place in DATA_region { block ZI }; +place in DATA_region { last block HEAP }; +place in CSTACK_region { block CSTACK }; + diff --git a/hw/bsp/lpc54/iar/LPC54628_flash.icf b/hw/bsp/lpc54/iar/LPC54628_flash.icf new file mode 100644 index 000000000..7cca18159 --- /dev/null +++ b/hw/bsp/lpc54/iar/LPC54628_flash.icf @@ -0,0 +1,83 @@ +/* +** ################################################################### +** Processor: LPC54628J512ET180 +** Compiler: IAR ANSI C/C++ Compiler for ARM +** Reference manual: LPC546xx User manual Rev.1.9 5 June 2017 +** Version: rev. 1.2, 2017-06-08 +** Build: b241125 +** +** Abstract: +** Linker file for the IAR ANSI C/C++ Compiler for ARM +** +** Copyright 2016 Freescale Semiconductor, Inc. +** Copyright 2016-2024 NXP +** SPDX-License-Identifier: BSD-3-Clause +** +** http: www.nxp.com +** mail: support@nxp.com +** +** ################################################################### +*/ + +define symbol m_interrupts_start = 0x00000000; +define symbol m_interrupts_end = 0x000003FF; + +define symbol m_text_start = 0x00000400; +define symbol m_text_end = 0x0007FFFF; + +define symbol m_data_start = 0x20000000; +define symbol m_data_end = 0x20027FFF; + +define symbol m_usb_sram_start = 0x40100000; +define symbol m_usb_sram_end = 0x40101FFF; + +/* USB BDT size */ +define symbol usb_bdt_size = 0x0; +/* Sizes */ +if (isdefinedsymbol(__stack_size__)) { + define symbol __size_cstack__ = __stack_size__; +} else { + define symbol __size_cstack__ = 0x0400; +} + +if (isdefinedsymbol(__heap_size__)) { + define symbol __size_heap__ = __heap_size__; +} else { + define symbol __size_heap__ = 0x0400; +} + + +define memory mem with size = 4G; +define region TEXT_region = mem:[from m_interrupts_start to m_interrupts_end] + | mem:[from m_text_start to m_text_end]; +define region DATA_region = mem:[from m_data_start to m_data_end-__size_cstack__]; +define region CSTACK_region = mem:[from m_data_end-__size_cstack__+1 to m_data_end]; + +define block CSTACK with alignment = 8, size = __size_cstack__ { }; +define block HEAP with alignment = 8, size = __size_heap__ { }; +define block RW { readwrite }; +define block ZI { zi }; + +/* regions for USB */ +define region USB_BDT_region = mem:[from m_usb_sram_start to m_usb_sram_start + usb_bdt_size - 1]; +define region USB_SRAM_region = mem:[from m_usb_sram_start + usb_bdt_size to m_usb_sram_end]; +place in USB_BDT_region { section m_usb_bdt }; +place in USB_SRAM_region { section m_usb_global }; + +initialize by copy { readwrite, section .textrw }; + +if (isdefinedsymbol(__USE_DLIB_PERTHREAD)) +{ + /* Required in a multi-threaded application */ + initialize by copy with packing = none { section __DLIB_PERTHREAD }; +} + +do not initialize { section .noinit, section m_usb_bdt, section m_usb_global }; + +place at address mem: m_interrupts_start { readonly section .intvec }; +place in TEXT_region { readonly }; +place in DATA_region { block RW }; +place in DATA_region { block ZI }; +place in DATA_region { last block HEAP }; +place in CSTACK_region { block CSTACK }; + diff --git a/hw/bsp/lpc54/iar/startup_LPC54608.s b/hw/bsp/lpc54/iar/startup_LPC54608.s new file mode 100644 index 000000000..05c4350e5 --- /dev/null +++ b/hw/bsp/lpc54/iar/startup_LPC54608.s @@ -0,0 +1,654 @@ +; ------------------------------------------------------------------------- +; @file: startup_LPC54608.s +; @purpose: CMSIS Cortex-M4 Core Device Startup File +; LPC54608 +; @version: 2.0 +; @date: 2024-10-29 +; @build: b250521 +; ------------------------------------------------------------------------- +; +; Copyright 1997-2016 Freescale Semiconductor, Inc. +; Copyright 2016-2025 NXP +; SPDX-License-Identifier: BSD-3-Clause +; +; The modules in this file are included in the libraries, and may be replaced +; by any user-defined modules that define the PUBLIC symbol _program_start or +; a user defined start symbol. +; To override the cstartup defined in the library, simply add your modified +; version to the workbench project. +; +; The vector table is normally located at address 0. +; When debugging in RAM, it can be located in RAM, aligned to at least 2^6. +; The name "__vector_table" has special meaning for C-SPY: +; it is where the SP start value is found, and the NVIC vector +; table register (VTOR) is initialized to this address if != 0. +; +; Cortex-M version +; + + MODULE ?cstartup + + ;; Forward declaration of sections. + SECTION CSTACK:DATA:NOROOT(3) + + SECTION .intvec:CODE:NOROOT(2) + + EXTERN __iar_program_start + EXTERN SystemInit + PUBLIC __vector_table + PUBLIC __vector_table_0x1c + PUBLIC __Vectors + PUBLIC __Vectors_End + PUBLIC __Vectors_Size + + DATA + +__iar_init$$done: ; The vector table is not needed + ; until after copy initialization is done + +__vector_table + DCD sfe(CSTACK) + DCD Reset_Handler + + DCD NMI_Handler ;NMI Handler + DCD HardFault_Handler ;Hard Fault Handler + DCD MemManage_Handler ;MPU Fault Handler + DCD BusFault_Handler ;Bus Fault Handler + DCD UsageFault_Handler ;Usage Fault Handler +__vector_table_0x1c + DCD 0 ;Reserved + DCD 0xFFFFFFFF ;ECRP + DCD 0 ;Reserved + DCD 0 ;Reserved + DCD SVC_Handler ;SVCall Handler + DCD DebugMon_Handler ;Debug Monitor Handler + DCD 0 ;Reserved + DCD PendSV_Handler ;PendSV Handler + DCD SysTick_Handler ;SysTick Handler + + ;External Interrupts + DCD WDT_BOD_IRQHandler ;Windowed watchdog timer, Brownout detect + DCD DMA0_IRQHandler ;DMA controller + DCD GINT0_IRQHandler ;GPIO group 0 + DCD GINT1_IRQHandler ;GPIO group 1 + DCD PIN_INT0_IRQHandler ;Pin interrupt 0 or pattern match engine slice 0 + DCD PIN_INT1_IRQHandler ;Pin interrupt 1or pattern match engine slice 1 + DCD PIN_INT2_IRQHandler ;Pin interrupt 2 or pattern match engine slice 2 + DCD PIN_INT3_IRQHandler ;Pin interrupt 3 or pattern match engine slice 3 + DCD UTICK0_IRQHandler ;Micro-tick Timer + DCD MRT0_IRQHandler ;Multi-rate timer + DCD CTIMER0_IRQHandler ;Standard counter/timer CTIMER0 + DCD CTIMER1_IRQHandler ;Standard counter/timer CTIMER1 + DCD SCT0_IRQHandler ;SCTimer/PWM + DCD CTIMER3_IRQHandler ;Standard counter/timer CTIMER3 + DCD FLEXCOMM0_IRQHandler ;Flexcomm Interface 0 (USART, SPI, I2C, FLEXCOMM) + DCD FLEXCOMM1_IRQHandler ;Flexcomm Interface 1 (USART, SPI, I2C, FLEXCOMM) + DCD FLEXCOMM2_IRQHandler ;Flexcomm Interface 2 (USART, SPI, I2C, FLEXCOMM) + DCD FLEXCOMM3_IRQHandler ;Flexcomm Interface 3 (USART, SPI, I2C, FLEXCOMM) + DCD FLEXCOMM4_IRQHandler ;Flexcomm Interface 4 (USART, SPI, I2C, FLEXCOMM) + DCD FLEXCOMM5_IRQHandler ;Flexcomm Interface 5 (USART, SPI, I2C,, FLEXCOMM) + DCD FLEXCOMM6_IRQHandler ;Flexcomm Interface 6 (USART, SPI, I2C, I2S,, FLEXCOMM) + DCD FLEXCOMM7_IRQHandler ;Flexcomm Interface 7 (USART, SPI, I2C, I2S,, FLEXCOMM) + DCD ADC0_SEQA_IRQHandler ;ADC0 sequence A completion. + DCD ADC0_SEQB_IRQHandler ;ADC0 sequence B completion. + DCD ADC0_THCMP_IRQHandler ;ADC0 threshold compare and error. + DCD DMIC0_IRQHandler ;Digital microphone and DMIC subsystem + DCD HWVAD0_IRQHandler ;Hardware Voice Activity Detector + DCD USB0_NEEDCLK_IRQHandler ;USB Activity Wake-up Interrupt + DCD USB0_IRQHandler ;USB device + DCD RTC_IRQHandler ;RTC alarm and wake-up interrupts + DCD Reserved46_IRQHandler ;Reserved interrupt + DCD Reserved47_IRQHandler ;Reserved interrupt + DCD PIN_INT4_IRQHandler ;Pin interrupt 4 or pattern match engine slice 4 int + DCD PIN_INT5_IRQHandler ;Pin interrupt 5 or pattern match engine slice 5 int + DCD PIN_INT6_IRQHandler ;Pin interrupt 6 or pattern match engine slice 6 int + DCD PIN_INT7_IRQHandler ;Pin interrupt 7 or pattern match engine slice 7 int + DCD CTIMER2_IRQHandler ;Standard counter/timer CTIMER2 + DCD CTIMER4_IRQHandler ;Standard counter/timer CTIMER4 + DCD RIT_IRQHandler ;Repetitive Interrupt Timer + DCD SPIFI0_IRQHandler ;SPI flash interface + DCD FLEXCOMM8_IRQHandler ;Flexcomm Interface 8 (USART, SPI, I2C, FLEXCOMM) + DCD FLEXCOMM9_IRQHandler ;Flexcomm Interface 9 (USART, SPI, I2C, FLEXCOMM) + DCD SDIO_IRQHandler ;SD/MMC + DCD CAN0_IRQ0_IRQHandler ;CAN0 interrupt0 + DCD CAN0_IRQ1_IRQHandler ;CAN0 interrupt1 + DCD CAN1_IRQ0_IRQHandler ;CAN1 interrupt0 + DCD CAN1_IRQ1_IRQHandler ;CAN1 interrupt1 + DCD USB1_IRQHandler ;USB1 interrupt + DCD USB1_NEEDCLK_IRQHandler ;USB1 activity + DCD ETHERNET_IRQHandler ;Ethernet + DCD ETHERNET_PMT_IRQHandler ;Ethernet power management interrupt + DCD ETHERNET_MACLP_IRQHandler ;Ethernet MAC interrupt + DCD EEPROM_IRQHandler ;EEPROM interrupt + DCD LCD_IRQHandler ;LCD interrupt + DCD SHA_IRQHandler ;SHA interrupt + DCD SMARTCARD0_IRQHandler ;Smart card 0 interrupt + DCD SMARTCARD1_IRQHandler ;Smart card 1 interrupt +__Vectors_End + +__Vectors EQU __vector_table +__Vectors_Size EQU __Vectors_End - __Vectors + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Default interrupt handlers. +;; + THUMB + + PUBWEAK Reset_Handler + SECTION .text:CODE:REORDER:NOROOT(2) +Reset_Handler + MOVS r0,#56 + LDR r1, =0x40000220 + STR r0, [r1] ;Enable SRAM clock used by Stack + LDR R0, =SystemInit + BLX R0 + LDR R0, =__iar_program_start + BX R0 + + PUBWEAK NMI_Handler + SECTION .text:CODE:REORDER:NOROOT(1) +NMI_Handler + B . + + PUBWEAK HardFault_Handler + SECTION .text:CODE:REORDER:NOROOT(1) +HardFault_Handler + B . + + PUBWEAK MemManage_Handler + SECTION .text:CODE:REORDER:NOROOT(1) +MemManage_Handler + B . + + PUBWEAK BusFault_Handler + SECTION .text:CODE:REORDER:NOROOT(1) +BusFault_Handler + B . + + PUBWEAK UsageFault_Handler + SECTION .text:CODE:REORDER:NOROOT(1) +UsageFault_Handler + B . + + PUBWEAK SVC_Handler + SECTION .text:CODE:REORDER:NOROOT(1) +SVC_Handler + B . + + PUBWEAK DebugMon_Handler + SECTION .text:CODE:REORDER:NOROOT(1) +DebugMon_Handler + B . + + PUBWEAK PendSV_Handler + SECTION .text:CODE:REORDER:NOROOT(1) +PendSV_Handler + B . + + PUBWEAK SysTick_Handler + SECTION .text:CODE:REORDER:NOROOT(1) +SysTick_Handler + B . + + PUBWEAK WDT_BOD_IRQHandler + PUBWEAK WDT_BOD_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +WDT_BOD_IRQHandler + LDR R0, =WDT_BOD_DriverIRQHandler + BX R0 + + PUBWEAK DMA0_IRQHandler + PUBWEAK DMA0_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +DMA0_IRQHandler + LDR R0, =DMA0_DriverIRQHandler + BX R0 + + PUBWEAK GINT0_IRQHandler + PUBWEAK GINT0_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +GINT0_IRQHandler + LDR R0, =GINT0_DriverIRQHandler + BX R0 + + PUBWEAK GINT1_IRQHandler + PUBWEAK GINT1_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +GINT1_IRQHandler + LDR R0, =GINT1_DriverIRQHandler + BX R0 + + PUBWEAK PIN_INT0_IRQHandler + PUBWEAK PIN_INT0_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +PIN_INT0_IRQHandler + LDR R0, =PIN_INT0_DriverIRQHandler + BX R0 + + PUBWEAK PIN_INT1_IRQHandler + PUBWEAK PIN_INT1_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +PIN_INT1_IRQHandler + LDR R0, =PIN_INT1_DriverIRQHandler + BX R0 + + PUBWEAK PIN_INT2_IRQHandler + PUBWEAK PIN_INT2_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +PIN_INT2_IRQHandler + LDR R0, =PIN_INT2_DriverIRQHandler + BX R0 + + PUBWEAK PIN_INT3_IRQHandler + PUBWEAK PIN_INT3_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +PIN_INT3_IRQHandler + LDR R0, =PIN_INT3_DriverIRQHandler + BX R0 + + PUBWEAK UTICK0_IRQHandler + PUBWEAK UTICK0_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +UTICK0_IRQHandler + LDR R0, =UTICK0_DriverIRQHandler + BX R0 + + PUBWEAK MRT0_IRQHandler + PUBWEAK MRT0_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +MRT0_IRQHandler + LDR R0, =MRT0_DriverIRQHandler + BX R0 + + PUBWEAK CTIMER0_IRQHandler + PUBWEAK CTIMER0_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +CTIMER0_IRQHandler + LDR R0, =CTIMER0_DriverIRQHandler + BX R0 + + PUBWEAK CTIMER1_IRQHandler + PUBWEAK CTIMER1_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +CTIMER1_IRQHandler + LDR R0, =CTIMER1_DriverIRQHandler + BX R0 + + PUBWEAK SCT0_IRQHandler + PUBWEAK SCT0_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +SCT0_IRQHandler + LDR R0, =SCT0_DriverIRQHandler + BX R0 + + PUBWEAK CTIMER3_IRQHandler + PUBWEAK CTIMER3_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +CTIMER3_IRQHandler + LDR R0, =CTIMER3_DriverIRQHandler + BX R0 + + PUBWEAK FLEXCOMM0_IRQHandler + PUBWEAK FLEXCOMM0_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +FLEXCOMM0_IRQHandler + LDR R0, =FLEXCOMM0_DriverIRQHandler + BX R0 + + PUBWEAK FLEXCOMM1_IRQHandler + PUBWEAK FLEXCOMM1_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +FLEXCOMM1_IRQHandler + LDR R0, =FLEXCOMM1_DriverIRQHandler + BX R0 + + PUBWEAK FLEXCOMM2_IRQHandler + PUBWEAK FLEXCOMM2_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +FLEXCOMM2_IRQHandler + LDR R0, =FLEXCOMM2_DriverIRQHandler + BX R0 + + PUBWEAK FLEXCOMM3_IRQHandler + PUBWEAK FLEXCOMM3_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +FLEXCOMM3_IRQHandler + LDR R0, =FLEXCOMM3_DriverIRQHandler + BX R0 + + PUBWEAK FLEXCOMM4_IRQHandler + PUBWEAK FLEXCOMM4_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +FLEXCOMM4_IRQHandler + LDR R0, =FLEXCOMM4_DriverIRQHandler + BX R0 + + PUBWEAK FLEXCOMM5_IRQHandler + PUBWEAK FLEXCOMM5_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +FLEXCOMM5_IRQHandler + LDR R0, =FLEXCOMM5_DriverIRQHandler + BX R0 + + PUBWEAK FLEXCOMM6_IRQHandler + PUBWEAK FLEXCOMM6_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +FLEXCOMM6_IRQHandler + LDR R0, =FLEXCOMM6_DriverIRQHandler + BX R0 + + PUBWEAK FLEXCOMM7_IRQHandler + PUBWEAK FLEXCOMM7_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +FLEXCOMM7_IRQHandler + LDR R0, =FLEXCOMM7_DriverIRQHandler + BX R0 + + PUBWEAK ADC0_SEQA_IRQHandler + PUBWEAK ADC0_SEQA_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +ADC0_SEQA_IRQHandler + LDR R0, =ADC0_SEQA_DriverIRQHandler + BX R0 + + PUBWEAK ADC0_SEQB_IRQHandler + PUBWEAK ADC0_SEQB_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +ADC0_SEQB_IRQHandler + LDR R0, =ADC0_SEQB_DriverIRQHandler + BX R0 + + PUBWEAK ADC0_THCMP_IRQHandler + PUBWEAK ADC0_THCMP_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +ADC0_THCMP_IRQHandler + LDR R0, =ADC0_THCMP_DriverIRQHandler + BX R0 + + PUBWEAK DMIC0_IRQHandler + PUBWEAK DMIC0_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +DMIC0_IRQHandler + LDR R0, =DMIC0_DriverIRQHandler + BX R0 + + PUBWEAK HWVAD0_IRQHandler + PUBWEAK HWVAD0_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +HWVAD0_IRQHandler + LDR R0, =HWVAD0_DriverIRQHandler + BX R0 + + PUBWEAK USB0_NEEDCLK_IRQHandler + PUBWEAK USB0_NEEDCLK_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +USB0_NEEDCLK_IRQHandler + LDR R0, =USB0_NEEDCLK_DriverIRQHandler + BX R0 + + PUBWEAK USB0_IRQHandler + PUBWEAK USB0_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +USB0_IRQHandler + LDR R0, =USB0_DriverIRQHandler + BX R0 + + PUBWEAK RTC_IRQHandler + PUBWEAK RTC_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +RTC_IRQHandler + LDR R0, =RTC_DriverIRQHandler + BX R0 + + PUBWEAK Reserved46_IRQHandler + PUBWEAK Reserved46_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +Reserved46_IRQHandler + LDR R0, =Reserved46_DriverIRQHandler + BX R0 + + PUBWEAK Reserved47_IRQHandler + PUBWEAK Reserved47_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +Reserved47_IRQHandler + LDR R0, =Reserved47_DriverIRQHandler + BX R0 + + PUBWEAK PIN_INT4_IRQHandler + PUBWEAK PIN_INT4_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +PIN_INT4_IRQHandler + LDR R0, =PIN_INT4_DriverIRQHandler + BX R0 + + PUBWEAK PIN_INT5_IRQHandler + PUBWEAK PIN_INT5_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +PIN_INT5_IRQHandler + LDR R0, =PIN_INT5_DriverIRQHandler + BX R0 + + PUBWEAK PIN_INT6_IRQHandler + PUBWEAK PIN_INT6_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +PIN_INT6_IRQHandler + LDR R0, =PIN_INT6_DriverIRQHandler + BX R0 + + PUBWEAK PIN_INT7_IRQHandler + PUBWEAK PIN_INT7_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +PIN_INT7_IRQHandler + LDR R0, =PIN_INT7_DriverIRQHandler + BX R0 + + PUBWEAK CTIMER2_IRQHandler + PUBWEAK CTIMER2_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +CTIMER2_IRQHandler + LDR R0, =CTIMER2_DriverIRQHandler + BX R0 + + PUBWEAK CTIMER4_IRQHandler + PUBWEAK CTIMER4_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +CTIMER4_IRQHandler + LDR R0, =CTIMER4_DriverIRQHandler + BX R0 + + PUBWEAK RIT_IRQHandler + PUBWEAK RIT_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +RIT_IRQHandler + LDR R0, =RIT_DriverIRQHandler + BX R0 + + PUBWEAK SPIFI0_IRQHandler + PUBWEAK SPIFI0_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +SPIFI0_IRQHandler + LDR R0, =SPIFI0_DriverIRQHandler + BX R0 + + PUBWEAK FLEXCOMM8_IRQHandler + PUBWEAK FLEXCOMM8_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +FLEXCOMM8_IRQHandler + LDR R0, =FLEXCOMM8_DriverIRQHandler + BX R0 + + PUBWEAK FLEXCOMM9_IRQHandler + PUBWEAK FLEXCOMM9_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +FLEXCOMM9_IRQHandler + LDR R0, =FLEXCOMM9_DriverIRQHandler + BX R0 + + PUBWEAK SDIO_IRQHandler + PUBWEAK SDIO_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +SDIO_IRQHandler + LDR R0, =SDIO_DriverIRQHandler + BX R0 + + PUBWEAK CAN0_IRQ0_IRQHandler + PUBWEAK CAN0_IRQ0_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +CAN0_IRQ0_IRQHandler + LDR R0, =CAN0_IRQ0_DriverIRQHandler + BX R0 + + PUBWEAK CAN0_IRQ1_IRQHandler + PUBWEAK CAN0_IRQ1_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +CAN0_IRQ1_IRQHandler + LDR R0, =CAN0_IRQ1_DriverIRQHandler + BX R0 + + PUBWEAK CAN1_IRQ0_IRQHandler + PUBWEAK CAN1_IRQ0_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +CAN1_IRQ0_IRQHandler + LDR R0, =CAN1_IRQ0_DriverIRQHandler + BX R0 + + PUBWEAK CAN1_IRQ1_IRQHandler + PUBWEAK CAN1_IRQ1_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +CAN1_IRQ1_IRQHandler + LDR R0, =CAN1_IRQ1_DriverIRQHandler + BX R0 + + PUBWEAK USB1_IRQHandler + PUBWEAK USB1_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +USB1_IRQHandler + LDR R0, =USB1_DriverIRQHandler + BX R0 + + PUBWEAK USB1_NEEDCLK_IRQHandler + PUBWEAK USB1_NEEDCLK_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +USB1_NEEDCLK_IRQHandler + LDR R0, =USB1_NEEDCLK_DriverIRQHandler + BX R0 + + PUBWEAK ETHERNET_IRQHandler + PUBWEAK ETHERNET_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +ETHERNET_IRQHandler + LDR R0, =ETHERNET_DriverIRQHandler + BX R0 + + PUBWEAK ETHERNET_PMT_IRQHandler + PUBWEAK ETHERNET_PMT_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +ETHERNET_PMT_IRQHandler + LDR R0, =ETHERNET_PMT_DriverIRQHandler + BX R0 + + PUBWEAK ETHERNET_MACLP_IRQHandler + PUBWEAK ETHERNET_MACLP_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +ETHERNET_MACLP_IRQHandler + LDR R0, =ETHERNET_MACLP_DriverIRQHandler + BX R0 + + PUBWEAK EEPROM_IRQHandler + PUBWEAK EEPROM_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +EEPROM_IRQHandler + LDR R0, =EEPROM_DriverIRQHandler + BX R0 + + PUBWEAK LCD_IRQHandler + PUBWEAK LCD_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +LCD_IRQHandler + LDR R0, =LCD_DriverIRQHandler + BX R0 + + PUBWEAK SHA_IRQHandler + PUBWEAK SHA_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +SHA_IRQHandler + LDR R0, =SHA_DriverIRQHandler + BX R0 + + PUBWEAK SMARTCARD0_IRQHandler + PUBWEAK SMARTCARD0_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +SMARTCARD0_IRQHandler + LDR R0, =SMARTCARD0_DriverIRQHandler + BX R0 + + PUBWEAK SMARTCARD1_IRQHandler + PUBWEAK SMARTCARD1_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +SMARTCARD1_IRQHandler + LDR R0, =SMARTCARD1_DriverIRQHandler + BX R0 + +WDT_BOD_DriverIRQHandler +DMA0_DriverIRQHandler +GINT0_DriverIRQHandler +GINT1_DriverIRQHandler +PIN_INT0_DriverIRQHandler +PIN_INT1_DriverIRQHandler +PIN_INT2_DriverIRQHandler +PIN_INT3_DriverIRQHandler +UTICK0_DriverIRQHandler +MRT0_DriverIRQHandler +CTIMER0_DriverIRQHandler +CTIMER1_DriverIRQHandler +SCT0_DriverIRQHandler +CTIMER3_DriverIRQHandler +FLEXCOMM0_DriverIRQHandler +FLEXCOMM1_DriverIRQHandler +FLEXCOMM2_DriverIRQHandler +FLEXCOMM3_DriverIRQHandler +FLEXCOMM4_DriverIRQHandler +FLEXCOMM5_DriverIRQHandler +FLEXCOMM6_DriverIRQHandler +FLEXCOMM7_DriverIRQHandler +ADC0_SEQA_DriverIRQHandler +ADC0_SEQB_DriverIRQHandler +ADC0_THCMP_DriverIRQHandler +DMIC0_DriverIRQHandler +HWVAD0_DriverIRQHandler +USB0_NEEDCLK_DriverIRQHandler +USB0_DriverIRQHandler +RTC_DriverIRQHandler +Reserved46_DriverIRQHandler +Reserved47_DriverIRQHandler +PIN_INT4_DriverIRQHandler +PIN_INT5_DriverIRQHandler +PIN_INT6_DriverIRQHandler +PIN_INT7_DriverIRQHandler +CTIMER2_DriverIRQHandler +CTIMER4_DriverIRQHandler +RIT_DriverIRQHandler +SPIFI0_DriverIRQHandler +FLEXCOMM8_DriverIRQHandler +FLEXCOMM9_DriverIRQHandler +SDIO_DriverIRQHandler +CAN0_IRQ0_DriverIRQHandler +CAN0_IRQ1_DriverIRQHandler +CAN1_IRQ0_DriverIRQHandler +CAN1_IRQ1_DriverIRQHandler +USB1_DriverIRQHandler +USB1_NEEDCLK_DriverIRQHandler +ETHERNET_DriverIRQHandler +ETHERNET_PMT_DriverIRQHandler +ETHERNET_MACLP_DriverIRQHandler +EEPROM_DriverIRQHandler +LCD_DriverIRQHandler +SHA_DriverIRQHandler +SMARTCARD0_DriverIRQHandler +SMARTCARD1_DriverIRQHandler +DefaultISR + B . + + END diff --git a/hw/bsp/lpc54/iar/startup_LPC54628.s b/hw/bsp/lpc54/iar/startup_LPC54628.s new file mode 100644 index 000000000..fec5f7fca --- /dev/null +++ b/hw/bsp/lpc54/iar/startup_LPC54628.s @@ -0,0 +1,654 @@ +; ------------------------------------------------------------------------- +; @file: startup_LPC54628.s +; @purpose: CMSIS Cortex-M4 Core Device Startup File +; LPC54628 +; @version: 2.0 +; @date: 2024-10-29 +; @build: b250521 +; ------------------------------------------------------------------------- +; +; Copyright 1997-2016 Freescale Semiconductor, Inc. +; Copyright 2016-2025 NXP +; SPDX-License-Identifier: BSD-3-Clause +; +; The modules in this file are included in the libraries, and may be replaced +; by any user-defined modules that define the PUBLIC symbol _program_start or +; a user defined start symbol. +; To override the cstartup defined in the library, simply add your modified +; version to the workbench project. +; +; The vector table is normally located at address 0. +; When debugging in RAM, it can be located in RAM, aligned to at least 2^6. +; The name "__vector_table" has special meaning for C-SPY: +; it is where the SP start value is found, and the NVIC vector +; table register (VTOR) is initialized to this address if != 0. +; +; Cortex-M version +; + + MODULE ?cstartup + + ;; Forward declaration of sections. + SECTION CSTACK:DATA:NOROOT(3) + + SECTION .intvec:CODE:NOROOT(2) + + EXTERN __iar_program_start + EXTERN SystemInit + PUBLIC __vector_table + PUBLIC __vector_table_0x1c + PUBLIC __Vectors + PUBLIC __Vectors_End + PUBLIC __Vectors_Size + + DATA + +__iar_init$$done: ; The vector table is not needed + ; until after copy initialization is done + +__vector_table + DCD sfe(CSTACK) + DCD Reset_Handler + + DCD NMI_Handler ;NMI Handler + DCD HardFault_Handler ;Hard Fault Handler + DCD MemManage_Handler ;MPU Fault Handler + DCD BusFault_Handler ;Bus Fault Handler + DCD UsageFault_Handler ;Usage Fault Handler +__vector_table_0x1c + DCD 0 ;Reserved + DCD 0xFFFFFFFF ;ECRP + DCD 0 ;Reserved + DCD 0 ;Reserved + DCD SVC_Handler ;SVCall Handler + DCD DebugMon_Handler ;Debug Monitor Handler + DCD 0 ;Reserved + DCD PendSV_Handler ;PendSV Handler + DCD SysTick_Handler ;SysTick Handler + + ;External Interrupts + DCD WDT_BOD_IRQHandler ;Windowed watchdog timer, Brownout detect + DCD DMA0_IRQHandler ;DMA controller + DCD GINT0_IRQHandler ;GPIO group 0 + DCD GINT1_IRQHandler ;GPIO group 1 + DCD PIN_INT0_IRQHandler ;Pin interrupt 0 or pattern match engine slice 0 + DCD PIN_INT1_IRQHandler ;Pin interrupt 1or pattern match engine slice 1 + DCD PIN_INT2_IRQHandler ;Pin interrupt 2 or pattern match engine slice 2 + DCD PIN_INT3_IRQHandler ;Pin interrupt 3 or pattern match engine slice 3 + DCD UTICK0_IRQHandler ;Micro-tick Timer + DCD MRT0_IRQHandler ;Multi-rate timer + DCD CTIMER0_IRQHandler ;Standard counter/timer CTIMER0 + DCD CTIMER1_IRQHandler ;Standard counter/timer CTIMER1 + DCD SCT0_IRQHandler ;SCTimer/PWM + DCD CTIMER3_IRQHandler ;Standard counter/timer CTIMER3 + DCD FLEXCOMM0_IRQHandler ;Flexcomm Interface 0 (USART, SPI, I2C, FLEXCOMM) + DCD FLEXCOMM1_IRQHandler ;Flexcomm Interface 1 (USART, SPI, I2C, FLEXCOMM) + DCD FLEXCOMM2_IRQHandler ;Flexcomm Interface 2 (USART, SPI, I2C, FLEXCOMM) + DCD FLEXCOMM3_IRQHandler ;Flexcomm Interface 3 (USART, SPI, I2C, FLEXCOMM) + DCD FLEXCOMM4_IRQHandler ;Flexcomm Interface 4 (USART, SPI, I2C, FLEXCOMM) + DCD FLEXCOMM5_IRQHandler ;Flexcomm Interface 5 (USART, SPI, I2C,, FLEXCOMM) + DCD FLEXCOMM6_IRQHandler ;Flexcomm Interface 6 (USART, SPI, I2C, I2S,, FLEXCOMM) + DCD FLEXCOMM7_IRQHandler ;Flexcomm Interface 7 (USART, SPI, I2C, I2S,, FLEXCOMM) + DCD ADC0_SEQA_IRQHandler ;ADC0 sequence A completion. + DCD ADC0_SEQB_IRQHandler ;ADC0 sequence B completion. + DCD ADC0_THCMP_IRQHandler ;ADC0 threshold compare and error. + DCD DMIC0_IRQHandler ;Digital microphone and DMIC subsystem + DCD HWVAD0_IRQHandler ;Hardware Voice Activity Detector + DCD USB0_NEEDCLK_IRQHandler ;USB Activity Wake-up Interrupt + DCD USB0_IRQHandler ;USB device + DCD RTC_IRQHandler ;RTC alarm and wake-up interrupts + DCD Reserved46_IRQHandler ;Reserved interrupt + DCD Reserved47_IRQHandler ;Reserved interrupt + DCD PIN_INT4_IRQHandler ;Pin interrupt 4 or pattern match engine slice 4 int + DCD PIN_INT5_IRQHandler ;Pin interrupt 5 or pattern match engine slice 5 int + DCD PIN_INT6_IRQHandler ;Pin interrupt 6 or pattern match engine slice 6 int + DCD PIN_INT7_IRQHandler ;Pin interrupt 7 or pattern match engine slice 7 int + DCD CTIMER2_IRQHandler ;Standard counter/timer CTIMER2 + DCD CTIMER4_IRQHandler ;Standard counter/timer CTIMER4 + DCD RIT_IRQHandler ;Repetitive Interrupt Timer + DCD SPIFI0_IRQHandler ;SPI flash interface + DCD FLEXCOMM8_IRQHandler ;Flexcomm Interface 8 (USART, SPI, I2C, FLEXCOMM) + DCD FLEXCOMM9_IRQHandler ;Flexcomm Interface 9 (USART, SPI, I2C, FLEXCOMM) + DCD SDIO_IRQHandler ;SD/MMC + DCD CAN0_IRQ0_IRQHandler ;CAN0 interrupt0 + DCD CAN0_IRQ1_IRQHandler ;CAN0 interrupt1 + DCD CAN1_IRQ0_IRQHandler ;CAN1 interrupt0 + DCD CAN1_IRQ1_IRQHandler ;CAN1 interrupt1 + DCD USB1_IRQHandler ;USB1 interrupt + DCD USB1_NEEDCLK_IRQHandler ;USB1 activity + DCD ETHERNET_IRQHandler ;Ethernet + DCD ETHERNET_PMT_IRQHandler ;Ethernet power management interrupt + DCD ETHERNET_MACLP_IRQHandler ;Ethernet MAC interrupt + DCD EEPROM_IRQHandler ;EEPROM interrupt + DCD LCD_IRQHandler ;LCD interrupt + DCD SHA_IRQHandler ;SHA interrupt + DCD SMARTCARD0_IRQHandler ;Smart card 0 interrupt + DCD SMARTCARD1_IRQHandler ;Smart card 1 interrupt +__Vectors_End + +__Vectors EQU __vector_table +__Vectors_Size EQU __Vectors_End - __Vectors + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Default interrupt handlers. +;; + THUMB + + PUBWEAK Reset_Handler + SECTION .text:CODE:REORDER:NOROOT(2) +Reset_Handler + MOVS r0,#56 + LDR r1, =0x40000220 + STR r0, [r1] ;Enable SRAM clock used by Stack + LDR R0, =SystemInit + BLX R0 + LDR R0, =__iar_program_start + BX R0 + + PUBWEAK NMI_Handler + SECTION .text:CODE:REORDER:NOROOT(1) +NMI_Handler + B . + + PUBWEAK HardFault_Handler + SECTION .text:CODE:REORDER:NOROOT(1) +HardFault_Handler + B . + + PUBWEAK MemManage_Handler + SECTION .text:CODE:REORDER:NOROOT(1) +MemManage_Handler + B . + + PUBWEAK BusFault_Handler + SECTION .text:CODE:REORDER:NOROOT(1) +BusFault_Handler + B . + + PUBWEAK UsageFault_Handler + SECTION .text:CODE:REORDER:NOROOT(1) +UsageFault_Handler + B . + + PUBWEAK SVC_Handler + SECTION .text:CODE:REORDER:NOROOT(1) +SVC_Handler + B . + + PUBWEAK DebugMon_Handler + SECTION .text:CODE:REORDER:NOROOT(1) +DebugMon_Handler + B . + + PUBWEAK PendSV_Handler + SECTION .text:CODE:REORDER:NOROOT(1) +PendSV_Handler + B . + + PUBWEAK SysTick_Handler + SECTION .text:CODE:REORDER:NOROOT(1) +SysTick_Handler + B . + + PUBWEAK WDT_BOD_IRQHandler + PUBWEAK WDT_BOD_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +WDT_BOD_IRQHandler + LDR R0, =WDT_BOD_DriverIRQHandler + BX R0 + + PUBWEAK DMA0_IRQHandler + PUBWEAK DMA0_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +DMA0_IRQHandler + LDR R0, =DMA0_DriverIRQHandler + BX R0 + + PUBWEAK GINT0_IRQHandler + PUBWEAK GINT0_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +GINT0_IRQHandler + LDR R0, =GINT0_DriverIRQHandler + BX R0 + + PUBWEAK GINT1_IRQHandler + PUBWEAK GINT1_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +GINT1_IRQHandler + LDR R0, =GINT1_DriverIRQHandler + BX R0 + + PUBWEAK PIN_INT0_IRQHandler + PUBWEAK PIN_INT0_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +PIN_INT0_IRQHandler + LDR R0, =PIN_INT0_DriverIRQHandler + BX R0 + + PUBWEAK PIN_INT1_IRQHandler + PUBWEAK PIN_INT1_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +PIN_INT1_IRQHandler + LDR R0, =PIN_INT1_DriverIRQHandler + BX R0 + + PUBWEAK PIN_INT2_IRQHandler + PUBWEAK PIN_INT2_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +PIN_INT2_IRQHandler + LDR R0, =PIN_INT2_DriverIRQHandler + BX R0 + + PUBWEAK PIN_INT3_IRQHandler + PUBWEAK PIN_INT3_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +PIN_INT3_IRQHandler + LDR R0, =PIN_INT3_DriverIRQHandler + BX R0 + + PUBWEAK UTICK0_IRQHandler + PUBWEAK UTICK0_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +UTICK0_IRQHandler + LDR R0, =UTICK0_DriverIRQHandler + BX R0 + + PUBWEAK MRT0_IRQHandler + PUBWEAK MRT0_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +MRT0_IRQHandler + LDR R0, =MRT0_DriverIRQHandler + BX R0 + + PUBWEAK CTIMER0_IRQHandler + PUBWEAK CTIMER0_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +CTIMER0_IRQHandler + LDR R0, =CTIMER0_DriverIRQHandler + BX R0 + + PUBWEAK CTIMER1_IRQHandler + PUBWEAK CTIMER1_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +CTIMER1_IRQHandler + LDR R0, =CTIMER1_DriverIRQHandler + BX R0 + + PUBWEAK SCT0_IRQHandler + PUBWEAK SCT0_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +SCT0_IRQHandler + LDR R0, =SCT0_DriverIRQHandler + BX R0 + + PUBWEAK CTIMER3_IRQHandler + PUBWEAK CTIMER3_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +CTIMER3_IRQHandler + LDR R0, =CTIMER3_DriverIRQHandler + BX R0 + + PUBWEAK FLEXCOMM0_IRQHandler + PUBWEAK FLEXCOMM0_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +FLEXCOMM0_IRQHandler + LDR R0, =FLEXCOMM0_DriverIRQHandler + BX R0 + + PUBWEAK FLEXCOMM1_IRQHandler + PUBWEAK FLEXCOMM1_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +FLEXCOMM1_IRQHandler + LDR R0, =FLEXCOMM1_DriverIRQHandler + BX R0 + + PUBWEAK FLEXCOMM2_IRQHandler + PUBWEAK FLEXCOMM2_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +FLEXCOMM2_IRQHandler + LDR R0, =FLEXCOMM2_DriverIRQHandler + BX R0 + + PUBWEAK FLEXCOMM3_IRQHandler + PUBWEAK FLEXCOMM3_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +FLEXCOMM3_IRQHandler + LDR R0, =FLEXCOMM3_DriverIRQHandler + BX R0 + + PUBWEAK FLEXCOMM4_IRQHandler + PUBWEAK FLEXCOMM4_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +FLEXCOMM4_IRQHandler + LDR R0, =FLEXCOMM4_DriverIRQHandler + BX R0 + + PUBWEAK FLEXCOMM5_IRQHandler + PUBWEAK FLEXCOMM5_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +FLEXCOMM5_IRQHandler + LDR R0, =FLEXCOMM5_DriverIRQHandler + BX R0 + + PUBWEAK FLEXCOMM6_IRQHandler + PUBWEAK FLEXCOMM6_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +FLEXCOMM6_IRQHandler + LDR R0, =FLEXCOMM6_DriverIRQHandler + BX R0 + + PUBWEAK FLEXCOMM7_IRQHandler + PUBWEAK FLEXCOMM7_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +FLEXCOMM7_IRQHandler + LDR R0, =FLEXCOMM7_DriverIRQHandler + BX R0 + + PUBWEAK ADC0_SEQA_IRQHandler + PUBWEAK ADC0_SEQA_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +ADC0_SEQA_IRQHandler + LDR R0, =ADC0_SEQA_DriverIRQHandler + BX R0 + + PUBWEAK ADC0_SEQB_IRQHandler + PUBWEAK ADC0_SEQB_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +ADC0_SEQB_IRQHandler + LDR R0, =ADC0_SEQB_DriverIRQHandler + BX R0 + + PUBWEAK ADC0_THCMP_IRQHandler + PUBWEAK ADC0_THCMP_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +ADC0_THCMP_IRQHandler + LDR R0, =ADC0_THCMP_DriverIRQHandler + BX R0 + + PUBWEAK DMIC0_IRQHandler + PUBWEAK DMIC0_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +DMIC0_IRQHandler + LDR R0, =DMIC0_DriverIRQHandler + BX R0 + + PUBWEAK HWVAD0_IRQHandler + PUBWEAK HWVAD0_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +HWVAD0_IRQHandler + LDR R0, =HWVAD0_DriverIRQHandler + BX R0 + + PUBWEAK USB0_NEEDCLK_IRQHandler + PUBWEAK USB0_NEEDCLK_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +USB0_NEEDCLK_IRQHandler + LDR R0, =USB0_NEEDCLK_DriverIRQHandler + BX R0 + + PUBWEAK USB0_IRQHandler + PUBWEAK USB0_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +USB0_IRQHandler + LDR R0, =USB0_DriverIRQHandler + BX R0 + + PUBWEAK RTC_IRQHandler + PUBWEAK RTC_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +RTC_IRQHandler + LDR R0, =RTC_DriverIRQHandler + BX R0 + + PUBWEAK Reserved46_IRQHandler + PUBWEAK Reserved46_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +Reserved46_IRQHandler + LDR R0, =Reserved46_DriverIRQHandler + BX R0 + + PUBWEAK Reserved47_IRQHandler + PUBWEAK Reserved47_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +Reserved47_IRQHandler + LDR R0, =Reserved47_DriverIRQHandler + BX R0 + + PUBWEAK PIN_INT4_IRQHandler + PUBWEAK PIN_INT4_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +PIN_INT4_IRQHandler + LDR R0, =PIN_INT4_DriverIRQHandler + BX R0 + + PUBWEAK PIN_INT5_IRQHandler + PUBWEAK PIN_INT5_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +PIN_INT5_IRQHandler + LDR R0, =PIN_INT5_DriverIRQHandler + BX R0 + + PUBWEAK PIN_INT6_IRQHandler + PUBWEAK PIN_INT6_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +PIN_INT6_IRQHandler + LDR R0, =PIN_INT6_DriverIRQHandler + BX R0 + + PUBWEAK PIN_INT7_IRQHandler + PUBWEAK PIN_INT7_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +PIN_INT7_IRQHandler + LDR R0, =PIN_INT7_DriverIRQHandler + BX R0 + + PUBWEAK CTIMER2_IRQHandler + PUBWEAK CTIMER2_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +CTIMER2_IRQHandler + LDR R0, =CTIMER2_DriverIRQHandler + BX R0 + + PUBWEAK CTIMER4_IRQHandler + PUBWEAK CTIMER4_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +CTIMER4_IRQHandler + LDR R0, =CTIMER4_DriverIRQHandler + BX R0 + + PUBWEAK RIT_IRQHandler + PUBWEAK RIT_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +RIT_IRQHandler + LDR R0, =RIT_DriverIRQHandler + BX R0 + + PUBWEAK SPIFI0_IRQHandler + PUBWEAK SPIFI0_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +SPIFI0_IRQHandler + LDR R0, =SPIFI0_DriverIRQHandler + BX R0 + + PUBWEAK FLEXCOMM8_IRQHandler + PUBWEAK FLEXCOMM8_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +FLEXCOMM8_IRQHandler + LDR R0, =FLEXCOMM8_DriverIRQHandler + BX R0 + + PUBWEAK FLEXCOMM9_IRQHandler + PUBWEAK FLEXCOMM9_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +FLEXCOMM9_IRQHandler + LDR R0, =FLEXCOMM9_DriverIRQHandler + BX R0 + + PUBWEAK SDIO_IRQHandler + PUBWEAK SDIO_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +SDIO_IRQHandler + LDR R0, =SDIO_DriverIRQHandler + BX R0 + + PUBWEAK CAN0_IRQ0_IRQHandler + PUBWEAK CAN0_IRQ0_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +CAN0_IRQ0_IRQHandler + LDR R0, =CAN0_IRQ0_DriverIRQHandler + BX R0 + + PUBWEAK CAN0_IRQ1_IRQHandler + PUBWEAK CAN0_IRQ1_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +CAN0_IRQ1_IRQHandler + LDR R0, =CAN0_IRQ1_DriverIRQHandler + BX R0 + + PUBWEAK CAN1_IRQ0_IRQHandler + PUBWEAK CAN1_IRQ0_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +CAN1_IRQ0_IRQHandler + LDR R0, =CAN1_IRQ0_DriverIRQHandler + BX R0 + + PUBWEAK CAN1_IRQ1_IRQHandler + PUBWEAK CAN1_IRQ1_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +CAN1_IRQ1_IRQHandler + LDR R0, =CAN1_IRQ1_DriverIRQHandler + BX R0 + + PUBWEAK USB1_IRQHandler + PUBWEAK USB1_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +USB1_IRQHandler + LDR R0, =USB1_DriverIRQHandler + BX R0 + + PUBWEAK USB1_NEEDCLK_IRQHandler + PUBWEAK USB1_NEEDCLK_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +USB1_NEEDCLK_IRQHandler + LDR R0, =USB1_NEEDCLK_DriverIRQHandler + BX R0 + + PUBWEAK ETHERNET_IRQHandler + PUBWEAK ETHERNET_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +ETHERNET_IRQHandler + LDR R0, =ETHERNET_DriverIRQHandler + BX R0 + + PUBWEAK ETHERNET_PMT_IRQHandler + PUBWEAK ETHERNET_PMT_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +ETHERNET_PMT_IRQHandler + LDR R0, =ETHERNET_PMT_DriverIRQHandler + BX R0 + + PUBWEAK ETHERNET_MACLP_IRQHandler + PUBWEAK ETHERNET_MACLP_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +ETHERNET_MACLP_IRQHandler + LDR R0, =ETHERNET_MACLP_DriverIRQHandler + BX R0 + + PUBWEAK EEPROM_IRQHandler + PUBWEAK EEPROM_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +EEPROM_IRQHandler + LDR R0, =EEPROM_DriverIRQHandler + BX R0 + + PUBWEAK LCD_IRQHandler + PUBWEAK LCD_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +LCD_IRQHandler + LDR R0, =LCD_DriverIRQHandler + BX R0 + + PUBWEAK SHA_IRQHandler + PUBWEAK SHA_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +SHA_IRQHandler + LDR R0, =SHA_DriverIRQHandler + BX R0 + + PUBWEAK SMARTCARD0_IRQHandler + PUBWEAK SMARTCARD0_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +SMARTCARD0_IRQHandler + LDR R0, =SMARTCARD0_DriverIRQHandler + BX R0 + + PUBWEAK SMARTCARD1_IRQHandler + PUBWEAK SMARTCARD1_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +SMARTCARD1_IRQHandler + LDR R0, =SMARTCARD1_DriverIRQHandler + BX R0 + +WDT_BOD_DriverIRQHandler +DMA0_DriverIRQHandler +GINT0_DriverIRQHandler +GINT1_DriverIRQHandler +PIN_INT0_DriverIRQHandler +PIN_INT1_DriverIRQHandler +PIN_INT2_DriverIRQHandler +PIN_INT3_DriverIRQHandler +UTICK0_DriverIRQHandler +MRT0_DriverIRQHandler +CTIMER0_DriverIRQHandler +CTIMER1_DriverIRQHandler +SCT0_DriverIRQHandler +CTIMER3_DriverIRQHandler +FLEXCOMM0_DriverIRQHandler +FLEXCOMM1_DriverIRQHandler +FLEXCOMM2_DriverIRQHandler +FLEXCOMM3_DriverIRQHandler +FLEXCOMM4_DriverIRQHandler +FLEXCOMM5_DriverIRQHandler +FLEXCOMM6_DriverIRQHandler +FLEXCOMM7_DriverIRQHandler +ADC0_SEQA_DriverIRQHandler +ADC0_SEQB_DriverIRQHandler +ADC0_THCMP_DriverIRQHandler +DMIC0_DriverIRQHandler +HWVAD0_DriverIRQHandler +USB0_NEEDCLK_DriverIRQHandler +USB0_DriverIRQHandler +RTC_DriverIRQHandler +Reserved46_DriverIRQHandler +Reserved47_DriverIRQHandler +PIN_INT4_DriverIRQHandler +PIN_INT5_DriverIRQHandler +PIN_INT6_DriverIRQHandler +PIN_INT7_DriverIRQHandler +CTIMER2_DriverIRQHandler +CTIMER4_DriverIRQHandler +RIT_DriverIRQHandler +SPIFI0_DriverIRQHandler +FLEXCOMM8_DriverIRQHandler +FLEXCOMM9_DriverIRQHandler +SDIO_DriverIRQHandler +CAN0_IRQ0_DriverIRQHandler +CAN0_IRQ1_DriverIRQHandler +CAN1_IRQ0_DriverIRQHandler +CAN1_IRQ1_DriverIRQHandler +USB1_DriverIRQHandler +USB1_NEEDCLK_DriverIRQHandler +ETHERNET_DriverIRQHandler +ETHERNET_PMT_DriverIRQHandler +ETHERNET_MACLP_DriverIRQHandler +EEPROM_DriverIRQHandler +LCD_DriverIRQHandler +SHA_DriverIRQHandler +SMARTCARD0_DriverIRQHandler +SMARTCARD1_DriverIRQHandler +DefaultISR + B . + + END diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index c4b1155f3..3dc3fb4b6 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -74,6 +74,10 @@ // TODO USB0 has 5, USB1 has 6 #define TUP_USBIP_IP3511 #define TUP_USBIP_IP3516 + #define TUP_USBIP_OHCI + #define TUP_USBIP_OHCI_NXP + #define TUP_OHCI_RHPORTS 1 // 1 downstream port + #define TUP_DCD_ENDPOINT_MAX 6 #elif TU_CHECK_MCU(OPT_MCU_LPC55) diff --git a/src/portable/nxp/lpc_ip3516/hcd_lpc_ip3516.c b/src/portable/nxp/lpc_ip3516/hcd_lpc_ip3516.c index 16936e2c1..32ef99418 100644 --- a/src/portable/nxp/lpc_ip3516/hcd_lpc_ip3516.c +++ b/src/portable/nxp/lpc_ip3516/hcd_lpc_ip3516.c @@ -36,7 +36,7 @@ #include "host/usbh.h" #include "hcd_lpc_ip3516.h" -#if CFG_TUSB_MCU == OPT_MCU_LPC55 +#if TU_CHECK_MCU(OPT_MCU_LPC55, OPT_MCU_LPC54) #include "fsl_device_registers.h" #else #error "Unsupported MCUs" @@ -46,6 +46,30 @@ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ +#if TU_CHECK_MCU(OPT_MCU_LPC54) + #define ATLPTD ATL_PTD_BASE_ADDR + #define INTPTD INT_PTD_BASE_ADDR + #define ISOPTD ISO_PTD_BASE_ADDR + #define ATLPTDD ATL_PTD_DONE_MAP + #define INTPTDD INT_PTD_DONE_MAP + #define ISOPTDD ISO_PTD_DONE_MAP + #define ATLPTDS ATL_PTD_SKIP_MAP + #define INTPTDS INT_PTD_SKIP_MAP + #define ISOPTDS ISO_PTD_SKIP_MAP + #define DATAPAYLOAD DATA_PAYLOAD_BASE_ADDR + #define LASTPTD LAST_PTD_INUSE + + #define USBHSH_ATLPTD_ATL_BASE_MASK USBHSH_ATL_PTD_BASE_ADDR_ATL_BASE_MASK + #define USBHSH_INTPTD_INT_BASE_MASK USBHSH_INT_PTD_BASE_ADDR_INT_BASE_MASK + #define USBHSH_ISOPTD_ISO_BASE_MASK USBHSH_ISO_PTD_BASE_ADDR_ISO_BASE_MASK + + #define USBHSH_DATAPAYLOAD_DAT_BASE_MASK USBHSH_DATA_PAYLOAD_BASE_ADDR_DAT_BASE_MASK + + #define USBHSH_LASTPTD_ATL_LAST USBHSH_LAST_PTD_INUSE_ATL_LAST + #define USBHSH_LASTPTD_INT_LAST USBHSH_LAST_PTD_INUSE_INT_LAST + #define USBHSH_LASTPTD_ISO_LAST USBHSH_LAST_PTD_INUSE_ISO_LAST +#endif + #define USBHSH_PORTSC1_W1C_MASK (USBHSH_PORTSC1_CSC_MASK | USBHSH_PORTSC1_PEDC_MASK | USBHSH_PORTSC1_OCC_MASK) //--------------------------------------------------------------------+ -- cgit v1.3.1 From b43b99a571e81fb99f6603d9534f7d4bb55e8d02 Mon Sep 17 00:00:00 2001 From: gab-k Date: Sun, 14 Dec 2025 01:30:12 +0100 Subject: bsp: nxp: add support for RW612 (FRDM-RW612) - Added `rw61x` family support. - Added `frdm_rw612` board support. - Update `get_deps.py` to include mcux-sdk for RW61x. - Add ci_hs_rw61x include to ChipIdea HS driver and enable host examples. --- 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 + hw/bsp/rw61x/FreeRTOSConfig/FreeRTOSConfig.h | 150 +++++++++++++++++ hw/bsp/rw61x/boards/frdm_rw612/board.cmake | 30 ++++ hw/bsp/rw61x/boards/frdm_rw612/board.h | 76 +++++++++ hw/bsp/rw61x/boards/frdm_rw612/board.mk | 20 +++ hw/bsp/rw61x/boards/frdm_rw612/clock_config.c | 170 ++++++++++++++++++++ hw/bsp/rw61x/boards/frdm_rw612/clock_config.h | 116 ++++++++++++++ hw/bsp/rw61x/boards/frdm_rw612/pin_mux.c | 223 ++++++++++++++++++++++++++ hw/bsp/rw61x/boards/frdm_rw612/pin_mux.h | 146 +++++++++++++++++ hw/bsp/rw61x/family.c | 135 ++++++++++++++++ hw/bsp/rw61x/family.cmake | 102 ++++++++++++ hw/bsp/rw61x/family.mk | 52 ++++++ src/portable/chipidea/ci_hs/hcd_ci_hs.c | 3 + tools/get_deps.py | 4 +- 20 files changed, 1232 insertions(+), 2 deletions(-) create mode 100644 hw/bsp/rw61x/FreeRTOSConfig/FreeRTOSConfig.h create mode 100644 hw/bsp/rw61x/boards/frdm_rw612/board.cmake create mode 100644 hw/bsp/rw61x/boards/frdm_rw612/board.h create mode 100644 hw/bsp/rw61x/boards/frdm_rw612/board.mk create mode 100644 hw/bsp/rw61x/boards/frdm_rw612/clock_config.c create mode 100644 hw/bsp/rw61x/boards/frdm_rw612/clock_config.h create mode 100644 hw/bsp/rw61x/boards/frdm_rw612/pin_mux.c create mode 100644 hw/bsp/rw61x/boards/frdm_rw612/pin_mux.h create mode 100644 hw/bsp/rw61x/family.c create mode 100644 hw/bsp/rw61x/family.cmake create mode 100644 hw/bsp/rw61x/family.mk (limited to 'src/portable') diff --git a/examples/host/bare_api/only.txt b/examples/host/bare_api/only.txt index cba58f8e8..1c9ae72eb 100644 --- a/examples/host/bare_api/only.txt +++ b/examples/host/bare_api/only.txt @@ -8,6 +8,7 @@ mcu:LPC43XX mcu:MIMXRT1XXX mcu:MIMXRT10XX mcu:MIMXRT11XX +mcu:RW61X mcu:RP2040 mcu:MSP432E4 mcu:RX65X diff --git a/examples/host/cdc_msc_hid/only.txt b/examples/host/cdc_msc_hid/only.txt index cba58f8e8..1c9ae72eb 100644 --- a/examples/host/cdc_msc_hid/only.txt +++ b/examples/host/cdc_msc_hid/only.txt @@ -8,6 +8,7 @@ mcu:LPC43XX mcu:MIMXRT1XXX mcu:MIMXRT10XX mcu:MIMXRT11XX +mcu:RW61X mcu:RP2040 mcu:MSP432E4 mcu:RX65X diff --git a/examples/host/cdc_msc_hid_freertos/only.txt b/examples/host/cdc_msc_hid_freertos/only.txt index ef0a1ac96..5c5b7c56d 100644 --- a/examples/host/cdc_msc_hid_freertos/only.txt +++ b/examples/host/cdc_msc_hid_freertos/only.txt @@ -6,6 +6,7 @@ mcu:LPC43XX mcu:MIMXRT1XXX mcu:MIMXRT10XX mcu:MIMXRT11XX +mcu:RW61X mcu:MSP432E4 mcu:RX65X mcu:MAX3421 diff --git a/examples/host/device_info/only.txt b/examples/host/device_info/only.txt index 61a08f68d..892cbf4b8 100644 --- a/examples/host/device_info/only.txt +++ b/examples/host/device_info/only.txt @@ -9,6 +9,7 @@ mcu:MAX3421 mcu:MIMXRT1XXX mcu:MIMXRT10XX mcu:MIMXRT11XX +mcu:RW61X mcu:MSP432E4 mcu:RP2040 mcu:RX65X diff --git a/examples/host/hid_controller/only.txt b/examples/host/hid_controller/only.txt index cba58f8e8..1c9ae72eb 100644 --- a/examples/host/hid_controller/only.txt +++ b/examples/host/hid_controller/only.txt @@ -8,6 +8,7 @@ mcu:LPC43XX mcu:MIMXRT1XXX mcu:MIMXRT10XX mcu:MIMXRT11XX +mcu:RW61X mcu:RP2040 mcu:MSP432E4 mcu:RX65X diff --git a/examples/host/midi_rx/only.txt b/examples/host/midi_rx/only.txt index 133a7c9a0..ff9c0bcb8 100644 --- a/examples/host/midi_rx/only.txt +++ b/examples/host/midi_rx/only.txt @@ -12,6 +12,7 @@ mcu:MAX3421 mcu:MIMXRT1XXX mcu:MIMXRT10XX mcu:MIMXRT11XX +mcu:RW61X mcu:MSP432E4 mcu:RP2040 mcu:RX65X diff --git a/examples/host/msc_file_explorer/only.txt b/examples/host/msc_file_explorer/only.txt index cba58f8e8..1c9ae72eb 100644 --- a/examples/host/msc_file_explorer/only.txt +++ b/examples/host/msc_file_explorer/only.txt @@ -8,6 +8,7 @@ mcu:LPC43XX mcu:MIMXRT1XXX mcu:MIMXRT10XX mcu:MIMXRT11XX +mcu:RW61X mcu:RP2040 mcu:MSP432E4 mcu:RX65X diff --git a/hw/bsp/rw61x/FreeRTOSConfig/FreeRTOSConfig.h b/hw/bsp/rw61x/FreeRTOSConfig/FreeRTOSConfig.h new file mode 100644 index 000000000..281b4d40c --- /dev/null +++ b/hw/bsp/rw61x/FreeRTOSConfig/FreeRTOSConfig.h @@ -0,0 +1,150 @@ +/* + * 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 "fsl_device_registers.h" +#endif + +/* Cortex M23/M33 port configuration. */ +#define configENABLE_MPU 0 +#define configENABLE_FPU 0 // RW61x has FPU but is disabled due to using cortex-m33-nodsp-nofp.mk +#define configENABLE_TRUSTZONE 0 +#define configRUN_FREERTOS_SECURE_ONLY 1 // Cortex-M33 runs in secure mode after reset by default! +#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 3 + +/* The lowest interrupt priority that can be used in a call to a "set priority" function. */ +#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1<CAU_SLP_CTRL & PMU_CAU_SLP_CTRL_SOC_SLP_RDY_MASK) == 0U) + { + /* Enable the CAU sleep clock. */ + CLOCK_EnableClock(kCLOCK_RefClkCauSlp); + } + if ((SYSCTL2->SOURCE_CLK_GATE & SYSCTL2_SOURCE_CLK_GATE_REFCLK_SYS_CG_MASK) != 0U) + { + /* Enable the REFCLK_SYS clock. */ + CLOCK_EnableClock(kCLOCK_RefClkSys); + } + /* Initialize T3 PLL and enable outputs that are not clock gated. */ + CLOCK_InitT3RefClk(kCLOCK_T3MciIrc48m); + /* Enable FFRO - T3 PLL 48/60 MHz IRC clock output */ + CLOCK_EnableClock(kCLOCK_T3PllMciIrcClk); + /* Enable T3 PLL 256 MHz clock output */ + CLOCK_EnableClock(kCLOCK_T3PllMci256mClk); + /* Set core clock to safe system oscillator clock for initialization of other sources. */ + CLOCK_AttachClk(kSYSOSC_to_MAIN_CLK); + CLOCK_SetClkDiv(kCLOCK_DivSysCpuAhbClk, 1); + /* Enable TCPU PLL MCI clock output */ + CLOCK_EnableClock(kCLOCK_TcpuMciClk); + /* Initialize TDDR PLL and enable outputs that are not clock gated. */ + CLOCK_InitTddrRefClk(kCLOCK_TddrFlexspiDiv10); + /* Enable TDDR PLL FlexSPI clock output */ + CLOCK_EnableClock(kCLOCK_TddrMciFlexspiClk); + /* Initialize AVPLL and enable both channels. */ + CLOCK_InitAvPll(&avpllConfig_BOARD_BootClockRUN); + /* Set up clock selectors - Attach clocks to the peripheries */ + CLOCK_AttachClk(kRC32K_to_CLK32K); /* Switch CLK32K to RC32K */ + /*!< Please note SYSTICK_CLK source is used only if the SysTick SYST_CSR register CLKSOURCE bit is set to 0. */ + CLOCK_AttachClk(kSYSTICK_DIV_to_SYSTICK_CLK); /* Switch SYSTICK_CLK to SYSTICK_DIV */ + /* Set up dividers */ + CLOCK_SetClkDiv(kCLOCK_DivAudioPllClk, 1U); /* Set .AUDIOPLLCLKDIV divider to value 1 */ + CLOCK_SetClkDiv(kCLOCK_DivPllFrgClk, 13U); /* Set .FRGPLLCLKDIV divider to value 13 */ + CLOCK_SetClkDiv(kCLOCK_DivMainPllClk, 1U); /* Set .MAINPLLCLKDIV divider to value 1 */ + CLOCK_SetClkDiv(kCLOCK_DivAux0PllClk, 1U); /* Set .AUX0PLLCLKDIV divider to value 1 */ + CLOCK_SetClkDiv(kCLOCK_DivSystickClk, 1U); /* Set .SYSTICKFCLKDIV divider to value 1 */ + CLOCK_SetClkDiv(kCLOCK_DivPmuFclk, 5U); /* Set .PMUFCLKDIV divider to value 5 */ + /* Select the main clock source for the main system clock (MAINCLKSELA and MAINCLKSELB). */ + CLOCK_AttachClk(kMAIN_PLL_to_MAIN_CLK); + /*!< Set SystemCoreClock variable. */ + SystemCoreClock = BOARD_BOOTCLOCKRUN_HCLK; +} + diff --git a/hw/bsp/rw61x/boards/frdm_rw612/clock_config.h b/hw/bsp/rw61x/boards/frdm_rw612/clock_config.h new file mode 100644 index 000000000..3b467d869 --- /dev/null +++ b/hw/bsp/rw61x/boards/frdm_rw612/clock_config.h @@ -0,0 +1,116 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#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_BootClockRUN *********************** + ******************************************************************************/ +/******************************************************************************* + * Definitions for BOARD_BootClockRUN configuration + ******************************************************************************/ + +/* Clock outputs (values are in Hz): */ +#define BOARD_BOOTCLOCKRUN_AUDIO_PLL_CLK 12287999UL /* Clock consumers of audio_pll_clk output : N/A */ +#define BOARD_BOOTCLOCKRUN_AUX0_PLL_CLK 260000000UL /* Clock consumers of aux0_pll_clk output : N/A */ +#define BOARD_BOOTCLOCKRUN_AUX1_PLL_CLK 0UL /* Clock consumers of aux1_pll_clk output : N/A */ +#define BOARD_BOOTCLOCKRUN_AVPLL_CH1_CLKOUT 12287999UL /* Clock consumers of avpll_ch1_clkout output : N/A */ +#define BOARD_BOOTCLOCKRUN_AVPLL_CH2_CLKOUT 63999997UL /* Clock consumers of avpll_ch2_clkout output : N/A */ +#define BOARD_BOOTCLOCKRUN_CAU_SLP_CLK 4000000UL /* Clock consumers of cau_slp_clk output : N/A */ +#define BOARD_BOOTCLOCKRUN_CLK_32K 32000UL /* Clock consumers of clk_32k output : RTC */ +#define BOARD_BOOTCLOCKRUN_CLK_OUT 0UL /* Clock consumers of clk_out output : N/A */ +#define BOARD_BOOTCLOCKRUN_CLK_PMU_SYS 52000000UL /* Clock consumers of clk_pmu_sys output : PMU */ +#define BOARD_BOOTCLOCKRUN_CTIMER0_FCLK 0UL /* Clock consumers of ctimer0_fclk output : CTIMER0 */ +#define BOARD_BOOTCLOCKRUN_CTIMER1_FCLK 0UL /* Clock consumers of ctimer1_fclk output : CTIMER1 */ +#define BOARD_BOOTCLOCKRUN_CTIMER2_FCLK 0UL /* Clock consumers of ctimer2_fclk output : CTIMER2 */ +#define BOARD_BOOTCLOCKRUN_CTIMER3_FCLK 0UL /* Clock consumers of ctimer3_fclk output : CTIMER3 */ +#define BOARD_BOOTCLOCKRUN_DMIC_FCLK 0UL /* Clock consumers of dmic_fclk output : DMIC0 */ +#define BOARD_BOOTCLOCKRUN_ELS_128M_CLK 128000000UL /* Clock consumers of els_128m_clk output : ELS */ +#define BOARD_BOOTCLOCKRUN_ELS_256M_CLK 256000000UL /* Clock consumers of els_256m_clk output : N/A */ +#define BOARD_BOOTCLOCKRUN_ELS_64M_CLK 64000000UL /* Clock consumers of els_64m_clk output : N/A */ +#define BOARD_BOOTCLOCKRUN_ELS_FCLK 0UL /* Clock consumers of els_fclk output : ELS */ +#define BOARD_BOOTCLOCKRUN_FFRO_CLK_DIV4 12075471UL /* Clock consumers of ffro_clk_div4 output : N/A */ +#define BOARD_BOOTCLOCKRUN_FLEXCOMM0_FCLK 0UL /* Clock consumers of flexcomm0_fclk output : FLEXCOMM0 */ +#define BOARD_BOOTCLOCKRUN_FLEXCOMM14_FCLK 0UL /* Clock consumers of flexcomm14_fclk output : FLEXCOMM14 */ +#define BOARD_BOOTCLOCKRUN_FLEXCOMM1_FCLK 0UL /* Clock consumers of flexcomm1_fclk output : FLEXCOMM1 */ +#define BOARD_BOOTCLOCKRUN_FLEXCOMM2_FCLK 0UL /* Clock consumers of flexcomm2_fclk output : FLEXCOMM2 */ +#define BOARD_BOOTCLOCKRUN_FLEXCOMM3_FCLK 0UL /* Clock consumers of flexcomm3_fclk output : FLEXCOMM3 */ +#define BOARD_BOOTCLOCKRUN_FLEXSPI_FCLK 0UL /* Clock consumers of flexspi_fclk output : FLEXSPI */ +#define BOARD_BOOTCLOCKRUN_GAU_FCLK 0UL /* Clock consumers of gau_fclk output : GAU_ACOMP, GAU_BG, GAU_DAC0, GAU_GPADC0, GAU_GPADC1 */ +#define BOARD_BOOTCLOCKRUN_HCLK 260000000UL /* Clock consumers of hclk output : AHB_SECURE_CTRL, APU0, APU1, BLEAPU, BLECTRL, BUCK11, BUCK18, CACHE64_CTRL0, CACHE64_CTRL1, CACHE64_POLSEL0, CACHE64_POLSEL1, CAU, CDOG, CLKCTL0, CLKCTL1, CRC, CTIMER0, CTIMER1, CTIMER2, CTIMER3, DMA0, DMA1, DMIC0, ELS, ENET, FLEXCOMM0, FLEXCOMM1, FLEXCOMM14, FLEXCOMM2, FLEXCOMM3, FLEXSPI, FREQME, GAU_ACOMP, GAU_BG, GAU_DAC0, GAU_GPADC0, GAU_GPADC1, GDMA, GPIO, INPUTMUX, ITRC, LCDIC, MCI_IO_MUX, MRT0, MRT1, OCOTP, OSTIMER, PINT, PKC, PMU, POWERQUAD, PUF, ROMCP, RSTCTL0, RSTCTL1, RTC, SCT0, SDU_FBR_CARD, SDU_FN0_CARD, SDU_FN_CARD, SECGPIO, SENSOR_CTRL, SOCCTRL, SOC_OTP_CTRL, SYSCTL0, SYSCTL1, SYSCTL2, SysTick, TRNG, USBOTG, USIM, UTICK, WLAPU, WLCTRL, WWDT0 */ +#define BOARD_BOOTCLOCKRUN_LCD_FCLK 0UL /* Clock consumers of lcd_fclk output : LCDIC */ +#define BOARD_BOOTCLOCKRUN_LPOSC_CLK_I 1000000UL /* Clock consumers of lposc_clk_i output : N/A */ +#define BOARD_BOOTCLOCKRUN_MAIN_CLK 260000000UL /* Clock consumers of main_clk output : N/A */ +#define BOARD_BOOTCLOCKRUN_MAIN_PLL_CLK 260000000UL /* Clock consumers of main_pll_clk output : N/A */ +#define BOARD_BOOTCLOCKRUN_MCLK_OUT 0UL /* Clock consumers of mclk_out output : N/A */ +#define BOARD_BOOTCLOCKRUN_OSEVENT_FCLK 0UL /* Clock consumers of osevent_fclk output : OSTIMER */ +#define BOARD_BOOTCLOCKRUN_OTP_FUSE_32M_CLK 32000000UL /* Clock consumers of otp_fuse_32m_clk output : OCOTP */ +#define BOARD_BOOTCLOCKRUN_REFCLK_PHY 40000000UL /* Clock consumers of refclk_phy output : USBOTG */ +#define BOARD_BOOTCLOCKRUN_REFCLK_SYS 0UL /* Clock consumers of refclk_sys output : N/A */ +#define BOARD_BOOTCLOCKRUN_SCT_FCLK 0UL /* Clock consumers of sct_fclk output : SCT0 */ +#define BOARD_BOOTCLOCKRUN_SFRO_CLK_I 16000000UL /* Clock consumers of sfro_clk_i output : N/A */ +#define BOARD_BOOTCLOCKRUN_SYSOSC_CLK_I 0UL /* Clock consumers of sysosc_clk_i output : N/A */ +#define BOARD_BOOTCLOCKRUN_SYSTICK_FCLK 260000000UL /* Clock consumers of systick_fclk output : SysTick */ +#define BOARD_BOOTCLOCKRUN_T3PLL_MCI_213P3M 0UL /* Clock consumers of t3pll_mci_213p3m output : N/A */ +#define BOARD_BOOTCLOCKRUN_T3PLL_MCI_256M 256000000UL /* Clock consumers of t3pll_mci_256m output : N/A */ +#define BOARD_BOOTCLOCKRUN_T3PLL_MCI_48_60M_IRC 48301886UL /* Clock consumers of t3pll_mci_48_60m_irc output : N/A */ +#define BOARD_BOOTCLOCKRUN_T3PLL_MCI_FLEXSPI_CLK 0UL /* Clock consumers of t3pll_mci_flexspi_clk output : N/A */ +#define BOARD_BOOTCLOCKRUN_TCPU_MCI_CLK 260000000UL /* Clock consumers of tcpu_mci_clk output : N/A */ +#define BOARD_BOOTCLOCKRUN_TCPU_MCI_FLEXSPI_CLK 0UL /* Clock consumers of tcpu_mci_flexspi_clk output : N/A */ +#define BOARD_BOOTCLOCKRUN_TDDR_MCI_ENET_CLK 0UL /* Clock consumers of tddr_mci_enet_clk output : ENET */ +#define BOARD_BOOTCLOCKRUN_TDDR_MCI_FLEXSPI_CLK 320000000UL /* Clock consumers of tddr_mci_flexspi_clk output : N/A */ +#define BOARD_BOOTCLOCKRUN_USIM_FCLK 0UL /* Clock consumers of usim_fclk output : USIM */ +#define BOARD_BOOTCLOCKRUN_UTICK_FCLK 0UL /* Clock consumers of utick_fclk output : UTICK */ +#define BOARD_BOOTCLOCKRUN_WDT0_FCLK 0UL /* Clock consumers of wdt0_fclk output : WWDT0 */ + +/*! @brief AVPLL set for BOARD_BootClockRUN configuration. + */ +extern const clock_avpll_config_t avpllConfig_BOARD_BootClockRUN; +/******************************************************************************* + * API for BOARD_BootClockRUN configuration + ******************************************************************************/ +#if defined(__cplusplus) +extern "C" { +#endif /* __cplusplus*/ + +/*! + * @brief This function executes configuration of clocks. + * + */ +void BOARD_BootClockRUN(void); + +#if defined(__cplusplus) +} +#endif /* __cplusplus*/ + + +#endif /* _CLOCK_CONFIG_H_ */ + diff --git a/hw/bsp/rw61x/boards/frdm_rw612/pin_mux.c b/hw/bsp/rw61x/boards/frdm_rw612/pin_mux.c new file mode 100644 index 000000000..49b74b2bb --- /dev/null +++ b/hw/bsp/rw61x/boards/frdm_rw612/pin_mux.c @@ -0,0 +1,223 @@ +/*********************************************************************************************************************** + * 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 v17.0 +processor: RW612 +package_id: RW612ETA2I +mcu_data: ksdk2_0 +processor_version: 25.09.10 +board: FRDM-RW612 +pin_labels: +- {pin_num: M2, pin_signal: GPIO_11, label: 'J1[6]/WAKEUP_BTN', identifier: WAKEUP;WAKEUP_BTN} +- {pin_num: L7, pin_signal: GPIO_5, label: 'J1[7]/MCLK', identifier: MCLKOUT} + * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS *********** + */ +/* clang-format on */ + +#include "fsl_common.h" +#include "fsl_gpio.h" +#include "fsl_io_mux.h" +#include "pin_mux.h" + +/* FUNCTION ************************************************************************************************************ + * + * Function Name : BOARD_InitBootPins + * Description : Calls initialization functions. + * + * END ****************************************************************************************************************/ +void BOARD_InitBootPins(void) +{ + BOARD_InitPins(); + BOARD_InitDEBUG_UARTPins(); + BOARD_InitSWD_DEBUGPins(); + BOARD_InitLEDPins(); +} + +/* clang-format off */ +/* + * TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* +BOARD_InitPins: +- options: {callFromInitBoot: 'true', coreID: cm33, enableClock: 'true'} +- pin_list: + - {pin_num: M2, peripheral: GPIO, signal: 'PIO0, 11', pin_signal: GPIO_11, identifier: WAKEUP_BTN, direction: INPUT} + * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS *********** + */ +/* clang-format on */ + +/* FUNCTION ************************************************************************************************************ + * + * Function Name : BOARD_InitPins + * Description : + * + * END ****************************************************************************************************************/ +/* Function assigned for the Cortex-M33 */ +void BOARD_InitPins(void) +{ + /* Enables the clock for the GPIO0 module */ + GPIO_PortInit(GPIO, 0); + + gpio_pin_config_t WAKEUP_BTN_config = { + .pinDirection = kGPIO_DigitalInput, + .outputLogic = 0U + }; + /* Initialize GPIO functionality on pin PIO0_11 (pin M2) */ + GPIO_PinInit(BOARD_INITPINS_WAKEUP_BTN_GPIO, BOARD_INITPINS_WAKEUP_BTN_PORT, BOARD_INITPINS_WAKEUP_BTN_PIN, &WAKEUP_BTN_config); +} + +/* clang-format off */ +/* + * TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* +BOARD_InitDEBUG_UARTPins: +- options: {callFromInitBoot: 'true', coreID: cm33, enableClock: 'true'} +- pin_list: + - {pin_num: E5, peripheral: FLEXCOMM3, signal: USART_RXD, pin_signal: GPIO_24} + - {pin_num: F6, peripheral: FLEXCOMM3, signal: USART_TXD, pin_signal: GPIO_26} + * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS *********** + */ +/* clang-format on */ + +/* FUNCTION ************************************************************************************************************ + * + * Function Name : BOARD_InitDEBUG_UARTPins + * Description : Configures pin routing and optionally pin electrical features. + * + * END ****************************************************************************************************************/ +/* Function assigned for the Cortex-M33 */ +void BOARD_InitDEBUG_UARTPins(void) +{ + /* Initialize FC3_USART_DATA functionality on pin GPIO_24, GPIO_26 (pin E5_F6) */ + IO_MUX_SetPinMux(IO_MUX_FC3_USART_DATA); +} + +/* clang-format off */ +/* + * TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* +BOARD_InitSWD_DEBUGPins: +- options: {callFromInitBoot: 'true', coreID: cm33, enableClock: 'true'} +- pin_list: + - {pin_num: G5, peripheral: SWD, signal: CLK, pin_signal: GPIO_13} + - {pin_num: K4, peripheral: SWD, signal: IO, pin_signal: GPIO_14} + * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS *********** + */ +/* clang-format on */ + +/* FUNCTION ************************************************************************************************************ + * + * Function Name : BOARD_InitSWD_DEBUGPins + * Description : Configures pin routing and optionally pin electrical features. + * + * END ****************************************************************************************************************/ +/* Function assigned for the Cortex-M33 */ +void BOARD_InitSWD_DEBUGPins(void) +{ + + MCI_IO_MUX->C_TIMER_IN = ((MCI_IO_MUX->C_TIMER_IN & + /* Mask bits to zero which are setting */ + (~(MCI_IO_MUX_C_TIMER_IN_CT_INP3_SEL_MASK | MCI_IO_MUX_C_TIMER_IN_CT_INP4_SEL_MASK))) + + /* sel GPIO-13 as ct_inp3: 0x00u */ + | MCI_IO_MUX_C_TIMER_IN_CT_INP3_SEL(0x00u) + /* sel GPIO-14 as ct_inp4: 0x00u */ + | MCI_IO_MUX_C_TIMER_IN_CT_INP4_SEL(0x00u)); + + MCI_IO_MUX->C_TIMER_OUT = ((MCI_IO_MUX->C_TIMER_OUT & + /* Mask bits to zero which are setting */ + (~(MCI_IO_MUX_C_TIMER_OUT_CT0MAT3_SEL_MASK | MCI_IO_MUX_C_TIMER_OUT_CT1MAT0_SEL_MASK))) + + /* sel GPIO-13 as ct0mat3: 0x00u */ + | MCI_IO_MUX_C_TIMER_OUT_CT0MAT3_SEL(0x00u) + /* sel GPIO-14 as ct1mat0: 0x00u */ + | MCI_IO_MUX_C_TIMER_OUT_CT1MAT0_SEL(0x00u)); + + MCI_IO_MUX->FC2 = + ((MCI_IO_MUX->FC2 & + /* Mask bits to zero which are setting */ + (~(MCI_IO_MUX_FC2_SEL_FC2_I2C_MASK | MCI_IO_MUX_FC2_SEL_FC2_I2S_MASK | MCI_IO_MUX_FC2_SEL_FC2_SPI_MASK | MCI_IO_MUX_FC2_SEL_FC2_I2S_DATA_ONLY_MASK | MCI_IO_MUX_FC2_SEL_FC2_USART_DATA_MASK))) + + /* flexcomm2:select GPIO-13/14 as i2c function: 0x00u */ + | MCI_IO_MUX_FC2_SEL_FC2_I2C(0x00u) + /* flexcomm2:select GPIO-13/14/15 as i2s function: 0x00u */ + | MCI_IO_MUX_FC2_SEL_FC2_I2S(0x00u) + /* flexcomm2:select GPIO-13/14/15/16 as spi function: 0x00u */ + | MCI_IO_MUX_FC2_SEL_FC2_SPI(0x00u) + /* flexcomm2:select GPIO-13 as i2s data function: 0x00u */ + | MCI_IO_MUX_FC2_SEL_FC2_I2S_DATA_ONLY(0x00u) + /* flexcomm2:select GPIO-13/14 as usart rxd/txd: 0x00u */ + | MCI_IO_MUX_FC2_SEL_FC2_USART_DATA(0x00u)); + + MCI_IO_MUX->GPIO_GRP0 = ((MCI_IO_MUX->GPIO_GRP0 & + /* Mask bits to zero which are setting */ + (~(MCI_IO_MUX_GPIO_GRP0_SEL_13_MASK | MCI_IO_MUX_GPIO_GRP0_SEL_14_MASK))) + + /* pio0[31:0] selection, high valid; sel[i]->pio0[i]->GPIO[i]: 0x00u */ + | MCI_IO_MUX_GPIO_GRP0_SEL(0x00u)); + + SOCCTRL->MCI_IOMUX_EN0 = ((SOCCTRL->MCI_IOMUX_EN0 & + /* Mask bits to zero which are setting */ + (~(SOCCIU_MCI_IOMUX_EN0_EN_21_0_13_MASK | SOCCIU_MCI_IOMUX_EN0_EN_21_0_14_MASK))) + + /* Bitwise enable control for mci_io_mux GPIO[21:0]: 0x00u */ + | SOCCIU_MCI_IOMUX_EN0_EN_21_0(0x00u)); +} + +/* clang-format off */ +/* + * TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* +BOARD_InitLEDPins: +- options: {callFromInitBoot: 'true', coreID: cm33, enableClock: 'true'} +- pin_list: + - {pin_num: M1, peripheral: GPIO, signal: 'PIO0, 0', pin_signal: GPIO_0, direction: OUTPUT, gpio_init_state: 'true'} + - {pin_num: N2, peripheral: GPIO, signal: 'PIO0, 1', pin_signal: GPIO_1, direction: OUTPUT, gpio_init_state: 'true'} + - {pin_num: N8, peripheral: GPIO, signal: 'PIO0, 12', pin_signal: GPIO_12, direction: OUTPUT, gpio_init_state: 'true'} + * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS *********** + */ +/* clang-format on */ + +/* FUNCTION ************************************************************************************************************ + * + * Function Name : BOARD_InitLEDPins + * Description : Configures pin routing and optionally pin electrical features. + * + * END ****************************************************************************************************************/ +/* Function assigned for the Cortex-M33 */ +void BOARD_InitLEDPins(void) +{ + /* Enables the clock for the GPIO0 module */ + CLOCK_EnableClock(kCLOCK_HsGpio0); + + gpio_pin_config_t LED_BLUE_config = { + .pinDirection = kGPIO_DigitalOutput, + .outputLogic = 1U + }; + /* Initialize GPIO functionality on pin PIO0_0 (pin M1) */ + GPIO_PinInit(BOARD_INITLEDPINS_LED_BLUE_GPIO, BOARD_INITLEDPINS_LED_BLUE_PORT, BOARD_INITLEDPINS_LED_BLUE_PIN, &LED_BLUE_config); + + gpio_pin_config_t LED_RED_config = { + .pinDirection = kGPIO_DigitalOutput, + .outputLogic = 1U + }; + /* Initialize GPIO functionality on pin PIO0_1 (pin N2) */ + GPIO_PinInit(BOARD_INITLEDPINS_LED_RED_GPIO, BOARD_INITLEDPINS_LED_RED_PORT, BOARD_INITLEDPINS_LED_RED_PIN, &LED_RED_config); + + gpio_pin_config_t LED_GREEN_config = { + .pinDirection = kGPIO_DigitalOutput, + .outputLogic = 1U + }; + /* Initialize GPIO functionality on pin PIO0_12 (pin N8) */ + GPIO_PinInit(BOARD_INITLEDPINS_LED_GREEN_GPIO, BOARD_INITLEDPINS_LED_GREEN_PORT, BOARD_INITLEDPINS_LED_GREEN_PIN, &LED_GREEN_config); + /* Initialize GPIO0 functionality on pin GPIO_0 (pin M1) */ + IO_MUX_SetPinMux(IO_MUX_GPIO0); + /* Initialize GPIO1 functionality on pin GPIO_1 (pin N2) */ + IO_MUX_SetPinMux(IO_MUX_GPIO1); + /* Initialize GPIO12 functionality on pin GPIO_12 (pin N8) */ + IO_MUX_SetPinMux(IO_MUX_GPIO12); +} +/*********************************************************************************************************************** + * EOF + **********************************************************************************************************************/ diff --git a/hw/bsp/rw61x/boards/frdm_rw612/pin_mux.h b/hw/bsp/rw61x/boards/frdm_rw612/pin_mux.h new file mode 100644 index 000000000..f4c9a9127 --- /dev/null +++ b/hw/bsp/rw61x/boards/frdm_rw612/pin_mux.h @@ -0,0 +1,146 @@ +/*********************************************************************************************************************** + * 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 mclk direction control: MCLK is in the output direction. */ +#define MCLKPINDIR_MCLKPINDIR_OUTPUT_DIRECTION 0x01u + +/*! @name GPIO_5 (coord L7), J1[7]/MCLK + @{ */ +/* Routed pin properties */ +#define BOARD_INITPINS_MCLKOUT_PERIPHERAL CLKCTL1 /*!<@brief Peripheral name */ +#define BOARD_INITPINS_MCLKOUT_SIGNAL MCLK /*!<@brief Signal name */ +#define BOARD_INITPINS_MCLKOUT_GPIO_PIN 5U /*!<@brief GPIO pin number */ +#define BOARD_INITPINS_MCLKOUT_PORT 0U /*!<@brief PORT number */ +#define BOARD_INITPINS_MCLKOUT_PIN 5U /*!<@brief PORT pin number */ +#define BOARD_INITPINS_MCLKOUT_PIN_MASK (1U << 5U) /*!<@brief PORT pin mask */ + /* @} */ + +/*! @name GPIO_11 (coord M2), J1[6]/WAKEUP_BTN + @{ */ +/* Routed pin properties */ +#define BOARD_INITPINS_WAKEUP_BTN_PERIPHERAL GPIO /*!<@brief Peripheral name */ +#define BOARD_INITPINS_WAKEUP_BTN_SIGNAL PIO0 /*!<@brief Signal name */ +#define BOARD_INITPINS_WAKEUP_BTN_CHANNEL 11 /*!<@brief Signal channel */ +#define BOARD_INITPINS_WAKEUP_BTN_GPIO GPIO /*!<@brief GPIO peripheral base pointer */ +#define BOARD_INITPINS_WAKEUP_BTN_GPIO_PIN 11U /*!<@brief GPIO pin number */ +#define BOARD_INITPINS_WAKEUP_BTN_PORT 0U /*!<@brief PORT number */ +#define BOARD_INITPINS_WAKEUP_BTN_PIN 11U /*!<@brief PORT pin number */ +#define BOARD_INITPINS_WAKEUP_BTN_PIN_MASK (1U << 11U) /*!<@brief PORT pin mask */ + /* @} */ + +/*! + * @brief + * + */ +void BOARD_InitPins(void); /* Function assigned for the Cortex-M33 */ + +/*! + * @brief Configures pin routing and optionally pin electrical features. + * + */ +void BOARD_InitDEBUG_UARTPins(void); /* Function assigned for the Cortex-M33 */ + +/*! + * @brief pio0[31:0] selection, high valid; sel[i]->pio0[i]->GPIO[i] Mask for item 13. */ +#define MCI_IO_MUX_GPIO_GRP0_SEL_13_MASK 0x2000u +/*! + * @brief pio0[31:0] selection, high valid; sel[i]->pio0[i]->GPIO[i] Mask for item 14. */ +#define MCI_IO_MUX_GPIO_GRP0_SEL_14_MASK 0x4000u +/*! + * @brief Bitwise enable control for mci_io_mux GPIO[21:0] Mask for item 13. */ +#define SOCCIU_MCI_IOMUX_EN0_EN_21_0_13_MASK 0x2000u +/*! + * @brief Bitwise enable control for mci_io_mux GPIO[21:0] Mask for item 14. */ +#define SOCCIU_MCI_IOMUX_EN0_EN_21_0_14_MASK 0x4000u + +/*! + * @brief Configures pin routing and optionally pin electrical features. + * + */ +void BOARD_InitSWD_DEBUGPins(void); /* Function assigned for the Cortex-M33 */ + +/*! @name GPIO_0 (coord M1), J1[14]/LED_BLUE + @{ */ +/* Routed pin properties */ +#define BOARD_INITLEDPINS_LED_BLUE_PERIPHERAL GPIO /*!<@brief Peripheral name */ +#define BOARD_INITLEDPINS_LED_BLUE_SIGNAL PIO0 /*!<@brief Signal name */ +#define BOARD_INITLEDPINS_LED_BLUE_CHANNEL 0 /*!<@brief Signal channel */ +#define BOARD_INITLEDPINS_LED_BLUE_GPIO GPIO /*!<@brief GPIO peripheral base pointer */ +#define BOARD_INITLEDPINS_LED_BLUE_INIT_GPIO_VALUE 1U /*!<@brief GPIO output initial state */ +#define BOARD_INITLEDPINS_LED_BLUE_GPIO_PIN 0U /*!<@brief GPIO pin number */ +#define BOARD_INITLEDPINS_LED_BLUE_PORT 0U /*!<@brief PORT number */ +#define BOARD_INITLEDPINS_LED_BLUE_PIN 0U /*!<@brief PORT pin number */ +#define BOARD_INITLEDPINS_LED_BLUE_PIN_MASK (1U << 0U) /*!<@brief PORT pin mask */ + /* @} */ + +/*! @name GPIO_1 (coord N2), J5[1]/LED_RED + @{ */ +/* Routed pin properties */ +#define BOARD_INITLEDPINS_LED_RED_PERIPHERAL GPIO /*!<@brief Peripheral name */ +#define BOARD_INITLEDPINS_LED_RED_SIGNAL PIO0 /*!<@brief Signal name */ +#define BOARD_INITLEDPINS_LED_RED_CHANNEL 1 /*!<@brief Signal channel */ +#define BOARD_INITLEDPINS_LED_RED_GPIO GPIO /*!<@brief GPIO peripheral base pointer */ +#define BOARD_INITLEDPINS_LED_RED_INIT_GPIO_VALUE 1U /*!<@brief GPIO output initial state */ +#define BOARD_INITLEDPINS_LED_RED_GPIO_PIN 1U /*!<@brief GPIO pin number */ +#define BOARD_INITLEDPINS_LED_RED_PORT 0U /*!<@brief PORT number */ +#define BOARD_INITLEDPINS_LED_RED_PIN 1U /*!<@brief PORT pin number */ +#define BOARD_INITLEDPINS_LED_RED_PIN_MASK (1U << 1U) /*!<@brief PORT pin mask */ + /* @} */ + +/*! @name GPIO_12 (coord N8), LED_GREEN + @{ */ +/* Routed pin properties */ +#define BOARD_INITLEDPINS_LED_GREEN_PERIPHERAL GPIO /*!<@brief Peripheral name */ +#define BOARD_INITLEDPINS_LED_GREEN_SIGNAL PIO0 /*!<@brief Signal name */ +#define BOARD_INITLEDPINS_LED_GREEN_CHANNEL 12 /*!<@brief Signal channel */ +#define BOARD_INITLEDPINS_LED_GREEN_GPIO GPIO /*!<@brief GPIO peripheral base pointer */ +#define BOARD_INITLEDPINS_LED_GREEN_INIT_GPIO_VALUE 1U /*!<@brief GPIO output initial state */ +#define BOARD_INITLEDPINS_LED_GREEN_GPIO_PIN 12U /*!<@brief GPIO pin number */ +#define BOARD_INITLEDPINS_LED_GREEN_PORT 0U /*!<@brief PORT number */ +#define BOARD_INITLEDPINS_LED_GREEN_PIN 12U /*!<@brief PORT pin number */ +#define BOARD_INITLEDPINS_LED_GREEN_PIN_MASK (1U << 12U) /*!<@brief PORT pin mask */ + /* @} */ + +/*! + * @brief Configures pin routing and optionally pin electrical features. + * + */ +void BOARD_InitLEDPins(void); /* Function assigned for the Cortex-M33 */ + +#if defined(__cplusplus) +} +#endif + +/*! + * @} + */ +#endif /* _PIN_MUX_H_ */ + +/*********************************************************************************************************************** + * EOF + **********************************************************************************************************************/ diff --git a/hw/bsp/rw61x/family.c b/hw/bsp/rw61x/family.c new file mode 100644 index 000000000..226956f15 --- /dev/null +++ b/hw/bsp/rw61x/family.c @@ -0,0 +1,135 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2018, hathach (tinyusb.org) + * Copyright (c) 2025, Gabriel Koppenstein + * + * 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: NXP +*/ + +#include "bsp/board_api.h" +#include "fsl_device_registers.h" +#include "fsl_gpio.h" +#include "board.h" +#include "fsl_usart.h" +#include "fsl_clock.h" + +#include "pin_mux.h" +#include "clock_config.h" + +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ + +void USB_IRQHandler(void) { + tusb_int_handler(1, true); +} + +void board_init(void) { + + // Init button pin, LED pins, SWD pins & UART pins + BOARD_InitBootPins(); + + // Init Clocks + BOARD_InitBootClocks(); + +#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 from running before scheduler start + SysTick->CTRL &= ~1U; + // If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher ) + NVIC_SetPriority(USB_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY); +#endif + +#ifdef NEOPIXEL_PIN + // No neo pixel support yet +#endif + +#ifdef UART_DEV + // Enable UART when debug log is on + board_uart_init_clock(); + usart_config_t uart_config; + USART_GetDefaultConfig(&uart_config); + uart_config.baudRate_Bps = CFG_BOARD_UART_BAUDRATE; + uart_config.enableRx = true; + uart_config.enableTx = true; + USART_Init(UART_DEV, &uart_config, CLOCK_GetFlexCommClkFreq(LP_FLEXCOMM_INST)); +#endif + + // USB Initialization + // Reset USB + RESET_PeripheralReset(kUSB_RST_SHIFT_RSTn); + + // Enable USB Clock + CLOCK_EnableClock(kCLOCK_Usb); + + // Enable USB PHY + CLOCK_EnableUsbhsPhyClock(); +} + +//--------------------------------------------------------------------+ +// Board porting API +//--------------------------------------------------------------------+ + +void board_led_write(bool state) { + GPIO_PinWrite(LED_GPIO, LED_PORT, LED_PIN, state ? LED_STATE_ON : (1 - LED_STATE_ON)); +} + +uint32_t board_button_read(void) { +#ifdef BUTTON_GPIO + return BUTTON_STATE_ACTIVE == GPIO_PinRead(BUTTON_GPIO, BOARD_INITPINS_WAKEUP_BTN_PORT, BUTTON_PIN); +#endif +} + +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 + USART_WriteBlocking(UART_DEV, (uint8_t const*) buf, len); + 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++; +} + +uint32_t board_millis(void) { + return system_ticks; +} + +#endif diff --git a/hw/bsp/rw61x/family.cmake b/hw/bsp/rw61x/family.cmake new file mode 100644 index 000000000..5428b7e50 --- /dev/null +++ b/hw/bsp/rw61x/family.cmake @@ -0,0 +1,102 @@ +include_guard() + +set(SDK_DIR ${TOP}/hw/mcu/nxp/mcux-sdk) +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-nodsp-nofp CACHE INTERNAL "System Processor") +set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake) + +set(FAMILY_MCUS RW61X CACHE INTERNAL "") + +#------------------------------------ +# Startup & Linker script +#------------------------------------ + +set(STARTUP_FILE_GNU ${SDK_DIR}/devices/${MCU_VARIANT}/gcc/startup_${MCU_CORE}.S) +set(LD_FILE_GNU ${SDK_DIR}/devices/${MCU_VARIANT}/gcc/${MCU_CORE}_flash.ld) + +#------------------------------------ +# BOARD_TARGET +#------------------------------------ +function(family_add_board BOARD_TARGET) + add_library(${BOARD_TARGET} STATIC + ${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_power.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/usart/fsl_usart.c + ${SDK_DIR}/drivers/flexspi/fsl_flexspi.c + ) + + target_include_directories(${BOARD_TARGET} PUBLIC + ${CMSIS_5}/CMSIS/Core/Include + ${SDK_DIR}/devices/${MCU_VARIANT} + ${SDK_DIR}/devices/${MCU_VARIANT}/drivers + ${SDK_DIR}/drivers + ${SDK_DIR}/drivers/common + ${SDK_DIR}/drivers/lpc_gpio + ${SDK_DIR}/drivers/flexcomm + ${SDK_DIR}/drivers/flexcomm/usart + ${SDK_DIR}/drivers/flexspi + ) + + update_board(${BOARD_TARGET}) +endfunction() + +#------------------------------------ +# Functions +#------------------------------------ +function(family_configure_example TARGET RTOS) + family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_RW61X) + + target_sources(${TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + + # ChipIdea HS + ${TOP}/src/portable/chipidea/ci_hs/dcd_ci_hs.c + ${TOP}/src/portable/chipidea/ci_hs/hcd_ci_hs.c + ${TOP}/src/portable/ehci/ehci.c + + # Startup File + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} + ) + + # Add Board specific includes + target_include_directories(${TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} + ) + + # Linker Options + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + --specs=nosys.specs + --specs=nano.specs + ) + endif() + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + + # Handle Startup File Properties (Linting/Warnings) + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w + ) + + # Flashing & Binary Generation + family_add_bin_hex(${TARGET}) + family_flash_jlink(${TARGET}) +endfunction() \ No newline at end of file diff --git a/hw/bsp/rw61x/family.mk b/hw/bsp/rw61x/family.mk new file mode 100644 index 000000000..e715adfa8 --- /dev/null +++ b/hw/bsp/rw61x/family.mk @@ -0,0 +1,52 @@ +UF2_FAMILY_ID = 0x2abc77ec +SDK_DIR = hw/mcu/nxp/mcux-sdk + +include $(TOP)/$(BOARD_PATH)/board.mk + +# Default to Highspeed PORT1 +PORT ?= 1 + +CFLAGS += \ + -flto \ + -DBOARD_TUD_RHPORT=$(PORT) \ + -DBOARD_TUH_RHPORT=$(PORT) \ + -DSERIAL_PORT_TYPE_UART=1 \ + -DBOARD_TUD_MAX_SPEED=OPT_MODE_HIGH_SPEED \ + -DBOARD_TUH_MAX_SPEED=OPT_MODE_HIGH_SPEED \ + +# mcu driver cause following warnings +CFLAGS += -Wno-error=unused-parameter -Wno-error=old-style-declaration -Wno-error=redundant-decls + +LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs + +# All source paths should be relative to the top level. +LD_FILE ?= $(SDK_DIR)/devices/$(MCU_VARIANT)/gcc/$(MCU_CORE)_flash.ld + +SRC_C += \ + src/portable/chipidea/ci_hs/dcd_ci_hs.c \ + src/portable/chipidea/ci_hs/hcd_ci_hs.c \ + src/portable/ehci/ehci.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_power.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/usart/fsl_usart.c \ + $(SDK_DIR)/drivers/flexspi/fsl_flexspi.c \ + +INC += \ + $(TOP)/$(BOARD_PATH) \ + $(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/common\ + $(TOP)/$(SDK_DIR)/drivers/lpc_gpio\ + $(TOP)/$(SDK_DIR)/drivers/flexcomm \ + $(TOP)/$(SDK_DIR)/drivers/flexcomm/usart \ + $(TOP)/$(SDK_DIR)/drivers/flexspi \ + + +SRC_S += $(SDK_DIR)/devices/$(MCU_VARIANT)/gcc/startup_$(MCU_CORE).S diff --git a/src/portable/chipidea/ci_hs/hcd_ci_hs.c b/src/portable/chipidea/ci_hs/hcd_ci_hs.c index b5324a754..fe2895f6a 100644 --- a/src/portable/chipidea/ci_hs/hcd_ci_hs.c +++ b/src/portable/chipidea/ci_hs/hcd_ci_hs.c @@ -61,6 +61,9 @@ bool hcd_dcache_clean_invalidate(void const* addr, uint32_t data_size) { #include "ci_hs_lpc18_43.h" +#elif TU_CHECK_MCU(OPT_MCU_RW61X) +#include "ci_hs_rw61x.h" + #else #error "Unsupported MCUs" #endif diff --git a/tools/get_deps.py b/tools/get_deps.py index 0d9c1a8f1..17c2ab8b8 100755 --- a/tools/get_deps.py +++ b/tools/get_deps.py @@ -60,7 +60,7 @@ deps_optional = { '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'], + 'kinetis_k kinetis_k32l2 kinetis_kl lpc51 lpc54 lpc55 mcx rw61x imxrt'], 'hw/mcu/raspberry_pi/Pico-PIO-USB': ['https://github.com/sekigon-gonnoc/Pico-PIO-USB.git', '675543bcc9baa8170f868ab7ba316d418dbcf41f', 'rp2040'], @@ -246,7 +246,7 @@ deps_optional = { 'at32f413'], '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 ' + 'imxrt kinetis_k32l2 kinetis_kl lpc51 lpc54 lpc55 mcx rw61x 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 stm32u0 stm32u5 stm32wb stm32wba ' -- cgit v1.3.1 From 1583864e0b1379cc2f03717f1bed2429e5473407 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 15 Dec 2025 13:28:24 +0700 Subject: minor clean up --- README.rst | 260 +++++++++++++------------- examples/host/bare_api/only.txt | 15 +- examples/host/cdc_msc_hid/only.txt | 15 +- examples/host/cdc_msc_hid_freertos/only.txt | 13 +- examples/host/device_info/only.txt | 13 +- examples/host/hid_controller/only.txt | 15 +- examples/host/midi_rx/only.txt | 13 +- examples/host/msc_file_explorer/only.txt | 15 +- hw/bsp/stm32u5/family.mk | 6 +- src/device/usbd.c | 6 +- src/portable/st/stm32_fsdev/fsdev_common.c | 16 +- src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c | 10 +- 12 files changed, 211 insertions(+), 186 deletions(-) (limited to 'src/portable') diff --git a/README.rst b/README.rst index 75f93f656..da1f49fcd 100644 --- a/README.rst +++ b/README.rst @@ -129,138 +129,134 @@ TinyUSB is completely thread-safe by pushing all Interrupt Service Request (ISR) Supported CPUs -------------- -+--------------+-----------------------------+--------+------+-----------+------------------------+------------------------+ -| Manufacturer | Family | Device | Host | Highspeed | Driver | Note | -+==============+=============================+========+======+===========+========================+========================+ -| Allwinner | F1C100s/F1C200s | ✔ | | ✔ | sunxi | musb variant | -+--------------+-----------------------------+--------+------+-----------+------------------------+------------------------+ -| Analog | MAX3421E | | ✔ | ✖ | max3421 | via SPI | -| +-----------------------------+--------+------+-----------+------------------------+------------------------+ -| | 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 | -+--------------+-----------------------------+--------+------+-----------+------------------------+------------------------+ -| Bridgetek | FT90x | ✔ | | ✔ | ft9xx | 1-dir ep | -+--------------+-----------------------------+--------+------+-----------+------------------------+------------------------+ -| Broadcom | BCM2711, BCM2837 | ✔ | | ✔ | dwc2 | | -+--------------+-----------------------------+--------+------+-----------+------------------------+------------------------+ -| Dialog | DA1469x | ✔ | ✖ | ✖ | da146xx | | -+--------------+-----------------------------+--------+------+-----------+------------------------+------------------------+ -| Espressif | S2, S3 | ✔ | ✔ | ✖ | dwc2 | | -| ESP32 +-----------------------------+--------+------+-----------+------------------------+------------------------+ -| | P4 | ✔ | ✔ | ✔ | dwc2 | | -| +-----------------------------+--------+------+-----------+------------------------+------------------------+ -| | H4 | ✔ | ✔ | ✖ | dwc2 | | -+--------------+-----------------------------+--------+------+-----------+------------------------+------------------------+ -| GigaDevice | GD32VF103 | ✔ | | ✖ | dwc2 | | -+--------------+-----------------------------+--------+------+-----------+------------------------+------------------------+ -| Infineon | XMC4500 | ✔ | ✔ | ✖ | dwc2 | | -+--------------+-----+-----------------------+--------+------+-----------+------------------------+------------------------+ -| MicroChip | SAM | D11, D21, L21, L22 | ✔ | | ✖ | samd | | -| | +-----------------------+--------+------+-----------+------------------------+------------------------+ -| | | D51, E5x | ✔ | | ✖ | samd | | -| | +-----------------------+--------+------+-----------+------------------------+------------------------+ -| | | G55 | ✔ | | ✖ | samg | 1-dir ep | -| | +-----------------------+--------+------+-----------+------------------------+------------------------+ -| | | E70,S70,V70,V71 | ✔ | | ✔ | samx7x | 1-dir ep | -| +-----+-----------------------+--------+------+-----------+------------------------+------------------------+ -| | PIC | 24 | ✔ | | | pic | ci_fs variant | -| | +-----------------------+--------+------+-----------+------------------------+------------------------+ -| | | 32 mm, mk, mx | ✔ | | | pic | ci_fs variant | -| | +-----------------------+--------+------+-----------+------------------------+------------------------+ -| | | dsPIC33 | ✔ | | | pic | ci_fs variant | -| | +-----------------------+--------+------+-----------+------------------------+------------------------+ -| | | 32mz | ✔ | | | pic32mz | musb variant | -+--------------+-----+-----------------------+--------+------+-----------+------------------------+------------------------+ -| MindMotion | mm32 | ✔ | | ✖ | mm32f327x_otg | ci_fs variant | -+--------------+-----+-----------------------+--------+------+-----------+------------------------+------------------------+ -| NordicSemi | nRF 52833, 52840, 5340 | ✔ | ✖ | ✖ | nrf5x | only ep8 is IO | -+--------------+-----------------------------+--------+------+-----------+------------------------+------------------------+ -| Nuvoton | NUC120 | ✔ | ✖ | ✖ | nuc120 | | -| +-----------------------------+--------+------+-----------+------------------------+------------------------+ -| | NUC121/NUC125 | ✔ | ✖ | ✖ | nuc121 | | -| +-----------------------------+--------+------+-----------+------------------------+------------------------+ -| | NUC126 | ✔ | ✖ | ✖ | nuc121 | | -| +-----------------------------+--------+------+-----------+------------------------+------------------------+ -| | NUC505 | ✔ | | ✔ | nuc505 | | -+--------------+---------+-------------------+--------+------+-----------+------------------------+------------------------+ -| NXP | iMXRT | RT 10xx, 11xx | ✔ | ✔ | ✔ | ci_hs, ehci | | -| +---------+-------------------+--------+------+-----------+------------------------+------------------------+ -| | Kinetis | KL | ✔ | ⚠ | ✖ | ci_fs, khci | | -| | +-------------------+--------+------+-----------+------------------------+------------------------+ -| | | K32L2 | ✔ | | ✖ | khci | ci_fs variant | -| +---------+-------------------+--------+------+-----------+------------------------+------------------------+ -| | LPC | 11u, 13, 15 | ✔ | ✖ | ✖ | lpc_ip3511 | | -| | +-------------------+--------+------+-----------+------------------------+------------------------+ -| | | 17, 40 | ✔ | ⚠ | ✖ | lpc17_40, ohci | | -| | +-------------------+--------+------+-----------+------------------------+------------------------+ -| | | 18, 43 | ✔ | ✔ | ✔ | ci_hs, ehci | | -| | +-------------------+--------+------+-----------+------------------------+------------------------+ -| | | 51u | ✔ | ✖ | ✖ | lpc_ip3511 | | -| | +-------------------+--------+------+-----------+------------------------+------------------------+ -| | | 54, 55 | ✔ | | ✔ | lpc_ip3511 | | -| +---------+-------------------+--------+------+-----------+------------------------+------------------------+ -| | MCX | N9 | ✔ | | ✔ | ci_fs, ci_hs, ehci | | -| | +-------------------+--------+------+-----------+------------------------+------------------------+ -| | | A15 | ✔ | | | ci_fs | | -+--------------+---------+-------------------+--------+------+-----------+------------------------+------------------------+ -| Raspberry Pi | RP2040, RP2350 | ✔ | ✔ | ✖ | rp2040, pio_usb | | -+--------------+-----+-----------------------+--------+------+-----------+------------------------+------------------------+ -| Renesas | RX | 63N, 65N, 72N | ✔ | ✔ | ✖ | rusb2 | | -| +-----+-----------------------+--------+------+-----------+------------------------+------------------------+ -| | RA | 4M1, 4M3, 6M1 | ✔ | ✔ | ✖ | rusb2 | | -| | +-----------------------+--------+------+-----------+------------------------+------------------------+ -| | | 6M5 | ✔ | ✔ | ✔ | rusb2 | | -+--------------+-----+-----------------------+--------+------+-----------+------------------------+------------------------+ -| Silabs | EFM32GG12 | ✔ | | ✖ | dwc2 | | -+--------------+-----------------------------+--------+------+-----------+------------------------+------------------------+ -| Sony | CXD56 | ✔ | ✖ | ✔ | cxd56 | | -+--------------+-----------------------------+--------+------+-----------+------------------------+------------------------+ -| ST STM32 | F0, F3, L0, L1, L5, WBx5 | ✔ | ✖ | ✖ | stm32_fsdev | | -| +----+------------------------+--------+------+-----------+------------------------+------------------------+ -| | F1 | 102, 103 | ✔ | ✖ | ✖ | stm32_fsdev | | -| | +------------------------+--------+------+-----------+------------------------+------------------------+ -| | | 105, 107 | ✔ | ✔ | ✖ | dwc2 | | -| +----+------------------------+--------+------+-----------+------------------------+------------------------+ -| | F2, F4, F7, H7, H7RS | ✔ | ✔ | ✔ | dwc2 | | -| +-----------------------------+--------+------+-----------+------------------------+------------------------+ -| | C0, G0, H5 | ✔ | ✔ | ✖ | stm32_fsdev | Host tested on C0, H5 | -| +-----------------------------+--------+------+-----------+------------------------+------------------------+ -| | G4 | ✔ | ✖ | ✖ | stm32_fsdev | | -| +----+------------------------+--------+------+-----------+------------------------+------------------------+ -| | L4 | 4x2, 4x3 | ✔ | ✖ | ✖ | stm32_fsdev | | -| | +------------------------+--------+------+-----------+------------------------+------------------------+ -| | | 4x5, 4x6, 4+ | ✔ | ✔ | ✖ | dwc2 | | -| +----+------------------------+--------+------+-----------+------------------------+------------------------+ -| | N6 | ✔ | ✔ | ✔ | dwc2 | | -| +----+------------------------+--------+------+-----------+------------------------+------------------------+ -| | U0 | ✔ | ✖ | ✖ | stm32_fsdev | | -| +----+------------------------+--------+------+-----------+------------------------+------------------------+ -| | U3 | ✔ | ✔ | ✖ | stm32_fsdev | Host tested on C0, H5 | -| +----+------------------------+--------+------+-----------+------------------------+------------------------+ -| | U5 | 535, 545 | ✔ | ✔ | ✖ | stm32_fsdev | Host tested on C0, H5 | -| | +------------------------+--------+------+-----------+------------------------+------------------------+ -| | | 575, 585 | ✔ | ✔ | ✖ | dwc2 | | -| | +------------------------+--------+------+-----------+------------------------+------------------------+ -| | | 59x,5Ax,5Fx,5Gx | ✔ | ✔ | ✔ | dwc2 | | -+--------------+----+------------------------+--------+------+-----------+------------------------+------------------------+ -| TI | MSP430 | ✔ | ✖ | ✖ | msp430x5xx | | -| +-----------------------------+--------+------+-----------+------------------------+------------------------+ -| | MSP432E4, TM4C123 | ✔ | | ✖ | musb | | -+--------------+-----------------------------+--------+------+-----------+------------------------+------------------------+ -| ValentyUSB | eptri | ✔ | ✖ | ✖ | eptri | | -+--------------+-----------------------------+--------+------+-----------+------------------------+------------------------+ -| WCH | CH32F20x | ✔ | | ✔ | ch32_usbhs | | -| +-----------------------------+--------+------+-----------+------------------------+------------------------+ -| | CH32V20x | ✔ | | ✖ | stm32_fsdev/ch32_usbfs | | -| +-----------------------------+--------+------+-----------+------------------------+------------------------+ -| | CH32V305, CH32V307 | ✔ | | ✔ | ch32_usbfs/hs | | -+--------------+-----------------------------+--------+------+-----------+------------------------+------------------------+ ++--------------+-----------------------------+--------+------+-----------+------------------------+--------------------+ +| Manufacturer | Family | Device | Host | Highspeed | Driver | Note | ++==============+=============================+========+======+===========+========================+====================+ +| Allwinner | F1C100s/F1C200s | ✔ | | ✔ | sunxi | musb variant | ++--------------+-----------------------------+--------+------+-----------+------------------------+--------------------+ +| Analog | MAX3421E | | ✔ | ✖ | max3421 | via SPI | +| +-----------------------------+--------+------+-----------+------------------------+--------------------+ +| | MAX32 650, 666, 690, | ✔ | | ✔ | musb | 1-dir ep | +| | MAX78002 | | | | | | ++--------------+-----------------------------+--------+------+-----------+------------------------+--------------------+ +| Artery AT32 | F403a_407, F413 | ✔ | | | fsdev | Packet SRAM 512 | +| +-----------------------------+--------+------+-----------+------------------------+--------------------+ +| | F415, F435_437, F423, F425 | ✔ | ✔ | | dwc2 | | +| +-----------------------------+--------+------+-----------+------------------------+--------------------+ +| | F402_F405 | ✔ | ✔ | ✔ | dwc2 | F405 is HS | ++--------------+-----------------------------+--------+------+-----------+------------------------+--------------------+ +| Bridgetek | FT90x | ✔ | | ✔ | ft9xx | 1-dir ep | ++--------------+-----------------------------+--------+------+-----------+------------------------+--------------------+ +| Broadcom | BCM2711, BCM2837 | ✔ | | ✔ | dwc2 | | ++--------------+-----------------------------+--------+------+-----------+------------------------+--------------------+ +| Dialog | DA1469x | ✔ | ✖ | ✖ | da146xx | | ++--------------+-----------------------------+--------+------+-----------+------------------------+--------------------+ +| Espressif | S2, S3 | ✔ | ✔ | ✖ | dwc2 | | +| ESP32 +-----------------------------+--------+------+-----------+------------------------+--------------------+ +| | P4 | ✔ | ✔ | ✔ | dwc2 | | +| +-----------------------------+--------+------+-----------+------------------------+--------------------+ +| | H4 | ✔ | ✔ | ✖ | dwc2 | | ++--------------+-----------------------------+--------+------+-----------+------------------------+--------------------+ +| GigaDevice | GD32VF103 | ✔ | | ✖ | dwc2 | | ++--------------+-----------------------------+--------+------+-----------+------------------------+--------------------+ +| Infineon | XMC4500 | ✔ | ✔ | ✖ | dwc2 | | ++--------------+-----+-----------------------+--------+------+-----------+------------------------+--------------------+ +| MicroChip | SAM | D11, D21, L21, L22 | ✔ | | ✖ | samd | | +| | +-----------------------+--------+------+-----------+------------------------+--------------------+ +| | | D51, E5x | ✔ | | ✖ | samd | | +| | +-----------------------+--------+------+-----------+------------------------+--------------------+ +| | | G55 | ✔ | | ✖ | samg | 1-dir ep | +| | +-----------------------+--------+------+-----------+------------------------+--------------------+ +| | | E70,S70,V70,V71 | ✔ | | ✔ | samx7x | 1-dir ep | +| +-----+-----------------------+--------+------+-----------+------------------------+--------------------+ +| | PIC | 24 | ✔ | | | pic | ci_fs variant | +| | +-----------------------+--------+------+-----------+------------------------+--------------------+ +| | | 32 mm, mk, mx | ✔ | | | pic | ci_fs variant | +| | +-----------------------+--------+------+-----------+------------------------+--------------------+ +| | | dsPIC33 | ✔ | | | pic | ci_fs variant | +| | +-----------------------+--------+------+-----------+------------------------+--------------------+ +| | | 32mz | ✔ | | | pic32mz | musb variant | ++--------------+-----+-----------------------+--------+------+-----------+------------------------+--------------------+ +| MindMotion | mm32 | ✔ | | ✖ | mm32f327x_otg | ci_fs variant | ++--------------+-----+-----------------------+--------+------+-----------+------------------------+--------------------+ +| NordicSemi | nRF 52833, 52840, 5340 | ✔ | ✖ | ✖ | nrf5x | only ep8 is ISO | ++--------------+-----------------------------+--------+------+-----------+------------------------+--------------------+ +| Nuvoton | NUC120 | ✔ | ✖ | ✖ | nuc120 | | +| +-----------------------------+--------+------+-----------+------------------------+--------------------+ +| | NUC121/NUC125, NUC126 | ✔ | ✖ | ✖ | nuc121 | | +| +-----------------------------+--------+------+-----------+------------------------+--------------------+ +| | NUC505 | ✔ | | ✔ | nuc505 | | ++--------------+---------+-------------------+--------+------+-----------+------------------------+--------------------+ +| NXP | iMXRT | RT 10xx, 11xx | ✔ | ✔ | ✔ | ci_hs, ehci | | +| +---------+-------------------+--------+------+-----------+------------------------+--------------------+ +| | Kinetis | KL | ✔ | ⚠ | ✖ | ci_fs, khci | | +| | +-------------------+--------+------+-----------+------------------------+--------------------+ +| | | K32L2 | ✔ | | ✖ | khci | ci_fs variant | +| +---------+-------------------+--------+------+-----------+------------------------+--------------------+ +| | LPC | 11u, 13, 15 | ✔ | ✖ | ✖ | lpc_ip3511 | | +| | +-------------------+--------+------+-----------+------------------------+--------------------+ +| | | 17, 40 | ✔ | ⚠ | ✖ | lpc17_40, ohci | | +| | +-------------------+--------+------+-----------+------------------------+--------------------+ +| | | 18, 43 | ✔ | ✔ | ✔ | ci_hs, ehci | | +| | +-------------------+--------+------+-----------+------------------------+--------------------+ +| | | 51u | ✔ | ✖ | ✖ | lpc_ip3511 | | +| | +-------------------+--------+------+-----------+------------------------+--------------------+ +| | | 54, 55 | ✔ | | ✔ | lpc_ip3511 | | +| +---------+-------------------+--------+------+-----------+------------------------+--------------------+ +| | MCX | N9 | ✔ | | ✔ | ci_fs, ci_hs, ehci | | +| | +-------------------+--------+------+-----------+------------------------+--------------------+ +| | | A15 | ✔ | | | ci_fs | | ++--------------+---------+-------------------+--------+------+-----------+------------------------+--------------------+ +| Raspberry Pi | RP2040, RP2350 | ✔ | ✔ | ✖ | rp2040, pio_usb | | ++--------------+-----+-----------------------+--------+------+-----------+------------------------+--------------------+ +| Renesas | RX | 63N, 65N, 72N | ✔ | ✔ | ✖ | rusb2 | | +| +-----+-----------------------+--------+------+-----------+------------------------+--------------------+ +| | RA | 4M1, 4M3, 6M1 | ✔ | ✔ | ✖ | rusb2 | | +| | +-----------------------+--------+------+-----------+------------------------+--------------------+ +| | | 6M5 | ✔ | ✔ | ✔ | rusb2 | | ++--------------+-----+-----------------------+--------+------+-----------+------------------------+--------------------+ +| Silabs | EFM32GG12 | ✔ | | ✖ | dwc2 | | ++--------------+-----------------------------+--------+------+-----------+------------------------+--------------------+ +| Sony | CXD56 | ✔ | ✖ | ✔ | cxd56 | | ++--------------+-----------------------------+--------+------+-----------+------------------------+--------------------+ +| ST STM32 | F0, F3, L0, L1, L5, WBx5 | ✔ | ✖ | ✖ | stm32_fsdev | | +| +----+------------------------+--------+------+-----------+------------------------+--------------------+ +| | F1 | 102, 103 | ✔ | ✖ | ✖ | stm32_fsdev | Packet SRAM 512 | +| | +------------------------+--------+------+-----------+------------------------+--------------------+ +| | | 105, 107 | ✔ | ✔ | ✖ | dwc2 | | +| +----+------------------------+--------+------+-----------+------------------------+--------------------+ +| | F2, F4, F7, H7, H7RS | ✔ | ✔ | ✔ | dwc2 | | +| +-----------------------------+--------+------+-----------+------------------------+--------------------+ +| | C0, G0, H5, U3 | ✔ | ✔ | ✖ | stm32_fsdev | Packet SRAM 2KB | +| +-----------------------------+--------+------+-----------+------------------------+--------------------+ +| | G4 | ✔ | ✖ | ✖ | stm32_fsdev | Packet SRAM 1KB | +| +----+------------------------+--------+------+-----------+------------------------+--------------------+ +| | L4 | 4x2, 4x3 | ✔ | ✖ | ✖ | stm32_fsdev | Packet SRAM 1KB | +| | +------------------------+--------+------+-----------+------------------------+--------------------+ +| | | 4x5, 4x6, 4+ | ✔ | ✔ | ✖ | dwc2 | | +| +----+------------------------+--------+------+-----------+------------------------+--------------------+ +| | N6 | ✔ | ✔ | ✔ | dwc2 | | +| +-----------------------------+--------+------+-----------+------------------------+--------------------+ +| | U0 | ✔ | ✖ | ✖ | stm32_fsdev | Packet SRAM 1KB | +| +----+------------------------+--------+------+-----------+------------------------+--------------------+ +| | U5 | 535, 545 | ✔ | ✔ | ✖ | stm32_fsdev | Packet SRAM 2KB | +| | +------------------------+--------+------+-----------+------------------------+--------------------+ +| | | 575, 585 | ✔ | ✔ | ✖ | dwc2 | | +| | +------------------------+--------+------+-----------+------------------------+--------------------+ +| | | 59x,5Ax,5Fx,5Gx | ✔ | ✔ | ✔ | dwc2 | | ++--------------+----+------------------------+--------+------+-----------+------------------------+--------------------+ +| TI | MSP430 | ✔ | ✖ | ✖ | msp430x5xx | | +| +-----------------------------+--------+------+-----------+------------------------+--------------------+ +| | MSP432E4, TM4C123 | ✔ | | ✖ | musb | | ++--------------+-----------------------------+--------+------+-----------+------------------------+--------------------+ +| ValentyUSB | eptri | ✔ | ✖ | ✖ | eptri | | ++--------------+-----------------------------+--------+------+-----------+------------------------+--------------------+ +| WCH | CH32F20x | ✔ | | ✔ | ch32_usbhs | | +| +-----------------------------+--------+------+-----------+------------------------+--------------------+ +| | CH32V20x | ✔ | | ✖ | stm32_fsdev/ch32_usbfs | | +| +-----------------------------+--------+------+-----------+------------------------+--------------------+ +| | CH32V305, CH32V307 | ✔ | | ✔ | ch32_usbfs/hs | | ++--------------+-----------------------------+--------+------+-----------+------------------------+--------------------+ Table Legend ^^^^^^^^^^^^ diff --git a/examples/host/bare_api/only.txt b/examples/host/bare_api/only.txt index 4cd457879..52e51242c 100644 --- a/examples/host/bare_api/only.txt +++ b/examples/host/bare_api/only.txt @@ -1,3 +1,5 @@ +family:samd21 +family:samd5x_e5x mcu:CH32V20X mcu:KINETIS_KL mcu:LPC175X_6X @@ -5,20 +7,21 @@ mcu:LPC177X_8X mcu:LPC18XX mcu:LPC40XX mcu:LPC43XX -mcu:MIMXRT1XXX +mcu:MAX3421 mcu:MIMXRT10XX mcu:MIMXRT11XX -mcu:RP2040 +mcu:MIMXRT1XXX mcu:MSP432E4 -mcu:RX65X mcu:RAXXX -mcu:MAX3421 +mcu:RP2040 +mcu:RX65X mcu:STM32C0 mcu:STM32F4 mcu:STM32F7 +mcu:STM32G0 mcu:STM32H5 mcu:STM32H7 mcu:STM32H7RS mcu:STM32N6 -family:samd21 -family:samd5x_e5x +mcu:STM32U3 +mcu:STM32U5 diff --git a/examples/host/cdc_msc_hid/only.txt b/examples/host/cdc_msc_hid/only.txt index 4cd457879..52e51242c 100644 --- a/examples/host/cdc_msc_hid/only.txt +++ b/examples/host/cdc_msc_hid/only.txt @@ -1,3 +1,5 @@ +family:samd21 +family:samd5x_e5x mcu:CH32V20X mcu:KINETIS_KL mcu:LPC175X_6X @@ -5,20 +7,21 @@ mcu:LPC177X_8X mcu:LPC18XX mcu:LPC40XX mcu:LPC43XX -mcu:MIMXRT1XXX +mcu:MAX3421 mcu:MIMXRT10XX mcu:MIMXRT11XX -mcu:RP2040 +mcu:MIMXRT1XXX mcu:MSP432E4 -mcu:RX65X mcu:RAXXX -mcu:MAX3421 +mcu:RP2040 +mcu:RX65X mcu:STM32C0 mcu:STM32F4 mcu:STM32F7 +mcu:STM32G0 mcu:STM32H5 mcu:STM32H7 mcu:STM32H7RS mcu:STM32N6 -family:samd21 -family:samd5x_e5x +mcu:STM32U3 +mcu:STM32U5 diff --git a/examples/host/cdc_msc_hid_freertos/only.txt b/examples/host/cdc_msc_hid_freertos/only.txt index 2322d4ecf..4cff741c3 100644 --- a/examples/host/cdc_msc_hid_freertos/only.txt +++ b/examples/host/cdc_msc_hid_freertos/only.txt @@ -1,21 +1,24 @@ +family:espressif +family:samd21 +family:samd5x_e5x mcu:LPC175X_6X mcu:LPC177X_8X mcu:LPC18XX mcu:LPC40XX mcu:LPC43XX -mcu:MIMXRT1XXX +mcu:MAX3421 mcu:MIMXRT10XX mcu:MIMXRT11XX +mcu:MIMXRT1XXX mcu:MSP432E4 mcu:RX65X -mcu:MAX3421 mcu:STM32C0 mcu:STM32F4 mcu:STM32F7 +mcu:STM32G0 mcu:STM32H5 mcu:STM32H7 mcu:STM32H7RS mcu:STM32N6 -family:espressif -family:samd21 -family:samd5x_e5x +mcu:STM32U3 +mcu:STM32U5 diff --git a/examples/host/device_info/only.txt b/examples/host/device_info/only.txt index 5b68f0774..becc8252d 100644 --- a/examples/host/device_info/only.txt +++ b/examples/host/device_info/only.txt @@ -1,3 +1,6 @@ +family:espressif +family:samd21 +family:samd5x_e5x mcu:CH32V20X mcu:KINETIS_KL mcu:LPC175X_6X @@ -6,20 +9,20 @@ mcu:LPC18XX mcu:LPC40XX mcu:LPC43XX mcu:MAX3421 -mcu:MIMXRT1XXX mcu:MIMXRT10XX mcu:MIMXRT11XX +mcu:MIMXRT1XXX mcu:MSP432E4 +mcu:RAXXX mcu:RP2040 mcu:RX65X -mcu:RAXXX mcu:STM32C0 mcu:STM32F4 mcu:STM32F7 +mcu:STM32G0 mcu:STM32H5 mcu:STM32H7 mcu:STM32H7RS mcu:STM32N6 -family:espressif -family:samd21 -family:samd5x_e5x +mcu:STM32U3 +mcu:STM32U5 diff --git a/examples/host/hid_controller/only.txt b/examples/host/hid_controller/only.txt index b859b4cc0..35b7c2361 100644 --- a/examples/host/hid_controller/only.txt +++ b/examples/host/hid_controller/only.txt @@ -1,3 +1,5 @@ +family:samd21 +family:samd5x_e5x mcu:CH32V20X mcu:KINETIS_KL mcu:LPC175X_6X @@ -5,19 +7,20 @@ mcu:LPC177X_8X mcu:LPC18XX mcu:LPC40XX mcu:LPC43XX -mcu:MIMXRT1XXX +mcu:MAX3421 mcu:MIMXRT10XX mcu:MIMXRT11XX -mcu:RP2040 +mcu:MIMXRT1XXX mcu:MSP432E4 -mcu:RX65X mcu:RAXXX -mcu:MAX3421 +mcu:RP2040 +mcu:RX65X mcu:STM32F4 mcu:STM32F7 +mcu:STM32G0 mcu:STM32H5 mcu:STM32H7 mcu:STM32H7RS mcu:STM32N6 -family:samd21 -family:samd5x_e5x +mcu:STM32U3 +mcu:STM32U5 diff --git a/examples/host/midi_rx/only.txt b/examples/host/midi_rx/only.txt index 09d725860..a3976f08d 100644 --- a/examples/host/midi_rx/only.txt +++ b/examples/host/midi_rx/only.txt @@ -1,7 +1,9 @@ +family:samd21 +family:samd5x_e5x mcu:CH32V20X +mcu:ESP32P4 mcu:ESP32S2 mcu:ESP32S3 -mcu:ESP32P4 mcu:KINETIS_KL mcu:LPC175X_6X mcu:LPC177X_8X @@ -9,19 +11,20 @@ mcu:LPC18XX mcu:LPC40XX mcu:LPC43XX mcu:MAX3421 -mcu:MIMXRT1XXX mcu:MIMXRT10XX mcu:MIMXRT11XX +mcu:MIMXRT1XXX mcu:MSP432E4 +mcu:RAXXX mcu:RP2040 mcu:RX65X -mcu:RAXXX mcu:STM32C0 mcu:STM32F4 mcu:STM32F7 +mcu:STM32G0 mcu:STM32H5 mcu:STM32H7 mcu:STM32H7RS mcu:STM32N6 -family:samd21 -family:samd5x_e5x +mcu:STM32U3 +mcu:STM32U5 diff --git a/examples/host/msc_file_explorer/only.txt b/examples/host/msc_file_explorer/only.txt index 4cd457879..52e51242c 100644 --- a/examples/host/msc_file_explorer/only.txt +++ b/examples/host/msc_file_explorer/only.txt @@ -1,3 +1,5 @@ +family:samd21 +family:samd5x_e5x mcu:CH32V20X mcu:KINETIS_KL mcu:LPC175X_6X @@ -5,20 +7,21 @@ mcu:LPC177X_8X mcu:LPC18XX mcu:LPC40XX mcu:LPC43XX -mcu:MIMXRT1XXX +mcu:MAX3421 mcu:MIMXRT10XX mcu:MIMXRT11XX -mcu:RP2040 +mcu:MIMXRT1XXX mcu:MSP432E4 -mcu:RX65X mcu:RAXXX -mcu:MAX3421 +mcu:RP2040 +mcu:RX65X mcu:STM32C0 mcu:STM32F4 mcu:STM32F7 +mcu:STM32G0 mcu:STM32H5 mcu:STM32H7 mcu:STM32H7RS mcu:STM32N6 -family:samd21 -family:samd5x_e5x +mcu:STM32U3 +mcu:STM32U5 diff --git a/hw/bsp/stm32u5/family.mk b/hw/bsp/stm32u5/family.mk index 79f181a68..47aed10a9 100644 --- a/hw/bsp/stm32u5/family.mk +++ b/hw/bsp/stm32u5/family.mk @@ -37,11 +37,7 @@ SRC_C += \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc_ex.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_uart.c -ifeq ($(MCU_VARIANT),stm32u545xx) -SRC_C += \ - src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ - src/portable/st/stm32_fsdev/fsdev_common.c -else ifeq ($(MCU_VARIANT),stm32u535xx) +ifneq ($(filter stm32u545xx stm32u535xx,$(MCU_VARIANT)),) SRC_C += \ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ src/portable/st/stm32_fsdev/fsdev_common.c diff --git a/src/device/usbd.c b/src/device/usbd.c index 5365ae2c2..1a9eb630c 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -574,6 +574,8 @@ bool tud_deinit(uint8_t rhport) { TU_LOG_USBD("USBD deinit on controller %u\r\n", rhport); + const uint8_t cfg_num = _usbd_dev.cfg_num; + // Deinit device controller driver dcd_int_disable(rhport); dcd_disconnect(rhport); @@ -604,7 +606,9 @@ bool tud_deinit(uint8_t rhport) { _usbd_rhport = RHPORT_INVALID; - tud_umount_cb(); + if (cfg_num > 0) { + tud_umount_cb(); + } return true; } diff --git a/src/portable/st/stm32_fsdev/fsdev_common.c b/src/portable/st/stm32_fsdev/fsdev_common.c index 60ef339a6..5d60ad9a2 100644 --- a/src/portable/st/stm32_fsdev/fsdev_common.c +++ b/src/portable/st/stm32_fsdev/fsdev_common.c @@ -78,7 +78,9 @@ void fsdev_deinit(void) { // - Packet memory must be either strictly 16-bit or 32-bit depending on FSDEV_BUS_32BIT // - Uses unaligned for RAM (since M0 cannot access unaligned address) bool fsdev_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t nbytes) { - if (nbytes == 0) return true; + if (nbytes == 0) { + return true; + } uint32_t n_write = nbytes / FSDEV_BUS_SIZE; fsdev_pma_buf_t* pma_buf = PMA_BUF_AT(dst); @@ -107,7 +109,9 @@ bool fsdev_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_ // - Packet memory must be either strictly 16-bit or 32-bit depending on FSDEV_BUS_32BIT // - Uses unaligned for RAM (since M0 cannot access unaligned address) bool fsdev_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t nbytes) { - if (nbytes == 0) return true; + if (nbytes == 0) { + return true; + } uint32_t n_read = nbytes / FSDEV_BUS_SIZE; fsdev_pma_buf_t* pma_buf = PMA_BUF_AT(src); @@ -134,7 +138,9 @@ bool fsdev_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t nbyte // Write to PMA from FIFO bool fsdev_write_packet_memory_ff(tu_fifo_t *ff, uint16_t dst, uint16_t wNBytes) { - if (wNBytes == 0) return true; + if (wNBytes == 0) { + return true; + } // Since we copy from a ring buffer FIFO, a wrap might occur making it necessary to conduct two copies tu_fifo_buffer_info_t info; @@ -183,7 +189,9 @@ bool fsdev_write_packet_memory_ff(tu_fifo_t *ff, uint16_t dst, uint16_t wNBytes) // Read from PMA to FIFO bool fsdev_read_packet_memory_ff(tu_fifo_t *ff, uint16_t src, uint16_t wNBytes) { - if (wNBytes == 0) return true; + if (wNBytes == 0) { + return true; + } // Since we copy into a ring buffer FIFO, a wrap might occur making it necessary to conduct two copies // Check for first linear part diff --git a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c index 212f620ac..da9c6961c 100644 --- a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c @@ -28,11 +28,11 @@ * This driver provides USB Host controller support for STM32 MCUs with "USB A"/"PCD"/"HCD" peripheral. * This covers these MCU families: * - * C0 2048 byte buffer; 32-bit bus; host mode - * G0 2048 byte buffer; 32-bit bus; host mode - * U3 2048 byte buffer; 32-bit bus; host mode - * H5 2048 byte buffer; 32-bit bus; host mode - * U535, U545 2048 byte buffer; 32-bit bus; host mode + * C0 2048 byte buffer; 32-bit bus; host mode + * G0 2048 byte buffer; 32-bit bus; host mode + * U3 2048 byte buffer; 32-bit bus; host mode + * H5 2048 byte buffer; 32-bit bus; host mode + * U535, U545 2048 byte buffer; 32-bit bus; host mode * */ -- cgit v1.3.1 From ba3319d90d546143d169b398166b457082ad21d4 Mon Sep 17 00:00:00 2001 From: Zhihong Chen Date: Mon, 8 Dec 2025 13:59:21 +0800 Subject: support hpmicro chips Signed-off-by: Zhihong Chen --- hw/bsp/hpmicro/boards/hpm6750evk2/board.c | 295 +++++++++ hw/bsp/hpmicro/boards/hpm6750evk2/board.cmake | 22 + hw/bsp/hpmicro/boards/hpm6750evk2/board.h | 105 ++++ hw/bsp/hpmicro/boards/hpm6750evk2/board.mk | 16 + hw/bsp/hpmicro/boards/hpm6750evk2/pinmux.c | 862 ++++++++++++++++++++++++++ hw/bsp/hpmicro/boards/hpm6750evk2/pinmux.h | 89 +++ hw/bsp/hpmicro/family.c | 115 ++++ hw/bsp/hpmicro/family.cmake | 131 ++++ hw/bsp/hpmicro/family.mk | 76 +++ src/common/tusb_mcu.h | 12 + src/portable/chipidea/ci_hs/ci_hs_hpm.h | 54 ++ src/portable/chipidea/ci_hs/dcd_ci_hs.c | 14 +- src/portable/chipidea/ci_hs/hcd_ci_hs.c | 8 + src/portable/ehci/ehci.c | 12 + src/tusb_option.h | 3 + tools/get_deps.py | 3 + 16 files changed, 1816 insertions(+), 1 deletion(-) create mode 100644 hw/bsp/hpmicro/boards/hpm6750evk2/board.c create mode 100644 hw/bsp/hpmicro/boards/hpm6750evk2/board.cmake create mode 100644 hw/bsp/hpmicro/boards/hpm6750evk2/board.h create mode 100644 hw/bsp/hpmicro/boards/hpm6750evk2/board.mk create mode 100644 hw/bsp/hpmicro/boards/hpm6750evk2/pinmux.c create mode 100644 hw/bsp/hpmicro/boards/hpm6750evk2/pinmux.h create mode 100644 hw/bsp/hpmicro/family.c create mode 100644 hw/bsp/hpmicro/family.cmake create mode 100644 hw/bsp/hpmicro/family.mk create mode 100644 src/portable/chipidea/ci_hs/ci_hs_hpm.h (limited to 'src/portable') diff --git a/hw/bsp/hpmicro/boards/hpm6750evk2/board.c b/hw/bsp/hpmicro/boards/hpm6750evk2/board.c new file mode 100644 index 000000000..c281356e3 --- /dev/null +++ b/hw/bsp/hpmicro/boards/hpm6750evk2/board.c @@ -0,0 +1,295 @@ +/* + * Copyright (c) 2025 HPMicro + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include "board.h" +#include "pinmux.h" +#include "hpm_pmp_drv.h" +#include "hpm_pllctl_drv.h" +#include "hpm_clock_drv.h" +#include "hpm_sysctl_drv.h" +#include "hpm_pcfg_drv.h" +#include "hpm_uart_drv.h" +#include "hpm_gpio_drv.h" + +/** + * @brief FLASH configuration option definitions: + * option[0]: + * [31:16] 0xfcf9 - FLASH configuration option tag + * [15:4] 0 - Reserved + * [3:0] option words (exclude option[0]) + * option[1]: + * [31:28] Flash probe type + * 0 - SFDP SDR / 1 - SFDP DDR + * 2 - 1-4-4 Read (0xEB, 24-bit address) / 3 - 1-2-2 Read(0xBB, 24-bit address) + * 4 - HyperFLASH 1.8V / 5 - HyperFLASH 3V + * 6 - OctaBus DDR (SPI -> OPI DDR) + * 8 - Xccela DDR (SPI -> OPI DDR) + * 10 - EcoXiP DDR (SPI -> OPI DDR) + * [27:24] Command Pads after Power-on Reset + * 0 - SPI / 1 - DPI / 2 - QPI / 3 - OPI + * [23:20] Command Pads after Configuring FLASH + * 0 - SPI / 1 - DPI / 2 - QPI / 3 - OPI + * [19:16] Quad Enable Sequence (for the device support SFDP 1.0 only) + * 0 - Not needed + * 1 - QE bit is at bit 6 in Status Register 1 + * 2 - QE bit is at bit1 in Status Register 2 + * 3 - QE bit is at bit7 in Status Register 2 + * 4 - QE bit is at bit1 in Status Register 2 and should be programmed by 0x31 + * [15:8] Dummy cycles + * 0 - Auto-probed / detected / default value + * Others - User specified value, for DDR read, the dummy cycles should be 2 * cycles on FLASH datasheet + * [7:4] Misc. + * 0 - Not used + * 1 - SPI mode + * 2 - Internal loopback + * 3 - External DQS + * [3:0] Frequency option + * 1 - 30MHz / 2 - 50MHz / 3 - 66MHz / 4 - 80MHz / 5 - 100MHz / 6 - 120MHz / 7 - 133MHz / 8 - 166MHz + * + * option[2] (Effective only if the bit[3:0] in option[0] > 1) + * [31:20] Reserved + * [19:16] IO voltage + * 0 - 3V / 1 - 1.8V + * [15:12] Pin group + * 0 - 1st group / 1 - 2nd group + * [11:8] Connection selection + * 0 - CA_CS0 / 1 - CB_CS0 / 2 - CA_CS0 + CB_CS0 (Two FLASH connected to CA and CB respectively) + * [7:0] Drive Strength + * 0 - Default value + * option[3] (Effective only if the bit[3:0] in option[0] > 2, required only for the QSPI NOR FLASH that not supports + * JESD216) + * [31:16] reserved + * [15:12] Sector Erase Command Option, not required here + * [11:8] Sector Size Option, not required here + * [7:0] Flash Size Option + * 0 - 4MB / 1 - 8MB / 2 - 16MB + */ +#if defined(FLASH_XIP) && FLASH_XIP +__attribute__ ((section(".nor_cfg_option"), used)) const uint32_t option[4] = {0xfcf90002, 0x00000007, 0xE, 0x0}; +#endif + +#if defined(FLASH_UF2) && FLASH_UF2 +ATTR_PLACE_AT(".uf2_signature") __attribute__((used)) const uint32_t uf2_signature = BOARD_UF2_SIGNATURE; +#endif + + +/* static function declarations */ +static void board_turnoff_rgb_led(void); +static void init_uart_pins(UART_Type *ptr); +static uint32_t board_init_uart_clock(UART_Type *ptr); +static void init_gpio_pins(void); +static void init_usb_pins(USB_Type *ptr); + +/* extern function definitions */ +void board_init_clock(void) +{ + uint32_t cpu0_freq = clock_get_frequency(clock_cpu0); + if (cpu0_freq == PLLCTL_SOC_PLL_REFCLK_FREQ) { + /* Configure the External OSC ramp-up time: ~9ms */ + pllctl_xtal_set_rampup_time(HPM_PLLCTL, 32UL * 1000UL * 9U); + + /* Select clock setting preset1 */ + sysctl_clock_set_preset(HPM_SYSCTL, sysctl_preset_1); + } + + /* Add clocks to group 0 */ + clock_add_to_group(clock_cpu0, 0); + clock_add_to_group(clock_mchtmr0, 0); + clock_add_to_group(clock_axi0, 0); + clock_add_to_group(clock_axi1, 0); + clock_add_to_group(clock_axi2, 0); + clock_add_to_group(clock_ahb, 0); + clock_add_to_group(clock_xdma, 0); + clock_add_to_group(clock_hdma, 0); + clock_add_to_group(clock_xpi0, 0); + clock_add_to_group(clock_xpi1, 0); + clock_add_to_group(clock_ram0, 0); + clock_add_to_group(clock_ram1, 0); + clock_add_to_group(clock_lmm0, 0); + clock_add_to_group(clock_lmm1, 0); + clock_add_to_group(clock_gpio, 0); + clock_add_to_group(clock_mot0, 0); + clock_add_to_group(clock_mot1, 0); + clock_add_to_group(clock_mot2, 0); + clock_add_to_group(clock_mot3, 0); + clock_add_to_group(clock_synt, 0); + clock_add_to_group(clock_ptpc, 0); + /* Connect Group0 to CPU0 */ + clock_connect_group_to_cpu(0, 0); + + /* Add clocks to Group1 */ + clock_add_to_group(clock_cpu1, 1); + clock_add_to_group(clock_mchtmr1, 1); + /* Connect Group1 to CPU1 */ + clock_connect_group_to_cpu(1, 1); + + /* Bump up DCDC voltage to 1275mv */ + pcfg_dcdc_set_voltage(HPM_PCFG, 1275); + pcfg_dcdc_switch_to_dcm_mode(HPM_PCFG); + + if (status_success != pllctl_init_int_pll_with_freq(HPM_PLLCTL, 0, BOARD_CPU_FREQ)) { + printf("Failed to set pll0_clk0 to %ldHz\n", BOARD_CPU_FREQ); + while (1) { + } + } + + clock_set_source_divider(clock_cpu0, clk_src_pll0_clk0, 1); + clock_set_source_divider(clock_cpu1, clk_src_pll0_clk0, 1); + clock_update_core_clock(); + + clock_set_source_divider(clock_ahb, clk_src_pll1_clk1, 2); /*200m hz*/ + clock_set_source_divider(clock_mchtmr0, clk_src_osc24m, 1); + clock_set_source_divider(clock_mchtmr1, clk_src_osc24m, 1); +} + +void board_init_pmp(void) +{ + uint32_t start_addr; + uint32_t end_addr; + uint32_t length; + pmp_entry_t pmp_entry[16] = {0}; + uint8_t index = 0; + + /* Init noncachable memory */ + extern uint32_t __noncacheable_start__[]; + extern uint32_t __noncacheable_end__[]; + start_addr = (uint32_t) __noncacheable_start__; + end_addr = (uint32_t) __noncacheable_end__; + length = end_addr - start_addr; + if (length > 0) { + /* Ensure the address and the length are power of 2 aligned */ + assert((length & (length - 1U)) == 0U); + assert((start_addr & (length - 1U)) == 0U); + pmp_entry[index].pmp_addr = PMP_NAPOT_ADDR(start_addr, length); + pmp_entry[index].pmp_cfg.val = PMP_CFG(READ_EN, WRITE_EN, EXECUTE_EN, ADDR_MATCH_NAPOT, REG_UNLOCK); + pmp_entry[index].pma_addr = PMA_NAPOT_ADDR(start_addr, length); + pmp_entry[index].pma_cfg.val = PMA_CFG(ADDR_MATCH_NAPOT, MEM_TYPE_MEM_NON_CACHE_BUF, AMO_EN); + index++; + } + + /* Init share memory */ + extern uint32_t __share_mem_start__[]; + extern uint32_t __share_mem_end__[]; + start_addr = (uint32_t)__share_mem_start__; + end_addr = (uint32_t)__share_mem_end__; + length = end_addr - start_addr; + if (length > 0) { + /* Ensure the address and the length are power of 2 aligned */ + assert((length & (length - 1U)) == 0U); + assert((start_addr & (length - 1U)) == 0U); + pmp_entry[index].pmp_addr = PMP_NAPOT_ADDR(start_addr, length); + pmp_entry[index].pmp_cfg.val = PMP_CFG(READ_EN, WRITE_EN, EXECUTE_EN, ADDR_MATCH_NAPOT, REG_UNLOCK); + pmp_entry[index].pma_addr = PMA_NAPOT_ADDR(start_addr, length); + pmp_entry[index].pma_cfg.val = PMA_CFG(ADDR_MATCH_NAPOT, MEM_TYPE_MEM_NON_CACHE_BUF, AMO_EN); + index++; + } + + pmp_config(&pmp_entry[0], index); +} + +void board_init_console(void) +{ + uart_config_t config = {0}; + uint32_t freq; + + /* uart needs to configure pin function before enabling clock, otherwise the level change of + uart rx pin when configuring pin function will cause a wrong data to be received. + And a uart rx dma request will be generated by default uart fifo dma trigger level. */ + init_uart_pins((UART_Type *) BOARD_CONSOLE_UART_BASE); + + freq = board_init_uart_clock((UART_Type *)BOARD_CONSOLE_UART_BASE); + + uart_default_config((UART_Type *)BOARD_CONSOLE_UART_BASE, &config); + config.src_freq_in_hz = freq; + config.baudrate = BOARD_CONSOLE_UART_BAUDRATE; + uart_init((UART_Type *)BOARD_CONSOLE_UART_BASE, &config); +} + +void board_init_gpio_pins(void) +{ + init_gpio_pins(); +} + +void board_init_led_pins(void) +{ + board_turnoff_rgb_led(); + init_led_pins_as_gpio(); + gpio_set_pin_output_with_initial(BOARD_R_GPIO_CTRL, BOARD_R_GPIO_INDEX, BOARD_R_GPIO_PIN, BOARD_LED_OFF_LEVEL); + gpio_set_pin_output_with_initial(BOARD_G_GPIO_CTRL, BOARD_G_GPIO_INDEX, BOARD_G_GPIO_PIN, BOARD_LED_OFF_LEVEL); + gpio_set_pin_output_with_initial(BOARD_B_GPIO_CTRL, BOARD_B_GPIO_INDEX, BOARD_B_GPIO_PIN, BOARD_LED_OFF_LEVEL); +} + +void board_init_usb(USB_Type *ptr) +{ + clock_name_t usb_clk = (ptr == HPM_USB0) ? clock_usb0 : clock_usb1; + + init_usb_pins(ptr); + clock_add_to_group(usb_clk, 0); +} + +/* static function definitions */ +static void board_turnoff_rgb_led(void) +{ + uint32_t pad_ctl = IOC_PAD_PAD_CTL_PE_SET(1) | IOC_PAD_PAD_CTL_PS_SET(BOARD_LED_OFF_LEVEL); + HPM_IOC->PAD[IOC_PAD_PB11].FUNC_CTL = IOC_PB11_FUNC_CTL_GPIO_B_11; + HPM_IOC->PAD[IOC_PAD_PB12].FUNC_CTL = IOC_PB12_FUNC_CTL_GPIO_B_12; + HPM_IOC->PAD[IOC_PAD_PB13].FUNC_CTL = IOC_PB13_FUNC_CTL_GPIO_B_13; + + HPM_IOC->PAD[IOC_PAD_PB11].PAD_CTL = pad_ctl; + HPM_IOC->PAD[IOC_PAD_PB12].PAD_CTL = pad_ctl; + HPM_IOC->PAD[IOC_PAD_PB13].PAD_CTL = pad_ctl; +} + +static void init_uart_pins(UART_Type *ptr) +{ + if (ptr == HPM_UART0) { + init_uart0_pins(); + } else if (ptr == HPM_UART2) { + init_uart2_pins(); + } else if (ptr == HPM_UART13) { + init_uart13_pins(); + } else if (ptr == HPM_PUART) { + init_puart_pins(); + } +} + +static uint32_t board_init_uart_clock(UART_Type *ptr) +{ + uint32_t freq = 0U; + if (ptr == HPM_UART0) { + clock_add_to_group(clock_uart0, 0); + freq = clock_get_frequency(clock_uart0); + } else if (ptr == HPM_UART6) { + clock_add_to_group(clock_uart6, 0); + freq = clock_get_frequency(clock_uart6); + } else if (ptr == HPM_UART13) { + clock_add_to_group(clock_uart13, 0); + freq = clock_get_frequency(clock_uart13); + } else if (ptr == HPM_UART14) { + clock_add_to_group(clock_uart14, 0); + freq = clock_get_frequency(clock_uart14); + } else { + /* Not supported */ + } + return freq; +} + +static void init_gpio_pins(void) +{ + init_gpio_pins_with_pull_up(); +#ifdef USING_GPIO0_FOR_GPIOZ + init_gpio_pins_using_gpio0(); +#endif +} + +static void init_usb_pins(USB_Type *ptr) +{ + if (ptr == HPM_USB0) { + init_usb0_pins(); + } else if (ptr == HPM_USB1) { + init_usb1_pins(); + } +} diff --git a/hw/bsp/hpmicro/boards/hpm6750evk2/board.cmake b/hw/bsp/hpmicro/boards/hpm6750evk2/board.cmake new file mode 100644 index 000000000..b15911cb5 --- /dev/null +++ b/hw/bsp/hpmicro/boards/hpm6750evk2/board.cmake @@ -0,0 +1,22 @@ +set(MCU_VARIANT HPM6750xVMx) +set(JLINK_DEVICE ${MCU_VARIANT}) + +set(JLINK_IF jtag) + +set(HPM_SOC ${SDK_DIR}/soc/HPM6700/HPM6750) +set(HPM_IP_REGS ${SDK_DIR}/soc/HPM6700/ip) + +set(BOARD_FLASH_SIZE 16M) +set(BOARD_STACK_SIZE 16K) +set(BOARD_HEAP_SIZE 16K) + +set(HPM_PLLCTL_DRV_FILE hpm_pllctl_drv.c) + +function(update_board TARGET) + target_compile_definitions(${TARGET} PUBLIC + BOARD_TUD_RHPORT=0 + BOARD_TUD_MAX_SPEED=OPT_MODE_HIGH_SPEED + BOARD_TUH_RHPORT=1 + BOARD_TUH_MAX_SPEED=OPT_MODE_HIGH_SPEED + ) +endfunction() diff --git a/hw/bsp/hpmicro/boards/hpm6750evk2/board.h b/hw/bsp/hpmicro/boards/hpm6750evk2/board.h new file mode 100644 index 000000000..0636a4722 --- /dev/null +++ b/hw/bsp/hpmicro/boards/hpm6750evk2/board.h @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2021-2025 HPMicro + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef _HPM_BOARD_H +#define _HPM_BOARD_H + +#include +#include "hpm_common.h" +#include "hpm_soc.h" +#include "hpm_soc_feature.h" +#include "pinmux.h" + +#define BOARD_NAME "hpm6750evk2" + +#ifndef BOARD_RUNNING_CORE +#define BOARD_RUNNING_CORE HPM_CORE0 +#endif + +#define BOARD_CPU_FREQ (816000000UL) + +/* console section */ +#if BOARD_RUNNING_CORE == HPM_CORE0 + #define BOARD_CONSOLE_UART_BASE HPM_UART0 + #define BOARD_CONSOLE_UART_CLK_NAME clock_uart0 + #define BOARD_CONSOLE_UART_IRQ IRQn_UART0 + #define BOARD_CONSOLE_UART_TX_DMA_REQ HPM_DMA_SRC_UART0_TX + #define BOARD_CONSOLE_UART_RX_DMA_REQ HPM_DMA_SRC_UART0_RX +#else + #define BOARD_CONSOLE_UART_BASE HPM_UART13 + #define BOARD_CONSOLE_UART_CLK_NAME clock_uart13 + #define BOARD_CONSOLE_UART_IRQ IRQn_UART13 + #define BOARD_CONSOLE_UART_TX_DMA_REQ HPM_DMA_SRC_UART13_TX + #define BOARD_CONSOLE_UART_RX_DMA_REQ HPM_DMA_SRC_UART13_RX +#endif + +#define BOARD_CONSOLE_UART_BAUDRATE (115200UL) + +/* sdram section */ +#define BOARD_SDRAM_ADDRESS (0x40000000UL) +#define BOARD_SDRAM_SIZE (32 * SIZE_1MB) +#define BOARD_SDRAM_CS FEMC_SDRAM_CS0 +#define BOARD_SDRAM_PORT_SIZE FEMC_SDRAM_PORT_SIZE_32_BITS +#define BOARD_SDRAM_COLUMN_ADDR_BITS FEMC_SDRAM_COLUMN_ADDR_9_BITS +#define BOARD_SDRAM_REFRESH_COUNT (8192UL) +#define BOARD_SDRAM_REFRESH_IN_MS (64UL) + +#define BOARD_FLASH_BASE_ADDRESS (0x80000000UL) +#define BOARD_FLASH_SIZE (16 << 20) + +/* gpio section */ +#define BOARD_R_GPIO_CTRL HPM_GPIO0 +#define BOARD_R_GPIO_INDEX GPIO_DI_GPIOB +#define BOARD_R_GPIO_PIN 11 +#define BOARD_G_GPIO_CTRL HPM_GPIO0 +#define BOARD_G_GPIO_INDEX GPIO_DI_GPIOB +#define BOARD_G_GPIO_PIN 12 +#define BOARD_B_GPIO_CTRL HPM_GPIO0 +#define BOARD_B_GPIO_INDEX GPIO_DI_GPIOB +#define BOARD_B_GPIO_PIN 13 + +#define BOARD_LED_GPIO_CTRL HPM_GPIO0 + +#define BOARD_LED_GPIO_INDEX GPIO_DI_GPIOB +#define BOARD_LED_GPIO_PIN 12 +#define BOARD_LED_OFF_LEVEL 0 +#define BOARD_LED_ON_LEVEL 1 + +#define BOARD_LED_TOGGLE_RGB 1 + +#define BOARD_APP_GPIO_INDEX GPIO_DI_GPIOZ +#define BOARD_APP_GPIO_PIN 2 +#define BOARD_BUTTON_PRESSED_VALUE 0 + +#define USING_GPIO0_FOR_GPIOZ +#ifndef USING_GPIO0_FOR_GPIOZ +#define BOARD_APP_GPIO_CTRL HPM_BGPIO +#define BOARD_APP_GPIO_IRQ IRQn_BGPIO +#else +#define BOARD_APP_GPIO_CTRL HPM_GPIO0 +#define BOARD_APP_GPIO_IRQ IRQn_GPIO0_Z +#endif + +#if defined(__cplusplus) +extern "C" { +#endif /* __cplusplus */ + + +void board_init_clock(void); +void board_init_pmp(void); +void board_init_console(void); +void board_init_gpio_pins(void); +void board_init_led_pins(void); +void board_init_usb(USB_Type *ptr); +void board_print_banner(void); +void board_print_clock_freq(void); + + +#if defined(__cplusplus) +} +#endif /* __cplusplus */ +#endif /* _HPM_BOARD_H */ diff --git a/hw/bsp/hpmicro/boards/hpm6750evk2/board.mk b/hw/bsp/hpmicro/boards/hpm6750evk2/board.mk new file mode 100644 index 000000000..26981ce28 --- /dev/null +++ b/hw/bsp/hpmicro/boards/hpm6750evk2/board.mk @@ -0,0 +1,16 @@ +MCU_VARIANT = HPM6750xVMx +JLINK_DEVICE = ${MCU_VARIANT} + +JLINK_IF = jtag + +HPM_SOC = $(SDK_DIR)/soc/HPM6700/HPM6750 +HPM_IP_REGS = $(SDK_DIR)/soc/HPM6700/ip + +BOARD_FLASH_SIZE = 16M +BOARD_STACK_SIZE = 16K +BOARD_HEAP_SIZE = 16K + +BOARD_TUD_RHPORT = 0 +BOARD_TUH_RHPORT = 1 + +HPM_PLLCTL_DRV_FILE = hpm_pllctl_drv.c diff --git a/hw/bsp/hpmicro/boards/hpm6750evk2/pinmux.c b/hw/bsp/hpmicro/boards/hpm6750evk2/pinmux.c new file mode 100644 index 000000000..7554e3a76 --- /dev/null +++ b/hw/bsp/hpmicro/boards/hpm6750evk2/pinmux.c @@ -0,0 +1,862 @@ + +/* + * Copyright (c) 2025 HPMicro + * + * SPDX-License-Identifier: BSD-3-Clause + * + * + * Automatically generated by HPM Pinmux Tool + * + * + * Note: + * PY and PZ IOs: if any SOC pin function needs to be routed to these IOs, + * besides of IOC, PIOC/BIOC needs to be configured SOC_GPIO_X_xx, so that + * expected SoC function can be enabled on these IOs. + */ + +#include "pinmux.h" +#include "board.h" +#include "hpm_trgm_drv.h" + + +/* PY port IO needs to configure PIOC as well */ +void init_uart0_pins(void) +{ + HPM_IOC->PAD[IOC_PAD_PY07].FUNC_CTL = IOC_PY07_FUNC_CTL_UART0_RXD; + HPM_PIOC->PAD[IOC_PAD_PY07].FUNC_CTL = PIOC_PY07_FUNC_CTL_SOC_PY_07; + + HPM_IOC->PAD[IOC_PAD_PY06].FUNC_CTL = IOC_PY06_FUNC_CTL_UART0_TXD; + HPM_PIOC->PAD[IOC_PAD_PY06].FUNC_CTL = PIOC_PY06_FUNC_CTL_SOC_PY_06; +} + +void init_uart2_pins(void) +{ + HPM_IOC->PAD[IOC_PAD_PE16].FUNC_CTL = IOC_PE16_FUNC_CTL_UART2_TXD; + + HPM_IOC->PAD[IOC_PAD_PE21].FUNC_CTL = IOC_PE21_FUNC_CTL_UART2_RXD; +} + +/* PZ port IO needs to configure BIOC as well */ +void init_uart13_pins(void) +{ + HPM_IOC->PAD[IOC_PAD_PZ08].FUNC_CTL = IOC_PZ08_FUNC_CTL_UART13_RXD; + HPM_BIOC->PAD[IOC_PAD_PZ08].FUNC_CTL = BIOC_PZ08_FUNC_CTL_SOC_PZ_08; + + HPM_IOC->PAD[IOC_PAD_PZ09].FUNC_CTL = IOC_PZ09_FUNC_CTL_UART13_TXD; + HPM_BIOC->PAD[IOC_PAD_PZ09].FUNC_CTL = BIOC_PZ09_FUNC_CTL_SOC_PZ_09; +} + +void init_puart_pins(void) +{ + HPM_PIOC->PAD[IOC_PAD_PY06].FUNC_CTL = PIOC_PY06_FUNC_CTL_PUART_TXD; + + HPM_PIOC->PAD[IOC_PAD_PY07].FUNC_CTL = PIOC_PY07_FUNC_CTL_PUART_RXD; +} + +/* + * PZ port IO needs to configure BIOC as well. + * PZ08 and PZ09 need pull up. + * Errata: E00029:IOC PAD_CTL register write restrictions. + * When the PE bit is 1, bit [3] must be set to 1, + * and DS can only be selected as 0b001 (low drive strength) or 0b110 (high drive strength). + */ +void init_uart13_pins_as_gpio(void) +{ + HPM_IOC->PAD[IOC_PAD_PZ08].FUNC_CTL = IOC_PZ08_FUNC_CTL_GPIO_Z_08; + HPM_BIOC->PAD[IOC_PAD_PZ08].FUNC_CTL = BIOC_PZ08_FUNC_CTL_SOC_PZ_08; + HPM_IOC->PAD[IOC_PAD_PZ08].PAD_CTL = IOC_PAD_PAD_CTL_DS_SET(1) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08 | IOC_PAD_PAD_CTL_PS_SET(1); + + HPM_IOC->PAD[IOC_PAD_PZ09].FUNC_CTL = IOC_PZ09_FUNC_CTL_GPIO_Z_09; + HPM_BIOC->PAD[IOC_PAD_PZ09].FUNC_CTL = BIOC_PZ09_FUNC_CTL_SOC_PZ_09; +} + +void init_lcd0_pins(void) +{ + HPM_IOC->PAD[IOC_PAD_PB03].FUNC_CTL = IOC_PB03_FUNC_CTL_DIS0_R_0; + + HPM_IOC->PAD[IOC_PAD_PB04].FUNC_CTL = IOC_PB04_FUNC_CTL_DIS0_R_1; + + HPM_IOC->PAD[IOC_PAD_PB00].FUNC_CTL = IOC_PB00_FUNC_CTL_DIS0_R_2; + + HPM_IOC->PAD[IOC_PAD_PA31].FUNC_CTL = IOC_PA31_FUNC_CTL_DIS0_R_3; + + HPM_IOC->PAD[IOC_PAD_PA26].FUNC_CTL = IOC_PA26_FUNC_CTL_DIS0_R_4; + + HPM_IOC->PAD[IOC_PAD_PA21].FUNC_CTL = IOC_PA21_FUNC_CTL_DIS0_R_5; + + HPM_IOC->PAD[IOC_PAD_PA27].FUNC_CTL = IOC_PA27_FUNC_CTL_DIS0_R_6; + + HPM_IOC->PAD[IOC_PAD_PA28].FUNC_CTL = IOC_PA28_FUNC_CTL_DIS0_R_7; + + HPM_IOC->PAD[IOC_PAD_PB06].FUNC_CTL = IOC_PB06_FUNC_CTL_DIS0_G_0; + + HPM_IOC->PAD[IOC_PAD_PB01].FUNC_CTL = IOC_PB01_FUNC_CTL_DIS0_G_1; + + HPM_IOC->PAD[IOC_PAD_PA22].FUNC_CTL = IOC_PA22_FUNC_CTL_DIS0_G_2; + + HPM_IOC->PAD[IOC_PAD_PA23].FUNC_CTL = IOC_PA23_FUNC_CTL_DIS0_G_3; + + HPM_IOC->PAD[IOC_PAD_PA29].FUNC_CTL = IOC_PA29_FUNC_CTL_DIS0_G_4; + + HPM_IOC->PAD[IOC_PAD_PA24].FUNC_CTL = IOC_PA24_FUNC_CTL_DIS0_G_5; + + HPM_IOC->PAD[IOC_PAD_PA30].FUNC_CTL = IOC_PA30_FUNC_CTL_DIS0_G_6; + + HPM_IOC->PAD[IOC_PAD_PA25].FUNC_CTL = IOC_PA25_FUNC_CTL_DIS0_G_7; + + HPM_IOC->PAD[IOC_PAD_PB05].FUNC_CTL = IOC_PB05_FUNC_CTL_DIS0_B_0; + + HPM_IOC->PAD[IOC_PAD_PB07].FUNC_CTL = IOC_PB07_FUNC_CTL_DIS0_B_1; + + HPM_IOC->PAD[IOC_PAD_PB02].FUNC_CTL = IOC_PB02_FUNC_CTL_DIS0_B_2; + + HPM_IOC->PAD[IOC_PAD_PA16].FUNC_CTL = IOC_PA16_FUNC_CTL_DIS0_B_3; + + HPM_IOC->PAD[IOC_PAD_PA12].FUNC_CTL = IOC_PA12_FUNC_CTL_DIS0_B_4; + + HPM_IOC->PAD[IOC_PAD_PA17].FUNC_CTL = IOC_PA17_FUNC_CTL_DIS0_B_5; + + HPM_IOC->PAD[IOC_PAD_PA13].FUNC_CTL = IOC_PA13_FUNC_CTL_DIS0_B_6; + + HPM_IOC->PAD[IOC_PAD_PA18].FUNC_CTL = IOC_PA18_FUNC_CTL_DIS0_B_7; + + HPM_IOC->PAD[IOC_PAD_PA20].FUNC_CTL = IOC_PA20_FUNC_CTL_DIS0_CLK; + + HPM_IOC->PAD[IOC_PAD_PA15].FUNC_CTL = IOC_PA15_FUNC_CTL_DIS0_EN; + + HPM_IOC->PAD[IOC_PAD_PA19].FUNC_CTL = IOC_PA19_FUNC_CTL_DIS0_HSYNC; + + HPM_IOC->PAD[IOC_PAD_PA14].FUNC_CTL = IOC_PA14_FUNC_CTL_DIS0_VSYNC; + + /* PWM */ + HPM_IOC->PAD[IOC_PAD_PB10].FUNC_CTL = IOC_PB10_FUNC_CTL_GPIO_B_10; + + /* RST */ + HPM_IOC->PAD[IOC_PAD_PB16].FUNC_CTL = IOC_PB16_FUNC_CTL_GPIO_B_16; + + HPM_IOC->PAD[IOC_PAD_PZ00].FUNC_CTL = IOC_PZ00_FUNC_CTL_GPIO_Z_00; + HPM_BIOC->PAD[IOC_PAD_PZ00].FUNC_CTL = BIOC_PZ00_FUNC_CTL_SOC_PZ_00; + HPM_IOC->PAD[IOC_PAD_PZ00].PAD_CTL = IOC_PAD_PAD_CTL_DS_SET(1) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08 | IOC_PAD_PAD_CTL_PS_SET(1); +} + +/* + * Errata: E00029:IOC PAD_CTL register write restrictions. + * When the PE bit is 1, bit [3] must be set to 1, + * and DS can only be selected as 0b001 (low drive strength) or 0b110 (high drive strength). + */ +void init_cap_pins(void) +{ + /* CAP_INT */ + HPM_IOC->PAD[IOC_PAD_PB08].FUNC_CTL = IOC_PB08_FUNC_CTL_GPIO_B_08; + HPM_IOC->PAD[IOC_PAD_PB08].PAD_CTL = IOC_PAD_PAD_CTL_PE_SET(1) | 0x08 | IOC_PAD_PAD_CTL_DS_SET(1); + + /* CAP_RST */ + HPM_IOC->PAD[IOC_PAD_PB09].FUNC_CTL = IOC_PB09_FUNC_CTL_GPIO_B_09; + HPM_IOC->PAD[IOC_PAD_PB09].PAD_CTL = IOC_PAD_PAD_CTL_PE_SET(1) | 0x08 | IOC_PAD_PAD_CTL_DS_SET(1); +} + +/* PZ port IO needs to configure BIOC as well */ +void init_i2c0_pins_as_gpio(void) +{ + HPM_IOC->PAD[IOC_PAD_PZ11].FUNC_CTL = IOC_PZ11_FUNC_CTL_GPIO_Z_11; + HPM_BIOC->PAD[IOC_PAD_PZ11].FUNC_CTL = BIOC_PZ11_FUNC_CTL_SOC_PZ_11; + + HPM_IOC->PAD[IOC_PAD_PZ10].FUNC_CTL = IOC_PZ10_FUNC_CTL_GPIO_Z_10; + HPM_BIOC->PAD[IOC_PAD_PZ10].FUNC_CTL = BIOC_PZ10_FUNC_CTL_SOC_PZ_10; +} + +/* PZ port IO needs to configure BIOC as well */ +void init_i2c0_pins(void) +{ + HPM_IOC->PAD[IOC_PAD_PZ11].FUNC_CTL = IOC_PZ11_FUNC_CTL_I2C0_SCL | IOC_PAD_FUNC_CTL_LOOP_BACK_MASK; + HPM_BIOC->PAD[IOC_PAD_PZ11].FUNC_CTL = BIOC_PZ11_FUNC_CTL_SOC_PZ_11; + HPM_IOC->PAD[IOC_PAD_PZ11].PAD_CTL = IOC_PAD_PAD_CTL_OD_SET(1); + + HPM_IOC->PAD[IOC_PAD_PZ10].FUNC_CTL = IOC_PZ10_FUNC_CTL_I2C0_SDA | IOC_PAD_FUNC_CTL_LOOP_BACK_MASK; + HPM_BIOC->PAD[IOC_PAD_PZ10].FUNC_CTL = BIOC_PZ10_FUNC_CTL_SOC_PZ_10; + HPM_IOC->PAD[IOC_PAD_PZ10].PAD_CTL = IOC_PAD_PAD_CTL_OD_SET(1); +} + +void init_femc_pins(void) +{ + HPM_IOC->PAD[IOC_PAD_PC01].FUNC_CTL = IOC_PC01_FUNC_CTL_FEMC_DQ_16; + + HPM_IOC->PAD[IOC_PAD_PC00].FUNC_CTL = IOC_PC00_FUNC_CTL_FEMC_DQ_17; + + HPM_IOC->PAD[IOC_PAD_PB31].FUNC_CTL = IOC_PB31_FUNC_CTL_FEMC_DQ_18; + + HPM_IOC->PAD[IOC_PAD_PB30].FUNC_CTL = IOC_PB30_FUNC_CTL_FEMC_DQ_30; + + HPM_IOC->PAD[IOC_PAD_PB29].FUNC_CTL = IOC_PB29_FUNC_CTL_FEMC_DQ_31; + + HPM_IOC->PAD[IOC_PAD_PB28].FUNC_CTL = IOC_PB28_FUNC_CTL_FEMC_DQ_19; + + HPM_IOC->PAD[IOC_PAD_PB27].FUNC_CTL = IOC_PB27_FUNC_CTL_FEMC_DQ_20; + + HPM_IOC->PAD[IOC_PAD_PB26].FUNC_CTL = IOC_PB26_FUNC_CTL_FEMC_DQ_21; + + HPM_IOC->PAD[IOC_PAD_PB25].FUNC_CTL = IOC_PB25_FUNC_CTL_FEMC_DQ_28; + + HPM_IOC->PAD[IOC_PAD_PB24].FUNC_CTL = IOC_PB24_FUNC_CTL_FEMC_DQ_29; + + HPM_IOC->PAD[IOC_PAD_PB23].FUNC_CTL = IOC_PB23_FUNC_CTL_FEMC_DQ_22; + + HPM_IOC->PAD[IOC_PAD_PB22].FUNC_CTL = IOC_PB22_FUNC_CTL_FEMC_DQ_26; + + HPM_IOC->PAD[IOC_PAD_PB21].FUNC_CTL = IOC_PB21_FUNC_CTL_FEMC_DQ_27; + + HPM_IOC->PAD[IOC_PAD_PB20].FUNC_CTL = IOC_PB20_FUNC_CTL_FEMC_DQ_23; + + HPM_IOC->PAD[IOC_PAD_PB19].FUNC_CTL = IOC_PB19_FUNC_CTL_FEMC_DQ_24; + + HPM_IOC->PAD[IOC_PAD_PB18].FUNC_CTL = IOC_PB18_FUNC_CTL_FEMC_DQ_25; + + HPM_IOC->PAD[IOC_PAD_PD13].FUNC_CTL = IOC_PD13_FUNC_CTL_FEMC_DQ_14; + + HPM_IOC->PAD[IOC_PAD_PD12].FUNC_CTL = IOC_PD12_FUNC_CTL_FEMC_DQ_15; + + HPM_IOC->PAD[IOC_PAD_PD10].FUNC_CTL = IOC_PD10_FUNC_CTL_FEMC_DQ_12; + + HPM_IOC->PAD[IOC_PAD_PD09].FUNC_CTL = IOC_PD09_FUNC_CTL_FEMC_DQ_13; + + HPM_IOC->PAD[IOC_PAD_PD08].FUNC_CTL = IOC_PD08_FUNC_CTL_FEMC_DQ_00; + + HPM_IOC->PAD[IOC_PAD_PD07].FUNC_CTL = IOC_PD07_FUNC_CTL_FEMC_DQ_10; + + HPM_IOC->PAD[IOC_PAD_PD06].FUNC_CTL = IOC_PD06_FUNC_CTL_FEMC_DQ_11; + + HPM_IOC->PAD[IOC_PAD_PD05].FUNC_CTL = IOC_PD05_FUNC_CTL_FEMC_DQ_01; + + HPM_IOC->PAD[IOC_PAD_PD04].FUNC_CTL = IOC_PD04_FUNC_CTL_FEMC_DQ_08; + + HPM_IOC->PAD[IOC_PAD_PD03].FUNC_CTL = IOC_PD03_FUNC_CTL_FEMC_DQ_09; + + HPM_IOC->PAD[IOC_PAD_PD02].FUNC_CTL = IOC_PD02_FUNC_CTL_FEMC_DQ_04; + + HPM_IOC->PAD[IOC_PAD_PD01].FUNC_CTL = IOC_PD01_FUNC_CTL_FEMC_DQ_03; + + HPM_IOC->PAD[IOC_PAD_PD00].FUNC_CTL = IOC_PD00_FUNC_CTL_FEMC_DQ_02; + + HPM_IOC->PAD[IOC_PAD_PC29].FUNC_CTL = IOC_PC29_FUNC_CTL_FEMC_DQ_07; + + HPM_IOC->PAD[IOC_PAD_PC28].FUNC_CTL = IOC_PC28_FUNC_CTL_FEMC_DQ_06; + + HPM_IOC->PAD[IOC_PAD_PC27].FUNC_CTL = IOC_PC27_FUNC_CTL_FEMC_DQ_05; + + /* SRAM #WE */ + HPM_IOC->PAD[IOC_PAD_PC21].FUNC_CTL = IOC_PC21_FUNC_CTL_FEMC_A_11; + + HPM_IOC->PAD[IOC_PAD_PC17].FUNC_CTL = IOC_PC17_FUNC_CTL_FEMC_A_09; + + HPM_IOC->PAD[IOC_PAD_PC15].FUNC_CTL = IOC_PC15_FUNC_CTL_FEMC_A_10; + + HPM_IOC->PAD[IOC_PAD_PC12].FUNC_CTL = IOC_PC12_FUNC_CTL_FEMC_A_08; + + HPM_IOC->PAD[IOC_PAD_PC11].FUNC_CTL = IOC_PC11_FUNC_CTL_FEMC_A_07; + + HPM_IOC->PAD[IOC_PAD_PC10].FUNC_CTL = IOC_PC10_FUNC_CTL_FEMC_A_06; + + HPM_IOC->PAD[IOC_PAD_PC09].FUNC_CTL = IOC_PC09_FUNC_CTL_FEMC_A_01; + + HPM_IOC->PAD[IOC_PAD_PC08].FUNC_CTL = IOC_PC08_FUNC_CTL_FEMC_A_00; + + HPM_IOC->PAD[IOC_PAD_PC07].FUNC_CTL = IOC_PC07_FUNC_CTL_FEMC_A_05; + + HPM_IOC->PAD[IOC_PAD_PC06].FUNC_CTL = IOC_PC06_FUNC_CTL_FEMC_A_04; + + HPM_IOC->PAD[IOC_PAD_PC05].FUNC_CTL = IOC_PC05_FUNC_CTL_FEMC_A_03; + + HPM_IOC->PAD[IOC_PAD_PC04].FUNC_CTL = IOC_PC04_FUNC_CTL_FEMC_A_02; + + /* SRAM #ADV */ + HPM_IOC->PAD[IOC_PAD_PC14].FUNC_CTL = IOC_PC14_FUNC_CTL_FEMC_BA1; + + HPM_IOC->PAD[IOC_PAD_PC13].FUNC_CTL = IOC_PC13_FUNC_CTL_FEMC_BA0; + + HPM_IOC->PAD[IOC_PAD_PC16].FUNC_CTL = IOC_PC16_FUNC_CTL_FEMC_DQS | IOC_PAD_FUNC_CTL_LOOP_BACK_MASK; + + HPM_IOC->PAD[IOC_PAD_PC26].FUNC_CTL = IOC_PC26_FUNC_CTL_FEMC_CLK; + + HPM_IOC->PAD[IOC_PAD_PC25].FUNC_CTL = IOC_PC25_FUNC_CTL_FEMC_CKE; + + HPM_IOC->PAD[IOC_PAD_PC19].FUNC_CTL = IOC_PC19_FUNC_CTL_FEMC_CS_0; + + HPM_IOC->PAD[IOC_PAD_PC18].FUNC_CTL = IOC_PC18_FUNC_CTL_FEMC_RAS; + + HPM_IOC->PAD[IOC_PAD_PC23].FUNC_CTL = IOC_PC23_FUNC_CTL_FEMC_CAS; + + HPM_IOC->PAD[IOC_PAD_PC24].FUNC_CTL = IOC_PC24_FUNC_CTL_FEMC_WE; + + /* SRAM #LB */ + HPM_IOC->PAD[IOC_PAD_PC30].FUNC_CTL = IOC_PC30_FUNC_CTL_FEMC_DM_0; + + /* SRAM #UB */ + HPM_IOC->PAD[IOC_PAD_PC31].FUNC_CTL = IOC_PC31_FUNC_CTL_FEMC_DM_1; + + HPM_IOC->PAD[IOC_PAD_PC02].FUNC_CTL = IOC_PC02_FUNC_CTL_FEMC_DM_2; + + HPM_IOC->PAD[IOC_PAD_PC03].FUNC_CTL = IOC_PC03_FUNC_CTL_FEMC_DM_3; + + /* SRAM #CE */ + HPM_IOC->PAD[IOC_PAD_PC20].FUNC_CTL = IOC_PC20_FUNC_CTL_FEMC_CS_1; + + /* SRAM #OE */ + HPM_IOC->PAD[IOC_PAD_PC22].FUNC_CTL = IOC_PC22_FUNC_CTL_FEMC_A_12; +} + +/* + * Errata: E00029:IOC PAD_CTL register write restrictions. + * When the PE bit is 1, bit [3] must be set to 1, + * and DS can only be selected as 0b001 (low drive strength) or 0b110 (high drive strength). + */ +void init_gpio_pins_with_pull_up(void) +{ + HPM_IOC->PAD[IOC_PAD_PB12].FUNC_CTL = IOC_PB12_FUNC_CTL_GPIO_B_12; + HPM_IOC->PAD[IOC_PAD_PB12].PAD_CTL = IOC_PAD_PAD_CTL_DS_SET(1) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08 | IOC_PAD_PAD_CTL_PS_SET(0); +} + +/* + * PZ port IO needs to configure BIOC as well. + * Errata: E00029:IOC PAD_CTL register write restrictions. + * When the PE bit is 1, bit [3] must be set to 1, + * and DS can only be selected as 0b001 (low drive strength) or 0b110 (high drive strength). + */ +void init_gpio_pins_using_gpio0(void) +{ + HPM_IOC->PAD[IOC_PAD_PZ02].FUNC_CTL = IOC_PZ02_FUNC_CTL_GPIO_Z_02; + HPM_BIOC->PAD[IOC_PAD_PZ02].FUNC_CTL = BIOC_PZ02_FUNC_CTL_SOC_PZ_02; + HPM_IOC->PAD[IOC_PAD_PZ02].PAD_CTL = IOC_PAD_PAD_CTL_DS_SET(1) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08 | IOC_PAD_PAD_CTL_PS_SET(1); +} + +/* + * Errata: E00029:IOC PAD_CTL register write restrictions. + * When the PE bit is 1, bit [3] must be set to 1, + * and DS can only be selected as 0b001 (low drive strength) or 0b110 (high drive strength). + */ +void init_spi2_pins(void) +{ + HPM_IOC->PAD[IOC_PAD_PE31].FUNC_CTL = IOC_PE31_FUNC_CTL_SPI2_CSN; + HPM_IOC->PAD[IOC_PAD_PE31].PAD_CTL = IOC_PAD_PAD_CTL_DS_SET(6) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08 | IOC_PAD_PAD_CTL_PS_SET(1); + + HPM_IOC->PAD[IOC_PAD_PE30].FUNC_CTL = IOC_PE30_FUNC_CTL_SPI2_MOSI; + HPM_IOC->PAD[IOC_PAD_PE30].PAD_CTL = IOC_PAD_PAD_CTL_DS_SET(6) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08; + + HPM_IOC->PAD[IOC_PAD_PE27].FUNC_CTL = IOC_PE27_FUNC_CTL_SPI2_SCLK | IOC_PAD_FUNC_CTL_LOOP_BACK_MASK; + HPM_IOC->PAD[IOC_PAD_PE27].PAD_CTL = IOC_PAD_PAD_CTL_DS_SET(6) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08; + + HPM_IOC->PAD[IOC_PAD_PE28].FUNC_CTL = IOC_PE28_FUNC_CTL_SPI2_MISO; + HPM_IOC->PAD[IOC_PAD_PE28].PAD_CTL = IOC_PAD_PAD_CTL_DS_SET(6) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08; +} + +/* + * Errata: E00029:IOC PAD_CTL register write restrictions. + * When the PE bit is 1, bit [3] must be set to 1, + * and DS can only be selected as 0b001 (low drive strength) or 0b110 (high drive strength). + */ +void init_spi2_pins_with_gpio_as_cs(void) +{ + HPM_IOC->PAD[IOC_PAD_PE27].FUNC_CTL = IOC_PE27_FUNC_CTL_SPI2_SCLK | IOC_PAD_FUNC_CTL_LOOP_BACK_MASK; + HPM_IOC->PAD[IOC_PAD_PE27].PAD_CTL = IOC_PAD_PAD_CTL_DS_SET(6) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08; + + HPM_IOC->PAD[IOC_PAD_PE28].FUNC_CTL = IOC_PE28_FUNC_CTL_SPI2_MISO; + HPM_IOC->PAD[IOC_PAD_PE28].PAD_CTL = IOC_PAD_PAD_CTL_DS_SET(6) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08; + + HPM_IOC->PAD[IOC_PAD_PE30].FUNC_CTL = IOC_PE30_FUNC_CTL_SPI2_MOSI; + HPM_IOC->PAD[IOC_PAD_PE30].PAD_CTL = IOC_PAD_PAD_CTL_DS_SET(6) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08; + + HPM_IOC->PAD[IOC_PAD_PE31].FUNC_CTL = IOC_PE31_FUNC_CTL_GPIO_E_31; + HPM_IOC->PAD[IOC_PAD_PE31].PAD_CTL = IOC_PAD_PAD_CTL_PE_SET(1) | 0x08 | IOC_PAD_PAD_CTL_DS_SET(6) | IOC_PAD_PAD_CTL_PS_SET(1); +} + +void init_gptmr3_pins(void) +{ + /* TMR3 compare 1 */ + HPM_IOC->PAD[IOC_PAD_PE24].FUNC_CTL = IOC_PE24_FUNC_CTL_GPTMR3_COMP_1; +} + +void init_gptmr4_pins(void) +{ + /* TMR4 capture 1 */ + HPM_IOC->PAD[IOC_PAD_PE25].FUNC_CTL = IOC_PE25_FUNC_CTL_GPTMR4_CAPT_1; +} + +void init_gptmr5_pins(void) +{ + /* TMR5 compare 2 */ + HPM_IOC->PAD[IOC_PAD_PD24].FUNC_CTL = IOC_PD24_FUNC_CTL_TRGM2_P_10; + + /* TMR5 compare 3 */ + HPM_IOC->PAD[IOC_PAD_PD23].FUNC_CTL = IOC_PD23_FUNC_CTL_TRGM2_P_11; + + trgm_output_t trgm2_io_config0 = {0}; + trgm2_io_config0.invert = 0; + trgm2_io_config0.type = trgm_output_same_as_input; + trgm2_io_config0.input = HPM_TRGM2_INPUT_SRC_GPTMR5_OUT2; + trgm_output_config(HPM_TRGM2, HPM_TRGM2_OUTPUT_SRC_TRGM2_P10, &trgm2_io_config0); + + trgm_enable_io_output(HPM_TRGM2, 1 << 10); + + trgm_output_t trgm2_io_config1 = {0}; + trgm2_io_config1.invert = 0; + trgm2_io_config1.type = trgm_output_same_as_input; + trgm2_io_config1.input = HPM_TRGM2_INPUT_SRC_GPTMR5_OUT3; + trgm_output_config(HPM_TRGM2, HPM_TRGM2_OUTPUT_SRC_TRGM2_P11, &trgm2_io_config1); + + trgm_enable_io_output(HPM_TRGM2, 1 << 11); +} + +void init_hall_trgm_pins(void) +{ + HPM_IOC->PAD[IOC_PAD_PD16].FUNC_CTL = IOC_PD16_FUNC_CTL_TRGM2_P_06; + + HPM_IOC->PAD[IOC_PAD_PD20].FUNC_CTL = IOC_PD20_FUNC_CTL_TRGM2_P_07; + + HPM_IOC->PAD[IOC_PAD_PD25].FUNC_CTL = IOC_PD25_FUNC_CTL_TRGM2_P_08; +} + +void init_qei_trgm_pins(void) +{ + HPM_IOC->PAD[IOC_PAD_PD19].FUNC_CTL = IOC_PD19_FUNC_CTL_TRGM2_P_09; + + HPM_IOC->PAD[IOC_PAD_PD24].FUNC_CTL = IOC_PD24_FUNC_CTL_TRGM2_P_10; +} + +void init_i2s0_pins(void) +{ + HPM_IOC->PAD[IOC_PAD_PF02].FUNC_CTL = IOC_PF02_FUNC_CTL_I2S0_RXD_2; + + HPM_IOC->PAD[IOC_PAD_PF03].FUNC_CTL = IOC_PF03_FUNC_CTL_I2S0_MCLK; + + HPM_IOC->PAD[IOC_PAD_PF04].FUNC_CTL = IOC_PF04_FUNC_CTL_I2S0_TXD_2; + + HPM_IOC->PAD[IOC_PAD_PF06].FUNC_CTL = IOC_PF06_FUNC_CTL_I2S0_BCLK; + + HPM_IOC->PAD[IOC_PAD_PF09].FUNC_CTL = IOC_PF09_FUNC_CTL_I2S0_FCLK; +} + +/* PY port IO needs to configure PIOC */ +void init_dao_pins(void) +{ + HPM_IOC->PAD[IOC_PAD_PY08].FUNC_CTL = IOC_PY08_FUNC_CTL_DAOR_P; + HPM_PIOC->PAD[IOC_PAD_PY08].FUNC_CTL = PIOC_PY08_FUNC_CTL_SOC_PY_08; + + HPM_IOC->PAD[IOC_PAD_PY09].FUNC_CTL = IOC_PY09_FUNC_CTL_DAOR_N; + HPM_PIOC->PAD[IOC_PAD_PY09].FUNC_CTL = PIOC_PY09_FUNC_CTL_SOC_PY_09; +} + +/* PY port IO needs to configure PIOC */ +void init_pdm_pins(void) +{ + HPM_IOC->PAD[IOC_PAD_PY10].FUNC_CTL = IOC_PY10_FUNC_CTL_PDM0_CLK; + HPM_PIOC->PAD[IOC_PAD_PY10].FUNC_CTL = PIOC_PY10_FUNC_CTL_SOC_PY_10; + + HPM_IOC->PAD[IOC_PAD_PY11].FUNC_CTL = IOC_PY11_FUNC_CTL_PDM0_D_0; + HPM_PIOC->PAD[IOC_PAD_PY11].FUNC_CTL = PIOC_PY11_FUNC_CTL_SOC_PY_11; +} + +void init_vad_pins(void) +{ + HPM_PIOC->PAD[IOC_PAD_PY10].FUNC_CTL = PIOC_PY10_FUNC_CTL_VAD_CLK; + + HPM_PIOC->PAD[IOC_PAD_PY11].FUNC_CTL = PIOC_PY11_FUNC_CTL_VAD_DAT; +} + +void init_cam_pins(void) +{ + /* configure rst pin function, PY port IO needs to configure PIOC */ + HPM_IOC->PAD[IOC_PAD_PY05].FUNC_CTL = IOC_PY05_FUNC_CTL_GPIO_Y_05; + HPM_PIOC->PAD[IOC_PAD_PY05].FUNC_CTL = PIOC_PY05_FUNC_CTL_SOC_PY_05; + + HPM_IOC->PAD[IOC_PAD_PA07].FUNC_CTL = IOC_PA07_FUNC_CTL_CAM0_D_2; + + HPM_IOC->PAD[IOC_PAD_PA03].FUNC_CTL = IOC_PA03_FUNC_CTL_CAM0_D_3; + + HPM_IOC->PAD[IOC_PAD_PA08].FUNC_CTL = IOC_PA08_FUNC_CTL_CAM0_D_4; + + HPM_IOC->PAD[IOC_PAD_PA09].FUNC_CTL = IOC_PA09_FUNC_CTL_CAM0_D_5; + + HPM_IOC->PAD[IOC_PAD_PA00].FUNC_CTL = IOC_PA00_FUNC_CTL_CAM0_D_6; + + HPM_IOC->PAD[IOC_PAD_PA04].FUNC_CTL = IOC_PA04_FUNC_CTL_CAM0_D_7; + + HPM_IOC->PAD[IOC_PAD_PA01].FUNC_CTL = IOC_PA01_FUNC_CTL_CAM0_D_8; + + HPM_IOC->PAD[IOC_PAD_PA02].FUNC_CTL = IOC_PA02_FUNC_CTL_CAM0_D_9; + + HPM_IOC->PAD[IOC_PAD_PA10].FUNC_CTL = IOC_PA10_FUNC_CTL_CAM0_XCLK; + + HPM_IOC->PAD[IOC_PAD_PA05].FUNC_CTL = IOC_PA05_FUNC_CTL_CAM0_HSYNC; + + HPM_IOC->PAD[IOC_PAD_PA06].FUNC_CTL = IOC_PA06_FUNC_CTL_CAM0_VSYNC; + + HPM_IOC->PAD[IOC_PAD_PA11].FUNC_CTL = IOC_PA11_FUNC_CTL_CAM0_PIXCLK; +} + +void init_butn_pins(void) +{ + HPM_BIOC->PAD[IOC_PAD_PZ02].FUNC_CTL = BIOC_PZ02_FUNC_CTL_PBUTN; + + HPM_BIOC->PAD[IOC_PAD_PZ03].FUNC_CTL = BIOC_PZ03_FUNC_CTL_WBUTN; + + HPM_BIOC->PAD[IOC_PAD_PZ04].FUNC_CTL = BIOC_PZ04_FUNC_CTL_PLED; + + HPM_BIOC->PAD[IOC_PAD_PZ05].FUNC_CTL = BIOC_PZ05_FUNC_CTL_WLED; +} + +void init_acmp_pins(void) +{ + /* configure to ACMP_COMP_1(ALT16) function */ + HPM_IOC->PAD[IOC_PAD_PE25].FUNC_CTL = IOC_PE25_FUNC_CTL_ACMP_COMP_1; + + /* configure to CMP1_INP7 function */ + HPM_IOC->PAD[IOC_PAD_PE23].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; + + /* configure to CMP1_INN6 function */ + HPM_IOC->PAD[IOC_PAD_PE21].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; +} + +void init_enet0_pins(void) +{ + HPM_IOC->PAD[IOC_PAD_PF00].FUNC_CTL = IOC_PF00_FUNC_CTL_GPIO_F_00; + + HPM_IOC->PAD[IOC_PAD_PE23].FUNC_CTL = IOC_PE23_FUNC_CTL_ETH0_MDIO; + + HPM_IOC->PAD[IOC_PAD_PE22].FUNC_CTL = IOC_PE22_FUNC_CTL_ETH0_MDC; + + HPM_IOC->PAD[IOC_PAD_PD31].FUNC_CTL = IOC_PD31_FUNC_CTL_ETH0_RXD_0; + + HPM_IOC->PAD[IOC_PAD_PE04].FUNC_CTL = IOC_PE04_FUNC_CTL_ETH0_RXD_1; + + HPM_IOC->PAD[IOC_PAD_PE02].FUNC_CTL = IOC_PE02_FUNC_CTL_ETH0_RXD_2; + + HPM_IOC->PAD[IOC_PAD_PE07].FUNC_CTL = IOC_PE07_FUNC_CTL_ETH0_RXD_3; + + HPM_IOC->PAD[IOC_PAD_PE03].FUNC_CTL = IOC_PE03_FUNC_CTL_ETH0_RXCK; + + HPM_IOC->PAD[IOC_PAD_PD30].FUNC_CTL = IOC_PD30_FUNC_CTL_ETH0_RXDV; + + HPM_IOC->PAD[IOC_PAD_PE06].FUNC_CTL = IOC_PE06_FUNC_CTL_ETH0_TXD_0; + + HPM_IOC->PAD[IOC_PAD_PD29].FUNC_CTL = IOC_PD29_FUNC_CTL_ETH0_TXD_1; + + HPM_IOC->PAD[IOC_PAD_PD28].FUNC_CTL = IOC_PD28_FUNC_CTL_ETH0_TXD_2; + + HPM_IOC->PAD[IOC_PAD_PE05].FUNC_CTL = IOC_PE05_FUNC_CTL_ETH0_TXD_3; + + HPM_IOC->PAD[IOC_PAD_PE01].FUNC_CTL = IOC_PE01_FUNC_CTL_ETH0_TXCK; + + HPM_IOC->PAD[IOC_PAD_PE00].FUNC_CTL = IOC_PE00_FUNC_CTL_ETH0_TXEN; +} + +void init_enet1_pins(void) +{ + HPM_IOC->PAD[IOC_PAD_PE26].FUNC_CTL = IOC_PE26_FUNC_CTL_GPIO_E_26; + + HPM_IOC->PAD[IOC_PAD_PD11].FUNC_CTL = IOC_PD11_FUNC_CTL_ETH1_MDC; + + HPM_IOC->PAD[IOC_PAD_PD14].FUNC_CTL = IOC_PD14_FUNC_CTL_ETH1_MDIO; + + HPM_IOC->PAD[IOC_PAD_PE20].FUNC_CTL = IOC_PE20_FUNC_CTL_ETH1_RXD_0; + + HPM_IOC->PAD[IOC_PAD_PE18].FUNC_CTL = IOC_PE18_FUNC_CTL_ETH1_RXD_1; + + HPM_IOC->PAD[IOC_PAD_PE15].FUNC_CTL = IOC_PE15_FUNC_CTL_ETH1_RXDV; + + HPM_IOC->PAD[IOC_PAD_PE19].FUNC_CTL = IOC_PE19_FUNC_CTL_ETH1_TXD_0; + + HPM_IOC->PAD[IOC_PAD_PE17].FUNC_CTL = IOC_PE17_FUNC_CTL_ETH1_TXD_1; + + HPM_IOC->PAD[IOC_PAD_PE14].FUNC_CTL = IOC_PE14_FUNC_CTL_ETH1_TXEN; + + HPM_IOC->PAD[IOC_PAD_PE16].FUNC_CTL = IOC_PE16_FUNC_CTL_ETH1_REFCLK | IOC_PAD_FUNC_CTL_LOOP_BACK_MASK; +} + +void init_pwm2_pins(void) +{ + HPM_IOC->PAD[IOC_PAD_PD28].FUNC_CTL = IOC_PD28_FUNC_CTL_PWM2_P_5; + + HPM_IOC->PAD[IOC_PAD_PD29].FUNC_CTL = IOC_PD29_FUNC_CTL_PWM2_P_4; + + HPM_IOC->PAD[IOC_PAD_PD30].FUNC_CTL = IOC_PD30_FUNC_CTL_PWM2_P_1; + + HPM_IOC->PAD[IOC_PAD_PD31].FUNC_CTL = IOC_PD31_FUNC_CTL_PWM2_P_0; + + HPM_IOC->PAD[IOC_PAD_PE03].FUNC_CTL = IOC_PE03_FUNC_CTL_PWM2_P_3; + + HPM_IOC->PAD[IOC_PAD_PE04].FUNC_CTL = IOC_PE04_FUNC_CTL_PWM2_P_2; +} + +void init_pwm3_pins(void) +{ + HPM_IOC->PAD[IOC_PAD_PE17].FUNC_CTL = IOC_PE17_FUNC_CTL_PWM3_P_6; + + HPM_IOC->PAD[IOC_PAD_PE18].FUNC_CTL = IOC_PE18_FUNC_CTL_PWM3_P_7; +} + +void init_adc12_pins(void) +{ + /* ADC0.VIN11 */ + HPM_IOC->PAD[IOC_PAD_PE25].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; +} + +void init_adc16_pins(void) +{ + /* ADC3.INA2 */ + HPM_IOC->PAD[IOC_PAD_PE29].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; +} + +void init_adc_bldc_pins(void) +{ + /* ADC0.VINP7 */ + HPM_IOC->PAD[IOC_PAD_PE21].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; + + /* ADC1.VINP10 */ + HPM_IOC->PAD[IOC_PAD_PE24].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; + + /* ADC2.VINP11 */ + HPM_IOC->PAD[IOC_PAD_PE25].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; +} + +void init_usb0_pins(void) +{ + HPM_IOC->PAD[IOC_PAD_PF10].FUNC_CTL = IOC_PF10_FUNC_CTL_USB0_ID; + + HPM_IOC->PAD[IOC_PAD_PF08].FUNC_CTL = IOC_PF08_FUNC_CTL_USB0_OC; +} + +void init_usb1_pins(void) +{ + HPM_IOC->PAD[IOC_PAD_PF07].FUNC_CTL = IOC_PF07_FUNC_CTL_USB1_ID; + + HPM_IOC->PAD[IOC_PAD_PF05].FUNC_CTL = IOC_PF05_FUNC_CTL_USB1_OC; +} + +void init_can0_pins(void) +{ + HPM_IOC->PAD[IOC_PAD_PB15].FUNC_CTL = IOC_PB15_FUNC_CTL_CAN0_TXD; + + HPM_IOC->PAD[IOC_PAD_PB17].FUNC_CTL = IOC_PB17_FUNC_CTL_CAN0_RXD; +} + +void init_mcan0_transceiver_phy_pin(void) +{ + HPM_IOC->PAD[IOC_PAD_PB14].FUNC_CTL = IOC_PB14_FUNC_CTL_GPIO_B_14; +} + +void init_sdxc1_cmd_pin_enable_1v8_enable_opendrain(void) +{ + /* SDXC1.CMD */ + HPM_IOC->PAD[IOC_PAD_PD21].FUNC_CTL = IOC_PD21_FUNC_CTL_SDC1_CMD | IOC_PAD_FUNC_CTL_LOOP_BACK_MASK; + HPM_IOC->PAD[IOC_PAD_PD21].PAD_CTL = IOC_PAD_PAD_CTL_MS_SET(1) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08 | IOC_PAD_PAD_CTL_DS_SET(6) | IOC_PAD_PAD_CTL_PS_SET(1) | IOC_PAD_PAD_CTL_OD_SET(1); +} + +void init_sdxc1_cmd_pin_enable_1v8_disable_opendrain(void) +{ + /* SDXC1.CMD */ + HPM_IOC->PAD[IOC_PAD_PD21].FUNC_CTL = IOC_PD21_FUNC_CTL_SDC1_CMD | IOC_PAD_FUNC_CTL_LOOP_BACK_MASK; + HPM_IOC->PAD[IOC_PAD_PD21].PAD_CTL = IOC_PAD_PAD_CTL_MS_SET(1) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08 | IOC_PAD_PAD_CTL_DS_SET(6) | IOC_PAD_PAD_CTL_PS_SET(1) | IOC_PAD_PAD_CTL_OD_SET(0); +} + +void init_sdxc1_cmd_pin_disable_1v8_enable_opendrain(void) +{ + /* SDXC1.CMD */ + HPM_IOC->PAD[IOC_PAD_PD21].FUNC_CTL = IOC_PD21_FUNC_CTL_SDC1_CMD | IOC_PAD_FUNC_CTL_LOOP_BACK_MASK; + HPM_IOC->PAD[IOC_PAD_PD21].PAD_CTL = IOC_PAD_PAD_CTL_MS_SET(0) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08 | IOC_PAD_PAD_CTL_DS_SET(6) | IOC_PAD_PAD_CTL_PS_SET(1) | IOC_PAD_PAD_CTL_OD_SET(1); +} + +void init_sdxc1_cmd_pin_disable_1v8_disable_opendrain(void) +{ + /* SDXC1.CMD */ + HPM_IOC->PAD[IOC_PAD_PD21].FUNC_CTL = IOC_PD21_FUNC_CTL_SDC1_CMD | IOC_PAD_FUNC_CTL_LOOP_BACK_MASK; + HPM_IOC->PAD[IOC_PAD_PD21].PAD_CTL = IOC_PAD_PAD_CTL_MS_SET(0) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08 | IOC_PAD_PAD_CTL_DS_SET(6) | IOC_PAD_PAD_CTL_PS_SET(1) | IOC_PAD_PAD_CTL_OD_SET(0); +} + +void init_sdxc1_cd_pin(void) +{ + /* SDXC1.CDN */ + HPM_IOC->PAD[IOC_PAD_PD15].FUNC_CTL = IOC_PD15_FUNC_CTL_GPIO_D_15; + HPM_IOC->PAD[IOC_PAD_PD15].PAD_CTL = IOC_PAD_PAD_CTL_DS_SET(6) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08 | IOC_PAD_PAD_CTL_PS_SET(1); +} + +void init_sdxc1_clk_data_pins_enable_1v8(void) +{ + /* SDXC1.CLK */ + HPM_IOC->PAD[IOC_PAD_PD22].FUNC_CTL = IOC_PD22_FUNC_CTL_SDC1_CLK; + HPM_IOC->PAD[IOC_PAD_PD22].PAD_CTL = IOC_PAD_PAD_CTL_MS_SET(1) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08 | IOC_PAD_PAD_CTL_DS_SET(6) | IOC_PAD_PAD_CTL_PS_SET(1); + + /* SDXC1.DATA0 */ + HPM_IOC->PAD[IOC_PAD_PD18].FUNC_CTL = IOC_PD18_FUNC_CTL_SDC1_DATA_0; + HPM_IOC->PAD[IOC_PAD_PD18].PAD_CTL = IOC_PAD_PAD_CTL_MS_SET(1) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08 | IOC_PAD_PAD_CTL_DS_SET(6) | IOC_PAD_PAD_CTL_PS_SET(1); +} + +void init_sdxc1_clk_data_pins_disable_1v8(void) +{ + /* SDXC1.CLK */ + HPM_IOC->PAD[IOC_PAD_PD22].FUNC_CTL = IOC_PD22_FUNC_CTL_SDC1_CLK; + HPM_IOC->PAD[IOC_PAD_PD22].PAD_CTL = IOC_PAD_PAD_CTL_MS_SET(0) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08 | IOC_PAD_PAD_CTL_DS_SET(6) | IOC_PAD_PAD_CTL_PS_SET(1); + + /* SDXC1.DATA0 */ + HPM_IOC->PAD[IOC_PAD_PD18].FUNC_CTL = IOC_PD18_FUNC_CTL_SDC1_DATA_0; + HPM_IOC->PAD[IOC_PAD_PD18].PAD_CTL = IOC_PAD_PAD_CTL_MS_SET(0) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08 | IOC_PAD_PAD_CTL_DS_SET(6) | IOC_PAD_PAD_CTL_PS_SET(1); +} + +void init_sdxc1_clk_data_pins_width4_enable_1v8(void) +{ + /* SDXC1.DATA1 */ + HPM_IOC->PAD[IOC_PAD_PD17].FUNC_CTL = IOC_PD17_FUNC_CTL_SDC1_DATA_1; + HPM_IOC->PAD[IOC_PAD_PD17].PAD_CTL = IOC_PAD_PAD_CTL_MS_SET(1) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08 | IOC_PAD_PAD_CTL_DS_SET(6) | IOC_PAD_PAD_CTL_PS_SET(1); + + /* SDXC1.DATA2 */ + HPM_IOC->PAD[IOC_PAD_PD27].FUNC_CTL = IOC_PD27_FUNC_CTL_SDC1_DATA_2; + HPM_IOC->PAD[IOC_PAD_PD27].PAD_CTL = IOC_PAD_PAD_CTL_MS_SET(1) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08 | IOC_PAD_PAD_CTL_DS_SET(6) | IOC_PAD_PAD_CTL_PS_SET(1); + + /* SDXC1.DATA3 */ + HPM_IOC->PAD[IOC_PAD_PD26].FUNC_CTL = IOC_PD26_FUNC_CTL_SDC1_DATA_3; + HPM_IOC->PAD[IOC_PAD_PD26].PAD_CTL = IOC_PAD_PAD_CTL_MS_SET(1) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08 | IOC_PAD_PAD_CTL_DS_SET(6) | IOC_PAD_PAD_CTL_PS_SET(1); + + /* SDXC1.CLK */ + HPM_IOC->PAD[IOC_PAD_PD22].FUNC_CTL = IOC_PD22_FUNC_CTL_SDC1_CLK; + HPM_IOC->PAD[IOC_PAD_PD22].PAD_CTL = IOC_PAD_PAD_CTL_MS_SET(1) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08 | IOC_PAD_PAD_CTL_DS_SET(6) | IOC_PAD_PAD_CTL_PS_SET(1); + + /* SDXC1.DATA0 */ + HPM_IOC->PAD[IOC_PAD_PD18].FUNC_CTL = IOC_PD18_FUNC_CTL_SDC1_DATA_0; + HPM_IOC->PAD[IOC_PAD_PD18].PAD_CTL = IOC_PAD_PAD_CTL_MS_SET(1) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08 | IOC_PAD_PAD_CTL_DS_SET(6) | IOC_PAD_PAD_CTL_PS_SET(1); +} + +void init_sdxc1_clk_data_pins_width4_disable_1v8(void) +{ + /* SDXC1.DATA1 */ + HPM_IOC->PAD[IOC_PAD_PD17].FUNC_CTL = IOC_PD17_FUNC_CTL_SDC1_DATA_1; + HPM_IOC->PAD[IOC_PAD_PD17].PAD_CTL = IOC_PAD_PAD_CTL_MS_SET(0) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08 | IOC_PAD_PAD_CTL_DS_SET(6) | IOC_PAD_PAD_CTL_PS_SET(1); + + /* SDXC1.DATA2 */ + HPM_IOC->PAD[IOC_PAD_PD27].FUNC_CTL = IOC_PD27_FUNC_CTL_SDC1_DATA_2; + HPM_IOC->PAD[IOC_PAD_PD27].PAD_CTL = IOC_PAD_PAD_CTL_MS_SET(0) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08 | IOC_PAD_PAD_CTL_DS_SET(6) | IOC_PAD_PAD_CTL_PS_SET(1); + + /* SDXC1.DATA3 */ + HPM_IOC->PAD[IOC_PAD_PD26].FUNC_CTL = IOC_PD26_FUNC_CTL_SDC1_DATA_3; + HPM_IOC->PAD[IOC_PAD_PD26].PAD_CTL = IOC_PAD_PAD_CTL_MS_SET(0) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08 | IOC_PAD_PAD_CTL_DS_SET(6) | IOC_PAD_PAD_CTL_PS_SET(1); + + /* SDXC1.CLK */ + HPM_IOC->PAD[IOC_PAD_PD22].FUNC_CTL = IOC_PD22_FUNC_CTL_SDC1_CLK; + HPM_IOC->PAD[IOC_PAD_PD22].PAD_CTL = IOC_PAD_PAD_CTL_MS_SET(0) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08 | IOC_PAD_PAD_CTL_DS_SET(6) | IOC_PAD_PAD_CTL_PS_SET(1); + + /* SDXC1.DATA0 */ + HPM_IOC->PAD[IOC_PAD_PD18].FUNC_CTL = IOC_PD18_FUNC_CTL_SDC1_DATA_0; + HPM_IOC->PAD[IOC_PAD_PD18].PAD_CTL = IOC_PAD_PAD_CTL_MS_SET(0) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08 | IOC_PAD_PAD_CTL_DS_SET(6) | IOC_PAD_PAD_CTL_PS_SET(1); +} + +void init_sdxc1_pwr_pin(void) +{ + HPM_IOC->PAD[IOC_PAD_PC20].FUNC_CTL = IOC_PC20_FUNC_CTL_GPIO_C_20; + HPM_IOC->PAD[IOC_PAD_PC20].PAD_CTL = IOC_PAD_PAD_CTL_DS_SET(1) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08 | IOC_PAD_PAD_CTL_PS_SET(1); +} + +void init_clk_obs_pins(void) +{ + HPM_IOC->PAD[IOC_PAD_PB02].FUNC_CTL = IOC_PB02_FUNC_CTL_SYSCTL_CLK_OBS_0; +} + +void init_rgb_pwm_pins(void) +{ + /* Red */ + HPM_IOC->PAD[IOC_PAD_PB11].FUNC_CTL = IOC_PB11_FUNC_CTL_TRGM1_P_01; + + /* Green */ + HPM_IOC->PAD[IOC_PAD_PB12].FUNC_CTL = IOC_PB12_FUNC_CTL_TRGM0_P_06; + + /* BLUE */ + HPM_IOC->PAD[IOC_PAD_PB13].FUNC_CTL = IOC_PB13_FUNC_CTL_TRGM1_P_03; +} + +void init_led_pins_as_gpio(void) +{ + HPM_IOC->PAD[IOC_PAD_PB11].FUNC_CTL = IOC_PB11_FUNC_CTL_GPIO_B_11; + + HPM_IOC->PAD[IOC_PAD_PB12].FUNC_CTL = IOC_PB12_FUNC_CTL_GPIO_B_12; + + HPM_IOC->PAD[IOC_PAD_PB13].FUNC_CTL = IOC_PB13_FUNC_CTL_GPIO_B_13; +} + +void init_enet_pps_pins(void) +{ + HPM_IOC->PAD[IOC_PAD_PF05].FUNC_CTL = IOC_PF05_FUNC_CTL_ETH0_EVTO_0; +} + +void init_enet_pps_capture_pins(void) +{ + HPM_IOC->PAD[IOC_PAD_PE25].FUNC_CTL = IOC_PE25_FUNC_CTL_ETH0_EVTI_1; +} + +void init_tamper_pins(void) +{ + HPM_BIOC->PAD[IOC_PAD_PZ08].FUNC_CTL = BIOC_PZ08_FUNC_CTL_TAMP_08 | IOC_PAD_FUNC_CTL_LOOP_BACK_MASK; + + HPM_BIOC->PAD[IOC_PAD_PZ09].FUNC_CTL = BIOC_PZ09_FUNC_CTL_TAMP_09; + + HPM_BIOC->PAD[IOC_PAD_PZ10].FUNC_CTL = BIOC_PZ10_FUNC_CTL_TAMP_10; +} + +/* for uart_rx_line_status case, need to a gpio pin to sent break signal */ +void init_uart_break_signal_pin(void) +{ + HPM_IOC->PAD[IOC_PAD_PE31].FUNC_CTL = IOC_PE31_FUNC_CTL_GPIO_E_31; + HPM_IOC->PAD[IOC_PAD_PE31].PAD_CTL = IOC_PAD_PAD_CTL_DS_SET(1) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08 | IOC_PAD_PAD_CTL_PS_SET(1); +} + +void init_gptmr3_channel_pin_as_output(void) +{ + HPM_IOC->PAD[IOC_PAD_PE24].FUNC_CTL = IOC_PE24_FUNC_CTL_GPTMR3_COMP_1; +} + +void init_gptmr4_channel_pin_as_capture(void) +{ + HPM_IOC->PAD[IOC_PAD_PE25].FUNC_CTL = IOC_PE25_FUNC_CTL_GPTMR4_CAPT_1; +} + +void init_gptmr5_channel2_pin_as_output(void) +{ + HPM_IOC->PAD[IOC_PAD_PD24].FUNC_CTL = IOC_PD24_FUNC_CTL_TRGM2_P_10; + + trgm_output_t trgm2_io_config0 = {0}; + trgm2_io_config0.invert = 0; + trgm2_io_config0.type = trgm_output_same_as_input; + trgm2_io_config0.input = HPM_TRGM2_INPUT_SRC_GPTMR5_OUT2; + trgm_output_config(HPM_TRGM2, HPM_TRGM2_OUTPUT_SRC_TRGM2_P10, &trgm2_io_config0); + + trgm_enable_io_output(HPM_TRGM2, 1 << 10); +} + +void init_gptmr5_channel3_pin_as_output(void) +{ + HPM_IOC->PAD[IOC_PAD_PD23].FUNC_CTL = IOC_PD23_FUNC_CTL_TRGM2_P_11; + + trgm_output_t trgm2_io_config0 = {0}; + trgm2_io_config0.invert = 0; + trgm2_io_config0.type = trgm_output_same_as_input; + trgm2_io_config0.input = HPM_TRGM2_INPUT_SRC_GPTMR5_OUT3; + trgm_output_config(HPM_TRGM2, HPM_TRGM2_OUTPUT_SRC_TRGM2_P11, &trgm2_io_config0); + + trgm_enable_io_output(HPM_TRGM2, 1 << 11); +} + +void init_clk_ref_pin(void) +{ + HPM_IOC->PAD[IOC_PAD_PE24].FUNC_CTL = IOC_PE24_FUNC_CTL_SOC_REF1; +} + +void init_brownout_indicate_pin(void) +{ + HPM_IOC->PAD[IOC_PAD_PE30].FUNC_CTL = IOC_PE30_FUNC_CTL_GPIO_E_30; +} + +void board_init_i2c_eeprom_pin(void) +{ + HPM_IOC->PAD[IOC_PAD_PZ11].FUNC_CTL = IOC_PZ11_FUNC_CTL_I2C0_SCL | IOC_PAD_FUNC_CTL_LOOP_BACK_MASK; + HPM_BIOC->PAD[IOC_PAD_PZ11].FUNC_CTL = BIOC_PZ11_FUNC_CTL_SOC_PZ_11; + HPM_IOC->PAD[IOC_PAD_PZ11].PAD_CTL = IOC_PAD_PAD_CTL_OD_SET(1); + + HPM_IOC->PAD[IOC_PAD_PZ10].FUNC_CTL = IOC_PZ10_FUNC_CTL_I2C0_SDA | IOC_PAD_FUNC_CTL_LOOP_BACK_MASK; + HPM_BIOC->PAD[IOC_PAD_PZ10].FUNC_CTL = BIOC_PZ10_FUNC_CTL_SOC_PZ_10; + HPM_IOC->PAD[IOC_PAD_PZ10].PAD_CTL = IOC_PAD_PAD_CTL_OD_SET(1); +} diff --git a/hw/bsp/hpmicro/boards/hpm6750evk2/pinmux.h b/hw/bsp/hpmicro/boards/hpm6750evk2/pinmux.h new file mode 100644 index 000000000..460feded2 --- /dev/null +++ b/hw/bsp/hpmicro/boards/hpm6750evk2/pinmux.h @@ -0,0 +1,89 @@ + +/* + * Copyright (c) 2025 HPMicro + * + * SPDX-License-Identifier: BSD-3-Clause + * + * + * Automatically generated by HPM Pinmux Tool + * + * + * Note: + * PY and PZ IOs: if any SOC pin function needs to be routed to these IOs, + * besides of IOC, PIOC/BIOC needs to be configured SOC_GPIO_X_xx, so that + * expected SoC function can be enabled on these IOs. + */ + +#ifndef HPM_PINMUX_H +#define HPM_PINMUX_H + +#ifdef __cplusplus +extern "C" { +#endif + +void init_uart0_pins(void); +void init_uart2_pins(void); +void init_uart13_pins(void); +void init_puart_pins(void); +void init_uart13_pins_as_gpio(void); +void init_lcd0_pins(void); +void init_cap_pins(void); +void init_i2c0_pins_as_gpio(void); +void init_i2c0_pins(void); +void init_femc_pins(void); +void init_gpio_pins_with_pull_up(void); +void init_gpio_pins_using_gpio0(void); +void init_spi2_pins(void); +void init_spi2_pins_with_gpio_as_cs(void); +void init_gptmr3_pins(void); +void init_gptmr4_pins(void); +void init_gptmr5_pins(void); +void init_hall_trgm_pins(void); +void init_qei_trgm_pins(void); +void init_i2s0_pins(void); +void init_dao_pins(void); +void init_pdm_pins(void); +void init_vad_pins(void); +void init_cam_pins(void); +void init_butn_pins(void); +void init_acmp_pins(void); +void init_enet0_pins(void); +void init_enet1_pins(void); +void init_pwm2_pins(void); +void init_pwm3_pins(void); +void init_adc12_pins(void); +void init_adc16_pins(void); +void init_adc_bldc_pins(void); +void init_usb0_pins(void); +void init_usb1_pins(void); +void init_can0_pins(void); +void init_mcan0_transceiver_phy_pin(void); +void init_sdxc1_cmd_pin_enable_1v8_enable_opendrain(void); +void init_sdxc1_cmd_pin_enable_1v8_disable_opendrain(void); +void init_sdxc1_cmd_pin_disable_1v8_enable_opendrain(void); +void init_sdxc1_cmd_pin_disable_1v8_disable_opendrain(void); +void init_sdxc1_cd_pin(void); +void init_sdxc1_clk_data_pins_enable_1v8(void); +void init_sdxc1_clk_data_pins_disable_1v8(void); +void init_sdxc1_clk_data_pins_width4_enable_1v8(void); +void init_sdxc1_clk_data_pins_width4_disable_1v8(void); +void init_sdxc1_pwr_pin(void); +void init_clk_obs_pins(void); +void init_rgb_pwm_pins(void); +void init_led_pins_as_gpio(void); +void init_enet_pps_pins(void); +void init_enet_pps_capture_pins(void); +void init_tamper_pins(void); +void init_uart_break_signal_pin(void); +void init_gptmr3_channel_pin_as_output(void); +void init_gptmr4_channel_pin_as_capture(void); +void init_gptmr5_channel2_pin_as_output(void); +void init_gptmr5_channel3_pin_as_output(void); +void init_clk_ref_pin(void); +void init_brownout_indicate_pin(void); +void board_init_i2c_eeprom_pin(void); + +#ifdef __cplusplus +} +#endif +#endif /* HPM_PINMUX_H */ diff --git a/hw/bsp/hpmicro/family.c b/hw/bsp/hpmicro/family.c new file mode 100644 index 000000000..ffec2523a --- /dev/null +++ b/hw/bsp/hpmicro/family.c @@ -0,0 +1,115 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2018, hathach (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: + manufacturer: HPMicro +*/ + +#include "bsp/board_api.h" +#include "board.h" +#include "hpm_clock_drv.h" +#include "hpm_uart_drv.h" +#include "hpm_gpio_drv.h" +#include "hpm_romapi.h" + + +//--------------------------------------------------------------------+ +// Board porting API +//--------------------------------------------------------------------+ + +// Initialize on-board peripherals : led, button, uart and USB +void board_init(void) { + board_init_clock(); + board_init_pmp(); + + board_init_usb(HPM_USB0); +#ifdef HPM_USB1 + board_init_usb(HPM_USB1); +#endif + + board_init_console(); + board_init_gpio_pins(); + board_init_led_pins(); +} + +//--------------------------------------------------------------------+ +// USB Interrupt Handler +//--------------------------------------------------------------------+ +SDK_DECLARE_EXT_ISR_M(IRQn_USB0, isr_usb0) +void isr_usb0(void) { + tusb_int_handler(0, true); +} + +#ifdef HPM_USB1_BASE +SDK_DECLARE_EXT_ISR_M(IRQn_USB1, isr_usb1) +void isr_usb1(void) { + tusb_int_handler(1, true); +} +#endif + +void board_led_write(bool state) { + if (state) { + gpio_write_pin(BOARD_LED_GPIO_CTRL, BOARD_LED_GPIO_INDEX, BOARD_LED_GPIO_PIN, BOARD_LED_ON_LEVEL); + } else { + gpio_write_pin(BOARD_LED_GPIO_CTRL, BOARD_LED_GPIO_INDEX, BOARD_LED_GPIO_PIN, BOARD_LED_OFF_LEVEL); + } +} + +uint32_t board_button_read(void) { + return (gpio_read_pin(BOARD_APP_GPIO_CTRL, BOARD_APP_GPIO_INDEX, BOARD_APP_GPIO_PIN) == BOARD_BUTTON_PRESSED_VALUE) ? 1 : 0; +} + +// Get characters from UART. Return number of read bytes +int board_uart_read(uint8_t *buf, int len) { + int count = 0; + hpm_stat_t status; + + while (count < len) { + status = uart_try_receive_byte((UART_Type *)BOARD_CONSOLE_UART_BASE, (uint8_t *)&buf[count]); + if (status == status_success) { + count++; + } else { + break; + } + } + + return count; +} + +// Send characters to UART. Return number of sent bytes +int board_uart_write(void const *buf, int len) { + uart_send_data((UART_Type *)BOARD_CONSOLE_UART_BASE, (uint8_t const *)buf, len); + + return len; +} + +#if CFG_TUSB_OS == OPT_OS_NONE +// Get current milliseconds, must be implemented when no RTOS is used +uint32_t board_millis(void) { + return (hpm_csr_get_core_cycle() / clock_get_core_clock_ticks_per_ms()); +} + +#endif diff --git a/hw/bsp/hpmicro/family.cmake b/hw/bsp/hpmicro/family.cmake new file mode 100644 index 000000000..4500f326f --- /dev/null +++ b/hw/bsp/hpmicro/family.cmake @@ -0,0 +1,131 @@ +include_guard() + +set(SDK_DIR ${TOP}/hw/mcu/hpmicro/hpm_sdk) + +set(CROSS_COMPILE "riscv32-unknown-elf-") + +# include board specific +include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) + +# toolchain set up +if (NOT DEFINED CMAKE_SYSTEM_CPU) + set(CMAKE_SYSTEM_CPU rv32imac-ilp32 CACHE INTERNAL "System Processor") +endif () +set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/riscv_${TOOLCHAIN}.cmake) + +set(FAMILY_MCUS HPMIRCO CACHE INTERNAL "") + +#------------------------------------ +# Startup & Linker script +#------------------------------------ +if (NOT DEFINED LD_FILE_GNU) +set(LD_FILE_GNU ${HPM_SOC}/toolchains/gcc/flash_xip.ld) +endif () +set(LD_FILE_Clang ${LD_FILE_GNU}) + +set(STARTUP_FILE_GNU ${HPM_SOC}/toolchains/gcc/start.S) +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) + +#------------------------------------ +# Board Target +#------------------------------------ +function(family_add_board BOARD_TARGET) + add_library(${BOARD_TARGET} STATIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD}/board.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD}/pinmux.c + ${HPM_SOC}/boot/hpm_bootheader.c + ${HPM_SOC}/toolchains/gcc/initfini.c + ${HPM_SOC}/toolchains/reset.c + ${HPM_SOC}/toolchains/trap.c + ${HPM_SOC}/system.c + ${HPM_SOC}/hpm_sysctl_drv.c + ${HPM_SOC}/hpm_clock_drv.c + ${HPM_SOC}/hpm_otp_drv.c + ${SDK_DIR}/arch/riscv/l1c/hpm_l1c_drv.c + ${SDK_DIR}/drivers/src/hpm_gpio_drv.c + ${SDK_DIR}/drivers/src/hpm_uart_drv.c + ${SDK_DIR}/drivers/src/hpm_usb_drv.c + ${SDK_DIR}/drivers/src/hpm_pcfg_drv.c + ${SDK_DIR}/drivers/src/hpm_pmp_drv.c + ${SDK_DIR}/drivers/src/${HPM_PLLCTL_DRV_FILE} + ) + + target_compile_definitions(${BOARD_TARGET} PUBLIC + FLASH_XIP + [=[CFG_TUD_MEM_SECTION=__attribute__((section(".noncacheable.non_init")))]=] + [=[CFG_TUH_MEM_SECTION=__attribute__((section(".noncacheable.non_init")))]=] + ) + + target_include_directories(${BOARD_TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD}/board + ${HPM_SOC} + ${HPM_IP_REGS} + ${HPM_SOC}/boot + ${HPM_SOC}/toolchains + ${HPM_SOC}/toolchains/gcc + ${SDK_DIR}/arch + ${SDK_DIR}/arch/riscv/intc + ${SDK_DIR}/arch/riscv/l1c + ${SDK_DIR}/drivers/inc + ) + + update_board(${BOARD_TARGET}) +endfunction() + +#------------------------------------ +# Functions +#------------------------------------ +function(family_configure_example TARGET RTOS) + family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_HPM) + + target_sources(${TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${SDK_DIR}/utils/hpm_sbrk.c + ${TOP}/src/portable/chipidea/ci_hs/dcd_ci_hs.c + ${TOP}/src/portable/chipidea/ci_hs/hcd_ci_hs.c + ${TOP}/src/portable/ehci/ehci.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} + ) + target_include_directories(${TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} + ${TOP}/src/portable/chipidea/ci_hs + ) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -nostartfiles + --specs=nosys.specs --specs=nano.specs + -Wl,--defsym,_flash_size=${BOARD_FLASH_SIZE} + -Wl,--defsym,_stack_size=${BOARD_STACK_SIZE} + -Wl,--defsym,_heap_size=${BOARD_HEAP_SIZE} + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -Wl,--defsym,_flash_size=${BOARD_FLASH_SIZE} + -Wl,--defsym,_stack_size=${BOARD_STACK_SIZE} + -Wl,--defsym,_heap_size=${BOARD_HEAP_SIZE} + ) + endif () + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties( + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c + ${SDK_DIR}/utils/hpm_sbrk.c + PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes -Wno-cast-align -Wno-discarded-qualifiers" + ) + endif () + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) + + # Flashing + family_add_bin_hex(${TARGET}) + family_flash_jlink(${TARGET}) +endfunction() diff --git a/hw/bsp/hpmicro/family.mk b/hw/bsp/hpmicro/family.mk new file mode 100644 index 000000000..9721e2f7d --- /dev/null +++ b/hw/bsp/hpmicro/family.mk @@ -0,0 +1,76 @@ +SDK_DIR = hw/mcu/hpmicro/hpm_sdk + +CROSS_COMPILE ?= riscv32-unknown-elf- + +include $(TOP)/$(BOARD_PATH)/board.mk + +CPU_CORE ?= rv32imac-ilp32 + +# All source paths should be relative to the top level. +LD_FILE = $(HPM_SOC)/toolchains/gcc/flash_xip.ld + +CFLAGS += \ + -DFLASH_XIP \ + -DCFG_TUSB_MCU=OPT_MCU_HPM \ + -DCFG_TUD_MEM_SECTION='__attribute__((section(".noncacheable.non_init")))' \ + -DCFG_TUH_MEM_SECTION='__attribute__((section(".noncacheable.non_init")))' + +ifdef BOARD_TUD_RHPORT +CFLAGS += -DBOARD_TUD_RHPORT=$(BOARD_TUD_RHPORT) +CFLAGS += -DBOARD_TUD_MAX_SPEED=OPT_MODE_HIGH_SPEED +endif + +ifdef BOARD_TUH_RHPORT +CFLAGS += -DBOARD_TUH_RHPORT=$(BOARD_TUH_RHPORT) +CFLAGS += -DBOARD_TUH_MAX_SPEED=OPT_MODE_HIGH_SPEED +endif + +# mcu driver cause following warnings +CFLAGS += -Wno-error=cast-align -Wno-error=double-promotion -Wno-error=discarded-qualifiers \ + -Wno-error=undef -Wno-error=unused-parameter -Wno-error=redundant-decls + +LDFLAGS_GCC += \ + -nostartfiles \ + --specs=nosys.specs --specs=nano.specs + +LDFLAGS += -Wl,--defsym,_flash_size=$(BOARD_FLASH_SIZE) +LDFLAGS += -Wl,--defsym,_stack_size=$(BOARD_STACK_SIZE) +LDFLAGS += -Wl,--defsym,_heap_size=$(BOARD_HEAP_SIZE) + +SRC_C += \ + src/portable/chipidea/ci_hs/dcd_ci_hs.c \ + src/portable/chipidea/ci_hs/hcd_ci_hs.c \ + src/portable/ehci/ehci.c \ + ${BOARD_PATH}/board.c \ + ${BOARD_PATH}/pinmux.c \ + $(HPM_SOC)/boot/hpm_bootheader.c \ + $(HPM_SOC)/toolchains/gcc/initfini.c \ + $(HPM_SOC)/toolchains/reset.c \ + $(HPM_SOC)/toolchains/trap.c \ + $(HPM_SOC)/system.c \ + $(HPM_SOC)/hpm_sysctl_drv.c \ + $(HPM_SOC)/hpm_clock_drv.c \ + $(HPM_SOC)/hpm_otp_drv.c \ + $(SDK_DIR)/arch/riscv/l1c/hpm_l1c_drv.c \ + $(SDK_DIR)/utils/hpm_sbrk.c \ + $(SDK_DIR)/drivers/src/hpm_gpio_drv.c \ + $(SDK_DIR)/drivers/src/hpm_uart_drv.c \ + $(SDK_DIR)/drivers/src/hpm_usb_drv.c \ + $(SDK_DIR)/drivers/src/hpm_pcfg_drv.c \ + $(SDK_DIR)/drivers/src/hpm_pmp_drv.c \ + $(SDK_DIR)/drivers/src/$(HPM_PLLCTL_DRV_FILE) \ + +INC += \ + $(TOP)/$(BOARD_PATH) \ + $(TOP)/src/portable/chipidea/ci_hs \ + $(TOP)/$(HPM_SOC) \ + $(TOP)/$(HPM_IP_REGS) \ + $(TOP)/$(HPM_SOC)/boot \ + $(TOP)/$(HPM_SOC)/toolchains \ + $(TOP)/$(HPM_SOC)/toolchains/gcc \ + $(TOP)/$(SDK_DIR)/arch \ + $(TOP)/$(SDK_DIR)/arch/riscv/intc \ + $(TOP)/$(SDK_DIR)/arch/riscv/l1c \ + $(TOP)/$(SDK_DIR)/drivers/inc \ + +SRC_S += $(HPM_SOC)/toolchains/gcc/start.S diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index 1e773bf96..95fbc061f 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -653,6 +653,18 @@ #define TUP_USBIP_DWC2_AT32 #define TUP_DCD_ENDPOINT_MAX 8 +//--------------------------------------------------------------------+ +// HPMicro +//--------------------------------------------------------------------+ +#elif TU_CHECK_MCU(OPT_MCU_HPM) + #define TUP_USBIP_CHIPIDEA_HS + #define TUP_USBIP_EHCI + + #define TUP_DCD_ENDPOINT_MAX 16 + #define TUP_RHPORT_HIGHSPEED 1 + + #define TU_ATTR_FAST_FUNC __attribute__((section(".fast"))) + #endif //--------------------------------------------------------------------+ diff --git a/src/portable/chipidea/ci_hs/ci_hs_hpm.h b/src/portable/chipidea/ci_hs/ci_hs_hpm.h new file mode 100644 index 000000000..68211448c --- /dev/null +++ b/src/portable/chipidea/ci_hs/ci_hs_hpm.h @@ -0,0 +1,54 @@ +/* + * 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. + */ + +#ifndef _CI_HS_HPM_H_ +#define _CI_HS_HPM_H_ + +#include "ci_hs_type.h" +#include "hpm_soc.h" +#include "hpm_interrupt.h" +#include "hpm_usb_drv.h" + +static const ci_hs_controller_t _ci_controller[] = +{ + { .reg_base = HPM_USB0_BASE, .irqnum = IRQn_USB0}, + #ifdef HPM_USB1_BASE + { .reg_base = HPM_USB1_BASE, .irqnum = IRQn_USB1}, + #endif +}; + +#define CI_HS_REG(_port) ((ci_hs_regs_t*) _ci_controller[_port].reg_base) + +//------------- DCD -------------// +#define CI_DCD_INT_ENABLE(_p) intc_m_enable_irq (_ci_controller[_p].irqnum) +#define CI_DCD_INT_DISABLE(_p) intc_m_disable_irq(_ci_controller[_p].irqnum) + +//------------- HCD -------------// +#define CI_HCD_INT_ENABLE(_p) intc_m_enable_irq (_ci_controller[_p].irqnum) +#define CI_HCD_INT_DISABLE(_p) intc_m_disable_irq(_ci_controller[_p].irqnum) + + +#endif diff --git a/src/portable/chipidea/ci_hs/dcd_ci_hs.c b/src/portable/chipidea/ci_hs/dcd_ci_hs.c index 4a5e5c91f..00df434d8 100644 --- a/src/portable/chipidea/ci_hs/dcd_ci_hs.c +++ b/src/portable/chipidea/ci_hs/dcd_ci_hs.c @@ -55,6 +55,10 @@ bool dcd_dcache_clean_invalidate(void const* addr, uint32_t data_size) { // MCX N9 only port 1 use this controller #include "ci_hs_mcx.h" +#elif TU_CHECK_MCU(OPT_MCU_HPM) + + #include "ci_hs_hpm.h" + #else #error "Unsupported MCUs" #endif @@ -230,6 +234,10 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { TU_ASSERT(ci_ep_count(dcd_reg) <= TUP_DCD_ENDPOINT_MAX); +#if TU_CHECK_MCU(OPT_MCU_HPM) + usb_phy_init((USB_Type *)dcd_reg, false); +#endif + // Reset controller dcd_reg->USBCMD |= USBCMD_RESET; while( dcd_reg->USBCMD & USBCMD_RESET ) {} @@ -246,7 +254,11 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { #endif #if !TUD_OPT_HIGH_SPEED - dcd_reg->PORTSC1 = PORTSC1_FORCE_FULL_SPEED; + dcd_reg->PORTSC1 |= PORTSC1_FORCE_FULL_SPEED; +#endif + +#if TU_CHECK_MCU(OPT_MCU_HPM) + dcd_reg->PORTSC1 &= ~USB_PORTSC1_STS_MASK; #endif dcd_dcache_clean_invalidate(&_dcd_data, sizeof(dcd_data_t)); diff --git a/src/portable/chipidea/ci_hs/hcd_ci_hs.c b/src/portable/chipidea/ci_hs/hcd_ci_hs.c index b5324a754..922d32989 100644 --- a/src/portable/chipidea/ci_hs/hcd_ci_hs.c +++ b/src/portable/chipidea/ci_hs/hcd_ci_hs.c @@ -61,6 +61,10 @@ bool hcd_dcache_clean_invalidate(void const* addr, uint32_t data_size) { #include "ci_hs_lpc18_43.h" +#elif TU_CHECK_MCU(OPT_MCU_HPM) + +#include "ci_hs_hpm.h" + #else #error "Unsupported MCUs" #endif @@ -77,6 +81,10 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { (void) rh_init; ci_hs_regs_t *hcd_reg = CI_HS_REG(rhport); +#if CFG_TUSB_MCU == OPT_MCU_HPM + usb_phy_init((USB_Type *)hcd_reg, true); +#endif + // Reset controller hcd_reg->USBCMD |= USBCMD_RESET; while ( hcd_reg->USBCMD & USBCMD_RESET ) {} diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c index c33c970e4..0d6f5ef12 100644 --- a/src/portable/ehci/ehci.c +++ b/src/portable/ehci/ehci.c @@ -44,6 +44,10 @@ #include "fsl_device_registers.h" #endif +#if TU_CHECK_MCU(OPT_MCU_HPM) +#include "ci_hs_hpm.h" +#endif + //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ @@ -237,6 +241,14 @@ void hcd_port_reset(uint8_t rhport) { // mask out Write-1-to-Clear bits uint32_t portsc = regs->portsc & ~EHCI_PORTSC_MASK_W1C; +#if TU_CHECK_MCU(OPT_MCU_HPM) + if (usb_phy_get_line_state((USB_Type *)CI_HS_REG(rhport)) == usb_line_state2) { + portsc |= USB_PORTSC1_STS_MASK; + } else { + portsc &= ~USB_PORTSC1_STS_MASK; + } +#endif + // EHCI Table 2-16 PortSC // when software writes Port Reset bit to a one, it must also write a zero to the Port Enable bit. portsc &= ~(EHCI_PORTSC_MASK_PORT_EANBLED); diff --git a/src/tusb_option.h b/src/tusb_option.h index 1dc920d84..cd131c119 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -216,6 +216,9 @@ #define OPT_MCU_AT32F425 2505 ///< ArteryTek AT32F425 #define OPT_MCU_AT32F413 2506 ///< ArteryTek AT32F413 +// HPMicro +#define OPT_MCU_HPM 2600 ///< HPMicro + // Check if configured MCU is one of listed // Apply TU_MCU_IS_EQUAL with || as separator to list of input #define TU_MCU_IS_EQUAL(_m) (CFG_TUSB_MCU == (_m)) diff --git a/tools/get_deps.py b/tools/get_deps.py index b1b50d319..42ead17ff 100755 --- a/tools/get_deps.py +++ b/tools/get_deps.py @@ -244,6 +244,9 @@ deps_optional = { 'hw/mcu/artery/at32f413': ['https://github.com/ArteryTek/AT32F413_Firmware_Library.git', 'f6fe62dfec9fd40c5b63d92fc5ef2c2b5e77a450', 'at32f413'], + 'hw/mcu/hpmicro/hpm_sdk': ['https://github.com/hpmicro/hpm_sdk', + '8d2af741ecc4aaa82d7ee395dc1ce25d7070c3ff', + 'hpm_sdk hpmicro hpm6750 hpm6300 hpm6200 hpm6800 hpm5300 hpm6e00 hpm5e00'], '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 ' -- cgit v1.3.1 From 239e20ba7399fc026325c4cd8c98c08a160a9773 Mon Sep 17 00:00:00 2001 From: zhiqiang-ch Date: Tue, 30 Dec 2025 10:44:03 +0800 Subject: support for the AT32F45X series --- README.rst | 3 +- docs/reference/boards.rst | 3 + docs/reference/dependencies.rst | 1 + hw/bsp/at32f45x/FreeRTOSConfig/FreeRTOSConfig.h | 177 ++++++++++++++++ hw/bsp/at32f45x/at32f45x_clock.c | 114 ++++++++++ hw/bsp/at32f45x/at32f45x_clock.h | 45 ++++ hw/bsp/at32f45x/at32f45x_conf.h | 174 +++++++++++++++ hw/bsp/at32f45x/at32f45x_int.c | 101 +++++++++ hw/bsp/at32f45x/at32f45x_int.h | 60 ++++++ hw/bsp/at32f45x/boards/at_start_f455/board.cmake | 8 + hw/bsp/at32f45x/boards/at_start_f455/board.h | 96 +++++++++ hw/bsp/at32f45x/boards/at_start_f455/board.mk | 7 + hw/bsp/at32f45x/boards/at_start_f456/board.cmake | 8 + hw/bsp/at32f45x/boards/at_start_f456/board.h | 96 +++++++++ hw/bsp/at32f45x/boards/at_start_f456/board.mk | 7 + hw/bsp/at32f45x/boards/at_start_f457/board.cmake | 8 + hw/bsp/at32f45x/boards/at_start_f457/board.h | 96 +++++++++ hw/bsp/at32f45x/boards/at_start_f457/board.mk | 7 + hw/bsp/at32f45x/family.c | 258 +++++++++++++++++++++++ hw/bsp/at32f45x/family.cmake | 97 +++++++++ hw/bsp/at32f45x/family.mk | 40 ++++ src/common/tusb_mcu.h | 5 + src/portable/synopsys/dwc2/dwc2_at32.h | 5 + src/tusb_option.h | 1 + tools/get_deps.py | 3 + 25 files changed, 1419 insertions(+), 1 deletion(-) create mode 100644 hw/bsp/at32f45x/FreeRTOSConfig/FreeRTOSConfig.h create mode 100644 hw/bsp/at32f45x/at32f45x_clock.c create mode 100644 hw/bsp/at32f45x/at32f45x_clock.h create mode 100644 hw/bsp/at32f45x/at32f45x_conf.h create mode 100644 hw/bsp/at32f45x/at32f45x_int.c create mode 100644 hw/bsp/at32f45x/at32f45x_int.h create mode 100644 hw/bsp/at32f45x/boards/at_start_f455/board.cmake create mode 100644 hw/bsp/at32f45x/boards/at_start_f455/board.h create mode 100644 hw/bsp/at32f45x/boards/at_start_f455/board.mk create mode 100644 hw/bsp/at32f45x/boards/at_start_f456/board.cmake create mode 100644 hw/bsp/at32f45x/boards/at_start_f456/board.h create mode 100644 hw/bsp/at32f45x/boards/at_start_f456/board.mk create mode 100644 hw/bsp/at32f45x/boards/at_start_f457/board.cmake create mode 100644 hw/bsp/at32f45x/boards/at_start_f457/board.h create mode 100644 hw/bsp/at32f45x/boards/at_start_f457/board.mk create mode 100644 hw/bsp/at32f45x/family.c create mode 100644 hw/bsp/at32f45x/family.cmake create mode 100644 hw/bsp/at32f45x/family.mk (limited to 'src/portable') diff --git a/README.rst b/README.rst index 178a084ce..29b2f4fca 100644 --- a/README.rst +++ b/README.rst @@ -141,7 +141,8 @@ Supported CPUs +--------------+-----------------------------+--------+------+-----------+------------------------+--------------------+ | Artery AT32 | F403a_407, F413 | ✔ | | | fsdev | Packet SRAM 512 | | +-----------------------------+--------+------+-----------+------------------------+--------------------+ -| | F415, F435_437, F423, F425 | ✔ | ✔ | | dwc2 | | +| | F415, F435_437, F423, | ✔ | ✔ | | dwc2 | | +| | F425, F45x | | | | | | | +-----------------------------+--------+------+-----------+------------------------+--------------------+ | | F402_F405 | ✔ | ✔ | ✔ | dwc2 | F405 is HS | +--------------+-----------------------------+--------+------+-----------+------------------------+--------------------+ diff --git a/docs/reference/boards.rst b/docs/reference/boards.rst index 12da5c90b..cacf52e1a 100644 --- a/docs/reference/boards.rst +++ b/docs/reference/boards.rst @@ -44,6 +44,9 @@ at_start_f423 AT-START-F423 at32f423 https:/ 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 +at_start_f455 AT-START-F455 at32f45x https://www.arterychip.com/en/product/AT32F455.jsp +at_start_f456 AT-START-F456 at32f45x https://www.arterychip.com/en/product/AT32F456.jsp +at_start_f457 AT-START-F457 at32f45x https://www.arterychip.com/en/product/AT32F457.jsp ========================= ============================= ============= ==================================================== ====== Bridgetek diff --git a/docs/reference/dependencies.rst b/docs/reference/dependencies.rst index de1603383..ce5f265d5 100644 --- a/docs/reference/dependencies.rst +++ b/docs/reference/dependencies.rst @@ -16,6 +16,7 @@ hw/mcu/artery/at32f415 https://github.com/ArteryTek/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/artery/at32f45x https://github.com/ArteryTek/AT32F45x_Firmware_Library.git 3d4a1b38be8ebac292e2350ca53bc4bfa4430233 at32f45x 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 diff --git a/hw/bsp/at32f45x/FreeRTOSConfig/FreeRTOSConfig.h b/hw/bsp/at32f45x/FreeRTOSConfig/FreeRTOSConfig.h new file mode 100644 index 000000000..8a9906d39 --- /dev/null +++ b/hw/bsp/at32f45x/FreeRTOSConfig/FreeRTOSConfig.h @@ -0,0 +1,177 @@ +/* + * 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 MCU header + #include "at32f45x.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 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 + +#ifdef __RX__ +/* Renesas RX series */ +#define vSoftwareInterruptISR INT_Excep_ICU_SWINT +#define vTickISR INT_Excep_CMT0_CMI0 +#define configPERIPHERAL_CLOCK_HZ (configCPU_CLOCK_HZ/2) +#define configKERNEL_INTERRUPT_PRIORITY 1 +#define configMAX_SYSCALL_INTERRUPT_PRIORITY 4 + +#else + +/* FreeRTOS hooks to NVIC vectors */ +#define xPortPendSVHandler PendSV_Handler +#define xPortSysTickHandler SysTick_Handler +#define vPortSVCHandler SVC_Handler + +//--------------------------------------------------------------------+ +// Interrupt nesting behavior configuration. +//--------------------------------------------------------------------+ +#if defined(__NVIC_PRIO_BITS) + // For Cortex-M specific: __NVIC_PRIO_BITS is defined in core_cmx.h + #define configPRIO_BITS __NVIC_PRIO_BITS + +#elif defined(__ECLIC_INTCTLBITS) + // RISC-V Bumblebee core from nuclei + #define configPRIO_BITS __ECLIC_INTCTLBITS + +#elif defined(__IASMARM__) + // FIXME: IAR Assembler cannot include mcu header directly to get __NVIC_PRIO_BITS. + // Therefore we will hard coded it to minimum value of 2 to get pass ci build. + // IAR user must update this to correct value of the target MCU + #message "configPRIO_BITS is hard coded to 2 to pass IAR build only. User should update it per MCU" + #define configPRIO_BITS 2 + +#else + #error "FreeRTOS configPRIO_BITS to be defined" +#endif + +/* The lowest interrupt priority that can be used in a call to a "set priority" function. */ +#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1<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++; +} + +uint32_t board_millis(void) { + return system_ticks; +} + +void SVC_Handler(void) { +} + +void PendSV_Handler(void) { +} +#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); +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) */ + /* USER CODE END 6 */ +} +#endif /* USE_FULL_ASSERT */ diff --git a/hw/bsp/at32f45x/family.cmake b/hw/bsp/at32f45x/family.cmake new file mode 100644 index 000000000..fe13347af --- /dev/null +++ b/hw/bsp/at32f45x/family.cmake @@ -0,0 +1,97 @@ +include_guard() + +set(AT32_FAMILY at32f45x) +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 "") + +#------------------------------------ +# 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) + +#------------------------------------ +# BOARD_TARGET +#------------------------------------ +function(family_add_board BOARD_TARGET) + 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 + ) + 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}) +endfunction() + +#------------------------------------ +# Functions +#------------------------------------ +function(family_configure_example TARGET RTOS) + family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_${AT32_FAMILY_UPPER}) + + target_sources(${TARGET} PUBLIC + ${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 + ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c + ${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c + ${TOP}/src/portable/synopsys/dwc2/dwc2_common.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} + ) + target_include_directories(${TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} + ) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -nostartfiles + --specs=nosys.specs --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_Clang}" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () + + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) + + # Flashing + family_add_bin_hex(${TARGET}) + family_flash_jlink(${TARGET}) +endfunction() diff --git a/hw/bsp/at32f45x/family.mk b/hw/bsp/at32f45x/family.mk new file mode 100644 index 000000000..e42f27557 --- /dev/null +++ b/hw/bsp/at32f45x/family.mk @@ -0,0 +1,40 @@ +AT32_FAMILY = at32f45x +AT32_SDK_LIB = hw/mcu/artery/${AT32_FAMILY}/libraries + +include $(TOP)/$(BOARD_PATH)/board.mk + +CPU_CORE ?= cortex-m4 + +CFLAGS_GCC += \ + -flto + +CFLAGS += \ + -DCFG_TUSB_MCU=OPT_MCU_AT32F45X \ + +LDFLAGS_GCC += \ + -flto --specs=nosys.specs -nostdlib -nostartfiles + +SRC_C += \ + src/portable/synopsys/dwc2/dcd_dwc2.c \ + src/portable/synopsys/dwc2/hcd_dwc2.c \ + src/portable/synopsys/dwc2/dwc2_common.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)/$(AT32_SDK_LIB)/drivers/inc \ + $(TOP)/$(AT32_SDK_LIB)/cmsis/cm4/core_support \ + $(TOP)/$(AT32_SDK_LIB)/cmsis/cm4/device_support + +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 + +flash: flash-atlink diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index 55f7e0b7c..ce690acb8 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -661,6 +661,11 @@ #define TUP_USBIP_DWC2_AT32 #define TUP_DCD_ENDPOINT_MAX 8 +#elif TU_CHECK_MCU(OPT_MCU_AT32F45X) + #define TUP_USBIP_DWC2 + #define TUP_USBIP_DWC2_AT32 + #define TUP_DCD_ENDPOINT_MAX 8 + //--------------------------------------------------------------------+ // HPMicro //--------------------------------------------------------------------+ diff --git a/src/portable/synopsys/dwc2/dwc2_at32.h b/src/portable/synopsys/dwc2/dwc2_at32.h index 513495eb1..10824ae92 100644 --- a/src/portable/synopsys/dwc2/dwc2_at32.h +++ b/src/portable/synopsys/dwc2/dwc2_at32.h @@ -61,6 +61,11 @@ #define OTG1_FIFO_SIZE 1280 #define OTG1_IRQn OTGFS1_IRQn #define DWC2_OTG1_REG_BASE 0x50000000UL +#elif CFG_TUSB_MCU == OPT_MCU_AT32F45X + #include + #define OTG1_FIFO_SIZE 1280 + #define OTG1_IRQn OTGFS1_IRQn + #define DWC2_OTG1_REG_BASE 0x50000000UL #endif #ifdef __cplusplus diff --git a/src/tusb_option.h b/src/tusb_option.h index 64fe899db..35a0d97db 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -216,6 +216,7 @@ #define OPT_MCU_AT32F402_405 2504 ///< ArteryTek AT32F402_405 #define OPT_MCU_AT32F425 2505 ///< ArteryTek AT32F425 #define OPT_MCU_AT32F413 2506 ///< ArteryTek AT32F413 +#define OPT_MCU_AT32F45X 2507 ///< ArteryTek AT32F45x // HPMicro #define OPT_MCU_HPM 2600 ///< HPMicro diff --git a/tools/get_deps.py b/tools/get_deps.py index deacbb23b..773445adc 100755 --- a/tools/get_deps.py +++ b/tools/get_deps.py @@ -244,6 +244,9 @@ deps_optional = { 'hw/mcu/artery/at32f413': ['https://github.com/ArteryTek/AT32F413_Firmware_Library.git', 'f6fe62dfec9fd40c5b63d92fc5ef2c2b5e77a450', 'at32f413'], + 'hw/mcu/artery/at32f45x': ['https://github.com/ArteryTek/AT32F45x_Firmware_Library.git', + '3d4a1b38be8ebac292e2350ca53bc4bfa4430233', + 'at32f45x'], 'hw/mcu/hpmicro/hpm_sdk': ['https://github.com/hpmicro/hpm_sdk', '8d2af741ecc4aaa82d7ee395dc1ce25d7070c3ff', 'hpmicro'], -- cgit v1.3.1 From 4e4398898040118969421dc236ec8f453f9b503d Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 30 Dec 2025 18:09:54 +0700 Subject: tusb_fifo remove item_size make it fifo of bytes --- src/class/audio/audio_device.c | 12 +-- src/common/tusb_fifo.c | 139 +++++++++++++++------------------- src/common/tusb_fifo.h | 39 +++++----- src/common/tusb_verify.h | 10 ++- src/osal/osal_none.h | 16 ++-- src/osal/osal_pico.h | 54 +++++++------ src/portable/synopsys/dwc2/dcd_dwc2.c | 17 ++--- src/tusb.c | 2 +- src/tusb_option.h | 1 + test/unit-test/project.yml | 1 + test/unit-test/test/test_fifo.c | 36 +-------- 11 files changed, 140 insertions(+), 187 deletions(-) (limited to 'src/portable') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 55eba81dd..be0224811 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -674,17 +674,17 @@ void audiod_init(void) { switch (i) { #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); + tu_fifo_config(&audio->ep_in_ff, ep_in_sw_buf.buf_1, CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ, true); 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); + tu_fifo_config(&audio->ep_in_ff, ep_in_sw_buf.buf_2, CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ, true); 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); + tu_fifo_config(&audio->ep_in_ff, ep_in_sw_buf.buf_3, CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ, true); break; #endif } @@ -716,17 +716,17 @@ void audiod_init(void) { switch (i) { #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); + tu_fifo_config(&audio->ep_out_ff, ep_out_sw_buf.buf_1, CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ, true); 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); + tu_fifo_config(&audio->ep_out_ff, ep_out_sw_buf.buf_2, CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ, true); 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); + tu_fifo_config(&audio->ep_out_ff, ep_out_sw_buf.buf_3, CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ, true); break; #endif } diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 450c31f57..7822b7aae 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -59,7 +59,7 @@ TU_ATTR_ALWAYS_INLINE static inline void ff_unlock(osal_mutex_t mutex) { //--------------------------------------------------------------------+ // Setup API //--------------------------------------------------------------------+ -bool tu_fifo_config(tu_fifo_t *f, void *buffer, uint16_t depth, uint16_t item_size, bool overwritable) { +bool tu_fifo_config(tu_fifo_t *f, void *buffer, uint16_t depth, bool overwritable) { // Limit index space to 2*depth - this allows for a fast "modulo" calculation // but limits the maximum depth to 2^16/2 = 2^15 and buffer overflows are detectable // only if overflow happens once (important for unsupervised DMA applications) @@ -72,7 +72,6 @@ bool tu_fifo_config(tu_fifo_t *f, void *buffer, uint16_t depth, uint16_t item_si f->buffer = (uint8_t *)buffer; f->depth = depth; - f->item_size = (uint16_t)(item_size & 0x7FFFu); f->overwritable = overwritable; f->rd_idx = 0u; f->wr_idx = 0u; @@ -130,7 +129,10 @@ enum { }; // Copy to fifo from fixed address buffer (usually a rx register) with TU_FIFO_FIXED_ADDR_RW32 mode -static void ff_push_fixed_addr(uint8_t *ff_buf, const volatile fixed_access_item_t *reg_rx, uint16_t len) { +static void ff_push_access_mode(uint8_t *ff_buf, const volatile fixed_access_item_t *reg_rx, uint16_t len, + uint8_t data_stride, uint8_t addr_stride) { + (void)data_stride; + (void)addr_stride; // Reading full available 16/32-bit data from const app address uint16_t n_items = len / sizeof(fixed_access_item_t); while (n_items--) { @@ -167,86 +169,70 @@ static void ff_pull_fixed_addr(volatile fixed_access_item_t *reg_tx, const uint8 #endif // send n items to fifo WITHOUT updating write pointer -static void ff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uint16_t wr_ptr, - tu_fifo_access_mode_t copy_mode) { - const uint16_t lin_count = f->depth - wr_ptr; - const uint16_t wrap_count = n - lin_count; - - uint16_t lin_bytes = lin_count * f->item_size; - uint16_t wrap_bytes = wrap_count * f->item_size; - - // current buffer of fifo - uint8_t *ff_buf = f->buffer + (wr_ptr * f->item_size); - - switch (copy_mode) { - case TU_FIFO_INC_ADDR_RW8: - if (n <= lin_count) { - // Linear only - memcpy(ff_buf, app_buf, n * f->item_size); +static void ff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uint16_t wr_ptr, uint8_t data_stride, + uint8_t addr_stride) { + uint16_t lin_bytes = f->depth - wr_ptr; + uint16_t wrap_bytes = n - lin_bytes; + uint8_t *ff_buf = f->buffer + wr_ptr; + +#if CFG_TUSB_FIFO_MULTI_BYTES_ACCESS + if (data_stride > 1) { + const volatile fixed_access_item_t *reg_rx = (volatile const fixed_access_item_t *)app_buf; + if (n <= lin_bytes) { + // Linear only + ff_push_access_mode(ff_buf, reg_rx, n, data_stride, addr_stride); + } else { + // Wrap around + + // Write full words to linear part of buffer + uint16_t lin_nitems_bytes = lin_bytes & ~FIXED_ACCESS_REMAINDER_MASK; + ff_push_access_mode(ff_buf, reg_rx, lin_nitems_bytes, data_stride, addr_stride); + ff_buf += lin_nitems_bytes; + + // There could be odd 1 byte (16bit) or 1-3 bytes (32bit) before the wrap-around boundary + const uint8_t rem = lin_bytes & FIXED_ACCESS_REMAINDER_MASK; + if (rem > 0) { + const uint8_t remrem = (uint8_t)tu_min16(wrap_bytes, sizeof(fixed_access_item_t) - rem); + const fixed_access_item_t tmp = *reg_rx; + tu_scatter_write32(tmp, ff_buf, rem, f->buffer, remrem); + + wrap_bytes -= remrem; + ff_buf = f->buffer + remrem; // wrap around } else { - // Wrap around - memcpy(ff_buf, app_buf, lin_bytes); // linear part - memcpy(f->buffer, ((const uint8_t *)app_buf) + lin_bytes, wrap_bytes); // wrapped part + ff_buf = f->buffer; // wrap around to beginning } - break; -#if CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_WIDTH - case TU_FIFO_FIXED_ADDR_RW32: { - const volatile fixed_access_item_t *reg_rx = (volatile const fixed_access_item_t *)app_buf; - if (n <= lin_count) { - // Linear only - ff_push_fixed_addr(ff_buf, reg_rx, n * f->item_size); - } else { - // Wrap around - - // Write full words to linear part of buffer - uint16_t lin_nitems_bytes = lin_bytes & ~FIXED_ACCESS_REMAINDER_MASK; - ff_push_fixed_addr(ff_buf, reg_rx, lin_nitems_bytes); - ff_buf += lin_nitems_bytes; - - // There could be odd 1 byte (16bit) or 1-3 bytes (32bit) before the wrap-around boundary - const uint8_t rem = lin_bytes & FIXED_ACCESS_REMAINDER_MASK; - if (rem > 0) { - const uint8_t remrem = (uint8_t)tu_min16(wrap_bytes, sizeof(fixed_access_item_t) - rem); - const fixed_access_item_t tmp = *reg_rx; - tu_scatter_write32(tmp, ff_buf, rem, f->buffer, remrem); - - wrap_bytes -= remrem; - ff_buf = f->buffer + remrem; // wrap around - } else { - ff_buf = f->buffer; // wrap around to beginning - } - - // Write data wrapped part - if (wrap_bytes > 0) { - ff_push_fixed_addr(ff_buf, reg_rx, wrap_bytes); - } + // Write data wrapped part + if (wrap_bytes > 0) { + ff_push_access_mode(ff_buf, reg_rx, wrap_bytes, data_stride, addr_stride); } - break; } + } else #endif - - default: - break; // unknown mode + { + // single byte access + if (n <= lin_bytes) { + // Linear only + memcpy(ff_buf, app_buf, n); + } else { + // Wrap around + memcpy(ff_buf, app_buf, lin_bytes); // linear part + memcpy(f->buffer, ((const uint8_t *)app_buf) + lin_bytes, wrap_bytes); // wrapped part + } } } // get n items from fifo WITHOUT updating read pointer static void ff_pull_n(const tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t rd_ptr, tu_fifo_access_mode_t copy_mode) { - const uint16_t lin_count = f->depth - rd_ptr; - const uint16_t wrap_count = n - lin_count; // only used if wrapped - - uint16_t lin_bytes = lin_count * f->item_size; - uint16_t wrap_bytes = wrap_count * f->item_size; - - // current buffer of fifo - const uint8_t *ff_buf = f->buffer + (rd_ptr * f->item_size); + uint16_t lin_bytes = f->depth - rd_ptr; + uint16_t wrap_bytes = n - lin_bytes; // only used if wrapped + const uint8_t *ff_buf = f->buffer + rd_ptr; switch (copy_mode) { case TU_FIFO_INC_ADDR_RW8: - if (n <= lin_count) { + if (n <= lin_bytes) { // Linear only - memcpy(app_buf, ff_buf, n * f->item_size); + memcpy(app_buf, ff_buf, n); } else { // Wrap around memcpy(app_buf, ff_buf, lin_bytes); // linear part @@ -258,9 +244,9 @@ static void ff_pull_n(const tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t rd case TU_FIFO_FIXED_ADDR_RW32: { volatile fixed_access_item_t *reg_tx = (volatile fixed_access_item_t *)app_buf; - if (n <= lin_count) { + if (n <= lin_bytes) { // Linear only - ff_pull_fixed_addr(reg_tx, ff_buf, n * f->item_size); + ff_pull_fixed_addr(reg_tx, ff_buf, n); } else { // Wrap around case @@ -389,7 +375,8 @@ uint16_t tu_fifo_read_n_access_mode(tu_fifo_t *f, void *buffer, uint16_t n, tu_f } // Write n items to fifo with access mode -uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n, tu_fifo_access_mode_t access_mode) { +uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n, uint8_t data_stride, + uint8_t addr_stride) { if (n == 0) { return 0; } @@ -415,8 +402,8 @@ uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n, // function! Since it would end up in a race condition with read functions! if (n >= f->depth) { // Only copy last part - if (access_mode == TU_FIFO_INC_ADDR_RW8) { - buf8 += (n - f->depth) * f->item_size; + if (data_stride == TU_FIFO_INC_ADDR_RW8) { + buf8 += (n - f->depth); } else { // TODO should read from hw fifo to discard data, however reading an odd number could // accidentally discard data. @@ -451,7 +438,7 @@ uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n, const uint16_t wr_ptr = idx2ptr(f->depth, wr_idx); TU_LOG(TU_FIFO_DBG, "actual_n = %u, wr_ptr = %u", n, wr_ptr); - ff_push_n(f, buf8, n, wr_ptr, access_mode); + ff_push_n(f, buf8, n, wr_ptr, data_stride, addr_stride); f->wr_idx = advance_index(f->depth, wr_idx, n); TU_LOG(TU_FIFO_DBG, "\tnew_wr = %u\r\n", f->wr_idx); @@ -491,7 +478,7 @@ static bool ff_peek_local(tu_fifo_t *f, void *buf, uint16_t wr_idx, uint16_t rd_ } const uint16_t rd_ptr = idx2ptr(f->depth, rd_idx); - memcpy(buf, f->buffer + (rd_ptr * f->item_size), f->item_size); + memcpy(buf, f->buffer + rd_ptr, 1); return true; } @@ -526,7 +513,7 @@ bool tu_fifo_write(tu_fifo_t *f, const void *data) { ret = false; } else { const uint16_t wr_ptr = idx2ptr(f->depth, wr_idx); - memcpy(f->buffer + (wr_ptr * f->item_size), data, f->item_size); + memcpy(f->buffer + wr_ptr, data, 1); f->wr_idx = advance_index(f->depth, wr_idx, 1); ret = true; } diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index f58cc3fcb..b48cf4cea 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -58,6 +58,9 @@ extern "C" { #define CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_WIDTH 0 #endif +#ifndef CFG_TUSB_FIFO_MULTI_BYTES_ACCESS + #define CFG_TUSB_FIFO_MULTI_BYTES_ACCESS 0 +#endif /* Write/Read "pointer" is in the range of: 0 .. depth - 1, and is used to get the fifo data. * Write/Read "index" is always in the range of: 0 .. 2*depth-1 @@ -118,13 +121,9 @@ extern "C" { typedef struct { uint8_t *buffer; // buffer pointer uint16_t depth; // max items + bool overwritable; // ovwerwritable when full - struct TU_ATTR_PACKED { - uint16_t item_size : 15; // size of each item - bool overwritable : 1; // ovwerwritable when full - }; - - volatile uint16_t wr_idx; // write index + volatile uint16_t wr_idx; // write index TODO maybe can drop volatile volatile uint16_t rd_idx; // read index #if OSAL_MUTEX_REQUIRED @@ -141,17 +140,16 @@ typedef struct { } linear, wrapped; } tu_fifo_buffer_info_t; -#define TU_FIFO_INIT(_buffer, _depth, _type, _overwritable) \ - { \ - .buffer = _buffer, \ - .depth = _depth, \ - .item_size = sizeof(_type), \ - .overwritable = _overwritable, \ +#define TU_FIFO_INIT(_buffer, _depth, _overwritable) \ + { \ + .buffer = _buffer, \ + .depth = _depth, \ + .overwritable = _overwritable, \ } -#define TU_FIFO_DEF(_name, _depth, _type, _overwritable) \ - uint8_t _name##_buf[_depth*sizeof(_type)]; \ - tu_fifo_t _name = TU_FIFO_INIT(_name##_buf, _depth, _type, _overwritable) +#define TU_FIFO_DEF(_name, _depth, _overwritable) \ + uint8_t _name##_buf[_depth]; \ + tu_fifo_t _name = TU_FIFO_INIT(_name##_buf, _depth, _overwritable) // Write modes intended to allow special read and write functions to be able to // copy data to and from USB hardware FIFOs as needed for e.g. STM32s and others @@ -163,7 +161,7 @@ typedef enum { //--------------------------------------------------------------------+ // Setup API //--------------------------------------------------------------------+ -bool tu_fifo_config(tu_fifo_t *f, void *buffer, uint16_t depth, uint16_t item_size, bool overwritable); +bool tu_fifo_config(tu_fifo_t *f, void *buffer, uint16_t depth, bool overwritable); void tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable); void tu_fifo_clear(tu_fifo_t *f); @@ -223,14 +221,11 @@ uint16_t tu_fifo_discard_n(tu_fifo_t *f, uint16_t n); //--------------------------------------------------------------------+ // Write API //--------------------------------------------------------------------+ -uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n, tu_fifo_access_mode_t access_mode); +uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n, uint8_t data_stride, + uint8_t addr_stride); bool tu_fifo_write(tu_fifo_t *f, const void *data); TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_write_n(tu_fifo_t *f, const void *data, uint16_t n) { - return tu_fifo_write_n_access_mode(f, data, n, TU_FIFO_INC_ADDR_RW8); -} - -TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_write_n_fixed_addr(tu_fifo_t *f, const void *data, uint16_t n) { - return tu_fifo_write_n_access_mode(f, data, n, TU_FIFO_FIXED_ADDR_RW32); + return tu_fifo_write_n_access_mode(f, data, n, 1, 1); } //--------------------------------------------------------------------+ diff --git a/src/common/tusb_verify.h b/src/common/tusb_verify.h index 587554e7f..c9e06361c 100644 --- a/src/common/tusb_verify.h +++ b/src/common/tusb_verify.h @@ -96,10 +96,12 @@ * - TU_VERIFY_1ARGS : return false if failed * - TU_VERIFY_2ARGS : return provided value if failed *------------------------------------------------------------------*/ -#define TU_VERIFY_DEFINE(_cond, _ret) \ - do { \ - if (!(_cond)) { return _ret; } \ - } while(0) +#define TU_VERIFY_DEFINE(_cond, _ret) \ + do { \ + if (!(_cond)) { \ + return _ret; \ + } \ + } while (0) #define TU_VERIFY_1ARGS(_cond) TU_VERIFY_DEFINE(_cond, false) #define TU_VERIFY_2ARGS(_cond, _ret) TU_VERIFY_DEFINE(_cond, _ret) diff --git a/src/osal/osal_none.h b/src/osal/osal_none.h index aa6111a16..6ab18ace8 100644 --- a/src/osal/osal_none.h +++ b/src/osal/osal_none.h @@ -157,18 +157,18 @@ TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hd typedef struct { void (* interrupt_set)(bool enabled); + uint16_t item_size; tu_fifo_t ff; } osal_queue_def_t; typedef osal_queue_def_t* osal_queue_t; // _int_set is used as mutex in OS NONE (disable/enable USB ISR) -#define OSAL_QUEUE_DEF(_int_set, _name, _depth, _type) \ - uint8_t _name##_buf[_depth*sizeof(_type)]; \ - osal_queue_def_t _name = { \ - .interrupt_set = _int_set, \ - .ff = TU_FIFO_INIT(_name##_buf, _depth, _type, false) \ - } +#define OSAL_QUEUE_DEF(_int_set, _name, _depth, _type) \ + uint8_t _name##_buf[_depth * sizeof(_type)]; \ + osal_queue_def_t _name = {.interrupt_set = _int_set, \ + .item_size = sizeof(_type), \ + .ff = TU_FIFO_INIT(_name##_buf, _depth * sizeof(_type), false)} TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) { tu_fifo_clear(&qdef->ff); @@ -184,7 +184,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, v (void) msec; // not used, always behave as msec = 0 qhdl->interrupt_set(false); - const bool success = tu_fifo_read(&qhdl->ff, data); + const bool success = tu_fifo_read_n(&qhdl->ff, data, qhdl->item_size); qhdl->interrupt_set(true); return success; @@ -195,7 +195,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_send(osal_queue_t qhdl, void qhdl->interrupt_set(false); } - const bool success = tu_fifo_write(&qhdl->ff, data); + const bool success = tu_fifo_write_n(&qhdl->ff, data, qhdl->item_size); if (!in_isr) { qhdl->interrupt_set(true); diff --git a/src/osal/osal_pico.h b/src/osal/osal_pico.h index f5385071a..79b728e9a 100644 --- a/src/osal/osal_pico.h +++ b/src/osal/osal_pico.h @@ -47,40 +47,39 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec) { // Spinlock API //--------------------------------------------------------------------+ typedef critical_section_t osal_spinlock_t; // pico implement critical section with spinlock -#define OSAL_SPINLOCK_DEF(_name, _int_set) \ - osal_spinlock_t _name +#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) { critical_section_init(ctx); } TU_ATTR_ALWAYS_INLINE static inline void osal_spin_lock(osal_spinlock_t *ctx, bool in_isr) { - (void) in_isr; + (void)in_isr; critical_section_enter_blocking(ctx); } TU_ATTR_ALWAYS_INLINE static inline void osal_spin_unlock(osal_spinlock_t *ctx, bool in_isr) { - (void) in_isr; + (void)in_isr; critical_section_exit(ctx); } //--------------------------------------------------------------------+ // Binary Semaphore API //--------------------------------------------------------------------+ -typedef struct semaphore osal_semaphore_def_t, * osal_semaphore_t; +typedef struct semaphore osal_semaphore_def_t, *osal_semaphore_t; -TU_ATTR_ALWAYS_INLINE static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef) { +TU_ATTR_ALWAYS_INLINE static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t *semdef) { sem_init(semdef, 0, 255); return semdef; } TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_delete(osal_semaphore_t semd_hdl) { - (void) semd_hdl; + (void)semd_hdl; return true; // nothing to do } TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) { - (void) in_isr; + (void)in_isr; return sem_release(sem_hdl); } @@ -96,15 +95,15 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_semaphore_reset(osal_semaphore_t s // MUTEX API // Within tinyusb, mutex is never used in ISR context //--------------------------------------------------------------------+ -typedef struct mutex osal_mutex_def_t, * osal_mutex_t; +typedef struct mutex osal_mutex_def_t, *osal_mutex_t; -TU_ATTR_ALWAYS_INLINE static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef) { +TU_ATTR_ALWAYS_INLINE static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t *mdef) { mutex_init(mdef); return mdef; } TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_delete(osal_mutex_t mutex_hdl) { - (void) mutex_hdl; + (void)mutex_hdl; return true; // nothing to do } @@ -123,46 +122,45 @@ TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hd #include "common/tusb_fifo.h" typedef struct { - tu_fifo_t ff; + uint16_t item_size; + tu_fifo_t ff; struct critical_section critsec; // osal_queue may be used in IRQs, so need critical section } osal_queue_def_t; -typedef osal_queue_def_t* osal_queue_t; +typedef osal_queue_def_t *osal_queue_t; // role device/host is used by OS NONE for mutex (disable usb isr) only -#define OSAL_QUEUE_DEF(_int_set, _name, _depth, _type) \ - uint8_t _name##_buf[_depth*sizeof(_type)]; \ - osal_queue_def_t _name = { \ - .ff = TU_FIFO_INIT(_name##_buf, _depth, _type, false) \ - } +#define OSAL_QUEUE_DEF(_int_set, _name, _depth, _type) \ + uint8_t _name##_buf[_depth * sizeof(_type)]; \ + osal_queue_def_t _name = {.item_size = sizeof(_type), .ff = TU_FIFO_INIT(_name##_buf, _depth * sizeof(_type), false)} -TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) { +TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t *qdef) { critical_section_init(&qdef->critsec); - (void) tu_fifo_clear(&qdef->ff); - return (osal_queue_t) qdef; + tu_fifo_clear(&qdef->ff); + return (osal_queue_t)qdef; } TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_delete(osal_queue_t qhdl) { - osal_queue_def_t* qdef = (osal_queue_def_t*) qhdl; + osal_queue_def_t *qdef = (osal_queue_def_t *)qhdl; critical_section_deinit(&qdef->critsec); return true; } -TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, void* data, uint32_t msec) { - (void) msec; // not used, always behave as msec = 0 +TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, void *data, uint32_t msec) { + (void)msec; // not used, always behave as msec = 0 critical_section_enter_blocking(&qhdl->critsec); - bool success = tu_fifo_read(&qhdl->ff, data); + bool success = tu_fifo_read_n(&qhdl->ff, data, qhdl->item_size); critical_section_exit(&qhdl->critsec); return success; } -TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_send(osal_queue_t qhdl, void const* data, bool in_isr) { - (void) in_isr; +TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_send(osal_queue_t qhdl, const void *data, bool in_isr) { + (void)in_isr; critical_section_enter_blocking(&qhdl->critsec); - bool success = tu_fifo_write(&qhdl->ff, data); + bool success = tu_fifo_write_n(&qhdl->ff, data, qhdl->item_size); critical_section_exit(&qhdl->critsec); return success; diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index ba40498e6..aacef691f 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -345,10 +345,9 @@ static void edpt_disable(uint8_t rhport, uint8_t ep_addr, bool stall) { } } -static uint16_t epin_write_tx_fifo(uint8_t rhport, uint8_t epnum) { - dwc2_regs_t* dwc2 = DWC2_REG(rhport); - dwc2_dep_t* const epin = &dwc2->ep[0][epnum]; - xfer_ctl_t* const xfer = XFER_CTL_BASE(epnum, TUSB_DIR_IN); +static uint16_t epin_write_tx_fifo(dwc2_regs_t *dwc2, uint8_t epnum) { + dwc2_dep_t *const epin = &dwc2->ep[0][epnum]; + xfer_ctl_t *const xfer = XFER_CTL_BASE(epnum, TUSB_DIR_IN); dwc2_ep_tsize_t tsiz = {.value = epin->tsiz}; const uint16_t remain_packets = tsiz.packet_count; @@ -438,7 +437,7 @@ static void edpt_schedule_packets(uint8_t rhport, const uint8_t epnum, const uin dep->diepctl = depctl.value; // enable endpoint if (dir == TUSB_DIR_IN && total_bytes != 0) { - const uint16_t xferred_bytes = epin_write_tx_fifo(rhport, epnum); + const uint16_t xferred_bytes = epin_write_tx_fifo(dwc2, epnum); // Enable TXFE interrupt if there are still data to be sent // EP0 only sends one packet at a time, so no need to check for EP0 @@ -689,9 +688,6 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to // into the USB buffer! bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_t total_bytes, bool is_isr) { (void) is_isr; - // USB buffers always work in bytes so to avoid unnecessary divisions we demand item_size = 1 - TU_ASSERT(ff->item_size == 1); - 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); @@ -893,7 +889,8 @@ static void handle_rxflvl_irq(uint8_t rhport) { if (byte_count != 0) { // Read packet off RxFIFO if (xfer->ff != NULL) { - tu_fifo_write_n_access_mode(xfer->ff, (const void *)(uintptr_t)rx_fifo, byte_count, TU_FIFO_FIXED_ADDR_RW32); + tu_fifo_write_n_access_mode(xfer->ff, (const void *)(uintptr_t)rx_fifo, byte_count, TU_FIFO_FIXED_ADDR_RW32, + 0); } else { dfifo_read_packet(dwc2, xfer->buffer, byte_count); xfer->buffer += byte_count; @@ -967,7 +964,7 @@ 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 && tu_bit_test(dwc2->diepempmsk, epnum)) { - epin_write_tx_fifo(rhport, epnum); + epin_write_tx_fifo(dwc2, epnum); // Turn off TXFE if all bytes are written. dwc2_ep_tsize_t tsiz = {.value = epin->tsiz}; diff --git a/src/tusb.c b/src/tusb.c index 8117c3e3e..ed254a10b 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -316,7 +316,7 @@ bool tu_edpt_stream_init(tu_edpt_stream_t *s, bool is_host, bool is_tx, bool ove #endif s->is_host = is_host; - tu_fifo_config(&s->ff, ff_buf, ff_bufsize, 1, overwritable); + tu_fifo_config(&s->ff, ff_buf, ff_bufsize, overwritable); #if OSAL_MUTEX_REQUIRED if (ff_buf != NULL && ff_bufsize > 0) { diff --git a/src/tusb_option.h b/src/tusb_option.h index 1dc920d84..de54d33d8 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -307,6 +307,7 @@ #if defined(TUP_USBIP_DWC2) #if CFG_TUD_DWC2_SLAVE_ENABLE && !CFG_TUD_DWC2_DMA_ENABLE #define CFG_TUD_EDPT_DEDICATED_HWFIFO 1 + #define CFG_TUSB_FIFO_MULTI_BYTES_ACCESS 1 #endif #if CFG_TUH_DWC2_SLAVE_ENABLE && !CFG_TUH_DWC2_DMA_ENABLE diff --git a/test/unit-test/project.yml b/test/unit-test/project.yml index 3968faaef..d7646ca7f 100644 --- a/test/unit-test/project.yml +++ b/test/unit-test/project.yml @@ -129,6 +129,7 @@ :test: - _UNITY_TEST_ - CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_WIDTH=32 + - CFG_TUSB_FIFO_MULTI_BYTES_ACCESS=1 :release: [] # Enable to inject name of a test as a unique compilation symbol into its respective executable build. diff --git a/test/unit-test/test/test_fifo.c b/test/unit-test/test/test_fifo.c index 35bbeaa62..d0e3c2d37 100644 --- a/test/unit-test/test/test_fifo.c +++ b/test/unit-test/test/test_fifo.c @@ -32,7 +32,7 @@ #define FIFO_SIZE 64 uint8_t tu_ff_buf[FIFO_SIZE * sizeof(uint8_t)]; -tu_fifo_t tu_ff = TU_FIFO_INIT(tu_ff_buf, FIFO_SIZE, uint8_t, false); +tu_fifo_t tu_ff = TU_FIFO_INIT(tu_ff_buf, FIFO_SIZE, false); tu_fifo_t *ff = &tu_ff; tu_fifo_buffer_info_t info; @@ -68,34 +68,6 @@ void test_normal(void) { } } -void test_item_size(void) { - uint8_t ff4_buf[FIFO_SIZE * sizeof(uint32_t)]; - tu_fifo_t ff4 = TU_FIFO_INIT(ff4_buf, FIFO_SIZE, uint32_t, false); - - uint32_t data4[2 * FIFO_SIZE]; - for (uint32_t i = 0; i < sizeof(data4) / 4; i++) { - data4[i] = i; - } - - // fill up fifo - tu_fifo_write_n(&ff4, data4, FIFO_SIZE); - - uint32_t rd_buf4[FIFO_SIZE]; - uint16_t rd_count; - - // read 0 -> 4 - rd_count = tu_fifo_read_n(&ff4, rd_buf4, 5); - TEST_ASSERT_EQUAL(5, rd_count); - TEST_ASSERT_EQUAL_UINT32_ARRAY(data4, rd_buf4, rd_count); // 0 -> 4 - - tu_fifo_write_n(&ff4, data4 + FIFO_SIZE, 5); - - // read all 5 -> 68 - rd_count = tu_fifo_read_n(&ff4, rd_buf4, FIFO_SIZE); - TEST_ASSERT_EQUAL(FIFO_SIZE, rd_count); - TEST_ASSERT_EQUAL_UINT32_ARRAY(data4 + 5, rd_buf4, rd_count); // 5 -> 68 -} - void test_read_n(void) { uint16_t rd_count; @@ -362,7 +334,7 @@ void test_rd_idx_wrap(void) { uint8_t buf[10]; uint8_t dst[10]; - tu_fifo_config(&ff10, buf, 10, 1, 1); + tu_fifo_config(&ff10, buf, 10, 1); uint16_t n; @@ -431,7 +403,7 @@ void test_write_n_fixed_addr_rw32_nowrap(void) { for (uint8_t n = 1; n <= 8; n++) { tu_fifo_clear(ff); - uint16_t written = tu_fifo_write_n_access_mode(ff, (const void *)®, n, TU_FIFO_FIXED_ADDR_RW32); + uint16_t written = tu_fifo_write_n_access_mode(ff, (const void *)®, n, sizeof(uint32_t), 0); TEST_ASSERT_EQUAL(n, written); TEST_ASSERT_EQUAL(n, tu_fifo_count(ff)); @@ -453,7 +425,7 @@ void test_write_n_fixed_addr_rw32_wrapped(void) { ff->wr_idx = FIFO_SIZE - 3; ff->rd_idx = FIFO_SIZE - 3; - uint16_t written = tu_fifo_write_n_access_mode(ff, (const void *)®, n, TU_FIFO_FIXED_ADDR_RW32); + uint16_t written = tu_fifo_write_n_access_mode(ff, (const void *)®, n, sizeof(uint32_t), 0); TEST_ASSERT_EQUAL(n, written); TEST_ASSERT_EQUAL(n, tu_fifo_count(ff)); -- cgit v1.3.1 From d61ed922206148081afa70803ad717858bc5b756 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 31 Dec 2025 01:07:52 +0700 Subject: re-branding fixed address fifo read/write to stride mode --- src/common/tusb_fifo.c | 205 +++++++++++++++---------------- src/common/tusb_fifo.h | 62 ++++------ src/portable/microchip/samg/dcd_samg.c | 4 +- src/portable/nuvoton/nuc505/dcd_nuc505.c | 4 +- src/portable/synopsys/dwc2/dcd_dwc2.c | 5 +- src/tusb_option.h | 3 +- test/unit-test/project.yml | 4 +- test/unit-test/test/test_fifo.c | 8 +- 8 files changed, 142 insertions(+), 153 deletions(-) (limited to 'src/portable') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 7822b7aae..a347fbee3 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -113,87 +113,92 @@ void tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable) { // Pull & Push // copy data to/from fifo without updating read/write pointers //--------------------------------------------------------------------+ -#if CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_WIDTH - #if CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_WIDTH == 32 - #define fixed_unaligned_write tu_unaligned_write32 - #define fixed_unaligned_read tu_unaligned_read32 -typedef uint32_t fixed_access_item_t; - #elif CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_WIDTH == 16 - #define fixed_unaligned_write tu_unaligned_write16 - #define fixed_unaligned_read tu_unaligned_read16 -typedef uint16_t fixed_access_item_t; +#if CFG_TUSB_FIFO_ACCESS_DATA_STRIDE + #if CFG_TUSB_FIFO_ACCESS_DATA_STRIDE == 4 + #define stride_unaligned_write tu_unaligned_write32 + #define stride_unaligned_read tu_unaligned_read32 +typedef uint32_t stride_item_t; + #elif CFG_TUSB_FIFO_ACCESS_DATA_STRIDE == 2 + #define stride_unaligned_write tu_unaligned_write16 + #define stride_unaligned_read tu_unaligned_read16 +typedef uint16_t stride_item_t; #endif enum { - FIXED_ACCESS_REMAINDER_MASK = sizeof(fixed_access_item_t) - 1u + STRIDE_REMAIN_MASK = sizeof(stride_item_t) - 1u }; // Copy to fifo from fixed address buffer (usually a rx register) with TU_FIFO_FIXED_ADDR_RW32 mode -static void ff_push_access_mode(uint8_t *ff_buf, const volatile fixed_access_item_t *reg_rx, uint16_t len, - uint8_t data_stride, uint8_t addr_stride) { - (void)data_stride; - (void)addr_stride; - // Reading full available 16/32-bit data from const app address - uint16_t n_items = len / sizeof(fixed_access_item_t); +static void ff_push_stride(uint8_t *ff_buf, const volatile stride_item_t *src, uint16_t len) { + // Reading full available 16/32-bit src and write to fifo + uint16_t n_items = len >> (CFG_TUSB_FIFO_ACCESS_DATA_STRIDE >> 1); // len / data_stride; while (n_items--) { - const fixed_access_item_t tmp = *reg_rx; - fixed_unaligned_write(ff_buf, tmp); - ff_buf += sizeof(fixed_access_item_t); + const stride_item_t tmp = *src; + stride_unaligned_write(ff_buf, tmp); + ff_buf += sizeof(stride_item_t); + + #if CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE + src = (const volatile uint8_t *)src + addr_stride; + #endif } - // Read the remaining 1 byte (16bit) or 1-3 bytes (32bit) from const app address - const uint8_t bytes_rem = len & FIXED_ACCESS_REMAINDER_MASK; + // Read the remaining 1 byte (16bit) or 1-3 bytes (32bit) + const uint8_t bytes_rem = len & STRIDE_REMAIN_MASK; if (bytes_rem) { - const fixed_access_item_t tmp = *reg_rx; + const stride_item_t tmp = *src; memcpy(ff_buf, &tmp, bytes_rem); } } // Copy from fifo to fixed address buffer (usually a tx register) with TU_FIFO_FIXED_ADDR_RW32 mode -static void ff_pull_fixed_addr(volatile fixed_access_item_t *reg_tx, const uint8_t *ff_buf, uint16_t len) { - // Write full available 32 bit words to const address - uint16_t n_itmes = len / sizeof(fixed_access_item_t); - while (n_itmes--) { - *reg_tx = fixed_unaligned_read(ff_buf); - ff_buf += sizeof(fixed_access_item_t); +static void ff_pull_stride(volatile stride_item_t *dest, const uint8_t *ff_buf, uint16_t len) { + // Write full available 16/32 bit words to dest + uint16_t n_items = len >> (CFG_TUSB_FIFO_ACCESS_DATA_STRIDE >> 1); // len / data_stride; + while (n_items--) { + *dest = stride_unaligned_read(ff_buf); + ff_buf += sizeof(stride_item_t); + + #if CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE + dest = (const volatile uint8_t *)dest + addr_stride; + #endif } // Write the remaining 1 byte (16bit) or 1-3 bytes (32bit) - const uint8_t bytes_rem = len & FIXED_ACCESS_REMAINDER_MASK; + const uint8_t bytes_rem = len & STRIDE_REMAIN_MASK; if (bytes_rem) { - fixed_access_item_t tmp = 0u; + stride_item_t tmp = 0u; memcpy(&tmp, ff_buf, bytes_rem); - *reg_tx = tmp; + *dest = tmp; } } #endif // send n items to fifo WITHOUT updating write pointer -static void ff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uint16_t wr_ptr, uint8_t data_stride, - uint8_t addr_stride) { +static void ff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uint16_t wr_ptr, bool stride_mode) { + (void)stride_mode; uint16_t lin_bytes = f->depth - wr_ptr; uint16_t wrap_bytes = n - lin_bytes; uint8_t *ff_buf = f->buffer + wr_ptr; -#if CFG_TUSB_FIFO_MULTI_BYTES_ACCESS - if (data_stride > 1) { - const volatile fixed_access_item_t *reg_rx = (volatile const fixed_access_item_t *)app_buf; +#if CFG_TUSB_FIFO_ACCESS_DATA_STRIDE + if (stride_mode) { + const volatile stride_item_t *stride_src = (const volatile stride_item_t *)app_buf; if (n <= lin_bytes) { - // Linear only - ff_push_access_mode(ff_buf, reg_rx, n, data_stride, addr_stride); + // Linear only case + ff_push_stride(ff_buf, stride_src, n); } else { - // Wrap around + // Wrap around case // Write full words to linear part of buffer - uint16_t lin_nitems_bytes = lin_bytes & ~FIXED_ACCESS_REMAINDER_MASK; - ff_push_access_mode(ff_buf, reg_rx, lin_nitems_bytes, data_stride, addr_stride); + uint16_t lin_nitems_bytes = lin_bytes & ~STRIDE_REMAIN_MASK; + ff_push_stride(ff_buf, stride_src, lin_nitems_bytes); ff_buf += lin_nitems_bytes; // There could be odd 1 byte (16bit) or 1-3 bytes (32bit) before the wrap-around boundary - const uint8_t rem = lin_bytes & FIXED_ACCESS_REMAINDER_MASK; + const uint8_t rem = lin_bytes & STRIDE_REMAIN_MASK; if (rem > 0) { - const uint8_t remrem = (uint8_t)tu_min16(wrap_bytes, sizeof(fixed_access_item_t) - rem); - const fixed_access_item_t tmp = *reg_rx; + const uint8_t remrem = (uint8_t)tu_min16(wrap_bytes, sizeof(stride_item_t) - rem); + const stride_item_t tmp = *stride_src; tu_scatter_write32(tmp, ff_buf, rem, f->buffer, remrem); wrap_bytes -= remrem; @@ -204,7 +209,7 @@ static void ff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uint1 // Write data wrapped part if (wrap_bytes > 0) { - ff_push_access_mode(ff_buf, reg_rx, wrap_bytes, data_stride, addr_stride); + ff_push_stride(ff_buf, stride_src, wrap_bytes); } } } else @@ -212,10 +217,10 @@ static void ff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uint1 { // single byte access if (n <= lin_bytes) { - // Linear only + // Linear only case memcpy(ff_buf, app_buf, n); } else { - // Wrap around + // Wrap around case memcpy(ff_buf, app_buf, lin_bytes); // linear part memcpy(f->buffer, ((const uint8_t *)app_buf) + lin_bytes, wrap_bytes); // wrapped part } @@ -223,63 +228,58 @@ static void ff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uint1 } // get n items from fifo WITHOUT updating read pointer -static void ff_pull_n(const tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t rd_ptr, tu_fifo_access_mode_t copy_mode) { +static void ff_pull_n(const tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t rd_ptr, bool stride_mode) { + (void)stride_mode; uint16_t lin_bytes = f->depth - rd_ptr; uint16_t wrap_bytes = n - lin_bytes; // only used if wrapped const uint8_t *ff_buf = f->buffer + rd_ptr; - switch (copy_mode) { - case TU_FIFO_INC_ADDR_RW8: - if (n <= lin_bytes) { - // Linear only - memcpy(app_buf, ff_buf, n); - } else { - // Wrap around - memcpy(app_buf, ff_buf, lin_bytes); // linear part - memcpy((uint8_t *)app_buf + lin_bytes, f->buffer, wrap_bytes); // wrapped part - } - break; +#if CFG_TUSB_FIFO_ACCESS_DATA_STRIDE + if (stride_mode) { + volatile stride_item_t *stride_dst = (volatile stride_item_t *)app_buf; + + if (n <= lin_bytes) { + // Linear only case + ff_pull_stride(stride_dst, ff_buf, n); + } else { + // Wrap around case + + // Read full words from linear part + uint16_t lin_nitems_bytes = lin_bytes & ~STRIDE_REMAIN_MASK; + ff_pull_stride(stride_dst, ff_buf, lin_nitems_bytes); + ff_buf += lin_nitems_bytes; + + // There could be odd 1 byte (16bit) or 1-3 bytes (32bit) before the wrap-around boundary + const uint8_t rem = lin_bytes & STRIDE_REMAIN_MASK; + if (rem > 0) { + const uint8_t remrem = (uint8_t)tu_min16(wrap_bytes, sizeof(stride_item_t) - rem); + const stride_item_t scatter = (stride_item_t)tu_scatter_read32(ff_buf, rem, f->buffer, remrem); -#ifdef CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_WIDTH - case TU_FIFO_FIXED_ADDR_RW32: { - volatile fixed_access_item_t *reg_tx = (volatile fixed_access_item_t *)app_buf; + *stride_dst = scatter; - if (n <= lin_bytes) { - // Linear only - ff_pull_fixed_addr(reg_tx, ff_buf, n); + wrap_bytes -= remrem; + ff_buf = f->buffer + remrem; // wrap around } else { - // Wrap around case - - // Read full words from linear part - uint16_t lin_nitems_bytes = lin_bytes & ~FIXED_ACCESS_REMAINDER_MASK; - ff_pull_fixed_addr(reg_tx, ff_buf, lin_nitems_bytes); - ff_buf += lin_nitems_bytes; - - // There could be odd 1 byte (16bit) or 1-3 bytes (32bit) before the wrap-around boundary - const uint8_t rem = lin_bytes & FIXED_ACCESS_REMAINDER_MASK; - if (rem > 0) { - const uint8_t remrem = (uint8_t)tu_min16(wrap_bytes, sizeof(fixed_access_item_t) - rem); - const fixed_access_item_t scatter = (fixed_access_item_t)tu_scatter_read32(ff_buf, rem, f->buffer, remrem); - - *reg_tx = scatter; - - wrap_bytes -= remrem; - ff_buf = f->buffer + remrem; // wrap around - } else { - ff_buf = f->buffer; // wrap around to beginning - } - - // Read data wrapped part - if (wrap_bytes > 0) { - ff_pull_fixed_addr(reg_tx, ff_buf, wrap_bytes); - } + ff_buf = f->buffer; // wrap around to beginning + } + + // Read data wrapped part + if (wrap_bytes > 0) { + ff_pull_stride(stride_dst, ff_buf, wrap_bytes); } - break; } + } else #endif - - default: - break; // unknown mode + { + // single byte access + if (n <= lin_bytes) { + // Linear only + memcpy(app_buf, ff_buf, n); + } else { + // Wrap around + memcpy(app_buf, ff_buf, lin_bytes); // linear part + memcpy((uint8_t *)app_buf + lin_bytes, f->buffer, wrap_bytes); // wrapped part + } } } @@ -332,7 +332,7 @@ static uint16_t correct_read_index(tu_fifo_t *f, uint16_t wr_idx) { // Works on local copies of w and r // Must be protected by read mutex since in case of an overflow read pointer gets modified uint16_t tu_fifo_peek_n_access_mode(tu_fifo_t *f, void *p_buffer, uint16_t n, uint16_t wr_idx, uint16_t rd_idx, - tu_fifo_access_mode_t access_mode) { + bool stride_mode) { uint16_t count = tu_ff_overflow_count(f->depth, wr_idx, rd_idx); if (count == 0) { return 0; // nothing to peek @@ -349,7 +349,7 @@ uint16_t tu_fifo_peek_n_access_mode(tu_fifo_t *f, void *p_buffer, uint16_t n, ui } const uint16_t rd_ptr = idx2ptr(f->depth, rd_idx); - ff_pull_n(f, p_buffer, n, rd_ptr, access_mode); + ff_pull_n(f, p_buffer, n, rd_ptr, stride_mode); return n; } @@ -357,17 +357,17 @@ uint16_t tu_fifo_peek_n_access_mode(tu_fifo_t *f, void *p_buffer, uint16_t n, ui // Read n items without removing it from the FIFO, correct read pointer if overflowed uint16_t tu_fifo_peek_n(tu_fifo_t *f, void *p_buffer, uint16_t n) { ff_lock(f->mutex_rd); - const uint16_t ret = tu_fifo_peek_n_access_mode(f, p_buffer, n, f->wr_idx, f->rd_idx, TU_FIFO_INC_ADDR_RW8); + const uint16_t ret = tu_fifo_peek_n_access_mode(f, p_buffer, n, f->wr_idx, f->rd_idx, false); ff_unlock(f->mutex_rd); return ret; } // Read n items from fifo with access mode -uint16_t tu_fifo_read_n_access_mode(tu_fifo_t *f, void *buffer, uint16_t n, tu_fifo_access_mode_t access_mode) { +uint16_t tu_fifo_read_n_access_mode(tu_fifo_t *f, void *buffer, uint16_t n, bool stride_mode) { ff_lock(f->mutex_rd); // Peek the data: f->rd_idx might get modified in case of an overflow so we can not use a local variable - n = tu_fifo_peek_n_access_mode(f, buffer, n, f->wr_idx, f->rd_idx, access_mode); + n = tu_fifo_peek_n_access_mode(f, buffer, n, f->wr_idx, f->rd_idx, stride_mode); f->rd_idx = advance_index(f->depth, f->rd_idx, n); ff_unlock(f->mutex_rd); @@ -375,8 +375,7 @@ uint16_t tu_fifo_read_n_access_mode(tu_fifo_t *f, void *buffer, uint16_t n, tu_f } // Write n items to fifo with access mode -uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n, uint8_t data_stride, - uint8_t addr_stride) { +uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n, bool stride_mode) { if (n == 0) { return 0; } @@ -402,7 +401,7 @@ uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n, // function! Since it would end up in a race condition with read functions! if (n >= f->depth) { // Only copy last part - if (data_stride == TU_FIFO_INC_ADDR_RW8) { + if (!stride_mode) { buf8 += (n - f->depth); } else { // TODO should read from hw fifo to discard data, however reading an odd number could @@ -438,7 +437,7 @@ uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n, const uint16_t wr_ptr = idx2ptr(f->depth, wr_idx); TU_LOG(TU_FIFO_DBG, "actual_n = %u, wr_ptr = %u", n, wr_ptr); - ff_push_n(f, buf8, n, wr_ptr, data_stride, addr_stride); + ff_push_n(f, buf8, n, wr_ptr, stride_mode); f->wr_idx = advance_index(f->depth, wr_idx, n); TU_LOG(TU_FIFO_DBG, "\tnew_wr = %u\r\n", f->wr_idx); diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index b48cf4cea..7623d4c4f 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -32,35 +32,31 @@ extern "C" { #endif -// Due to the use of unmasked pointers, this FIFO does not suffer from losing -// one item slice. Furthermore, write and read operations are completely -// decoupled as write and read functions do not modify a common state. Henceforth, -// writing or reading from the FIFO within an ISR is safe as long as no other -// process (thread or ISR) interferes. -// Also, this FIFO is ready to be used in combination with a DMA as the write and -// read pointers can be updated from within a DMA ISR. Overflows are detectable -// within a certain number (see tu_fifo_overflow()). - #include "common/tusb_common.h" #include "osal/osal.h" -// mutex is only needed for RTOS -// for OS None, we don't get preempted +//--------------------------------------------------------------------+ +// Configuration +//--------------------------------------------------------------------+ +// mutex is only needed for RTOS. For OS None, we don't get preempted #define CFG_FIFO_MUTEX OSAL_MUTEX_REQUIRED -#if CFG_TUD_EDPT_DEDICATED_HWFIFO || CFG_TUH_EDPT_DEDICATED_HWFIFO - #ifndef CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_WIDTH - #define CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_WIDTH 32 - #endif +#ifndef CFG_TUSB_FIFO_ACCESS_DATA_STRIDE + #define CFG_TUSB_FIFO_ACCESS_DATA_STRIDE 0 #endif -#ifndef CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_WIDTH - #define CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_WIDTH 0 +#ifndef CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE + #define CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE 0 #endif -#ifndef CFG_TUSB_FIFO_MULTI_BYTES_ACCESS - #define CFG_TUSB_FIFO_MULTI_BYTES_ACCESS 0 -#endif +// Due to the use of unmasked pointers, this FIFO does not suffer from losing +// one item slice. Furthermore, write and read operations are completely +// decoupled as write and read functions do not modify a common state. Henceforth, +// writing or reading from the FIFO within an ISR is safe as long as no other +// process (thread or ISR) interferes. +// Also, this FIFO is ready to be used in combination with a DMA as the write and +// read pointers can be updated from within a DMA ISR. Overflows are detectable +// within a certain number (see tu_fifo_overflow()). /* Write/Read "pointer" is in the range of: 0 .. depth - 1, and is used to get the fifo data. * Write/Read "index" is always in the range of: 0 .. 2*depth-1 @@ -122,6 +118,7 @@ typedef struct { uint8_t *buffer; // buffer pointer uint16_t depth; // max items bool overwritable; // ovwerwritable when full + // 1 byte padding here volatile uint16_t wr_idx; // write index TODO maybe can drop volatile volatile uint16_t rd_idx; // read index @@ -151,12 +148,10 @@ typedef struct { uint8_t _name##_buf[_depth]; \ tu_fifo_t _name = TU_FIFO_INIT(_name##_buf, _depth, _overwritable) -// Write modes intended to allow special read and write functions to be able to -// copy data to and from USB hardware FIFOs as needed for e.g. STM32s and others -typedef enum { - TU_FIFO_INC_ADDR_RW8, // increased address read/write by bytes - normal (default) mode - TU_FIFO_FIXED_ADDR_RW32, // fixed address read/write by 2/4 bytes (items). -} tu_fifo_access_mode_t; +// Moving data from tusb_fifo <-> USB hardware FIFOs e.g. STM32s need to use a special stride mode which reads/writes +// data in 2/4 byte chunks from/to a fixed address (USB FIFO register) instead of incrementing the address. For this use +// read/write access_mode with stride_mode = true. The STRIPE DATA and ADDR stride must be configured with +// CFG_TUSB_FIFO_ACCESS_DATA_STRIDE and CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE //--------------------------------------------------------------------+ // Setup API @@ -196,7 +191,7 @@ void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info); // peek() will correct/re-index read pointer in case of an overflowed fifo to form a full fifo //--------------------------------------------------------------------+ uint16_t tu_fifo_peek_n_access_mode(tu_fifo_t *f, void *p_buffer, uint16_t n, uint16_t wr_idx, uint16_t rd_idx, - tu_fifo_access_mode_t access_mode); + bool stride_mode); bool tu_fifo_peek(tu_fifo_t *f, void *p_buffer); uint16_t tu_fifo_peek_n(tu_fifo_t *f, void *p_buffer, uint16_t n); @@ -204,14 +199,10 @@ uint16_t tu_fifo_peek_n(tu_fifo_t *f, void *p_buffer, uint16_t n); // Read API // peek() + advance read index //--------------------------------------------------------------------+ -uint16_t tu_fifo_read_n_access_mode(tu_fifo_t *f, void *buffer, uint16_t n, tu_fifo_access_mode_t access_mode); +uint16_t tu_fifo_read_n_access_mode(tu_fifo_t *f, void *buffer, uint16_t n, bool stride_mode); bool tu_fifo_read(tu_fifo_t *f, void *buffer); TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_read_n(tu_fifo_t *f, void *buffer, uint16_t n) { - return tu_fifo_read_n_access_mode(f, buffer, n, TU_FIFO_INC_ADDR_RW8); -} - -TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_read_n_fixed_addr(tu_fifo_t *f, void *buffer, uint16_t n) { - return tu_fifo_read_n_access_mode(f, buffer, n, TU_FIFO_FIXED_ADDR_RW32); + return tu_fifo_read_n_access_mode(f, buffer, n, false); } // discard first n items from fifo i.e advance read pointer by n with mutex @@ -221,11 +212,10 @@ uint16_t tu_fifo_discard_n(tu_fifo_t *f, uint16_t n); //--------------------------------------------------------------------+ // Write API //--------------------------------------------------------------------+ -uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n, uint8_t data_stride, - uint8_t addr_stride); +uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n, bool stride_mode); bool tu_fifo_write(tu_fifo_t *f, const void *data); TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_write_n(tu_fifo_t *f, const void *data, uint16_t n) { - return tu_fifo_write_n_access_mode(f, data, n, 1, 1); + return tu_fifo_write_n_access_mode(f, data, n, false); } //--------------------------------------------------------------------+ diff --git a/src/portable/microchip/samg/dcd_samg.c b/src/portable/microchip/samg/dcd_samg.c index 1faac2aa8..4115eecc5 100644 --- a/src/portable/microchip/samg/dcd_samg.c +++ b/src/portable/microchip/samg/dcd_samg.c @@ -437,7 +437,7 @@ void dcd_int_handler(uint8_t rhport) // write to EP fifo #if 0 // TODO support dcd_edpt_xfer_fifo if (xfer->ff) { - tu_fifo_read_n_access_mode(xfer->ff, (void *) &UDP->UDP_FDR[epnum], xact_len, TU_FIFO_FIXED_ADDR_RW32); + tu_fifo_read_n_access_mode(xfer->ff, (void *) &UDP->UDP_FDR[epnum], xact_len, true); } else #endif @@ -471,7 +471,7 @@ void dcd_int_handler(uint8_t rhport) // Read from EP fifo #if 0 // TODO support dcd_edpt_xfer_fifo API if (xfer->ff) { - tu_fifo_write_n_access_mode(xfer->ff, (const void *) &UDP->UDP_FDR[epnum], xact_len, TU_FIFO_FIXED_ADDR_RW32); + tu_fifo_write_n_access_mode(xfer->ff, (const void *) &UDP->UDP_FDR[epnum], xact_len, true); } else #endif diff --git a/src/portable/nuvoton/nuc505/dcd_nuc505.c b/src/portable/nuvoton/nuc505/dcd_nuc505.c index 91b876718..ca17d6251 100644 --- a/src/portable/nuvoton/nuc505/dcd_nuc505.c +++ b/src/portable/nuvoton/nuc505/dcd_nuc505.c @@ -194,7 +194,7 @@ static void dcd_userEP_in_xfer(struct xfer_ctl_t *xfer, USBD_EP_T *ep) /* provided buffers are thankfully 32-bit aligned, allowing most data to be transferred as 32-bit */ #if 0 // TODO support dcd_edpt_xfer_fifo API if (xfer->ff) { - tu_fifo_read_n_access_mode(xfer->ff, (void *) (&ep->EPDAT_BYTE), bytes_now, TU_FIFO_FIXED_ADDR_RW32); + tu_fifo_read_n_access_mode(xfer->ff, (void *) (&ep->EPDAT_BYTE), bytes_now, true); } else #endif @@ -696,7 +696,7 @@ void dcd_int_handler(uint8_t rhport) /* copy the data from the PC to the previously provided buffer */ #if 0 // TODO support dcd_edpt_xfer_fifo API if (xfer->ff) { - tu_fifo_write_n_access_mode(xfer->ff, (const void *) &ep->EPDAT_BYTE, tu_min16(available_bytes, xfer->total_bytes - xfer->out_bytes_so_far), TU_FIFO_FIXED_ADDR_RW32); + tu_fifo_write_n_access_mode(xfer->ff, (const void *) &ep->EPDAT_BYTE, tu_min16(available_bytes, xfer->total_bytes - xfer->out_bytes_so_far), true); } else #endif diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index aacef691f..8c97eaa2f 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -367,7 +367,7 @@ static uint16_t epin_write_tx_fifo(dwc2_regs_t *dwc2, uint8_t epnum) { // Push packet to Tx-FIFO if (xfer->ff) { volatile uint32_t* tx_fifo = dwc2->fifo[epnum]; - tu_fifo_read_n_access_mode(xfer->ff, (void *)(uintptr_t)tx_fifo, xact_bytes, TU_FIFO_FIXED_ADDR_RW32); + tu_fifo_read_n_access_mode(xfer->ff, (void *)(uintptr_t)tx_fifo, xact_bytes, true); total_bytes_written += xact_bytes; } else { dfifo_write_packet(dwc2, epnum, xfer->buffer, xact_bytes); @@ -889,8 +889,7 @@ static void handle_rxflvl_irq(uint8_t rhport) { if (byte_count != 0) { // Read packet off RxFIFO if (xfer->ff != NULL) { - tu_fifo_write_n_access_mode(xfer->ff, (const void *)(uintptr_t)rx_fifo, byte_count, TU_FIFO_FIXED_ADDR_RW32, - 0); + tu_fifo_write_n_access_mode(xfer->ff, (const void *)(uintptr_t)rx_fifo, byte_count, true); } else { dfifo_read_packet(dwc2, xfer->buffer, byte_count); xfer->buffer += byte_count; diff --git a/src/tusb_option.h b/src/tusb_option.h index de54d33d8..a0f4e7057 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -307,7 +307,8 @@ #if defined(TUP_USBIP_DWC2) #if CFG_TUD_DWC2_SLAVE_ENABLE && !CFG_TUD_DWC2_DMA_ENABLE #define CFG_TUD_EDPT_DEDICATED_HWFIFO 1 - #define CFG_TUSB_FIFO_MULTI_BYTES_ACCESS 1 + #define CFG_TUSB_FIFO_ACCESS_DATA_STRIDE 4 // 32bit access + #define CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE 0 // fixed hwfifo address #endif #if CFG_TUH_DWC2_SLAVE_ENABLE && !CFG_TUH_DWC2_DMA_ENABLE diff --git a/test/unit-test/project.yml b/test/unit-test/project.yml index d7646ca7f..ea20c5f72 100644 --- a/test/unit-test/project.yml +++ b/test/unit-test/project.yml @@ -128,8 +128,8 @@ :defines: :test: - _UNITY_TEST_ - - CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_WIDTH=32 - - CFG_TUSB_FIFO_MULTI_BYTES_ACCESS=1 + - CFG_TUSB_FIFO_ACCESS_DATA_STRIDE=4 + - CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE=0 :release: [] # Enable to inject name of a test as a unique compilation symbol into its respective executable build. diff --git a/test/unit-test/test/test_fifo.c b/test/unit-test/test/test_fifo.c index d0e3c2d37..453930a2f 100644 --- a/test/unit-test/test/test_fifo.c +++ b/test/unit-test/test/test_fifo.c @@ -403,7 +403,7 @@ void test_write_n_fixed_addr_rw32_nowrap(void) { for (uint8_t n = 1; n <= 8; n++) { tu_fifo_clear(ff); - uint16_t written = tu_fifo_write_n_access_mode(ff, (const void *)®, n, sizeof(uint32_t), 0); + uint16_t written = tu_fifo_write_n_access_mode(ff, (const void *)®, n, true); TEST_ASSERT_EQUAL(n, written); TEST_ASSERT_EQUAL(n, tu_fifo_count(ff)); @@ -425,7 +425,7 @@ void test_write_n_fixed_addr_rw32_wrapped(void) { ff->wr_idx = FIFO_SIZE - 3; ff->rd_idx = FIFO_SIZE - 3; - uint16_t written = tu_fifo_write_n_access_mode(ff, (const void *)®, n, sizeof(uint32_t), 0); + uint16_t written = tu_fifo_write_n_access_mode(ff, (const void *)®, n, true); TEST_ASSERT_EQUAL(n, written); TEST_ASSERT_EQUAL(n, tu_fifo_count(ff)); @@ -445,7 +445,7 @@ void test_read_n_fixed_addr_rw32_nowrap(void) { tu_fifo_write_n(ff, pattern, 8); uint32_t reg = 0; - uint16_t read_cnt = tu_fifo_read_n_access_mode(ff, ®, n, TU_FIFO_FIXED_ADDR_RW32); + uint16_t read_cnt = tu_fifo_read_n_access_mode(ff, ®, n, true); TEST_ASSERT_EQUAL(n, read_cnt); TEST_ASSERT_EQUAL(8 - n, tu_fifo_count(ff)); @@ -469,7 +469,7 @@ void test_read_n_fixed_addr_rw32_wrapped(void) { } uint32_t reg = 0; - uint16_t read_cnt = tu_fifo_read_n_access_mode(ff, ®, n, TU_FIFO_FIXED_ADDR_RW32); + uint16_t read_cnt = tu_fifo_read_n_access_mode(ff, ®, n, true); TEST_ASSERT_EQUAL(n, read_cnt); TEST_ASSERT_EQUAL(0, tu_fifo_count(ff)); -- cgit v1.3.1 From f20ad05d71919dd5656aa7f92b9e27582744348a Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 31 Dec 2025 16:26:24 +0700 Subject: update tu_fifo to work with fsdev hwfifo with increased address 16/32bit --- README.rst | 14 +- src/common/tusb_fifo.c | 10 +- src/common/tusb_fifo.h | 6 + src/common/tusb_mcu.h | 145 ++++++++++---------- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 12 +- src/portable/st/stm32_fsdev/fsdev_at32.h | 1 - src/portable/st/stm32_fsdev/fsdev_ch32.h | 1 - src/portable/st/stm32_fsdev/fsdev_stm32.h | 186 ++++++++++++-------------- src/portable/synopsys/dwc2/dcd_dwc2.c | 4 +- src/tusb_option.h | 16 ++- test/unit-test/project.yml | 1 + 11 files changed, 205 insertions(+), 191 deletions(-) (limited to 'src/portable') diff --git a/README.rst b/README.rst index da1f49fcd..4ab991bf5 100644 --- a/README.rst +++ b/README.rst @@ -139,7 +139,7 @@ Supported CPUs | | MAX32 650, 666, 690, | ✔ | | ✔ | musb | 1-dir ep | | | MAX78002 | | | | | | +--------------+-----------------------------+--------+------+-----------+------------------------+--------------------+ -| Artery AT32 | F403a_407, F413 | ✔ | | | fsdev | Packet SRAM 512 | +| Artery AT32 | F403a_407, F413 | ✔ | | | fsdev | 512 USB RAM | | +-----------------------------+--------+------+-----------+------------------------+--------------------+ | | F415, F435_437, F423, F425 | ✔ | ✔ | | dwc2 | | | +-----------------------------+--------+------+-----------+------------------------+--------------------+ @@ -221,25 +221,25 @@ Supported CPUs +--------------+-----------------------------+--------+------+-----------+------------------------+--------------------+ | ST STM32 | F0, F3, L0, L1, L5, WBx5 | ✔ | ✖ | ✖ | stm32_fsdev | | | +----+------------------------+--------+------+-----------+------------------------+--------------------+ -| | F1 | 102, 103 | ✔ | ✖ | ✖ | stm32_fsdev | Packet SRAM 512 | +| | F1 | 102, 103 | ✔ | ✖ | ✖ | stm32_fsdev | 512 USB RAM | | | +------------------------+--------+------+-----------+------------------------+--------------------+ | | | 105, 107 | ✔ | ✔ | ✖ | dwc2 | | | +----+------------------------+--------+------+-----------+------------------------+--------------------+ | | F2, F4, F7, H7, H7RS | ✔ | ✔ | ✔ | dwc2 | | | +-----------------------------+--------+------+-----------+------------------------+--------------------+ -| | C0, G0, H5, U3 | ✔ | ✔ | ✖ | stm32_fsdev | Packet SRAM 2KB | +| | C0, G0, H5, U3 | ✔ | ✔ | ✖ | stm32_fsdev | 2KB USB RAM | | +-----------------------------+--------+------+-----------+------------------------+--------------------+ -| | G4 | ✔ | ✖ | ✖ | stm32_fsdev | Packet SRAM 1KB | +| | G4 | ✔ | ✖ | ✖ | stm32_fsdev | 1KB USB RAM | | +----+------------------------+--------+------+-----------+------------------------+--------------------+ -| | L4 | 4x2, 4x3 | ✔ | ✖ | ✖ | stm32_fsdev | Packet SRAM 1KB | +| | L4 | 4x2, 4x3 | ✔ | ✖ | ✖ | stm32_fsdev | 1KB USB RAM | | | +------------------------+--------+------+-----------+------------------------+--------------------+ | | | 4x5, 4x6, 4+ | ✔ | ✔ | ✖ | dwc2 | | | +----+------------------------+--------+------+-----------+------------------------+--------------------+ | | N6 | ✔ | ✔ | ✔ | dwc2 | | | +-----------------------------+--------+------+-----------+------------------------+--------------------+ -| | U0 | ✔ | ✖ | ✖ | stm32_fsdev | Packet SRAM 1KB | +| | U0 | ✔ | ✖ | ✖ | stm32_fsdev | 1KB USB RAM | | +----+------------------------+--------+------+-----------+------------------------+--------------------+ -| | U5 | 535, 545 | ✔ | ✔ | ✖ | stm32_fsdev | Packet SRAM 2KB | +| | U5 | 535, 545 | ✔ | ✔ | ✖ | stm32_fsdev | 2KB USB RAM | | | +------------------------+--------+------+-----------+------------------------+--------------------+ | | | 575, 585 | ✔ | ✔ | ✖ | dwc2 | | | | +------------------------+--------+------+-----------+------------------------+--------------------+ diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index a347fbee3..bc4ee180c 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -113,7 +113,7 @@ void tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable) { // Pull & Push // copy data to/from fifo without updating read/write pointers //--------------------------------------------------------------------+ -#if CFG_TUSB_FIFO_ACCESS_DATA_STRIDE +#if CFG_TUD_EDPT_DEDICATED_HWFIFO #if CFG_TUSB_FIFO_ACCESS_DATA_STRIDE == 4 #define stride_unaligned_write tu_unaligned_write32 #define stride_unaligned_read tu_unaligned_read32 @@ -138,7 +138,7 @@ static void ff_push_stride(uint8_t *ff_buf, const volatile stride_item_t *src, u ff_buf += sizeof(stride_item_t); #if CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE - src = (const volatile uint8_t *)src + addr_stride; + src = (const volatile stride_item_t *)((uintptr_t)src + CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE); #endif } @@ -159,7 +159,7 @@ static void ff_pull_stride(volatile stride_item_t *dest, const uint8_t *ff_buf, ff_buf += sizeof(stride_item_t); #if CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE - dest = (const volatile uint8_t *)dest + addr_stride; + dest = (volatile stride_item_t *)((uintptr_t)dest + CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE); #endif } @@ -180,7 +180,7 @@ static void ff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uint1 uint16_t wrap_bytes = n - lin_bytes; uint8_t *ff_buf = f->buffer + wr_ptr; -#if CFG_TUSB_FIFO_ACCESS_DATA_STRIDE +#if CFG_TUD_EDPT_DEDICATED_HWFIFO if (stride_mode) { const volatile stride_item_t *stride_src = (const volatile stride_item_t *)app_buf; if (n <= lin_bytes) { @@ -234,7 +234,7 @@ static void ff_pull_n(const tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t rd uint16_t wrap_bytes = n - lin_bytes; // only used if wrapped const uint8_t *ff_buf = f->buffer + rd_ptr; -#if CFG_TUSB_FIFO_ACCESS_DATA_STRIDE +#if CFG_TUD_EDPT_DEDICATED_HWFIFO if (stride_mode) { volatile stride_item_t *stride_dst = (volatile stride_item_t *)app_buf; diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 7623d4c4f..53c5f6e56 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -204,6 +204,9 @@ bool tu_fifo_read(tu_fifo_t *f, void *buffer); TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_read_n(tu_fifo_t *f, void *buffer, uint16_t n) { return tu_fifo_read_n_access_mode(f, buffer, n, false); } +TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_read_to_hwfifo(tu_fifo_t *f, void *buffer, uint16_t n) { + return tu_fifo_read_n_access_mode(f, buffer, n, true); +} // discard first n items from fifo i.e advance read pointer by n with mutex // return number of discarded items @@ -217,6 +220,9 @@ bool tu_fifo_write(tu_fifo_t *f, const void *data); TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_write_n(tu_fifo_t *f, const void *data, uint16_t n) { return tu_fifo_write_n_access_mode(f, data, n, false); } +TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_write_from_hwfifo(tu_fifo_t *f, const void *data, uint16_t n) { + return tu_fifo_write_n_access_mode(f, data, n, true); +} //--------------------------------------------------------------------+ // Internal Helper Local diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index 1e773bf96..f525a5a3d 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -176,10 +176,15 @@ //--------------------------------------------------------------------+ // ST //--------------------------------------------------------------------+ +#elif TU_CHECK_MCU(OPT_MCU_STM32C0) + #define TUP_USBIP_FSDEV + #define TUP_USBIP_FSDEV_STM32 + #define FSDEV_PMA_SIZE 2048u + #elif TU_CHECK_MCU(OPT_MCU_STM32F0) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define TUP_DCD_ENDPOINT_MAX 8 + #define FSDEV_PMA_SIZE 1024u #elif TU_CHECK_MCU(OPT_MCU_STM32F1) // - F102, F103 use fsdev @@ -195,7 +200,7 @@ defined(STM32F103xE) || defined(STM32F103xG) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define TUP_DCD_ENDPOINT_MAX 8 + #define FSDEV_PMA_SIZE 512u #else #error "Unsupported STM32F1 mcu" #endif @@ -210,7 +215,16 @@ #elif TU_CHECK_MCU(OPT_MCU_STM32F3) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define TUP_DCD_ENDPOINT_MAX 8 + + #if defined(STM32F302xB) || defined(STM32F302xC) || defined(STM32F303xB) || defined(STM32F303xC) || \ + defined(STM32F373xC) + #define FSDEV_PMA_SIZE 512u + #elif defined(STM32F302x6) || defined(STM32F302x8) || defined(STM32F302xD) || defined(STM32F302xE) || \ + defined(STM32F303xD) || defined(STM32F303xE) + #define FSDEV_PMA_SIZE 1024u + #else + #error "Unsupported STM32F3 mcu" + #endif #elif TU_CHECK_MCU(OPT_MCU_STM32F4) #define TUP_USBIP_DWC2 @@ -236,6 +250,26 @@ #define CFG_TUH_MEM_DCACHE_ENABLE_DEFAULT CFG_TUH_DWC2_DMA_ENABLE #define CFG_TUSB_MEM_DCACHE_LINE_SIZE_DEFAULT 32 +#elif TU_CHECK_MCU(OPT_MCU_STM32G0) + #define TUP_USBIP_FSDEV + #define TUP_USBIP_FSDEV_STM32 + #define FSDEV_PMA_SIZE 2048u + +#elif TU_CHECK_MCU(OPT_MCU_STM32G4) + // Device controller + #define TUP_USBIP_FSDEV + #define TUP_USBIP_FSDEV_STM32 + #define FSDEV_PMA_SIZE 1024u + + // TypeC controller + #define TUP_USBIP_TYPEC_STM32 + #define TUP_TYPEC_RHPORTS_NUM 1 + +#elif TU_CHECK_MCU(OPT_MCU_STM32H5) + #define TUP_USBIP_FSDEV + #define TUP_USBIP_FSDEV_STM32 + #define FSDEV_PMA_SIZE 2048u + #elif TU_CHECK_MCU(OPT_MCU_STM32H7) #include "stm32h7xx.h" #define TUP_USBIP_DWC2 @@ -250,35 +284,30 @@ #define CFG_TUSB_MEM_DCACHE_LINE_SIZE_DEFAULT 32 #endif -#elif TU_CHECK_MCU(OPT_MCU_STM32H5) - #define TUP_USBIP_FSDEV - #define TUP_USBIP_FSDEV_STM32 - #define TUP_DCD_ENDPOINT_MAX 8 +#elif TU_CHECK_MCU(OPT_MCU_STM32H7RS, OPT_MCU_STM32N6) + #define TUP_USBIP_DWC2 + #define TUP_USBIP_DWC2_STM32 -#elif TU_CHECK_MCU(OPT_MCU_STM32G4) - // Device controller - #define TUP_USBIP_FSDEV - #define TUP_USBIP_FSDEV_STM32 + // FS has 6, HS has 9 + #define TUP_DCD_ENDPOINT_MAX 9 - // TypeC controller - #define TUP_USBIP_TYPEC_STM32 - #define TUP_DCD_ENDPOINT_MAX 8 - #define TUP_TYPEC_RHPORTS_NUM 1 + // MCU with on-chip HS Phy + #define TUP_RHPORT_HIGHSPEED 1 -#elif TU_CHECK_MCU(OPT_MCU_STM32G0) - #define TUP_USBIP_FSDEV - #define TUP_USBIP_FSDEV_STM32 - #define TUP_DCD_ENDPOINT_MAX 8 + // 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_DEFAULT 32 -#elif TU_CHECK_MCU(OPT_MCU_STM32C0) +#elif TU_CHECK_MCU(OPT_MCU_STM32L0) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define TUP_DCD_ENDPOINT_MAX 8 + #define FSDEV_PMA_SIZE 1024u -#elif TU_CHECK_MCU(OPT_MCU_STM32L0, OPT_MCU_STM32L1) +#elif TU_CHECK_MCU(OPT_MCU_STM32L1) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define TUP_DCD_ENDPOINT_MAX 8 + #define FSDEV_PMA_SIZE 512u #elif TU_CHECK_MCU(OPT_MCU_STM32L4) // - L4x2, L4x3 use fsdev @@ -295,28 +324,32 @@ defined(STM32L442xx) || defined(STM32L443xx) || defined(STM32L452xx) || defined(STM32L462xx) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define TUP_DCD_ENDPOINT_MAX 8 + #define FSDEV_PMA_SIZE 1024u #else #error "Unsupported STM32L4 mcu" #endif -#elif TU_CHECK_MCU(OPT_MCU_STM32WB) +#elif TU_CHECK_MCU(OPT_MCU_STM32L5) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define TUP_DCD_ENDPOINT_MAX 8 + #define FSDEV_PMA_SIZE (1024u) -#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_STM32U0) + #define TUP_USBIP_FSDEV + #define TUP_USBIP_FSDEV_STM32 + #define FSDEV_PMA_SIZE 1024u + +#elif TU_CHECK_MCU(OPT_MCU_STM32U3) + #define TUP_USBIP_FSDEV + #define TUP_USBIP_FSDEV_STM32 + #define FSDEV_PMA_SIZE 2048u #elif TU_CHECK_MCU(OPT_MCU_STM32U5) + // U535/545 use fsdev #if defined(STM32U535xx) || defined(STM32U545xx) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define TUP_DCD_ENDPOINT_MAX 8 - + #define FSDEV_PMA_SIZE 2048u #else #define TUP_USBIP_DWC2 #define TUP_USBIP_DWC2_STM32 @@ -331,35 +364,16 @@ #endif #endif -#elif TU_CHECK_MCU(OPT_MCU_STM32L5) - #define TUP_USBIP_FSDEV - #define TUP_USBIP_FSDEV_STM32 - #define TUP_DCD_ENDPOINT_MAX 8 - -#elif TU_CHECK_MCU(OPT_MCU_STM32U0) +#elif TU_CHECK_MCU(OPT_MCU_STM32WB) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define TUP_DCD_ENDPOINT_MAX 8 + #define FSDEV_PMA_SIZE 1024u -#elif TU_CHECK_MCU(OPT_MCU_STM32U3) - #define TUP_USBIP_FSDEV - #define TUP_USBIP_FSDEV_STM32 - #define TUP_DCD_ENDPOINT_MAX 8 - -#elif TU_CHECK_MCU(OPT_MCU_STM32H7RS, OPT_MCU_STM32N6) +#elif TU_CHECK_MCU(OPT_MCU_STM32WBA) #define TUP_USBIP_DWC2 #define TUP_USBIP_DWC2_STM32 - - // FS has 6, HS has 9 - #define TUP_DCD_ENDPOINT_MAX 9 - - // MCU with on-chip HS Phy - #define TUP_RHPORT_HIGHSPEED 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_DEFAULT 32 + #define TUP_DCD_ENDPOINT_MAX 9 + #define TUP_RHPORT_HIGHSPEED 1 //--------------------------------------------------------------------+ // Sony @@ -566,6 +580,7 @@ #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_CH32 + #define FSDEV_PMA_SIZE 512u // default to FSDEV for device #if !defined(CFG_TUD_WCH_USBIP_USBFS) @@ -611,15 +626,10 @@ //--------------------------------------------------------------------+ // ArteryTek //--------------------------------------------------------------------+ -#elif TU_CHECK_MCU(OPT_MCU_AT32F403A_407) +#elif TU_CHECK_MCU(OPT_MCU_AT32F403A_407, OPT_MCU_AT32F413) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_AT32 - #define TUP_DCD_ENDPOINT_MAX 8 - -#elif TU_CHECK_MCU(OPT_MCU_AT32F413) - #define TUP_USBIP_FSDEV - #define TUP_USBIP_FSDEV_AT32 - #define TUP_DCD_ENDPOINT_MAX 8 + #define FSDEV_PMA_SIZE 512u #elif TU_CHECK_MCU(OPT_MCU_AT32F415) #define TUP_USBIP_DWC2 @@ -655,10 +665,7 @@ #endif -//--------------------------------------------------------------------+ // External USB controller -//--------------------------------------------------------------------+ - #if defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 #ifndef CFG_TUH_MAX3421_ENDPOINT_TOTAL #define CFG_TUH_MAX3421_ENDPOINT_TOTAL (8 + 4 * (CFG_TUH_DEVICE_MAX - 1)) @@ -670,6 +677,10 @@ // Default Values //--------------------------------------------------------------------+ +#if defined(TUP_USBIP_FSDEV) + #define TUP_DCD_ENDPOINT_MAX 8 +#endif + #ifndef TUP_MCU_MULTIPLE_CORE #define TUP_MCU_MULTIPLE_CORE 0 #endif diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 087639d4b..0c6f58cfb 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -319,11 +319,13 @@ static void handle_ctr_rx(uint32_t ep_id) { } else { buf_id = BTABLE_BUF_RX; } - uint16_t const rx_count = btable_get_count(ep_id, buf_id); + const uint16_t rx_count = btable_get_count(ep_id, buf_id); uint16_t pma_addr = (uint16_t) btable_get_addr(ep_id, buf_id); if (xfer->ff) { - fsdev_read_packet_memory_ff(xfer->ff, pma_addr, rx_count); + // fsdev_read_packet_memory_ff(xfer->ff, pma_addr, rx_count); + fsdev_pma_buf_t *pma_buf = PMA_BUF_AT(pma_addr); + tu_fifo_write_from_hwfifo(xfer->ff, (void *)pma_buf, rx_count); } else { fsdev_read_packet_memory(xfer->buffer + xfer->queued_len, pma_addr, rx_count); } @@ -720,7 +722,9 @@ static void dcd_transmit_packet(xfer_ctl_t *xfer, uint16_t ep_ix) { uint16_t addr_ptr = (uint16_t) btable_get_addr(ep_ix, buf_id); if (xfer->ff) { - fsdev_write_packet_memory_ff(xfer->ff, addr_ptr, len); + // fsdev_write_packet_memory_ff(xfer->ff, addr_ptr, len); + fsdev_pma_buf_t *pma_buf = PMA_BUF_AT(addr_ptr); + tu_fifo_read_to_hwfifo(xfer->ff, (void *)(uintptr_t)pma_buf, len); } else { fsdev_write_packet_memory(addr_ptr, &(xfer->buffer[xfer->queued_len]), len); } @@ -740,7 +744,7 @@ static bool edpt_xfer(uint8_t rhport, uint8_t ep_num, tusb_dir_t dir) { (void) rhport; xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, dir); - uint8_t const ep_idx = xfer->ep_idx; + const uint8_t ep_idx = xfer->ep_idx; if (dir == TUSB_DIR_IN) { dcd_transmit_packet(xfer, ep_idx); diff --git a/src/portable/st/stm32_fsdev/fsdev_at32.h b/src/portable/st/stm32_fsdev/fsdev_at32.h index 6877dc131..e75430396 100644 --- a/src/portable/st/stm32_fsdev/fsdev_at32.h +++ b/src/portable/st/stm32_fsdev/fsdev_at32.h @@ -35,7 +35,6 @@ #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) diff --git a/src/portable/st/stm32_fsdev/fsdev_ch32.h b/src/portable/st/stm32_fsdev/fsdev_ch32.h index ee0057cb4..37ea7808e 100644 --- a/src/portable/st/stm32_fsdev/fsdev_ch32.h +++ b/src/portable/st/stm32_fsdev/fsdev_ch32.h @@ -53,7 +53,6 @@ #pragma GCC diagnostic pop #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) diff --git a/src/portable/st/stm32_fsdev/fsdev_stm32.h b/src/portable/st/stm32_fsdev/fsdev_stm32.h index 4b7d3d301..85ca88f1c 100644 --- a/src/portable/st/stm32_fsdev/fsdev_stm32.h +++ b/src/portable/st/stm32_fsdev/fsdev_stm32.h @@ -32,10 +32,23 @@ #ifndef TUSB_FSDEV_STM32_H #define TUSB_FSDEV_STM32_H -#if CFG_TUSB_MCU == OPT_MCU_STM32F0 +#if CFG_TUSB_MCU == OPT_MCU_STM32C0 + #include "stm32c0xx.h" + #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 + #define USB_EPREG_MASK USB_CHEP_REG_MASK + #define USB_CNTR_FRES USB_CNTR_USBRST + #define USB_CNTR_RESUME USB_CNTR_L2RES + #define USB_ISTR_EP_ID USB_ISTR_IDN + #define USB_EPADDR_FIELD USB_CHEP_ADDR + #define USB_CNTR_LPMODE USB_CNTR_SUSPRDY + #define USB_CNTR_FSUSP USB_CNTR_SUSPEN + +#elif CFG_TUSB_MCU == OPT_MCU_STM32F0 #include "stm32f0xx.h" - #define FSDEV_PMA_SIZE (1024u) - #define FSDEV_REG_BASE USB_BASE + #define FSDEV_REG_BASE USB_BASE #define FSDEV_HAS_SBUF_ISO 0 // F0x2 models are crystal-less // All have internal D+ pull-up @@ -44,29 +57,24 @@ #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 // F1 names this differently from the rest - #define USB_CNTR_LPMODE USB_CNTR_LP_MODE + #define USB_CNTR_LPMODE USB_CNTR_LP_MODE -#elif defined(STM32F302xB) || defined(STM32F302xC) || \ - defined(STM32F303xB) || defined(STM32F303xC) || \ - defined(STM32F373xC) +#elif defined(STM32F302xB) || defined(STM32F302xC) || defined(STM32F303xB) || defined(STM32F303xC) || \ + 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) -#elif defined(STM32F302x6) || defined(STM32F302x8) || \ - defined(STM32F302xD) || defined(STM32F302xE) || \ - defined(STM32F303xD) || defined(STM32F303xE) +#elif defined(STM32F302x6) || defined(STM32F302x8) || defined(STM32F302xD) || defined(STM32F302xE) || \ + 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 @@ -74,28 +82,32 @@ #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) +#elif CFG_TUSB_MCU == OPT_MCU_STM32L4 + #include "stm32l4xx.h" #define FSDEV_HAS_SBUF_ISO 0 +#elif CFG_TUSB_MCU == OPT_MCU_STM32L5 + #include "stm32l5xx.h" + #define FSDEV_HAS_SBUF_ISO 0 + + #ifndef USB_PMAADDR + #define USB_PMAADDR (USB_BASE + (USB_PMAADDR_NS - USB_BASE_NS)) + #endif + #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 FSDEV_HAS_SBUF_ISO 1 + #define USB USB_DRD_FS - #define USB_EP_CTR_RX USB_EP_VTRX - #define USB_EP_CTR_TX USB_EP_VTTX - #define USB_EP_T_FIELD USB_CHEP_UTYPE + #define USB_EP_CTR_RX USB_EP_VTRX + #define USB_EP_CTR_TX USB_EP_VTTX + #define USB_EP_T_FIELD USB_CHEP_UTYPE #define USB_EPREG_MASK USB_CHEP_REG_MASK #define USB_EPTX_DTOGMASK USB_CHEP_TX_DTOGMASK #define USB_EPRX_DTOGMASK USB_CHEP_RX_DTOGMASK @@ -110,78 +122,20 @@ #define USB_ISTR_EP_ID USB_ISTR_IDN #define USB_EPADDR_FIELD USB_CHEP_ADDR #define USB_CNTR_LPMODE USB_CNTR_SUSPRDY - #define USB_CNTR_FSUSP USB_CNTR_SUSPEN + #define USB_CNTR_FSUSP USB_CNTR_SUSPEN -#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 - #define USB_EPREG_MASK USB_CHEP_REG_MASK - #define USB_CNTR_FRES USB_CNTR_USBRST - #define USB_CNTR_RESUME USB_CNTR_L2RES - #define USB_ISTR_EP_ID USB_ISTR_IDN - #define USB_EPADDR_FIELD USB_CHEP_ADDR - #define USB_CNTR_LPMODE USB_CNTR_SUSPRDY - #define USB_CNTR_FSUSP USB_CNTR_SUSPEN +#elif CFG_TUSB_MCU == OPT_MCU_STM32G4 + #include "stm32g4xx.h" + #define FSDEV_HAS_SBUF_ISO 0 #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 - #define USB_EP_CTR_TX USB_EP_VTTX - #define USB_EP_T_FIELD USB_CHEP_UTYPE - #define USB_EPREG_MASK USB_CHEP_REG_MASK - #define USB_EPTX_DTOGMASK USB_CHEP_TX_DTOGMASK - #define USB_EPRX_DTOGMASK USB_CHEP_RX_DTOGMASK - #define USB_EPTX_DTOG1 USB_CHEP_TX_DTOG1 - #define USB_EPTX_DTOG2 USB_CHEP_TX_DTOG2 - #define USB_EPRX_DTOG1 USB_CHEP_RX_DTOG1 - #define USB_EPRX_DTOG2 USB_CHEP_RX_DTOG2 - #define USB_EPRX_STAT USB_CH_RX_VALID - #define USB_EPKIND_MASK USB_EP_KIND_MASK - #define USB_CNTR_FRES USB_CNTR_USBRST - #define USB_CNTR_RESUME USB_CNTR_L2RES - #define USB_ISTR_EP_ID USB_ISTR_IDN - #define USB_EPADDR_FIELD USB_CHEP_ADDR - #define USB_CNTR_LPMODE USB_CNTR_SUSPRDY - #define USB_CNTR_FSUSP USB_CNTR_SUSPEN - -#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)) - #endif - -#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 USB_DRD_FS - #define USB_EP_CTR_RX USB_EP_VTRX - #define USB_EP_CTR_TX USB_EP_VTTX - #define USB_EP_T_FIELD USB_CHEP_UTYPE + #define USB_EP_CTR_RX USB_EP_VTRX + #define USB_EP_CTR_TX USB_EP_VTTX + #define USB_EP_T_FIELD USB_CHEP_UTYPE #define USB_EPREG_MASK USB_CHEP_REG_MASK #define USB_EPTX_DTOGMASK USB_CHEP_TX_DTOGMASK #define USB_EPRX_DTOGMASK USB_CHEP_RX_DTOGMASK @@ -200,7 +154,6 @@ #elif CFG_TUSB_MCU == OPT_MCU_STM32U0 #include "stm32u0xx.h" - #define FSDEV_PMA_SIZE (1024u) #define FSDEV_BUS_32BIT #define FSDEV_HAS_SBUF_ISO 1 #define USB USB_DRD_FS @@ -226,10 +179,9 @@ #elif CFG_TUSB_MCU == OPT_MCU_STM32U3 #include "stm32u3xx.h" - #define FSDEV_PMA_SIZE (2048u) #define FSDEV_BUS_32BIT #define FSDEV_HAS_SBUF_ISO 1 // This is assumed to work but has not been tested... - #define USB USB_DRD_FS + #define USB USB_DRD_FS #define USB_EP_CTR_RX USB_EP_VTRX #define USB_EP_CTR_TX USB_EP_VTTX @@ -240,15 +192,45 @@ #define USB_EPTX_DTOG1 USB_CHEP_TX_DTOG1 #define USB_EPTX_DTOG2 USB_CHEP_TX_DTOG2 #define USB_EPRX_DTOG1 USB_CHEP_RX_DTOG1 - #define USB_EPRX_DTOG2 USB_CHEP_RX_DTOG2 - #define USB_EPRX_STAT USB_CH_RX_VALID - #define USB_EPKIND_MASK USB_EP_KIND_MASK - #define USB_CNTR_FRES USB_CNTR_USBRST - #define USB_CNTR_RESUME USB_CNTR_L2RES - #define USB_ISTR_EP_ID USB_ISTR_IDN - #define USB_EPADDR_FIELD USB_CHEP_ADDR - #define USB_CNTR_LPMODE USB_CNTR_SUSPRDY - #define USB_CNTR_FSUSP USB_CNTR_SUSPEN + #define USB_EPRX_DTOG2 USB_CHEP_RX_DTOG2 + #define USB_EPRX_STAT USB_CH_RX_VALID + #define USB_EPKIND_MASK USB_EP_KIND_MASK + #define USB_CNTR_FRES USB_CNTR_USBRST + #define USB_CNTR_RESUME USB_CNTR_L2RES + #define USB_ISTR_EP_ID USB_ISTR_IDN + #define USB_EPADDR_FIELD USB_CHEP_ADDR + #define USB_CNTR_LPMODE USB_CNTR_SUSPRDY + #define USB_CNTR_FSUSP USB_CNTR_SUSPEN + +#elif CFG_TUSB_MCU == OPT_MCU_STM32U5 + #include "stm32u5xx.h" + #define FSDEV_HAS_SBUF_ISO 1 + #define USB USB_DRD_FS + + #define USB_EP_CTR_RX USB_EP_VTRX + #define USB_EP_CTR_TX USB_EP_VTTX + #define USB_EP_T_FIELD USB_CHEP_UTYPE + #define USB_EPREG_MASK USB_CHEP_REG_MASK + #define USB_EPTX_DTOGMASK USB_CHEP_TX_DTOGMASK + #define USB_EPRX_DTOGMASK USB_CHEP_RX_DTOGMASK + #define USB_EPTX_DTOG1 USB_CHEP_TX_DTOG1 + #define USB_EPTX_DTOG2 USB_CHEP_TX_DTOG2 + #define USB_EPRX_DTOG1 USB_CHEP_RX_DTOG1 + #define USB_EPRX_DTOG2 USB_CHEP_RX_DTOG2 + #define USB_EPRX_STAT USB_CH_RX_VALID + #define USB_EPKIND_MASK USB_EP_KIND_MASK + #define USB_CNTR_FRES USB_CNTR_USBRST + #define USB_CNTR_RESUME USB_CNTR_L2RES + #define USB_ISTR_EP_ID USB_ISTR_IDN + #define USB_EPADDR_FIELD USB_CHEP_ADDR + #define USB_CNTR_LPMODE USB_CNTR_SUSPRDY + #define USB_CNTR_FSUSP USB_CNTR_SUSPEN + +#elif CFG_TUSB_MCU == OPT_MCU_STM32WB + #include "stm32wbxx.h" + #define FSDEV_HAS_SBUF_ISO 0 + /* ST provided header has incorrect value of USB_PMAADDR */ + #define FSDEV_PMA_BASE USB1_PMAADDR #else #error You are using an untested or unimplemented STM32 variant. Please update the driver. diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index 8c97eaa2f..02523d0d2 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -367,7 +367,7 @@ static uint16_t epin_write_tx_fifo(dwc2_regs_t *dwc2, uint8_t epnum) { // Push packet to Tx-FIFO if (xfer->ff) { volatile uint32_t* tx_fifo = dwc2->fifo[epnum]; - tu_fifo_read_n_access_mode(xfer->ff, (void *)(uintptr_t)tx_fifo, xact_bytes, true); + tu_fifo_read_to_hwfifo(xfer->ff, (void *)(uintptr_t)tx_fifo, xact_bytes); total_bytes_written += xact_bytes; } else { dfifo_write_packet(dwc2, epnum, xfer->buffer, xact_bytes); @@ -889,7 +889,7 @@ static void handle_rxflvl_irq(uint8_t rhport) { if (byte_count != 0) { // Read packet off RxFIFO if (xfer->ff != NULL) { - tu_fifo_write_n_access_mode(xfer->ff, (const void *)(uintptr_t)rx_fifo, byte_count, true); + tu_fifo_write_from_hwfifo(xfer->ff, (const void *)(uintptr_t)rx_fifo, byte_count); } else { dfifo_read_packet(dwc2, xfer->buffer, byte_count); xfer->buffer += byte_count; diff --git a/src/tusb_option.h b/src/tusb_option.h index a0f4e7057..6129a9532 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -307,13 +307,14 @@ #if defined(TUP_USBIP_DWC2) #if CFG_TUD_DWC2_SLAVE_ENABLE && !CFG_TUD_DWC2_DMA_ENABLE #define CFG_TUD_EDPT_DEDICATED_HWFIFO 1 - #define CFG_TUSB_FIFO_ACCESS_DATA_STRIDE 4 // 32bit access - #define CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE 0 // fixed hwfifo address #endif #if CFG_TUH_DWC2_SLAVE_ENABLE && !CFG_TUH_DWC2_DMA_ENABLE #define CFG_TUH_EDPT_DEDICATED_HWFIFO 1 #endif + + #define CFG_TUSB_FIFO_ACCESS_DATA_STRIDE 4 // 32bit access + #define CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE 0 // fixed hwfifo address #endif //------------- ChipIdea -------------// @@ -354,6 +355,17 @@ //------------ FSDEV --------------// #if defined(TUP_USBIP_FSDEV) #define CFG_TUD_EDPT_DEDICATED_HWFIFO 1 + + #if FSDEV_PMA_SIZE == 512 + #define CFG_TUSB_FIFO_ACCESS_DATA_STRIDE 2 // 16-bit data + #define CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE 4 // 32-bit address increase + #elif FSDEV_PMA_SIZE == 1024 + #define CFG_TUSB_FIFO_ACCESS_DATA_STRIDE 2 // 16-bit data + #define CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE 2 // 16-bit address increase + #elif FSDEV_PMA_SIZE == 2048 + #define CFG_TUSB_FIFO_ACCESS_DATA_STRIDE 4 // 32-bit data + #define CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE 4 // 32-bit address increase + #endif #endif //------------ MUSB --------------// diff --git a/test/unit-test/project.yml b/test/unit-test/project.yml index ea20c5f72..bf7cb5115 100644 --- a/test/unit-test/project.yml +++ b/test/unit-test/project.yml @@ -128,6 +128,7 @@ :defines: :test: - _UNITY_TEST_ + - CFG_TUD_EDPT_DEDICATED_HWFIFO=1 - CFG_TUSB_FIFO_ACCESS_DATA_STRIDE=4 - CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE=0 :release: [] -- cgit v1.3.1 From 9b5c7761cc6ea816cf35f330cb269030256be7ca Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 31 Dec 2025 17:45:20 +0700 Subject: add separate tu_hwifo_*() with data from buffer/software fifo. Remove duplicated packet write/read for fsdev --- src/common/tusb_fifo.c | 43 ++++++----- src/common/tusb_fifo.h | 26 +++++-- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 16 ++-- src/portable/st/stm32_fsdev/fsdev_common.c | 106 -------------------------- src/portable/st/stm32_fsdev/fsdev_common.h | 6 -- src/portable/synopsys/dwc2/dcd_dwc2.c | 4 +- 6 files changed, 53 insertions(+), 148 deletions(-) (limited to 'src/portable') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index bc4ee180c..a46bee955 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -128,14 +128,15 @@ enum { STRIDE_REMAIN_MASK = sizeof(stride_item_t) - 1u }; -// Copy to fifo from fixed address buffer (usually a rx register) with TU_FIFO_FIXED_ADDR_RW32 mode -static void ff_push_stride(uint8_t *ff_buf, const volatile stride_item_t *src, uint16_t len) { - // Reading full available 16/32-bit src and write to fifo +void tu_hwfifo_read(const volatile void *hwfifo, uint8_t *dest, uint16_t len) { + const volatile stride_item_t *src = (const volatile stride_item_t *)hwfifo; + + // Reading full available 16/32-bit hwfifo and write to fifo uint16_t n_items = len >> (CFG_TUSB_FIFO_ACCESS_DATA_STRIDE >> 1); // len / data_stride; while (n_items--) { const stride_item_t tmp = *src; - stride_unaligned_write(ff_buf, tmp); - ff_buf += sizeof(stride_item_t); + stride_unaligned_write(dest, tmp); + dest += sizeof(stride_item_t); #if CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE src = (const volatile stride_item_t *)((uintptr_t)src + CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE); @@ -146,17 +147,19 @@ static void ff_push_stride(uint8_t *ff_buf, const volatile stride_item_t *src, u const uint8_t bytes_rem = len & STRIDE_REMAIN_MASK; if (bytes_rem) { const stride_item_t tmp = *src; - memcpy(ff_buf, &tmp, bytes_rem); + memcpy(dest, &tmp, bytes_rem); } } // Copy from fifo to fixed address buffer (usually a tx register) with TU_FIFO_FIXED_ADDR_RW32 mode -static void ff_pull_stride(volatile stride_item_t *dest, const uint8_t *ff_buf, uint16_t len) { +void tu_hwfifo_write(volatile void *hwfifo, const uint8_t *src, uint16_t len) { + volatile stride_item_t *dest = (volatile stride_item_t *)hwfifo; + // Write full available 16/32 bit words to dest uint16_t n_items = len >> (CFG_TUSB_FIFO_ACCESS_DATA_STRIDE >> 1); // len / data_stride; while (n_items--) { - *dest = stride_unaligned_read(ff_buf); - ff_buf += sizeof(stride_item_t); + *dest = stride_unaligned_read(src); + src += sizeof(stride_item_t); #if CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE dest = (volatile stride_item_t *)((uintptr_t)dest + CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE); @@ -167,7 +170,7 @@ static void ff_pull_stride(volatile stride_item_t *dest, const uint8_t *ff_buf, const uint8_t bytes_rem = len & STRIDE_REMAIN_MASK; if (bytes_rem) { stride_item_t tmp = 0u; - memcpy(&tmp, ff_buf, bytes_rem); + memcpy(&tmp, src, bytes_rem); *dest = tmp; } } @@ -182,23 +185,23 @@ static void ff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uint1 #if CFG_TUD_EDPT_DEDICATED_HWFIFO if (stride_mode) { - const volatile stride_item_t *stride_src = (const volatile stride_item_t *)app_buf; + const volatile stride_item_t *hwfifo = (const volatile stride_item_t *)app_buf; if (n <= lin_bytes) { // Linear only case - ff_push_stride(ff_buf, stride_src, n); + tu_hwfifo_read(hwfifo, ff_buf, n); } else { // Wrap around case // Write full words to linear part of buffer uint16_t lin_nitems_bytes = lin_bytes & ~STRIDE_REMAIN_MASK; - ff_push_stride(ff_buf, stride_src, lin_nitems_bytes); + tu_hwfifo_read(hwfifo, ff_buf, lin_nitems_bytes); ff_buf += lin_nitems_bytes; // There could be odd 1 byte (16bit) or 1-3 bytes (32bit) before the wrap-around boundary const uint8_t rem = lin_bytes & STRIDE_REMAIN_MASK; if (rem > 0) { const uint8_t remrem = (uint8_t)tu_min16(wrap_bytes, sizeof(stride_item_t) - rem); - const stride_item_t tmp = *stride_src; + const stride_item_t tmp = *hwfifo; tu_scatter_write32(tmp, ff_buf, rem, f->buffer, remrem); wrap_bytes -= remrem; @@ -209,7 +212,7 @@ static void ff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uint1 // Write data wrapped part if (wrap_bytes > 0) { - ff_push_stride(ff_buf, stride_src, wrap_bytes); + tu_hwfifo_read(hwfifo, ff_buf, wrap_bytes); } } } else @@ -236,17 +239,17 @@ static void ff_pull_n(const tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t rd #if CFG_TUD_EDPT_DEDICATED_HWFIFO if (stride_mode) { - volatile stride_item_t *stride_dst = (volatile stride_item_t *)app_buf; + volatile stride_item_t *hwfifo = (volatile stride_item_t *)app_buf; if (n <= lin_bytes) { // Linear only case - ff_pull_stride(stride_dst, ff_buf, n); + tu_hwfifo_write(hwfifo, ff_buf, n); } else { // Wrap around case // Read full words from linear part uint16_t lin_nitems_bytes = lin_bytes & ~STRIDE_REMAIN_MASK; - ff_pull_stride(stride_dst, ff_buf, lin_nitems_bytes); + tu_hwfifo_write(hwfifo, ff_buf, lin_nitems_bytes); ff_buf += lin_nitems_bytes; // There could be odd 1 byte (16bit) or 1-3 bytes (32bit) before the wrap-around boundary @@ -255,7 +258,7 @@ static void ff_pull_n(const tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t rd const uint8_t remrem = (uint8_t)tu_min16(wrap_bytes, sizeof(stride_item_t) - rem); const stride_item_t scatter = (stride_item_t)tu_scatter_read32(ff_buf, rem, f->buffer, remrem); - *stride_dst = scatter; + *hwfifo = scatter; wrap_bytes -= remrem; ff_buf = f->buffer + remrem; // wrap around @@ -265,7 +268,7 @@ static void ff_pull_n(const tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t rd // Read data wrapped part if (wrap_bytes > 0) { - ff_pull_stride(stride_dst, ff_buf, wrap_bytes); + tu_hwfifo_write(hwfifo, ff_buf, wrap_bytes); } } } else diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 53c5f6e56..f28f54749 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -204,9 +204,6 @@ bool tu_fifo_read(tu_fifo_t *f, void *buffer); TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_read_n(tu_fifo_t *f, void *buffer, uint16_t n) { return tu_fifo_read_n_access_mode(f, buffer, n, false); } -TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_read_to_hwfifo(tu_fifo_t *f, void *buffer, uint16_t n) { - return tu_fifo_read_n_access_mode(f, buffer, n, true); -} // discard first n items from fifo i.e advance read pointer by n with mutex // return number of discarded items @@ -220,10 +217,29 @@ bool tu_fifo_write(tu_fifo_t *f, const void *data); TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_write_n(tu_fifo_t *f, const void *data, uint16_t n) { return tu_fifo_write_n_access_mode(f, data, n, false); } -TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_write_from_hwfifo(tu_fifo_t *f, const void *data, uint16_t n) { - return tu_fifo_write_n_access_mode(f, data, n, true); + +//--------------------------------------------------------------------+ +// Hardware FIFO API +// Special hardware FIFO/Buffer to hold USB data, usually requires certain access method these can be configured with +// CFG_TUSB_FIFO_ACCESS_DATA_STRIDE (data width) and CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE (address increment) +// Note: these usually has opposiite direction (read/write) to/from our software FIFO (tu_fifo_t) +//--------------------------------------------------------------------+ +#if CFG_TUD_EDPT_DEDICATED_HWFIFO +TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_hwfifo_write_from_fifo(tu_fifo_t *f, void *hwfifo, uint16_t n) { + return tu_fifo_read_n_access_mode(f, hwfifo, n, true); } +TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_hwfifo_read_to_fifo(tu_fifo_t *f, const void *hwfifo, uint16_t n) { + return tu_fifo_write_n_access_mode(f, hwfifo, n, true); +} + +// read from hwfifo to buffer +void tu_hwfifo_read(const volatile void *hwfifo, uint8_t *dest, uint16_t len); + +// write to hwfifo from buffer +void tu_hwfifo_write(volatile void *hwfifo, const uint8_t *src, uint16_t len); +#endif + //--------------------------------------------------------------------+ // Internal Helper Local // work on local copies of read/write indices in order to only access them once for re-entrancy diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 0c6f58cfb..cc2626383 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -321,13 +321,12 @@ static void handle_ctr_rx(uint32_t ep_id) { } const uint16_t rx_count = btable_get_count(ep_id, buf_id); uint16_t pma_addr = (uint16_t) btable_get_addr(ep_id, buf_id); + fsdev_pma_buf_t *pma_buf = PMA_BUF_AT(pma_addr); if (xfer->ff) { - // fsdev_read_packet_memory_ff(xfer->ff, pma_addr, rx_count); - fsdev_pma_buf_t *pma_buf = PMA_BUF_AT(pma_addr); - tu_fifo_write_from_hwfifo(xfer->ff, (void *)pma_buf, rx_count); + tu_hwfifo_read_to_fifo(xfer->ff, (void *)pma_buf, rx_count); } else { - fsdev_read_packet_memory(xfer->buffer + xfer->queued_len, pma_addr, rx_count); + tu_hwfifo_read(pma_buf, xfer->buffer + xfer->queued_len, rx_count); } xfer->queued_len += rx_count; @@ -719,14 +718,13 @@ static void dcd_transmit_packet(xfer_ctl_t *xfer, uint16_t ep_ix) { } else { buf_id = BTABLE_BUF_TX; } - uint16_t addr_ptr = (uint16_t) btable_get_addr(ep_ix, buf_id); + uint16_t addr_ptr = (uint16_t)btable_get_addr(ep_ix, buf_id); + fsdev_pma_buf_t *pma_buf = PMA_BUF_AT(addr_ptr); if (xfer->ff) { - // fsdev_write_packet_memory_ff(xfer->ff, addr_ptr, len); - fsdev_pma_buf_t *pma_buf = PMA_BUF_AT(addr_ptr); - tu_fifo_read_to_hwfifo(xfer->ff, (void *)(uintptr_t)pma_buf, len); + tu_hwfifo_write_from_fifo(xfer->ff, (void *)(uintptr_t)pma_buf, len); } else { - fsdev_write_packet_memory(addr_ptr, &(xfer->buffer[xfer->queued_len]), len); + tu_hwfifo_write(pma_buf, &(xfer->buffer[xfer->queued_len]), len); } xfer->queued_len += len; diff --git a/src/portable/st/stm32_fsdev/fsdev_common.c b/src/portable/st/stm32_fsdev/fsdev_common.c index 5d60ad9a2..19f36b492 100644 --- a/src/portable/st/stm32_fsdev/fsdev_common.c +++ b/src/portable/st/stm32_fsdev/fsdev_common.c @@ -136,112 +136,6 @@ bool fsdev_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t nbyte return true; } -// Write to PMA from FIFO -bool fsdev_write_packet_memory_ff(tu_fifo_t *ff, uint16_t dst, uint16_t wNBytes) { - if (wNBytes == 0) { - return true; - } - - // Since we copy from a ring buffer FIFO, a wrap might occur making it necessary to conduct two copies - tu_fifo_buffer_info_t info; - tu_fifo_get_read_info(ff, &info); - - uint16_t cnt_lin = tu_min16(wNBytes, info.linear.len); - uint16_t cnt_wrap = tu_min16(wNBytes - cnt_lin, info.wrapped.len); - uint16_t const cnt_total = cnt_lin + cnt_wrap; - - // We want to read from the FIFO and write it into the PMA, if LIN part is ODD and has WRAPPED part, - // last lin byte will be combined with wrapped part To ensure PMA is always access aligned - uint16_t lin_even = cnt_lin & ~(FSDEV_BUS_SIZE - 1); - uint16_t lin_odd = cnt_lin & (FSDEV_BUS_SIZE - 1); - uint8_t const *src8 = (uint8_t const*) info.linear.ptr; - - // write even linear part - fsdev_write_packet_memory(dst, src8, lin_even); - dst += lin_even; - src8 += lin_even; - - if (lin_odd == 0) { - src8 = (uint8_t const*) info.wrapped.ptr; - } else { - // Combine last linear bytes + first wrapped bytes to form fsdev bus width data - fsdev_bus_t temp = 0; - uint16_t i; - for(i = 0; i < lin_odd; i++) { - temp |= *src8++ << (i * 8); - } - - src8 = (uint8_t const*) info.wrapped.ptr; - for(; i < FSDEV_BUS_SIZE && cnt_wrap > 0; i++, cnt_wrap--) { - temp |= *src8++ << (i * 8); - } - - fsdev_write_packet_memory(dst, &temp, FSDEV_BUS_SIZE); - dst += FSDEV_BUS_SIZE; - } - - // write the rest of the wrapped part - fsdev_write_packet_memory(dst, src8, cnt_wrap); - - tu_fifo_advance_read_pointer(ff, cnt_total); - return true; -} - -// Read from PMA to FIFO -bool fsdev_read_packet_memory_ff(tu_fifo_t *ff, uint16_t src, uint16_t wNBytes) { - if (wNBytes == 0) { - return true; - } - - // Since we copy into a ring buffer FIFO, a wrap might occur making it necessary to conduct two copies - // Check for first linear part - tu_fifo_buffer_info_t info; - tu_fifo_get_write_info(ff, &info); // We want to read from the FIFO - - uint16_t cnt_lin = tu_min16(wNBytes, info.linear.len); - uint16_t cnt_wrap = tu_min16(wNBytes - cnt_lin, info.wrapped.len); - uint16_t cnt_total = cnt_lin + cnt_wrap; - - // We want to read from the FIFO and write it into the PMA, if LIN part is ODD and has WRAPPED part, - // last lin byte will be combined with wrapped part To ensure PMA is always access aligned - - uint16_t lin_even = cnt_lin & ~(FSDEV_BUS_SIZE - 1); - uint16_t lin_odd = cnt_lin & (FSDEV_BUS_SIZE - 1); - uint8_t *dst8 = (uint8_t *) info.linear.ptr; - - // read even linear part - fsdev_read_packet_memory(dst8, src, lin_even); - dst8 += lin_even; - src += lin_even; - - if (lin_odd == 0) { - dst8 = (uint8_t *) info.wrapped.ptr; - } else { - // Combine last linear bytes + first wrapped bytes to form fsdev bus width data - fsdev_bus_t temp; - fsdev_read_packet_memory(&temp, src, FSDEV_BUS_SIZE); - src += FSDEV_BUS_SIZE; - - uint16_t i; - for (i = 0; i < lin_odd; i++) { - *dst8++ = (uint8_t) (temp & 0xfful); - temp >>= 8; - } - - dst8 = (uint8_t *) info.wrapped.ptr; - for (; i < FSDEV_BUS_SIZE && cnt_wrap > 0; i++, cnt_wrap--) { - *dst8++ = (uint8_t) (temp & 0xfful); - temp >>= 8; - } - } - - // read the rest of the wrapped part - fsdev_read_packet_memory(dst8, src, cnt_wrap); - - tu_fifo_advance_write_pointer(ff, cnt_total); - return true; -} - //--------------------------------------------------------------------+ // BTable Helper //--------------------------------------------------------------------+ diff --git a/src/portable/st/stm32_fsdev/fsdev_common.h b/src/portable/st/stm32_fsdev/fsdev_common.h index 0c67ee0c7..4715f438f 100644 --- a/src/portable/st/stm32_fsdev/fsdev_common.h +++ b/src/portable/st/stm32_fsdev/fsdev_common.h @@ -337,12 +337,6 @@ bool fsdev_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_ // - Uses unaligned for RAM (since M0 cannot access unaligned address) bool fsdev_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t nbytes); -// Write to PMA from FIFO -bool fsdev_write_packet_memory_ff(tu_fifo_t *ff, uint16_t dst, uint16_t wNBytes); - -// Read from PMA to FIFO -bool fsdev_read_packet_memory_ff(tu_fifo_t *ff, uint16_t src, uint16_t wNBytes); - #ifdef __cplusplus } #endif diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index 02523d0d2..ea952dbcc 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -367,7 +367,7 @@ static uint16_t epin_write_tx_fifo(dwc2_regs_t *dwc2, uint8_t epnum) { // Push packet to Tx-FIFO if (xfer->ff) { volatile uint32_t* tx_fifo = dwc2->fifo[epnum]; - tu_fifo_read_to_hwfifo(xfer->ff, (void *)(uintptr_t)tx_fifo, xact_bytes); + tu_hwfifo_write_from_fifo(xfer->ff, (void *)(uintptr_t)tx_fifo, xact_bytes); total_bytes_written += xact_bytes; } else { dfifo_write_packet(dwc2, epnum, xfer->buffer, xact_bytes); @@ -889,7 +889,7 @@ static void handle_rxflvl_irq(uint8_t rhport) { if (byte_count != 0) { // Read packet off RxFIFO if (xfer->ff != NULL) { - tu_fifo_write_from_hwfifo(xfer->ff, (const void *)(uintptr_t)rx_fifo, byte_count); + tu_hwfifo_read_to_fifo(xfer->ff, (const void *)(uintptr_t)rx_fifo, byte_count); } else { dfifo_read_packet(dwc2, xfer->buffer, byte_count); xfer->buffer += byte_count; -- cgit v1.3.1 From 111247337c3911691acd7d218362460a6c0a2572 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 31 Dec 2025 18:01:50 +0700 Subject: replace PMA buffer packet read/write by using tu_hwfifo API --- src/common/tusb_fifo.c | 6 +-- src/common/tusb_fifo.h | 4 +- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 2 +- src/portable/st/stm32_fsdev/fsdev_common.c | 67 --------------------------- src/portable/st/stm32_fsdev/fsdev_common.h | 14 ------ src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c | 16 +++---- 6 files changed, 15 insertions(+), 94 deletions(-) (limited to 'src/portable') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index a46bee955..8be137628 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -113,7 +113,7 @@ void tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable) { // Pull & Push // copy data to/from fifo without updating read/write pointers //--------------------------------------------------------------------+ -#if CFG_TUD_EDPT_DEDICATED_HWFIFO +#if CFG_TUSB_FIFO_HWFIFO_API #if CFG_TUSB_FIFO_ACCESS_DATA_STRIDE == 4 #define stride_unaligned_write tu_unaligned_write32 #define stride_unaligned_read tu_unaligned_read32 @@ -183,7 +183,7 @@ static void ff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uint1 uint16_t wrap_bytes = n - lin_bytes; uint8_t *ff_buf = f->buffer + wr_ptr; -#if CFG_TUD_EDPT_DEDICATED_HWFIFO +#if CFG_TUSB_FIFO_HWFIFO_API if (stride_mode) { const volatile stride_item_t *hwfifo = (const volatile stride_item_t *)app_buf; if (n <= lin_bytes) { @@ -237,7 +237,7 @@ static void ff_pull_n(const tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t rd uint16_t wrap_bytes = n - lin_bytes; // only used if wrapped const uint8_t *ff_buf = f->buffer + rd_ptr; -#if CFG_TUD_EDPT_DEDICATED_HWFIFO +#if CFG_TUSB_FIFO_HWFIFO_API if (stride_mode) { volatile stride_item_t *hwfifo = (volatile stride_item_t *)app_buf; diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index f28f54749..b17f6a1d6 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -41,6 +41,8 @@ extern "C" { // mutex is only needed for RTOS. For OS None, we don't get preempted #define CFG_FIFO_MUTEX OSAL_MUTEX_REQUIRED +#define CFG_TUSB_FIFO_HWFIFO_API (CFG_TUD_EDPT_DEDICATED_HWFIFO) + #ifndef CFG_TUSB_FIFO_ACCESS_DATA_STRIDE #define CFG_TUSB_FIFO_ACCESS_DATA_STRIDE 0 #endif @@ -224,7 +226,6 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_write_n(tu_fifo_t *f, const // CFG_TUSB_FIFO_ACCESS_DATA_STRIDE (data width) and CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE (address increment) // Note: these usually has opposiite direction (read/write) to/from our software FIFO (tu_fifo_t) //--------------------------------------------------------------------+ -#if CFG_TUD_EDPT_DEDICATED_HWFIFO TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_hwfifo_write_from_fifo(tu_fifo_t *f, void *hwfifo, uint16_t n) { return tu_fifo_read_n_access_mode(f, hwfifo, n, true); } @@ -233,6 +234,7 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_hwfifo_read_to_fifo(tu_fifo_t *f return tu_fifo_write_n_access_mode(f, hwfifo, n, true); } +#if CFG_TUSB_FIFO_HWFIFO_API // read from hwfifo to buffer void tu_hwfifo_read(const volatile void *hwfifo, uint8_t *dest, uint16_t len); diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index cc2626383..dae921049 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -285,7 +285,7 @@ static void handle_ctr_setup(uint32_t ep_id) { uint16_t rx_addr = btable_get_addr(ep_id, BTABLE_BUF_RX); uint8_t setup_packet[8] TU_ATTR_ALIGNED(4); - fsdev_read_packet_memory(setup_packet, rx_addr, rx_count); + tu_hwfifo_read(PMA_BUF_AT(rx_addr), setup_packet, rx_count); // Clear CTR RX if another setup packet arrived before this, it will be discarded ep_write_clear_ctr(ep_id, TUSB_DIR_OUT); diff --git a/src/portable/st/stm32_fsdev/fsdev_common.c b/src/portable/st/stm32_fsdev/fsdev_common.c index 19f36b492..4f127ae86 100644 --- a/src/portable/st/stm32_fsdev/fsdev_common.c +++ b/src/portable/st/stm32_fsdev/fsdev_common.c @@ -69,73 +69,6 @@ void fsdev_deinit(void) { } } - -//--------------------------------------------------------------------+ -// PMA read/write -//--------------------------------------------------------------------+ - -// Write to packet memory area (PMA) from user memory -// - Packet memory must be either strictly 16-bit or 32-bit depending on FSDEV_BUS_32BIT -// - Uses unaligned for RAM (since M0 cannot access unaligned address) -bool fsdev_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t nbytes) { - if (nbytes == 0) { - return true; - } - uint32_t n_write = nbytes / FSDEV_BUS_SIZE; - - fsdev_pma_buf_t* pma_buf = PMA_BUF_AT(dst); - const uint8_t *src8 = src; - - while (n_write--) { - pma_buf->value = fsdevbus_unaligned_read(src8); - src8 += FSDEV_BUS_SIZE; - pma_buf++; - } - - // odd bytes e.g 1 for 16-bit or 1-3 for 32-bit - uint16_t odd = nbytes & (FSDEV_BUS_SIZE - 1); - if (odd) { - fsdev_bus_t temp = 0; - for(uint16_t i = 0; i < odd; i++) { - temp |= *src8++ << (i * 8); - } - pma_buf->value = temp; - } - - return true; -} - -// Read from packet memory area (PMA) to user memory. -// - Packet memory must be either strictly 16-bit or 32-bit depending on FSDEV_BUS_32BIT -// - Uses unaligned for RAM (since M0 cannot access unaligned address) -bool fsdev_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t nbytes) { - if (nbytes == 0) { - return true; - } - uint32_t n_read = nbytes / FSDEV_BUS_SIZE; - - fsdev_pma_buf_t* pma_buf = PMA_BUF_AT(src); - uint8_t *dst8 = (uint8_t *)dst; - - while (n_read--) { - fsdevbus_unaligned_write(dst8, (fsdev_bus_t ) pma_buf->value); - dst8 += FSDEV_BUS_SIZE; - pma_buf++; - } - - // odd bytes e.g 1 for 16-bit or 1-3 for 32-bit - uint16_t odd = nbytes & (FSDEV_BUS_SIZE - 1); - if (odd) { - fsdev_bus_t temp = pma_buf->value; - while (odd--) { - *dst8++ = (uint8_t) (temp & 0xfful); - temp >>= 8; - } - } - - return true; -} - //--------------------------------------------------------------------+ // BTable Helper //--------------------------------------------------------------------+ diff --git a/src/portable/st/stm32_fsdev/fsdev_common.h b/src/portable/st/stm32_fsdev/fsdev_common.h index 4715f438f..69440aa32 100644 --- a/src/portable/st/stm32_fsdev/fsdev_common.h +++ b/src/portable/st/stm32_fsdev/fsdev_common.h @@ -323,20 +323,6 @@ uint16_t pma_align_buffer_size(uint16_t size, uint8_t* blsize, uint8_t* num_bloc // Set RX buffer size void btable_set_rx_bufsize(uint32_t ep_id, uint8_t buf_id, uint16_t wCount); -//--------------------------------------------------------------------+ -// PMA (Packet Memory Area) Access -//--------------------------------------------------------------------+ - -// Write to packet memory area (PMA) from user memory -// - Packet memory must be either strictly 16-bit or 32-bit depending on FSDEV_BUS_32BIT -// - Uses unaligned for RAM (since M0 cannot access unaligned address) -bool fsdev_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t nbytes); - -// Read from packet memory area (PMA) to user memory. -// - Packet memory must be either strictly 16-bit or 32-bit depending on FSDEV_BUS_32BIT -// - Uses unaligned for RAM (since M0 cannot access unaligned address) -bool fsdev_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t nbytes); - #ifdef __cplusplus } #endif diff --git a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c index da9c6961c..480e460cb 100644 --- a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c @@ -303,10 +303,12 @@ static void ch_handle_ack(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) { uint8_t const daddr = (ch_reg & USB_CHEP_DEVADDR_Msk) >> USB_CHEP_DEVADDR_Pos; uint8_t ep_id = endpoint_find(daddr, ep_num | (dir == TUSB_DIR_IN ? TUSB_DIR_IN_MASK : 0)); - if (ep_id == TUSB_INDEX_INVALID_8) return; + if (ep_id == TUSB_INDEX_INVALID_8) { + return; + } - hcd_endpoint_t* edpt = &_hcd_data.edpt[ep_id]; - hcd_channel_t* channel = &_hcd_data.channel[ch_id]; + hcd_endpoint_t *edpt = &_hcd_data.edpt[ep_id]; + hcd_channel_t *channel = &_hcd_data.channel[ch_id]; if (dir == TUSB_DIR_OUT) { // OUT/TX direction @@ -314,7 +316,7 @@ static void ch_handle_ack(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) { // More data to send uint16_t const len = tu_min16(edpt->buflen - edpt->queued_len, edpt->max_packet_size); uint16_t pma_addr = (uint16_t) btable_get_addr(ch_id, BTABLE_BUF_TX); - fsdev_write_packet_memory(pma_addr, &(edpt->buffer[edpt->queued_len]), len); + tu_hwfifo_write(PMA_BUF_AT(pma_addr), &(edpt->buffer[edpt->queued_len]), len); btable_set_count(ch_id, BTABLE_BUF_TX, len); edpt->queued_len += len; channel_write_status(ch_id, ch_reg, TUSB_DIR_OUT, EP_STAT_VALID, false); @@ -329,8 +331,7 @@ static void ch_handle_ack(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) { // IN/RX direction uint16_t const rx_count = channel_get_rx_count(ch_id); uint16_t pma_addr = (uint16_t) btable_get_addr(ch_id, BTABLE_BUF_RX); - - fsdev_read_packet_memory(edpt->buffer + edpt->queued_len, pma_addr, rx_count); + tu_hwfifo_read(PMA_BUF_AT(pma_addr), edpt->buffer + edpt->queued_len, rx_count); edpt->queued_len += rx_count; if ((rx_count < edpt->max_packet_size) || (edpt->queued_len >= edpt->buflen)) { @@ -841,8 +842,7 @@ static bool channel_xfer_start(uint8_t ch_id, tusb_dir_t dir) { if (dir == TUSB_DIR_OUT) { uint16_t const len = tu_min16(edpt->buflen - edpt->queued_len, edpt->max_packet_size); - - fsdev_write_packet_memory(pma_addr, &(edpt->buffer[edpt->queued_len]), len); + tu_hwfifo_write(PMA_BUF_AT(pma_addr), &(edpt->buffer[edpt->queued_len]), len); btable_set_count(ch_id, BTABLE_BUF_TX, len); edpt->queued_len += len; -- cgit v1.3.1 From 009750c747ff1d5a25d976de9161b974eb5f18e7 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 1 Jan 2026 11:35:09 +0700 Subject: minor refactor --- src/common/tusb_fifo.c | 62 ++++++++++++++++------------------ src/common/tusb_fifo.h | 12 +++---- src/portable/renesas/rusb2/dcd_rusb2.c | 9 +++-- src/tusb_option.h | 19 ++++++----- test/unit-test/project.yml | 4 +-- 5 files changed, 55 insertions(+), 51 deletions(-) (limited to 'src/portable') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 8be137628..38b00d9d6 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -114,63 +114,61 @@ void tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable) { // copy data to/from fifo without updating read/write pointers //--------------------------------------------------------------------+ #if CFG_TUSB_FIFO_HWFIFO_API - #if CFG_TUSB_FIFO_ACCESS_DATA_STRIDE == 4 + #if CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE == 4 #define stride_unaligned_write tu_unaligned_write32 #define stride_unaligned_read tu_unaligned_read32 -typedef uint32_t stride_item_t; - #elif CFG_TUSB_FIFO_ACCESS_DATA_STRIDE == 2 +typedef uint32_t hwfifo_item_t; + #elif CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE == 2 #define stride_unaligned_write tu_unaligned_write16 #define stride_unaligned_read tu_unaligned_read16 -typedef uint16_t stride_item_t; +typedef uint16_t hwfifo_item_t; #endif enum { - STRIDE_REMAIN_MASK = sizeof(stride_item_t) - 1u + STRIDE_REMAIN_MASK = sizeof(hwfifo_item_t) - 1u }; void tu_hwfifo_read(const volatile void *hwfifo, uint8_t *dest, uint16_t len) { - const volatile stride_item_t *src = (const volatile stride_item_t *)hwfifo; + const volatile hwfifo_item_t *src = (const volatile hwfifo_item_t *)hwfifo; // Reading full available 16/32-bit hwfifo and write to fifo - uint16_t n_items = len >> (CFG_TUSB_FIFO_ACCESS_DATA_STRIDE >> 1); // len / data_stride; - while (n_items--) { - const stride_item_t tmp = *src; + while (len >= sizeof(hwfifo_item_t)) { + const hwfifo_item_t tmp = *src; stride_unaligned_write(dest, tmp); - dest += sizeof(stride_item_t); + dest += sizeof(hwfifo_item_t); + len -= sizeof(hwfifo_item_t); - #if CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE - src = (const volatile stride_item_t *)((uintptr_t)src + CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE); + #if CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE + src = (const volatile hwfifo_item_t *)((uintptr_t)src + CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE); #endif } // Read the remaining 1 byte (16bit) or 1-3 bytes (32bit) - const uint8_t bytes_rem = len & STRIDE_REMAIN_MASK; - if (bytes_rem) { - const stride_item_t tmp = *src; - memcpy(dest, &tmp, bytes_rem); + if (len > 0) { + const hwfifo_item_t tmp = *src; + memcpy(dest, &tmp, len); } } // Copy from fifo to fixed address buffer (usually a tx register) with TU_FIFO_FIXED_ADDR_RW32 mode void tu_hwfifo_write(volatile void *hwfifo, const uint8_t *src, uint16_t len) { - volatile stride_item_t *dest = (volatile stride_item_t *)hwfifo; + volatile hwfifo_item_t *dest = (volatile hwfifo_item_t *)hwfifo; // Write full available 16/32 bit words to dest - uint16_t n_items = len >> (CFG_TUSB_FIFO_ACCESS_DATA_STRIDE >> 1); // len / data_stride; - while (n_items--) { + while (len >= sizeof(hwfifo_item_t)) { *dest = stride_unaligned_read(src); - src += sizeof(stride_item_t); + src += sizeof(hwfifo_item_t); + len -= sizeof(hwfifo_item_t); - #if CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE - dest = (volatile stride_item_t *)((uintptr_t)dest + CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE); + #if CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE + dest = (volatile hwfifo_item_t *)((uintptr_t)dest + CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE); #endif } // Write the remaining 1 byte (16bit) or 1-3 bytes (32bit) - const uint8_t bytes_rem = len & STRIDE_REMAIN_MASK; - if (bytes_rem) { - stride_item_t tmp = 0u; - memcpy(&tmp, src, bytes_rem); + if (len > 0) { + hwfifo_item_t tmp = 0u; + memcpy(&tmp, src, len); *dest = tmp; } } @@ -185,7 +183,7 @@ static void ff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uint1 #if CFG_TUSB_FIFO_HWFIFO_API if (stride_mode) { - const volatile stride_item_t *hwfifo = (const volatile stride_item_t *)app_buf; + const volatile hwfifo_item_t *hwfifo = (const volatile hwfifo_item_t *)app_buf; if (n <= lin_bytes) { // Linear only case tu_hwfifo_read(hwfifo, ff_buf, n); @@ -200,8 +198,8 @@ static void ff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uint1 // There could be odd 1 byte (16bit) or 1-3 bytes (32bit) before the wrap-around boundary const uint8_t rem = lin_bytes & STRIDE_REMAIN_MASK; if (rem > 0) { - const uint8_t remrem = (uint8_t)tu_min16(wrap_bytes, sizeof(stride_item_t) - rem); - const stride_item_t tmp = *hwfifo; + const uint8_t remrem = (uint8_t)tu_min16(wrap_bytes, sizeof(hwfifo_item_t) - rem); + const hwfifo_item_t tmp = *hwfifo; tu_scatter_write32(tmp, ff_buf, rem, f->buffer, remrem); wrap_bytes -= remrem; @@ -239,7 +237,7 @@ static void ff_pull_n(const tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t rd #if CFG_TUSB_FIFO_HWFIFO_API if (stride_mode) { - volatile stride_item_t *hwfifo = (volatile stride_item_t *)app_buf; + volatile hwfifo_item_t *hwfifo = (volatile hwfifo_item_t *)app_buf; if (n <= lin_bytes) { // Linear only case @@ -255,8 +253,8 @@ static void ff_pull_n(const tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t rd // There could be odd 1 byte (16bit) or 1-3 bytes (32bit) before the wrap-around boundary const uint8_t rem = lin_bytes & STRIDE_REMAIN_MASK; if (rem > 0) { - const uint8_t remrem = (uint8_t)tu_min16(wrap_bytes, sizeof(stride_item_t) - rem); - const stride_item_t scatter = (stride_item_t)tu_scatter_read32(ff_buf, rem, f->buffer, remrem); + const uint8_t remrem = (uint8_t)tu_min16(wrap_bytes, sizeof(hwfifo_item_t) - rem); + const hwfifo_item_t scatter = (hwfifo_item_t)tu_scatter_read32(ff_buf, rem, f->buffer, remrem); *hwfifo = scatter; diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index b17f6a1d6..2473a5605 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -43,12 +43,12 @@ extern "C" { #define CFG_TUSB_FIFO_HWFIFO_API (CFG_TUD_EDPT_DEDICATED_HWFIFO) -#ifndef CFG_TUSB_FIFO_ACCESS_DATA_STRIDE - #define CFG_TUSB_FIFO_ACCESS_DATA_STRIDE 0 +#ifndef CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE + #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE 0 #endif -#ifndef CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE - #define CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE 0 +#ifndef CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE + #define CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE 0 #endif // Due to the use of unmasked pointers, this FIFO does not suffer from losing @@ -153,7 +153,7 @@ typedef struct { // Moving data from tusb_fifo <-> USB hardware FIFOs e.g. STM32s need to use a special stride mode which reads/writes // data in 2/4 byte chunks from/to a fixed address (USB FIFO register) instead of incrementing the address. For this use // read/write access_mode with stride_mode = true. The STRIPE DATA and ADDR stride must be configured with -// CFG_TUSB_FIFO_ACCESS_DATA_STRIDE and CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE +// CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE and CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE //--------------------------------------------------------------------+ // Setup API @@ -223,7 +223,7 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_write_n(tu_fifo_t *f, const //--------------------------------------------------------------------+ // Hardware FIFO API // Special hardware FIFO/Buffer to hold USB data, usually requires certain access method these can be configured with -// CFG_TUSB_FIFO_ACCESS_DATA_STRIDE (data width) and CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE (address increment) +// CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE (data width) and CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE (address increment) // Note: these usually has opposiite direction (read/write) to/from our software FIFO (tu_fifo_t) //--------------------------------------------------------------------+ TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_hwfifo_write_from_fifo(tu_fifo_t *f, void *hwfifo, uint16_t n) { diff --git a/src/portable/renesas/rusb2/dcd_rusb2.c b/src/portable/renesas/rusb2/dcd_rusb2.c index 779c7bc3d..63a6352ac 100644 --- a/src/portable/renesas/rusb2/dcd_rusb2.c +++ b/src/portable/renesas/rusb2/dcd_rusb2.c @@ -899,7 +899,6 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_ { (void) is_isr; // USB buffers always work in bytes so to avoid unnecessary divisions we demand item_size = 1 - TU_ASSERT(ff->item_size == 1); rusb2_reg_t* rusb = RUSB2_REG(rhport); dcd_int_disable(rhport); @@ -912,7 +911,9 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { volatile uint16_t *ctr = ep_addr_to_pipectr(rhport, ep_addr); - if (!ctr) return; + if (!ctr) { + return; + } dcd_int_disable(rhport); const uint32_t pid = *ctr & 0x3; *ctr = pid | RUSB2_PIPE_CTR_PID_STALL; @@ -924,7 +925,9 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { rusb2_reg_t * rusb = RUSB2_REG(rhport); volatile uint16_t *ctr = ep_addr_to_pipectr(rhport, ep_addr); - if (!ctr) return; + if (!ctr) { + return; + } dcd_int_disable(rhport); *ctr = RUSB2_PIPE_CTR_SQCLR_Msk; diff --git a/src/tusb_option.h b/src/tusb_option.h index 6129a9532..e22cb7525 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -313,8 +313,8 @@ #define CFG_TUH_EDPT_DEDICATED_HWFIFO 1 #endif - #define CFG_TUSB_FIFO_ACCESS_DATA_STRIDE 4 // 32bit access - #define CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE 0 // fixed hwfifo address + #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE 4 // 32bit access + #define CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE 0 // fixed hwfifo address #endif //------------- ChipIdea -------------// @@ -357,14 +357,14 @@ #define CFG_TUD_EDPT_DEDICATED_HWFIFO 1 #if FSDEV_PMA_SIZE == 512 - #define CFG_TUSB_FIFO_ACCESS_DATA_STRIDE 2 // 16-bit data - #define CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE 4 // 32-bit address increase + #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE 2 // 16-bit data + #define CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE 4 // 32-bit address increase #elif FSDEV_PMA_SIZE == 1024 - #define CFG_TUSB_FIFO_ACCESS_DATA_STRIDE 2 // 16-bit data - #define CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE 2 // 16-bit address increase + #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE 2 // 16-bit data + #define CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE 2 // 16-bit address increase #elif FSDEV_PMA_SIZE == 2048 - #define CFG_TUSB_FIFO_ACCESS_DATA_STRIDE 4 // 32-bit data - #define CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE 4 // 32-bit address increase + #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE 4 // 32-bit data + #define CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE 4 // 32-bit address increase #endif #endif @@ -376,6 +376,9 @@ //------------ RUSB2 --------------// #if defined(TUP_USBIP_RUSB2) #define CFG_TUD_EDPT_DEDICATED_HWFIFO 1 + #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE 2 // 16-bit data + #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE_ODD_BYTE // support odd byte access + #define CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE 0 #endif //-------------------------------------------------------------------- diff --git a/test/unit-test/project.yml b/test/unit-test/project.yml index bf7cb5115..186eacbf0 100644 --- a/test/unit-test/project.yml +++ b/test/unit-test/project.yml @@ -129,8 +129,8 @@ :test: - _UNITY_TEST_ - CFG_TUD_EDPT_DEDICATED_HWFIFO=1 - - CFG_TUSB_FIFO_ACCESS_DATA_STRIDE=4 - - CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE=0 + - CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE=4 + - CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE=0 :release: [] # Enable to inject name of a test as a unique compilation symbol into its respective executable build. -- cgit v1.3.1 From 9ab605ef0b7402e72f9540d4b54af607d60cfd7a Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 1 Jan 2026 12:51:05 +0700 Subject: change signature of tu_hwfifo_* to have hwfifo as first parameter --- src/common/tusb_fifo.c | 8 ++++++++ src/common/tusb_fifo.h | 10 ++++++---- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 4 ++-- src/portable/synopsys/dwc2/dcd_dwc2.c | 4 ++-- 4 files changed, 18 insertions(+), 8 deletions(-) (limited to 'src/portable') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 38b00d9d6..828240b6c 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -167,9 +167,17 @@ void tu_hwfifo_write(volatile void *hwfifo, const uint8_t *src, uint16_t len) { // Write the remaining 1 byte (16bit) or 1-3 bytes (32bit) if (len > 0) { + #ifdef CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE_ODD_BYTE + // odd byte access, write byte per byte e.g for rusb2. No address stride needed + volatile uint8_t *dest8 = (volatile uint8_t *)dest; + for (uint16_t i = 0; i < len; ++i) { + *dest8 = src[i]; + } + #else hwfifo_item_t tmp = 0u; memcpy(&tmp, src, len); *dest = tmp; + #endif } } #endif diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 2473a5605..e1ea1126c 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -226,12 +226,14 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_write_n(tu_fifo_t *f, const // CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE (data width) and CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE (address increment) // Note: these usually has opposiite direction (read/write) to/from our software FIFO (tu_fifo_t) //--------------------------------------------------------------------+ -TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_hwfifo_write_from_fifo(tu_fifo_t *f, void *hwfifo, uint16_t n) { - return tu_fifo_read_n_access_mode(f, hwfifo, n, true); +TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_hwfifo_write_from_fifo(volatile void *hwfifo, tu_fifo_t *f, + uint16_t n) { + return tu_fifo_read_n_access_mode(f, (void *)(uintptr_t)hwfifo, n, true); } -TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_hwfifo_read_to_fifo(tu_fifo_t *f, const void *hwfifo, uint16_t n) { - return tu_fifo_write_n_access_mode(f, hwfifo, n, true); +TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_hwfifo_read_to_fifo(const volatile void *hwfifo, tu_fifo_t *f, + uint16_t n) { + return tu_fifo_write_n_access_mode(f, (const void *)(uintptr_t)hwfifo, n, true); } #if CFG_TUSB_FIFO_HWFIFO_API diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index dae921049..fe4f649da 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -324,7 +324,7 @@ static void handle_ctr_rx(uint32_t ep_id) { fsdev_pma_buf_t *pma_buf = PMA_BUF_AT(pma_addr); if (xfer->ff) { - tu_hwfifo_read_to_fifo(xfer->ff, (void *)pma_buf, rx_count); + tu_hwfifo_read_to_fifo(pma_buf, xfer->ff, rx_count); } else { tu_hwfifo_read(pma_buf, xfer->buffer + xfer->queued_len, rx_count); } @@ -722,7 +722,7 @@ static void dcd_transmit_packet(xfer_ctl_t *xfer, uint16_t ep_ix) { fsdev_pma_buf_t *pma_buf = PMA_BUF_AT(addr_ptr); if (xfer->ff) { - tu_hwfifo_write_from_fifo(xfer->ff, (void *)(uintptr_t)pma_buf, len); + tu_hwfifo_write_from_fifo(pma_buf, xfer->ff, len); } else { tu_hwfifo_write(pma_buf, &(xfer->buffer[xfer->queued_len]), len); } diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index ea952dbcc..b44b8b56e 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -367,7 +367,7 @@ static uint16_t epin_write_tx_fifo(dwc2_regs_t *dwc2, uint8_t epnum) { // Push packet to Tx-FIFO if (xfer->ff) { volatile uint32_t* tx_fifo = dwc2->fifo[epnum]; - tu_hwfifo_write_from_fifo(xfer->ff, (void *)(uintptr_t)tx_fifo, xact_bytes); + tu_hwfifo_write_from_fifo(tx_fifo, xfer->ff, xact_bytes); total_bytes_written += xact_bytes; } else { dfifo_write_packet(dwc2, epnum, xfer->buffer, xact_bytes); @@ -889,7 +889,7 @@ static void handle_rxflvl_irq(uint8_t rhport) { if (byte_count != 0) { // Read packet off RxFIFO if (xfer->ff != NULL) { - tu_hwfifo_read_to_fifo(xfer->ff, (const void *)(uintptr_t)rx_fifo, byte_count); + tu_hwfifo_read_to_fifo(rx_fifo, xfer->ff, byte_count); } else { dfifo_read_packet(dwc2, xfer->buffer, byte_count); xfer->buffer += byte_count; -- cgit v1.3.1 From 0b638c5d74ed112535556e47e42a088267bbc527 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 1 Jan 2026 12:57:24 +0700 Subject: rusb2 use tu_hwfifo API to write usb packet --- src/common/tusb_fifo.c | 18 +++++--- src/portable/renesas/rusb2/dcd_rusb2.c | 82 +++++++++++++++++++--------------- src/tusb_option.h | 8 ++-- 3 files changed, 63 insertions(+), 45 deletions(-) (limited to 'src/portable') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 828240b6c..fe17f1f2b 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -139,14 +139,22 @@ void tu_hwfifo_read(const volatile void *hwfifo, uint8_t *dest, uint16_t len) { len -= sizeof(hwfifo_item_t); #if CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE - src = (const volatile hwfifo_item_t *)((uintptr_t)src + CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE); + src = (const volatile hwfifo_item_t *)((uintptr_t)src + CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE); #endif } - // Read the remaining 1 byte (16bit) or 1-3 bytes (32bit) + // Read odd bytes i.e 1 byte for 16 bit or 1-3 bytes for 32 bit if (len > 0) { + #ifdef CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE_ODD_BYTE_SUPPORT + // odd byte access, read byte per byte e.g for rusb2. No address stride needed + const volatile uint8_t *src8 = (const volatile uint8_t *)src; + for (uint16_t i = 0; i < len; ++i) { + dest[i] = *src8; + } + #else const hwfifo_item_t tmp = *src; memcpy(dest, &tmp, len); + #endif } } @@ -161,13 +169,13 @@ void tu_hwfifo_write(volatile void *hwfifo, const uint8_t *src, uint16_t len) { len -= sizeof(hwfifo_item_t); #if CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE - dest = (volatile hwfifo_item_t *)((uintptr_t)dest + CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE); + dest = (volatile hwfifo_item_t *)((uintptr_t)dest + CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE); #endif } - // Write the remaining 1 byte (16bit) or 1-3 bytes (32bit) + // Write odd bytes i.e 1 byte for 16 bit or 1-3 bytes for 32 bit if (len > 0) { - #ifdef CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE_ODD_BYTE + #ifdef CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE_ODD_BYTE_SUPPORT // odd byte access, write byte per byte e.g for rusb2. No address stride needed volatile uint8_t *dest8 = (volatile uint8_t *)dest; for (uint16_t i = 0; i < len; ++i) { diff --git a/src/portable/renesas/rusb2/dcd_rusb2.c b/src/portable/renesas/rusb2/dcd_rusb2.c index 63a6352ac..6c6406dcf 100644 --- a/src/portable/renesas/rusb2/dcd_rusb2.c +++ b/src/portable/renesas/rusb2/dcd_rusb2.c @@ -163,7 +163,7 @@ static inline void pipe_wait_for_ready(rusb2_reg_t * rusb, unsigned num) { //--------------------------------------------------------------------+ // Pipe FIFO //--------------------------------------------------------------------+ - +#if 0 // Write data buffer --> hw fifo static void pipe_write_packet(rusb2_reg_t * rusb, void *buf, volatile void *fifo, unsigned len) { @@ -196,18 +196,6 @@ static void pipe_write_packet(rusb2_reg_t * rusb, void *buf, volatile void *fifo } } -// Read data buffer <-- hw fifo -static void pipe_read_packet(rusb2_reg_t * rusb, void *buf, volatile void *fifo, unsigned len) -{ - (void) rusb; - - // TODO 16/32-bit access for better performance - - uint8_t *p = (uint8_t*)buf; - volatile uint8_t *reg = (volatile uint8_t*)fifo; /* byte access is always at base register address */ - while (len--) *p++ = *reg; -} - // Write data sw fifo --> hw fifo static void pipe_write_packet_ff(rusb2_reg_t * rusb, tu_fifo_t *f, volatile void *fifo, uint16_t total_len) { tu_fifo_buffer_info_t info; @@ -235,8 +223,21 @@ static void pipe_write_packet_ff(rusb2_reg_t * rusb, tu_fifo_t *f, volatile void tu_fifo_advance_read_pointer(f, cnt_written); } +// Read data buffer <-- hw fifo +static void pipe_read_packet(rusb2_reg_t *rusb, void *buf, volatile void *fifo, unsigned len) { + (void)rusb; + + // TODO 16/32-bit access for better performance + + uint8_t *p = (uint8_t *)buf; + volatile uint8_t *reg = (volatile uint8_t *)fifo; /* byte access is always at base register address */ + while (len--) { + *p++ = *reg; + } +} + // Read data sw fifo <-- hw fifo -static void pipe_read_packet_ff(rusb2_reg_t * rusb, tu_fifo_t *f, volatile void *fifo, uint16_t total_len) { +static void pipe_read_packet_ff(rusb2_reg_t *rusb, tu_fifo_t *f, volatile void *fifo, uint16_t total_len) { tu_fifo_buffer_info_t info; tu_fifo_get_write_info(f, &info); @@ -252,15 +253,15 @@ static void pipe_read_packet_ff(rusb2_reg_t * rusb, tu_fifo_t *f, volatile void tu_fifo_advance_write_pointer(f, count); } + #endif //--------------------------------------------------------------------+ // Pipe Transfer //--------------------------------------------------------------------+ -static bool pipe0_xfer_in(rusb2_reg_t* rusb) -{ - pipe_state_t *pipe = &_dcd.pipe[0]; - const unsigned rem = pipe->remaining; +static bool pipe0_xfer_in(rusb2_reg_t *rusb) { + pipe_state_t *pipe = &_dcd.pipe[0]; + const unsigned rem = pipe->remaining; if (!rem) { pipe->buf = NULL; @@ -273,10 +274,13 @@ static bool pipe0_xfer_in(rusb2_reg_t* rusb) if (len) { if (pipe->ff) { - pipe_write_packet_ff(rusb, (tu_fifo_t*)buf, (volatile void*)&rusb->CFIFO, len); + // pipe_write_packet_ff(rusb, (tu_fifo_t*)buf, (volatile void*)&rusb->CFIFO, len); + tu_hwfifo_write_from_fifo(&rusb->CFIFO, (tu_fifo_t *)buf, len); } else { - pipe_write_packet(rusb, buf, (volatile void*)&rusb->CFIFO, len); - pipe->buf = (uint8_t*)buf + len; + // pipe_write_packet(rusb, buf, (volatile void*)&rusb->CFIFO, len); + // TODO check highspeed for 32-bit access + tu_hwfifo_write(&rusb->CFIFO, buf, len); + pipe->buf = (uint8_t *)buf + len; } } @@ -288,10 +292,9 @@ static bool pipe0_xfer_in(rusb2_reg_t* rusb) return false; } -static bool pipe0_xfer_out(rusb2_reg_t* rusb) -{ - pipe_state_t *pipe = &_dcd.pipe[0]; - const unsigned rem = pipe->remaining; +static bool pipe0_xfer_out(rusb2_reg_t *rusb) { + pipe_state_t *pipe = &_dcd.pipe[0]; + const unsigned rem = pipe->remaining; const uint16_t mps = edpt0_max_packet_size(rusb); const uint16_t vld = rusb->CFIFOCTR_b.DTLN; @@ -300,10 +303,12 @@ static bool pipe0_xfer_out(rusb2_reg_t* rusb) if (len) { if (pipe->ff) { - pipe_read_packet_ff(rusb, (tu_fifo_t*)buf, (volatile void*)&rusb->CFIFO, len); + // pipe_read_packet_ff(rusb, (tu_fifo_t *)buf, (volatile void *)&rusb->CFIFO, len); + tu_hwfifo_read_to_fifo(&rusb->CFIFO, (tu_fifo_t *)buf, len); } else { - pipe_read_packet(rusb, buf, (volatile void*)&rusb->CFIFO, len); - pipe->buf = (uint8_t*)buf + len; + // pipe_read_packet(rusb, buf, (volatile void *)&rusb->CFIFO, len); + tu_hwfifo_read(&rusb->CFIFO, buf, len); + pipe->buf = (uint8_t *)buf + len; } } @@ -338,9 +343,12 @@ static bool pipe_xfer_in(rusb2_reg_t* rusb, unsigned num) if (len) { if (pipe->ff) { - pipe_write_packet_ff(rusb, (tu_fifo_t*)buf, (volatile void*)&rusb->D0FIFO, len); + // pipe_write_packet_ff(rusb, (tu_fifo_t*)buf, (volatile void*)&rusb->D0FIFO, len); + tu_hwfifo_write_from_fifo(&rusb->D0FIFO, (tu_fifo_t *)buf, len); } else { - pipe_write_packet(rusb, buf, (volatile void*)&rusb->D0FIFO, len); + // pipe_write_packet(rusb, buf, (volatile void*)&rusb->D0FIFO, len); + // TODO check highspeed for 32-bit access + tu_hwfifo_write(&rusb->D0FIFO, buf, len); pipe->buf = (uint8_t*)buf + len; } } @@ -362,7 +370,7 @@ static bool pipe_xfer_out(rusb2_reg_t* rusb, unsigned num) pipe_state_t *pipe = &_dcd.pipe[num]; const uint16_t rem = pipe->remaining; - rusb->D0FIFOSEL = num | RUSB2_FIFOSEL_MBW_8BIT; + rusb->D0FIFOSEL = num | RUSB2_FIFOSEL_MBW_16BIT; // RUSB2_FIFOSEL_MBW_8BIT; const uint16_t mps = edpt_max_packet_size(rusb, num); pipe_wait_for_ready(rusb, num); @@ -372,9 +380,11 @@ static bool pipe_xfer_out(rusb2_reg_t* rusb, unsigned num) if (len) { if (pipe->ff) { - pipe_read_packet_ff(rusb, (tu_fifo_t*)buf, (volatile void*)&rusb->D0FIFO, len); + // pipe_read_packet_ff(rusb, (tu_fifo_t*)buf, (volatile void*)&rusb->D0FIFO, len); + tu_hwfifo_read_to_fifo(&rusb->D0FIFO, (tu_fifo_t *)buf, len); } else { - pipe_read_packet(rusb, buf, (volatile void*)&rusb->D0FIFO, len); + // pipe_read_packet(rusb, buf, (volatile void*)&rusb->D0FIFO, len); + tu_hwfifo_read(&rusb->D0FIFO, buf, len); pipe->buf = (uint8_t*)buf + len; } } @@ -431,14 +441,14 @@ static void process_status_completion(uint8_t rhport) static bool process_pipe0_xfer(rusb2_reg_t* rusb, int buffer_type, uint8_t ep_addr, void* buffer, uint16_t total_bytes) { /* configure fifo direction and access unit settings */ - if ( ep_addr ) { + if (ep_addr != 0) { /* IN, 2 bytes */ rusb->CFIFOSEL = RUSB2_CFIFOSEL_ISEL_WRITE | RUSB2_FIFOSEL_MBW_16BIT | (TU_BYTE_ORDER == TU_BIG_ENDIAN ? RUSB2_FIFOSEL_BIGEND : 0); while ( !(rusb->CFIFOSEL & RUSB2_CFIFOSEL_ISEL_WRITE) ) {} } else { - /* OUT, a byte */ - rusb->CFIFOSEL = RUSB2_FIFOSEL_MBW_8BIT; + /* OUT, 2 bytes */ + rusb->CFIFOSEL = RUSB2_FIFOSEL_MBW_16BIT; // RUSB2_FIFOSEL_MBW_8BIT; while ( rusb->CFIFOSEL & RUSB2_CFIFOSEL_ISEL_WRITE ) {} } diff --git a/src/tusb_option.h b/src/tusb_option.h index e22cb7525..8e147707a 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -375,10 +375,10 @@ //------------ RUSB2 --------------// #if defined(TUP_USBIP_RUSB2) - #define CFG_TUD_EDPT_DEDICATED_HWFIFO 1 - #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE 2 // 16-bit data - #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE_ODD_BYTE // support odd byte access - #define CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE 0 + #define CFG_TUD_EDPT_DEDICATED_HWFIFO 1 + #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE 2 // 16-bit data + #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE_ODD_BYTE_SUPPORT // support odd byte access + #define CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE 0 #endif //-------------------------------------------------------------------- -- cgit v1.3.1 From c87f0db45978b6b1f11f151bf5c061b926dba245 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 3 Jan 2026 00:34:49 +0700 Subject: add tu_hwfifo_access_t param to hwfifo API --- src/common/tusb_fifo.c | 73 ++++++++++++--------------- src/common/tusb_fifo.h | 30 ++++++----- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 13 +++-- src/portable/synopsys/dwc2/dcd_dwc2.c | 12 +++-- src/portable/synopsys/dwc2/dwc2_common.c | 54 -------------------- src/portable/synopsys/dwc2/hcd_dwc2.c | 6 ++- test/unit-test/CMakeLists.txt | 1 - test/unit-test/test/test_fifo.c | 26 +++++++--- 8 files changed, 87 insertions(+), 128 deletions(-) (limited to 'src/portable') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 5988f16d8..e34494c84 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -147,8 +147,9 @@ static void stride_read(const volatile void *hwfifo, void *dest, uint8_t data_st #endif } -void tu_hwfifo_read(const volatile void *hwfifo, uint8_t *dest, uint16_t len, uint8_t data_stride) { +void tu_hwfifo_read(const volatile void *hwfifo, uint8_t *dest, uint16_t len, const tu_hwfifo_access_t *access_mode) { // Reading full available 16/32-bit hwfifo and write to fifo + const uint8_t data_stride = access_mode->data_stride; while (len >= data_stride) { stride_read(hwfifo, dest, data_stride); dest += data_stride; @@ -159,23 +160,16 @@ void tu_hwfifo_read(const volatile void *hwfifo, uint8_t *dest, uint16_t len, ui // Read odd bytes i.e 1 byte for 16 bit or 1-3 bytes for 32 bit if (len > 0) { - #ifdef CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE_ODD_BYTE_SUPPORT - // odd byte access, read byte per byte e.g for rusb2. No address stride needed - const volatile uint8_t *src8 = (const volatile uint8_t *)hwfifo; - for (uint16_t i = 0; i < len; ++i) { - dest[i] = *(src8 + 3); - } - #else uint32_t tmp; stride_read(hwfifo, &tmp, data_stride); memcpy(dest, &tmp, len); - #endif } } // Copy from fifo to fixed address buffer (usually a tx register) with TU_FIFO_FIXED_ADDR_RW32 mode -void tu_hwfifo_write(volatile void *hwfifo, const uint8_t *src, uint16_t len, uint8_t data_stride) { +void tu_hwfifo_write(volatile void *hwfifo, const uint8_t *src, uint16_t len, const tu_hwfifo_access_t *access_mode) { // Write full available 16/32 bit words to dest + const uint8_t data_stride = access_mode->data_stride; while (len >= data_stride) { stride_write(hwfifo, src, data_stride); src += data_stride; @@ -186,21 +180,14 @@ void tu_hwfifo_write(volatile void *hwfifo, const uint8_t *src, uint16_t len, ui // Write odd bytes i.e 1 byte for 16 bit or 1-3 bytes for 32 bit if (len > 0) { - #ifdef CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE_ODD_BYTE_SUPPORT - // odd byte access, write byte per byte e.g for rusb2. No address stride needed - volatile uint8_t *dest8 = (volatile uint8_t *)hwfifo; - for (uint16_t i = 0; i < len; ++i) { - *(dest8 + 3) = src[i]; - } - #else uint32_t tmp = 0u; memcpy(&tmp, src, len); stride_write(hwfifo, &tmp, data_stride); - #endif } } -static void hwff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uint16_t wr_ptr, uint8_t data_stride) { +static void hwff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uint16_t wr_ptr, + const tu_hwfifo_access_t *access_mode) { uint16_t lin_bytes = f->depth - wr_ptr; uint16_t wrap_bytes = n - lin_bytes; uint8_t *ff_buf = f->buffer + wr_ptr; @@ -208,14 +195,15 @@ static void hwff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uin const volatile void *hwfifo = (const volatile void *)app_buf; if (n <= lin_bytes) { // Linear only case - tu_hwfifo_read(hwfifo, ff_buf, n, data_stride); + tu_hwfifo_read(hwfifo, ff_buf, n, access_mode); } else { // Wrap around case // Write full words to linear part of buffer - const uint32_t odd_mask = data_stride - 1; - uint16_t lin_even = lin_bytes & ~odd_mask; - tu_hwfifo_read(hwfifo, ff_buf, lin_even, data_stride); + const uint8_t data_stride = access_mode->data_stride; + const uint32_t odd_mask = data_stride - 1; + uint16_t lin_even = lin_bytes & ~odd_mask; + tu_hwfifo_read(hwfifo, ff_buf, lin_even, access_mode); ff_buf += lin_even; // There could be odd 1 byte (16bit) or 1-3 bytes (32bit) before the wrap-around boundary @@ -224,7 +212,7 @@ static void hwff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uin if (lin_odd > 0) { const uint8_t wrap_odd = (uint8_t)tu_min16(wrap_bytes, data_stride - lin_odd); uint8_t buf_temp[4]; - tu_hwfifo_read(hwfifo, buf_temp, lin_odd + wrap_odd, data_stride); + tu_hwfifo_read(hwfifo, buf_temp, lin_odd + wrap_odd, access_mode); for (uint8_t i = 0; i < lin_odd; ++i) { ff_buf[i] = buf_temp[i]; @@ -241,12 +229,13 @@ static void hwff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uin // Write data wrapped part if (wrap_bytes > 0) { - tu_hwfifo_read(hwfifo, ff_buf, wrap_bytes, data_stride); + tu_hwfifo_read(hwfifo, ff_buf, wrap_bytes, access_mode); } } } -static void hwff_pull_n(const tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t rd_ptr, uint8_t data_stride) { +static void hwff_pull_n(const tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t rd_ptr, + const tu_hwfifo_access_t *access_mode) { uint16_t lin_bytes = f->depth - rd_ptr; uint16_t wrap_bytes = n - lin_bytes; // only used if wrapped const uint8_t *ff_buf = f->buffer + rd_ptr; @@ -255,14 +244,15 @@ static void hwff_pull_n(const tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t if (n <= lin_bytes) { // Linear only case - tu_hwfifo_write(hwfifo, ff_buf, n, data_stride); + tu_hwfifo_write(hwfifo, ff_buf, n, access_mode); } else { // Wrap around case // Read full words from linear part - const uint32_t odd_mask = data_stride - 1; + const uint8_t data_stride = access_mode->data_stride; + const uint32_t odd_mask = data_stride - 1; uint16_t lin_even = lin_bytes & ~odd_mask; - tu_hwfifo_write(hwfifo, ff_buf, lin_even, data_stride); + tu_hwfifo_write(hwfifo, ff_buf, lin_even, access_mode); ff_buf += lin_even; // There could be odd 1 byte (16bit) or 1-3 bytes (32bit) before the wrap-around boundary @@ -278,7 +268,7 @@ static void hwff_pull_n(const tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t buf_temp[lin_odd + i] = f->buffer[i]; } - tu_hwfifo_write(hwfifo, buf_temp, lin_odd + wrap_odd, data_stride); + tu_hwfifo_write(hwfifo, buf_temp, lin_odd + wrap_odd, access_mode); wrap_bytes -= wrap_odd; ff_buf = f->buffer + wrap_odd; // wrap around @@ -288,7 +278,7 @@ static void hwff_pull_n(const tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t // Read data wrapped part if (wrap_bytes > 0) { - tu_hwfifo_write(hwfifo, ff_buf, wrap_bytes, data_stride); + tu_hwfifo_write(hwfifo, ff_buf, wrap_bytes, access_mode); } } } @@ -376,7 +366,7 @@ static uint16_t correct_read_index(tu_fifo_t *f, uint16_t wr_idx) { // Works on local copies of w and r // Must be protected by read mutex since in case of an overflow read pointer gets modified uint16_t tu_fifo_peek_n_access_mode(tu_fifo_t *f, void *p_buffer, uint16_t n, uint16_t wr_idx, uint16_t rd_idx, - uint8_t data_stride) { + const tu_hwfifo_access_t *access_mode) { uint16_t count = tu_ff_overflow_count(f->depth, wr_idx, rd_idx); if (count == 0) { return 0; // nothing to peek @@ -395,8 +385,8 @@ uint16_t tu_fifo_peek_n_access_mode(tu_fifo_t *f, void *p_buffer, uint16_t n, ui const uint16_t rd_ptr = idx2ptr(f->depth, rd_idx); #if CFG_TUSB_FIFO_HWFIFO_API - if (data_stride > 0) { - hwff_pull_n(f, p_buffer, n, rd_ptr, data_stride); + if (access_mode != NULL) { + hwff_pull_n(f, p_buffer, n, rd_ptr, access_mode); } else #endif { @@ -409,17 +399,17 @@ uint16_t tu_fifo_peek_n_access_mode(tu_fifo_t *f, void *p_buffer, uint16_t n, ui // Read n items without removing it from the FIFO, correct read pointer if overflowed uint16_t tu_fifo_peek_n(tu_fifo_t *f, void *p_buffer, uint16_t n) { ff_lock(f->mutex_rd); - const uint16_t ret = tu_fifo_peek_n_access_mode(f, p_buffer, n, f->wr_idx, f->rd_idx, 0); + const uint16_t ret = tu_fifo_peek_n_access_mode(f, p_buffer, n, f->wr_idx, f->rd_idx, NULL); ff_unlock(f->mutex_rd); return ret; } // Read n items from fifo with access mode -uint16_t tu_fifo_read_n_access_mode(tu_fifo_t *f, void *buffer, uint16_t n, uint8_t data_stride) { +uint16_t tu_fifo_read_n_access_mode(tu_fifo_t *f, void *buffer, uint16_t n, const tu_hwfifo_access_t *access_mode) { ff_lock(f->mutex_rd); // Peek the data: f->rd_idx might get modified in case of an overflow so we can not use a local variable - n = tu_fifo_peek_n_access_mode(f, buffer, n, f->wr_idx, f->rd_idx, data_stride); + n = tu_fifo_peek_n_access_mode(f, buffer, n, f->wr_idx, f->rd_idx, access_mode); f->rd_idx = advance_index(f->depth, f->rd_idx, n); ff_unlock(f->mutex_rd); @@ -427,7 +417,8 @@ uint16_t tu_fifo_read_n_access_mode(tu_fifo_t *f, void *buffer, uint16_t n, uint } // Write n items to fifo with access mode -uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n, uint8_t data_stride) { +uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n, + const tu_hwfifo_access_t *access_mode) { if (n == 0) { return 0; } @@ -453,7 +444,7 @@ uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n, // function! Since it would end up in a race condition with read functions! if (n >= f->depth) { // Only copy last part - if (!data_stride) { + if (access_mode == NULL) { buf8 += (n - f->depth); } else { // TODO should read from hw fifo to discard data, however reading an odd number could @@ -490,8 +481,8 @@ uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n, TU_LOG(TU_FIFO_DBG, "actual_n = %u, wr_ptr = %u", n, wr_ptr); #if CFG_TUSB_FIFO_HWFIFO_API - if (data_stride > 0) { - hwff_push_n(f, buf8, n, wr_ptr, data_stride); + if (access_mode != NULL) { + hwff_push_n(f, buf8, n, wr_ptr, access_mode); } else #endif { diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index d7e5416fd..6fcc7020c 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -138,6 +138,12 @@ typedef struct { } linear, wrapped; } tu_fifo_buffer_info_t; +// Access mode for hardware fifo read/write +typedef struct { + uint8_t data_stride; + uintptr_t param; +} tu_hwfifo_access_t; + #define TU_FIFO_INIT(_buffer, _depth, _overwritable) \ { \ .buffer = _buffer, \ @@ -192,7 +198,7 @@ void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info); // peek() will correct/re-index read pointer in case of an overflowed fifo to form a full fifo //--------------------------------------------------------------------+ uint16_t tu_fifo_peek_n_access_mode(tu_fifo_t *f, void *p_buffer, uint16_t n, uint16_t wr_idx, uint16_t rd_idx, - uint8_t data_stride); + const tu_hwfifo_access_t *access_mode); bool tu_fifo_peek(tu_fifo_t *f, void *p_buffer); uint16_t tu_fifo_peek_n(tu_fifo_t *f, void *p_buffer, uint16_t n); @@ -200,10 +206,10 @@ uint16_t tu_fifo_peek_n(tu_fifo_t *f, void *p_buffer, uint16_t n); // Read API // peek() + advance read index //--------------------------------------------------------------------+ -uint16_t tu_fifo_read_n_access_mode(tu_fifo_t *f, void *buffer, uint16_t n, uint8_t data_stride); +uint16_t tu_fifo_read_n_access_mode(tu_fifo_t *f, void *buffer, uint16_t n, const tu_hwfifo_access_t *access_mode); bool tu_fifo_read(tu_fifo_t *f, void *buffer); TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_read_n(tu_fifo_t *f, void *buffer, uint16_t n) { - return tu_fifo_read_n_access_mode(f, buffer, n, 0); + return tu_fifo_read_n_access_mode(f, buffer, n, NULL); } // discard first n items from fifo i.e advance read pointer by n with mutex @@ -213,10 +219,10 @@ uint16_t tu_fifo_discard_n(tu_fifo_t *f, uint16_t n); //--------------------------------------------------------------------+ // Write API //--------------------------------------------------------------------+ -uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n, uint8_t data_stride); +uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n, const tu_hwfifo_access_t *access_mode); bool tu_fifo_write(tu_fifo_t *f, const void *data); TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_write_n(tu_fifo_t *f, const void *data, uint16_t n) { - return tu_fifo_write_n_access_mode(f, data, n, 0); + return tu_fifo_write_n_access_mode(f, data, n, NULL); } //--------------------------------------------------------------------+ @@ -225,22 +231,22 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_write_n(tu_fifo_t *f, const // CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE (data width) and CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE (address increment) // Note: these usually has opposiite direction (read/write) to/from our software FIFO (tu_fifo_t) //--------------------------------------------------------------------+ -TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_hwfifo_write_from_fifo(volatile void *hwfifo, tu_fifo_t *f, - uint16_t n) { - return tu_fifo_read_n_access_mode(f, (void *)(uintptr_t)hwfifo, n, CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE); +TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_hwfifo_write_from_fifo(volatile void *hwfifo, tu_fifo_t *f, uint16_t n, + const tu_hwfifo_access_t *access_mode) { + return tu_fifo_read_n_access_mode(f, (void *)(uintptr_t)hwfifo, n, access_mode); } TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_hwfifo_read_to_fifo(const volatile void *hwfifo, tu_fifo_t *f, - uint16_t n) { - return tu_fifo_write_n_access_mode(f, (const void *)(uintptr_t)hwfifo, n, CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE); + uint16_t n, const tu_hwfifo_access_t *access_mode) { + return tu_fifo_write_n_access_mode(f, (const void *)(uintptr_t)hwfifo, n, access_mode); } #if CFG_TUSB_FIFO_HWFIFO_API // read from hwfifo to buffer -void tu_hwfifo_read(const volatile void *hwfifo, uint8_t *dest, uint16_t len, uint8_t data_stride); +void tu_hwfifo_read(const volatile void *hwfifo, uint8_t *dest, uint16_t len, const tu_hwfifo_access_t *access_mode); // write to hwfifo from buffer with access mode -void tu_hwfifo_write(volatile void *hwfifo, const uint8_t *src, uint16_t len, uint8_t data_stride); +void tu_hwfifo_write(volatile void *hwfifo, const uint8_t *src, uint16_t len, const tu_hwfifo_access_t *access_mode); #endif diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index fe4f649da..2832611ff 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -285,7 +285,8 @@ static void handle_ctr_setup(uint32_t ep_id) { uint16_t rx_addr = btable_get_addr(ep_id, BTABLE_BUF_RX); uint8_t setup_packet[8] TU_ATTR_ALIGNED(4); - tu_hwfifo_read(PMA_BUF_AT(rx_addr), setup_packet, rx_count); + const tu_hwfifo_access_t access_mode = {.data_stride = CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE}; + tu_hwfifo_read(PMA_BUF_AT(rx_addr), setup_packet, rx_count, &access_mode); // Clear CTR RX if another setup packet arrived before this, it will be discarded ep_write_clear_ctr(ep_id, TUSB_DIR_OUT); @@ -323,10 +324,11 @@ static void handle_ctr_rx(uint32_t ep_id) { uint16_t pma_addr = (uint16_t) btable_get_addr(ep_id, buf_id); fsdev_pma_buf_t *pma_buf = PMA_BUF_AT(pma_addr); + const tu_hwfifo_access_t access_mode = {.data_stride = CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE}; if (xfer->ff) { - tu_hwfifo_read_to_fifo(pma_buf, xfer->ff, rx_count); + tu_hwfifo_read_to_fifo(pma_buf, xfer->ff, rx_count, &access_mode); } else { - tu_hwfifo_read(pma_buf, xfer->buffer + xfer->queued_len, rx_count); + tu_hwfifo_read(pma_buf, xfer->buffer + xfer->queued_len, rx_count, &access_mode); } xfer->queued_len += rx_count; @@ -721,10 +723,11 @@ static void dcd_transmit_packet(xfer_ctl_t *xfer, uint16_t ep_ix) { uint16_t addr_ptr = (uint16_t)btable_get_addr(ep_ix, buf_id); fsdev_pma_buf_t *pma_buf = PMA_BUF_AT(addr_ptr); + const tu_hwfifo_access_t access_mode = {.data_stride = CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE}; if (xfer->ff) { - tu_hwfifo_write_from_fifo(pma_buf, xfer->ff, len); + tu_hwfifo_write_from_fifo(pma_buf, xfer->ff, len, &access_mode); } else { - tu_hwfifo_write(pma_buf, &(xfer->buffer[xfer->queued_len]), len); + tu_hwfifo_write(pma_buf, &(xfer->buffer[xfer->queued_len]), len, &access_mode); } xfer->queued_len += len; diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index b44b8b56e..2309afd53 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -365,12 +365,13 @@ static uint16_t epin_write_tx_fifo(dwc2_regs_t *dwc2, uint8_t epnum) { } // Push packet to Tx-FIFO + const tu_hwfifo_access_t access_mode = {.data_stride = CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE}; + volatile uint32_t *tx_fifo = dwc2->fifo[epnum]; if (xfer->ff) { - volatile uint32_t* tx_fifo = dwc2->fifo[epnum]; - tu_hwfifo_write_from_fifo(tx_fifo, xfer->ff, xact_bytes); + tu_hwfifo_write_from_fifo(tx_fifo, xfer->ff, xact_bytes, &access_mode); total_bytes_written += xact_bytes; } else { - dfifo_write_packet(dwc2, epnum, xfer->buffer, xact_bytes); + tu_hwfifo_write(tx_fifo, xfer->buffer, xact_bytes, &access_mode); xfer->buffer += xact_bytes; total_bytes_written += xact_bytes; } @@ -888,10 +889,11 @@ static void handle_rxflvl_irq(uint8_t rhport) { if (byte_count != 0) { // Read packet off RxFIFO + const tu_hwfifo_access_t access_mode = {.data_stride = CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE}; if (xfer->ff != NULL) { - tu_hwfifo_read_to_fifo(rx_fifo, xfer->ff, byte_count); + tu_hwfifo_read_to_fifo(rx_fifo, xfer->ff, byte_count, &access_mode); } else { - dfifo_read_packet(dwc2, xfer->buffer, byte_count); + tu_hwfifo_read(rx_fifo, xfer->buffer, byte_count, &access_mode); xfer->buffer += byte_count; } } diff --git a/src/portable/synopsys/dwc2/dwc2_common.c b/src/portable/synopsys/dwc2/dwc2_common.c index 980574e12..a7e6188df 100644 --- a/src/portable/synopsys/dwc2/dwc2_common.c +++ b/src/portable/synopsys/dwc2/dwc2_common.c @@ -264,58 +264,4 @@ bool dwc2_core_init(uint8_t rhport, bool is_highspeed, bool is_dma) { // // } -//-------------------------------------------------------------------- -// DFIFO -//-------------------------------------------------------------------- -// Read a single data packet from receive DFIFO -void dfifo_read_packet(dwc2_regs_t* dwc2, uint8_t* dst, uint16_t len) { - const volatile uint32_t* rx_fifo = dwc2->fifo[0]; - - // Reading full available 32 bit words from fifo - uint16_t word_count = len >> 2; - while (word_count--) { - tu_unaligned_write32(dst, *rx_fifo); - dst += 4; - } - - // Read the remaining 1-3 bytes from fifo - const uint8_t bytes_rem = len & 0x03; - if (bytes_rem != 0) { - const uint32_t tmp = *rx_fifo; - dst[0] = tu_u32_byte0(tmp); - if (bytes_rem > 1) { - dst[1] = tu_u32_byte1(tmp); - } - if (bytes_rem > 2) { - dst[2] = tu_u32_byte2(tmp); - } - } -} - -// Write a single data packet to DFIFO -void dfifo_write_packet(dwc2_regs_t* dwc2, uint8_t fifo_num, const uint8_t* src, uint16_t len) { - volatile uint32_t* tx_fifo = dwc2->fifo[fifo_num]; - - // Pushing full available 32 bit words to fifo - uint16_t word_count = len >> 2; - while (word_count--) { - *tx_fifo = tu_unaligned_read32(src); - src += 4; - } - - // Write the remaining 1-3 bytes into fifo - const uint8_t bytes_rem = len & 0x03; - if (bytes_rem) { - uint32_t tmp_word = src[0]; - if (bytes_rem > 1) { - tmp_word |= (src[1] << 8); - } - if (bytes_rem > 2) { - tmp_word |= (src[2] << 16); - } - - *tx_fifo = tmp_word; - } -} - #endif diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index fc748c85f..570b1c14c 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -856,7 +856,8 @@ static void handle_rxflvl_irq(uint8_t rhport) { hcd_endpoint_t* edpt = &_hcd_data.edpt[xfer->ep_id]; if (byte_count > 0) { - dfifo_read_packet(dwc2, edpt->buffer + xfer->xferred_bytes, byte_count); + const tu_hwfifo_access_t access_mode = {.data_stride = CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE}; + tu_hwfifo_read(dwc2->fifo[0], edpt->buffer + xfer->xferred_bytes, byte_count, &access_mode); xfer->xferred_bytes += byte_count; xfer->fifo_bytes = byte_count; } @@ -907,7 +908,8 @@ static bool handle_txfifo_empty(dwc2_regs_t* dwc2, bool is_periodic) { return true; } - dfifo_write_packet(dwc2, ch_id, edpt->buffer + xfer->fifo_bytes, xact_bytes); + const tu_hwfifo_access_t access_mode = {.data_stride = CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE}; + tu_hwfifo_write(dwc2->fifo[ch_id], edpt->buffer + xfer->fifo_bytes, xact_bytes, &access_mode); xfer->fifo_bytes += xact_bytes; } } diff --git a/test/unit-test/CMakeLists.txt b/test/unit-test/CMakeLists.txt index 3339361db..b44a91d57 100644 --- a/test/unit-test/CMakeLists.txt +++ b/test/unit-test/CMakeLists.txt @@ -113,7 +113,6 @@ add_ceedling_test( ${CEEDLING_WORKDIR}/../../src/common/tusb_fifo.c "" ) -target_compile_definitions(test_fifo PRIVATE CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_WIDTH=32) add_ceedling_test( test_usbd diff --git a/test/unit-test/test/test_fifo.c b/test/unit-test/test/test_fifo.c index 6e1c13d6d..b9279cb25 100644 --- a/test/unit-test/test/test_fifo.c +++ b/test/unit-test/test/test_fifo.c @@ -40,6 +40,16 @@ tu_fifo_buffer_info_t info; uint8_t test_data[4096]; uint8_t rd_buf[FIFO_SIZE]; +static const tu_hwfifo_access_t hwfifo_access_32 = { + .data_stride = 4, + .param = 0, +}; + +static const tu_hwfifo_access_t hwfifo_access_16 = { + .data_stride = 2, + .param = 0, +}; + void setUp(void) { tu_fifo_clear(ff); memset(&info, 0, sizeof(tu_fifo_buffer_info_t)); @@ -403,7 +413,7 @@ void test_write_n_fixed_addr_rw32_nowrap(void) { for (uint8_t n = 1; n <= 8; n++) { tu_fifo_clear(ff); - uint16_t written = tu_fifo_write_n_access_mode(ff, (const void *)®, n, 4); + uint16_t written = tu_fifo_write_n_access_mode(ff, (const void *)®, n, &hwfifo_access_32); TEST_ASSERT_EQUAL(n, written); TEST_ASSERT_EQUAL(n, tu_fifo_count(ff)); @@ -425,7 +435,7 @@ void test_write_n_fixed_addr_rw32_wrapped(void) { ff->wr_idx = FIFO_SIZE - 3; ff->rd_idx = FIFO_SIZE - 3; - uint16_t written = tu_fifo_write_n_access_mode(ff, (const void *)®, n, 4); + uint16_t written = tu_fifo_write_n_access_mode(ff, (const void *)®, n, &hwfifo_access_32); TEST_ASSERT_EQUAL(n, written); TEST_ASSERT_EQUAL(n, tu_fifo_count(ff)); @@ -445,7 +455,7 @@ void test_read_n_fixed_addr_rw32_nowrap(void) { tu_fifo_write_n(ff, pattern, 8); uint32_t reg = 0; - uint16_t read_cnt = tu_fifo_read_n_access_mode(ff, ®, n, 4); + uint16_t read_cnt = tu_fifo_read_n_access_mode(ff, ®, n, &hwfifo_access_32); TEST_ASSERT_EQUAL(n, read_cnt); TEST_ASSERT_EQUAL(8 - n, tu_fifo_count(ff)); @@ -469,7 +479,7 @@ void test_read_n_fixed_addr_rw32_wrapped(void) { } uint32_t reg = 0; - uint16_t read_cnt = tu_fifo_read_n_access_mode(ff, ®, n, 4); + uint16_t read_cnt = tu_fifo_read_n_access_mode(ff, ®, n, &hwfifo_access_32); TEST_ASSERT_EQUAL(n, read_cnt); TEST_ASSERT_EQUAL(0, tu_fifo_count(ff)); @@ -485,7 +495,7 @@ void test_write_n_fixed_addr_rw16_nowrap(void) { for (uint8_t n = 1; n <= 6; n++) { tu_fifo_clear(ff); - uint16_t written = tu_fifo_write_n_access_mode(ff, (const void *)®, n, 2); + uint16_t written = tu_fifo_write_n_access_mode(ff, (const void *)®, n, &hwfifo_access_16); TEST_ASSERT_EQUAL(n, written); TEST_ASSERT_EQUAL(n, tu_fifo_count(ff)); @@ -507,7 +517,7 @@ void test_write_n_fixed_addr_rw16_wrapped(void) { ff->wr_idx = FIFO_SIZE - 3; ff->rd_idx = FIFO_SIZE - 3; - uint16_t written = tu_fifo_write_n_access_mode(ff, (const void *)®, n, 2); + uint16_t written = tu_fifo_write_n_access_mode(ff, (const void *)®, n, &hwfifo_access_16); TEST_ASSERT_EQUAL(n, written); TEST_ASSERT_EQUAL(n, tu_fifo_count(ff)); @@ -526,7 +536,7 @@ void test_read_n_fixed_addr_rw16_nowrap(void) { tu_fifo_write_n(ff, pattern, 6); uint16_t reg = 0; - uint16_t read_cnt = tu_fifo_read_n_access_mode(ff, ®, n, 2); + uint16_t read_cnt = tu_fifo_read_n_access_mode(ff, ®, n, &hwfifo_access_16); TEST_ASSERT_EQUAL(n, read_cnt); TEST_ASSERT_EQUAL(6 - n, tu_fifo_count(ff)); @@ -549,7 +559,7 @@ void test_read_n_fixed_addr_rw16_wrapped(void) { } uint16_t reg = 0; - uint16_t read_cnt = tu_fifo_read_n_access_mode(ff, ®, n, 2); + uint16_t read_cnt = tu_fifo_read_n_access_mode(ff, ®, n, &hwfifo_access_16); TEST_ASSERT_EQUAL(n, read_cnt); TEST_ASSERT_EQUAL(0, tu_fifo_count(ff)); -- cgit v1.3.1 From e158a3dd38fccd99169a3e5b8cecf7a1ac45915e Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 3 Jan 2026 12:49:01 +0700 Subject: hwfifo support custom write/read rusb use custom write enable all hil test for ra4m1 --- src/common/tusb_fifo.c | 45 ++++--- src/portable/renesas/rusb2/dcd_rusb2.c | 226 ++++++++++++++++++++++++--------- src/tusb_option.h | 9 +- test/hil/tinyusb.json | 5 +- 4 files changed, 199 insertions(+), 86 deletions(-) (limited to 'src/portable') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index e34494c84..f6963a98d 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -121,6 +121,7 @@ void tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable) { #define HWFIFO_ADDR_NEXT(_const, _hwfifo) #endif +#ifndef CFG_TUSB_FIFO_HWFIFO_CUSTOM_WRITE static void stride_write(volatile void *hwfifo, const void *src, uint8_t data_stride) { #if CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE & 4 if (data_stride == 4) { @@ -134,6 +135,28 @@ static void stride_write(volatile void *hwfifo, const void *src, uint8_t data_st #endif } +// Copy from fifo to fixed address buffer (usually a tx register) with TU_FIFO_FIXED_ADDR_RW32 mode +void tu_hwfifo_write(volatile void *hwfifo, const uint8_t *src, uint16_t len, const tu_hwfifo_access_t *access_mode) { + // Write full available 16/32 bit words to dest + const uint8_t data_stride = access_mode->data_stride; + while (len >= data_stride) { + stride_write(hwfifo, src, data_stride); + src += data_stride; + len -= data_stride; + + HWFIFO_ADDR_NEXT(, hwfifo); + } + + // Write odd bytes i.e 1 byte for 16 bit or 1-3 bytes for 32 bit + if (len > 0) { + uint32_t tmp = 0u; + memcpy(&tmp, src, len); + stride_write(hwfifo, &tmp, data_stride); + } +} + #endif + + #ifndef CFG_TUSB_FIFO_HWFIFO_CUSTOM_READ static void stride_read(const volatile void *hwfifo, void *dest, uint8_t data_stride) { #if CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE & 4 if (data_stride == 4) { @@ -165,26 +188,7 @@ void tu_hwfifo_read(const volatile void *hwfifo, uint8_t *dest, uint16_t len, co memcpy(dest, &tmp, len); } } - -// Copy from fifo to fixed address buffer (usually a tx register) with TU_FIFO_FIXED_ADDR_RW32 mode -void tu_hwfifo_write(volatile void *hwfifo, const uint8_t *src, uint16_t len, const tu_hwfifo_access_t *access_mode) { - // Write full available 16/32 bit words to dest - const uint8_t data_stride = access_mode->data_stride; - while (len >= data_stride) { - stride_write(hwfifo, src, data_stride); - src += data_stride; - len -= data_stride; - - HWFIFO_ADDR_NEXT(, hwfifo); - } - - // Write odd bytes i.e 1 byte for 16 bit or 1-3 bytes for 32 bit - if (len > 0) { - uint32_t tmp = 0u; - memcpy(&tmp, src, len); - stride_write(hwfifo, &tmp, data_stride); - } -} + #endif static void hwff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uint16_t wr_ptr, const tu_hwfifo_access_t *access_mode) { @@ -390,6 +394,7 @@ uint16_t tu_fifo_peek_n_access_mode(tu_fifo_t *f, void *p_buffer, uint16_t n, ui } else #endif { + (void)access_mode; ff_pull_n(f, p_buffer, n, rd_ptr); } diff --git a/src/portable/renesas/rusb2/dcd_rusb2.c b/src/portable/renesas/rusb2/dcd_rusb2.c index 6c6406dcf..f8fc7a643 100644 --- a/src/portable/renesas/rusb2/dcd_rusb2.c +++ b/src/portable/renesas/rusb2/dcd_rusb2.c @@ -57,6 +57,10 @@ enum { PIPE_COUNT = 10, }; +enum { + FIFOSEL_BIGEND = (TU_BYTE_ORDER == TU_BIG_ENDIAN ? RUSB2_FIFOSEL_BIGEND : 0) +}; + typedef struct { void *buf; /* the start address of a transfer data buffer */ uint16_t length; /* the number of bytes in the buffer */ @@ -163,7 +167,8 @@ static inline void pipe_wait_for_ready(rusb2_reg_t * rusb, unsigned num) { //--------------------------------------------------------------------+ // Pipe FIFO //--------------------------------------------------------------------+ -#if 0 +#define USE_HWFIFO 1 + #if !USE_HWFIFO // Write data buffer --> hw fifo static void pipe_write_packet(rusb2_reg_t * rusb, void *buf, volatile void *fifo, unsigned len) { @@ -172,27 +177,48 @@ static void pipe_write_packet(rusb2_reg_t * rusb, void *buf, volatile void *fifo volatile uint16_t *ff16; volatile uint8_t *ff8; + const uint8_t *buf8 = (const uint8_t *)buf; + // Highspeed FIFO is 32-bit if ( rusb2_is_highspeed_reg(rusb) ) { // TODO 32-bit access for better performance + volatile uint32_t *ff32 = (volatile uint32_t *)fifo; ff16 = (volatile uint16_t*) ((uintptr_t) fifo+2); ff8 = (volatile uint8_t *) ((uintptr_t) fifo+3); - }else { - ff16 = (volatile uint16_t*) fifo; - ff8 = ((volatile uint8_t*) fifo); - } - uint8_t const* buf8 = (uint8_t const*) buf; + while (len >= 4) { + *ff32 = tu_unaligned_read32(buf8); + buf8 += 4; + len -= 4; + } - while (len >= 2) { - *ff16 = tu_unaligned_read16(buf8); - buf8 += 2; - len -= 2; - } + if (len >= 2) { + // switch to 16-bit access + rusb->CFIFOSEL = RUSB2_CFIFOSEL_ISEL_WRITE | RUSB2_FIFOSEL_MBW_16BIT | + (TU_BYTE_ORDER == TU_BIG_ENDIAN ? RUSB2_FIFOSEL_BIGEND : 0); + *ff16 = tu_unaligned_read16(buf8); + buf8 += 2; + len -= 2; + } - if (len > 0) { - *ff8 = *buf8; - ++buf8; + if (len > 0) { + *ff8 = *buf8; + ++buf8; + } + } else { + ff16 = (volatile uint16_t*) fifo; + ff8 = ((volatile uint8_t *)fifo); + + while (len >= 2) { + *ff16 = tu_unaligned_read16(buf8); + buf8 += 2; + len -= 2; + } + + if (len > 0) { + *ff8 = *buf8; + ++buf8; + } } } @@ -255,6 +281,66 @@ static void pipe_read_packet_ff(rusb2_reg_t *rusb, tu_fifo_t *f, volatile void * } #endif +static void hwfifo_set_mbw(rusb2_reg_t *rusb, uintptr_t hwfifo, uint16_t mbw) { + volatile uint16_t *fifo_sel; + if (hwfifo == (uintptr_t)&rusb->CFIFO) { + fifo_sel = &rusb->CFIFOSEL; + } else if (hwfifo == (uintptr_t)&rusb->D0FIFO) { + fifo_sel = &rusb->D0FIFOSEL; + } else if (hwfifo == (uintptr_t)&rusb->D1FIFO) { + fifo_sel = &rusb->D1FIFOSEL; + } else { + return; + } + + *fifo_sel = (*fifo_sel & ~RUSB2_CFIFOSEL_MBW_Msk) | mbw; +} + +// write to hwfifo from buffer with access mode +void tu_hwfifo_write(volatile void *hwfifo, const uint8_t *src, uint16_t len, const tu_hwfifo_access_t *access_mode) { + rusb2_reg_t *rusb = (rusb2_reg_t *)access_mode->param; + const uint8_t *buf8 = (const uint8_t *)src; + + volatile uint16_t *ff16; + volatile uint8_t *ff8; + const bool is_highspeed = rusb2_is_highspeed_reg(rusb); + if (is_highspeed) { + ff16 = (volatile uint16_t *)((uintptr_t)hwfifo + 2); + ff8 = (volatile uint8_t *)((uintptr_t)hwfifo + 3); + } else { + ff16 = (volatile uint16_t *)hwfifo; + ff8 = ((volatile uint8_t *)hwfifo); + } + + // 32-bit access for highspeed + if (is_highspeed) { + volatile uint32_t *ff32 = (volatile uint32_t *)hwfifo; + while (len >= 4) { + *ff32 = tu_unaligned_read32(buf8); + buf8 += 4; + len -= 4; + } + + if (len >= 2) { + // switch to 16-bit access + hwfifo_set_mbw(rusb, (uintptr_t)hwfifo, RUSB2_FIFOSEL_MBW_16BIT); + } + } + + // 16-bit access + while (len >= 2) { + *ff16 = tu_unaligned_read16(buf8); + buf8 += 2; + len -= 2; + } + + // 8-bit access does not need to change MBW + if (len > 0) { + *ff8 = *buf8; + ++buf8; + } +} + //--------------------------------------------------------------------+ // Pipe Transfer //--------------------------------------------------------------------+ @@ -273,13 +359,12 @@ static bool pipe0_xfer_in(rusb2_reg_t *rusb) { void *buf = pipe->buf; if (len) { + tu_hwfifo_access_t access_mode = {.data_stride = (rusb2_is_highspeed_reg(rusb) ? 4u : 2u), + .param = (uintptr_t)rusb}; if (pipe->ff) { - // pipe_write_packet_ff(rusb, (tu_fifo_t*)buf, (volatile void*)&rusb->CFIFO, len); - tu_hwfifo_write_from_fifo(&rusb->CFIFO, (tu_fifo_t *)buf, len); + tu_hwfifo_write_from_fifo(&rusb->CFIFO, (tu_fifo_t *)buf, len, &access_mode); } else { - // pipe_write_packet(rusb, buf, (volatile void*)&rusb->CFIFO, len); - // TODO check highspeed for 32-bit access - tu_hwfifo_write(&rusb->CFIFO, buf, len); + tu_hwfifo_write(&rusb->CFIFO, buf, len, &access_mode); pipe->buf = (uint8_t *)buf + len; } } @@ -302,12 +387,13 @@ static bool pipe0_xfer_out(rusb2_reg_t *rusb) { void *buf = pipe->buf; if (len) { + tu_hwfifo_access_t access_mode = {.data_stride = (rusb2_is_highspeed_reg(rusb) ? 4u : 2u), + .param = (uintptr_t)rusb}; + if (pipe->ff) { - // pipe_read_packet_ff(rusb, (tu_fifo_t *)buf, (volatile void *)&rusb->CFIFO, len); - tu_hwfifo_read_to_fifo(&rusb->CFIFO, (tu_fifo_t *)buf, len); + tu_hwfifo_read_to_fifo(&rusb->CFIFO, (tu_fifo_t *)buf, len, &access_mode); } else { - // pipe_read_packet(rusb, buf, (volatile void *)&rusb->CFIFO, len); - tu_hwfifo_read(&rusb->CFIFO, buf, len); + tu_hwfifo_read(&rusb->CFIFO, buf, len, &access_mode); pipe->buf = (uint8_t *)buf + len; } } @@ -335,21 +421,27 @@ static bool pipe_xfer_in(rusb2_reg_t* rusb, unsigned num) return true; } - rusb->D0FIFOSEL = num | RUSB2_FIFOSEL_MBW_16BIT | (TU_BYTE_ORDER == TU_BIG_ENDIAN ? RUSB2_FIFOSEL_BIGEND : 0); - const uint16_t mps = edpt_max_packet_size(rusb, num); + const uint16_t fifo_sel = num | FIFOSEL_BIGEND; + const bool is_highspeed = rusb2_is_highspeed_reg(rusb); + if (is_highspeed) { + rusb->D0FIFOSEL = fifo_sel | RUSB2_FIFOSEL_MBW_32BIT; + } else { + rusb->D0FIFOSEL = fifo_sel | RUSB2_FIFOSEL_MBW_16BIT; + } + + const uint16_t mps = edpt_max_packet_size(rusb, num); pipe_wait_for_ready(rusb, num); - const uint16_t len = tu_min16(rem, mps); - void *buf = pipe->buf; + uint16_t len = tu_min16(rem, mps); + void *buf = pipe->buf; if (len) { + tu_hwfifo_access_t access_mode = {.data_stride = (rusb2_is_highspeed_reg(rusb) ? 4u : 2u), + .param = (uintptr_t)rusb}; if (pipe->ff) { - // pipe_write_packet_ff(rusb, (tu_fifo_t*)buf, (volatile void*)&rusb->D0FIFO, len); - tu_hwfifo_write_from_fifo(&rusb->D0FIFO, (tu_fifo_t *)buf, len); + tu_hwfifo_write_from_fifo(&rusb->D0FIFO, (tu_fifo_t *)buf, len, &access_mode); } else { - // pipe_write_packet(rusb, buf, (volatile void*)&rusb->D0FIFO, len); - // TODO check highspeed for 32-bit access - tu_hwfifo_write(&rusb->D0FIFO, buf, len); - pipe->buf = (uint8_t*)buf + len; + tu_hwfifo_write(&rusb->D0FIFO, buf, len, &access_mode); + pipe->buf = (uint8_t *)buf + len; } } @@ -370,7 +462,14 @@ static bool pipe_xfer_out(rusb2_reg_t* rusb, unsigned num) pipe_state_t *pipe = &_dcd.pipe[num]; const uint16_t rem = pipe->remaining; - rusb->D0FIFOSEL = num | RUSB2_FIFOSEL_MBW_16BIT; // RUSB2_FIFOSEL_MBW_8BIT; + uint16_t fifo_sel = num | FIFOSEL_BIGEND; + if (rusb2_is_highspeed_reg(rusb)) { + fifo_sel |= RUSB2_FIFOSEL_MBW_32BIT; + } else { + fifo_sel |= RUSB2_FIFOSEL_MBW_16BIT; + } + rusb->D0FIFOSEL = fifo_sel; + const uint16_t mps = edpt_max_packet_size(rusb, num); pipe_wait_for_ready(rusb, num); @@ -379,13 +478,13 @@ static bool pipe_xfer_out(rusb2_reg_t* rusb, unsigned num) void *buf = pipe->buf; if (len) { + tu_hwfifo_access_t access_mode = {.data_stride = (rusb2_is_highspeed_reg(rusb) ? 4u : 2u), + .param = (uintptr_t)rusb}; if (pipe->ff) { - // pipe_read_packet_ff(rusb, (tu_fifo_t*)buf, (volatile void*)&rusb->D0FIFO, len); - tu_hwfifo_read_to_fifo(&rusb->D0FIFO, (tu_fifo_t *)buf, len); + tu_hwfifo_read_to_fifo(&rusb->D0FIFO, (tu_fifo_t *)buf, len, &access_mode); } else { - // pipe_read_packet(rusb, buf, (volatile void*)&rusb->D0FIFO, len); - tu_hwfifo_read(&rusb->D0FIFO, buf, len); - pipe->buf = (uint8_t*)buf + len; + tu_hwfifo_read(&rusb->D0FIFO, buf, len, &access_mode); + pipe->buf = (uint8_t *)buf + len; } } @@ -438,28 +537,33 @@ static void process_status_completion(uint8_t rhport) dcd_event_xfer_complete(rhport, ep_addr, 0, XFER_RESULT_SUCCESS, true); } -static bool process_pipe0_xfer(rusb2_reg_t* rusb, int buffer_type, uint8_t ep_addr, void* buffer, uint16_t total_bytes) -{ +static bool process_pipe0_xfer(rusb2_reg_t *rusb, int buffer_type, uint8_t ep_addr, void *buffer, + uint16_t total_bytes) { + uint16_t fifo_sel = FIFOSEL_BIGEND; + if (rusb2_is_highspeed_reg(rusb)) { + fifo_sel |= RUSB2_FIFOSEL_MBW_32BIT; + } else { + fifo_sel |= RUSB2_FIFOSEL_MBW_16BIT; + } + /* configure fifo direction and access unit settings */ if (ep_addr != 0) { - /* IN, 2 bytes */ - rusb->CFIFOSEL = RUSB2_CFIFOSEL_ISEL_WRITE | RUSB2_FIFOSEL_MBW_16BIT | - (TU_BYTE_ORDER == TU_BIG_ENDIAN ? RUSB2_FIFOSEL_BIGEND : 0); - while ( !(rusb->CFIFOSEL & RUSB2_CFIFOSEL_ISEL_WRITE) ) {} + /* IN, 2 bytes */ rusb->CFIFOSEL = RUSB2_CFIFOSEL_ISEL_WRITE | fifo_sel; + while (!(rusb->CFIFOSEL & RUSB2_CFIFOSEL_ISEL_WRITE)) {} } else { /* OUT, 2 bytes */ - rusb->CFIFOSEL = RUSB2_FIFOSEL_MBW_16BIT; // RUSB2_FIFOSEL_MBW_8BIT; - while ( rusb->CFIFOSEL & RUSB2_CFIFOSEL_ISEL_WRITE ) {} + rusb->CFIFOSEL = fifo_sel; + while (rusb->CFIFOSEL & RUSB2_CFIFOSEL_ISEL_WRITE) {} } pipe_state_t *pipe = &_dcd.pipe[0]; - pipe->ff = buffer_type; - pipe->length = total_bytes; - pipe->remaining = total_bytes; + pipe->ff = buffer_type; + pipe->length = total_bytes; + pipe->remaining = total_bytes; - if ( total_bytes ) { + if (total_bytes) { pipe->buf = buffer; - if ( ep_addr ) { + if (ep_addr) { /* IN */ TU_ASSERT(rusb->DCPCTR_b.BSTS && (rusb->USBREQ & 0x80)); pipe0_xfer_in(rusb); @@ -631,18 +735,20 @@ static void process_set_address(uint8_t rhport) { rusb2_reg_t* rusb = RUSB2_REG(rhport); const uint16_t addr = rusb->USBADDR_b.USBADDR; - if (!addr) return; + if (!addr) { + return; + } const tusb_control_request_t setup_packet = { #if defined(__CCRX__) .bmRequestType = { 0 }, /* Note: CCRX needs the braces over this struct member */ -#else - .bmRequestType = 0, -#endif - .bRequest = TUSB_REQ_SET_ADDRESS, - .wValue = addr, - .wIndex = 0, - .wLength = 0, + #else + .bmRequestType = 0, + #endif + .bRequest = TUSB_REQ_SET_ADDRESS, + .wValue = addr, + .wIndex = 0, + .wLength = 0, }; dcd_event_setup_received(rhport, (const uint8_t *) &setup_packet, true); diff --git a/src/tusb_option.h b/src/tusb_option.h index 8e147707a..0abae6116 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -375,10 +375,11 @@ //------------ RUSB2 --------------// #if defined(TUP_USBIP_RUSB2) - #define CFG_TUD_EDPT_DEDICATED_HWFIFO 1 - #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE 2 // 16-bit data - #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE_ODD_BYTE_SUPPORT // support odd byte access - #define CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE 0 + #define CFG_TUD_EDPT_DEDICATED_HWFIFO 1 + #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE (2 + (TUD_OPT_HIGH_SPEED ? 4 : 0)) // 16 bit and 32 bit data if highspeed + #define CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE 0 + #define CFG_TUSB_FIFO_HWFIFO_CUSTOM_WRITE // custom write since rusb2 can change access width 32 -> 16 and can write + // odd byte with byte access #endif //-------------------------------------------------------------------- diff --git a/test/hil/tinyusb.json b/test/hil/tinyusb.json index 6afcb2186..047d0879c 100644 --- a/test/hil/tinyusb.json +++ b/test/hil/tinyusb.json @@ -103,8 +103,9 @@ "name": "ra4m1_ek", "uid": "152E163038303131393346E46F26574B", "tests": { - "device": true, "host": false, "dual": false, - "skip": ["device/cdc_msc", "device/cdc_msc_freertos"] + "device": true, + "host": false, + "dual": false }, "comment": "MSC is slow to enumerated #2602", "flasher": { -- cgit v1.3.1 From ea23966aa785a630012097943c70d8121c5139c1 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 3 Jan 2026 15:37:22 +0700 Subject: add default access mode for tu_hwfifo API make it easier for non-custom read/write --- src/common/tusb_fifo.c | 4 ++-- src/common/tusb_fifo.h | 8 ++++++-- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 13 +++++-------- src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c | 6 +++--- src/portable/synopsys/dwc2/dcd_dwc2.c | 10 ++++------ 5 files changed, 20 insertions(+), 21 deletions(-) (limited to 'src/portable') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index f6963a98d..362439fb8 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -138,7 +138,7 @@ static void stride_write(volatile void *hwfifo, const void *src, uint8_t data_st // Copy from fifo to fixed address buffer (usually a tx register) with TU_FIFO_FIXED_ADDR_RW32 mode void tu_hwfifo_write(volatile void *hwfifo, const uint8_t *src, uint16_t len, const tu_hwfifo_access_t *access_mode) { // Write full available 16/32 bit words to dest - const uint8_t data_stride = access_mode->data_stride; + const uint8_t data_stride = (access_mode != NULL) ? access_mode->data_stride : CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE; while (len >= data_stride) { stride_write(hwfifo, src, data_stride); src += data_stride; @@ -172,7 +172,7 @@ static void stride_read(const volatile void *hwfifo, void *dest, uint8_t data_st void tu_hwfifo_read(const volatile void *hwfifo, uint8_t *dest, uint16_t len, const tu_hwfifo_access_t *access_mode) { // Reading full available 16/32-bit hwfifo and write to fifo - const uint8_t data_stride = access_mode->data_stride; + const uint8_t data_stride = (access_mode != NULL) ? access_mode->data_stride : CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE; while (len >= data_stride) { stride_read(hwfifo, dest, data_stride); dest += data_stride; diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 6fcc7020c..6c653c729 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -233,12 +233,16 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_write_n(tu_fifo_t *f, const //--------------------------------------------------------------------+ TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_hwfifo_write_from_fifo(volatile void *hwfifo, tu_fifo_t *f, uint16_t n, const tu_hwfifo_access_t *access_mode) { - return tu_fifo_read_n_access_mode(f, (void *)(uintptr_t)hwfifo, n, access_mode); + const tu_hwfifo_access_t default_access = {.data_stride = CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE}; + return tu_fifo_read_n_access_mode(f, (void *)(uintptr_t)hwfifo, n, + (access_mode != NULL) ? access_mode : &default_access); } TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_hwfifo_read_to_fifo(const volatile void *hwfifo, tu_fifo_t *f, uint16_t n, const tu_hwfifo_access_t *access_mode) { - return tu_fifo_write_n_access_mode(f, (const void *)(uintptr_t)hwfifo, n, access_mode); + const tu_hwfifo_access_t default_access = {.data_stride = CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE}; + return tu_fifo_write_n_access_mode(f, (const void *)(uintptr_t)hwfifo, n, + (access_mode != NULL) ? access_mode : &default_access); } #if CFG_TUSB_FIFO_HWFIFO_API diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 2832611ff..72527a9ec 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -285,8 +285,7 @@ static void handle_ctr_setup(uint32_t ep_id) { uint16_t rx_addr = btable_get_addr(ep_id, BTABLE_BUF_RX); uint8_t setup_packet[8] TU_ATTR_ALIGNED(4); - const tu_hwfifo_access_t access_mode = {.data_stride = CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE}; - tu_hwfifo_read(PMA_BUF_AT(rx_addr), setup_packet, rx_count, &access_mode); + tu_hwfifo_read(PMA_BUF_AT(rx_addr), setup_packet, rx_count, NULL); // Clear CTR RX if another setup packet arrived before this, it will be discarded ep_write_clear_ctr(ep_id, TUSB_DIR_OUT); @@ -324,11 +323,10 @@ static void handle_ctr_rx(uint32_t ep_id) { uint16_t pma_addr = (uint16_t) btable_get_addr(ep_id, buf_id); fsdev_pma_buf_t *pma_buf = PMA_BUF_AT(pma_addr); - const tu_hwfifo_access_t access_mode = {.data_stride = CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE}; if (xfer->ff) { - tu_hwfifo_read_to_fifo(pma_buf, xfer->ff, rx_count, &access_mode); + tu_hwfifo_read_to_fifo(pma_buf, xfer->ff, rx_count, NULL); } else { - tu_hwfifo_read(pma_buf, xfer->buffer + xfer->queued_len, rx_count, &access_mode); + tu_hwfifo_read(pma_buf, xfer->buffer + xfer->queued_len, rx_count, NULL); } xfer->queued_len += rx_count; @@ -723,11 +721,10 @@ static void dcd_transmit_packet(xfer_ctl_t *xfer, uint16_t ep_ix) { uint16_t addr_ptr = (uint16_t)btable_get_addr(ep_ix, buf_id); fsdev_pma_buf_t *pma_buf = PMA_BUF_AT(addr_ptr); - const tu_hwfifo_access_t access_mode = {.data_stride = CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE}; if (xfer->ff) { - tu_hwfifo_write_from_fifo(pma_buf, xfer->ff, len, &access_mode); + tu_hwfifo_write_from_fifo(pma_buf, xfer->ff, len, NULL); } else { - tu_hwfifo_write(pma_buf, &(xfer->buffer[xfer->queued_len]), len, &access_mode); + tu_hwfifo_write(pma_buf, &(xfer->buffer[xfer->queued_len]), len, NULL); } xfer->queued_len += len; diff --git a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c index 480e460cb..f232f7d94 100644 --- a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c @@ -316,7 +316,7 @@ static void ch_handle_ack(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) { // More data to send uint16_t const len = tu_min16(edpt->buflen - edpt->queued_len, edpt->max_packet_size); uint16_t pma_addr = (uint16_t) btable_get_addr(ch_id, BTABLE_BUF_TX); - tu_hwfifo_write(PMA_BUF_AT(pma_addr), &(edpt->buffer[edpt->queued_len]), len); + tu_hwfifo_write(PMA_BUF_AT(pma_addr), &(edpt->buffer[edpt->queued_len]), len, NULL); btable_set_count(ch_id, BTABLE_BUF_TX, len); edpt->queued_len += len; channel_write_status(ch_id, ch_reg, TUSB_DIR_OUT, EP_STAT_VALID, false); @@ -331,7 +331,7 @@ static void ch_handle_ack(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) { // IN/RX direction uint16_t const rx_count = channel_get_rx_count(ch_id); uint16_t pma_addr = (uint16_t) btable_get_addr(ch_id, BTABLE_BUF_RX); - tu_hwfifo_read(PMA_BUF_AT(pma_addr), edpt->buffer + edpt->queued_len, rx_count); + tu_hwfifo_read(PMA_BUF_AT(pma_addr), edpt->buffer + edpt->queued_len, rx_count, NULL); edpt->queued_len += rx_count; if ((rx_count < edpt->max_packet_size) || (edpt->queued_len >= edpt->buflen)) { @@ -842,7 +842,7 @@ static bool channel_xfer_start(uint8_t ch_id, tusb_dir_t dir) { if (dir == TUSB_DIR_OUT) { uint16_t const len = tu_min16(edpt->buflen - edpt->queued_len, edpt->max_packet_size); - tu_hwfifo_write(PMA_BUF_AT(pma_addr), &(edpt->buffer[edpt->queued_len]), len); + tu_hwfifo_write(PMA_BUF_AT(pma_addr), &(edpt->buffer[edpt->queued_len]), len, NULL); btable_set_count(ch_id, BTABLE_BUF_TX, len); edpt->queued_len += len; diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index 2309afd53..4110e1530 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -365,13 +365,12 @@ static uint16_t epin_write_tx_fifo(dwc2_regs_t *dwc2, uint8_t epnum) { } // Push packet to Tx-FIFO - const tu_hwfifo_access_t access_mode = {.data_stride = CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE}; volatile uint32_t *tx_fifo = dwc2->fifo[epnum]; if (xfer->ff) { - tu_hwfifo_write_from_fifo(tx_fifo, xfer->ff, xact_bytes, &access_mode); + tu_hwfifo_write_from_fifo(tx_fifo, xfer->ff, xact_bytes, NULL); total_bytes_written += xact_bytes; } else { - tu_hwfifo_write(tx_fifo, xfer->buffer, xact_bytes, &access_mode); + tu_hwfifo_write(tx_fifo, xfer->buffer, xact_bytes, NULL); xfer->buffer += xact_bytes; total_bytes_written += xact_bytes; } @@ -889,11 +888,10 @@ static void handle_rxflvl_irq(uint8_t rhport) { if (byte_count != 0) { // Read packet off RxFIFO - const tu_hwfifo_access_t access_mode = {.data_stride = CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE}; if (xfer->ff != NULL) { - tu_hwfifo_read_to_fifo(rx_fifo, xfer->ff, byte_count, &access_mode); + tu_hwfifo_read_to_fifo(rx_fifo, xfer->ff, byte_count, NULL); } else { - tu_hwfifo_read(rx_fifo, xfer->buffer, byte_count, &access_mode); + tu_hwfifo_read(rx_fifo, xfer->buffer, byte_count, NULL); xfer->buffer += byte_count; } } -- cgit v1.3.1 From 93a1e8093a8abaac799e2aa45ec7dd1239a92196 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 3 Jan 2026 16:37:17 +0700 Subject: rusb2 move tu_hwfifo_write() to rusb2_common.c --- src/portable/renesas/rusb2/dcd_rusb2.c | 105 ++++++++---------------------- src/portable/renesas/rusb2/rusb2_common.c | 63 +++++++++++++++++- 2 files changed, 89 insertions(+), 79 deletions(-) (limited to 'src/portable') diff --git a/src/portable/renesas/rusb2/dcd_rusb2.c b/src/portable/renesas/rusb2/dcd_rusb2.c index f8fc7a643..6722e7a75 100644 --- a/src/portable/renesas/rusb2/dcd_rusb2.c +++ b/src/portable/renesas/rusb2/dcd_rusb2.c @@ -281,71 +281,12 @@ static void pipe_read_packet_ff(rusb2_reg_t *rusb, tu_fifo_t *f, volatile void * } #endif -static void hwfifo_set_mbw(rusb2_reg_t *rusb, uintptr_t hwfifo, uint16_t mbw) { - volatile uint16_t *fifo_sel; - if (hwfifo == (uintptr_t)&rusb->CFIFO) { - fifo_sel = &rusb->CFIFOSEL; - } else if (hwfifo == (uintptr_t)&rusb->D0FIFO) { - fifo_sel = &rusb->D0FIFOSEL; - } else if (hwfifo == (uintptr_t)&rusb->D1FIFO) { - fifo_sel = &rusb->D1FIFOSEL; - } else { - return; - } - - *fifo_sel = (*fifo_sel & ~RUSB2_CFIFOSEL_MBW_Msk) | mbw; -} - -// write to hwfifo from buffer with access mode -void tu_hwfifo_write(volatile void *hwfifo, const uint8_t *src, uint16_t len, const tu_hwfifo_access_t *access_mode) { - rusb2_reg_t *rusb = (rusb2_reg_t *)access_mode->param; - const uint8_t *buf8 = (const uint8_t *)src; - - volatile uint16_t *ff16; - volatile uint8_t *ff8; - const bool is_highspeed = rusb2_is_highspeed_reg(rusb); - if (is_highspeed) { - ff16 = (volatile uint16_t *)((uintptr_t)hwfifo + 2); - ff8 = (volatile uint8_t *)((uintptr_t)hwfifo + 3); - } else { - ff16 = (volatile uint16_t *)hwfifo; - ff8 = ((volatile uint8_t *)hwfifo); - } - - // 32-bit access for highspeed - if (is_highspeed) { - volatile uint32_t *ff32 = (volatile uint32_t *)hwfifo; - while (len >= 4) { - *ff32 = tu_unaligned_read32(buf8); - buf8 += 4; - len -= 4; - } - - if (len >= 2) { - // switch to 16-bit access - hwfifo_set_mbw(rusb, (uintptr_t)hwfifo, RUSB2_FIFOSEL_MBW_16BIT); - } - } - - // 16-bit access - while (len >= 2) { - *ff16 = tu_unaligned_read16(buf8); - buf8 += 2; - len -= 2; - } - // 8-bit access does not need to change MBW - if (len > 0) { - *ff8 = *buf8; - ++buf8; - } -} //--------------------------------------------------------------------+ // Pipe Transfer //--------------------------------------------------------------------+ - -static bool pipe0_xfer_in(rusb2_reg_t *rusb) { +static bool pipe0_xact_in(rusb2_reg_t *rusb) { pipe_state_t *pipe = &_dcd.pipe[0]; const unsigned rem = pipe->remaining; @@ -359,8 +300,20 @@ static bool pipe0_xfer_in(rusb2_reg_t *rusb) { void *buf = pipe->buf; if (len) { - tu_hwfifo_access_t access_mode = {.data_stride = (rusb2_is_highspeed_reg(rusb) ? 4u : 2u), - .param = (uintptr_t)rusb}; + // uint16_t fifo_sel = RUSB2_CFIFOSEL_ISEL_WRITE | FIFOSEL_BIGEND; + tu_hwfifo_access_t access_mode; + access_mode.param = (uintptr_t)rusb; + // + if (rusb2_is_highspeed_reg(rusb)) { + // fifo_sel |= RUSB2_FIFOSEL_MBW_32BIT; + access_mode.data_stride = 4u; + } else { + // fifo_sel |= RUSB2_FIFOSEL_MBW_16BIT; + access_mode.data_stride = 2u; + } + // rusb->CFIFOSEL = fifo_sel; + // while (0 == (rusb->CFIFOSEL & RUSB2_CFIFOSEL_ISEL_WRITE)) {} + if (pipe->ff) { tu_hwfifo_write_from_fifo(&rusb->CFIFO, (tu_fifo_t *)buf, len, &access_mode); } else { @@ -377,7 +330,7 @@ static bool pipe0_xfer_in(rusb2_reg_t *rusb) { return false; } -static bool pipe0_xfer_out(rusb2_reg_t *rusb) { +static bool pipe0_xact_out(rusb2_reg_t *rusb) { pipe_state_t *pipe = &_dcd.pipe[0]; const unsigned rem = pipe->remaining; @@ -539,21 +492,17 @@ static void process_status_completion(uint8_t rhport) static bool process_pipe0_xfer(rusb2_reg_t *rusb, int buffer_type, uint8_t ep_addr, void *buffer, uint16_t total_bytes) { - uint16_t fifo_sel = FIFOSEL_BIGEND; - if (rusb2_is_highspeed_reg(rusb)) { - fifo_sel |= RUSB2_FIFOSEL_MBW_32BIT; - } else { - fifo_sel |= RUSB2_FIFOSEL_MBW_16BIT; - } + uint16_t fifo_sel = + (rusb2_is_highspeed_reg(rusb) ? RUSB2_FIFOSEL_MBW_32BIT : RUSB2_FIFOSEL_MBW_16BIT) | FIFOSEL_BIGEND; /* configure fifo direction and access unit settings */ if (ep_addr != 0) { - /* IN, 2 bytes */ rusb->CFIFOSEL = RUSB2_CFIFOSEL_ISEL_WRITE | fifo_sel; - while (!(rusb->CFIFOSEL & RUSB2_CFIFOSEL_ISEL_WRITE)) {} - } else { - /* OUT, 2 bytes */ - rusb->CFIFOSEL = fifo_sel; - while (rusb->CFIFOSEL & RUSB2_CFIFOSEL_ISEL_WRITE) {} + // Control IN + fifo_sel |= RUSB2_CFIFOSEL_ISEL_WRITE; + } + rusb->CFIFOSEL = fifo_sel; + while ((rusb->CFIFOSEL & RUSB2_CFIFOSEL_ISEL_WRITE) != (fifo_sel & RUSB2_CFIFOSEL_ISEL_WRITE)) { + // wait until ISEL_WRITE take effect } pipe_state_t *pipe = &_dcd.pipe[0]; @@ -566,7 +515,7 @@ static bool process_pipe0_xfer(rusb2_reg_t *rusb, int buffer_type, uint8_t ep_ad if (ep_addr) { /* IN */ TU_ASSERT(rusb->DCPCTR_b.BSTS && (rusb->USBREQ & 0x80)); - pipe0_xfer_in(rusb); + pipe0_xact_in(rusb); } rusb->DCPCTR = RUSB2_PIPE_CTR_PID_BUF; } else { @@ -639,7 +588,7 @@ static bool process_edpt_xfer(rusb2_reg_t* rusb, int buffer_type, uint8_t ep_add static void process_pipe0_bemp(uint8_t rhport) { rusb2_reg_t* rusb = RUSB2_REG(rhport); - bool completed = pipe0_xfer_in(rusb); + bool completed = pipe0_xact_in(rusb); if (completed) { pipe_state_t *pipe = &_dcd.pipe[0]; dcd_event_xfer_complete(rhport, tu_edpt_addr(0, TUSB_DIR_IN), @@ -662,7 +611,7 @@ static void process_pipe_brdy(uint8_t rhport, unsigned num) if (num) { completed = pipe_xfer_out(rusb, num); } else { - completed = pipe0_xfer_out(rusb); + completed = pipe0_xact_out(rusb); } } if (completed) { diff --git a/src/portable/renesas/rusb2/rusb2_common.c b/src/portable/renesas/rusb2/rusb2_common.c index 856f9714f..3ed6f2be1 100644 --- a/src/portable/renesas/rusb2/rusb2_common.c +++ b/src/portable/renesas/rusb2/rusb2_common.c @@ -25,9 +25,10 @@ */ #include "tusb_option.h" +#include "osal/osal.h" +#include "common/tusb_fifo.h" #if defined(TUP_USBIP_RUSB2) && (CFG_TUH_ENABLED || CFG_TUD_ENABLED) - #include "rusb2_type.h" #if TU_CHECK_MCU(OPT_MCU_RX63X, OPT_MCU_RX65X, OPT_MCU_RX72N) @@ -55,4 +56,64 @@ void tusb_rusb2_set_irqnum(uint8_t rhport, int32_t irqnum) { #endif +static void hwfifo_set_mbw(rusb2_reg_t *rusb, uintptr_t hwfifo, uint16_t mbw) { + volatile uint16_t *fifo_sel; + if (hwfifo == (uintptr_t)&rusb->CFIFO) { + fifo_sel = &rusb->CFIFOSEL; + } else if (hwfifo == (uintptr_t)&rusb->D0FIFO) { + fifo_sel = &rusb->D0FIFOSEL; + } else if (hwfifo == (uintptr_t)&rusb->D1FIFO) { + fifo_sel = &rusb->D1FIFOSEL; + } else { + return; + } + + *fifo_sel = (*fifo_sel & ~RUSB2_CFIFOSEL_MBW_Msk) | mbw; +} + +// write to hwfifo from buffer with access mode +void tu_hwfifo_write(volatile void *hwfifo, const uint8_t *src, uint16_t len, const tu_hwfifo_access_t *access_mode) { + rusb2_reg_t *rusb = (rusb2_reg_t *)access_mode->param; + const uint8_t *buf8 = (const uint8_t *)src; + + volatile uint16_t *ff16; + volatile uint8_t *ff8; + const bool is_highspeed = rusb2_is_highspeed_reg(rusb); + if (is_highspeed) { + ff16 = (volatile uint16_t *)((uintptr_t)hwfifo + 2); + ff8 = (volatile uint8_t *)((uintptr_t)hwfifo + 3); + } else { + ff16 = (volatile uint16_t *)hwfifo; + ff8 = ((volatile uint8_t *)hwfifo); + } + + // 32-bit access for highspeed + if (is_highspeed) { + volatile uint32_t *ff32 = (volatile uint32_t *)hwfifo; + while (len >= 4) { + *ff32 = tu_unaligned_read32(buf8); + buf8 += 4; + len -= 4; + } + + if (len >= 2) { + // switch to 16-bit access + hwfifo_set_mbw(rusb, (uintptr_t)hwfifo, RUSB2_FIFOSEL_MBW_16BIT); + } + } + + // 16-bit access + while (len >= 2) { + *ff16 = tu_unaligned_read16(buf8); + buf8 += 2; + len -= 2; + } + + // 8-bit access does not need to change MBW + if (len > 0) { + *ff8 = *buf8; + ++buf8; + } +} + #endif -- cgit v1.3.1 From d457ea3d3ca6727099211528bc0c415ed12eadff Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 3 Jan 2026 17:52:58 +0700 Subject: fix build with dwc2 --- src/common/tusb_fifo.h | 2 +- src/common/tusb_mcu.h | 8 ---- src/portable/synopsys/dwc2/dcd_dwc2.c | 85 +++++++++++++++++++---------------- src/tusb_option.h | 39 +++++++--------- 4 files changed, 65 insertions(+), 69 deletions(-) (limited to 'src/portable') diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 6c653c729..967e6702c 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -41,7 +41,7 @@ extern "C" { // mutex is only needed for RTOS. For OS None, we don't get preempted #define CFG_FIFO_MUTEX OSAL_MUTEX_REQUIRED -#define CFG_TUSB_FIFO_HWFIFO_API (CFG_TUD_EDPT_DEDICATED_HWFIFO) +#define CFG_TUSB_FIFO_HWFIFO_API (CFG_TUD_EDPT_DEDICATED_HWFIFO || CFG_TUH_EDPT_DEDICATED_HWFIFO) #ifndef CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE 0 diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index f525a5a3d..8dd4078c4 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -429,10 +429,6 @@ #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 - #elif TU_CHECK_MCU(OPT_MCU_ESP32P4) #define TUP_USBIP_DWC2 #define TUP_USBIP_DWC2_ESP32 @@ -445,10 +441,6 @@ #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 - // 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 diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index 4110e1530..44f7137f9 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -98,10 +98,14 @@ TU_ATTR_ALWAYS_INLINE static inline bool edpt_is_enabled(dwc2_dep_t* dep) { return (dep->ctl & EPCTL_EPENA) != 0; } -//-------------------------------------------------------------------- -// DMA -//-------------------------------------------------------------------- -#if CFG_TUD_MEM_DCACHE_ENABLE + #if CFG_TUD_DWC2_SLAVE_ENABLE +static uint16_t epin_write_tx_fifo(dwc2_regs_t *dwc2, uint8_t epnum); + #endif + + //-------------------------------------------------------------------- + // DMA + //-------------------------------------------------------------------- + #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); @@ -345,39 +349,6 @@ static void edpt_disable(uint8_t rhport, uint8_t ep_addr, bool stall) { } } -static uint16_t epin_write_tx_fifo(dwc2_regs_t *dwc2, uint8_t epnum) { - dwc2_dep_t *const epin = &dwc2->ep[0][epnum]; - xfer_ctl_t *const xfer = XFER_CTL_BASE(epnum, TUSB_DIR_IN); - - dwc2_ep_tsize_t tsiz = {.value = epin->tsiz}; - const uint16_t remain_packets = tsiz.packet_count; - - uint16_t total_bytes_written = 0; - // Process every single packet (only whole packets can be written to fifo) - for (uint16_t i = 0; i < remain_packets; i++) { - 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 - if (xact_bytes > ((epin->dtxfsts & DTXFSTS_INEPTFSAV_Msk) << 2)) { - break; - } - - // Push packet to Tx-FIFO - volatile uint32_t *tx_fifo = dwc2->fifo[epnum]; - if (xfer->ff) { - tu_hwfifo_write_from_fifo(tx_fifo, xfer->ff, xact_bytes, NULL); - total_bytes_written += xact_bytes; - } else { - tu_hwfifo_write(tx_fifo, xfer->buffer, xact_bytes, NULL); - xfer->buffer += xact_bytes; - total_bytes_written += xact_bytes; - } - } - return total_bytes_written; -} - // 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 @@ -422,6 +393,7 @@ static void edpt_schedule_packets(uint8_t rhport, const uint8_t epnum, const uin } } + #if CFG_TUD_DWC2_DMA_ENABLE const bool is_dma = dma_device_enabled(dwc2); if(is_dma) { if (dir == TUSB_DIR_IN && total_bytes != 0) { @@ -433,7 +405,10 @@ static void edpt_schedule_packets(uint8_t rhport, const uint8_t epnum, const uin if (epnum == 0) { xfer->buffer += total_bytes; } - } else { + } else + #endif + { + #if CFG_TUD_DWC2_SLAVE_ENABLE dep->diepctl = depctl.value; // enable endpoint if (dir == TUSB_DIR_IN && total_bytes != 0) { @@ -445,6 +420,7 @@ static void edpt_schedule_packets(uint8_t rhport, const uint8_t epnum, const uin dwc2->diepempmsk |= (1u << epnum); } } + #endif } } @@ -850,6 +826,39 @@ TU_ATTR_ALWAYS_INLINE static inline void print_doepint(uint32_t doepint) { #endif #if CFG_TUD_DWC2_SLAVE_ENABLE +static uint16_t epin_write_tx_fifo(dwc2_regs_t *dwc2, uint8_t epnum) { + dwc2_dep_t *const epin = &dwc2->ep[0][epnum]; + xfer_ctl_t *const xfer = XFER_CTL_BASE(epnum, TUSB_DIR_IN); + + dwc2_ep_tsize_t tsiz = {.value = epin->tsiz}; + const uint16_t remain_packets = tsiz.packet_count; + + uint16_t total_bytes_written = 0; + // Process every single packet (only whole packets can be written to fifo) + for (uint16_t i = 0; i < remain_packets; i++) { + 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 + if (xact_bytes > ((epin->dtxfsts & DTXFSTS_INEPTFSAV_Msk) << 2)) { + break; + } + + // Push packet to Tx-FIFO + volatile uint32_t *tx_fifo = dwc2->fifo[epnum]; + if (xfer->ff) { + tu_hwfifo_write_from_fifo(tx_fifo, xfer->ff, xact_bytes, NULL); + total_bytes_written += xact_bytes; + } else { + tu_hwfifo_write(tx_fifo, xfer->buffer, xact_bytes, NULL); + xfer->buffer += xact_bytes; + total_bytes_written += xact_bytes; + } + } + return total_bytes_written; +} + // Process shared receive FIFO, this interrupt is only used in Slave mode static void handle_rxflvl_irq(uint8_t rhport) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); diff --git a/src/tusb_option.h b/src/tusb_option.h index 0abae6116..453dddb7c 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -268,16 +268,7 @@ //--------------------------------------------------------------------+ //------------- DWC2 -------------// -// Slave mode for device -#ifndef CFG_TUD_DWC2_SLAVE_ENABLE - #ifndef CFG_TUD_DWC2_SLAVE_ENABLE_DEFAULT - #define CFG_TUD_DWC2_SLAVE_ENABLE_DEFAULT 1 - #endif - - #define CFG_TUD_DWC2_SLAVE_ENABLE CFG_TUD_DWC2_SLAVE_ENABLE_DEFAULT -#endif - -// DMA for device +// DMA mode for device #ifndef CFG_TUD_DWC2_DMA_ENABLE #ifndef CFG_TUD_DWC2_DMA_ENABLE_DEFAULT #define CFG_TUD_DWC2_DMA_ENABLE_DEFAULT 0 @@ -286,16 +277,16 @@ #define CFG_TUD_DWC2_DMA_ENABLE CFG_TUD_DWC2_DMA_ENABLE_DEFAULT #endif -// Slave mode for host -#ifndef CFG_TUH_DWC2_SLAVE_ENABLE - #ifndef CFG_TUH_DWC2_SLAVE_ENABLE_DEFAULT - #define CFG_TUH_DWC2_SLAVE_ENABLE_DEFAULT 1 +// Slave mode for device +#ifndef CFG_TUD_DWC2_SLAVE_ENABLE + #ifndef CFG_TUD_DWC2_SLAVE_ENABLE_DEFAULT + #define CFG_TUD_DWC2_SLAVE_ENABLE_DEFAULT !CFG_TUD_DWC2_DMA_ENABLE // disabled if DMA is enabled #endif - #define CFG_TUH_DWC2_SLAVE_ENABLE CFG_TUH_DWC2_SLAVE_ENABLE_DEFAULT + #define CFG_TUD_DWC2_SLAVE_ENABLE CFG_TUD_DWC2_SLAVE_ENABLE_DEFAULT #endif -// DMA for host +// DMA mode for host #ifndef CFG_TUH_DWC2_DMA_ENABLE #ifndef CFG_TUH_DWC2_DMA_ENABLE_DEFAULT #define CFG_TUH_DWC2_DMA_ENABLE_DEFAULT 0 @@ -304,14 +295,18 @@ #define CFG_TUH_DWC2_DMA_ENABLE CFG_TUH_DWC2_DMA_ENABLE_DEFAULT #endif -#if defined(TUP_USBIP_DWC2) - #if CFG_TUD_DWC2_SLAVE_ENABLE && !CFG_TUD_DWC2_DMA_ENABLE - #define CFG_TUD_EDPT_DEDICATED_HWFIFO 1 +// Slave mode for host +#ifndef CFG_TUH_DWC2_SLAVE_ENABLE + #ifndef CFG_TUH_DWC2_SLAVE_ENABLE_DEFAULT + #define CFG_TUH_DWC2_SLAVE_ENABLE_DEFAULT !CFG_TUH_DWC2_DMA_ENABLE // disabled if DMA is enabled #endif - #if CFG_TUH_DWC2_SLAVE_ENABLE && !CFG_TUH_DWC2_DMA_ENABLE - #define CFG_TUH_EDPT_DEDICATED_HWFIFO 1 - #endif + #define CFG_TUH_DWC2_SLAVE_ENABLE CFG_TUH_DWC2_SLAVE_ENABLE_DEFAULT +#endif + +#if defined(TUP_USBIP_DWC2) + #define CFG_TUD_EDPT_DEDICATED_HWFIFO CFG_TUD_DWC2_SLAVE_ENABLE + #define CFG_TUH_EDPT_DEDICATED_HWFIFO CFG_TUH_DWC2_SLAVE_ENABLE #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE 4 // 32bit access #define CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE 0 // fixed hwfifo address -- cgit v1.3.1 From b93d463afa11a7a24bc43dc7969a287c1d056b27 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 3 Jan 2026 23:54:05 +0700 Subject: fix rusb2 hcd_port_connect_status() using line state, add post root reset delay for stable speed detection --- src/host/usbh.c | 14 ++++++----- src/portable/renesas/rusb2/hcd_rusb2.c | 43 +++++++++------------------------ src/portable/renesas/rusb2/rusb2_type.h | 13 +++++++--- 3 files changed, 28 insertions(+), 42 deletions(-) (limited to 'src/portable') diff --git a/src/host/usbh.c b/src/host/usbh.c index e99d9e977..a725b7c8b 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -1405,12 +1405,13 @@ static void remove_device_tree(uint8_t rhport, uint8_t hub_addr, uint8_t hub_por // NOTE: due to the shared control buffer, we must complete enumerating // one device before enumerating another one. //--------------------------------------------------------------------+ -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_SET_ADDRESS_RECOVERY_DELAY_MS = 2, // USB 2.0 Spec 9.2.6.3 min is 2 ms +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_ROOT_POST_DELAY_MS = 2, // 2 ms delay after root port reset before getting speed/status + 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 { @@ -1469,6 +1470,7 @@ static bool enum_new_device(hcd_event_t* event) { hcd_port_reset(dev0_bus->rhport); tusb_time_delay_ms_api(ENUM_RESET_ROOT_DELAY_MS); hcd_port_reset_end(dev0_bus->rhport); + tusb_time_delay_ms_api(ENUM_RESET_ROOT_POST_DELAY_MS); if (!hcd_port_connect_status(dev0_bus->rhport)) { // device unplugged while delaying diff --git a/src/portable/renesas/rusb2/hcd_rusb2.c b/src/portable/renesas/rusb2/hcd_rusb2.c index 6f6d27d0e..d70599f5b 100644 --- a/src/portable/renesas/rusb2/hcd_rusb2.c +++ b/src/portable/renesas/rusb2/hcd_rusb2.c @@ -76,12 +76,10 @@ typedef struct TU_ATTR_PACKED { TU_ATTR_PACKED_END // End of definition of packed structs (used by the CCRX toolchain) TU_ATTR_BIT_FIELD_ORDER_END -typedef struct -{ - bool need_reset; /* The device has not been reset after connection. */ +typedef struct { pipe_state_t pipe[PIPE_COUNT]; - uint8_t ep[4][2][15]; /* a lookup table for a pipe index from an endpoint address */ - uint8_t ctl_mps[5]; /* EP0 max packet size for each device */ + uint8_t ep[4][2][15]; /* a lookup table for a pipe index from an endpoint address */ + uint8_t ctl_mps[5]; /* EP0 max packet size for each device */ } hcd_data_t; //--------------------------------------------------------------------+ @@ -535,13 +533,8 @@ void hcd_int_disable(uint8_t rhport) { rusb2_int_disable(rhport); } -uint32_t hcd_frame_number(uint8_t rhport) -{ - rusb2_reg_t* rusb = RUSB2_REG(rhport); - - /* The device must be reset at least once after connection - * in order to start the frame counter. */ - if (_hcd.need_reset) hcd_port_reset(rhport); +uint32_t hcd_frame_number(uint8_t rhport) { + rusb2_reg_t *rusb = RUSB2_REG(rhport); return rusb->FRMNUM_b.FRNM; } @@ -550,32 +543,18 @@ uint32_t hcd_frame_number(uint8_t rhport) *--------------------------------------------------------------------+*/ bool hcd_port_connect_status(uint8_t rhport) { rusb2_reg_t* rusb = RUSB2_REG(rhport); - return rusb->INTSTS1_b.ATTCH ? true : false; + const uint16_t line_state = rusb->SYSSTS0 & RUSB2_SYSSTS0_LNST_Msk; + return line_state == RUSB2_SYSSTS0_LNST_FS_J || line_state == RUSB2_SYSSTS0_LNST_FS_K; } void hcd_port_reset(uint8_t rhport) { rusb2_reg_t* rusb = RUSB2_REG(rhport); - rusb->DCPCTR = RUSB2_PIPE_CTR_PID_NAK; - while (rusb->DCPCTR_b.PBUSY) {} - - hcd_int_disable(rhport); - rusb->DVSTCTR0_b.UACT = 0; - if (rusb->DCPCTR_b.SUREQ) { - rusb->DCPCTR_b.SUREQCLR = 1; - } - hcd_int_enable(rhport); - - /* Reset should be asserted 10-20ms. */ rusb->DVSTCTR0_b.USBRST = 1; - for (volatile int i = 0; i < 2400000; ++i) {} - rusb->DVSTCTR0_b.USBRST = 0; - - rusb->DVSTCTR0_b.UACT = 1; - _hcd.need_reset = false; } void hcd_port_reset_end(uint8_t rhport) { - (void) rhport; + rusb2_reg_t *rusb = RUSB2_REG(rhport); + rusb->DVSTCTR0_b.USBRST = 0; } tusb_speed_t hcd_port_speed_get(uint8_t rhport) { @@ -584,7 +563,8 @@ tusb_speed_t hcd_port_speed_get(uint8_t rhport) { case RUSB2_DVSTCTR0_RHST_HS: return TUSB_SPEED_HIGH; case RUSB2_DVSTCTR0_RHST_FS: return TUSB_SPEED_FULL; case RUSB2_DVSTCTR0_RHST_LS: return TUSB_SPEED_LOW; - default: return TUSB_SPEED_INVALID; + default: + return TUSB_SPEED_INVALID; } } @@ -802,7 +782,6 @@ void hcd_int_handler(uint8_t rhport, bool in_isr) { if (is1 & RUSB2_INTSTS1_ATTCH_Msk) { rusb->DVSTCTR0_b.UACT = 1; - _hcd.need_reset = true; rusb->INTENB1 = (rusb->INTENB1 & ~RUSB2_INTSTS1_ATTCH_Msk) | RUSB2_INTSTS1_DTCH_Msk; hcd_event_device_attach(rhport, true); } diff --git a/src/portable/renesas/rusb2/rusb2_type.h b/src/portable/renesas/rusb2/rusb2_type.h index 71837d03c..cf685ea3c 100644 --- a/src/portable/renesas/rusb2/rusb2_type.h +++ b/src/portable/renesas/rusb2/rusb2_type.h @@ -1669,15 +1669,20 @@ TU_ATTR_BIT_FIELD_ORDER_END /*--------------------------------------------------------------------*/ /* Register Bit Utils */ /*--------------------------------------------------------------------*/ -#define RUSB2_PIPE_CTR_PID_NAK (0U << RUSB2_PIPE_CTR_PID_Pos) /* NAK response */ -#define RUSB2_PIPE_CTR_PID_BUF (1U << RUSB2_PIPE_CTR_PID_Pos) /* BUF response (depends buffer state) */ -#define RUSB2_PIPE_CTR_PID_STALL (2U << RUSB2_PIPE_CTR_PID_Pos) /* STALL response */ -#define RUSB2_PIPE_CTR_PID_STALL2 (3U << RUSB2_PIPE_CTR_PID_Pos) /* Also STALL response */ +#define RUSB2_SYSSTS0_LNST_SE0 (0) +#define RUSB2_SYSSTS0_LNST_FS_J (1u << RUSB2_SYSSTS0_LNST_Pos) /* Full-speed J state */ +#define RUSB2_SYSSTS0_LNST_FS_K (2u << RUSB2_SYSSTS0_LNST_Pos) /* Full-speed K state */ +#define RUSB2_SYSSTS0_LNST_LS_SE1 (3u << RUSB2_SYSSTS0_LNST_Pos) /* Low-speed SE1 state */ #define RUSB2_DVSTCTR0_RHST_LS (1U << RUSB2_DVSTCTR0_RHST_Pos) /* Low-speed connection */ #define RUSB2_DVSTCTR0_RHST_FS (2U << RUSB2_DVSTCTR0_RHST_Pos) /* Full-speed connection */ #define RUSB2_DVSTCTR0_RHST_HS (3U << RUSB2_DVSTCTR0_RHST_Pos) /* Full-speed connection */ +#define RUSB2_PIPE_CTR_PID_NAK (0U << RUSB2_PIPE_CTR_PID_Pos) /* NAK response */ +#define RUSB2_PIPE_CTR_PID_BUF (1U << RUSB2_PIPE_CTR_PID_Pos) /* BUF response (depends buffer state) */ +#define RUSB2_PIPE_CTR_PID_STALL (2U << RUSB2_PIPE_CTR_PID_Pos) /* STALL response */ +#define RUSB2_PIPE_CTR_PID_STALL2 (3U << RUSB2_PIPE_CTR_PID_Pos) /* Also STALL response */ + #define RUSB2_DEVADD_USBSPD_LS (1U << RUSB2_DEVADD_USBSPD_Pos) /* Target Device Low-speed */ #define RUSB2_DEVADD_USBSPD_FS (2U << RUSB2_DEVADD_USBSPD_Pos) /* Target Device Full-speed */ -- cgit v1.3.1 From a9479f5ad96c28747661d9392ac28698f84c7bac Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 4 Jan 2026 01:01:52 +0700 Subject: update hcd rusb2 to use tu_hwfifo read/write --- src/common/tusb_fifo.h | 4 +- src/portable/renesas/rusb2/dcd_rusb2.c | 153 ++---------------------------- src/portable/renesas/rusb2/hcd_rusb2.c | 92 +++++++++--------- src/portable/renesas/rusb2/rusb2_common.c | 25 +++-- src/portable/renesas/rusb2/rusb2_common.h | 58 +++++++++++ src/portable/renesas/rusb2/rusb2_type.h | 7 +- 6 files changed, 125 insertions(+), 214 deletions(-) create mode 100644 src/portable/renesas/rusb2/rusb2_common.h (limited to 'src/portable') diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 967e6702c..5515ffb91 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -233,14 +233,14 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_write_n(tu_fifo_t *f, const //--------------------------------------------------------------------+ TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_hwfifo_write_from_fifo(volatile void *hwfifo, tu_fifo_t *f, uint16_t n, const tu_hwfifo_access_t *access_mode) { - const tu_hwfifo_access_t default_access = {.data_stride = CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE}; + const tu_hwfifo_access_t default_access = {.data_stride = CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE, .param = 0}; return tu_fifo_read_n_access_mode(f, (void *)(uintptr_t)hwfifo, n, (access_mode != NULL) ? access_mode : &default_access); } TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_hwfifo_read_to_fifo(const volatile void *hwfifo, tu_fifo_t *f, uint16_t n, const tu_hwfifo_access_t *access_mode) { - const tu_hwfifo_access_t default_access = {.data_stride = CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE}; + const tu_hwfifo_access_t default_access = {.data_stride = CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE, .param = 0}; return tu_fifo_write_n_access_mode(f, (const void *)(uintptr_t)hwfifo, n, (access_mode != NULL) ? access_mode : &default_access); } diff --git a/src/portable/renesas/rusb2/dcd_rusb2.c b/src/portable/renesas/rusb2/dcd_rusb2.c index 6722e7a75..e2a51a5ca 100644 --- a/src/portable/renesas/rusb2/dcd_rusb2.c +++ b/src/portable/renesas/rusb2/dcd_rusb2.c @@ -30,25 +30,7 @@ #if CFG_TUD_ENABLED && defined(TUP_USBIP_RUSB2) #include "device/dcd.h" -#include "rusb2_type.h" - -#if TU_CHECK_MCU(OPT_MCU_RX63X, OPT_MCU_RX65X, OPT_MCU_RX72N) - #include "rusb2_rx.h" -#elif TU_CHECK_MCU(OPT_MCU_RAXXX) - #include "rusb2_ra.h" - #if defined(RENESAS_CORTEX_M23) - #define D0FIFO CFIFO - #define D0FIFOSEL CFIFOSEL - #define D0FIFOSEL_b CFIFOSEL_b - #define D1FIFOSEL CFIFOSEL - #define D1FIFOSEL_b CFIFOSEL_b - #define D0FIFOCTR CFIFOCTR - #define D0FIFOCTR_b CFIFOCTR_b - #endif - -#else - #error "Unsupported MCU" -#endif +#include "rusb2_common.h" //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM @@ -57,10 +39,6 @@ enum { PIPE_COUNT = 10, }; -enum { - FIFOSEL_BIGEND = (TU_BYTE_ORDER == TU_BIG_ENDIAN ? RUSB2_FIFOSEL_BIGEND : 0) -}; - typedef struct { void *buf; /* the start address of a transfer data buffer */ uint16_t length; /* the number of bytes in the buffer */ @@ -164,129 +142,10 @@ static inline void pipe_wait_for_ready(rusb2_reg_t * rusb, unsigned num) { while ( !rusb->D0FIFOCTR_b.FRDY ) {} } -//--------------------------------------------------------------------+ -// Pipe FIFO -//--------------------------------------------------------------------+ -#define USE_HWFIFO 1 - #if !USE_HWFIFO -// Write data buffer --> hw fifo -static void pipe_write_packet(rusb2_reg_t * rusb, void *buf, volatile void *fifo, unsigned len) -{ - (void) rusb; - - volatile uint16_t *ff16; - volatile uint8_t *ff8; - - const uint8_t *buf8 = (const uint8_t *)buf; - - // Highspeed FIFO is 32-bit - if ( rusb2_is_highspeed_reg(rusb) ) { - // TODO 32-bit access for better performance - volatile uint32_t *ff32 = (volatile uint32_t *)fifo; - ff16 = (volatile uint16_t*) ((uintptr_t) fifo+2); - ff8 = (volatile uint8_t *) ((uintptr_t) fifo+3); - - while (len >= 4) { - *ff32 = tu_unaligned_read32(buf8); - buf8 += 4; - len -= 4; - } - - if (len >= 2) { - // switch to 16-bit access - rusb->CFIFOSEL = RUSB2_CFIFOSEL_ISEL_WRITE | RUSB2_FIFOSEL_MBW_16BIT | - (TU_BYTE_ORDER == TU_BIG_ENDIAN ? RUSB2_FIFOSEL_BIGEND : 0); - *ff16 = tu_unaligned_read16(buf8); - buf8 += 2; - len -= 2; - } - - if (len > 0) { - *ff8 = *buf8; - ++buf8; - } - } else { - ff16 = (volatile uint16_t*) fifo; - ff8 = ((volatile uint8_t *)fifo); - - while (len >= 2) { - *ff16 = tu_unaligned_read16(buf8); - buf8 += 2; - len -= 2; - } - - if (len > 0) { - *ff8 = *buf8; - ++buf8; - } - } -} - -// Write data sw fifo --> hw fifo -static void pipe_write_packet_ff(rusb2_reg_t * rusb, tu_fifo_t *f, volatile void *fifo, uint16_t total_len) { - tu_fifo_buffer_info_t info; - tu_fifo_get_read_info(f, &info); - - uint16_t cnt_lin = tu_min16(total_len, info.linear.len); - uint16_t cnt_wrap = tu_min16(total_len - cnt_lin, info.wrapped.len); - uint16_t const cnt_written = cnt_lin + cnt_wrap; - - // Ensure only the last write is odd if total_len is odd - if (cnt_wrap == 0) { - pipe_write_packet(rusb, info.linear.ptr, fifo, cnt_lin); - } else { - pipe_write_packet(rusb, info.linear.ptr, fifo, cnt_lin & ~1); - - if (cnt_lin & 1) { - uint8_t glue[2] = {info.linear.ptr[cnt_lin & ~1], info.wrapped.ptr[0]}; - pipe_write_packet(rusb, glue, fifo, 2); - cnt_wrap--; - info.wrapped.ptr++; - } - - pipe_write_packet(rusb, info.wrapped.ptr, fifo, cnt_wrap); - } - tu_fifo_advance_read_pointer(f, cnt_written); -} - -// Read data buffer <-- hw fifo -static void pipe_read_packet(rusb2_reg_t *rusb, void *buf, volatile void *fifo, unsigned len) { - (void)rusb; - - // TODO 16/32-bit access for better performance - - uint8_t *p = (uint8_t *)buf; - volatile uint8_t *reg = (volatile uint8_t *)fifo; /* byte access is always at base register address */ - while (len--) { - *p++ = *reg; - } -} - -// Read data sw fifo <-- hw fifo -static void pipe_read_packet_ff(rusb2_reg_t *rusb, tu_fifo_t *f, volatile void *fifo, uint16_t total_len) { - tu_fifo_buffer_info_t info; - tu_fifo_get_write_info(f, &info); - - uint16_t count = tu_min16(total_len, info.linear.len); - pipe_read_packet(rusb, info.linear.ptr, fifo, count); - - uint16_t rem = total_len - count; - if (rem) { - rem = tu_min16(rem, info.wrapped.len); - pipe_read_packet(rusb, info.wrapped.ptr, fifo, rem); - count += rem; - } - - tu_fifo_advance_write_pointer(f, count); -} - #endif - - - //--------------------------------------------------------------------+ // Pipe Transfer //--------------------------------------------------------------------+ -static bool pipe0_xact_in(rusb2_reg_t *rusb) { +static bool pipe0_xfer_in(rusb2_reg_t *rusb) { pipe_state_t *pipe = &_dcd.pipe[0]; const unsigned rem = pipe->remaining; @@ -330,7 +189,7 @@ static bool pipe0_xact_in(rusb2_reg_t *rusb) { return false; } -static bool pipe0_xact_out(rusb2_reg_t *rusb) { +static bool pipe0_xfer_out(rusb2_reg_t *rusb) { pipe_state_t *pipe = &_dcd.pipe[0]; const unsigned rem = pipe->remaining; @@ -515,7 +374,7 @@ static bool process_pipe0_xfer(rusb2_reg_t *rusb, int buffer_type, uint8_t ep_ad if (ep_addr) { /* IN */ TU_ASSERT(rusb->DCPCTR_b.BSTS && (rusb->USBREQ & 0x80)); - pipe0_xact_in(rusb); + pipe0_xfer_in(rusb); } rusb->DCPCTR = RUSB2_PIPE_CTR_PID_BUF; } else { @@ -588,7 +447,7 @@ static bool process_edpt_xfer(rusb2_reg_t* rusb, int buffer_type, uint8_t ep_add static void process_pipe0_bemp(uint8_t rhport) { rusb2_reg_t* rusb = RUSB2_REG(rhport); - bool completed = pipe0_xact_in(rusb); + bool completed = pipe0_xfer_in(rusb); if (completed) { pipe_state_t *pipe = &_dcd.pipe[0]; dcd_event_xfer_complete(rhport, tu_edpt_addr(0, TUSB_DIR_IN), @@ -611,7 +470,7 @@ static void process_pipe_brdy(uint8_t rhport, unsigned num) if (num) { completed = pipe_xfer_out(rusb, num); } else { - completed = pipe0_xact_out(rusb); + completed = pipe0_xfer_out(rusb); } } if (completed) { diff --git a/src/portable/renesas/rusb2/hcd_rusb2.c b/src/portable/renesas/rusb2/hcd_rusb2.c index d70599f5b..4c3315044 100644 --- a/src/portable/renesas/rusb2/hcd_rusb2.c +++ b/src/portable/renesas/rusb2/hcd_rusb2.c @@ -31,17 +31,9 @@ #include "host/hcd.h" #include "host/usbh.h" -#include "rusb2_type.h" +#include "rusb2_common.h" -#if TU_CHECK_MCU(OPT_MCU_RX63X, OPT_MCU_RX65X, OPT_MCU_RX72N) - #include "rusb2_rx.h" -#elif TU_CHECK_MCU(OPT_MCU_RAXXX) - #include "rusb2_ra.h" -#else - #error "Unsupported MCU" -#endif - -#define TU_RUSB2_HCD_DBG 2 + #define TU_RUSB2_HCD_DBG 2 //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM DECLARATION @@ -164,29 +156,6 @@ static inline void pipe_wait_for_ready(rusb2_reg_t* rusb, unsigned num) while (!rusb->D0FIFOCTR_b.FRDY) {} } -static void pipe_write_packet(void *buf, volatile void *fifo, unsigned len) -{ - // NOTE: unlike DCD, Highspeed 32-bit FIFO does not need to adjust the fifo address - volatile hw_fifo_t *reg = (volatile hw_fifo_t*)fifo; - uintptr_t addr = (uintptr_t)buf; - while (len >= 2) { - reg->u16 = *(const uint16_t *)addr; - addr += 2; - len -= 2; - } - if (len) { - reg->u8 = *(const uint8_t *)addr; - ++addr; - } -} - -static void pipe_read_packet(void *buf, volatile void *fifo, unsigned len) -{ - uint8_t *p = (uint8_t*)buf; - volatile uint8_t *reg = (volatile uint8_t*)fifo; /* byte access is always at base register address */ - while (len--) *p++ = *reg; -} - static bool pipe0_xfer_in(rusb2_reg_t* rusb) { pipe_state_t *pipe = &_hcd.pipe[0]; @@ -197,8 +166,12 @@ static bool pipe0_xfer_in(rusb2_reg_t* rusb) const unsigned len = TU_MIN(TU_MIN(rem, mps), vld); void *buf = pipe->buf; if (len) { + tu_hwfifo_access_t access_mode = {.data_stride = (rusb2_is_highspeed_reg(rusb) ? 4u : 2u), + .param = (uintptr_t)rusb}; + rusb->DCPCTR = RUSB2_PIPE_CTR_PID_NAK; - pipe_read_packet(buf, (volatile void*)&rusb->CFIFO, len); + // pipe_read_packet(buf, (volatile void*)&rusb->CFIFO, len); + tu_hwfifo_read(&rusb->CFIFO, buf, len, &access_mode); pipe->buf = (uint8_t*)buf + len; } if (len < mps) { @@ -225,7 +198,11 @@ static bool pipe0_xfer_out(rusb2_reg_t* rusb) const unsigned len = TU_MIN(mps, rem); void *buf = pipe->buf; if (len) { - pipe_write_packet(buf, (volatile void*)&rusb->CFIFO, len); + tu_hwfifo_access_t access_mode = {.data_stride = (rusb2_is_highspeed_reg(rusb) ? 4u : 2u), + .param = (uintptr_t)rusb}; + + // pipe_write_packet(buf, (volatile void*)&rusb->CFIFO, len); + tu_hwfifo_write(&rusb->CFIFO, buf, len, &access_mode); pipe->buf = (uint8_t*)buf + len; } if (len < mps) { @@ -240,14 +217,24 @@ static bool pipe_xfer_in(rusb2_reg_t* rusb, unsigned num) pipe_state_t *pipe = &_hcd.pipe[num]; const unsigned rem = pipe->remaining; - rusb->D0FIFOSEL = num | RUSB2_FIFOSEL_MBW_8BIT; + uint16_t fifo_sel = num | FIFOSEL_BIGEND; + if (rusb2_is_highspeed_reg(rusb)) { + fifo_sel |= RUSB2_FIFOSEL_MBW_32BIT; + } else { + fifo_sel |= RUSB2_FIFOSEL_MBW_16BIT; + } + rusb->D0FIFOSEL = fifo_sel; + const unsigned mps = edpt_max_packet_size(rusb, num); pipe_wait_for_ready(rusb, num); const unsigned vld = rusb->D0FIFOCTR_b.DTLN; const unsigned len = TU_MIN(TU_MIN(rem, mps), vld); void *buf = pipe->buf; if (len) { - pipe_read_packet(buf, (volatile void*)&rusb->D0FIFO, len); + // pipe_read_packet(buf, (volatile void*)&rusb->D0FIFO, len); + tu_hwfifo_access_t access_mode = {.data_stride = (rusb2_is_highspeed_reg(rusb) ? 4u : 2u), + .param = (uintptr_t)rusb}; + tu_hwfifo_read(&rusb->D0FIFO, buf, len, &access_mode); pipe->buf = (uint8_t*)buf + len; } if (len < mps) { @@ -273,13 +260,23 @@ static bool pipe_xfer_out(rusb2_reg_t* rusb, unsigned num) return true; } - rusb->D0FIFOSEL = num | RUSB2_FIFOSEL_MBW_16BIT | (TU_BYTE_ORDER == TU_BIG_ENDIAN ? RUSB2_FIFOSEL_BIGEND : 0); + uint16_t fifo_sel = num | FIFOSEL_BIGEND; + if (rusb2_is_highspeed_reg(rusb)) { + fifo_sel |= RUSB2_FIFOSEL_MBW_32BIT; + } else { + fifo_sel |= RUSB2_FIFOSEL_MBW_16BIT; + } + rusb->D0FIFOSEL = fifo_sel; + const unsigned mps = edpt_max_packet_size(rusb, num); pipe_wait_for_ready(rusb, num); const unsigned len = TU_MIN(rem, mps); void *buf = pipe->buf; if (len) { - pipe_write_packet(buf, (volatile void*)&rusb->D0FIFO, len); + // pipe_write_packet(buf, (volatile void*)&rusb->D0FIFO, len); + tu_hwfifo_access_t access_mode = {.data_stride = (rusb2_is_highspeed_reg(rusb) ? 4u : 2u), + .param = (uintptr_t)rusb}; + tu_hwfifo_write(&rusb->D0FIFO, buf, len, &access_mode); pipe->buf = (uint8_t*)buf + len; } if (len < mps) { @@ -294,18 +291,19 @@ static bool pipe_xfer_out(rusb2_reg_t* rusb, unsigned num) static bool process_pipe0_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, void* buffer, uint16_t buflen) { (void)dev_addr; - rusb2_reg_t* rusb = RUSB2_REG(rhport); const unsigned dir_in = tu_edpt_dir(ep_addr); + uint16_t fifo_sel = + (rusb2_is_highspeed_reg(rusb) ? RUSB2_FIFOSEL_MBW_32BIT : RUSB2_FIFOSEL_MBW_16BIT) | FIFOSEL_BIGEND; + /* configure fifo direction and access unit settings */ - if (dir_in) { /* IN, a byte */ - rusb->CFIFOSEL = RUSB2_FIFOSEL_MBW_8BIT; - while (rusb->CFIFOSEL & RUSB2_CFIFOSEL_ISEL_WRITE) ; - } else { /* OUT, 2 bytes */ - rusb->CFIFOSEL = RUSB2_CFIFOSEL_ISEL_WRITE | RUSB2_FIFOSEL_MBW_16BIT | - (TU_BYTE_ORDER == TU_BIG_ENDIAN ? RUSB2_FIFOSEL_BIGEND : 0); - while (!(rusb->CFIFOSEL & RUSB2_CFIFOSEL_ISEL_WRITE)) ; + if (dir_in == TUSB_DIR_OUT) { + fifo_sel |= RUSB2_CFIFOSEL_ISEL_WRITE; + } + rusb->CFIFOSEL = fifo_sel; + while ((rusb->CFIFOSEL & RUSB2_CFIFOSEL_ISEL_WRITE) != (fifo_sel & RUSB2_CFIFOSEL_ISEL_WRITE)) { + // wait until ISEL_WRITE take effect } pipe_state_t *pipe = &_hcd.pipe[0]; diff --git a/src/portable/renesas/rusb2/rusb2_common.c b/src/portable/renesas/rusb2/rusb2_common.c index 3ed6f2be1..8addbe4c6 100644 --- a/src/portable/renesas/rusb2/rusb2_common.c +++ b/src/portable/renesas/rusb2/rusb2_common.c @@ -25,23 +25,21 @@ */ #include "tusb_option.h" -#include "osal/osal.h" -#include "common/tusb_fifo.h" #if defined(TUP_USBIP_RUSB2) && (CFG_TUH_ENABLED || CFG_TUD_ENABLED) -#include "rusb2_type.h" + #include "osal/osal.h" + #include "common/tusb_fifo.h" -#if TU_CHECK_MCU(OPT_MCU_RX63X, OPT_MCU_RX65X, OPT_MCU_RX72N) -#include "rusb2_rx.h" + #include "rusb2_common.h" -#elif TU_CHECK_MCU(OPT_MCU_RAXXX) -#include "rusb2_ra.h" + #if TU_CHECK_MCU(OPT_MCU_RAXXX) + #include "rusb2_ra.h" // USBFS_INT_IRQn and USBHS_USB_INT_RESUME_IRQn are generated by FSP rusb2_controller_t rusb2_controller[] = { - { .reg_base = R_USB_FS0_BASE, .irqnum = USBFS_INT_IRQn }, + {.reg_base = R_USB_FS0_BASE, .irqnum = USBFS_INT_IRQn}, #ifdef RUSB2_SUPPORT_HIGHSPEED - { .reg_base = R_USB_HS0_BASE, .irqnum = USBHS_USB_INT_RESUME_IRQn }, + {.reg_base = R_USB_HS0_BASE, .irqnum = USBHS_USB_INT_RESUME_IRQn}, #endif }; @@ -50,12 +48,11 @@ void tusb_rusb2_set_irqnum(uint8_t rhport, int32_t irqnum); void tusb_rusb2_set_irqnum(uint8_t rhport, int32_t irqnum) { rusb2_controller[rhport].irqnum = irqnum; } + #endif -#else - #error "Unsupported MCU" -#endif - - +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ static void hwfifo_set_mbw(rusb2_reg_t *rusb, uintptr_t hwfifo, uint16_t mbw) { volatile uint16_t *fifo_sel; if (hwfifo == (uintptr_t)&rusb->CFIFO) { diff --git a/src/portable/renesas/rusb2/rusb2_common.h b/src/portable/renesas/rusb2/rusb2_common.h new file mode 100644 index 000000000..6b8c3d7f2 --- /dev/null +++ b/src/portable/renesas/rusb2/rusb2_common.h @@ -0,0 +1,58 @@ +/* + * 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. + */ +#pragma once + +#include "common/tusb_common.h" +#include "rusb2_type.h" + +#if TU_CHECK_MCU(OPT_MCU_RX63X, OPT_MCU_RX65X, OPT_MCU_RX72N) + #include "rusb2_rx.h" +#elif TU_CHECK_MCU(OPT_MCU_RAXXX) + #include "rusb2_ra.h" + + // Hack for D0FIFO definitions on RA Cortex-M23 + #if defined(RENESAS_CORTEX_M23) + #define D0FIFO CFIFO + #define D0FIFOSEL CFIFOSEL + #define D0FIFOSEL_b CFIFOSEL_b + #define D1FIFOSEL CFIFOSEL + #define D1FIFOSEL_b CFIFOSEL_b + #define D0FIFOCTR CFIFOCTR + #define D0FIFOCTR_b CFIFOCTR_b + #endif + +#else + #error "Unsupported MCU" +#endif + + +//--------------------------------------------------------------------+ +// Common +//--------------------------------------------------------------------+ + +enum { + FIFOSEL_BIGEND = (TU_BYTE_ORDER == TU_BIG_ENDIAN ? RUSB2_FIFOSEL_BIGEND : 0) +}; diff --git a/src/portable/renesas/rusb2/rusb2_type.h b/src/portable/renesas/rusb2/rusb2_type.h index cf685ea3c..21f116857 100644 --- a/src/portable/renesas/rusb2/rusb2_type.h +++ b/src/portable/renesas/rusb2/rusb2_type.h @@ -41,10 +41,9 @@ extern "C" { #define _ccrx_evenaccess #endif -/*--------------------------------------------------------------------*/ -/* Register Definitions */ -/*--------------------------------------------------------------------*/ - +//--------------------------------------------------------------------+ +// Register Definitions +//--------------------------------------------------------------------+ /* Start of definition of packed structs (used by the CCRX toolchain) */ TU_ATTR_PACKED_BEGIN TU_ATTR_BIT_FIELD_ORDER_BEGIN -- cgit v1.3.1 From 20d009daa1f886432d42a2f56ce8edfe62e3b0de Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 5 Jan 2026 23:42:05 +0700 Subject: enable dedidcated hwfifo for musb with odd access with 16-bit and 8-bit --- src/common/tusb_fifo.c | 65 +++++++++++++++++++++++++++----- src/portable/mentor/musb/dcd_musb.c | 74 +++---------------------------------- src/tusb_option.h | 9 ++++- 3 files changed, 69 insertions(+), 79 deletions(-) (limited to 'src/portable') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index ee07f66df..a92435912 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -123,8 +123,8 @@ void tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable) { #define HWFIFO_ADDR_NEXT(_hwfifo, _const) HWFIFO_ADDR_NEXT_N(_hwfifo, _const, CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE) #ifndef CFG_TUSB_FIFO_HWFIFO_CUSTOM_WRITE -static void stride_write(volatile void *hwfifo, const void *src, uint8_t data_stride) { - #if CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE & 4 +static inline void stride_write(volatile void *hwfifo, const void *src, uint8_t data_stride) { + #if CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE & 4 if (data_stride == 4) { *((volatile uint32_t *)hwfifo) = tu_unaligned_read32(src); } @@ -147,6 +147,25 @@ void tu_hwfifo_write(volatile void *hwfifo, const uint8_t *src, uint16_t len, co HWFIFO_ADDR_NEXT(hwfifo, ); } + #ifdef CFG_TUSB_FIFO_HWFIFO_DATA_ODD_16BIT_ACCESS + // 16-bit access is allowed for odd bytes + if (len >= 2) { + *((volatile uint16_t *)hwfifo) = tu_unaligned_read16(src); + src += 2; + len -= 2; + HWFIFO_ADDR_NEXT_N(hwfifo, , 2); + } + #endif + + #ifdef CFG_TUSB_FIFO_HWFIFO_DATA_ODD_8BIT_ACCESS + // 8-bit access is allowed for odd bytes + while (len > 0) { + *((volatile uint8_t *)hwfifo) = *src++; + len--; + HWFIFO_ADDR_NEXT_N(hwfifo, , 1); + } + #else + // Write odd bytes i.e 1 byte for 16 bit or 1-3 bytes for 32 bit if (len > 0) { uint32_t tmp = 0u; @@ -154,21 +173,30 @@ void tu_hwfifo_write(volatile void *hwfifo, const uint8_t *src, uint16_t len, co stride_write(hwfifo, &tmp, data_stride); HWFIFO_ADDR_NEXT(hwfifo, ); } + #endif } #endif #ifndef CFG_TUSB_FIFO_HWFIFO_CUSTOM_READ -static void stride_read(const volatile void *hwfifo, void *dest, uint8_t data_stride) { - #if CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE & 4 - if (data_stride == 4) { +static inline void stride_read(const volatile void *hwfifo, void *dest, uint8_t data_stride) { + (void)data_stride; // possible unused + #if CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE & 4 + #if CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE != 4 + if (data_stride == 4) + #endif + { tu_unaligned_write32(dest, *((const volatile uint32_t *)hwfifo)); } - #endif - #if CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE & 2 - if (data_stride == 2) { + #endif + + #if CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE & 2 + #if CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE != 2 + if (data_stride == 2) + #endif + { tu_unaligned_write16(dest, *((const volatile uint16_t *)hwfifo)); } - #endif + #endif } void tu_hwfifo_read(const volatile void *hwfifo, uint8_t *dest, uint16_t len, const tu_hwfifo_access_t *access_mode) { @@ -181,6 +209,24 @@ void tu_hwfifo_read(const volatile void *hwfifo, uint8_t *dest, uint16_t len, co HWFIFO_ADDR_NEXT(hwfifo, const); } + #ifdef CFG_TUSB_FIFO_HWFIFO_DATA_ODD_16BIT_ACCESS + // 16-bit access is allowed for odd bytes + if (len >= 2) { + tu_unaligned_write16(dest, *((const volatile uint16_t *)hwfifo)); + dest += 2; + len -= 2; + HWFIFO_ADDR_NEXT_N(hwfifo, const, 2); + } + #endif + + #ifdef CFG_TUSB_FIFO_HWFIFO_DATA_ODD_8BIT_ACCESS + // 8-bit access is allowed for odd bytes + while (len > 0) { + *dest++ = *((const volatile uint8_t *)hwfifo); + len--; + HWFIFO_ADDR_NEXT_N(hwfifo, const, 1); + } + #else // Read odd bytes i.e 1 byte for 16 bit or 1-3 bytes for 32 bit if (len > 0) { uint32_t tmp; @@ -188,6 +234,7 @@ void tu_hwfifo_read(const volatile void *hwfifo, uint8_t *dest, uint16_t len, co memcpy(dest, &tmp, len); HWFIFO_ADDR_NEXT(hwfifo, const); } + #endif } #endif diff --git a/src/portable/mentor/musb/dcd_musb.c b/src/portable/mentor/musb/dcd_musb.c index ad20d64bd..3827be318 100644 --- a/src/portable/mentor/musb/dcd_musb.c +++ b/src/portable/mentor/musb/dcd_musb.c @@ -170,68 +170,6 @@ TU_ATTR_ALWAYS_INLINE static inline void hwfifo_flush(musb_regs_t* musb, unsigne } } -static void pipe_write_packet(void *buf, volatile void *fifo, unsigned len) -{ - volatile hw_fifo_t *reg = (volatile hw_fifo_t*)fifo; - uintptr_t addr = (uintptr_t)buf; - while (len >= 4) { - reg->u32 = *(uint32_t const *)addr; - addr += 4; - len -= 4; - } - if (len >= 2) { - reg->u16 = *(uint16_t const *)addr; - addr += 2; - len -= 2; - } - if (len) { - reg->u8 = *(uint8_t const *)addr; - } -} - -static void pipe_read_packet(void *buf, volatile void *fifo, unsigned len) -{ - volatile hw_fifo_t *reg = (volatile hw_fifo_t*)fifo; - uintptr_t addr = (uintptr_t)buf; - while (len >= 4) { - *(uint32_t *)addr = reg->u32; - addr += 4; - len -= 4; - } - if (len >= 2) { - *(uint16_t *)addr = reg->u16; - addr += 2; - len -= 2; - } - if (len) { - *(uint8_t *)addr = reg->u8; - } -} - -static void pipe_read_write_packet_ff(tu_fifo_t *f, volatile void *fifo, unsigned len, unsigned dir) -{ - static const struct { - void (*tu_fifo_get_info)(tu_fifo_t *f, tu_fifo_buffer_info_t *info); - void (*tu_fifo_advance)(tu_fifo_t *f, uint16_t n); - void (*pipe_read_write)(void *buf, volatile void *fifo, unsigned len); - } ops[] = { - /* OUT */ {tu_fifo_get_write_info,tu_fifo_advance_write_pointer,pipe_read_packet}, - /* IN */ {tu_fifo_get_read_info, tu_fifo_advance_read_pointer, pipe_write_packet}, - }; - tu_fifo_buffer_info_t info; - ops[dir].tu_fifo_get_info(f, &info); - unsigned total_len = len; - len = TU_MIN(total_len, info.linear.len); - ops[dir].pipe_read_write(info.linear.ptr, fifo, len); - unsigned rem = total_len - len; - if (rem) { - len = TU_MIN(rem, info.wrapped.len); - ops[dir].pipe_read_write(info.wrapped.ptr, fifo, len); - rem -= len; - } - ops[dir].tu_fifo_advance(f, total_len - rem); -} - static void process_setup_packet(uint8_t rhport) { musb_regs_t* musb_regs = MUSB_REGS(rhport); @@ -277,9 +215,9 @@ static bool handle_xfer_in(uint8_t rhport, uint_fast8_t ep_addr) // TU_LOG1(" %p mps %d len %d rem %d\r\n", buf, mps, len, rem); if (len) { if (_dcd.pipe_buf_is_fifo[TUSB_DIR_IN] & TU_BIT(epnum_minus1)) { - pipe_read_write_packet_ff(buf, fifo_ptr, len, TUSB_DIR_IN); + tu_hwfifo_write_from_fifo(fifo_ptr, (tu_fifo_t *)buf, len, NULL); } else { - pipe_write_packet(buf, fifo_ptr, len); + tu_hwfifo_write(fifo_ptr, buf, len, NULL); pipe->buf = buf + len; } pipe->remaining = rem - len; @@ -308,9 +246,9 @@ static bool handle_xfer_out(uint8_t rhport, uint_fast8_t ep_addr) volatile void *fifo_ptr = &musb_regs->fifo[epnum]; if (len) { if (_dcd.pipe_buf_is_fifo[TUSB_DIR_OUT] & TU_BIT(epnum_minus1)) { - pipe_read_write_packet_ff(buf, fifo_ptr, len, TUSB_DIR_OUT); + tu_hwfifo_read_to_fifo(fifo_ptr, (tu_fifo_t *)buf, len, NULL); } else { - pipe_read_packet(buf, fifo_ptr, len); + tu_hwfifo_read(fifo_ptr, buf, len, NULL); pipe->buf = buf + len; } pipe->remaining = rem - len; @@ -378,7 +316,7 @@ static bool edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_ const unsigned len = TU_MIN(TU_MIN(rem, 64), total_bytes); volatile void *fifo_ptr = &musb_regs->fifo[0]; if (dir_in) { - pipe_write_packet(buffer, fifo_ptr, len); + tu_hwfifo_write(fifo_ptr, buffer, len, NULL); _dcd.pipe0.buf = buffer + len; _dcd.pipe0.length = len; @@ -458,7 +396,7 @@ static void process_ep0(uint8_t rhport) const unsigned rem = _dcd.pipe0.remaining; const unsigned len = TU_MIN(TU_MIN(rem, 64), vld); volatile void *fifo_ptr = &musb_regs->fifo[0]; - pipe_read_packet(_dcd.pipe0.buf, fifo_ptr, len); + tu_hwfifo_read(fifo_ptr, _dcd.pipe0.buf, len, NULL); _dcd.pipe0.remaining = rem - len; _dcd.remaining_ctrl -= len; diff --git a/src/tusb_option.h b/src/tusb_option.h index 453dddb7c..87aba6a6c 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -365,13 +365,18 @@ //------------ MUSB --------------// #if defined(TUP_USBIP_MUSB) - #define CFG_TUD_EDPT_DEDICATED_HWFIFO 0 // need testing to enable + #define CFG_TUD_EDPT_DEDICATED_HWFIFO 1 + #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE 4 // 32 bit data + #define CFG_TUSB_FIFO_HWFIFO_DATA_ODD_16BIT_ACCESS // allow odd 16bit access + #define CFG_TUSB_FIFO_HWFIFO_DATA_ODD_8BIT_ACCESS // allow odd 8bit access + #define CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE 0 // fixed hwfifo + #endif //------------ RUSB2 --------------// #if defined(TUP_USBIP_RUSB2) #define CFG_TUD_EDPT_DEDICATED_HWFIFO 1 - #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE (2 + (TUD_OPT_HIGH_SPEED ? 4 : 0)) // 16 bit and 32 bit data if highspeed + #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE (2 | (TUD_OPT_HIGH_SPEED ? 4 : 0)) // 16 bit and 32 bit data if highspeed #define CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE 0 #define CFG_TUSB_FIFO_HWFIFO_CUSTOM_WRITE // custom write since rusb2 can change access width 32 -> 16 and can write // odd byte with byte access -- cgit v1.3.1 From 1c19fc540868d699bd7eedba741108dfabb36c00 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 6 Jan 2026 00:56:33 +0700 Subject: rename FSDEV_PMA_SIZE CFG_TUSB_FSDEV_PMA_SIZE --- src/common/tusb_mcu.h | 36 ++-- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 286 +++++++++++++------------- src/portable/st/stm32_fsdev/fsdev_common.h | 108 +++++----- src/portable/st/stm32_fsdev/fsdev_stm32.h | 2 +- src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c | 2 +- src/portable/synopsys/dwc2/hcd_dwc2.c | 6 +- src/tusb_option.h | 6 +- 7 files changed, 217 insertions(+), 229 deletions(-) (limited to 'src/portable') diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index 8dd4078c4..d546703bc 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -179,12 +179,12 @@ #elif TU_CHECK_MCU(OPT_MCU_STM32C0) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define FSDEV_PMA_SIZE 2048u + #define CFG_TUSB_FSDEV_PMA_SIZE 2048u #elif TU_CHECK_MCU(OPT_MCU_STM32F0) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define FSDEV_PMA_SIZE 1024u + #define CFG_TUSB_FSDEV_PMA_SIZE 1024u #elif TU_CHECK_MCU(OPT_MCU_STM32F1) // - F102, F103 use fsdev @@ -200,7 +200,7 @@ defined(STM32F103xE) || defined(STM32F103xG) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define FSDEV_PMA_SIZE 512u + #define CFG_TUSB_FSDEV_PMA_SIZE 512u #else #error "Unsupported STM32F1 mcu" #endif @@ -218,10 +218,10 @@ #if defined(STM32F302xB) || defined(STM32F302xC) || defined(STM32F303xB) || defined(STM32F303xC) || \ defined(STM32F373xC) - #define FSDEV_PMA_SIZE 512u + #define CFG_TUSB_FSDEV_PMA_SIZE 512u #elif defined(STM32F302x6) || defined(STM32F302x8) || defined(STM32F302xD) || defined(STM32F302xE) || \ defined(STM32F303xD) || defined(STM32F303xE) - #define FSDEV_PMA_SIZE 1024u + #define CFG_TUSB_FSDEV_PMA_SIZE 1024u #else #error "Unsupported STM32F3 mcu" #endif @@ -253,13 +253,13 @@ #elif TU_CHECK_MCU(OPT_MCU_STM32G0) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define FSDEV_PMA_SIZE 2048u + #define CFG_TUSB_FSDEV_PMA_SIZE 2048u #elif TU_CHECK_MCU(OPT_MCU_STM32G4) // Device controller #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define FSDEV_PMA_SIZE 1024u + #define CFG_TUSB_FSDEV_PMA_SIZE 1024u // TypeC controller #define TUP_USBIP_TYPEC_STM32 @@ -268,7 +268,7 @@ #elif TU_CHECK_MCU(OPT_MCU_STM32H5) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define FSDEV_PMA_SIZE 2048u + #define CFG_TUSB_FSDEV_PMA_SIZE 2048u #elif TU_CHECK_MCU(OPT_MCU_STM32H7) #include "stm32h7xx.h" @@ -302,12 +302,12 @@ #elif TU_CHECK_MCU(OPT_MCU_STM32L0) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define FSDEV_PMA_SIZE 1024u + #define CFG_TUSB_FSDEV_PMA_SIZE 1024u #elif TU_CHECK_MCU(OPT_MCU_STM32L1) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define FSDEV_PMA_SIZE 512u + #define CFG_TUSB_FSDEV_PMA_SIZE 512u #elif TU_CHECK_MCU(OPT_MCU_STM32L4) // - L4x2, L4x3 use fsdev @@ -324,7 +324,7 @@ defined(STM32L442xx) || defined(STM32L443xx) || defined(STM32L452xx) || defined(STM32L462xx) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define FSDEV_PMA_SIZE 1024u + #define CFG_TUSB_FSDEV_PMA_SIZE 1024u #else #error "Unsupported STM32L4 mcu" #endif @@ -332,24 +332,24 @@ #elif TU_CHECK_MCU(OPT_MCU_STM32L5) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define FSDEV_PMA_SIZE (1024u) + #define CFG_TUSB_FSDEV_PMA_SIZE (1024u) #elif TU_CHECK_MCU(OPT_MCU_STM32U0) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define FSDEV_PMA_SIZE 1024u + #define CFG_TUSB_FSDEV_PMA_SIZE 1024u #elif TU_CHECK_MCU(OPT_MCU_STM32U3) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define FSDEV_PMA_SIZE 2048u + #define CFG_TUSB_FSDEV_PMA_SIZE 2048u #elif TU_CHECK_MCU(OPT_MCU_STM32U5) // U535/545 use fsdev #if defined(STM32U535xx) || defined(STM32U545xx) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define FSDEV_PMA_SIZE 2048u + #define CFG_TUSB_FSDEV_PMA_SIZE 2048u #else #define TUP_USBIP_DWC2 #define TUP_USBIP_DWC2_STM32 @@ -367,7 +367,7 @@ #elif TU_CHECK_MCU(OPT_MCU_STM32WB) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define FSDEV_PMA_SIZE 1024u + #define CFG_TUSB_FSDEV_PMA_SIZE 1024u #elif TU_CHECK_MCU(OPT_MCU_STM32WBA) #define TUP_USBIP_DWC2 @@ -572,7 +572,7 @@ #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_CH32 - #define FSDEV_PMA_SIZE 512u + #define CFG_TUSB_FSDEV_PMA_SIZE 512u // default to FSDEV for device #if !defined(CFG_TUD_WCH_USBIP_USBFS) @@ -621,7 +621,7 @@ #elif TU_CHECK_MCU(OPT_MCU_AT32F403A_407, OPT_MCU_AT32F413) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_AT32 - #define FSDEV_PMA_SIZE 512u + #define CFG_TUSB_FSDEV_PMA_SIZE 512u #elif TU_CHECK_MCU(OPT_MCU_AT32F415) #define TUP_USBIP_DWC2 diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 72527a9ec..22a9e4af8 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -108,11 +108,10 @@ #include "tusb_option.h" -#if CFG_TUD_ENABLED && defined(TUP_USBIP_FSDEV) && \ - !(defined(TUP_USBIP_FSDEV_CH32) && CFG_TUD_WCH_USBIP_FSDEV == 0) +#if CFG_TUD_ENABLED && defined(TUP_USBIP_FSDEV) && !(defined(TUP_USBIP_FSDEV_CH32) && CFG_TUD_WCH_USBIP_FSDEV == 0) -#include "device/dcd.h" -#include "fsdev_common.h" + #include "device/dcd.h" + #include "fsdev_common.h" //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF @@ -120,25 +119,25 @@ // One of these for every EP IN & OUT, uses a bit of RAM.... typedef struct { - uint8_t *buffer; + uint8_t *buffer; tu_fifo_t *ff; - uint16_t total_len; - uint16_t queued_len; - uint16_t max_packet_size; - uint8_t ep_idx; // index for USB_EPnR register - bool iso_in_sending; // Workaround for ISO IN EP doesn't have interrupt mask + uint16_t total_len; + uint16_t queued_len; + uint16_t max_packet_size; + uint8_t ep_idx; // index for USB_EPnR register + bool iso_in_sending; // Workaround for ISO IN EP doesn't have interrupt mask } xfer_ctl_t; // EP allocator typedef struct { uint8_t ep_num; uint8_t ep_type; - bool allocated[2]; + bool allocated[2]; } ep_alloc_t; static xfer_ctl_t xfer_status[CFG_TUD_ENDPPOINT_MAX][2]; static ep_alloc_t ep_alloc_status[FSDEV_EP_COUNT]; -static uint8_t remoteWakeCountdown; // When wake is requested +static uint8_t remoteWakeCountdown; // When wake is requested //--------------------------------------------------------------------+ // Prototypes @@ -152,12 +151,12 @@ static bool edpt_xfer(uint8_t rhport, uint8_t ep_num, tusb_dir_t dir); // PMA allocation/access static uint16_t ep_buf_ptr; ///< Points to first free memory location static uint32_t dcd_pma_alloc(uint16_t len, bool dbuf); -static uint8_t dcd_ep_alloc(uint8_t ep_addr, uint8_t ep_type); +static uint8_t dcd_ep_alloc(uint8_t ep_addr, uint8_t ep_type); static void edpt0_open(uint8_t rhport); TU_ATTR_ALWAYS_INLINE static inline void edpt0_prepare_setup(void) { - btable_set_rx_bufsize(0, BTABLE_BUF_RX, 8); + btable_set_rx_bufsize(0, BTABLE_BUF_RX, 8); } //--------------------------------------------------------------------+ @@ -171,21 +170,21 @@ TU_ATTR_ALWAYS_INLINE static inline xfer_ctl_t *xfer_ctl_ptr(uint8_t epnum, uint //--------------------------------------------------------------------+ // Controller API //--------------------------------------------------------------------+ -bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { - (void) rh_init; +bool dcd_init(uint8_t rhport, const tusb_rhport_init_t *rh_init) { + (void)rh_init; fsdev_core_reset(); FSDEV_REG->CNTR = 0; // Enable USB -#if !defined(FSDEV_BUS_32BIT) + #if !defined(FSDEV_BUS_32BIT) // BTABLE register does not exist any more on 32-bit bus devices FSDEV_REG->BTABLE = FSDEV_BTABLE_BASE; -#endif + #endif // Enable interrupts for device mode - FSDEV_REG->CNTR |= USB_CNTR_RESETM | USB_CNTR_ESOFM | USB_CNTR_CTRM | - USB_CNTR_SUSPM | USB_CNTR_WKUPM | USB_CNTR_PMAOVRM; + FSDEV_REG->CNTR |= + USB_CNTR_RESETM | USB_CNTR_ESOFM | USB_CNTR_CTRM | USB_CNTR_SUSPM | USB_CNTR_WKUPM | USB_CNTR_PMAOVRM; handle_bus_reset(rhport); @@ -236,8 +235,8 @@ static void handle_bus_reset(uint8_t rhport) { for (uint32_t i = 0; i < FSDEV_EP_COUNT; i++) { // Clear EP allocation status - ep_alloc_status[i].ep_num = 0xFF; - ep_alloc_status[i].ep_type = 0xFF; + ep_alloc_status[i].ep_num = 0xFF; + ep_alloc_status[i].ep_type = 0xFF; ep_alloc_status[i].allocated[0] = false; ep_alloc_status[i].allocated[1] = false; } @@ -245,7 +244,7 @@ static void handle_bus_reset(uint8_t rhport) { // Reset PMA allocation ep_buf_ptr = FSDEV_BTABLE_BASE + 8 * FSDEV_EP_COUNT; - edpt0_open(rhport); // open control endpoint (both IN & OUT) + edpt0_open(rhport); // open control endpoint (both IN & OUT) FSDEV_REG->DADDR = USB_DADDR_EF; // Enable USB Function } @@ -254,8 +253,8 @@ static void handle_bus_reset(uint8_t rhport) { static void handle_ctr_tx(uint32_t ep_id) { uint32_t ep_reg = ep_read(ep_id) | USB_EP_CTR_TX | USB_EP_CTR_RX; - uint8_t const ep_num = ep_reg & USB_EPADDR_FIELD; - xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, TUSB_DIR_IN); + const uint8_t ep_num = ep_reg & USB_EPADDR_FIELD; + xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, TUSB_DIR_IN); if (ep_is_iso(ep_reg)) { // Ignore spurious interrupts that we don't schedule @@ -265,11 +264,11 @@ static void handle_ctr_tx(uint32_t ep_id) { return; } xfer->iso_in_sending = false; -#if FSDEV_USE_SBUF_ISO == 0 + #if FSDEV_USE_SBUF_ISO == 0 uint8_t buf_id = (ep_reg & USB_EP_DTOG_TX) ? 0 : 1; -#else + #else uint8_t buf_id = BTABLE_BUF_TX; -#endif + #endif btable_set_count(ep_id, buf_id, 0); } @@ -282,8 +281,8 @@ static void handle_ctr_tx(uint32_t ep_id) { static void handle_ctr_setup(uint32_t ep_id) { uint16_t rx_count = btable_get_count(ep_id, BTABLE_BUF_RX); - uint16_t rx_addr = btable_get_addr(ep_id, BTABLE_BUF_RX); - uint8_t setup_packet[8] TU_ATTR_ALIGNED(4); + uint16_t rx_addr = btable_get_addr(ep_id, BTABLE_BUF_RX); + uint8_t setup_packet[8] TU_ATTR_ALIGNED(4); tu_hwfifo_read(PMA_BUF_AT(rx_addr), setup_packet, rx_count, NULL); @@ -292,7 +291,7 @@ static void handle_ctr_setup(uint32_t ep_id) { // Setup packet should always be 8 bytes. If not, we probably missed the packet if (rx_count == 8) { - dcd_event_setup_received(0, (uint8_t*) setup_packet, true); + dcd_event_setup_received(0, (uint8_t *)setup_packet, true); // Hardware should reset EP0 RX/TX to NAK and both toggle to 1 } else { // Missed setup packet !!! @@ -303,24 +302,24 @@ static void handle_ctr_setup(uint32_t ep_id) { // Handle CTR interrupt for the RX/OUT direction static void handle_ctr_rx(uint32_t ep_id) { - uint32_t ep_reg = ep_read(ep_id) | USB_EP_CTR_TX | USB_EP_CTR_RX; - uint8_t const ep_num = ep_reg & USB_EPADDR_FIELD; - bool const is_iso = ep_is_iso(ep_reg); - xfer_ctl_t* xfer = xfer_ctl_ptr(ep_num, TUSB_DIR_OUT); + uint32_t ep_reg = ep_read(ep_id) | USB_EP_CTR_TX | USB_EP_CTR_RX; + const uint8_t ep_num = ep_reg & USB_EPADDR_FIELD; + const bool is_iso = ep_is_iso(ep_reg); + xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, TUSB_DIR_OUT); uint8_t buf_id; -#if FSDEV_USE_SBUF_ISO == 0 + #if FSDEV_USE_SBUF_ISO == 0 bool const dbl_buf = is_iso; -#else + #else bool const dbl_buf = false; -#endif + #endif if (dbl_buf) { buf_id = (ep_reg & USB_EP_DTOG_RX) ? 0 : 1; } else { buf_id = BTABLE_BUF_RX; } - const uint16_t rx_count = btable_get_count(ep_id, buf_id); - uint16_t pma_addr = (uint16_t) btable_get_addr(ep_id, buf_id); + const uint16_t rx_count = btable_get_count(ep_id, buf_id); + uint16_t pma_addr = (uint16_t)btable_get_addr(ep_id, buf_id); fsdev_pma_buf_t *pma_buf = PMA_BUF_AT(pma_addr); if (xfer->ff) { @@ -344,7 +343,7 @@ static void handle_ctr_rx(uint32_t ep_id) { } else { // Set endpoint active again for receiving more data. Note that isochronous endpoints stay active always if (!is_iso) { - uint16_t const cnt = tu_min16(xfer->total_len - xfer->queued_len, xfer->max_packet_size); + const uint16_t cnt = tu_min16(xfer->total_len - xfer->queued_len, xfer->max_packet_size); btable_set_rx_bufsize(ep_id, BTABLE_BUF_RX, cnt); } ep_reg &= USB_EPREG_MASK | EP_STAT_MASK(TUSB_DIR_OUT); // will change RX Status, reserved other toggle bits @@ -404,18 +403,18 @@ void dcd_int_handler(uint8_t rhport) { // loop to handle all pending CTR interrupts while (FSDEV_REG->ISTR & USB_ISTR_CTR) { // skip DIR bit, and use CTR TX/RX instead, since there is chance we have both TX/RX completed in one interrupt - uint32_t const ep_id = FSDEV_REG->ISTR & USB_ISTR_EP_ID; - uint32_t const ep_reg = ep_read(ep_id); + const uint32_t ep_id = FSDEV_REG->ISTR & USB_ISTR_EP_ID; + const uint32_t ep_reg = ep_read(ep_id); if (ep_reg & USB_EP_CTR_RX) { - #ifdef FSDEV_BUS_32BIT + #ifdef FSDEV_BUS_32BIT /* https://www.st.com/resource/en/errata_sheet/es0561-stm32h503cbebkbrb-device-errata-stmicroelectronics.pdf * https://www.st.com/resource/en/errata_sheet/es0587-stm32u535xx-and-stm32u545xx-device-errata-stmicroelectronics.pdf * From H503/U535 errata: Buffer description table update completes after CTR interrupt triggers * Description: - * - During OUT transfers, the correct transfer interrupt (CTR) is triggered a little before the last USB SRAM accesses - * have completed. If the software responds quickly to the interrupt, the full buffer contents may not be correct. - * Workaround: + * - During OUT transfers, the correct transfer interrupt (CTR) is triggered a little before the last USB SRAM + * accesses have completed. If the software responds quickly to the interrupt, the full buffer contents may not be + * correct. Workaround: * - Software should ensure that a small delay is included before accessing the SRAM contents. This delay * should be 800 ns in Full Speed mode and 6.4 μs in Low Speed mode * - Since H5 can run up to 250Mhz -> 1 cycle = 4ns. Per errata, we need to wait 200 cycles. Though executing code @@ -426,9 +425,9 @@ void dcd_int_handler(uint8_t rhport) { */ volatile uint32_t cycle_count = 20; // defined as PCD_RX_PMA_CNT in stm32 hal_driver while (cycle_count > 0U) { - cycle_count--; // each count take 3 cycles (1 for sub, jump, and compare) + cycle_count--; // each count take 3 cycles (1 for sub, jump, and compare) } - #endif + #endif if (ep_reg & USB_EP_SETUP) { handle_ctr_setup(ep_id); // CTR will be clear after copied setup packet @@ -456,14 +455,13 @@ void dcd_int_handler(uint8_t rhport) { // Invoked when a control transfer's status stage is complete. // May help DCD to prepare for next control transfer, this API is optional. -void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const *request) { +void dcd_edpt0_status_complete(uint8_t rhport, const tusb_control_request_t *request) { (void)rhport; if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE && - request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && - request->bRequest == TUSB_REQ_SET_ADDRESS) { - uint8_t const dev_addr = (uint8_t)request->wValue; - FSDEV_REG->DADDR = (USB_DADDR_EF | dev_addr); + request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && request->bRequest == TUSB_REQ_SET_ADDRESS) { + const uint8_t dev_addr = (uint8_t)request->wValue; + FSDEV_REG->DADDR = (USB_DADDR_EF | dev_addr); } edpt0_prepare_setup(); @@ -474,15 +472,14 @@ void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const *req * In case of double buffering, high 16bit is the address of 2nd buffer * During failure, TU_ASSERT is used. If this happens, rework/reallocate memory manually. */ -static uint32_t dcd_pma_alloc(uint16_t len, bool dbuf) -{ - uint8_t blsize, num_block; +static uint32_t dcd_pma_alloc(uint16_t len, bool dbuf) { + uint8_t blsize, num_block; uint16_t aligned_len = pma_align_buffer_size(len, &blsize, &num_block); - (void) blsize; - (void) num_block; + (void)blsize; + (void)num_block; uint32_t addr = ep_buf_ptr; - ep_buf_ptr = (uint16_t)(ep_buf_ptr + aligned_len); // increment buffer pointer + ep_buf_ptr = (uint16_t)(ep_buf_ptr + aligned_len); // increment buffer pointer if (dbuf) { addr |= ((uint32_t)ep_buf_ptr) << 16; @@ -490,7 +487,7 @@ static uint32_t dcd_pma_alloc(uint16_t len, bool dbuf) } // Verify packet buffer is not overflowed - TU_ASSERT(ep_buf_ptr <= FSDEV_PMA_SIZE, 0xFFFF); + TU_ASSERT(ep_buf_ptr <= CFG_TUSB_FSDEV_PMA_SIZE, 0xFFFF); return addr; } @@ -498,35 +495,32 @@ static uint32_t dcd_pma_alloc(uint16_t len, bool dbuf) /*** * Allocate hardware endpoint */ -static uint8_t dcd_ep_alloc(uint8_t ep_addr, uint8_t ep_type) -{ - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); +static uint8_t dcd_ep_alloc(uint8_t ep_addr, uint8_t ep_type) { + const uint8_t epnum = tu_edpt_number(ep_addr); + const uint8_t dir = tu_edpt_dir(ep_addr); for (uint8_t i = 0; i < FSDEV_EP_COUNT; i++) { // Check if already allocated - if (ep_alloc_status[i].allocated[dir] && - ep_alloc_status[i].ep_type == ep_type && + if (ep_alloc_status[i].allocated[dir] && ep_alloc_status[i].ep_type == ep_type && ep_alloc_status[i].ep_num == epnum) { return i; } -#if FSDEV_USE_SBUF_ISO == 0 + #if FSDEV_USE_SBUF_ISO == 0 bool const dbl_buf = ep_type == TUSB_XFER_ISOCHRONOUS; -#else + #else bool const dbl_buf = false; -#endif + #endif // If EP of current direction is not allocated // For double-buffered mode both directions needs to be free - if (!ep_alloc_status[i].allocated[dir] && - (!dbl_buf || !ep_alloc_status[i].allocated[dir ^ 1])) { + if (!ep_alloc_status[i].allocated[dir] && (!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 if (ep_alloc_status[i].ep_type == 0xFF || ep_alloc_status[i].ep_type == ep_type) { - ep_alloc_status[i].ep_num = epnum; - ep_alloc_status[i].ep_type = ep_type; + ep_alloc_status[i].ep_num = epnum; + ep_alloc_status[i].ep_type = ep_type; ep_alloc_status[i].allocated[dir] = true; return i; @@ -540,16 +534,16 @@ static uint8_t dcd_ep_alloc(uint8_t ep_addr, uint8_t ep_type) } void edpt0_open(uint8_t rhport) { - (void) rhport; + (void)rhport; dcd_ep_alloc(0x0, TUSB_XFER_CONTROL); dcd_ep_alloc(0x80, TUSB_XFER_CONTROL); xfer_status[0][0].max_packet_size = CFG_TUD_ENDPOINT0_SIZE; - xfer_status[0][0].ep_idx = 0; + xfer_status[0][0].ep_idx = 0; xfer_status[0][1].max_packet_size = CFG_TUD_ENDPOINT0_SIZE; - xfer_status[0][1].ep_idx = 0; + xfer_status[0][1].ep_idx = 0; uint16_t pma_addr0 = dcd_pma_alloc(CFG_TUD_ENDPOINT0_SIZE, false); uint16_t pma_addr1 = dcd_pma_alloc(CFG_TUD_ENDPOINT0_SIZE, false); @@ -567,13 +561,13 @@ void edpt0_open(uint8_t rhport) { ep_write(0, ep_reg, false); } -bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) { +bool dcd_edpt_open(uint8_t rhport, const tusb_desc_endpoint_t *desc_ep) { (void)rhport; - uint8_t const ep_addr = desc_ep->bEndpointAddress; - uint8_t const ep_num = tu_edpt_number(ep_addr); - tusb_dir_t const dir = tu_edpt_dir(ep_addr); - const uint16_t packet_size = tu_edpt_packet_size(desc_ep); - uint8_t const ep_idx = dcd_ep_alloc(ep_addr, desc_ep->bmAttributes.xfer); + const uint8_t ep_addr = desc_ep->bEndpointAddress; + const uint8_t ep_num = tu_edpt_number(ep_addr); + const tusb_dir_t dir = tu_edpt_dir(ep_addr); + const uint16_t packet_size = tu_edpt_packet_size(desc_ep); + const uint8_t ep_idx = dcd_ep_alloc(ep_addr, desc_ep->bmAttributes.xfer); TU_ASSERT(ep_idx < FSDEV_EP_COUNT); uint32_t ep_reg = ep_read(ep_idx) & ~USB_EPREG_MASK; @@ -597,9 +591,9 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) { uint16_t pma_addr = dcd_pma_alloc(packet_size, false); btable_set_addr(ep_idx, dir == TUSB_DIR_IN ? BTABLE_BUF_TX : BTABLE_BUF_RX, pma_addr); - xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, dir); + xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, dir); xfer->max_packet_size = packet_size; - xfer->ep_idx = ep_idx; + xfer->ep_idx = ep_idx; ep_change_status(&ep_reg, dir, EP_STAT_NAK); ep_change_dtog(&ep_reg, dir, 0); @@ -623,8 +617,8 @@ void dcd_edpt_close_all(uint8_t rhport) { // Reset endpoint ep_write(i, 0, false); // Clear EP allocation status - ep_alloc_status[i].ep_num = 0xFF; - ep_alloc_status[i].ep_type = 0xFF; + ep_alloc_status[i].ep_num = 0xFF; + ep_alloc_status[i].ep_type = 0xFF; ep_alloc_status[i].allocated[0] = false; ep_alloc_status[i].allocated[1] = false; } @@ -638,46 +632,46 @@ void dcd_edpt_close_all(uint8_t rhport) { bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { (void)rhport; - uint8_t const ep_num = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - uint8_t const ep_idx = dcd_ep_alloc(ep_addr, TUSB_XFER_ISOCHRONOUS); + const uint8_t ep_num = tu_edpt_number(ep_addr); + const uint8_t dir = tu_edpt_dir(ep_addr); + const uint8_t ep_idx = dcd_ep_alloc(ep_addr, TUSB_XFER_ISOCHRONOUS); -#if CFG_TUD_FSDEV_DOUBLE_BUFFERED_ISO_EP != 0 - uint32_t pma_addr = dcd_pma_alloc(largest_packet_size, true); + #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 - uint32_t pma_addr = dcd_pma_alloc(largest_packet_size, false); + #else + uint32_t pma_addr = dcd_pma_alloc(largest_packet_size, false); uint16_t pma_addr2 = pma_addr; -#endif + #endif -#if FSDEV_USE_SBUF_ISO == 0 + #if FSDEV_USE_SBUF_ISO == 0 btable_set_addr(ep_idx, 0, pma_addr); btable_set_addr(ep_idx, 1, pma_addr2); -#else + #else btable_set_addr(ep_idx, dir == TUSB_DIR_IN ? BTABLE_BUF_TX : BTABLE_BUF_RX, pma_addr); - (void) pma_addr2; -#endif + (void)pma_addr2; + #endif - xfer_ctl_t* xfer = xfer_ctl_ptr(ep_num, dir); - xfer->ep_idx = ep_idx; + xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, dir); + xfer->ep_idx = ep_idx; return true; } -bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) { +bool dcd_edpt_iso_activate(uint8_t rhport, const tusb_desc_endpoint_t *desc_ep) { (void)rhport; - uint8_t const ep_addr = desc_ep->bEndpointAddress; - uint8_t const ep_num = tu_edpt_number(ep_addr); - tusb_dir_t const dir = tu_edpt_dir(ep_addr); - xfer_ctl_t* xfer = xfer_ctl_ptr(ep_num, dir); + const uint8_t ep_addr = desc_ep->bEndpointAddress; + const uint8_t ep_num = tu_edpt_number(ep_addr); + const tusb_dir_t dir = tu_edpt_dir(ep_addr); + xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, dir); - uint8_t const ep_idx = xfer->ep_idx; + const uint8_t ep_idx = xfer->ep_idx; xfer->max_packet_size = tu_edpt_packet_size(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 + #if FSDEV_USE_SBUF_ISO != 0 ep_reg |= USB_EP_KIND; ep_change_status(&ep_reg, dir, EP_STAT_DISABLED); @@ -688,12 +682,12 @@ bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) } else { ep_reg &= ~(USB_EPTX_STAT | USB_EP_DTOG_TX); } -#else + #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 + #endif ep_write(ep_idx, ep_reg, true); @@ -702,17 +696,17 @@ bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) // Currently, single-buffered, and only 64 bytes at a time (max) static void dcd_transmit_packet(xfer_ctl_t *xfer, uint16_t ep_ix) { - uint16_t len = tu_min16(xfer->total_len - xfer->queued_len, xfer->max_packet_size); + uint16_t len = tu_min16(xfer->total_len - xfer->queued_len, xfer->max_packet_size); uint32_t ep_reg = ep_read(ep_ix) | USB_EP_CTR_TX | USB_EP_CTR_RX; // reserve CTR - bool const is_iso = ep_is_iso(ep_reg); + const bool is_iso = ep_is_iso(ep_reg); uint8_t buf_id; -#if FSDEV_USE_SBUF_ISO == 0 + #if FSDEV_USE_SBUF_ISO == 0 bool const dbl_buf = is_iso; -#else + #else bool const dbl_buf = false; -#endif + #endif if (dbl_buf) { buf_id = (ep_reg & USB_EP_DTOG_TX) ? 1 : 0; } else { @@ -739,9 +733,9 @@ static void dcd_transmit_packet(xfer_ctl_t *xfer, uint16_t ep_ix) { } static bool edpt_xfer(uint8_t rhport, uint8_t ep_num, tusb_dir_t dir) { - (void) rhport; + (void)rhport; - xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, dir); + xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, dir); const uint8_t ep_idx = xfer->ep_idx; if (dir == TUSB_DIR_IN) { @@ -752,11 +746,11 @@ static bool edpt_xfer(uint8_t rhport, uint8_t ep_num, tusb_dir_t dir) { uint16_t cnt = tu_min16(xfer->total_len, xfer->max_packet_size); -#if FSDEV_USE_SBUF_ISO == 0 + #if FSDEV_USE_SBUF_ISO == 0 bool const dbl_buf = ep_is_iso(ep_reg); -#else + #else bool const dbl_buf = false; -#endif + #endif if (dbl_buf) { btable_set_rx_bufsize(ep_idx, 0, cnt); btable_set_rx_bufsize(ep_idx, 1, cnt); @@ -771,29 +765,29 @@ static bool edpt_xfer(uint8_t rhport, uint8_t ep_num, tusb_dir_t dir) { return true; } -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) { - (void) is_isr; - uint8_t const ep_num = tu_edpt_number(ep_addr); - tusb_dir_t const dir = tu_edpt_dir(ep_addr); - xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, dir); +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes, bool is_isr) { + (void)is_isr; + const uint8_t ep_num = tu_edpt_number(ep_addr); + const tusb_dir_t dir = tu_edpt_dir(ep_addr); + xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, dir); - xfer->buffer = buffer; - xfer->ff = NULL; - xfer->total_len = total_bytes; + xfer->buffer = buffer; + xfer->ff = NULL; + xfer->total_len = total_bytes; xfer->queued_len = 0; return edpt_xfer(rhport, ep_num, dir); } -bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes, bool is_isr) { - (void) is_isr; - uint8_t const ep_num = tu_edpt_number(ep_addr); - tusb_dir_t const dir = tu_edpt_dir(ep_addr); - xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, dir); +bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t *ff, uint16_t total_bytes, bool is_isr) { + (void)is_isr; + const uint8_t ep_num = tu_edpt_number(ep_addr); + const tusb_dir_t dir = tu_edpt_dir(ep_addr); + xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, dir); - xfer->buffer = NULL; - xfer->ff = ff; - xfer->total_len = total_bytes; + xfer->buffer = NULL; + xfer->ff = ff; + xfer->total_len = total_bytes; xfer->queued_len = 0; return edpt_xfer(rhport, ep_num, dir); @@ -801,10 +795,10 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { (void)rhport; - uint8_t const ep_num = tu_edpt_number(ep_addr); - tusb_dir_t const dir = tu_edpt_dir(ep_addr); - xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, dir); - uint8_t const ep_idx = xfer->ep_idx; + const uint8_t ep_num = tu_edpt_number(ep_addr); + const tusb_dir_t dir = tu_edpt_dir(ep_addr); + xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, dir); + const uint8_t ep_idx = xfer->ep_idx; uint32_t ep_reg = ep_read(ep_idx) | USB_EP_CTR_TX | USB_EP_CTR_RX; // reserve CTR bits ep_reg &= USB_EPREG_MASK | EP_STAT_MASK(dir); @@ -816,10 +810,10 @@ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { (void)rhport; - uint8_t const ep_num = tu_edpt_number(ep_addr); - tusb_dir_t const dir = tu_edpt_dir(ep_addr); - xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, dir); - uint8_t const ep_idx = xfer->ep_idx; + const uint8_t ep_num = tu_edpt_number(ep_addr); + const tusb_dir_t dir = tu_edpt_dir(ep_addr); + xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, dir); + const uint8_t ep_idx = xfer->ep_idx; uint32_t ep_reg = ep_read(ep_idx) | USB_EP_CTR_TX | USB_EP_CTR_RX; // reserve CTR bits ep_reg &= USB_EPREG_MASK | EP_STAT_MASK(dir) | EP_DTOG_MASK(dir); @@ -839,7 +833,7 @@ void dcd_int_disable(uint8_t rhport) { fsdev_int_disable(rhport); } -#if defined(USB_BCDR_DPPU) || defined(SYSCFG_PMC_USB_PU) + #if defined(USB_BCDR_DPPU) || defined(SYSCFG_PMC_USB_PU) void dcd_connect(uint8_t rhport) { fsdev_connect(rhport); } @@ -847,6 +841,6 @@ void dcd_connect(uint8_t rhport) { void dcd_disconnect(uint8_t rhport) { fsdev_disconnect(rhport); } -#endif + #endif #endif diff --git a/src/portable/st/stm32_fsdev/fsdev_common.h b/src/portable/st/stm32_fsdev/fsdev_common.h index 69440aa32..c53e345b0 100644 --- a/src/portable/st/stm32_fsdev/fsdev_common.h +++ b/src/portable/st/stm32_fsdev/fsdev_common.h @@ -32,11 +32,11 @@ #include "common/tusb_common.h" #if CFG_TUD_ENABLED -#include "device/dcd.h" + #include "device/dcd.h" #endif #if CFG_TUH_ENABLED -#include "host/hcd.h" + #include "host/hcd.h" #endif #if defined(TUP_USBIP_FSDEV_STM32) @@ -56,41 +56,37 @@ extern "C" { // If sharing with CAN, one can set this to be non-zero to give CAN space where it wants it // Both of these MUST be a multiple of 2, and are in byte units. #ifndef FSDEV_BTABLE_BASE -#define FSDEV_BTABLE_BASE 0U + #define FSDEV_BTABLE_BASE 0U #endif TU_VERIFY_STATIC(FSDEV_BTABLE_BASE % 8 == 0, "BTABLE base must be aligned to 8 bytes"); -// FSDEV_PMA_SIZE is PMA buffer size in bytes. +// CFG_TUSB_FSDEV_PMA_SIZE is PMA buffer size in bytes. // - 512-byte devices, access with a stride of two words (use every other 16-bit address) // - 1024-byte devices, access with a stride of one word (use every 16-bit address) // - 2048-byte devices, access with 32-bit address // For purposes of accessing the packet -#if FSDEV_PMA_SIZE == 512 +#if CFG_TUSB_FSDEV_PMA_SIZE == 512 // 1x16 bit / word access scheme #define FSDEV_PMA_STRIDE 2 #define pma_access_scheme TU_ATTR_ALIGNED(4) -#elif FSDEV_PMA_SIZE == 1024 +#elif CFG_TUSB_FSDEV_PMA_SIZE == 1024 // 2x16 bit / word access scheme - #define FSDEV_PMA_STRIDE 1 + #define FSDEV_PMA_STRIDE 1 #define pma_access_scheme -#elif FSDEV_PMA_SIZE == 2048 +#elif CFG_TUSB_FSDEV_PMA_SIZE == 2048 // 32 bit access scheme #define FSDEV_BUS_32BIT - #define FSDEV_PMA_STRIDE 1 + #define FSDEV_PMA_STRIDE 1 #define pma_access_scheme #endif // The fsdev_bus_t type can be used for both register and PMA access necessities #ifdef FSDEV_BUS_32BIT - typedef uint32_t fsdev_bus_t; - #define fsdevbus_unaligned_read(_addr) tu_unaligned_read32(_addr) - #define fsdevbus_unaligned_write(_addr, _value) tu_unaligned_write32(_addr, _value) +typedef uint32_t fsdev_bus_t; #else - typedef uint16_t fsdev_bus_t; - #define fsdevbus_unaligned_read(_addr) tu_unaligned_read16(_addr) - #define fsdevbus_unaligned_write(_addr, _value) tu_unaligned_write16(_addr, _value) +typedef uint16_t fsdev_bus_t; #endif enum { @@ -124,77 +120,77 @@ typedef union { } ep32[FSDEV_EP_COUNT][2]; } fsdev_btable_t; -TU_VERIFY_STATIC(sizeof(fsdev_btable_t) == FSDEV_EP_COUNT*8*FSDEV_PMA_STRIDE, "size is not correct"); -TU_VERIFY_STATIC(FSDEV_BTABLE_BASE + FSDEV_EP_COUNT*8 <= FSDEV_PMA_SIZE, "BTABLE does not fit in PMA RAM"); +TU_VERIFY_STATIC(sizeof(fsdev_btable_t) == FSDEV_EP_COUNT * 8 * FSDEV_PMA_STRIDE, "size is not correct"); +TU_VERIFY_STATIC(FSDEV_BTABLE_BASE + FSDEV_EP_COUNT * 8 <= CFG_TUSB_FSDEV_PMA_SIZE, "BTABLE does not fit in PMA RAM"); -#define FSDEV_BTABLE ((volatile fsdev_btable_t*) (FSDEV_PMA_BASE + FSDEV_PMA_STRIDE*(FSDEV_BTABLE_BASE))) +#define FSDEV_BTABLE ((volatile fsdev_btable_t *)(FSDEV_PMA_BASE + FSDEV_PMA_STRIDE * (FSDEV_BTABLE_BASE))) typedef struct { volatile pma_access_scheme fsdev_bus_t value; } fsdev_pma_buf_t; -#define PMA_BUF_AT(_addr) ((fsdev_pma_buf_t*) (FSDEV_PMA_BASE + FSDEV_PMA_STRIDE*(_addr))) +#define PMA_BUF_AT(_addr) ((fsdev_pma_buf_t *)(FSDEV_PMA_BASE + FSDEV_PMA_STRIDE * (_addr))) //--------------------------------------------------------------------+ // Registers Typedef //--------------------------------------------------------------------+ // volatile 32-bit aligned -#define _va32 volatile TU_ATTR_ALIGNED(4) +#define _va32 volatile TU_ATTR_ALIGNED(4) typedef struct { struct { _va32 fsdev_bus_t reg; - }ep[FSDEV_EP_COUNT]; - - _va32 uint32_t RESERVED7[8]; // Reserved - _va32 fsdev_bus_t CNTR; // 40: Control register - _va32 fsdev_bus_t ISTR; // 44: Interrupt status register - _va32 fsdev_bus_t FNR; // 48: Frame number register - _va32 fsdev_bus_t DADDR; // 4C: Device address register - _va32 fsdev_bus_t BTABLE; // 50: Buffer Table address register (16-bit only) - _va32 fsdev_bus_t LPMCSR; // 54: LPM Control and Status Register (32-bit only) - _va32 fsdev_bus_t BCDR; // 58: Battery Charging Detector Register (32-bit only) + } ep[FSDEV_EP_COUNT]; + + _va32 uint32_t RESERVED7[8]; // Reserved + _va32 fsdev_bus_t CNTR; // 40: Control register + _va32 fsdev_bus_t ISTR; // 44: Interrupt status register + _va32 fsdev_bus_t FNR; // 48: Frame number register + _va32 fsdev_bus_t DADDR; // 4C: Device address register + _va32 fsdev_bus_t BTABLE; // 50: Buffer Table address register (16-bit only) + _va32 fsdev_bus_t LPMCSR; // 54: LPM Control and Status Register (32-bit only) + _va32 fsdev_bus_t BCDR; // 58: Battery Charging Detector Register (32-bit only) } fsdev_regs_t; TU_VERIFY_STATIC(offsetof(fsdev_regs_t, CNTR) == 0x40, "Wrong offset"); TU_VERIFY_STATIC(sizeof(fsdev_regs_t) == 0x5C, "Size is not correct"); -#define FSDEV_REG ((fsdev_regs_t*) FSDEV_REG_BASE) +#define FSDEV_REG ((fsdev_regs_t *)FSDEV_REG_BASE) #ifndef USB_EPTX_STAT -#define USB_EPTX_STAT 0x0030U + #define USB_EPTX_STAT 0x0030U #endif #ifndef USB_EPRX_STAT -#define USB_EPRX_STAT 0x3000U + #define USB_EPRX_STAT 0x3000U #endif #ifndef USB_EPTX_STAT_Pos -#define USB_EPTX_STAT_Pos 4u + #define USB_EPTX_STAT_Pos 4u #endif #ifndef USB_EP_DTOG_TX_Pos -#define USB_EP_DTOG_TX_Pos 6u + #define USB_EP_DTOG_TX_Pos 6u #endif #ifndef USB_EP_CTR_TX_Pos -#define USB_EP_CTR_TX_Pos 7u + #define USB_EP_CTR_TX_Pos 7u #endif typedef enum { EP_STAT_DISABLED = 0, - EP_STAT_STALL = 1, - EP_STAT_NAK = 2, - EP_STAT_VALID = 3 -}ep_stat_t; + EP_STAT_STALL = 1, + EP_STAT_NAK = 2, + EP_STAT_VALID = 3 +} ep_stat_t; -#define EP_STAT_MASK(_dir) (3u << (USB_EPTX_STAT_Pos + ((_dir) == TUSB_DIR_IN ? 0 : 8))) -#define EP_DTOG_MASK(_dir) (1u << (USB_EP_DTOG_TX_Pos + ((_dir) == TUSB_DIR_IN ? 0 : 8))) +#define EP_STAT_MASK(_dir) (3u << (USB_EPTX_STAT_Pos + ((_dir) == TUSB_DIR_IN ? 0 : 8))) +#define EP_DTOG_MASK(_dir) (1u << (USB_EP_DTOG_TX_Pos + ((_dir) == TUSB_DIR_IN ? 0 : 8))) -#define CH_STAT_MASK(_dir) (3u << (USB_EPTX_STAT_Pos + ((_dir) == TUSB_DIR_IN ? 8 : 0))) -#define CH_DTOG_MASK(_dir) (1u << (USB_EP_DTOG_TX_Pos + ((_dir) == TUSB_DIR_IN ? 8 : 0))) +#define CH_STAT_MASK(_dir) (3u << (USB_EPTX_STAT_Pos + ((_dir) == TUSB_DIR_IN ? 8 : 0))) +#define CH_DTOG_MASK(_dir) (1u << (USB_EP_DTOG_TX_Pos + ((_dir) == TUSB_DIR_IN ? 8 : 0))) //--------------------------------------------------------------------+ // Endpoint Helper @@ -211,7 +207,7 @@ TU_ATTR_ALWAYS_INLINE static inline void ep_write(uint32_t ep_id, uint32_t value fsdev_int_disable(0); } - FSDEV_REG->ep[ep_id].reg = (fsdev_bus_t) value; + FSDEV_REG->ep[ep_id].reg = (fsdev_bus_t)value; if (need_exclusive) { fsdev_int_enable(0); @@ -226,11 +222,11 @@ TU_ATTR_ALWAYS_INLINE static inline void ep_write_clear_ctr(uint32_t ep_id, tusb ep_write(ep_id, reg, false); } -TU_ATTR_ALWAYS_INLINE static inline void ep_change_status(uint32_t* reg, tusb_dir_t dir, ep_stat_t state) { +TU_ATTR_ALWAYS_INLINE static inline void ep_change_status(uint32_t *reg, tusb_dir_t dir, ep_stat_t state) { *reg ^= (state << (USB_EPTX_STAT_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); } -TU_ATTR_ALWAYS_INLINE static inline void ep_change_dtog(uint32_t* reg, tusb_dir_t dir, uint8_t state) { +TU_ATTR_ALWAYS_INLINE static inline void ep_change_dtog(uint32_t *reg, tusb_dir_t dir, uint8_t state) { *reg ^= (state << (USB_EP_DTOG_TX_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); } @@ -259,11 +255,11 @@ TU_ATTR_ALWAYS_INLINE static inline void ch_write_clear_ctr(uint32_t ch_id, tusb ep_write(ch_id, reg, false); } -TU_ATTR_ALWAYS_INLINE static inline void ch_change_status(uint32_t* reg, tusb_dir_t dir, ep_stat_t state) { +TU_ATTR_ALWAYS_INLINE static inline void ch_change_status(uint32_t *reg, tusb_dir_t dir, ep_stat_t state) { *reg ^= (state << (USB_EPTX_STAT_Pos + (dir == TUSB_DIR_IN ? 8 : 0))); } -TU_ATTR_ALWAYS_INLINE static inline void ch_change_dtog(uint32_t* reg, tusb_dir_t dir, uint8_t state) { +TU_ATTR_ALWAYS_INLINE static inline void ch_change_dtog(uint32_t *reg, tusb_dir_t dir, uint8_t state) { *reg ^= (state << (USB_EP_DTOG_TX_Pos + (dir == TUSB_DIR_IN ? 8 : 0))); } @@ -281,8 +277,8 @@ TU_ATTR_ALWAYS_INLINE static inline uint32_t btable_get_addr(uint32_t ep_id, uin TU_ATTR_ALWAYS_INLINE static inline void btable_set_addr(uint32_t ep_id, uint8_t buf_id, uint16_t addr) { #ifdef FSDEV_BUS_32BIT - uint32_t count_addr = FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr; - count_addr = (count_addr & 0xFFFF0000u) | (addr & 0x0000FFFCu); + uint32_t count_addr = FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr; + count_addr = (count_addr & 0xFFFF0000u) | (addr & 0x0000FFFCu); FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr = count_addr; #else FSDEV_BTABLE->ep16[ep_id][buf_id].addr = addr; @@ -301,12 +297,12 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t btable_get_count(uint32_t ep_id, ui TU_ATTR_ALWAYS_INLINE static inline void btable_set_count(uint32_t ep_id, uint8_t buf_id, uint16_t byte_count) { #ifdef FSDEV_BUS_32BIT - uint32_t count_addr = FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr; - count_addr = (count_addr & ~0x03FF0000u) | ((byte_count & 0x3FFu) << 16); + uint32_t count_addr = FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr; + count_addr = (count_addr & ~0x03FF0000u) | ((byte_count & 0x3FFu) << 16); FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr = count_addr; #else - uint16_t cnt = FSDEV_BTABLE->ep16[ep_id][buf_id].count; - cnt = (cnt & ~0x3FFU) | (byte_count & 0x3FFU); + uint16_t cnt = FSDEV_BTABLE->ep16[ep_id][buf_id].count; + cnt = (cnt & ~0x3FFU) | (byte_count & 0x3FFU); FSDEV_BTABLE->ep16[ep_id][buf_id].count = cnt; #endif } @@ -318,7 +314,7 @@ void fsdev_core_reset(void); void fsdev_deinit(void); // Aligned buffer size according to hardware -uint16_t pma_align_buffer_size(uint16_t size, uint8_t* blsize, uint8_t* num_block); +uint16_t pma_align_buffer_size(uint16_t size, uint8_t *blsize, uint8_t *num_block); // Set RX buffer size void btable_set_rx_bufsize(uint32_t ep_id, uint8_t buf_id, uint16_t wCount); diff --git a/src/portable/st/stm32_fsdev/fsdev_stm32.h b/src/portable/st/stm32_fsdev/fsdev_stm32.h index 85ca88f1c..02dba05a6 100644 --- a/src/portable/st/stm32_fsdev/fsdev_stm32.h +++ b/src/portable/st/stm32_fsdev/fsdev_stm32.h @@ -281,7 +281,7 @@ // - 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 + #if CFG_TUSB_FSDEV_PMA_SIZE > 1024u #define CFG_TUD_FSDEV_DOUBLE_BUFFERED_ISO_EP 1 #else #define CFG_TUD_FSDEV_DOUBLE_BUFFERED_ISO_EP 0 diff --git a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c index f232f7d94..acdeccf6d 100644 --- a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c @@ -741,7 +741,7 @@ static uint32_t hcd_pma_alloc(uint8_t channel, tusb_dir_t dir, uint16_t len) { uint16_t addr = FSDEV_BTABLE_BASE + 8 * FSDEV_EP_COUNT; addr += channel * TUSB_EPSIZE_BULK_FS * 2 + (dir == TUSB_DIR_IN ? TUSB_EPSIZE_BULK_FS : 0); - TU_ASSERT(addr <= FSDEV_PMA_SIZE, 0xFFFF); + TU_ASSERT(addr <= CFG_TUSB_FSDEV_PMA_SIZE, 0xFFFF); return addr; } diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index 570b1c14c..c40703b09 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -856,8 +856,7 @@ static void handle_rxflvl_irq(uint8_t rhport) { hcd_endpoint_t* edpt = &_hcd_data.edpt[xfer->ep_id]; if (byte_count > 0) { - const tu_hwfifo_access_t access_mode = {.data_stride = CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE}; - tu_hwfifo_read(dwc2->fifo[0], edpt->buffer + xfer->xferred_bytes, byte_count, &access_mode); + tu_hwfifo_read(dwc2->fifo[0], edpt->buffer + xfer->xferred_bytes, byte_count, NULL); xfer->xferred_bytes += byte_count; xfer->fifo_bytes = byte_count; } @@ -908,8 +907,7 @@ static bool handle_txfifo_empty(dwc2_regs_t* dwc2, bool is_periodic) { return true; } - const tu_hwfifo_access_t access_mode = {.data_stride = CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE}; - tu_hwfifo_write(dwc2->fifo[ch_id], edpt->buffer + xfer->fifo_bytes, xact_bytes, &access_mode); + tu_hwfifo_write(dwc2->fifo[ch_id], edpt->buffer + xfer->fifo_bytes, xact_bytes, NULL); xfer->fifo_bytes += xact_bytes; } } diff --git a/src/tusb_option.h b/src/tusb_option.h index 87aba6a6c..5135ff05b 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -351,13 +351,13 @@ #if defined(TUP_USBIP_FSDEV) #define CFG_TUD_EDPT_DEDICATED_HWFIFO 1 - #if FSDEV_PMA_SIZE == 512 + #if CFG_TUSB_FSDEV_PMA_SIZE == 512 #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE 2 // 16-bit data #define CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE 4 // 32-bit address increase - #elif FSDEV_PMA_SIZE == 1024 + #elif CFG_TUSB_FSDEV_PMA_SIZE == 1024 #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE 2 // 16-bit data #define CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE 2 // 16-bit address increase - #elif FSDEV_PMA_SIZE == 2048 + #elif CFG_TUSB_FSDEV_PMA_SIZE == 2048 #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE 4 // 32-bit data #define CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE 4 // 32-bit address increase #endif -- cgit v1.3.1 From 3302c07d129e8a6c2631a9b15d5a3549b455a3ea Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 28 Nov 2025 15:37:57 +0100 Subject: dwc2: implement deinit Signed-off-by: HiFiPhile --- src/portable/synopsys/dwc2/dcd_dwc2.c | 12 ++++++++++++ src/portable/synopsys/dwc2/dwc2_common.c | 13 +++++++++++++ src/portable/synopsys/dwc2/dwc2_common.h | 1 + src/portable/synopsys/dwc2/hcd_dwc2.c | 10 ++++++++++ 4 files changed, 36 insertions(+) (limited to 'src/portable') diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index 44f7137f9..57dcb6fba 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -491,6 +491,18 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { return true; } +bool dcd_deinit(uint8_t rhport) { + dwc2_regs_t* dwc2 = DWC2_REG(rhport); + + // Disable global interrupt + dwc2->gahbcfg &= ~GAHBCFG_GINT; + + dcd_disconnect(rhport); + + dwc2_core_deinit(rhport); + return true; +} + void dcd_int_enable(uint8_t rhport) { dwc2_dcd_int_enable(rhport); } diff --git a/src/portable/synopsys/dwc2/dwc2_common.c b/src/portable/synopsys/dwc2/dwc2_common.c index a7e6188df..ce38ed6ec 100644 --- a/src/portable/synopsys/dwc2/dwc2_common.c +++ b/src/portable/synopsys/dwc2/dwc2_common.c @@ -251,6 +251,19 @@ bool dwc2_core_init(uint8_t rhport, bool is_highspeed, bool is_dma) { return true; } +void dwc2_core_deinit(uint8_t rhport) { + dwc2_regs_t* dwc2 = DWC2_REG(rhport); + + // Soft disconnect + dwc2->dctl |= DCTL_SDIS; + + // Reset global registers + dwc2->gotgctl = 0; + + // Reset core + reset_core(dwc2); +} + // void dwc2_core_handle_common_irq(uint8_t rhport, bool in_isr) { // (void) in_isr; // dwc2_regs_t * const dwc2 = DWC2_REG(rhport); diff --git a/src/portable/synopsys/dwc2/dwc2_common.h b/src/portable/synopsys/dwc2/dwc2_common.h index 428304ba9..af532dc5e 100644 --- a/src/portable/synopsys/dwc2/dwc2_common.h +++ b/src/portable/synopsys/dwc2/dwc2_common.h @@ -86,6 +86,7 @@ TU_ATTR_ALWAYS_INLINE static inline dwc2_regs_t* DWC2_REG(uint8_t rhport) { bool dwc2_core_is_highspeed(dwc2_regs_t* dwc2, tusb_role_t role); bool dwc2_core_init(uint8_t rhport, bool is_highspeed, bool is_dma); +void dwc2_core_deinit(uint8_t rhport); void dwc2_core_handle_common_irq(uint8_t rhport, bool in_isr); //--------------------------------------------------------------------+ diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index c40703b09..fc27b3f55 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -445,6 +445,16 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { return true; } +bool hcd_deinit(uint8_t rhport) { + dwc2_regs_t* dwc2 = DWC2_REG(rhport); + + // Disable global interrupt + dwc2->gahbcfg &= ~GAHBCFG_GINT; + + dwc2_core_deinit(rhport); + return true; +} + // Enable USB interrupt void hcd_int_enable (uint8_t rhport) { dwc2_int_set(rhport, TUSB_ROLE_HOST, true); -- cgit v1.3.1 From 104cf33239eda282b34c1f7971fbfc8e310eabf8 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sat, 29 Nov 2025 16:07:41 +0100 Subject: hcd/dwc2: disable ID change interrupt due to stuck on stm32f7 Signed-off-by: HiFiPhile --- src/portable/synopsys/dwc2/hcd_dwc2.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'src/portable') diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index fc27b3f55..9d58dd4a3 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -435,7 +435,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 | GINTSTS_DISCINT; + dwc2->gintmsk |= GINTSTS_OTGINT | 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; @@ -1448,16 +1448,6 @@ void hcd_int_handler(uint8_t rhport, bool in_isr) { // TU_LOG1_HEX(gintsts); - if (gintsts & GINTSTS_CONIDSTSCHNG) { - // Connector ID status change - dwc2->gintsts = GINTSTS_CONIDSTSCHNG; - - //if (dwc2->gotgctl) - // dwc2->hprt = HPRT_POWER; // power on port to turn on VBUS - //dwc2->gintmsk |= GINTMSK_PRTIM; - // TODO wait for SRP if OTG - } - if (gintsts & GINTSTS_SOF) { const bool more_sof = handle_sof_irq(rhport, in_isr); if (!more_sof) { -- cgit v1.3.1 From 4914ae83e516f9f81f75f5d0dc461904b6fcd551 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 28 Nov 2025 22:05:02 +0100 Subject: hcd/dwc2: retry transfer on data toggle error Signed-off-by: HiFiPhile --- src/portable/synopsys/dwc2/hcd_dwc2.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src/portable') diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index 9d58dd4a3..fb075582f 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -879,7 +879,7 @@ static void handle_rxflvl_irq(uint8_t rhport) { break; case GRXSTS_PKTSTS_HOST_DATATOGGLE_ERR: - TU_ASSERT(0, ); // maybe try to change DToggle + // handle in channel interrupt break; case GRXSTS_PKTSTS_HOST_CHANNEL_HALTED: @@ -1019,8 +1019,11 @@ static bool handle_channel_in_slave(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t h channel_xfer_in_retry(dwc2, ch_id, hcint); } } else if (hcint & HCINT_DATATOGGLE_ERR) { + channel->hcintmsk &= ~HCINT_DATATOGGLE_ERR; xfer->err_count = 0; - TU_ASSERT(false); + hcsplt.split_compl = 0; // restart with start-split + channel->hcsplt = hcsplt.value; + channel_disable(dwc2, channel); } else { // nothing to do } -- cgit v1.3.1 From bbe1be349a3011da3839906d6b90110e140ddbe1 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Mon, 15 Dec 2025 22:19:35 +0100 Subject: hcd/stm32_fsdev: fix init after device mode Signed-off-by: HiFiPhile --- src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src/portable') diff --git a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c index acdeccf6d..1813ef70b 100644 --- a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c @@ -223,9 +223,13 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { tu_memclr(&_hcd_data, sizeof(_hcd_data)); + // Clear pending interrupts + // Normally no interrupts should be pending here since we just reset the core, + // but device mode suspend needs to cleared by WKUP flag + FSDEV_REG->ISTR = 0; + // Enable interrupts for host mode - FSDEV_REG->CNTR |= USB_CNTR_RESETM | USB_CNTR_CTRM | USB_CNTR_SOFM | USB_CNTR_SUSPM | - USB_CNTR_WKUPM | USB_CNTR_ERRM | USB_CNTR_PMAOVRM; + FSDEV_REG->CNTR |= USB_CNTR_DCON | USB_CNTR_CTRM | USB_CNTR_SOFM | USB_CNTR_ERRM | USB_CNTR_PMAOVRM; // Initialize port state _hcd_data.connected = false; -- cgit v1.3.1 From a124edf9f6d008074f838c6daaed7c0502569ab7 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 7 Jan 2026 09:58:23 +0700 Subject: refactor remove endpoint_control/buffer_control from hw_endpoint_t --- src/portable/raspberrypi/rp2040/dcd_rp2040.c | 49 ++++++++------- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 33 +++++------ src/portable/raspberrypi/rp2040/rp2040_usb.c | 29 ++++----- src/portable/raspberrypi/rp2040/rp2040_usb.h | 89 +++++++++++++++++++++------- 4 files changed, 123 insertions(+), 77 deletions(-) (limited to 'src/portable') diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index 15852f29f..31683502a 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -55,14 +55,14 @@ static struct hw_endpoint hw_endpoints[USB_MAX_ENDPOINTS][2]; // SOF may be used by remote wakeup as RESUME, this indicate whether SOF is actually used by usbd static bool _sof_enable = false; -TU_ATTR_ALWAYS_INLINE static inline struct hw_endpoint* hw_endpoint_get_by_num(uint8_t num, tusb_dir_t dir) { +TU_ATTR_ALWAYS_INLINE static inline struct hw_endpoint *hw_endpoint_get(uint8_t num, tusb_dir_t dir) { return &hw_endpoints[num][dir]; } TU_ATTR_ALWAYS_INLINE static inline struct hw_endpoint* hw_endpoint_get_by_addr(uint8_t ep_addr) { uint8_t num = tu_edpt_number(ep_addr); tusb_dir_t dir = tu_edpt_dir(ep_addr); - return hw_endpoint_get_by_num(num, dir); + return hw_endpoint_get(num, dir); } // Allocate from the USB buffer space (max 3840 bytes) @@ -86,15 +86,14 @@ static void hw_endpoint_alloc(struct hw_endpoint* ep, size_t size) { // Enable endpoint TU_ATTR_ALWAYS_INLINE static inline void hw_endpoint_enable(struct hw_endpoint* ep) { uint32_t const reg = EP_CTRL_ENABLE_BITS | ((uint) ep->transfer_type << EP_CTRL_BUFFER_TYPE_LSB) | hw_data_offset(ep->hw_data_buf); - *ep->endpoint_control = reg; + *hwep_ctrl_reg(ep) = reg; } // main processing for dcd_edpt_iso_activate static void hw_endpoint_init(uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t transfer_type) { - struct hw_endpoint* ep = hw_endpoint_get_by_addr(ep_addr); - const uint8_t num = tu_edpt_number(ep_addr); const tusb_dir_t dir = tu_edpt_dir(ep_addr); + hw_endpoint_t* ep = hw_endpoint_get(num, dir); ep->ep_addr = ep_addr; @@ -106,28 +105,28 @@ static void hw_endpoint_init(uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t t ep->transfer_type = transfer_type; // Every endpoint has a buffer control register in dpram - if (dir == TUSB_DIR_IN) { - ep->buffer_control = &usb_dpram->ep_buf_ctrl[num].in; - } else { - ep->buffer_control = &usb_dpram->ep_buf_ctrl[num].out; - } + // if (dir == TUSB_DIR_IN) { + // ep->buffer_control = &usb_dpram->ep_buf_ctrl[num].in; + // } else { + // ep->buffer_control = &usb_dpram->ep_buf_ctrl[num].out; + // } // Clear existing buffer control state - *ep->buffer_control = 0; + *hwep_buf_ctrl_reg(ep) = 0; if (num == 0) { // EP0 has no endpoint control register because the buffer offsets are fixed - ep->endpoint_control = NULL; + // ep->endpoint_control = NULL; // Buffer offset is fixed (also double buffered) ep->hw_data_buf = (uint8_t*) &usb_dpram->ep0_buf_a[0]; } else { // Set the endpoint control register (starts at EP1, hence num-1) - if (dir == TUSB_DIR_IN) { - ep->endpoint_control = &usb_dpram->ep_ctrl[num - 1].in; - } else { - ep->endpoint_control = &usb_dpram->ep_ctrl[num - 1].out; - } + // if (dir == TUSB_DIR_IN) { + // ep->endpoint_control = &usb_dpram->ep_ctrl[num - 1].in; + // } else { + // ep->endpoint_control = &usb_dpram->ep_ctrl[num - 1].out; + // } } } @@ -165,7 +164,7 @@ static void hw_endpoint_abort_xfer(struct hw_endpoint* ep) { buf_ctrl |= USB_BUF_CTRL_DATA1_PID; } - _hw_endpoint_buffer_control_set_value32(ep, buf_ctrl); + hwep_buf_ctrl_set(ep, buf_ctrl); hw_endpoint_reset_transfer(ep); if (rp2040_chip_version() >= 2) { @@ -184,7 +183,7 @@ static void __tusb_irq_path_func(hw_handle_buff_status)(void) { usb_hw_clear->buf_status = bit; // IN transfer for even i, OUT transfer for odd i - struct hw_endpoint* ep = hw_endpoint_get_by_num(i >> 1u, (i & 1u) ? TUSB_DIR_OUT : TUSB_DIR_IN); + struct hw_endpoint *ep = hw_endpoint_get(i >> 1u, (i & 1u) ? TUSB_DIR_OUT : TUSB_DIR_IN); // Continue xfer bool done = hw_endpoint_xfer_continue(ep); @@ -204,7 +203,7 @@ TU_ATTR_ALWAYS_INLINE static inline void reset_ep0(void) { // If we have finished this transfer on EP0 set pid back to 1 for next // setup transfer. Also clear a stall in case for (uint8_t dir = 0; dir < 2; dir++) { - struct hw_endpoint* ep = hw_endpoint_get_by_num(0, dir); + struct hw_endpoint *ep = hw_endpoint_get(0, dir); ep->next_pid = 1u; if (ep->active) { hw_endpoint_abort_xfer(ep); // Abort any pending transfer per USB specs @@ -240,7 +239,7 @@ static void __tusb_irq_path_func(dcd_rp2040_irq)(void) { e15_last_sof = time_us_32(); for (uint8_t i = 0; i < USB_MAX_ENDPOINTS; i++) { - struct hw_endpoint* ep = hw_endpoint_get_by_num(i, TUSB_DIR_IN); + struct hw_endpoint *ep = hw_endpoint_get(i, TUSB_DIR_IN); // Active Bulk IN endpoint requires SOF if ((ep->transfer_type == TUSB_XFER_BULK) && ep->active) { @@ -369,9 +368,9 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { TU_LOG(2, "Chip Version B%u\r\n", rp2040_chip_version()); // Reset hardware to default state - rp2040_usb_init(); + rp2usb_init(); -#if FORCE_VBUS_DETECT + #if FORCE_VBUS_DETECT // Force VBUS detect so the device thinks it is plugged into a host usb_hw->pwr = USB_USB_PWR_VBUS_DETECT_BITS | USB_USB_PWR_VBUS_DETECT_OVERRIDE_EN_BITS; #endif @@ -546,7 +545,7 @@ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { // stall and clear current pending buffer // may need to use EP_ABORT - _hw_endpoint_buffer_control_set_value32(ep, USB_BUF_CTRL_STALL); + hwep_buf_ctrl_set(ep, USB_BUF_CTRL_STALL); } void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { @@ -557,7 +556,7 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { // clear stall also reset toggle to DATA0, ready for next transfer ep->next_pid = 0; - _hw_endpoint_buffer_control_clear_mask32(ep, USB_BUF_CTRL_STALL); + hwep_buf_ctrl_clear_mask(ep, USB_BUF_CTRL_STALL); } } diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index cd8c905d5..12a2f2d25 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -122,7 +122,7 @@ static void __tusb_irq_path_func(hw_handle_buff_status)(void) remaining_buffers &= ~bit; struct hw_endpoint * ep = &epx; - uint32_t ep_ctrl = *ep->endpoint_control; + uint32_t ep_ctrl = *hwep_ctrl_reg(ep); if ( ep_ctrl & EP_CTRL_DOUBLE_BUFFERED_BITS ) { TU_LOG(3, "Double Buffered: "); @@ -240,9 +240,8 @@ static void __tusb_irq_path_func(hcd_rp2040_irq)(void) if ( status & USB_INTS_ERROR_DATA_SEQ_BITS ) { usb_hw_clear->sie_status = USB_SIE_STATUS_DATA_SEQ_ERROR_BITS; - TU_LOG(3, " Seq Error: [0] = 0x%04u [1] = 0x%04x\r\n", - tu_u32_low16(*epx.buffer_control), - tu_u32_high16(*epx.buffer_control)); + TU_LOG(3, " Seq Error: [0] = 0x%04u [1] = 0x%04x\r\n", tu_u32_low16(*hw_endpoint_get_buf_ctrl(&epx)), + tu_u32_high16(*hw_endpoint_get_buf_ctrl(&epx))); panic("Data Seq Error \n"); } @@ -285,8 +284,8 @@ static struct hw_endpoint *_hw_endpoint_allocate(uint8_t transfer_type) ep = _next_free_interrupt_ep(); pico_info("Allocate %s ep %d\n", tu_edpt_type_str(transfer_type), ep->interrupt_num); assert(ep); - ep->buffer_control = &usbh_dpram->int_ep_buffer_ctrl[ep->interrupt_num].ctrl; - ep->endpoint_control = &usbh_dpram->int_ep_ctrl[ep->interrupt_num].ctrl; + // ep->buffer_control = &usbh_dpram->int_ep_buffer_ctrl[ep->interrupt_num].ctrl; + // ep->endpoint_control = &usbh_dpram->int_ep_ctrl[ep->interrupt_num].ctrl; // 0 for epx (double buffered): TODO increase to 1024 for ISO // 2x64 for intep0 // 3x64 for intep1 @@ -296,8 +295,8 @@ static struct hw_endpoint *_hw_endpoint_allocate(uint8_t transfer_type) else { ep = &epx; - ep->buffer_control = &usbh_dpram->epx_buf_ctrl; - ep->endpoint_control = &usbh_dpram->epx_ctrl; + // ep->buffer_control = &usbh_dpram->epx_buf_ctrl; + // ep->endpoint_control = &usbh_dpram->epx_ctrl; ep->hw_data_buf = &usbh_dpram->epx_data[0]; } @@ -307,8 +306,8 @@ static struct hw_endpoint *_hw_endpoint_allocate(uint8_t transfer_type) static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t dev_addr, uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t transfer_type, uint8_t bmInterval) { // Already has data buffer, endpoint control, and buffer control allocated at this point - assert(ep->endpoint_control); - assert(ep->buffer_control); + // assert(ep->endpoint_control); + // assert(ep->buffer_control); assert(ep->hw_data_buf); uint8_t const num = tu_edpt_number(ep_addr); @@ -340,8 +339,8 @@ static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t dev_addr, uint8_t { ep_reg |= (uint32_t) ((bmInterval - 1) << EP_CTRL_HOST_INTERRUPT_INTERVAL_LSB); } - *ep->endpoint_control = ep_reg; - pico_trace("endpoint control (0x%p) <- 0x%lx\n", ep->endpoint_control, ep_reg); + *hwep_ctrl_reg(ep) = ep_reg; + // pico_trace("endpoint control (0x%p) <- 0x%lx\n", ep->endpoint_control, ep_reg); ep->configured = true; if ( ep != &epx ) @@ -382,7 +381,7 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { assert(rhport == 0); // Reset any previous state - rp2040_usb_init(); + rp2usb_init(); // Force VBUS detect to always present, for now we assume vbus is always provided (without using VBUS En) usb_hw->pwr = USB_USB_PWR_VBUS_DETECT_BITS | USB_USB_PWR_VBUS_DETECT_OVERRIDE_EN_BITS; @@ -466,8 +465,8 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr) { // reset epx if it is currently active with unplugged device if (epx.configured && epx.active && epx.dev_addr == dev_addr) { epx.configured = false; - *epx.endpoint_control = 0; - *epx.buffer_control = 0; + *hwep_ctrl_reg(&epx) = 0; + *hwep_buf_ctrl_reg(&epx) = 0; hw_endpoint_reset_transfer(&epx); } @@ -482,8 +481,8 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr) { // unconfigure the endpoint ep->configured = false; - *ep->endpoint_control = 0; - *ep->buffer_control = 0; + *hwep_ctrl_reg(ep) = 0; + *hwep_buf_ctrl_reg(ep) = 0; hw_endpoint_reset_transfer(ep); } } diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index 9d0bd762d..61f978b0d 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -62,7 +62,7 @@ static void unaligned_memcpy(void *dst, const void *src, size_t n) { } } -void rp2040_usb_init(void) { +void rp2usb_init(void) { // Reset usb controller reset_block(RESETS_RESET_USBCTRL_BITS); unreset_block_wait(RESETS_RESET_USBCTRL_BITS); @@ -93,21 +93,21 @@ void __tusb_irq_path_func(hw_endpoint_reset_transfer)(struct hw_endpoint* ep) { ep->user_buf = 0; } -void __tusb_irq_path_func(_hw_endpoint_buffer_control_update32)(struct hw_endpoint* ep, uint32_t and_mask, - uint32_t or_mask) { +void __tusb_irq_path_func(hwep_buf_ctrl_update)(struct hw_endpoint *ep, uint32_t and_mask, uint32_t or_mask) { uint32_t value = 0; + io_rw_32 *buf_ctrl = hwep_buf_ctrl_reg(ep); if (and_mask) { - value = *ep->buffer_control & and_mask; + value = *buf_ctrl & and_mask; } if (or_mask) { value |= or_mask; if (or_mask & USB_BUF_CTRL_AVAIL) { - if (*ep->buffer_control & USB_BUF_CTRL_AVAIL) { + if (*buf_ctrl & USB_BUF_CTRL_AVAIL) { panic("ep %02X was already available", ep->ep_addr); } - *ep->buffer_control = value & ~USB_BUF_CTRL_AVAIL; + *buf_ctrl = value & ~USB_BUF_CTRL_AVAIL; // 4.1.2.5.1 Con-current access: 12 cycles (should be good for 48*12Mhz = 576Mhz) after write to buffer control // Don't need delay in host mode as host is in charge if (!is_host_mode()) { @@ -116,7 +116,7 @@ void __tusb_irq_path_func(_hw_endpoint_buffer_control_update32)(struct hw_endpoi } } - *ep->buffer_control = value; + *buf_ctrl = value; } // prepare buffer, return buffer control @@ -153,7 +153,8 @@ static uint32_t __tusb_irq_path_func(prepare_ep_buffer)(struct hw_endpoint* ep, // Prepare buffer control register value void __tusb_irq_path_func(hw_endpoint_start_next_buffer)(struct hw_endpoint* ep) { - uint32_t ep_ctrl = *ep->endpoint_control; + io_rw_32 *ep_ctrl_reg = hwep_ctrl_reg(ep); + uint32_t ep_ctrl = *ep_ctrl_reg; // always compute and start with buffer 0 uint32_t buf_ctrl = prepare_ep_buffer(ep, 0) | USB_BUF_CTRL_SEL; @@ -182,13 +183,13 @@ void __tusb_irq_path_func(hw_endpoint_start_next_buffer)(struct hw_endpoint* ep) ep_ctrl |= EP_CTRL_INTERRUPT_PER_BUFFER; } - *ep->endpoint_control = ep_ctrl; + *ep_ctrl_reg = ep_ctrl; TU_LOG(3, " Prepare BufCtrl: [0] = 0x%04x [1] = 0x%04x\r\n", tu_u32_low16(buf_ctrl), tu_u32_high16(buf_ctrl)); // Finally, write to buffer_control which will trigger the transfer // the next time the controller polls this dpram address - _hw_endpoint_buffer_control_set_value32(ep, buf_ctrl); + hwep_buf_ctrl_set(ep, buf_ctrl); } void hw_endpoint_xfer_start(struct hw_endpoint* ep, uint8_t* buffer, uint16_t total_len) { @@ -221,7 +222,7 @@ void hw_endpoint_xfer_start(struct hw_endpoint* ep, uint8_t* buffer, uint16_t to // sync endpoint buffer and return transferred bytes static uint16_t __tusb_irq_path_func(sync_ep_buffer)(struct hw_endpoint* ep, uint8_t buf_id) { - uint32_t buf_ctrl = _hw_endpoint_buffer_control_get_value32(ep); + uint32_t buf_ctrl = hwep_buf_ctrl_get(ep); if (buf_id) buf_ctrl = buf_ctrl >> 16; uint16_t xferred_bytes = buf_ctrl & USB_BUF_CTRL_LEN_MASK; @@ -256,14 +257,14 @@ static void __tusb_irq_path_func(_hw_endpoint_xfer_sync)(struct hw_endpoint* ep) // Update hw endpoint struct with info from hardware // after a buff status interrupt - uint32_t __unused buf_ctrl = _hw_endpoint_buffer_control_get_value32(ep); + uint32_t __unused buf_ctrl = hwep_buf_ctrl_get(ep); TU_LOG(3, " Sync BufCtrl: [0] = 0x%04x [1] = 0x%04x\r\n", tu_u32_low16(buf_ctrl), tu_u32_high16(buf_ctrl)); // always sync buffer 0 uint16_t buf0_bytes = sync_ep_buffer(ep, 0); // sync buffer 1 if double buffered - if ((*ep->endpoint_control) & EP_CTRL_DOUBLE_BUFFERED_BITS) { + if ((*hwep_ctrl_reg(ep)) & EP_CTRL_DOUBLE_BUFFERED_BITS) { if (buf0_bytes == ep->wMaxPacketSize) { // sync buffer 1 if not short packet sync_ep_buffer(ep, 1); @@ -287,7 +288,7 @@ static void __tusb_irq_path_func(_hw_endpoint_xfer_sync)(struct hw_endpoint* ep) ep_ctrl &= ~(EP_CTRL_DOUBLE_BUFFERED_BITS | EP_CTRL_INTERRUPT_PER_DOUBLE_BUFFER); ep_ctrl |= EP_CTRL_INTERRUPT_PER_BUFFER; - _hw_endpoint_buffer_control_set_value32(ep, 0); + hwep_buf_ctrl_set(ep, 0); usb_hw->abort &= ~TU_BIT(ep_id); diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.h b/src/portable/raspberrypi/rp2040/rp2040_usb.h index d4d29a816..603640c6d 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.h +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.h @@ -56,10 +56,10 @@ typedef struct hw_endpoint uint8_t next_pid; // Endpoint control register - io_rw_32 *endpoint_control; + // io_rw_32 *endpoint_control; // Buffer control register - io_rw_32 *buffer_control; + // io_rw_32 *buffer_control; // Buffer pointer in usb dpram uint8_t *hw_data_buf; @@ -97,7 +97,12 @@ typedef struct hw_endpoint extern volatile uint32_t e15_last_sof; #endif -void rp2040_usb_init(void); +void rp2usb_init(void); + +// if usb hardware is in host mode +TU_ATTR_ALWAYS_INLINE static inline bool rp2usb_is_host_mode(void) { + return (usb_hw->main_ctrl & USB_MAIN_CTRL_HOST_NDEVICE_BITS) ? true : false; +} void hw_endpoint_xfer_start(struct hw_endpoint *ep, uint8_t *buffer, uint16_t total_len); bool hw_endpoint_xfer_continue(struct hw_endpoint *ep); @@ -110,34 +115,76 @@ TU_ATTR_ALWAYS_INLINE static inline void hw_endpoint_lock_update(__unused struct // sense to have worker and IRQ on same core, however I think using critsec is about equivalent. } -void _hw_endpoint_buffer_control_update32(struct hw_endpoint *ep, uint32_t and_mask, uint32_t or_mask); +TU_ATTR_ALWAYS_INLINE static inline io_rw_32 *hwep_ctrl_reg(struct hw_endpoint *ep) { + (void)ep; +#if CFG_TUH_ENABLED + if (rp2usb_is_host_mode()) { + if (ep->transfer_type == TUSB_XFER_CONTROL) { + return &usbh_dpram->epx_ctrl; + } + return &usbh_dpram->int_ep_ctrl[ep->interrupt_num].ctrl; + } +#endif -TU_ATTR_ALWAYS_INLINE static inline uint32_t _hw_endpoint_buffer_control_get_value32 (struct hw_endpoint *ep) -{ - return *ep->buffer_control; +#if CFG_TUD_ENABLED + if (!rp2usb_is_host_mode()) { + const uint8_t num = tu_edpt_number(ep->ep_addr); + if (num == 0) { + return NULL; + } + return (tu_edpt_dir(ep->ep_addr) == TUSB_DIR_IN) ? &usb_dpram->ep_ctrl[num - 1].in + : &usb_dpram->ep_ctrl[num - 1].out; + } +#endif + + return NULL; } -TU_ATTR_ALWAYS_INLINE static inline void _hw_endpoint_buffer_control_set_value32 (struct hw_endpoint *ep, uint32_t value) -{ - _hw_endpoint_buffer_control_update32(ep, 0, value); +TU_ATTR_ALWAYS_INLINE static inline io_rw_32 *hwep_buf_ctrl_reg(struct hw_endpoint *ep) { + (void)ep; +#if CFG_TUH_ENABLED + if (rp2usb_is_host_mode()) { + if (ep->transfer_type == TUSB_XFER_CONTROL) { + return &usbh_dpram->epx_buf_ctrl; + } + return &usbh_dpram->int_ep_buffer_ctrl[ep->interrupt_num].ctrl; + } +#endif + +#if CFG_TUD_ENABLED + if (!rp2usb_is_host_mode()) { + const uint8_t num = tu_edpt_number(ep->ep_addr); + return (tu_edpt_dir(ep->ep_addr) == TUSB_DIR_IN) ? &usb_dpram->ep_buf_ctrl[num].in + : &usb_dpram->ep_buf_ctrl[num].out; + } +#endif + return NULL; } -TU_ATTR_ALWAYS_INLINE static inline void _hw_endpoint_buffer_control_set_mask32 (struct hw_endpoint *ep, uint32_t value) -{ - _hw_endpoint_buffer_control_update32(ep, ~value, value); +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ +void hwep_buf_ctrl_update(struct hw_endpoint *ep, uint32_t and_mask, uint32_t or_mask); + +TU_ATTR_ALWAYS_INLINE static inline uint32_t hwep_buf_ctrl_get(struct hw_endpoint *ep) { + return *hwep_buf_ctrl_reg(ep); } -TU_ATTR_ALWAYS_INLINE static inline void _hw_endpoint_buffer_control_clear_mask32 (struct hw_endpoint *ep, uint32_t value) -{ - _hw_endpoint_buffer_control_update32(ep, ~value, 0); +TU_ATTR_ALWAYS_INLINE static inline void hwep_buf_ctrl_set(struct hw_endpoint *ep, uint32_t value) { + hwep_buf_ctrl_update(ep, 0, value); } -static inline uintptr_t hw_data_offset (uint8_t *buf) -{ - // Remove usb base from buffer pointer - return (uintptr_t) buf ^ (uintptr_t) usb_dpram; +TU_ATTR_ALWAYS_INLINE static inline void hwep_buf_ctrl_set_mask32(struct hw_endpoint *ep, uint32_t value) { + hwep_buf_ctrl_update(ep, ~value, value); +} + +TU_ATTR_ALWAYS_INLINE static inline void hwep_buf_ctrl_clear_mask(struct hw_endpoint *ep, uint32_t value) { + hwep_buf_ctrl_update(ep, ~value, 0); } -extern const char *ep_dir_string[]; +static inline uintptr_t hw_data_offset(uint8_t *buf) { + // Remove usb base from buffer pointer + return (uintptr_t)buf ^ (uintptr_t)usb_dpram; +} #endif -- cgit v1.3.1 From 475e97cc8b048e2ea0244f310657b8e02a5cfe73 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 7 Jan 2026 22:49:18 +0700 Subject: remove hw_endpoint_t rx, rename/change signature of helper functions --- src/portable/raspberrypi/rp2040/dcd_rp2040.c | 205 ++++++++++++--------------- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 15 +- src/portable/raspberrypi/rp2040/rp2040_usb.c | 182 +++++++++++++++--------- src/portable/raspberrypi/rp2040/rp2040_usb.h | 69 ++++----- 4 files changed, 239 insertions(+), 232 deletions(-) (limited to 'src/portable') diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index 31683502a..6c74029d8 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -41,83 +41,49 @@ // Current implementation force vbus detection as always present, causing device think it is always plugged into host. // Therefore it cannot detect disconnect event, mistaken it as suspend. // Note: won't work if change to 0 (for now) -#define FORCE_VBUS_DETECT 1 +#define FORCE_VBUS_DETECT 1 + + #define USB_INTS_ERROR_BITS \ + (USB_INTS_ERROR_DATA_SEQ_BITS | USB_INTS_ERROR_BIT_STUFF_BITS | USB_INTS_ERROR_CRC_BITS | \ + USB_INTS_ERROR_RX_OVERFLOW_BITS | USB_INTS_ERROR_RX_TIMEOUT_BITS) /*------------------------------------------------------------------*/ /* Low level controller *------------------------------------------------------------------*/ -// Init these in dcd_init -static uint8_t* next_buffer_ptr; +// HW buffer pointer from USB buffer space (max 3840 bytes) +static uint8_t *hw_buffer_ptr; // USB_MAX_ENDPOINTS Endpoints, direction TUSB_DIR_OUT for out and TUSB_DIR_IN for in. static struct hw_endpoint hw_endpoints[USB_MAX_ENDPOINTS][2]; -// SOF may be used by remote wakeup as RESUME, this indicate whether SOF is actually used by usbd +// SOF may be used by remote wakeup as RESUME, this indicates whether SOF is actually used by usbd static bool _sof_enable = false; -TU_ATTR_ALWAYS_INLINE static inline struct hw_endpoint *hw_endpoint_get(uint8_t num, tusb_dir_t dir) { - return &hw_endpoints[num][dir]; +TU_ATTR_ALWAYS_INLINE static inline hw_endpoint_t *hw_endpoint_get(uint8_t epnum, tusb_dir_t dir) { + return &hw_endpoints[epnum][dir]; } -TU_ATTR_ALWAYS_INLINE static inline struct hw_endpoint* hw_endpoint_get_by_addr(uint8_t ep_addr) { - uint8_t num = tu_edpt_number(ep_addr); - tusb_dir_t dir = tu_edpt_dir(ep_addr); +TU_ATTR_ALWAYS_INLINE static inline hw_endpoint_t *hw_endpoint_get_by_addr(uint8_t ep_addr) { + const uint8_t num = tu_edpt_number(ep_addr); + const tusb_dir_t dir = tu_edpt_dir(ep_addr); return hw_endpoint_get(num, dir); } -// Allocate from the USB buffer space (max 3840 bytes) -static void hw_endpoint_alloc(struct hw_endpoint* ep, size_t size) { - // round up size to multiple of 64 - size = tu_round_up(ep->wMaxPacketSize, 64); - - // double buffered Bulk endpoint - if (ep->transfer_type == TUSB_XFER_BULK) { - size *= 2u; - } - - // assign buffer - ep->hw_data_buf = next_buffer_ptr; - next_buffer_ptr += size; - - hard_assert(next_buffer_ptr < usb_dpram->epx_data + sizeof(usb_dpram->epx_data)); - pico_info(" Allocated %d bytes (0x%p)\r\n", size, ep->hw_data_buf); -} - -// Enable endpoint -TU_ATTR_ALWAYS_INLINE static inline void hw_endpoint_enable(struct hw_endpoint* ep) { - uint32_t const reg = EP_CTRL_ENABLE_BITS | ((uint) ep->transfer_type << EP_CTRL_BUFFER_TYPE_LSB) | hw_data_offset(ep->hw_data_buf); - *hwep_ctrl_reg(ep) = reg; -} - // main processing for dcd_edpt_iso_activate -static void hw_endpoint_init(uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t transfer_type) { - const uint8_t num = tu_edpt_number(ep_addr); - const tusb_dir_t dir = tu_edpt_dir(ep_addr); - hw_endpoint_t* ep = hw_endpoint_get(num, dir); - - ep->ep_addr = ep_addr; - - // For device, IN is a tx transfer and OUT is an rx transfer - ep->rx = (dir == TUSB_DIR_OUT); +static void hw_endpoint_init(hw_endpoint_t *ep, uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t transfer_type) { + const uint8_t epnum = tu_edpt_number(ep_addr); - ep->next_pid = 0u; + ep->ep_addr = ep_addr; + ep->next_pid = 0u; ep->wMaxPacketSize = wMaxPacketSize; - ep->transfer_type = transfer_type; - - // Every endpoint has a buffer control register in dpram - // if (dir == TUSB_DIR_IN) { - // ep->buffer_control = &usb_dpram->ep_buf_ctrl[num].in; - // } else { - // ep->buffer_control = &usb_dpram->ep_buf_ctrl[num].out; - // } + ep->transfer_type = transfer_type; // Clear existing buffer control state - *hwep_buf_ctrl_reg(ep) = 0; - - if (num == 0) { - // EP0 has no endpoint control register because the buffer offsets are fixed - // ep->endpoint_control = NULL; + io_rw_32 *buf_ctrl_reg = hwep_buf_ctrl_reg_device(ep); + *buf_ctrl_reg = 0; + // allocated hw buffer + if (epnum == 0) { // Buffer offset is fixed (also double buffered) ep->hw_data_buf = (uint8_t*) &usb_dpram->ep0_buf_a[0]; } else { @@ -127,33 +93,49 @@ static void hw_endpoint_init(uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t t // } else { // ep->endpoint_control = &usb_dpram->ep_ctrl[num - 1].out; // } + + // round up size to multiple of 64 + uint16_t size = (uint16_t)tu_round_up(wMaxPacketSize, 64); + + // double buffered Bulk endpoint + if (transfer_type == TUSB_XFER_BULK) { + size *= 2u; + } + + // assign buffer + ep->hw_data_buf = hw_buffer_ptr; + hw_buffer_ptr += size; + + hard_assert(hw_buffer_ptr < usb_dpram->epx_data + sizeof(usb_dpram->epx_data)); + pico_info(" Allocated %d bytes (0x%p)\r\n", size, ep->hw_data_buf); } } // Init, allocate buffer and enable endpoint static void hw_endpoint_open(uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t transfer_type) { - struct hw_endpoint* ep = hw_endpoint_get_by_addr(ep_addr); - hw_endpoint_init(ep_addr, wMaxPacketSize, transfer_type); - const uint8_t num = tu_edpt_number(ep_addr); - if (num != 0) { - // EP0 is already enabled - hw_endpoint_alloc(ep, ep->wMaxPacketSize); - hw_endpoint_enable(ep); + const uint8_t epnum = tu_edpt_number(ep_addr); + const tusb_dir_t dir = tu_edpt_dir(ep_addr); + hw_endpoint_t *ep = hw_endpoint_get(epnum, dir); + + hw_endpoint_init(ep, ep_addr, wMaxPacketSize, transfer_type); + + // Set endpoint control register to enable (EP0 has no endpoint control register) + io_rw_32 *ctrl_reg = hwep_ctrl_reg_device(ep); + if (ctrl_reg != NULL) { + const uint32_t ctrl_value = + EP_CTRL_ENABLE_BITS | ((uint32_t)transfer_type << EP_CTRL_BUFFER_TYPE_LSB) | hw_data_offset(ep->hw_data_buf); + *ctrl_reg = ctrl_value; } } -static void hw_endpoint_xfer(uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) { - struct hw_endpoint* ep = hw_endpoint_get_by_addr(ep_addr); - hw_endpoint_xfer_start(ep, buffer, total_bytes); -} - static void hw_endpoint_abort_xfer(struct hw_endpoint* ep) { // Abort any pending transfer // Due to Errata RP2040-E2: ABORT flag is only applicable for B2 and later (unusable for B0, B1). // Which means we are not guaranteed to safely abort pending transfer on B0 and B1. - const uint8_t dir = tu_edpt_dir(ep->ep_addr); + const uint8_t dir = (uint8_t)tu_edpt_dir(ep->ep_addr); const uint8_t epnum = tu_edpt_number(ep->ep_addr); const uint32_t abort_mask = TU_BIT((epnum << 1) | (dir ? 0 : 1)); + if (rp2040_chip_version() >= 2) { usb_hw_set->abort = abort_mask; while ((usb_hw->abort_done & abort_mask) != abort_mask) {} @@ -173,7 +155,7 @@ static void hw_endpoint_abort_xfer(struct hw_endpoint* ep) { } } -static void __tusb_irq_path_func(hw_handle_buff_status)(void) { +static void __tusb_irq_path_func(handle_hw_buff_status)(void) { uint32_t remaining_buffers = usb_hw->buf_status; pico_trace("buf_status = 0x%08lx\r\n", remaining_buffers); uint bit = 1u; @@ -183,12 +165,13 @@ static void __tusb_irq_path_func(hw_handle_buff_status)(void) { usb_hw_clear->buf_status = bit; // IN transfer for even i, OUT transfer for odd i - struct hw_endpoint *ep = hw_endpoint_get(i >> 1u, (i & 1u) ? TUSB_DIR_OUT : TUSB_DIR_IN); + const uint8_t epnum = i >> 1u; + const tusb_dir_t dir = (i & 1u) ? TUSB_DIR_OUT : TUSB_DIR_IN; + hw_endpoint_t *ep = hw_endpoint_get(epnum, dir); - // Continue xfer - bool done = hw_endpoint_xfer_continue(ep); + const bool done = hw_endpoint_xfer_continue(ep); if (done) { - // Notify + // Notify usbd 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); @@ -222,11 +205,11 @@ static void __tusb_irq_path_func(reset_non_control_endpoints)(void) { tu_memclr(hw_endpoints[1], sizeof(hw_endpoints) - 2 * sizeof(hw_endpoint_t)); // reclaim buffer space - next_buffer_ptr = &usb_dpram->epx_data[0]; + hw_buffer_ptr = &usb_dpram->epx_data[0]; } static void __tusb_irq_path_func(dcd_rp2040_irq)(void) { - uint32_t const status = usb_hw->ints; + const uint32_t status = usb_hw->ints; uint32_t handled = 0; if (status & USB_INTF_DEV_SOF_BITS) { @@ -259,7 +242,9 @@ static void __tusb_irq_path_func(dcd_rp2040_irq)(void) { #endif // disable SOF interrupt if it is used for RESUME in remote wakeup - if (!keep_sof_alive && !_sof_enable) usb_hw_clear->inte = USB_INTS_DEV_SOF_BITS; + if (!keep_sof_alive && !_sof_enable) { + usb_hw_clear->inte = USB_INTS_DEV_SOF_BITS; + } dcd_event_sof(0, usb_hw->sof_rd & USB_SOF_RD_BITS, true); } @@ -268,7 +253,7 @@ static void __tusb_irq_path_func(dcd_rp2040_irq)(void) { // before closing the EP, the events will be delivered in same order. if (status & USB_INTS_BUFF_STATUS_BITS) { handled |= USB_INTS_BUFF_STATUS_BITS; - hw_handle_buff_status(); + handle_hw_buff_status(); } if (status & USB_INTS_SETUP_REQ_BITS) { @@ -345,13 +330,6 @@ static void __tusb_irq_path_func(dcd_rp2040_irq)(void) { } } -#define USB_INTS_ERROR_BITS ( \ - USB_INTS_ERROR_DATA_SEQ_BITS | \ - USB_INTS_ERROR_BIT_STUFF_BITS | \ - USB_INTS_ERROR_CRC_BITS | \ - USB_INTS_ERROR_RX_OVERFLOW_BITS | \ - USB_INTS_ERROR_RX_TIMEOUT_BITS) - /*------------------------------------------------------------------*/ /* Controller API *------------------------------------------------------------------*/ @@ -424,12 +402,11 @@ void dcd_int_disable(__unused uint8_t rhport) { irq_set_enabled(USBCTRL_IRQ, false); } -void dcd_set_address(__unused uint8_t rhport, __unused uint8_t dev_addr) { - assert(rhport == 0); - +void dcd_set_address(uint8_t rhport, uint8_t dev_addr) { + (void)dev_addr; // Can't set device address in hardware until status xfer has complete // Send 0len complete response on EP0 IN - hw_endpoint_xfer(0x80, NULL, 0); + dcd_edpt_xfer(rhport, 0x80, NULL, 0, false); } void dcd_remote_wakeup(__unused uint8_t rhport) { @@ -474,7 +451,6 @@ void dcd_sof_enable(uint8_t rhport, bool en) { /*------------------------------------------------------------------*/ /* DCD Endpoint port *------------------------------------------------------------------*/ - void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const* request) { (void) rhport; @@ -496,25 +472,32 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const* desc_edpt) { // New API: Allocate packet buffer used by ISO endpoints // Some MCU need manual packet buffer allocation, we allocate the largest size to avoid clustering bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { - (void) rhport; - struct hw_endpoint* ep = hw_endpoint_get_by_addr(ep_addr); - hw_endpoint_init(ep_addr, largest_packet_size, TUSB_XFER_ISOCHRONOUS); - hw_endpoint_alloc(ep, largest_packet_size); + (void)rhport; + struct hw_endpoint *ep = hw_endpoint_get_by_addr(ep_addr); + hw_endpoint_init(ep, ep_addr, largest_packet_size, TUSB_XFER_ISOCHRONOUS); return true; } // New API: Configure and enable an ISO endpoint according to descriptor -bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) { - (void) rhport; - struct hw_endpoint* ep = hw_endpoint_get_by_addr(ep_desc->bEndpointAddress); +bool dcd_edpt_iso_activate(uint8_t rhport, const tusb_desc_endpoint_t *ep_desc) { + (void)rhport; + const uint8_t epnum = tu_edpt_number(ep_desc->bEndpointAddress); + const tusb_dir_t dir = tu_edpt_dir(ep_desc->bEndpointAddress); + struct hw_endpoint *ep = hw_endpoint_get(epnum, dir); TU_ASSERT(ep->hw_data_buf != NULL); // must be inited and allocated previously if (ep->active) { hw_endpoint_abort_xfer(ep); // abort any pending transfer } - ep->wMaxPacketSize = ep_desc->wMaxPacketSize; - hw_endpoint_enable(ep); + + // Set control register to enable endpoint + io_rw_32 *ctrl_reg = hwep_ctrl_reg_device(ep); + if (ctrl_reg != NULL) { + const uint32_t ctrl_value = EP_CTRL_ENABLE_BITS | ((uint32_t)TUSB_XFER_ISOCHRONOUS << EP_CTRL_BUFFER_TYPE_LSB) | + hw_data_offset(ep->hw_data_buf); + *ctrl_reg = ctrl_value; + } return true; } @@ -525,26 +508,26 @@ void dcd_edpt_close_all(uint8_t rhport) { reset_non_control_endpoints(); } -bool dcd_edpt_xfer(__unused uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes, bool is_isr) { - (void) is_isr; - assert(rhport == 0); - hw_endpoint_xfer(ep_addr, buffer, total_bytes); +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes, bool is_isr) { + (void)rhport; + (void)is_isr; + hw_endpoint_t *ep = hw_endpoint_get_by_addr(ep_addr); + hw_endpoint_xfer_start(ep, buffer, total_bytes); return true; } void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { - (void) rhport; + (void)rhport; + const uint8_t epnum = tu_edpt_number(ep_addr); + const tusb_dir_t dir = tu_edpt_dir(ep_addr); + hw_endpoint_t *ep = hw_endpoint_get(epnum, dir); - if (tu_edpt_number(ep_addr) == 0) { + if (epnum == 0) { // A stall on EP0 has to be armed so it can be cleared on the next setup packet - usb_hw_set->ep_stall_arm = (tu_edpt_dir(ep_addr) == TUSB_DIR_IN) ? USB_EP_STALL_ARM_EP0_IN_BITS - : USB_EP_STALL_ARM_EP0_OUT_BITS; + usb_hw_set->ep_stall_arm = (dir == TUSB_DIR_IN) ? USB_EP_STALL_ARM_EP0_IN_BITS : USB_EP_STALL_ARM_EP0_OUT_BITS; } - struct hw_endpoint* ep = hw_endpoint_get_by_addr(ep_addr); - - // stall and clear current pending buffer - // may need to use EP_ABORT + // stall and clear current pending buffer, may need to use EP_ABORT hwep_buf_ctrl_set(ep, USB_BUF_CTRL_STALL); } diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index 12a2f2d25..5ec84be16 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -122,7 +122,7 @@ static void __tusb_irq_path_func(hw_handle_buff_status)(void) remaining_buffers &= ~bit; struct hw_endpoint * ep = &epx; - uint32_t ep_ctrl = *hwep_ctrl_reg(ep); + uint32_t ep_ctrl = *hwep_ctrl_reg_host(ep); if ( ep_ctrl & EP_CTRL_DOUBLE_BUFFERED_BITS ) { TU_LOG(3, "Double Buffered: "); @@ -316,9 +316,6 @@ static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t dev_addr, uint8_t ep->ep_addr = ep_addr; ep->dev_addr = dev_addr; - // For host, IN to host == RX, anything else rx == false - ep->rx = (dir == TUSB_DIR_IN); - // Response to a setup packet on EP0 starts with pid of 1 ep->next_pid = (num == 0 ? 1u : 0u); ep->wMaxPacketSize = wMaxPacketSize; @@ -339,7 +336,7 @@ static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t dev_addr, uint8_t { ep_reg |= (uint32_t) ((bmInterval - 1) << EP_CTRL_HOST_INTERRUPT_INTERVAL_LSB); } - *hwep_ctrl_reg(ep) = ep_reg; + *hwep_ctrl_reg_host(ep) = ep_reg; // pico_trace("endpoint control (0x%p) <- 0x%lx\n", ep->endpoint_control, ep_reg); ep->configured = true; @@ -465,8 +462,8 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr) { // reset epx if it is currently active with unplugged device if (epx.configured && epx.active && epx.dev_addr == dev_addr) { epx.configured = false; - *hwep_ctrl_reg(&epx) = 0; - *hwep_buf_ctrl_reg(&epx) = 0; + *hwep_ctrl_reg_host(&epx) = 0; + *hwep_buf_ctrl_reg_host(&epx) = 0; hw_endpoint_reset_transfer(&epx); } @@ -481,8 +478,8 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr) { // unconfigure the endpoint ep->configured = false; - *hwep_ctrl_reg(ep) = 0; - *hwep_buf_ctrl_reg(ep) = 0; + *hwep_ctrl_reg_host(ep) = 0; + *hwep_buf_ctrl_reg_host(ep) = 0; hw_endpoint_reset_transfer(ep); } } diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index 61f978b0d..8e7bf2dae 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -35,20 +35,15 @@ //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF PROTOTYPE //--------------------------------------------------------------------+ -static void _hw_endpoint_xfer_sync(struct hw_endpoint* ep); +static void hwep_xfer_sync(hw_endpoint_t *ep); -#if TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX - static bool e15_is_bulkin_ep(struct hw_endpoint* ep); - static bool e15_is_critical_frame_period(struct hw_endpoint* ep); -#else - #define e15_is_bulkin_ep(x) (false) - #define e15_is_critical_frame_period(x) (false) -#endif - -// if usb hardware is in host mode -TU_ATTR_ALWAYS_INLINE static inline bool is_host_mode(void) { - return (usb_hw->main_ctrl & USB_MAIN_CTRL_HOST_NDEVICE_BITS) ? true : false; -} + #if TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX +static bool e15_is_bulkin_ep(struct hw_endpoint *ep); +static bool e15_is_critical_frame_period(struct hw_endpoint *ep); + #else + #define e15_is_bulkin_ep(x) (false) + #define e15_is_critical_frame_period(x) (false) + #endif //--------------------------------------------------------------------+ // Implementation @@ -94,8 +89,18 @@ void __tusb_irq_path_func(hw_endpoint_reset_transfer)(struct hw_endpoint* ep) { } void __tusb_irq_path_func(hwep_buf_ctrl_update)(struct hw_endpoint *ep, uint32_t and_mask, uint32_t or_mask) { + const bool is_host = rp2usb_is_host_mode(); uint32_t value = 0; - io_rw_32 *buf_ctrl = hwep_buf_ctrl_reg(ep); + io_rw_32 *buf_ctrl; + + #if CFG_TUH_ENABLED + if (is_host) { + buf_ctrl = hwep_buf_ctrl_reg_host(ep); + } else + #endif + { + buf_ctrl = hwep_buf_ctrl_reg_device(ep); + } if (and_mask) { value = *buf_ctrl & and_mask; @@ -110,7 +115,7 @@ void __tusb_irq_path_func(hwep_buf_ctrl_update)(struct hw_endpoint *ep, uint32_t *buf_ctrl = value & ~USB_BUF_CTRL_AVAIL; // 4.1.2.5.1 Con-current access: 12 cycles (should be good for 48*12Mhz = 576Mhz) after write to buffer control // Don't need delay in host mode as host is in charge - if (!is_host_mode()) { + if (!is_host) { busy_wait_at_least_cycles(12); } } @@ -119,9 +124,9 @@ void __tusb_irq_path_func(hwep_buf_ctrl_update)(struct hw_endpoint *ep, uint32_t *buf_ctrl = value; } -// prepare buffer, return buffer control -static uint32_t __tusb_irq_path_func(prepare_ep_buffer)(struct hw_endpoint* ep, uint8_t buf_id) { - uint16_t const buflen = tu_min16(ep->remaining_len, ep->wMaxPacketSize); +// prepare buffer, move data if tx, return buffer control +static uint32_t __tusb_irq_path_func(prepare_ep_buffer)(struct hw_endpoint *ep, uint8_t buf_id, bool is_rx) { + const uint16_t buflen = tu_min16(ep->remaining_len, ep->wMaxPacketSize); ep->remaining_len = (uint16_t) (ep->remaining_len - buflen); uint32_t buf_ctrl = buflen | USB_BUF_CTRL_AVAIL; @@ -130,7 +135,7 @@ static uint32_t __tusb_irq_path_func(prepare_ep_buffer)(struct hw_endpoint* ep, buf_ctrl |= ep->next_pid ? USB_BUF_CTRL_DATA1_PID : USB_BUF_CTRL_DATA0_PID; ep->next_pid ^= 1u; - if (!ep->rx) { + if (!is_rx) { // Copy data from user buffer to hw buffer unaligned_memcpy(ep->hw_data_buf + buf_id * 64, ep->user_buf, buflen); ep->user_buf += buflen; @@ -146,44 +151,66 @@ static uint32_t __tusb_irq_path_func(prepare_ep_buffer)(struct hw_endpoint* ep, buf_ctrl |= USB_BUF_CTRL_LAST; } - if (buf_id) buf_ctrl = buf_ctrl << 16; + if (buf_id) { + buf_ctrl = buf_ctrl << 16; + } return buf_ctrl; } // Prepare buffer control register value void __tusb_irq_path_func(hw_endpoint_start_next_buffer)(struct hw_endpoint* ep) { - io_rw_32 *ep_ctrl_reg = hwep_ctrl_reg(ep); - uint32_t ep_ctrl = *ep_ctrl_reg; + const tusb_dir_t dir = tu_edpt_dir(ep->ep_addr); + bool is_rx; + + io_rw_32 *ep_ctrl_reg; + // io_rw_32 *buf_ctrl_reg; + + #if CFG_TUH_ENABLED + const bool is_host = rp2usb_is_host_mode(); + if (is_host) { + // buf_ctrl_reg = hwep_buf_ctrl_reg_host(ep); + ep_ctrl_reg = hwep_ctrl_reg_host(ep); + is_rx = (dir == TUSB_DIR_IN); + } else + #endif + { + // buf_ctrl_reg = hwep_buf_ctrl_reg_device(ep); + ep_ctrl_reg = hwep_ctrl_reg_device(ep); + is_rx = (dir == TUSB_DIR_OUT); + } // always compute and start with buffer 0 - uint32_t buf_ctrl = prepare_ep_buffer(ep, 0) | USB_BUF_CTRL_SEL; - - // For now: skip double buffered for OUT endpoint in Device mode, since - // host could send < 64 bytes and cause short packet on buffer0 - // NOTE: this could happen to Host mode IN endpoint - // Also, Host mode "interrupt" endpoint hardware is only single buffered, - // NOTE2: Currently Host bulk is implemented using "interrupt" endpoint - bool const is_host = is_host_mode(); - bool const force_single = (!is_host && !tu_edpt_dir(ep->ep_addr)) || - (is_host && tu_edpt_number(ep->ep_addr) != 0); - - if (ep->remaining_len && !force_single) { - // Use buffer 1 (double buffered) if there is still data - // TODO: Isochronous for buffer1 bit-field is different than CBI (control bulk, interrupt) - - buf_ctrl |= prepare_ep_buffer(ep, 1); - - // Set endpoint control double buffered bit if needed - ep_ctrl &= ~EP_CTRL_INTERRUPT_PER_BUFFER; - ep_ctrl |= EP_CTRL_DOUBLE_BUFFERED_BITS | EP_CTRL_INTERRUPT_PER_DOUBLE_BUFFER; - } else { - // Single buffered since 1 is enough - ep_ctrl &= ~(EP_CTRL_DOUBLE_BUFFERED_BITS | EP_CTRL_INTERRUPT_PER_DOUBLE_BUFFER); - ep_ctrl |= EP_CTRL_INTERRUPT_PER_BUFFER; - } + uint32_t buf_ctrl = prepare_ep_buffer(ep, 0, is_rx) | USB_BUF_CTRL_SEL; + + // EP0 has no endpoint control register, also usbd only schedule 1 packet at a time (single buffer) + if (ep_ctrl_reg != NULL) { + uint32_t ep_ctrl = *ep_ctrl_reg; + + // For now: skip double buffered for RX e.g OUT endpoint in Device mode, since host could send < 64 bytes and cause + // short packet on buffer0 + // NOTE: this could happen to Host mode IN endpoint Also, Host mode "interrupt" endpoint hardware is only single + // buffered, + // NOTE2: Currently Host bulk is implemented using "interrupt" endpoint + const bool force_single = is_rx; - *ep_ctrl_reg = ep_ctrl; + if (ep->remaining_len && !force_single) { + // Use buffer 1 (double buffered) if there is still data + // TODO: Isochronous for buffer1 bit-field is different than CBI (control bulk, interrupt) + + buf_ctrl |= prepare_ep_buffer(ep, 1, is_rx); + + // Set endpoint control double buffered bit if needed + ep_ctrl &= ~EP_CTRL_INTERRUPT_PER_BUFFER; + ep_ctrl |= EP_CTRL_DOUBLE_BUFFERED_BITS | EP_CTRL_INTERRUPT_PER_DOUBLE_BUFFER; + } else { + // Single buffered since 1 is enough + ep_ctrl &= ~(EP_CTRL_DOUBLE_BUFFERED_BITS | EP_CTRL_INTERRUPT_PER_DOUBLE_BUFFER); + ep_ctrl |= EP_CTRL_INTERRUPT_PER_BUFFER; + } + + *ep_ctrl_reg = ep_ctrl; + } TU_LOG(3, " Prepare BufCtrl: [0] = 0x%04x [1] = 0x%04x\r\n", tu_u32_low16(buf_ctrl), tu_u32_high16(buf_ctrl)); @@ -221,13 +248,16 @@ void hw_endpoint_xfer_start(struct hw_endpoint* ep, uint8_t* buffer, uint16_t to } // sync endpoint buffer and return transferred bytes -static uint16_t __tusb_irq_path_func(sync_ep_buffer)(struct hw_endpoint* ep, uint8_t buf_id) { - uint32_t buf_ctrl = hwep_buf_ctrl_get(ep); - if (buf_id) buf_ctrl = buf_ctrl >> 16; +static uint16_t __tusb_irq_path_func(sync_ep_buffer)(hw_endpoint_t *ep, io_rw_32 *buf_ctrl_reg, uint8_t buf_id, + bool is_rx) { + uint32_t buf_ctrl = *buf_ctrl_reg; + if (buf_id) { + buf_ctrl = buf_ctrl >> 16; + } - uint16_t xferred_bytes = buf_ctrl & USB_BUF_CTRL_LEN_MASK; + const uint16_t xferred_bytes = buf_ctrl & USB_BUF_CTRL_LEN_MASK; - if (!ep->rx) { + if (!is_rx) { // We are continuing a transfer here. If we are TX, we have successfully // sent some data can increase the length we have sent assert(!(buf_ctrl & USB_BUF_CTRL_FULL)); @@ -245,7 +275,6 @@ static uint16_t __tusb_irq_path_func(sync_ep_buffer)(struct hw_endpoint* ep, uin // Short packet if (xferred_bytes < ep->wMaxPacketSize) { - pico_trace(" Short packet on buffer %d with %u bytes\r\n", buf_id, xferred_bytes); // Reduce total length as this is last packet ep->remaining_len = 0; } @@ -253,21 +282,38 @@ static uint16_t __tusb_irq_path_func(sync_ep_buffer)(struct hw_endpoint* ep, uin return xferred_bytes; } -static void __tusb_irq_path_func(_hw_endpoint_xfer_sync)(struct hw_endpoint* ep) { - // Update hw endpoint struct with info from hardware - // after a buff status interrupt - - uint32_t __unused buf_ctrl = hwep_buf_ctrl_get(ep); - TU_LOG(3, " Sync BufCtrl: [0] = 0x%04x [1] = 0x%04x\r\n", tu_u32_low16(buf_ctrl), tu_u32_high16(buf_ctrl)); +// Update hw endpoint struct with info from hardware after a buff status interrupt +static void __tusb_irq_path_func(hwep_xfer_sync)(hw_endpoint_t *ep) { + // const uint8_t ep_num = tu_edpt_number(ep->ep_addr); + const tusb_dir_t dir = tu_edpt_dir(ep->ep_addr); + + io_rw_32 *buf_ctrl_reg; + io_rw_32 *ep_ctrl_reg; + bool is_rx; + + #if CFG_TUH_ENABLED + const bool is_host = rp2usb_is_host_mode(); + if (is_host) { + buf_ctrl_reg = hwep_buf_ctrl_reg_host(ep); + ep_ctrl_reg = hwep_ctrl_reg_host(ep); + is_rx = (dir == TUSB_DIR_IN); + } else + #endif + { + buf_ctrl_reg = hwep_buf_ctrl_reg_device(ep); + ep_ctrl_reg = hwep_ctrl_reg_device(ep); + is_rx = (dir == TUSB_DIR_OUT); + } - // always sync buffer 0 - uint16_t buf0_bytes = sync_ep_buffer(ep, 0); + TU_LOG(3, " Sync BufCtrl: [0] = 0x%04x [1] = 0x%04x\r\n", tu_u32_low16(*buf_ctrl_reg), + tu_u32_high16(*buf_ctrl_reg)); + uint16_t buf0_bytes = sync_ep_buffer(ep, buf_ctrl_reg, 0, is_rx); // always sync buffer 0 // sync buffer 1 if double buffered - if ((*hwep_ctrl_reg(ep)) & EP_CTRL_DOUBLE_BUFFERED_BITS) { + if (ep_ctrl_reg != NULL && (*ep_ctrl_reg) & EP_CTRL_DOUBLE_BUFFERED_BITS) { if (buf0_bytes == ep->wMaxPacketSize) { // sync buffer 1 if not short packet - sync_ep_buffer(ep, 1); + sync_ep_buffer(ep, buf_ctrl_reg, 1, is_rx); } else { // short packet on buffer 0 // TODO couldn't figure out how to handle this case which happen with net_lwip_webserver example @@ -309,7 +355,7 @@ bool __tusb_irq_path_func(hw_endpoint_xfer_continue)(struct hw_endpoint* ep) { } // Update EP struct from hardware state - _hw_endpoint_xfer_sync(ep); + hwep_xfer_sync(ep); // Now we have synced our state with the hardware. Is there more data to transfer? // If we are done then notify tinyusb @@ -336,6 +382,7 @@ bool __tusb_irq_path_func(hw_endpoint_xfer_continue)(struct hw_endpoint* ep) { //--------------------------------------------------------------------+ #if TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX +// E15 is fixed with RP2350 /* Don't mark IN buffers as available during the last 200us of a full-speed frame. This avoids a situation seen with the USB2.0 hub on a Raspberry @@ -356,9 +403,8 @@ bool __tusb_irq_path_func(hw_endpoint_xfer_continue)(struct hw_endpoint* ep) { volatile uint32_t e15_last_sof = 0; // check if Errata 15 is needed for this endpoint i.e device bulk-in -static bool __tusb_irq_path_func(e15_is_bulkin_ep)(struct hw_endpoint* ep) { - return (!is_host_mode() && tu_edpt_dir(ep->ep_addr) == TUSB_DIR_IN && - ep->transfer_type == TUSB_XFER_BULK); +static bool __tusb_irq_path_func(e15_is_bulkin_ep)(struct hw_endpoint *ep) { + return (!rp2usb_is_host_mode() && tu_edpt_dir(ep->ep_addr) == TUSB_DIR_IN && ep->transfer_type == TUSB_XFER_BULK); } // check if we need to apply Errata 15 workaround : i.e diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.h b/src/portable/raspberrypi/rp2040/rp2040_usb.h index 603640c6d..2ec00694e 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.h +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.h @@ -48,10 +48,6 @@ typedef struct hw_endpoint // Is this a valid struct bool configured; - // Transfer direction (i.e. IN is rx for host but tx for device) - // allows us to common up transfer functions - bool rx; - uint8_t ep_addr; uint8_t next_pid; @@ -115,61 +111,46 @@ TU_ATTR_ALWAYS_INLINE static inline void hw_endpoint_lock_update(__unused struct // sense to have worker and IRQ on same core, however I think using critsec is about equivalent. } -TU_ATTR_ALWAYS_INLINE static inline io_rw_32 *hwep_ctrl_reg(struct hw_endpoint *ep) { - (void)ep; -#if CFG_TUH_ENABLED - if (rp2usb_is_host_mode()) { - if (ep->transfer_type == TUSB_XFER_CONTROL) { - return &usbh_dpram->epx_ctrl; - } - return &usbh_dpram->int_ep_ctrl[ep->interrupt_num].ctrl; +// #if CFG_TUD_ENABLED +TU_ATTR_ALWAYS_INLINE static inline io_rw_32 *hwep_ctrl_reg_device(struct hw_endpoint *ep) { + uint8_t const epnum = tu_edpt_number(ep->ep_addr); + const uint8_t dir = (uint8_t)tu_edpt_dir(ep->ep_addr); + if (epnum == 0) { + // EP0 has no endpoint control register because the buffer offsets are fixed and always enabled + return NULL; } -#endif - -#if CFG_TUD_ENABLED - if (!rp2usb_is_host_mode()) { - const uint8_t num = tu_edpt_number(ep->ep_addr); - if (num == 0) { - return NULL; - } - return (tu_edpt_dir(ep->ep_addr) == TUSB_DIR_IN) ? &usb_dpram->ep_ctrl[num - 1].in - : &usb_dpram->ep_ctrl[num - 1].out; - } -#endif + return (dir == TUSB_DIR_IN) ? &usb_dpram->ep_ctrl[epnum - 1].in : &usb_dpram->ep_ctrl[epnum - 1].out; +} - return NULL; +TU_ATTR_ALWAYS_INLINE static inline io_rw_32 *hwep_buf_ctrl_reg_device(struct hw_endpoint *ep) { + const uint8_t epnum = tu_edpt_number(ep->ep_addr); + const uint8_t dir = (uint8_t)tu_edpt_dir(ep->ep_addr); + return (dir == TUSB_DIR_IN) ? &usb_dpram->ep_buf_ctrl[epnum].in : &usb_dpram->ep_buf_ctrl[epnum].out; } +// #endif -TU_ATTR_ALWAYS_INLINE static inline io_rw_32 *hwep_buf_ctrl_reg(struct hw_endpoint *ep) { - (void)ep; #if CFG_TUH_ENABLED - if (rp2usb_is_host_mode()) { - if (ep->transfer_type == TUSB_XFER_CONTROL) { - return &usbh_dpram->epx_buf_ctrl; - } - return &usbh_dpram->int_ep_buffer_ctrl[ep->interrupt_num].ctrl; +TU_ATTR_ALWAYS_INLINE static inline io_rw_32 *hwep_ctrl_reg_host(struct hw_endpoint *ep) { + if (ep->transfer_type == TUSB_XFER_CONTROL) { + return &usbh_dpram->epx_ctrl; } -#endif + return &usbh_dpram->int_ep_ctrl[ep->interrupt_num].ctrl; +} -#if CFG_TUD_ENABLED - if (!rp2usb_is_host_mode()) { - const uint8_t num = tu_edpt_number(ep->ep_addr); - return (tu_edpt_dir(ep->ep_addr) == TUSB_DIR_IN) ? &usb_dpram->ep_buf_ctrl[num].in - : &usb_dpram->ep_buf_ctrl[num].out; +TU_ATTR_ALWAYS_INLINE static inline io_rw_32 *hwep_buf_ctrl_reg_host(struct hw_endpoint *ep) { + if (ep->transfer_type == TUSB_XFER_CONTROL) { + return &usbh_dpram->epx_buf_ctrl; } -#endif - return NULL; + return &usbh_dpram->int_ep_buffer_ctrl[ep->interrupt_num].ctrl; } +#endif + //--------------------------------------------------------------------+ // //--------------------------------------------------------------------+ void hwep_buf_ctrl_update(struct hw_endpoint *ep, uint32_t and_mask, uint32_t or_mask); -TU_ATTR_ALWAYS_INLINE static inline uint32_t hwep_buf_ctrl_get(struct hw_endpoint *ep) { - return *hwep_buf_ctrl_reg(ep); -} - TU_ATTR_ALWAYS_INLINE static inline void hwep_buf_ctrl_set(struct hw_endpoint *ep, uint32_t value) { hwep_buf_ctrl_update(ep, 0, value); } -- cgit v1.3.1 From f0a3d448347047c9df62518fbd641502b2d55333 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 8 Jan 2026 00:54:21 +0700 Subject: change signature for hwep_buf_ctrl_* to take pointer to buf control instead of hwep --- src/portable/raspberrypi/rp2040/dcd_rp2040.c | 16 ++++----- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 6 ---- src/portable/raspberrypi/rp2040/rp2040_usb.c | 42 ++++++++++------------- src/portable/raspberrypi/rp2040/rp2040_usb.h | 50 ++++++++++------------------ 4 files changed, 42 insertions(+), 72 deletions(-) (limited to 'src/portable') diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index 6c74029d8..5c21590c4 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -87,13 +87,6 @@ static void hw_endpoint_init(hw_endpoint_t *ep, uint8_t ep_addr, uint16_t wMaxPa // Buffer offset is fixed (also double buffered) ep->hw_data_buf = (uint8_t*) &usb_dpram->ep0_buf_a[0]; } else { - // Set the endpoint control register (starts at EP1, hence num-1) - // if (dir == TUSB_DIR_IN) { - // ep->endpoint_control = &usb_dpram->ep_ctrl[num - 1].in; - // } else { - // ep->endpoint_control = &usb_dpram->ep_ctrl[num - 1].out; - // } - // round up size to multiple of 64 uint16_t size = (uint16_t)tu_round_up(wMaxPacketSize, 64); @@ -146,7 +139,8 @@ static void hw_endpoint_abort_xfer(struct hw_endpoint* ep) { buf_ctrl |= USB_BUF_CTRL_DATA1_PID; } - hwep_buf_ctrl_set(ep, buf_ctrl); + io_rw_32 *buf_ctrl_reg = hwep_buf_ctrl_reg_device(ep); + hwep_buf_ctrl_set(buf_ctrl_reg, buf_ctrl); hw_endpoint_reset_transfer(ep); if (rp2040_chip_version() >= 2) { @@ -528,7 +522,8 @@ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { } // stall and clear current pending buffer, may need to use EP_ABORT - hwep_buf_ctrl_set(ep, USB_BUF_CTRL_STALL); + io_rw_32 *buf_ctrl_reg = hwep_buf_ctrl_reg_device(ep); + hwep_buf_ctrl_set(buf_ctrl_reg, USB_BUF_CTRL_STALL); } void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { @@ -539,7 +534,8 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { // clear stall also reset toggle to DATA0, ready for next transfer ep->next_pid = 0; - hwep_buf_ctrl_clear_mask(ep, USB_BUF_CTRL_STALL); + io_rw_32 *buf_ctrl_reg = hwep_buf_ctrl_reg_device(ep); + hwep_buf_ctrl_clear_mask(buf_ctrl_reg, USB_BUF_CTRL_STALL); } } diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index 5ec84be16..2e5f0fe1f 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -284,8 +284,6 @@ static struct hw_endpoint *_hw_endpoint_allocate(uint8_t transfer_type) ep = _next_free_interrupt_ep(); pico_info("Allocate %s ep %d\n", tu_edpt_type_str(transfer_type), ep->interrupt_num); assert(ep); - // ep->buffer_control = &usbh_dpram->int_ep_buffer_ctrl[ep->interrupt_num].ctrl; - // ep->endpoint_control = &usbh_dpram->int_ep_ctrl[ep->interrupt_num].ctrl; // 0 for epx (double buffered): TODO increase to 1024 for ISO // 2x64 for intep0 // 3x64 for intep1 @@ -295,8 +293,6 @@ static struct hw_endpoint *_hw_endpoint_allocate(uint8_t transfer_type) else { ep = &epx; - // ep->buffer_control = &usbh_dpram->epx_buf_ctrl; - // ep->endpoint_control = &usbh_dpram->epx_ctrl; ep->hw_data_buf = &usbh_dpram->epx_data[0]; } @@ -306,8 +302,6 @@ static struct hw_endpoint *_hw_endpoint_allocate(uint8_t transfer_type) static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t dev_addr, uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t transfer_type, uint8_t bmInterval) { // Already has data buffer, endpoint control, and buffer control allocated at this point - // assert(ep->endpoint_control); - // assert(ep->buffer_control); assert(ep->hw_data_buf); uint8_t const num = tu_edpt_number(ep_addr); diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index 8e7bf2dae..5258b9705 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -88,32 +88,25 @@ void __tusb_irq_path_func(hw_endpoint_reset_transfer)(struct hw_endpoint* ep) { ep->user_buf = 0; } -void __tusb_irq_path_func(hwep_buf_ctrl_update)(struct hw_endpoint *ep, uint32_t and_mask, uint32_t or_mask) { +void __tusb_irq_path_func(hwep_buf_ctrl_update)(io_rw_32 *buf_ctrl_reg, uint32_t and_mask, uint32_t or_mask) { const bool is_host = rp2usb_is_host_mode(); - uint32_t value = 0; - io_rw_32 *buf_ctrl; - - #if CFG_TUH_ENABLED - if (is_host) { - buf_ctrl = hwep_buf_ctrl_reg_host(ep); - } else - #endif - { - buf_ctrl = hwep_buf_ctrl_reg_device(ep); - } + uint32_t value = 0; + uint32_t buf_ctrl = *buf_ctrl_reg; if (and_mask) { - value = *buf_ctrl & and_mask; + value = buf_ctrl & and_mask; } if (or_mask) { value |= or_mask; if (or_mask & USB_BUF_CTRL_AVAIL) { - if (*buf_ctrl & USB_BUF_CTRL_AVAIL) { - panic("ep %02X was already available", ep->ep_addr); + if (buf_ctrl & USB_BUF_CTRL_AVAIL) { + panic("buf_ctrl @%lX already available", (uintptr_t)buf_ctrl_reg); } - *buf_ctrl = value & ~USB_BUF_CTRL_AVAIL; - // 4.1.2.5.1 Con-current access: 12 cycles (should be good for 48*12Mhz = 576Mhz) after write to buffer control + *buf_ctrl_reg = value & ~USB_BUF_CTRL_AVAIL; + + // Section 4.1.2.7.1 (rp2040) / 12.7.3.7.1 (rp2350) Concurrent access: after write to buffer control, we need to + // wait at least 1/48 mhz (usb clock), 12 cycles should be good for 48*12Mhz = 576Mhz. // Don't need delay in host mode as host is in charge if (!is_host) { busy_wait_at_least_cycles(12); @@ -121,7 +114,7 @@ void __tusb_irq_path_func(hwep_buf_ctrl_update)(struct hw_endpoint *ep, uint32_t } } - *buf_ctrl = value; + *buf_ctrl_reg = value; } // prepare buffer, move data if tx, return buffer control @@ -161,21 +154,21 @@ static uint32_t __tusb_irq_path_func(prepare_ep_buffer)(struct hw_endpoint *ep, // Prepare buffer control register value void __tusb_irq_path_func(hw_endpoint_start_next_buffer)(struct hw_endpoint* ep) { const tusb_dir_t dir = tu_edpt_dir(ep->ep_addr); - bool is_rx; + bool is_rx; io_rw_32 *ep_ctrl_reg; - // io_rw_32 *buf_ctrl_reg; + io_rw_32 *buf_ctrl_reg; #if CFG_TUH_ENABLED const bool is_host = rp2usb_is_host_mode(); if (is_host) { - // buf_ctrl_reg = hwep_buf_ctrl_reg_host(ep); + buf_ctrl_reg = hwep_buf_ctrl_reg_host(ep); ep_ctrl_reg = hwep_ctrl_reg_host(ep); is_rx = (dir == TUSB_DIR_IN); } else #endif { - // buf_ctrl_reg = hwep_buf_ctrl_reg_device(ep); + buf_ctrl_reg = hwep_buf_ctrl_reg_device(ep); ep_ctrl_reg = hwep_ctrl_reg_device(ep); is_rx = (dir == TUSB_DIR_OUT); } @@ -216,7 +209,7 @@ void __tusb_irq_path_func(hw_endpoint_start_next_buffer)(struct hw_endpoint* ep) // Finally, write to buffer_control which will trigger the transfer // the next time the controller polls this dpram address - hwep_buf_ctrl_set(ep, buf_ctrl); + hwep_buf_ctrl_set(buf_ctrl_reg, buf_ctrl); } void hw_endpoint_xfer_start(struct hw_endpoint* ep, uint8_t* buffer, uint16_t total_len) { @@ -334,7 +327,8 @@ static void __tusb_irq_path_func(hwep_xfer_sync)(hw_endpoint_t *ep) { ep_ctrl &= ~(EP_CTRL_DOUBLE_BUFFERED_BITS | EP_CTRL_INTERRUPT_PER_DOUBLE_BUFFER); ep_ctrl |= EP_CTRL_INTERRUPT_PER_BUFFER; - hwep_buf_ctrl_set(ep, 0); + io_rw_32 *buf_ctrl_reg = is_host ? hwep_buf_ctrl_reg_host(ep) : hwep_buf_ctrl_reg_device(ep); + hwep_buf_ctrl_set(buf_ctrl_reg, 0); usb_hw->abort &= ~TU_BIT(ep_id); diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.h b/src/portable/raspberrypi/rp2040/rp2040_usb.h index 2ec00694e..e9fed73de 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.h +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.h @@ -45,41 +45,27 @@ // Hardware information per endpoint typedef struct hw_endpoint { - // Is this a valid struct - bool configured; - uint8_t ep_addr; uint8_t next_pid; + // Interrupt, bulk, etc + uint8_t transfer_type; - // Endpoint control register - // io_rw_32 *endpoint_control; - - // Buffer control register - // io_rw_32 *buffer_control; + bool active; // Endpoint is in use + uint8_t pending; // Transfer scheduled but not active - // Buffer pointer in usb dpram - uint8_t *hw_data_buf; + uint16_t wMaxPacketSize; - // User buffer in main memory - uint8_t *user_buf; + uint8_t *hw_data_buf; // Buffer pointer in usb dpram + uint8_t *user_buf; // User buffer in main memory // Current transfer information uint16_t remaining_len; uint16_t xferred_len; - // Data needed from EP descriptor - uint16_t wMaxPacketSize; - - // Endpoint is in use - bool active; - - // Interrupt, bulk, etc - uint8_t transfer_type; - - // Transfer scheduled but not active - uint8_t pending; - #if CFG_TUH_ENABLED + // Is this a valid struct + bool configured; + // Only needed for host uint8_t dev_addr; @@ -131,7 +117,7 @@ TU_ATTR_ALWAYS_INLINE static inline io_rw_32 *hwep_buf_ctrl_reg_device(struct hw #if CFG_TUH_ENABLED TU_ATTR_ALWAYS_INLINE static inline io_rw_32 *hwep_ctrl_reg_host(struct hw_endpoint *ep) { - if (ep->transfer_type == TUSB_XFER_CONTROL) { + if (tu_edpt_number(ep->ep_addr) == 0) { return &usbh_dpram->epx_ctrl; } return &usbh_dpram->int_ep_ctrl[ep->interrupt_num].ctrl; @@ -149,18 +135,18 @@ TU_ATTR_ALWAYS_INLINE static inline io_rw_32 *hwep_buf_ctrl_reg_host(struct hw_e //--------------------------------------------------------------------+ // //--------------------------------------------------------------------+ -void hwep_buf_ctrl_update(struct hw_endpoint *ep, uint32_t and_mask, uint32_t or_mask); +void hwep_buf_ctrl_update(io_rw_32 *buf_ctrl_reg, uint32_t and_mask, uint32_t or_mask); -TU_ATTR_ALWAYS_INLINE static inline void hwep_buf_ctrl_set(struct hw_endpoint *ep, uint32_t value) { - hwep_buf_ctrl_update(ep, 0, value); +TU_ATTR_ALWAYS_INLINE static inline void hwep_buf_ctrl_set(io_rw_32 *buf_ctrl_reg, uint32_t value) { + hwep_buf_ctrl_update(buf_ctrl_reg, 0, value); } -TU_ATTR_ALWAYS_INLINE static inline void hwep_buf_ctrl_set_mask32(struct hw_endpoint *ep, uint32_t value) { - hwep_buf_ctrl_update(ep, ~value, value); +TU_ATTR_ALWAYS_INLINE static inline void hwep_buf_ctrl_set_mask(io_rw_32 *buf_ctrl_reg, uint32_t value) { + hwep_buf_ctrl_update(buf_ctrl_reg, ~value, value); } -TU_ATTR_ALWAYS_INLINE static inline void hwep_buf_ctrl_clear_mask(struct hw_endpoint *ep, uint32_t value) { - hwep_buf_ctrl_update(ep, ~value, 0); +TU_ATTR_ALWAYS_INLINE static inline void hwep_buf_ctrl_clear_mask(io_rw_32 *buf_ctrl_reg, uint32_t value) { + hwep_buf_ctrl_update(buf_ctrl_reg, ~value, 0); } static inline uintptr_t hw_data_offset(uint8_t *buf) { -- cgit v1.3.1 From 07416f704f1a55b286d5c9b082e6f1e3e51ce9b0 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 8 Jan 2026 11:33:08 +0700 Subject: minor clean up --- src/portable/raspberrypi/rp2040/dcd_rp2040.c | 68 +++++++++++++--------------- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 31 ++++++------- src/portable/raspberrypi/rp2040/rp2040_usb.c | 26 +++++------ src/portable/raspberrypi/rp2040/rp2040_usb.h | 34 +++++++------- 4 files changed, 77 insertions(+), 82 deletions(-) (limited to 'src/portable') diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index 5c21590c4..952245cb1 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -71,18 +71,17 @@ TU_ATTR_ALWAYS_INLINE static inline hw_endpoint_t *hw_endpoint_get_by_addr(uint8 // main processing for dcd_edpt_iso_activate static void hw_endpoint_init(hw_endpoint_t *ep, uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t transfer_type) { - const uint8_t epnum = tu_edpt_number(ep_addr); - ep->ep_addr = ep_addr; ep->next_pid = 0u; ep->wMaxPacketSize = wMaxPacketSize; ep->transfer_type = transfer_type; // Clear existing buffer control state - io_rw_32 *buf_ctrl_reg = hwep_buf_ctrl_reg_device(ep); + io_rw_32 *buf_ctrl_reg = hwbuf_ctrl_reg_device(ep); *buf_ctrl_reg = 0; // allocated hw buffer + const uint8_t epnum = tu_edpt_number(ep_addr); if (epnum == 0) { // Buffer offset is fixed (also double buffered) ep->hw_data_buf = (uint8_t*) &usb_dpram->ep0_buf_a[0]; @@ -104,16 +103,9 @@ static void hw_endpoint_init(hw_endpoint_t *ep, uint8_t ep_addr, uint16_t wMaxPa } } -// Init, allocate buffer and enable endpoint -static void hw_endpoint_open(uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t transfer_type) { - const uint8_t epnum = tu_edpt_number(ep_addr); - const tusb_dir_t dir = tu_edpt_dir(ep_addr); - hw_endpoint_t *ep = hw_endpoint_get(epnum, dir); - - hw_endpoint_init(ep, ep_addr, wMaxPacketSize, transfer_type); - - // Set endpoint control register to enable (EP0 has no endpoint control register) +static void hw_endpoint_enable(hw_endpoint_t *ep, uint8_t transfer_type) { io_rw_32 *ctrl_reg = hwep_ctrl_reg_device(ep); + // Set endpoint control register to enable (EP0 has no endpoint control register) if (ctrl_reg != NULL) { const uint32_t ctrl_value = EP_CTRL_ENABLE_BITS | ((uint32_t)transfer_type << EP_CTRL_BUFFER_TYPE_LSB) | hw_data_offset(ep->hw_data_buf); @@ -121,14 +113,24 @@ static void hw_endpoint_open(uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t t } } +// Init and enable endpoint +static void hw_endpoint_open(uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t transfer_type) { + const uint8_t epnum = tu_edpt_number(ep_addr); + const tusb_dir_t dir = tu_edpt_dir(ep_addr); + hw_endpoint_t *ep = hw_endpoint_get(epnum, dir); + + hw_endpoint_init(ep, ep_addr, wMaxPacketSize, transfer_type); + hw_endpoint_enable(ep, transfer_type); +} + static void hw_endpoint_abort_xfer(struct hw_endpoint* ep) { // Abort any pending transfer - // Due to Errata RP2040-E2: ABORT flag is only applicable for B2 and later (unusable for B0, B1). - // Which means we are not guaranteed to safely abort pending transfer on B0 and B1. const uint8_t dir = (uint8_t)tu_edpt_dir(ep->ep_addr); - const uint8_t epnum = tu_edpt_number(ep->ep_addr); + const uint8_t epnum = tu_edpt_number(ep->ep_addr); const uint32_t abort_mask = TU_BIT((epnum << 1) | (dir ? 0 : 1)); + // Due to Errata RP2040-E2: ABORT flag is only applicable for B2 and later (unusable for B0, B1). + // Which means we are not guaranteed to safely abort pending transfer on B0 and B1. if (rp2040_chip_version() >= 2) { usb_hw_set->abort = abort_mask; while ((usb_hw->abort_done & abort_mask) != abort_mask) {} @@ -139,8 +141,8 @@ static void hw_endpoint_abort_xfer(struct hw_endpoint* ep) { buf_ctrl |= USB_BUF_CTRL_DATA1_PID; } - io_rw_32 *buf_ctrl_reg = hwep_buf_ctrl_reg_device(ep); - hwep_buf_ctrl_set(buf_ctrl_reg, buf_ctrl); + io_rw_32 *buf_ctrl_reg = hwbuf_ctrl_reg_device(ep); + hwbuf_ctrl_set(buf_ctrl_reg, buf_ctrl); hw_endpoint_reset_transfer(ep); if (rp2040_chip_version() >= 2) { @@ -265,15 +267,12 @@ static void __tusb_irq_path_func(dcd_rp2040_irq)(void) { #if FORCE_VBUS_DETECT == 0 // Since we force VBUS detect On, device will always think it is connected and // couldn't distinguish between disconnect and suspend - if (status & USB_INTS_DEV_CONN_DIS_BITS) - { + if (status & USB_INTS_DEV_CONN_DIS_BITS) { handled |= USB_INTS_DEV_CONN_DIS_BITS; - if ( usb_hw->sie_status & USB_SIE_STATUS_CONNECTED_BITS ) - { + if (usb_hw->sie_status & USB_SIE_STATUS_CONNECTED_BITS) { // Connected: nothing to do - }else - { + } else { // Disconnected dcd_event_bus_signal(0, DCD_EVENT_UNPLUGGED, true); } @@ -295,8 +294,10 @@ static void __tusb_irq_path_func(dcd_rp2040_irq)(void) { #if TUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX // Only run enumeration workaround if pull up is enabled - if (usb_hw->sie_ctrl & USB_SIE_CTRL_PULLUP_EN_BITS) rp2040_usb_device_enumeration_fix(); -#endif + if (usb_hw->sie_ctrl & USB_SIE_CTRL_PULLUP_EN_BITS) { + rp2040_usb_device_enumeration_fix(); + } + #endif } /* Note from pico datasheet 4.1.2.6.4 (v1.2) @@ -458,7 +459,6 @@ void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const* req bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const* desc_edpt) { (void) rhport; const uint8_t xfer_type = desc_edpt->bmAttributes.xfer; - TU_VERIFY(xfer_type != TUSB_XFER_ISOCHRONOUS); hw_endpoint_open(desc_edpt->bEndpointAddress, tu_edpt_packet_size(desc_edpt), xfer_type); return true; } @@ -485,13 +485,7 @@ bool dcd_edpt_iso_activate(uint8_t rhport, const tusb_desc_endpoint_t *ep_desc) } ep->wMaxPacketSize = ep_desc->wMaxPacketSize; - // Set control register to enable endpoint - io_rw_32 *ctrl_reg = hwep_ctrl_reg_device(ep); - if (ctrl_reg != NULL) { - const uint32_t ctrl_value = EP_CTRL_ENABLE_BITS | ((uint32_t)TUSB_XFER_ISOCHRONOUS << EP_CTRL_BUFFER_TYPE_LSB) | - hw_data_offset(ep->hw_data_buf); - *ctrl_reg = ctrl_value; - } + hw_endpoint_enable(ep, TUSB_XFER_ISOCHRONOUS); return true; } @@ -522,8 +516,8 @@ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { } // stall and clear current pending buffer, may need to use EP_ABORT - io_rw_32 *buf_ctrl_reg = hwep_buf_ctrl_reg_device(ep); - hwep_buf_ctrl_set(buf_ctrl_reg, USB_BUF_CTRL_STALL); + io_rw_32 *buf_ctrl_reg = hwbuf_ctrl_reg_device(ep); + hwbuf_ctrl_set(buf_ctrl_reg, USB_BUF_CTRL_STALL); } void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { @@ -534,8 +528,8 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { // clear stall also reset toggle to DATA0, ready for next transfer ep->next_pid = 0; - io_rw_32 *buf_ctrl_reg = hwep_buf_ctrl_reg_device(ep); - hwep_buf_ctrl_clear_mask(buf_ctrl_reg, USB_BUF_CTRL_STALL); + io_rw_32 *buf_ctrl_reg = hwbuf_ctrl_reg_device(ep); + hwbuf_ctrl_clear_mask(buf_ctrl_reg, USB_BUF_CTRL_STALL); } } diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index 2e5f0fe1f..c4eba0d5f 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -62,22 +62,23 @@ enum { USB_SIE_CTRL_PULLDOWN_EN_BITS | USB_SIE_CTRL_EP0_INT_1BUF_BITS }; -static struct hw_endpoint *get_dev_ep(uint8_t dev_addr, uint8_t ep_addr) -{ +static struct hw_endpoint *get_dev_ep(uint8_t dev_addr, uint8_t ep_addr) { uint8_t num = tu_edpt_number(ep_addr); - if ( num == 0 ) return &epx; + if (num == 0) { + return &epx; + } - for ( uint32_t i = 1; i < TU_ARRAY_SIZE(ep_pool); i++ ) - { + for (uint32_t i = 1; i < TU_ARRAY_SIZE(ep_pool); i++) { struct hw_endpoint *ep = &ep_pool[i]; - if ( ep->configured && (ep->dev_addr == dev_addr) && (ep->ep_addr == ep_addr) ) return ep; + if (ep->configured && (ep->dev_addr == dev_addr) && (ep->ep_addr == ep_addr)) { + return ep; + } } return NULL; } -TU_ATTR_ALWAYS_INLINE static inline uint8_t dev_speed(void) -{ +TU_ATTR_ALWAYS_INLINE static inline uint8_t dev_speed(void) { return (usb_hw->sie_status & USB_SIE_STATUS_SPEED_BITS) >> USB_SIE_STATUS_SPEED_LSB; } @@ -98,8 +99,7 @@ static void __tusb_irq_path_func(hw_xfer_complete)(struct hw_endpoint *ep, xfer_ hcd_event_xfer_complete(dev_addr, ep_addr, xferred_len, xfer_result, true); } -static void __tusb_irq_path_func(_handle_buff_status_bit)(uint bit, struct hw_endpoint *ep) -{ +static void __tusb_irq_path_func(_handle_buff_status_bit)(uint bit, struct hw_endpoint *ep) { usb_hw_clear->buf_status = bit; // EP may have been stalled? assert(ep->active); @@ -357,8 +357,7 @@ static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t dev_addr, uint8_t // Finally, enable interrupt that endpoint usb_hw_set->int_ep_ctrl = 1 << (ep->interrupt_num + 1); - // If it's an interrupt endpoint we need to set up the buffer control - // register + // If it's an interrupt endpoint we need to set up the buffer control register } } @@ -456,8 +455,8 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr) { // reset epx if it is currently active with unplugged device if (epx.configured && epx.active && epx.dev_addr == dev_addr) { epx.configured = false; - *hwep_ctrl_reg_host(&epx) = 0; - *hwep_buf_ctrl_reg_host(&epx) = 0; + *hwep_ctrl_reg_host(&epx) = 0; + *hwbuf_ctrl_reg_host(&epx) = 0; hw_endpoint_reset_transfer(&epx); } @@ -472,8 +471,8 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr) { // unconfigure the endpoint ep->configured = false; - *hwep_ctrl_reg_host(ep) = 0; - *hwep_buf_ctrl_reg_host(ep) = 0; + *hwep_ctrl_reg_host(ep) = 0; + *hwbuf_ctrl_reg_host(ep) = 0; hw_endpoint_reset_transfer(ep); } } diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index 5258b9705..798129e0c 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -88,7 +88,7 @@ void __tusb_irq_path_func(hw_endpoint_reset_transfer)(struct hw_endpoint* ep) { ep->user_buf = 0; } -void __tusb_irq_path_func(hwep_buf_ctrl_update)(io_rw_32 *buf_ctrl_reg, uint32_t and_mask, uint32_t or_mask) { +void __tusb_irq_path_func(hwbuf_ctrl_update)(io_rw_32 *buf_ctrl_reg, uint32_t and_mask, uint32_t or_mask) { const bool is_host = rp2usb_is_host_mode(); uint32_t value = 0; uint32_t buf_ctrl = *buf_ctrl_reg; @@ -101,7 +101,7 @@ void __tusb_irq_path_func(hwep_buf_ctrl_update)(io_rw_32 *buf_ctrl_reg, uint32_t value |= or_mask; if (or_mask & USB_BUF_CTRL_AVAIL) { if (buf_ctrl & USB_BUF_CTRL_AVAIL) { - panic("buf_ctrl @%lX already available", (uintptr_t)buf_ctrl_reg); + panic("buf_ctrl @ 0x%lX already available", (uintptr_t)buf_ctrl_reg); } *buf_ctrl_reg = value & ~USB_BUF_CTRL_AVAIL; @@ -162,15 +162,15 @@ void __tusb_irq_path_func(hw_endpoint_start_next_buffer)(struct hw_endpoint* ep) #if CFG_TUH_ENABLED const bool is_host = rp2usb_is_host_mode(); if (is_host) { - buf_ctrl_reg = hwep_buf_ctrl_reg_host(ep); - ep_ctrl_reg = hwep_ctrl_reg_host(ep); - is_rx = (dir == TUSB_DIR_IN); + buf_ctrl_reg = hwbuf_ctrl_reg_host(ep); + ep_ctrl_reg = hwep_ctrl_reg_host(ep); + is_rx = (dir == TUSB_DIR_IN); } else #endif { - buf_ctrl_reg = hwep_buf_ctrl_reg_device(ep); - ep_ctrl_reg = hwep_ctrl_reg_device(ep); - is_rx = (dir == TUSB_DIR_OUT); + buf_ctrl_reg = hwbuf_ctrl_reg_device(ep); + ep_ctrl_reg = hwep_ctrl_reg_device(ep); + is_rx = (dir == TUSB_DIR_OUT); } // always compute and start with buffer 0 @@ -209,7 +209,7 @@ void __tusb_irq_path_func(hw_endpoint_start_next_buffer)(struct hw_endpoint* ep) // Finally, write to buffer_control which will trigger the transfer // the next time the controller polls this dpram address - hwep_buf_ctrl_set(buf_ctrl_reg, buf_ctrl); + hwbuf_ctrl_set(buf_ctrl_reg, buf_ctrl); } void hw_endpoint_xfer_start(struct hw_endpoint* ep, uint8_t* buffer, uint16_t total_len) { @@ -287,13 +287,13 @@ static void __tusb_irq_path_func(hwep_xfer_sync)(hw_endpoint_t *ep) { #if CFG_TUH_ENABLED const bool is_host = rp2usb_is_host_mode(); if (is_host) { - buf_ctrl_reg = hwep_buf_ctrl_reg_host(ep); + buf_ctrl_reg = hwbuf_ctrl_reg_host(ep); ep_ctrl_reg = hwep_ctrl_reg_host(ep); is_rx = (dir == TUSB_DIR_IN); } else #endif { - buf_ctrl_reg = hwep_buf_ctrl_reg_device(ep); + buf_ctrl_reg = hwbuf_ctrl_reg_device(ep); ep_ctrl_reg = hwep_ctrl_reg_device(ep); is_rx = (dir == TUSB_DIR_OUT); } @@ -327,8 +327,8 @@ static void __tusb_irq_path_func(hwep_xfer_sync)(hw_endpoint_t *ep) { ep_ctrl &= ~(EP_CTRL_DOUBLE_BUFFERED_BITS | EP_CTRL_INTERRUPT_PER_DOUBLE_BUFFER); ep_ctrl |= EP_CTRL_INTERRUPT_PER_BUFFER; - io_rw_32 *buf_ctrl_reg = is_host ? hwep_buf_ctrl_reg_host(ep) : hwep_buf_ctrl_reg_device(ep); - hwep_buf_ctrl_set(buf_ctrl_reg, 0); + io_rw_32 *buf_ctrl_reg = is_host ? hwbuf_ctrl_reg_host(ep) : hwbuf_ctrl_reg_device(ep); + hwbuf_ctrl_set(buf_ctrl_reg, 0); usb_hw->abort &= ~TU_BIT(ep_id); diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.h b/src/portable/raspberrypi/rp2040/rp2040_usb.h index e9fed73de..368bb6509 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.h +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.h @@ -1,10 +1,6 @@ #ifndef RP2040_COMMON_H_ #define RP2040_COMMON_H_ -#if defined(RP2040_USB_HOST_MODE) && defined(RP2040_USB_DEVICE_MODE) -#error TinyUSB device and host mode not supported at the same time -#endif - #include "common/tusb_common.h" #include "pico.h" @@ -13,6 +9,10 @@ #include "hardware/resets.h" #include "hardware/timer.h" +#if defined(RP2040_USB_HOST_MODE) && defined(RP2040_USB_DEVICE_MODE) + #error TinyUSB device and host mode not supported at the same time +#endif + #if defined(PICO_RP2040_USB_DEVICE_ENUMERATION_FIX) && !defined(TUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX) #define TUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX PICO_RP2040_USB_DEVICE_ENUMERATION_FIX #endif @@ -36,6 +36,9 @@ #define __tusb_irq_path_func(x) x #endif +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ #define usb_hw_set ((usb_hw_t *) hw_set_alias_untyped(usb_hw)) #define usb_hw_clear ((usb_hw_t *) hw_clear_alias_untyped(usb_hw)) @@ -56,9 +59,9 @@ typedef struct hw_endpoint uint16_t wMaxPacketSize; uint8_t *hw_data_buf; // Buffer pointer in usb dpram - uint8_t *user_buf; // User buffer in main memory // Current transfer information + uint8_t *user_buf; // User buffer in main memory uint16_t remaining_len; uint16_t xferred_len; @@ -108,7 +111,7 @@ TU_ATTR_ALWAYS_INLINE static inline io_rw_32 *hwep_ctrl_reg_device(struct hw_end return (dir == TUSB_DIR_IN) ? &usb_dpram->ep_ctrl[epnum - 1].in : &usb_dpram->ep_ctrl[epnum - 1].out; } -TU_ATTR_ALWAYS_INLINE static inline io_rw_32 *hwep_buf_ctrl_reg_device(struct hw_endpoint *ep) { +TU_ATTR_ALWAYS_INLINE static inline io_rw_32 *hwbuf_ctrl_reg_device(struct hw_endpoint *ep) { const uint8_t epnum = tu_edpt_number(ep->ep_addr); const uint8_t dir = (uint8_t)tu_edpt_dir(ep->ep_addr); return (dir == TUSB_DIR_IN) ? &usb_dpram->ep_buf_ctrl[epnum].in : &usb_dpram->ep_buf_ctrl[epnum].out; @@ -123,30 +126,29 @@ TU_ATTR_ALWAYS_INLINE static inline io_rw_32 *hwep_ctrl_reg_host(struct hw_endpo return &usbh_dpram->int_ep_ctrl[ep->interrupt_num].ctrl; } -TU_ATTR_ALWAYS_INLINE static inline io_rw_32 *hwep_buf_ctrl_reg_host(struct hw_endpoint *ep) { - if (ep->transfer_type == TUSB_XFER_CONTROL) { +TU_ATTR_ALWAYS_INLINE static inline io_rw_32 *hwbuf_ctrl_reg_host(struct hw_endpoint *ep) { + if (tu_edpt_number(ep->ep_addr) == 0) { return &usbh_dpram->epx_buf_ctrl; } return &usbh_dpram->int_ep_buffer_ctrl[ep->interrupt_num].ctrl; } #endif - //--------------------------------------------------------------------+ // //--------------------------------------------------------------------+ -void hwep_buf_ctrl_update(io_rw_32 *buf_ctrl_reg, uint32_t and_mask, uint32_t or_mask); +void hwbuf_ctrl_update(io_rw_32 *buf_ctrl_reg, uint32_t and_mask, uint32_t or_mask); -TU_ATTR_ALWAYS_INLINE static inline void hwep_buf_ctrl_set(io_rw_32 *buf_ctrl_reg, uint32_t value) { - hwep_buf_ctrl_update(buf_ctrl_reg, 0, value); +TU_ATTR_ALWAYS_INLINE static inline void hwbuf_ctrl_set(io_rw_32 *buf_ctrl_reg, uint32_t value) { + hwbuf_ctrl_update(buf_ctrl_reg, 0, value); } -TU_ATTR_ALWAYS_INLINE static inline void hwep_buf_ctrl_set_mask(io_rw_32 *buf_ctrl_reg, uint32_t value) { - hwep_buf_ctrl_update(buf_ctrl_reg, ~value, value); +TU_ATTR_ALWAYS_INLINE static inline void hwbuf_ctrl_set_mask(io_rw_32 *buf_ctrl_reg, uint32_t value) { + hwbuf_ctrl_update(buf_ctrl_reg, ~value, value); } -TU_ATTR_ALWAYS_INLINE static inline void hwep_buf_ctrl_clear_mask(io_rw_32 *buf_ctrl_reg, uint32_t value) { - hwep_buf_ctrl_update(buf_ctrl_reg, ~value, 0); +TU_ATTR_ALWAYS_INLINE static inline void hwbuf_ctrl_clear_mask(io_rw_32 *buf_ctrl_reg, uint32_t value) { + hwbuf_ctrl_update(buf_ctrl_reg, ~value, 0); } static inline uintptr_t hw_data_offset(uint8_t *buf) { -- cgit v1.3.1 From d7e715d5c238e9b05ef711a1a73d54c40b37729e Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 8 Jan 2026 15:42:08 +0700 Subject: fix hcd force_single mistake by refactor --- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 42 +++++++++------------------- src/portable/raspberrypi/rp2040/rp2040_usb.c | 5 ++-- 2 files changed, 16 insertions(+), 31 deletions(-) (limited to 'src/portable') diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index c4eba0d5f..db3a81c87 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -110,35 +110,24 @@ static void __tusb_irq_path_func(_handle_buff_status_bit)(uint bit, struct hw_en } } -static void __tusb_irq_path_func(hw_handle_buff_status)(void) -{ +static void __tusb_irq_path_func(handle_hwbuf_status)(void) { uint32_t remaining_buffers = usb_hw->buf_status; pico_trace("buf_status 0x%08lx\n", remaining_buffers); // Check EPX first uint bit = 0b1; - if ( remaining_buffers & bit ) - { + if (remaining_buffers & bit) { remaining_buffers &= ~bit; struct hw_endpoint * ep = &epx; - uint32_t ep_ctrl = *hwep_ctrl_reg_host(ep); - if ( ep_ctrl & EP_CTRL_DOUBLE_BUFFERED_BITS ) - { - TU_LOG(3, "Double Buffered: "); - } - else - { - TU_LOG(3, "Single Buffered: "); - } - TU_LOG_HEX(3, ep_ctrl); + // uint32_t ep_ctrl = *hwep_ctrl_reg_host(ep); + // TU_LOG_HEX(3, ep_ctrl); _handle_buff_status_bit(bit, ep); } // Check "interrupt" (asynchronous) endpoints for both IN and OUT - for ( uint i = 1; i <= USB_HOST_INTERRUPT_ENDPOINTS && remaining_buffers; i++ ) - { + for (uint i = 1; i <= USB_HOST_INTERRUPT_ENDPOINTS && remaining_buffers; i++) { // EPX is bit 0 & 1 // IEP1 IN is bit 2 // IEP1 OUT is bit 3 @@ -147,19 +136,16 @@ static void __tusb_irq_path_func(hw_handle_buff_status)(void) // IEP3 IN is bit 6 // IEP3 OUT is bit 7 // etc - for ( uint j = 0; j < 2; j++ ) - { + for (uint j = 0; j < 2; j++) { bit = 1 << (i * 2 + j); - if ( remaining_buffers & bit ) - { + if (remaining_buffers & bit) { remaining_buffers &= ~bit; _handle_buff_status_bit(bit, &ep_pool[i]); } } } - if ( remaining_buffers ) - { + if (remaining_buffers) { panic("Unhandled buffer %d\n", remaining_buffers); } } @@ -220,7 +206,7 @@ static void __tusb_irq_path_func(hcd_rp2040_irq)(void) { handled |= USB_INTS_BUFF_STATUS_BITS; TU_LOG(2, "Buffer complete\r\n"); - hw_handle_buff_status(); + handle_hwbuf_status(); } if ( status & USB_INTS_TRANS_COMPLETE_BITS ) @@ -240,8 +226,8 @@ static void __tusb_irq_path_func(hcd_rp2040_irq)(void) if ( status & USB_INTS_ERROR_DATA_SEQ_BITS ) { usb_hw_clear->sie_status = USB_SIE_STATUS_DATA_SEQ_ERROR_BITS; - TU_LOG(3, " Seq Error: [0] = 0x%04u [1] = 0x%04x\r\n", tu_u32_low16(*hw_endpoint_get_buf_ctrl(&epx)), - tu_u32_high16(*hw_endpoint_get_buf_ctrl(&epx))); + TU_LOG(3, " Seq Error: [0] = 0x%04u [1] = 0x%04x\r\n", tu_u32_low16(*hwbuf_ctrl_reg_host(&epx)), + tu_u32_high16(*hwbuf_ctrl_reg_host(&epx))); panic("Data Seq Error \n"); } @@ -322,10 +308,8 @@ static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t dev_addr, uint8_t assert(!(dpram_offset & 0b111111)); // Fill in endpoint control register with buffer offset - uint32_t ep_reg = EP_CTRL_ENABLE_BITS - | EP_CTRL_INTERRUPT_PER_BUFFER - | (ep->transfer_type << EP_CTRL_BUFFER_TYPE_LSB) - | dpram_offset; + uint32_t ep_reg = EP_CTRL_ENABLE_BITS | EP_CTRL_INTERRUPT_PER_BUFFER | + ((uint)transfer_type << EP_CTRL_BUFFER_TYPE_LSB) | dpram_offset; if ( bmInterval ) { ep_reg |= (uint32_t) ((bmInterval - 1) << EP_CTRL_HOST_INTERRUPT_INTERVAL_LSB); diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index 798129e0c..9c9255518 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -156,11 +156,12 @@ void __tusb_irq_path_func(hw_endpoint_start_next_buffer)(struct hw_endpoint* ep) const tusb_dir_t dir = tu_edpt_dir(ep->ep_addr); bool is_rx; + bool is_host = false; io_rw_32 *ep_ctrl_reg; io_rw_32 *buf_ctrl_reg; #if CFG_TUH_ENABLED - const bool is_host = rp2usb_is_host_mode(); + is_host = rp2usb_is_host_mode(); if (is_host) { buf_ctrl_reg = hwbuf_ctrl_reg_host(ep); ep_ctrl_reg = hwep_ctrl_reg_host(ep); @@ -185,7 +186,7 @@ void __tusb_irq_path_func(hw_endpoint_start_next_buffer)(struct hw_endpoint* ep) // NOTE: this could happen to Host mode IN endpoint Also, Host mode "interrupt" endpoint hardware is only single // buffered, // NOTE2: Currently Host bulk is implemented using "interrupt" endpoint - const bool force_single = is_rx; + const bool force_single = (!is_host && is_rx) || (is_host && tu_edpt_number(ep->ep_addr) != 0); if (ep->remaining_len && !force_single) { // Use buffer 1 (double buffered) if there is still data -- cgit v1.3.1 From 0b970e6a6633f703acb0f40b52b741cf492ff166 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 9 Jan 2026 00:08:43 +0700 Subject: only apply errata E5 and E15 for rp2040. rp2350 already fixes these --- hw/bsp/rp2040/family.cmake | 6 +- src/portable/raspberrypi/rp2040/dcd_rp2040.c | 14 ++-- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 119 ++++++++++----------------- src/portable/raspberrypi/rp2040/rp2040_usb.c | 25 +++--- src/portable/raspberrypi/rp2040/rp2040_usb.h | 67 +++++++++------ 5 files changed, 109 insertions(+), 122 deletions(-) (limited to 'src/portable') diff --git a/hw/bsp/rp2040/family.cmake b/hw/bsp/rp2040/family.cmake index 1602e35eb..9dc28fc70 100644 --- a/hw/bsp/rp2040/family.cmake +++ b/hw/bsp/rp2040/family.cmake @@ -126,7 +126,7 @@ target_compile_definitions(tinyusb_host_base INTERFACE #------------------------------------ # Host MAX3421 -#------------------------------------ +#------------------------------------1 add_library(tinyusb_host_max3421 INTERFACE) target_sources(tinyusb_host_max3421 INTERFACE ${TOP}/src/portable/analog/max3421/hcd_max3421.c @@ -157,10 +157,12 @@ target_link_libraries(tinyusb_bsp INTERFACE # tinyusb_additions will hold our extra settings for examples add_library(tinyusb_additions INTERFACE) +if (PICO_PLATFORM STREQUAL rp2040) target_compile_definitions(tinyusb_additions INTERFACE PICO_RP2040_USB_DEVICE_ENUMERATION_FIX=1 PICO_RP2040_USB_DEVICE_UFRAME_FIX=1 -) + ) +endif () if(LOGGER STREQUAL "RTT" OR LOGGER STREQUAL "rtt") target_compile_definitions(tinyusb_additions INTERFACE diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index 952245cb1..bdd0d1728 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -92,6 +92,12 @@ static void hw_endpoint_init(hw_endpoint_t *ep, uint8_t ep_addr, uint16_t wMaxPa // double buffered Bulk endpoint if (transfer_type == TUSB_XFER_BULK) { size *= 2u; + + #if TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX + if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN) { + ep->e15_bulk_in = true; + } + #endif } // assign buffer @@ -221,17 +227,14 @@ static void __tusb_irq_path_func(dcd_rp2040_irq)(void) { struct hw_endpoint *ep = hw_endpoint_get(i, TUSB_DIR_IN); // Active Bulk IN endpoint requires SOF - if ((ep->transfer_type == TUSB_XFER_BULK) && ep->active) { + if (ep->e15_bulk_in && ep->active) { keep_sof_alive = true; hw_endpoint_lock_update(ep, 1); - - // Deferred enable? if (ep->pending) { ep->pending = 0; hw_endpoint_start_next_buffer(ep); } - hw_endpoint_lock_update(ep, -1); } } @@ -292,7 +295,7 @@ static void __tusb_irq_path_func(dcd_rp2040_irq)(void) { dcd_event_bus_reset(0, TUSB_SPEED_FULL, true); usb_hw_clear->sie_status = USB_SIE_STATUS_BUS_RESET_BITS; -#if TUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX + #if TUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX // Only run enumeration workaround if pull up is enabled if (usb_hw->sie_ctrl & USB_SIE_CTRL_PULLUP_EN_BITS) { rp2040_usb_device_enumeration_fix(); @@ -491,7 +494,6 @@ bool dcd_edpt_iso_activate(uint8_t rhport, const tusb_desc_endpoint_t *ep_desc) void dcd_edpt_close_all(uint8_t rhport) { (void) rhport; - // may need to use EP Abort reset_non_control_endpoints(); } diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index db3a81c87..1193009ef 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -82,15 +82,13 @@ TU_ATTR_ALWAYS_INLINE static inline uint8_t dev_speed(void) { return (usb_hw->sie_status & USB_SIE_STATUS_SPEED_BITS) >> USB_SIE_STATUS_SPEED_LSB; } -TU_ATTR_ALWAYS_INLINE static inline bool need_pre(uint8_t dev_addr) -{ +TU_ATTR_ALWAYS_INLINE static inline bool need_pre(uint8_t dev_addr) { // If this device is different to the speed of the root device // (i.e. is a low speed device on a full speed hub) then need pre return hcd_port_speed_get(0) != tuh_speed_get(dev_addr); } -static void __tusb_irq_path_func(hw_xfer_complete)(struct hw_endpoint *ep, xfer_result_t xfer_result) -{ +static void __tusb_irq_path_func(hw_xfer_complete)(struct hw_endpoint *ep, xfer_result_t xfer_result) { // Mark transfer as done before we tell the tinyusb stack uint8_t dev_addr = ep->dev_addr; uint8_t ep_addr = ep->ep_addr; @@ -99,35 +97,28 @@ static void __tusb_irq_path_func(hw_xfer_complete)(struct hw_endpoint *ep, xfer_ hcd_event_xfer_complete(dev_addr, ep_addr, xferred_len, xfer_result, true); } -static void __tusb_irq_path_func(_handle_buff_status_bit)(uint bit, struct hw_endpoint *ep) { +static void __tusb_irq_path_func(handle_hhwbuf_status_bit)(uint bit, struct hw_endpoint *ep) { usb_hw_clear->buf_status = bit; - // EP may have been stalled? - assert(ep->active); - bool done = hw_endpoint_xfer_continue(ep); - if ( done ) - { + const bool done = hw_endpoint_xfer_continue(ep); + if (done) { hw_xfer_complete(ep, XFER_RESULT_SUCCESS); } } static void __tusb_irq_path_func(handle_hwbuf_status)(void) { - uint32_t remaining_buffers = usb_hw->buf_status; - pico_trace("buf_status 0x%08lx\n", remaining_buffers); + uint32_t buf_status = usb_hw->buf_status; + pico_trace("buf_status 0x%08lx\n", buf_status); // Check EPX first uint bit = 0b1; - if (remaining_buffers & bit) { - remaining_buffers &= ~bit; + if (buf_status & bit) { + buf_status &= ~bit; struct hw_endpoint * ep = &epx; - - // uint32_t ep_ctrl = *hwep_ctrl_reg_host(ep); - // TU_LOG_HEX(3, ep_ctrl); - - _handle_buff_status_bit(bit, ep); + handle_hhwbuf_status_bit(bit, ep); } // Check "interrupt" (asynchronous) endpoints for both IN and OUT - for (uint i = 1; i <= USB_HOST_INTERRUPT_ENDPOINTS && remaining_buffers; i++) { + for (uint i = 1; i <= USB_HOST_INTERRUPT_ENDPOINTS && buf_status; i++) { // EPX is bit 0 & 1 // IEP1 IN is bit 2 // IEP1 OUT is bit 3 @@ -138,15 +129,15 @@ static void __tusb_irq_path_func(handle_hwbuf_status)(void) { // etc for (uint j = 0; j < 2; j++) { bit = 1 << (i * 2 + j); - if (remaining_buffers & bit) { - remaining_buffers &= ~bit; - _handle_buff_status_bit(bit, &ep_pool[i]); + if (buf_status & bit) { + buf_status &= ~bit; + handle_hhwbuf_status_bit(bit, &ep_pool[i]); } } } - if (remaining_buffers) { - panic("Unhandled buffer %d\n", remaining_buffers); + if (buf_status) { + panic("Unhandled buffer %d\n", buf_status); } } @@ -251,7 +242,7 @@ static struct hw_endpoint *_next_free_interrupt_ep(void) ep = &ep_pool[i]; if ( !ep->configured ) { - // Will be configured by _hw_endpoint_init / _hw_endpoint_allocate + // Will be configured by hw_endpoint_init / hw_endpoint_allocate ep->interrupt_num = (uint8_t) (i - 1); return ep; } @@ -259,12 +250,13 @@ static struct hw_endpoint *_next_free_interrupt_ep(void) return ep; } -static struct hw_endpoint *_hw_endpoint_allocate(uint8_t transfer_type) -{ - struct hw_endpoint * ep = NULL; +static hw_endpoint_t *hw_endpoint_allocate(uint8_t transfer_type) { + hw_endpoint_t *ep = NULL; - if ( transfer_type != TUSB_XFER_CONTROL ) - { + if (transfer_type == TUSB_XFER_CONTROL) { + ep = &epx; + ep->hw_data_buf = &usbh_dpram->epx_data[0]; + } else { // Note: even though datasheet name these "Interrupt" endpoints. These are actually // "Asynchronous" endpoints and can be used for other type such as: Bulk (ISO need confirmation) ep = _next_free_interrupt_ep(); @@ -276,17 +268,12 @@ static struct hw_endpoint *_hw_endpoint_allocate(uint8_t transfer_type) // etc ep->hw_data_buf = &usbh_dpram->epx_data[64 * (ep->interrupt_num + 2)]; } - else - { - ep = &epx; - ep->hw_data_buf = &usbh_dpram->epx_data[0]; - } return ep; } -static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t dev_addr, uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t transfer_type, uint8_t bmInterval) -{ +static void hw_endpoint_init(struct hw_endpoint *ep, uint8_t dev_addr, uint8_t ep_addr, uint16_t wMaxPacketSize, + uint8_t transfer_type, uint8_t bmInterval) { // Already has data buffer, endpoint control, and buffer control allocated at this point assert(ep->hw_data_buf); @@ -299,7 +286,6 @@ static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t dev_addr, uint8_t // Response to a setup packet on EP0 starts with pid of 1 ep->next_pid = (num == 0 ? 1u : 0u); ep->wMaxPacketSize = wMaxPacketSize; - ep->transfer_type = transfer_type; pico_trace("hw_endpoint_init dev %d ep %02X xfer %d\n", ep->dev_addr, ep->ep_addr, ep->transfer_type); pico_trace("dev %d ep %02X setup buffer @ 0x%p\n", ep->dev_addr, ep->ep_addr, ep->hw_data_buf); @@ -463,46 +449,33 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr) { } } -uint32_t hcd_frame_number(uint8_t rhport) -{ - (void) rhport; +uint32_t hcd_frame_number(uint8_t rhport) { + (void)rhport; return usb_hw->sof_rd; } -void hcd_int_enable(uint8_t rhport) -{ - (void) rhport; - assert(rhport == 0); +void hcd_int_enable(uint8_t rhport) { + (void)rhport; irq_set_enabled(USBCTRL_IRQ, true); } -void hcd_int_disable(uint8_t rhport) -{ - (void) rhport; +void hcd_int_disable(uint8_t rhport) { + (void)rhport; // todo we should check this is disabling from the correct core; note currently this is never called - assert(rhport == 0); irq_set_enabled(USBCTRL_IRQ, false); } //--------------------------------------------------------------------+ // 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, const tusb_desc_endpoint_t *ep_desc) { + (void)rhport; pico_trace("hcd_edpt_open dev_addr %d, ep_addr %d\n", dev_addr, ep_desc->bEndpointAddress); - - // Allocated differently based on if it's an interrupt endpoint or not - struct hw_endpoint *ep = _hw_endpoint_allocate(ep_desc->bmAttributes.xfer); + hw_endpoint_t *ep = hw_endpoint_allocate(ep_desc->bmAttributes.xfer); TU_ASSERT(ep); - _hw_endpoint_init(ep, - dev_addr, - ep_desc->bEndpointAddress, - tu_edpt_packet_size(ep_desc), - ep_desc->bmAttributes.xfer, - ep_desc->bInterval); + hw_endpoint_init(ep, dev_addr, ep_desc->bEndpointAddress, tu_edpt_packet_size(ep_desc), ep_desc->bmAttributes.xfer, + ep_desc->bInterval); return true; } @@ -512,13 +485,12 @@ bool hcd_edpt_close(uint8_t rhport, uint8_t daddr, uint8_t 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 hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *buffer, uint16_t buflen) { (void) rhport; pico_trace("hcd_edpt_xfer dev_addr %d, ep_addr 0x%x, len %d\n", dev_addr, ep_addr, buflen); - uint8_t const ep_num = tu_edpt_number(ep_addr); + const uint8_t ep_num = tu_edpt_number(ep_addr); tusb_dir_t const ep_dir = tu_edpt_dir(ep_addr); // Get appropriate ep. Either EPX or interrupt endpoint @@ -530,19 +502,17 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * assert(!ep->active); // Control endpoint can change direction 0x00 <-> 0x80 - if ( ep_addr != ep->ep_addr ) - { + if (ep_addr != ep->ep_addr) { assert(ep_num == 0); // Direction has flipped on endpoint control so re init it but with same properties - _hw_endpoint_init(ep, dev_addr, ep_addr, ep->wMaxPacketSize, ep->transfer_type, 0); + hw_endpoint_init(ep, dev_addr, ep_addr, ep->wMaxPacketSize, TUSB_XFER_CONTROL, 0); } // If a normal transfer (non-interrupt) then initiate using // sie ctrl registers. Otherwise, interrupt ep registers should // already be configured - if ( ep == &epx ) - { + if (ep == &epx) { hw_endpoint_xfer_start(ep, buffer, buflen); // That has set up buffer control, endpoint control etc @@ -558,8 +528,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * usb_hw->sie_ctrl = flags & ~USB_SIE_CTRL_START_TRANS_BITS; busy_wait_at_least_cycles(12); usb_hw->sie_ctrl = flags; - }else - { + } else { hw_endpoint_xfer_start(ep, buffer, buflen); } @@ -584,14 +553,14 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet } // Configure EP0 struct with setup info for the trans complete - struct hw_endpoint * ep = _hw_endpoint_allocate( (uint8_t) TUSB_XFER_CONTROL); + hw_endpoint_t *ep = hw_endpoint_allocate((uint8_t)TUSB_XFER_CONTROL); TU_ASSERT(ep); // EPX should be inactive assert(!ep->active); // EP0 out - _hw_endpoint_init(ep, dev_addr, 0x00, ep->wMaxPacketSize, 0, 0); + hw_endpoint_init(ep, dev_addr, 0x00, ep->wMaxPacketSize, 0, 0); assert(ep->configured); ep->remaining_len = 8; diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index 9c9255518..8f91ecf22 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -38,10 +38,8 @@ static void hwep_xfer_sync(hw_endpoint_t *ep); #if TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX -static bool e15_is_bulkin_ep(struct hw_endpoint *ep); static bool e15_is_critical_frame_period(struct hw_endpoint *ep); #else - #define e15_is_bulkin_ep(x) (false) #define e15_is_critical_frame_period(x) (false) #endif @@ -228,13 +226,16 @@ void hw_endpoint_xfer_start(struct hw_endpoint* ep, uint8_t* buffer, uint16_t to ep->active = true; ep->user_buf = buffer; - if (e15_is_bulkin_ep(ep)) { + #if TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX + if (ep->e15_bulk_in) { usb_hw_set->inte = USB_INTS_DEV_SOF_BITS; } if (e15_is_critical_frame_period(ep)) { - ep->pending = 1; - } else { + ep->pending = 1; // skip transfer if we are in critical frame period + } else + #endif + { hw_endpoint_start_next_buffer(ep); } @@ -360,9 +361,12 @@ bool __tusb_irq_path_func(hw_endpoint_xfer_continue)(struct hw_endpoint* ep) { hw_endpoint_lock_update(ep, -1); return true; } else { + #if TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX if (e15_is_critical_frame_period(ep)) { ep->pending = 1; - } else { + } else + #endif + { hw_endpoint_start_next_buffer(ep); } } @@ -397,15 +401,12 @@ bool __tusb_irq_path_func(hw_endpoint_xfer_continue)(struct hw_endpoint* ep) { volatile uint32_t e15_last_sof = 0; -// check if Errata 15 is needed for this endpoint i.e device bulk-in -static bool __tusb_irq_path_func(e15_is_bulkin_ep)(struct hw_endpoint *ep) { - return (!rp2usb_is_host_mode() && tu_edpt_dir(ep->ep_addr) == TUSB_DIR_IN && ep->transfer_type == TUSB_XFER_BULK); -} - // check if we need to apply Errata 15 workaround : i.e // Endpoint is BULK IN and is currently in critical frame period i.e 20% of last usb frame static bool __tusb_irq_path_func(e15_is_critical_frame_period)(struct hw_endpoint* ep) { - TU_VERIFY(e15_is_bulkin_ep(ep)); + if (!ep->e15_bulk_in) { + return false; + } /* Avoid the last 200us (uframe 6.5-7) of a frame, up to the EOF2 point. * The device state machine cannot recover from receiving an incorrect PID diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.h b/src/portable/raspberrypi/rp2040/rp2040_usb.h index 368bb6509..944d604bc 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.h +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.h @@ -13,17 +13,30 @@ #error TinyUSB device and host mode not supported at the same time #endif -#if defined(PICO_RP2040_USB_DEVICE_ENUMERATION_FIX) && !defined(TUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX) -#define TUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX PICO_RP2040_USB_DEVICE_ENUMERATION_FIX +// E5 and E15 only apply to RP2040 +#if defined(PICO_RP2040) && PICO_RP2040 == 1 + // RP2040 E5: USB device fails to exit RESET state on busy USB bus. + #if defined(PICO_RP2040_USB_DEVICE_ENUMERATION_FIX) && !defined(TUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX) + #define TUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX PICO_RP2040_USB_DEVICE_ENUMERATION_FIX + #endif + + // RP2040 E15: USB Device controller will hang if certain bus errors occur during an IN transfer. + #if defined(PICO_RP2040_USB_DEVICE_UFRAME_FIX) && !defined(TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX) + #define TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX PICO_RP2040_USB_DEVICE_UFRAME_FIX + #endif #endif -#if defined(PICO_RP2040_USB_DEVICE_UFRAME_FIX) && !defined(TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX) -#define TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX PICO_RP2040_USB_DEVICE_UFRAME_FIX +#ifndef TUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX + #define TUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX 0 +#endif + +#ifndef TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX + #define TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX 0 #endif #if TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX -#undef PICO_RP2040_USB_FAST_IRQ -#define PICO_RP2040_USB_FAST_IRQ 1 + #undef PICO_RP2040_USB_FAST_IRQ + #define PICO_RP2040_USB_FAST_IRQ 1 #endif #ifndef PICO_RP2040_USB_FAST_IRQ @@ -46,36 +59,36 @@ #define pico_trace(...) TU_LOG(3, __VA_ARGS__) // Hardware information per endpoint -typedef struct hw_endpoint -{ - uint8_t ep_addr; - uint8_t next_pid; - // Interrupt, bulk, etc - uint8_t transfer_type; +typedef struct hw_endpoint { + uint8_t ep_addr; + uint8_t next_pid; + uint8_t transfer_type; - bool active; // Endpoint is in use - uint8_t pending; // Transfer scheduled but not active + bool active; // transferring data - uint16_t wMaxPacketSize; +#if TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX + bool e15_bulk_in; // Errata15 device bulk in + uint8_t pending; // Transfer scheduled but not active +#endif - uint8_t *hw_data_buf; // Buffer pointer in usb dpram + uint16_t wMaxPacketSize; + uint8_t *hw_data_buf; // Buffer pointer in usb dpram - // Current transfer information - uint8_t *user_buf; // User buffer in main memory - uint16_t remaining_len; - uint16_t xferred_len; + // Current transfer information + uint8_t *user_buf; // User buffer in main memory + uint16_t remaining_len; + uint16_t xferred_len; #if CFG_TUH_ENABLED - // Is this a valid struct - bool configured; + // Is this a valid struct + bool configured; - // Only needed for host - uint8_t dev_addr; + // Only needed for host + uint8_t dev_addr; - // If interrupt endpoint - uint8_t interrupt_num; + // If interrupt endpoint + uint8_t interrupt_num; #endif - } hw_endpoint_t; #if TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX -- cgit v1.3.1 From 8452dfe3055c876a1c8cb1f52c7bceeae6678452 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 9 Jan 2026 10:28:27 +0700 Subject: clean up --- .idea/debugServers/mcxa153.xml | 13 ++++++++++ .idea/debugServers/ra6m1.xml | 13 ++++++++++ .idea/debugServers/ra6m5.xml | 13 ++++++++++ .idea/debugServers/rt1011.xml | 13 ++++++++++ .idea/debugServers/rt1170.xml | 13 ++++++++++ .idea/debugServers/stm32f072.xml | 13 ++++++++++ .idea/debugServers/stm32f303.xml | 13 ++++++++++ .idea/debugServers/stm32l053.xml | 13 ++++++++++ hw/bsp/rp2040/family.cmake | 2 +- src/portable/raspberrypi/rp2040/dcd_rp2040.c | 4 ++-- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 36 +++++++++++++--------------- src/tusb_option.h | 2 +- 12 files changed, 125 insertions(+), 23 deletions(-) create mode 100644 .idea/debugServers/mcxa153.xml create mode 100644 .idea/debugServers/ra6m1.xml create mode 100644 .idea/debugServers/ra6m5.xml create mode 100644 .idea/debugServers/rt1011.xml create mode 100644 .idea/debugServers/rt1170.xml create mode 100644 .idea/debugServers/stm32f072.xml create mode 100644 .idea/debugServers/stm32f303.xml create mode 100644 .idea/debugServers/stm32l053.xml (limited to 'src/portable') diff --git a/.idea/debugServers/mcxa153.xml b/.idea/debugServers/mcxa153.xml new file mode 100644 index 000000000..0e493cbd5 --- /dev/null +++ b/.idea/debugServers/mcxa153.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/debugServers/ra6m1.xml b/.idea/debugServers/ra6m1.xml new file mode 100644 index 000000000..17c902ec4 --- /dev/null +++ b/.idea/debugServers/ra6m1.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/debugServers/ra6m5.xml b/.idea/debugServers/ra6m5.xml new file mode 100644 index 000000000..d8dfbdeeb --- /dev/null +++ b/.idea/debugServers/ra6m5.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/debugServers/rt1011.xml b/.idea/debugServers/rt1011.xml new file mode 100644 index 000000000..b4be501bd --- /dev/null +++ b/.idea/debugServers/rt1011.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/debugServers/rt1170.xml b/.idea/debugServers/rt1170.xml new file mode 100644 index 000000000..9a564ed57 --- /dev/null +++ b/.idea/debugServers/rt1170.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/debugServers/stm32f072.xml b/.idea/debugServers/stm32f072.xml new file mode 100644 index 000000000..c56f5a8fb --- /dev/null +++ b/.idea/debugServers/stm32f072.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/debugServers/stm32f303.xml b/.idea/debugServers/stm32f303.xml new file mode 100644 index 000000000..84aafc1e3 --- /dev/null +++ b/.idea/debugServers/stm32f303.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/debugServers/stm32l053.xml b/.idea/debugServers/stm32l053.xml new file mode 100644 index 000000000..5365189cc --- /dev/null +++ b/.idea/debugServers/stm32l053.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/hw/bsp/rp2040/family.cmake b/hw/bsp/rp2040/family.cmake index 9dc28fc70..40eee082d 100644 --- a/hw/bsp/rp2040/family.cmake +++ b/hw/bsp/rp2040/family.cmake @@ -126,7 +126,7 @@ target_compile_definitions(tinyusb_host_base INTERFACE #------------------------------------ # Host MAX3421 -#------------------------------------1 +#------------------------------------ add_library(tinyusb_host_max3421 INTERFACE) target_sources(tinyusb_host_max3421 INTERFACE ${TOP}/src/portable/analog/max3421/hcd_max3421.c diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index bdd0d1728..71d5cf19c 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -39,9 +39,9 @@ #include "device/dcd.h" // Current implementation force vbus detection as always present, causing device think it is always plugged into host. -// Therefore it cannot detect disconnect event, mistaken it as suspend. +// Therefore, it cannot detect disconnect event, mistaken it as suspend. // Note: won't work if change to 0 (for now) -#define FORCE_VBUS_DETECT 1 + #define FORCE_VBUS_DETECT 1 #define USB_INTS_ERROR_BITS \ (USB_INTS_ERROR_DATA_SEQ_BITS | USB_INTS_ERROR_BIT_STUFF_BITS | USB_INTS_ERROR_CRC_BITS | \ diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index 1193009ef..7bf247ced 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -97,7 +97,7 @@ static void __tusb_irq_path_func(hw_xfer_complete)(struct hw_endpoint *ep, xfer_ hcd_event_xfer_complete(dev_addr, ep_addr, xferred_len, xfer_result, true); } -static void __tusb_irq_path_func(handle_hhwbuf_status_bit)(uint bit, struct hw_endpoint *ep) { +static void __tusb_irq_path_func(handle_hwbuf_status_bit)(uint bit, struct hw_endpoint *ep) { usb_hw_clear->buf_status = bit; const bool done = hw_endpoint_xfer_continue(ep); if (done) { @@ -110,11 +110,11 @@ static void __tusb_irq_path_func(handle_hwbuf_status)(void) { pico_trace("buf_status 0x%08lx\n", buf_status); // Check EPX first - uint bit = 0b1; + uint32_t bit = 1u; if (buf_status & bit) { buf_status &= ~bit; struct hw_endpoint * ep = &epx; - handle_hhwbuf_status_bit(bit, ep); + handle_hwbuf_status_bit(bit, ep); } // Check "interrupt" (asynchronous) endpoints for both IN and OUT @@ -131,7 +131,7 @@ static void __tusb_irq_path_func(handle_hwbuf_status)(void) { bit = 1 << (i * 2 + j); if (buf_status & bit) { buf_status &= ~bit; - handle_hhwbuf_status_bit(bit, &ep_pool[i]); + handle_hwbuf_status_bit(bit, &ep_pool[i]); } } } @@ -287,39 +287,37 @@ static void hw_endpoint_init(struct hw_endpoint *ep, uint8_t dev_addr, uint8_t e ep->next_pid = (num == 0 ? 1u : 0u); ep->wMaxPacketSize = wMaxPacketSize; - pico_trace("hw_endpoint_init dev %d ep %02X xfer %d\n", ep->dev_addr, ep->ep_addr, ep->transfer_type); + pico_trace("hw_endpoint_init dev %d ep %02X xfer %d\n", ep->dev_addr, ep->ep_addr, transfer_type); pico_trace("dev %d ep %02X setup buffer @ 0x%p\n", ep->dev_addr, ep->ep_addr, ep->hw_data_buf); uint dpram_offset = hw_data_offset(ep->hw_data_buf); // Bits 0-5 should be 0 assert(!(dpram_offset & 0b111111)); // Fill in endpoint control register with buffer offset - uint32_t ep_reg = EP_CTRL_ENABLE_BITS | EP_CTRL_INTERRUPT_PER_BUFFER | - ((uint)transfer_type << EP_CTRL_BUFFER_TYPE_LSB) | dpram_offset; - if ( bmInterval ) - { - ep_reg |= (uint32_t) ((bmInterval - 1) << EP_CTRL_HOST_INTERRUPT_INTERVAL_LSB); + uint32_t ctrl_value = EP_CTRL_ENABLE_BITS | EP_CTRL_INTERRUPT_PER_BUFFER | + ((uint32_t)transfer_type << EP_CTRL_BUFFER_TYPE_LSB) | dpram_offset; + if (bmInterval) { + ctrl_value |= (uint32_t)((bmInterval - 1) << EP_CTRL_HOST_INTERRUPT_INTERVAL_LSB); } - *hwep_ctrl_reg_host(ep) = ep_reg; - // pico_trace("endpoint control (0x%p) <- 0x%lx\n", ep->endpoint_control, ep_reg); + + io_rw_32 *ctrl_reg = hwep_ctrl_reg_host(ep); + *ctrl_reg = ctrl_value; + pico_trace("endpoint control (0x%p) <- 0x%lx\n", ctrl_reg, ctrl_value); ep->configured = true; - if ( ep != &epx ) - { + if (ep != &epx) { // Endpoint has its own addr_endp and interrupt bits to be setup! // This is an interrupt/async endpoint. so need to set up ADDR_ENDP register with: // - device address // - endpoint number / direction // - preamble - uint32_t reg = (uint32_t) (dev_addr | (num << USB_ADDR_ENDP1_ENDPOINT_LSB)); + uint32_t reg = (uint32_t)(dev_addr | (num << USB_ADDR_ENDP1_ENDPOINT_LSB)); - if ( dir == TUSB_DIR_OUT ) - { + if (dir == TUSB_DIR_OUT) { reg |= USB_ADDR_ENDP1_INTEP_DIR_BITS; } - if ( need_pre(dev_addr) ) - { + if (need_pre(dev_addr)) { reg |= USB_ADDR_ENDP1_INTEP_PREAMBLE_BITS; } usb_hw->int_ep_addr_ctrl[ep->interrupt_num] = reg; diff --git a/src/tusb_option.h b/src/tusb_option.h index 08a0ba2ef..9b0da3ac7 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -335,7 +335,7 @@ #define CFG_TUD_EDPT_DEDICATED_HWFIFO 1 #endif -//------------- pio-usb -------------// +//------------- Raspberry Pi -------------// // Enable PIO-USB software host controller #ifndef CFG_TUH_RPI_PIO_USB #define CFG_TUH_RPI_PIO_USB 0 -- cgit v1.3.1 From 4c86cbdc822ccf0f71a67c5f2d627e18ecbad46f Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 9 Jan 2026 18:40:55 +0700 Subject: enable dedicated hwfifo for rp2 --- src/common/tusb_fifo.c | 76 +++++++++++++++++++------- src/portable/raspberrypi/rp2040/dcd_rp2040.c | 10 +++- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 4 +- src/portable/raspberrypi/rp2040/rp2040_usb.c | 55 +++++++++++++------ src/portable/raspberrypi/rp2040/rp2040_usb.h | 35 ++++++------ src/tusb_option.h | 79 +++++++++++++++------------- 6 files changed, 169 insertions(+), 90 deletions(-) (limited to 'src/portable') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index a92435912..9f188f296 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -33,7 +33,7 @@ // Suppress IAR warning // Warning[Pa082]: undefined behavior: the order of volatile accesses is undefined in this statement #if defined(__ICCARM__) -#pragma diag_suppress = Pa082 + #pragma diag_suppress = Pa082 #endif #if OSAL_MUTEX_REQUIRED @@ -110,8 +110,9 @@ void tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable) { } //--------------------------------------------------------------------+ -// Pull & Push -// copy data to/from fifo without updating read/write pointers +// Hardware FIFO API +// Support different data access width and address increment scheme +// Can support multiple i.e both 16 and 32-bit data access if needed //--------------------------------------------------------------------+ #if CFG_TUSB_FIFO_HWFIFO_API #if CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE @@ -122,18 +123,31 @@ void tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable) { #define HWFIFO_ADDR_NEXT(_hwfifo, _const) HWFIFO_ADDR_NEXT_N(_hwfifo, _const, CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE) +//------------- Write -------------// #ifndef CFG_TUSB_FIFO_HWFIFO_CUSTOM_WRITE -static inline void stride_write(volatile void *hwfifo, const void *src, uint8_t data_stride) { +TU_ATTR_ALWAYS_INLINE static inline void stride_write(volatile void *hwfifo, const void *src, uint8_t data_stride) { + (void)data_stride; // possible unused #if CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE & 4 - if (data_stride == 4) { + #if CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE != 4 + if (data_stride == 4) + #endif + { *((volatile uint32_t *)hwfifo) = tu_unaligned_read32(src); } - #endif - #if CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE & 2 - if (data_stride == 2) { + #endif + + #if CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE & 2 + #if CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE != 2 + if (data_stride == 2) + #endif + { *((volatile uint16_t *)hwfifo) = tu_unaligned_read16(src); } - #endif + #endif + + #if CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE == 1 + *((volatile uint8_t *)hwfifo) = *(const uint8_t *)src; + #endif } // Copy from fifo to fixed address buffer (usually a tx register) with TU_FIFO_FIXED_ADDR_RW32 mode @@ -147,7 +161,8 @@ void tu_hwfifo_write(volatile void *hwfifo, const uint8_t *src, uint16_t len, co HWFIFO_ADDR_NEXT(hwfifo, ); } - #ifdef CFG_TUSB_FIFO_HWFIFO_DATA_ODD_16BIT_ACCESS + #if CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE > 1 + #ifdef CFG_TUSB_FIFO_HWFIFO_DATA_ODD_16BIT_ACCESS // 16-bit access is allowed for odd bytes if (len >= 2) { *((volatile uint16_t *)hwfifo) = tu_unaligned_read16(src); @@ -155,16 +170,16 @@ void tu_hwfifo_write(volatile void *hwfifo, const uint8_t *src, uint16_t len, co len -= 2; HWFIFO_ADDR_NEXT_N(hwfifo, , 2); } - #endif + #endif - #ifdef CFG_TUSB_FIFO_HWFIFO_DATA_ODD_8BIT_ACCESS + #ifdef CFG_TUSB_FIFO_HWFIFO_DATA_ODD_8BIT_ACCESS // 8-bit access is allowed for odd bytes while (len > 0) { *((volatile uint8_t *)hwfifo) = *src++; len--; HWFIFO_ADDR_NEXT_N(hwfifo, , 1); } - #else + #else // Write odd bytes i.e 1 byte for 16 bit or 1-3 bytes for 32 bit if (len > 0) { @@ -173,13 +188,16 @@ void tu_hwfifo_write(volatile void *hwfifo, const uint8_t *src, uint16_t len, co stride_write(hwfifo, &tmp, data_stride); HWFIFO_ADDR_NEXT(hwfifo, ); } + #endif #endif } #endif +//------------- Read -------------// #ifndef CFG_TUSB_FIFO_HWFIFO_CUSTOM_READ -static inline void stride_read(const volatile void *hwfifo, void *dest, uint8_t data_stride) { +TU_ATTR_ALWAYS_INLINE static inline void stride_read(const volatile void *hwfifo, void *dest, uint8_t data_stride) { (void)data_stride; // possible unused + #if CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE & 4 #if CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE != 4 if (data_stride == 4) @@ -197,6 +215,10 @@ static inline void stride_read(const volatile void *hwfifo, void *dest, uint8_t tu_unaligned_write16(dest, *((const volatile uint16_t *)hwfifo)); } #endif + + #if CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE == 1 + *(uint8_t *)dest = *((const volatile uint8_t *)hwfifo); + #endif } void tu_hwfifo_read(const volatile void *hwfifo, uint8_t *dest, uint16_t len, const tu_hwfifo_access_t *access_mode) { @@ -209,7 +231,8 @@ void tu_hwfifo_read(const volatile void *hwfifo, uint8_t *dest, uint16_t len, co HWFIFO_ADDR_NEXT(hwfifo, const); } - #ifdef CFG_TUSB_FIFO_HWFIFO_DATA_ODD_16BIT_ACCESS + #if CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE > 1 + #ifdef CFG_TUSB_FIFO_HWFIFO_DATA_ODD_16BIT_ACCESS // 16-bit access is allowed for odd bytes if (len >= 2) { tu_unaligned_write16(dest, *((const volatile uint16_t *)hwfifo)); @@ -235,6 +258,7 @@ void tu_hwfifo_read(const volatile void *hwfifo, uint8_t *dest, uint16_t len, co HWFIFO_ADDR_NEXT(hwfifo, const); } #endif + #endif } #endif @@ -251,7 +275,11 @@ static void hwff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uin tu_hwfifo_read(hwfifo, ff_buf, n, access_mode); } else { // Wrap around case - + #if CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE == 1 + tu_hwfifo_read(hwfifo, ff_buf, lin_bytes, access_mode); // linear part + HWFIFO_ADDR_NEXT_N(hwfifo, const, lin_bytes); + tu_hwfifo_read(hwfifo, f->buffer, wrap_bytes, access_mode); // wrapped part + #else // Write full words to linear part of buffer const uint8_t data_stride = access_mode->data_stride; const uint32_t odd_mask = data_stride - 1; @@ -286,6 +314,7 @@ static void hwff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uin if (wrap_bytes > 0) { tu_hwfifo_read(hwfifo, ff_buf, wrap_bytes, access_mode); } + #endif } } @@ -303,11 +332,15 @@ static void hwff_pull_n(const tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t tu_hwfifo_write(hwfifo, ff_buf, n, access_mode); } else { // Wrap around case - + #if CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE == 1 + tu_hwfifo_write(hwfifo, ff_buf, lin_bytes, access_mode); // linear part + HWFIFO_ADDR_NEXT_N(hwfifo, , lin_bytes); + tu_hwfifo_write(hwfifo, f->buffer, wrap_bytes, access_mode); // wrapped part + #else // Read full words from linear part const uint8_t data_stride = access_mode->data_stride; const uint32_t odd_mask = data_stride - 1; - uint16_t lin_even = lin_bytes & ~odd_mask; + uint16_t lin_even = lin_bytes & ~odd_mask; tu_hwfifo_write(hwfifo, ff_buf, lin_even, access_mode); HWFIFO_ADDR_NEXT_N(hwfifo, , lin_even); ff_buf += lin_even; @@ -338,10 +371,15 @@ static void hwff_pull_n(const tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t if (wrap_bytes > 0) { tu_hwfifo_write(hwfifo, ff_buf, wrap_bytes, access_mode); } + #endif } } #endif +//--------------------------------------------------------------------+ +// Pull & Push +// copy data to/from fifo without updating read/write pointers +//--------------------------------------------------------------------+ // send n items to fifo WITHOUT updating write pointer static void ff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uint16_t wr_ptr) { uint16_t lin_bytes = f->depth - wr_ptr; @@ -787,6 +825,6 @@ void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info) { } else { info->linear.len = f->depth - wr_ptr; info->wrapped.len = remain - info->linear.len; // Remaining length - n already was limited to remain or FIFO depth - info->wrapped.ptr = f->buffer; // Always start of buffer + info->wrapped.ptr = f->buffer; // Always start of buffer } } diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index 71d5cf19c..f25d808d4 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -502,7 +502,15 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to (void)rhport; (void)is_isr; hw_endpoint_t *ep = hw_endpoint_get_by_addr(ep_addr); - hw_endpoint_xfer_start(ep, buffer, total_bytes); + hw_endpoint_xfer_start(ep, buffer, NULL, total_bytes); + return true; +} + +bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t *ff, uint16_t total_bytes, bool is_isr) { + (void)rhport; + (void)is_isr; + hw_endpoint_t *ep = hw_endpoint_get_by_addr(ep_addr); + hw_endpoint_xfer_start(ep, NULL, ff, total_bytes); return true; } diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index 7bf247ced..06c0ce340 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -511,7 +511,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *b // sie ctrl registers. Otherwise, interrupt ep registers should // already be configured if (ep == &epx) { - hw_endpoint_xfer_start(ep, buffer, buflen); + hw_endpoint_xfer_start(ep, buffer, NULL, buflen); // That has set up buffer control, endpoint control etc // for host we have to initiate the transfer @@ -527,7 +527,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *b busy_wait_at_least_cycles(12); usb_hw->sie_ctrl = flags; } else { - hw_endpoint_xfer_start(ep, buffer, buflen); + hw_endpoint_xfer_start(ep, buffer, NULL, buflen); } return true; diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index 8f91ecf22..bde45db1b 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -35,7 +35,7 @@ //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF PROTOTYPE //--------------------------------------------------------------------+ -static void hwep_xfer_sync(hw_endpoint_t *ep); +static void sync_xfer(hw_endpoint_t *ep); #if TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX static bool e15_is_critical_frame_period(struct hw_endpoint *ep); @@ -55,6 +55,16 @@ static void unaligned_memcpy(void *dst, const void *src, size_t n) { } } +void tu_hwfifo_write(volatile void *hwfifo, const uint8_t *src, uint16_t len, const tu_hwfifo_access_t *access_mode) { + (void)access_mode; + unaligned_memcpy((void *)(uintptr_t)hwfifo, src, len); +} + +void tu_hwfifo_read(const volatile void *hwfifo, uint8_t *dest, uint16_t len, const tu_hwfifo_access_t *access_mode) { + (void)access_mode; + unaligned_memcpy(dest, (const void *)(uintptr_t)hwfifo, len); +} + void rp2usb_init(void) { // Reset usb controller reset_block(RESETS_RESET_USBCTRL_BITS); @@ -127,9 +137,16 @@ static uint32_t __tusb_irq_path_func(prepare_ep_buffer)(struct hw_endpoint *ep, ep->next_pid ^= 1u; if (!is_rx) { - // Copy data from user buffer to hw buffer - unaligned_memcpy(ep->hw_data_buf + buf_id * 64, ep->user_buf, buflen); - ep->user_buf += buflen; + if (buflen) { + // Copy data from user buffer/fifo to hw buffer + uint8_t *hw_buf = ep->hw_data_buf + buf_id * 64; + if (ep->is_xfer_fifo) { + tu_hwfifo_write_from_fifo(hw_buf, ep->user_fifo, buflen, NULL); + } else { + unaligned_memcpy(hw_buf, ep->user_buf, buflen); + ep->user_buf += buflen; + } + } // Mark as full buf_ctrl |= USB_BUF_CTRL_FULL; @@ -152,7 +169,6 @@ static uint32_t __tusb_irq_path_func(prepare_ep_buffer)(struct hw_endpoint *ep, // Prepare buffer control register value void __tusb_irq_path_func(hw_endpoint_start_next_buffer)(struct hw_endpoint* ep) { const tusb_dir_t dir = tu_edpt_dir(ep->ep_addr); - bool is_rx; bool is_host = false; io_rw_32 *ep_ctrl_reg; @@ -211,7 +227,7 @@ void __tusb_irq_path_func(hw_endpoint_start_next_buffer)(struct hw_endpoint* ep) hwbuf_ctrl_set(buf_ctrl_reg, buf_ctrl); } -void hw_endpoint_xfer_start(struct hw_endpoint* ep, uint8_t* buffer, uint16_t total_len) { +void hw_endpoint_xfer_start(struct hw_endpoint *ep, uint8_t *buffer, tu_fifo_t *ff, uint16_t total_len) { hw_endpoint_lock_update(ep, 1); if (ep->active) { @@ -224,7 +240,14 @@ void hw_endpoint_xfer_start(struct hw_endpoint* ep, uint8_t* buffer, uint16_t to ep->remaining_len = total_len; ep->xferred_len = 0; ep->active = true; - ep->user_buf = buffer; + + if (ff != NULL) { + ep->user_fifo = ff; + ep->is_xfer_fifo = true; + } else { + ep->user_buf = buffer; + ep->is_xfer_fifo = false; + } #if TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX if (ep->e15_bulk_in) { @@ -256,17 +279,20 @@ static uint16_t __tusb_irq_path_func(sync_ep_buffer)(hw_endpoint_t *ep, io_rw_32 // We are continuing a transfer here. If we are TX, we have successfully // sent some data can increase the length we have sent assert(!(buf_ctrl & USB_BUF_CTRL_FULL)); - - ep->xferred_len = (uint16_t) (ep->xferred_len + xferred_bytes); } else { // If we have received some data, so can increase the length // we have received AFTER we have copied it to the user buffer at the appropriate offset assert(buf_ctrl & USB_BUF_CTRL_FULL); - unaligned_memcpy(ep->user_buf, ep->hw_data_buf + buf_id * 64, xferred_bytes); - ep->xferred_len = (uint16_t) (ep->xferred_len + xferred_bytes); - ep->user_buf += xferred_bytes; + uint8_t *hw_buf = ep->hw_data_buf + buf_id * 64; + if (ep->is_xfer_fifo) { + tu_hwfifo_read_to_fifo(hw_buf, ep->user_fifo, xferred_bytes, NULL); + } else { + unaligned_memcpy(ep->user_buf, hw_buf, xferred_bytes); + ep->user_buf += xferred_bytes; + } } + ep->xferred_len += xferred_bytes; // Short packet if (xferred_bytes < ep->wMaxPacketSize) { @@ -278,7 +304,7 @@ static uint16_t __tusb_irq_path_func(sync_ep_buffer)(hw_endpoint_t *ep, io_rw_32 } // Update hw endpoint struct with info from hardware after a buff status interrupt -static void __tusb_irq_path_func(hwep_xfer_sync)(hw_endpoint_t *ep) { +static void __tusb_irq_path_func(sync_xfer)(hw_endpoint_t *ep) { // const uint8_t ep_num = tu_edpt_number(ep->ep_addr); const tusb_dir_t dir = tu_edpt_dir(ep->ep_addr); @@ -350,8 +376,7 @@ bool __tusb_irq_path_func(hw_endpoint_xfer_continue)(struct hw_endpoint* ep) { panic("Can't continue xfer on inactive ep %02X", ep->ep_addr); } - // Update EP struct from hardware state - hwep_xfer_sync(ep); + sync_xfer(ep); // Update EP struct from hardware state // Now we have synced our state with the hardware. Is there more data to transfer? // If we are done then notify tinyusb diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.h b/src/portable/raspberrypi/rp2040/rp2040_usb.h index 944d604bc..cce868540 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.h +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.h @@ -1,14 +1,16 @@ #ifndef RP2040_COMMON_H_ #define RP2040_COMMON_H_ -#include "common/tusb_common.h" - #include "pico.h" #include "hardware/structs/usb.h" #include "hardware/irq.h" #include "hardware/resets.h" #include "hardware/timer.h" +#include "common/tusb_common.h" +#include "osal/osal.h" +#include "common/tusb_fifo.h" + #if defined(RP2040_USB_HOST_MODE) && defined(RP2040_USB_DEVICE_MODE) #error TinyUSB device and host mode not supported at the same time #endif @@ -63,32 +65,31 @@ typedef struct hw_endpoint { uint8_t ep_addr; uint8_t next_pid; uint8_t transfer_type; - - bool active; // transferring data + bool active; // transferring data + bool is_xfer_fifo; // transfer using fifo #if TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX bool e15_bulk_in; // Errata15 device bulk in uint8_t pending; // Transfer scheduled but not active #endif +#if CFG_TUH_ENABLED + bool configured; // Is this a valid struct + uint8_t dev_addr; + uint8_t interrupt_num; // for host interrupt endpoints +#endif + uint16_t wMaxPacketSize; uint8_t *hw_data_buf; // Buffer pointer in usb dpram - // Current transfer information - uint8_t *user_buf; // User buffer in main memory + // transfer info + union { + uint8_t *user_buf; // User buffer in main memory + tu_fifo_t *user_fifo; + }; uint16_t remaining_len; uint16_t xferred_len; -#if CFG_TUH_ENABLED - // Is this a valid struct - bool configured; - - // Only needed for host - uint8_t dev_addr; - - // If interrupt endpoint - uint8_t interrupt_num; -#endif } hw_endpoint_t; #if TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX @@ -102,7 +103,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool rp2usb_is_host_mode(void) { return (usb_hw->main_ctrl & USB_MAIN_CTRL_HOST_NDEVICE_BITS) ? true : false; } -void hw_endpoint_xfer_start(struct hw_endpoint *ep, uint8_t *buffer, uint16_t total_len); +void hw_endpoint_xfer_start(struct hw_endpoint *ep, uint8_t *buffer, tu_fifo_t *ff, uint16_t total_len); bool hw_endpoint_xfer_continue(struct hw_endpoint *ep); void hw_endpoint_reset_transfer(struct hw_endpoint *ep); void hw_endpoint_start_next_buffer(struct hw_endpoint *ep); diff --git a/src/tusb_option.h b/src/tusb_option.h index e0a52593f..abf5e0608 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -272,6 +272,25 @@ // USBIP //--------------------------------------------------------------------+ +//------------- ChipIdea -------------// +// 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 + #endif + #define CFG_TUD_CI_HS_VBUS_CHARGE CFG_TUD_CI_HS_VBUS_CHARGE_DEFAULT +#endif + +// CI_HS support FIFO transfer if endpoint buffer is 4k aligned and size is multiple of 4k, also DCACHE is disabled +#ifndef CFG_TUD_CI_HS_EPBUF_4K_ALIGNED + #define CFG_TUD_CI_HS_EPBUF_4K_ALIGNED 0 +#endif + +#if CFG_TUD_CI_HS_EPBUF_4K_ALIGNED && !CFG_TUD_MEM_DCACHE_ENABLE + #define CFG_TUD_EDPT_DEDICATED_HWFIFO 1 +#endif + //------------- DWC2 -------------// // DMA mode for device #ifndef CFG_TUD_DWC2_DMA_ENABLE @@ -317,41 +336,6 @@ #define CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE 0 // fixed hwfifo address #endif -//------------- ChipIdea -------------// -// 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 - #endif - #define CFG_TUD_CI_HS_VBUS_CHARGE CFG_TUD_CI_HS_VBUS_CHARGE_DEFAULT -#endif - -// CI_HS support FIFO transfer if endpoint buffer is 4k aligned and size is multiple of 4k, also DCACHE is disabled -#ifndef CFG_TUD_CI_HS_EPBUF_4K_ALIGNED - #define CFG_TUD_CI_HS_EPBUF_4K_ALIGNED 0 -#endif - -#if CFG_TUD_CI_HS_EPBUF_4K_ALIGNED && !CFG_TUD_MEM_DCACHE_ENABLE - #define CFG_TUD_EDPT_DEDICATED_HWFIFO 1 -#endif - -//------------- Raspberry Pi -------------// -// Enable PIO-USB software host controller -#ifndef CFG_TUH_RPI_PIO_USB - #define CFG_TUH_RPI_PIO_USB 0 -#endif - -#ifndef CFG_TUD_RPI_PIO_USB - #define CFG_TUD_RPI_PIO_USB 0 -#endif - -//------------ MAX3421 -------------// -// Enable MAX3421 USB host controller -#ifndef CFG_TUH_MAX3421 - #define CFG_TUH_MAX3421 0 -#endif - //------------ FSDEV --------------// #if defined(TUP_USBIP_FSDEV) #define CFG_TUD_EDPT_DEDICATED_HWFIFO 1 @@ -368,6 +352,12 @@ #endif #endif +//------------ MAX3421 -------------// +// Enable MAX3421 USB host controller +#ifndef CFG_TUH_MAX3421 + #define CFG_TUH_MAX3421 0 +#endif + //------------ MUSB --------------// #if defined(TUP_USBIP_MUSB) #define CFG_TUD_EDPT_DEDICATED_HWFIFO 1 @@ -375,13 +365,30 @@ #define CFG_TUSB_FIFO_HWFIFO_DATA_ODD_16BIT_ACCESS // allow odd 16bit access #define CFG_TUSB_FIFO_HWFIFO_DATA_ODD_8BIT_ACCESS // allow odd 8bit access #define CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE 0 // fixed hwfifo +#endif + +//------------- Raspberry Pi -------------// +// Enable PIO-USB software host controller +#ifndef CFG_TUH_RPI_PIO_USB + #define CFG_TUH_RPI_PIO_USB 0 +#endif + +#ifndef CFG_TUD_RPI_PIO_USB + #define CFG_TUD_RPI_PIO_USB 0 +#endif +#if (CFG_TUSB_MCU == OPT_MCU_RP2040) && !CFG_TUD_RPI_PIO_USB + #define CFG_TUD_EDPT_DEDICATED_HWFIFO 1 + #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE 1 + #define CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE 1 + #define CFG_TUSB_FIFO_HWFIFO_CUSTOM_WRITE + #define CFG_TUSB_FIFO_HWFIFO_CUSTOM_READ #endif //------------ RUSB2 --------------// #if defined(TUP_USBIP_RUSB2) #define CFG_TUD_EDPT_DEDICATED_HWFIFO 1 - #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE (2 | (TUD_OPT_HIGH_SPEED ? 4 : 0)) // 16 bit and 32 bit data if highspeed + #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE (2 | (TUD_OPT_HIGH_SPEED ? 4 : 0)) // 16 bit and 32 bit if highspeed #define CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE 0 #define CFG_TUSB_FIFO_HWFIFO_CUSTOM_WRITE // custom write since rusb2 can change access width 32 -> 16 and can write // odd byte with byte access -- cgit v1.3.1 From 09b8f4008450e55caea2f8ee559a3d0abcd87a36 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 9 Jan 2026 23:34:00 +0700 Subject: remove transfer_type from hw_endpoint --- hw/bsp/rp2040/family.cmake | 1 + src/portable/raspberrypi/rp2040/dcd_rp2040.c | 1 - src/portable/raspberrypi/rp2040/rp2040_usb.c | 12 ++++++------ src/portable/raspberrypi/rp2040/rp2040_usb.h | 1 - 4 files changed, 7 insertions(+), 8 deletions(-) (limited to 'src/portable') diff --git a/hw/bsp/rp2040/family.cmake b/hw/bsp/rp2040/family.cmake index 40eee082d..e617ab3ca 100644 --- a/hw/bsp/rp2040/family.cmake +++ b/hw/bsp/rp2040/family.cmake @@ -251,6 +251,7 @@ function(family_configure_target TARGET RTOS) family_flash_jlink(${TARGET}) # Generate linkermap target and post build. LINKERMAP_OPTION can be set with -D to change default options + family_add_bloaty(${TARGET}) family_add_linkermap(${TARGET}) endfunction() diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index f25d808d4..240e6c727 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -74,7 +74,6 @@ static void hw_endpoint_init(hw_endpoint_t *ep, uint8_t ep_addr, uint16_t wMaxPa ep->ep_addr = ep_addr; ep->next_pid = 0u; ep->wMaxPacketSize = wMaxPacketSize; - ep->transfer_type = transfer_type; // Clear existing buffer control state io_rw_32 *buf_ctrl_reg = hwbuf_ctrl_reg_device(ep); diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index bde45db1b..3b65f57a4 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -47,22 +47,20 @@ static bool e15_is_critical_frame_period(struct hw_endpoint *ep); // Implementation //--------------------------------------------------------------------+ // Provide own byte by byte memcpy as not all copies are aligned -static void unaligned_memcpy(void *dst, const void *src, size_t n) { - uint8_t *dst_byte = (uint8_t*)dst; - const uint8_t *src_byte = (const uint8_t*)src; +static void unaligned_memcpy(uint8_t *dst, const uint8_t *src, size_t n) { while (n--) { - *dst_byte++ = *src_byte++; + *dst++ = *src++; } } void tu_hwfifo_write(volatile void *hwfifo, const uint8_t *src, uint16_t len, const tu_hwfifo_access_t *access_mode) { (void)access_mode; - unaligned_memcpy((void *)(uintptr_t)hwfifo, src, len); + unaligned_memcpy((uint8_t *)(uintptr_t)hwfifo, src, len); } void tu_hwfifo_read(const volatile void *hwfifo, uint8_t *dest, uint16_t len, const tu_hwfifo_access_t *access_mode) { (void)access_mode; - unaligned_memcpy(dest, (const void *)(uintptr_t)hwfifo, len); + unaligned_memcpy(dest, (const uint8_t *)(uintptr_t)hwfifo, len); } void rp2usb_init(void) { @@ -141,6 +139,7 @@ static uint32_t __tusb_irq_path_func(prepare_ep_buffer)(struct hw_endpoint *ep, // Copy data from user buffer/fifo to hw buffer uint8_t *hw_buf = ep->hw_data_buf + buf_id * 64; if (ep->is_xfer_fifo) { + // not in sram, may mess up timing with E15 workaround tu_hwfifo_write_from_fifo(hw_buf, ep->user_fifo, buflen, NULL); } else { unaligned_memcpy(hw_buf, ep->user_buf, buflen); @@ -286,6 +285,7 @@ static uint16_t __tusb_irq_path_func(sync_ep_buffer)(hw_endpoint_t *ep, io_rw_32 uint8_t *hw_buf = ep->hw_data_buf + buf_id * 64; if (ep->is_xfer_fifo) { + // not in sram, may mess up timing with E15 workaround tu_hwfifo_read_to_fifo(hw_buf, ep->user_fifo, xferred_bytes, NULL); } else { unaligned_memcpy(ep->user_buf, hw_buf, xferred_bytes); diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.h b/src/portable/raspberrypi/rp2040/rp2040_usb.h index cce868540..c03dc34b2 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.h +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.h @@ -64,7 +64,6 @@ typedef struct hw_endpoint { uint8_t ep_addr; uint8_t next_pid; - uint8_t transfer_type; bool active; // transferring data bool is_xfer_fifo; // transfer using fifo -- cgit v1.3.1 From 104d3f2545e460ead95dc8482fcadcf98c3749e1 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Wed, 14 Jan 2026 00:18:26 +0100 Subject: bsp: add TI EK-TM4C1294XL Signed-off-by: HiFiPhile --- docs/reference/boards.rst | 1 + examples/device/dfu/skip.txt | 2 +- hw/bsp/BoardPresets.json | 44 ++++++++++++++ hw/bsp/tm4c/FreeRTOSConfig/FreeRTOSConfig.h | 8 ++- hw/bsp/tm4c/boards/ek_tm4c123gxl/board.h | 6 ++ hw/bsp/tm4c/boards/ek_tm4c123gxl/tm4c123.ld | 2 +- hw/bsp/tm4c/boards/ek_tm4c1294xl/TM4C1294NC.icf | 28 +++++++++ hw/bsp/tm4c/boards/ek_tm4c1294xl/board.cmake | 13 +++++ hw/bsp/tm4c/boards/ek_tm4c1294xl/board.h | 75 ++++++++++++++++++++++++ hw/bsp/tm4c/boards/ek_tm4c1294xl/board.mk | 16 ++++++ hw/bsp/tm4c/boards/ek_tm4c1294xl/tm4c1294nc.ld | 66 +++++++++++++++++++++ hw/bsp/tm4c/family.c | 76 ++++++++++++++++++++----- hw/bsp/tm4c/family.cmake | 14 ++--- hw/bsp/tm4c/family.mk | 6 +- src/portable/mentor/musb/musb_ti.h | 5 +- src/portable/mentor/musb/musb_type.h | 2 +- 16 files changed, 333 insertions(+), 31 deletions(-) create mode 100644 hw/bsp/tm4c/boards/ek_tm4c1294xl/TM4C1294NC.icf create mode 100644 hw/bsp/tm4c/boards/ek_tm4c1294xl/board.cmake create mode 100644 hw/bsp/tm4c/boards/ek_tm4c1294xl/board.h create mode 100644 hw/bsp/tm4c/boards/ek_tm4c1294xl/board.mk create mode 100644 hw/bsp/tm4c/boards/ek_tm4c1294xl/tm4c1294nc.ld (limited to 'src/portable') diff --git a/docs/reference/boards.rst b/docs/reference/boards.rst index cacf52e1a..09c90e08f 100644 --- a/docs/reference/boards.rst +++ b/docs/reference/boards.rst @@ -333,6 +333,7 @@ Board Name Family URL msp_exp430f5529lp MSP430F5529 LaunchPad msp430 https://www.ti.com/tool/MSP-EXP430F5529LP msp_exp432e401y MSP432E401Y LaunchPad msp432e4 https://www.ti.com/tool/MSP-EXP432E401Y ek_tm4c123gxl TM4C123G LaunchPad tm4c https://www.ti.com/tool/EK-TM4C123GXL +ek_tm4c1294xl TM4C1294 LaunchPad tm4c https://www.ti.com/tool/EK-TM4C1294XL ================= ===================== ======== ========================================= ====== Tomu diff --git a/examples/device/dfu/skip.txt b/examples/device/dfu/skip.txt index 9dde06c30..79d3da9d2 100644 --- a/examples/device/dfu/skip.txt +++ b/examples/device/dfu/skip.txt @@ -1,3 +1,3 @@ -mcu:TM4C123 +mcu:TM4C mcu:BCM2835 family:espressif diff --git a/hw/bsp/BoardPresets.json b/hw/bsp/BoardPresets.json index 440ef8733..fabbeed93 100644 --- a/hw/bsp/BoardPresets.json +++ b/hw/bsp/BoardPresets.json @@ -174,6 +174,10 @@ "name": "ek_tm4c123gxl", "inherits": "default" }, + { + "name": "ek_tm4c1294xl", + "inherits": "default" + }, { "name": "f1c100s", "inherits": "default" @@ -718,6 +722,10 @@ "name": "stm32h745disco", "inherits": "default" }, + { + "name": "stm32h747disco", + "inherits": "default" + }, { "name": "stm32h750_weact", "inherits": "default" @@ -1108,6 +1116,11 @@ "description": "Build preset for the ek_tm4c123gxl board", "configurePreset": "ek_tm4c123gxl" }, + { + "name": "ek_tm4c1294xl", + "description": "Build preset for the ek_tm4c1294xl board", + "configurePreset": "ek_tm4c1294xl" + }, { "name": "espressif_addax_1", "description": "Build preset for the espressif_addax_1 board", @@ -1833,6 +1846,11 @@ "description": "Build preset for the stm32h745disco board", "configurePreset": "stm32h745disco" }, + { + "name": "stm32h747disco", + "description": "Build preset for the stm32h747disco board", + "configurePreset": "stm32h747disco" + }, { "name": "stm32h750_weact", "description": "Build preset for the stm32h750_weact board", @@ -2542,6 +2560,19 @@ } ] }, + { + "name": "ek_tm4c1294xl", + "steps": [ + { + "type": "configure", + "name": "ek_tm4c1294xl" + }, + { + "type": "build", + "name": "ek_tm4c1294xl" + } + ] + }, { "name": "espressif_addax_1", "steps": [ @@ -4427,6 +4458,19 @@ } ] }, + { + "name": "stm32h747disco", + "steps": [ + { + "type": "configure", + "name": "stm32h747disco" + }, + { + "type": "build", + "name": "stm32h747disco" + } + ] + }, { "name": "stm32h750_weact", "steps": [ diff --git a/hw/bsp/tm4c/FreeRTOSConfig/FreeRTOSConfig.h b/hw/bsp/tm4c/FreeRTOSConfig/FreeRTOSConfig.h index 454b085e9..b4423e269 100644 --- a/hw/bsp/tm4c/FreeRTOSConfig/FreeRTOSConfig.h +++ b/hw/bsp/tm4c/FreeRTOSConfig/FreeRTOSConfig.h @@ -44,7 +44,13 @@ // skip if included from IAR assembler #ifndef __IASMARM__ - #include "TM4C123.h" + #ifdef TM4C123GH6PM + #include "TM4C123.h" + #elif TM4C1294NCPDT + #include "TM4C129.h" + #else + #error "Unknown TM4C device" + #endif #endif /* Cortex M23/M33 port configuration. */ diff --git a/hw/bsp/tm4c/boards/ek_tm4c123gxl/board.h b/hw/bsp/tm4c/boards/ek_tm4c123gxl/board.h index c0ceb4cd8..fc0ab4c60 100644 --- a/hw/bsp/tm4c/boards/ek_tm4c123gxl/board.h +++ b/hw/bsp/tm4c/boards/ek_tm4c123gxl/board.h @@ -36,20 +36,26 @@ extern "C" { #endif +#include "TM4C123.h" + #define BOARD_UART UART0 #define BOARD_UART_PORT GPIOA +#define BTN_PORT_CLK 5 #define BOARD_BTN_PORT GPIOF #define BOARD_BTN 4 #define BOARD_BTN_Msk (1u<<4) #define BUTTON_STATE_ACTIVE 0 +#define LED_PORT_CLK 5 #define LED_PORT GPIOF #define LED_PIN_RED 1 #define LED_PIN_BLUE 2 #define LED_PIN_GREEN 3 #define LED_STATE_ON 1 +#define BOARD_LED_PIN LED_PIN_BLUE + #ifdef __cplusplus } #endif diff --git a/hw/bsp/tm4c/boards/ek_tm4c123gxl/tm4c123.ld b/hw/bsp/tm4c/boards/ek_tm4c123gxl/tm4c123.ld index 11e9608cc..3f06d8f03 100644 --- a/hw/bsp/tm4c/boards/ek_tm4c123gxl/tm4c123.ld +++ b/hw/bsp/tm4c/boards/ek_tm4c123gxl/tm4c123.ld @@ -17,7 +17,7 @@ SECTIONS .text : { . = ALIGN(4) ; - *(.vectors) + KEEP(*(.vectors)) *(.text) *(.text.*) *(.init) diff --git a/hw/bsp/tm4c/boards/ek_tm4c1294xl/TM4C1294NC.icf b/hw/bsp/tm4c/boards/ek_tm4c1294xl/TM4C1294NC.icf new file mode 100644 index 000000000..2dba41866 --- /dev/null +++ b/hw/bsp/tm4c/boards/ek_tm4c1294xl/TM4C1294NC.icf @@ -0,0 +1,28 @@ +/*###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__ = 0x00000000; +/*-Memory Regions-*/ +define symbol __ICFEDIT_region_ROM_start__ = 0x00000000; +define symbol __ICFEDIT_region_ROM_end__ = 0x000FFFFF; +define symbol __ICFEDIT_region_RAM_start__ = 0x20000000; +define symbol __ICFEDIT_region_RAM_end__ = 0x2003FFFF; +/*-Sizes-*/ +define symbol __ICFEDIT_size_cstack__ = 0x8000; +define symbol __ICFEDIT_size_heap__ = 0x10000; +/**** End of ICF editor section. ###ICF###*/ + +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 block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { }; +define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { }; + +initialize by copy { readwrite }; + +place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec }; +place in ROM_region { readonly }; +place in RAM_region { readwrite, + block CSTACK, block HEAP }; diff --git a/hw/bsp/tm4c/boards/ek_tm4c1294xl/board.cmake b/hw/bsp/tm4c/boards/ek_tm4c1294xl/board.cmake new file mode 100644 index 000000000..3e03b3f72 --- /dev/null +++ b/hw/bsp/tm4c/boards/ek_tm4c1294xl/board.cmake @@ -0,0 +1,13 @@ +set(MCU_SUB_VARIANT 129) + +set(JLINK_DEVICE TM4C1294NCPDT) +set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/tm4c1294nc.ld) +set(LD_FILE_IAR ${CMAKE_CURRENT_LIST_DIR}/TM4C1294NC.icf) + +set(OPENOCD_OPTION "-f board/ti_ek-tm4c1294xl.cfg") + +function(update_board TARGET) + target_compile_definitions(${TARGET} PUBLIC + TM4C1294NCPDT + ) +endfunction() diff --git a/hw/bsp/tm4c/boards/ek_tm4c1294xl/board.h b/hw/bsp/tm4c/boards/ek_tm4c1294xl/board.h new file mode 100644 index 000000000..4530e9430 --- /dev/null +++ b/hw/bsp/tm4c/boards/ek_tm4c1294xl/board.h @@ -0,0 +1,75 @@ +/* + * 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: TM4C1294 LaunchPad + url: https://www.ti.com/tool/EK-TM4C1294XL +*/ + +#ifndef _BOARD_H_ +#define _BOARD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +#include "TM4C129.h" + +#define BOARD_UART UART0 +#define BOARD_UART_PORT GPIOA + +#define BTN_PORT_CLK 8 +#define BOARD_BTN_PORT GPIOJ +#define BOARD_BTN 0 +#define BOARD_BTN_Msk (1u<<0) +#define BUTTON_STATE_ACTIVE 0 + +#define LED_PORT_CLK 12 +#define LED_PORT GPION +#define LED_PIN_1 1 +#define LED_PIN_2 0 +#define LED_STATE_ON 1 + +#define BOARD_LED_PIN LED_PIN_2 + +#define GPIOA GPIOA_AHB +#define GPIOB GPIOB_AHB +#define GPIOC GPIOC_AHB +#define GPIOD GPIOD_AHB +#define GPIOE GPIOE_AHB +#define GPIOF GPIOF_AHB +#define GPIOG GPIOG_AHB +#define GPIOH GPIOH_AHB +#define GPIOI GPIOI_AHB +#define GPIOJ GPIOJ_AHB + +#define GPIOA_Type GPIOA_AHB_Type + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/hw/bsp/tm4c/boards/ek_tm4c1294xl/board.mk b/hw/bsp/tm4c/boards/ek_tm4c1294xl/board.mk new file mode 100644 index 000000000..b01977674 --- /dev/null +++ b/hw/bsp/tm4c/boards/ek_tm4c1294xl/board.mk @@ -0,0 +1,16 @@ +MCU_SUB_VARIANT = 129 + +CFLAGS += -DTM4C1294NCPDT + +LD_FILE_GCC = $(BOARD_PATH)/tm4c1294nc.ld +LD_FILE_IAR = $(BOARD_PATH)/TM4C1294NC.icf + +# For flash-jlink target +JLINK_DEVICE = TM4C1294NCPDT + +# flash using openocd +OPENOCD_OPTION = -f board/ti_ek-tm4c1294xl.cfg + +UNIFLASH_OPTION = -c ${TOP}/${BOARD_PATH}/${BOARD}.ccxml -r 1 + +flash: flash-openocd diff --git a/hw/bsp/tm4c/boards/ek_tm4c1294xl/tm4c1294nc.ld b/hw/bsp/tm4c/boards/ek_tm4c1294xl/tm4c1294nc.ld new file mode 100644 index 000000000..fa4ea4dc5 --- /dev/null +++ b/hw/bsp/tm4c/boards/ek_tm4c1294xl/tm4c1294nc.ld @@ -0,0 +1,66 @@ +ENTRY(Reset_Handler) + +_estack = 0x20008000; /* end of RAM */ +/* Generate a link error if heap and stack don't fit into RAM */ +_Min_Heap_Size = 0; /* required amount of heap */ +_Min_Stack_Size = 0x1000; /* required amount of stack */ + + +MEMORY +{ + FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00100000 + SRAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00040000 +} + +SECTIONS +{ + .text : + { + . = ALIGN(4) ; + _text = . ; + KEEP(*(.isr_vector)) + *(.text) + *(.text.*) + *(.init) + *(.fini) + *(.rodata) + *(.rodata.*) + *(.ARM.exidx*) + _etext = . ; + . = ALIGN(4) ; + } >FLASH + + .data : AT(ADDR(.text) + SIZEOF(.text)) + { + _data = .; + . = ALIGN(4); + _ldata = LOADADDR (.data); + *(.data) + *(.data.*) + _edata = .; + . = ALIGN(4); + + } >SRAM + + .bss : + { + . = ALIGN(4) ; + _bss = .; + *(.bss) + *(.bss.*) + *(.COMMON) + _ebss = .; + . = ALIGN(4); + }>SRAM + + /* 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); + } >SRAM +} diff --git a/hw/bsp/tm4c/family.c b/hw/bsp/tm4c/family.c index ee1fa2a3c..ae7f22f00 100644 --- a/hw/bsp/tm4c/family.c +++ b/hw/bsp/tm4c/family.c @@ -2,7 +2,6 @@ manufacturer: Texas Instruments */ -#include "TM4C123.h" #include "bsp/board_api.h" #include "board.h" @@ -27,6 +26,9 @@ static void board_uart_init(void) { SYSCTL->RCGCUART |= (1 << 0); // Enable the clock to UART0 SYSCTL->RCGCGPIO |= (1 << 0); // Enable the clock to GPIOA + while (!(SYSCTL->PRGPIO & (1 << 0))) {} // Wait for the GPIOA clock to stabilize + while (!(SYSCTL->PRUART & (1 << 0))) {} // Wait for the UART0 clock to stabilize + GPIOA->AFSEL |= (1 << 1) | (1 << 0); // Enable the alternate function on pin PA0 & PA1 GPIOA->PCTL |= (1 << 0) | (1 << 4); // Configure the GPIOPCTL register to select UART0 in PA0 and PA1 GPIOA->DEN |= (1 << 0) | (1 << 1); // Enable the digital functionality in PA0 and PA1 @@ -44,12 +46,26 @@ static void board_uart_init(void) { UART0->CTL = (1 << 0) | (1 << 8) | (1 << 9); // UART0 Enable, Transmit Enable, Receive Enable } -static void initialize_board_led(GPIOA_Type* port, uint8_t PinMsk, uint8_t dirmsk) { - /* Enable PortF Clock */ - SYSCTL->RCGCGPIO |= (1 << 5); +static void board_button_init(GPIOA_Type* port, uint8_t PinMsk) { + /* Enable Port Clock */ + SYSCTL->RCGCGPIO |= (1 << BTN_PORT_CLK); + + /* Let the clock stabilize */ + while (!((SYSCTL->PRGPIO) & (1 << BTN_PORT_CLK))) {} + + /* Port Digital Enable */ + port->DEN |= PinMsk; + + /* Set direction */ + port->DIR &= ~PinMsk; +} + +static void board_led_init(GPIOA_Type* port, uint8_t PinMsk, uint8_t dirmsk) { + /* Enable Port Clock */ + SYSCTL->RCGCGPIO |= (1 << LED_PORT_CLK); /* Let the clock stabilize */ - while (!((SYSCTL->PRGPIO) & (1 << 5))) {} + while (!((SYSCTL->PRGPIO) & (1 << LED_PORT_CLK))) {} /* Port Digital Enable */ port->DEN |= PinMsk; @@ -71,7 +87,9 @@ static uint32_t ReadGPIOPin(GPIOA_Type* port, uint8_t pinMsk) { } void board_init(void) { +#ifdef TM4C123_H SystemCoreClockUpdate(); +#endif #if CFG_TUSB_OS == OPT_OS_NONE // 1ms tick timer @@ -83,6 +101,7 @@ void board_init(void) { NVIC_SetPriority(USB0_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY ); #endif +#ifdef TM4C123_H /* Reset USB */ SYSCTL->SRCR2 |= (1u << 16); @@ -99,7 +118,7 @@ void board_init(void) { /* USB IO Initialization */ SYSCTL->RCGCGPIO |= (1u << 3); - /* Let the clock stabilize */ + /* Let the clock stabilize */ while (!(SYSCTL->PRGPIO & (1u << 3))) {} /* USB IOs to Analog Mode */ @@ -107,16 +126,43 @@ void board_init(void) { GPIOD->DEN &= ~((1u << 4) | (1u << 5)); GPIOD->AMSEL |= ((1u << 4) | (1u << 5)); - uint8_t leds = (1 << LED_PIN_RED) | (1 << LED_PIN_BLUE) | (1 << LED_PIN_GREEN); - uint8_t dirmsk = (1 << LED_PIN_RED) | (1 << LED_PIN_BLUE) | (1 << LED_PIN_GREEN); +#else // TM4C129 + /* Reset USB */ + SYSCTL->SRUSB = 1; - /* Configure GPIO for board LED */ - initialize_board_led(LED_PORT, leds, dirmsk); + for (volatile uint8_t i = 0; i < 20; i++) {} + + SYSCTL->SRUSB = 0; - /* Configure GPIO for board switch */ - GPIOF->DIR &= ~(1 << BOARD_BTN); - GPIOF->PUR |= (1 << BOARD_BTN); - GPIOF->DEN |= (1 << BOARD_BTN); + /* Open the USB clock gate */ + SYSCTL->RCGCUSB = 1; + + /* Let the clock stabilize */ + while(!(SYSCTL->PRUSB & 1)) {} + + /* USB IO Initialization */ + SYSCTL->RCGCGPIO |= (1u << 10); + + /* Let the clock stabilize */ + while (!(SYSCTL->PRGPIO & (1u << 10))) {} + + /* USB IOs to Analog Mode */ + GPIOL->AFSEL &= ~((1u << 6) | (1u << 7)); + GPIOL->DEN &= ~((1u << 6) | (1u << 7)); + GPIOL->AMSEL |= ((1u << 6) | (1u << 7)); + + /* USB Clock Configuration */ + USB0->CC = 0x207; +#endif + + uint8_t leds = 1 << BOARD_LED_PIN; + uint8_t dirmsk = 1 << BOARD_LED_PIN; + + /* Configure GPIO for board button */ + board_button_init(BOARD_BTN_PORT, BOARD_BTN_Msk); + + /* Configure GPIO for board LED */ + board_led_init(LED_PORT, leds, dirmsk); /* Initialize board UART */ board_uart_init(); @@ -125,7 +171,7 @@ void board_init(void) { } void board_led_write(bool state) { - WriteGPIOPin(LED_PORT, (1 << LED_PIN_BLUE), state); + WriteGPIOPin(LED_PORT, (1 << BOARD_LED_PIN), state); } uint32_t board_button_read(void) { diff --git a/hw/bsp/tm4c/family.cmake b/hw/bsp/tm4c/family.cmake index 12f0448a3..9cef96b9d 100644 --- a/hw/bsp/tm4c/family.cmake +++ b/hw/bsp/tm4c/family.cmake @@ -5,14 +5,14 @@ include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) set(MCU_VARIANT tm4c${MCU_SUB_VARIANT}) set(MCU_VARIANT_UPPER TM4C${MCU_SUB_VARIANT}) -set(SDK_DIR ${TOP}/hw/mcu/ti/${MCU_VARIANT}xx) +set(SDK_DIR ${TOP}/hw/mcu/ti/tm4c) set(CMSIS_DIR ${TOP}/lib/CMSIS_5) # 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 TM4C123 CACHE INTERNAL "") +set(FAMILY_MCUS TM4C CACHE INTERNAL "") #------------------------------------ # Startup & Linker script @@ -20,7 +20,7 @@ set(FAMILY_MCUS TM4C123 CACHE INTERNAL "") set(LD_FILE_Clang ${LD_FILE_GNU}) set(STARTUP_FILE_GNU ${SDK_DIR}/Source/GCC/${MCU_VARIANT}_startup.c) set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) - +set(STARTUP_FILE_IAR ${SDK_DIR}/Source/IAR/${MCU_VARIANT}_startup.c) #------------------------------------ # Board Target #------------------------------------ @@ -29,7 +29,7 @@ function(family_add_board BOARD_TARGET) ${SDK_DIR}/Source/system_${MCU_VARIANT_UPPER}.c ) target_include_directories(${BOARD_TARGET} PUBLIC - ${SDK_DIR}/Include/${MCU_VARIANT_UPPER} + ${SDK_DIR}/Include ${CMSIS_DIR}/CMSIS/Core/Include ) @@ -41,7 +41,7 @@ endfunction() #------------------------------------ function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) - family_add_tinyusb(${TARGET} OPT_MCU_TM4C123) + family_add_tinyusb(${TARGET} OPT_MCU_TM4C${MCU_SUB_VARIANT}) target_sources(${TARGET} PUBLIC ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c @@ -72,12 +72,10 @@ function(family_configure_example TARGET RTOS) if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") endif () - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES - SKIP_LINTING ON - COMPILE_OPTIONS -w) # Flashing family_add_bin_hex(${TARGET}) + family_flash_jlink(${TARGET}) family_flash_openocd(${TARGET}) family_flash_uniflash(${TARGET}) endfunction() diff --git a/hw/bsp/tm4c/family.mk b/hw/bsp/tm4c/family.mk index 76ae785b2..bc966d98e 100644 --- a/hw/bsp/tm4c/family.mk +++ b/hw/bsp/tm4c/family.mk @@ -4,11 +4,11 @@ CPU_CORE ?= cortex-m4 MCU_VARIANT = tm4c${MCU_SUB_VARIANT} MCU_VARIANT_UPPER = TM4C${MCU_SUB_VARIANT} -SDK_DIR = hw/mcu/ti/${MCU_VARIANT}xx +SDK_DIR = hw/mcu/ti/tm4c CFLAGS += \ -flto \ - -DCFG_TUSB_MCU=OPT_MCU_TM4C123 \ + -DCFG_TUSB_MCU=OPT_MCU_TM4C${MCU_SUB_VARIANT} \ -uvectors \ # mcu driver cause following warnings @@ -18,7 +18,7 @@ LDFLAGS_GCC += --specs=nosys.specs --specs=nano.specs INC += \ $(TOP)/lib/CMSIS_5/CMSIS/Core/Include \ - $(TOP)/$(SDK_DIR)/Include/${MCU_VARIANT_UPPER} \ + $(TOP)/$(SDK_DIR)/Include \ $(TOP)/$(BOARD_PATH) SRC_C += \ diff --git a/src/portable/mentor/musb/musb_ti.h b/src/portable/mentor/musb/musb_ti.h index d17e836ee..68e89d77d 100644 --- a/src/portable/mentor/musb/musb_ti.h +++ b/src/portable/mentor/musb/musb_ti.h @@ -35,7 +35,10 @@ #include "TM4C123.h" #define FIFO0_WORD FIFO0 #define FIFO1_WORD FIFO1 -//#elif CFG_TUSB_MCU == OPT_MCU_TM4C129 +#elif CFG_TUSB_MCU == OPT_MCU_TM4C129 + #include "TM4C129.h" + #define FIFO0_WORD FIFOA + #define FIFO1_WORD FIFOB #elif CFG_TUSB_MCU == OPT_MCU_MSP432E4 #include "msp.h" #else diff --git a/src/portable/mentor/musb/musb_type.h b/src/portable/mentor/musb/musb_type.h index 4e448c0ed..b2f6492fa 100644 --- a/src/portable/mentor/musb/musb_type.h +++ b/src/portable/mentor/musb/musb_type.h @@ -147,7 +147,7 @@ typedef struct TU_ATTR_PACKED { TU_VERIFY_STATIC(sizeof(musb_ep_csr_t) == 16, "size is not correct"); -typedef struct TU_ATTR_PACKED { +typedef struct { //------------- Common -------------// __IO uint8_t faddr; // 0x00: FADDR union { -- cgit v1.3.1 From c1a506793b0617f91ec2317af6ea6ed53192bccc Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Wed, 14 Jan 2026 00:19:18 +0100 Subject: dcd/musb: fix IAR build Signed-off-by: HiFiPhile --- src/portable/mentor/musb/dcd_musb.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'src/portable') diff --git a/src/portable/mentor/musb/dcd_musb.c b/src/portable/mentor/musb/dcd_musb.c index 3827be318..f0c5aa722 100644 --- a/src/portable/mentor/musb/dcd_musb.c +++ b/src/portable/mentor/musb/dcd_musb.c @@ -175,9 +175,8 @@ static void process_setup_packet(uint8_t rhport) { // Read setup packet uint32_t *p = (void*)&_dcd.setup_packet; - volatile uint32_t *fifo_ptr = &musb_regs->fifo[0]; - p[0] = *fifo_ptr; - p[1] = *fifo_ptr; + p[0] = musb_regs->fifo[0]; + p[1] = musb_regs->fifo[0]; _dcd.pipe0.buf = NULL; _dcd.pipe0.length = 0; @@ -218,7 +217,7 @@ static bool handle_xfer_in(uint8_t rhport, uint_fast8_t ep_addr) tu_hwfifo_write_from_fifo(fifo_ptr, (tu_fifo_t *)buf, len, NULL); } else { tu_hwfifo_write(fifo_ptr, buf, len, NULL); - pipe->buf = buf + len; + pipe->buf = (uint8_t*)buf + len; } pipe->remaining = rem - len; } @@ -249,7 +248,7 @@ static bool handle_xfer_out(uint8_t rhport, uint_fast8_t ep_addr) tu_hwfifo_read_to_fifo(fifo_ptr, (tu_fifo_t *)buf, len, NULL); } else { tu_hwfifo_read(fifo_ptr, buf, len, NULL); - pipe->buf = buf + len; + pipe->buf = (uint8_t*)buf + len; } pipe->remaining = rem - len; } -- cgit v1.3.1 From 0f3c90b445e8d28b7925b629157ffe22b5d385ff Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 15 Jan 2026 10:53:06 +0700 Subject: draft: hcd control work --- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 266 +++++++++++++-------------- src/portable/raspberrypi/rp2040/rp2040_usb.h | 5 +- 2 files changed, 126 insertions(+), 145 deletions(-) (limited to 'src/portable') diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index 06c0ce340..8e3379622 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -56,21 +56,33 @@ static_assert(PICO_USB_HOST_INTERRUPT_ENDPOINTS <= USB_MAX_ENDPOINTS, ""); static struct hw_endpoint ep_pool[1 + PICO_USB_HOST_INTERRUPT_ENDPOINTS]; #define epx (ep_pool[0]) +static hw_endpoint_t *ep_active = NULL; + // Flags we set by default in sie_ctrl (we add other bits on top) enum { SIE_CTRL_BASE = USB_SIE_CTRL_SOF_EN_BITS | USB_SIE_CTRL_KEEP_ALIVE_EN_BITS | USB_SIE_CTRL_PULLDOWN_EN_BITS | USB_SIE_CTRL_EP0_INT_1BUF_BITS }; -static struct hw_endpoint *get_dev_ep(uint8_t dev_addr, uint8_t ep_addr) { - uint8_t num = tu_edpt_number(ep_addr); - if (num == 0) { - return &epx; +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ + +static hw_endpoint_t *edpt_alloc(void) { + for (uint i = 0; i < TU_ARRAY_SIZE(ep_pool); i++) { + hw_endpoint_t *ep = &ep_pool[i]; + if (ep->wMaxPacketSize == 0) { + return ep; + } } + return NULL; +} - for (uint32_t i = 1; i < TU_ARRAY_SIZE(ep_pool); i++) { +static hw_endpoint_t *edpt_find(uint8_t daddr, uint8_t ep_addr) { + for (uint32_t i = 0; i < TU_ARRAY_SIZE(ep_pool); i++) { struct hw_endpoint *ep = &ep_pool[i]; - if (ep->configured && (ep->dev_addr == dev_addr) && (ep->ep_addr == ep_addr)) { + if ((ep->dev_addr == daddr) && (ep->wMaxPacketSize > 0) && + (ep->ep_addr == ep_addr || (tu_edpt_number(ep_addr) == 0 && tu_edpt_number(ep->ep_addr) == 0))) { return ep; } } @@ -78,6 +90,10 @@ static struct hw_endpoint *get_dev_ep(uint8_t dev_addr, uint8_t ep_addr) { return NULL; } +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ + TU_ATTR_ALWAYS_INLINE static inline uint8_t dev_speed(void) { return (usb_hw->sie_status & USB_SIE_STATUS_SPEED_BITS) >> USB_SIE_STATUS_SPEED_LSB; } @@ -113,7 +129,7 @@ static void __tusb_irq_path_func(handle_hwbuf_status)(void) { uint32_t bit = 1u; if (buf_status & bit) { buf_status &= ~bit; - struct hw_endpoint * ep = &epx; + hw_endpoint_t *ep = ep_active; handle_hwbuf_status_bit(bit, ep); } @@ -141,91 +157,58 @@ static void __tusb_irq_path_func(handle_hwbuf_status)(void) { } } -static void __tusb_irq_path_func(hw_trans_complete)(void) -{ - if (usb_hw->sie_ctrl & USB_SIE_CTRL_SEND_SETUP_BITS) - { - pico_trace("Sent setup packet\n"); - struct hw_endpoint *ep = &epx; - assert(ep->active); - // Set transferred length to 8 for a setup packet +static void __tusb_irq_path_func(hw_trans_complete)(void) { + if (usb_hw->sie_ctrl & USB_SIE_CTRL_SEND_SETUP_BITS) { + hw_endpoint_t *ep = ep_active; ep->xferred_len = 8; hw_xfer_complete(ep, XFER_RESULT_SUCCESS); - } - else - { + } else { // Don't care. Will handle this in buff status return; } } -static void __tusb_irq_path_func(hcd_rp2040_irq)(void) -{ - uint32_t status = usb_hw->ints; - uint32_t handled = 0; +static void __tusb_irq_path_func(hcd_rp2040_irq)(void) { + const uint32_t status = usb_hw->ints; - if ( status & USB_INTS_HOST_CONN_DIS_BITS ) - { - handled |= USB_INTS_HOST_CONN_DIS_BITS; - - if ( dev_speed() ) - { + if (status & USB_INTS_HOST_CONN_DIS_BITS) { + if (dev_speed()) { hcd_event_device_attach(RHPORT_NATIVE, true); - } - else - { + } else { hcd_event_device_remove(RHPORT_NATIVE, true); } - // Clear speed change interrupt usb_hw_clear->sie_status = USB_SIE_STATUS_SPEED_BITS; } - if ( status & USB_INTS_STALL_BITS ) - { + if (status & USB_INTS_STALL_BITS) { // We have rx'd a stall from the device // NOTE THIS SHOULD HAVE PRIORITY OVER BUFF_STATUS // AND TRANS_COMPLETE as the stall is an alternative response // to one of those events - pico_trace("Stall REC\n"); - handled |= USB_INTS_STALL_BITS; usb_hw_clear->sie_status = USB_SIE_STATUS_STALL_REC_BITS; hw_xfer_complete(&epx, XFER_RESULT_STALLED); } - if ( status & USB_INTS_BUFF_STATUS_BITS ) - { - handled |= USB_INTS_BUFF_STATUS_BITS; - TU_LOG(2, "Buffer complete\r\n"); + if (status & USB_INTS_BUFF_STATUS_BITS) { handle_hwbuf_status(); } - if ( status & USB_INTS_TRANS_COMPLETE_BITS ) - { - handled |= USB_INTS_TRANS_COMPLETE_BITS; + if (status & USB_INTS_TRANS_COMPLETE_BITS) { usb_hw_clear->sie_status = USB_SIE_STATUS_TRANS_COMPLETE_BITS; - TU_LOG(2, "Transfer complete\r\n"); hw_trans_complete(); } - if ( status & USB_INTS_ERROR_RX_TIMEOUT_BITS ) - { - handled |= USB_INTS_ERROR_RX_TIMEOUT_BITS; + if (status & USB_INTS_ERROR_RX_TIMEOUT_BITS) { usb_hw_clear->sie_status = USB_SIE_STATUS_RX_TIMEOUT_BITS; } - if ( status & USB_INTS_ERROR_DATA_SEQ_BITS ) - { + if (status & USB_INTS_ERROR_DATA_SEQ_BITS) { usb_hw_clear->sie_status = USB_SIE_STATUS_DATA_SEQ_ERROR_BITS; TU_LOG(3, " Seq Error: [0] = 0x%04u [1] = 0x%04x\r\n", tu_u32_low16(*hwbuf_ctrl_reg_host(&epx)), tu_u32_high16(*hwbuf_ctrl_reg_host(&epx))); panic("Data Seq Error \n"); } - - if ( status ^ handled ) - { - panic("Unhandled IRQ 0x%x\n", (uint) (status ^ handled)); - } } void __tusb_irq_path_func(hcd_int_handler)(uint8_t rhport, bool in_isr) { @@ -234,54 +217,16 @@ void __tusb_irq_path_func(hcd_int_handler)(uint8_t rhport, bool in_isr) { hcd_rp2040_irq(); } -static struct hw_endpoint *_next_free_interrupt_ep(void) -{ - struct hw_endpoint * ep = NULL; - for ( uint i = 1; i < TU_ARRAY_SIZE(ep_pool); i++ ) - { - ep = &ep_pool[i]; - if ( !ep->configured ) - { - // Will be configured by hw_endpoint_init / hw_endpoint_allocate - ep->interrupt_num = (uint8_t) (i - 1); - return ep; - } - } - return ep; -} - -static hw_endpoint_t *hw_endpoint_allocate(uint8_t transfer_type) { - hw_endpoint_t *ep = NULL; - - if (transfer_type == TUSB_XFER_CONTROL) { - ep = &epx; - ep->hw_data_buf = &usbh_dpram->epx_data[0]; - } else { - // Note: even though datasheet name these "Interrupt" endpoints. These are actually - // "Asynchronous" endpoints and can be used for other type such as: Bulk (ISO need confirmation) - ep = _next_free_interrupt_ep(); - pico_info("Allocate %s ep %d\n", tu_edpt_type_str(transfer_type), ep->interrupt_num); - assert(ep); - // 0 for epx (double buffered): TODO increase to 1024 for ISO - // 2x64 for intep0 - // 3x64 for intep1 - // etc - ep->hw_data_buf = &usbh_dpram->epx_data[64 * (ep->interrupt_num + 2)]; - } - - return ep; -} - -static void hw_endpoint_init(struct hw_endpoint *ep, uint8_t dev_addr, uint8_t ep_addr, uint16_t wMaxPacketSize, - uint8_t transfer_type, uint8_t bmInterval) { - // Already has data buffer, endpoint control, and buffer control allocated at this point - assert(ep->hw_data_buf); - - uint8_t const num = tu_edpt_number(ep_addr); - tusb_dir_t const dir = tu_edpt_dir(ep_addr); - - ep->ep_addr = ep_addr; - ep->dev_addr = dev_addr; +static void hw_endpoint_init(hw_endpoint_t *ep, uint8_t dev_addr, const tusb_desc_endpoint_t *ep_desc) { + const uint8_t ep_addr = ep_desc->bEndpointAddress; + const uint16_t wMaxPacketSize = tu_edpt_packet_size(ep_desc); + const uint8_t transfer_type = ep_desc->bmAttributes.xfer; + const uint8_t bmInterval = ep_desc->bInterval; + const uint8_t num = tu_edpt_number(ep_addr); + const tusb_dir_t dir = tu_edpt_dir(ep_addr); + ep->ep_addr = ep_addr; + ep->dev_addr = dev_addr; + ep->transfer_type = transfer_type; // Response to a setup packet on EP0 starts with pid of 1 ep->next_pid = (num == 0 ? 1u : 0u); @@ -303,7 +248,6 @@ static void hw_endpoint_init(struct hw_endpoint *ep, uint8_t dev_addr, uint8_t e io_rw_32 *ctrl_reg = hwep_ctrl_reg_host(ep); *ctrl_reg = ctrl_value; pico_trace("endpoint control (0x%p) <- 0x%lx\n", ctrl_reg, ctrl_value); - ep->configured = true; if (ep != &epx) { // Endpoint has its own addr_endp and interrupt bits to be setup! @@ -376,24 +320,17 @@ bool hcd_deinit(uint8_t rhport) { return true; } -void hcd_port_reset(uint8_t rhport) -{ +void hcd_port_reset(uint8_t rhport) { (void) rhport; - pico_trace("hcd_port_reset\n"); - assert(rhport == 0); // TODO: Nothing to do here yet. Perhaps need to reset some state? } -void hcd_port_reset_end(uint8_t rhport) -{ - (void) rhport; +void hcd_port_reset_end(uint8_t rhport) { + (void)rhport; } -bool hcd_port_connect_status(uint8_t rhport) -{ +bool hcd_port_connect_status(uint8_t rhport) { (void) rhport; - pico_trace("hcd_port_connect_status\n"); - assert(rhport == 0); return usb_hw->sie_status & USB_SIE_STATUS_SPEED_BITS; } @@ -421,8 +358,8 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr) { (void) rhport; // reset epx if it is currently active with unplugged device - if (epx.configured && epx.active && epx.dev_addr == dev_addr) { - epx.configured = false; + if (epx.wMaxPacketSize > 0 && epx.active && epx.dev_addr == dev_addr) { + epx.wMaxPacketSize = 0; *hwep_ctrl_reg_host(&epx) = 0; *hwbuf_ctrl_reg_host(&epx) = 0; hw_endpoint_reset_transfer(&epx); @@ -432,13 +369,13 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr) { if (dev_addr != 0) { for (size_t i = 1; i < TU_ARRAY_SIZE(ep_pool); i++) { hw_endpoint_t *ep = &ep_pool[i]; - if (ep->dev_addr == dev_addr && ep->configured) { + if (ep->dev_addr == dev_addr && ep->wMaxPacketSize > 0) { // in case it is an interrupt endpoint, disable it usb_hw_clear->int_ep_ctrl = (1 << (ep->interrupt_num + 1)); usb_hw->int_ep_addr_ctrl[ep->interrupt_num] = 0; // unconfigure the endpoint - ep->configured = false; + ep->wMaxPacketSize = 0; *hwep_ctrl_reg_host(ep) = 0; *hwbuf_ctrl_reg_host(ep) = 0; hw_endpoint_reset_transfer(ep); @@ -468,36 +405,82 @@ void hcd_int_disable(uint8_t rhport) { //--------------------------------------------------------------------+ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, const tusb_desc_endpoint_t *ep_desc) { (void)rhport; - pico_trace("hcd_edpt_open dev_addr %d, ep_addr %d\n", dev_addr, ep_desc->bEndpointAddress); - hw_endpoint_t *ep = hw_endpoint_allocate(ep_desc->bmAttributes.xfer); + hw_endpoint_t *ep = edpt_alloc(); TU_ASSERT(ep); - hw_endpoint_init(ep, dev_addr, ep_desc->bEndpointAddress, tu_edpt_packet_size(ep_desc), ep_desc->bmAttributes.xfer, - ep_desc->bInterval); + hw_endpoint_init(ep, dev_addr, ep_desc); return true; } bool hcd_edpt_close(uint8_t rhport, uint8_t daddr, uint8_t ep_addr) { - (void) rhport; (void) daddr; (void) 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; +// xfer using epx +static bool edpt_xfer(hw_endpoint_t *ep, uint8_t *buffer, tu_fifo_t *ff, uint16_t total_len) { + const uint8_t ep_num = tu_edpt_number(ep->ep_addr); + const tusb_dir_t ep_dir = tu_edpt_dir(ep->ep_addr); - pico_trace("hcd_edpt_xfer dev_addr %d, ep_addr 0x%x, len %d\n", dev_addr, ep_addr, buflen); + ep->remaining_len = total_len; + ep->xferred_len = 0; + ep->active = true; - const uint8_t ep_num = tu_edpt_number(ep_addr); - tusb_dir_t const ep_dir = tu_edpt_dir(ep_addr); + if (ff != NULL) { + ep->user_fifo = ff; + ep->is_xfer_fifo = true; + } else { + ep->user_buf = buffer; + ep->is_xfer_fifo = false; + } + + ep_active = ep; - // Get appropriate ep. Either EPX or interrupt endpoint - struct hw_endpoint *ep = get_dev_ep(dev_addr, ep_addr); + ep->hw_data_buf = &usbh_dpram->epx_data[0]; + uint dpram_offset = hw_data_offset(ep->hw_data_buf); + // Fill in endpoint control register with buffer offset + uint32_t ctrl_value = EP_CTRL_ENABLE_BITS | EP_CTRL_INTERRUPT_PER_BUFFER | + ((uint32_t)ep->transfer_type << EP_CTRL_BUFFER_TYPE_LSB) | dpram_offset; + usbh_dpram->epx_ctrl = ctrl_value; + + hw_endpoint_start_next_buffer(ep); + + usb_hw->dev_addr_ctrl = (uint32_t)(ep->dev_addr | (ep_num << USB_ADDR_ENDP_ENDPOINT_LSB)); + uint32_t flags = USB_SIE_CTRL_START_TRANS_BITS | SIE_CTRL_BASE | + (ep_dir ? USB_SIE_CTRL_RECEIVE_DATA_BITS : USB_SIE_CTRL_SEND_DATA_BITS) | + (need_pre(ep->dev_addr) ? USB_SIE_CTRL_PREAMBLE_EN_BITS : 0); + + // START_TRANS bit on SIE_CTRL seems to exhibit the same behavior as the AVAILABLE bit + // described in RP2040 Datasheet, release 2.1, section "4.1.2.5.1. Concurrent access". + // We write everything except the START_TRANS bit first, then wait some cycles. + usb_hw->sie_ctrl = flags & ~USB_SIE_CTRL_START_TRANS_BITS; + busy_wait_at_least_cycles(12); + usb_hw->sie_ctrl = flags; + + 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; + + hw_endpoint_t *ep = edpt_find(dev_addr, ep_addr); TU_ASSERT(ep); + // Control endpoint can change direction 0x00 <-> 0x80 + if (tu_edpt_number(ep_addr) == 0) { + ep->ep_addr = ep_addr; + ep->next_pid = 1; // data and status stage start with DATA1 + } + + edpt_xfer(ep, buffer, NULL, buflen); + + #if 0 // EP should be inactive - assert(!ep->active); + // assert(!ep->active); // Control endpoint can change direction 0x00 <-> 0x80 if (ep_addr != ep->ep_addr) { @@ -529,6 +512,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *b } else { hw_endpoint_xfer_start(ep, buffer, NULL, buflen); } + #endif return true; } @@ -541,9 +525,8 @@ bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { return false; } -bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]) -{ - (void) rhport; +bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, const uint8_t setup_packet[8]) { + (void)rhport; // Copy data into setup packet buffer for (uint8_t i = 0; i < 8; i++) { @@ -551,18 +534,15 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet } // Configure EP0 struct with setup info for the trans complete - hw_endpoint_t *ep = hw_endpoint_allocate((uint8_t)TUSB_XFER_CONTROL); + // hw_endpoint_t *ep = hw_endpoint_allocate((uint8_t)TUSB_XFER_CONTROL); + hw_endpoint_t *ep = edpt_find(dev_addr, 0x00); TU_ASSERT(ep); - // EPX should be inactive - assert(!ep->active); - - // EP0 out - hw_endpoint_init(ep, dev_addr, 0x00, ep->wMaxPacketSize, 0, 0); - assert(ep->configured); - + ep->ep_addr = 0; // setup is OUT ep->remaining_len = 8; - ep->active = true; + ep->active = true; + + ep_active = ep; // Set device address usb_hw->dev_addr_ctrl = dev_addr; diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.h b/src/portable/raspberrypi/rp2040/rp2040_usb.h index c03dc34b2..682e9dab4 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.h +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.h @@ -73,12 +73,13 @@ typedef struct hw_endpoint { #endif #if CFG_TUH_ENABLED - bool configured; // Is this a valid struct uint8_t dev_addr; uint8_t interrupt_num; // for host interrupt endpoints + uint8_t transfer_type; + bool need_pre; // need preamble for low speed device behind full speed hub #endif - uint16_t wMaxPacketSize; + uint16_t wMaxPacketSize; // max packet size also indicates configured uint8_t *hw_data_buf; // Buffer pointer in usb dpram // transfer info -- cgit v1.3.1 From b03a87731cb38d7f1fbf82f07886e071f0a48bbf Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Thu, 15 Jan 2026 19:13:02 +0100 Subject: dcd/musb: fix unaligned cast Signed-off-by: HiFiPhile --- src/portable/mentor/musb/dcd_musb.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) (limited to 'src/portable') diff --git a/src/portable/mentor/musb/dcd_musb.c b/src/portable/mentor/musb/dcd_musb.c index f0c5aa722..06f62b0d3 100644 --- a/src/portable/mentor/musb/dcd_musb.c +++ b/src/portable/mentor/musb/dcd_musb.c @@ -32,12 +32,6 @@ #define MUSB_DEBUG 2 #define MUSB_REGS(rhport) ((musb_regs_t*) MUSB_BASES[rhport]) -#if __GNUC__ > 8 && defined(__ARM_FEATURE_UNALIGNED) -/* GCC warns that an address may be unaligned, even though - * the target CPU has the capability for unaligned memory access. */ -_Pragma("GCC diagnostic ignored \"-Waddress-of-packed-member\""); -#endif - #include "musb_type.h" #include "device/dcd.h" @@ -73,7 +67,10 @@ typedef struct TU_ATTR_PACKED typedef struct { - tusb_control_request_t setup_packet; + union { + tusb_control_request_t setup_packet; + uint32_t setup_buffer[2]; + }; uint16_t remaining_ctrl; /* The number of bytes remaining in data stage of control transfer. */ int8_t status_out; pipe_state_t pipe0; @@ -174,9 +171,8 @@ static void process_setup_packet(uint8_t rhport) { musb_regs_t* musb_regs = MUSB_REGS(rhport); // Read setup packet - uint32_t *p = (void*)&_dcd.setup_packet; - p[0] = musb_regs->fifo[0]; - p[1] = musb_regs->fifo[0]; + _dcd.setup_buffer[0] = musb_regs->fifo[0]; + _dcd.setup_buffer[1] = musb_regs->fifo[0]; _dcd.pipe0.buf = NULL; _dcd.pipe0.length = 0; -- cgit v1.3.1 From 8ef8ee1946f3c0f600500eb49b2b0c1352f8dcb8 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Thu, 15 Jan 2026 19:13:18 +0100 Subject: dcd/musb: fix zlp IN Signed-off-by: HiFiPhile --- src/portable/mentor/musb/dcd_musb.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/portable') diff --git a/src/portable/mentor/musb/dcd_musb.c b/src/portable/mentor/musb/dcd_musb.c index 06f62b0d3..9e6ee6f5d 100644 --- a/src/portable/mentor/musb/dcd_musb.c +++ b/src/portable/mentor/musb/dcd_musb.c @@ -189,14 +189,14 @@ static void process_setup_packet(uint8_t rhport) { } } -static bool handle_xfer_in(uint8_t rhport, uint_fast8_t ep_addr) +static bool handle_xfer_in(uint8_t rhport, uint_fast8_t ep_addr, bool is_zlp) { unsigned epnum = tu_edpt_number(ep_addr); unsigned epnum_minus1 = epnum - 1; pipe_state_t *pipe = &_dcd.pipe[tu_edpt_dir(ep_addr)][epnum_minus1]; const unsigned rem = pipe->remaining; - if (!rem) { + if (!rem && !is_zlp) { pipe->buf = NULL; return true; } @@ -268,7 +268,7 @@ static bool edpt_n_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16 pipe->remaining = total_bytes; if (dir_in) { - handle_xfer_in(rhport, ep_addr); + handle_xfer_in(rhport, ep_addr, total_bytes == 0); } else { musb_regs_t* musb_regs = MUSB_REGS(rhport); musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, epnum); @@ -445,7 +445,7 @@ static void process_edpt_n(uint8_t rhport, uint_fast8_t ep_addr) ep_csr->tx_csrl &= ~(MUSB_TXCSRL1_STALLED | MUSB_TXCSRL1_UNDRN); return; } - completed = handle_xfer_in(rhport, ep_addr); + completed = handle_xfer_in(rhport, ep_addr, false); } else { // TU_LOG1(" RX CSRL%d = %x\r\n", epn, ep_csr->rx_csrl); if (ep_csr->rx_csrl & MUSB_RXCSRL1_STALLED) { -- cgit v1.3.1 From 084ef43be65484c3fd928d1f224aed70b3d6af8a Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 16 Jan 2026 11:48:09 +0700 Subject: refactor hcd, get both control and interrupt endpoint working --- src/portable/raspberrypi/rp2040/dcd_rp2040.c | 33 ++- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 364 +++++++++++++++------------ src/portable/raspberrypi/rp2040/rp2040_usb.c | 84 +++---- src/portable/raspberrypi/rp2040/rp2040_usb.h | 65 ++--- 4 files changed, 290 insertions(+), 256 deletions(-) (limited to 'src/portable') diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index 240e6c727..8c7dc83b8 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -69,6 +69,22 @@ TU_ATTR_ALWAYS_INLINE static inline hw_endpoint_t *hw_endpoint_get_by_addr(uint8 return hw_endpoint_get(num, dir); } +TU_ATTR_ALWAYS_INLINE static inline io_rw_32 *hwep_ctrl_reg_device(struct hw_endpoint *ep) { + const uint8_t epnum = tu_edpt_number(ep->ep_addr); + const uint8_t dir = (uint8_t)tu_edpt_dir(ep->ep_addr); + if (epnum == 0) { + // EP0 has no endpoint control register because the buffer offsets are fixed and always enabled + return NULL; + } + return (dir == TUSB_DIR_IN) ? &usb_dpram->ep_ctrl[epnum - 1].in : &usb_dpram->ep_ctrl[epnum - 1].out; +} + +TU_ATTR_ALWAYS_INLINE static inline io_rw_32 *hwbuf_ctrl_reg_device(struct hw_endpoint *ep) { + const uint8_t epnum = tu_edpt_number(ep->ep_addr); + const uint8_t dir = (uint8_t)tu_edpt_dir(ep->ep_addr); + return (dir == TUSB_DIR_IN) ? &usb_dpram->ep_buf_ctrl[epnum].in : &usb_dpram->ep_buf_ctrl[epnum].out; +} + // main processing for dcd_edpt_iso_activate static void hw_endpoint_init(hw_endpoint_t *ep, uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t transfer_type) { ep->ep_addr = ep_addr; @@ -170,7 +186,10 @@ static void __tusb_irq_path_func(handle_hw_buff_status)(void) { const tusb_dir_t dir = (i & 1u) ? TUSB_DIR_OUT : TUSB_DIR_IN; hw_endpoint_t *ep = hw_endpoint_get(epnum, dir); - const bool done = hw_endpoint_xfer_continue(ep); + io_rw_32 *ep_reg = hwep_ctrl_reg_device(ep); + io_rw_32 *buf_reg = hwbuf_ctrl_reg_device(ep); + const bool done = hw_endpoint_xfer_continue(ep, ep_reg, buf_reg); + if (done) { // Notify usbd const uint16_t xferred_len = ep->xferred_len; @@ -232,7 +251,9 @@ static void __tusb_irq_path_func(dcd_rp2040_irq)(void) { hw_endpoint_lock_update(ep, 1); if (ep->pending) { ep->pending = 0; - hw_endpoint_start_next_buffer(ep); + io_rw_32 *ep_reg = hwep_ctrl_reg_device(ep); + io_rw_32 *buf_reg = hwbuf_ctrl_reg_device(ep); + hw_endpoint_start_next_buffer(ep, ep_reg, buf_reg); } hw_endpoint_lock_update(ep, -1); } @@ -501,7 +522,9 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to (void)rhport; (void)is_isr; hw_endpoint_t *ep = hw_endpoint_get_by_addr(ep_addr); - hw_endpoint_xfer_start(ep, buffer, NULL, total_bytes); + io_rw_32 *ep_reg = hwep_ctrl_reg_device(ep); + io_rw_32 *buf_reg = hwbuf_ctrl_reg_device(ep); + hw_endpoint_xfer_start(ep, ep_reg, buf_reg, buffer, NULL, total_bytes); return true; } @@ -509,7 +532,9 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t *ff, uint16_t (void)rhport; (void)is_isr; hw_endpoint_t *ep = hw_endpoint_get_by_addr(ep_addr); - hw_endpoint_xfer_start(ep, NULL, ff, total_bytes); + io_rw_32 *ep_reg = hwep_ctrl_reg_device(ep); + io_rw_32 *buf_reg = hwbuf_ctrl_reg_device(ep); + hw_endpoint_xfer_start(ep, ep_reg, buf_reg, NULL, ff, total_bytes); return true; } diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index 8e3379622..ff2db2499 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -47,42 +47,42 @@ // Low level rp2040 controller functions //--------------------------------------------------------------------+ -#ifndef PICO_USB_HOST_INTERRUPT_ENDPOINTS -#define PICO_USB_HOST_INTERRUPT_ENDPOINTS (USB_MAX_ENDPOINTS - 1) -#endif -static_assert(PICO_USB_HOST_INTERRUPT_ENDPOINTS <= USB_MAX_ENDPOINTS, ""); - // Host mode uses one shared endpoint register for non-interrupt endpoint -static struct hw_endpoint ep_pool[1 + PICO_USB_HOST_INTERRUPT_ENDPOINTS]; -#define epx (ep_pool[0]) - -static hw_endpoint_t *ep_active = NULL; +static hcd_endpoint_t ep_pool[USB_MAX_ENDPOINTS]; +static hcd_endpoint_t *epx = &ep_pool[0]; // current active endpoint // Flags we set by default in sie_ctrl (we add other bits on top) enum { - SIE_CTRL_BASE = USB_SIE_CTRL_SOF_EN_BITS | USB_SIE_CTRL_KEEP_ALIVE_EN_BITS | - USB_SIE_CTRL_PULLDOWN_EN_BITS | USB_SIE_CTRL_EP0_INT_1BUF_BITS + SIE_CTRL_BASE = USB_SIE_CTRL_PULLDOWN_EN_BITS | USB_SIE_CTRL_EP0_INT_1BUF_BITS, + SIE_CTRL_BASE_MASK = USB_SIE_CTRL_PULLDOWN_EN_BITS | USB_SIE_CTRL_EP0_INT_1BUF_BITS | USB_SIE_CTRL_SOF_EN_BITS | + USB_SIE_CTRL_KEEP_ALIVE_EN_BITS +}; + +enum { + SIE_CTRL_SPEED_DISCONNECT = 0, + SIE_CTRL_SPEED_LOW = 1, + SIE_CTRL_SPEED_FULL = 2, }; //--------------------------------------------------------------------+ // //--------------------------------------------------------------------+ -static hw_endpoint_t *edpt_alloc(void) { +static hcd_endpoint_t *edpt_alloc(void) { for (uint i = 0; i < TU_ARRAY_SIZE(ep_pool); i++) { - hw_endpoint_t *ep = &ep_pool[i]; - if (ep->wMaxPacketSize == 0) { + hcd_endpoint_t *ep = &ep_pool[i]; + if (ep->hwep.wMaxPacketSize == 0) { return ep; } } return NULL; } -static hw_endpoint_t *edpt_find(uint8_t daddr, uint8_t ep_addr) { +static hcd_endpoint_t *edpt_find(uint8_t daddr, uint8_t ep_addr) { for (uint32_t i = 0; i < TU_ARRAY_SIZE(ep_pool); i++) { - struct hw_endpoint *ep = &ep_pool[i]; - if ((ep->dev_addr == daddr) && (ep->wMaxPacketSize > 0) && - (ep->ep_addr == ep_addr || (tu_edpt_number(ep_addr) == 0 && tu_edpt_number(ep->ep_addr) == 0))) { + hcd_endpoint_t *ep = &ep_pool[i]; + if ((ep->dev_addr == daddr) && (ep->hwep.wMaxPacketSize > 0) && + (ep->hwep.ep_addr == ep_addr || (tu_edpt_number(ep_addr) == 0 && tu_edpt_number(ep->hwep.ep_addr) == 0))) { return ep; } } @@ -90,6 +90,24 @@ static hw_endpoint_t *edpt_find(uint8_t daddr, uint8_t ep_addr) { return NULL; } +// static hcd_endpoint_t* epdt_find_interrupt(uint8_t ) + +TU_ATTR_ALWAYS_INLINE static inline io_rw_32 *hwep_ctrl_reg_host(hw_endpoint_t *ep) { + if (tu_edpt_number(ep->ep_addr) == 0) { + return &usbh_dpram->epx_ctrl; + } + // return &usbh_dpram->int_ep_ctrl[ep->interrupt_num].ctrl; + return NULL; +} + +TU_ATTR_ALWAYS_INLINE static inline io_rw_32 *hwbuf_ctrl_reg_host(hw_endpoint_t *ep) { + if (tu_edpt_number(ep->ep_addr) == 0) { + return &usbh_dpram->epx_buf_ctrl; + } + // return &usbh_dpram->int_ep_buffer_ctrl[ep->interrupt_num].ctrl; + return NULL; +} + //--------------------------------------------------------------------+ // //--------------------------------------------------------------------+ @@ -104,18 +122,17 @@ TU_ATTR_ALWAYS_INLINE static inline bool need_pre(uint8_t dev_addr) { return hcd_port_speed_get(0) != tuh_speed_get(dev_addr); } -static void __tusb_irq_path_func(hw_xfer_complete)(struct hw_endpoint *ep, xfer_result_t xfer_result) { +static void __tusb_irq_path_func(hw_xfer_complete)(hcd_endpoint_t *ep, xfer_result_t xfer_result) { // Mark transfer as done before we tell the tinyusb stack - uint8_t dev_addr = ep->dev_addr; - uint8_t ep_addr = ep->ep_addr; - uint xferred_len = ep->xferred_len; - hw_endpoint_reset_transfer(ep); + uint8_t dev_addr = ep->dev_addr; + uint8_t ep_addr = ep->hwep.ep_addr; + uint xferred_len = ep->hwep.xferred_len; + hw_endpoint_reset_transfer(&ep->hwep); hcd_event_xfer_complete(dev_addr, ep_addr, xferred_len, xfer_result, true); } -static void __tusb_irq_path_func(handle_hwbuf_status_bit)(uint bit, struct hw_endpoint *ep) { - usb_hw_clear->buf_status = bit; - const bool done = hw_endpoint_xfer_continue(ep); +static void __tusb_irq_path_func(handle_hwbuf_status_bit)(hcd_endpoint_t *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg) { + const bool done = hw_endpoint_xfer_continue(&ep->hwep, ep_reg, buf_reg); if (done) { hw_xfer_complete(ep, XFER_RESULT_SUCCESS); } @@ -129,25 +146,35 @@ static void __tusb_irq_path_func(handle_hwbuf_status)(void) { uint32_t bit = 1u; if (buf_status & bit) { buf_status &= ~bit; - hw_endpoint_t *ep = ep_active; - handle_hwbuf_status_bit(bit, ep); + usb_hw_clear->buf_status = bit; + + io_rw_32 *ep_reg = &usbh_dpram->epx_ctrl; + io_rw_32 *buf_reg = &usbh_dpram->epx_buf_ctrl; + handle_hwbuf_status_bit(epx, ep_reg, buf_reg); } // Check "interrupt" (asynchronous) endpoints for both IN and OUT + // TODO use clz for better efficiency for (uint i = 1; i <= USB_HOST_INTERRUPT_ENDPOINTS && buf_status; i++) { - // EPX is bit 0 & 1 - // IEP1 IN is bit 2 - // IEP1 OUT is bit 3 - // IEP2 IN is bit 4 - // IEP2 OUT is bit 5 - // IEP3 IN is bit 6 - // IEP3 OUT is bit 7 + // EPX IN/OUT is bit 0, 1 + // IEP1 IN/OUT is bit 2, 3 + // IEP2 IN/OUT is bit 4, 5 // etc for (uint j = 0; j < 2; j++) { bit = 1 << (i * 2 + j); if (buf_status & bit) { buf_status &= ~bit; - handle_hwbuf_status_bit(bit, &ep_pool[i]); + usb_hw_clear->buf_status = bit; + + for (uint8_t e = 0; e < USB_MAX_ENDPOINTS; e++) { + hcd_endpoint_t *ep = &ep_pool[e]; + if (ep->interrupt_num == i) { + io_rw_32 *ep_reg = &usbh_dpram->int_ep_ctrl[ep->interrupt_num - 1].ctrl; + io_rw_32 *buf_reg = &usbh_dpram->int_ep_buffer_ctrl[ep->interrupt_num - 1].ctrl; + handle_hwbuf_status_bit(ep, ep_reg, buf_reg); + break; + } + } } } } @@ -157,27 +184,24 @@ static void __tusb_irq_path_func(handle_hwbuf_status)(void) { } } -static void __tusb_irq_path_func(hw_trans_complete)(void) { - if (usb_hw->sie_ctrl & USB_SIE_CTRL_SEND_SETUP_BITS) { - hw_endpoint_t *ep = ep_active; - ep->xferred_len = 8; - hw_xfer_complete(ep, XFER_RESULT_SUCCESS); - } else { - // Don't care. Will handle this in buff status - return; - } -} +// static void edpt_scheduler(void) { +// } static void __tusb_irq_path_func(hcd_rp2040_irq)(void) { const uint32_t status = usb_hw->ints; if (status & USB_INTS_HOST_CONN_DIS_BITS) { - if (dev_speed()) { - hcd_event_device_attach(RHPORT_NATIVE, true); - } else { + uint8_t speed = dev_speed(); + if (speed == SIE_CTRL_SPEED_DISCONNECT) { hcd_event_device_remove(RHPORT_NATIVE, true); + } else { + if (speed == SIE_CTRL_SPEED_LOW) { + usb_hw->sie_ctrl = SIE_CTRL_BASE | USB_SIE_CTRL_KEEP_ALIVE_EN_BITS; + } else { + usb_hw->sie_ctrl = SIE_CTRL_BASE | USB_SIE_CTRL_SOF_EN_BITS; + } + hcd_event_device_attach(RHPORT_NATIVE, true); } - usb_hw_clear->sie_status = USB_SIE_STATUS_SPEED_BITS; } @@ -187,7 +211,7 @@ static void __tusb_irq_path_func(hcd_rp2040_irq)(void) { // AND TRANS_COMPLETE as the stall is an alternative response // to one of those events usb_hw_clear->sie_status = USB_SIE_STATUS_STALL_REC_BITS; - hw_xfer_complete(&epx, XFER_RESULT_STALLED); + hw_xfer_complete(epx, XFER_RESULT_STALLED); } if (status & USB_INTS_BUFF_STATUS_BITS) { @@ -196,7 +220,14 @@ static void __tusb_irq_path_func(hcd_rp2040_irq)(void) { if (status & USB_INTS_TRANS_COMPLETE_BITS) { usb_hw_clear->sie_status = USB_SIE_STATUS_TRANS_COMPLETE_BITS; - hw_trans_complete(); + + // only handle setup packet + if (usb_hw->sie_ctrl & USB_SIE_CTRL_SEND_SETUP_BITS) { + epx->hwep.xferred_len = 8; + hw_xfer_complete(epx, XFER_RESULT_SUCCESS); + } else { + // Don't care. Will handle this in buff status + } } if (status & USB_INTS_ERROR_RX_TIMEOUT_BITS) { @@ -205,36 +236,69 @@ static void __tusb_irq_path_func(hcd_rp2040_irq)(void) { if (status & USB_INTS_ERROR_DATA_SEQ_BITS) { usb_hw_clear->sie_status = USB_SIE_STATUS_DATA_SEQ_ERROR_BITS; - TU_LOG(3, " Seq Error: [0] = 0x%04u [1] = 0x%04x\r\n", tu_u32_low16(*hwbuf_ctrl_reg_host(&epx)), - tu_u32_high16(*hwbuf_ctrl_reg_host(&epx))); panic("Data Seq Error \n"); } } void __tusb_irq_path_func(hcd_int_handler)(uint8_t rhport, bool in_isr) { - (void) rhport; - (void) in_isr; + (void)rhport; + (void)in_isr; hcd_rp2040_irq(); } -static void hw_endpoint_init(hw_endpoint_t *ep, uint8_t dev_addr, const tusb_desc_endpoint_t *ep_desc) { +static void hw_endpoint_init(hcd_endpoint_t *ep, uint8_t dev_addr, const tusb_desc_endpoint_t *ep_desc) { const uint8_t ep_addr = ep_desc->bEndpointAddress; const uint16_t wMaxPacketSize = tu_edpt_packet_size(ep_desc); const uint8_t transfer_type = ep_desc->bmAttributes.xfer; - const uint8_t bmInterval = ep_desc->bInterval; - const uint8_t num = tu_edpt_number(ep_addr); - const tusb_dir_t dir = tu_edpt_dir(ep_addr); - ep->ep_addr = ep_addr; - ep->dev_addr = dev_addr; - ep->transfer_type = transfer_type; - - // Response to a setup packet on EP0 starts with pid of 1 - ep->next_pid = (num == 0 ? 1u : 0u); - ep->wMaxPacketSize = wMaxPacketSize; - - pico_trace("hw_endpoint_init dev %d ep %02X xfer %d\n", ep->dev_addr, ep->ep_addr, transfer_type); - pico_trace("dev %d ep %02X setup buffer @ 0x%p\n", ep->dev_addr, ep->ep_addr, ep->hw_data_buf); - uint dpram_offset = hw_data_offset(ep->hw_data_buf); + // const uint8_t bmInterval = ep_desc->bInterval; + + ep->hwep.ep_addr = ep_addr; + ep->dev_addr = dev_addr; + ep->transfer_type = transfer_type; + ep->need_pre = need_pre(dev_addr); + ep->hwep.next_pid = 0u; + ep->hwep.wMaxPacketSize = wMaxPacketSize; + + if (transfer_type != TUSB_XFER_INTERRUPT) { + ep->hwep.hw_data_buf = usbh_dpram->epx_data; + } else { + // from 15 interrupt endpoints pool + uint8_t int_idx; + for (int_idx = 0; int_idx < USB_HOST_INTERRUPT_ENDPOINTS; int_idx++) { + if (!tu_bit_test(usb_hw_set->int_ep_ctrl, 1 + int_idx)) { + ep->interrupt_num = int_idx + 1; + break; + } + } + assert(int_idx < USB_HOST_INTERRUPT_ENDPOINTS); + assert(ep_desc->bInterval > 0); + + //------------- dpram buf -------------// + // 15x64 last bytes of DPRAM for interrupt endpoint buffers + ep->hwep.hw_data_buf = (uint8_t *)(USBCTRL_DPRAM_BASE + USB_DPRAM_MAX - (int_idx + 1u) * 64u); + uint32_t ep_ctrl = EP_CTRL_ENABLE_BITS | EP_CTRL_INTERRUPT_PER_BUFFER | + (TUSB_XFER_INTERRUPT << EP_CTRL_BUFFER_TYPE_LSB) | hw_data_offset(ep->hwep.hw_data_buf) | + (uint32_t)((ep_desc->bInterval - 1) << EP_CTRL_HOST_INTERRUPT_INTERVAL_LSB); + usbh_dpram->int_ep_ctrl[int_idx].ctrl = ep_ctrl; + + //------------- address control -------------// + const uint8_t epnum = tu_edpt_number(ep_addr); + uint32_t addr_ctrl = (uint32_t)(dev_addr | (epnum << USB_ADDR_ENDP1_ENDPOINT_LSB)); + if (tu_edpt_dir(ep_addr) == TUSB_DIR_OUT) { + addr_ctrl |= USB_ADDR_ENDP1_INTEP_DIR_BITS; + } + if (ep->need_pre) { + addr_ctrl |= USB_ADDR_ENDP1_INTEP_PREAMBLE_BITS; + } + usb_hw->int_ep_addr_ctrl[int_idx] = addr_ctrl; + + // Finally, activate interrupt endpoint + usb_hw_set->int_ep_ctrl |= 1u << ep->interrupt_num; + } + #if 0 + pico_trace("hw_endpoint_init dev %d ep %02X xfer %d\n", ep->dev_addr, ep->hwep.ep_addr, transfer_type); + pico_trace("dev %d ep %02X setup buffer @ 0x%p\n", ep->dev_addr, ep->hwep.ep_addr, ep->hwep.hw_data_buf); + uint dpram_offset = hw_data_offset(ep->hwep.hw_data_buf); // Bits 0-5 should be 0 assert(!(dpram_offset & 0b111111)); @@ -271,6 +335,7 @@ static void hw_endpoint_init(hw_endpoint_t *ep, uint8_t dev_addr, const tusb_des // If it's an interrupt endpoint we need to set up the buffer control register } + #endif } //--------------------------------------------------------------------+ @@ -312,11 +377,9 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { bool hcd_deinit(uint8_t rhport) { (void) rhport; - irq_remove_handler(USBCTRL_IRQ, hcd_rp2040_irq); reset_block(RESETS_RESET_USBCTRL_BITS); unreset_block_wait(RESETS_RESET_USBCTRL_BITS); - return true; } @@ -330,58 +393,54 @@ void hcd_port_reset_end(uint8_t rhport) { } bool hcd_port_connect_status(uint8_t rhport) { - (void) rhport; + (void)rhport; return usb_hw->sie_status & USB_SIE_STATUS_SPEED_BITS; } -tusb_speed_t hcd_port_speed_get(uint8_t rhport) -{ - (void) rhport; - assert(rhport == 0); - - // TODO: Should enumval this register - switch ( dev_speed() ) - { - case 1: +tusb_speed_t hcd_port_speed_get(uint8_t rhport) { + (void)rhport; + switch (dev_speed()) { + case SIE_CTRL_SPEED_LOW: return TUSB_SPEED_LOW; - case 2: + case SIE_CTRL_SPEED_FULL: return TUSB_SPEED_FULL; default: - panic("Invalid speed\n"); - // return TUSB_SPEED_INVALID; + return TUSB_SPEED_INVALID; } } // Close all opened endpoint belong to this device void hcd_device_close(uint8_t rhport, uint8_t dev_addr) { - pico_trace("hcd_device_close %d\n", dev_addr); - (void) rhport; + (void)rhport; + (void)dev_addr; + #if 0 // reset epx if it is currently active with unplugged device - if (epx.wMaxPacketSize > 0 && epx.active && epx.dev_addr == dev_addr) { - epx.wMaxPacketSize = 0; + if (epx.hw_ep.wMaxPacketSize > 0 && epx.hw_ep.active && epx.dev_addr == dev_addr) { + epx.hw_ep.wMaxPacketSize = 0; *hwep_ctrl_reg_host(&epx) = 0; *hwbuf_ctrl_reg_host(&epx) = 0; - hw_endpoint_reset_transfer(&epx); + hw_endpoint_reset_transfer(&epx.hw_ep); } // dev0 only has ep0 if (dev_addr != 0) { for (size_t i = 1; i < TU_ARRAY_SIZE(ep_pool); i++) { - hw_endpoint_t *ep = &ep_pool[i]; - if (ep->dev_addr == dev_addr && ep->wMaxPacketSize > 0) { + hcd_endpoint_t *ep = &ep_pool[i]; + if (ep->dev_addr == dev_addr && ep->hwep.wMaxPacketSize > 0) { // in case it is an interrupt endpoint, disable it usb_hw_clear->int_ep_ctrl = (1 << (ep->interrupt_num + 1)); usb_hw->int_ep_addr_ctrl[ep->interrupt_num] = 0; // unconfigure the endpoint - ep->wMaxPacketSize = 0; + ep->hwep.wMaxPacketSize = 0; *hwep_ctrl_reg_host(ep) = 0; *hwbuf_ctrl_reg_host(ep) = 0; - hw_endpoint_reset_transfer(ep); + hw_endpoint_reset_transfer(&ep->hwep); } } } + #endif } uint32_t hcd_frame_number(uint8_t rhport) { @@ -405,9 +464,9 @@ void hcd_int_disable(uint8_t rhport) { //--------------------------------------------------------------------+ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, const tusb_desc_endpoint_t *ep_desc) { (void)rhport; - hw_endpoint_t *ep = edpt_alloc(); + pico_trace("hcd_edpt_open dev_addr %d, ep_addr %d\n", dev_addr, ep_desc->bEndpointAddress); + hcd_endpoint_t *ep = edpt_alloc(); TU_ASSERT(ep); - hw_endpoint_init(ep, dev_addr, ep_desc); return true; @@ -420,46 +479,49 @@ bool hcd_edpt_close(uint8_t rhport, uint8_t daddr, uint8_t ep_addr) { return false; // TODO not implemented yet } -// xfer using epx -static bool edpt_xfer(hw_endpoint_t *ep, uint8_t *buffer, tu_fifo_t *ff, uint16_t total_len) { - const uint8_t ep_num = tu_edpt_number(ep->ep_addr); - const tusb_dir_t ep_dir = tu_edpt_dir(ep->ep_addr); +TU_ATTR_ALWAYS_INLINE static inline void sie_start_xfer(uint32_t value) { + value |= (usb_hw->sie_ctrl & SIE_CTRL_BASE_MASK); // preserve base bits - ep->remaining_len = total_len; - ep->xferred_len = 0; - ep->active = true; + // START_TRANS bit on SIE_CTRL has the same behavior as the AVAILABLE bit + // described in RP2040 Datasheet, release 2.1, section "4.1.2.5.1. Concurrent access". + // We write everything except the START_TRANS bit first, then wait some cycles. + usb_hw->sie_ctrl = value; + busy_wait_at_least_cycles(12); + usb_hw->sie_ctrl = value | USB_SIE_CTRL_START_TRANS_BITS; +} - if (ff != NULL) { - ep->user_fifo = ff; - ep->is_xfer_fifo = true; +// xfer using epx +static bool edpt_xfer(hcd_endpoint_t *ep, uint8_t *buffer, tu_fifo_t *ff, uint16_t total_len) { + if (ep->transfer_type == TUSB_XFER_INTERRUPT) { + // For interrupt endpoint control and buffer is already configured + // Note: Interrupt is single buffered only + io_rw_32 *ep_reg = &usbh_dpram->int_ep_ctrl[ep->interrupt_num - 1].ctrl; + io_rw_32 *buf_reg = &usbh_dpram->int_ep_buffer_ctrl[ep->interrupt_num - 1].ctrl; + hw_endpoint_xfer_start(&ep->hwep, ep_reg, buf_reg, buffer, ff, total_len); } else { - ep->user_buf = buffer; - ep->is_xfer_fifo = false; - } - - ep_active = ep; + const uint8_t ep_num = tu_edpt_number(ep->hwep.ep_addr); + const tusb_dir_t ep_dir = tu_edpt_dir(ep->hwep.ep_addr); - ep->hw_data_buf = &usbh_dpram->epx_data[0]; - uint dpram_offset = hw_data_offset(ep->hw_data_buf); + // ep control + const uint32_t dpram_offset = hw_data_offset(ep->hwep.hw_data_buf); + const uint32_t ep_ctrl = EP_CTRL_ENABLE_BITS | EP_CTRL_INTERRUPT_PER_BUFFER | + ((uint32_t)ep->transfer_type << EP_CTRL_BUFFER_TYPE_LSB) | dpram_offset; + usbh_dpram->epx_ctrl = ep_ctrl; - // Fill in endpoint control register with buffer offset - uint32_t ctrl_value = EP_CTRL_ENABLE_BITS | EP_CTRL_INTERRUPT_PER_BUFFER | - ((uint32_t)ep->transfer_type << EP_CTRL_BUFFER_TYPE_LSB) | dpram_offset; - usbh_dpram->epx_ctrl = ctrl_value; + io_rw_32 *ep_reg = &usbh_dpram->epx_ctrl; + io_rw_32 *buf_reg = &usbh_dpram->epx_buf_ctrl; + hw_endpoint_xfer_start(&ep->hwep, ep_reg, buf_reg, buffer, ff, total_len); - hw_endpoint_start_next_buffer(ep); + // addr control + usb_hw->dev_addr_ctrl = (uint32_t)(ep->dev_addr | (ep_num << USB_ADDR_ENDP_ENDPOINT_LSB)); - usb_hw->dev_addr_ctrl = (uint32_t)(ep->dev_addr | (ep_num << USB_ADDR_ENDP_ENDPOINT_LSB)); - uint32_t flags = USB_SIE_CTRL_START_TRANS_BITS | SIE_CTRL_BASE | - (ep_dir ? USB_SIE_CTRL_RECEIVE_DATA_BITS : USB_SIE_CTRL_SEND_DATA_BITS) | - (need_pre(ep->dev_addr) ? USB_SIE_CTRL_PREAMBLE_EN_BITS : 0); + epx = ep; - // START_TRANS bit on SIE_CTRL seems to exhibit the same behavior as the AVAILABLE bit - // described in RP2040 Datasheet, release 2.1, section "4.1.2.5.1. Concurrent access". - // We write everything except the START_TRANS bit first, then wait some cycles. - usb_hw->sie_ctrl = flags & ~USB_SIE_CTRL_START_TRANS_BITS; - busy_wait_at_least_cycles(12); - usb_hw->sie_ctrl = flags; + // start transfer + const uint32_t sie_ctrl = (ep_dir ? USB_SIE_CTRL_RECEIVE_DATA_BITS : USB_SIE_CTRL_SEND_DATA_BITS) | + (ep->need_pre ? USB_SIE_CTRL_PREAMBLE_EN_BITS : 0); + sie_start_xfer(sie_ctrl); + } return true; } @@ -467,13 +529,13 @@ static bool edpt_xfer(hw_endpoint_t *ep, uint8_t *buffer, tu_fifo_t *ff, uint16_ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *buffer, uint16_t buflen) { (void)rhport; - hw_endpoint_t *ep = edpt_find(dev_addr, ep_addr); + hcd_endpoint_t *ep = edpt_find(dev_addr, ep_addr); TU_ASSERT(ep); // Control endpoint can change direction 0x00 <-> 0x80 - if (tu_edpt_number(ep_addr) == 0) { - ep->ep_addr = ep_addr; - ep->next_pid = 1; // data and status stage start with DATA1 + if (ep_addr != ep->hwep.ep_addr) { + ep->hwep.ep_addr = ep_addr; + ep->hwep.next_pid = 1; // data and status stage start with DATA1 } edpt_xfer(ep, buffer, NULL, buflen); @@ -518,9 +580,9 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *b } 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; // TODO not implemented yet return false; } @@ -533,38 +595,30 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, const uint8_t setup_packet usbh_dpram->setup_packet[i] = setup_packet[i]; } - // Configure EP0 struct with setup info for the trans complete - // hw_endpoint_t *ep = hw_endpoint_allocate((uint8_t)TUSB_XFER_CONTROL); - hw_endpoint_t *ep = edpt_find(dev_addr, 0x00); + hcd_endpoint_t *ep = edpt_find(dev_addr, 0x00); TU_ASSERT(ep); - ep->ep_addr = 0; // setup is OUT - ep->remaining_len = 8; - ep->active = true; + ep->hwep.ep_addr = 0; // setup is OUT + ep->hwep.remaining_len = 8; + ep->hwep.xferred_len = 0; + ep->hwep.active = true; - ep_active = ep; + epx = ep; // Set device address usb_hw->dev_addr_ctrl = dev_addr; // Set pre if we are a low speed device on full speed hub - uint32_t const flags = SIE_CTRL_BASE | USB_SIE_CTRL_SEND_SETUP_BITS | USB_SIE_CTRL_START_TRANS_BITS | - (need_pre(dev_addr) ? USB_SIE_CTRL_PREAMBLE_EN_BITS : 0); - - // START_TRANS bit on SIE_CTRL seems to exhibit the same behavior as the AVAILABLE bit - // described in RP2040 Datasheet, release 2.1, section "4.1.2.5.1. Concurrent access". - // We write everything except the START_TRANS bit first, then wait some cycles. - usb_hw->sie_ctrl = flags & ~USB_SIE_CTRL_START_TRANS_BITS; - busy_wait_at_least_cycles(12); - usb_hw->sie_ctrl = flags; + const uint32_t sie_ctrl = USB_SIE_CTRL_SEND_SETUP_BITS | (ep->need_pre ? USB_SIE_CTRL_PREAMBLE_EN_BITS : 0); + sie_start_xfer(sie_ctrl); return true; } 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; panic("hcd_clear_stall"); // return true; diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index 3b65f57a4..74c6bf655 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -35,7 +35,7 @@ //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF PROTOTYPE //--------------------------------------------------------------------+ -static void sync_xfer(hw_endpoint_t *ep); +static void sync_xfer(hw_endpoint_t *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg); #if TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX static bool e15_is_critical_frame_period(struct hw_endpoint *ep); @@ -92,6 +92,7 @@ void __tusb_irq_path_func(hw_endpoint_reset_transfer)(struct hw_endpoint* ep) { ep->remaining_len = 0; ep->xferred_len = 0; ep->user_buf = 0; + ep->is_xfer_fifo = false; } void __tusb_irq_path_func(hwbuf_ctrl_update)(io_rw_32 *buf_ctrl_reg, uint32_t and_mask, uint32_t or_mask) { @@ -124,7 +125,7 @@ void __tusb_irq_path_func(hwbuf_ctrl_update)(io_rw_32 *buf_ctrl_reg, uint32_t an } // prepare buffer, move data if tx, return buffer control -static uint32_t __tusb_irq_path_func(prepare_ep_buffer)(struct hw_endpoint *ep, uint8_t buf_id, bool is_rx) { +uint32_t __tusb_irq_path_func(hwbuf_prepare)(struct hw_endpoint *ep, uint8_t buf_id, bool is_rx) { const uint16_t buflen = tu_min16(ep->remaining_len, ep->wMaxPacketSize); ep->remaining_len = (uint16_t) (ep->remaining_len - buflen); @@ -166,33 +167,23 @@ static uint32_t __tusb_irq_path_func(prepare_ep_buffer)(struct hw_endpoint *ep, } // Prepare buffer control register value -void __tusb_irq_path_func(hw_endpoint_start_next_buffer)(struct hw_endpoint* ep) { +void __tusb_irq_path_func(hw_endpoint_start_next_buffer)(struct hw_endpoint *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg) { const tusb_dir_t dir = tu_edpt_dir(ep->ep_addr); - bool is_rx; - bool is_host = false; - io_rw_32 *ep_ctrl_reg; - io_rw_32 *buf_ctrl_reg; + const bool is_host = rp2usb_is_host_mode(); - #if CFG_TUH_ENABLED - is_host = rp2usb_is_host_mode(); + bool is_rx; if (is_host) { - buf_ctrl_reg = hwbuf_ctrl_reg_host(ep); - ep_ctrl_reg = hwep_ctrl_reg_host(ep); - is_rx = (dir == TUSB_DIR_IN); - } else - #endif - { - buf_ctrl_reg = hwbuf_ctrl_reg_device(ep); - ep_ctrl_reg = hwep_ctrl_reg_device(ep); - is_rx = (dir == TUSB_DIR_OUT); + is_rx = (dir == TUSB_DIR_IN); + } else { + is_rx = (dir == TUSB_DIR_OUT); } // always compute and start with buffer 0 - uint32_t buf_ctrl = prepare_ep_buffer(ep, 0, is_rx) | USB_BUF_CTRL_SEL; + uint32_t buf_ctrl = hwbuf_prepare(ep, 0, is_rx) | USB_BUF_CTRL_SEL; // EP0 has no endpoint control register, also usbd only schedule 1 packet at a time (single buffer) - if (ep_ctrl_reg != NULL) { - uint32_t ep_ctrl = *ep_ctrl_reg; + if (ep_reg != NULL) { + uint32_t ep_ctrl = *ep_reg; // For now: skip double buffered for RX e.g OUT endpoint in Device mode, since host could send < 64 bytes and cause // short packet on buffer0 @@ -205,7 +196,7 @@ void __tusb_irq_path_func(hw_endpoint_start_next_buffer)(struct hw_endpoint* ep) // Use buffer 1 (double buffered) if there is still data // TODO: Isochronous for buffer1 bit-field is different than CBI (control bulk, interrupt) - buf_ctrl |= prepare_ep_buffer(ep, 1, is_rx); + buf_ctrl |= hwbuf_prepare(ep, 1, is_rx); // Set endpoint control double buffered bit if needed ep_ctrl &= ~EP_CTRL_INTERRUPT_PER_BUFFER; @@ -216,17 +207,18 @@ void __tusb_irq_path_func(hw_endpoint_start_next_buffer)(struct hw_endpoint* ep) ep_ctrl |= EP_CTRL_INTERRUPT_PER_BUFFER; } - *ep_ctrl_reg = ep_ctrl; + *ep_reg = ep_ctrl; } TU_LOG(3, " Prepare BufCtrl: [0] = 0x%04x [1] = 0x%04x\r\n", tu_u32_low16(buf_ctrl), tu_u32_high16(buf_ctrl)); // Finally, write to buffer_control which will trigger the transfer // the next time the controller polls this dpram address - hwbuf_ctrl_set(buf_ctrl_reg, buf_ctrl); + hwbuf_ctrl_set(buf_reg, buf_ctrl); } -void hw_endpoint_xfer_start(struct hw_endpoint *ep, uint8_t *buffer, tu_fifo_t *ff, uint16_t total_len) { +void hw_endpoint_xfer_start(struct hw_endpoint *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg, uint8_t *buffer, tu_fifo_t *ff, + uint16_t total_len) { hw_endpoint_lock_update(ep, 1); if (ep->active) { @@ -258,15 +250,14 @@ void hw_endpoint_xfer_start(struct hw_endpoint *ep, uint8_t *buffer, tu_fifo_t * } else #endif { - hw_endpoint_start_next_buffer(ep); + hw_endpoint_start_next_buffer(ep, ep_reg, buf_reg); } hw_endpoint_lock_update(ep, -1); } // sync endpoint buffer and return transferred bytes -static uint16_t __tusb_irq_path_func(sync_ep_buffer)(hw_endpoint_t *ep, io_rw_32 *buf_ctrl_reg, uint8_t buf_id, - bool is_rx) { +uint16_t __tusb_irq_path_func(hwbuf_sync)(hw_endpoint_t *ep, io_rw_32 *buf_ctrl_reg, uint8_t buf_id, bool is_rx) { uint32_t buf_ctrl = *buf_ctrl_reg; if (buf_id) { buf_ctrl = buf_ctrl >> 16; @@ -304,37 +295,26 @@ static uint16_t __tusb_irq_path_func(sync_ep_buffer)(hw_endpoint_t *ep, io_rw_32 } // Update hw endpoint struct with info from hardware after a buff status interrupt -static void __tusb_irq_path_func(sync_xfer)(hw_endpoint_t *ep) { +static void __tusb_irq_path_func(sync_xfer)(hw_endpoint_t *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg) { // const uint8_t ep_num = tu_edpt_number(ep->ep_addr); const tusb_dir_t dir = tu_edpt_dir(ep->ep_addr); + const bool is_host = rp2usb_is_host_mode(); + bool is_rx; - io_rw_32 *buf_ctrl_reg; - io_rw_32 *ep_ctrl_reg; - bool is_rx; - - #if CFG_TUH_ENABLED - const bool is_host = rp2usb_is_host_mode(); if (is_host) { - buf_ctrl_reg = hwbuf_ctrl_reg_host(ep); - ep_ctrl_reg = hwep_ctrl_reg_host(ep); - is_rx = (dir == TUSB_DIR_IN); - } else - #endif - { - buf_ctrl_reg = hwbuf_ctrl_reg_device(ep); - ep_ctrl_reg = hwep_ctrl_reg_device(ep); - is_rx = (dir == TUSB_DIR_OUT); + is_rx = (dir == TUSB_DIR_IN); + } else { + is_rx = (dir == TUSB_DIR_OUT); } - TU_LOG(3, " Sync BufCtrl: [0] = 0x%04x [1] = 0x%04x\r\n", tu_u32_low16(*buf_ctrl_reg), - tu_u32_high16(*buf_ctrl_reg)); - uint16_t buf0_bytes = sync_ep_buffer(ep, buf_ctrl_reg, 0, is_rx); // always sync buffer 0 + TU_LOG(3, " Sync BufCtrl: [0] = 0x%04x [1] = 0x%04x\r\n", tu_u32_low16(*buf_reg), tu_u32_high16(*buf_reg)); + uint16_t buf0_bytes = hwbuf_sync(ep, buf_reg, 0, is_rx); // always sync buffer 0 // sync buffer 1 if double buffered - if (ep_ctrl_reg != NULL && (*ep_ctrl_reg) & EP_CTRL_DOUBLE_BUFFERED_BITS) { + if (ep_reg != NULL && (*ep_reg) & EP_CTRL_DOUBLE_BUFFERED_BITS) { if (buf0_bytes == ep->wMaxPacketSize) { // sync buffer 1 if not short packet - sync_ep_buffer(ep, buf_ctrl_reg, 1, is_rx); + hwbuf_sync(ep, buf_reg, 1, is_rx); } else { // short packet on buffer 0 // TODO couldn't figure out how to handle this case which happen with net_lwip_webserver example @@ -368,7 +348,7 @@ static void __tusb_irq_path_func(sync_xfer)(hw_endpoint_t *ep) { } // Returns true if transfer is complete -bool __tusb_irq_path_func(hw_endpoint_xfer_continue)(struct hw_endpoint* ep) { +bool __tusb_irq_path_func(hw_endpoint_xfer_continue)(struct hw_endpoint *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg) { hw_endpoint_lock_update(ep, 1); // Part way through a transfer @@ -376,7 +356,7 @@ bool __tusb_irq_path_func(hw_endpoint_xfer_continue)(struct hw_endpoint* ep) { panic("Can't continue xfer on inactive ep %02X", ep->ep_addr); } - sync_xfer(ep); // Update EP struct from hardware state + sync_xfer(ep, ep_reg, buf_reg); // Update EP struct from hardware state // Now we have synced our state with the hardware. Is there more data to transfer? // If we are done then notify tinyusb @@ -392,7 +372,7 @@ bool __tusb_irq_path_func(hw_endpoint_xfer_continue)(struct hw_endpoint* ep) { } else #endif { - hw_endpoint_start_next_buffer(ep); + hw_endpoint_start_next_buffer(ep, ep_reg, buf_reg); } } diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.h b/src/portable/raspberrypi/rp2040/rp2040_usb.h index 682e9dab4..ac1d8610a 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.h +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.h @@ -72,13 +72,6 @@ typedef struct hw_endpoint { uint8_t pending; // Transfer scheduled but not active #endif -#if CFG_TUH_ENABLED - uint8_t dev_addr; - uint8_t interrupt_num; // for host interrupt endpoints - uint8_t transfer_type; - bool need_pre; // need preamble for low speed device behind full speed hub -#endif - uint16_t wMaxPacketSize; // max packet size also indicates configured uint8_t *hw_data_buf; // Buffer pointer in usb dpram @@ -92,6 +85,15 @@ typedef struct hw_endpoint { } hw_endpoint_t; +// Host controller endpoint +typedef struct { + hw_endpoint_t hwep; + uint8_t dev_addr; + uint8_t interrupt_num; // 1-15 for interrupt endpoints + uint8_t transfer_type; + bool need_pre; // need preamble for low speed device behind full speed hub +} hcd_endpoint_t; + #if TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX extern volatile uint32_t e15_last_sof; #endif @@ -103,10 +105,14 @@ TU_ATTR_ALWAYS_INLINE static inline bool rp2usb_is_host_mode(void) { return (usb_hw->main_ctrl & USB_MAIN_CTRL_HOST_NDEVICE_BITS) ? true : false; } -void hw_endpoint_xfer_start(struct hw_endpoint *ep, uint8_t *buffer, tu_fifo_t *ff, uint16_t total_len); -bool hw_endpoint_xfer_continue(struct hw_endpoint *ep); +//--------------------------------------------------------------------+ +// Hardware Endpoint +//--------------------------------------------------------------------+ +void hw_endpoint_xfer_start(struct hw_endpoint *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg, uint8_t *buffer, tu_fifo_t *ff, + uint16_t total_len); +bool hw_endpoint_xfer_continue(struct hw_endpoint *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg); void hw_endpoint_reset_transfer(struct hw_endpoint *ep); -void hw_endpoint_start_next_buffer(struct hw_endpoint *ep); +void hw_endpoint_start_next_buffer(struct hw_endpoint *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg); TU_ATTR_ALWAYS_INLINE static inline void hw_endpoint_lock_update(__unused struct hw_endpoint * ep, __unused int delta) { // todo add critsec as necessary to prevent issues between worker and IRQ... @@ -114,43 +120,12 @@ TU_ATTR_ALWAYS_INLINE static inline void hw_endpoint_lock_update(__unused struct // sense to have worker and IRQ on same core, however I think using critsec is about equivalent. } -// #if CFG_TUD_ENABLED -TU_ATTR_ALWAYS_INLINE static inline io_rw_32 *hwep_ctrl_reg_device(struct hw_endpoint *ep) { - uint8_t const epnum = tu_edpt_number(ep->ep_addr); - const uint8_t dir = (uint8_t)tu_edpt_dir(ep->ep_addr); - if (epnum == 0) { - // EP0 has no endpoint control register because the buffer offsets are fixed and always enabled - return NULL; - } - return (dir == TUSB_DIR_IN) ? &usb_dpram->ep_ctrl[epnum - 1].in : &usb_dpram->ep_ctrl[epnum - 1].out; -} - -TU_ATTR_ALWAYS_INLINE static inline io_rw_32 *hwbuf_ctrl_reg_device(struct hw_endpoint *ep) { - const uint8_t epnum = tu_edpt_number(ep->ep_addr); - const uint8_t dir = (uint8_t)tu_edpt_dir(ep->ep_addr); - return (dir == TUSB_DIR_IN) ? &usb_dpram->ep_buf_ctrl[epnum].in : &usb_dpram->ep_buf_ctrl[epnum].out; -} -// #endif - -#if CFG_TUH_ENABLED -TU_ATTR_ALWAYS_INLINE static inline io_rw_32 *hwep_ctrl_reg_host(struct hw_endpoint *ep) { - if (tu_edpt_number(ep->ep_addr) == 0) { - return &usbh_dpram->epx_ctrl; - } - return &usbh_dpram->int_ep_ctrl[ep->interrupt_num].ctrl; -} - -TU_ATTR_ALWAYS_INLINE static inline io_rw_32 *hwbuf_ctrl_reg_host(struct hw_endpoint *ep) { - if (tu_edpt_number(ep->ep_addr) == 0) { - return &usbh_dpram->epx_buf_ctrl; - } - return &usbh_dpram->int_ep_buffer_ctrl[ep->interrupt_num].ctrl; -} -#endif - //--------------------------------------------------------------------+ -// +// Hardware Buffer //--------------------------------------------------------------------+ +uint32_t hwbuf_prepare(struct hw_endpoint *ep, uint8_t buf_id, bool is_rx); +uint16_t hwbuf_sync(hw_endpoint_t *ep, io_rw_32 *buf_ctrl_reg, uint8_t buf_id, bool is_rx); + void hwbuf_ctrl_update(io_rw_32 *buf_ctrl_reg, uint32_t and_mask, uint32_t or_mask); TU_ATTR_ALWAYS_INLINE static inline void hwbuf_ctrl_set(io_rw_32 *buf_ctrl_reg, uint32_t value) { -- cgit v1.3.1 From 0c9a170dca9b0a0982b4b0462508ee4bda7a06da Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 16 Jan 2026 13:39:06 +0700 Subject: implement hcd_device_close() --- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 123 +++++---------------------- 1 file changed, 20 insertions(+), 103 deletions(-) (limited to 'src/portable') diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index ff2db2499..8a891c49a 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -252,12 +252,12 @@ static void hw_endpoint_init(hcd_endpoint_t *ep, uint8_t dev_addr, const tusb_de const uint8_t transfer_type = ep_desc->bmAttributes.xfer; // const uint8_t bmInterval = ep_desc->bInterval; + ep->hwep.wMaxPacketSize = wMaxPacketSize; ep->hwep.ep_addr = ep_addr; ep->dev_addr = dev_addr; ep->transfer_type = transfer_type; ep->need_pre = need_pre(dev_addr); ep->hwep.next_pid = 0u; - ep->hwep.wMaxPacketSize = wMaxPacketSize; if (transfer_type != TUSB_XFER_INTERRUPT) { ep->hwep.hw_data_buf = usbh_dpram->epx_data; @@ -293,49 +293,8 @@ static void hw_endpoint_init(hcd_endpoint_t *ep, uint8_t dev_addr, const tusb_de usb_hw->int_ep_addr_ctrl[int_idx] = addr_ctrl; // Finally, activate interrupt endpoint - usb_hw_set->int_ep_ctrl |= 1u << ep->interrupt_num; - } - #if 0 - pico_trace("hw_endpoint_init dev %d ep %02X xfer %d\n", ep->dev_addr, ep->hwep.ep_addr, transfer_type); - pico_trace("dev %d ep %02X setup buffer @ 0x%p\n", ep->dev_addr, ep->hwep.ep_addr, ep->hwep.hw_data_buf); - uint dpram_offset = hw_data_offset(ep->hwep.hw_data_buf); - // Bits 0-5 should be 0 - assert(!(dpram_offset & 0b111111)); - - // Fill in endpoint control register with buffer offset - uint32_t ctrl_value = EP_CTRL_ENABLE_BITS | EP_CTRL_INTERRUPT_PER_BUFFER | - ((uint32_t)transfer_type << EP_CTRL_BUFFER_TYPE_LSB) | dpram_offset; - if (bmInterval) { - ctrl_value |= (uint32_t)((bmInterval - 1) << EP_CTRL_HOST_INTERRUPT_INTERVAL_LSB); - } - - io_rw_32 *ctrl_reg = hwep_ctrl_reg_host(ep); - *ctrl_reg = ctrl_value; - pico_trace("endpoint control (0x%p) <- 0x%lx\n", ctrl_reg, ctrl_value); - - if (ep != &epx) { - // Endpoint has its own addr_endp and interrupt bits to be setup! - // This is an interrupt/async endpoint. so need to set up ADDR_ENDP register with: - // - device address - // - endpoint number / direction - // - preamble - uint32_t reg = (uint32_t)(dev_addr | (num << USB_ADDR_ENDP1_ENDPOINT_LSB)); - - if (dir == TUSB_DIR_OUT) { - reg |= USB_ADDR_ENDP1_INTEP_DIR_BITS; - } - - if (need_pre(dev_addr)) { - reg |= USB_ADDR_ENDP1_INTEP_PREAMBLE_BITS; - } - usb_hw->int_ep_addr_ctrl[ep->interrupt_num] = reg; - - // Finally, enable interrupt that endpoint - usb_hw_set->int_ep_ctrl = 1 << (ep->interrupt_num + 1); - - // If it's an interrupt endpoint we need to set up the buffer control register + usb_hw_set->int_ep_ctrl = 1u << ep->interrupt_num; } - #endif } //--------------------------------------------------------------------+ @@ -414,33 +373,29 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr) { (void)rhport; (void)dev_addr; - #if 0 // reset epx if it is currently active with unplugged device - if (epx.hw_ep.wMaxPacketSize > 0 && epx.hw_ep.active && epx.dev_addr == dev_addr) { - epx.hw_ep.wMaxPacketSize = 0; - *hwep_ctrl_reg_host(&epx) = 0; - *hwbuf_ctrl_reg_host(&epx) = 0; - hw_endpoint_reset_transfer(&epx.hw_ep); + if (epx->hwep.wMaxPacketSize > 0 && epx->dev_addr == dev_addr) { + // if (epx->hwep.active) { + // // need to abort transfer + // } + epx->hwep.wMaxPacketSize = 0; } - // dev0 only has ep0 - if (dev_addr != 0) { - for (size_t i = 1; i < TU_ARRAY_SIZE(ep_pool); i++) { - hcd_endpoint_t *ep = &ep_pool[i]; - if (ep->dev_addr == dev_addr && ep->hwep.wMaxPacketSize > 0) { - // in case it is an interrupt endpoint, disable it - usb_hw_clear->int_ep_ctrl = (1 << (ep->interrupt_num + 1)); - usb_hw->int_ep_addr_ctrl[ep->interrupt_num] = 0; - - // unconfigure the endpoint - ep->hwep.wMaxPacketSize = 0; - *hwep_ctrl_reg_host(ep) = 0; - *hwbuf_ctrl_reg_host(ep) = 0; - hw_endpoint_reset_transfer(&ep->hwep); + for (size_t i = 0; i < TU_ARRAY_SIZE(ep_pool); i++) { + hcd_endpoint_t *ep = &ep_pool[i]; + if (ep->dev_addr == dev_addr && ep->hwep.wMaxPacketSize > 0) { + if (ep->interrupt_num) { + // disable interrupt endpoint + usb_hw_clear->int_ep_ctrl = 1u << ep->interrupt_num; + usb_hw->int_ep_addr_ctrl[ep->interrupt_num - 1] = 0; + + usbh_dpram->int_ep_buffer_ctrl[ep->interrupt_num - 1].ctrl = 0; + usbh_dpram->int_ep_ctrl[ep->interrupt_num - 1].ctrl = 0; } + + ep->hwep.wMaxPacketSize = 0; // mark as unused } } - #endif } uint32_t hcd_frame_number(uint8_t rhport) { @@ -491,7 +446,7 @@ TU_ATTR_ALWAYS_INLINE static inline void sie_start_xfer(uint32_t value) { } // xfer using epx -static bool edpt_xfer(hcd_endpoint_t *ep, uint8_t *buffer, tu_fifo_t *ff, uint16_t total_len) { +static void edpt_xfer(hcd_endpoint_t *ep, uint8_t *buffer, tu_fifo_t *ff, uint16_t total_len) { if (ep->transfer_type == TUSB_XFER_INTERRUPT) { // For interrupt endpoint control and buffer is already configured // Note: Interrupt is single buffered only @@ -522,8 +477,6 @@ static bool edpt_xfer(hcd_endpoint_t *ep, uint8_t *buffer, tu_fifo_t *ff, uint16 (ep->need_pre ? USB_SIE_CTRL_PREAMBLE_EN_BITS : 0); sie_start_xfer(sie_ctrl); } - - return true; } bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *buffer, uint16_t buflen) { @@ -540,42 +493,6 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *b edpt_xfer(ep, buffer, NULL, buflen); - #if 0 - // EP should be inactive - // assert(!ep->active); - - // Control endpoint can change direction 0x00 <-> 0x80 - if (ep_addr != ep->ep_addr) { - assert(ep_num == 0); - - // Direction has flipped on endpoint control so re init it but with same properties - hw_endpoint_init(ep, dev_addr, ep_addr, ep->wMaxPacketSize, TUSB_XFER_CONTROL, 0); - } - - // If a normal transfer (non-interrupt) then initiate using - // sie ctrl registers. Otherwise, interrupt ep registers should - // already be configured - if (ep == &epx) { - hw_endpoint_xfer_start(ep, buffer, NULL, buflen); - - // That has set up buffer control, endpoint control etc - // for host we have to initiate the transfer - usb_hw->dev_addr_ctrl = (uint32_t) (dev_addr | (ep_num << USB_ADDR_ENDP_ENDPOINT_LSB)); - - uint32_t flags = USB_SIE_CTRL_START_TRANS_BITS | SIE_CTRL_BASE | - (ep_dir ? USB_SIE_CTRL_RECEIVE_DATA_BITS : USB_SIE_CTRL_SEND_DATA_BITS) | - (need_pre(dev_addr) ? USB_SIE_CTRL_PREAMBLE_EN_BITS : 0); - // START_TRANS bit on SIE_CTRL seems to exhibit the same behavior as the AVAILABLE bit - // described in RP2040 Datasheet, release 2.1, section "4.1.2.5.1. Concurrent access". - // We write everything except the START_TRANS bit first, then wait some cycles. - usb_hw->sie_ctrl = flags & ~USB_SIE_CTRL_START_TRANS_BITS; - busy_wait_at_least_cycles(12); - usb_hw->sie_ctrl = flags; - } else { - hw_endpoint_xfer_start(ep, buffer, NULL, buflen); - } - #endif - return true; } -- cgit v1.3.1 From 292f334bd9b9d76524bbd6b76aea3cf9e6fd24c4 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 16 Jan 2026 15:03:09 +0700 Subject: rename --- src/portable/raspberrypi/rp2040/dcd_rp2040.c | 14 +++++++------- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 23 ++++++++++++----------- src/portable/raspberrypi/rp2040/rp2040_usb.c | 15 ++++++++------- src/portable/raspberrypi/rp2040/rp2040_usb.h | 9 +++------ 4 files changed, 30 insertions(+), 31 deletions(-) (limited to 'src/portable') diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index 8c7dc83b8..7af6cdb43 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -89,7 +89,7 @@ TU_ATTR_ALWAYS_INLINE static inline io_rw_32 *hwbuf_ctrl_reg_device(struct hw_en static void hw_endpoint_init(hw_endpoint_t *ep, uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t transfer_type) { ep->ep_addr = ep_addr; ep->next_pid = 0u; - ep->wMaxPacketSize = wMaxPacketSize; + ep->max_packet_size = wMaxPacketSize; // Clear existing buffer control state io_rw_32 *buf_ctrl_reg = hwbuf_ctrl_reg_device(ep); @@ -99,7 +99,7 @@ static void hw_endpoint_init(hw_endpoint_t *ep, uint8_t ep_addr, uint16_t wMaxPa const uint8_t epnum = tu_edpt_number(ep_addr); if (epnum == 0) { // Buffer offset is fixed (also double buffered) - ep->hw_data_buf = (uint8_t*) &usb_dpram->ep0_buf_a[0]; + ep->dpram_buf = (uint8_t *)&usb_dpram->ep0_buf_a[0]; } else { // round up size to multiple of 64 uint16_t size = (uint16_t)tu_round_up(wMaxPacketSize, 64); @@ -116,11 +116,11 @@ static void hw_endpoint_init(hw_endpoint_t *ep, uint8_t ep_addr, uint16_t wMaxPa } // assign buffer - ep->hw_data_buf = hw_buffer_ptr; + ep->dpram_buf = hw_buffer_ptr; hw_buffer_ptr += size; hard_assert(hw_buffer_ptr < usb_dpram->epx_data + sizeof(usb_dpram->epx_data)); - pico_info(" Allocated %d bytes (0x%p)\r\n", size, ep->hw_data_buf); + pico_info(" Allocated %d bytes (0x%p)\r\n", size, ep->dpram_buf); } } @@ -129,7 +129,7 @@ static void hw_endpoint_enable(hw_endpoint_t *ep, uint8_t transfer_type) { // Set endpoint control register to enable (EP0 has no endpoint control register) if (ctrl_reg != NULL) { const uint32_t ctrl_value = - EP_CTRL_ENABLE_BITS | ((uint32_t)transfer_type << EP_CTRL_BUFFER_TYPE_LSB) | hw_data_offset(ep->hw_data_buf); + EP_CTRL_ENABLE_BITS | ((uint32_t)transfer_type << EP_CTRL_BUFFER_TYPE_LSB) | hw_data_offset(ep->dpram_buf); *ctrl_reg = ctrl_value; } } @@ -501,12 +501,12 @@ bool dcd_edpt_iso_activate(uint8_t rhport, const tusb_desc_endpoint_t *ep_desc) const uint8_t epnum = tu_edpt_number(ep_desc->bEndpointAddress); const tusb_dir_t dir = tu_edpt_dir(ep_desc->bEndpointAddress); struct hw_endpoint *ep = hw_endpoint_get(epnum, dir); - TU_ASSERT(ep->hw_data_buf != NULL); // must be inited and allocated previously + TU_ASSERT(ep->dpram_buf != NULL); // must be inited and allocated previously if (ep->active) { hw_endpoint_abort_xfer(ep); // abort any pending transfer } - ep->wMaxPacketSize = ep_desc->wMaxPacketSize; + ep->max_packet_size = ep_desc->wMaxPacketSize; hw_endpoint_enable(ep, TUSB_XFER_ISOCHRONOUS); return true; diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index 8a891c49a..6377a5d75 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -71,7 +71,7 @@ enum { static hcd_endpoint_t *edpt_alloc(void) { for (uint i = 0; i < TU_ARRAY_SIZE(ep_pool); i++) { hcd_endpoint_t *ep = &ep_pool[i]; - if (ep->hwep.wMaxPacketSize == 0) { + if (ep->hwep.max_packet_size == 0) { return ep; } } @@ -81,7 +81,7 @@ static hcd_endpoint_t *edpt_alloc(void) { static hcd_endpoint_t *edpt_find(uint8_t daddr, uint8_t ep_addr) { for (uint32_t i = 0; i < TU_ARRAY_SIZE(ep_pool); i++) { hcd_endpoint_t *ep = &ep_pool[i]; - if ((ep->dev_addr == daddr) && (ep->hwep.wMaxPacketSize > 0) && + if ((ep->dev_addr == daddr) && (ep->hwep.max_packet_size > 0) && (ep->hwep.ep_addr == ep_addr || (tu_edpt_number(ep_addr) == 0 && tu_edpt_number(ep->hwep.ep_addr) == 0))) { return ep; } @@ -184,6 +184,7 @@ static void __tusb_irq_path_func(handle_hwbuf_status)(void) { } } +// // static void edpt_scheduler(void) { // } @@ -252,7 +253,7 @@ static void hw_endpoint_init(hcd_endpoint_t *ep, uint8_t dev_addr, const tusb_de const uint8_t transfer_type = ep_desc->bmAttributes.xfer; // const uint8_t bmInterval = ep_desc->bInterval; - ep->hwep.wMaxPacketSize = wMaxPacketSize; + ep->hwep.max_packet_size = wMaxPacketSize; ep->hwep.ep_addr = ep_addr; ep->dev_addr = dev_addr; ep->transfer_type = transfer_type; @@ -260,7 +261,7 @@ static void hw_endpoint_init(hcd_endpoint_t *ep, uint8_t dev_addr, const tusb_de ep->hwep.next_pid = 0u; if (transfer_type != TUSB_XFER_INTERRUPT) { - ep->hwep.hw_data_buf = usbh_dpram->epx_data; + ep->hwep.dpram_buf = usbh_dpram->epx_data; } else { // from 15 interrupt endpoints pool uint8_t int_idx; @@ -275,9 +276,9 @@ static void hw_endpoint_init(hcd_endpoint_t *ep, uint8_t dev_addr, const tusb_de //------------- dpram buf -------------// // 15x64 last bytes of DPRAM for interrupt endpoint buffers - ep->hwep.hw_data_buf = (uint8_t *)(USBCTRL_DPRAM_BASE + USB_DPRAM_MAX - (int_idx + 1u) * 64u); + ep->hwep.dpram_buf = (uint8_t *)(USBCTRL_DPRAM_BASE + USB_DPRAM_MAX - (int_idx + 1u) * 64u); uint32_t ep_ctrl = EP_CTRL_ENABLE_BITS | EP_CTRL_INTERRUPT_PER_BUFFER | - (TUSB_XFER_INTERRUPT << EP_CTRL_BUFFER_TYPE_LSB) | hw_data_offset(ep->hwep.hw_data_buf) | + (TUSB_XFER_INTERRUPT << EP_CTRL_BUFFER_TYPE_LSB) | hw_data_offset(ep->hwep.dpram_buf) | (uint32_t)((ep_desc->bInterval - 1) << EP_CTRL_HOST_INTERRUPT_INTERVAL_LSB); usbh_dpram->int_ep_ctrl[int_idx].ctrl = ep_ctrl; @@ -374,16 +375,16 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr) { (void)dev_addr; // reset epx if it is currently active with unplugged device - if (epx->hwep.wMaxPacketSize > 0 && epx->dev_addr == dev_addr) { + if (epx->hwep.max_packet_size > 0 && epx->dev_addr == dev_addr) { // if (epx->hwep.active) { // // need to abort transfer // } - epx->hwep.wMaxPacketSize = 0; + epx->hwep.max_packet_size = 0; } for (size_t i = 0; i < TU_ARRAY_SIZE(ep_pool); i++) { hcd_endpoint_t *ep = &ep_pool[i]; - if (ep->dev_addr == dev_addr && ep->hwep.wMaxPacketSize > 0) { + if (ep->dev_addr == dev_addr && ep->hwep.max_packet_size > 0) { if (ep->interrupt_num) { // disable interrupt endpoint usb_hw_clear->int_ep_ctrl = 1u << ep->interrupt_num; @@ -393,7 +394,7 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr) { usbh_dpram->int_ep_ctrl[ep->interrupt_num - 1].ctrl = 0; } - ep->hwep.wMaxPacketSize = 0; // mark as unused + ep->hwep.max_packet_size = 0; // mark as unused } } } @@ -458,7 +459,7 @@ static void edpt_xfer(hcd_endpoint_t *ep, uint8_t *buffer, tu_fifo_t *ff, uint16 const tusb_dir_t ep_dir = tu_edpt_dir(ep->hwep.ep_addr); // ep control - const uint32_t dpram_offset = hw_data_offset(ep->hwep.hw_data_buf); + const uint32_t dpram_offset = hw_data_offset(ep->hwep.dpram_buf); const uint32_t ep_ctrl = EP_CTRL_ENABLE_BITS | EP_CTRL_INTERRUPT_PER_BUFFER | ((uint32_t)ep->transfer_type << EP_CTRL_BUFFER_TYPE_LSB) | dpram_offset; usbh_dpram->epx_ctrl = ep_ctrl; diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index 74c6bf655..477e50a6a 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -125,8 +125,8 @@ void __tusb_irq_path_func(hwbuf_ctrl_update)(io_rw_32 *buf_ctrl_reg, uint32_t an } // prepare buffer, move data if tx, return buffer control -uint32_t __tusb_irq_path_func(hwbuf_prepare)(struct hw_endpoint *ep, uint8_t buf_id, bool is_rx) { - const uint16_t buflen = tu_min16(ep->remaining_len, ep->wMaxPacketSize); +static uint32_t __tusb_irq_path_func(hwbuf_prepare)(struct hw_endpoint *ep, uint8_t buf_id, bool is_rx) { + const uint16_t buflen = tu_min16(ep->remaining_len, ep->max_packet_size); ep->remaining_len = (uint16_t) (ep->remaining_len - buflen); uint32_t buf_ctrl = buflen | USB_BUF_CTRL_AVAIL; @@ -138,7 +138,7 @@ uint32_t __tusb_irq_path_func(hwbuf_prepare)(struct hw_endpoint *ep, uint8_t buf if (!is_rx) { if (buflen) { // Copy data from user buffer/fifo to hw buffer - uint8_t *hw_buf = ep->hw_data_buf + buf_id * 64; + uint8_t *hw_buf = ep->dpram_buf + buf_id * 64; if (ep->is_xfer_fifo) { // not in sram, may mess up timing with E15 workaround tu_hwfifo_write_from_fifo(hw_buf, ep->user_fifo, buflen, NULL); @@ -257,7 +257,8 @@ void hw_endpoint_xfer_start(struct hw_endpoint *ep, io_rw_32 *ep_reg, io_rw_32 * } // sync endpoint buffer and return transferred bytes -uint16_t __tusb_irq_path_func(hwbuf_sync)(hw_endpoint_t *ep, io_rw_32 *buf_ctrl_reg, uint8_t buf_id, bool is_rx) { +static uint16_t __tusb_irq_path_func(hwbuf_sync)(hw_endpoint_t *ep, io_rw_32 *buf_ctrl_reg, uint8_t buf_id, + bool is_rx) { uint32_t buf_ctrl = *buf_ctrl_reg; if (buf_id) { buf_ctrl = buf_ctrl >> 16; @@ -274,7 +275,7 @@ uint16_t __tusb_irq_path_func(hwbuf_sync)(hw_endpoint_t *ep, io_rw_32 *buf_ctrl_ // we have received AFTER we have copied it to the user buffer at the appropriate offset assert(buf_ctrl & USB_BUF_CTRL_FULL); - uint8_t *hw_buf = ep->hw_data_buf + buf_id * 64; + uint8_t *hw_buf = ep->dpram_buf + buf_id * 64; if (ep->is_xfer_fifo) { // not in sram, may mess up timing with E15 workaround tu_hwfifo_read_to_fifo(hw_buf, ep->user_fifo, xferred_bytes, NULL); @@ -286,7 +287,7 @@ uint16_t __tusb_irq_path_func(hwbuf_sync)(hw_endpoint_t *ep, io_rw_32 *buf_ctrl_ ep->xferred_len += xferred_bytes; // Short packet - if (xferred_bytes < ep->wMaxPacketSize) { + if (xferred_bytes < ep->max_packet_size) { // Reduce total length as this is last packet ep->remaining_len = 0; } @@ -312,7 +313,7 @@ static void __tusb_irq_path_func(sync_xfer)(hw_endpoint_t *ep, io_rw_32 *ep_reg, // sync buffer 1 if double buffered if (ep_reg != NULL && (*ep_reg) & EP_CTRL_DOUBLE_BUFFERED_BITS) { - if (buf0_bytes == ep->wMaxPacketSize) { + if (buf0_bytes == ep->max_packet_size) { // sync buffer 1 if not short packet hwbuf_sync(ep, buf_reg, 1, is_rx); } else { diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.h b/src/portable/raspberrypi/rp2040/rp2040_usb.h index ac1d8610a..cbb2290c1 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.h +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.h @@ -72,8 +72,8 @@ typedef struct hw_endpoint { uint8_t pending; // Transfer scheduled but not active #endif - uint16_t wMaxPacketSize; // max packet size also indicates configured - uint8_t *hw_data_buf; // Buffer pointer in usb dpram + uint16_t max_packet_size; // max packet size also indicates configured + uint8_t *dpram_buf; // Buffer pointer in usb dpram // transfer info union { @@ -111,8 +111,8 @@ TU_ATTR_ALWAYS_INLINE static inline bool rp2usb_is_host_mode(void) { void hw_endpoint_xfer_start(struct hw_endpoint *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg, uint8_t *buffer, tu_fifo_t *ff, uint16_t total_len); bool hw_endpoint_xfer_continue(struct hw_endpoint *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg); -void hw_endpoint_reset_transfer(struct hw_endpoint *ep); void hw_endpoint_start_next_buffer(struct hw_endpoint *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg); +void hw_endpoint_reset_transfer(struct hw_endpoint *ep); TU_ATTR_ALWAYS_INLINE static inline void hw_endpoint_lock_update(__unused struct hw_endpoint * ep, __unused int delta) { // todo add critsec as necessary to prevent issues between worker and IRQ... @@ -123,9 +123,6 @@ TU_ATTR_ALWAYS_INLINE static inline void hw_endpoint_lock_update(__unused struct //--------------------------------------------------------------------+ // Hardware Buffer //--------------------------------------------------------------------+ -uint32_t hwbuf_prepare(struct hw_endpoint *ep, uint8_t buf_id, bool is_rx); -uint16_t hwbuf_sync(hw_endpoint_t *ep, io_rw_32 *buf_ctrl_reg, uint8_t buf_id, bool is_rx); - void hwbuf_ctrl_update(io_rw_32 *buf_ctrl_reg, uint32_t and_mask, uint32_t or_mask); TU_ATTR_ALWAYS_INLINE static inline void hwbuf_ctrl_set(io_rw_32 *buf_ctrl_reg, uint32_t value) { -- cgit v1.3.1 From edcc95de2e0605603d2400239587ea078631076f Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 16 Jan 2026 15:03:41 +0700 Subject: rename --- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 16 ---------------- 1 file changed, 16 deletions(-) (limited to 'src/portable') diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index 6377a5d75..8c2e93805 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -92,22 +92,6 @@ static hcd_endpoint_t *edpt_find(uint8_t daddr, uint8_t ep_addr) { // static hcd_endpoint_t* epdt_find_interrupt(uint8_t ) -TU_ATTR_ALWAYS_INLINE static inline io_rw_32 *hwep_ctrl_reg_host(hw_endpoint_t *ep) { - if (tu_edpt_number(ep->ep_addr) == 0) { - return &usbh_dpram->epx_ctrl; - } - // return &usbh_dpram->int_ep_ctrl[ep->interrupt_num].ctrl; - return NULL; -} - -TU_ATTR_ALWAYS_INLINE static inline io_rw_32 *hwbuf_ctrl_reg_host(hw_endpoint_t *ep) { - if (tu_edpt_number(ep->ep_addr) == 0) { - return &usbh_dpram->epx_buf_ctrl; - } - // return &usbh_dpram->int_ep_buffer_ctrl[ep->interrupt_num].ctrl; - return NULL; -} - //--------------------------------------------------------------------+ // //--------------------------------------------------------------------+ -- cgit v1.3.1 From 0dd509ad3639a49f7f6a885da02670c09c05a058 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 16 Jan 2026 16:10:00 +0700 Subject: revert back to shared hw_endpoint_t --- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 96 ++++++++++++++-------------- src/portable/raspberrypi/rp2040/rp2040_usb.h | 18 +++--- 2 files changed, 56 insertions(+), 58 deletions(-) (limited to 'src/portable') diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index 8c2e93805..0a8dbe11a 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -48,8 +48,8 @@ //--------------------------------------------------------------------+ // Host mode uses one shared endpoint register for non-interrupt endpoint -static hcd_endpoint_t ep_pool[USB_MAX_ENDPOINTS]; -static hcd_endpoint_t *epx = &ep_pool[0]; // current active endpoint +static hw_endpoint_t ep_pool[USB_MAX_ENDPOINTS]; +static hw_endpoint_t *epx = &ep_pool[0]; // current active endpoint // Flags we set by default in sie_ctrl (we add other bits on top) enum { @@ -68,21 +68,21 @@ enum { // //--------------------------------------------------------------------+ -static hcd_endpoint_t *edpt_alloc(void) { +static hw_endpoint_t *edpt_alloc(void) { for (uint i = 0; i < TU_ARRAY_SIZE(ep_pool); i++) { - hcd_endpoint_t *ep = &ep_pool[i]; - if (ep->hwep.max_packet_size == 0) { + hw_endpoint_t *ep = &ep_pool[i]; + if (ep->max_packet_size == 0) { return ep; } } return NULL; } -static hcd_endpoint_t *edpt_find(uint8_t daddr, uint8_t ep_addr) { +static hw_endpoint_t *edpt_find(uint8_t daddr, uint8_t ep_addr) { for (uint32_t i = 0; i < TU_ARRAY_SIZE(ep_pool); i++) { - hcd_endpoint_t *ep = &ep_pool[i]; - if ((ep->dev_addr == daddr) && (ep->hwep.max_packet_size > 0) && - (ep->hwep.ep_addr == ep_addr || (tu_edpt_number(ep_addr) == 0 && tu_edpt_number(ep->hwep.ep_addr) == 0))) { + hw_endpoint_t *ep = &ep_pool[i]; + if ((ep->dev_addr == daddr) && (ep->max_packet_size > 0) && + (ep->ep_addr == ep_addr || (tu_edpt_number(ep_addr) == 0 && tu_edpt_number(ep->ep_addr) == 0))) { return ep; } } @@ -90,7 +90,7 @@ static hcd_endpoint_t *edpt_find(uint8_t daddr, uint8_t ep_addr) { return NULL; } -// static hcd_endpoint_t* epdt_find_interrupt(uint8_t ) +// static hw_endpoint_t* epdt_find_interrupt(uint8_t ) //--------------------------------------------------------------------+ // @@ -106,17 +106,17 @@ TU_ATTR_ALWAYS_INLINE static inline bool need_pre(uint8_t dev_addr) { return hcd_port_speed_get(0) != tuh_speed_get(dev_addr); } -static void __tusb_irq_path_func(hw_xfer_complete)(hcd_endpoint_t *ep, xfer_result_t xfer_result) { +static void __tusb_irq_path_func(hw_xfer_complete)(hw_endpoint_t *ep, xfer_result_t xfer_result) { // Mark transfer as done before we tell the tinyusb stack uint8_t dev_addr = ep->dev_addr; - uint8_t ep_addr = ep->hwep.ep_addr; - uint xferred_len = ep->hwep.xferred_len; - hw_endpoint_reset_transfer(&ep->hwep); + uint8_t ep_addr = ep->ep_addr; + uint xferred_len = ep->xferred_len; + hw_endpoint_reset_transfer(ep); hcd_event_xfer_complete(dev_addr, ep_addr, xferred_len, xfer_result, true); } -static void __tusb_irq_path_func(handle_hwbuf_status_bit)(hcd_endpoint_t *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg) { - const bool done = hw_endpoint_xfer_continue(&ep->hwep, ep_reg, buf_reg); +static void __tusb_irq_path_func(handle_hwbuf_status_bit)(hw_endpoint_t *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg) { + const bool done = hw_endpoint_xfer_continue(ep, ep_reg, buf_reg); if (done) { hw_xfer_complete(ep, XFER_RESULT_SUCCESS); } @@ -151,7 +151,7 @@ static void __tusb_irq_path_func(handle_hwbuf_status)(void) { usb_hw_clear->buf_status = bit; for (uint8_t e = 0; e < USB_MAX_ENDPOINTS; e++) { - hcd_endpoint_t *ep = &ep_pool[e]; + hw_endpoint_t *ep = &ep_pool[e]; if (ep->interrupt_num == i) { io_rw_32 *ep_reg = &usbh_dpram->int_ep_ctrl[ep->interrupt_num - 1].ctrl; io_rw_32 *buf_reg = &usbh_dpram->int_ep_buffer_ctrl[ep->interrupt_num - 1].ctrl; @@ -168,7 +168,7 @@ static void __tusb_irq_path_func(handle_hwbuf_status)(void) { } } -// +// All non-interrupt endpoints use shared EPX. // static void edpt_scheduler(void) { // } @@ -208,7 +208,7 @@ static void __tusb_irq_path_func(hcd_rp2040_irq)(void) { // only handle setup packet if (usb_hw->sie_ctrl & USB_SIE_CTRL_SEND_SETUP_BITS) { - epx->hwep.xferred_len = 8; + epx->xferred_len = 8; hw_xfer_complete(epx, XFER_RESULT_SUCCESS); } else { // Don't care. Will handle this in buff status @@ -231,21 +231,21 @@ void __tusb_irq_path_func(hcd_int_handler)(uint8_t rhport, bool in_isr) { hcd_rp2040_irq(); } -static void hw_endpoint_init(hcd_endpoint_t *ep, uint8_t dev_addr, const tusb_desc_endpoint_t *ep_desc) { +static void hw_endpoint_init(hw_endpoint_t *ep, uint8_t dev_addr, const tusb_desc_endpoint_t *ep_desc) { const uint8_t ep_addr = ep_desc->bEndpointAddress; const uint16_t wMaxPacketSize = tu_edpt_packet_size(ep_desc); const uint8_t transfer_type = ep_desc->bmAttributes.xfer; // const uint8_t bmInterval = ep_desc->bInterval; - ep->hwep.max_packet_size = wMaxPacketSize; - ep->hwep.ep_addr = ep_addr; + ep->max_packet_size = wMaxPacketSize; + ep->ep_addr = ep_addr; ep->dev_addr = dev_addr; ep->transfer_type = transfer_type; ep->need_pre = need_pre(dev_addr); - ep->hwep.next_pid = 0u; + ep->next_pid = 0u; if (transfer_type != TUSB_XFER_INTERRUPT) { - ep->hwep.dpram_buf = usbh_dpram->epx_data; + ep->dpram_buf = usbh_dpram->epx_data; } else { // from 15 interrupt endpoints pool uint8_t int_idx; @@ -260,9 +260,9 @@ static void hw_endpoint_init(hcd_endpoint_t *ep, uint8_t dev_addr, const tusb_de //------------- dpram buf -------------// // 15x64 last bytes of DPRAM for interrupt endpoint buffers - ep->hwep.dpram_buf = (uint8_t *)(USBCTRL_DPRAM_BASE + USB_DPRAM_MAX - (int_idx + 1u) * 64u); + ep->dpram_buf = (uint8_t *)(USBCTRL_DPRAM_BASE + USB_DPRAM_MAX - (int_idx + 1u) * 64u); uint32_t ep_ctrl = EP_CTRL_ENABLE_BITS | EP_CTRL_INTERRUPT_PER_BUFFER | - (TUSB_XFER_INTERRUPT << EP_CTRL_BUFFER_TYPE_LSB) | hw_data_offset(ep->hwep.dpram_buf) | + (TUSB_XFER_INTERRUPT << EP_CTRL_BUFFER_TYPE_LSB) | hw_data_offset(ep->dpram_buf) | (uint32_t)((ep_desc->bInterval - 1) << EP_CTRL_HOST_INTERRUPT_INTERVAL_LSB); usbh_dpram->int_ep_ctrl[int_idx].ctrl = ep_ctrl; @@ -359,16 +359,16 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr) { (void)dev_addr; // reset epx if it is currently active with unplugged device - if (epx->hwep.max_packet_size > 0 && epx->dev_addr == dev_addr) { - // if (epx->hwep.active) { + if (epx->max_packet_size > 0 && epx->dev_addr == dev_addr) { + // if (epx->active) { // // need to abort transfer // } - epx->hwep.max_packet_size = 0; + epx->max_packet_size = 0; } for (size_t i = 0; i < TU_ARRAY_SIZE(ep_pool); i++) { - hcd_endpoint_t *ep = &ep_pool[i]; - if (ep->dev_addr == dev_addr && ep->hwep.max_packet_size > 0) { + hw_endpoint_t *ep = &ep_pool[i]; + if (ep->dev_addr == dev_addr && ep->max_packet_size > 0) { if (ep->interrupt_num) { // disable interrupt endpoint usb_hw_clear->int_ep_ctrl = 1u << ep->interrupt_num; @@ -378,7 +378,7 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr) { usbh_dpram->int_ep_ctrl[ep->interrupt_num - 1].ctrl = 0; } - ep->hwep.max_packet_size = 0; // mark as unused + ep->max_packet_size = 0; // mark as unused } } } @@ -405,7 +405,7 @@ void hcd_int_disable(uint8_t rhport) { bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, const tusb_desc_endpoint_t *ep_desc) { (void)rhport; pico_trace("hcd_edpt_open dev_addr %d, ep_addr %d\n", dev_addr, ep_desc->bEndpointAddress); - hcd_endpoint_t *ep = edpt_alloc(); + hw_endpoint_t *ep = edpt_alloc(); TU_ASSERT(ep); hw_endpoint_init(ep, dev_addr, ep_desc); @@ -431,26 +431,26 @@ TU_ATTR_ALWAYS_INLINE static inline void sie_start_xfer(uint32_t value) { } // xfer using epx -static void edpt_xfer(hcd_endpoint_t *ep, uint8_t *buffer, tu_fifo_t *ff, uint16_t total_len) { +static void edpt_xfer(hw_endpoint_t *ep, uint8_t *buffer, tu_fifo_t *ff, uint16_t total_len) { if (ep->transfer_type == TUSB_XFER_INTERRUPT) { // For interrupt endpoint control and buffer is already configured // Note: Interrupt is single buffered only io_rw_32 *ep_reg = &usbh_dpram->int_ep_ctrl[ep->interrupt_num - 1].ctrl; io_rw_32 *buf_reg = &usbh_dpram->int_ep_buffer_ctrl[ep->interrupt_num - 1].ctrl; - hw_endpoint_xfer_start(&ep->hwep, ep_reg, buf_reg, buffer, ff, total_len); + hw_endpoint_xfer_start(ep, ep_reg, buf_reg, buffer, ff, total_len); } else { - const uint8_t ep_num = tu_edpt_number(ep->hwep.ep_addr); - const tusb_dir_t ep_dir = tu_edpt_dir(ep->hwep.ep_addr); + const uint8_t ep_num = tu_edpt_number(ep->ep_addr); + const tusb_dir_t ep_dir = tu_edpt_dir(ep->ep_addr); // ep control - const uint32_t dpram_offset = hw_data_offset(ep->hwep.dpram_buf); + const uint32_t dpram_offset = hw_data_offset(ep->dpram_buf); const uint32_t ep_ctrl = EP_CTRL_ENABLE_BITS | EP_CTRL_INTERRUPT_PER_BUFFER | ((uint32_t)ep->transfer_type << EP_CTRL_BUFFER_TYPE_LSB) | dpram_offset; usbh_dpram->epx_ctrl = ep_ctrl; io_rw_32 *ep_reg = &usbh_dpram->epx_ctrl; io_rw_32 *buf_reg = &usbh_dpram->epx_buf_ctrl; - hw_endpoint_xfer_start(&ep->hwep, ep_reg, buf_reg, buffer, ff, total_len); + hw_endpoint_xfer_start(ep, ep_reg, buf_reg, buffer, ff, total_len); // addr control usb_hw->dev_addr_ctrl = (uint32_t)(ep->dev_addr | (ep_num << USB_ADDR_ENDP_ENDPOINT_LSB)); @@ -467,13 +467,13 @@ static void edpt_xfer(hcd_endpoint_t *ep, uint8_t *buffer, tu_fifo_t *ff, uint16 bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *buffer, uint16_t buflen) { (void)rhport; - hcd_endpoint_t *ep = edpt_find(dev_addr, ep_addr); + hw_endpoint_t *ep = edpt_find(dev_addr, ep_addr); TU_ASSERT(ep); // Control endpoint can change direction 0x00 <-> 0x80 - if (ep_addr != ep->hwep.ep_addr) { - ep->hwep.ep_addr = ep_addr; - ep->hwep.next_pid = 1; // data and status stage start with DATA1 + if (ep_addr != ep->ep_addr) { + ep->ep_addr = ep_addr; + ep->next_pid = 1; // data and status stage start with DATA1 } edpt_xfer(ep, buffer, NULL, buflen); @@ -497,13 +497,13 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, const uint8_t setup_packet usbh_dpram->setup_packet[i] = setup_packet[i]; } - hcd_endpoint_t *ep = edpt_find(dev_addr, 0x00); + hw_endpoint_t *ep = edpt_find(dev_addr, 0x00); TU_ASSERT(ep); - ep->hwep.ep_addr = 0; // setup is OUT - ep->hwep.remaining_len = 8; - ep->hwep.xferred_len = 0; - ep->hwep.active = true; + ep->ep_addr = 0; // setup is OUT + ep->remaining_len = 8; + ep->xferred_len = 0; + ep->active = true; epx = ep; diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.h b/src/portable/raspberrypi/rp2040/rp2040_usb.h index cbb2290c1..46bd727c8 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.h +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.h @@ -65,11 +65,18 @@ typedef struct hw_endpoint { uint8_t ep_addr; uint8_t next_pid; bool active; // transferring data + uint8_t pending; // Transfer scheduled but not active bool is_xfer_fifo; // transfer using fifo #if TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX bool e15_bulk_in; // Errata15 device bulk in - uint8_t pending; // Transfer scheduled but not active +#endif + +#if CFG_TUH_ENABLED + uint8_t dev_addr; + uint8_t interrupt_num; // 1-15 for interrupt endpoints + uint8_t transfer_type; + bool need_pre; // need preamble for low speed device behind full speed hub #endif uint16_t max_packet_size; // max packet size also indicates configured @@ -85,15 +92,6 @@ typedef struct hw_endpoint { } hw_endpoint_t; -// Host controller endpoint -typedef struct { - hw_endpoint_t hwep; - uint8_t dev_addr; - uint8_t interrupt_num; // 1-15 for interrupt endpoints - uint8_t transfer_type; - bool need_pre; // need preamble for low speed device behind full speed hub -} hcd_endpoint_t; - #if TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX extern volatile uint32_t e15_last_sof; #endif -- cgit v1.3.1 From d89a5812c3b3d1d88911f9c6307f343c9d3756bd Mon Sep 17 00:00:00 2001 From: Mitsumine Suzu <60875431+verylowfreq@users.noreply.github.com> Date: Sat, 24 Jan 2026 17:08:55 +0900 Subject: Fix macro directive for FSDEV of CH32V20x --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/portable') diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 22a9e4af8..a6abc6244 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -833,7 +833,7 @@ void dcd_int_disable(uint8_t rhport) { fsdev_int_disable(rhport); } - #if defined(USB_BCDR_DPPU) || defined(SYSCFG_PMC_USB_PU) + #if defined(USB_BCDR_DPPU) || defined(SYSCFG_PMC_USB_PU) || defined(EXTEN_USBD_PU_EN) void dcd_connect(uint8_t rhport) { fsdev_connect(rhport); } -- cgit v1.3.1 From 31dfd673ec7549006474a03786bfd3a01508b68c Mon Sep 17 00:00:00 2001 From: Zixun LI Date: Mon, 26 Jan 2026 17:15:23 +0100 Subject: fix stm32u0 data stride Signed-off-by: Zixun LI --- src/portable/st/stm32_fsdev/fsdev_common.h | 4 ++-- src/tusb_option.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src/portable') diff --git a/src/portable/st/stm32_fsdev/fsdev_common.h b/src/portable/st/stm32_fsdev/fsdev_common.h index c53e345b0..442e738ae 100644 --- a/src/portable/st/stm32_fsdev/fsdev_common.h +++ b/src/portable/st/stm32_fsdev/fsdev_common.h @@ -71,11 +71,11 @@ TU_VERIFY_STATIC(FSDEV_BTABLE_BASE % 8 == 0, "BTABLE base must be aligned to 8 b // 1x16 bit / word access scheme #define FSDEV_PMA_STRIDE 2 #define pma_access_scheme TU_ATTR_ALIGNED(4) -#elif CFG_TUSB_FSDEV_PMA_SIZE == 1024 +#elif CFG_TUSB_FSDEV_PMA_SIZE == 1024 && CFG_TUSB_MCU != OPT_MCU_STM32U0 // 2x16 bit / word access scheme #define FSDEV_PMA_STRIDE 1 #define pma_access_scheme -#elif CFG_TUSB_FSDEV_PMA_SIZE == 2048 +#elif CFG_TUSB_FSDEV_PMA_SIZE == 2048 || CFG_TUSB_MCU == OPT_MCU_STM32U0 // 32 bit access scheme #define FSDEV_BUS_32BIT #define FSDEV_PMA_STRIDE 1 diff --git a/src/tusb_option.h b/src/tusb_option.h index abf5e0608..1b65cc5aa 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -343,10 +343,10 @@ #if CFG_TUSB_FSDEV_PMA_SIZE == 512 #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE 2 // 16-bit data #define CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE 4 // 32-bit address increase - #elif CFG_TUSB_FSDEV_PMA_SIZE == 1024 + #elif CFG_TUSB_FSDEV_PMA_SIZE == 1024 && CFG_TUSB_MCU != OPT_MCU_STM32U0 #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE 2 // 16-bit data #define CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE 2 // 16-bit address increase - #elif CFG_TUSB_FSDEV_PMA_SIZE == 2048 + #elif CFG_TUSB_FSDEV_PMA_SIZE == 2048 || CFG_TUSB_MCU == OPT_MCU_STM32U0 #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE 4 // 32-bit data #define CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE 4 // 32-bit address increase #endif -- cgit v1.3.1 From 78411bbefa2187bee3b9b99561a34aa75c2d562b Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 30 Jan 2026 14:09:26 +0100 Subject: dcd/dwc2: Fix SEDET unable to be cleared on stm32u5 Signed-off-by: HiFiPhile --- src/portable/synopsys/dwc2/dcd_dwc2.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/portable') diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index 44f7137f9..f73c36d2f 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -780,7 +780,7 @@ static void handle_bus_reset(uint8_t rhport) { dwc2->epout[0].doeptsiz |= (3 << DOEPTSIZ_STUPCNT_Pos); } - dwc2->gintmsk |= GINTMSK_OEPINT | GINTMSK_IEPINT | GINTMSK_IISOIXFRM; + dwc2->gintmsk |= GINTMSK_OTGINT | GINTMSK_OEPINT | GINTMSK_IEPINT | GINTMSK_IISOIXFRM; } static void handle_enum_done(uint8_t rhport) { @@ -1180,6 +1180,7 @@ void dcd_int_handler(uint8_t rhport) { const uint32_t otg_int = dwc2->gotgint; if (otg_int & GOTGINT_SEDET) { + dwc2->gintmsk &= ~GINTMSK_OTGINT; dcd_event_bus_signal(rhport, DCD_EVENT_UNPLUGGED, true); } -- cgit v1.3.1 From fd369937279594eb8c48a81eabebb7f66bd8306a Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 30 Jan 2026 19:24:12 +0100 Subject: dwc2: add vbus sense config Signed-off-by: HiFiPhile --- src/device/usbd.h | 1 + src/portable/synopsys/dwc2/dcd_dwc2.c | 12 +-- src/portable/synopsys/dwc2/dwc2_stm32.h | 130 ++++++++++++++++++++++++++++++++ src/portable/synopsys/dwc2/dwc2_type.h | 45 ++++++----- src/portable/synopsys/dwc2/hcd_dwc2.c | 4 + 5 files changed, 169 insertions(+), 23 deletions(-) (limited to 'src/portable') diff --git a/src/device/usbd.h b/src/device/usbd.h index bd5a3c395..f923b1c56 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -41,6 +41,7 @@ enum { typedef struct { uint16_t bm_double_buffered; // bitmap of IN endpoints to be double buffered, only effective for bulk endpoints + bool vbus_sensing; // Vbus pin is used for device connection detection, mandatory for tud_umount_cb() } tud_configure_dwc2_t; typedef union { diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index f73c36d2f..36cb763aa 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -78,7 +78,8 @@ CFG_TUD_MEM_SECTION static struct { } _dcd_usbbuf; static tud_configure_dwc2_t _tud_cfg = { - .bm_double_buffered = 0 + .bm_double_buffered = 0, + .vbus_sensing = false }; TU_ATTR_ALWAYS_INLINE static inline uint8_t dwc2_ep_count(const dwc2_regs_t* dwc2) { @@ -472,12 +473,11 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { // Force device mode dwc2->gusbcfg = (dwc2->gusbcfg & ~GUSBCFG_FHMOD) | GUSBCFG_FDMOD; - // Clear A override, force B Valid - dwc2->gotgctl = (dwc2->gotgctl & ~GOTGCTL_AVALOEN) | GOTGCTL_BVALOEN | GOTGCTL_BVALOVAL; + // Clear A override, force B Valid if Vbus sensing is not used + dwc2->gotgctl = (dwc2->gotgctl & ~GOTGCTL_AVALOEN) | (_tud_cfg.vbus_sensing ? 0 : 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; +#ifdef TUP_USBIP_DWC2_STM32 + dwc2_stm32_gccfg_cfg(dwc2, _tud_cfg.vbus_sensing, false); #endif // Enable required interrupts diff --git a/src/portable/synopsys/dwc2/dwc2_stm32.h b/src/portable/synopsys/dwc2/dwc2_stm32.h index 516eb021b..a87eef068 100644 --- a/src/portable/synopsys/dwc2/dwc2_stm32.h +++ b/src/portable/synopsys/dwc2/dwc2_stm32.h @@ -300,6 +300,136 @@ static inline void dwc2_phy_update(dwc2_regs_t* dwc2, uint8_t hs_phy_type) { } } +//------------- GCCFG configuration -------------// +static inline void dwc2_stm32_gccfg_cfg(dwc2_regs_t* dwc2, bool vbus_sensing, bool is_host) { + if (is_host) { + vbus_sensing = false; + } +#if CFG_TUSB_MCU == OPT_MCU_STM32F1 + // F1: Basic FS-only core, no VBUS sensing support + // Only PWRDWN bit is used (set in dwc2_phy_init) + (void) vbus_sensing; + +#elif CFG_TUSB_MCU == OPT_MCU_STM32F2 || CFG_TUSB_MCU == OPT_MCU_STM32F4 + // F2/F4: Dual FS/HS with VBUSBSEN/VBUSASEN/NOVBUSSENS bits + if (is_host) { + dwc2->stm32_gccfg &= ~(STM32_GCCFG_NOVBUSSENS | STM32_GCCFG_VBUSBSEN | STM32_GCCFG_VBUSASEN); + } else { + if (vbus_sensing) { + dwc2->stm32_gccfg &= ~STM32_GCCFG_NOVBUSSENS; + dwc2->stm32_gccfg |= STM32_GCCFG_VBUSBSEN; + } else { + dwc2->stm32_gccfg |= STM32_GCCFG_NOVBUSSENS; + dwc2->stm32_gccfg &= ~STM32_GCCFG_VBUSBSEN; + dwc2->stm32_gccfg &= ~STM32_GCCFG_VBUSASEN; + } + } +#elif CFG_TUSB_MCU == OPT_MCU_STM32F7 + // F7: Enhanced FS/HS with battery charging detection + if (vbus_sensing) { + dwc2->stm32_gccfg |= STM32_GCCFG_VBDEN; + } else { + dwc2->stm32_gccfg &= ~STM32_GCCFG_VBDEN; + } + +#elif CFG_TUSB_MCU == OPT_MCU_STM32H7 + if (vbus_sensing) { + dwc2->stm32_gccfg |= STM32_GCCFG_VBDEN; + } else { + dwc2->stm32_gccfg &= ~STM32_GCCFG_VBDEN; + } + +#elif CFG_TUSB_MCU == OPT_MCU_STM32H7RS + // H7FS: Port0: Basic FS-only core; Port1: femtoPHY + if ((uintptr_t)dwc2 == _dwc2_controller[0].reg_base) { + if (vbus_sensing) { + dwc2->stm32_gccfg |= STM32_GCCFG_VBDEN; + } else { + dwc2->stm32_gccfg &= ~STM32_GCCFG_VBDEN; + } + return; + } else { + // Uses VBVALEXTOEN and VBVALOVAL for external VBUS sensing override + if (is_host) { + dwc2->stm32_gccfg |= STM32_GCCFG_PULLDOWNEN; + dwc2->stm32_gccfg &= ~(STM32_GCCFG_VBDEN | STM32_GCCFG_VBVALEXTOEN | STM32_GCCFG_VBVALOVAL); + } else { + dwc2->stm32_gccfg &= ~STM32_GCCFG_PULLDOWNEN; + if (vbus_sensing) { + dwc2->stm32_gccfg |= STM32_GCCFG_VBDEN; + dwc2->stm32_gccfg &= ~(STM32_GCCFG_VBVALEXTOEN | STM32_GCCFG_VBVALOVAL); + } else { + dwc2->stm32_gccfg &= ~STM32_GCCFG_VBDEN; + dwc2->stm32_gccfg |= STM32_GCCFG_VBVALEXTOEN | STM32_GCCFG_VBVALOVAL; + } + } + } + +#elif CFG_TUSB_MCU == OPT_MCU_STM32N6 + // N6: femtoPHY + // In this device, the software override is always active + (void) vbus_sensing; + if (is_host) { + dwc2->stm32_gccfg |= STM32_GCCFG_PULLDOWNEN; + dwc2->stm32_gccfg &= ~(STM32_GCCFG_VBVALOVAL); + } else { + dwc2->stm32_gccfg &= ~STM32_GCCFG_PULLDOWNEN; + dwc2->stm32_gccfg |= STM32_GCCFG_VBVALOVAL; + } + +#elif CFG_TUSB_MCU == OPT_MCU_STM32L4 + // L4: Low-power FS-only with VBUS detection + if (vbus_sensing) { + dwc2->stm32_gccfg |= STM32_GCCFG_VBDEN; + } else { + dwc2->stm32_gccfg &= ~STM32_GCCFG_VBDEN; + } + +#elif CFG_TUSB_MCU == OPT_MCU_STM32U5 + #ifdef USB_OTG_FS + // U5: FS PHY (U575/585 have FS only) + if (vbus_sensing) { + dwc2->stm32_gccfg |= STM32_GCCFG_VBDEN; + } else { + dwc2->stm32_gccfg &= ~STM32_GCCFG_VBDEN; + } + #else + // U5: femtoPHY (U59x/5Ax/5Fx/5Gx have HS) + // Uses VBVALEXTOEN and VBVALOVAL for external VBUS sensing override + if (is_host) { + dwc2->stm32_gccfg |= STM32_GCCFG_PULLDOWNEN; + dwc2->stm32_gccfg &= ~(STM32_GCCFG_VBDEN | STM32_GCCFG_VBVALEXTOEN | STM32_GCCFG_VBVALOVAL); + } else { + dwc2->stm32_gccfg &= ~STM32_GCCFG_PULLDOWNEN; + if (vbus_sensing) { + dwc2->stm32_gccfg |= STM32_GCCFG_VBDEN; + dwc2->stm32_gccfg &= ~(STM32_GCCFG_VBVALEXTOEN | STM32_GCCFG_VBVALOVAL); + } else { + dwc2->stm32_gccfg &= ~STM32_GCCFG_VBDEN; + dwc2->stm32_gccfg |= STM32_GCCFG_VBVALEXTOEN | STM32_GCCFG_VBVALOVAL; + } + } + #endif +#elif CFG_TUSB_MCU == OPT_MCU_STM32WBA + // WBA: femtoPHY + // In this device, the software override is always active + if (is_host) { + dwc2->stm32_gccfg |= STM32_GCCFG_PULLDOWNEN; + dwc2->stm32_gccfg &= ~(STM32_GCCFG_VBVALOVAL); + } else { + dwc2->stm32_gccfg &= ~STM32_GCCFG_PULLDOWNEN; + if (vbus_sensing) { + dwc2->stm32_gccfg &= ~(STM32_GCCFG_VBVALOVAL); + } else { + dwc2->stm32_gccfg |= STM32_GCCFG_VBVALOVAL; + } + } + +#else + #error "Unsupported MCU family" +#endif +} + //------------- DCache -------------// #if CFG_TUD_MEM_DCACHE_ENABLE || CFG_TUH_MEM_DCACHE_ENABLE diff --git a/src/portable/synopsys/dwc2/dwc2_type.h b/src/portable/synopsys/dwc2/dwc2_type.h index 7693ce02a..2dd73c184 100644 --- a/src/portable/synopsys/dwc2/dwc2_type.h +++ b/src/portable/synopsys/dwc2/dwc2_type.h @@ -1650,23 +1650,34 @@ TU_VERIFY_STATIC(offsetof(dwc2_regs_t, fifo ) == 0x1000, "incorrect size"); #define STM32_GCCFG_PHYHSEN_Msk (0x1UL << STM32_GCCFG_PHYHSEN_Pos) // 0x00800000 #define STM32_GCCFG_PHYHSEN STM32_GCCFG_PHYHSEN_Msk // HS PHY enable -// TODO stm32u5a5 SDEN is 22nd bit, conflict with 20th bit above -//#define STM32_GCCFG_SDEN_Pos (22U) -//#define STM32_GCCFG_SDEN_Msk (0x1U << STM32_GCCFG_SDEN_Pos) // 0x00400000 -//#define STM32_GCCFG_SDEN STM32_GCCFG_SDEN_Msk // Secondary detection (PD) mode enable - -// TODO stm32u5a5 VBVALOVA is 23rd bit, conflict with PHYHSEN bit above -#define STM32_GCCFG_VBVALOVAL_Pos (23U) -#define STM32_GCCFG_VBVALOVAL_Msk (0x1U << STM32_GCCFG_VBVALOVAL_Pos) // 0x00800000 -#define STM32_GCCFG_VBVALOVAL STM32_GCCFG_VBVALOVAL_Msk // Value of VBUSVLDEXT0 femtoPHY input - -#define STM32_GCCFG_VBVALEXTOEN_Pos (24U) -#define STM32_GCCFG_VBVALEXTOEN_Msk (0x1U << STM32_GCCFG_VBVALEXTOEN_Pos) // 0x01000000 -#define STM32_GCCFG_VBVALEXTOEN STM32_GCCFG_VBVALEXTOEN_Msk // Enables of VBUSVLDEXT0 femtoPHY input override - -#define STM32_GCCFG_PULLDOWNEN_Pos (25U) -#define STM32_GCCFG_PULLDOWNEN_Msk (0x1U << STM32_GCCFG_PULLDOWNEN_Pos) // 0x02000000 -#define STM32_GCCFG_PULLDOWNEN STM32_GCCFG_PULLDOWNEN_Msk // Enables of femtoPHY pulldown resistors, used when ID PAD is disabled +// stm32f2/stm32f4 +#define STM32_GCCFG_VBUSASEN_Pos (18U) +#define STM32_GCCFG_VBUSASEN_Msk (0x1UL << STM32_GCCFG_VBUSASEN_Pos) // 0x00040000 +#define STM32_GCCFG_VBUSASEN STM32_GCCFG_VBUSASEN_Msk // Enable A-device (host) VBUS sensing +#define STM32_GCCFG_VBUSBSEN_Pos (19U) +#define STM32_GCCFG_VBUSBSEN_Msk (0x1UL << STM32_GCCFG_VBUSBSEN_Pos) // 0x00080000 +#define STM32_GCCFG_VBUSBSEN STM32_GCCFG_VBUSBSEN_Msk // Enable B-device (peripheral) VBUS sensing +#define STM32_GCCFG_NOVBUSSENS_Pos (21U) +#define STM32_GCCFG_NOVBUSSENS_Msk (0x1UL << STM32_GCCFG_NOVBUSSENS_Pos) // 0x00200000 +#define STM32_GCCFG_NOVBUSSENS STM32_GCCFG_NOVBUSSENS_Msk // VBUS sensing disable option + +// TODO: stm32u5a5 SDEN is 22nd bit, conflict with 20th bit above +// #define STM32_GCCFG_SDEN_Pos (22U) +// #define STM32_GCCFG_SDEN_Msk (0x1U << STM32_GCCFG_SDEN_Pos) // 0x00400000 +// #define STM32_GCCFG_SDEN STM32_GCCFG_SDEN_Msk // Secondary detection (PD) mode enable + +// stm32u5a5 VBVALOVA is 23rd bit, conflict with PHYHSEN bit above +#define STM32_GCCFG_VBVALOVAL_Pos (23U) +#define STM32_GCCFG_VBVALOVAL_Msk (0x1U << STM32_GCCFG_VBVALOVAL_Pos) // 0x00800000 +#define STM32_GCCFG_VBVALOVAL STM32_GCCFG_VBVALOVAL_Msk // Value of VBUSVLDEXT0 femtoPHY input + +#define STM32_GCCFG_VBVALEXTOEN_Pos (24U) +#define STM32_GCCFG_VBVALEXTOEN_Msk (0x1U << STM32_GCCFG_VBVALEXTOEN_Pos) // 0x01000000 +#define STM32_GCCFG_VBVALEXTOEN STM32_GCCFG_VBVALEXTOEN_Msk // Enables of VBUSVLDEXT0 femtoPHY input override + +#define STM32_GCCFG_PULLDOWNEN_Pos (25U) +#define STM32_GCCFG_PULLDOWNEN_Msk (0x1U << STM32_GCCFG_PULLDOWNEN_Pos) // 0x02000000 +#define STM32_GCCFG_PULLDOWNEN STM32_GCCFG_PULLDOWNEN_Msk // Enables of femtoPHY pulldown resistors, used when ID PAD is disabled /******************** Bit definition for DEACHINTMSK register ********************/ diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index c40703b09..8182fd6cc 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -428,6 +428,10 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { #endif while ((dwc2->gintsts & GINTSTS_CMOD) != GINTSTS_CMODE_HOST) {} +#ifdef TUP_USBIP_DWC2_STM32 + dwc2_stm32_gccfg_cfg(dwc2, false, true); +#endif + // configure fixed-allocated fifo scheme dfifo_host_init(rhport); -- cgit v1.3.1 From c57d355af63080ab425143d1ce7a4579100b626f Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sat, 31 Jan 2026 16:32:58 +0100 Subject: dwc2: add stm32n6 DMA regions Signed-off-by: HiFiPhile --- src/portable/synopsys/dwc2/dwc2_stm32.h | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'src/portable') diff --git a/src/portable/synopsys/dwc2/dwc2_stm32.h b/src/portable/synopsys/dwc2/dwc2_stm32.h index a87eef068..3da78b893 100644 --- a/src/portable/synopsys/dwc2/dwc2_stm32.h +++ b/src/portable/synopsys/dwc2/dwc2_stm32.h @@ -85,8 +85,11 @@ extern "C" { #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 + #define USB_OTG_FS_PERIPH_BASE USB1_OTG_HS_BASE + #define OTG_FS_IRQn USB1_OTG_HS_IRQn + + #define USB_OTG_HS_PERIPH_BASE USB2_OTG_HS_BASE + #define OTG_HS_IRQn USB2_OTG_HS_IRQn #elif CFG_TUSB_MCU == OPT_MCU_STM32F7 #include "stm32f7xx.h" @@ -451,8 +454,13 @@ static mem_region_t uncached_regions[] = { // DTCM (although USB DMA can't transfer to/from DTCM) {.start = 0x20000000, .end = 0x2002FFFF}, #elif CFG_TUSB_MCU == OPT_MCU_STM32F7 - // DTCM + // DTCM {.start = 0x20000000, .end = 0x2000FFFF}, +#elif CFG_TUSB_MCU == OPT_MCU_STM32N6 + // DTCM NS + {.start = 0x20000000, .end = 0x2003FFFF}, + // DTCM S + {.start = 0x30000000, .end = 0x3003FFFF}, #else #error "Cache maintenance is not supported yet" #endif -- cgit v1.3.1 From 26ca4e232b44023cb470457bf1a889c8df4508db Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 5 Feb 2026 14:22:00 +0700 Subject: reverse pma size check to reduce duplication --- .idea/cmake.xml | 1 + src/portable/st/stm32_fsdev/fsdev_common.h | 22 ++++++++++------------ src/tusb_option.h | 10 +++++----- 3 files changed, 16 insertions(+), 17 deletions(-) (limited to 'src/portable') diff --git a/.idea/cmake.xml b/.idea/cmake.xml index cc73ca8fc..5f9e1acd2 100644 --- a/.idea/cmake.xml +++ b/.idea/cmake.xml @@ -131,6 +131,7 @@ + diff --git a/src/portable/st/stm32_fsdev/fsdev_common.h b/src/portable/st/stm32_fsdev/fsdev_common.h index 442e738ae..b749a92ff 100644 --- a/src/portable/st/stm32_fsdev/fsdev_common.h +++ b/src/portable/st/stm32_fsdev/fsdev_common.h @@ -63,23 +63,21 @@ TU_VERIFY_STATIC(FSDEV_BTABLE_BASE % 8 == 0, "BTABLE base must be aligned to 8 b // CFG_TUSB_FSDEV_PMA_SIZE is PMA buffer size in bytes. // - 512-byte devices, access with a stride of two words (use every other 16-bit address) -// - 1024-byte devices, access with a stride of one word (use every 16-bit address) +// - 1024-byte devices, access with a stride of one word (use every 16-bit address) or 32-bit address // - 2048-byte devices, access with 32-bit address - -// For purposes of accessing the packet -#if CFG_TUSB_FSDEV_PMA_SIZE == 512 - // 1x16 bit / word access scheme - #define FSDEV_PMA_STRIDE 2 - #define pma_access_scheme TU_ATTR_ALIGNED(4) -#elif CFG_TUSB_FSDEV_PMA_SIZE == 1024 && CFG_TUSB_MCU != OPT_MCU_STM32U0 - // 2x16 bit / word access scheme - #define FSDEV_PMA_STRIDE 1 - #define pma_access_scheme -#elif CFG_TUSB_FSDEV_PMA_SIZE == 2048 || CFG_TUSB_MCU == OPT_MCU_STM32U0 +#if CFG_TUSB_FSDEV_PMA_SIZE == 2048 || TU_CHECK_MCU(OPT_MCU_STM32U0) // 32 bit access scheme #define FSDEV_BUS_32BIT #define FSDEV_PMA_STRIDE 1 #define pma_access_scheme +#elif CFG_TUSB_FSDEV_PMA_SIZE == 1024 + // 2x16 bit / word access scheme + #define FSDEV_PMA_STRIDE 1 + #define pma_access_scheme +#elif CFG_TUSB_FSDEV_PMA_SIZE == 512 + // 1x16 bit / word access scheme + #define FSDEV_PMA_STRIDE 2 + #define pma_access_scheme TU_ATTR_ALIGNED(4) #endif // The fsdev_bus_t type can be used for both register and PMA access necessities diff --git a/src/tusb_option.h b/src/tusb_option.h index 1b65cc5aa..bbef13344 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -340,14 +340,14 @@ #if defined(TUP_USBIP_FSDEV) #define CFG_TUD_EDPT_DEDICATED_HWFIFO 1 - #if CFG_TUSB_FSDEV_PMA_SIZE == 512 - #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE 2 // 16-bit data + #if CFG_TUSB_FSDEV_PMA_SIZE == 2048 || TU_CHECK_MCU(OPT_MCU_STM32U0) + #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE 4 // 32-bit data #define CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE 4 // 32-bit address increase - #elif CFG_TUSB_FSDEV_PMA_SIZE == 1024 && CFG_TUSB_MCU != OPT_MCU_STM32U0 + #elif CFG_TUSB_FSDEV_PMA_SIZE == 1024 #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE 2 // 16-bit data #define CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE 2 // 16-bit address increase - #elif CFG_TUSB_FSDEV_PMA_SIZE == 2048 || CFG_TUSB_MCU == OPT_MCU_STM32U0 - #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE 4 // 32-bit data + #elif CFG_TUSB_FSDEV_PMA_SIZE == 512 + #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE 2 // 16-bit data #define CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE 4 // 32-bit address increase #endif #endif -- cgit v1.3.1 From 9f1d86c2e30b318eb78cb8c0c976793a7812cd34 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 6 Feb 2026 23:56:30 +0700 Subject: adjust handle_xfer_in logic to simplify ZLP handling --- src/portable/mentor/musb/dcd_musb.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'src/portable') diff --git a/src/portable/mentor/musb/dcd_musb.c b/src/portable/mentor/musb/dcd_musb.c index 9e6ee6f5d..d329285e9 100644 --- a/src/portable/mentor/musb/dcd_musb.c +++ b/src/portable/mentor/musb/dcd_musb.c @@ -189,14 +189,13 @@ static void process_setup_packet(uint8_t rhport) { } } -static bool handle_xfer_in(uint8_t rhport, uint_fast8_t ep_addr, bool is_zlp) -{ +static bool handle_xfer_in(uint8_t rhport, uint_fast8_t ep_addr) { unsigned epnum = tu_edpt_number(ep_addr); unsigned epnum_minus1 = epnum - 1; pipe_state_t *pipe = &_dcd.pipe[tu_edpt_dir(ep_addr)][epnum_minus1]; const unsigned rem = pipe->remaining; - if (!rem && !is_zlp) { + if (rem == 0 && pipe->length > 0) { pipe->buf = NULL; return true; } @@ -268,7 +267,7 @@ static bool edpt_n_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16 pipe->remaining = total_bytes; if (dir_in) { - handle_xfer_in(rhport, ep_addr, total_bytes == 0); + handle_xfer_in(rhport, ep_addr); } else { musb_regs_t* musb_regs = MUSB_REGS(rhport); musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, epnum); @@ -445,7 +444,7 @@ static void process_edpt_n(uint8_t rhport, uint_fast8_t ep_addr) ep_csr->tx_csrl &= ~(MUSB_TXCSRL1_STALLED | MUSB_TXCSRL1_UNDRN); return; } - completed = handle_xfer_in(rhport, ep_addr, false); + completed = handle_xfer_in(rhport, ep_addr); } else { // TU_LOG1(" RX CSRL%d = %x\r\n", epn, ep_csr->rx_csrl); if (ep_csr->rx_csrl & MUSB_RXCSRL1_STALLED) { -- cgit v1.3.1 From 8f14cf4bfa061690084c7c32b3f8b70301f5e0ff Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 13 Feb 2026 19:45:09 +0700 Subject: add CFG_TUD_VBUS_SENSE, that could allow to skip tud_configure() for fixed vbus sensing simplify dwc2_stm32_gccfg_cfg() using guid value --- .../stm32h7rs/boards/stm32h7s3nucleo/board.cmake | 2 + hw/bsp/stm32h7rs/family.cmake | 2 +- src/device/usbd.h | 2 + src/portable/synopsys/dwc2/dcd_dwc2.c | 15 ++- src/portable/synopsys/dwc2/dwc2_info.md | 116 ++++++++-------- src/portable/synopsys/dwc2/dwc2_info.py | 10 +- src/portable/synopsys/dwc2/dwc2_stm32.h | 146 ++++++--------------- src/portable/synopsys/dwc2/dwc2_type.h | 9 +- src/tusb_option.h | 11 +- 9 files changed, 131 insertions(+), 182 deletions(-) (limited to 'src/portable') diff --git a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.cmake b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.cmake index 7b3456585..189c175dd 100644 --- a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.cmake +++ b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.cmake @@ -2,6 +2,8 @@ set(MCU_VARIANT stm32h7s3xx) set(JLINK_DEVICE stm32h7s3l8) set(LD_FILE_Clang ${LD_FILE_GNU}) +set(RHPORT_DEVICE 1) +set(RHPORT_HOST 1) function(update_board TARGET) target_compile_definitions(${TARGET} PUBLIC diff --git a/hw/bsp/stm32h7rs/family.cmake b/hw/bsp/stm32h7rs/family.cmake index 1fd1cb057..3b9dbf5cf 100644 --- a/hw/bsp/stm32h7rs/family.cmake +++ b/hw/bsp/stm32h7rs/family.cmake @@ -24,7 +24,7 @@ if (NOT DEFINED RHPORT_DEVICE) set(RHPORT_DEVICE 1) endif () if (NOT DEFINED RHPORT_HOST) - set(RHPORT_HOST 1) + set(RHPORT_HOST 0) endif () if (NOT DEFINED RHPORT_SPEED) diff --git a/src/device/usbd.h b/src/device/usbd.h index 7d7604c81..eaf07b81e 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -44,6 +44,8 @@ typedef struct { bool vbus_sensing; // Vbus pin is used for device connection detection, mandatory for tud_umount_cb() } tud_configure_dwc2_t; +#define TUD_CONFIGURE_DWC2_DEFAULT { .bm_double_buffered = 0, .vbus_sensing = CFG_TUD_VBUS_SENSE } + typedef union { tud_configure_dwc2_t dwc2; } tud_configure_param_t; diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index 36cb763aa..a6a598dbf 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -77,10 +77,7 @@ CFG_TUD_MEM_SECTION static struct { TUD_EPBUF_DEF(setup_packet, 8); } _dcd_usbbuf; -static tud_configure_dwc2_t _tud_cfg = { - .bm_double_buffered = 0, - .vbus_sensing = false -}; +static tud_configure_dwc2_t _tud_cfg = TUD_CONFIGURE_DWC2_DEFAULT; TU_ATTR_ALWAYS_INLINE static inline uint8_t dwc2_ep_count(const dwc2_regs_t* dwc2) { #if TU_CHECK_MCU(OPT_MCU_GD32VF103) @@ -473,10 +470,14 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { // Force device mode dwc2->gusbcfg = (dwc2->gusbcfg & ~GUSBCFG_FHMOD) | GUSBCFG_FDMOD; - // Clear A override, force B Valid if Vbus sensing is not used - dwc2->gotgctl = (dwc2->gotgctl & ~GOTGCTL_AVALOEN) | (_tud_cfg.vbus_sensing ? 0 : GOTGCTL_BVALOEN | GOTGCTL_BVALOVAL); + // OTG Ctrl + uint32_t gotgctl = dwc2->gotgctl & ~GOTGCTL_AVALOEN; // Clear A-override + if (!_tud_cfg.vbus_sensing) { + gotgctl |= GOTGCTL_BVALOEN | GOTGCTL_BVALOVAL; // force B Valid if not sensing VBus + } + dwc2->gotgctl = gotgctl; -#ifdef TUP_USBIP_DWC2_STM32 + #ifdef TUP_USBIP_DWC2_STM32 dwc2_stm32_gccfg_cfg(dwc2, _tud_cfg.vbus_sensing, false); #endif diff --git a/src/portable/synopsys/dwc2/dwc2_info.md b/src/portable/synopsys/dwc2/dwc2_info.md index f655e4dba..f83007b8c 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 | 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 | +| | AT32 F405 FS | AT32 F405 HS | AT32 F415 | BCM2711 (Pi4) | EFM32GG | ESP32-S2/S3 | ESP32-P4 | nRF54 | ST F407/429 HS | ST F207/F407/411/429 FS | ST L476 FS | ST F412/76x FS | ST F76x HS | ST H743/H750 | ST F723/L4P5 FS | ST F723 HS | ST H7RS FS | ST U5A5/H7RS/N6 HS | XMC4500 | GD32VF103 | +|:---------------------------|:---------------|:---------------|:------------|:----------------|:-------------|:--------------|:-------------|:-------------|:-----------------|:--------------------------|:-------------|:-----------------|:-------------|:---------------|:------------------|:-------------|:-------------|:---------------------|:-------------|:------------| +| GUID | 0x00002000 | 0x00000000 | 0x00001000 | 0x2708A000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00001100 | 0x00001200 | 0x00002000 | 0x00002000 | 0x00002100 | 0x00002300 | 0x00003000 | 0x00003100 | 0x00004000 | 0x00005000 | 0x00AEC000 | 0x00001000 | +| GSNPSID | 0x4F54400A | 0x4F54400A | 0x4F54400A | 0x4F54280A | 0x4F54330A | 0x4F54400A | 0x4F54400A | 0x4F54430A | 0x4F54281A | 0x4F54281A | 0x4F54310A | 0x4F54320A | 0x4F54320A | 0x4F54330A | 0x4F54330A | 0x4F54330A | 0x4F54411A | 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.10a | 3.20a | 3.20a | 3.30a | 3.30a | 3.30a | 4.11a | 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 | 0x00000000 | +| GHWCFG2 | 0x228FDD00 | 0x229FDDD0 | 0x228DCD00 | 0x228DDD50 | 0x228F5910 | 0x224DD930 | 0x215FFFD0 | 0x228BFC72 | 0x229ED590 | 0x229DCD20 | 0x229ED520 | 0x229ED520 | 0x229FE190 | 0x229FE190 | 0x229ED520 | 0x229FE1D0 | 0x229ED522 | 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 | noHNP noSRP | HNP SRP | HNP SRP | +| - arch | Slave only | DMA internal | Slave only | DMA internal | DMA internal | DMA internal | DMA internal | DMA internal | DMA internal | Slave only | Slave only | Slave only | DMA internal | DMA internal | Slave only | 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 | n/a | hub | hub | n/a | hub | n/a | hub | n/a | hub | +| - hs_phy_type | n/a | UTMI+/ULPI | n/a | UTMI+ | n/a | n/a | UTMI+/ULPI | UTMI+ | ULPI | n/a | n/a | n/a | ULPI | ULPI | n/a | UTMI+/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 | Dedicated | n/a | Dedicated | n/a | +| - num_dev_ep | 7 | 7 | 3 | 7 | 6 | 6 | 15 | 15 | 5 | 3 | 5 | 5 | 8 | 8 | 5 | 8 | 5 | 8 | 6 | 0 | +| - num_host_ch | 15 | 15 | 7 | 7 | 13 | 7 | 15 | 15 | 11 | 7 | 11 | 11 | 15 | 15 | 11 | 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 | 1 | 0 | +| - enable_dynamic_fifo | 1 | 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 | 1 | 0 | 0 | 0 | +| - reserved21 | 0 | 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 | 8 | 2 | +| - ptx_q_depth | 8 | 8 | 8 | 8 | 8 | 8 | 4 | 8 | 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 | 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 | 0 | +| GHWCFG3 | 0x020004E8 | 0x03F006E8 | 0x020004E8 | 0x0FF000E8 | 0x01F204E8 | 0x00C804B5 | 0x03805EB5 | 0x0BEAC0E8 | 0x03F403E8 | 0x020001E8 | 0x0200D1E8 | 0x0200D1E8 | 0x03EED2E8 | 0x03B8D2E8 | 0x0200D1E8 | 0x03EED2E8 | 0x020081E8 | 0x03B882E8 | 0x027A01E5 | 0x00000000 | +| - xfer_size_width | 8 | 8 | 8 | 8 | 8 | 5 | 5 | 8 | 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 | 6 | 0 | +| - otg_enable | 1 | 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 | 1 | 0 | 1 | 0 | 1 | 0 | +| - vendor_ctrl_itf | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 0 | 0 | 1 | 1 | 0 | 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 | 0 | +| - synch_reset | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 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 | 0 | +| - otg_enable_hsic | 0 | 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 | 0 | +| - lpm_mode | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | +| - dfifo_depth | 512 | 1008 | 512 | 4080 | 498 | 200 | 896 | 3050 | 1012 | 512 | 512 | 512 | 1006 | 952 | 512 | 1006 | 512 | 952 | 634 | 0 | +| GHWCFG4 | 0x1FF0A020 | 0x1FF0A020 | 0x0000000F | 0x1FF00020 | 0x1BF08030 | 0xD3F0A030 | 0xDFF1A030 | 0x1E10AA60 | 0x17F00030 | 0x0FF08030 | 0x17F08030 | 0x17F08030 | 0x23F00030 | 0xE3F00030 | 0x17F08030 | 0x23F00030 | 0x1610B230 | 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 | 0 | +| - partial_powerdown | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 0 | 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 | 1 | 1 | 0 | +| - hibernation | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 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 | 0 | 0 | +| - reserved8 | 0 | 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 | 1 | 0 | 0 | +| - service_interval_flow | 0 | 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 | 0 | 1 | 0 | 0 | +| - acg_support | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | +| - enhanced_lpm_support | 1 | 1 | 0 | 0 | 0 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 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/16 bit | 8 bit | 8 bit | 8/16 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 | 0 | +| - iddg_filter | 1 | 1 | 0 | 1 | 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 | 0 | 1 | 0 | +| - a_valid_filter | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | 0 | +| - b_valid_filter | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | 0 | +| - session_end_filter | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | 0 | +| - dedicated_fifos | 1 | 1 | 0 | 1 | 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 | 5 | 3 | 5 | 5 | 8 | 8 | 5 | 8 | 5 | 8 | 6 | 0 | +| - dma_desc_enable | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 1 | 1 | 0 | +| - dma_desc_dynamic | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 1 | 1 | 0 | diff --git a/src/portable/synopsys/dwc2/dwc2_info.py b/src/portable/synopsys/dwc2/dwc2_info.py index 8fbbc00a0..e6601f482 100755 --- a/src/portable/synopsys/dwc2/dwc2_info.py +++ b/src/portable/synopsys/dwc2/dwc2_info.py @@ -16,14 +16,16 @@ dwc2_reg_value = { '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 sort by GUID 'ST F407/429 HS': [0x1100, 0x4F54281A, 0, 0x229ED590, 0x03F403E8, 0x17F00030], + 'ST F207/F407/411/429 FS': [0x1200, 0x4F54281A, 0, 0x229DCD20, 0x020001E8, 0x0FF08030], + 'ST L476 FS': [0x2000, 0x4F54310A, 0, 0x229ED520, 0x0200D1E8, 0x17F08030], 'ST F412/76x FS': [0x2000, 0x4F54320A, 0, 0x229ED520, 0x0200D1E8, 0x17F08030], - 'ST F723/L4P5 FS': [0x3000, 0x4F54330A, 0, 0x229ED520, 0x0200D1E8, 0x17F08030], - 'ST F723 HS': [0x3100, 0x4F54330A, 0, 0x229FE1D0, 0x03EED2E8, 0x23F00030], '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 F723/L4P5 FS': [0x3000, 0x4F54330A, 0, 0x229ED520, 0x0200D1E8, 0x17F08030], + 'ST F723 HS': [0x3100, 0x4F54330A, 0, 0x229FE1D0, 0x03EED2E8, 0x23F00030], + 'ST H7RS FS': [0x4000, 0x4F54411A, 0, 0x229ED522, 0x20081E8, 0x1610B230], 'ST U5A5/H7RS/N6 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 3da78b893..753917a20 100644 --- a/src/portable/synopsys/dwc2/dwc2_stm32.h +++ b/src/portable/synopsys/dwc2/dwc2_stm32.h @@ -308,129 +308,59 @@ static inline void dwc2_stm32_gccfg_cfg(dwc2_regs_t* dwc2, bool vbus_sensing, bo if (is_host) { vbus_sensing = false; } -#if CFG_TUSB_MCU == OPT_MCU_STM32F1 - // F1: Basic FS-only core, no VBUS sensing support - // Only PWRDWN bit is used (set in dwc2_phy_init) - (void) vbus_sensing; - -#elif CFG_TUSB_MCU == OPT_MCU_STM32F2 || CFG_TUSB_MCU == OPT_MCU_STM32F4 - // F2/F4: Dual FS/HS with VBUSBSEN/VBUSASEN/NOVBUSSENS bits - if (is_host) { - dwc2->stm32_gccfg &= ~(STM32_GCCFG_NOVBUSSENS | STM32_GCCFG_VBUSBSEN | STM32_GCCFG_VBUSASEN); - } else { - if (vbus_sensing) { - dwc2->stm32_gccfg &= ~STM32_GCCFG_NOVBUSSENS; - dwc2->stm32_gccfg |= STM32_GCCFG_VBUSBSEN; - } else { - dwc2->stm32_gccfg |= STM32_GCCFG_NOVBUSSENS; - dwc2->stm32_gccfg &= ~STM32_GCCFG_VBUSBSEN; - dwc2->stm32_gccfg &= ~STM32_GCCFG_VBUSASEN; - } - } -#elif CFG_TUSB_MCU == OPT_MCU_STM32F7 - // F7: Enhanced FS/HS with battery charging detection - if (vbus_sensing) { - dwc2->stm32_gccfg |= STM32_GCCFG_VBDEN; - } else { - dwc2->stm32_gccfg &= ~STM32_GCCFG_VBDEN; - } -#elif CFG_TUSB_MCU == OPT_MCU_STM32H7 - if (vbus_sensing) { - dwc2->stm32_gccfg |= STM32_GCCFG_VBDEN; - } else { - dwc2->stm32_gccfg &= ~STM32_GCCFG_VBDEN; - } - -#elif CFG_TUSB_MCU == OPT_MCU_STM32H7RS - // H7FS: Port0: Basic FS-only core; Port1: femtoPHY - if ((uintptr_t)dwc2 == _dwc2_controller[0].reg_base) { - if (vbus_sensing) { - dwc2->stm32_gccfg |= STM32_GCCFG_VBDEN; - } else { - dwc2->stm32_gccfg &= ~STM32_GCCFG_VBDEN; - } - return; - } else { - // Uses VBVALEXTOEN and VBVALOVAL for external VBUS sensing override + uint32_t gccfg = dwc2->stm32_gccfg; + if (dwc2->guid < 0x2000) { + // use VBUSASEN/VBUSBSEN/NOVBUSSENS bits if (is_host) { - dwc2->stm32_gccfg |= STM32_GCCFG_PULLDOWNEN; - dwc2->stm32_gccfg &= ~(STM32_GCCFG_VBDEN | STM32_GCCFG_VBVALEXTOEN | STM32_GCCFG_VBVALOVAL); + gccfg &= ~(STM32_GCCFG_NOVBUSSENS | STM32_GCCFG_VBUSBSEN | STM32_GCCFG_VBUSASEN); } else { - dwc2->stm32_gccfg &= ~STM32_GCCFG_PULLDOWNEN; if (vbus_sensing) { - dwc2->stm32_gccfg |= STM32_GCCFG_VBDEN; - dwc2->stm32_gccfg &= ~(STM32_GCCFG_VBVALEXTOEN | STM32_GCCFG_VBVALOVAL); + gccfg &= ~STM32_GCCFG_NOVBUSSENS; + gccfg |= STM32_GCCFG_VBUSBSEN; } else { - dwc2->stm32_gccfg &= ~STM32_GCCFG_VBDEN; - dwc2->stm32_gccfg |= STM32_GCCFG_VBVALEXTOEN | STM32_GCCFG_VBVALOVAL; + gccfg |= STM32_GCCFG_NOVBUSSENS; + gccfg &= ~(STM32_GCCFG_VBUSBSEN | STM32_GCCFG_VBUSASEN); } } - } - -#elif CFG_TUSB_MCU == OPT_MCU_STM32N6 - // N6: femtoPHY - // In this device, the software override is always active - (void) vbus_sensing; - if (is_host) { - dwc2->stm32_gccfg |= STM32_GCCFG_PULLDOWNEN; - dwc2->stm32_gccfg &= ~(STM32_GCCFG_VBVALOVAL); - } else { - dwc2->stm32_gccfg &= ~STM32_GCCFG_PULLDOWNEN; - dwc2->stm32_gccfg |= STM32_GCCFG_VBVALOVAL; - } - -#elif CFG_TUSB_MCU == OPT_MCU_STM32L4 - // L4: Low-power FS-only with VBUS detection - if (vbus_sensing) { - dwc2->stm32_gccfg |= STM32_GCCFG_VBDEN; - } else { - dwc2->stm32_gccfg &= ~STM32_GCCFG_VBDEN; - } - -#elif CFG_TUSB_MCU == OPT_MCU_STM32U5 - #ifdef USB_OTG_FS - // U5: FS PHY (U575/585 have FS only) - if (vbus_sensing) { - dwc2->stm32_gccfg |= STM32_GCCFG_VBDEN; - } else { - dwc2->stm32_gccfg &= ~STM32_GCCFG_VBDEN; - } - #else - // U5: femtoPHY (U59x/5Ax/5Fx/5Gx have HS) - // Uses VBVALEXTOEN and VBVALOVAL for external VBUS sensing override - if (is_host) { - dwc2->stm32_gccfg |= STM32_GCCFG_PULLDOWNEN; - dwc2->stm32_gccfg &= ~(STM32_GCCFG_VBDEN | STM32_GCCFG_VBVALEXTOEN | STM32_GCCFG_VBVALOVAL); - } else { - dwc2->stm32_gccfg &= ~STM32_GCCFG_PULLDOWNEN; + } else if (dwc2->guid < 0x5000) { + // the later version uses VBDEN with battery charging detection if (vbus_sensing) { - dwc2->stm32_gccfg |= STM32_GCCFG_VBDEN; - dwc2->stm32_gccfg &= ~(STM32_GCCFG_VBVALEXTOEN | STM32_GCCFG_VBVALOVAL); + gccfg |= STM32_GCCFG_VBDEN; } else { - dwc2->stm32_gccfg &= ~STM32_GCCFG_VBDEN; - dwc2->stm32_gccfg |= STM32_GCCFG_VBVALEXTOEN | STM32_GCCFG_VBVALOVAL; + gccfg &= ~STM32_GCCFG_VBDEN; } - } - #endif -#elif CFG_TUSB_MCU == OPT_MCU_STM32WBA - // WBA: femtoPHY - // In this device, the software override is always active - if (is_host) { - dwc2->stm32_gccfg |= STM32_GCCFG_PULLDOWNEN; - dwc2->stm32_gccfg &= ~(STM32_GCCFG_VBVALOVAL); } else { - dwc2->stm32_gccfg &= ~STM32_GCCFG_PULLDOWNEN; - if (vbus_sensing) { - dwc2->stm32_gccfg &= ~(STM32_GCCFG_VBVALOVAL); + // from 0x5000 ST seems to use femtoPHY for UTMI+ HS PHY. Which use VBVALEXTOEN and VBVALOVAL for software override + // external VBUS sensing + // Note: N6 does not support hardware VBUS sensing, so the software override is always active. Therefore, VBDEN and + // VBVALEXTOEN are not available +#if CFG_TUSB_MCU == OPT_MCU_STM32N6 + if (is_host) { + gccfg |= STM32_GCCFG_PULLDOWNEN; + gccfg &= ~(STM32_GCCFG_VBVALOVAL); } else { - dwc2->stm32_gccfg |= STM32_GCCFG_VBVALOVAL; + gccfg &= ~STM32_GCCFG_PULLDOWNEN; + gccfg |= STM32_GCCFG_VBVALOVAL; } - } - #else - #error "Unsupported MCU family" + if (is_host) { + gccfg |= STM32_GCCFG_PULLDOWNEN; + gccfg &= ~(STM32_GCCFG_VBDEN | STM32_GCCFG_VBVALEXTOEN | STM32_GCCFG_VBVALOVAL); + } else { + gccfg &= ~STM32_GCCFG_PULLDOWNEN; + if (vbus_sensing) { + gccfg |= STM32_GCCFG_VBDEN; + gccfg &= ~(STM32_GCCFG_VBVALEXTOEN | STM32_GCCFG_VBVALOVAL); + } else { + gccfg &= ~STM32_GCCFG_VBDEN; + gccfg |= STM32_GCCFG_VBVALEXTOEN | STM32_GCCFG_VBVALOVAL; + } + } #endif + } + + dwc2->stm32_gccfg = gccfg; } //------------- DCache -------------// diff --git a/src/portable/synopsys/dwc2/dwc2_type.h b/src/portable/synopsys/dwc2/dwc2_type.h index 2dd73c184..596bd0b34 100644 --- a/src/portable/synopsys/dwc2/dwc2_type.h +++ b/src/portable/synopsys/dwc2/dwc2_type.h @@ -1650,23 +1650,26 @@ TU_VERIFY_STATIC(offsetof(dwc2_regs_t, fifo ) == 0x1000, "incorrect size"); #define STM32_GCCFG_PHYHSEN_Msk (0x1UL << STM32_GCCFG_PHYHSEN_Pos) // 0x00800000 #define STM32_GCCFG_PHYHSEN STM32_GCCFG_PHYHSEN_Msk // HS PHY enable -// stm32f2/stm32f4 +// GUID < 0x2000: VBUSASEN, VBUSBSEN, NOVBUSSENS bits #define STM32_GCCFG_VBUSASEN_Pos (18U) #define STM32_GCCFG_VBUSASEN_Msk (0x1UL << STM32_GCCFG_VBUSASEN_Pos) // 0x00040000 #define STM32_GCCFG_VBUSASEN STM32_GCCFG_VBUSASEN_Msk // Enable A-device (host) VBUS sensing + #define STM32_GCCFG_VBUSBSEN_Pos (19U) #define STM32_GCCFG_VBUSBSEN_Msk (0x1UL << STM32_GCCFG_VBUSBSEN_Pos) // 0x00080000 #define STM32_GCCFG_VBUSBSEN STM32_GCCFG_VBUSBSEN_Msk // Enable B-device (peripheral) VBUS sensing + #define STM32_GCCFG_NOVBUSSENS_Pos (21U) #define STM32_GCCFG_NOVBUSSENS_Msk (0x1UL << STM32_GCCFG_NOVBUSSENS_Pos) // 0x00200000 #define STM32_GCCFG_NOVBUSSENS STM32_GCCFG_NOVBUSSENS_Msk // VBUS sensing disable option +// GUID < 0x2000: end // TODO: stm32u5a5 SDEN is 22nd bit, conflict with 20th bit above // #define STM32_GCCFG_SDEN_Pos (22U) // #define STM32_GCCFG_SDEN_Msk (0x1U << STM32_GCCFG_SDEN_Pos) // 0x00400000 // #define STM32_GCCFG_SDEN STM32_GCCFG_SDEN_Msk // Secondary detection (PD) mode enable -// stm32u5a5 VBVALOVA is 23rd bit, conflict with PHYHSEN bit above +// GUID >= 0x5000 use femtoPHY: VBVALOVA, VBVALEXTOEN, PULLDOWNEN #define STM32_GCCFG_VBVALOVAL_Pos (23U) #define STM32_GCCFG_VBVALOVAL_Msk (0x1U << STM32_GCCFG_VBVALOVAL_Pos) // 0x00800000 #define STM32_GCCFG_VBVALOVAL STM32_GCCFG_VBVALOVAL_Msk // Value of VBUSVLDEXT0 femtoPHY input @@ -1678,7 +1681,7 @@ TU_VERIFY_STATIC(offsetof(dwc2_regs_t, fifo ) == 0x1000, "incorrect size"); #define STM32_GCCFG_PULLDOWNEN_Pos (25U) #define STM32_GCCFG_PULLDOWNEN_Msk (0x1U << STM32_GCCFG_PULLDOWNEN_Pos) // 0x02000000 #define STM32_GCCFG_PULLDOWNEN STM32_GCCFG_PULLDOWNEN_Msk // Enables of femtoPHY pulldown resistors, used when ID PAD is disabled - +// GUID >= 0x5000: end /******************** Bit definition for DEACHINTMSK register ********************/ #define DEACHINTMSK_IEP1INTM_Pos (1U) diff --git a/src/tusb_option.h b/src/tusb_option.h index 8e270e5f2..ebf366e17 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -579,9 +579,18 @@ #define CFG_TUD_TEST_MODE 0 #endif +#ifndef CFG_TUD_VBUS_SENSE_DEFAULT + #define CFG_TUD_VBUS_SENSE_DEFAULT 0 +#endif + +// Enable VBUS Sensing +#ifndef CFG_TUD_VBUS_SENSE + #define CFG_TUD_VBUS_SENSE CFG_TUD_VBUS_SENSE_DEFAULT +#endif + //------------- Device Class Driver -------------// #ifndef CFG_TUD_BTH - #define CFG_TUD_BTH 0 + #define CFG_TUD_BTH 0 #endif #if CFG_TUD_BTH && !defined(CFG_TUD_BTH_ISO_ALT_COUNT) -- cgit v1.3.1 From f0b44ec6154237a4bd65a5a9d8f8bf944669af64 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 13 Feb 2026 22:29:14 +0700 Subject: use CFG_TUD_CONFIGURE_DWC2_DEFAULT to make it easier to add more value --- hw/bsp/stm32f2/family.c | 6 ++---- hw/bsp/stm32f4/family.c | 6 ++---- hw/bsp/stm32f7/family.c | 12 ++++-------- hw/bsp/stm32h7/family.c | 12 ++++-------- hw/bsp/stm32h7rs/family.c | 12 ++++-------- hw/bsp/stm32l4/family.c | 6 ++---- hw/bsp/stm32u5/family.c | 12 ++++-------- src/device/usbd.h | 4 +++- src/portable/synopsys/dwc2/dcd_dwc2.c | 2 +- src/tusb_option.h | 10 +++++----- 10 files changed, 31 insertions(+), 51 deletions(-) (limited to 'src/portable') diff --git a/hw/bsp/stm32f2/family.c b/hw/bsp/stm32f2/family.c index f863a59f0..f95128040 100644 --- a/hw/bsp/stm32f2/family.c +++ b/hw/bsp/stm32f2/family.c @@ -106,10 +106,8 @@ void board_init(void) { #if CFG_TUD_ENABLED // Enable VBUS sense (B device) via pin PA9 - tud_configure_dwc2_t cfg = { - .bm_double_buffered = 0, - .vbus_sensing = true - }; + tud_configure_dwc2_t cfg = CFG_TUD_CONFIGURE_DWC2_DEFAULT; + cfg.vbus_sensing = true; tud_configure(0, TUD_CFGID_DWC2, &cfg); #endif } diff --git a/hw/bsp/stm32f4/family.c b/hw/bsp/stm32f4/family.c index 2170faca7..f0e9620f2 100644 --- a/hw/bsp/stm32f4/family.c +++ b/hw/bsp/stm32f4/family.c @@ -180,10 +180,8 @@ void board_init(void) { #endif #if CFG_TUD_ENABLED - tud_configure_dwc2_t cfg = { - .bm_double_buffered = 0, - .vbus_sensing = VBUS_SENSE_EN - }; + tud_configure_dwc2_t cfg = CFG_TUD_CONFIGURE_DWC2_DEFAULT; + cfg.vbus_sensing = VBUS_SENSE_EN; tud_configure(BOARD_TUD_RHPORT, TUD_CFGID_DWC2, &cfg); board_vbus_set(BOARD_TUD_RHPORT, false); #endif diff --git a/hw/bsp/stm32f7/family.c b/hw/bsp/stm32f7/family.c index fc1c0bd13..d8f0da201 100644 --- a/hw/bsp/stm32f7/family.c +++ b/hw/bsp/stm32f7/family.c @@ -157,10 +157,8 @@ void board_init(void) { #endif // vbus sense #if CFG_TUD_ENABLED && BOARD_TUD_RHPORT == 0 - tud_configure_dwc2_t cfg = { - .bm_double_buffered = 0, - .vbus_sensing = OTG_FS_VBUS_SENSE - }; + tud_configure_dwc2_t cfg = CFG_TUD_CONFIGURE_DWC2_DEFAULT; + cfg.vbus_sensing = OTG_FS_VBUS_SENSE; tud_configure(0, TUD_CFGID_DWC2, &cfg); #endif @@ -239,10 +237,8 @@ void board_init(void) { __HAL_RCC_USB_OTG_HS_CLK_ENABLE(); #if CFG_TUD_ENABLED && BOARD_TUD_RHPORT == 1 - tud_configure_dwc2_t cfg = { - .bm_double_buffered = 0, - .vbus_sensing = OTG_HS_VBUS_SENSE - }; + tud_configure_dwc2_t cfg = CFG_TUD_CONFIGURE_DWC2_DEFAULT; + cfg.vbus_sensing = OTG_HS_VBUS_SENSE; tud_configure(1, TUD_CFGID_DWC2, &cfg); #endif diff --git a/hw/bsp/stm32h7/family.c b/hw/bsp/stm32h7/family.c index 920f222d7..a320a7e72 100644 --- a/hw/bsp/stm32h7/family.c +++ b/hw/bsp/stm32h7/family.c @@ -183,10 +183,8 @@ void board_init(void) { #endif // vbus sense #if CFG_TUD_ENABLED && BOARD_TUD_RHPORT == 0 - tud_configure_dwc2_t cfg = { - .bm_double_buffered = 0, - .vbus_sensing = OTG_FS_VBUS_SENSE - }; + tud_configure_dwc2_t cfg = CFG_TUD_CONFIGURE_DWC2_DEFAULT; + cfg.vbus_sensing = OTG_FS_VBUS_SENSE; tud_configure(0, TUD_CFGID_DWC2, &cfg); #endif @@ -215,10 +213,8 @@ void board_init(void) { __HAL_RCC_USB1_OTG_HS_CLK_ENABLE(); #if CFG_TUD_ENABLED && BOARD_TUD_RHPORT == 1 - tud_configure_dwc2_t cfg = { - .bm_double_buffered = 0, - .vbus_sensing = OTG_HS_VBUS_SENSE - }; + tud_configure_dwc2_t cfg = CFG_TUD_CONFIGURE_DWC2_DEFAULT; + cfg.vbus_sensing = OTG_HS_VBUS_SENSE; tud_configure(1, TUD_CFGID_DWC2, &cfg); #endif #endif diff --git a/hw/bsp/stm32h7rs/family.c b/hw/bsp/stm32h7rs/family.c index b1980f2ed..2cc39b7ac 100644 --- a/hw/bsp/stm32h7rs/family.c +++ b/hw/bsp/stm32h7rs/family.c @@ -359,10 +359,8 @@ void board_init(void) { #endif // vbus sense #if CFG_TUD_ENABLED && BOARD_TUD_RHPORT == 0 - tud_configure_dwc2_t cfg = { - .bm_double_buffered = 0, - .vbus_sensing = OTG_FS_VBUS_SENSE - }; + tud_configure_dwc2_t cfg = CFG_TUD_CONFIGURE_DWC2_DEFAULT; + cfg.vbus_sensing = OTG_FS_VBUS_SENSE; tud_configure(0, TUD_CFGID_DWC2, &cfg); #endif @@ -390,10 +388,8 @@ void board_init(void) { #endif #if CFG_TUD_ENABLED && BOARD_TUD_RHPORT == 1 - tud_configure_dwc2_t cfg = { - .bm_double_buffered = 0, - .vbus_sensing = OTG_HS_VBUS_SENSE - }; + tud_configure_dwc2_t cfg = CFG_TUD_CONFIGURE_DWC2_DEFAULT; + cfg.vbus_sensing = OTG_HS_VBUS_SENSE; tud_configure(1, TUD_CFGID_DWC2, &cfg); #endif diff --git a/hw/bsp/stm32l4/family.c b/hw/bsp/stm32l4/family.c index b51a9fc8f..65f6b9ab3 100644 --- a/hw/bsp/stm32l4/family.c +++ b/hw/bsp/stm32l4/family.c @@ -176,10 +176,8 @@ void board_init(void) { #if CFG_TUD_ENABLED /* Set Vbus sense */ - tud_configure_dwc2_t cfg = { - .bm_double_buffered = 0, - .vbus_sensing = VBUS_SENSE_EN - }; + tud_configure_dwc2_t cfg = CFG_TUD_CONFIGURE_DWC2_DEFAULT; + cfg.vbus_sensing = VBUS_SENSE_EN; tud_configure(0, TUD_CFGID_DWC2, &cfg); #endif #else diff --git a/hw/bsp/stm32u5/family.c b/hw/bsp/stm32u5/family.c index c2ea270df..dfcf5c537 100644 --- a/hw/bsp/stm32u5/family.c +++ b/hw/bsp/stm32u5/family.c @@ -182,10 +182,8 @@ void board_init(void) { #endif // vbus sense #if CFG_TUD_ENABLED - tud_configure_dwc2_t cfg = { - .bm_double_buffered = 0, - .vbus_sensing = VBUS_SENSE_EN - }; + tud_configure_dwc2_t cfg = CFG_TUD_CONFIGURE_DWC2_DEFAULT; + cfg.vbus_sensing = VBUS_SENSE_EN; tud_configure(0, TUD_CFGID_DWC2, &cfg); #endif @@ -217,10 +215,8 @@ void board_init(void) { HAL_SYSCFG_EnableOTGPHY(SYSCFG_OTG_HS_PHY_ENABLE); #if CFG_TUD_ENABLED - tud_configure_dwc2_t cfg = { - .bm_double_buffered = 0, - .vbus_sensing = VBUS_SENSE_EN - }; + tud_configure_dwc2_t cfg = CFG_TUD_CONFIGURE_DWC2_DEFAULT; + cfg.vbus_sensing = VBUS_SENSE_EN; tud_configure(0, TUD_CFGID_DWC2, &cfg); #endif #endif // USB_OTG_FS diff --git a/src/device/usbd.h b/src/device/usbd.h index eaf07b81e..825fdba90 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -44,7 +44,9 @@ typedef struct { bool vbus_sensing; // Vbus pin is used for device connection detection, mandatory for tud_umount_cb() } tud_configure_dwc2_t; -#define TUD_CONFIGURE_DWC2_DEFAULT { .bm_double_buffered = 0, .vbus_sensing = CFG_TUD_VBUS_SENSE } + #ifndef CFG_TUD_CONFIGURE_DWC2_DEFAULT + #define CFG_TUD_CONFIGURE_DWC2_DEFAULT {.bm_double_buffered = 0, .vbus_sensing = CFG_TUD_VBUS_DETECT_HW} + #endif typedef union { tud_configure_dwc2_t dwc2; diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index a6a598dbf..97e83f4e1 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -77,7 +77,7 @@ CFG_TUD_MEM_SECTION static struct { TUD_EPBUF_DEF(setup_packet, 8); } _dcd_usbbuf; -static tud_configure_dwc2_t _tud_cfg = TUD_CONFIGURE_DWC2_DEFAULT; +static tud_configure_dwc2_t _tud_cfg = CFG_TUD_CONFIGURE_DWC2_DEFAULT; TU_ATTR_ALWAYS_INLINE static inline uint8_t dwc2_ep_count(const dwc2_regs_t* dwc2) { #if TU_CHECK_MCU(OPT_MCU_GD32VF103) diff --git a/src/tusb_option.h b/src/tusb_option.h index ebf366e17..d87c2dc8b 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -579,13 +579,13 @@ #define CFG_TUD_TEST_MODE 0 #endif -#ifndef CFG_TUD_VBUS_SENSE_DEFAULT - #define CFG_TUD_VBUS_SENSE_DEFAULT 0 +#ifndef CFG_TUD_VBUS_DETECT_HW_DEFAULT + #define CFG_TUD_VBUS_DETECT_HW_DEFAULT 0 #endif -// Enable VBUS Sensing -#ifndef CFG_TUD_VBUS_SENSE - #define CFG_TUD_VBUS_SENSE CFG_TUD_VBUS_SENSE_DEFAULT +// Enable VBUS Detect hardware, usually via functional GPIO +#ifndef CFG_TUD_VBUS_DETECT_HW + #define CFG_TUD_VBUS_DETECT_HW CFG_TUD_VBUS_DETECT_HW_DEFAULT #endif //------------- Device Class Driver -------------// -- cgit v1.3.1 From db1ff5d1692a4407496284b6684438256e1988db Mon Sep 17 00:00:00 2001 From: Cédric Berger Date: Thu, 19 Feb 2026 23:00:27 +0100 Subject: Better variable/function names --- src/portable/synopsys/dwc2/dcd_dwc2.c | 6 +++--- src/portable/synopsys/dwc2/dwc2_common.c | 6 +++--- src/portable/synopsys/dwc2/dwc2_common.h | 4 ++-- src/portable/synopsys/dwc2/hcd_dwc2.c | 10 +++++----- 4 files changed, 13 insertions(+), 13 deletions(-) (limited to 'src/portable') diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index 97e83f4e1..558065134 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -442,14 +442,14 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { tu_memclr(&_dcd_data, sizeof(_dcd_data)); // Core Initialization - const bool is_highspeed = dwc2_core_is_highspeed(dwc2, TUSB_ROLE_DEVICE); + const bool highspeed_phy = dwc2_core_is_highspeed_phy(dwc2, TUSB_ROLE_DEVICE); const bool is_dma = dma_device_enabled(dwc2); - TU_ASSERT(dwc2_core_init(rhport, is_highspeed, is_dma)); + TU_ASSERT(dwc2_core_init(rhport, highspeed_phy, is_dma)); //------------- 7.1 Device Initialization -------------// // Set device max speed uint32_t dcfg = dwc2->dcfg & ~DCFG_DSPD_Msk; - if (is_highspeed) { + if (highspeed_phy) { // dcfg Highspeed's mask is 0 // XCVRDLY: transceiver delay between xcvr_sel and txvalid during device chirp is required diff --git a/src/portable/synopsys/dwc2/dwc2_common.c b/src/portable/synopsys/dwc2/dwc2_common.c index a7e6188df..5429af440 100644 --- a/src/portable/synopsys/dwc2/dwc2_common.c +++ b/src/portable/synopsys/dwc2/dwc2_common.c @@ -179,7 +179,7 @@ static bool check_dwc2(dwc2_regs_t* dwc2) { //-------------------------------------------------------------------- // //-------------------------------------------------------------------- -bool dwc2_core_is_highspeed(dwc2_regs_t* dwc2, tusb_role_t role) { +bool dwc2_core_is_highspeed_phy(dwc2_regs_t* dwc2, tusb_role_t role) { (void)dwc2; #if CFG_TUD_ENABLED if (role == TUSB_ROLE_DEVICE && !TUD_OPT_HIGH_SPEED) { @@ -204,7 +204,7 @@ bool dwc2_core_is_highspeed(dwc2_regs_t* dwc2, tusb_role_t role) { * In addition, UTMI+/ULPI can be shared to run at fullspeed mode with 48Mhz * */ -bool dwc2_core_init(uint8_t rhport, bool is_highspeed, bool is_dma) { +bool dwc2_core_init(uint8_t rhport, bool highspeed_phy, bool is_dma) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); // Check Synopsys ID register, failed if controller clock/power is not enabled @@ -213,7 +213,7 @@ bool dwc2_core_init(uint8_t rhport, bool is_highspeed, bool is_dma) { // disable global interrupt dwc2->gahbcfg &= ~GAHBCFG_GINT; - if (is_highspeed) { + if (highspeed_phy) { phy_hs_init(dwc2); } else { phy_fs_init(dwc2); diff --git a/src/portable/synopsys/dwc2/dwc2_common.h b/src/portable/synopsys/dwc2/dwc2_common.h index 428304ba9..b03fecad9 100644 --- a/src/portable/synopsys/dwc2/dwc2_common.h +++ b/src/portable/synopsys/dwc2/dwc2_common.h @@ -84,8 +84,8 @@ TU_ATTR_ALWAYS_INLINE static inline dwc2_regs_t* DWC2_REG(uint8_t rhport) { return (dwc2_regs_t*)_dwc2_controller[rhport].reg_base; } -bool dwc2_core_is_highspeed(dwc2_regs_t* dwc2, tusb_role_t role); -bool dwc2_core_init(uint8_t rhport, bool is_highspeed, bool is_dma); +bool dwc2_core_is_highspeed_phy(dwc2_regs_t* dwc2, tusb_role_t role); +bool dwc2_core_init(uint8_t rhport, bool highspeed_phy, bool is_dma); void dwc2_core_handle_common_irq(uint8_t rhport, bool in_isr); //--------------------------------------------------------------------+ diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index 8182fd6cc..2d667eb43 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -364,9 +364,9 @@ static void dfifo_host_init(uint8_t rhport) { // fixed allocation for now, improve later: // - ptx_largest is limited to 256 for FS since most FS core only has 1024 bytes total - bool is_highspeed = dwc2_core_is_highspeed(dwc2, TUSB_ROLE_HOST); - uint32_t nptx_largest = is_highspeed ? TUSB_EPSIZE_BULK_HS/4 : TUSB_EPSIZE_BULK_FS/4; - uint32_t ptx_largest = is_highspeed ? TUSB_EPSIZE_ISO_HS_MAX/4 : 256/4; + bool highspeed_phy = dwc2_core_is_highspeed_phy(dwc2, TUSB_ROLE_HOST); + uint32_t nptx_largest = highspeed_phy ? TUSB_EPSIZE_BULK_HS/4 : TUSB_EPSIZE_BULK_FS/4; + uint32_t ptx_largest = highspeed_phy ? TUSB_EPSIZE_ISO_HS_MAX/4 : 256/4; uint16_t nptxfsiz = 2 * nptx_largest; uint16_t rxfsiz = 2 * (ptx_largest + 2) + ghwcfg2.num_host_ch; @@ -406,9 +406,9 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { tu_memclr(&_hcd_data, sizeof(_hcd_data)); // Core Initialization - const bool is_highspeed = dwc2_core_is_highspeed(dwc2, TUSB_ROLE_HOST); + const bool highspeed_phy = dwc2_core_is_highspeed_phy(dwc2, TUSB_ROLE_HOST); const bool is_dma = dma_host_enabled(dwc2); - TU_ASSERT(dwc2_core_init(rhport, is_highspeed, is_dma)); + TU_ASSERT(dwc2_core_init(rhport, highspeed_phy, is_dma)); //------------- 3.1 Host Initialization -------------// -- cgit v1.3.1 From c8265a3709ebe6b5f77aa3b5bb148740c5818f00 Mon Sep 17 00:00:00 2001 From: Cédric Berger Date: Thu, 19 Feb 2026 23:03:32 +0100 Subject: Introduce TUH_CFGID_PHY_SPEED configure option --- src/host/usbh.h | 1 + src/portable/synopsys/dwc2/dwc2_common.c | 9 +++++++-- src/portable/synopsys/dwc2/dwc2_common.h | 3 +++ src/portable/synopsys/dwc2/hcd_dwc2.c | 18 +++++++++++------- 4 files changed, 22 insertions(+), 9 deletions(-) (limited to 'src/portable') diff --git a/src/host/usbh.h b/src/host/usbh.h index d86efbcb2..03577ba3f 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -93,6 +93,7 @@ typedef struct { // ConfigID for tuh_configure() enum { TUH_CFGID_INVALID = 0, + TUH_CFGID_PHY_SPEED = 10, // cfg_param: tusb_speed_t TUH_CFGID_RPI_PIO_USB_CONFIGURATION = 100, // cfg_param: pio_usb_configuration_t TUH_CFGID_MAX3421 = 200, TUH_CFGID_FSDEV = 300, diff --git a/src/portable/synopsys/dwc2/dwc2_common.c b/src/portable/synopsys/dwc2/dwc2_common.c index 5429af440..429c56123 100644 --- a/src/portable/synopsys/dwc2/dwc2_common.c +++ b/src/portable/synopsys/dwc2/dwc2_common.c @@ -187,8 +187,13 @@ bool dwc2_core_is_highspeed_phy(dwc2_regs_t* dwc2, tusb_role_t role) { } #endif #if CFG_TUH_ENABLED - if (role == TUSB_ROLE_HOST && !TUH_OPT_HIGH_SPEED) { - return false; + if (role == TUSB_ROLE_HOST) { + if (_hcd_cfg_phy_speed == TUSB_SPEED_HIGH) + return true; + if (_hcd_cfg_phy_speed < TUSB_SPEED_HIGH) + return false; + if (!TUH_OPT_HIGH_SPEED) + return false; } #endif diff --git a/src/portable/synopsys/dwc2/dwc2_common.h b/src/portable/synopsys/dwc2/dwc2_common.h index b03fecad9..16a18c673 100644 --- a/src/portable/synopsys/dwc2/dwc2_common.h +++ b/src/portable/synopsys/dwc2/dwc2_common.h @@ -76,6 +76,9 @@ enum { //--------------------------------------------------------------------+ // Core/Controller //--------------------------------------------------------------------+ + +extern tusb_speed_t _hcd_cfg_phy_speed; + TU_ATTR_ALWAYS_INLINE static inline dwc2_regs_t* DWC2_REG(uint8_t rhport) { if (rhport >= DWC2_CONTROLLER_COUNT) { // user mis-configured, ignore and use first controller diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index 2d667eb43..99be779ef 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -112,6 +112,7 @@ typedef struct { } hcd_data_t; hcd_data_t _hcd_data; +tusb_speed_t _hcd_cfg_phy_speed = TUSB_SPEED_AUTO; //-------------------------------------------------------------------- // @@ -392,15 +393,13 @@ static void dfifo_host_init(uint8_t rhport) { // 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; - + TU_VERIFY(cfg_id == TUH_CFGID_PHY_SPEED && cfg_param != NULL); + _hcd_cfg_phy_speed = *(const tusb_speed_t *)cfg_param; return true; } // Initialize controller to host mode bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { - (void) rh_init; dwc2_regs_t* dwc2 = DWC2_REG(rhport); tu_memclr(&_hcd_data, sizeof(_hcd_data)); @@ -412,9 +411,6 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { //------------- 3.1 Host Initialization -------------// - // work at max supported speed - dwc2->hcfg &= ~HCFG_FSLS_ONLY; - // Enable HFIR reload if (dwc2->gsnpsid >= DWC2_CORE_REV_2_92a) { dwc2->hfir |= HFIR_RELOAD_CTRL; @@ -432,6 +428,14 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { dwc2_stm32_gccfg_cfg(dwc2, false, true); #endif + if (highspeed_phy && rh_init->speed < TUSB_SPEED_HIGH) { + // disable high speed mode + dwc2->hcfg |= HCFG_FSLS_ONLY; + } else { + // work at max supported speed + dwc2->hcfg &= ~HCFG_FSLS_ONLY; + } + // configure fixed-allocated fifo scheme dfifo_host_init(rhport); -- cgit v1.3.1 From 7e6177097166073579418ce1ff98aa2185f48396 Mon Sep 17 00:00:00 2001 From: Cédric Berger Date: Thu, 19 Feb 2026 23:30:25 +0100 Subject: Fix a couple indentations --- src/portable/synopsys/dwc2/dwc2_common.c | 12 ++++++------ src/portable/synopsys/dwc2/hcd_dwc2.c | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) (limited to 'src/portable') diff --git a/src/portable/synopsys/dwc2/dwc2_common.c b/src/portable/synopsys/dwc2/dwc2_common.c index 429c56123..8c2324283 100644 --- a/src/portable/synopsys/dwc2/dwc2_common.c +++ b/src/portable/synopsys/dwc2/dwc2_common.c @@ -188,12 +188,12 @@ bool dwc2_core_is_highspeed_phy(dwc2_regs_t* dwc2, tusb_role_t role) { #endif #if CFG_TUH_ENABLED if (role == TUSB_ROLE_HOST) { - if (_hcd_cfg_phy_speed == TUSB_SPEED_HIGH) - return true; - if (_hcd_cfg_phy_speed < TUSB_SPEED_HIGH) - return false; - if (!TUH_OPT_HIGH_SPEED) - return false; + if (_hcd_cfg_phy_speed == TUSB_SPEED_HIGH) + return true; + if (_hcd_cfg_phy_speed < TUSB_SPEED_HIGH) + return false; + if (!TUH_OPT_HIGH_SPEED) + return false; } #endif diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index 99be779ef..9f8133196 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -429,11 +429,11 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { #endif if (highspeed_phy && rh_init->speed < TUSB_SPEED_HIGH) { - // disable high speed mode - dwc2->hcfg |= HCFG_FSLS_ONLY; + // disable high speed mode + dwc2->hcfg |= HCFG_FSLS_ONLY; } else { - // work at max supported speed - dwc2->hcfg &= ~HCFG_FSLS_ONLY; + // work at max supported speed + dwc2->hcfg &= ~HCFG_FSLS_ONLY; } // configure fixed-allocated fifo scheme -- cgit v1.3.1 From c5ec572396d3f5bae05d4f0baa2c026598604f48 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 20 Feb 2026 13:57:34 +0100 Subject: refactor config option Signed-off-by: HiFiPhile --- src/host/usbh.h | 7 ++++++- src/portable/synopsys/dwc2/dwc2_common.c | 9 ++------- src/portable/synopsys/dwc2/dwc2_common.h | 3 --- src/portable/synopsys/dwc2/hcd_dwc2.c | 13 +++++++------ 4 files changed, 15 insertions(+), 17 deletions(-) (limited to 'src/portable') diff --git a/src/host/usbh.h b/src/host/usbh.h index 03577ba3f..2f332b442 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -93,10 +93,10 @@ typedef struct { // ConfigID for tuh_configure() enum { TUH_CFGID_INVALID = 0, - TUH_CFGID_PHY_SPEED = 10, // cfg_param: tusb_speed_t TUH_CFGID_RPI_PIO_USB_CONFIGURATION = 100, // cfg_param: pio_usb_configuration_t TUH_CFGID_MAX3421 = 200, TUH_CFGID_FSDEV = 300, + TUH_CFGID_DWC2 = 400 }; typedef struct { @@ -109,10 +109,15 @@ typedef struct { uint8_t max_nak; // max NAK per endpoint per frame to save CPU usage (0=unlimited) } tuh_configure_fsdev_t; +typedef struct { + bool use_hs_phy; // Always use high-speed ULPI/UTMI phy even working at full-speed +} tuh_configure_dwc2_t; + typedef union { // For TUH_CFGID_RPI_PIO_USB_CONFIGURATION use pio_usb_configuration_t tuh_configure_max3421_t max3421; tuh_configure_fsdev_t fsdev; + tuh_configure_dwc2_t dwc2; } tuh_configure_param_t; //--------------------------------------------------------------------+ diff --git a/src/portable/synopsys/dwc2/dwc2_common.c b/src/portable/synopsys/dwc2/dwc2_common.c index 8c2324283..5429af440 100644 --- a/src/portable/synopsys/dwc2/dwc2_common.c +++ b/src/portable/synopsys/dwc2/dwc2_common.c @@ -187,13 +187,8 @@ bool dwc2_core_is_highspeed_phy(dwc2_regs_t* dwc2, tusb_role_t role) { } #endif #if CFG_TUH_ENABLED - if (role == TUSB_ROLE_HOST) { - if (_hcd_cfg_phy_speed == TUSB_SPEED_HIGH) - return true; - if (_hcd_cfg_phy_speed < TUSB_SPEED_HIGH) - return false; - if (!TUH_OPT_HIGH_SPEED) - return false; + if (role == TUSB_ROLE_HOST && !TUH_OPT_HIGH_SPEED) { + return false; } #endif diff --git a/src/portable/synopsys/dwc2/dwc2_common.h b/src/portable/synopsys/dwc2/dwc2_common.h index 16a18c673..b03fecad9 100644 --- a/src/portable/synopsys/dwc2/dwc2_common.h +++ b/src/portable/synopsys/dwc2/dwc2_common.h @@ -76,9 +76,6 @@ enum { //--------------------------------------------------------------------+ // Core/Controller //--------------------------------------------------------------------+ - -extern tusb_speed_t _hcd_cfg_phy_speed; - TU_ATTR_ALWAYS_INLINE static inline dwc2_regs_t* DWC2_REG(uint8_t rhport) { if (rhport >= DWC2_CONTROLLER_COUNT) { // user mis-configured, ignore and use first controller diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index 9f8133196..0fbb55191 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -111,8 +111,9 @@ typedef struct { hcd_endpoint_t edpt[CFG_TUH_DWC2_ENDPOINT_MAX]; } hcd_data_t; -hcd_data_t _hcd_data; -tusb_speed_t _hcd_cfg_phy_speed = TUSB_SPEED_AUTO; +static hcd_data_t _hcd_data; + +static tuh_configure_dwc2_t _tuh_cfg = {.use_hs_phy = TUH_OPT_HIGH_SPEED}; //-------------------------------------------------------------------- // @@ -393,8 +394,8 @@ static void dfifo_host_init(uint8_t rhport) { // optional hcd configuration, called by tuh_configure() bool hcd_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param) { (void) rhport; - TU_VERIFY(cfg_id == TUH_CFGID_PHY_SPEED && cfg_param != NULL); - _hcd_cfg_phy_speed = *(const tusb_speed_t *)cfg_param; + TU_VERIFY(cfg_id == TUH_CFGID_DWC2 && cfg_param != NULL); + _tuh_cfg = *(const tuh_configure_dwc2_t *)cfg_param; return true; } @@ -405,7 +406,7 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { tu_memclr(&_hcd_data, sizeof(_hcd_data)); // Core Initialization - const bool highspeed_phy = dwc2_core_is_highspeed_phy(dwc2, TUSB_ROLE_HOST); + const bool highspeed_phy = dwc2_core_is_highspeed_phy(dwc2, TUSB_ROLE_HOST) || _tuh_cfg.use_hs_phy; const bool is_dma = dma_host_enabled(dwc2); TU_ASSERT(dwc2_core_init(rhport, highspeed_phy, is_dma)); @@ -428,7 +429,7 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { dwc2_stm32_gccfg_cfg(dwc2, false, true); #endif - if (highspeed_phy && rh_init->speed < TUSB_SPEED_HIGH) { + if (rh_init->speed < TUSB_SPEED_HIGH || !TUH_OPT_HIGH_SPEED) { // disable high speed mode dwc2->hcfg |= HCFG_FSLS_ONLY; } else { -- cgit v1.3.1 From 167a50714636261b72ed6fc3f7c6682c209c0d7f Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sat, 21 Feb 2026 17:03:06 +0100 Subject: fix ci Signed-off-by: HiFiPhile --- src/portable/synopsys/dwc2/hcd_dwc2.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/portable') diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index 0fbb55191..f7dc93ae1 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -432,10 +432,13 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { if (rh_init->speed < TUSB_SPEED_HIGH || !TUH_OPT_HIGH_SPEED) { // disable high speed mode dwc2->hcfg |= HCFG_FSLS_ONLY; - } else { + } +#if TUH_OPT_HIGH_SPEED + else { // work at max supported speed dwc2->hcfg &= ~HCFG_FSLS_ONLY; } +#endif // configure fixed-allocated fifo scheme dfifo_host_init(rhport); -- cgit v1.3.1 From dafb0d2bf4b99531fe632acb621861cb64c80e66 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sat, 21 Feb 2026 17:34:11 +0100 Subject: check femtoPHY speed Signed-off-by: HiFiPhile --- src/portable/synopsys/dwc2/dwc2_common.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src/portable') diff --git a/src/portable/synopsys/dwc2/dwc2_common.c b/src/portable/synopsys/dwc2/dwc2_common.c index 5429af440..70e38b9f7 100644 --- a/src/portable/synopsys/dwc2/dwc2_common.c +++ b/src/portable/synopsys/dwc2/dwc2_common.c @@ -180,7 +180,13 @@ static bool check_dwc2(dwc2_regs_t* dwc2) { // //-------------------------------------------------------------------- bool dwc2_core_is_highspeed_phy(dwc2_regs_t* dwc2, tusb_role_t role) { - (void)dwc2; +#ifdef TUP_USBIP_DWC2_STM32 + if (dwc2->guid >= 0x5000) { + // femtoPHY UTMI+ PHY + return true; + } +#endif + #if CFG_TUD_ENABLED if (role == TUSB_ROLE_DEVICE && !TUD_OPT_HIGH_SPEED) { return false; -- cgit v1.3.1 From b585df168a3489845cda3cb732560d4fe260e609 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sat, 21 Feb 2026 17:44:17 +0100 Subject: refactor speed check Signed-off-by: HiFiPhile --- src/portable/synopsys/dwc2/dcd_dwc2.c | 2 +- src/portable/synopsys/dwc2/dwc2_common.c | 11 ++--------- src/portable/synopsys/dwc2/dwc2_common.h | 2 +- src/portable/synopsys/dwc2/hcd_dwc2.c | 4 ++-- 4 files changed, 6 insertions(+), 13 deletions(-) (limited to 'src/portable') diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index 558065134..dec2db5f2 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -442,7 +442,7 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { tu_memclr(&_dcd_data, sizeof(_dcd_data)); // Core Initialization - const bool highspeed_phy = dwc2_core_is_highspeed_phy(dwc2, TUSB_ROLE_DEVICE); + const bool highspeed_phy = dwc2_core_is_highspeed_phy(dwc2, TUD_OPT_HIGH_SPEED); const bool is_dma = dma_device_enabled(dwc2); TU_ASSERT(dwc2_core_init(rhport, highspeed_phy, is_dma)); diff --git a/src/portable/synopsys/dwc2/dwc2_common.c b/src/portable/synopsys/dwc2/dwc2_common.c index 70e38b9f7..d26e2daca 100644 --- a/src/portable/synopsys/dwc2/dwc2_common.c +++ b/src/portable/synopsys/dwc2/dwc2_common.c @@ -179,7 +179,7 @@ static bool check_dwc2(dwc2_regs_t* dwc2) { //-------------------------------------------------------------------- // //-------------------------------------------------------------------- -bool dwc2_core_is_highspeed_phy(dwc2_regs_t* dwc2, tusb_role_t role) { +bool dwc2_core_is_highspeed_phy(dwc2_regs_t* dwc2, bool prefer_hs_phy) { #ifdef TUP_USBIP_DWC2_STM32 if (dwc2->guid >= 0x5000) { // femtoPHY UTMI+ PHY @@ -187,16 +187,9 @@ bool dwc2_core_is_highspeed_phy(dwc2_regs_t* dwc2, tusb_role_t role) { } #endif -#if CFG_TUD_ENABLED - if (role == TUSB_ROLE_DEVICE && !TUD_OPT_HIGH_SPEED) { + if (!prefer_hs_phy) { return false; } -#endif -#if CFG_TUH_ENABLED - if (role == TUSB_ROLE_HOST && !TUH_OPT_HIGH_SPEED) { - return false; - } -#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_common.h b/src/portable/synopsys/dwc2/dwc2_common.h index b03fecad9..aacb62536 100644 --- a/src/portable/synopsys/dwc2/dwc2_common.h +++ b/src/portable/synopsys/dwc2/dwc2_common.h @@ -84,7 +84,7 @@ TU_ATTR_ALWAYS_INLINE static inline dwc2_regs_t* DWC2_REG(uint8_t rhport) { return (dwc2_regs_t*)_dwc2_controller[rhport].reg_base; } -bool dwc2_core_is_highspeed_phy(dwc2_regs_t* dwc2, tusb_role_t role); +bool dwc2_core_is_highspeed_phy(dwc2_regs_t* dwc2, bool prefer_hs_phy); bool dwc2_core_init(uint8_t rhport, bool highspeed_phy, bool is_dma); void dwc2_core_handle_common_irq(uint8_t rhport, bool in_isr); diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index f7dc93ae1..c9ea144c8 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -366,7 +366,7 @@ static void dfifo_host_init(uint8_t rhport) { // fixed allocation for now, improve later: // - ptx_largest is limited to 256 for FS since most FS core only has 1024 bytes total - bool highspeed_phy = dwc2_core_is_highspeed_phy(dwc2, TUSB_ROLE_HOST); + bool highspeed_phy = dwc2_core_is_highspeed_phy(dwc2, _tuh_cfg.use_hs_phy); uint32_t nptx_largest = highspeed_phy ? TUSB_EPSIZE_BULK_HS/4 : TUSB_EPSIZE_BULK_FS/4; uint32_t ptx_largest = highspeed_phy ? TUSB_EPSIZE_ISO_HS_MAX/4 : 256/4; @@ -406,7 +406,7 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { tu_memclr(&_hcd_data, sizeof(_hcd_data)); // Core Initialization - const bool highspeed_phy = dwc2_core_is_highspeed_phy(dwc2, TUSB_ROLE_HOST) || _tuh_cfg.use_hs_phy; + const bool highspeed_phy = dwc2_core_is_highspeed_phy(dwc2, _tuh_cfg.use_hs_phy); const bool is_dma = dma_host_enabled(dwc2); TU_ASSERT(dwc2_core_init(rhport, highspeed_phy, is_dma)); -- cgit v1.3.1 From e947af26c62fe8717f754e072a18e9e24f33ca96 Mon Sep 17 00:00:00 2001 From: Zixun LI Date: Sun, 22 Feb 2026 13:33:29 +0100 Subject: Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/host/usbh.h | 2 +- src/portable/synopsys/dwc2/hcd_dwc2.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'src/portable') diff --git a/src/host/usbh.h b/src/host/usbh.h index 2f332b442..143d36f8c 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -110,7 +110,7 @@ typedef struct { } tuh_configure_fsdev_t; typedef struct { - bool use_hs_phy; // Always use high-speed ULPI/UTMI phy even working at full-speed + bool use_hs_phy; // Always use high-speed ULPI/UTMI phy even when working at full-speed } tuh_configure_dwc2_t; typedef union { diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index c9ea144c8..ac6fcceb1 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -395,7 +395,8 @@ static void dfifo_host_init(uint8_t rhport) { bool hcd_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param) { (void) rhport; TU_VERIFY(cfg_id == TUH_CFGID_DWC2 && cfg_param != NULL); - _tuh_cfg = *(const tuh_configure_dwc2_t *)cfg_param; + tuh_configure_param_t const* cfg = (tuh_configure_param_t const*) cfg_param; + _tuh_cfg = cfg->dwc2; return true; } -- cgit v1.3.1 From 1eef6f4f4f7a26a5be3c4b774992aadcc8660820 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 23 Feb 2026 15:34:59 +0700 Subject: refactor: improve high-speed PHY handling and FIFO configuration in DWC2 driver --- src/portable/synopsys/dwc2/dcd_dwc2.c | 6 ++--- src/portable/synopsys/dwc2/dwc2_common.c | 4 ++-- src/portable/synopsys/dwc2/dwc2_common.h | 2 +- src/portable/synopsys/dwc2/hcd_dwc2.c | 39 +++++++++++++++----------------- 4 files changed, 24 insertions(+), 27 deletions(-) (limited to 'src/portable') diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index dec2db5f2..d1d4b080e 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -442,14 +442,14 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { tu_memclr(&_dcd_data, sizeof(_dcd_data)); // Core Initialization - const bool highspeed_phy = dwc2_core_is_highspeed_phy(dwc2, TUD_OPT_HIGH_SPEED); + const bool is_hs_phy = dwc2_core_is_highspeed_phy(dwc2, TUD_OPT_HIGH_SPEED); const bool is_dma = dma_device_enabled(dwc2); - TU_ASSERT(dwc2_core_init(rhport, highspeed_phy, is_dma)); + TU_ASSERT(dwc2_core_init(rhport, is_hs_phy, is_dma)); //------------- 7.1 Device Initialization -------------// // Set device max speed uint32_t dcfg = dwc2->dcfg & ~DCFG_DSPD_Msk; - if (highspeed_phy) { + if (is_hs_phy) { // dcfg Highspeed's mask is 0 // XCVRDLY: transceiver delay between xcvr_sel and txvalid during device chirp is required diff --git a/src/portable/synopsys/dwc2/dwc2_common.c b/src/portable/synopsys/dwc2/dwc2_common.c index d26e2daca..98ef22d03 100644 --- a/src/portable/synopsys/dwc2/dwc2_common.c +++ b/src/portable/synopsys/dwc2/dwc2_common.c @@ -203,7 +203,7 @@ bool dwc2_core_is_highspeed_phy(dwc2_regs_t* dwc2, bool prefer_hs_phy) { * In addition, UTMI+/ULPI can be shared to run at fullspeed mode with 48Mhz * */ -bool dwc2_core_init(uint8_t rhport, bool highspeed_phy, bool is_dma) { +bool dwc2_core_init(uint8_t rhport, bool is_hs_phy, bool is_dma) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); // Check Synopsys ID register, failed if controller clock/power is not enabled @@ -212,7 +212,7 @@ bool dwc2_core_init(uint8_t rhport, bool highspeed_phy, bool is_dma) { // disable global interrupt dwc2->gahbcfg &= ~GAHBCFG_GINT; - if (highspeed_phy) { + if (is_hs_phy) { phy_hs_init(dwc2); } else { phy_fs_init(dwc2); diff --git a/src/portable/synopsys/dwc2/dwc2_common.h b/src/portable/synopsys/dwc2/dwc2_common.h index aacb62536..6ee351ab5 100644 --- a/src/portable/synopsys/dwc2/dwc2_common.h +++ b/src/portable/synopsys/dwc2/dwc2_common.h @@ -85,7 +85,7 @@ TU_ATTR_ALWAYS_INLINE static inline dwc2_regs_t* DWC2_REG(uint8_t rhport) { } bool dwc2_core_is_highspeed_phy(dwc2_regs_t* dwc2, bool prefer_hs_phy); -bool dwc2_core_init(uint8_t rhport, bool highspeed_phy, bool is_dma); +bool dwc2_core_init(uint8_t rhport, bool is_hs_phy, bool is_dma); void dwc2_core_handle_common_irq(uint8_t rhport, bool in_isr); //--------------------------------------------------------------------+ diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index ac6fcceb1..cc11c82d7 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -112,7 +112,6 @@ typedef struct { } hcd_data_t; static hcd_data_t _hcd_data; - static tuh_configure_dwc2_t _tuh_cfg = {.use_hs_phy = TUH_OPT_HIGH_SPEED}; //-------------------------------------------------------------------- @@ -352,7 +351,7 @@ TU_ATTR_ALWAYS_INLINE static inline uint8_t cal_next_pid(uint8_t pid, uint8_t pa * TX periodic (PTX) * - At least largest-EPsize*MulCount/4 (MulCount up to 3 for high-bandwidth ISO/interrupt) */ -static void dfifo_host_init(uint8_t rhport) { +static void dfifo_host_init(uint8_t rhport, bool is_highspeed) { const dwc2_controller_t* dwc2_controller = &_dwc2_controller[rhport]; dwc2_regs_t* dwc2 = DWC2_REG(rhport); const dwc2_ghwcfg2_t ghwcfg2 = {.value = dwc2->ghwcfg2}; @@ -365,10 +364,9 @@ static void dfifo_host_init(uint8_t rhport) { } // fixed allocation for now, improve later: - // - ptx_largest is limited to 256 for FS since most FS core only has 1024 bytes total - bool highspeed_phy = dwc2_core_is_highspeed_phy(dwc2, _tuh_cfg.use_hs_phy); - uint32_t nptx_largest = highspeed_phy ? TUSB_EPSIZE_BULK_HS/4 : TUSB_EPSIZE_BULK_FS/4; - uint32_t ptx_largest = highspeed_phy ? TUSB_EPSIZE_ISO_HS_MAX/4 : 256/4; + // - ptx_largest is limited to 256 for FS since most FS core only has 1024 bytes total + uint32_t nptx_largest = is_highspeed ? TUSB_EPSIZE_BULK_HS / 4 : TUSB_EPSIZE_BULK_FS / 4; + 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) + ghwcfg2.num_host_ch; @@ -403,16 +401,14 @@ bool hcd_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param) { // Initialize controller to host mode bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); - tu_memclr(&_hcd_data, sizeof(_hcd_data)); // Core Initialization - const bool highspeed_phy = dwc2_core_is_highspeed_phy(dwc2, _tuh_cfg.use_hs_phy); + const bool is_hs_phy = dwc2_core_is_highspeed_phy(dwc2, _tuh_cfg.use_hs_phy); const bool is_dma = dma_host_enabled(dwc2); - TU_ASSERT(dwc2_core_init(rhport, highspeed_phy, is_dma)); + TU_ASSERT(dwc2_core_init(rhport, is_hs_phy, is_dma)); //------------- 3.1 Host Initialization -------------// - // Enable HFIR reload if (dwc2->gsnpsid >= DWC2_CORE_REV_2_92a) { dwc2->hfir |= HFIR_RELOAD_CTRL; @@ -426,23 +422,24 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { #endif while ((dwc2->gintsts & GINTSTS_CMOD) != GINTSTS_CMODE_HOST) {} -#ifdef TUP_USBIP_DWC2_STM32 + #ifdef TUP_USBIP_DWC2_STM32 dwc2_stm32_gccfg_cfg(dwc2, false, true); -#endif + #endif - if (rh_init->speed < TUSB_SPEED_HIGH || !TUH_OPT_HIGH_SPEED) { - // disable high speed mode - dwc2->hcfg |= HCFG_FSLS_ONLY; + bool is_highspeed; + if (!TUH_OPT_HIGH_SPEED || rh_init->speed < TUSB_SPEED_HIGH) { + dwc2->hcfg |= HCFG_FSLS_ONLY; // disable high speed mode + is_highspeed = false; } -#if TUH_OPT_HIGH_SPEED + #if TUH_OPT_HIGH_SPEED else { - // work at max supported speed - dwc2->hcfg &= ~HCFG_FSLS_ONLY; + dwc2->hcfg &= ~HCFG_FSLS_ONLY; // work at max supported speed + is_highspeed = true; } -#endif + #endif - // configure fixed-allocated fifo scheme - dfifo_host_init(rhport); + // configure a fixed-allocated fifo scheme + dfifo_host_init(rhport, is_highspeed); dwc2->hprt = HPRT_W1_MASK; // clear all write-1-clear bits dwc2->hprt = HPRT_POWER; // turn on VBUS -- cgit v1.3.1 From f179b2957dbe00ad937eb50ada42dc32233a7a93 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 23 Feb 2026 19:33:29 +0700 Subject: refactor: streamline high-speed PHY detection and configuration in DWC2 driver --- AGENTS.md | 10 +++++++-- src/portable/synopsys/dwc2/dcd_dwc2.c | 2 +- src/portable/synopsys/dwc2/dwc2_common.c | 35 +++++++++++++++----------------- src/portable/synopsys/dwc2/dwc2_common.h | 1 + src/portable/synopsys/dwc2/hcd_dwc2.c | 27 ++++++++++-------------- 5 files changed, 37 insertions(+), 38 deletions(-) (limited to 'src/portable') diff --git a/AGENTS.md b/AGENTS.md index 73bf1f599..ef8baec5a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -101,9 +101,15 @@ make BOARD=raspberry_pi_pico all ## Hardware-in-the-Loop (HIL) Testing +- `-B examples` means `examples` is the parent folder that contains multi-board build outputs such as `examples/cmake-build-BOARD_NAME/...` +- Select config file before running HIL tests: + - if GitHub Actions self-hosted runner service is running, use `tinyusb.json` + - otherwise use `local.json` + - example: + `HIL_CONFIG=$( (systemctl list-units --type=service --state=running 2>/dev/null; systemctl --user list-units --type=service --state=running 2>/dev/null) | grep -q 'actions\.runner' && echo tinyusb.json || echo local.json )` - Run tests on actual hardware, one of following ways: - - test a specific board `python test/hil/hil_test.py -b BOARD_NAME -B examples local.json` - - test all boards in config `python test/hil/hil_test.py -B examples local.json` + - test a specific board `python test/hil/hil_test.py -b BOARD_NAME -B examples $HIL_CONFIG` + - test all boards in config `python test/hil/hil_test.py -B examples $HIL_CONFIG` - In case of error, enabled verbose mode with `-v` flag for detailed logs. Also try to observe script output, and try to modify hil_test.py (temporarily) to add more debug prints to pinpoint the issue. - Requires pre-built (all) examples for target boards (see Build Examples section 2) diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index d1d4b080e..2e2b050bc 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -479,7 +479,7 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { #ifdef TUP_USBIP_DWC2_STM32 dwc2_stm32_gccfg_cfg(dwc2, _tud_cfg.vbus_sensing, false); -#endif + #endif // Enable required interrupts dwc2->gintmsk |= GINTMSK_OTGINT | GINTMSK_USBRST | GINTMSK_ENUMDNEM | GINTMSK_WUIM; diff --git a/src/portable/synopsys/dwc2/dwc2_common.c b/src/portable/synopsys/dwc2/dwc2_common.c index 98ef22d03..27dda44ee 100644 --- a/src/portable/synopsys/dwc2/dwc2_common.c +++ b/src/portable/synopsys/dwc2/dwc2_common.c @@ -60,6 +60,7 @@ static void reset_core(dwc2_regs_t* dwc2) { while (!(dwc2->grstctl & GRSTCTL_AHBIDL)) {} // wait for AHB master IDLE } +// Dedicated FS PHY is internal with a clock 48Mhz. static void phy_fs_init(dwc2_regs_t* dwc2) { TU_LOG(DWC2_COMMON_DEBUG, "Fullspeed PHY init\r\n"); @@ -86,6 +87,13 @@ static void phy_fs_init(dwc2_regs_t* dwc2) { dwc2_phy_update(dwc2, GHWCFG2_HSPHY_NOT_SUPPORTED); } +/* dwc2 has 2 highspeed PHYs options + * - UTMI+ is internal highspeed PHY, can be clocked at 30/60 Mhz for fullspeed or 60 Mhz for highspeed. Can be either + * 8 or 16-bit interface. + * - ULPI is external highspeed PHY, clocked at 60Mhz with 8-bit interface. + * + * In addition, UTMI+/ULPI can be shared to run at fullspeed mode with 48Mhz + */ static void phy_hs_init(dwc2_regs_t* dwc2) { uint32_t gusbcfg = dwc2->gusbcfg; const dwc2_ghwcfg2_t ghwcfg2 = {.value = dwc2->ghwcfg2}; @@ -180,29 +188,18 @@ static bool check_dwc2(dwc2_regs_t* dwc2) { // //-------------------------------------------------------------------- bool dwc2_core_is_highspeed_phy(dwc2_regs_t* dwc2, bool prefer_hs_phy) { -#ifdef TUP_USBIP_DWC2_STM32 - if (dwc2->guid >= 0x5000) { - // femtoPHY UTMI+ PHY - return true; - } -#endif + const dwc2_ghwcfg2_t ghwcfg2 = {.value = dwc2->ghwcfg2}; + const bool has_hs_phy = (ghwcfg2.hs_phy_type != GHWCFG2_HSPHY_NOT_SUPPORTED); - if (!prefer_hs_phy) { - return false; + if (prefer_hs_phy) { + return has_hs_phy; + } else { + const bool has_fs_phy = (ghwcfg2.fs_phy_type != GHWCFG2_FSPHY_NOT_SUPPORTED); + // false if has fs phy, otherwise true since hs phy is the only available phy + return !has_fs_phy && has_hs_phy; } - - const dwc2_ghwcfg2_t ghwcfg2 = {.value = dwc2->ghwcfg2}; - return ghwcfg2.hs_phy_type != GHWCFG2_HSPHY_NOT_SUPPORTED; } -/* dwc2 has several PHYs option - * - UTMI+ is internal highspeed PHY, clock can be 30 Mhz (8-bit) or 60 Mhz (16-bit) - * - ULPI is external highspeed PHY, clock is 60Mhz with only 8-bit interface - * - Dedicated FS PHY is internal with clock 48Mhz. - * - * In addition, UTMI+/ULPI can be shared to run at fullspeed mode with 48Mhz - * -*/ bool dwc2_core_init(uint8_t rhport, bool is_hs_phy, bool is_dma) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); diff --git a/src/portable/synopsys/dwc2/dwc2_common.h b/src/portable/synopsys/dwc2/dwc2_common.h index 6ee351ab5..1947173b2 100644 --- a/src/portable/synopsys/dwc2/dwc2_common.h +++ b/src/portable/synopsys/dwc2/dwc2_common.h @@ -84,6 +84,7 @@ TU_ATTR_ALWAYS_INLINE static inline dwc2_regs_t* DWC2_REG(uint8_t rhport) { return (dwc2_regs_t*)_dwc2_controller[rhport].reg_base; } +// check if highspeed phy should be used bool dwc2_core_is_highspeed_phy(dwc2_regs_t* dwc2, bool prefer_hs_phy); bool dwc2_core_init(uint8_t rhport, bool is_hs_phy, bool is_dma); void dwc2_core_handle_common_irq(uint8_t rhport, bool in_isr); diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index cc11c82d7..0fd60b35d 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -351,7 +351,7 @@ TU_ATTR_ALWAYS_INLINE static inline uint8_t cal_next_pid(uint8_t pid, uint8_t pa * TX periodic (PTX) * - At least largest-EPsize*MulCount/4 (MulCount up to 3 for high-bandwidth ISO/interrupt) */ -static void dfifo_host_init(uint8_t rhport, bool is_highspeed) { +static void dfifo_host_init(uint8_t rhport, bool is_hs_phy) { const dwc2_controller_t* dwc2_controller = &_dwc2_controller[rhport]; dwc2_regs_t* dwc2 = DWC2_REG(rhport); const dwc2_ghwcfg2_t ghwcfg2 = {.value = dwc2->ghwcfg2}; @@ -365,8 +365,8 @@ static void dfifo_host_init(uint8_t rhport, bool is_highspeed) { // fixed allocation for now, improve later: // - ptx_largest is limited to 256 for FS since most FS core only has 1024 bytes total - uint32_t nptx_largest = is_highspeed ? TUSB_EPSIZE_BULK_HS / 4 : TUSB_EPSIZE_BULK_FS / 4; - uint32_t ptx_largest = is_highspeed ? TUSB_EPSIZE_ISO_HS_MAX / 4 : 256 / 4; + uint32_t nptx_largest = is_hs_phy ? TUSB_EPSIZE_BULK_HS / 4 : TUSB_EPSIZE_BULK_FS / 4; + uint32_t ptx_largest = is_hs_phy ? TUSB_EPSIZE_ISO_HS_MAX / 4 : 256 / 4; uint16_t nptxfsiz = 2 * nptx_largest; uint16_t rxfsiz = 2 * (ptx_largest + 2) + ghwcfg2.num_host_ch; @@ -416,30 +416,25 @@ 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 + #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 + #endif + while ((dwc2->gintsts & GINTSTS_CMOD) != GINTSTS_CMODE_HOST) {} #ifdef TUP_USBIP_DWC2_STM32 dwc2_stm32_gccfg_cfg(dwc2, false, true); #endif - bool is_highspeed; - if (!TUH_OPT_HIGH_SPEED || rh_init->speed < TUSB_SPEED_HIGH) { - dwc2->hcfg |= HCFG_FSLS_ONLY; // disable high speed mode - is_highspeed = false; - } - #if TUH_OPT_HIGH_SPEED - else { - dwc2->hcfg &= ~HCFG_FSLS_ONLY; // work at max supported speed - is_highspeed = true; + if (is_hs_phy && (rh_init->speed == TUSB_SPEED_HIGH || rh_init->speed == TUSB_SPEED_AUTO)) { + dwc2->hcfg &= ~HCFG_FSLS_ONLY; // max speed + } else { + dwc2->hcfg |= HCFG_FSLS_ONLY; // disable high speed mode } - #endif // configure a fixed-allocated fifo scheme - dfifo_host_init(rhport, is_highspeed); + dfifo_host_init(rhport, is_hs_phy); dwc2->hprt = HPRT_W1_MASK; // clear all write-1-clear bits dwc2->hprt = HPRT_POWER; // turn on VBUS -- cgit v1.3.1 From bb8845c8e89002629d8eb4f8d72eaf370b97b004 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 27 Feb 2026 10:58:01 +0100 Subject: dcd/samx7x: synchronize DMA and cache options Signed-off-by: HiFiPhile --- src/common/tusb_mcu.h | 4 + src/portable/microchip/samx7x/common_usb_regs.h | 2108 ---------------------- src/portable/microchip/samx7x/dcd_samx7x.c | 58 +- src/portable/microchip/samx7x/samx7x_common.h | 2173 +++++++++++++++++++++++ src/tusb_option.h | 18 + 5 files changed, 2218 insertions(+), 2143 deletions(-) delete mode 100644 src/portable/microchip/samx7x/common_usb_regs.h create mode 100644 src/portable/microchip/samx7x/samx7x_common.h (limited to 'src/portable') diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index 5b9497b9a..32f7eb557 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -172,6 +172,10 @@ #define TUP_RHPORT_HIGHSPEED 1 #define TUD_ENDPOINT_ONE_DIRECTION_ONLY + // Enable dcache if DMA is enabled + #define CFG_TUD_MEM_DCACHE_ENABLE_DEFAULT CFG_TUD_SAMX7X_DMA_ENABLE + #define CFG_TUSB_MEM_DCACHE_LINE_SIZE_DEFAULT 32 + #elif TU_CHECK_MCU(OPT_MCU_PIC32MZ) #define TUP_DCD_ENDPOINT_MAX 8 #define TUD_ENDPOINT_ONE_DIRECTION_ONLY diff --git a/src/portable/microchip/samx7x/common_usb_regs.h b/src/portable/microchip/samx7x/common_usb_regs.h deleted file mode 100644 index db4a81e0e..000000000 --- a/src/portable/microchip/samx7x/common_usb_regs.h +++ /dev/null @@ -1,2108 +0,0 @@ - /* -* The MIT License (MIT) -* -* Copyright (c) 2019 Microchip Technology Inc. -* Copyright (c) 2018, hathach (tinyusb.org) -* Copyright (c) 2021, HiFiPhile -* -* 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 _COMMON_USB_REGS_H_ -#define _COMMON_USB_REGS_H_ - -#if CFG_TUSB_MCU == OPT_MCU_SAMX7X - -/* -------- DEVDMANXTDSC : (USBHS Offset: 0x00) (R/W 32) Device DMA Channel Next Descriptor Address Register -------- */ - -#define DEVDMANXTDSC_OFFSET (0x00) /**< (DEVDMANXTDSC) Device DMA Channel Next Descriptor Address Register Offset */ - -#define DEVDMANXTDSC_NXT_DSC_ADD_Pos 0 /**< (DEVDMANXTDSC) Next Descriptor Address Position */ -#define DEVDMANXTDSC_NXT_DSC_ADD (_U_(0xFFFFFFFF) << DEVDMANXTDSC_NXT_DSC_ADD_Pos) /**< (DEVDMANXTDSC) Next Descriptor Address Mask */ -#define DEVDMANXTDSC_Msk _U_(0xFFFFFFFF) /**< (DEVDMANXTDSC) Register Mask */ - - -/* -------- DEVDMAADDRESS : (USBHS Offset: 0x04) (R/W 32) Device DMA Channel Address Register -------- */ - -#define DEVDMAADDRESS_OFFSET (0x04) /**< (DEVDMAADDRESS) Device DMA Channel Address Register Offset */ - -#define DEVDMAADDRESS_BUFF_ADD_Pos 0 /**< (DEVDMAADDRESS) Buffer Address Position */ -#define DEVDMAADDRESS_BUFF_ADD (_U_(0xFFFFFFFF) << DEVDMAADDRESS_BUFF_ADD_Pos) /**< (DEVDMAADDRESS) Buffer Address Mask */ -#define DEVDMAADDRESS_Msk _U_(0xFFFFFFFF) /**< (DEVDMAADDRESS) Register Mask */ - - -/* -------- DEVDMACONTROL : (USBHS Offset: 0x08) (R/W 32) Device DMA Channel Control Register -------- */ - -#define DEVDMACONTROL_OFFSET (0x08) /**< (DEVDMACONTROL) Device DMA Channel Control Register Offset */ - -#define DEVDMACONTROL_CHANN_ENB_Pos 0 /**< (DEVDMACONTROL) Channel Enable Command Position */ -#define DEVDMACONTROL_CHANN_ENB (_U_(0x1) << DEVDMACONTROL_CHANN_ENB_Pos) /**< (DEVDMACONTROL) Channel Enable Command Mask */ -#define DEVDMACONTROL_LDNXT_DSC_Pos 1 /**< (DEVDMACONTROL) Load Next Channel Transfer Descriptor Enable Command Position */ -#define DEVDMACONTROL_LDNXT_DSC (_U_(0x1) << DEVDMACONTROL_LDNXT_DSC_Pos) /**< (DEVDMACONTROL) Load Next Channel Transfer Descriptor Enable Command Mask */ -#define DEVDMACONTROL_END_TR_EN_Pos 2 /**< (DEVDMACONTROL) End of Transfer Enable Control (OUT transfers only) Position */ -#define DEVDMACONTROL_END_TR_EN (_U_(0x1) << DEVDMACONTROL_END_TR_EN_Pos) /**< (DEVDMACONTROL) End of Transfer Enable Control (OUT transfers only) Mask */ -#define DEVDMACONTROL_END_B_EN_Pos 3 /**< (DEVDMACONTROL) End of Buffer Enable Control Position */ -#define DEVDMACONTROL_END_B_EN (_U_(0x1) << DEVDMACONTROL_END_B_EN_Pos) /**< (DEVDMACONTROL) End of Buffer Enable Control Mask */ -#define DEVDMACONTROL_END_TR_IT_Pos 4 /**< (DEVDMACONTROL) End of Transfer Interrupt Enable Position */ -#define DEVDMACONTROL_END_TR_IT (_U_(0x1) << DEVDMACONTROL_END_TR_IT_Pos) /**< (DEVDMACONTROL) End of Transfer Interrupt Enable Mask */ -#define DEVDMACONTROL_END_BUFFIT_Pos 5 /**< (DEVDMACONTROL) End of Buffer Interrupt Enable Position */ -#define DEVDMACONTROL_END_BUFFIT (_U_(0x1) << DEVDMACONTROL_END_BUFFIT_Pos) /**< (DEVDMACONTROL) End of Buffer Interrupt Enable Mask */ -#define DEVDMACONTROL_DESC_LD_IT_Pos 6 /**< (DEVDMACONTROL) Descriptor Loaded Interrupt Enable Position */ -#define DEVDMACONTROL_DESC_LD_IT (_U_(0x1) << DEVDMACONTROL_DESC_LD_IT_Pos) /**< (DEVDMACONTROL) Descriptor Loaded Interrupt Enable Mask */ -#define DEVDMACONTROL_BURST_LCK_Pos 7 /**< (DEVDMACONTROL) Burst Lock Enable Position */ -#define DEVDMACONTROL_BURST_LCK (_U_(0x1) << DEVDMACONTROL_BURST_LCK_Pos) /**< (DEVDMACONTROL) Burst Lock Enable Mask */ -#define DEVDMACONTROL_BUFF_LENGTH_Pos 16 /**< (DEVDMACONTROL) Buffer Byte Length (Write-only) Position */ -#define DEVDMACONTROL_BUFF_LENGTH (_U_(0xFFFF) << DEVDMACONTROL_BUFF_LENGTH_Pos) /**< (DEVDMACONTROL) Buffer Byte Length (Write-only) Mask */ -#define DEVDMACONTROL_Msk _U_(0xFFFF00FF) /**< (DEVDMACONTROL) Register Mask */ - - -/* -------- DEVDMASTATUS : (USBHS Offset: 0x0c) (R/W 32) Device DMA Channel Status Register -------- */ - -#define DEVDMASTATUS_OFFSET (0x0C) /**< (DEVDMASTATUS) Device DMA Channel Status Register Offset */ - -#define DEVDMASTATUS_CHANN_ENB_Pos 0 /**< (DEVDMASTATUS) Channel Enable Status Position */ -#define DEVDMASTATUS_CHANN_ENB (_U_(0x1) << DEVDMASTATUS_CHANN_ENB_Pos) /**< (DEVDMASTATUS) Channel Enable Status Mask */ -#define DEVDMASTATUS_CHANN_ACT_Pos 1 /**< (DEVDMASTATUS) Channel Active Status Position */ -#define DEVDMASTATUS_CHANN_ACT (_U_(0x1) << DEVDMASTATUS_CHANN_ACT_Pos) /**< (DEVDMASTATUS) Channel Active Status Mask */ -#define DEVDMASTATUS_END_TR_ST_Pos 4 /**< (DEVDMASTATUS) End of Channel Transfer Status Position */ -#define DEVDMASTATUS_END_TR_ST (_U_(0x1) << DEVDMASTATUS_END_TR_ST_Pos) /**< (DEVDMASTATUS) End of Channel Transfer Status Mask */ -#define DEVDMASTATUS_END_BF_ST_Pos 5 /**< (DEVDMASTATUS) End of Channel Buffer Status Position */ -#define DEVDMASTATUS_END_BF_ST (_U_(0x1) << DEVDMASTATUS_END_BF_ST_Pos) /**< (DEVDMASTATUS) End of Channel Buffer Status Mask */ -#define DEVDMASTATUS_DESC_LDST_Pos 6 /**< (DEVDMASTATUS) Descriptor Loaded Status Position */ -#define DEVDMASTATUS_DESC_LDST (_U_(0x1) << DEVDMASTATUS_DESC_LDST_Pos) /**< (DEVDMASTATUS) Descriptor Loaded Status Mask */ -#define DEVDMASTATUS_BUFF_COUNT_Pos 16 /**< (DEVDMASTATUS) Buffer Byte Count Position */ -#define DEVDMASTATUS_BUFF_COUNT (_U_(0xFFFF) << DEVDMASTATUS_BUFF_COUNT_Pos) /**< (DEVDMASTATUS) Buffer Byte Count Mask */ -#define DEVDMASTATUS_Msk _U_(0xFFFF0073) /**< (DEVDMASTATUS) Register Mask */ - - -/* -------- HSTDMANXTDSC : (USBHS Offset: 0x00) (R/W 32) Host DMA Channel Next Descriptor Address Register -------- */ - -#define HSTDMANXTDSC_OFFSET (0x00) /**< (HSTDMANXTDSC) Host DMA Channel Next Descriptor Address Register Offset */ - -#define HSTDMANXTDSC_NXT_DSC_ADD_Pos 0 /**< (HSTDMANXTDSC) Next Descriptor Address Position */ -#define HSTDMANXTDSC_NXT_DSC_ADD (_U_(0xFFFFFFFF) << HSTDMANXTDSC_NXT_DSC_ADD_Pos) /**< (HSTDMANXTDSC) Next Descriptor Address Mask */ -#define HSTDMANXTDSC_Msk _U_(0xFFFFFFFF) /**< (HSTDMANXTDSC) Register Mask */ - - -/* -------- HSTDMAADDRESS : (USBHS Offset: 0x04) (R/W 32) Host DMA Channel Address Register -------- */ - -#define HSTDMAADDRESS_OFFSET (0x04) /**< (HSTDMAADDRESS) Host DMA Channel Address Register Offset */ - -#define HSTDMAADDRESS_BUFF_ADD_Pos 0 /**< (HSTDMAADDRESS) Buffer Address Position */ -#define HSTDMAADDRESS_BUFF_ADD (_U_(0xFFFFFFFF) << HSTDMAADDRESS_BUFF_ADD_Pos) /**< (HSTDMAADDRESS) Buffer Address Mask */ -#define HSTDMAADDRESS_Msk _U_(0xFFFFFFFF) /**< (HSTDMAADDRESS) Register Mask */ - - -/* -------- HSTDMACONTROL : (USBHS Offset: 0x08) (R/W 32) Host DMA Channel Control Register -------- */ - -#define HSTDMACONTROL_OFFSET (0x08) /**< (HSTDMACONTROL) Host DMA Channel Control Register Offset */ - -#define HSTDMACONTROL_CHANN_ENB_Pos 0 /**< (HSTDMACONTROL) Channel Enable Command Position */ -#define HSTDMACONTROL_CHANN_ENB (_U_(0x1) << HSTDMACONTROL_CHANN_ENB_Pos) /**< (HSTDMACONTROL) Channel Enable Command Mask */ -#define HSTDMACONTROL_LDNXT_DSC_Pos 1 /**< (HSTDMACONTROL) Load Next Channel Transfer Descriptor Enable Command Position */ -#define HSTDMACONTROL_LDNXT_DSC (_U_(0x1) << HSTDMACONTROL_LDNXT_DSC_Pos) /**< (HSTDMACONTROL) Load Next Channel Transfer Descriptor Enable Command Mask */ -#define HSTDMACONTROL_END_TR_EN_Pos 2 /**< (HSTDMACONTROL) End of Transfer Enable Control (OUT transfers only) Position */ -#define HSTDMACONTROL_END_TR_EN (_U_(0x1) << HSTDMACONTROL_END_TR_EN_Pos) /**< (HSTDMACONTROL) End of Transfer Enable Control (OUT transfers only) Mask */ -#define HSTDMACONTROL_END_B_EN_Pos 3 /**< (HSTDMACONTROL) End of Buffer Enable Control Position */ -#define HSTDMACONTROL_END_B_EN (_U_(0x1) << HSTDMACONTROL_END_B_EN_Pos) /**< (HSTDMACONTROL) End of Buffer Enable Control Mask */ -#define HSTDMACONTROL_END_TR_IT_Pos 4 /**< (HSTDMACONTROL) End of Transfer Interrupt Enable Position */ -#define HSTDMACONTROL_END_TR_IT (_U_(0x1) << HSTDMACONTROL_END_TR_IT_Pos) /**< (HSTDMACONTROL) End of Transfer Interrupt Enable Mask */ -#define HSTDMACONTROL_END_BUFFIT_Pos 5 /**< (HSTDMACONTROL) End of Buffer Interrupt Enable Position */ -#define HSTDMACONTROL_END_BUFFIT (_U_(0x1) << HSTDMACONTROL_END_BUFFIT_Pos) /**< (HSTDMACONTROL) End of Buffer Interrupt Enable Mask */ -#define HSTDMACONTROL_DESC_LD_IT_Pos 6 /**< (HSTDMACONTROL) Descriptor Loaded Interrupt Enable Position */ -#define HSTDMACONTROL_DESC_LD_IT (_U_(0x1) << HSTDMACONTROL_DESC_LD_IT_Pos) /**< (HSTDMACONTROL) Descriptor Loaded Interrupt Enable Mask */ -#define HSTDMACONTROL_BURST_LCK_Pos 7 /**< (HSTDMACONTROL) Burst Lock Enable Position */ -#define HSTDMACONTROL_BURST_LCK (_U_(0x1) << HSTDMACONTROL_BURST_LCK_Pos) /**< (HSTDMACONTROL) Burst Lock Enable Mask */ -#define HSTDMACONTROL_BUFF_LENGTH_Pos 16 /**< (HSTDMACONTROL) Buffer Byte Length (Write-only) Position */ -#define HSTDMACONTROL_BUFF_LENGTH (_U_(0xFFFF) << HSTDMACONTROL_BUFF_LENGTH_Pos) /**< (HSTDMACONTROL) Buffer Byte Length (Write-only) Mask */ -#define HSTDMACONTROL_Msk _U_(0xFFFF00FF) /**< (HSTDMACONTROL) Register Mask */ - - -/* -------- HSTDMASTATUS : (USBHS Offset: 0x0c) (R/W 32) Host DMA Channel Status Register -------- */ - -#define HSTDMASTATUS_OFFSET (0x0C) /**< (HSTDMASTATUS) Host DMA Channel Status Register Offset */ - -#define HSTDMASTATUS_CHANN_ENB_Pos 0 /**< (HSTDMASTATUS) Channel Enable Status Position */ -#define HSTDMASTATUS_CHANN_ENB (_U_(0x1) << HSTDMASTATUS_CHANN_ENB_Pos) /**< (HSTDMASTATUS) Channel Enable Status Mask */ -#define HSTDMASTATUS_CHANN_ACT_Pos 1 /**< (HSTDMASTATUS) Channel Active Status Position */ -#define HSTDMASTATUS_CHANN_ACT (_U_(0x1) << HSTDMASTATUS_CHANN_ACT_Pos) /**< (HSTDMASTATUS) Channel Active Status Mask */ -#define HSTDMASTATUS_END_TR_ST_Pos 4 /**< (HSTDMASTATUS) End of Channel Transfer Status Position */ -#define HSTDMASTATUS_END_TR_ST (_U_(0x1) << HSTDMASTATUS_END_TR_ST_Pos) /**< (HSTDMASTATUS) End of Channel Transfer Status Mask */ -#define HSTDMASTATUS_END_BF_ST_Pos 5 /**< (HSTDMASTATUS) End of Channel Buffer Status Position */ -#define HSTDMASTATUS_END_BF_ST (_U_(0x1) << HSTDMASTATUS_END_BF_ST_Pos) /**< (HSTDMASTATUS) End of Channel Buffer Status Mask */ -#define HSTDMASTATUS_DESC_LDST_Pos 6 /**< (HSTDMASTATUS) Descriptor Loaded Status Position */ -#define HSTDMASTATUS_DESC_LDST (_U_(0x1) << HSTDMASTATUS_DESC_LDST_Pos) /**< (HSTDMASTATUS) Descriptor Loaded Status Mask */ -#define HSTDMASTATUS_BUFF_COUNT_Pos 16 /**< (HSTDMASTATUS) Buffer Byte Count Position */ -#define HSTDMASTATUS_BUFF_COUNT (_U_(0xFFFF) << HSTDMASTATUS_BUFF_COUNT_Pos) /**< (HSTDMASTATUS) Buffer Byte Count Mask */ -#define HSTDMASTATUS_Msk _U_(0xFFFF0073) /**< (HSTDMASTATUS) Register Mask */ - - -/* -------- DEVCTRL : (USBHS Offset: 0x00) (R/W 32) Device General Control Register -------- */ - -#define DEVCTRL_OFFSET (0x00) /**< (DEVCTRL) Device General Control Register Offset */ - -#define DEVCTRL_UADD_Pos 0 /**< (DEVCTRL) USB Address Position */ -#define DEVCTRL_UADD (_U_(0x7F) << DEVCTRL_UADD_Pos) /**< (DEVCTRL) USB Address Mask */ -#define DEVCTRL_ADDEN_Pos 7 /**< (DEVCTRL) Address Enable Position */ -#define DEVCTRL_ADDEN (_U_(0x1) << DEVCTRL_ADDEN_Pos) /**< (DEVCTRL) Address Enable Mask */ -#define DEVCTRL_DETACH_Pos 8 /**< (DEVCTRL) Detach Position */ -#define DEVCTRL_DETACH (_U_(0x1) << DEVCTRL_DETACH_Pos) /**< (DEVCTRL) Detach Mask */ -#define DEVCTRL_RMWKUP_Pos 9 /**< (DEVCTRL) Remote Wake-Up Position */ -#define DEVCTRL_RMWKUP (_U_(0x1) << DEVCTRL_RMWKUP_Pos) /**< (DEVCTRL) Remote Wake-Up Mask */ -#define DEVCTRL_SPDCONF_Pos 10 /**< (DEVCTRL) Mode Configuration Position */ -#define DEVCTRL_SPDCONF (_U_(0x3) << DEVCTRL_SPDCONF_Pos) /**< (DEVCTRL) Mode Configuration Mask */ -#define DEVCTRL_SPDCONF_NORMAL_Val _U_(0x0) /**< (DEVCTRL) The peripheral starts in Full-speed mode and performs a high-speed reset to switch to High-speed mode if the host is high-speed-capable. */ -#define DEVCTRL_SPDCONF_LOW_POWER_Val _U_(0x1) /**< (DEVCTRL) For a better consumption, if high speed is not needed. */ -#define DEVCTRL_SPDCONF_HIGH_SPEED_Val _U_(0x2) /**< (DEVCTRL) Forced high speed. */ -#define DEVCTRL_SPDCONF_FORCED_FS_Val _U_(0x3) /**< (DEVCTRL) The peripheral remains in Full-speed mode whatever the host speed capability. */ -#define DEVCTRL_SPDCONF_NORMAL (DEVCTRL_SPDCONF_NORMAL_Val << DEVCTRL_SPDCONF_Pos) /**< (DEVCTRL) The peripheral starts in Full-speed mode and performs a high-speed reset to switch to High-speed mode if the host is high-speed-capable. Position */ -#define DEVCTRL_SPDCONF_LOW_POWER (DEVCTRL_SPDCONF_LOW_POWER_Val << DEVCTRL_SPDCONF_Pos) /**< (DEVCTRL) For a better consumption, if high speed is not needed. Position */ -#define DEVCTRL_SPDCONF_HIGH_SPEED (DEVCTRL_SPDCONF_HIGH_SPEED_Val << DEVCTRL_SPDCONF_Pos) /**< (DEVCTRL) Forced high speed. Position */ -#define DEVCTRL_SPDCONF_FORCED_FS (DEVCTRL_SPDCONF_FORCED_FS_Val << DEVCTRL_SPDCONF_Pos) /**< (DEVCTRL) The peripheral remains in Full-speed mode whatever the host speed capability. Position */ -#define DEVCTRL_LS_Pos 12 /**< (DEVCTRL) Low-Speed Mode Force Position */ -#define DEVCTRL_LS (_U_(0x1) << DEVCTRL_LS_Pos) /**< (DEVCTRL) Low-Speed Mode Force Mask */ -#define DEVCTRL_TSTJ_Pos 13 /**< (DEVCTRL) Test mode J Position */ -#define DEVCTRL_TSTJ (_U_(0x1) << DEVCTRL_TSTJ_Pos) /**< (DEVCTRL) Test mode J Mask */ -#define DEVCTRL_TSTK_Pos 14 /**< (DEVCTRL) Test mode K Position */ -#define DEVCTRL_TSTK (_U_(0x1) << DEVCTRL_TSTK_Pos) /**< (DEVCTRL) Test mode K Mask */ -#define DEVCTRL_TSTPCKT_Pos 15 /**< (DEVCTRL) Test packet mode Position */ -#define DEVCTRL_TSTPCKT (_U_(0x1) << DEVCTRL_TSTPCKT_Pos) /**< (DEVCTRL) Test packet mode Mask */ -#define DEVCTRL_OPMODE2_Pos 16 /**< (DEVCTRL) Specific Operational mode Position */ -#define DEVCTRL_OPMODE2 (_U_(0x1) << DEVCTRL_OPMODE2_Pos) /**< (DEVCTRL) Specific Operational mode Mask */ -#define DEVCTRL_Msk _U_(0x1FFFF) /**< (DEVCTRL) Register Mask */ - -#define DEVCTRL_OPMODE_Pos 16 /**< (DEVCTRL Position) Specific Operational mode */ -#define DEVCTRL_OPMODE (_U_(0x1) << DEVCTRL_OPMODE_Pos) /**< (DEVCTRL Mask) OPMODE */ - -/* -------- DEVISR : (USBHS Offset: 0x04) (R/ 32) Device Global Interrupt Status Register -------- */ - -#define DEVISR_OFFSET (0x04) /**< (DEVISR) Device Global Interrupt Status Register Offset */ - -#define DEVISR_SUSP_Pos 0 /**< (DEVISR) Suspend Interrupt Position */ -#define DEVISR_SUSP (_U_(0x1) << DEVISR_SUSP_Pos) /**< (DEVISR) Suspend Interrupt Mask */ -#define DEVISR_MSOF_Pos 1 /**< (DEVISR) Micro Start of Frame Interrupt Position */ -#define DEVISR_MSOF (_U_(0x1) << DEVISR_MSOF_Pos) /**< (DEVISR) Micro Start of Frame Interrupt Mask */ -#define DEVISR_SOF_Pos 2 /**< (DEVISR) Start of Frame Interrupt Position */ -#define DEVISR_SOF (_U_(0x1) << DEVISR_SOF_Pos) /**< (DEVISR) Start of Frame Interrupt Mask */ -#define DEVISR_EORST_Pos 3 /**< (DEVISR) End of Reset Interrupt Position */ -#define DEVISR_EORST (_U_(0x1) << DEVISR_EORST_Pos) /**< (DEVISR) End of Reset Interrupt Mask */ -#define DEVISR_WAKEUP_Pos 4 /**< (DEVISR) Wake-Up Interrupt Position */ -#define DEVISR_WAKEUP (_U_(0x1) << DEVISR_WAKEUP_Pos) /**< (DEVISR) Wake-Up Interrupt Mask */ -#define DEVISR_EORSM_Pos 5 /**< (DEVISR) End of Resume Interrupt Position */ -#define DEVISR_EORSM (_U_(0x1) << DEVISR_EORSM_Pos) /**< (DEVISR) End of Resume Interrupt Mask */ -#define DEVISR_UPRSM_Pos 6 /**< (DEVISR) Upstream Resume Interrupt Position */ -#define DEVISR_UPRSM (_U_(0x1) << DEVISR_UPRSM_Pos) /**< (DEVISR) Upstream Resume Interrupt Mask */ -#define DEVISR_PEP_0_Pos 12 /**< (DEVISR) Endpoint 0 Interrupt Position */ -#define DEVISR_PEP_0 (_U_(0x1) << DEVISR_PEP_0_Pos) /**< (DEVISR) Endpoint 0 Interrupt Mask */ -#define DEVISR_PEP_1_Pos 13 /**< (DEVISR) Endpoint 1 Interrupt Position */ -#define DEVISR_PEP_1 (_U_(0x1) << DEVISR_PEP_1_Pos) /**< (DEVISR) Endpoint 1 Interrupt Mask */ -#define DEVISR_PEP_2_Pos 14 /**< (DEVISR) Endpoint 2 Interrupt Position */ -#define DEVISR_PEP_2 (_U_(0x1) << DEVISR_PEP_2_Pos) /**< (DEVISR) Endpoint 2 Interrupt Mask */ -#define DEVISR_PEP_3_Pos 15 /**< (DEVISR) Endpoint 3 Interrupt Position */ -#define DEVISR_PEP_3 (_U_(0x1) << DEVISR_PEP_3_Pos) /**< (DEVISR) Endpoint 3 Interrupt Mask */ -#define DEVISR_PEP_4_Pos 16 /**< (DEVISR) Endpoint 4 Interrupt Position */ -#define DEVISR_PEP_4 (_U_(0x1) << DEVISR_PEP_4_Pos) /**< (DEVISR) Endpoint 4 Interrupt Mask */ -#define DEVISR_PEP_5_Pos 17 /**< (DEVISR) Endpoint 5 Interrupt Position */ -#define DEVISR_PEP_5 (_U_(0x1) << DEVISR_PEP_5_Pos) /**< (DEVISR) Endpoint 5 Interrupt Mask */ -#define DEVISR_PEP_6_Pos 18 /**< (DEVISR) Endpoint 6 Interrupt Position */ -#define DEVISR_PEP_6 (_U_(0x1) << DEVISR_PEP_6_Pos) /**< (DEVISR) Endpoint 6 Interrupt Mask */ -#define DEVISR_PEP_7_Pos 19 /**< (DEVISR) Endpoint 7 Interrupt Position */ -#define DEVISR_PEP_7 (_U_(0x1) << DEVISR_PEP_7_Pos) /**< (DEVISR) Endpoint 7 Interrupt Mask */ -#define DEVISR_PEP_8_Pos 20 /**< (DEVISR) Endpoint 8 Interrupt Position */ -#define DEVISR_PEP_8 (_U_(0x1) << DEVISR_PEP_8_Pos) /**< (DEVISR) Endpoint 8 Interrupt Mask */ -#define DEVISR_PEP_9_Pos 21 /**< (DEVISR) Endpoint 9 Interrupt Position */ -#define DEVISR_PEP_9 (_U_(0x1) << DEVISR_PEP_9_Pos) /**< (DEVISR) Endpoint 9 Interrupt Mask */ -#define DEVISR_DMA_1_Pos 25 /**< (DEVISR) DMA Channel 1 Interrupt Position */ -#define DEVISR_DMA_1 (_U_(0x1) << DEVISR_DMA_1_Pos) /**< (DEVISR) DMA Channel 1 Interrupt Mask */ -#define DEVISR_DMA_2_Pos 26 /**< (DEVISR) DMA Channel 2 Interrupt Position */ -#define DEVISR_DMA_2 (_U_(0x1) << DEVISR_DMA_2_Pos) /**< (DEVISR) DMA Channel 2 Interrupt Mask */ -#define DEVISR_DMA_3_Pos 27 /**< (DEVISR) DMA Channel 3 Interrupt Position */ -#define DEVISR_DMA_3 (_U_(0x1) << DEVISR_DMA_3_Pos) /**< (DEVISR) DMA Channel 3 Interrupt Mask */ -#define DEVISR_DMA_4_Pos 28 /**< (DEVISR) DMA Channel 4 Interrupt Position */ -#define DEVISR_DMA_4 (_U_(0x1) << DEVISR_DMA_4_Pos) /**< (DEVISR) DMA Channel 4 Interrupt Mask */ -#define DEVISR_DMA_5_Pos 29 /**< (DEVISR) DMA Channel 5 Interrupt Position */ -#define DEVISR_DMA_5 (_U_(0x1) << DEVISR_DMA_5_Pos) /**< (DEVISR) DMA Channel 5 Interrupt Mask */ -#define DEVISR_DMA_6_Pos 30 /**< (DEVISR) DMA Channel 6 Interrupt Position */ -#define DEVISR_DMA_6 (_U_(0x1) << DEVISR_DMA_6_Pos) /**< (DEVISR) DMA Channel 6 Interrupt Mask */ -#define DEVISR_DMA_7_Pos 31 /**< (DEVISR) DMA Channel 7 Interrupt Position */ -#define DEVISR_DMA_7 (_U_(0x1) << DEVISR_DMA_7_Pos) /**< (DEVISR) DMA Channel 7 Interrupt Mask */ -#define DEVISR_Msk _U_(0xFE3FF07F) /**< (DEVISR) Register Mask */ - -#define DEVISR_PEP__Pos 12 /**< (DEVISR Position) Endpoint x Interrupt */ -#define DEVISR_PEP_ (_U_(0x3FF) << DEVISR_PEP__Pos) /**< (DEVISR Mask) PEP_ */ -#define DEVISR_DMA__Pos 25 /**< (DEVISR Position) DMA Channel 7 Interrupt */ -#define DEVISR_DMA_ (_U_(0x7F) << DEVISR_DMA__Pos) /**< (DEVISR Mask) DMA_ */ - -/* -------- DEVICR : (USBHS Offset: 0x08) (/W 32) Device Global Interrupt Clear Register -------- */ - -#define DEVICR_OFFSET (0x08) /**< (DEVICR) Device Global Interrupt Clear Register Offset */ - -#define DEVICR_SUSPC_Pos 0 /**< (DEVICR) Suspend Interrupt Clear Position */ -#define DEVICR_SUSPC (_U_(0x1) << DEVICR_SUSPC_Pos) /**< (DEVICR) Suspend Interrupt Clear Mask */ -#define DEVICR_MSOFC_Pos 1 /**< (DEVICR) Micro Start of Frame Interrupt Clear Position */ -#define DEVICR_MSOFC (_U_(0x1) << DEVICR_MSOFC_Pos) /**< (DEVICR) Micro Start of Frame Interrupt Clear Mask */ -#define DEVICR_SOFC_Pos 2 /**< (DEVICR) Start of Frame Interrupt Clear Position */ -#define DEVICR_SOFC (_U_(0x1) << DEVICR_SOFC_Pos) /**< (DEVICR) Start of Frame Interrupt Clear Mask */ -#define DEVICR_EORSTC_Pos 3 /**< (DEVICR) End of Reset Interrupt Clear Position */ -#define DEVICR_EORSTC (_U_(0x1) << DEVICR_EORSTC_Pos) /**< (DEVICR) End of Reset Interrupt Clear Mask */ -#define DEVICR_WAKEUPC_Pos 4 /**< (DEVICR) Wake-Up Interrupt Clear Position */ -#define DEVICR_WAKEUPC (_U_(0x1) << DEVICR_WAKEUPC_Pos) /**< (DEVICR) Wake-Up Interrupt Clear Mask */ -#define DEVICR_EORSMC_Pos 5 /**< (DEVICR) End of Resume Interrupt Clear Position */ -#define DEVICR_EORSMC (_U_(0x1) << DEVICR_EORSMC_Pos) /**< (DEVICR) End of Resume Interrupt Clear Mask */ -#define DEVICR_UPRSMC_Pos 6 /**< (DEVICR) Upstream Resume Interrupt Clear Position */ -#define DEVICR_UPRSMC (_U_(0x1) << DEVICR_UPRSMC_Pos) /**< (DEVICR) Upstream Resume Interrupt Clear Mask */ -#define DEVICR_Msk _U_(0x7F) /**< (DEVICR) Register Mask */ - - -/* -------- DEVIFR : (USBHS Offset: 0x0c) (/W 32) Device Global Interrupt Set Register -------- */ - -#define DEVIFR_OFFSET (0x0C) /**< (DEVIFR) Device Global Interrupt Set Register Offset */ - -#define DEVIFR_SUSPS_Pos 0 /**< (DEVIFR) Suspend Interrupt Set Position */ -#define DEVIFR_SUSPS (_U_(0x1) << DEVIFR_SUSPS_Pos) /**< (DEVIFR) Suspend Interrupt Set Mask */ -#define DEVIFR_MSOFS_Pos 1 /**< (DEVIFR) Micro Start of Frame Interrupt Set Position */ -#define DEVIFR_MSOFS (_U_(0x1) << DEVIFR_MSOFS_Pos) /**< (DEVIFR) Micro Start of Frame Interrupt Set Mask */ -#define DEVIFR_SOFS_Pos 2 /**< (DEVIFR) Start of Frame Interrupt Set Position */ -#define DEVIFR_SOFS (_U_(0x1) << DEVIFR_SOFS_Pos) /**< (DEVIFR) Start of Frame Interrupt Set Mask */ -#define DEVIFR_EORSTS_Pos 3 /**< (DEVIFR) End of Reset Interrupt Set Position */ -#define DEVIFR_EORSTS (_U_(0x1) << DEVIFR_EORSTS_Pos) /**< (DEVIFR) End of Reset Interrupt Set Mask */ -#define DEVIFR_WAKEUPS_Pos 4 /**< (DEVIFR) Wake-Up Interrupt Set Position */ -#define DEVIFR_WAKEUPS (_U_(0x1) << DEVIFR_WAKEUPS_Pos) /**< (DEVIFR) Wake-Up Interrupt Set Mask */ -#define DEVIFR_EORSMS_Pos 5 /**< (DEVIFR) End of Resume Interrupt Set Position */ -#define DEVIFR_EORSMS (_U_(0x1) << DEVIFR_EORSMS_Pos) /**< (DEVIFR) End of Resume Interrupt Set Mask */ -#define DEVIFR_UPRSMS_Pos 6 /**< (DEVIFR) Upstream Resume Interrupt Set Position */ -#define DEVIFR_UPRSMS (_U_(0x1) << DEVIFR_UPRSMS_Pos) /**< (DEVIFR) Upstream Resume Interrupt Set Mask */ -#define DEVIFR_DMA_1_Pos 25 /**< (DEVIFR) DMA Channel 1 Interrupt Set Position */ -#define DEVIFR_DMA_1 (_U_(0x1) << DEVIFR_DMA_1_Pos) /**< (DEVIFR) DMA Channel 1 Interrupt Set Mask */ -#define DEVIFR_DMA_2_Pos 26 /**< (DEVIFR) DMA Channel 2 Interrupt Set Position */ -#define DEVIFR_DMA_2 (_U_(0x1) << DEVIFR_DMA_2_Pos) /**< (DEVIFR) DMA Channel 2 Interrupt Set Mask */ -#define DEVIFR_DMA_3_Pos 27 /**< (DEVIFR) DMA Channel 3 Interrupt Set Position */ -#define DEVIFR_DMA_3 (_U_(0x1) << DEVIFR_DMA_3_Pos) /**< (DEVIFR) DMA Channel 3 Interrupt Set Mask */ -#define DEVIFR_DMA_4_Pos 28 /**< (DEVIFR) DMA Channel 4 Interrupt Set Position */ -#define DEVIFR_DMA_4 (_U_(0x1) << DEVIFR_DMA_4_Pos) /**< (DEVIFR) DMA Channel 4 Interrupt Set Mask */ -#define DEVIFR_DMA_5_Pos 29 /**< (DEVIFR) DMA Channel 5 Interrupt Set Position */ -#define DEVIFR_DMA_5 (_U_(0x1) << DEVIFR_DMA_5_Pos) /**< (DEVIFR) DMA Channel 5 Interrupt Set Mask */ -#define DEVIFR_DMA_6_Pos 30 /**< (DEVIFR) DMA Channel 6 Interrupt Set Position */ -#define DEVIFR_DMA_6 (_U_(0x1) << DEVIFR_DMA_6_Pos) /**< (DEVIFR) DMA Channel 6 Interrupt Set Mask */ -#define DEVIFR_DMA_7_Pos 31 /**< (DEVIFR) DMA Channel 7 Interrupt Set Position */ -#define DEVIFR_DMA_7 (_U_(0x1) << DEVIFR_DMA_7_Pos) /**< (DEVIFR) DMA Channel 7 Interrupt Set Mask */ -#define DEVIFR_Msk _U_(0xFE00007F) /**< (DEVIFR) Register Mask */ - -#define DEVIFR_DMA__Pos 25 /**< (DEVIFR Position) DMA Channel 7 Interrupt Set */ -#define DEVIFR_DMA_ (_U_(0x7F) << DEVIFR_DMA__Pos) /**< (DEVIFR Mask) DMA_ */ - -/* -------- DEVIMR : (USBHS Offset: 0x10) (R/ 32) Device Global Interrupt Mask Register -------- */ - -#define DEVIMR_OFFSET (0x10) /**< (DEVIMR) Device Global Interrupt Mask Register Offset */ - -#define DEVIMR_SUSPE_Pos 0 /**< (DEVIMR) Suspend Interrupt Mask Position */ -#define DEVIMR_SUSPE (_U_(0x1) << DEVIMR_SUSPE_Pos) /**< (DEVIMR) Suspend Interrupt Mask Mask */ -#define DEVIMR_MSOFE_Pos 1 /**< (DEVIMR) Micro Start of Frame Interrupt Mask Position */ -#define DEVIMR_MSOFE (_U_(0x1) << DEVIMR_MSOFE_Pos) /**< (DEVIMR) Micro Start of Frame Interrupt Mask Mask */ -#define DEVIMR_SOFE_Pos 2 /**< (DEVIMR) Start of Frame Interrupt Mask Position */ -#define DEVIMR_SOFE (_U_(0x1) << DEVIMR_SOFE_Pos) /**< (DEVIMR) Start of Frame Interrupt Mask Mask */ -#define DEVIMR_EORSTE_Pos 3 /**< (DEVIMR) End of Reset Interrupt Mask Position */ -#define DEVIMR_EORSTE (_U_(0x1) << DEVIMR_EORSTE_Pos) /**< (DEVIMR) End of Reset Interrupt Mask Mask */ -#define DEVIMR_WAKEUPE_Pos 4 /**< (DEVIMR) Wake-Up Interrupt Mask Position */ -#define DEVIMR_WAKEUPE (_U_(0x1) << DEVIMR_WAKEUPE_Pos) /**< (DEVIMR) Wake-Up Interrupt Mask Mask */ -#define DEVIMR_EORSME_Pos 5 /**< (DEVIMR) End of Resume Interrupt Mask Position */ -#define DEVIMR_EORSME (_U_(0x1) << DEVIMR_EORSME_Pos) /**< (DEVIMR) End of Resume Interrupt Mask Mask */ -#define DEVIMR_UPRSME_Pos 6 /**< (DEVIMR) Upstream Resume Interrupt Mask Position */ -#define DEVIMR_UPRSME (_U_(0x1) << DEVIMR_UPRSME_Pos) /**< (DEVIMR) Upstream Resume Interrupt Mask Mask */ -#define DEVIMR_PEP_0_Pos 12 /**< (DEVIMR) Endpoint 0 Interrupt Mask Position */ -#define DEVIMR_PEP_0 (_U_(0x1) << DEVIMR_PEP_0_Pos) /**< (DEVIMR) Endpoint 0 Interrupt Mask Mask */ -#define DEVIMR_PEP_1_Pos 13 /**< (DEVIMR) Endpoint 1 Interrupt Mask Position */ -#define DEVIMR_PEP_1 (_U_(0x1) << DEVIMR_PEP_1_Pos) /**< (DEVIMR) Endpoint 1 Interrupt Mask Mask */ -#define DEVIMR_PEP_2_Pos 14 /**< (DEVIMR) Endpoint 2 Interrupt Mask Position */ -#define DEVIMR_PEP_2 (_U_(0x1) << DEVIMR_PEP_2_Pos) /**< (DEVIMR) Endpoint 2 Interrupt Mask Mask */ -#define DEVIMR_PEP_3_Pos 15 /**< (DEVIMR) Endpoint 3 Interrupt Mask Position */ -#define DEVIMR_PEP_3 (_U_(0x1) << DEVIMR_PEP_3_Pos) /**< (DEVIMR) Endpoint 3 Interrupt Mask Mask */ -#define DEVIMR_PEP_4_Pos 16 /**< (DEVIMR) Endpoint 4 Interrupt Mask Position */ -#define DEVIMR_PEP_4 (_U_(0x1) << DEVIMR_PEP_4_Pos) /**< (DEVIMR) Endpoint 4 Interrupt Mask Mask */ -#define DEVIMR_PEP_5_Pos 17 /**< (DEVIMR) Endpoint 5 Interrupt Mask Position */ -#define DEVIMR_PEP_5 (_U_(0x1) << DEVIMR_PEP_5_Pos) /**< (DEVIMR) Endpoint 5 Interrupt Mask Mask */ -#define DEVIMR_PEP_6_Pos 18 /**< (DEVIMR) Endpoint 6 Interrupt Mask Position */ -#define DEVIMR_PEP_6 (_U_(0x1) << DEVIMR_PEP_6_Pos) /**< (DEVIMR) Endpoint 6 Interrupt Mask Mask */ -#define DEVIMR_PEP_7_Pos 19 /**< (DEVIMR) Endpoint 7 Interrupt Mask Position */ -#define DEVIMR_PEP_7 (_U_(0x1) << DEVIMR_PEP_7_Pos) /**< (DEVIMR) Endpoint 7 Interrupt Mask Mask */ -#define DEVIMR_PEP_8_Pos 20 /**< (DEVIMR) Endpoint 8 Interrupt Mask Position */ -#define DEVIMR_PEP_8 (_U_(0x1) << DEVIMR_PEP_8_Pos) /**< (DEVIMR) Endpoint 8 Interrupt Mask Mask */ -#define DEVIMR_PEP_9_Pos 21 /**< (DEVIMR) Endpoint 9 Interrupt Mask Position */ -#define DEVIMR_PEP_9 (_U_(0x1) << DEVIMR_PEP_9_Pos) /**< (DEVIMR) Endpoint 9 Interrupt Mask Mask */ -#define DEVIMR_DMA_1_Pos 25 /**< (DEVIMR) DMA Channel 1 Interrupt Mask Position */ -#define DEVIMR_DMA_1 (_U_(0x1) << DEVIMR_DMA_1_Pos) /**< (DEVIMR) DMA Channel 1 Interrupt Mask Mask */ -#define DEVIMR_DMA_2_Pos 26 /**< (DEVIMR) DMA Channel 2 Interrupt Mask Position */ -#define DEVIMR_DMA_2 (_U_(0x1) << DEVIMR_DMA_2_Pos) /**< (DEVIMR) DMA Channel 2 Interrupt Mask Mask */ -#define DEVIMR_DMA_3_Pos 27 /**< (DEVIMR) DMA Channel 3 Interrupt Mask Position */ -#define DEVIMR_DMA_3 (_U_(0x1) << DEVIMR_DMA_3_Pos) /**< (DEVIMR) DMA Channel 3 Interrupt Mask Mask */ -#define DEVIMR_DMA_4_Pos 28 /**< (DEVIMR) DMA Channel 4 Interrupt Mask Position */ -#define DEVIMR_DMA_4 (_U_(0x1) << DEVIMR_DMA_4_Pos) /**< (DEVIMR) DMA Channel 4 Interrupt Mask Mask */ -#define DEVIMR_DMA_5_Pos 29 /**< (DEVIMR) DMA Channel 5 Interrupt Mask Position */ -#define DEVIMR_DMA_5 (_U_(0x1) << DEVIMR_DMA_5_Pos) /**< (DEVIMR) DMA Channel 5 Interrupt Mask Mask */ -#define DEVIMR_DMA_6_Pos 30 /**< (DEVIMR) DMA Channel 6 Interrupt Mask Position */ -#define DEVIMR_DMA_6 (_U_(0x1) << DEVIMR_DMA_6_Pos) /**< (DEVIMR) DMA Channel 6 Interrupt Mask Mask */ -#define DEVIMR_DMA_7_Pos 31 /**< (DEVIMR) DMA Channel 7 Interrupt Mask Position */ -#define DEVIMR_DMA_7 (_U_(0x1) << DEVIMR_DMA_7_Pos) /**< (DEVIMR) DMA Channel 7 Interrupt Mask Mask */ -#define DEVIMR_Msk _U_(0xFE3FF07F) /**< (DEVIMR) Register Mask */ - -#define DEVIMR_PEP__Pos 12 /**< (DEVIMR Position) Endpoint x Interrupt Mask */ -#define DEVIMR_PEP_ (_U_(0x3FF) << DEVIMR_PEP__Pos) /**< (DEVIMR Mask) PEP_ */ -#define DEVIMR_DMA__Pos 25 /**< (DEVIMR Position) DMA Channel 7 Interrupt Mask */ -#define DEVIMR_DMA_ (_U_(0x7F) << DEVIMR_DMA__Pos) /**< (DEVIMR Mask) DMA_ */ - -/* -------- DEVIDR : (USBHS Offset: 0x14) (/W 32) Device Global Interrupt Disable Register -------- */ - -#define DEVIDR_OFFSET (0x14) /**< (DEVIDR) Device Global Interrupt Disable Register Offset */ - -#define DEVIDR_SUSPEC_Pos 0 /**< (DEVIDR) Suspend Interrupt Disable Position */ -#define DEVIDR_SUSPEC (_U_(0x1) << DEVIDR_SUSPEC_Pos) /**< (DEVIDR) Suspend Interrupt Disable Mask */ -#define DEVIDR_MSOFEC_Pos 1 /**< (DEVIDR) Micro Start of Frame Interrupt Disable Position */ -#define DEVIDR_MSOFEC (_U_(0x1) << DEVIDR_MSOFEC_Pos) /**< (DEVIDR) Micro Start of Frame Interrupt Disable Mask */ -#define DEVIDR_SOFEC_Pos 2 /**< (DEVIDR) Start of Frame Interrupt Disable Position */ -#define DEVIDR_SOFEC (_U_(0x1) << DEVIDR_SOFEC_Pos) /**< (DEVIDR) Start of Frame Interrupt Disable Mask */ -#define DEVIDR_EORSTEC_Pos 3 /**< (DEVIDR) End of Reset Interrupt Disable Position */ -#define DEVIDR_EORSTEC (_U_(0x1) << DEVIDR_EORSTEC_Pos) /**< (DEVIDR) End of Reset Interrupt Disable Mask */ -#define DEVIDR_WAKEUPEC_Pos 4 /**< (DEVIDR) Wake-Up Interrupt Disable Position */ -#define DEVIDR_WAKEUPEC (_U_(0x1) << DEVIDR_WAKEUPEC_Pos) /**< (DEVIDR) Wake-Up Interrupt Disable Mask */ -#define DEVIDR_EORSMEC_Pos 5 /**< (DEVIDR) End of Resume Interrupt Disable Position */ -#define DEVIDR_EORSMEC (_U_(0x1) << DEVIDR_EORSMEC_Pos) /**< (DEVIDR) End of Resume Interrupt Disable Mask */ -#define DEVIDR_UPRSMEC_Pos 6 /**< (DEVIDR) Upstream Resume Interrupt Disable Position */ -#define DEVIDR_UPRSMEC (_U_(0x1) << DEVIDR_UPRSMEC_Pos) /**< (DEVIDR) Upstream Resume Interrupt Disable Mask */ -#define DEVIDR_PEP_0_Pos 12 /**< (DEVIDR) Endpoint 0 Interrupt Disable Position */ -#define DEVIDR_PEP_0 (_U_(0x1) << DEVIDR_PEP_0_Pos) /**< (DEVIDR) Endpoint 0 Interrupt Disable Mask */ -#define DEVIDR_PEP_1_Pos 13 /**< (DEVIDR) Endpoint 1 Interrupt Disable Position */ -#define DEVIDR_PEP_1 (_U_(0x1) << DEVIDR_PEP_1_Pos) /**< (DEVIDR) Endpoint 1 Interrupt Disable Mask */ -#define DEVIDR_PEP_2_Pos 14 /**< (DEVIDR) Endpoint 2 Interrupt Disable Position */ -#define DEVIDR_PEP_2 (_U_(0x1) << DEVIDR_PEP_2_Pos) /**< (DEVIDR) Endpoint 2 Interrupt Disable Mask */ -#define DEVIDR_PEP_3_Pos 15 /**< (DEVIDR) Endpoint 3 Interrupt Disable Position */ -#define DEVIDR_PEP_3 (_U_(0x1) << DEVIDR_PEP_3_Pos) /**< (DEVIDR) Endpoint 3 Interrupt Disable Mask */ -#define DEVIDR_PEP_4_Pos 16 /**< (DEVIDR) Endpoint 4 Interrupt Disable Position */ -#define DEVIDR_PEP_4 (_U_(0x1) << DEVIDR_PEP_4_Pos) /**< (DEVIDR) Endpoint 4 Interrupt Disable Mask */ -#define DEVIDR_PEP_5_Pos 17 /**< (DEVIDR) Endpoint 5 Interrupt Disable Position */ -#define DEVIDR_PEP_5 (_U_(0x1) << DEVIDR_PEP_5_Pos) /**< (DEVIDR) Endpoint 5 Interrupt Disable Mask */ -#define DEVIDR_PEP_6_Pos 18 /**< (DEVIDR) Endpoint 6 Interrupt Disable Position */ -#define DEVIDR_PEP_6 (_U_(0x1) << DEVIDR_PEP_6_Pos) /**< (DEVIDR) Endpoint 6 Interrupt Disable Mask */ -#define DEVIDR_PEP_7_Pos 19 /**< (DEVIDR) Endpoint 7 Interrupt Disable Position */ -#define DEVIDR_PEP_7 (_U_(0x1) << DEVIDR_PEP_7_Pos) /**< (DEVIDR) Endpoint 7 Interrupt Disable Mask */ -#define DEVIDR_PEP_8_Pos 20 /**< (DEVIDR) Endpoint 8 Interrupt Disable Position */ -#define DEVIDR_PEP_8 (_U_(0x1) << DEVIDR_PEP_8_Pos) /**< (DEVIDR) Endpoint 8 Interrupt Disable Mask */ -#define DEVIDR_PEP_9_Pos 21 /**< (DEVIDR) Endpoint 9 Interrupt Disable Position */ -#define DEVIDR_PEP_9 (_U_(0x1) << DEVIDR_PEP_9_Pos) /**< (DEVIDR) Endpoint 9 Interrupt Disable Mask */ -#define DEVIDR_DMA_1_Pos 25 /**< (DEVIDR) DMA Channel 1 Interrupt Disable Position */ -#define DEVIDR_DMA_1 (_U_(0x1) << DEVIDR_DMA_1_Pos) /**< (DEVIDR) DMA Channel 1 Interrupt Disable Mask */ -#define DEVIDR_DMA_2_Pos 26 /**< (DEVIDR) DMA Channel 2 Interrupt Disable Position */ -#define DEVIDR_DMA_2 (_U_(0x1) << DEVIDR_DMA_2_Pos) /**< (DEVIDR) DMA Channel 2 Interrupt Disable Mask */ -#define DEVIDR_DMA_3_Pos 27 /**< (DEVIDR) DMA Channel 3 Interrupt Disable Position */ -#define DEVIDR_DMA_3 (_U_(0x1) << DEVIDR_DMA_3_Pos) /**< (DEVIDR) DMA Channel 3 Interrupt Disable Mask */ -#define DEVIDR_DMA_4_Pos 28 /**< (DEVIDR) DMA Channel 4 Interrupt Disable Position */ -#define DEVIDR_DMA_4 (_U_(0x1) << DEVIDR_DMA_4_Pos) /**< (DEVIDR) DMA Channel 4 Interrupt Disable Mask */ -#define DEVIDR_DMA_5_Pos 29 /**< (DEVIDR) DMA Channel 5 Interrupt Disable Position */ -#define DEVIDR_DMA_5 (_U_(0x1) << DEVIDR_DMA_5_Pos) /**< (DEVIDR) DMA Channel 5 Interrupt Disable Mask */ -#define DEVIDR_DMA_6_Pos 30 /**< (DEVIDR) DMA Channel 6 Interrupt Disable Position */ -#define DEVIDR_DMA_6 (_U_(0x1) << DEVIDR_DMA_6_Pos) /**< (DEVIDR) DMA Channel 6 Interrupt Disable Mask */ -#define DEVIDR_DMA_7_Pos 31 /**< (DEVIDR) DMA Channel 7 Interrupt Disable Position */ -#define DEVIDR_DMA_7 (_U_(0x1) << DEVIDR_DMA_7_Pos) /**< (DEVIDR) DMA Channel 7 Interrupt Disable Mask */ -#define DEVIDR_Msk _U_(0xFE3FF07F) /**< (DEVIDR) Register Mask */ - -#define DEVIDR_PEP__Pos 12 /**< (DEVIDR Position) Endpoint x Interrupt Disable */ -#define DEVIDR_PEP_ (_U_(0x3FF) << DEVIDR_PEP__Pos) /**< (DEVIDR Mask) PEP_ */ -#define DEVIDR_DMA__Pos 25 /**< (DEVIDR Position) DMA Channel 7 Interrupt Disable */ -#define DEVIDR_DMA_ (_U_(0x7F) << DEVIDR_DMA__Pos) /**< (DEVIDR Mask) DMA_ */ - -/* -------- DEVIER : (USBHS Offset: 0x18) (/W 32) Device Global Interrupt Enable Register -------- */ - -#define DEVIER_OFFSET (0x18) /**< (DEVIER) Device Global Interrupt Enable Register Offset */ - -#define DEVIER_SUSPES_Pos 0 /**< (DEVIER) Suspend Interrupt Enable Position */ -#define DEVIER_SUSPES (_U_(0x1) << DEVIER_SUSPES_Pos) /**< (DEVIER) Suspend Interrupt Enable Mask */ -#define DEVIER_MSOFES_Pos 1 /**< (DEVIER) Micro Start of Frame Interrupt Enable Position */ -#define DEVIER_MSOFES (_U_(0x1) << DEVIER_MSOFES_Pos) /**< (DEVIER) Micro Start of Frame Interrupt Enable Mask */ -#define DEVIER_SOFES_Pos 2 /**< (DEVIER) Start of Frame Interrupt Enable Position */ -#define DEVIER_SOFES (_U_(0x1) << DEVIER_SOFES_Pos) /**< (DEVIER) Start of Frame Interrupt Enable Mask */ -#define DEVIER_EORSTES_Pos 3 /**< (DEVIER) End of Reset Interrupt Enable Position */ -#define DEVIER_EORSTES (_U_(0x1) << DEVIER_EORSTES_Pos) /**< (DEVIER) End of Reset Interrupt Enable Mask */ -#define DEVIER_WAKEUPES_Pos 4 /**< (DEVIER) Wake-Up Interrupt Enable Position */ -#define DEVIER_WAKEUPES (_U_(0x1) << DEVIER_WAKEUPES_Pos) /**< (DEVIER) Wake-Up Interrupt Enable Mask */ -#define DEVIER_EORSMES_Pos 5 /**< (DEVIER) End of Resume Interrupt Enable Position */ -#define DEVIER_EORSMES (_U_(0x1) << DEVIER_EORSMES_Pos) /**< (DEVIER) End of Resume Interrupt Enable Mask */ -#define DEVIER_UPRSMES_Pos 6 /**< (DEVIER) Upstream Resume Interrupt Enable Position */ -#define DEVIER_UPRSMES (_U_(0x1) << DEVIER_UPRSMES_Pos) /**< (DEVIER) Upstream Resume Interrupt Enable Mask */ -#define DEVIER_PEP_0_Pos 12 /**< (DEVIER) Endpoint 0 Interrupt Enable Position */ -#define DEVIER_PEP_0 (_U_(0x1) << DEVIER_PEP_0_Pos) /**< (DEVIER) Endpoint 0 Interrupt Enable Mask */ -#define DEVIER_PEP_1_Pos 13 /**< (DEVIER) Endpoint 1 Interrupt Enable Position */ -#define DEVIER_PEP_1 (_U_(0x1) << DEVIER_PEP_1_Pos) /**< (DEVIER) Endpoint 1 Interrupt Enable Mask */ -#define DEVIER_PEP_2_Pos 14 /**< (DEVIER) Endpoint 2 Interrupt Enable Position */ -#define DEVIER_PEP_2 (_U_(0x1) << DEVIER_PEP_2_Pos) /**< (DEVIER) Endpoint 2 Interrupt Enable Mask */ -#define DEVIER_PEP_3_Pos 15 /**< (DEVIER) Endpoint 3 Interrupt Enable Position */ -#define DEVIER_PEP_3 (_U_(0x1) << DEVIER_PEP_3_Pos) /**< (DEVIER) Endpoint 3 Interrupt Enable Mask */ -#define DEVIER_PEP_4_Pos 16 /**< (DEVIER) Endpoint 4 Interrupt Enable Position */ -#define DEVIER_PEP_4 (_U_(0x1) << DEVIER_PEP_4_Pos) /**< (DEVIER) Endpoint 4 Interrupt Enable Mask */ -#define DEVIER_PEP_5_Pos 17 /**< (DEVIER) Endpoint 5 Interrupt Enable Position */ -#define DEVIER_PEP_5 (_U_(0x1) << DEVIER_PEP_5_Pos) /**< (DEVIER) Endpoint 5 Interrupt Enable Mask */ -#define DEVIER_PEP_6_Pos 18 /**< (DEVIER) Endpoint 6 Interrupt Enable Position */ -#define DEVIER_PEP_6 (_U_(0x1) << DEVIER_PEP_6_Pos) /**< (DEVIER) Endpoint 6 Interrupt Enable Mask */ -#define DEVIER_PEP_7_Pos 19 /**< (DEVIER) Endpoint 7 Interrupt Enable Position */ -#define DEVIER_PEP_7 (_U_(0x1) << DEVIER_PEP_7_Pos) /**< (DEVIER) Endpoint 7 Interrupt Enable Mask */ -#define DEVIER_PEP_8_Pos 20 /**< (DEVIER) Endpoint 8 Interrupt Enable Position */ -#define DEVIER_PEP_8 (_U_(0x1) << DEVIER_PEP_8_Pos) /**< (DEVIER) Endpoint 8 Interrupt Enable Mask */ -#define DEVIER_PEP_9_Pos 21 /**< (DEVIER) Endpoint 9 Interrupt Enable Position */ -#define DEVIER_PEP_9 (_U_(0x1) << DEVIER_PEP_9_Pos) /**< (DEVIER) Endpoint 9 Interrupt Enable Mask */ -#define DEVIER_DMA_1_Pos 25 /**< (DEVIER) DMA Channel 1 Interrupt Enable Position */ -#define DEVIER_DMA_1 (_U_(0x1) << DEVIER_DMA_1_Pos) /**< (DEVIER) DMA Channel 1 Interrupt Enable Mask */ -#define DEVIER_DMA_2_Pos 26 /**< (DEVIER) DMA Channel 2 Interrupt Enable Position */ -#define DEVIER_DMA_2 (_U_(0x1) << DEVIER_DMA_2_Pos) /**< (DEVIER) DMA Channel 2 Interrupt Enable Mask */ -#define DEVIER_DMA_3_Pos 27 /**< (DEVIER) DMA Channel 3 Interrupt Enable Position */ -#define DEVIER_DMA_3 (_U_(0x1) << DEVIER_DMA_3_Pos) /**< (DEVIER) DMA Channel 3 Interrupt Enable Mask */ -#define DEVIER_DMA_4_Pos 28 /**< (DEVIER) DMA Channel 4 Interrupt Enable Position */ -#define DEVIER_DMA_4 (_U_(0x1) << DEVIER_DMA_4_Pos) /**< (DEVIER) DMA Channel 4 Interrupt Enable Mask */ -#define DEVIER_DMA_5_Pos 29 /**< (DEVIER) DMA Channel 5 Interrupt Enable Position */ -#define DEVIER_DMA_5 (_U_(0x1) << DEVIER_DMA_5_Pos) /**< (DEVIER) DMA Channel 5 Interrupt Enable Mask */ -#define DEVIER_DMA_6_Pos 30 /**< (DEVIER) DMA Channel 6 Interrupt Enable Position */ -#define DEVIER_DMA_6 (_U_(0x1) << DEVIER_DMA_6_Pos) /**< (DEVIER) DMA Channel 6 Interrupt Enable Mask */ -#define DEVIER_DMA_7_Pos 31 /**< (DEVIER) DMA Channel 7 Interrupt Enable Position */ -#define DEVIER_DMA_7 (_U_(0x1) << DEVIER_DMA_7_Pos) /**< (DEVIER) DMA Channel 7 Interrupt Enable Mask */ -#define DEVIER_Msk _U_(0xFE3FF07F) /**< (DEVIER) Register Mask */ - -#define DEVIER_PEP__Pos 12 /**< (DEVIER Position) Endpoint x Interrupt Enable */ -#define DEVIER_PEP_ (_U_(0x3FF) << DEVIER_PEP__Pos) /**< (DEVIER Mask) PEP_ */ -#define DEVIER_DMA__Pos 25 /**< (DEVIER Position) DMA Channel 7 Interrupt Enable */ -#define DEVIER_DMA_ (_U_(0x7F) << DEVIER_DMA__Pos) /**< (DEVIER Mask) DMA_ */ - -/* -------- DEVEPT : (USBHS Offset: 0x1c) (R/W 32) Device Endpoint Register -------- */ - -#define DEVEPT_OFFSET (0x1C) /**< (DEVEPT) Device Endpoint Register Offset */ - -#define DEVEPT_EPEN0_Pos 0 /**< (DEVEPT) Endpoint 0 Enable Position */ -#define DEVEPT_EPEN0 (_U_(0x1) << DEVEPT_EPEN0_Pos) /**< (DEVEPT) Endpoint 0 Enable Mask */ -#define DEVEPT_EPEN1_Pos 1 /**< (DEVEPT) Endpoint 1 Enable Position */ -#define DEVEPT_EPEN1 (_U_(0x1) << DEVEPT_EPEN1_Pos) /**< (DEVEPT) Endpoint 1 Enable Mask */ -#define DEVEPT_EPEN2_Pos 2 /**< (DEVEPT) Endpoint 2 Enable Position */ -#define DEVEPT_EPEN2 (_U_(0x1) << DEVEPT_EPEN2_Pos) /**< (DEVEPT) Endpoint 2 Enable Mask */ -#define DEVEPT_EPEN3_Pos 3 /**< (DEVEPT) Endpoint 3 Enable Position */ -#define DEVEPT_EPEN3 (_U_(0x1) << DEVEPT_EPEN3_Pos) /**< (DEVEPT) Endpoint 3 Enable Mask */ -#define DEVEPT_EPEN4_Pos 4 /**< (DEVEPT) Endpoint 4 Enable Position */ -#define DEVEPT_EPEN4 (_U_(0x1) << DEVEPT_EPEN4_Pos) /**< (DEVEPT) Endpoint 4 Enable Mask */ -#define DEVEPT_EPEN5_Pos 5 /**< (DEVEPT) Endpoint 5 Enable Position */ -#define DEVEPT_EPEN5 (_U_(0x1) << DEVEPT_EPEN5_Pos) /**< (DEVEPT) Endpoint 5 Enable Mask */ -#define DEVEPT_EPEN6_Pos 6 /**< (DEVEPT) Endpoint 6 Enable Position */ -#define DEVEPT_EPEN6 (_U_(0x1) << DEVEPT_EPEN6_Pos) /**< (DEVEPT) Endpoint 6 Enable Mask */ -#define DEVEPT_EPEN7_Pos 7 /**< (DEVEPT) Endpoint 7 Enable Position */ -#define DEVEPT_EPEN7 (_U_(0x1) << DEVEPT_EPEN7_Pos) /**< (DEVEPT) Endpoint 7 Enable Mask */ -#define DEVEPT_EPEN8_Pos 8 /**< (DEVEPT) Endpoint 8 Enable Position */ -#define DEVEPT_EPEN8 (_U_(0x1) << DEVEPT_EPEN8_Pos) /**< (DEVEPT) Endpoint 8 Enable Mask */ -#define DEVEPT_EPEN9_Pos 9 /**< (DEVEPT) Endpoint 9 Enable Position */ -#define DEVEPT_EPEN9 (_U_(0x1) << DEVEPT_EPEN9_Pos) /**< (DEVEPT) Endpoint 9 Enable Mask */ -#define DEVEPT_EPRST0_Pos 16 /**< (DEVEPT) Endpoint 0 Reset Position */ -#define DEVEPT_EPRST0 (_U_(0x1) << DEVEPT_EPRST0_Pos) /**< (DEVEPT) Endpoint 0 Reset Mask */ -#define DEVEPT_EPRST1_Pos 17 /**< (DEVEPT) Endpoint 1 Reset Position */ -#define DEVEPT_EPRST1 (_U_(0x1) << DEVEPT_EPRST1_Pos) /**< (DEVEPT) Endpoint 1 Reset Mask */ -#define DEVEPT_EPRST2_Pos 18 /**< (DEVEPT) Endpoint 2 Reset Position */ -#define DEVEPT_EPRST2 (_U_(0x1) << DEVEPT_EPRST2_Pos) /**< (DEVEPT) Endpoint 2 Reset Mask */ -#define DEVEPT_EPRST3_Pos 19 /**< (DEVEPT) Endpoint 3 Reset Position */ -#define DEVEPT_EPRST3 (_U_(0x1) << DEVEPT_EPRST3_Pos) /**< (DEVEPT) Endpoint 3 Reset Mask */ -#define DEVEPT_EPRST4_Pos 20 /**< (DEVEPT) Endpoint 4 Reset Position */ -#define DEVEPT_EPRST4 (_U_(0x1) << DEVEPT_EPRST4_Pos) /**< (DEVEPT) Endpoint 4 Reset Mask */ -#define DEVEPT_EPRST5_Pos 21 /**< (DEVEPT) Endpoint 5 Reset Position */ -#define DEVEPT_EPRST5 (_U_(0x1) << DEVEPT_EPRST5_Pos) /**< (DEVEPT) Endpoint 5 Reset Mask */ -#define DEVEPT_EPRST6_Pos 22 /**< (DEVEPT) Endpoint 6 Reset Position */ -#define DEVEPT_EPRST6 (_U_(0x1) << DEVEPT_EPRST6_Pos) /**< (DEVEPT) Endpoint 6 Reset Mask */ -#define DEVEPT_EPRST7_Pos 23 /**< (DEVEPT) Endpoint 7 Reset Position */ -#define DEVEPT_EPRST7 (_U_(0x1) << DEVEPT_EPRST7_Pos) /**< (DEVEPT) Endpoint 7 Reset Mask */ -#define DEVEPT_EPRST8_Pos 24 /**< (DEVEPT) Endpoint 8 Reset Position */ -#define DEVEPT_EPRST8 (_U_(0x1) << DEVEPT_EPRST8_Pos) /**< (DEVEPT) Endpoint 8 Reset Mask */ -#define DEVEPT_EPRST9_Pos 25 /**< (DEVEPT) Endpoint 9 Reset Position */ -#define DEVEPT_EPRST9 (_U_(0x1) << DEVEPT_EPRST9_Pos) /**< (DEVEPT) Endpoint 9 Reset Mask */ -#define DEVEPT_Msk _U_(0x3FF03FF) /**< (DEVEPT) Register Mask */ - -#define DEVEPT_EPEN_Pos 0 /**< (DEVEPT Position) Endpoint x Enable */ -#define DEVEPT_EPEN (_U_(0x3FF) << DEVEPT_EPEN_Pos) /**< (DEVEPT Mask) EPEN */ -#define DEVEPT_EPRST_Pos 16 /**< (DEVEPT Position) Endpoint 9 Reset */ -#define DEVEPT_EPRST (_U_(0x3FF) << DEVEPT_EPRST_Pos) /**< (DEVEPT Mask) EPRST */ - -/* -------- DEVFNUM : (USBHS Offset: 0x20) (R/ 32) Device Frame Number Register -------- */ - -#define DEVFNUM_OFFSET (0x20) /**< (DEVFNUM) Device Frame Number Register Offset */ - -#define DEVFNUM_MFNUM_Pos 0 /**< (DEVFNUM) Micro Frame Number Position */ -#define DEVFNUM_MFNUM (_U_(0x7) << DEVFNUM_MFNUM_Pos) /**< (DEVFNUM) Micro Frame Number Mask */ -#define DEVFNUM_FNUM_Pos 3 /**< (DEVFNUM) Frame Number Position */ -#define DEVFNUM_FNUM (_U_(0x7FF) << DEVFNUM_FNUM_Pos) /**< (DEVFNUM) Frame Number Mask */ -#define DEVFNUM_FNCERR_Pos 15 /**< (DEVFNUM) Frame Number CRC Error Position */ -#define DEVFNUM_FNCERR (_U_(0x1) << DEVFNUM_FNCERR_Pos) /**< (DEVFNUM) Frame Number CRC Error Mask */ -#define DEVFNUM_Msk _U_(0xBFFF) /**< (DEVFNUM) Register Mask */ - - -/* -------- DEVEPTCFG : (USBHS Offset: 0x100) (R/W 32) Device Endpoint Configuration Register -------- */ - -#define DEVEPTCFG_OFFSET (0x100) /**< (DEVEPTCFG) Device Endpoint Configuration Register Offset */ - -#define DEVEPTCFG_ALLOC_Pos 1 /**< (DEVEPTCFG) Endpoint Memory Allocate Position */ -#define DEVEPTCFG_ALLOC (_U_(0x1) << DEVEPTCFG_ALLOC_Pos) /**< (DEVEPTCFG) Endpoint Memory Allocate Mask */ -#define DEVEPTCFG_EPBK_Pos 2 /**< (DEVEPTCFG) Endpoint Banks Position */ -#define DEVEPTCFG_EPBK (_U_(0x3) << DEVEPTCFG_EPBK_Pos) /**< (DEVEPTCFG) Endpoint Banks Mask */ -#define DEVEPTCFG_EPBK_1_BANK_Val _U_(0x0) /**< (DEVEPTCFG) Single-bank endpoint */ -#define DEVEPTCFG_EPBK_2_BANK_Val _U_(0x1) /**< (DEVEPTCFG) Double-bank endpoint */ -#define DEVEPTCFG_EPBK_3_BANK_Val _U_(0x2) /**< (DEVEPTCFG) Triple-bank endpoint */ -#define DEVEPTCFG_EPBK_1_BANK (DEVEPTCFG_EPBK_1_BANK_Val << DEVEPTCFG_EPBK_Pos) /**< (DEVEPTCFG) Single-bank endpoint Position */ -#define DEVEPTCFG_EPBK_2_BANK (DEVEPTCFG_EPBK_2_BANK_Val << DEVEPTCFG_EPBK_Pos) /**< (DEVEPTCFG) Double-bank endpoint Position */ -#define DEVEPTCFG_EPBK_3_BANK (DEVEPTCFG_EPBK_3_BANK_Val << DEVEPTCFG_EPBK_Pos) /**< (DEVEPTCFG) Triple-bank endpoint Position */ -#define DEVEPTCFG_EPSIZE_Pos 4 /**< (DEVEPTCFG) Endpoint Size Position */ -#define DEVEPTCFG_EPSIZE (_U_(0x7) << DEVEPTCFG_EPSIZE_Pos) /**< (DEVEPTCFG) Endpoint Size Mask */ -#define DEVEPTCFG_EPSIZE_8_BYTE_Val _U_(0x0) /**< (DEVEPTCFG) 8 bytes */ -#define DEVEPTCFG_EPSIZE_16_BYTE_Val _U_(0x1) /**< (DEVEPTCFG) 16 bytes */ -#define DEVEPTCFG_EPSIZE_32_BYTE_Val _U_(0x2) /**< (DEVEPTCFG) 32 bytes */ -#define DEVEPTCFG_EPSIZE_64_BYTE_Val _U_(0x3) /**< (DEVEPTCFG) 64 bytes */ -#define DEVEPTCFG_EPSIZE_128_BYTE_Val _U_(0x4) /**< (DEVEPTCFG) 128 bytes */ -#define DEVEPTCFG_EPSIZE_256_BYTE_Val _U_(0x5) /**< (DEVEPTCFG) 256 bytes */ -#define DEVEPTCFG_EPSIZE_512_BYTE_Val _U_(0x6) /**< (DEVEPTCFG) 512 bytes */ -#define DEVEPTCFG_EPSIZE_1024_BYTE_Val _U_(0x7) /**< (DEVEPTCFG) 1024 bytes */ -#define DEVEPTCFG_EPSIZE_8_BYTE (DEVEPTCFG_EPSIZE_8_BYTE_Val << DEVEPTCFG_EPSIZE_Pos) /**< (DEVEPTCFG) 8 bytes Position */ -#define DEVEPTCFG_EPSIZE_16_BYTE (DEVEPTCFG_EPSIZE_16_BYTE_Val << DEVEPTCFG_EPSIZE_Pos) /**< (DEVEPTCFG) 16 bytes Position */ -#define DEVEPTCFG_EPSIZE_32_BYTE (DEVEPTCFG_EPSIZE_32_BYTE_Val << DEVEPTCFG_EPSIZE_Pos) /**< (DEVEPTCFG) 32 bytes Position */ -#define DEVEPTCFG_EPSIZE_64_BYTE (DEVEPTCFG_EPSIZE_64_BYTE_Val << DEVEPTCFG_EPSIZE_Pos) /**< (DEVEPTCFG) 64 bytes Position */ -#define DEVEPTCFG_EPSIZE_128_BYTE (DEVEPTCFG_EPSIZE_128_BYTE_Val << DEVEPTCFG_EPSIZE_Pos) /**< (DEVEPTCFG) 128 bytes Position */ -#define DEVEPTCFG_EPSIZE_256_BYTE (DEVEPTCFG_EPSIZE_256_BYTE_Val << DEVEPTCFG_EPSIZE_Pos) /**< (DEVEPTCFG) 256 bytes Position */ -#define DEVEPTCFG_EPSIZE_512_BYTE (DEVEPTCFG_EPSIZE_512_BYTE_Val << DEVEPTCFG_EPSIZE_Pos) /**< (DEVEPTCFG) 512 bytes Position */ -#define DEVEPTCFG_EPSIZE_1024_BYTE (DEVEPTCFG_EPSIZE_1024_BYTE_Val << DEVEPTCFG_EPSIZE_Pos) /**< (DEVEPTCFG) 1024 bytes Position */ -#define DEVEPTCFG_EPDIR_Pos 8 /**< (DEVEPTCFG) Endpoint Direction Position */ -#define DEVEPTCFG_EPDIR (_U_(0x1) << DEVEPTCFG_EPDIR_Pos) /**< (DEVEPTCFG) Endpoint Direction Mask */ -#define DEVEPTCFG_EPDIR_OUT_Val _U_(0x0) /**< (DEVEPTCFG) The endpoint direction is OUT. */ -#define DEVEPTCFG_EPDIR_IN_Val _U_(0x1) /**< (DEVEPTCFG) The endpoint direction is IN (nor for control endpoints). */ -#define DEVEPTCFG_EPDIR_OUT (DEVEPTCFG_EPDIR_OUT_Val << DEVEPTCFG_EPDIR_Pos) /**< (DEVEPTCFG) The endpoint direction is OUT. Position */ -#define DEVEPTCFG_EPDIR_IN (DEVEPTCFG_EPDIR_IN_Val << DEVEPTCFG_EPDIR_Pos) /**< (DEVEPTCFG) The endpoint direction is IN (nor for control endpoints). Position */ -#define DEVEPTCFG_AUTOSW_Pos 9 /**< (DEVEPTCFG) Automatic Switch Position */ -#define DEVEPTCFG_AUTOSW (_U_(0x1) << DEVEPTCFG_AUTOSW_Pos) /**< (DEVEPTCFG) Automatic Switch Mask */ -#define DEVEPTCFG_EPTYPE_Pos 11 /**< (DEVEPTCFG) Endpoint Type Position */ -#define DEVEPTCFG_EPTYPE (_U_(0x3) << DEVEPTCFG_EPTYPE_Pos) /**< (DEVEPTCFG) Endpoint Type Mask */ -#define DEVEPTCFG_EPTYPE_CTRL_Val _U_(0x0) /**< (DEVEPTCFG) Control */ -#define DEVEPTCFG_EPTYPE_ISO_Val _U_(0x1) /**< (DEVEPTCFG) Isochronous */ -#define DEVEPTCFG_EPTYPE_BLK_Val _U_(0x2) /**< (DEVEPTCFG) Bulk */ -#define DEVEPTCFG_EPTYPE_INTRPT_Val _U_(0x3) /**< (DEVEPTCFG) Interrupt */ -#define DEVEPTCFG_EPTYPE_CTRL (DEVEPTCFG_EPTYPE_CTRL_Val << DEVEPTCFG_EPTYPE_Pos) /**< (DEVEPTCFG) Control Position */ -#define DEVEPTCFG_EPTYPE_ISO (DEVEPTCFG_EPTYPE_ISO_Val << DEVEPTCFG_EPTYPE_Pos) /**< (DEVEPTCFG) Isochronous Position */ -#define DEVEPTCFG_EPTYPE_BLK (DEVEPTCFG_EPTYPE_BLK_Val << DEVEPTCFG_EPTYPE_Pos) /**< (DEVEPTCFG) Bulk Position */ -#define DEVEPTCFG_EPTYPE_INTRPT (DEVEPTCFG_EPTYPE_INTRPT_Val << DEVEPTCFG_EPTYPE_Pos) /**< (DEVEPTCFG) Interrupt Position */ -#define DEVEPTCFG_NBTRANS_Pos 13 /**< (DEVEPTCFG) Number of transactions per microframe for isochronous endpoint Position */ -#define DEVEPTCFG_NBTRANS (_U_(0x3) << DEVEPTCFG_NBTRANS_Pos) /**< (DEVEPTCFG) Number of transactions per microframe for isochronous endpoint Mask */ -#define DEVEPTCFG_NBTRANS_0_TRANS_Val _U_(0x0) /**< (DEVEPTCFG) Reserved to endpoint that does not have the high-bandwidth isochronous capability. */ -#define DEVEPTCFG_NBTRANS_1_TRANS_Val _U_(0x1) /**< (DEVEPTCFG) Default value: one transaction per microframe. */ -#define DEVEPTCFG_NBTRANS_2_TRANS_Val _U_(0x2) /**< (DEVEPTCFG) Two transactions per microframe. This endpoint should be configured as double-bank. */ -#define DEVEPTCFG_NBTRANS_3_TRANS_Val _U_(0x3) /**< (DEVEPTCFG) Three transactions per microframe. This endpoint should be configured as triple-bank. */ -#define DEVEPTCFG_NBTRANS_0_TRANS (DEVEPTCFG_NBTRANS_0_TRANS_Val << DEVEPTCFG_NBTRANS_Pos) /**< (DEVEPTCFG) Reserved to endpoint that does not have the high-bandwidth isochronous capability. Position */ -#define DEVEPTCFG_NBTRANS_1_TRANS (DEVEPTCFG_NBTRANS_1_TRANS_Val << DEVEPTCFG_NBTRANS_Pos) /**< (DEVEPTCFG) Default value: one transaction per microframe. Position */ -#define DEVEPTCFG_NBTRANS_2_TRANS (DEVEPTCFG_NBTRANS_2_TRANS_Val << DEVEPTCFG_NBTRANS_Pos) /**< (DEVEPTCFG) Two transactions per microframe. This endpoint should be configured as double-bank. Position */ -#define DEVEPTCFG_NBTRANS_3_TRANS (DEVEPTCFG_NBTRANS_3_TRANS_Val << DEVEPTCFG_NBTRANS_Pos) /**< (DEVEPTCFG) Three transactions per microframe. This endpoint should be configured as triple-bank. Position */ -#define DEVEPTCFG_Msk _U_(0x7B7E) /**< (DEVEPTCFG) Register Mask */ - - -/* -------- DEVEPTISR : (USBHS Offset: 0x130) (R/ 32) Device Endpoint Interrupt Status Register -------- */ - -#define DEVEPTISR_OFFSET (0x130) /**< (DEVEPTISR) Device Endpoint Interrupt Status Register Offset */ - -#define DEVEPTISR_TXINI_Pos 0 /**< (DEVEPTISR) Transmitted IN Data Interrupt Position */ -#define DEVEPTISR_TXINI (_U_(0x1) << DEVEPTISR_TXINI_Pos) /**< (DEVEPTISR) Transmitted IN Data Interrupt Mask */ -#define DEVEPTISR_RXOUTI_Pos 1 /**< (DEVEPTISR) Received OUT Data Interrupt Position */ -#define DEVEPTISR_RXOUTI (_U_(0x1) << DEVEPTISR_RXOUTI_Pos) /**< (DEVEPTISR) Received OUT Data Interrupt Mask */ -#define DEVEPTISR_OVERFI_Pos 5 /**< (DEVEPTISR) Overflow Interrupt Position */ -#define DEVEPTISR_OVERFI (_U_(0x1) << DEVEPTISR_OVERFI_Pos) /**< (DEVEPTISR) Overflow Interrupt Mask */ -#define DEVEPTISR_SHORTPACKET_Pos 7 /**< (DEVEPTISR) Short Packet Interrupt Position */ -#define DEVEPTISR_SHORTPACKET (_U_(0x1) << DEVEPTISR_SHORTPACKET_Pos) /**< (DEVEPTISR) Short Packet Interrupt Mask */ -#define DEVEPTISR_DTSEQ_Pos 8 /**< (DEVEPTISR) Data Toggle Sequence Position */ -#define DEVEPTISR_DTSEQ (_U_(0x3) << DEVEPTISR_DTSEQ_Pos) /**< (DEVEPTISR) Data Toggle Sequence Mask */ -#define DEVEPTISR_DTSEQ_DATA0_Val _U_(0x0) /**< (DEVEPTISR) Data0 toggle sequence */ -#define DEVEPTISR_DTSEQ_DATA1_Val _U_(0x1) /**< (DEVEPTISR) Data1 toggle sequence */ -#define DEVEPTISR_DTSEQ_DATA2_Val _U_(0x2) /**< (DEVEPTISR) Reserved for high-bandwidth isochronous endpoint */ -#define DEVEPTISR_DTSEQ_MDATA_Val _U_(0x3) /**< (DEVEPTISR) Reserved for high-bandwidth isochronous endpoint */ -#define DEVEPTISR_DTSEQ_DATA0 (DEVEPTISR_DTSEQ_DATA0_Val << DEVEPTISR_DTSEQ_Pos) /**< (DEVEPTISR) Data0 toggle sequence Position */ -#define DEVEPTISR_DTSEQ_DATA1 (DEVEPTISR_DTSEQ_DATA1_Val << DEVEPTISR_DTSEQ_Pos) /**< (DEVEPTISR) Data1 toggle sequence Position */ -#define DEVEPTISR_DTSEQ_DATA2 (DEVEPTISR_DTSEQ_DATA2_Val << DEVEPTISR_DTSEQ_Pos) /**< (DEVEPTISR) Reserved for high-bandwidth isochronous endpoint Position */ -#define DEVEPTISR_DTSEQ_MDATA (DEVEPTISR_DTSEQ_MDATA_Val << DEVEPTISR_DTSEQ_Pos) /**< (DEVEPTISR) Reserved for high-bandwidth isochronous endpoint Position */ -#define DEVEPTISR_NBUSYBK_Pos 12 /**< (DEVEPTISR) Number of Busy Banks Position */ -#define DEVEPTISR_NBUSYBK (_U_(0x3) << DEVEPTISR_NBUSYBK_Pos) /**< (DEVEPTISR) Number of Busy Banks Mask */ -#define DEVEPTISR_NBUSYBK_0_BUSY_Val _U_(0x0) /**< (DEVEPTISR) 0 busy bank (all banks free) */ -#define DEVEPTISR_NBUSYBK_1_BUSY_Val _U_(0x1) /**< (DEVEPTISR) 1 busy bank */ -#define DEVEPTISR_NBUSYBK_2_BUSY_Val _U_(0x2) /**< (DEVEPTISR) 2 busy banks */ -#define DEVEPTISR_NBUSYBK_3_BUSY_Val _U_(0x3) /**< (DEVEPTISR) 3 busy banks */ -#define DEVEPTISR_NBUSYBK_0_BUSY (DEVEPTISR_NBUSYBK_0_BUSY_Val << DEVEPTISR_NBUSYBK_Pos) /**< (DEVEPTISR) 0 busy bank (all banks free) Position */ -#define DEVEPTISR_NBUSYBK_1_BUSY (DEVEPTISR_NBUSYBK_1_BUSY_Val << DEVEPTISR_NBUSYBK_Pos) /**< (DEVEPTISR) 1 busy bank Position */ -#define DEVEPTISR_NBUSYBK_2_BUSY (DEVEPTISR_NBUSYBK_2_BUSY_Val << DEVEPTISR_NBUSYBK_Pos) /**< (DEVEPTISR) 2 busy banks Position */ -#define DEVEPTISR_NBUSYBK_3_BUSY (DEVEPTISR_NBUSYBK_3_BUSY_Val << DEVEPTISR_NBUSYBK_Pos) /**< (DEVEPTISR) 3 busy banks Position */ -#define DEVEPTISR_CURRBK_Pos 14 /**< (DEVEPTISR) Current Bank Position */ -#define DEVEPTISR_CURRBK (_U_(0x3) << DEVEPTISR_CURRBK_Pos) /**< (DEVEPTISR) Current Bank Mask */ -#define DEVEPTISR_CURRBK_BANK0_Val _U_(0x0) /**< (DEVEPTISR) Current bank is bank0 */ -#define DEVEPTISR_CURRBK_BANK1_Val _U_(0x1) /**< (DEVEPTISR) Current bank is bank1 */ -#define DEVEPTISR_CURRBK_BANK2_Val _U_(0x2) /**< (DEVEPTISR) Current bank is bank2 */ -#define DEVEPTISR_CURRBK_BANK0 (DEVEPTISR_CURRBK_BANK0_Val << DEVEPTISR_CURRBK_Pos) /**< (DEVEPTISR) Current bank is bank0 Position */ -#define DEVEPTISR_CURRBK_BANK1 (DEVEPTISR_CURRBK_BANK1_Val << DEVEPTISR_CURRBK_Pos) /**< (DEVEPTISR) Current bank is bank1 Position */ -#define DEVEPTISR_CURRBK_BANK2 (DEVEPTISR_CURRBK_BANK2_Val << DEVEPTISR_CURRBK_Pos) /**< (DEVEPTISR) Current bank is bank2 Position */ -#define DEVEPTISR_RWALL_Pos 16 /**< (DEVEPTISR) Read/Write Allowed Position */ -#define DEVEPTISR_RWALL (_U_(0x1) << DEVEPTISR_RWALL_Pos) /**< (DEVEPTISR) Read/Write Allowed Mask */ -#define DEVEPTISR_CFGOK_Pos 18 /**< (DEVEPTISR) Configuration OK Status Position */ -#define DEVEPTISR_CFGOK (_U_(0x1) << DEVEPTISR_CFGOK_Pos) /**< (DEVEPTISR) Configuration OK Status Mask */ -#define DEVEPTISR_BYCT_Pos 20 /**< (DEVEPTISR) Byte Count Position */ -#define DEVEPTISR_BYCT (_U_(0x7FF) << DEVEPTISR_BYCT_Pos) /**< (DEVEPTISR) Byte Count Mask */ -#define DEVEPTISR_Msk _U_(0x7FF5F3A3) /**< (DEVEPTISR) Register Mask */ - -/* CTRL mode */ -#define DEVEPTISR_CTRL_RXSTPI_Pos 2 /**< (DEVEPTISR) Received SETUP Interrupt Position */ -#define DEVEPTISR_CTRL_RXSTPI (_U_(0x1) << DEVEPTISR_CTRL_RXSTPI_Pos) /**< (DEVEPTISR) Received SETUP Interrupt Mask */ -#define DEVEPTISR_CTRL_NAKOUTI_Pos 3 /**< (DEVEPTISR) NAKed OUT Interrupt Position */ -#define DEVEPTISR_CTRL_NAKOUTI (_U_(0x1) << DEVEPTISR_CTRL_NAKOUTI_Pos) /**< (DEVEPTISR) NAKed OUT Interrupt Mask */ -#define DEVEPTISR_CTRL_NAKINI_Pos 4 /**< (DEVEPTISR) NAKed IN Interrupt Position */ -#define DEVEPTISR_CTRL_NAKINI (_U_(0x1) << DEVEPTISR_CTRL_NAKINI_Pos) /**< (DEVEPTISR) NAKed IN Interrupt Mask */ -#define DEVEPTISR_CTRL_STALLEDI_Pos 6 /**< (DEVEPTISR) STALLed Interrupt Position */ -#define DEVEPTISR_CTRL_STALLEDI (_U_(0x1) << DEVEPTISR_CTRL_STALLEDI_Pos) /**< (DEVEPTISR) STALLed Interrupt Mask */ -#define DEVEPTISR_CTRL_CTRLDIR_Pos 17 /**< (DEVEPTISR) Control Direction Position */ -#define DEVEPTISR_CTRL_CTRLDIR (_U_(0x1) << DEVEPTISR_CTRL_CTRLDIR_Pos) /**< (DEVEPTISR) Control Direction Mask */ -#define DEVEPTISR_CTRL_Msk _U_(0x2005C) /**< (DEVEPTISR_CTRL) Register Mask */ - -/* ISO mode */ -#define DEVEPTISR_ISO_UNDERFI_Pos 2 /**< (DEVEPTISR) Underflow Interrupt Position */ -#define DEVEPTISR_ISO_UNDERFI (_U_(0x1) << DEVEPTISR_ISO_UNDERFI_Pos) /**< (DEVEPTISR) Underflow Interrupt Mask */ -#define DEVEPTISR_ISO_HBISOINERRI_Pos 3 /**< (DEVEPTISR) High Bandwidth Isochronous IN Underflow Error Interrupt Position */ -#define DEVEPTISR_ISO_HBISOINERRI (_U_(0x1) << DEVEPTISR_ISO_HBISOINERRI_Pos) /**< (DEVEPTISR) High Bandwidth Isochronous IN Underflow Error Interrupt Mask */ -#define DEVEPTISR_ISO_HBISOFLUSHI_Pos 4 /**< (DEVEPTISR) High Bandwidth Isochronous IN Flush Interrupt Position */ -#define DEVEPTISR_ISO_HBISOFLUSHI (_U_(0x1) << DEVEPTISR_ISO_HBISOFLUSHI_Pos) /**< (DEVEPTISR) High Bandwidth Isochronous IN Flush Interrupt Mask */ -#define DEVEPTISR_ISO_CRCERRI_Pos 6 /**< (DEVEPTISR) CRC Error Interrupt Position */ -#define DEVEPTISR_ISO_CRCERRI (_U_(0x1) << DEVEPTISR_ISO_CRCERRI_Pos) /**< (DEVEPTISR) CRC Error Interrupt Mask */ -#define DEVEPTISR_ISO_ERRORTRANS_Pos 10 /**< (DEVEPTISR) High-bandwidth Isochronous OUT Endpoint Transaction Error Interrupt Position */ -#define DEVEPTISR_ISO_ERRORTRANS (_U_(0x1) << DEVEPTISR_ISO_ERRORTRANS_Pos) /**< (DEVEPTISR) High-bandwidth Isochronous OUT Endpoint Transaction Error Interrupt Mask */ -#define DEVEPTISR_ISO_Msk _U_(0x45C) /**< (DEVEPTISR_ISO) Register Mask */ - -/* BLK mode */ -#define DEVEPTISR_BLK_RXSTPI_Pos 2 /**< (DEVEPTISR) Received SETUP Interrupt Position */ -#define DEVEPTISR_BLK_RXSTPI (_U_(0x1) << DEVEPTISR_BLK_RXSTPI_Pos) /**< (DEVEPTISR) Received SETUP Interrupt Mask */ -#define DEVEPTISR_BLK_NAKOUTI_Pos 3 /**< (DEVEPTISR) NAKed OUT Interrupt Position */ -#define DEVEPTISR_BLK_NAKOUTI (_U_(0x1) << DEVEPTISR_BLK_NAKOUTI_Pos) /**< (DEVEPTISR) NAKed OUT Interrupt Mask */ -#define DEVEPTISR_BLK_NAKINI_Pos 4 /**< (DEVEPTISR) NAKed IN Interrupt Position */ -#define DEVEPTISR_BLK_NAKINI (_U_(0x1) << DEVEPTISR_BLK_NAKINI_Pos) /**< (DEVEPTISR) NAKed IN Interrupt Mask */ -#define DEVEPTISR_BLK_STALLEDI_Pos 6 /**< (DEVEPTISR) STALLed Interrupt Position */ -#define DEVEPTISR_BLK_STALLEDI (_U_(0x1) << DEVEPTISR_BLK_STALLEDI_Pos) /**< (DEVEPTISR) STALLed Interrupt Mask */ -#define DEVEPTISR_BLK_CTRLDIR_Pos 17 /**< (DEVEPTISR) Control Direction Position */ -#define DEVEPTISR_BLK_CTRLDIR (_U_(0x1) << DEVEPTISR_BLK_CTRLDIR_Pos) /**< (DEVEPTISR) Control Direction Mask */ -#define DEVEPTISR_BLK_Msk _U_(0x2005C) /**< (DEVEPTISR_BLK) Register Mask */ - -/* INTRPT mode */ -#define DEVEPTISR_INTRPT_RXSTPI_Pos 2 /**< (DEVEPTISR) Received SETUP Interrupt Position */ -#define DEVEPTISR_INTRPT_RXSTPI (_U_(0x1) << DEVEPTISR_INTRPT_RXSTPI_Pos) /**< (DEVEPTISR) Received SETUP Interrupt Mask */ -#define DEVEPTISR_INTRPT_NAKOUTI_Pos 3 /**< (DEVEPTISR) NAKed OUT Interrupt Position */ -#define DEVEPTISR_INTRPT_NAKOUTI (_U_(0x1) << DEVEPTISR_INTRPT_NAKOUTI_Pos) /**< (DEVEPTISR) NAKed OUT Interrupt Mask */ -#define DEVEPTISR_INTRPT_NAKINI_Pos 4 /**< (DEVEPTISR) NAKed IN Interrupt Position */ -#define DEVEPTISR_INTRPT_NAKINI (_U_(0x1) << DEVEPTISR_INTRPT_NAKINI_Pos) /**< (DEVEPTISR) NAKed IN Interrupt Mask */ -#define DEVEPTISR_INTRPT_STALLEDI_Pos 6 /**< (DEVEPTISR) STALLed Interrupt Position */ -#define DEVEPTISR_INTRPT_STALLEDI (_U_(0x1) << DEVEPTISR_INTRPT_STALLEDI_Pos) /**< (DEVEPTISR) STALLed Interrupt Mask */ -#define DEVEPTISR_INTRPT_CTRLDIR_Pos 17 /**< (DEVEPTISR) Control Direction Position */ -#define DEVEPTISR_INTRPT_CTRLDIR (_U_(0x1) << DEVEPTISR_INTRPT_CTRLDIR_Pos) /**< (DEVEPTISR) Control Direction Mask */ -#define DEVEPTISR_INTRPT_Msk _U_(0x2005C) /**< (DEVEPTISR_INTRPT) Register Mask */ - - -/* -------- DEVEPTICR : (USBHS Offset: 0x160) (/W 32) Device Endpoint Interrupt Clear Register -------- */ - -#define DEVEPTICR_OFFSET (0x160) /**< (DEVEPTICR) Device Endpoint Interrupt Clear Register Offset */ - -#define DEVEPTICR_TXINIC_Pos 0 /**< (DEVEPTICR) Transmitted IN Data Interrupt Clear Position */ -#define DEVEPTICR_TXINIC (_U_(0x1) << DEVEPTICR_TXINIC_Pos) /**< (DEVEPTICR) Transmitted IN Data Interrupt Clear Mask */ -#define DEVEPTICR_RXOUTIC_Pos 1 /**< (DEVEPTICR) Received OUT Data Interrupt Clear Position */ -#define DEVEPTICR_RXOUTIC (_U_(0x1) << DEVEPTICR_RXOUTIC_Pos) /**< (DEVEPTICR) Received OUT Data Interrupt Clear Mask */ -#define DEVEPTICR_OVERFIC_Pos 5 /**< (DEVEPTICR) Overflow Interrupt Clear Position */ -#define DEVEPTICR_OVERFIC (_U_(0x1) << DEVEPTICR_OVERFIC_Pos) /**< (DEVEPTICR) Overflow Interrupt Clear Mask */ -#define DEVEPTICR_SHORTPACKETC_Pos 7 /**< (DEVEPTICR) Short Packet Interrupt Clear Position */ -#define DEVEPTICR_SHORTPACKETC (_U_(0x1) << DEVEPTICR_SHORTPACKETC_Pos) /**< (DEVEPTICR) Short Packet Interrupt Clear Mask */ -#define DEVEPTICR_Msk _U_(0xA3) /**< (DEVEPTICR) Register Mask */ - -/* CTRL mode */ -#define DEVEPTICR_CTRL_RXSTPIC_Pos 2 /**< (DEVEPTICR) Received SETUP Interrupt Clear Position */ -#define DEVEPTICR_CTRL_RXSTPIC (_U_(0x1) << DEVEPTICR_CTRL_RXSTPIC_Pos) /**< (DEVEPTICR) Received SETUP Interrupt Clear Mask */ -#define DEVEPTICR_CTRL_NAKOUTIC_Pos 3 /**< (DEVEPTICR) NAKed OUT Interrupt Clear Position */ -#define DEVEPTICR_CTRL_NAKOUTIC (_U_(0x1) << DEVEPTICR_CTRL_NAKOUTIC_Pos) /**< (DEVEPTICR) NAKed OUT Interrupt Clear Mask */ -#define DEVEPTICR_CTRL_NAKINIC_Pos 4 /**< (DEVEPTICR) NAKed IN Interrupt Clear Position */ -#define DEVEPTICR_CTRL_NAKINIC (_U_(0x1) << DEVEPTICR_CTRL_NAKINIC_Pos) /**< (DEVEPTICR) NAKed IN Interrupt Clear Mask */ -#define DEVEPTICR_CTRL_STALLEDIC_Pos 6 /**< (DEVEPTICR) STALLed Interrupt Clear Position */ -#define DEVEPTICR_CTRL_STALLEDIC (_U_(0x1) << DEVEPTICR_CTRL_STALLEDIC_Pos) /**< (DEVEPTICR) STALLed Interrupt Clear Mask */ -#define DEVEPTICR_CTRL_Msk _U_(0x5C) /**< (DEVEPTICR_CTRL) Register Mask */ - -/* ISO mode */ -#define DEVEPTICR_ISO_UNDERFIC_Pos 2 /**< (DEVEPTICR) Underflow Interrupt Clear Position */ -#define DEVEPTICR_ISO_UNDERFIC (_U_(0x1) << DEVEPTICR_ISO_UNDERFIC_Pos) /**< (DEVEPTICR) Underflow Interrupt Clear Mask */ -#define DEVEPTICR_ISO_HBISOINERRIC_Pos 3 /**< (DEVEPTICR) High Bandwidth Isochronous IN Underflow Error Interrupt Clear Position */ -#define DEVEPTICR_ISO_HBISOINERRIC (_U_(0x1) << DEVEPTICR_ISO_HBISOINERRIC_Pos) /**< (DEVEPTICR) High Bandwidth Isochronous IN Underflow Error Interrupt Clear Mask */ -#define DEVEPTICR_ISO_HBISOFLUSHIC_Pos 4 /**< (DEVEPTICR) High Bandwidth Isochronous IN Flush Interrupt Clear Position */ -#define DEVEPTICR_ISO_HBISOFLUSHIC (_U_(0x1) << DEVEPTICR_ISO_HBISOFLUSHIC_Pos) /**< (DEVEPTICR) High Bandwidth Isochronous IN Flush Interrupt Clear Mask */ -#define DEVEPTICR_ISO_CRCERRIC_Pos 6 /**< (DEVEPTICR) CRC Error Interrupt Clear Position */ -#define DEVEPTICR_ISO_CRCERRIC (_U_(0x1) << DEVEPTICR_ISO_CRCERRIC_Pos) /**< (DEVEPTICR) CRC Error Interrupt Clear Mask */ -#define DEVEPTICR_ISO_Msk _U_(0x5C) /**< (DEVEPTICR_ISO) Register Mask */ - -/* BLK mode */ -#define DEVEPTICR_BLK_RXSTPIC_Pos 2 /**< (DEVEPTICR) Received SETUP Interrupt Clear Position */ -#define DEVEPTICR_BLK_RXSTPIC (_U_(0x1) << DEVEPTICR_BLK_RXSTPIC_Pos) /**< (DEVEPTICR) Received SETUP Interrupt Clear Mask */ -#define DEVEPTICR_BLK_NAKOUTIC_Pos 3 /**< (DEVEPTICR) NAKed OUT Interrupt Clear Position */ -#define DEVEPTICR_BLK_NAKOUTIC (_U_(0x1) << DEVEPTICR_BLK_NAKOUTIC_Pos) /**< (DEVEPTICR) NAKed OUT Interrupt Clear Mask */ -#define DEVEPTICR_BLK_NAKINIC_Pos 4 /**< (DEVEPTICR) NAKed IN Interrupt Clear Position */ -#define DEVEPTICR_BLK_NAKINIC (_U_(0x1) << DEVEPTICR_BLK_NAKINIC_Pos) /**< (DEVEPTICR) NAKed IN Interrupt Clear Mask */ -#define DEVEPTICR_BLK_STALLEDIC_Pos 6 /**< (DEVEPTICR) STALLed Interrupt Clear Position */ -#define DEVEPTICR_BLK_STALLEDIC (_U_(0x1) << DEVEPTICR_BLK_STALLEDIC_Pos) /**< (DEVEPTICR) STALLed Interrupt Clear Mask */ -#define DEVEPTICR_BLK_Msk _U_(0x5C) /**< (DEVEPTICR_BLK) Register Mask */ - -/* INTRPT mode */ -#define DEVEPTICR_INTRPT_RXSTPIC_Pos 2 /**< (DEVEPTICR) Received SETUP Interrupt Clear Position */ -#define DEVEPTICR_INTRPT_RXSTPIC (_U_(0x1) << DEVEPTICR_INTRPT_RXSTPIC_Pos) /**< (DEVEPTICR) Received SETUP Interrupt Clear Mask */ -#define DEVEPTICR_INTRPT_NAKOUTIC_Pos 3 /**< (DEVEPTICR) NAKed OUT Interrupt Clear Position */ -#define DEVEPTICR_INTRPT_NAKOUTIC (_U_(0x1) << DEVEPTICR_INTRPT_NAKOUTIC_Pos) /**< (DEVEPTICR) NAKed OUT Interrupt Clear Mask */ -#define DEVEPTICR_INTRPT_NAKINIC_Pos 4 /**< (DEVEPTICR) NAKed IN Interrupt Clear Position */ -#define DEVEPTICR_INTRPT_NAKINIC (_U_(0x1) << DEVEPTICR_INTRPT_NAKINIC_Pos) /**< (DEVEPTICR) NAKed IN Interrupt Clear Mask */ -#define DEVEPTICR_INTRPT_STALLEDIC_Pos 6 /**< (DEVEPTICR) STALLed Interrupt Clear Position */ -#define DEVEPTICR_INTRPT_STALLEDIC (_U_(0x1) << DEVEPTICR_INTRPT_STALLEDIC_Pos) /**< (DEVEPTICR) STALLed Interrupt Clear Mask */ -#define DEVEPTICR_INTRPT_Msk _U_(0x5C) /**< (DEVEPTICR_INTRPT) Register Mask */ - - -/* -------- DEVEPTIFR : (USBHS Offset: 0x190) (/W 32) Device Endpoint Interrupt Set Register -------- */ - -#define DEVEPTIFR_OFFSET (0x190) /**< (DEVEPTIFR) Device Endpoint Interrupt Set Register Offset */ - -#define DEVEPTIFR_TXINIS_Pos 0 /**< (DEVEPTIFR) Transmitted IN Data Interrupt Set Position */ -#define DEVEPTIFR_TXINIS (_U_(0x1) << DEVEPTIFR_TXINIS_Pos) /**< (DEVEPTIFR) Transmitted IN Data Interrupt Set Mask */ -#define DEVEPTIFR_RXOUTIS_Pos 1 /**< (DEVEPTIFR) Received OUT Data Interrupt Set Position */ -#define DEVEPTIFR_RXOUTIS (_U_(0x1) << DEVEPTIFR_RXOUTIS_Pos) /**< (DEVEPTIFR) Received OUT Data Interrupt Set Mask */ -#define DEVEPTIFR_OVERFIS_Pos 5 /**< (DEVEPTIFR) Overflow Interrupt Set Position */ -#define DEVEPTIFR_OVERFIS (_U_(0x1) << DEVEPTIFR_OVERFIS_Pos) /**< (DEVEPTIFR) Overflow Interrupt Set Mask */ -#define DEVEPTIFR_SHORTPACKETS_Pos 7 /**< (DEVEPTIFR) Short Packet Interrupt Set Position */ -#define DEVEPTIFR_SHORTPACKETS (_U_(0x1) << DEVEPTIFR_SHORTPACKETS_Pos) /**< (DEVEPTIFR) Short Packet Interrupt Set Mask */ -#define DEVEPTIFR_NBUSYBKS_Pos 12 /**< (DEVEPTIFR) Number of Busy Banks Interrupt Set Position */ -#define DEVEPTIFR_NBUSYBKS (_U_(0x1) << DEVEPTIFR_NBUSYBKS_Pos) /**< (DEVEPTIFR) Number of Busy Banks Interrupt Set Mask */ -#define DEVEPTIFR_Msk _U_(0x10A3) /**< (DEVEPTIFR) Register Mask */ - -/* CTRL mode */ -#define DEVEPTIFR_CTRL_RXSTPIS_Pos 2 /**< (DEVEPTIFR) Received SETUP Interrupt Set Position */ -#define DEVEPTIFR_CTRL_RXSTPIS (_U_(0x1) << DEVEPTIFR_CTRL_RXSTPIS_Pos) /**< (DEVEPTIFR) Received SETUP Interrupt Set Mask */ -#define DEVEPTIFR_CTRL_NAKOUTIS_Pos 3 /**< (DEVEPTIFR) NAKed OUT Interrupt Set Position */ -#define DEVEPTIFR_CTRL_NAKOUTIS (_U_(0x1) << DEVEPTIFR_CTRL_NAKOUTIS_Pos) /**< (DEVEPTIFR) NAKed OUT Interrupt Set Mask */ -#define DEVEPTIFR_CTRL_NAKINIS_Pos 4 /**< (DEVEPTIFR) NAKed IN Interrupt Set Position */ -#define DEVEPTIFR_CTRL_NAKINIS (_U_(0x1) << DEVEPTIFR_CTRL_NAKINIS_Pos) /**< (DEVEPTIFR) NAKed IN Interrupt Set Mask */ -#define DEVEPTIFR_CTRL_STALLEDIS_Pos 6 /**< (DEVEPTIFR) STALLed Interrupt Set Position */ -#define DEVEPTIFR_CTRL_STALLEDIS (_U_(0x1) << DEVEPTIFR_CTRL_STALLEDIS_Pos) /**< (DEVEPTIFR) STALLed Interrupt Set Mask */ -#define DEVEPTIFR_CTRL_Msk _U_(0x5C) /**< (DEVEPTIFR_CTRL) Register Mask */ - -/* ISO mode */ -#define DEVEPTIFR_ISO_UNDERFIS_Pos 2 /**< (DEVEPTIFR) Underflow Interrupt Set Position */ -#define DEVEPTIFR_ISO_UNDERFIS (_U_(0x1) << DEVEPTIFR_ISO_UNDERFIS_Pos) /**< (DEVEPTIFR) Underflow Interrupt Set Mask */ -#define DEVEPTIFR_ISO_HBISOINERRIS_Pos 3 /**< (DEVEPTIFR) High Bandwidth Isochronous IN Underflow Error Interrupt Set Position */ -#define DEVEPTIFR_ISO_HBISOINERRIS (_U_(0x1) << DEVEPTIFR_ISO_HBISOINERRIS_Pos) /**< (DEVEPTIFR) High Bandwidth Isochronous IN Underflow Error Interrupt Set Mask */ -#define DEVEPTIFR_ISO_HBISOFLUSHIS_Pos 4 /**< (DEVEPTIFR) High Bandwidth Isochronous IN Flush Interrupt Set Position */ -#define DEVEPTIFR_ISO_HBISOFLUSHIS (_U_(0x1) << DEVEPTIFR_ISO_HBISOFLUSHIS_Pos) /**< (DEVEPTIFR) High Bandwidth Isochronous IN Flush Interrupt Set Mask */ -#define DEVEPTIFR_ISO_CRCERRIS_Pos 6 /**< (DEVEPTIFR) CRC Error Interrupt Set Position */ -#define DEVEPTIFR_ISO_CRCERRIS (_U_(0x1) << DEVEPTIFR_ISO_CRCERRIS_Pos) /**< (DEVEPTIFR) CRC Error Interrupt Set Mask */ -#define DEVEPTIFR_ISO_Msk _U_(0x5C) /**< (DEVEPTIFR_ISO) Register Mask */ - -/* BLK mode */ -#define DEVEPTIFR_BLK_RXSTPIS_Pos 2 /**< (DEVEPTIFR) Received SETUP Interrupt Set Position */ -#define DEVEPTIFR_BLK_RXSTPIS (_U_(0x1) << DEVEPTIFR_BLK_RXSTPIS_Pos) /**< (DEVEPTIFR) Received SETUP Interrupt Set Mask */ -#define DEVEPTIFR_BLK_NAKOUTIS_Pos 3 /**< (DEVEPTIFR) NAKed OUT Interrupt Set Position */ -#define DEVEPTIFR_BLK_NAKOUTIS (_U_(0x1) << DEVEPTIFR_BLK_NAKOUTIS_Pos) /**< (DEVEPTIFR) NAKed OUT Interrupt Set Mask */ -#define DEVEPTIFR_BLK_NAKINIS_Pos 4 /**< (DEVEPTIFR) NAKed IN Interrupt Set Position */ -#define DEVEPTIFR_BLK_NAKINIS (_U_(0x1) << DEVEPTIFR_BLK_NAKINIS_Pos) /**< (DEVEPTIFR) NAKed IN Interrupt Set Mask */ -#define DEVEPTIFR_BLK_STALLEDIS_Pos 6 /**< (DEVEPTIFR) STALLed Interrupt Set Position */ -#define DEVEPTIFR_BLK_STALLEDIS (_U_(0x1) << DEVEPTIFR_BLK_STALLEDIS_Pos) /**< (DEVEPTIFR) STALLed Interrupt Set Mask */ -#define DEVEPTIFR_BLK_Msk _U_(0x5C) /**< (DEVEPTIFR_BLK) Register Mask */ - -/* INTRPT mode */ -#define DEVEPTIFR_INTRPT_RXSTPIS_Pos 2 /**< (DEVEPTIFR) Received SETUP Interrupt Set Position */ -#define DEVEPTIFR_INTRPT_RXSTPIS (_U_(0x1) << DEVEPTIFR_INTRPT_RXSTPIS_Pos) /**< (DEVEPTIFR) Received SETUP Interrupt Set Mask */ -#define DEVEPTIFR_INTRPT_NAKOUTIS_Pos 3 /**< (DEVEPTIFR) NAKed OUT Interrupt Set Position */ -#define DEVEPTIFR_INTRPT_NAKOUTIS (_U_(0x1) << DEVEPTIFR_INTRPT_NAKOUTIS_Pos) /**< (DEVEPTIFR) NAKed OUT Interrupt Set Mask */ -#define DEVEPTIFR_INTRPT_NAKINIS_Pos 4 /**< (DEVEPTIFR) NAKed IN Interrupt Set Position */ -#define DEVEPTIFR_INTRPT_NAKINIS (_U_(0x1) << DEVEPTIFR_INTRPT_NAKINIS_Pos) /**< (DEVEPTIFR) NAKed IN Interrupt Set Mask */ -#define DEVEPTIFR_INTRPT_STALLEDIS_Pos 6 /**< (DEVEPTIFR) STALLed Interrupt Set Position */ -#define DEVEPTIFR_INTRPT_STALLEDIS (_U_(0x1) << DEVEPTIFR_INTRPT_STALLEDIS_Pos) /**< (DEVEPTIFR) STALLed Interrupt Set Mask */ -#define DEVEPTIFR_INTRPT_Msk _U_(0x5C) /**< (DEVEPTIFR_INTRPT) Register Mask */ - - -/* -------- DEVEPTIMR : (USBHS Offset: 0x1c0) (R/ 32) Device Endpoint Interrupt Mask Register -------- */ - -#define DEVEPTIMR_OFFSET (0x1C0) /**< (DEVEPTIMR) Device Endpoint Interrupt Mask Register Offset */ - -#define DEVEPTIMR_TXINE_Pos 0 /**< (DEVEPTIMR) Transmitted IN Data Interrupt Position */ -#define DEVEPTIMR_TXINE (_U_(0x1) << DEVEPTIMR_TXINE_Pos) /**< (DEVEPTIMR) Transmitted IN Data Interrupt Mask */ -#define DEVEPTIMR_RXOUTE_Pos 1 /**< (DEVEPTIMR) Received OUT Data Interrupt Position */ -#define DEVEPTIMR_RXOUTE (_U_(0x1) << DEVEPTIMR_RXOUTE_Pos) /**< (DEVEPTIMR) Received OUT Data Interrupt Mask */ -#define DEVEPTIMR_OVERFE_Pos 5 /**< (DEVEPTIMR) Overflow Interrupt Position */ -#define DEVEPTIMR_OVERFE (_U_(0x1) << DEVEPTIMR_OVERFE_Pos) /**< (DEVEPTIMR) Overflow Interrupt Mask */ -#define DEVEPTIMR_SHORTPACKETE_Pos 7 /**< (DEVEPTIMR) Short Packet Interrupt Position */ -#define DEVEPTIMR_SHORTPACKETE (_U_(0x1) << DEVEPTIMR_SHORTPACKETE_Pos) /**< (DEVEPTIMR) Short Packet Interrupt Mask */ -#define DEVEPTIMR_NBUSYBKE_Pos 12 /**< (DEVEPTIMR) Number of Busy Banks Interrupt Position */ -#define DEVEPTIMR_NBUSYBKE (_U_(0x1) << DEVEPTIMR_NBUSYBKE_Pos) /**< (DEVEPTIMR) Number of Busy Banks Interrupt Mask */ -#define DEVEPTIMR_KILLBK_Pos 13 /**< (DEVEPTIMR) Kill IN Bank Position */ -#define DEVEPTIMR_KILLBK (_U_(0x1) << DEVEPTIMR_KILLBK_Pos) /**< (DEVEPTIMR) Kill IN Bank Mask */ -#define DEVEPTIMR_FIFOCON_Pos 14 /**< (DEVEPTIMR) FIFO Control Position */ -#define DEVEPTIMR_FIFOCON (_U_(0x1) << DEVEPTIMR_FIFOCON_Pos) /**< (DEVEPTIMR) FIFO Control Mask */ -#define DEVEPTIMR_EPDISHDMA_Pos 16 /**< (DEVEPTIMR) Endpoint Interrupts Disable HDMA Request Position */ -#define DEVEPTIMR_EPDISHDMA (_U_(0x1) << DEVEPTIMR_EPDISHDMA_Pos) /**< (DEVEPTIMR) Endpoint Interrupts Disable HDMA Request Mask */ -#define DEVEPTIMR_RSTDT_Pos 18 /**< (DEVEPTIMR) Reset Data Toggle Position */ -#define DEVEPTIMR_RSTDT (_U_(0x1) << DEVEPTIMR_RSTDT_Pos) /**< (DEVEPTIMR) Reset Data Toggle Mask */ -#define DEVEPTIMR_Msk _U_(0x570A3) /**< (DEVEPTIMR) Register Mask */ - -/* CTRL mode */ -#define DEVEPTIMR_CTRL_RXSTPE_Pos 2 /**< (DEVEPTIMR) Received SETUP Interrupt Position */ -#define DEVEPTIMR_CTRL_RXSTPE (_U_(0x1) << DEVEPTIMR_CTRL_RXSTPE_Pos) /**< (DEVEPTIMR) Received SETUP Interrupt Mask */ -#define DEVEPTIMR_CTRL_NAKOUTE_Pos 3 /**< (DEVEPTIMR) NAKed OUT Interrupt Position */ -#define DEVEPTIMR_CTRL_NAKOUTE (_U_(0x1) << DEVEPTIMR_CTRL_NAKOUTE_Pos) /**< (DEVEPTIMR) NAKed OUT Interrupt Mask */ -#define DEVEPTIMR_CTRL_NAKINE_Pos 4 /**< (DEVEPTIMR) NAKed IN Interrupt Position */ -#define DEVEPTIMR_CTRL_NAKINE (_U_(0x1) << DEVEPTIMR_CTRL_NAKINE_Pos) /**< (DEVEPTIMR) NAKed IN Interrupt Mask */ -#define DEVEPTIMR_CTRL_STALLEDE_Pos 6 /**< (DEVEPTIMR) STALLed Interrupt Position */ -#define DEVEPTIMR_CTRL_STALLEDE (_U_(0x1) << DEVEPTIMR_CTRL_STALLEDE_Pos) /**< (DEVEPTIMR) STALLed Interrupt Mask */ -#define DEVEPTIMR_CTRL_NYETDIS_Pos 17 /**< (DEVEPTIMR) NYET Token Disable Position */ -#define DEVEPTIMR_CTRL_NYETDIS (_U_(0x1) << DEVEPTIMR_CTRL_NYETDIS_Pos) /**< (DEVEPTIMR) NYET Token Disable Mask */ -#define DEVEPTIMR_CTRL_STALLRQ_Pos 19 /**< (DEVEPTIMR) STALL Request Position */ -#define DEVEPTIMR_CTRL_STALLRQ (_U_(0x1) << DEVEPTIMR_CTRL_STALLRQ_Pos) /**< (DEVEPTIMR) STALL Request Mask */ -#define DEVEPTIMR_CTRL_Msk _U_(0xA005C) /**< (DEVEPTIMR_CTRL) Register Mask */ - -/* ISO mode */ -#define DEVEPTIMR_ISO_UNDERFE_Pos 2 /**< (DEVEPTIMR) Underflow Interrupt Position */ -#define DEVEPTIMR_ISO_UNDERFE (_U_(0x1) << DEVEPTIMR_ISO_UNDERFE_Pos) /**< (DEVEPTIMR) Underflow Interrupt Mask */ -#define DEVEPTIMR_ISO_HBISOINERRE_Pos 3 /**< (DEVEPTIMR) High Bandwidth Isochronous IN Underflow Error Interrupt Position */ -#define DEVEPTIMR_ISO_HBISOINERRE (_U_(0x1) << DEVEPTIMR_ISO_HBISOINERRE_Pos) /**< (DEVEPTIMR) High Bandwidth Isochronous IN Underflow Error Interrupt Mask */ -#define DEVEPTIMR_ISO_HBISOFLUSHE_Pos 4 /**< (DEVEPTIMR) High Bandwidth Isochronous IN Flush Interrupt Position */ -#define DEVEPTIMR_ISO_HBISOFLUSHE (_U_(0x1) << DEVEPTIMR_ISO_HBISOFLUSHE_Pos) /**< (DEVEPTIMR) High Bandwidth Isochronous IN Flush Interrupt Mask */ -#define DEVEPTIMR_ISO_CRCERRE_Pos 6 /**< (DEVEPTIMR) CRC Error Interrupt Position */ -#define DEVEPTIMR_ISO_CRCERRE (_U_(0x1) << DEVEPTIMR_ISO_CRCERRE_Pos) /**< (DEVEPTIMR) CRC Error Interrupt Mask */ -#define DEVEPTIMR_ISO_MDATAE_Pos 8 /**< (DEVEPTIMR) MData Interrupt Position */ -#define DEVEPTIMR_ISO_MDATAE (_U_(0x1) << DEVEPTIMR_ISO_MDATAE_Pos) /**< (DEVEPTIMR) MData Interrupt Mask */ -#define DEVEPTIMR_ISO_DATAXE_Pos 9 /**< (DEVEPTIMR) DataX Interrupt Position */ -#define DEVEPTIMR_ISO_DATAXE (_U_(0x1) << DEVEPTIMR_ISO_DATAXE_Pos) /**< (DEVEPTIMR) DataX Interrupt Mask */ -#define DEVEPTIMR_ISO_ERRORTRANSE_Pos 10 /**< (DEVEPTIMR) Transaction Error Interrupt Position */ -#define DEVEPTIMR_ISO_ERRORTRANSE (_U_(0x1) << DEVEPTIMR_ISO_ERRORTRANSE_Pos) /**< (DEVEPTIMR) Transaction Error Interrupt Mask */ -#define DEVEPTIMR_ISO_Msk _U_(0x75C) /**< (DEVEPTIMR_ISO) Register Mask */ - -/* BLK mode */ -#define DEVEPTIMR_BLK_RXSTPE_Pos 2 /**< (DEVEPTIMR) Received SETUP Interrupt Position */ -#define DEVEPTIMR_BLK_RXSTPE (_U_(0x1) << DEVEPTIMR_BLK_RXSTPE_Pos) /**< (DEVEPTIMR) Received SETUP Interrupt Mask */ -#define DEVEPTIMR_BLK_NAKOUTE_Pos 3 /**< (DEVEPTIMR) NAKed OUT Interrupt Position */ -#define DEVEPTIMR_BLK_NAKOUTE (_U_(0x1) << DEVEPTIMR_BLK_NAKOUTE_Pos) /**< (DEVEPTIMR) NAKed OUT Interrupt Mask */ -#define DEVEPTIMR_BLK_NAKINE_Pos 4 /**< (DEVEPTIMR) NAKed IN Interrupt Position */ -#define DEVEPTIMR_BLK_NAKINE (_U_(0x1) << DEVEPTIMR_BLK_NAKINE_Pos) /**< (DEVEPTIMR) NAKed IN Interrupt Mask */ -#define DEVEPTIMR_BLK_STALLEDE_Pos 6 /**< (DEVEPTIMR) STALLed Interrupt Position */ -#define DEVEPTIMR_BLK_STALLEDE (_U_(0x1) << DEVEPTIMR_BLK_STALLEDE_Pos) /**< (DEVEPTIMR) STALLed Interrupt Mask */ -#define DEVEPTIMR_BLK_NYETDIS_Pos 17 /**< (DEVEPTIMR) NYET Token Disable Position */ -#define DEVEPTIMR_BLK_NYETDIS (_U_(0x1) << DEVEPTIMR_BLK_NYETDIS_Pos) /**< (DEVEPTIMR) NYET Token Disable Mask */ -#define DEVEPTIMR_BLK_STALLRQ_Pos 19 /**< (DEVEPTIMR) STALL Request Position */ -#define DEVEPTIMR_BLK_STALLRQ (_U_(0x1) << DEVEPTIMR_BLK_STALLRQ_Pos) /**< (DEVEPTIMR) STALL Request Mask */ -#define DEVEPTIMR_BLK_Msk _U_(0xA005C) /**< (DEVEPTIMR_BLK) Register Mask */ - -/* INTRPT mode */ -#define DEVEPTIMR_INTRPT_RXSTPE_Pos 2 /**< (DEVEPTIMR) Received SETUP Interrupt Position */ -#define DEVEPTIMR_INTRPT_RXSTPE (_U_(0x1) << DEVEPTIMR_INTRPT_RXSTPE_Pos) /**< (DEVEPTIMR) Received SETUP Interrupt Mask */ -#define DEVEPTIMR_INTRPT_NAKOUTE_Pos 3 /**< (DEVEPTIMR) NAKed OUT Interrupt Position */ -#define DEVEPTIMR_INTRPT_NAKOUTE (_U_(0x1) << DEVEPTIMR_INTRPT_NAKOUTE_Pos) /**< (DEVEPTIMR) NAKed OUT Interrupt Mask */ -#define DEVEPTIMR_INTRPT_NAKINE_Pos 4 /**< (DEVEPTIMR) NAKed IN Interrupt Position */ -#define DEVEPTIMR_INTRPT_NAKINE (_U_(0x1) << DEVEPTIMR_INTRPT_NAKINE_Pos) /**< (DEVEPTIMR) NAKed IN Interrupt Mask */ -#define DEVEPTIMR_INTRPT_STALLEDE_Pos 6 /**< (DEVEPTIMR) STALLed Interrupt Position */ -#define DEVEPTIMR_INTRPT_STALLEDE (_U_(0x1) << DEVEPTIMR_INTRPT_STALLEDE_Pos) /**< (DEVEPTIMR) STALLed Interrupt Mask */ -#define DEVEPTIMR_INTRPT_NYETDIS_Pos 17 /**< (DEVEPTIMR) NYET Token Disable Position */ -#define DEVEPTIMR_INTRPT_NYETDIS (_U_(0x1) << DEVEPTIMR_INTRPT_NYETDIS_Pos) /**< (DEVEPTIMR) NYET Token Disable Mask */ -#define DEVEPTIMR_INTRPT_STALLRQ_Pos 19 /**< (DEVEPTIMR) STALL Request Position */ -#define DEVEPTIMR_INTRPT_STALLRQ (_U_(0x1) << DEVEPTIMR_INTRPT_STALLRQ_Pos) /**< (DEVEPTIMR) STALL Request Mask */ -#define DEVEPTIMR_INTRPT_Msk _U_(0xA005C) /**< (DEVEPTIMR_INTRPT) Register Mask */ - - -/* -------- DEVEPTIER : (USBHS Offset: 0x1f0) (/W 32) Device Endpoint Interrupt Enable Register -------- */ - -#define DEVEPTIER_OFFSET (0x1F0) /**< (DEVEPTIER) Device Endpoint Interrupt Enable Register Offset */ - -#define DEVEPTIER_TXINES_Pos 0 /**< (DEVEPTIER) Transmitted IN Data Interrupt Enable Position */ -#define DEVEPTIER_TXINES (_U_(0x1) << DEVEPTIER_TXINES_Pos) /**< (DEVEPTIER) Transmitted IN Data Interrupt Enable Mask */ -#define DEVEPTIER_RXOUTES_Pos 1 /**< (DEVEPTIER) Received OUT Data Interrupt Enable Position */ -#define DEVEPTIER_RXOUTES (_U_(0x1) << DEVEPTIER_RXOUTES_Pos) /**< (DEVEPTIER) Received OUT Data Interrupt Enable Mask */ -#define DEVEPTIER_OVERFES_Pos 5 /**< (DEVEPTIER) Overflow Interrupt Enable Position */ -#define DEVEPTIER_OVERFES (_U_(0x1) << DEVEPTIER_OVERFES_Pos) /**< (DEVEPTIER) Overflow Interrupt Enable Mask */ -#define DEVEPTIER_SHORTPACKETES_Pos 7 /**< (DEVEPTIER) Short Packet Interrupt Enable Position */ -#define DEVEPTIER_SHORTPACKETES (_U_(0x1) << DEVEPTIER_SHORTPACKETES_Pos) /**< (DEVEPTIER) Short Packet Interrupt Enable Mask */ -#define DEVEPTIER_NBUSYBKES_Pos 12 /**< (DEVEPTIER) Number of Busy Banks Interrupt Enable Position */ -#define DEVEPTIER_NBUSYBKES (_U_(0x1) << DEVEPTIER_NBUSYBKES_Pos) /**< (DEVEPTIER) Number of Busy Banks Interrupt Enable Mask */ -#define DEVEPTIER_KILLBKS_Pos 13 /**< (DEVEPTIER) Kill IN Bank Position */ -#define DEVEPTIER_KILLBKS (_U_(0x1) << DEVEPTIER_KILLBKS_Pos) /**< (DEVEPTIER) Kill IN Bank Mask */ -#define DEVEPTIER_FIFOCONS_Pos 14 /**< (DEVEPTIER) FIFO Control Position */ -#define DEVEPTIER_FIFOCONS (_U_(0x1) << DEVEPTIER_FIFOCONS_Pos) /**< (DEVEPTIER) FIFO Control Mask */ -#define DEVEPTIER_EPDISHDMAS_Pos 16 /**< (DEVEPTIER) Endpoint Interrupts Disable HDMA Request Enable Position */ -#define DEVEPTIER_EPDISHDMAS (_U_(0x1) << DEVEPTIER_EPDISHDMAS_Pos) /**< (DEVEPTIER) Endpoint Interrupts Disable HDMA Request Enable Mask */ -#define DEVEPTIER_RSTDTS_Pos 18 /**< (DEVEPTIER) Reset Data Toggle Enable Position */ -#define DEVEPTIER_RSTDTS (_U_(0x1) << DEVEPTIER_RSTDTS_Pos) /**< (DEVEPTIER) Reset Data Toggle Enable Mask */ -#define DEVEPTIER_Msk _U_(0x570A3) /**< (DEVEPTIER) Register Mask */ - -/* CTRL mode */ -#define DEVEPTIER_CTRL_RXSTPES_Pos 2 /**< (DEVEPTIER) Received SETUP Interrupt Enable Position */ -#define DEVEPTIER_CTRL_RXSTPES (_U_(0x1) << DEVEPTIER_CTRL_RXSTPES_Pos) /**< (DEVEPTIER) Received SETUP Interrupt Enable Mask */ -#define DEVEPTIER_CTRL_NAKOUTES_Pos 3 /**< (DEVEPTIER) NAKed OUT Interrupt Enable Position */ -#define DEVEPTIER_CTRL_NAKOUTES (_U_(0x1) << DEVEPTIER_CTRL_NAKOUTES_Pos) /**< (DEVEPTIER) NAKed OUT Interrupt Enable Mask */ -#define DEVEPTIER_CTRL_NAKINES_Pos 4 /**< (DEVEPTIER) NAKed IN Interrupt Enable Position */ -#define DEVEPTIER_CTRL_NAKINES (_U_(0x1) << DEVEPTIER_CTRL_NAKINES_Pos) /**< (DEVEPTIER) NAKed IN Interrupt Enable Mask */ -#define DEVEPTIER_CTRL_STALLEDES_Pos 6 /**< (DEVEPTIER) STALLed Interrupt Enable Position */ -#define DEVEPTIER_CTRL_STALLEDES (_U_(0x1) << DEVEPTIER_CTRL_STALLEDES_Pos) /**< (DEVEPTIER) STALLed Interrupt Enable Mask */ -#define DEVEPTIER_CTRL_NYETDISS_Pos 17 /**< (DEVEPTIER) NYET Token Disable Enable Position */ -#define DEVEPTIER_CTRL_NYETDISS (_U_(0x1) << DEVEPTIER_CTRL_NYETDISS_Pos) /**< (DEVEPTIER) NYET Token Disable Enable Mask */ -#define DEVEPTIER_CTRL_STALLRQS_Pos 19 /**< (DEVEPTIER) STALL Request Enable Position */ -#define DEVEPTIER_CTRL_STALLRQS (_U_(0x1) << DEVEPTIER_CTRL_STALLRQS_Pos) /**< (DEVEPTIER) STALL Request Enable Mask */ -#define DEVEPTIER_CTRL_Msk _U_(0xA005C) /**< (DEVEPTIER_CTRL) Register Mask */ - -/* ISO mode */ -#define DEVEPTIER_ISO_UNDERFES_Pos 2 /**< (DEVEPTIER) Underflow Interrupt Enable Position */ -#define DEVEPTIER_ISO_UNDERFES (_U_(0x1) << DEVEPTIER_ISO_UNDERFES_Pos) /**< (DEVEPTIER) Underflow Interrupt Enable Mask */ -#define DEVEPTIER_ISO_HBISOINERRES_Pos 3 /**< (DEVEPTIER) High Bandwidth Isochronous IN Underflow Error Interrupt Enable Position */ -#define DEVEPTIER_ISO_HBISOINERRES (_U_(0x1) << DEVEPTIER_ISO_HBISOINERRES_Pos) /**< (DEVEPTIER) High Bandwidth Isochronous IN Underflow Error Interrupt Enable Mask */ -#define DEVEPTIER_ISO_HBISOFLUSHES_Pos 4 /**< (DEVEPTIER) High Bandwidth Isochronous IN Flush Interrupt Enable Position */ -#define DEVEPTIER_ISO_HBISOFLUSHES (_U_(0x1) << DEVEPTIER_ISO_HBISOFLUSHES_Pos) /**< (DEVEPTIER) High Bandwidth Isochronous IN Flush Interrupt Enable Mask */ -#define DEVEPTIER_ISO_CRCERRES_Pos 6 /**< (DEVEPTIER) CRC Error Interrupt Enable Position */ -#define DEVEPTIER_ISO_CRCERRES (_U_(0x1) << DEVEPTIER_ISO_CRCERRES_Pos) /**< (DEVEPTIER) CRC Error Interrupt Enable Mask */ -#define DEVEPTIER_ISO_MDATAES_Pos 8 /**< (DEVEPTIER) MData Interrupt Enable Position */ -#define DEVEPTIER_ISO_MDATAES (_U_(0x1) << DEVEPTIER_ISO_MDATAES_Pos) /**< (DEVEPTIER) MData Interrupt Enable Mask */ -#define DEVEPTIER_ISO_DATAXES_Pos 9 /**< (DEVEPTIER) DataX Interrupt Enable Position */ -#define DEVEPTIER_ISO_DATAXES (_U_(0x1) << DEVEPTIER_ISO_DATAXES_Pos) /**< (DEVEPTIER) DataX Interrupt Enable Mask */ -#define DEVEPTIER_ISO_ERRORTRANSES_Pos 10 /**< (DEVEPTIER) Transaction Error Interrupt Enable Position */ -#define DEVEPTIER_ISO_ERRORTRANSES (_U_(0x1) << DEVEPTIER_ISO_ERRORTRANSES_Pos) /**< (DEVEPTIER) Transaction Error Interrupt Enable Mask */ -#define DEVEPTIER_ISO_Msk _U_(0x75C) /**< (DEVEPTIER_ISO) Register Mask */ - -/* BLK mode */ -#define DEVEPTIER_BLK_RXSTPES_Pos 2 /**< (DEVEPTIER) Received SETUP Interrupt Enable Position */ -#define DEVEPTIER_BLK_RXSTPES (_U_(0x1) << DEVEPTIER_BLK_RXSTPES_Pos) /**< (DEVEPTIER) Received SETUP Interrupt Enable Mask */ -#define DEVEPTIER_BLK_NAKOUTES_Pos 3 /**< (DEVEPTIER) NAKed OUT Interrupt Enable Position */ -#define DEVEPTIER_BLK_NAKOUTES (_U_(0x1) << DEVEPTIER_BLK_NAKOUTES_Pos) /**< (DEVEPTIER) NAKed OUT Interrupt Enable Mask */ -#define DEVEPTIER_BLK_NAKINES_Pos 4 /**< (DEVEPTIER) NAKed IN Interrupt Enable Position */ -#define DEVEPTIER_BLK_NAKINES (_U_(0x1) << DEVEPTIER_BLK_NAKINES_Pos) /**< (DEVEPTIER) NAKed IN Interrupt Enable Mask */ -#define DEVEPTIER_BLK_STALLEDES_Pos 6 /**< (DEVEPTIER) STALLed Interrupt Enable Position */ -#define DEVEPTIER_BLK_STALLEDES (_U_(0x1) << DEVEPTIER_BLK_STALLEDES_Pos) /**< (DEVEPTIER) STALLed Interrupt Enable Mask */ -#define DEVEPTIER_BLK_NYETDISS_Pos 17 /**< (DEVEPTIER) NYET Token Disable Enable Position */ -#define DEVEPTIER_BLK_NYETDISS (_U_(0x1) << DEVEPTIER_BLK_NYETDISS_Pos) /**< (DEVEPTIER) NYET Token Disable Enable Mask */ -#define DEVEPTIER_BLK_STALLRQS_Pos 19 /**< (DEVEPTIER) STALL Request Enable Position */ -#define DEVEPTIER_BLK_STALLRQS (_U_(0x1) << DEVEPTIER_BLK_STALLRQS_Pos) /**< (DEVEPTIER) STALL Request Enable Mask */ -#define DEVEPTIER_BLK_Msk _U_(0xA005C) /**< (DEVEPTIER_BLK) Register Mask */ - -/* INTRPT mode */ -#define DEVEPTIER_INTRPT_RXSTPES_Pos 2 /**< (DEVEPTIER) Received SETUP Interrupt Enable Position */ -#define DEVEPTIER_INTRPT_RXSTPES (_U_(0x1) << DEVEPTIER_INTRPT_RXSTPES_Pos) /**< (DEVEPTIER) Received SETUP Interrupt Enable Mask */ -#define DEVEPTIER_INTRPT_NAKOUTES_Pos 3 /**< (DEVEPTIER) NAKed OUT Interrupt Enable Position */ -#define DEVEPTIER_INTRPT_NAKOUTES (_U_(0x1) << DEVEPTIER_INTRPT_NAKOUTES_Pos) /**< (DEVEPTIER) NAKed OUT Interrupt Enable Mask */ -#define DEVEPTIER_INTRPT_NAKINES_Pos 4 /**< (DEVEPTIER) NAKed IN Interrupt Enable Position */ -#define DEVEPTIER_INTRPT_NAKINES (_U_(0x1) << DEVEPTIER_INTRPT_NAKINES_Pos) /**< (DEVEPTIER) NAKed IN Interrupt Enable Mask */ -#define DEVEPTIER_INTRPT_STALLEDES_Pos 6 /**< (DEVEPTIER) STALLed Interrupt Enable Position */ -#define DEVEPTIER_INTRPT_STALLEDES (_U_(0x1) << DEVEPTIER_INTRPT_STALLEDES_Pos) /**< (DEVEPTIER) STALLed Interrupt Enable Mask */ -#define DEVEPTIER_INTRPT_NYETDISS_Pos 17 /**< (DEVEPTIER) NYET Token Disable Enable Position */ -#define DEVEPTIER_INTRPT_NYETDISS (_U_(0x1) << DEVEPTIER_INTRPT_NYETDISS_Pos) /**< (DEVEPTIER) NYET Token Disable Enable Mask */ -#define DEVEPTIER_INTRPT_STALLRQS_Pos 19 /**< (DEVEPTIER) STALL Request Enable Position */ -#define DEVEPTIER_INTRPT_STALLRQS (_U_(0x1) << DEVEPTIER_INTRPT_STALLRQS_Pos) /**< (DEVEPTIER) STALL Request Enable Mask */ -#define DEVEPTIER_INTRPT_Msk _U_(0xA005C) /**< (DEVEPTIER_INTRPT) Register Mask */ - - -/* -------- DEVEPTIDR : (USBHS Offset: 0x220) (/W 32) Device Endpoint Interrupt Disable Register -------- */ - -#define DEVEPTIDR_OFFSET (0x220) /**< (DEVEPTIDR) Device Endpoint Interrupt Disable Register Offset */ - -#define DEVEPTIDR_TXINEC_Pos 0 /**< (DEVEPTIDR) Transmitted IN Interrupt Clear Position */ -#define DEVEPTIDR_TXINEC (_U_(0x1) << DEVEPTIDR_TXINEC_Pos) /**< (DEVEPTIDR) Transmitted IN Interrupt Clear Mask */ -#define DEVEPTIDR_RXOUTEC_Pos 1 /**< (DEVEPTIDR) Received OUT Data Interrupt Clear Position */ -#define DEVEPTIDR_RXOUTEC (_U_(0x1) << DEVEPTIDR_RXOUTEC_Pos) /**< (DEVEPTIDR) Received OUT Data Interrupt Clear Mask */ -#define DEVEPTIDR_OVERFEC_Pos 5 /**< (DEVEPTIDR) Overflow Interrupt Clear Position */ -#define DEVEPTIDR_OVERFEC (_U_(0x1) << DEVEPTIDR_OVERFEC_Pos) /**< (DEVEPTIDR) Overflow Interrupt Clear Mask */ -#define DEVEPTIDR_SHORTPACKETEC_Pos 7 /**< (DEVEPTIDR) Shortpacket Interrupt Clear Position */ -#define DEVEPTIDR_SHORTPACKETEC (_U_(0x1) << DEVEPTIDR_SHORTPACKETEC_Pos) /**< (DEVEPTIDR) Shortpacket Interrupt Clear Mask */ -#define DEVEPTIDR_NBUSYBKEC_Pos 12 /**< (DEVEPTIDR) Number of Busy Banks Interrupt Clear Position */ -#define DEVEPTIDR_NBUSYBKEC (_U_(0x1) << DEVEPTIDR_NBUSYBKEC_Pos) /**< (DEVEPTIDR) Number of Busy Banks Interrupt Clear Mask */ -#define DEVEPTIDR_FIFOCONC_Pos 14 /**< (DEVEPTIDR) FIFO Control Clear Position */ -#define DEVEPTIDR_FIFOCONC (_U_(0x1) << DEVEPTIDR_FIFOCONC_Pos) /**< (DEVEPTIDR) FIFO Control Clear Mask */ -#define DEVEPTIDR_EPDISHDMAC_Pos 16 /**< (DEVEPTIDR) Endpoint Interrupts Disable HDMA Request Clear Position */ -#define DEVEPTIDR_EPDISHDMAC (_U_(0x1) << DEVEPTIDR_EPDISHDMAC_Pos) /**< (DEVEPTIDR) Endpoint Interrupts Disable HDMA Request Clear Mask */ -#define DEVEPTIDR_Msk _U_(0x150A3) /**< (DEVEPTIDR) Register Mask */ - -/* CTRL mode */ -#define DEVEPTIDR_CTRL_RXSTPEC_Pos 2 /**< (DEVEPTIDR) Received SETUP Interrupt Clear Position */ -#define DEVEPTIDR_CTRL_RXSTPEC (_U_(0x1) << DEVEPTIDR_CTRL_RXSTPEC_Pos) /**< (DEVEPTIDR) Received SETUP Interrupt Clear Mask */ -#define DEVEPTIDR_CTRL_NAKOUTEC_Pos 3 /**< (DEVEPTIDR) NAKed OUT Interrupt Clear Position */ -#define DEVEPTIDR_CTRL_NAKOUTEC (_U_(0x1) << DEVEPTIDR_CTRL_NAKOUTEC_Pos) /**< (DEVEPTIDR) NAKed OUT Interrupt Clear Mask */ -#define DEVEPTIDR_CTRL_NAKINEC_Pos 4 /**< (DEVEPTIDR) NAKed IN Interrupt Clear Position */ -#define DEVEPTIDR_CTRL_NAKINEC (_U_(0x1) << DEVEPTIDR_CTRL_NAKINEC_Pos) /**< (DEVEPTIDR) NAKed IN Interrupt Clear Mask */ -#define DEVEPTIDR_CTRL_STALLEDEC_Pos 6 /**< (DEVEPTIDR) STALLed Interrupt Clear Position */ -#define DEVEPTIDR_CTRL_STALLEDEC (_U_(0x1) << DEVEPTIDR_CTRL_STALLEDEC_Pos) /**< (DEVEPTIDR) STALLed Interrupt Clear Mask */ -#define DEVEPTIDR_CTRL_NYETDISC_Pos 17 /**< (DEVEPTIDR) NYET Token Disable Clear Position */ -#define DEVEPTIDR_CTRL_NYETDISC (_U_(0x1) << DEVEPTIDR_CTRL_NYETDISC_Pos) /**< (DEVEPTIDR) NYET Token Disable Clear Mask */ -#define DEVEPTIDR_CTRL_STALLRQC_Pos 19 /**< (DEVEPTIDR) STALL Request Clear Position */ -#define DEVEPTIDR_CTRL_STALLRQC (_U_(0x1) << DEVEPTIDR_CTRL_STALLRQC_Pos) /**< (DEVEPTIDR) STALL Request Clear Mask */ -#define DEVEPTIDR_CTRL_Msk _U_(0xA005C) /**< (DEVEPTIDR_CTRL) Register Mask */ - -/* ISO mode */ -#define DEVEPTIDR_ISO_UNDERFEC_Pos 2 /**< (DEVEPTIDR) Underflow Interrupt Clear Position */ -#define DEVEPTIDR_ISO_UNDERFEC (_U_(0x1) << DEVEPTIDR_ISO_UNDERFEC_Pos) /**< (DEVEPTIDR) Underflow Interrupt Clear Mask */ -#define DEVEPTIDR_ISO_HBISOINERREC_Pos 3 /**< (DEVEPTIDR) High Bandwidth Isochronous IN Underflow Error Interrupt Clear Position */ -#define DEVEPTIDR_ISO_HBISOINERREC (_U_(0x1) << DEVEPTIDR_ISO_HBISOINERREC_Pos) /**< (DEVEPTIDR) High Bandwidth Isochronous IN Underflow Error Interrupt Clear Mask */ -#define DEVEPTIDR_ISO_HBISOFLUSHEC_Pos 4 /**< (DEVEPTIDR) High Bandwidth Isochronous IN Flush Interrupt Clear Position */ -#define DEVEPTIDR_ISO_HBISOFLUSHEC (_U_(0x1) << DEVEPTIDR_ISO_HBISOFLUSHEC_Pos) /**< (DEVEPTIDR) High Bandwidth Isochronous IN Flush Interrupt Clear Mask */ -#define DEVEPTIDR_ISO_MDATAEC_Pos 8 /**< (DEVEPTIDR) MData Interrupt Clear Position */ -#define DEVEPTIDR_ISO_MDATAEC (_U_(0x1) << DEVEPTIDR_ISO_MDATAEC_Pos) /**< (DEVEPTIDR) MData Interrupt Clear Mask */ -#define DEVEPTIDR_ISO_DATAXEC_Pos 9 /**< (DEVEPTIDR) DataX Interrupt Clear Position */ -#define DEVEPTIDR_ISO_DATAXEC (_U_(0x1) << DEVEPTIDR_ISO_DATAXEC_Pos) /**< (DEVEPTIDR) DataX Interrupt Clear Mask */ -#define DEVEPTIDR_ISO_ERRORTRANSEC_Pos 10 /**< (DEVEPTIDR) Transaction Error Interrupt Clear Position */ -#define DEVEPTIDR_ISO_ERRORTRANSEC (_U_(0x1) << DEVEPTIDR_ISO_ERRORTRANSEC_Pos) /**< (DEVEPTIDR) Transaction Error Interrupt Clear Mask */ -#define DEVEPTIDR_ISO_Msk _U_(0x71C) /**< (DEVEPTIDR_ISO) Register Mask */ - -/* BLK mode */ -#define DEVEPTIDR_BLK_RXSTPEC_Pos 2 /**< (DEVEPTIDR) Received SETUP Interrupt Clear Position */ -#define DEVEPTIDR_BLK_RXSTPEC (_U_(0x1) << DEVEPTIDR_BLK_RXSTPEC_Pos) /**< (DEVEPTIDR) Received SETUP Interrupt Clear Mask */ -#define DEVEPTIDR_BLK_NAKOUTEC_Pos 3 /**< (DEVEPTIDR) NAKed OUT Interrupt Clear Position */ -#define DEVEPTIDR_BLK_NAKOUTEC (_U_(0x1) << DEVEPTIDR_BLK_NAKOUTEC_Pos) /**< (DEVEPTIDR) NAKed OUT Interrupt Clear Mask */ -#define DEVEPTIDR_BLK_NAKINEC_Pos 4 /**< (DEVEPTIDR) NAKed IN Interrupt Clear Position */ -#define DEVEPTIDR_BLK_NAKINEC (_U_(0x1) << DEVEPTIDR_BLK_NAKINEC_Pos) /**< (DEVEPTIDR) NAKed IN Interrupt Clear Mask */ -#define DEVEPTIDR_BLK_STALLEDEC_Pos 6 /**< (DEVEPTIDR) STALLed Interrupt Clear Position */ -#define DEVEPTIDR_BLK_STALLEDEC (_U_(0x1) << DEVEPTIDR_BLK_STALLEDEC_Pos) /**< (DEVEPTIDR) STALLed Interrupt Clear Mask */ -#define DEVEPTIDR_BLK_NYETDISC_Pos 17 /**< (DEVEPTIDR) NYET Token Disable Clear Position */ -#define DEVEPTIDR_BLK_NYETDISC (_U_(0x1) << DEVEPTIDR_BLK_NYETDISC_Pos) /**< (DEVEPTIDR) NYET Token Disable Clear Mask */ -#define DEVEPTIDR_BLK_STALLRQC_Pos 19 /**< (DEVEPTIDR) STALL Request Clear Position */ -#define DEVEPTIDR_BLK_STALLRQC (_U_(0x1) << DEVEPTIDR_BLK_STALLRQC_Pos) /**< (DEVEPTIDR) STALL Request Clear Mask */ -#define DEVEPTIDR_BLK_Msk _U_(0xA005C) /**< (DEVEPTIDR_BLK) Register Mask */ - -/* INTRPT mode */ -#define DEVEPTIDR_INTRPT_RXSTPEC_Pos 2 /**< (DEVEPTIDR) Received SETUP Interrupt Clear Position */ -#define DEVEPTIDR_INTRPT_RXSTPEC (_U_(0x1) << DEVEPTIDR_INTRPT_RXSTPEC_Pos) /**< (DEVEPTIDR) Received SETUP Interrupt Clear Mask */ -#define DEVEPTIDR_INTRPT_NAKOUTEC_Pos 3 /**< (DEVEPTIDR) NAKed OUT Interrupt Clear Position */ -#define DEVEPTIDR_INTRPT_NAKOUTEC (_U_(0x1) << DEVEPTIDR_INTRPT_NAKOUTEC_Pos) /**< (DEVEPTIDR) NAKed OUT Interrupt Clear Mask */ -#define DEVEPTIDR_INTRPT_NAKINEC_Pos 4 /**< (DEVEPTIDR) NAKed IN Interrupt Clear Position */ -#define DEVEPTIDR_INTRPT_NAKINEC (_U_(0x1) << DEVEPTIDR_INTRPT_NAKINEC_Pos) /**< (DEVEPTIDR) NAKed IN Interrupt Clear Mask */ -#define DEVEPTIDR_INTRPT_STALLEDEC_Pos 6 /**< (DEVEPTIDR) STALLed Interrupt Clear Position */ -#define DEVEPTIDR_INTRPT_STALLEDEC (_U_(0x1) << DEVEPTIDR_INTRPT_STALLEDEC_Pos) /**< (DEVEPTIDR) STALLed Interrupt Clear Mask */ -#define DEVEPTIDR_INTRPT_NYETDISC_Pos 17 /**< (DEVEPTIDR) NYET Token Disable Clear Position */ -#define DEVEPTIDR_INTRPT_NYETDISC (_U_(0x1) << DEVEPTIDR_INTRPT_NYETDISC_Pos) /**< (DEVEPTIDR) NYET Token Disable Clear Mask */ -#define DEVEPTIDR_INTRPT_STALLRQC_Pos 19 /**< (DEVEPTIDR) STALL Request Clear Position */ -#define DEVEPTIDR_INTRPT_STALLRQC (_U_(0x1) << DEVEPTIDR_INTRPT_STALLRQC_Pos) /**< (DEVEPTIDR) STALL Request Clear Mask */ -#define DEVEPTIDR_INTRPT_Msk _U_(0xA005C) /**< (DEVEPTIDR_INTRPT) Register Mask */ - - -/* -------- HSTCTRL : (USBHS Offset: 0x400) (R/W 32) Host General Control Register -------- */ - -#define HSTCTRL_OFFSET (0x400) /**< (HSTCTRL) Host General Control Register Offset */ - -#define HSTCTRL_SOFE_Pos 8 /**< (HSTCTRL) Start of Frame Generation Enable Position */ -#define HSTCTRL_SOFE (_U_(0x1) << HSTCTRL_SOFE_Pos) /**< (HSTCTRL) Start of Frame Generation Enable Mask */ -#define HSTCTRL_RESET_Pos 9 /**< (HSTCTRL) Send USB Reset Position */ -#define HSTCTRL_RESET (_U_(0x1) << HSTCTRL_RESET_Pos) /**< (HSTCTRL) Send USB Reset Mask */ -#define HSTCTRL_RESUME_Pos 10 /**< (HSTCTRL) Send USB Resume Position */ -#define HSTCTRL_RESUME (_U_(0x1) << HSTCTRL_RESUME_Pos) /**< (HSTCTRL) Send USB Resume Mask */ -#define HSTCTRL_SPDCONF_Pos 12 /**< (HSTCTRL) Mode Configuration Position */ -#define HSTCTRL_SPDCONF (_U_(0x3) << HSTCTRL_SPDCONF_Pos) /**< (HSTCTRL) Mode Configuration Mask */ -#define HSTCTRL_SPDCONF_NORMAL_Val _U_(0x0) /**< (HSTCTRL) The host starts in Full-speed mode and performs a high-speed reset to switch to High-speed mode if the downstream peripheral is high-speed capable. */ -#define HSTCTRL_SPDCONF_LOW_POWER_Val _U_(0x1) /**< (HSTCTRL) For a better consumption, if high speed is not needed. */ -#define HSTCTRL_SPDCONF_HIGH_SPEED_Val _U_(0x2) /**< (HSTCTRL) Forced high speed. */ -#define HSTCTRL_SPDCONF_FORCED_FS_Val _U_(0x3) /**< (HSTCTRL) The host remains in Full-speed mode whatever the peripheral speed capability. */ -#define HSTCTRL_SPDCONF_NORMAL (HSTCTRL_SPDCONF_NORMAL_Val << HSTCTRL_SPDCONF_Pos) /**< (HSTCTRL) The host starts in Full-speed mode and performs a high-speed reset to switch to High-speed mode if the downstream peripheral is high-speed capable. Position */ -#define HSTCTRL_SPDCONF_LOW_POWER (HSTCTRL_SPDCONF_LOW_POWER_Val << HSTCTRL_SPDCONF_Pos) /**< (HSTCTRL) For a better consumption, if high speed is not needed. Position */ -#define HSTCTRL_SPDCONF_HIGH_SPEED (HSTCTRL_SPDCONF_HIGH_SPEED_Val << HSTCTRL_SPDCONF_Pos) /**< (HSTCTRL) Forced high speed. Position */ -#define HSTCTRL_SPDCONF_FORCED_FS (HSTCTRL_SPDCONF_FORCED_FS_Val << HSTCTRL_SPDCONF_Pos) /**< (HSTCTRL) The host remains in Full-speed mode whatever the peripheral speed capability. Position */ -#define HSTCTRL_Msk _U_(0x3700) /**< (HSTCTRL) Register Mask */ - - -/* -------- HSTISR : (USBHS Offset: 0x404) (R/ 32) Host Global Interrupt Status Register -------- */ - -#define HSTISR_OFFSET (0x404) /**< (HSTISR) Host Global Interrupt Status Register Offset */ - -#define HSTISR_DCONNI_Pos 0 /**< (HSTISR) Device Connection Interrupt Position */ -#define HSTISR_DCONNI (_U_(0x1) << HSTISR_DCONNI_Pos) /**< (HSTISR) Device Connection Interrupt Mask */ -#define HSTISR_DDISCI_Pos 1 /**< (HSTISR) Device Disconnection Interrupt Position */ -#define HSTISR_DDISCI (_U_(0x1) << HSTISR_DDISCI_Pos) /**< (HSTISR) Device Disconnection Interrupt Mask */ -#define HSTISR_RSTI_Pos 2 /**< (HSTISR) USB Reset Sent Interrupt Position */ -#define HSTISR_RSTI (_U_(0x1) << HSTISR_RSTI_Pos) /**< (HSTISR) USB Reset Sent Interrupt Mask */ -#define HSTISR_RSMEDI_Pos 3 /**< (HSTISR) Downstream Resume Sent Interrupt Position */ -#define HSTISR_RSMEDI (_U_(0x1) << HSTISR_RSMEDI_Pos) /**< (HSTISR) Downstream Resume Sent Interrupt Mask */ -#define HSTISR_RXRSMI_Pos 4 /**< (HSTISR) Upstream Resume Received Interrupt Position */ -#define HSTISR_RXRSMI (_U_(0x1) << HSTISR_RXRSMI_Pos) /**< (HSTISR) Upstream Resume Received Interrupt Mask */ -#define HSTISR_HSOFI_Pos 5 /**< (HSTISR) Host Start of Frame Interrupt Position */ -#define HSTISR_HSOFI (_U_(0x1) << HSTISR_HSOFI_Pos) /**< (HSTISR) Host Start of Frame Interrupt Mask */ -#define HSTISR_HWUPI_Pos 6 /**< (HSTISR) Host Wake-Up Interrupt Position */ -#define HSTISR_HWUPI (_U_(0x1) << HSTISR_HWUPI_Pos) /**< (HSTISR) Host Wake-Up Interrupt Mask */ -#define HSTISR_PEP_0_Pos 8 /**< (HSTISR) Pipe 0 Interrupt Position */ -#define HSTISR_PEP_0 (_U_(0x1) << HSTISR_PEP_0_Pos) /**< (HSTISR) Pipe 0 Interrupt Mask */ -#define HSTISR_PEP_1_Pos 9 /**< (HSTISR) Pipe 1 Interrupt Position */ -#define HSTISR_PEP_1 (_U_(0x1) << HSTISR_PEP_1_Pos) /**< (HSTISR) Pipe 1 Interrupt Mask */ -#define HSTISR_PEP_2_Pos 10 /**< (HSTISR) Pipe 2 Interrupt Position */ -#define HSTISR_PEP_2 (_U_(0x1) << HSTISR_PEP_2_Pos) /**< (HSTISR) Pipe 2 Interrupt Mask */ -#define HSTISR_PEP_3_Pos 11 /**< (HSTISR) Pipe 3 Interrupt Position */ -#define HSTISR_PEP_3 (_U_(0x1) << HSTISR_PEP_3_Pos) /**< (HSTISR) Pipe 3 Interrupt Mask */ -#define HSTISR_PEP_4_Pos 12 /**< (HSTISR) Pipe 4 Interrupt Position */ -#define HSTISR_PEP_4 (_U_(0x1) << HSTISR_PEP_4_Pos) /**< (HSTISR) Pipe 4 Interrupt Mask */ -#define HSTISR_PEP_5_Pos 13 /**< (HSTISR) Pipe 5 Interrupt Position */ -#define HSTISR_PEP_5 (_U_(0x1) << HSTISR_PEP_5_Pos) /**< (HSTISR) Pipe 5 Interrupt Mask */ -#define HSTISR_PEP_6_Pos 14 /**< (HSTISR) Pipe 6 Interrupt Position */ -#define HSTISR_PEP_6 (_U_(0x1) << HSTISR_PEP_6_Pos) /**< (HSTISR) Pipe 6 Interrupt Mask */ -#define HSTISR_PEP_7_Pos 15 /**< (HSTISR) Pipe 7 Interrupt Position */ -#define HSTISR_PEP_7 (_U_(0x1) << HSTISR_PEP_7_Pos) /**< (HSTISR) Pipe 7 Interrupt Mask */ -#define HSTISR_PEP_8_Pos 16 /**< (HSTISR) Pipe 8 Interrupt Position */ -#define HSTISR_PEP_8 (_U_(0x1) << HSTISR_PEP_8_Pos) /**< (HSTISR) Pipe 8 Interrupt Mask */ -#define HSTISR_PEP_9_Pos 17 /**< (HSTISR) Pipe 9 Interrupt Position */ -#define HSTISR_PEP_9 (_U_(0x1) << HSTISR_PEP_9_Pos) /**< (HSTISR) Pipe 9 Interrupt Mask */ -#define HSTISR_DMA_0_Pos 25 /**< (HSTISR) DMA Channel 0 Interrupt Position */ -#define HSTISR_DMA_0 (_U_(0x1) << HSTISR_DMA_0_Pos) /**< (HSTISR) DMA Channel 0 Interrupt Mask */ -#define HSTISR_DMA_1_Pos 26 /**< (HSTISR) DMA Channel 1 Interrupt Position */ -#define HSTISR_DMA_1 (_U_(0x1) << HSTISR_DMA_1_Pos) /**< (HSTISR) DMA Channel 1 Interrupt Mask */ -#define HSTISR_DMA_2_Pos 27 /**< (HSTISR) DMA Channel 2 Interrupt Position */ -#define HSTISR_DMA_2 (_U_(0x1) << HSTISR_DMA_2_Pos) /**< (HSTISR) DMA Channel 2 Interrupt Mask */ -#define HSTISR_DMA_3_Pos 28 /**< (HSTISR) DMA Channel 3 Interrupt Position */ -#define HSTISR_DMA_3 (_U_(0x1) << HSTISR_DMA_3_Pos) /**< (HSTISR) DMA Channel 3 Interrupt Mask */ -#define HSTISR_DMA_4_Pos 29 /**< (HSTISR) DMA Channel 4 Interrupt Position */ -#define HSTISR_DMA_4 (_U_(0x1) << HSTISR_DMA_4_Pos) /**< (HSTISR) DMA Channel 4 Interrupt Mask */ -#define HSTISR_DMA_5_Pos 30 /**< (HSTISR) DMA Channel 5 Interrupt Position */ -#define HSTISR_DMA_5 (_U_(0x1) << HSTISR_DMA_5_Pos) /**< (HSTISR) DMA Channel 5 Interrupt Mask */ -#define HSTISR_DMA_6_Pos 31 /**< (HSTISR) DMA Channel 6 Interrupt Position */ -#define HSTISR_DMA_6 (_U_(0x1) << HSTISR_DMA_6_Pos) /**< (HSTISR) DMA Channel 6 Interrupt Mask */ -#define HSTISR_Msk _U_(0xFE03FF7F) /**< (HSTISR) Register Mask */ - -#define HSTISR_PEP__Pos 8 /**< (HSTISR Position) Pipe x Interrupt */ -#define HSTISR_PEP_ (_U_(0x3FF) << HSTISR_PEP__Pos) /**< (HSTISR Mask) PEP_ */ -#define HSTISR_DMA__Pos 25 /**< (HSTISR Position) DMA Channel 6 Interrupt */ -#define HSTISR_DMA_ (_U_(0x7F) << HSTISR_DMA__Pos) /**< (HSTISR Mask) DMA_ */ - -/* -------- HSTICR : (USBHS Offset: 0x408) (/W 32) Host Global Interrupt Clear Register -------- */ - -#define HSTICR_OFFSET (0x408) /**< (HSTICR) Host Global Interrupt Clear Register Offset */ - -#define HSTICR_DCONNIC_Pos 0 /**< (HSTICR) Device Connection Interrupt Clear Position */ -#define HSTICR_DCONNIC (_U_(0x1) << HSTICR_DCONNIC_Pos) /**< (HSTICR) Device Connection Interrupt Clear Mask */ -#define HSTICR_DDISCIC_Pos 1 /**< (HSTICR) Device Disconnection Interrupt Clear Position */ -#define HSTICR_DDISCIC (_U_(0x1) << HSTICR_DDISCIC_Pos) /**< (HSTICR) Device Disconnection Interrupt Clear Mask */ -#define HSTICR_RSTIC_Pos 2 /**< (HSTICR) USB Reset Sent Interrupt Clear Position */ -#define HSTICR_RSTIC (_U_(0x1) << HSTICR_RSTIC_Pos) /**< (HSTICR) USB Reset Sent Interrupt Clear Mask */ -#define HSTICR_RSMEDIC_Pos 3 /**< (HSTICR) Downstream Resume Sent Interrupt Clear Position */ -#define HSTICR_RSMEDIC (_U_(0x1) << HSTICR_RSMEDIC_Pos) /**< (HSTICR) Downstream Resume Sent Interrupt Clear Mask */ -#define HSTICR_RXRSMIC_Pos 4 /**< (HSTICR) Upstream Resume Received Interrupt Clear Position */ -#define HSTICR_RXRSMIC (_U_(0x1) << HSTICR_RXRSMIC_Pos) /**< (HSTICR) Upstream Resume Received Interrupt Clear Mask */ -#define HSTICR_HSOFIC_Pos 5 /**< (HSTICR) Host Start of Frame Interrupt Clear Position */ -#define HSTICR_HSOFIC (_U_(0x1) << HSTICR_HSOFIC_Pos) /**< (HSTICR) Host Start of Frame Interrupt Clear Mask */ -#define HSTICR_HWUPIC_Pos 6 /**< (HSTICR) Host Wake-Up Interrupt Clear Position */ -#define HSTICR_HWUPIC (_U_(0x1) << HSTICR_HWUPIC_Pos) /**< (HSTICR) Host Wake-Up Interrupt Clear Mask */ -#define HSTICR_Msk _U_(0x7F) /**< (HSTICR) Register Mask */ - - -/* -------- HSTIFR : (USBHS Offset: 0x40c) (/W 32) Host Global Interrupt Set Register -------- */ - -#define HSTIFR_OFFSET (0x40C) /**< (HSTIFR) Host Global Interrupt Set Register Offset */ - -#define HSTIFR_DCONNIS_Pos 0 /**< (HSTIFR) Device Connection Interrupt Set Position */ -#define HSTIFR_DCONNIS (_U_(0x1) << HSTIFR_DCONNIS_Pos) /**< (HSTIFR) Device Connection Interrupt Set Mask */ -#define HSTIFR_DDISCIS_Pos 1 /**< (HSTIFR) Device Disconnection Interrupt Set Position */ -#define HSTIFR_DDISCIS (_U_(0x1) << HSTIFR_DDISCIS_Pos) /**< (HSTIFR) Device Disconnection Interrupt Set Mask */ -#define HSTIFR_RSTIS_Pos 2 /**< (HSTIFR) USB Reset Sent Interrupt Set Position */ -#define HSTIFR_RSTIS (_U_(0x1) << HSTIFR_RSTIS_Pos) /**< (HSTIFR) USB Reset Sent Interrupt Set Mask */ -#define HSTIFR_RSMEDIS_Pos 3 /**< (HSTIFR) Downstream Resume Sent Interrupt Set Position */ -#define HSTIFR_RSMEDIS (_U_(0x1) << HSTIFR_RSMEDIS_Pos) /**< (HSTIFR) Downstream Resume Sent Interrupt Set Mask */ -#define HSTIFR_RXRSMIS_Pos 4 /**< (HSTIFR) Upstream Resume Received Interrupt Set Position */ -#define HSTIFR_RXRSMIS (_U_(0x1) << HSTIFR_RXRSMIS_Pos) /**< (HSTIFR) Upstream Resume Received Interrupt Set Mask */ -#define HSTIFR_HSOFIS_Pos 5 /**< (HSTIFR) Host Start of Frame Interrupt Set Position */ -#define HSTIFR_HSOFIS (_U_(0x1) << HSTIFR_HSOFIS_Pos) /**< (HSTIFR) Host Start of Frame Interrupt Set Mask */ -#define HSTIFR_HWUPIS_Pos 6 /**< (HSTIFR) Host Wake-Up Interrupt Set Position */ -#define HSTIFR_HWUPIS (_U_(0x1) << HSTIFR_HWUPIS_Pos) /**< (HSTIFR) Host Wake-Up Interrupt Set Mask */ -#define HSTIFR_DMA_0_Pos 25 /**< (HSTIFR) DMA Channel 0 Interrupt Set Position */ -#define HSTIFR_DMA_0 (_U_(0x1) << HSTIFR_DMA_0_Pos) /**< (HSTIFR) DMA Channel 0 Interrupt Set Mask */ -#define HSTIFR_DMA_1_Pos 26 /**< (HSTIFR) DMA Channel 1 Interrupt Set Position */ -#define HSTIFR_DMA_1 (_U_(0x1) << HSTIFR_DMA_1_Pos) /**< (HSTIFR) DMA Channel 1 Interrupt Set Mask */ -#define HSTIFR_DMA_2_Pos 27 /**< (HSTIFR) DMA Channel 2 Interrupt Set Position */ -#define HSTIFR_DMA_2 (_U_(0x1) << HSTIFR_DMA_2_Pos) /**< (HSTIFR) DMA Channel 2 Interrupt Set Mask */ -#define HSTIFR_DMA_3_Pos 28 /**< (HSTIFR) DMA Channel 3 Interrupt Set Position */ -#define HSTIFR_DMA_3 (_U_(0x1) << HSTIFR_DMA_3_Pos) /**< (HSTIFR) DMA Channel 3 Interrupt Set Mask */ -#define HSTIFR_DMA_4_Pos 29 /**< (HSTIFR) DMA Channel 4 Interrupt Set Position */ -#define HSTIFR_DMA_4 (_U_(0x1) << HSTIFR_DMA_4_Pos) /**< (HSTIFR) DMA Channel 4 Interrupt Set Mask */ -#define HSTIFR_DMA_5_Pos 30 /**< (HSTIFR) DMA Channel 5 Interrupt Set Position */ -#define HSTIFR_DMA_5 (_U_(0x1) << HSTIFR_DMA_5_Pos) /**< (HSTIFR) DMA Channel 5 Interrupt Set Mask */ -#define HSTIFR_DMA_6_Pos 31 /**< (HSTIFR) DMA Channel 6 Interrupt Set Position */ -#define HSTIFR_DMA_6 (_U_(0x1) << HSTIFR_DMA_6_Pos) /**< (HSTIFR) DMA Channel 6 Interrupt Set Mask */ -#define HSTIFR_Msk _U_(0xFE00007F) /**< (HSTIFR) Register Mask */ - -#define HSTIFR_DMA__Pos 25 /**< (HSTIFR Position) DMA Channel 6 Interrupt Set */ -#define HSTIFR_DMA_ (_U_(0x7F) << HSTIFR_DMA__Pos) /**< (HSTIFR Mask) DMA_ */ - -/* -------- HSTIMR : (USBHS Offset: 0x410) (R/ 32) Host Global Interrupt Mask Register -------- */ - -#define HSTIMR_OFFSET (0x410) /**< (HSTIMR) Host Global Interrupt Mask Register Offset */ - -#define HSTIMR_DCONNIE_Pos 0 /**< (HSTIMR) Device Connection Interrupt Enable Position */ -#define HSTIMR_DCONNIE (_U_(0x1) << HSTIMR_DCONNIE_Pos) /**< (HSTIMR) Device Connection Interrupt Enable Mask */ -#define HSTIMR_DDISCIE_Pos 1 /**< (HSTIMR) Device Disconnection Interrupt Enable Position */ -#define HSTIMR_DDISCIE (_U_(0x1) << HSTIMR_DDISCIE_Pos) /**< (HSTIMR) Device Disconnection Interrupt Enable Mask */ -#define HSTIMR_RSTIE_Pos 2 /**< (HSTIMR) USB Reset Sent Interrupt Enable Position */ -#define HSTIMR_RSTIE (_U_(0x1) << HSTIMR_RSTIE_Pos) /**< (HSTIMR) USB Reset Sent Interrupt Enable Mask */ -#define HSTIMR_RSMEDIE_Pos 3 /**< (HSTIMR) Downstream Resume Sent Interrupt Enable Position */ -#define HSTIMR_RSMEDIE (_U_(0x1) << HSTIMR_RSMEDIE_Pos) /**< (HSTIMR) Downstream Resume Sent Interrupt Enable Mask */ -#define HSTIMR_RXRSMIE_Pos 4 /**< (HSTIMR) Upstream Resume Received Interrupt Enable Position */ -#define HSTIMR_RXRSMIE (_U_(0x1) << HSTIMR_RXRSMIE_Pos) /**< (HSTIMR) Upstream Resume Received Interrupt Enable Mask */ -#define HSTIMR_HSOFIE_Pos 5 /**< (HSTIMR) Host Start of Frame Interrupt Enable Position */ -#define HSTIMR_HSOFIE (_U_(0x1) << HSTIMR_HSOFIE_Pos) /**< (HSTIMR) Host Start of Frame Interrupt Enable Mask */ -#define HSTIMR_HWUPIE_Pos 6 /**< (HSTIMR) Host Wake-Up Interrupt Enable Position */ -#define HSTIMR_HWUPIE (_U_(0x1) << HSTIMR_HWUPIE_Pos) /**< (HSTIMR) Host Wake-Up Interrupt Enable Mask */ -#define HSTIMR_PEP_0_Pos 8 /**< (HSTIMR) Pipe 0 Interrupt Enable Position */ -#define HSTIMR_PEP_0 (_U_(0x1) << HSTIMR_PEP_0_Pos) /**< (HSTIMR) Pipe 0 Interrupt Enable Mask */ -#define HSTIMR_PEP_1_Pos 9 /**< (HSTIMR) Pipe 1 Interrupt Enable Position */ -#define HSTIMR_PEP_1 (_U_(0x1) << HSTIMR_PEP_1_Pos) /**< (HSTIMR) Pipe 1 Interrupt Enable Mask */ -#define HSTIMR_PEP_2_Pos 10 /**< (HSTIMR) Pipe 2 Interrupt Enable Position */ -#define HSTIMR_PEP_2 (_U_(0x1) << HSTIMR_PEP_2_Pos) /**< (HSTIMR) Pipe 2 Interrupt Enable Mask */ -#define HSTIMR_PEP_3_Pos 11 /**< (HSTIMR) Pipe 3 Interrupt Enable Position */ -#define HSTIMR_PEP_3 (_U_(0x1) << HSTIMR_PEP_3_Pos) /**< (HSTIMR) Pipe 3 Interrupt Enable Mask */ -#define HSTIMR_PEP_4_Pos 12 /**< (HSTIMR) Pipe 4 Interrupt Enable Position */ -#define HSTIMR_PEP_4 (_U_(0x1) << HSTIMR_PEP_4_Pos) /**< (HSTIMR) Pipe 4 Interrupt Enable Mask */ -#define HSTIMR_PEP_5_Pos 13 /**< (HSTIMR) Pipe 5 Interrupt Enable Position */ -#define HSTIMR_PEP_5 (_U_(0x1) << HSTIMR_PEP_5_Pos) /**< (HSTIMR) Pipe 5 Interrupt Enable Mask */ -#define HSTIMR_PEP_6_Pos 14 /**< (HSTIMR) Pipe 6 Interrupt Enable Position */ -#define HSTIMR_PEP_6 (_U_(0x1) << HSTIMR_PEP_6_Pos) /**< (HSTIMR) Pipe 6 Interrupt Enable Mask */ -#define HSTIMR_PEP_7_Pos 15 /**< (HSTIMR) Pipe 7 Interrupt Enable Position */ -#define HSTIMR_PEP_7 (_U_(0x1) << HSTIMR_PEP_7_Pos) /**< (HSTIMR) Pipe 7 Interrupt Enable Mask */ -#define HSTIMR_PEP_8_Pos 16 /**< (HSTIMR) Pipe 8 Interrupt Enable Position */ -#define HSTIMR_PEP_8 (_U_(0x1) << HSTIMR_PEP_8_Pos) /**< (HSTIMR) Pipe 8 Interrupt Enable Mask */ -#define HSTIMR_PEP_9_Pos 17 /**< (HSTIMR) Pipe 9 Interrupt Enable Position */ -#define HSTIMR_PEP_9 (_U_(0x1) << HSTIMR_PEP_9_Pos) /**< (HSTIMR) Pipe 9 Interrupt Enable Mask */ -#define HSTIMR_DMA_0_Pos 25 /**< (HSTIMR) DMA Channel 0 Interrupt Enable Position */ -#define HSTIMR_DMA_0 (_U_(0x1) << HSTIMR_DMA_0_Pos) /**< (HSTIMR) DMA Channel 0 Interrupt Enable Mask */ -#define HSTIMR_DMA_1_Pos 26 /**< (HSTIMR) DMA Channel 1 Interrupt Enable Position */ -#define HSTIMR_DMA_1 (_U_(0x1) << HSTIMR_DMA_1_Pos) /**< (HSTIMR) DMA Channel 1 Interrupt Enable Mask */ -#define HSTIMR_DMA_2_Pos 27 /**< (HSTIMR) DMA Channel 2 Interrupt Enable Position */ -#define HSTIMR_DMA_2 (_U_(0x1) << HSTIMR_DMA_2_Pos) /**< (HSTIMR) DMA Channel 2 Interrupt Enable Mask */ -#define HSTIMR_DMA_3_Pos 28 /**< (HSTIMR) DMA Channel 3 Interrupt Enable Position */ -#define HSTIMR_DMA_3 (_U_(0x1) << HSTIMR_DMA_3_Pos) /**< (HSTIMR) DMA Channel 3 Interrupt Enable Mask */ -#define HSTIMR_DMA_4_Pos 29 /**< (HSTIMR) DMA Channel 4 Interrupt Enable Position */ -#define HSTIMR_DMA_4 (_U_(0x1) << HSTIMR_DMA_4_Pos) /**< (HSTIMR) DMA Channel 4 Interrupt Enable Mask */ -#define HSTIMR_DMA_5_Pos 30 /**< (HSTIMR) DMA Channel 5 Interrupt Enable Position */ -#define HSTIMR_DMA_5 (_U_(0x1) << HSTIMR_DMA_5_Pos) /**< (HSTIMR) DMA Channel 5 Interrupt Enable Mask */ -#define HSTIMR_DMA_6_Pos 31 /**< (HSTIMR) DMA Channel 6 Interrupt Enable Position */ -#define HSTIMR_DMA_6 (_U_(0x1) << HSTIMR_DMA_6_Pos) /**< (HSTIMR) DMA Channel 6 Interrupt Enable Mask */ -#define HSTIMR_Msk _U_(0xFE03FF7F) /**< (HSTIMR) Register Mask */ - -#define HSTIMR_PEP__Pos 8 /**< (HSTIMR Position) Pipe x Interrupt Enable */ -#define HSTIMR_PEP_ (_U_(0x3FF) << HSTIMR_PEP__Pos) /**< (HSTIMR Mask) PEP_ */ -#define HSTIMR_DMA__Pos 25 /**< (HSTIMR Position) DMA Channel 6 Interrupt Enable */ -#define HSTIMR_DMA_ (_U_(0x7F) << HSTIMR_DMA__Pos) /**< (HSTIMR Mask) DMA_ */ - -/* -------- HSTIDR : (USBHS Offset: 0x414) (/W 32) Host Global Interrupt Disable Register -------- */ - -#define HSTIDR_OFFSET (0x414) /**< (HSTIDR) Host Global Interrupt Disable Register Offset */ - -#define HSTIDR_DCONNIEC_Pos 0 /**< (HSTIDR) Device Connection Interrupt Disable Position */ -#define HSTIDR_DCONNIEC (_U_(0x1) << HSTIDR_DCONNIEC_Pos) /**< (HSTIDR) Device Connection Interrupt Disable Mask */ -#define HSTIDR_DDISCIEC_Pos 1 /**< (HSTIDR) Device Disconnection Interrupt Disable Position */ -#define HSTIDR_DDISCIEC (_U_(0x1) << HSTIDR_DDISCIEC_Pos) /**< (HSTIDR) Device Disconnection Interrupt Disable Mask */ -#define HSTIDR_RSTIEC_Pos 2 /**< (HSTIDR) USB Reset Sent Interrupt Disable Position */ -#define HSTIDR_RSTIEC (_U_(0x1) << HSTIDR_RSTIEC_Pos) /**< (HSTIDR) USB Reset Sent Interrupt Disable Mask */ -#define HSTIDR_RSMEDIEC_Pos 3 /**< (HSTIDR) Downstream Resume Sent Interrupt Disable Position */ -#define HSTIDR_RSMEDIEC (_U_(0x1) << HSTIDR_RSMEDIEC_Pos) /**< (HSTIDR) Downstream Resume Sent Interrupt Disable Mask */ -#define HSTIDR_RXRSMIEC_Pos 4 /**< (HSTIDR) Upstream Resume Received Interrupt Disable Position */ -#define HSTIDR_RXRSMIEC (_U_(0x1) << HSTIDR_RXRSMIEC_Pos) /**< (HSTIDR) Upstream Resume Received Interrupt Disable Mask */ -#define HSTIDR_HSOFIEC_Pos 5 /**< (HSTIDR) Host Start of Frame Interrupt Disable Position */ -#define HSTIDR_HSOFIEC (_U_(0x1) << HSTIDR_HSOFIEC_Pos) /**< (HSTIDR) Host Start of Frame Interrupt Disable Mask */ -#define HSTIDR_HWUPIEC_Pos 6 /**< (HSTIDR) Host Wake-Up Interrupt Disable Position */ -#define HSTIDR_HWUPIEC (_U_(0x1) << HSTIDR_HWUPIEC_Pos) /**< (HSTIDR) Host Wake-Up Interrupt Disable Mask */ -#define HSTIDR_PEP_0_Pos 8 /**< (HSTIDR) Pipe 0 Interrupt Disable Position */ -#define HSTIDR_PEP_0 (_U_(0x1) << HSTIDR_PEP_0_Pos) /**< (HSTIDR) Pipe 0 Interrupt Disable Mask */ -#define HSTIDR_PEP_1_Pos 9 /**< (HSTIDR) Pipe 1 Interrupt Disable Position */ -#define HSTIDR_PEP_1 (_U_(0x1) << HSTIDR_PEP_1_Pos) /**< (HSTIDR) Pipe 1 Interrupt Disable Mask */ -#define HSTIDR_PEP_2_Pos 10 /**< (HSTIDR) Pipe 2 Interrupt Disable Position */ -#define HSTIDR_PEP_2 (_U_(0x1) << HSTIDR_PEP_2_Pos) /**< (HSTIDR) Pipe 2 Interrupt Disable Mask */ -#define HSTIDR_PEP_3_Pos 11 /**< (HSTIDR) Pipe 3 Interrupt Disable Position */ -#define HSTIDR_PEP_3 (_U_(0x1) << HSTIDR_PEP_3_Pos) /**< (HSTIDR) Pipe 3 Interrupt Disable Mask */ -#define HSTIDR_PEP_4_Pos 12 /**< (HSTIDR) Pipe 4 Interrupt Disable Position */ -#define HSTIDR_PEP_4 (_U_(0x1) << HSTIDR_PEP_4_Pos) /**< (HSTIDR) Pipe 4 Interrupt Disable Mask */ -#define HSTIDR_PEP_5_Pos 13 /**< (HSTIDR) Pipe 5 Interrupt Disable Position */ -#define HSTIDR_PEP_5 (_U_(0x1) << HSTIDR_PEP_5_Pos) /**< (HSTIDR) Pipe 5 Interrupt Disable Mask */ -#define HSTIDR_PEP_6_Pos 14 /**< (HSTIDR) Pipe 6 Interrupt Disable Position */ -#define HSTIDR_PEP_6 (_U_(0x1) << HSTIDR_PEP_6_Pos) /**< (HSTIDR) Pipe 6 Interrupt Disable Mask */ -#define HSTIDR_PEP_7_Pos 15 /**< (HSTIDR) Pipe 7 Interrupt Disable Position */ -#define HSTIDR_PEP_7 (_U_(0x1) << HSTIDR_PEP_7_Pos) /**< (HSTIDR) Pipe 7 Interrupt Disable Mask */ -#define HSTIDR_PEP_8_Pos 16 /**< (HSTIDR) Pipe 8 Interrupt Disable Position */ -#define HSTIDR_PEP_8 (_U_(0x1) << HSTIDR_PEP_8_Pos) /**< (HSTIDR) Pipe 8 Interrupt Disable Mask */ -#define HSTIDR_PEP_9_Pos 17 /**< (HSTIDR) Pipe 9 Interrupt Disable Position */ -#define HSTIDR_PEP_9 (_U_(0x1) << HSTIDR_PEP_9_Pos) /**< (HSTIDR) Pipe 9 Interrupt Disable Mask */ -#define HSTIDR_DMA_0_Pos 25 /**< (HSTIDR) DMA Channel 0 Interrupt Disable Position */ -#define HSTIDR_DMA_0 (_U_(0x1) << HSTIDR_DMA_0_Pos) /**< (HSTIDR) DMA Channel 0 Interrupt Disable Mask */ -#define HSTIDR_DMA_1_Pos 26 /**< (HSTIDR) DMA Channel 1 Interrupt Disable Position */ -#define HSTIDR_DMA_1 (_U_(0x1) << HSTIDR_DMA_1_Pos) /**< (HSTIDR) DMA Channel 1 Interrupt Disable Mask */ -#define HSTIDR_DMA_2_Pos 27 /**< (HSTIDR) DMA Channel 2 Interrupt Disable Position */ -#define HSTIDR_DMA_2 (_U_(0x1) << HSTIDR_DMA_2_Pos) /**< (HSTIDR) DMA Channel 2 Interrupt Disable Mask */ -#define HSTIDR_DMA_3_Pos 28 /**< (HSTIDR) DMA Channel 3 Interrupt Disable Position */ -#define HSTIDR_DMA_3 (_U_(0x1) << HSTIDR_DMA_3_Pos) /**< (HSTIDR) DMA Channel 3 Interrupt Disable Mask */ -#define HSTIDR_DMA_4_Pos 29 /**< (HSTIDR) DMA Channel 4 Interrupt Disable Position */ -#define HSTIDR_DMA_4 (_U_(0x1) << HSTIDR_DMA_4_Pos) /**< (HSTIDR) DMA Channel 4 Interrupt Disable Mask */ -#define HSTIDR_DMA_5_Pos 30 /**< (HSTIDR) DMA Channel 5 Interrupt Disable Position */ -#define HSTIDR_DMA_5 (_U_(0x1) << HSTIDR_DMA_5_Pos) /**< (HSTIDR) DMA Channel 5 Interrupt Disable Mask */ -#define HSTIDR_DMA_6_Pos 31 /**< (HSTIDR) DMA Channel 6 Interrupt Disable Position */ -#define HSTIDR_DMA_6 (_U_(0x1) << HSTIDR_DMA_6_Pos) /**< (HSTIDR) DMA Channel 6 Interrupt Disable Mask */ -#define HSTIDR_Msk _U_(0xFE03FF7F) /**< (HSTIDR) Register Mask */ - -#define HSTIDR_PEP__Pos 8 /**< (HSTIDR Position) Pipe x Interrupt Disable */ -#define HSTIDR_PEP_ (_U_(0x3FF) << HSTIDR_PEP__Pos) /**< (HSTIDR Mask) PEP_ */ -#define HSTIDR_DMA__Pos 25 /**< (HSTIDR Position) DMA Channel 6 Interrupt Disable */ -#define HSTIDR_DMA_ (_U_(0x7F) << HSTIDR_DMA__Pos) /**< (HSTIDR Mask) DMA_ */ - -/* -------- HSTIER : (USBHS Offset: 0x418) (/W 32) Host Global Interrupt Enable Register -------- */ - -#define HSTIER_OFFSET (0x418) /**< (HSTIER) Host Global Interrupt Enable Register Offset */ - -#define HSTIER_DCONNIES_Pos 0 /**< (HSTIER) Device Connection Interrupt Enable Position */ -#define HSTIER_DCONNIES (_U_(0x1) << HSTIER_DCONNIES_Pos) /**< (HSTIER) Device Connection Interrupt Enable Mask */ -#define HSTIER_DDISCIES_Pos 1 /**< (HSTIER) Device Disconnection Interrupt Enable Position */ -#define HSTIER_DDISCIES (_U_(0x1) << HSTIER_DDISCIES_Pos) /**< (HSTIER) Device Disconnection Interrupt Enable Mask */ -#define HSTIER_RSTIES_Pos 2 /**< (HSTIER) USB Reset Sent Interrupt Enable Position */ -#define HSTIER_RSTIES (_U_(0x1) << HSTIER_RSTIES_Pos) /**< (HSTIER) USB Reset Sent Interrupt Enable Mask */ -#define HSTIER_RSMEDIES_Pos 3 /**< (HSTIER) Downstream Resume Sent Interrupt Enable Position */ -#define HSTIER_RSMEDIES (_U_(0x1) << HSTIER_RSMEDIES_Pos) /**< (HSTIER) Downstream Resume Sent Interrupt Enable Mask */ -#define HSTIER_RXRSMIES_Pos 4 /**< (HSTIER) Upstream Resume Received Interrupt Enable Position */ -#define HSTIER_RXRSMIES (_U_(0x1) << HSTIER_RXRSMIES_Pos) /**< (HSTIER) Upstream Resume Received Interrupt Enable Mask */ -#define HSTIER_HSOFIES_Pos 5 /**< (HSTIER) Host Start of Frame Interrupt Enable Position */ -#define HSTIER_HSOFIES (_U_(0x1) << HSTIER_HSOFIES_Pos) /**< (HSTIER) Host Start of Frame Interrupt Enable Mask */ -#define HSTIER_HWUPIES_Pos 6 /**< (HSTIER) Host Wake-Up Interrupt Enable Position */ -#define HSTIER_HWUPIES (_U_(0x1) << HSTIER_HWUPIES_Pos) /**< (HSTIER) Host Wake-Up Interrupt Enable Mask */ -#define HSTIER_PEP_0_Pos 8 /**< (HSTIER) Pipe 0 Interrupt Enable Position */ -#define HSTIER_PEP_0 (_U_(0x1) << HSTIER_PEP_0_Pos) /**< (HSTIER) Pipe 0 Interrupt Enable Mask */ -#define HSTIER_PEP_1_Pos 9 /**< (HSTIER) Pipe 1 Interrupt Enable Position */ -#define HSTIER_PEP_1 (_U_(0x1) << HSTIER_PEP_1_Pos) /**< (HSTIER) Pipe 1 Interrupt Enable Mask */ -#define HSTIER_PEP_2_Pos 10 /**< (HSTIER) Pipe 2 Interrupt Enable Position */ -#define HSTIER_PEP_2 (_U_(0x1) << HSTIER_PEP_2_Pos) /**< (HSTIER) Pipe 2 Interrupt Enable Mask */ -#define HSTIER_PEP_3_Pos 11 /**< (HSTIER) Pipe 3 Interrupt Enable Position */ -#define HSTIER_PEP_3 (_U_(0x1) << HSTIER_PEP_3_Pos) /**< (HSTIER) Pipe 3 Interrupt Enable Mask */ -#define HSTIER_PEP_4_Pos 12 /**< (HSTIER) Pipe 4 Interrupt Enable Position */ -#define HSTIER_PEP_4 (_U_(0x1) << HSTIER_PEP_4_Pos) /**< (HSTIER) Pipe 4 Interrupt Enable Mask */ -#define HSTIER_PEP_5_Pos 13 /**< (HSTIER) Pipe 5 Interrupt Enable Position */ -#define HSTIER_PEP_5 (_U_(0x1) << HSTIER_PEP_5_Pos) /**< (HSTIER) Pipe 5 Interrupt Enable Mask */ -#define HSTIER_PEP_6_Pos 14 /**< (HSTIER) Pipe 6 Interrupt Enable Position */ -#define HSTIER_PEP_6 (_U_(0x1) << HSTIER_PEP_6_Pos) /**< (HSTIER) Pipe 6 Interrupt Enable Mask */ -#define HSTIER_PEP_7_Pos 15 /**< (HSTIER) Pipe 7 Interrupt Enable Position */ -#define HSTIER_PEP_7 (_U_(0x1) << HSTIER_PEP_7_Pos) /**< (HSTIER) Pipe 7 Interrupt Enable Mask */ -#define HSTIER_PEP_8_Pos 16 /**< (HSTIER) Pipe 8 Interrupt Enable Position */ -#define HSTIER_PEP_8 (_U_(0x1) << HSTIER_PEP_8_Pos) /**< (HSTIER) Pipe 8 Interrupt Enable Mask */ -#define HSTIER_PEP_9_Pos 17 /**< (HSTIER) Pipe 9 Interrupt Enable Position */ -#define HSTIER_PEP_9 (_U_(0x1) << HSTIER_PEP_9_Pos) /**< (HSTIER) Pipe 9 Interrupt Enable Mask */ -#define HSTIER_DMA_0_Pos 25 /**< (HSTIER) DMA Channel 0 Interrupt Enable Position */ -#define HSTIER_DMA_0 (_U_(0x1) << HSTIER_DMA_0_Pos) /**< (HSTIER) DMA Channel 0 Interrupt Enable Mask */ -#define HSTIER_DMA_1_Pos 26 /**< (HSTIER) DMA Channel 1 Interrupt Enable Position */ -#define HSTIER_DMA_1 (_U_(0x1) << HSTIER_DMA_1_Pos) /**< (HSTIER) DMA Channel 1 Interrupt Enable Mask */ -#define HSTIER_DMA_2_Pos 27 /**< (HSTIER) DMA Channel 2 Interrupt Enable Position */ -#define HSTIER_DMA_2 (_U_(0x1) << HSTIER_DMA_2_Pos) /**< (HSTIER) DMA Channel 2 Interrupt Enable Mask */ -#define HSTIER_DMA_3_Pos 28 /**< (HSTIER) DMA Channel 3 Interrupt Enable Position */ -#define HSTIER_DMA_3 (_U_(0x1) << HSTIER_DMA_3_Pos) /**< (HSTIER) DMA Channel 3 Interrupt Enable Mask */ -#define HSTIER_DMA_4_Pos 29 /**< (HSTIER) DMA Channel 4 Interrupt Enable Position */ -#define HSTIER_DMA_4 (_U_(0x1) << HSTIER_DMA_4_Pos) /**< (HSTIER) DMA Channel 4 Interrupt Enable Mask */ -#define HSTIER_DMA_5_Pos 30 /**< (HSTIER) DMA Channel 5 Interrupt Enable Position */ -#define HSTIER_DMA_5 (_U_(0x1) << HSTIER_DMA_5_Pos) /**< (HSTIER) DMA Channel 5 Interrupt Enable Mask */ -#define HSTIER_DMA_6_Pos 31 /**< (HSTIER) DMA Channel 6 Interrupt Enable Position */ -#define HSTIER_DMA_6 (_U_(0x1) << HSTIER_DMA_6_Pos) /**< (HSTIER) DMA Channel 6 Interrupt Enable Mask */ -#define HSTIER_Msk _U_(0xFE03FF7F) /**< (HSTIER) Register Mask */ - -#define HSTIER_PEP__Pos 8 /**< (HSTIER Position) Pipe x Interrupt Enable */ -#define HSTIER_PEP_ (_U_(0x3FF) << HSTIER_PEP__Pos) /**< (HSTIER Mask) PEP_ */ -#define HSTIER_DMA__Pos 25 /**< (HSTIER Position) DMA Channel 6 Interrupt Enable */ -#define HSTIER_DMA_ (_U_(0x7F) << HSTIER_DMA__Pos) /**< (HSTIER Mask) DMA_ */ - -/* -------- HSTPIP : (USBHS Offset: 0x41c) (R/W 32) Host Pipe Register -------- */ - -#define HSTPIP_OFFSET (0x41C) /**< (HSTPIP) Host Pipe Register Offset */ - -#define HSTPIP_PEN0_Pos 0 /**< (HSTPIP) Pipe 0 Enable Position */ -#define HSTPIP_PEN0 (_U_(0x1) << HSTPIP_PEN0_Pos) /**< (HSTPIP) Pipe 0 Enable Mask */ -#define HSTPIP_PEN1_Pos 1 /**< (HSTPIP) Pipe 1 Enable Position */ -#define HSTPIP_PEN1 (_U_(0x1) << HSTPIP_PEN1_Pos) /**< (HSTPIP) Pipe 1 Enable Mask */ -#define HSTPIP_PEN2_Pos 2 /**< (HSTPIP) Pipe 2 Enable Position */ -#define HSTPIP_PEN2 (_U_(0x1) << HSTPIP_PEN2_Pos) /**< (HSTPIP) Pipe 2 Enable Mask */ -#define HSTPIP_PEN3_Pos 3 /**< (HSTPIP) Pipe 3 Enable Position */ -#define HSTPIP_PEN3 (_U_(0x1) << HSTPIP_PEN3_Pos) /**< (HSTPIP) Pipe 3 Enable Mask */ -#define HSTPIP_PEN4_Pos 4 /**< (HSTPIP) Pipe 4 Enable Position */ -#define HSTPIP_PEN4 (_U_(0x1) << HSTPIP_PEN4_Pos) /**< (HSTPIP) Pipe 4 Enable Mask */ -#define HSTPIP_PEN5_Pos 5 /**< (HSTPIP) Pipe 5 Enable Position */ -#define HSTPIP_PEN5 (_U_(0x1) << HSTPIP_PEN5_Pos) /**< (HSTPIP) Pipe 5 Enable Mask */ -#define HSTPIP_PEN6_Pos 6 /**< (HSTPIP) Pipe 6 Enable Position */ -#define HSTPIP_PEN6 (_U_(0x1) << HSTPIP_PEN6_Pos) /**< (HSTPIP) Pipe 6 Enable Mask */ -#define HSTPIP_PEN7_Pos 7 /**< (HSTPIP) Pipe 7 Enable Position */ -#define HSTPIP_PEN7 (_U_(0x1) << HSTPIP_PEN7_Pos) /**< (HSTPIP) Pipe 7 Enable Mask */ -#define HSTPIP_PEN8_Pos 8 /**< (HSTPIP) Pipe 8 Enable Position */ -#define HSTPIP_PEN8 (_U_(0x1) << HSTPIP_PEN8_Pos) /**< (HSTPIP) Pipe 8 Enable Mask */ -#define HSTPIP_PRST0_Pos 16 /**< (HSTPIP) Pipe 0 Reset Position */ -#define HSTPIP_PRST0 (_U_(0x1) << HSTPIP_PRST0_Pos) /**< (HSTPIP) Pipe 0 Reset Mask */ -#define HSTPIP_PRST1_Pos 17 /**< (HSTPIP) Pipe 1 Reset Position */ -#define HSTPIP_PRST1 (_U_(0x1) << HSTPIP_PRST1_Pos) /**< (HSTPIP) Pipe 1 Reset Mask */ -#define HSTPIP_PRST2_Pos 18 /**< (HSTPIP) Pipe 2 Reset Position */ -#define HSTPIP_PRST2 (_U_(0x1) << HSTPIP_PRST2_Pos) /**< (HSTPIP) Pipe 2 Reset Mask */ -#define HSTPIP_PRST3_Pos 19 /**< (HSTPIP) Pipe 3 Reset Position */ -#define HSTPIP_PRST3 (_U_(0x1) << HSTPIP_PRST3_Pos) /**< (HSTPIP) Pipe 3 Reset Mask */ -#define HSTPIP_PRST4_Pos 20 /**< (HSTPIP) Pipe 4 Reset Position */ -#define HSTPIP_PRST4 (_U_(0x1) << HSTPIP_PRST4_Pos) /**< (HSTPIP) Pipe 4 Reset Mask */ -#define HSTPIP_PRST5_Pos 21 /**< (HSTPIP) Pipe 5 Reset Position */ -#define HSTPIP_PRST5 (_U_(0x1) << HSTPIP_PRST5_Pos) /**< (HSTPIP) Pipe 5 Reset Mask */ -#define HSTPIP_PRST6_Pos 22 /**< (HSTPIP) Pipe 6 Reset Position */ -#define HSTPIP_PRST6 (_U_(0x1) << HSTPIP_PRST6_Pos) /**< (HSTPIP) Pipe 6 Reset Mask */ -#define HSTPIP_PRST7_Pos 23 /**< (HSTPIP) Pipe 7 Reset Position */ -#define HSTPIP_PRST7 (_U_(0x1) << HSTPIP_PRST7_Pos) /**< (HSTPIP) Pipe 7 Reset Mask */ -#define HSTPIP_PRST8_Pos 24 /**< (HSTPIP) Pipe 8 Reset Position */ -#define HSTPIP_PRST8 (_U_(0x1) << HSTPIP_PRST8_Pos) /**< (HSTPIP) Pipe 8 Reset Mask */ -#define HSTPIP_Msk _U_(0x1FF01FF) /**< (HSTPIP) Register Mask */ - -#define HSTPIP_PEN_Pos 0 /**< (HSTPIP Position) Pipe x Enable */ -#define HSTPIP_PEN (_U_(0x1FF) << HSTPIP_PEN_Pos) /**< (HSTPIP Mask) PEN */ -#define HSTPIP_PRST_Pos 16 /**< (HSTPIP Position) Pipe 8 Reset */ -#define HSTPIP_PRST (_U_(0x1FF) << HSTPIP_PRST_Pos) /**< (HSTPIP Mask) PRST */ - -/* -------- HSTFNUM : (USBHS Offset: 0x420) (R/W 32) Host Frame Number Register -------- */ - -#define HSTFNUM_OFFSET (0x420) /**< (HSTFNUM) Host Frame Number Register Offset */ - -#define HSTFNUM_MFNUM_Pos 0 /**< (HSTFNUM) Micro Frame Number Position */ -#define HSTFNUM_MFNUM (_U_(0x7) << HSTFNUM_MFNUM_Pos) /**< (HSTFNUM) Micro Frame Number Mask */ -#define HSTFNUM_FNUM_Pos 3 /**< (HSTFNUM) Frame Number Position */ -#define HSTFNUM_FNUM (_U_(0x7FF) << HSTFNUM_FNUM_Pos) /**< (HSTFNUM) Frame Number Mask */ -#define HSTFNUM_FLENHIGH_Pos 16 /**< (HSTFNUM) Frame Length Position */ -#define HSTFNUM_FLENHIGH (_U_(0xFF) << HSTFNUM_FLENHIGH_Pos) /**< (HSTFNUM) Frame Length Mask */ -#define HSTFNUM_Msk _U_(0xFF3FFF) /**< (HSTFNUM) Register Mask */ - - -/* -------- HSTADDR1 : (USBHS Offset: 0x424) (R/W 32) Host Address 1 Register -------- */ - -#define HSTADDR1_OFFSET (0x424) /**< (HSTADDR1) Host Address 1 Register Offset */ - -#define HSTADDR1_HSTADDRP0_Pos 0 /**< (HSTADDR1) USB Host Address Position */ -#define HSTADDR1_HSTADDRP0 (_U_(0x7F) << HSTADDR1_HSTADDRP0_Pos) /**< (HSTADDR1) USB Host Address Mask */ -#define HSTADDR1_HSTADDRP1_Pos 8 /**< (HSTADDR1) USB Host Address Position */ -#define HSTADDR1_HSTADDRP1 (_U_(0x7F) << HSTADDR1_HSTADDRP1_Pos) /**< (HSTADDR1) USB Host Address Mask */ -#define HSTADDR1_HSTADDRP2_Pos 16 /**< (HSTADDR1) USB Host Address Position */ -#define HSTADDR1_HSTADDRP2 (_U_(0x7F) << HSTADDR1_HSTADDRP2_Pos) /**< (HSTADDR1) USB Host Address Mask */ -#define HSTADDR1_HSTADDRP3_Pos 24 /**< (HSTADDR1) USB Host Address Position */ -#define HSTADDR1_HSTADDRP3 (_U_(0x7F) << HSTADDR1_HSTADDRP3_Pos) /**< (HSTADDR1) USB Host Address Mask */ -#define HSTADDR1_Msk _U_(0x7F7F7F7F) /**< (HSTADDR1) Register Mask */ - - -/* -------- HSTADDR2 : (USBHS Offset: 0x428) (R/W 32) Host Address 2 Register -------- */ - -#define HSTADDR2_OFFSET (0x428) /**< (HSTADDR2) Host Address 2 Register Offset */ - -#define HSTADDR2_HSTADDRP4_Pos 0 /**< (HSTADDR2) USB Host Address Position */ -#define HSTADDR2_HSTADDRP4 (_U_(0x7F) << HSTADDR2_HSTADDRP4_Pos) /**< (HSTADDR2) USB Host Address Mask */ -#define HSTADDR2_HSTADDRP5_Pos 8 /**< (HSTADDR2) USB Host Address Position */ -#define HSTADDR2_HSTADDRP5 (_U_(0x7F) << HSTADDR2_HSTADDRP5_Pos) /**< (HSTADDR2) USB Host Address Mask */ -#define HSTADDR2_HSTADDRP6_Pos 16 /**< (HSTADDR2) USB Host Address Position */ -#define HSTADDR2_HSTADDRP6 (_U_(0x7F) << HSTADDR2_HSTADDRP6_Pos) /**< (HSTADDR2) USB Host Address Mask */ -#define HSTADDR2_HSTADDRP7_Pos 24 /**< (HSTADDR2) USB Host Address Position */ -#define HSTADDR2_HSTADDRP7 (_U_(0x7F) << HSTADDR2_HSTADDRP7_Pos) /**< (HSTADDR2) USB Host Address Mask */ -#define HSTADDR2_Msk _U_(0x7F7F7F7F) /**< (HSTADDR2) Register Mask */ - - -/* -------- HSTADDR3 : (USBHS Offset: 0x42c) (R/W 32) Host Address 3 Register -------- */ - -#define HSTADDR3_OFFSET (0x42C) /**< (HSTADDR3) Host Address 3 Register Offset */ - -#define HSTADDR3_HSTADDRP8_Pos 0 /**< (HSTADDR3) USB Host Address Position */ -#define HSTADDR3_HSTADDRP8 (_U_(0x7F) << HSTADDR3_HSTADDRP8_Pos) /**< (HSTADDR3) USB Host Address Mask */ -#define HSTADDR3_HSTADDRP9_Pos 8 /**< (HSTADDR3) USB Host Address Position */ -#define HSTADDR3_HSTADDRP9 (_U_(0x7F) << HSTADDR3_HSTADDRP9_Pos) /**< (HSTADDR3) USB Host Address Mask */ -#define HSTADDR3_Msk _U_(0x7F7F) /**< (HSTADDR3) Register Mask */ - - -/* -------- HSTPIPCFG : (USBHS Offset: 0x500) (R/W 32) Host Pipe Configuration Register -------- */ - -#define HSTPIPCFG_OFFSET (0x500) /**< (HSTPIPCFG) Host Pipe Configuration Register Offset */ - -#define HSTPIPCFG_ALLOC_Pos 1 /**< (HSTPIPCFG) Pipe Memory Allocate Position */ -#define HSTPIPCFG_ALLOC (_U_(0x1) << HSTPIPCFG_ALLOC_Pos) /**< (HSTPIPCFG) Pipe Memory Allocate Mask */ -#define HSTPIPCFG_PBK_Pos 2 /**< (HSTPIPCFG) Pipe Banks Position */ -#define HSTPIPCFG_PBK (_U_(0x3) << HSTPIPCFG_PBK_Pos) /**< (HSTPIPCFG) Pipe Banks Mask */ -#define HSTPIPCFG_PBK_1_BANK_Val _U_(0x0) /**< (HSTPIPCFG) Single-bank pipe */ -#define HSTPIPCFG_PBK_2_BANK_Val _U_(0x1) /**< (HSTPIPCFG) Double-bank pipe */ -#define HSTPIPCFG_PBK_3_BANK_Val _U_(0x2) /**< (HSTPIPCFG) Triple-bank pipe */ -#define HSTPIPCFG_PBK_1_BANK (HSTPIPCFG_PBK_1_BANK_Val << HSTPIPCFG_PBK_Pos) /**< (HSTPIPCFG) Single-bank pipe Position */ -#define HSTPIPCFG_PBK_2_BANK (HSTPIPCFG_PBK_2_BANK_Val << HSTPIPCFG_PBK_Pos) /**< (HSTPIPCFG) Double-bank pipe Position */ -#define HSTPIPCFG_PBK_3_BANK (HSTPIPCFG_PBK_3_BANK_Val << HSTPIPCFG_PBK_Pos) /**< (HSTPIPCFG) Triple-bank pipe Position */ -#define HSTPIPCFG_PSIZE_Pos 4 /**< (HSTPIPCFG) Pipe Size Position */ -#define HSTPIPCFG_PSIZE (_U_(0x7) << HSTPIPCFG_PSIZE_Pos) /**< (HSTPIPCFG) Pipe Size Mask */ -#define HSTPIPCFG_PSIZE_8_BYTE_Val _U_(0x0) /**< (HSTPIPCFG) 8 bytes */ -#define HSTPIPCFG_PSIZE_16_BYTE_Val _U_(0x1) /**< (HSTPIPCFG) 16 bytes */ -#define HSTPIPCFG_PSIZE_32_BYTE_Val _U_(0x2) /**< (HSTPIPCFG) 32 bytes */ -#define HSTPIPCFG_PSIZE_64_BYTE_Val _U_(0x3) /**< (HSTPIPCFG) 64 bytes */ -#define HSTPIPCFG_PSIZE_128_BYTE_Val _U_(0x4) /**< (HSTPIPCFG) 128 bytes */ -#define HSTPIPCFG_PSIZE_256_BYTE_Val _U_(0x5) /**< (HSTPIPCFG) 256 bytes */ -#define HSTPIPCFG_PSIZE_512_BYTE_Val _U_(0x6) /**< (HSTPIPCFG) 512 bytes */ -#define HSTPIPCFG_PSIZE_1024_BYTE_Val _U_(0x7) /**< (HSTPIPCFG) 1024 bytes */ -#define HSTPIPCFG_PSIZE_8_BYTE (HSTPIPCFG_PSIZE_8_BYTE_Val << HSTPIPCFG_PSIZE_Pos) /**< (HSTPIPCFG) 8 bytes Position */ -#define HSTPIPCFG_PSIZE_16_BYTE (HSTPIPCFG_PSIZE_16_BYTE_Val << HSTPIPCFG_PSIZE_Pos) /**< (HSTPIPCFG) 16 bytes Position */ -#define HSTPIPCFG_PSIZE_32_BYTE (HSTPIPCFG_PSIZE_32_BYTE_Val << HSTPIPCFG_PSIZE_Pos) /**< (HSTPIPCFG) 32 bytes Position */ -#define HSTPIPCFG_PSIZE_64_BYTE (HSTPIPCFG_PSIZE_64_BYTE_Val << HSTPIPCFG_PSIZE_Pos) /**< (HSTPIPCFG) 64 bytes Position */ -#define HSTPIPCFG_PSIZE_128_BYTE (HSTPIPCFG_PSIZE_128_BYTE_Val << HSTPIPCFG_PSIZE_Pos) /**< (HSTPIPCFG) 128 bytes Position */ -#define HSTPIPCFG_PSIZE_256_BYTE (HSTPIPCFG_PSIZE_256_BYTE_Val << HSTPIPCFG_PSIZE_Pos) /**< (HSTPIPCFG) 256 bytes Position */ -#define HSTPIPCFG_PSIZE_512_BYTE (HSTPIPCFG_PSIZE_512_BYTE_Val << HSTPIPCFG_PSIZE_Pos) /**< (HSTPIPCFG) 512 bytes Position */ -#define HSTPIPCFG_PSIZE_1024_BYTE (HSTPIPCFG_PSIZE_1024_BYTE_Val << HSTPIPCFG_PSIZE_Pos) /**< (HSTPIPCFG) 1024 bytes Position */ -#define HSTPIPCFG_PTOKEN_Pos 8 /**< (HSTPIPCFG) Pipe Token Position */ -#define HSTPIPCFG_PTOKEN (_U_(0x3) << HSTPIPCFG_PTOKEN_Pos) /**< (HSTPIPCFG) Pipe Token Mask */ -#define HSTPIPCFG_PTOKEN_SETUP_Val _U_(0x0) /**< (HSTPIPCFG) SETUP */ -#define HSTPIPCFG_PTOKEN_IN_Val _U_(0x1) /**< (HSTPIPCFG) IN */ -#define HSTPIPCFG_PTOKEN_OUT_Val _U_(0x2) /**< (HSTPIPCFG) OUT */ -#define HSTPIPCFG_PTOKEN_SETUP (HSTPIPCFG_PTOKEN_SETUP_Val << HSTPIPCFG_PTOKEN_Pos) /**< (HSTPIPCFG) SETUP Position */ -#define HSTPIPCFG_PTOKEN_IN (HSTPIPCFG_PTOKEN_IN_Val << HSTPIPCFG_PTOKEN_Pos) /**< (HSTPIPCFG) IN Position */ -#define HSTPIPCFG_PTOKEN_OUT (HSTPIPCFG_PTOKEN_OUT_Val << HSTPIPCFG_PTOKEN_Pos) /**< (HSTPIPCFG) OUT Position */ -#define HSTPIPCFG_AUTOSW_Pos 10 /**< (HSTPIPCFG) Automatic Switch Position */ -#define HSTPIPCFG_AUTOSW (_U_(0x1) << HSTPIPCFG_AUTOSW_Pos) /**< (HSTPIPCFG) Automatic Switch Mask */ -#define HSTPIPCFG_PTYPE_Pos 12 /**< (HSTPIPCFG) Pipe Type Position */ -#define HSTPIPCFG_PTYPE (_U_(0x3) << HSTPIPCFG_PTYPE_Pos) /**< (HSTPIPCFG) Pipe Type Mask */ -#define HSTPIPCFG_PTYPE_CTRL_Val _U_(0x0) /**< (HSTPIPCFG) Control */ -#define HSTPIPCFG_PTYPE_ISO_Val _U_(0x1) /**< (HSTPIPCFG) Isochronous */ -#define HSTPIPCFG_PTYPE_BLK_Val _U_(0x2) /**< (HSTPIPCFG) Bulk */ -#define HSTPIPCFG_PTYPE_INTRPT_Val _U_(0x3) /**< (HSTPIPCFG) Interrupt */ -#define HSTPIPCFG_PTYPE_CTRL (HSTPIPCFG_PTYPE_CTRL_Val << HSTPIPCFG_PTYPE_Pos) /**< (HSTPIPCFG) Control Position */ -#define HSTPIPCFG_PTYPE_ISO (HSTPIPCFG_PTYPE_ISO_Val << HSTPIPCFG_PTYPE_Pos) /**< (HSTPIPCFG) Isochronous Position */ -#define HSTPIPCFG_PTYPE_BLK (HSTPIPCFG_PTYPE_BLK_Val << HSTPIPCFG_PTYPE_Pos) /**< (HSTPIPCFG) Bulk Position */ -#define HSTPIPCFG_PTYPE_INTRPT (HSTPIPCFG_PTYPE_INTRPT_Val << HSTPIPCFG_PTYPE_Pos) /**< (HSTPIPCFG) Interrupt Position */ -#define HSTPIPCFG_PEPNUM_Pos 16 /**< (HSTPIPCFG) Pipe Endpoint Number Position */ -#define HSTPIPCFG_PEPNUM (_U_(0xF) << HSTPIPCFG_PEPNUM_Pos) /**< (HSTPIPCFG) Pipe Endpoint Number Mask */ -#define HSTPIPCFG_INTFRQ_Pos 24 /**< (HSTPIPCFG) Pipe Interrupt Request Frequency Position */ -#define HSTPIPCFG_INTFRQ (_U_(0xFF) << HSTPIPCFG_INTFRQ_Pos) /**< (HSTPIPCFG) Pipe Interrupt Request Frequency Mask */ -#define HSTPIPCFG_Msk _U_(0xFF0F377E) /**< (HSTPIPCFG) Register Mask */ - -/* CTRL_BULK mode */ -#define HSTPIPCFG_CTRL_BULK_PINGEN_Pos 20 /**< (HSTPIPCFG) Ping Enable Position */ -#define HSTPIPCFG_CTRL_BULK_PINGEN (_U_(0x1) << HSTPIPCFG_CTRL_BULK_PINGEN_Pos) /**< (HSTPIPCFG) Ping Enable Mask */ -#define HSTPIPCFG_CTRL_BULK_BINTERVAL_Pos 24 /**< (HSTPIPCFG) bInterval Parameter for the Bulk-Out/Ping Transaction Position */ -#define HSTPIPCFG_CTRL_BULK_BINTERVAL (_U_(0xFF) << HSTPIPCFG_CTRL_BULK_BINTERVAL_Pos) /**< (HSTPIPCFG) bInterval Parameter for the Bulk-Out/Ping Transaction Mask */ -#define HSTPIPCFG_CTRL_BULK_Msk _U_(0xFF100000) /**< (HSTPIPCFG_CTRL_BULK) Register Mask */ - - -/* -------- HSTPIPISR : (USBHS Offset: 0x530) (R/ 32) Host Pipe Status Register -------- */ - -#define HSTPIPISR_OFFSET (0x530) /**< (HSTPIPISR) Host Pipe Status Register Offset */ - -#define HSTPIPISR_RXINI_Pos 0 /**< (HSTPIPISR) Received IN Data Interrupt Position */ -#define HSTPIPISR_RXINI (_U_(0x1) << HSTPIPISR_RXINI_Pos) /**< (HSTPIPISR) Received IN Data Interrupt Mask */ -#define HSTPIPISR_TXOUTI_Pos 1 /**< (HSTPIPISR) Transmitted OUT Data Interrupt Position */ -#define HSTPIPISR_TXOUTI (_U_(0x1) << HSTPIPISR_TXOUTI_Pos) /**< (HSTPIPISR) Transmitted OUT Data Interrupt Mask */ -#define HSTPIPISR_PERRI_Pos 3 /**< (HSTPIPISR) Pipe Error Interrupt Position */ -#define HSTPIPISR_PERRI (_U_(0x1) << HSTPIPISR_PERRI_Pos) /**< (HSTPIPISR) Pipe Error Interrupt Mask */ -#define HSTPIPISR_NAKEDI_Pos 4 /**< (HSTPIPISR) NAKed Interrupt Position */ -#define HSTPIPISR_NAKEDI (_U_(0x1) << HSTPIPISR_NAKEDI_Pos) /**< (HSTPIPISR) NAKed Interrupt Mask */ -#define HSTPIPISR_OVERFI_Pos 5 /**< (HSTPIPISR) Overflow Interrupt Position */ -#define HSTPIPISR_OVERFI (_U_(0x1) << HSTPIPISR_OVERFI_Pos) /**< (HSTPIPISR) Overflow Interrupt Mask */ -#define HSTPIPISR_SHORTPACKETI_Pos 7 /**< (HSTPIPISR) Short Packet Interrupt Position */ -#define HSTPIPISR_SHORTPACKETI (_U_(0x1) << HSTPIPISR_SHORTPACKETI_Pos) /**< (HSTPIPISR) Short Packet Interrupt Mask */ -#define HSTPIPISR_DTSEQ_Pos 8 /**< (HSTPIPISR) Data Toggle Sequence Position */ -#define HSTPIPISR_DTSEQ (_U_(0x3) << HSTPIPISR_DTSEQ_Pos) /**< (HSTPIPISR) Data Toggle Sequence Mask */ -#define HSTPIPISR_DTSEQ_DATA0_Val _U_(0x0) /**< (HSTPIPISR) Data0 toggle sequence */ -#define HSTPIPISR_DTSEQ_DATA1_Val _U_(0x1) /**< (HSTPIPISR) Data1 toggle sequence */ -#define HSTPIPISR_DTSEQ_DATA0 (HSTPIPISR_DTSEQ_DATA0_Val << HSTPIPISR_DTSEQ_Pos) /**< (HSTPIPISR) Data0 toggle sequence Position */ -#define HSTPIPISR_DTSEQ_DATA1 (HSTPIPISR_DTSEQ_DATA1_Val << HSTPIPISR_DTSEQ_Pos) /**< (HSTPIPISR) Data1 toggle sequence Position */ -#define HSTPIPISR_NBUSYBK_Pos 12 /**< (HSTPIPISR) Number of Busy Banks Position */ -#define HSTPIPISR_NBUSYBK (_U_(0x3) << HSTPIPISR_NBUSYBK_Pos) /**< (HSTPIPISR) Number of Busy Banks Mask */ -#define HSTPIPISR_NBUSYBK_0_BUSY_Val _U_(0x0) /**< (HSTPIPISR) 0 busy bank (all banks free) */ -#define HSTPIPISR_NBUSYBK_1_BUSY_Val _U_(0x1) /**< (HSTPIPISR) 1 busy bank */ -#define HSTPIPISR_NBUSYBK_2_BUSY_Val _U_(0x2) /**< (HSTPIPISR) 2 busy banks */ -#define HSTPIPISR_NBUSYBK_3_BUSY_Val _U_(0x3) /**< (HSTPIPISR) 3 busy banks */ -#define HSTPIPISR_NBUSYBK_0_BUSY (HSTPIPISR_NBUSYBK_0_BUSY_Val << HSTPIPISR_NBUSYBK_Pos) /**< (HSTPIPISR) 0 busy bank (all banks free) Position */ -#define HSTPIPISR_NBUSYBK_1_BUSY (HSTPIPISR_NBUSYBK_1_BUSY_Val << HSTPIPISR_NBUSYBK_Pos) /**< (HSTPIPISR) 1 busy bank Position */ -#define HSTPIPISR_NBUSYBK_2_BUSY (HSTPIPISR_NBUSYBK_2_BUSY_Val << HSTPIPISR_NBUSYBK_Pos) /**< (HSTPIPISR) 2 busy banks Position */ -#define HSTPIPISR_NBUSYBK_3_BUSY (HSTPIPISR_NBUSYBK_3_BUSY_Val << HSTPIPISR_NBUSYBK_Pos) /**< (HSTPIPISR) 3 busy banks Position */ -#define HSTPIPISR_CURRBK_Pos 14 /**< (HSTPIPISR) Current Bank Position */ -#define HSTPIPISR_CURRBK (_U_(0x3) << HSTPIPISR_CURRBK_Pos) /**< (HSTPIPISR) Current Bank Mask */ -#define HSTPIPISR_CURRBK_BANK0_Val _U_(0x0) /**< (HSTPIPISR) Current bank is bank0 */ -#define HSTPIPISR_CURRBK_BANK1_Val _U_(0x1) /**< (HSTPIPISR) Current bank is bank1 */ -#define HSTPIPISR_CURRBK_BANK2_Val _U_(0x2) /**< (HSTPIPISR) Current bank is bank2 */ -#define HSTPIPISR_CURRBK_BANK0 (HSTPIPISR_CURRBK_BANK0_Val << HSTPIPISR_CURRBK_Pos) /**< (HSTPIPISR) Current bank is bank0 Position */ -#define HSTPIPISR_CURRBK_BANK1 (HSTPIPISR_CURRBK_BANK1_Val << HSTPIPISR_CURRBK_Pos) /**< (HSTPIPISR) Current bank is bank1 Position */ -#define HSTPIPISR_CURRBK_BANK2 (HSTPIPISR_CURRBK_BANK2_Val << HSTPIPISR_CURRBK_Pos) /**< (HSTPIPISR) Current bank is bank2 Position */ -#define HSTPIPISR_RWALL_Pos 16 /**< (HSTPIPISR) Read/Write Allowed Position */ -#define HSTPIPISR_RWALL (_U_(0x1) << HSTPIPISR_RWALL_Pos) /**< (HSTPIPISR) Read/Write Allowed Mask */ -#define HSTPIPISR_CFGOK_Pos 18 /**< (HSTPIPISR) Configuration OK Status Position */ -#define HSTPIPISR_CFGOK (_U_(0x1) << HSTPIPISR_CFGOK_Pos) /**< (HSTPIPISR) Configuration OK Status Mask */ -#define HSTPIPISR_PBYCT_Pos 20 /**< (HSTPIPISR) Pipe Byte Count Position */ -#define HSTPIPISR_PBYCT (_U_(0x7FF) << HSTPIPISR_PBYCT_Pos) /**< (HSTPIPISR) Pipe Byte Count Mask */ -#define HSTPIPISR_Msk _U_(0x7FF5F3BB) /**< (HSTPIPISR) Register Mask */ - -/* CTRL mode */ -#define HSTPIPISR_CTRL_TXSTPI_Pos 2 /**< (HSTPIPISR) Transmitted SETUP Interrupt Position */ -#define HSTPIPISR_CTRL_TXSTPI (_U_(0x1) << HSTPIPISR_CTRL_TXSTPI_Pos) /**< (HSTPIPISR) Transmitted SETUP Interrupt Mask */ -#define HSTPIPISR_CTRL_RXSTALLDI_Pos 6 /**< (HSTPIPISR) Received STALLed Interrupt Position */ -#define HSTPIPISR_CTRL_RXSTALLDI (_U_(0x1) << HSTPIPISR_CTRL_RXSTALLDI_Pos) /**< (HSTPIPISR) Received STALLed Interrupt Mask */ -#define HSTPIPISR_CTRL_Msk _U_(0x44) /**< (HSTPIPISR_CTRL) Register Mask */ - -/* ISO mode */ -#define HSTPIPISR_ISO_UNDERFI_Pos 2 /**< (HSTPIPISR) Underflow Interrupt Position */ -#define HSTPIPISR_ISO_UNDERFI (_U_(0x1) << HSTPIPISR_ISO_UNDERFI_Pos) /**< (HSTPIPISR) Underflow Interrupt Mask */ -#define HSTPIPISR_ISO_CRCERRI_Pos 6 /**< (HSTPIPISR) CRC Error Interrupt Position */ -#define HSTPIPISR_ISO_CRCERRI (_U_(0x1) << HSTPIPISR_ISO_CRCERRI_Pos) /**< (HSTPIPISR) CRC Error Interrupt Mask */ -#define HSTPIPISR_ISO_Msk _U_(0x44) /**< (HSTPIPISR_ISO) Register Mask */ - -/* BLK mode */ -#define HSTPIPISR_BLK_TXSTPI_Pos 2 /**< (HSTPIPISR) Transmitted SETUP Interrupt Position */ -#define HSTPIPISR_BLK_TXSTPI (_U_(0x1) << HSTPIPISR_BLK_TXSTPI_Pos) /**< (HSTPIPISR) Transmitted SETUP Interrupt Mask */ -#define HSTPIPISR_BLK_RXSTALLDI_Pos 6 /**< (HSTPIPISR) Received STALLed Interrupt Position */ -#define HSTPIPISR_BLK_RXSTALLDI (_U_(0x1) << HSTPIPISR_BLK_RXSTALLDI_Pos) /**< (HSTPIPISR) Received STALLed Interrupt Mask */ -#define HSTPIPISR_BLK_Msk _U_(0x44) /**< (HSTPIPISR_BLK) Register Mask */ - -/* INTRPT mode */ -#define HSTPIPISR_INTRPT_UNDERFI_Pos 2 /**< (HSTPIPISR) Underflow Interrupt Position */ -#define HSTPIPISR_INTRPT_UNDERFI (_U_(0x1) << HSTPIPISR_INTRPT_UNDERFI_Pos) /**< (HSTPIPISR) Underflow Interrupt Mask */ -#define HSTPIPISR_INTRPT_RXSTALLDI_Pos 6 /**< (HSTPIPISR) Received STALLed Interrupt Position */ -#define HSTPIPISR_INTRPT_RXSTALLDI (_U_(0x1) << HSTPIPISR_INTRPT_RXSTALLDI_Pos) /**< (HSTPIPISR) Received STALLed Interrupt Mask */ -#define HSTPIPISR_INTRPT_Msk _U_(0x44) /**< (HSTPIPISR_INTRPT) Register Mask */ - - -/* -------- HSTPIPICR : (USBHS Offset: 0x560) (/W 32) Host Pipe Clear Register -------- */ - -#define HSTPIPICR_OFFSET (0x560) /**< (HSTPIPICR) Host Pipe Clear Register Offset */ - -#define HSTPIPICR_RXINIC_Pos 0 /**< (HSTPIPICR) Received IN Data Interrupt Clear Position */ -#define HSTPIPICR_RXINIC (_U_(0x1) << HSTPIPICR_RXINIC_Pos) /**< (HSTPIPICR) Received IN Data Interrupt Clear Mask */ -#define HSTPIPICR_TXOUTIC_Pos 1 /**< (HSTPIPICR) Transmitted OUT Data Interrupt Clear Position */ -#define HSTPIPICR_TXOUTIC (_U_(0x1) << HSTPIPICR_TXOUTIC_Pos) /**< (HSTPIPICR) Transmitted OUT Data Interrupt Clear Mask */ -#define HSTPIPICR_NAKEDIC_Pos 4 /**< (HSTPIPICR) NAKed Interrupt Clear Position */ -#define HSTPIPICR_NAKEDIC (_U_(0x1) << HSTPIPICR_NAKEDIC_Pos) /**< (HSTPIPICR) NAKed Interrupt Clear Mask */ -#define HSTPIPICR_OVERFIC_Pos 5 /**< (HSTPIPICR) Overflow Interrupt Clear Position */ -#define HSTPIPICR_OVERFIC (_U_(0x1) << HSTPIPICR_OVERFIC_Pos) /**< (HSTPIPICR) Overflow Interrupt Clear Mask */ -#define HSTPIPICR_SHORTPACKETIC_Pos 7 /**< (HSTPIPICR) Short Packet Interrupt Clear Position */ -#define HSTPIPICR_SHORTPACKETIC (_U_(0x1) << HSTPIPICR_SHORTPACKETIC_Pos) /**< (HSTPIPICR) Short Packet Interrupt Clear Mask */ -#define HSTPIPICR_Msk _U_(0xB3) /**< (HSTPIPICR) Register Mask */ - -/* CTRL mode */ -#define HSTPIPICR_CTRL_TXSTPIC_Pos 2 /**< (HSTPIPICR) Transmitted SETUP Interrupt Clear Position */ -#define HSTPIPICR_CTRL_TXSTPIC (_U_(0x1) << HSTPIPICR_CTRL_TXSTPIC_Pos) /**< (HSTPIPICR) Transmitted SETUP Interrupt Clear Mask */ -#define HSTPIPICR_CTRL_RXSTALLDIC_Pos 6 /**< (HSTPIPICR) Received STALLed Interrupt Clear Position */ -#define HSTPIPICR_CTRL_RXSTALLDIC (_U_(0x1) << HSTPIPICR_CTRL_RXSTALLDIC_Pos) /**< (HSTPIPICR) Received STALLed Interrupt Clear Mask */ -#define HSTPIPICR_CTRL_Msk _U_(0x44) /**< (HSTPIPICR_CTRL) Register Mask */ - -/* ISO mode */ -#define HSTPIPICR_ISO_UNDERFIC_Pos 2 /**< (HSTPIPICR) Underflow Interrupt Clear Position */ -#define HSTPIPICR_ISO_UNDERFIC (_U_(0x1) << HSTPIPICR_ISO_UNDERFIC_Pos) /**< (HSTPIPICR) Underflow Interrupt Clear Mask */ -#define HSTPIPICR_ISO_CRCERRIC_Pos 6 /**< (HSTPIPICR) CRC Error Interrupt Clear Position */ -#define HSTPIPICR_ISO_CRCERRIC (_U_(0x1) << HSTPIPICR_ISO_CRCERRIC_Pos) /**< (HSTPIPICR) CRC Error Interrupt Clear Mask */ -#define HSTPIPICR_ISO_Msk _U_(0x44) /**< (HSTPIPICR_ISO) Register Mask */ - -/* BLK mode */ -#define HSTPIPICR_BLK_TXSTPIC_Pos 2 /**< (HSTPIPICR) Transmitted SETUP Interrupt Clear Position */ -#define HSTPIPICR_BLK_TXSTPIC (_U_(0x1) << HSTPIPICR_BLK_TXSTPIC_Pos) /**< (HSTPIPICR) Transmitted SETUP Interrupt Clear Mask */ -#define HSTPIPICR_BLK_RXSTALLDIC_Pos 6 /**< (HSTPIPICR) Received STALLed Interrupt Clear Position */ -#define HSTPIPICR_BLK_RXSTALLDIC (_U_(0x1) << HSTPIPICR_BLK_RXSTALLDIC_Pos) /**< (HSTPIPICR) Received STALLed Interrupt Clear Mask */ -#define HSTPIPICR_BLK_Msk _U_(0x44) /**< (HSTPIPICR_BLK) Register Mask */ - -/* INTRPT mode */ -#define HSTPIPICR_INTRPT_UNDERFIC_Pos 2 /**< (HSTPIPICR) Underflow Interrupt Clear Position */ -#define HSTPIPICR_INTRPT_UNDERFIC (_U_(0x1) << HSTPIPICR_INTRPT_UNDERFIC_Pos) /**< (HSTPIPICR) Underflow Interrupt Clear Mask */ -#define HSTPIPICR_INTRPT_RXSTALLDIC_Pos 6 /**< (HSTPIPICR) Received STALLed Interrupt Clear Position */ -#define HSTPIPICR_INTRPT_RXSTALLDIC (_U_(0x1) << HSTPIPICR_INTRPT_RXSTALLDIC_Pos) /**< (HSTPIPICR) Received STALLed Interrupt Clear Mask */ -#define HSTPIPICR_INTRPT_Msk _U_(0x44) /**< (HSTPIPICR_INTRPT) Register Mask */ - - -/* -------- HSTPIPIFR : (USBHS Offset: 0x590) (/W 32) Host Pipe Set Register -------- */ - -#define HSTPIPIFR_OFFSET (0x590) /**< (HSTPIPIFR) Host Pipe Set Register Offset */ - -#define HSTPIPIFR_RXINIS_Pos 0 /**< (HSTPIPIFR) Received IN Data Interrupt Set Position */ -#define HSTPIPIFR_RXINIS (_U_(0x1) << HSTPIPIFR_RXINIS_Pos) /**< (HSTPIPIFR) Received IN Data Interrupt Set Mask */ -#define HSTPIPIFR_TXOUTIS_Pos 1 /**< (HSTPIPIFR) Transmitted OUT Data Interrupt Set Position */ -#define HSTPIPIFR_TXOUTIS (_U_(0x1) << HSTPIPIFR_TXOUTIS_Pos) /**< (HSTPIPIFR) Transmitted OUT Data Interrupt Set Mask */ -#define HSTPIPIFR_PERRIS_Pos 3 /**< (HSTPIPIFR) Pipe Error Interrupt Set Position */ -#define HSTPIPIFR_PERRIS (_U_(0x1) << HSTPIPIFR_PERRIS_Pos) /**< (HSTPIPIFR) Pipe Error Interrupt Set Mask */ -#define HSTPIPIFR_NAKEDIS_Pos 4 /**< (HSTPIPIFR) NAKed Interrupt Set Position */ -#define HSTPIPIFR_NAKEDIS (_U_(0x1) << HSTPIPIFR_NAKEDIS_Pos) /**< (HSTPIPIFR) NAKed Interrupt Set Mask */ -#define HSTPIPIFR_OVERFIS_Pos 5 /**< (HSTPIPIFR) Overflow Interrupt Set Position */ -#define HSTPIPIFR_OVERFIS (_U_(0x1) << HSTPIPIFR_OVERFIS_Pos) /**< (HSTPIPIFR) Overflow Interrupt Set Mask */ -#define HSTPIPIFR_SHORTPACKETIS_Pos 7 /**< (HSTPIPIFR) Short Packet Interrupt Set Position */ -#define HSTPIPIFR_SHORTPACKETIS (_U_(0x1) << HSTPIPIFR_SHORTPACKETIS_Pos) /**< (HSTPIPIFR) Short Packet Interrupt Set Mask */ -#define HSTPIPIFR_NBUSYBKS_Pos 12 /**< (HSTPIPIFR) Number of Busy Banks Set Position */ -#define HSTPIPIFR_NBUSYBKS (_U_(0x1) << HSTPIPIFR_NBUSYBKS_Pos) /**< (HSTPIPIFR) Number of Busy Banks Set Mask */ -#define HSTPIPIFR_Msk _U_(0x10BB) /**< (HSTPIPIFR) Register Mask */ - -/* CTRL mode */ -#define HSTPIPIFR_CTRL_TXSTPIS_Pos 2 /**< (HSTPIPIFR) Transmitted SETUP Interrupt Set Position */ -#define HSTPIPIFR_CTRL_TXSTPIS (_U_(0x1) << HSTPIPIFR_CTRL_TXSTPIS_Pos) /**< (HSTPIPIFR) Transmitted SETUP Interrupt Set Mask */ -#define HSTPIPIFR_CTRL_RXSTALLDIS_Pos 6 /**< (HSTPIPIFR) Received STALLed Interrupt Set Position */ -#define HSTPIPIFR_CTRL_RXSTALLDIS (_U_(0x1) << HSTPIPIFR_CTRL_RXSTALLDIS_Pos) /**< (HSTPIPIFR) Received STALLed Interrupt Set Mask */ -#define HSTPIPIFR_CTRL_Msk _U_(0x44) /**< (HSTPIPIFR_CTRL) Register Mask */ - -/* ISO mode */ -#define HSTPIPIFR_ISO_UNDERFIS_Pos 2 /**< (HSTPIPIFR) Underflow Interrupt Set Position */ -#define HSTPIPIFR_ISO_UNDERFIS (_U_(0x1) << HSTPIPIFR_ISO_UNDERFIS_Pos) /**< (HSTPIPIFR) Underflow Interrupt Set Mask */ -#define HSTPIPIFR_ISO_CRCERRIS_Pos 6 /**< (HSTPIPIFR) CRC Error Interrupt Set Position */ -#define HSTPIPIFR_ISO_CRCERRIS (_U_(0x1) << HSTPIPIFR_ISO_CRCERRIS_Pos) /**< (HSTPIPIFR) CRC Error Interrupt Set Mask */ -#define HSTPIPIFR_ISO_Msk _U_(0x44) /**< (HSTPIPIFR_ISO) Register Mask */ - -/* BLK mode */ -#define HSTPIPIFR_BLK_TXSTPIS_Pos 2 /**< (HSTPIPIFR) Transmitted SETUP Interrupt Set Position */ -#define HSTPIPIFR_BLK_TXSTPIS (_U_(0x1) << HSTPIPIFR_BLK_TXSTPIS_Pos) /**< (HSTPIPIFR) Transmitted SETUP Interrupt Set Mask */ -#define HSTPIPIFR_BLK_RXSTALLDIS_Pos 6 /**< (HSTPIPIFR) Received STALLed Interrupt Set Position */ -#define HSTPIPIFR_BLK_RXSTALLDIS (_U_(0x1) << HSTPIPIFR_BLK_RXSTALLDIS_Pos) /**< (HSTPIPIFR) Received STALLed Interrupt Set Mask */ -#define HSTPIPIFR_BLK_Msk _U_(0x44) /**< (HSTPIPIFR_BLK) Register Mask */ - -/* INTRPT mode */ -#define HSTPIPIFR_INTRPT_UNDERFIS_Pos 2 /**< (HSTPIPIFR) Underflow Interrupt Set Position */ -#define HSTPIPIFR_INTRPT_UNDERFIS (_U_(0x1) << HSTPIPIFR_INTRPT_UNDERFIS_Pos) /**< (HSTPIPIFR) Underflow Interrupt Set Mask */ -#define HSTPIPIFR_INTRPT_RXSTALLDIS_Pos 6 /**< (HSTPIPIFR) Received STALLed Interrupt Set Position */ -#define HSTPIPIFR_INTRPT_RXSTALLDIS (_U_(0x1) << HSTPIPIFR_INTRPT_RXSTALLDIS_Pos) /**< (HSTPIPIFR) Received STALLed Interrupt Set Mask */ -#define HSTPIPIFR_INTRPT_Msk _U_(0x44) /**< (HSTPIPIFR_INTRPT) Register Mask */ - - -/* -------- HSTPIPIMR : (USBHS Offset: 0x5c0) (R/ 32) Host Pipe Mask Register -------- */ - -#define HSTPIPIMR_OFFSET (0x5C0) /**< (HSTPIPIMR) Host Pipe Mask Register Offset */ - -#define HSTPIPIMR_RXINE_Pos 0 /**< (HSTPIPIMR) Received IN Data Interrupt Enable Position */ -#define HSTPIPIMR_RXINE (_U_(0x1) << HSTPIPIMR_RXINE_Pos) /**< (HSTPIPIMR) Received IN Data Interrupt Enable Mask */ -#define HSTPIPIMR_TXOUTE_Pos 1 /**< (HSTPIPIMR) Transmitted OUT Data Interrupt Enable Position */ -#define HSTPIPIMR_TXOUTE (_U_(0x1) << HSTPIPIMR_TXOUTE_Pos) /**< (HSTPIPIMR) Transmitted OUT Data Interrupt Enable Mask */ -#define HSTPIPIMR_PERRE_Pos 3 /**< (HSTPIPIMR) Pipe Error Interrupt Enable Position */ -#define HSTPIPIMR_PERRE (_U_(0x1) << HSTPIPIMR_PERRE_Pos) /**< (HSTPIPIMR) Pipe Error Interrupt Enable Mask */ -#define HSTPIPIMR_NAKEDE_Pos 4 /**< (HSTPIPIMR) NAKed Interrupt Enable Position */ -#define HSTPIPIMR_NAKEDE (_U_(0x1) << HSTPIPIMR_NAKEDE_Pos) /**< (HSTPIPIMR) NAKed Interrupt Enable Mask */ -#define HSTPIPIMR_OVERFIE_Pos 5 /**< (HSTPIPIMR) Overflow Interrupt Enable Position */ -#define HSTPIPIMR_OVERFIE (_U_(0x1) << HSTPIPIMR_OVERFIE_Pos) /**< (HSTPIPIMR) Overflow Interrupt Enable Mask */ -#define HSTPIPIMR_SHORTPACKETIE_Pos 7 /**< (HSTPIPIMR) Short Packet Interrupt Enable Position */ -#define HSTPIPIMR_SHORTPACKETIE (_U_(0x1) << HSTPIPIMR_SHORTPACKETIE_Pos) /**< (HSTPIPIMR) Short Packet Interrupt Enable Mask */ -#define HSTPIPIMR_NBUSYBKE_Pos 12 /**< (HSTPIPIMR) Number of Busy Banks Interrupt Enable Position */ -#define HSTPIPIMR_NBUSYBKE (_U_(0x1) << HSTPIPIMR_NBUSYBKE_Pos) /**< (HSTPIPIMR) Number of Busy Banks Interrupt Enable Mask */ -#define HSTPIPIMR_FIFOCON_Pos 14 /**< (HSTPIPIMR) FIFO Control Position */ -#define HSTPIPIMR_FIFOCON (_U_(0x1) << HSTPIPIMR_FIFOCON_Pos) /**< (HSTPIPIMR) FIFO Control Mask */ -#define HSTPIPIMR_PDISHDMA_Pos 16 /**< (HSTPIPIMR) Pipe Interrupts Disable HDMA Request Enable Position */ -#define HSTPIPIMR_PDISHDMA (_U_(0x1) << HSTPIPIMR_PDISHDMA_Pos) /**< (HSTPIPIMR) Pipe Interrupts Disable HDMA Request Enable Mask */ -#define HSTPIPIMR_PFREEZE_Pos 17 /**< (HSTPIPIMR) Pipe Freeze Position */ -#define HSTPIPIMR_PFREEZE (_U_(0x1) << HSTPIPIMR_PFREEZE_Pos) /**< (HSTPIPIMR) Pipe Freeze Mask */ -#define HSTPIPIMR_RSTDT_Pos 18 /**< (HSTPIPIMR) Reset Data Toggle Position */ -#define HSTPIPIMR_RSTDT (_U_(0x1) << HSTPIPIMR_RSTDT_Pos) /**< (HSTPIPIMR) Reset Data Toggle Mask */ -#define HSTPIPIMR_Msk _U_(0x750BB) /**< (HSTPIPIMR) Register Mask */ - -/* CTRL mode */ -#define HSTPIPIMR_CTRL_TXSTPE_Pos 2 /**< (HSTPIPIMR) Transmitted SETUP Interrupt Enable Position */ -#define HSTPIPIMR_CTRL_TXSTPE (_U_(0x1) << HSTPIPIMR_CTRL_TXSTPE_Pos) /**< (HSTPIPIMR) Transmitted SETUP Interrupt Enable Mask */ -#define HSTPIPIMR_CTRL_RXSTALLDE_Pos 6 /**< (HSTPIPIMR) Received STALLed Interrupt Enable Position */ -#define HSTPIPIMR_CTRL_RXSTALLDE (_U_(0x1) << HSTPIPIMR_CTRL_RXSTALLDE_Pos) /**< (HSTPIPIMR) Received STALLed Interrupt Enable Mask */ -#define HSTPIPIMR_CTRL_Msk _U_(0x44) /**< (HSTPIPIMR_CTRL) Register Mask */ - -/* ISO mode */ -#define HSTPIPIMR_ISO_UNDERFIE_Pos 2 /**< (HSTPIPIMR) Underflow Interrupt Enable Position */ -#define HSTPIPIMR_ISO_UNDERFIE (_U_(0x1) << HSTPIPIMR_ISO_UNDERFIE_Pos) /**< (HSTPIPIMR) Underflow Interrupt Enable Mask */ -#define HSTPIPIMR_ISO_CRCERRE_Pos 6 /**< (HSTPIPIMR) CRC Error Interrupt Enable Position */ -#define HSTPIPIMR_ISO_CRCERRE (_U_(0x1) << HSTPIPIMR_ISO_CRCERRE_Pos) /**< (HSTPIPIMR) CRC Error Interrupt Enable Mask */ -#define HSTPIPIMR_ISO_Msk _U_(0x44) /**< (HSTPIPIMR_ISO) Register Mask */ - -/* BLK mode */ -#define HSTPIPIMR_BLK_TXSTPE_Pos 2 /**< (HSTPIPIMR) Transmitted SETUP Interrupt Enable Position */ -#define HSTPIPIMR_BLK_TXSTPE (_U_(0x1) << HSTPIPIMR_BLK_TXSTPE_Pos) /**< (HSTPIPIMR) Transmitted SETUP Interrupt Enable Mask */ -#define HSTPIPIMR_BLK_RXSTALLDE_Pos 6 /**< (HSTPIPIMR) Received STALLed Interrupt Enable Position */ -#define HSTPIPIMR_BLK_RXSTALLDE (_U_(0x1) << HSTPIPIMR_BLK_RXSTALLDE_Pos) /**< (HSTPIPIMR) Received STALLed Interrupt Enable Mask */ -#define HSTPIPIMR_BLK_Msk _U_(0x44) /**< (HSTPIPIMR_BLK) Register Mask */ - -/* INTRPT mode */ -#define HSTPIPIMR_INTRPT_UNDERFIE_Pos 2 /**< (HSTPIPIMR) Underflow Interrupt Enable Position */ -#define HSTPIPIMR_INTRPT_UNDERFIE (_U_(0x1) << HSTPIPIMR_INTRPT_UNDERFIE_Pos) /**< (HSTPIPIMR) Underflow Interrupt Enable Mask */ -#define HSTPIPIMR_INTRPT_RXSTALLDE_Pos 6 /**< (HSTPIPIMR) Received STALLed Interrupt Enable Position */ -#define HSTPIPIMR_INTRPT_RXSTALLDE (_U_(0x1) << HSTPIPIMR_INTRPT_RXSTALLDE_Pos) /**< (HSTPIPIMR) Received STALLed Interrupt Enable Mask */ -#define HSTPIPIMR_INTRPT_Msk _U_(0x44) /**< (HSTPIPIMR_INTRPT) Register Mask */ - - -/* -------- HSTPIPIER : (USBHS Offset: 0x5f0) (/W 32) Host Pipe Enable Register -------- */ - -#define HSTPIPIER_OFFSET (0x5F0) /**< (HSTPIPIER) Host Pipe Enable Register Offset */ - -#define HSTPIPIER_RXINES_Pos 0 /**< (HSTPIPIER) Received IN Data Interrupt Enable Position */ -#define HSTPIPIER_RXINES (_U_(0x1) << HSTPIPIER_RXINES_Pos) /**< (HSTPIPIER) Received IN Data Interrupt Enable Mask */ -#define HSTPIPIER_TXOUTES_Pos 1 /**< (HSTPIPIER) Transmitted OUT Data Interrupt Enable Position */ -#define HSTPIPIER_TXOUTES (_U_(0x1) << HSTPIPIER_TXOUTES_Pos) /**< (HSTPIPIER) Transmitted OUT Data Interrupt Enable Mask */ -#define HSTPIPIER_PERRES_Pos 3 /**< (HSTPIPIER) Pipe Error Interrupt Enable Position */ -#define HSTPIPIER_PERRES (_U_(0x1) << HSTPIPIER_PERRES_Pos) /**< (HSTPIPIER) Pipe Error Interrupt Enable Mask */ -#define HSTPIPIER_NAKEDES_Pos 4 /**< (HSTPIPIER) NAKed Interrupt Enable Position */ -#define HSTPIPIER_NAKEDES (_U_(0x1) << HSTPIPIER_NAKEDES_Pos) /**< (HSTPIPIER) NAKed Interrupt Enable Mask */ -#define HSTPIPIER_OVERFIES_Pos 5 /**< (HSTPIPIER) Overflow Interrupt Enable Position */ -#define HSTPIPIER_OVERFIES (_U_(0x1) << HSTPIPIER_OVERFIES_Pos) /**< (HSTPIPIER) Overflow Interrupt Enable Mask */ -#define HSTPIPIER_SHORTPACKETIES_Pos 7 /**< (HSTPIPIER) Short Packet Interrupt Enable Position */ -#define HSTPIPIER_SHORTPACKETIES (_U_(0x1) << HSTPIPIER_SHORTPACKETIES_Pos) /**< (HSTPIPIER) Short Packet Interrupt Enable Mask */ -#define HSTPIPIER_NBUSYBKES_Pos 12 /**< (HSTPIPIER) Number of Busy Banks Enable Position */ -#define HSTPIPIER_NBUSYBKES (_U_(0x1) << HSTPIPIER_NBUSYBKES_Pos) /**< (HSTPIPIER) Number of Busy Banks Enable Mask */ -#define HSTPIPIER_PDISHDMAS_Pos 16 /**< (HSTPIPIER) Pipe Interrupts Disable HDMA Request Enable Position */ -#define HSTPIPIER_PDISHDMAS (_U_(0x1) << HSTPIPIER_PDISHDMAS_Pos) /**< (HSTPIPIER) Pipe Interrupts Disable HDMA Request Enable Mask */ -#define HSTPIPIER_PFREEZES_Pos 17 /**< (HSTPIPIER) Pipe Freeze Enable Position */ -#define HSTPIPIER_PFREEZES (_U_(0x1) << HSTPIPIER_PFREEZES_Pos) /**< (HSTPIPIER) Pipe Freeze Enable Mask */ -#define HSTPIPIER_RSTDTS_Pos 18 /**< (HSTPIPIER) Reset Data Toggle Enable Position */ -#define HSTPIPIER_RSTDTS (_U_(0x1) << HSTPIPIER_RSTDTS_Pos) /**< (HSTPIPIER) Reset Data Toggle Enable Mask */ -#define HSTPIPIER_Msk _U_(0x710BB) /**< (HSTPIPIER) Register Mask */ - -/* CTRL mode */ -#define HSTPIPIER_CTRL_TXSTPES_Pos 2 /**< (HSTPIPIER) Transmitted SETUP Interrupt Enable Position */ -#define HSTPIPIER_CTRL_TXSTPES (_U_(0x1) << HSTPIPIER_CTRL_TXSTPES_Pos) /**< (HSTPIPIER) Transmitted SETUP Interrupt Enable Mask */ -#define HSTPIPIER_CTRL_RXSTALLDES_Pos 6 /**< (HSTPIPIER) Received STALLed Interrupt Enable Position */ -#define HSTPIPIER_CTRL_RXSTALLDES (_U_(0x1) << HSTPIPIER_CTRL_RXSTALLDES_Pos) /**< (HSTPIPIER) Received STALLed Interrupt Enable Mask */ -#define HSTPIPIER_CTRL_Msk _U_(0x44) /**< (HSTPIPIER_CTRL) Register Mask */ - -/* ISO mode */ -#define HSTPIPIER_ISO_UNDERFIES_Pos 2 /**< (HSTPIPIER) Underflow Interrupt Enable Position */ -#define HSTPIPIER_ISO_UNDERFIES (_U_(0x1) << HSTPIPIER_ISO_UNDERFIES_Pos) /**< (HSTPIPIER) Underflow Interrupt Enable Mask */ -#define HSTPIPIER_ISO_CRCERRES_Pos 6 /**< (HSTPIPIER) CRC Error Interrupt Enable Position */ -#define HSTPIPIER_ISO_CRCERRES (_U_(0x1) << HSTPIPIER_ISO_CRCERRES_Pos) /**< (HSTPIPIER) CRC Error Interrupt Enable Mask */ -#define HSTPIPIER_ISO_Msk _U_(0x44) /**< (HSTPIPIER_ISO) Register Mask */ - -/* BLK mode */ -#define HSTPIPIER_BLK_TXSTPES_Pos 2 /**< (HSTPIPIER) Transmitted SETUP Interrupt Enable Position */ -#define HSTPIPIER_BLK_TXSTPES (_U_(0x1) << HSTPIPIER_BLK_TXSTPES_Pos) /**< (HSTPIPIER) Transmitted SETUP Interrupt Enable Mask */ -#define HSTPIPIER_BLK_RXSTALLDES_Pos 6 /**< (HSTPIPIER) Received STALLed Interrupt Enable Position */ -#define HSTPIPIER_BLK_RXSTALLDES (_U_(0x1) << HSTPIPIER_BLK_RXSTALLDES_Pos) /**< (HSTPIPIER) Received STALLed Interrupt Enable Mask */ -#define HSTPIPIER_BLK_Msk _U_(0x44) /**< (HSTPIPIER_BLK) Register Mask */ - -/* INTRPT mode */ -#define HSTPIPIER_INTRPT_UNDERFIES_Pos 2 /**< (HSTPIPIER) Underflow Interrupt Enable Position */ -#define HSTPIPIER_INTRPT_UNDERFIES (_U_(0x1) << HSTPIPIER_INTRPT_UNDERFIES_Pos) /**< (HSTPIPIER) Underflow Interrupt Enable Mask */ -#define HSTPIPIER_INTRPT_RXSTALLDES_Pos 6 /**< (HSTPIPIER) Received STALLed Interrupt Enable Position */ -#define HSTPIPIER_INTRPT_RXSTALLDES (_U_(0x1) << HSTPIPIER_INTRPT_RXSTALLDES_Pos) /**< (HSTPIPIER) Received STALLed Interrupt Enable Mask */ -#define HSTPIPIER_INTRPT_Msk _U_(0x44) /**< (HSTPIPIER_INTRPT) Register Mask */ - - -/* -------- HSTPIPIDR : (USBHS Offset: 0x620) (/W 32) Host Pipe Disable Register -------- */ - -#define HSTPIPIDR_OFFSET (0x620) /**< (HSTPIPIDR) Host Pipe Disable Register Offset */ - -#define HSTPIPIDR_RXINEC_Pos 0 /**< (HSTPIPIDR) Received IN Data Interrupt Disable Position */ -#define HSTPIPIDR_RXINEC (_U_(0x1) << HSTPIPIDR_RXINEC_Pos) /**< (HSTPIPIDR) Received IN Data Interrupt Disable Mask */ -#define HSTPIPIDR_TXOUTEC_Pos 1 /**< (HSTPIPIDR) Transmitted OUT Data Interrupt Disable Position */ -#define HSTPIPIDR_TXOUTEC (_U_(0x1) << HSTPIPIDR_TXOUTEC_Pos) /**< (HSTPIPIDR) Transmitted OUT Data Interrupt Disable Mask */ -#define HSTPIPIDR_PERREC_Pos 3 /**< (HSTPIPIDR) Pipe Error Interrupt Disable Position */ -#define HSTPIPIDR_PERREC (_U_(0x1) << HSTPIPIDR_PERREC_Pos) /**< (HSTPIPIDR) Pipe Error Interrupt Disable Mask */ -#define HSTPIPIDR_NAKEDEC_Pos 4 /**< (HSTPIPIDR) NAKed Interrupt Disable Position */ -#define HSTPIPIDR_NAKEDEC (_U_(0x1) << HSTPIPIDR_NAKEDEC_Pos) /**< (HSTPIPIDR) NAKed Interrupt Disable Mask */ -#define HSTPIPIDR_OVERFIEC_Pos 5 /**< (HSTPIPIDR) Overflow Interrupt Disable Position */ -#define HSTPIPIDR_OVERFIEC (_U_(0x1) << HSTPIPIDR_OVERFIEC_Pos) /**< (HSTPIPIDR) Overflow Interrupt Disable Mask */ -#define HSTPIPIDR_SHORTPACKETIEC_Pos 7 /**< (HSTPIPIDR) Short Packet Interrupt Disable Position */ -#define HSTPIPIDR_SHORTPACKETIEC (_U_(0x1) << HSTPIPIDR_SHORTPACKETIEC_Pos) /**< (HSTPIPIDR) Short Packet Interrupt Disable Mask */ -#define HSTPIPIDR_NBUSYBKEC_Pos 12 /**< (HSTPIPIDR) Number of Busy Banks Disable Position */ -#define HSTPIPIDR_NBUSYBKEC (_U_(0x1) << HSTPIPIDR_NBUSYBKEC_Pos) /**< (HSTPIPIDR) Number of Busy Banks Disable Mask */ -#define HSTPIPIDR_FIFOCONC_Pos 14 /**< (HSTPIPIDR) FIFO Control Disable Position */ -#define HSTPIPIDR_FIFOCONC (_U_(0x1) << HSTPIPIDR_FIFOCONC_Pos) /**< (HSTPIPIDR) FIFO Control Disable Mask */ -#define HSTPIPIDR_PDISHDMAC_Pos 16 /**< (HSTPIPIDR) Pipe Interrupts Disable HDMA Request Disable Position */ -#define HSTPIPIDR_PDISHDMAC (_U_(0x1) << HSTPIPIDR_PDISHDMAC_Pos) /**< (HSTPIPIDR) Pipe Interrupts Disable HDMA Request Disable Mask */ -#define HSTPIPIDR_PFREEZEC_Pos 17 /**< (HSTPIPIDR) Pipe Freeze Disable Position */ -#define HSTPIPIDR_PFREEZEC (_U_(0x1) << HSTPIPIDR_PFREEZEC_Pos) /**< (HSTPIPIDR) Pipe Freeze Disable Mask */ -#define HSTPIPIDR_Msk _U_(0x350BB) /**< (HSTPIPIDR) Register Mask */ - -/* CTRL mode */ -#define HSTPIPIDR_CTRL_TXSTPEC_Pos 2 /**< (HSTPIPIDR) Transmitted SETUP Interrupt Disable Position */ -#define HSTPIPIDR_CTRL_TXSTPEC (_U_(0x1) << HSTPIPIDR_CTRL_TXSTPEC_Pos) /**< (HSTPIPIDR) Transmitted SETUP Interrupt Disable Mask */ -#define HSTPIPIDR_CTRL_RXSTALLDEC_Pos 6 /**< (HSTPIPIDR) Received STALLed Interrupt Disable Position */ -#define HSTPIPIDR_CTRL_RXSTALLDEC (_U_(0x1) << HSTPIPIDR_CTRL_RXSTALLDEC_Pos) /**< (HSTPIPIDR) Received STALLed Interrupt Disable Mask */ -#define HSTPIPIDR_CTRL_Msk _U_(0x44) /**< (HSTPIPIDR_CTRL) Register Mask */ - -/* ISO mode */ -#define HSTPIPIDR_ISO_UNDERFIEC_Pos 2 /**< (HSTPIPIDR) Underflow Interrupt Disable Position */ -#define HSTPIPIDR_ISO_UNDERFIEC (_U_(0x1) << HSTPIPIDR_ISO_UNDERFIEC_Pos) /**< (HSTPIPIDR) Underflow Interrupt Disable Mask */ -#define HSTPIPIDR_ISO_CRCERREC_Pos 6 /**< (HSTPIPIDR) CRC Error Interrupt Disable Position */ -#define HSTPIPIDR_ISO_CRCERREC (_U_(0x1) << HSTPIPIDR_ISO_CRCERREC_Pos) /**< (HSTPIPIDR) CRC Error Interrupt Disable Mask */ -#define HSTPIPIDR_ISO_Msk _U_(0x44) /**< (HSTPIPIDR_ISO) Register Mask */ - -/* BLK mode */ -#define HSTPIPIDR_BLK_TXSTPEC_Pos 2 /**< (HSTPIPIDR) Transmitted SETUP Interrupt Disable Position */ -#define HSTPIPIDR_BLK_TXSTPEC (_U_(0x1) << HSTPIPIDR_BLK_TXSTPEC_Pos) /**< (HSTPIPIDR) Transmitted SETUP Interrupt Disable Mask */ -#define HSTPIPIDR_BLK_RXSTALLDEC_Pos 6 /**< (HSTPIPIDR) Received STALLed Interrupt Disable Position */ -#define HSTPIPIDR_BLK_RXSTALLDEC (_U_(0x1) << HSTPIPIDR_BLK_RXSTALLDEC_Pos) /**< (HSTPIPIDR) Received STALLed Interrupt Disable Mask */ -#define HSTPIPIDR_BLK_Msk _U_(0x44) /**< (HSTPIPIDR_BLK) Register Mask */ - -/* INTRPT mode */ -#define HSTPIPIDR_INTRPT_UNDERFIEC_Pos 2 /**< (HSTPIPIDR) Underflow Interrupt Disable Position */ -#define HSTPIPIDR_INTRPT_UNDERFIEC (_U_(0x1) << HSTPIPIDR_INTRPT_UNDERFIEC_Pos) /**< (HSTPIPIDR) Underflow Interrupt Disable Mask */ -#define HSTPIPIDR_INTRPT_RXSTALLDEC_Pos 6 /**< (HSTPIPIDR) Received STALLed Interrupt Disable Position */ -#define HSTPIPIDR_INTRPT_RXSTALLDEC (_U_(0x1) << HSTPIPIDR_INTRPT_RXSTALLDEC_Pos) /**< (HSTPIPIDR) Received STALLed Interrupt Disable Mask */ -#define HSTPIPIDR_INTRPT_Msk _U_(0x44) /**< (HSTPIPIDR_INTRPT) Register Mask */ - - -/* -------- HSTPIPINRQ : (USBHS Offset: 0x650) (R/W 32) Host Pipe IN Request Register -------- */ - -#define HSTPIPINRQ_OFFSET (0x650) /**< (HSTPIPINRQ) Host Pipe IN Request Register Offset */ - -#define HSTPIPINRQ_INRQ_Pos 0 /**< (HSTPIPINRQ) IN Request Number before Freeze Position */ -#define HSTPIPINRQ_INRQ (_U_(0xFF) << HSTPIPINRQ_INRQ_Pos) /**< (HSTPIPINRQ) IN Request Number before Freeze Mask */ -#define HSTPIPINRQ_INMODE_Pos 8 /**< (HSTPIPINRQ) IN Request Mode Position */ -#define HSTPIPINRQ_INMODE (_U_(0x1) << HSTPIPINRQ_INMODE_Pos) /**< (HSTPIPINRQ) IN Request Mode Mask */ -#define HSTPIPINRQ_Msk _U_(0x1FF) /**< (HSTPIPINRQ) Register Mask */ - - -/* -------- HSTPIPERR : (USBHS Offset: 0x680) (R/W 32) Host Pipe Error Register -------- */ - -#define HSTPIPERR_OFFSET (0x680) /**< (HSTPIPERR) Host Pipe Error Register Offset */ - -#define HSTPIPERR_DATATGL_Pos 0 /**< (HSTPIPERR) Data Toggle Error Position */ -#define HSTPIPERR_DATATGL (_U_(0x1) << HSTPIPERR_DATATGL_Pos) /**< (HSTPIPERR) Data Toggle Error Mask */ -#define HSTPIPERR_DATAPID_Pos 1 /**< (HSTPIPERR) Data PID Error Position */ -#define HSTPIPERR_DATAPID (_U_(0x1) << HSTPIPERR_DATAPID_Pos) /**< (HSTPIPERR) Data PID Error Mask */ -#define HSTPIPERR_PID_Pos 2 /**< (HSTPIPERR) Data PID Error Position */ -#define HSTPIPERR_PID (_U_(0x1) << HSTPIPERR_PID_Pos) /**< (HSTPIPERR) Data PID Error Mask */ -#define HSTPIPERR_TIMEOUT_Pos 3 /**< (HSTPIPERR) Time-Out Error Position */ -#define HSTPIPERR_TIMEOUT (_U_(0x1) << HSTPIPERR_TIMEOUT_Pos) /**< (HSTPIPERR) Time-Out Error Mask */ -#define HSTPIPERR_CRC16_Pos 4 /**< (HSTPIPERR) CRC16 Error Position */ -#define HSTPIPERR_CRC16 (_U_(0x1) << HSTPIPERR_CRC16_Pos) /**< (HSTPIPERR) CRC16 Error Mask */ -#define HSTPIPERR_COUNTER_Pos 5 /**< (HSTPIPERR) Error Counter Position */ -#define HSTPIPERR_COUNTER (_U_(0x3) << HSTPIPERR_COUNTER_Pos) /**< (HSTPIPERR) Error Counter Mask */ -#define HSTPIPERR_Msk _U_(0x7F) /**< (HSTPIPERR) Register Mask */ - -#define HSTPIPERR_CRC_Pos 4 /**< (HSTPIPERR Position) CRCx6 Error */ -#define HSTPIPERR_CRC (_U_(0x1) << HSTPIPERR_CRC_Pos) /**< (HSTPIPERR Mask) CRC */ - -/* -------- CTRL : (USBHS Offset: 0x800) (R/W 32) General Control Register -------- */ - -#define CTRL_OFFSET (0x800) /**< (CTRL) General Control Register Offset */ - -#define CTRL_RDERRE_Pos 4 /**< (CTRL) Remote Device Connection Error Interrupt Enable Position */ -#define CTRL_RDERRE (_U_(0x1) << CTRL_RDERRE_Pos) /**< (CTRL) Remote Device Connection Error Interrupt Enable Mask */ -#define CTRL_VBUSHWC_Pos 8 /**< (CTRL) VBUS Hardware Control Position */ -#define CTRL_VBUSHWC (_U_(0x1) << CTRL_VBUSHWC_Pos) /**< (CTRL) VBUS Hardware Control Mask */ -#define CTRL_FRZCLK_Pos 14 /**< (CTRL) Freeze USB Clock Position */ -#define CTRL_FRZCLK (_U_(0x1) << CTRL_FRZCLK_Pos) /**< (CTRL) Freeze USB Clock Mask */ -#define CTRL_USBE_Pos 15 /**< (CTRL) USBHS Enable Position */ -#define CTRL_USBE (_U_(0x1) << CTRL_USBE_Pos) /**< (CTRL) USBHS Enable Mask */ -#define CTRL_UID_Pos 24 /**< (CTRL) UID Pin Enable Position */ -#define CTRL_UID (_U_(0x1) << CTRL_UID_Pos) /**< (CTRL) UID Pin Enable Mask */ -#define CTRL_UIMOD_Pos 25 /**< (CTRL) USBHS Mode Position */ -#define CTRL_UIMOD (_U_(0x1) << CTRL_UIMOD_Pos) /**< (CTRL) USBHS Mode Mask */ -#define CTRL_UIMOD_HOST_Val _U_(0x0) /**< (CTRL) The module is in USB Host mode. */ -#define CTRL_UIMOD_DEVICE_Val _U_(0x1) /**< (CTRL) The module is in USB Device mode. */ -#define CTRL_UIMOD_HOST (CTRL_UIMOD_HOST_Val << CTRL_UIMOD_Pos) /**< (CTRL) The module is in USB Host mode. Position */ -#define CTRL_UIMOD_DEVICE (CTRL_UIMOD_DEVICE_Val << CTRL_UIMOD_Pos) /**< (CTRL) The module is in USB Device mode. Position */ -#define CTRL_Msk _U_(0x300C110) /**< (CTRL) Register Mask */ - - -/* -------- SR : (USBHS Offset: 0x804) (R/ 32) General Status Register -------- */ - -#define SR_OFFSET (0x804) /**< (SR) General Status Register Offset */ - -#define SR_RDERRI_Pos 4 /**< (SR) Remote Device Connection Error Interrupt (Host mode only) Position */ -#define SR_RDERRI (_U_(0x1) << SR_RDERRI_Pos) /**< (SR) Remote Device Connection Error Interrupt (Host mode only) Mask */ -#define SR_SPEED_Pos 12 /**< (SR) Speed Status (Device mode only) Position */ -#define SR_SPEED (_U_(0x3) << SR_SPEED_Pos) /**< (SR) Speed Status (Device mode only) Mask */ -#define SR_SPEED_FULL_SPEED_Val _U_(0x0) /**< (SR) Full-Speed mode */ -#define SR_SPEED_HIGH_SPEED_Val _U_(0x1) /**< (SR) High-Speed mode */ -#define SR_SPEED_LOW_SPEED_Val _U_(0x2) /**< (SR) Low-Speed mode */ -#define SR_SPEED_FULL_SPEED (SR_SPEED_FULL_SPEED_Val << SR_SPEED_Pos) /**< (SR) Full-Speed mode Position */ -#define SR_SPEED_HIGH_SPEED (SR_SPEED_HIGH_SPEED_Val << SR_SPEED_Pos) /**< (SR) High-Speed mode Position */ -#define SR_SPEED_LOW_SPEED (SR_SPEED_LOW_SPEED_Val << SR_SPEED_Pos) /**< (SR) Low-Speed mode Position */ -#define SR_CLKUSABLE_Pos 14 /**< (SR) UTMI Clock Usable Position */ -#define SR_CLKUSABLE (_U_(0x1) << SR_CLKUSABLE_Pos) /**< (SR) UTMI Clock Usable Mask */ -#define SR_Msk _U_(0x7010) /**< (SR) Register Mask */ - - -/* -------- SCR : (USBHS Offset: 0x808) (/W 32) General Status Clear Register -------- */ - -#define SCR_OFFSET (0x808) /**< (SCR) General Status Clear Register Offset */ - -#define SCR_RDERRIC_Pos 4 /**< (SCR) Remote Device Connection Error Interrupt Clear Position */ -#define SCR_RDERRIC (_U_(0x1) << SCR_RDERRIC_Pos) /**< (SCR) Remote Device Connection Error Interrupt Clear Mask */ -#define SCR_Msk _U_(0x10) /**< (SCR) Register Mask */ - - -/* -------- SFR : (USBHS Offset: 0x80c) (/W 32) General Status Set Register -------- */ - -#define SFR_OFFSET (0x80C) /**< (SFR) General Status Set Register Offset */ - -#define SFR_RDERRIS_Pos 4 /**< (SFR) Remote Device Connection Error Interrupt Set Position */ -#define SFR_RDERRIS (_U_(0x1) << SFR_RDERRIS_Pos) /**< (SFR) Remote Device Connection Error Interrupt Set Mask */ -#define SFR_VBUSRQS_Pos 9 /**< (SFR) VBUS Request Set Position */ -#define SFR_VBUSRQS (_U_(0x1) << SFR_VBUSRQS_Pos) /**< (SFR) VBUS Request Set Mask */ -#define SFR_Msk _U_(0x210) /**< (SFR) Register Mask */ - - -/** \brief DEVDMA hardware registers */ -typedef struct -{ - __IO uint32_t DEVDMANXTDSC; /**< (DEVDMA Offset: 0x00) Device DMA Channel Next Descriptor Address Register */ - __IO uint32_t DEVDMAADDRESS; /**< (DEVDMA Offset: 0x04) Device DMA Channel Address Register */ - __IO uint32_t DEVDMACONTROL; /**< (DEVDMA Offset: 0x08) Device DMA Channel Control Register */ - __IO uint32_t DEVDMASTATUS; /**< (DEVDMA Offset: 0x0C) Device DMA Channel Status Register */ -} devdma_t; - -/** \brief HSTDMA hardware registers */ -typedef struct -{ - __IO uint32_t HSTDMANXTDSC; /**< (HSTDMA Offset: 0x00) Host DMA Channel Next Descriptor Address Register */ - __IO uint32_t HSTDMAADDRESS; /**< (HSTDMA Offset: 0x04) Host DMA Channel Address Register */ - __IO uint32_t HSTDMACONTROL; /**< (HSTDMA Offset: 0x08) Host DMA Channel Control Register */ - __IO uint32_t HSTDMASTATUS; /**< (HSTDMA Offset: 0x0C) Host DMA Channel Status Register */ -} hstdma_t; - -/** \brief USBHS hardware registers */ -typedef struct -{ - __IO uint32_t DEVCTRL; /**< (USBHS Offset: 0x00) Device General Control Register */ - __I uint32_t DEVISR; /**< (USBHS Offset: 0x04) Device Global Interrupt Status Register */ - __O uint32_t DEVICR; /**< (USBHS Offset: 0x08) Device Global Interrupt Clear Register */ - __O uint32_t DEVIFR; /**< (USBHS Offset: 0x0C) Device Global Interrupt Set Register */ - __I uint32_t DEVIMR; /**< (USBHS Offset: 0x10) Device Global Interrupt Mask Register */ - __O uint32_t DEVIDR; /**< (USBHS Offset: 0x14) Device Global Interrupt Disable Register */ - __O uint32_t DEVIER; /**< (USBHS Offset: 0x18) Device Global Interrupt Enable Register */ - __IO uint32_t DEVEPT; /**< (USBHS Offset: 0x1C) Device Endpoint Register */ - __I uint32_t DEVFNUM; /**< (USBHS Offset: 0x20) Device Frame Number Register */ - __I uint8_t Reserved1[220]; - __IO uint32_t DEVEPTCFG[10]; /**< (USBHS Offset: 0x100) Device Endpoint Configuration Register */ - __I uint8_t Reserved2[8]; - __I uint32_t DEVEPTISR[10]; /**< (USBHS Offset: 0x130) Device Endpoint Interrupt Status Register */ - __I uint8_t Reserved3[8]; - __O uint32_t DEVEPTICR[10]; /**< (USBHS Offset: 0x160) Device Endpoint Interrupt Clear Register */ - __I uint8_t Reserved4[8]; - __O uint32_t DEVEPTIFR[10]; /**< (USBHS Offset: 0x190) Device Endpoint Interrupt Set Register */ - __I uint8_t Reserved5[8]; - __I uint32_t DEVEPTIMR[10]; /**< (USBHS Offset: 0x1C0) Device Endpoint Interrupt Mask Register */ - __I uint8_t Reserved6[8]; - __O uint32_t DEVEPTIER[10]; /**< (USBHS Offset: 0x1F0) Device Endpoint Interrupt Enable Register */ - __I uint8_t Reserved7[8]; - __O uint32_t DEVEPTIDR[10]; /**< (USBHS Offset: 0x220) Device Endpoint Interrupt Disable Register */ - __I uint8_t Reserved8[200]; - devdma_t DEVDMA[7]; /**< Offset: 0x310 Device DMA Channel Next Descriptor Address Register */ - __I uint8_t Reserved9[128]; - __IO uint32_t HSTCTRL; /**< (USBHS Offset: 0x400) Host General Control Register */ - __I uint32_t HSTISR; /**< (USBHS Offset: 0x404) Host Global Interrupt Status Register */ - __O uint32_t HSTICR; /**< (USBHS Offset: 0x408) Host Global Interrupt Clear Register */ - __O uint32_t HSTIFR; /**< (USBHS Offset: 0x40C) Host Global Interrupt Set Register */ - __I uint32_t HSTIMR; /**< (USBHS Offset: 0x410) Host Global Interrupt Mask Register */ - __O uint32_t HSTIDR; /**< (USBHS Offset: 0x414) Host Global Interrupt Disable Register */ - __O uint32_t HSTIER; /**< (USBHS Offset: 0x418) Host Global Interrupt Enable Register */ - __IO uint32_t HSTPIP; /**< (USBHS Offset: 0x41C) Host Pipe Register */ - __IO uint32_t HSTFNUM; /**< (USBHS Offset: 0x420) Host Frame Number Register */ - __IO uint32_t HSTADDR1; /**< (USBHS Offset: 0x424) Host Address 1 Register */ - __IO uint32_t HSTADDR2; /**< (USBHS Offset: 0x428) Host Address 2 Register */ - __IO uint32_t HSTADDR3; /**< (USBHS Offset: 0x42C) Host Address 3 Register */ - __I uint8_t Reserved10[208]; - __IO uint32_t HSTPIPCFG[10]; /**< (USBHS Offset: 0x500) Host Pipe Configuration Register */ - __I uint8_t Reserved11[8]; - __I uint32_t HSTPIPISR[10]; /**< (USBHS Offset: 0x530) Host Pipe Status Register */ - __I uint8_t Reserved12[8]; - __O uint32_t HSTPIPICR[10]; /**< (USBHS Offset: 0x560) Host Pipe Clear Register */ - __I uint8_t Reserved13[8]; - __O uint32_t HSTPIPIFR[10]; /**< (USBHS Offset: 0x590) Host Pipe Set Register */ - __I uint8_t Reserved14[8]; - __I uint32_t HSTPIPIMR[10]; /**< (USBHS Offset: 0x5C0) Host Pipe Mask Register */ - __I uint8_t Reserved15[8]; - __O uint32_t HSTPIPIER[10]; /**< (USBHS Offset: 0x5F0) Host Pipe Enable Register */ - __I uint8_t Reserved16[8]; - __O uint32_t HSTPIPIDR[10]; /**< (USBHS Offset: 0x620) Host Pipe Disable Register */ - __I uint8_t Reserved17[8]; - __IO uint32_t HSTPIPINRQ[10]; /**< (USBHS Offset: 0x650) Host Pipe IN Request Register */ - __I uint8_t Reserved18[8]; - __IO uint32_t HSTPIPERR[10]; /**< (USBHS Offset: 0x680) Host Pipe Error Register */ - __I uint8_t Reserved19[104]; - hstdma_t HSTDMA[7]; /**< Offset: 0x710 Host DMA Channel Next Descriptor Address Register */ - __I uint8_t Reserved20[128]; - __IO uint32_t CTRL; /**< (USBHS Offset: 0x800) General Control Register */ - __I uint32_t SR; /**< (USBHS Offset: 0x804) General Status Register */ - __O uint32_t SCR; /**< (USBHS Offset: 0x808) General Status Clear Register */ - __O uint32_t SFR; /**< (USBHS Offset: 0x80C) General Status Set Register */ -} dcd_registers_t; - -#define USB_REG ((dcd_registers_t *)0x40038000U) /**< \brief (USBHS) Base Address */ - -#define EP_MAX 10 - -#define FIFO_RAM_ADDR 0xA0100000u - -// Errata: The DMA feature is not available for Pipe/Endpoint 7 -#define EP_DMA_SUPPORT(epnum) (epnum >= 1 && epnum <= 6) - -#else // TODO : SAM3U - - -#endif - -#endif /* _COMMON_USB_REGS_H_ */ diff --git a/src/portable/microchip/samx7x/dcd_samx7x.c b/src/portable/microchip/samx7x/dcd_samx7x.c index b0a053c01..979d08fe9 100644 --- a/src/portable/microchip/samx7x/dcd_samx7x.c +++ b/src/portable/microchip/samx7x/dcd_samx7x.c @@ -31,7 +31,7 @@ #include "device/dcd.h" #include "sam.h" -#include "common_usb_regs.h" +#include "samx7x_common.h" //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM DECLARATION //--------------------------------------------------------------------+ @@ -87,18 +87,22 @@ static const tusb_desc_endpoint_t ep0_desc = .wMaxPacketSize = CFG_TUD_ENDPOINT0_SIZE, }; -TU_ATTR_ALWAYS_INLINE static inline void CleanInValidateCache(uint32_t *addr, int32_t size) -{ - if (SCB->CCR & SCB_CCR_DC_Msk) - { - SCB_CleanInvalidateDCache_by_Addr(addr, size); - } - else - { - __DSB(); - __ISB(); - } +#if CFG_TUD_MEM_DCACHE_ENABLE +bool dcd_dcache_clean(const void* addr, uint32_t data_size) { + TU_VERIFY(addr && data_size); + return samx7x_dcache_clean(addr, data_size); } + +bool dcd_dcache_invalidate(const void* addr, uint32_t data_size) { + TU_VERIFY(addr && data_size); + return samx7x_dcache_invalidate(addr, data_size); +} + +bool dcd_dcache_clean_invalidate(const void* addr, uint32_t data_size) { + TU_VERIFY(addr && data_size); + return samx7x_dcache_clean_invalidate(addr, data_size); +} +#endif //------------------------------------------------------------------ // Device API //------------------------------------------------------------------ @@ -255,7 +259,7 @@ static void dcd_ep_handler(uint8_t ep_ix) memcpy(xfer->buffer + xfer->queued_len, ptr, count); } else { - tu_fifo_write_n(xfer->fifo, ptr, count); + tu_hwfifo_read_to_fifo(ptr, xfer->fifo, count, NULL); } xfer->queued_len = (uint16_t)(xfer->queued_len + count); } @@ -309,7 +313,7 @@ static void dcd_ep_handler(uint8_t ep_ix) { memcpy(xfer->buffer + xfer->queued_len, ptr, count); } else { - tu_fifo_write_n(xfer->fifo, ptr, count); + tu_hwfifo_read_to_fifo(ptr, xfer->fifo, count, NULL); } xfer->queued_len = (uint16_t)(xfer->queued_len + count); } @@ -362,6 +366,7 @@ static void dcd_dma_handler(uint8_t ep_ix) dcd_event_xfer_complete(0, 0x80 + ep_ix, count, XFER_RESULT_SUCCESS, true); } else { + dcd_dcache_invalidate(xfer->buffer, xfer->total_len); dcd_event_xfer_complete(0, ep_ix, count, XFER_RESULT_SUCCESS, true); } } @@ -588,7 +593,7 @@ static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix) } else { - tu_fifo_read_n(xfer->fifo, ptr, len); + tu_hwfifo_write_from_fifo(ptr, xfer->fifo, len, NULL); } __DSB(); __ISB(); @@ -623,35 +628,18 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t t if (EP_DMA_SUPPORT(epnum) && total_bytes != 0) { - // Force the CPU to flush the buffer. We increase the size by 32 because the call aligns the - // address to 32-byte boundaries. - CleanInValidateCache((uint32_t*) tu_align((uint32_t) buffer, 4), total_bytes + 31); uint32_t udd_dma_ctrl = total_bytes << DEVDMACONTROL_BUFF_LENGTH_Pos; if (dir == TUSB_DIR_OUT) { udd_dma_ctrl |= DEVDMACONTROL_END_TR_IT | DEVDMACONTROL_END_TR_EN; } else { udd_dma_ctrl |= DEVDMACONTROL_END_B_EN; + dcd_dcache_clean(xfer->buffer, total_bytes); } USB_REG->DEVDMA[epnum - 1].DEVDMAADDRESS = (uint32_t)buffer; udd_dma_ctrl |= DEVDMACONTROL_END_BUFFIT | DEVDMACONTROL_CHANN_ENB; - // Disable IRQs to have a short sequence - // between read of EOT_STA and DMA enable - uint32_t irq_state = __get_PRIMASK(); - __disable_irq(); - if (!(USB_REG->DEVDMA[epnum - 1].DEVDMASTATUS & DEVDMASTATUS_END_TR_ST)) - { - USB_REG->DEVDMA[epnum - 1].DEVDMACONTROL = udd_dma_ctrl; - USB_REG->DEVIER = DEVIER_DMA_1 << (epnum - 1); - __set_PRIMASK(irq_state); - return true; - } - __set_PRIMASK(irq_state); - - // Here a ZLP has been received - // and the DMA transfer must be not started. - // It is the end of transfer - return false; + USB_REG->DEVDMA[epnum - 1].DEVDMACONTROL = udd_dma_ctrl; + USB_REG->DEVIER = DEVIER_DMA_1 << (epnum - 1); } else { if (dir == TUSB_DIR_OUT) diff --git a/src/portable/microchip/samx7x/samx7x_common.h b/src/portable/microchip/samx7x/samx7x_common.h new file mode 100644 index 000000000..4fd63b7f8 --- /dev/null +++ b/src/portable/microchip/samx7x/samx7x_common.h @@ -0,0 +1,2173 @@ + /* +* The MIT License (MIT) +* +* Copyright (c) 2019 Microchip Technology Inc. +* Copyright (c) 2018, hathach (tinyusb.org) +* Copyright (c) 2021, HiFiPhile +* +* 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 _COMMON_USB_REGS_H_ +#define _COMMON_USB_REGS_H_ + +#if CFG_TUSB_MCU == OPT_MCU_SAMX7X + +/* -------- DEVDMANXTDSC : (USBHS Offset: 0x00) (R/W 32) Device DMA Channel Next Descriptor Address Register -------- */ + +#define DEVDMANXTDSC_OFFSET (0x00) /**< (DEVDMANXTDSC) Device DMA Channel Next Descriptor Address Register Offset */ + +#define DEVDMANXTDSC_NXT_DSC_ADD_Pos 0 /**< (DEVDMANXTDSC) Next Descriptor Address Position */ +#define DEVDMANXTDSC_NXT_DSC_ADD (_U_(0xFFFFFFFF) << DEVDMANXTDSC_NXT_DSC_ADD_Pos) /**< (DEVDMANXTDSC) Next Descriptor Address Mask */ +#define DEVDMANXTDSC_Msk _U_(0xFFFFFFFF) /**< (DEVDMANXTDSC) Register Mask */ + + +/* -------- DEVDMAADDRESS : (USBHS Offset: 0x04) (R/W 32) Device DMA Channel Address Register -------- */ + +#define DEVDMAADDRESS_OFFSET (0x04) /**< (DEVDMAADDRESS) Device DMA Channel Address Register Offset */ + +#define DEVDMAADDRESS_BUFF_ADD_Pos 0 /**< (DEVDMAADDRESS) Buffer Address Position */ +#define DEVDMAADDRESS_BUFF_ADD (_U_(0xFFFFFFFF) << DEVDMAADDRESS_BUFF_ADD_Pos) /**< (DEVDMAADDRESS) Buffer Address Mask */ +#define DEVDMAADDRESS_Msk _U_(0xFFFFFFFF) /**< (DEVDMAADDRESS) Register Mask */ + + +/* -------- DEVDMACONTROL : (USBHS Offset: 0x08) (R/W 32) Device DMA Channel Control Register -------- */ + +#define DEVDMACONTROL_OFFSET (0x08) /**< (DEVDMACONTROL) Device DMA Channel Control Register Offset */ + +#define DEVDMACONTROL_CHANN_ENB_Pos 0 /**< (DEVDMACONTROL) Channel Enable Command Position */ +#define DEVDMACONTROL_CHANN_ENB (_U_(0x1) << DEVDMACONTROL_CHANN_ENB_Pos) /**< (DEVDMACONTROL) Channel Enable Command Mask */ +#define DEVDMACONTROL_LDNXT_DSC_Pos 1 /**< (DEVDMACONTROL) Load Next Channel Transfer Descriptor Enable Command Position */ +#define DEVDMACONTROL_LDNXT_DSC (_U_(0x1) << DEVDMACONTROL_LDNXT_DSC_Pos) /**< (DEVDMACONTROL) Load Next Channel Transfer Descriptor Enable Command Mask */ +#define DEVDMACONTROL_END_TR_EN_Pos 2 /**< (DEVDMACONTROL) End of Transfer Enable Control (OUT transfers only) Position */ +#define DEVDMACONTROL_END_TR_EN (_U_(0x1) << DEVDMACONTROL_END_TR_EN_Pos) /**< (DEVDMACONTROL) End of Transfer Enable Control (OUT transfers only) Mask */ +#define DEVDMACONTROL_END_B_EN_Pos 3 /**< (DEVDMACONTROL) End of Buffer Enable Control Position */ +#define DEVDMACONTROL_END_B_EN (_U_(0x1) << DEVDMACONTROL_END_B_EN_Pos) /**< (DEVDMACONTROL) End of Buffer Enable Control Mask */ +#define DEVDMACONTROL_END_TR_IT_Pos 4 /**< (DEVDMACONTROL) End of Transfer Interrupt Enable Position */ +#define DEVDMACONTROL_END_TR_IT (_U_(0x1) << DEVDMACONTROL_END_TR_IT_Pos) /**< (DEVDMACONTROL) End of Transfer Interrupt Enable Mask */ +#define DEVDMACONTROL_END_BUFFIT_Pos 5 /**< (DEVDMACONTROL) End of Buffer Interrupt Enable Position */ +#define DEVDMACONTROL_END_BUFFIT (_U_(0x1) << DEVDMACONTROL_END_BUFFIT_Pos) /**< (DEVDMACONTROL) End of Buffer Interrupt Enable Mask */ +#define DEVDMACONTROL_DESC_LD_IT_Pos 6 /**< (DEVDMACONTROL) Descriptor Loaded Interrupt Enable Position */ +#define DEVDMACONTROL_DESC_LD_IT (_U_(0x1) << DEVDMACONTROL_DESC_LD_IT_Pos) /**< (DEVDMACONTROL) Descriptor Loaded Interrupt Enable Mask */ +#define DEVDMACONTROL_BURST_LCK_Pos 7 /**< (DEVDMACONTROL) Burst Lock Enable Position */ +#define DEVDMACONTROL_BURST_LCK (_U_(0x1) << DEVDMACONTROL_BURST_LCK_Pos) /**< (DEVDMACONTROL) Burst Lock Enable Mask */ +#define DEVDMACONTROL_BUFF_LENGTH_Pos 16 /**< (DEVDMACONTROL) Buffer Byte Length (Write-only) Position */ +#define DEVDMACONTROL_BUFF_LENGTH (_U_(0xFFFF) << DEVDMACONTROL_BUFF_LENGTH_Pos) /**< (DEVDMACONTROL) Buffer Byte Length (Write-only) Mask */ +#define DEVDMACONTROL_Msk _U_(0xFFFF00FF) /**< (DEVDMACONTROL) Register Mask */ + + +/* -------- DEVDMASTATUS : (USBHS Offset: 0x0c) (R/W 32) Device DMA Channel Status Register -------- */ + +#define DEVDMASTATUS_OFFSET (0x0C) /**< (DEVDMASTATUS) Device DMA Channel Status Register Offset */ + +#define DEVDMASTATUS_CHANN_ENB_Pos 0 /**< (DEVDMASTATUS) Channel Enable Status Position */ +#define DEVDMASTATUS_CHANN_ENB (_U_(0x1) << DEVDMASTATUS_CHANN_ENB_Pos) /**< (DEVDMASTATUS) Channel Enable Status Mask */ +#define DEVDMASTATUS_CHANN_ACT_Pos 1 /**< (DEVDMASTATUS) Channel Active Status Position */ +#define DEVDMASTATUS_CHANN_ACT (_U_(0x1) << DEVDMASTATUS_CHANN_ACT_Pos) /**< (DEVDMASTATUS) Channel Active Status Mask */ +#define DEVDMASTATUS_END_TR_ST_Pos 4 /**< (DEVDMASTATUS) End of Channel Transfer Status Position */ +#define DEVDMASTATUS_END_TR_ST (_U_(0x1) << DEVDMASTATUS_END_TR_ST_Pos) /**< (DEVDMASTATUS) End of Channel Transfer Status Mask */ +#define DEVDMASTATUS_END_BF_ST_Pos 5 /**< (DEVDMASTATUS) End of Channel Buffer Status Position */ +#define DEVDMASTATUS_END_BF_ST (_U_(0x1) << DEVDMASTATUS_END_BF_ST_Pos) /**< (DEVDMASTATUS) End of Channel Buffer Status Mask */ +#define DEVDMASTATUS_DESC_LDST_Pos 6 /**< (DEVDMASTATUS) Descriptor Loaded Status Position */ +#define DEVDMASTATUS_DESC_LDST (_U_(0x1) << DEVDMASTATUS_DESC_LDST_Pos) /**< (DEVDMASTATUS) Descriptor Loaded Status Mask */ +#define DEVDMASTATUS_BUFF_COUNT_Pos 16 /**< (DEVDMASTATUS) Buffer Byte Count Position */ +#define DEVDMASTATUS_BUFF_COUNT (_U_(0xFFFF) << DEVDMASTATUS_BUFF_COUNT_Pos) /**< (DEVDMASTATUS) Buffer Byte Count Mask */ +#define DEVDMASTATUS_Msk _U_(0xFFFF0073) /**< (DEVDMASTATUS) Register Mask */ + + +/* -------- HSTDMANXTDSC : (USBHS Offset: 0x00) (R/W 32) Host DMA Channel Next Descriptor Address Register -------- */ + +#define HSTDMANXTDSC_OFFSET (0x00) /**< (HSTDMANXTDSC) Host DMA Channel Next Descriptor Address Register Offset */ + +#define HSTDMANXTDSC_NXT_DSC_ADD_Pos 0 /**< (HSTDMANXTDSC) Next Descriptor Address Position */ +#define HSTDMANXTDSC_NXT_DSC_ADD (_U_(0xFFFFFFFF) << HSTDMANXTDSC_NXT_DSC_ADD_Pos) /**< (HSTDMANXTDSC) Next Descriptor Address Mask */ +#define HSTDMANXTDSC_Msk _U_(0xFFFFFFFF) /**< (HSTDMANXTDSC) Register Mask */ + + +/* -------- HSTDMAADDRESS : (USBHS Offset: 0x04) (R/W 32) Host DMA Channel Address Register -------- */ + +#define HSTDMAADDRESS_OFFSET (0x04) /**< (HSTDMAADDRESS) Host DMA Channel Address Register Offset */ + +#define HSTDMAADDRESS_BUFF_ADD_Pos 0 /**< (HSTDMAADDRESS) Buffer Address Position */ +#define HSTDMAADDRESS_BUFF_ADD (_U_(0xFFFFFFFF) << HSTDMAADDRESS_BUFF_ADD_Pos) /**< (HSTDMAADDRESS) Buffer Address Mask */ +#define HSTDMAADDRESS_Msk _U_(0xFFFFFFFF) /**< (HSTDMAADDRESS) Register Mask */ + + +/* -------- HSTDMACONTROL : (USBHS Offset: 0x08) (R/W 32) Host DMA Channel Control Register -------- */ + +#define HSTDMACONTROL_OFFSET (0x08) /**< (HSTDMACONTROL) Host DMA Channel Control Register Offset */ + +#define HSTDMACONTROL_CHANN_ENB_Pos 0 /**< (HSTDMACONTROL) Channel Enable Command Position */ +#define HSTDMACONTROL_CHANN_ENB (_U_(0x1) << HSTDMACONTROL_CHANN_ENB_Pos) /**< (HSTDMACONTROL) Channel Enable Command Mask */ +#define HSTDMACONTROL_LDNXT_DSC_Pos 1 /**< (HSTDMACONTROL) Load Next Channel Transfer Descriptor Enable Command Position */ +#define HSTDMACONTROL_LDNXT_DSC (_U_(0x1) << HSTDMACONTROL_LDNXT_DSC_Pos) /**< (HSTDMACONTROL) Load Next Channel Transfer Descriptor Enable Command Mask */ +#define HSTDMACONTROL_END_TR_EN_Pos 2 /**< (HSTDMACONTROL) End of Transfer Enable Control (OUT transfers only) Position */ +#define HSTDMACONTROL_END_TR_EN (_U_(0x1) << HSTDMACONTROL_END_TR_EN_Pos) /**< (HSTDMACONTROL) End of Transfer Enable Control (OUT transfers only) Mask */ +#define HSTDMACONTROL_END_B_EN_Pos 3 /**< (HSTDMACONTROL) End of Buffer Enable Control Position */ +#define HSTDMACONTROL_END_B_EN (_U_(0x1) << HSTDMACONTROL_END_B_EN_Pos) /**< (HSTDMACONTROL) End of Buffer Enable Control Mask */ +#define HSTDMACONTROL_END_TR_IT_Pos 4 /**< (HSTDMACONTROL) End of Transfer Interrupt Enable Position */ +#define HSTDMACONTROL_END_TR_IT (_U_(0x1) << HSTDMACONTROL_END_TR_IT_Pos) /**< (HSTDMACONTROL) End of Transfer Interrupt Enable Mask */ +#define HSTDMACONTROL_END_BUFFIT_Pos 5 /**< (HSTDMACONTROL) End of Buffer Interrupt Enable Position */ +#define HSTDMACONTROL_END_BUFFIT (_U_(0x1) << HSTDMACONTROL_END_BUFFIT_Pos) /**< (HSTDMACONTROL) End of Buffer Interrupt Enable Mask */ +#define HSTDMACONTROL_DESC_LD_IT_Pos 6 /**< (HSTDMACONTROL) Descriptor Loaded Interrupt Enable Position */ +#define HSTDMACONTROL_DESC_LD_IT (_U_(0x1) << HSTDMACONTROL_DESC_LD_IT_Pos) /**< (HSTDMACONTROL) Descriptor Loaded Interrupt Enable Mask */ +#define HSTDMACONTROL_BURST_LCK_Pos 7 /**< (HSTDMACONTROL) Burst Lock Enable Position */ +#define HSTDMACONTROL_BURST_LCK (_U_(0x1) << HSTDMACONTROL_BURST_LCK_Pos) /**< (HSTDMACONTROL) Burst Lock Enable Mask */ +#define HSTDMACONTROL_BUFF_LENGTH_Pos 16 /**< (HSTDMACONTROL) Buffer Byte Length (Write-only) Position */ +#define HSTDMACONTROL_BUFF_LENGTH (_U_(0xFFFF) << HSTDMACONTROL_BUFF_LENGTH_Pos) /**< (HSTDMACONTROL) Buffer Byte Length (Write-only) Mask */ +#define HSTDMACONTROL_Msk _U_(0xFFFF00FF) /**< (HSTDMACONTROL) Register Mask */ + + +/* -------- HSTDMASTATUS : (USBHS Offset: 0x0c) (R/W 32) Host DMA Channel Status Register -------- */ + +#define HSTDMASTATUS_OFFSET (0x0C) /**< (HSTDMASTATUS) Host DMA Channel Status Register Offset */ + +#define HSTDMASTATUS_CHANN_ENB_Pos 0 /**< (HSTDMASTATUS) Channel Enable Status Position */ +#define HSTDMASTATUS_CHANN_ENB (_U_(0x1) << HSTDMASTATUS_CHANN_ENB_Pos) /**< (HSTDMASTATUS) Channel Enable Status Mask */ +#define HSTDMASTATUS_CHANN_ACT_Pos 1 /**< (HSTDMASTATUS) Channel Active Status Position */ +#define HSTDMASTATUS_CHANN_ACT (_U_(0x1) << HSTDMASTATUS_CHANN_ACT_Pos) /**< (HSTDMASTATUS) Channel Active Status Mask */ +#define HSTDMASTATUS_END_TR_ST_Pos 4 /**< (HSTDMASTATUS) End of Channel Transfer Status Position */ +#define HSTDMASTATUS_END_TR_ST (_U_(0x1) << HSTDMASTATUS_END_TR_ST_Pos) /**< (HSTDMASTATUS) End of Channel Transfer Status Mask */ +#define HSTDMASTATUS_END_BF_ST_Pos 5 /**< (HSTDMASTATUS) End of Channel Buffer Status Position */ +#define HSTDMASTATUS_END_BF_ST (_U_(0x1) << HSTDMASTATUS_END_BF_ST_Pos) /**< (HSTDMASTATUS) End of Channel Buffer Status Mask */ +#define HSTDMASTATUS_DESC_LDST_Pos 6 /**< (HSTDMASTATUS) Descriptor Loaded Status Position */ +#define HSTDMASTATUS_DESC_LDST (_U_(0x1) << HSTDMASTATUS_DESC_LDST_Pos) /**< (HSTDMASTATUS) Descriptor Loaded Status Mask */ +#define HSTDMASTATUS_BUFF_COUNT_Pos 16 /**< (HSTDMASTATUS) Buffer Byte Count Position */ +#define HSTDMASTATUS_BUFF_COUNT (_U_(0xFFFF) << HSTDMASTATUS_BUFF_COUNT_Pos) /**< (HSTDMASTATUS) Buffer Byte Count Mask */ +#define HSTDMASTATUS_Msk _U_(0xFFFF0073) /**< (HSTDMASTATUS) Register Mask */ + + +/* -------- DEVCTRL : (USBHS Offset: 0x00) (R/W 32) Device General Control Register -------- */ + +#define DEVCTRL_OFFSET (0x00) /**< (DEVCTRL) Device General Control Register Offset */ + +#define DEVCTRL_UADD_Pos 0 /**< (DEVCTRL) USB Address Position */ +#define DEVCTRL_UADD (_U_(0x7F) << DEVCTRL_UADD_Pos) /**< (DEVCTRL) USB Address Mask */ +#define DEVCTRL_ADDEN_Pos 7 /**< (DEVCTRL) Address Enable Position */ +#define DEVCTRL_ADDEN (_U_(0x1) << DEVCTRL_ADDEN_Pos) /**< (DEVCTRL) Address Enable Mask */ +#define DEVCTRL_DETACH_Pos 8 /**< (DEVCTRL) Detach Position */ +#define DEVCTRL_DETACH (_U_(0x1) << DEVCTRL_DETACH_Pos) /**< (DEVCTRL) Detach Mask */ +#define DEVCTRL_RMWKUP_Pos 9 /**< (DEVCTRL) Remote Wake-Up Position */ +#define DEVCTRL_RMWKUP (_U_(0x1) << DEVCTRL_RMWKUP_Pos) /**< (DEVCTRL) Remote Wake-Up Mask */ +#define DEVCTRL_SPDCONF_Pos 10 /**< (DEVCTRL) Mode Configuration Position */ +#define DEVCTRL_SPDCONF (_U_(0x3) << DEVCTRL_SPDCONF_Pos) /**< (DEVCTRL) Mode Configuration Mask */ +#define DEVCTRL_SPDCONF_NORMAL_Val _U_(0x0) /**< (DEVCTRL) The peripheral starts in Full-speed mode and performs a high-speed reset to switch to High-speed mode if the host is high-speed-capable. */ +#define DEVCTRL_SPDCONF_LOW_POWER_Val _U_(0x1) /**< (DEVCTRL) For a better consumption, if high speed is not needed. */ +#define DEVCTRL_SPDCONF_HIGH_SPEED_Val _U_(0x2) /**< (DEVCTRL) Forced high speed. */ +#define DEVCTRL_SPDCONF_FORCED_FS_Val _U_(0x3) /**< (DEVCTRL) The peripheral remains in Full-speed mode whatever the host speed capability. */ +#define DEVCTRL_SPDCONF_NORMAL (DEVCTRL_SPDCONF_NORMAL_Val << DEVCTRL_SPDCONF_Pos) /**< (DEVCTRL) The peripheral starts in Full-speed mode and performs a high-speed reset to switch to High-speed mode if the host is high-speed-capable. Position */ +#define DEVCTRL_SPDCONF_LOW_POWER (DEVCTRL_SPDCONF_LOW_POWER_Val << DEVCTRL_SPDCONF_Pos) /**< (DEVCTRL) For a better consumption, if high speed is not needed. Position */ +#define DEVCTRL_SPDCONF_HIGH_SPEED (DEVCTRL_SPDCONF_HIGH_SPEED_Val << DEVCTRL_SPDCONF_Pos) /**< (DEVCTRL) Forced high speed. Position */ +#define DEVCTRL_SPDCONF_FORCED_FS (DEVCTRL_SPDCONF_FORCED_FS_Val << DEVCTRL_SPDCONF_Pos) /**< (DEVCTRL) The peripheral remains in Full-speed mode whatever the host speed capability. Position */ +#define DEVCTRL_LS_Pos 12 /**< (DEVCTRL) Low-Speed Mode Force Position */ +#define DEVCTRL_LS (_U_(0x1) << DEVCTRL_LS_Pos) /**< (DEVCTRL) Low-Speed Mode Force Mask */ +#define DEVCTRL_TSTJ_Pos 13 /**< (DEVCTRL) Test mode J Position */ +#define DEVCTRL_TSTJ (_U_(0x1) << DEVCTRL_TSTJ_Pos) /**< (DEVCTRL) Test mode J Mask */ +#define DEVCTRL_TSTK_Pos 14 /**< (DEVCTRL) Test mode K Position */ +#define DEVCTRL_TSTK (_U_(0x1) << DEVCTRL_TSTK_Pos) /**< (DEVCTRL) Test mode K Mask */ +#define DEVCTRL_TSTPCKT_Pos 15 /**< (DEVCTRL) Test packet mode Position */ +#define DEVCTRL_TSTPCKT (_U_(0x1) << DEVCTRL_TSTPCKT_Pos) /**< (DEVCTRL) Test packet mode Mask */ +#define DEVCTRL_OPMODE2_Pos 16 /**< (DEVCTRL) Specific Operational mode Position */ +#define DEVCTRL_OPMODE2 (_U_(0x1) << DEVCTRL_OPMODE2_Pos) /**< (DEVCTRL) Specific Operational mode Mask */ +#define DEVCTRL_Msk _U_(0x1FFFF) /**< (DEVCTRL) Register Mask */ + +#define DEVCTRL_OPMODE_Pos 16 /**< (DEVCTRL Position) Specific Operational mode */ +#define DEVCTRL_OPMODE (_U_(0x1) << DEVCTRL_OPMODE_Pos) /**< (DEVCTRL Mask) OPMODE */ + +/* -------- DEVISR : (USBHS Offset: 0x04) (R/ 32) Device Global Interrupt Status Register -------- */ + +#define DEVISR_OFFSET (0x04) /**< (DEVISR) Device Global Interrupt Status Register Offset */ + +#define DEVISR_SUSP_Pos 0 /**< (DEVISR) Suspend Interrupt Position */ +#define DEVISR_SUSP (_U_(0x1) << DEVISR_SUSP_Pos) /**< (DEVISR) Suspend Interrupt Mask */ +#define DEVISR_MSOF_Pos 1 /**< (DEVISR) Micro Start of Frame Interrupt Position */ +#define DEVISR_MSOF (_U_(0x1) << DEVISR_MSOF_Pos) /**< (DEVISR) Micro Start of Frame Interrupt Mask */ +#define DEVISR_SOF_Pos 2 /**< (DEVISR) Start of Frame Interrupt Position */ +#define DEVISR_SOF (_U_(0x1) << DEVISR_SOF_Pos) /**< (DEVISR) Start of Frame Interrupt Mask */ +#define DEVISR_EORST_Pos 3 /**< (DEVISR) End of Reset Interrupt Position */ +#define DEVISR_EORST (_U_(0x1) << DEVISR_EORST_Pos) /**< (DEVISR) End of Reset Interrupt Mask */ +#define DEVISR_WAKEUP_Pos 4 /**< (DEVISR) Wake-Up Interrupt Position */ +#define DEVISR_WAKEUP (_U_(0x1) << DEVISR_WAKEUP_Pos) /**< (DEVISR) Wake-Up Interrupt Mask */ +#define DEVISR_EORSM_Pos 5 /**< (DEVISR) End of Resume Interrupt Position */ +#define DEVISR_EORSM (_U_(0x1) << DEVISR_EORSM_Pos) /**< (DEVISR) End of Resume Interrupt Mask */ +#define DEVISR_UPRSM_Pos 6 /**< (DEVISR) Upstream Resume Interrupt Position */ +#define DEVISR_UPRSM (_U_(0x1) << DEVISR_UPRSM_Pos) /**< (DEVISR) Upstream Resume Interrupt Mask */ +#define DEVISR_PEP_0_Pos 12 /**< (DEVISR) Endpoint 0 Interrupt Position */ +#define DEVISR_PEP_0 (_U_(0x1) << DEVISR_PEP_0_Pos) /**< (DEVISR) Endpoint 0 Interrupt Mask */ +#define DEVISR_PEP_1_Pos 13 /**< (DEVISR) Endpoint 1 Interrupt Position */ +#define DEVISR_PEP_1 (_U_(0x1) << DEVISR_PEP_1_Pos) /**< (DEVISR) Endpoint 1 Interrupt Mask */ +#define DEVISR_PEP_2_Pos 14 /**< (DEVISR) Endpoint 2 Interrupt Position */ +#define DEVISR_PEP_2 (_U_(0x1) << DEVISR_PEP_2_Pos) /**< (DEVISR) Endpoint 2 Interrupt Mask */ +#define DEVISR_PEP_3_Pos 15 /**< (DEVISR) Endpoint 3 Interrupt Position */ +#define DEVISR_PEP_3 (_U_(0x1) << DEVISR_PEP_3_Pos) /**< (DEVISR) Endpoint 3 Interrupt Mask */ +#define DEVISR_PEP_4_Pos 16 /**< (DEVISR) Endpoint 4 Interrupt Position */ +#define DEVISR_PEP_4 (_U_(0x1) << DEVISR_PEP_4_Pos) /**< (DEVISR) Endpoint 4 Interrupt Mask */ +#define DEVISR_PEP_5_Pos 17 /**< (DEVISR) Endpoint 5 Interrupt Position */ +#define DEVISR_PEP_5 (_U_(0x1) << DEVISR_PEP_5_Pos) /**< (DEVISR) Endpoint 5 Interrupt Mask */ +#define DEVISR_PEP_6_Pos 18 /**< (DEVISR) Endpoint 6 Interrupt Position */ +#define DEVISR_PEP_6 (_U_(0x1) << DEVISR_PEP_6_Pos) /**< (DEVISR) Endpoint 6 Interrupt Mask */ +#define DEVISR_PEP_7_Pos 19 /**< (DEVISR) Endpoint 7 Interrupt Position */ +#define DEVISR_PEP_7 (_U_(0x1) << DEVISR_PEP_7_Pos) /**< (DEVISR) Endpoint 7 Interrupt Mask */ +#define DEVISR_PEP_8_Pos 20 /**< (DEVISR) Endpoint 8 Interrupt Position */ +#define DEVISR_PEP_8 (_U_(0x1) << DEVISR_PEP_8_Pos) /**< (DEVISR) Endpoint 8 Interrupt Mask */ +#define DEVISR_PEP_9_Pos 21 /**< (DEVISR) Endpoint 9 Interrupt Position */ +#define DEVISR_PEP_9 (_U_(0x1) << DEVISR_PEP_9_Pos) /**< (DEVISR) Endpoint 9 Interrupt Mask */ +#define DEVISR_DMA_1_Pos 25 /**< (DEVISR) DMA Channel 1 Interrupt Position */ +#define DEVISR_DMA_1 (_U_(0x1) << DEVISR_DMA_1_Pos) /**< (DEVISR) DMA Channel 1 Interrupt Mask */ +#define DEVISR_DMA_2_Pos 26 /**< (DEVISR) DMA Channel 2 Interrupt Position */ +#define DEVISR_DMA_2 (_U_(0x1) << DEVISR_DMA_2_Pos) /**< (DEVISR) DMA Channel 2 Interrupt Mask */ +#define DEVISR_DMA_3_Pos 27 /**< (DEVISR) DMA Channel 3 Interrupt Position */ +#define DEVISR_DMA_3 (_U_(0x1) << DEVISR_DMA_3_Pos) /**< (DEVISR) DMA Channel 3 Interrupt Mask */ +#define DEVISR_DMA_4_Pos 28 /**< (DEVISR) DMA Channel 4 Interrupt Position */ +#define DEVISR_DMA_4 (_U_(0x1) << DEVISR_DMA_4_Pos) /**< (DEVISR) DMA Channel 4 Interrupt Mask */ +#define DEVISR_DMA_5_Pos 29 /**< (DEVISR) DMA Channel 5 Interrupt Position */ +#define DEVISR_DMA_5 (_U_(0x1) << DEVISR_DMA_5_Pos) /**< (DEVISR) DMA Channel 5 Interrupt Mask */ +#define DEVISR_DMA_6_Pos 30 /**< (DEVISR) DMA Channel 6 Interrupt Position */ +#define DEVISR_DMA_6 (_U_(0x1) << DEVISR_DMA_6_Pos) /**< (DEVISR) DMA Channel 6 Interrupt Mask */ +#define DEVISR_DMA_7_Pos 31 /**< (DEVISR) DMA Channel 7 Interrupt Position */ +#define DEVISR_DMA_7 (_U_(0x1) << DEVISR_DMA_7_Pos) /**< (DEVISR) DMA Channel 7 Interrupt Mask */ +#define DEVISR_Msk _U_(0xFE3FF07F) /**< (DEVISR) Register Mask */ + +#define DEVISR_PEP__Pos 12 /**< (DEVISR Position) Endpoint x Interrupt */ +#define DEVISR_PEP_ (_U_(0x3FF) << DEVISR_PEP__Pos) /**< (DEVISR Mask) PEP_ */ +#define DEVISR_DMA__Pos 25 /**< (DEVISR Position) DMA Channel 7 Interrupt */ +#define DEVISR_DMA_ (_U_(0x7F) << DEVISR_DMA__Pos) /**< (DEVISR Mask) DMA_ */ + +/* -------- DEVICR : (USBHS Offset: 0x08) (/W 32) Device Global Interrupt Clear Register -------- */ + +#define DEVICR_OFFSET (0x08) /**< (DEVICR) Device Global Interrupt Clear Register Offset */ + +#define DEVICR_SUSPC_Pos 0 /**< (DEVICR) Suspend Interrupt Clear Position */ +#define DEVICR_SUSPC (_U_(0x1) << DEVICR_SUSPC_Pos) /**< (DEVICR) Suspend Interrupt Clear Mask */ +#define DEVICR_MSOFC_Pos 1 /**< (DEVICR) Micro Start of Frame Interrupt Clear Position */ +#define DEVICR_MSOFC (_U_(0x1) << DEVICR_MSOFC_Pos) /**< (DEVICR) Micro Start of Frame Interrupt Clear Mask */ +#define DEVICR_SOFC_Pos 2 /**< (DEVICR) Start of Frame Interrupt Clear Position */ +#define DEVICR_SOFC (_U_(0x1) << DEVICR_SOFC_Pos) /**< (DEVICR) Start of Frame Interrupt Clear Mask */ +#define DEVICR_EORSTC_Pos 3 /**< (DEVICR) End of Reset Interrupt Clear Position */ +#define DEVICR_EORSTC (_U_(0x1) << DEVICR_EORSTC_Pos) /**< (DEVICR) End of Reset Interrupt Clear Mask */ +#define DEVICR_WAKEUPC_Pos 4 /**< (DEVICR) Wake-Up Interrupt Clear Position */ +#define DEVICR_WAKEUPC (_U_(0x1) << DEVICR_WAKEUPC_Pos) /**< (DEVICR) Wake-Up Interrupt Clear Mask */ +#define DEVICR_EORSMC_Pos 5 /**< (DEVICR) End of Resume Interrupt Clear Position */ +#define DEVICR_EORSMC (_U_(0x1) << DEVICR_EORSMC_Pos) /**< (DEVICR) End of Resume Interrupt Clear Mask */ +#define DEVICR_UPRSMC_Pos 6 /**< (DEVICR) Upstream Resume Interrupt Clear Position */ +#define DEVICR_UPRSMC (_U_(0x1) << DEVICR_UPRSMC_Pos) /**< (DEVICR) Upstream Resume Interrupt Clear Mask */ +#define DEVICR_Msk _U_(0x7F) /**< (DEVICR) Register Mask */ + + +/* -------- DEVIFR : (USBHS Offset: 0x0c) (/W 32) Device Global Interrupt Set Register -------- */ + +#define DEVIFR_OFFSET (0x0C) /**< (DEVIFR) Device Global Interrupt Set Register Offset */ + +#define DEVIFR_SUSPS_Pos 0 /**< (DEVIFR) Suspend Interrupt Set Position */ +#define DEVIFR_SUSPS (_U_(0x1) << DEVIFR_SUSPS_Pos) /**< (DEVIFR) Suspend Interrupt Set Mask */ +#define DEVIFR_MSOFS_Pos 1 /**< (DEVIFR) Micro Start of Frame Interrupt Set Position */ +#define DEVIFR_MSOFS (_U_(0x1) << DEVIFR_MSOFS_Pos) /**< (DEVIFR) Micro Start of Frame Interrupt Set Mask */ +#define DEVIFR_SOFS_Pos 2 /**< (DEVIFR) Start of Frame Interrupt Set Position */ +#define DEVIFR_SOFS (_U_(0x1) << DEVIFR_SOFS_Pos) /**< (DEVIFR) Start of Frame Interrupt Set Mask */ +#define DEVIFR_EORSTS_Pos 3 /**< (DEVIFR) End of Reset Interrupt Set Position */ +#define DEVIFR_EORSTS (_U_(0x1) << DEVIFR_EORSTS_Pos) /**< (DEVIFR) End of Reset Interrupt Set Mask */ +#define DEVIFR_WAKEUPS_Pos 4 /**< (DEVIFR) Wake-Up Interrupt Set Position */ +#define DEVIFR_WAKEUPS (_U_(0x1) << DEVIFR_WAKEUPS_Pos) /**< (DEVIFR) Wake-Up Interrupt Set Mask */ +#define DEVIFR_EORSMS_Pos 5 /**< (DEVIFR) End of Resume Interrupt Set Position */ +#define DEVIFR_EORSMS (_U_(0x1) << DEVIFR_EORSMS_Pos) /**< (DEVIFR) End of Resume Interrupt Set Mask */ +#define DEVIFR_UPRSMS_Pos 6 /**< (DEVIFR) Upstream Resume Interrupt Set Position */ +#define DEVIFR_UPRSMS (_U_(0x1) << DEVIFR_UPRSMS_Pos) /**< (DEVIFR) Upstream Resume Interrupt Set Mask */ +#define DEVIFR_DMA_1_Pos 25 /**< (DEVIFR) DMA Channel 1 Interrupt Set Position */ +#define DEVIFR_DMA_1 (_U_(0x1) << DEVIFR_DMA_1_Pos) /**< (DEVIFR) DMA Channel 1 Interrupt Set Mask */ +#define DEVIFR_DMA_2_Pos 26 /**< (DEVIFR) DMA Channel 2 Interrupt Set Position */ +#define DEVIFR_DMA_2 (_U_(0x1) << DEVIFR_DMA_2_Pos) /**< (DEVIFR) DMA Channel 2 Interrupt Set Mask */ +#define DEVIFR_DMA_3_Pos 27 /**< (DEVIFR) DMA Channel 3 Interrupt Set Position */ +#define DEVIFR_DMA_3 (_U_(0x1) << DEVIFR_DMA_3_Pos) /**< (DEVIFR) DMA Channel 3 Interrupt Set Mask */ +#define DEVIFR_DMA_4_Pos 28 /**< (DEVIFR) DMA Channel 4 Interrupt Set Position */ +#define DEVIFR_DMA_4 (_U_(0x1) << DEVIFR_DMA_4_Pos) /**< (DEVIFR) DMA Channel 4 Interrupt Set Mask */ +#define DEVIFR_DMA_5_Pos 29 /**< (DEVIFR) DMA Channel 5 Interrupt Set Position */ +#define DEVIFR_DMA_5 (_U_(0x1) << DEVIFR_DMA_5_Pos) /**< (DEVIFR) DMA Channel 5 Interrupt Set Mask */ +#define DEVIFR_DMA_6_Pos 30 /**< (DEVIFR) DMA Channel 6 Interrupt Set Position */ +#define DEVIFR_DMA_6 (_U_(0x1) << DEVIFR_DMA_6_Pos) /**< (DEVIFR) DMA Channel 6 Interrupt Set Mask */ +#define DEVIFR_DMA_7_Pos 31 /**< (DEVIFR) DMA Channel 7 Interrupt Set Position */ +#define DEVIFR_DMA_7 (_U_(0x1) << DEVIFR_DMA_7_Pos) /**< (DEVIFR) DMA Channel 7 Interrupt Set Mask */ +#define DEVIFR_Msk _U_(0xFE00007F) /**< (DEVIFR) Register Mask */ + +#define DEVIFR_DMA__Pos 25 /**< (DEVIFR Position) DMA Channel 7 Interrupt Set */ +#define DEVIFR_DMA_ (_U_(0x7F) << DEVIFR_DMA__Pos) /**< (DEVIFR Mask) DMA_ */ + +/* -------- DEVIMR : (USBHS Offset: 0x10) (R/ 32) Device Global Interrupt Mask Register -------- */ + +#define DEVIMR_OFFSET (0x10) /**< (DEVIMR) Device Global Interrupt Mask Register Offset */ + +#define DEVIMR_SUSPE_Pos 0 /**< (DEVIMR) Suspend Interrupt Mask Position */ +#define DEVIMR_SUSPE (_U_(0x1) << DEVIMR_SUSPE_Pos) /**< (DEVIMR) Suspend Interrupt Mask Mask */ +#define DEVIMR_MSOFE_Pos 1 /**< (DEVIMR) Micro Start of Frame Interrupt Mask Position */ +#define DEVIMR_MSOFE (_U_(0x1) << DEVIMR_MSOFE_Pos) /**< (DEVIMR) Micro Start of Frame Interrupt Mask Mask */ +#define DEVIMR_SOFE_Pos 2 /**< (DEVIMR) Start of Frame Interrupt Mask Position */ +#define DEVIMR_SOFE (_U_(0x1) << DEVIMR_SOFE_Pos) /**< (DEVIMR) Start of Frame Interrupt Mask Mask */ +#define DEVIMR_EORSTE_Pos 3 /**< (DEVIMR) End of Reset Interrupt Mask Position */ +#define DEVIMR_EORSTE (_U_(0x1) << DEVIMR_EORSTE_Pos) /**< (DEVIMR) End of Reset Interrupt Mask Mask */ +#define DEVIMR_WAKEUPE_Pos 4 /**< (DEVIMR) Wake-Up Interrupt Mask Position */ +#define DEVIMR_WAKEUPE (_U_(0x1) << DEVIMR_WAKEUPE_Pos) /**< (DEVIMR) Wake-Up Interrupt Mask Mask */ +#define DEVIMR_EORSME_Pos 5 /**< (DEVIMR) End of Resume Interrupt Mask Position */ +#define DEVIMR_EORSME (_U_(0x1) << DEVIMR_EORSME_Pos) /**< (DEVIMR) End of Resume Interrupt Mask Mask */ +#define DEVIMR_UPRSME_Pos 6 /**< (DEVIMR) Upstream Resume Interrupt Mask Position */ +#define DEVIMR_UPRSME (_U_(0x1) << DEVIMR_UPRSME_Pos) /**< (DEVIMR) Upstream Resume Interrupt Mask Mask */ +#define DEVIMR_PEP_0_Pos 12 /**< (DEVIMR) Endpoint 0 Interrupt Mask Position */ +#define DEVIMR_PEP_0 (_U_(0x1) << DEVIMR_PEP_0_Pos) /**< (DEVIMR) Endpoint 0 Interrupt Mask Mask */ +#define DEVIMR_PEP_1_Pos 13 /**< (DEVIMR) Endpoint 1 Interrupt Mask Position */ +#define DEVIMR_PEP_1 (_U_(0x1) << DEVIMR_PEP_1_Pos) /**< (DEVIMR) Endpoint 1 Interrupt Mask Mask */ +#define DEVIMR_PEP_2_Pos 14 /**< (DEVIMR) Endpoint 2 Interrupt Mask Position */ +#define DEVIMR_PEP_2 (_U_(0x1) << DEVIMR_PEP_2_Pos) /**< (DEVIMR) Endpoint 2 Interrupt Mask Mask */ +#define DEVIMR_PEP_3_Pos 15 /**< (DEVIMR) Endpoint 3 Interrupt Mask Position */ +#define DEVIMR_PEP_3 (_U_(0x1) << DEVIMR_PEP_3_Pos) /**< (DEVIMR) Endpoint 3 Interrupt Mask Mask */ +#define DEVIMR_PEP_4_Pos 16 /**< (DEVIMR) Endpoint 4 Interrupt Mask Position */ +#define DEVIMR_PEP_4 (_U_(0x1) << DEVIMR_PEP_4_Pos) /**< (DEVIMR) Endpoint 4 Interrupt Mask Mask */ +#define DEVIMR_PEP_5_Pos 17 /**< (DEVIMR) Endpoint 5 Interrupt Mask Position */ +#define DEVIMR_PEP_5 (_U_(0x1) << DEVIMR_PEP_5_Pos) /**< (DEVIMR) Endpoint 5 Interrupt Mask Mask */ +#define DEVIMR_PEP_6_Pos 18 /**< (DEVIMR) Endpoint 6 Interrupt Mask Position */ +#define DEVIMR_PEP_6 (_U_(0x1) << DEVIMR_PEP_6_Pos) /**< (DEVIMR) Endpoint 6 Interrupt Mask Mask */ +#define DEVIMR_PEP_7_Pos 19 /**< (DEVIMR) Endpoint 7 Interrupt Mask Position */ +#define DEVIMR_PEP_7 (_U_(0x1) << DEVIMR_PEP_7_Pos) /**< (DEVIMR) Endpoint 7 Interrupt Mask Mask */ +#define DEVIMR_PEP_8_Pos 20 /**< (DEVIMR) Endpoint 8 Interrupt Mask Position */ +#define DEVIMR_PEP_8 (_U_(0x1) << DEVIMR_PEP_8_Pos) /**< (DEVIMR) Endpoint 8 Interrupt Mask Mask */ +#define DEVIMR_PEP_9_Pos 21 /**< (DEVIMR) Endpoint 9 Interrupt Mask Position */ +#define DEVIMR_PEP_9 (_U_(0x1) << DEVIMR_PEP_9_Pos) /**< (DEVIMR) Endpoint 9 Interrupt Mask Mask */ +#define DEVIMR_DMA_1_Pos 25 /**< (DEVIMR) DMA Channel 1 Interrupt Mask Position */ +#define DEVIMR_DMA_1 (_U_(0x1) << DEVIMR_DMA_1_Pos) /**< (DEVIMR) DMA Channel 1 Interrupt Mask Mask */ +#define DEVIMR_DMA_2_Pos 26 /**< (DEVIMR) DMA Channel 2 Interrupt Mask Position */ +#define DEVIMR_DMA_2 (_U_(0x1) << DEVIMR_DMA_2_Pos) /**< (DEVIMR) DMA Channel 2 Interrupt Mask Mask */ +#define DEVIMR_DMA_3_Pos 27 /**< (DEVIMR) DMA Channel 3 Interrupt Mask Position */ +#define DEVIMR_DMA_3 (_U_(0x1) << DEVIMR_DMA_3_Pos) /**< (DEVIMR) DMA Channel 3 Interrupt Mask Mask */ +#define DEVIMR_DMA_4_Pos 28 /**< (DEVIMR) DMA Channel 4 Interrupt Mask Position */ +#define DEVIMR_DMA_4 (_U_(0x1) << DEVIMR_DMA_4_Pos) /**< (DEVIMR) DMA Channel 4 Interrupt Mask Mask */ +#define DEVIMR_DMA_5_Pos 29 /**< (DEVIMR) DMA Channel 5 Interrupt Mask Position */ +#define DEVIMR_DMA_5 (_U_(0x1) << DEVIMR_DMA_5_Pos) /**< (DEVIMR) DMA Channel 5 Interrupt Mask Mask */ +#define DEVIMR_DMA_6_Pos 30 /**< (DEVIMR) DMA Channel 6 Interrupt Mask Position */ +#define DEVIMR_DMA_6 (_U_(0x1) << DEVIMR_DMA_6_Pos) /**< (DEVIMR) DMA Channel 6 Interrupt Mask Mask */ +#define DEVIMR_DMA_7_Pos 31 /**< (DEVIMR) DMA Channel 7 Interrupt Mask Position */ +#define DEVIMR_DMA_7 (_U_(0x1) << DEVIMR_DMA_7_Pos) /**< (DEVIMR) DMA Channel 7 Interrupt Mask Mask */ +#define DEVIMR_Msk _U_(0xFE3FF07F) /**< (DEVIMR) Register Mask */ + +#define DEVIMR_PEP__Pos 12 /**< (DEVIMR Position) Endpoint x Interrupt Mask */ +#define DEVIMR_PEP_ (_U_(0x3FF) << DEVIMR_PEP__Pos) /**< (DEVIMR Mask) PEP_ */ +#define DEVIMR_DMA__Pos 25 /**< (DEVIMR Position) DMA Channel 7 Interrupt Mask */ +#define DEVIMR_DMA_ (_U_(0x7F) << DEVIMR_DMA__Pos) /**< (DEVIMR Mask) DMA_ */ + +/* -------- DEVIDR : (USBHS Offset: 0x14) (/W 32) Device Global Interrupt Disable Register -------- */ + +#define DEVIDR_OFFSET (0x14) /**< (DEVIDR) Device Global Interrupt Disable Register Offset */ + +#define DEVIDR_SUSPEC_Pos 0 /**< (DEVIDR) Suspend Interrupt Disable Position */ +#define DEVIDR_SUSPEC (_U_(0x1) << DEVIDR_SUSPEC_Pos) /**< (DEVIDR) Suspend Interrupt Disable Mask */ +#define DEVIDR_MSOFEC_Pos 1 /**< (DEVIDR) Micro Start of Frame Interrupt Disable Position */ +#define DEVIDR_MSOFEC (_U_(0x1) << DEVIDR_MSOFEC_Pos) /**< (DEVIDR) Micro Start of Frame Interrupt Disable Mask */ +#define DEVIDR_SOFEC_Pos 2 /**< (DEVIDR) Start of Frame Interrupt Disable Position */ +#define DEVIDR_SOFEC (_U_(0x1) << DEVIDR_SOFEC_Pos) /**< (DEVIDR) Start of Frame Interrupt Disable Mask */ +#define DEVIDR_EORSTEC_Pos 3 /**< (DEVIDR) End of Reset Interrupt Disable Position */ +#define DEVIDR_EORSTEC (_U_(0x1) << DEVIDR_EORSTEC_Pos) /**< (DEVIDR) End of Reset Interrupt Disable Mask */ +#define DEVIDR_WAKEUPEC_Pos 4 /**< (DEVIDR) Wake-Up Interrupt Disable Position */ +#define DEVIDR_WAKEUPEC (_U_(0x1) << DEVIDR_WAKEUPEC_Pos) /**< (DEVIDR) Wake-Up Interrupt Disable Mask */ +#define DEVIDR_EORSMEC_Pos 5 /**< (DEVIDR) End of Resume Interrupt Disable Position */ +#define DEVIDR_EORSMEC (_U_(0x1) << DEVIDR_EORSMEC_Pos) /**< (DEVIDR) End of Resume Interrupt Disable Mask */ +#define DEVIDR_UPRSMEC_Pos 6 /**< (DEVIDR) Upstream Resume Interrupt Disable Position */ +#define DEVIDR_UPRSMEC (_U_(0x1) << DEVIDR_UPRSMEC_Pos) /**< (DEVIDR) Upstream Resume Interrupt Disable Mask */ +#define DEVIDR_PEP_0_Pos 12 /**< (DEVIDR) Endpoint 0 Interrupt Disable Position */ +#define DEVIDR_PEP_0 (_U_(0x1) << DEVIDR_PEP_0_Pos) /**< (DEVIDR) Endpoint 0 Interrupt Disable Mask */ +#define DEVIDR_PEP_1_Pos 13 /**< (DEVIDR) Endpoint 1 Interrupt Disable Position */ +#define DEVIDR_PEP_1 (_U_(0x1) << DEVIDR_PEP_1_Pos) /**< (DEVIDR) Endpoint 1 Interrupt Disable Mask */ +#define DEVIDR_PEP_2_Pos 14 /**< (DEVIDR) Endpoint 2 Interrupt Disable Position */ +#define DEVIDR_PEP_2 (_U_(0x1) << DEVIDR_PEP_2_Pos) /**< (DEVIDR) Endpoint 2 Interrupt Disable Mask */ +#define DEVIDR_PEP_3_Pos 15 /**< (DEVIDR) Endpoint 3 Interrupt Disable Position */ +#define DEVIDR_PEP_3 (_U_(0x1) << DEVIDR_PEP_3_Pos) /**< (DEVIDR) Endpoint 3 Interrupt Disable Mask */ +#define DEVIDR_PEP_4_Pos 16 /**< (DEVIDR) Endpoint 4 Interrupt Disable Position */ +#define DEVIDR_PEP_4 (_U_(0x1) << DEVIDR_PEP_4_Pos) /**< (DEVIDR) Endpoint 4 Interrupt Disable Mask */ +#define DEVIDR_PEP_5_Pos 17 /**< (DEVIDR) Endpoint 5 Interrupt Disable Position */ +#define DEVIDR_PEP_5 (_U_(0x1) << DEVIDR_PEP_5_Pos) /**< (DEVIDR) Endpoint 5 Interrupt Disable Mask */ +#define DEVIDR_PEP_6_Pos 18 /**< (DEVIDR) Endpoint 6 Interrupt Disable Position */ +#define DEVIDR_PEP_6 (_U_(0x1) << DEVIDR_PEP_6_Pos) /**< (DEVIDR) Endpoint 6 Interrupt Disable Mask */ +#define DEVIDR_PEP_7_Pos 19 /**< (DEVIDR) Endpoint 7 Interrupt Disable Position */ +#define DEVIDR_PEP_7 (_U_(0x1) << DEVIDR_PEP_7_Pos) /**< (DEVIDR) Endpoint 7 Interrupt Disable Mask */ +#define DEVIDR_PEP_8_Pos 20 /**< (DEVIDR) Endpoint 8 Interrupt Disable Position */ +#define DEVIDR_PEP_8 (_U_(0x1) << DEVIDR_PEP_8_Pos) /**< (DEVIDR) Endpoint 8 Interrupt Disable Mask */ +#define DEVIDR_PEP_9_Pos 21 /**< (DEVIDR) Endpoint 9 Interrupt Disable Position */ +#define DEVIDR_PEP_9 (_U_(0x1) << DEVIDR_PEP_9_Pos) /**< (DEVIDR) Endpoint 9 Interrupt Disable Mask */ +#define DEVIDR_DMA_1_Pos 25 /**< (DEVIDR) DMA Channel 1 Interrupt Disable Position */ +#define DEVIDR_DMA_1 (_U_(0x1) << DEVIDR_DMA_1_Pos) /**< (DEVIDR) DMA Channel 1 Interrupt Disable Mask */ +#define DEVIDR_DMA_2_Pos 26 /**< (DEVIDR) DMA Channel 2 Interrupt Disable Position */ +#define DEVIDR_DMA_2 (_U_(0x1) << DEVIDR_DMA_2_Pos) /**< (DEVIDR) DMA Channel 2 Interrupt Disable Mask */ +#define DEVIDR_DMA_3_Pos 27 /**< (DEVIDR) DMA Channel 3 Interrupt Disable Position */ +#define DEVIDR_DMA_3 (_U_(0x1) << DEVIDR_DMA_3_Pos) /**< (DEVIDR) DMA Channel 3 Interrupt Disable Mask */ +#define DEVIDR_DMA_4_Pos 28 /**< (DEVIDR) DMA Channel 4 Interrupt Disable Position */ +#define DEVIDR_DMA_4 (_U_(0x1) << DEVIDR_DMA_4_Pos) /**< (DEVIDR) DMA Channel 4 Interrupt Disable Mask */ +#define DEVIDR_DMA_5_Pos 29 /**< (DEVIDR) DMA Channel 5 Interrupt Disable Position */ +#define DEVIDR_DMA_5 (_U_(0x1) << DEVIDR_DMA_5_Pos) /**< (DEVIDR) DMA Channel 5 Interrupt Disable Mask */ +#define DEVIDR_DMA_6_Pos 30 /**< (DEVIDR) DMA Channel 6 Interrupt Disable Position */ +#define DEVIDR_DMA_6 (_U_(0x1) << DEVIDR_DMA_6_Pos) /**< (DEVIDR) DMA Channel 6 Interrupt Disable Mask */ +#define DEVIDR_DMA_7_Pos 31 /**< (DEVIDR) DMA Channel 7 Interrupt Disable Position */ +#define DEVIDR_DMA_7 (_U_(0x1) << DEVIDR_DMA_7_Pos) /**< (DEVIDR) DMA Channel 7 Interrupt Disable Mask */ +#define DEVIDR_Msk _U_(0xFE3FF07F) /**< (DEVIDR) Register Mask */ + +#define DEVIDR_PEP__Pos 12 /**< (DEVIDR Position) Endpoint x Interrupt Disable */ +#define DEVIDR_PEP_ (_U_(0x3FF) << DEVIDR_PEP__Pos) /**< (DEVIDR Mask) PEP_ */ +#define DEVIDR_DMA__Pos 25 /**< (DEVIDR Position) DMA Channel 7 Interrupt Disable */ +#define DEVIDR_DMA_ (_U_(0x7F) << DEVIDR_DMA__Pos) /**< (DEVIDR Mask) DMA_ */ + +/* -------- DEVIER : (USBHS Offset: 0x18) (/W 32) Device Global Interrupt Enable Register -------- */ + +#define DEVIER_OFFSET (0x18) /**< (DEVIER) Device Global Interrupt Enable Register Offset */ + +#define DEVIER_SUSPES_Pos 0 /**< (DEVIER) Suspend Interrupt Enable Position */ +#define DEVIER_SUSPES (_U_(0x1) << DEVIER_SUSPES_Pos) /**< (DEVIER) Suspend Interrupt Enable Mask */ +#define DEVIER_MSOFES_Pos 1 /**< (DEVIER) Micro Start of Frame Interrupt Enable Position */ +#define DEVIER_MSOFES (_U_(0x1) << DEVIER_MSOFES_Pos) /**< (DEVIER) Micro Start of Frame Interrupt Enable Mask */ +#define DEVIER_SOFES_Pos 2 /**< (DEVIER) Start of Frame Interrupt Enable Position */ +#define DEVIER_SOFES (_U_(0x1) << DEVIER_SOFES_Pos) /**< (DEVIER) Start of Frame Interrupt Enable Mask */ +#define DEVIER_EORSTES_Pos 3 /**< (DEVIER) End of Reset Interrupt Enable Position */ +#define DEVIER_EORSTES (_U_(0x1) << DEVIER_EORSTES_Pos) /**< (DEVIER) End of Reset Interrupt Enable Mask */ +#define DEVIER_WAKEUPES_Pos 4 /**< (DEVIER) Wake-Up Interrupt Enable Position */ +#define DEVIER_WAKEUPES (_U_(0x1) << DEVIER_WAKEUPES_Pos) /**< (DEVIER) Wake-Up Interrupt Enable Mask */ +#define DEVIER_EORSMES_Pos 5 /**< (DEVIER) End of Resume Interrupt Enable Position */ +#define DEVIER_EORSMES (_U_(0x1) << DEVIER_EORSMES_Pos) /**< (DEVIER) End of Resume Interrupt Enable Mask */ +#define DEVIER_UPRSMES_Pos 6 /**< (DEVIER) Upstream Resume Interrupt Enable Position */ +#define DEVIER_UPRSMES (_U_(0x1) << DEVIER_UPRSMES_Pos) /**< (DEVIER) Upstream Resume Interrupt Enable Mask */ +#define DEVIER_PEP_0_Pos 12 /**< (DEVIER) Endpoint 0 Interrupt Enable Position */ +#define DEVIER_PEP_0 (_U_(0x1) << DEVIER_PEP_0_Pos) /**< (DEVIER) Endpoint 0 Interrupt Enable Mask */ +#define DEVIER_PEP_1_Pos 13 /**< (DEVIER) Endpoint 1 Interrupt Enable Position */ +#define DEVIER_PEP_1 (_U_(0x1) << DEVIER_PEP_1_Pos) /**< (DEVIER) Endpoint 1 Interrupt Enable Mask */ +#define DEVIER_PEP_2_Pos 14 /**< (DEVIER) Endpoint 2 Interrupt Enable Position */ +#define DEVIER_PEP_2 (_U_(0x1) << DEVIER_PEP_2_Pos) /**< (DEVIER) Endpoint 2 Interrupt Enable Mask */ +#define DEVIER_PEP_3_Pos 15 /**< (DEVIER) Endpoint 3 Interrupt Enable Position */ +#define DEVIER_PEP_3 (_U_(0x1) << DEVIER_PEP_3_Pos) /**< (DEVIER) Endpoint 3 Interrupt Enable Mask */ +#define DEVIER_PEP_4_Pos 16 /**< (DEVIER) Endpoint 4 Interrupt Enable Position */ +#define DEVIER_PEP_4 (_U_(0x1) << DEVIER_PEP_4_Pos) /**< (DEVIER) Endpoint 4 Interrupt Enable Mask */ +#define DEVIER_PEP_5_Pos 17 /**< (DEVIER) Endpoint 5 Interrupt Enable Position */ +#define DEVIER_PEP_5 (_U_(0x1) << DEVIER_PEP_5_Pos) /**< (DEVIER) Endpoint 5 Interrupt Enable Mask */ +#define DEVIER_PEP_6_Pos 18 /**< (DEVIER) Endpoint 6 Interrupt Enable Position */ +#define DEVIER_PEP_6 (_U_(0x1) << DEVIER_PEP_6_Pos) /**< (DEVIER) Endpoint 6 Interrupt Enable Mask */ +#define DEVIER_PEP_7_Pos 19 /**< (DEVIER) Endpoint 7 Interrupt Enable Position */ +#define DEVIER_PEP_7 (_U_(0x1) << DEVIER_PEP_7_Pos) /**< (DEVIER) Endpoint 7 Interrupt Enable Mask */ +#define DEVIER_PEP_8_Pos 20 /**< (DEVIER) Endpoint 8 Interrupt Enable Position */ +#define DEVIER_PEP_8 (_U_(0x1) << DEVIER_PEP_8_Pos) /**< (DEVIER) Endpoint 8 Interrupt Enable Mask */ +#define DEVIER_PEP_9_Pos 21 /**< (DEVIER) Endpoint 9 Interrupt Enable Position */ +#define DEVIER_PEP_9 (_U_(0x1) << DEVIER_PEP_9_Pos) /**< (DEVIER) Endpoint 9 Interrupt Enable Mask */ +#define DEVIER_DMA_1_Pos 25 /**< (DEVIER) DMA Channel 1 Interrupt Enable Position */ +#define DEVIER_DMA_1 (_U_(0x1) << DEVIER_DMA_1_Pos) /**< (DEVIER) DMA Channel 1 Interrupt Enable Mask */ +#define DEVIER_DMA_2_Pos 26 /**< (DEVIER) DMA Channel 2 Interrupt Enable Position */ +#define DEVIER_DMA_2 (_U_(0x1) << DEVIER_DMA_2_Pos) /**< (DEVIER) DMA Channel 2 Interrupt Enable Mask */ +#define DEVIER_DMA_3_Pos 27 /**< (DEVIER) DMA Channel 3 Interrupt Enable Position */ +#define DEVIER_DMA_3 (_U_(0x1) << DEVIER_DMA_3_Pos) /**< (DEVIER) DMA Channel 3 Interrupt Enable Mask */ +#define DEVIER_DMA_4_Pos 28 /**< (DEVIER) DMA Channel 4 Interrupt Enable Position */ +#define DEVIER_DMA_4 (_U_(0x1) << DEVIER_DMA_4_Pos) /**< (DEVIER) DMA Channel 4 Interrupt Enable Mask */ +#define DEVIER_DMA_5_Pos 29 /**< (DEVIER) DMA Channel 5 Interrupt Enable Position */ +#define DEVIER_DMA_5 (_U_(0x1) << DEVIER_DMA_5_Pos) /**< (DEVIER) DMA Channel 5 Interrupt Enable Mask */ +#define DEVIER_DMA_6_Pos 30 /**< (DEVIER) DMA Channel 6 Interrupt Enable Position */ +#define DEVIER_DMA_6 (_U_(0x1) << DEVIER_DMA_6_Pos) /**< (DEVIER) DMA Channel 6 Interrupt Enable Mask */ +#define DEVIER_DMA_7_Pos 31 /**< (DEVIER) DMA Channel 7 Interrupt Enable Position */ +#define DEVIER_DMA_7 (_U_(0x1) << DEVIER_DMA_7_Pos) /**< (DEVIER) DMA Channel 7 Interrupt Enable Mask */ +#define DEVIER_Msk _U_(0xFE3FF07F) /**< (DEVIER) Register Mask */ + +#define DEVIER_PEP__Pos 12 /**< (DEVIER Position) Endpoint x Interrupt Enable */ +#define DEVIER_PEP_ (_U_(0x3FF) << DEVIER_PEP__Pos) /**< (DEVIER Mask) PEP_ */ +#define DEVIER_DMA__Pos 25 /**< (DEVIER Position) DMA Channel 7 Interrupt Enable */ +#define DEVIER_DMA_ (_U_(0x7F) << DEVIER_DMA__Pos) /**< (DEVIER Mask) DMA_ */ + +/* -------- DEVEPT : (USBHS Offset: 0x1c) (R/W 32) Device Endpoint Register -------- */ + +#define DEVEPT_OFFSET (0x1C) /**< (DEVEPT) Device Endpoint Register Offset */ + +#define DEVEPT_EPEN0_Pos 0 /**< (DEVEPT) Endpoint 0 Enable Position */ +#define DEVEPT_EPEN0 (_U_(0x1) << DEVEPT_EPEN0_Pos) /**< (DEVEPT) Endpoint 0 Enable Mask */ +#define DEVEPT_EPEN1_Pos 1 /**< (DEVEPT) Endpoint 1 Enable Position */ +#define DEVEPT_EPEN1 (_U_(0x1) << DEVEPT_EPEN1_Pos) /**< (DEVEPT) Endpoint 1 Enable Mask */ +#define DEVEPT_EPEN2_Pos 2 /**< (DEVEPT) Endpoint 2 Enable Position */ +#define DEVEPT_EPEN2 (_U_(0x1) << DEVEPT_EPEN2_Pos) /**< (DEVEPT) Endpoint 2 Enable Mask */ +#define DEVEPT_EPEN3_Pos 3 /**< (DEVEPT) Endpoint 3 Enable Position */ +#define DEVEPT_EPEN3 (_U_(0x1) << DEVEPT_EPEN3_Pos) /**< (DEVEPT) Endpoint 3 Enable Mask */ +#define DEVEPT_EPEN4_Pos 4 /**< (DEVEPT) Endpoint 4 Enable Position */ +#define DEVEPT_EPEN4 (_U_(0x1) << DEVEPT_EPEN4_Pos) /**< (DEVEPT) Endpoint 4 Enable Mask */ +#define DEVEPT_EPEN5_Pos 5 /**< (DEVEPT) Endpoint 5 Enable Position */ +#define DEVEPT_EPEN5 (_U_(0x1) << DEVEPT_EPEN5_Pos) /**< (DEVEPT) Endpoint 5 Enable Mask */ +#define DEVEPT_EPEN6_Pos 6 /**< (DEVEPT) Endpoint 6 Enable Position */ +#define DEVEPT_EPEN6 (_U_(0x1) << DEVEPT_EPEN6_Pos) /**< (DEVEPT) Endpoint 6 Enable Mask */ +#define DEVEPT_EPEN7_Pos 7 /**< (DEVEPT) Endpoint 7 Enable Position */ +#define DEVEPT_EPEN7 (_U_(0x1) << DEVEPT_EPEN7_Pos) /**< (DEVEPT) Endpoint 7 Enable Mask */ +#define DEVEPT_EPEN8_Pos 8 /**< (DEVEPT) Endpoint 8 Enable Position */ +#define DEVEPT_EPEN8 (_U_(0x1) << DEVEPT_EPEN8_Pos) /**< (DEVEPT) Endpoint 8 Enable Mask */ +#define DEVEPT_EPEN9_Pos 9 /**< (DEVEPT) Endpoint 9 Enable Position */ +#define DEVEPT_EPEN9 (_U_(0x1) << DEVEPT_EPEN9_Pos) /**< (DEVEPT) Endpoint 9 Enable Mask */ +#define DEVEPT_EPRST0_Pos 16 /**< (DEVEPT) Endpoint 0 Reset Position */ +#define DEVEPT_EPRST0 (_U_(0x1) << DEVEPT_EPRST0_Pos) /**< (DEVEPT) Endpoint 0 Reset Mask */ +#define DEVEPT_EPRST1_Pos 17 /**< (DEVEPT) Endpoint 1 Reset Position */ +#define DEVEPT_EPRST1 (_U_(0x1) << DEVEPT_EPRST1_Pos) /**< (DEVEPT) Endpoint 1 Reset Mask */ +#define DEVEPT_EPRST2_Pos 18 /**< (DEVEPT) Endpoint 2 Reset Position */ +#define DEVEPT_EPRST2 (_U_(0x1) << DEVEPT_EPRST2_Pos) /**< (DEVEPT) Endpoint 2 Reset Mask */ +#define DEVEPT_EPRST3_Pos 19 /**< (DEVEPT) Endpoint 3 Reset Position */ +#define DEVEPT_EPRST3 (_U_(0x1) << DEVEPT_EPRST3_Pos) /**< (DEVEPT) Endpoint 3 Reset Mask */ +#define DEVEPT_EPRST4_Pos 20 /**< (DEVEPT) Endpoint 4 Reset Position */ +#define DEVEPT_EPRST4 (_U_(0x1) << DEVEPT_EPRST4_Pos) /**< (DEVEPT) Endpoint 4 Reset Mask */ +#define DEVEPT_EPRST5_Pos 21 /**< (DEVEPT) Endpoint 5 Reset Position */ +#define DEVEPT_EPRST5 (_U_(0x1) << DEVEPT_EPRST5_Pos) /**< (DEVEPT) Endpoint 5 Reset Mask */ +#define DEVEPT_EPRST6_Pos 22 /**< (DEVEPT) Endpoint 6 Reset Position */ +#define DEVEPT_EPRST6 (_U_(0x1) << DEVEPT_EPRST6_Pos) /**< (DEVEPT) Endpoint 6 Reset Mask */ +#define DEVEPT_EPRST7_Pos 23 /**< (DEVEPT) Endpoint 7 Reset Position */ +#define DEVEPT_EPRST7 (_U_(0x1) << DEVEPT_EPRST7_Pos) /**< (DEVEPT) Endpoint 7 Reset Mask */ +#define DEVEPT_EPRST8_Pos 24 /**< (DEVEPT) Endpoint 8 Reset Position */ +#define DEVEPT_EPRST8 (_U_(0x1) << DEVEPT_EPRST8_Pos) /**< (DEVEPT) Endpoint 8 Reset Mask */ +#define DEVEPT_EPRST9_Pos 25 /**< (DEVEPT) Endpoint 9 Reset Position */ +#define DEVEPT_EPRST9 (_U_(0x1) << DEVEPT_EPRST9_Pos) /**< (DEVEPT) Endpoint 9 Reset Mask */ +#define DEVEPT_Msk _U_(0x3FF03FF) /**< (DEVEPT) Register Mask */ + +#define DEVEPT_EPEN_Pos 0 /**< (DEVEPT Position) Endpoint x Enable */ +#define DEVEPT_EPEN (_U_(0x3FF) << DEVEPT_EPEN_Pos) /**< (DEVEPT Mask) EPEN */ +#define DEVEPT_EPRST_Pos 16 /**< (DEVEPT Position) Endpoint 9 Reset */ +#define DEVEPT_EPRST (_U_(0x3FF) << DEVEPT_EPRST_Pos) /**< (DEVEPT Mask) EPRST */ + +/* -------- DEVFNUM : (USBHS Offset: 0x20) (R/ 32) Device Frame Number Register -------- */ + +#define DEVFNUM_OFFSET (0x20) /**< (DEVFNUM) Device Frame Number Register Offset */ + +#define DEVFNUM_MFNUM_Pos 0 /**< (DEVFNUM) Micro Frame Number Position */ +#define DEVFNUM_MFNUM (_U_(0x7) << DEVFNUM_MFNUM_Pos) /**< (DEVFNUM) Micro Frame Number Mask */ +#define DEVFNUM_FNUM_Pos 3 /**< (DEVFNUM) Frame Number Position */ +#define DEVFNUM_FNUM (_U_(0x7FF) << DEVFNUM_FNUM_Pos) /**< (DEVFNUM) Frame Number Mask */ +#define DEVFNUM_FNCERR_Pos 15 /**< (DEVFNUM) Frame Number CRC Error Position */ +#define DEVFNUM_FNCERR (_U_(0x1) << DEVFNUM_FNCERR_Pos) /**< (DEVFNUM) Frame Number CRC Error Mask */ +#define DEVFNUM_Msk _U_(0xBFFF) /**< (DEVFNUM) Register Mask */ + + +/* -------- DEVEPTCFG : (USBHS Offset: 0x100) (R/W 32) Device Endpoint Configuration Register -------- */ + +#define DEVEPTCFG_OFFSET (0x100) /**< (DEVEPTCFG) Device Endpoint Configuration Register Offset */ + +#define DEVEPTCFG_ALLOC_Pos 1 /**< (DEVEPTCFG) Endpoint Memory Allocate Position */ +#define DEVEPTCFG_ALLOC (_U_(0x1) << DEVEPTCFG_ALLOC_Pos) /**< (DEVEPTCFG) Endpoint Memory Allocate Mask */ +#define DEVEPTCFG_EPBK_Pos 2 /**< (DEVEPTCFG) Endpoint Banks Position */ +#define DEVEPTCFG_EPBK (_U_(0x3) << DEVEPTCFG_EPBK_Pos) /**< (DEVEPTCFG) Endpoint Banks Mask */ +#define DEVEPTCFG_EPBK_1_BANK_Val _U_(0x0) /**< (DEVEPTCFG) Single-bank endpoint */ +#define DEVEPTCFG_EPBK_2_BANK_Val _U_(0x1) /**< (DEVEPTCFG) Double-bank endpoint */ +#define DEVEPTCFG_EPBK_3_BANK_Val _U_(0x2) /**< (DEVEPTCFG) Triple-bank endpoint */ +#define DEVEPTCFG_EPBK_1_BANK (DEVEPTCFG_EPBK_1_BANK_Val << DEVEPTCFG_EPBK_Pos) /**< (DEVEPTCFG) Single-bank endpoint Position */ +#define DEVEPTCFG_EPBK_2_BANK (DEVEPTCFG_EPBK_2_BANK_Val << DEVEPTCFG_EPBK_Pos) /**< (DEVEPTCFG) Double-bank endpoint Position */ +#define DEVEPTCFG_EPBK_3_BANK (DEVEPTCFG_EPBK_3_BANK_Val << DEVEPTCFG_EPBK_Pos) /**< (DEVEPTCFG) Triple-bank endpoint Position */ +#define DEVEPTCFG_EPSIZE_Pos 4 /**< (DEVEPTCFG) Endpoint Size Position */ +#define DEVEPTCFG_EPSIZE (_U_(0x7) << DEVEPTCFG_EPSIZE_Pos) /**< (DEVEPTCFG) Endpoint Size Mask */ +#define DEVEPTCFG_EPSIZE_8_BYTE_Val _U_(0x0) /**< (DEVEPTCFG) 8 bytes */ +#define DEVEPTCFG_EPSIZE_16_BYTE_Val _U_(0x1) /**< (DEVEPTCFG) 16 bytes */ +#define DEVEPTCFG_EPSIZE_32_BYTE_Val _U_(0x2) /**< (DEVEPTCFG) 32 bytes */ +#define DEVEPTCFG_EPSIZE_64_BYTE_Val _U_(0x3) /**< (DEVEPTCFG) 64 bytes */ +#define DEVEPTCFG_EPSIZE_128_BYTE_Val _U_(0x4) /**< (DEVEPTCFG) 128 bytes */ +#define DEVEPTCFG_EPSIZE_256_BYTE_Val _U_(0x5) /**< (DEVEPTCFG) 256 bytes */ +#define DEVEPTCFG_EPSIZE_512_BYTE_Val _U_(0x6) /**< (DEVEPTCFG) 512 bytes */ +#define DEVEPTCFG_EPSIZE_1024_BYTE_Val _U_(0x7) /**< (DEVEPTCFG) 1024 bytes */ +#define DEVEPTCFG_EPSIZE_8_BYTE (DEVEPTCFG_EPSIZE_8_BYTE_Val << DEVEPTCFG_EPSIZE_Pos) /**< (DEVEPTCFG) 8 bytes Position */ +#define DEVEPTCFG_EPSIZE_16_BYTE (DEVEPTCFG_EPSIZE_16_BYTE_Val << DEVEPTCFG_EPSIZE_Pos) /**< (DEVEPTCFG) 16 bytes Position */ +#define DEVEPTCFG_EPSIZE_32_BYTE (DEVEPTCFG_EPSIZE_32_BYTE_Val << DEVEPTCFG_EPSIZE_Pos) /**< (DEVEPTCFG) 32 bytes Position */ +#define DEVEPTCFG_EPSIZE_64_BYTE (DEVEPTCFG_EPSIZE_64_BYTE_Val << DEVEPTCFG_EPSIZE_Pos) /**< (DEVEPTCFG) 64 bytes Position */ +#define DEVEPTCFG_EPSIZE_128_BYTE (DEVEPTCFG_EPSIZE_128_BYTE_Val << DEVEPTCFG_EPSIZE_Pos) /**< (DEVEPTCFG) 128 bytes Position */ +#define DEVEPTCFG_EPSIZE_256_BYTE (DEVEPTCFG_EPSIZE_256_BYTE_Val << DEVEPTCFG_EPSIZE_Pos) /**< (DEVEPTCFG) 256 bytes Position */ +#define DEVEPTCFG_EPSIZE_512_BYTE (DEVEPTCFG_EPSIZE_512_BYTE_Val << DEVEPTCFG_EPSIZE_Pos) /**< (DEVEPTCFG) 512 bytes Position */ +#define DEVEPTCFG_EPSIZE_1024_BYTE (DEVEPTCFG_EPSIZE_1024_BYTE_Val << DEVEPTCFG_EPSIZE_Pos) /**< (DEVEPTCFG) 1024 bytes Position */ +#define DEVEPTCFG_EPDIR_Pos 8 /**< (DEVEPTCFG) Endpoint Direction Position */ +#define DEVEPTCFG_EPDIR (_U_(0x1) << DEVEPTCFG_EPDIR_Pos) /**< (DEVEPTCFG) Endpoint Direction Mask */ +#define DEVEPTCFG_EPDIR_OUT_Val _U_(0x0) /**< (DEVEPTCFG) The endpoint direction is OUT. */ +#define DEVEPTCFG_EPDIR_IN_Val _U_(0x1) /**< (DEVEPTCFG) The endpoint direction is IN (nor for control endpoints). */ +#define DEVEPTCFG_EPDIR_OUT (DEVEPTCFG_EPDIR_OUT_Val << DEVEPTCFG_EPDIR_Pos) /**< (DEVEPTCFG) The endpoint direction is OUT. Position */ +#define DEVEPTCFG_EPDIR_IN (DEVEPTCFG_EPDIR_IN_Val << DEVEPTCFG_EPDIR_Pos) /**< (DEVEPTCFG) The endpoint direction is IN (nor for control endpoints). Position */ +#define DEVEPTCFG_AUTOSW_Pos 9 /**< (DEVEPTCFG) Automatic Switch Position */ +#define DEVEPTCFG_AUTOSW (_U_(0x1) << DEVEPTCFG_AUTOSW_Pos) /**< (DEVEPTCFG) Automatic Switch Mask */ +#define DEVEPTCFG_EPTYPE_Pos 11 /**< (DEVEPTCFG) Endpoint Type Position */ +#define DEVEPTCFG_EPTYPE (_U_(0x3) << DEVEPTCFG_EPTYPE_Pos) /**< (DEVEPTCFG) Endpoint Type Mask */ +#define DEVEPTCFG_EPTYPE_CTRL_Val _U_(0x0) /**< (DEVEPTCFG) Control */ +#define DEVEPTCFG_EPTYPE_ISO_Val _U_(0x1) /**< (DEVEPTCFG) Isochronous */ +#define DEVEPTCFG_EPTYPE_BLK_Val _U_(0x2) /**< (DEVEPTCFG) Bulk */ +#define DEVEPTCFG_EPTYPE_INTRPT_Val _U_(0x3) /**< (DEVEPTCFG) Interrupt */ +#define DEVEPTCFG_EPTYPE_CTRL (DEVEPTCFG_EPTYPE_CTRL_Val << DEVEPTCFG_EPTYPE_Pos) /**< (DEVEPTCFG) Control Position */ +#define DEVEPTCFG_EPTYPE_ISO (DEVEPTCFG_EPTYPE_ISO_Val << DEVEPTCFG_EPTYPE_Pos) /**< (DEVEPTCFG) Isochronous Position */ +#define DEVEPTCFG_EPTYPE_BLK (DEVEPTCFG_EPTYPE_BLK_Val << DEVEPTCFG_EPTYPE_Pos) /**< (DEVEPTCFG) Bulk Position */ +#define DEVEPTCFG_EPTYPE_INTRPT (DEVEPTCFG_EPTYPE_INTRPT_Val << DEVEPTCFG_EPTYPE_Pos) /**< (DEVEPTCFG) Interrupt Position */ +#define DEVEPTCFG_NBTRANS_Pos 13 /**< (DEVEPTCFG) Number of transactions per microframe for isochronous endpoint Position */ +#define DEVEPTCFG_NBTRANS (_U_(0x3) << DEVEPTCFG_NBTRANS_Pos) /**< (DEVEPTCFG) Number of transactions per microframe for isochronous endpoint Mask */ +#define DEVEPTCFG_NBTRANS_0_TRANS_Val _U_(0x0) /**< (DEVEPTCFG) Reserved to endpoint that does not have the high-bandwidth isochronous capability. */ +#define DEVEPTCFG_NBTRANS_1_TRANS_Val _U_(0x1) /**< (DEVEPTCFG) Default value: one transaction per microframe. */ +#define DEVEPTCFG_NBTRANS_2_TRANS_Val _U_(0x2) /**< (DEVEPTCFG) Two transactions per microframe. This endpoint should be configured as double-bank. */ +#define DEVEPTCFG_NBTRANS_3_TRANS_Val _U_(0x3) /**< (DEVEPTCFG) Three transactions per microframe. This endpoint should be configured as triple-bank. */ +#define DEVEPTCFG_NBTRANS_0_TRANS (DEVEPTCFG_NBTRANS_0_TRANS_Val << DEVEPTCFG_NBTRANS_Pos) /**< (DEVEPTCFG) Reserved to endpoint that does not have the high-bandwidth isochronous capability. Position */ +#define DEVEPTCFG_NBTRANS_1_TRANS (DEVEPTCFG_NBTRANS_1_TRANS_Val << DEVEPTCFG_NBTRANS_Pos) /**< (DEVEPTCFG) Default value: one transaction per microframe. Position */ +#define DEVEPTCFG_NBTRANS_2_TRANS (DEVEPTCFG_NBTRANS_2_TRANS_Val << DEVEPTCFG_NBTRANS_Pos) /**< (DEVEPTCFG) Two transactions per microframe. This endpoint should be configured as double-bank. Position */ +#define DEVEPTCFG_NBTRANS_3_TRANS (DEVEPTCFG_NBTRANS_3_TRANS_Val << DEVEPTCFG_NBTRANS_Pos) /**< (DEVEPTCFG) Three transactions per microframe. This endpoint should be configured as triple-bank. Position */ +#define DEVEPTCFG_Msk _U_(0x7B7E) /**< (DEVEPTCFG) Register Mask */ + + +/* -------- DEVEPTISR : (USBHS Offset: 0x130) (R/ 32) Device Endpoint Interrupt Status Register -------- */ + +#define DEVEPTISR_OFFSET (0x130) /**< (DEVEPTISR) Device Endpoint Interrupt Status Register Offset */ + +#define DEVEPTISR_TXINI_Pos 0 /**< (DEVEPTISR) Transmitted IN Data Interrupt Position */ +#define DEVEPTISR_TXINI (_U_(0x1) << DEVEPTISR_TXINI_Pos) /**< (DEVEPTISR) Transmitted IN Data Interrupt Mask */ +#define DEVEPTISR_RXOUTI_Pos 1 /**< (DEVEPTISR) Received OUT Data Interrupt Position */ +#define DEVEPTISR_RXOUTI (_U_(0x1) << DEVEPTISR_RXOUTI_Pos) /**< (DEVEPTISR) Received OUT Data Interrupt Mask */ +#define DEVEPTISR_OVERFI_Pos 5 /**< (DEVEPTISR) Overflow Interrupt Position */ +#define DEVEPTISR_OVERFI (_U_(0x1) << DEVEPTISR_OVERFI_Pos) /**< (DEVEPTISR) Overflow Interrupt Mask */ +#define DEVEPTISR_SHORTPACKET_Pos 7 /**< (DEVEPTISR) Short Packet Interrupt Position */ +#define DEVEPTISR_SHORTPACKET (_U_(0x1) << DEVEPTISR_SHORTPACKET_Pos) /**< (DEVEPTISR) Short Packet Interrupt Mask */ +#define DEVEPTISR_DTSEQ_Pos 8 /**< (DEVEPTISR) Data Toggle Sequence Position */ +#define DEVEPTISR_DTSEQ (_U_(0x3) << DEVEPTISR_DTSEQ_Pos) /**< (DEVEPTISR) Data Toggle Sequence Mask */ +#define DEVEPTISR_DTSEQ_DATA0_Val _U_(0x0) /**< (DEVEPTISR) Data0 toggle sequence */ +#define DEVEPTISR_DTSEQ_DATA1_Val _U_(0x1) /**< (DEVEPTISR) Data1 toggle sequence */ +#define DEVEPTISR_DTSEQ_DATA2_Val _U_(0x2) /**< (DEVEPTISR) Reserved for high-bandwidth isochronous endpoint */ +#define DEVEPTISR_DTSEQ_MDATA_Val _U_(0x3) /**< (DEVEPTISR) Reserved for high-bandwidth isochronous endpoint */ +#define DEVEPTISR_DTSEQ_DATA0 (DEVEPTISR_DTSEQ_DATA0_Val << DEVEPTISR_DTSEQ_Pos) /**< (DEVEPTISR) Data0 toggle sequence Position */ +#define DEVEPTISR_DTSEQ_DATA1 (DEVEPTISR_DTSEQ_DATA1_Val << DEVEPTISR_DTSEQ_Pos) /**< (DEVEPTISR) Data1 toggle sequence Position */ +#define DEVEPTISR_DTSEQ_DATA2 (DEVEPTISR_DTSEQ_DATA2_Val << DEVEPTISR_DTSEQ_Pos) /**< (DEVEPTISR) Reserved for high-bandwidth isochronous endpoint Position */ +#define DEVEPTISR_DTSEQ_MDATA (DEVEPTISR_DTSEQ_MDATA_Val << DEVEPTISR_DTSEQ_Pos) /**< (DEVEPTISR) Reserved for high-bandwidth isochronous endpoint Position */ +#define DEVEPTISR_NBUSYBK_Pos 12 /**< (DEVEPTISR) Number of Busy Banks Position */ +#define DEVEPTISR_NBUSYBK (_U_(0x3) << DEVEPTISR_NBUSYBK_Pos) /**< (DEVEPTISR) Number of Busy Banks Mask */ +#define DEVEPTISR_NBUSYBK_0_BUSY_Val _U_(0x0) /**< (DEVEPTISR) 0 busy bank (all banks free) */ +#define DEVEPTISR_NBUSYBK_1_BUSY_Val _U_(0x1) /**< (DEVEPTISR) 1 busy bank */ +#define DEVEPTISR_NBUSYBK_2_BUSY_Val _U_(0x2) /**< (DEVEPTISR) 2 busy banks */ +#define DEVEPTISR_NBUSYBK_3_BUSY_Val _U_(0x3) /**< (DEVEPTISR) 3 busy banks */ +#define DEVEPTISR_NBUSYBK_0_BUSY (DEVEPTISR_NBUSYBK_0_BUSY_Val << DEVEPTISR_NBUSYBK_Pos) /**< (DEVEPTISR) 0 busy bank (all banks free) Position */ +#define DEVEPTISR_NBUSYBK_1_BUSY (DEVEPTISR_NBUSYBK_1_BUSY_Val << DEVEPTISR_NBUSYBK_Pos) /**< (DEVEPTISR) 1 busy bank Position */ +#define DEVEPTISR_NBUSYBK_2_BUSY (DEVEPTISR_NBUSYBK_2_BUSY_Val << DEVEPTISR_NBUSYBK_Pos) /**< (DEVEPTISR) 2 busy banks Position */ +#define DEVEPTISR_NBUSYBK_3_BUSY (DEVEPTISR_NBUSYBK_3_BUSY_Val << DEVEPTISR_NBUSYBK_Pos) /**< (DEVEPTISR) 3 busy banks Position */ +#define DEVEPTISR_CURRBK_Pos 14 /**< (DEVEPTISR) Current Bank Position */ +#define DEVEPTISR_CURRBK (_U_(0x3) << DEVEPTISR_CURRBK_Pos) /**< (DEVEPTISR) Current Bank Mask */ +#define DEVEPTISR_CURRBK_BANK0_Val _U_(0x0) /**< (DEVEPTISR) Current bank is bank0 */ +#define DEVEPTISR_CURRBK_BANK1_Val _U_(0x1) /**< (DEVEPTISR) Current bank is bank1 */ +#define DEVEPTISR_CURRBK_BANK2_Val _U_(0x2) /**< (DEVEPTISR) Current bank is bank2 */ +#define DEVEPTISR_CURRBK_BANK0 (DEVEPTISR_CURRBK_BANK0_Val << DEVEPTISR_CURRBK_Pos) /**< (DEVEPTISR) Current bank is bank0 Position */ +#define DEVEPTISR_CURRBK_BANK1 (DEVEPTISR_CURRBK_BANK1_Val << DEVEPTISR_CURRBK_Pos) /**< (DEVEPTISR) Current bank is bank1 Position */ +#define DEVEPTISR_CURRBK_BANK2 (DEVEPTISR_CURRBK_BANK2_Val << DEVEPTISR_CURRBK_Pos) /**< (DEVEPTISR) Current bank is bank2 Position */ +#define DEVEPTISR_RWALL_Pos 16 /**< (DEVEPTISR) Read/Write Allowed Position */ +#define DEVEPTISR_RWALL (_U_(0x1) << DEVEPTISR_RWALL_Pos) /**< (DEVEPTISR) Read/Write Allowed Mask */ +#define DEVEPTISR_CFGOK_Pos 18 /**< (DEVEPTISR) Configuration OK Status Position */ +#define DEVEPTISR_CFGOK (_U_(0x1) << DEVEPTISR_CFGOK_Pos) /**< (DEVEPTISR) Configuration OK Status Mask */ +#define DEVEPTISR_BYCT_Pos 20 /**< (DEVEPTISR) Byte Count Position */ +#define DEVEPTISR_BYCT (_U_(0x7FF) << DEVEPTISR_BYCT_Pos) /**< (DEVEPTISR) Byte Count Mask */ +#define DEVEPTISR_Msk _U_(0x7FF5F3A3) /**< (DEVEPTISR) Register Mask */ + +/* CTRL mode */ +#define DEVEPTISR_CTRL_RXSTPI_Pos 2 /**< (DEVEPTISR) Received SETUP Interrupt Position */ +#define DEVEPTISR_CTRL_RXSTPI (_U_(0x1) << DEVEPTISR_CTRL_RXSTPI_Pos) /**< (DEVEPTISR) Received SETUP Interrupt Mask */ +#define DEVEPTISR_CTRL_NAKOUTI_Pos 3 /**< (DEVEPTISR) NAKed OUT Interrupt Position */ +#define DEVEPTISR_CTRL_NAKOUTI (_U_(0x1) << DEVEPTISR_CTRL_NAKOUTI_Pos) /**< (DEVEPTISR) NAKed OUT Interrupt Mask */ +#define DEVEPTISR_CTRL_NAKINI_Pos 4 /**< (DEVEPTISR) NAKed IN Interrupt Position */ +#define DEVEPTISR_CTRL_NAKINI (_U_(0x1) << DEVEPTISR_CTRL_NAKINI_Pos) /**< (DEVEPTISR) NAKed IN Interrupt Mask */ +#define DEVEPTISR_CTRL_STALLEDI_Pos 6 /**< (DEVEPTISR) STALLed Interrupt Position */ +#define DEVEPTISR_CTRL_STALLEDI (_U_(0x1) << DEVEPTISR_CTRL_STALLEDI_Pos) /**< (DEVEPTISR) STALLed Interrupt Mask */ +#define DEVEPTISR_CTRL_CTRLDIR_Pos 17 /**< (DEVEPTISR) Control Direction Position */ +#define DEVEPTISR_CTRL_CTRLDIR (_U_(0x1) << DEVEPTISR_CTRL_CTRLDIR_Pos) /**< (DEVEPTISR) Control Direction Mask */ +#define DEVEPTISR_CTRL_Msk _U_(0x2005C) /**< (DEVEPTISR_CTRL) Register Mask */ + +/* ISO mode */ +#define DEVEPTISR_ISO_UNDERFI_Pos 2 /**< (DEVEPTISR) Underflow Interrupt Position */ +#define DEVEPTISR_ISO_UNDERFI (_U_(0x1) << DEVEPTISR_ISO_UNDERFI_Pos) /**< (DEVEPTISR) Underflow Interrupt Mask */ +#define DEVEPTISR_ISO_HBISOINERRI_Pos 3 /**< (DEVEPTISR) High Bandwidth Isochronous IN Underflow Error Interrupt Position */ +#define DEVEPTISR_ISO_HBISOINERRI (_U_(0x1) << DEVEPTISR_ISO_HBISOINERRI_Pos) /**< (DEVEPTISR) High Bandwidth Isochronous IN Underflow Error Interrupt Mask */ +#define DEVEPTISR_ISO_HBISOFLUSHI_Pos 4 /**< (DEVEPTISR) High Bandwidth Isochronous IN Flush Interrupt Position */ +#define DEVEPTISR_ISO_HBISOFLUSHI (_U_(0x1) << DEVEPTISR_ISO_HBISOFLUSHI_Pos) /**< (DEVEPTISR) High Bandwidth Isochronous IN Flush Interrupt Mask */ +#define DEVEPTISR_ISO_CRCERRI_Pos 6 /**< (DEVEPTISR) CRC Error Interrupt Position */ +#define DEVEPTISR_ISO_CRCERRI (_U_(0x1) << DEVEPTISR_ISO_CRCERRI_Pos) /**< (DEVEPTISR) CRC Error Interrupt Mask */ +#define DEVEPTISR_ISO_ERRORTRANS_Pos 10 /**< (DEVEPTISR) High-bandwidth Isochronous OUT Endpoint Transaction Error Interrupt Position */ +#define DEVEPTISR_ISO_ERRORTRANS (_U_(0x1) << DEVEPTISR_ISO_ERRORTRANS_Pos) /**< (DEVEPTISR) High-bandwidth Isochronous OUT Endpoint Transaction Error Interrupt Mask */ +#define DEVEPTISR_ISO_Msk _U_(0x45C) /**< (DEVEPTISR_ISO) Register Mask */ + +/* BLK mode */ +#define DEVEPTISR_BLK_RXSTPI_Pos 2 /**< (DEVEPTISR) Received SETUP Interrupt Position */ +#define DEVEPTISR_BLK_RXSTPI (_U_(0x1) << DEVEPTISR_BLK_RXSTPI_Pos) /**< (DEVEPTISR) Received SETUP Interrupt Mask */ +#define DEVEPTISR_BLK_NAKOUTI_Pos 3 /**< (DEVEPTISR) NAKed OUT Interrupt Position */ +#define DEVEPTISR_BLK_NAKOUTI (_U_(0x1) << DEVEPTISR_BLK_NAKOUTI_Pos) /**< (DEVEPTISR) NAKed OUT Interrupt Mask */ +#define DEVEPTISR_BLK_NAKINI_Pos 4 /**< (DEVEPTISR) NAKed IN Interrupt Position */ +#define DEVEPTISR_BLK_NAKINI (_U_(0x1) << DEVEPTISR_BLK_NAKINI_Pos) /**< (DEVEPTISR) NAKed IN Interrupt Mask */ +#define DEVEPTISR_BLK_STALLEDI_Pos 6 /**< (DEVEPTISR) STALLed Interrupt Position */ +#define DEVEPTISR_BLK_STALLEDI (_U_(0x1) << DEVEPTISR_BLK_STALLEDI_Pos) /**< (DEVEPTISR) STALLed Interrupt Mask */ +#define DEVEPTISR_BLK_CTRLDIR_Pos 17 /**< (DEVEPTISR) Control Direction Position */ +#define DEVEPTISR_BLK_CTRLDIR (_U_(0x1) << DEVEPTISR_BLK_CTRLDIR_Pos) /**< (DEVEPTISR) Control Direction Mask */ +#define DEVEPTISR_BLK_Msk _U_(0x2005C) /**< (DEVEPTISR_BLK) Register Mask */ + +/* INTRPT mode */ +#define DEVEPTISR_INTRPT_RXSTPI_Pos 2 /**< (DEVEPTISR) Received SETUP Interrupt Position */ +#define DEVEPTISR_INTRPT_RXSTPI (_U_(0x1) << DEVEPTISR_INTRPT_RXSTPI_Pos) /**< (DEVEPTISR) Received SETUP Interrupt Mask */ +#define DEVEPTISR_INTRPT_NAKOUTI_Pos 3 /**< (DEVEPTISR) NAKed OUT Interrupt Position */ +#define DEVEPTISR_INTRPT_NAKOUTI (_U_(0x1) << DEVEPTISR_INTRPT_NAKOUTI_Pos) /**< (DEVEPTISR) NAKed OUT Interrupt Mask */ +#define DEVEPTISR_INTRPT_NAKINI_Pos 4 /**< (DEVEPTISR) NAKed IN Interrupt Position */ +#define DEVEPTISR_INTRPT_NAKINI (_U_(0x1) << DEVEPTISR_INTRPT_NAKINI_Pos) /**< (DEVEPTISR) NAKed IN Interrupt Mask */ +#define DEVEPTISR_INTRPT_STALLEDI_Pos 6 /**< (DEVEPTISR) STALLed Interrupt Position */ +#define DEVEPTISR_INTRPT_STALLEDI (_U_(0x1) << DEVEPTISR_INTRPT_STALLEDI_Pos) /**< (DEVEPTISR) STALLed Interrupt Mask */ +#define DEVEPTISR_INTRPT_CTRLDIR_Pos 17 /**< (DEVEPTISR) Control Direction Position */ +#define DEVEPTISR_INTRPT_CTRLDIR (_U_(0x1) << DEVEPTISR_INTRPT_CTRLDIR_Pos) /**< (DEVEPTISR) Control Direction Mask */ +#define DEVEPTISR_INTRPT_Msk _U_(0x2005C) /**< (DEVEPTISR_INTRPT) Register Mask */ + + +/* -------- DEVEPTICR : (USBHS Offset: 0x160) (/W 32) Device Endpoint Interrupt Clear Register -------- */ + +#define DEVEPTICR_OFFSET (0x160) /**< (DEVEPTICR) Device Endpoint Interrupt Clear Register Offset */ + +#define DEVEPTICR_TXINIC_Pos 0 /**< (DEVEPTICR) Transmitted IN Data Interrupt Clear Position */ +#define DEVEPTICR_TXINIC (_U_(0x1) << DEVEPTICR_TXINIC_Pos) /**< (DEVEPTICR) Transmitted IN Data Interrupt Clear Mask */ +#define DEVEPTICR_RXOUTIC_Pos 1 /**< (DEVEPTICR) Received OUT Data Interrupt Clear Position */ +#define DEVEPTICR_RXOUTIC (_U_(0x1) << DEVEPTICR_RXOUTIC_Pos) /**< (DEVEPTICR) Received OUT Data Interrupt Clear Mask */ +#define DEVEPTICR_OVERFIC_Pos 5 /**< (DEVEPTICR) Overflow Interrupt Clear Position */ +#define DEVEPTICR_OVERFIC (_U_(0x1) << DEVEPTICR_OVERFIC_Pos) /**< (DEVEPTICR) Overflow Interrupt Clear Mask */ +#define DEVEPTICR_SHORTPACKETC_Pos 7 /**< (DEVEPTICR) Short Packet Interrupt Clear Position */ +#define DEVEPTICR_SHORTPACKETC (_U_(0x1) << DEVEPTICR_SHORTPACKETC_Pos) /**< (DEVEPTICR) Short Packet Interrupt Clear Mask */ +#define DEVEPTICR_Msk _U_(0xA3) /**< (DEVEPTICR) Register Mask */ + +/* CTRL mode */ +#define DEVEPTICR_CTRL_RXSTPIC_Pos 2 /**< (DEVEPTICR) Received SETUP Interrupt Clear Position */ +#define DEVEPTICR_CTRL_RXSTPIC (_U_(0x1) << DEVEPTICR_CTRL_RXSTPIC_Pos) /**< (DEVEPTICR) Received SETUP Interrupt Clear Mask */ +#define DEVEPTICR_CTRL_NAKOUTIC_Pos 3 /**< (DEVEPTICR) NAKed OUT Interrupt Clear Position */ +#define DEVEPTICR_CTRL_NAKOUTIC (_U_(0x1) << DEVEPTICR_CTRL_NAKOUTIC_Pos) /**< (DEVEPTICR) NAKed OUT Interrupt Clear Mask */ +#define DEVEPTICR_CTRL_NAKINIC_Pos 4 /**< (DEVEPTICR) NAKed IN Interrupt Clear Position */ +#define DEVEPTICR_CTRL_NAKINIC (_U_(0x1) << DEVEPTICR_CTRL_NAKINIC_Pos) /**< (DEVEPTICR) NAKed IN Interrupt Clear Mask */ +#define DEVEPTICR_CTRL_STALLEDIC_Pos 6 /**< (DEVEPTICR) STALLed Interrupt Clear Position */ +#define DEVEPTICR_CTRL_STALLEDIC (_U_(0x1) << DEVEPTICR_CTRL_STALLEDIC_Pos) /**< (DEVEPTICR) STALLed Interrupt Clear Mask */ +#define DEVEPTICR_CTRL_Msk _U_(0x5C) /**< (DEVEPTICR_CTRL) Register Mask */ + +/* ISO mode */ +#define DEVEPTICR_ISO_UNDERFIC_Pos 2 /**< (DEVEPTICR) Underflow Interrupt Clear Position */ +#define DEVEPTICR_ISO_UNDERFIC (_U_(0x1) << DEVEPTICR_ISO_UNDERFIC_Pos) /**< (DEVEPTICR) Underflow Interrupt Clear Mask */ +#define DEVEPTICR_ISO_HBISOINERRIC_Pos 3 /**< (DEVEPTICR) High Bandwidth Isochronous IN Underflow Error Interrupt Clear Position */ +#define DEVEPTICR_ISO_HBISOINERRIC (_U_(0x1) << DEVEPTICR_ISO_HBISOINERRIC_Pos) /**< (DEVEPTICR) High Bandwidth Isochronous IN Underflow Error Interrupt Clear Mask */ +#define DEVEPTICR_ISO_HBISOFLUSHIC_Pos 4 /**< (DEVEPTICR) High Bandwidth Isochronous IN Flush Interrupt Clear Position */ +#define DEVEPTICR_ISO_HBISOFLUSHIC (_U_(0x1) << DEVEPTICR_ISO_HBISOFLUSHIC_Pos) /**< (DEVEPTICR) High Bandwidth Isochronous IN Flush Interrupt Clear Mask */ +#define DEVEPTICR_ISO_CRCERRIC_Pos 6 /**< (DEVEPTICR) CRC Error Interrupt Clear Position */ +#define DEVEPTICR_ISO_CRCERRIC (_U_(0x1) << DEVEPTICR_ISO_CRCERRIC_Pos) /**< (DEVEPTICR) CRC Error Interrupt Clear Mask */ +#define DEVEPTICR_ISO_Msk _U_(0x5C) /**< (DEVEPTICR_ISO) Register Mask */ + +/* BLK mode */ +#define DEVEPTICR_BLK_RXSTPIC_Pos 2 /**< (DEVEPTICR) Received SETUP Interrupt Clear Position */ +#define DEVEPTICR_BLK_RXSTPIC (_U_(0x1) << DEVEPTICR_BLK_RXSTPIC_Pos) /**< (DEVEPTICR) Received SETUP Interrupt Clear Mask */ +#define DEVEPTICR_BLK_NAKOUTIC_Pos 3 /**< (DEVEPTICR) NAKed OUT Interrupt Clear Position */ +#define DEVEPTICR_BLK_NAKOUTIC (_U_(0x1) << DEVEPTICR_BLK_NAKOUTIC_Pos) /**< (DEVEPTICR) NAKed OUT Interrupt Clear Mask */ +#define DEVEPTICR_BLK_NAKINIC_Pos 4 /**< (DEVEPTICR) NAKed IN Interrupt Clear Position */ +#define DEVEPTICR_BLK_NAKINIC (_U_(0x1) << DEVEPTICR_BLK_NAKINIC_Pos) /**< (DEVEPTICR) NAKed IN Interrupt Clear Mask */ +#define DEVEPTICR_BLK_STALLEDIC_Pos 6 /**< (DEVEPTICR) STALLed Interrupt Clear Position */ +#define DEVEPTICR_BLK_STALLEDIC (_U_(0x1) << DEVEPTICR_BLK_STALLEDIC_Pos) /**< (DEVEPTICR) STALLed Interrupt Clear Mask */ +#define DEVEPTICR_BLK_Msk _U_(0x5C) /**< (DEVEPTICR_BLK) Register Mask */ + +/* INTRPT mode */ +#define DEVEPTICR_INTRPT_RXSTPIC_Pos 2 /**< (DEVEPTICR) Received SETUP Interrupt Clear Position */ +#define DEVEPTICR_INTRPT_RXSTPIC (_U_(0x1) << DEVEPTICR_INTRPT_RXSTPIC_Pos) /**< (DEVEPTICR) Received SETUP Interrupt Clear Mask */ +#define DEVEPTICR_INTRPT_NAKOUTIC_Pos 3 /**< (DEVEPTICR) NAKed OUT Interrupt Clear Position */ +#define DEVEPTICR_INTRPT_NAKOUTIC (_U_(0x1) << DEVEPTICR_INTRPT_NAKOUTIC_Pos) /**< (DEVEPTICR) NAKed OUT Interrupt Clear Mask */ +#define DEVEPTICR_INTRPT_NAKINIC_Pos 4 /**< (DEVEPTICR) NAKed IN Interrupt Clear Position */ +#define DEVEPTICR_INTRPT_NAKINIC (_U_(0x1) << DEVEPTICR_INTRPT_NAKINIC_Pos) /**< (DEVEPTICR) NAKed IN Interrupt Clear Mask */ +#define DEVEPTICR_INTRPT_STALLEDIC_Pos 6 /**< (DEVEPTICR) STALLed Interrupt Clear Position */ +#define DEVEPTICR_INTRPT_STALLEDIC (_U_(0x1) << DEVEPTICR_INTRPT_STALLEDIC_Pos) /**< (DEVEPTICR) STALLed Interrupt Clear Mask */ +#define DEVEPTICR_INTRPT_Msk _U_(0x5C) /**< (DEVEPTICR_INTRPT) Register Mask */ + + +/* -------- DEVEPTIFR : (USBHS Offset: 0x190) (/W 32) Device Endpoint Interrupt Set Register -------- */ + +#define DEVEPTIFR_OFFSET (0x190) /**< (DEVEPTIFR) Device Endpoint Interrupt Set Register Offset */ + +#define DEVEPTIFR_TXINIS_Pos 0 /**< (DEVEPTIFR) Transmitted IN Data Interrupt Set Position */ +#define DEVEPTIFR_TXINIS (_U_(0x1) << DEVEPTIFR_TXINIS_Pos) /**< (DEVEPTIFR) Transmitted IN Data Interrupt Set Mask */ +#define DEVEPTIFR_RXOUTIS_Pos 1 /**< (DEVEPTIFR) Received OUT Data Interrupt Set Position */ +#define DEVEPTIFR_RXOUTIS (_U_(0x1) << DEVEPTIFR_RXOUTIS_Pos) /**< (DEVEPTIFR) Received OUT Data Interrupt Set Mask */ +#define DEVEPTIFR_OVERFIS_Pos 5 /**< (DEVEPTIFR) Overflow Interrupt Set Position */ +#define DEVEPTIFR_OVERFIS (_U_(0x1) << DEVEPTIFR_OVERFIS_Pos) /**< (DEVEPTIFR) Overflow Interrupt Set Mask */ +#define DEVEPTIFR_SHORTPACKETS_Pos 7 /**< (DEVEPTIFR) Short Packet Interrupt Set Position */ +#define DEVEPTIFR_SHORTPACKETS (_U_(0x1) << DEVEPTIFR_SHORTPACKETS_Pos) /**< (DEVEPTIFR) Short Packet Interrupt Set Mask */ +#define DEVEPTIFR_NBUSYBKS_Pos 12 /**< (DEVEPTIFR) Number of Busy Banks Interrupt Set Position */ +#define DEVEPTIFR_NBUSYBKS (_U_(0x1) << DEVEPTIFR_NBUSYBKS_Pos) /**< (DEVEPTIFR) Number of Busy Banks Interrupt Set Mask */ +#define DEVEPTIFR_Msk _U_(0x10A3) /**< (DEVEPTIFR) Register Mask */ + +/* CTRL mode */ +#define DEVEPTIFR_CTRL_RXSTPIS_Pos 2 /**< (DEVEPTIFR) Received SETUP Interrupt Set Position */ +#define DEVEPTIFR_CTRL_RXSTPIS (_U_(0x1) << DEVEPTIFR_CTRL_RXSTPIS_Pos) /**< (DEVEPTIFR) Received SETUP Interrupt Set Mask */ +#define DEVEPTIFR_CTRL_NAKOUTIS_Pos 3 /**< (DEVEPTIFR) NAKed OUT Interrupt Set Position */ +#define DEVEPTIFR_CTRL_NAKOUTIS (_U_(0x1) << DEVEPTIFR_CTRL_NAKOUTIS_Pos) /**< (DEVEPTIFR) NAKed OUT Interrupt Set Mask */ +#define DEVEPTIFR_CTRL_NAKINIS_Pos 4 /**< (DEVEPTIFR) NAKed IN Interrupt Set Position */ +#define DEVEPTIFR_CTRL_NAKINIS (_U_(0x1) << DEVEPTIFR_CTRL_NAKINIS_Pos) /**< (DEVEPTIFR) NAKed IN Interrupt Set Mask */ +#define DEVEPTIFR_CTRL_STALLEDIS_Pos 6 /**< (DEVEPTIFR) STALLed Interrupt Set Position */ +#define DEVEPTIFR_CTRL_STALLEDIS (_U_(0x1) << DEVEPTIFR_CTRL_STALLEDIS_Pos) /**< (DEVEPTIFR) STALLed Interrupt Set Mask */ +#define DEVEPTIFR_CTRL_Msk _U_(0x5C) /**< (DEVEPTIFR_CTRL) Register Mask */ + +/* ISO mode */ +#define DEVEPTIFR_ISO_UNDERFIS_Pos 2 /**< (DEVEPTIFR) Underflow Interrupt Set Position */ +#define DEVEPTIFR_ISO_UNDERFIS (_U_(0x1) << DEVEPTIFR_ISO_UNDERFIS_Pos) /**< (DEVEPTIFR) Underflow Interrupt Set Mask */ +#define DEVEPTIFR_ISO_HBISOINERRIS_Pos 3 /**< (DEVEPTIFR) High Bandwidth Isochronous IN Underflow Error Interrupt Set Position */ +#define DEVEPTIFR_ISO_HBISOINERRIS (_U_(0x1) << DEVEPTIFR_ISO_HBISOINERRIS_Pos) /**< (DEVEPTIFR) High Bandwidth Isochronous IN Underflow Error Interrupt Set Mask */ +#define DEVEPTIFR_ISO_HBISOFLUSHIS_Pos 4 /**< (DEVEPTIFR) High Bandwidth Isochronous IN Flush Interrupt Set Position */ +#define DEVEPTIFR_ISO_HBISOFLUSHIS (_U_(0x1) << DEVEPTIFR_ISO_HBISOFLUSHIS_Pos) /**< (DEVEPTIFR) High Bandwidth Isochronous IN Flush Interrupt Set Mask */ +#define DEVEPTIFR_ISO_CRCERRIS_Pos 6 /**< (DEVEPTIFR) CRC Error Interrupt Set Position */ +#define DEVEPTIFR_ISO_CRCERRIS (_U_(0x1) << DEVEPTIFR_ISO_CRCERRIS_Pos) /**< (DEVEPTIFR) CRC Error Interrupt Set Mask */ +#define DEVEPTIFR_ISO_Msk _U_(0x5C) /**< (DEVEPTIFR_ISO) Register Mask */ + +/* BLK mode */ +#define DEVEPTIFR_BLK_RXSTPIS_Pos 2 /**< (DEVEPTIFR) Received SETUP Interrupt Set Position */ +#define DEVEPTIFR_BLK_RXSTPIS (_U_(0x1) << DEVEPTIFR_BLK_RXSTPIS_Pos) /**< (DEVEPTIFR) Received SETUP Interrupt Set Mask */ +#define DEVEPTIFR_BLK_NAKOUTIS_Pos 3 /**< (DEVEPTIFR) NAKed OUT Interrupt Set Position */ +#define DEVEPTIFR_BLK_NAKOUTIS (_U_(0x1) << DEVEPTIFR_BLK_NAKOUTIS_Pos) /**< (DEVEPTIFR) NAKed OUT Interrupt Set Mask */ +#define DEVEPTIFR_BLK_NAKINIS_Pos 4 /**< (DEVEPTIFR) NAKed IN Interrupt Set Position */ +#define DEVEPTIFR_BLK_NAKINIS (_U_(0x1) << DEVEPTIFR_BLK_NAKINIS_Pos) /**< (DEVEPTIFR) NAKed IN Interrupt Set Mask */ +#define DEVEPTIFR_BLK_STALLEDIS_Pos 6 /**< (DEVEPTIFR) STALLed Interrupt Set Position */ +#define DEVEPTIFR_BLK_STALLEDIS (_U_(0x1) << DEVEPTIFR_BLK_STALLEDIS_Pos) /**< (DEVEPTIFR) STALLed Interrupt Set Mask */ +#define DEVEPTIFR_BLK_Msk _U_(0x5C) /**< (DEVEPTIFR_BLK) Register Mask */ + +/* INTRPT mode */ +#define DEVEPTIFR_INTRPT_RXSTPIS_Pos 2 /**< (DEVEPTIFR) Received SETUP Interrupt Set Position */ +#define DEVEPTIFR_INTRPT_RXSTPIS (_U_(0x1) << DEVEPTIFR_INTRPT_RXSTPIS_Pos) /**< (DEVEPTIFR) Received SETUP Interrupt Set Mask */ +#define DEVEPTIFR_INTRPT_NAKOUTIS_Pos 3 /**< (DEVEPTIFR) NAKed OUT Interrupt Set Position */ +#define DEVEPTIFR_INTRPT_NAKOUTIS (_U_(0x1) << DEVEPTIFR_INTRPT_NAKOUTIS_Pos) /**< (DEVEPTIFR) NAKed OUT Interrupt Set Mask */ +#define DEVEPTIFR_INTRPT_NAKINIS_Pos 4 /**< (DEVEPTIFR) NAKed IN Interrupt Set Position */ +#define DEVEPTIFR_INTRPT_NAKINIS (_U_(0x1) << DEVEPTIFR_INTRPT_NAKINIS_Pos) /**< (DEVEPTIFR) NAKed IN Interrupt Set Mask */ +#define DEVEPTIFR_INTRPT_STALLEDIS_Pos 6 /**< (DEVEPTIFR) STALLed Interrupt Set Position */ +#define DEVEPTIFR_INTRPT_STALLEDIS (_U_(0x1) << DEVEPTIFR_INTRPT_STALLEDIS_Pos) /**< (DEVEPTIFR) STALLed Interrupt Set Mask */ +#define DEVEPTIFR_INTRPT_Msk _U_(0x5C) /**< (DEVEPTIFR_INTRPT) Register Mask */ + + +/* -------- DEVEPTIMR : (USBHS Offset: 0x1c0) (R/ 32) Device Endpoint Interrupt Mask Register -------- */ + +#define DEVEPTIMR_OFFSET (0x1C0) /**< (DEVEPTIMR) Device Endpoint Interrupt Mask Register Offset */ + +#define DEVEPTIMR_TXINE_Pos 0 /**< (DEVEPTIMR) Transmitted IN Data Interrupt Position */ +#define DEVEPTIMR_TXINE (_U_(0x1) << DEVEPTIMR_TXINE_Pos) /**< (DEVEPTIMR) Transmitted IN Data Interrupt Mask */ +#define DEVEPTIMR_RXOUTE_Pos 1 /**< (DEVEPTIMR) Received OUT Data Interrupt Position */ +#define DEVEPTIMR_RXOUTE (_U_(0x1) << DEVEPTIMR_RXOUTE_Pos) /**< (DEVEPTIMR) Received OUT Data Interrupt Mask */ +#define DEVEPTIMR_OVERFE_Pos 5 /**< (DEVEPTIMR) Overflow Interrupt Position */ +#define DEVEPTIMR_OVERFE (_U_(0x1) << DEVEPTIMR_OVERFE_Pos) /**< (DEVEPTIMR) Overflow Interrupt Mask */ +#define DEVEPTIMR_SHORTPACKETE_Pos 7 /**< (DEVEPTIMR) Short Packet Interrupt Position */ +#define DEVEPTIMR_SHORTPACKETE (_U_(0x1) << DEVEPTIMR_SHORTPACKETE_Pos) /**< (DEVEPTIMR) Short Packet Interrupt Mask */ +#define DEVEPTIMR_NBUSYBKE_Pos 12 /**< (DEVEPTIMR) Number of Busy Banks Interrupt Position */ +#define DEVEPTIMR_NBUSYBKE (_U_(0x1) << DEVEPTIMR_NBUSYBKE_Pos) /**< (DEVEPTIMR) Number of Busy Banks Interrupt Mask */ +#define DEVEPTIMR_KILLBK_Pos 13 /**< (DEVEPTIMR) Kill IN Bank Position */ +#define DEVEPTIMR_KILLBK (_U_(0x1) << DEVEPTIMR_KILLBK_Pos) /**< (DEVEPTIMR) Kill IN Bank Mask */ +#define DEVEPTIMR_FIFOCON_Pos 14 /**< (DEVEPTIMR) FIFO Control Position */ +#define DEVEPTIMR_FIFOCON (_U_(0x1) << DEVEPTIMR_FIFOCON_Pos) /**< (DEVEPTIMR) FIFO Control Mask */ +#define DEVEPTIMR_EPDISHDMA_Pos 16 /**< (DEVEPTIMR) Endpoint Interrupts Disable HDMA Request Position */ +#define DEVEPTIMR_EPDISHDMA (_U_(0x1) << DEVEPTIMR_EPDISHDMA_Pos) /**< (DEVEPTIMR) Endpoint Interrupts Disable HDMA Request Mask */ +#define DEVEPTIMR_RSTDT_Pos 18 /**< (DEVEPTIMR) Reset Data Toggle Position */ +#define DEVEPTIMR_RSTDT (_U_(0x1) << DEVEPTIMR_RSTDT_Pos) /**< (DEVEPTIMR) Reset Data Toggle Mask */ +#define DEVEPTIMR_Msk _U_(0x570A3) /**< (DEVEPTIMR) Register Mask */ + +/* CTRL mode */ +#define DEVEPTIMR_CTRL_RXSTPE_Pos 2 /**< (DEVEPTIMR) Received SETUP Interrupt Position */ +#define DEVEPTIMR_CTRL_RXSTPE (_U_(0x1) << DEVEPTIMR_CTRL_RXSTPE_Pos) /**< (DEVEPTIMR) Received SETUP Interrupt Mask */ +#define DEVEPTIMR_CTRL_NAKOUTE_Pos 3 /**< (DEVEPTIMR) NAKed OUT Interrupt Position */ +#define DEVEPTIMR_CTRL_NAKOUTE (_U_(0x1) << DEVEPTIMR_CTRL_NAKOUTE_Pos) /**< (DEVEPTIMR) NAKed OUT Interrupt Mask */ +#define DEVEPTIMR_CTRL_NAKINE_Pos 4 /**< (DEVEPTIMR) NAKed IN Interrupt Position */ +#define DEVEPTIMR_CTRL_NAKINE (_U_(0x1) << DEVEPTIMR_CTRL_NAKINE_Pos) /**< (DEVEPTIMR) NAKed IN Interrupt Mask */ +#define DEVEPTIMR_CTRL_STALLEDE_Pos 6 /**< (DEVEPTIMR) STALLed Interrupt Position */ +#define DEVEPTIMR_CTRL_STALLEDE (_U_(0x1) << DEVEPTIMR_CTRL_STALLEDE_Pos) /**< (DEVEPTIMR) STALLed Interrupt Mask */ +#define DEVEPTIMR_CTRL_NYETDIS_Pos 17 /**< (DEVEPTIMR) NYET Token Disable Position */ +#define DEVEPTIMR_CTRL_NYETDIS (_U_(0x1) << DEVEPTIMR_CTRL_NYETDIS_Pos) /**< (DEVEPTIMR) NYET Token Disable Mask */ +#define DEVEPTIMR_CTRL_STALLRQ_Pos 19 /**< (DEVEPTIMR) STALL Request Position */ +#define DEVEPTIMR_CTRL_STALLRQ (_U_(0x1) << DEVEPTIMR_CTRL_STALLRQ_Pos) /**< (DEVEPTIMR) STALL Request Mask */ +#define DEVEPTIMR_CTRL_Msk _U_(0xA005C) /**< (DEVEPTIMR_CTRL) Register Mask */ + +/* ISO mode */ +#define DEVEPTIMR_ISO_UNDERFE_Pos 2 /**< (DEVEPTIMR) Underflow Interrupt Position */ +#define DEVEPTIMR_ISO_UNDERFE (_U_(0x1) << DEVEPTIMR_ISO_UNDERFE_Pos) /**< (DEVEPTIMR) Underflow Interrupt Mask */ +#define DEVEPTIMR_ISO_HBISOINERRE_Pos 3 /**< (DEVEPTIMR) High Bandwidth Isochronous IN Underflow Error Interrupt Position */ +#define DEVEPTIMR_ISO_HBISOINERRE (_U_(0x1) << DEVEPTIMR_ISO_HBISOINERRE_Pos) /**< (DEVEPTIMR) High Bandwidth Isochronous IN Underflow Error Interrupt Mask */ +#define DEVEPTIMR_ISO_HBISOFLUSHE_Pos 4 /**< (DEVEPTIMR) High Bandwidth Isochronous IN Flush Interrupt Position */ +#define DEVEPTIMR_ISO_HBISOFLUSHE (_U_(0x1) << DEVEPTIMR_ISO_HBISOFLUSHE_Pos) /**< (DEVEPTIMR) High Bandwidth Isochronous IN Flush Interrupt Mask */ +#define DEVEPTIMR_ISO_CRCERRE_Pos 6 /**< (DEVEPTIMR) CRC Error Interrupt Position */ +#define DEVEPTIMR_ISO_CRCERRE (_U_(0x1) << DEVEPTIMR_ISO_CRCERRE_Pos) /**< (DEVEPTIMR) CRC Error Interrupt Mask */ +#define DEVEPTIMR_ISO_MDATAE_Pos 8 /**< (DEVEPTIMR) MData Interrupt Position */ +#define DEVEPTIMR_ISO_MDATAE (_U_(0x1) << DEVEPTIMR_ISO_MDATAE_Pos) /**< (DEVEPTIMR) MData Interrupt Mask */ +#define DEVEPTIMR_ISO_DATAXE_Pos 9 /**< (DEVEPTIMR) DataX Interrupt Position */ +#define DEVEPTIMR_ISO_DATAXE (_U_(0x1) << DEVEPTIMR_ISO_DATAXE_Pos) /**< (DEVEPTIMR) DataX Interrupt Mask */ +#define DEVEPTIMR_ISO_ERRORTRANSE_Pos 10 /**< (DEVEPTIMR) Transaction Error Interrupt Position */ +#define DEVEPTIMR_ISO_ERRORTRANSE (_U_(0x1) << DEVEPTIMR_ISO_ERRORTRANSE_Pos) /**< (DEVEPTIMR) Transaction Error Interrupt Mask */ +#define DEVEPTIMR_ISO_Msk _U_(0x75C) /**< (DEVEPTIMR_ISO) Register Mask */ + +/* BLK mode */ +#define DEVEPTIMR_BLK_RXSTPE_Pos 2 /**< (DEVEPTIMR) Received SETUP Interrupt Position */ +#define DEVEPTIMR_BLK_RXSTPE (_U_(0x1) << DEVEPTIMR_BLK_RXSTPE_Pos) /**< (DEVEPTIMR) Received SETUP Interrupt Mask */ +#define DEVEPTIMR_BLK_NAKOUTE_Pos 3 /**< (DEVEPTIMR) NAKed OUT Interrupt Position */ +#define DEVEPTIMR_BLK_NAKOUTE (_U_(0x1) << DEVEPTIMR_BLK_NAKOUTE_Pos) /**< (DEVEPTIMR) NAKed OUT Interrupt Mask */ +#define DEVEPTIMR_BLK_NAKINE_Pos 4 /**< (DEVEPTIMR) NAKed IN Interrupt Position */ +#define DEVEPTIMR_BLK_NAKINE (_U_(0x1) << DEVEPTIMR_BLK_NAKINE_Pos) /**< (DEVEPTIMR) NAKed IN Interrupt Mask */ +#define DEVEPTIMR_BLK_STALLEDE_Pos 6 /**< (DEVEPTIMR) STALLed Interrupt Position */ +#define DEVEPTIMR_BLK_STALLEDE (_U_(0x1) << DEVEPTIMR_BLK_STALLEDE_Pos) /**< (DEVEPTIMR) STALLed Interrupt Mask */ +#define DEVEPTIMR_BLK_NYETDIS_Pos 17 /**< (DEVEPTIMR) NYET Token Disable Position */ +#define DEVEPTIMR_BLK_NYETDIS (_U_(0x1) << DEVEPTIMR_BLK_NYETDIS_Pos) /**< (DEVEPTIMR) NYET Token Disable Mask */ +#define DEVEPTIMR_BLK_STALLRQ_Pos 19 /**< (DEVEPTIMR) STALL Request Position */ +#define DEVEPTIMR_BLK_STALLRQ (_U_(0x1) << DEVEPTIMR_BLK_STALLRQ_Pos) /**< (DEVEPTIMR) STALL Request Mask */ +#define DEVEPTIMR_BLK_Msk _U_(0xA005C) /**< (DEVEPTIMR_BLK) Register Mask */ + +/* INTRPT mode */ +#define DEVEPTIMR_INTRPT_RXSTPE_Pos 2 /**< (DEVEPTIMR) Received SETUP Interrupt Position */ +#define DEVEPTIMR_INTRPT_RXSTPE (_U_(0x1) << DEVEPTIMR_INTRPT_RXSTPE_Pos) /**< (DEVEPTIMR) Received SETUP Interrupt Mask */ +#define DEVEPTIMR_INTRPT_NAKOUTE_Pos 3 /**< (DEVEPTIMR) NAKed OUT Interrupt Position */ +#define DEVEPTIMR_INTRPT_NAKOUTE (_U_(0x1) << DEVEPTIMR_INTRPT_NAKOUTE_Pos) /**< (DEVEPTIMR) NAKed OUT Interrupt Mask */ +#define DEVEPTIMR_INTRPT_NAKINE_Pos 4 /**< (DEVEPTIMR) NAKed IN Interrupt Position */ +#define DEVEPTIMR_INTRPT_NAKINE (_U_(0x1) << DEVEPTIMR_INTRPT_NAKINE_Pos) /**< (DEVEPTIMR) NAKed IN Interrupt Mask */ +#define DEVEPTIMR_INTRPT_STALLEDE_Pos 6 /**< (DEVEPTIMR) STALLed Interrupt Position */ +#define DEVEPTIMR_INTRPT_STALLEDE (_U_(0x1) << DEVEPTIMR_INTRPT_STALLEDE_Pos) /**< (DEVEPTIMR) STALLed Interrupt Mask */ +#define DEVEPTIMR_INTRPT_NYETDIS_Pos 17 /**< (DEVEPTIMR) NYET Token Disable Position */ +#define DEVEPTIMR_INTRPT_NYETDIS (_U_(0x1) << DEVEPTIMR_INTRPT_NYETDIS_Pos) /**< (DEVEPTIMR) NYET Token Disable Mask */ +#define DEVEPTIMR_INTRPT_STALLRQ_Pos 19 /**< (DEVEPTIMR) STALL Request Position */ +#define DEVEPTIMR_INTRPT_STALLRQ (_U_(0x1) << DEVEPTIMR_INTRPT_STALLRQ_Pos) /**< (DEVEPTIMR) STALL Request Mask */ +#define DEVEPTIMR_INTRPT_Msk _U_(0xA005C) /**< (DEVEPTIMR_INTRPT) Register Mask */ + + +/* -------- DEVEPTIER : (USBHS Offset: 0x1f0) (/W 32) Device Endpoint Interrupt Enable Register -------- */ + +#define DEVEPTIER_OFFSET (0x1F0) /**< (DEVEPTIER) Device Endpoint Interrupt Enable Register Offset */ + +#define DEVEPTIER_TXINES_Pos 0 /**< (DEVEPTIER) Transmitted IN Data Interrupt Enable Position */ +#define DEVEPTIER_TXINES (_U_(0x1) << DEVEPTIER_TXINES_Pos) /**< (DEVEPTIER) Transmitted IN Data Interrupt Enable Mask */ +#define DEVEPTIER_RXOUTES_Pos 1 /**< (DEVEPTIER) Received OUT Data Interrupt Enable Position */ +#define DEVEPTIER_RXOUTES (_U_(0x1) << DEVEPTIER_RXOUTES_Pos) /**< (DEVEPTIER) Received OUT Data Interrupt Enable Mask */ +#define DEVEPTIER_OVERFES_Pos 5 /**< (DEVEPTIER) Overflow Interrupt Enable Position */ +#define DEVEPTIER_OVERFES (_U_(0x1) << DEVEPTIER_OVERFES_Pos) /**< (DEVEPTIER) Overflow Interrupt Enable Mask */ +#define DEVEPTIER_SHORTPACKETES_Pos 7 /**< (DEVEPTIER) Short Packet Interrupt Enable Position */ +#define DEVEPTIER_SHORTPACKETES (_U_(0x1) << DEVEPTIER_SHORTPACKETES_Pos) /**< (DEVEPTIER) Short Packet Interrupt Enable Mask */ +#define DEVEPTIER_NBUSYBKES_Pos 12 /**< (DEVEPTIER) Number of Busy Banks Interrupt Enable Position */ +#define DEVEPTIER_NBUSYBKES (_U_(0x1) << DEVEPTIER_NBUSYBKES_Pos) /**< (DEVEPTIER) Number of Busy Banks Interrupt Enable Mask */ +#define DEVEPTIER_KILLBKS_Pos 13 /**< (DEVEPTIER) Kill IN Bank Position */ +#define DEVEPTIER_KILLBKS (_U_(0x1) << DEVEPTIER_KILLBKS_Pos) /**< (DEVEPTIER) Kill IN Bank Mask */ +#define DEVEPTIER_FIFOCONS_Pos 14 /**< (DEVEPTIER) FIFO Control Position */ +#define DEVEPTIER_FIFOCONS (_U_(0x1) << DEVEPTIER_FIFOCONS_Pos) /**< (DEVEPTIER) FIFO Control Mask */ +#define DEVEPTIER_EPDISHDMAS_Pos 16 /**< (DEVEPTIER) Endpoint Interrupts Disable HDMA Request Enable Position */ +#define DEVEPTIER_EPDISHDMAS (_U_(0x1) << DEVEPTIER_EPDISHDMAS_Pos) /**< (DEVEPTIER) Endpoint Interrupts Disable HDMA Request Enable Mask */ +#define DEVEPTIER_RSTDTS_Pos 18 /**< (DEVEPTIER) Reset Data Toggle Enable Position */ +#define DEVEPTIER_RSTDTS (_U_(0x1) << DEVEPTIER_RSTDTS_Pos) /**< (DEVEPTIER) Reset Data Toggle Enable Mask */ +#define DEVEPTIER_Msk _U_(0x570A3) /**< (DEVEPTIER) Register Mask */ + +/* CTRL mode */ +#define DEVEPTIER_CTRL_RXSTPES_Pos 2 /**< (DEVEPTIER) Received SETUP Interrupt Enable Position */ +#define DEVEPTIER_CTRL_RXSTPES (_U_(0x1) << DEVEPTIER_CTRL_RXSTPES_Pos) /**< (DEVEPTIER) Received SETUP Interrupt Enable Mask */ +#define DEVEPTIER_CTRL_NAKOUTES_Pos 3 /**< (DEVEPTIER) NAKed OUT Interrupt Enable Position */ +#define DEVEPTIER_CTRL_NAKOUTES (_U_(0x1) << DEVEPTIER_CTRL_NAKOUTES_Pos) /**< (DEVEPTIER) NAKed OUT Interrupt Enable Mask */ +#define DEVEPTIER_CTRL_NAKINES_Pos 4 /**< (DEVEPTIER) NAKed IN Interrupt Enable Position */ +#define DEVEPTIER_CTRL_NAKINES (_U_(0x1) << DEVEPTIER_CTRL_NAKINES_Pos) /**< (DEVEPTIER) NAKed IN Interrupt Enable Mask */ +#define DEVEPTIER_CTRL_STALLEDES_Pos 6 /**< (DEVEPTIER) STALLed Interrupt Enable Position */ +#define DEVEPTIER_CTRL_STALLEDES (_U_(0x1) << DEVEPTIER_CTRL_STALLEDES_Pos) /**< (DEVEPTIER) STALLed Interrupt Enable Mask */ +#define DEVEPTIER_CTRL_NYETDISS_Pos 17 /**< (DEVEPTIER) NYET Token Disable Enable Position */ +#define DEVEPTIER_CTRL_NYETDISS (_U_(0x1) << DEVEPTIER_CTRL_NYETDISS_Pos) /**< (DEVEPTIER) NYET Token Disable Enable Mask */ +#define DEVEPTIER_CTRL_STALLRQS_Pos 19 /**< (DEVEPTIER) STALL Request Enable Position */ +#define DEVEPTIER_CTRL_STALLRQS (_U_(0x1) << DEVEPTIER_CTRL_STALLRQS_Pos) /**< (DEVEPTIER) STALL Request Enable Mask */ +#define DEVEPTIER_CTRL_Msk _U_(0xA005C) /**< (DEVEPTIER_CTRL) Register Mask */ + +/* ISO mode */ +#define DEVEPTIER_ISO_UNDERFES_Pos 2 /**< (DEVEPTIER) Underflow Interrupt Enable Position */ +#define DEVEPTIER_ISO_UNDERFES (_U_(0x1) << DEVEPTIER_ISO_UNDERFES_Pos) /**< (DEVEPTIER) Underflow Interrupt Enable Mask */ +#define DEVEPTIER_ISO_HBISOINERRES_Pos 3 /**< (DEVEPTIER) High Bandwidth Isochronous IN Underflow Error Interrupt Enable Position */ +#define DEVEPTIER_ISO_HBISOINERRES (_U_(0x1) << DEVEPTIER_ISO_HBISOINERRES_Pos) /**< (DEVEPTIER) High Bandwidth Isochronous IN Underflow Error Interrupt Enable Mask */ +#define DEVEPTIER_ISO_HBISOFLUSHES_Pos 4 /**< (DEVEPTIER) High Bandwidth Isochronous IN Flush Interrupt Enable Position */ +#define DEVEPTIER_ISO_HBISOFLUSHES (_U_(0x1) << DEVEPTIER_ISO_HBISOFLUSHES_Pos) /**< (DEVEPTIER) High Bandwidth Isochronous IN Flush Interrupt Enable Mask */ +#define DEVEPTIER_ISO_CRCERRES_Pos 6 /**< (DEVEPTIER) CRC Error Interrupt Enable Position */ +#define DEVEPTIER_ISO_CRCERRES (_U_(0x1) << DEVEPTIER_ISO_CRCERRES_Pos) /**< (DEVEPTIER) CRC Error Interrupt Enable Mask */ +#define DEVEPTIER_ISO_MDATAES_Pos 8 /**< (DEVEPTIER) MData Interrupt Enable Position */ +#define DEVEPTIER_ISO_MDATAES (_U_(0x1) << DEVEPTIER_ISO_MDATAES_Pos) /**< (DEVEPTIER) MData Interrupt Enable Mask */ +#define DEVEPTIER_ISO_DATAXES_Pos 9 /**< (DEVEPTIER) DataX Interrupt Enable Position */ +#define DEVEPTIER_ISO_DATAXES (_U_(0x1) << DEVEPTIER_ISO_DATAXES_Pos) /**< (DEVEPTIER) DataX Interrupt Enable Mask */ +#define DEVEPTIER_ISO_ERRORTRANSES_Pos 10 /**< (DEVEPTIER) Transaction Error Interrupt Enable Position */ +#define DEVEPTIER_ISO_ERRORTRANSES (_U_(0x1) << DEVEPTIER_ISO_ERRORTRANSES_Pos) /**< (DEVEPTIER) Transaction Error Interrupt Enable Mask */ +#define DEVEPTIER_ISO_Msk _U_(0x75C) /**< (DEVEPTIER_ISO) Register Mask */ + +/* BLK mode */ +#define DEVEPTIER_BLK_RXSTPES_Pos 2 /**< (DEVEPTIER) Received SETUP Interrupt Enable Position */ +#define DEVEPTIER_BLK_RXSTPES (_U_(0x1) << DEVEPTIER_BLK_RXSTPES_Pos) /**< (DEVEPTIER) Received SETUP Interrupt Enable Mask */ +#define DEVEPTIER_BLK_NAKOUTES_Pos 3 /**< (DEVEPTIER) NAKed OUT Interrupt Enable Position */ +#define DEVEPTIER_BLK_NAKOUTES (_U_(0x1) << DEVEPTIER_BLK_NAKOUTES_Pos) /**< (DEVEPTIER) NAKed OUT Interrupt Enable Mask */ +#define DEVEPTIER_BLK_NAKINES_Pos 4 /**< (DEVEPTIER) NAKed IN Interrupt Enable Position */ +#define DEVEPTIER_BLK_NAKINES (_U_(0x1) << DEVEPTIER_BLK_NAKINES_Pos) /**< (DEVEPTIER) NAKed IN Interrupt Enable Mask */ +#define DEVEPTIER_BLK_STALLEDES_Pos 6 /**< (DEVEPTIER) STALLed Interrupt Enable Position */ +#define DEVEPTIER_BLK_STALLEDES (_U_(0x1) << DEVEPTIER_BLK_STALLEDES_Pos) /**< (DEVEPTIER) STALLed Interrupt Enable Mask */ +#define DEVEPTIER_BLK_NYETDISS_Pos 17 /**< (DEVEPTIER) NYET Token Disable Enable Position */ +#define DEVEPTIER_BLK_NYETDISS (_U_(0x1) << DEVEPTIER_BLK_NYETDISS_Pos) /**< (DEVEPTIER) NYET Token Disable Enable Mask */ +#define DEVEPTIER_BLK_STALLRQS_Pos 19 /**< (DEVEPTIER) STALL Request Enable Position */ +#define DEVEPTIER_BLK_STALLRQS (_U_(0x1) << DEVEPTIER_BLK_STALLRQS_Pos) /**< (DEVEPTIER) STALL Request Enable Mask */ +#define DEVEPTIER_BLK_Msk _U_(0xA005C) /**< (DEVEPTIER_BLK) Register Mask */ + +/* INTRPT mode */ +#define DEVEPTIER_INTRPT_RXSTPES_Pos 2 /**< (DEVEPTIER) Received SETUP Interrupt Enable Position */ +#define DEVEPTIER_INTRPT_RXSTPES (_U_(0x1) << DEVEPTIER_INTRPT_RXSTPES_Pos) /**< (DEVEPTIER) Received SETUP Interrupt Enable Mask */ +#define DEVEPTIER_INTRPT_NAKOUTES_Pos 3 /**< (DEVEPTIER) NAKed OUT Interrupt Enable Position */ +#define DEVEPTIER_INTRPT_NAKOUTES (_U_(0x1) << DEVEPTIER_INTRPT_NAKOUTES_Pos) /**< (DEVEPTIER) NAKed OUT Interrupt Enable Mask */ +#define DEVEPTIER_INTRPT_NAKINES_Pos 4 /**< (DEVEPTIER) NAKed IN Interrupt Enable Position */ +#define DEVEPTIER_INTRPT_NAKINES (_U_(0x1) << DEVEPTIER_INTRPT_NAKINES_Pos) /**< (DEVEPTIER) NAKed IN Interrupt Enable Mask */ +#define DEVEPTIER_INTRPT_STALLEDES_Pos 6 /**< (DEVEPTIER) STALLed Interrupt Enable Position */ +#define DEVEPTIER_INTRPT_STALLEDES (_U_(0x1) << DEVEPTIER_INTRPT_STALLEDES_Pos) /**< (DEVEPTIER) STALLed Interrupt Enable Mask */ +#define DEVEPTIER_INTRPT_NYETDISS_Pos 17 /**< (DEVEPTIER) NYET Token Disable Enable Position */ +#define DEVEPTIER_INTRPT_NYETDISS (_U_(0x1) << DEVEPTIER_INTRPT_NYETDISS_Pos) /**< (DEVEPTIER) NYET Token Disable Enable Mask */ +#define DEVEPTIER_INTRPT_STALLRQS_Pos 19 /**< (DEVEPTIER) STALL Request Enable Position */ +#define DEVEPTIER_INTRPT_STALLRQS (_U_(0x1) << DEVEPTIER_INTRPT_STALLRQS_Pos) /**< (DEVEPTIER) STALL Request Enable Mask */ +#define DEVEPTIER_INTRPT_Msk _U_(0xA005C) /**< (DEVEPTIER_INTRPT) Register Mask */ + + +/* -------- DEVEPTIDR : (USBHS Offset: 0x220) (/W 32) Device Endpoint Interrupt Disable Register -------- */ + +#define DEVEPTIDR_OFFSET (0x220) /**< (DEVEPTIDR) Device Endpoint Interrupt Disable Register Offset */ + +#define DEVEPTIDR_TXINEC_Pos 0 /**< (DEVEPTIDR) Transmitted IN Interrupt Clear Position */ +#define DEVEPTIDR_TXINEC (_U_(0x1) << DEVEPTIDR_TXINEC_Pos) /**< (DEVEPTIDR) Transmitted IN Interrupt Clear Mask */ +#define DEVEPTIDR_RXOUTEC_Pos 1 /**< (DEVEPTIDR) Received OUT Data Interrupt Clear Position */ +#define DEVEPTIDR_RXOUTEC (_U_(0x1) << DEVEPTIDR_RXOUTEC_Pos) /**< (DEVEPTIDR) Received OUT Data Interrupt Clear Mask */ +#define DEVEPTIDR_OVERFEC_Pos 5 /**< (DEVEPTIDR) Overflow Interrupt Clear Position */ +#define DEVEPTIDR_OVERFEC (_U_(0x1) << DEVEPTIDR_OVERFEC_Pos) /**< (DEVEPTIDR) Overflow Interrupt Clear Mask */ +#define DEVEPTIDR_SHORTPACKETEC_Pos 7 /**< (DEVEPTIDR) Shortpacket Interrupt Clear Position */ +#define DEVEPTIDR_SHORTPACKETEC (_U_(0x1) << DEVEPTIDR_SHORTPACKETEC_Pos) /**< (DEVEPTIDR) Shortpacket Interrupt Clear Mask */ +#define DEVEPTIDR_NBUSYBKEC_Pos 12 /**< (DEVEPTIDR) Number of Busy Banks Interrupt Clear Position */ +#define DEVEPTIDR_NBUSYBKEC (_U_(0x1) << DEVEPTIDR_NBUSYBKEC_Pos) /**< (DEVEPTIDR) Number of Busy Banks Interrupt Clear Mask */ +#define DEVEPTIDR_FIFOCONC_Pos 14 /**< (DEVEPTIDR) FIFO Control Clear Position */ +#define DEVEPTIDR_FIFOCONC (_U_(0x1) << DEVEPTIDR_FIFOCONC_Pos) /**< (DEVEPTIDR) FIFO Control Clear Mask */ +#define DEVEPTIDR_EPDISHDMAC_Pos 16 /**< (DEVEPTIDR) Endpoint Interrupts Disable HDMA Request Clear Position */ +#define DEVEPTIDR_EPDISHDMAC (_U_(0x1) << DEVEPTIDR_EPDISHDMAC_Pos) /**< (DEVEPTIDR) Endpoint Interrupts Disable HDMA Request Clear Mask */ +#define DEVEPTIDR_Msk _U_(0x150A3) /**< (DEVEPTIDR) Register Mask */ + +/* CTRL mode */ +#define DEVEPTIDR_CTRL_RXSTPEC_Pos 2 /**< (DEVEPTIDR) Received SETUP Interrupt Clear Position */ +#define DEVEPTIDR_CTRL_RXSTPEC (_U_(0x1) << DEVEPTIDR_CTRL_RXSTPEC_Pos) /**< (DEVEPTIDR) Received SETUP Interrupt Clear Mask */ +#define DEVEPTIDR_CTRL_NAKOUTEC_Pos 3 /**< (DEVEPTIDR) NAKed OUT Interrupt Clear Position */ +#define DEVEPTIDR_CTRL_NAKOUTEC (_U_(0x1) << DEVEPTIDR_CTRL_NAKOUTEC_Pos) /**< (DEVEPTIDR) NAKed OUT Interrupt Clear Mask */ +#define DEVEPTIDR_CTRL_NAKINEC_Pos 4 /**< (DEVEPTIDR) NAKed IN Interrupt Clear Position */ +#define DEVEPTIDR_CTRL_NAKINEC (_U_(0x1) << DEVEPTIDR_CTRL_NAKINEC_Pos) /**< (DEVEPTIDR) NAKed IN Interrupt Clear Mask */ +#define DEVEPTIDR_CTRL_STALLEDEC_Pos 6 /**< (DEVEPTIDR) STALLed Interrupt Clear Position */ +#define DEVEPTIDR_CTRL_STALLEDEC (_U_(0x1) << DEVEPTIDR_CTRL_STALLEDEC_Pos) /**< (DEVEPTIDR) STALLed Interrupt Clear Mask */ +#define DEVEPTIDR_CTRL_NYETDISC_Pos 17 /**< (DEVEPTIDR) NYET Token Disable Clear Position */ +#define DEVEPTIDR_CTRL_NYETDISC (_U_(0x1) << DEVEPTIDR_CTRL_NYETDISC_Pos) /**< (DEVEPTIDR) NYET Token Disable Clear Mask */ +#define DEVEPTIDR_CTRL_STALLRQC_Pos 19 /**< (DEVEPTIDR) STALL Request Clear Position */ +#define DEVEPTIDR_CTRL_STALLRQC (_U_(0x1) << DEVEPTIDR_CTRL_STALLRQC_Pos) /**< (DEVEPTIDR) STALL Request Clear Mask */ +#define DEVEPTIDR_CTRL_Msk _U_(0xA005C) /**< (DEVEPTIDR_CTRL) Register Mask */ + +/* ISO mode */ +#define DEVEPTIDR_ISO_UNDERFEC_Pos 2 /**< (DEVEPTIDR) Underflow Interrupt Clear Position */ +#define DEVEPTIDR_ISO_UNDERFEC (_U_(0x1) << DEVEPTIDR_ISO_UNDERFEC_Pos) /**< (DEVEPTIDR) Underflow Interrupt Clear Mask */ +#define DEVEPTIDR_ISO_HBISOINERREC_Pos 3 /**< (DEVEPTIDR) High Bandwidth Isochronous IN Underflow Error Interrupt Clear Position */ +#define DEVEPTIDR_ISO_HBISOINERREC (_U_(0x1) << DEVEPTIDR_ISO_HBISOINERREC_Pos) /**< (DEVEPTIDR) High Bandwidth Isochronous IN Underflow Error Interrupt Clear Mask */ +#define DEVEPTIDR_ISO_HBISOFLUSHEC_Pos 4 /**< (DEVEPTIDR) High Bandwidth Isochronous IN Flush Interrupt Clear Position */ +#define DEVEPTIDR_ISO_HBISOFLUSHEC (_U_(0x1) << DEVEPTIDR_ISO_HBISOFLUSHEC_Pos) /**< (DEVEPTIDR) High Bandwidth Isochronous IN Flush Interrupt Clear Mask */ +#define DEVEPTIDR_ISO_MDATAEC_Pos 8 /**< (DEVEPTIDR) MData Interrupt Clear Position */ +#define DEVEPTIDR_ISO_MDATAEC (_U_(0x1) << DEVEPTIDR_ISO_MDATAEC_Pos) /**< (DEVEPTIDR) MData Interrupt Clear Mask */ +#define DEVEPTIDR_ISO_DATAXEC_Pos 9 /**< (DEVEPTIDR) DataX Interrupt Clear Position */ +#define DEVEPTIDR_ISO_DATAXEC (_U_(0x1) << DEVEPTIDR_ISO_DATAXEC_Pos) /**< (DEVEPTIDR) DataX Interrupt Clear Mask */ +#define DEVEPTIDR_ISO_ERRORTRANSEC_Pos 10 /**< (DEVEPTIDR) Transaction Error Interrupt Clear Position */ +#define DEVEPTIDR_ISO_ERRORTRANSEC (_U_(0x1) << DEVEPTIDR_ISO_ERRORTRANSEC_Pos) /**< (DEVEPTIDR) Transaction Error Interrupt Clear Mask */ +#define DEVEPTIDR_ISO_Msk _U_(0x71C) /**< (DEVEPTIDR_ISO) Register Mask */ + +/* BLK mode */ +#define DEVEPTIDR_BLK_RXSTPEC_Pos 2 /**< (DEVEPTIDR) Received SETUP Interrupt Clear Position */ +#define DEVEPTIDR_BLK_RXSTPEC (_U_(0x1) << DEVEPTIDR_BLK_RXSTPEC_Pos) /**< (DEVEPTIDR) Received SETUP Interrupt Clear Mask */ +#define DEVEPTIDR_BLK_NAKOUTEC_Pos 3 /**< (DEVEPTIDR) NAKed OUT Interrupt Clear Position */ +#define DEVEPTIDR_BLK_NAKOUTEC (_U_(0x1) << DEVEPTIDR_BLK_NAKOUTEC_Pos) /**< (DEVEPTIDR) NAKed OUT Interrupt Clear Mask */ +#define DEVEPTIDR_BLK_NAKINEC_Pos 4 /**< (DEVEPTIDR) NAKed IN Interrupt Clear Position */ +#define DEVEPTIDR_BLK_NAKINEC (_U_(0x1) << DEVEPTIDR_BLK_NAKINEC_Pos) /**< (DEVEPTIDR) NAKed IN Interrupt Clear Mask */ +#define DEVEPTIDR_BLK_STALLEDEC_Pos 6 /**< (DEVEPTIDR) STALLed Interrupt Clear Position */ +#define DEVEPTIDR_BLK_STALLEDEC (_U_(0x1) << DEVEPTIDR_BLK_STALLEDEC_Pos) /**< (DEVEPTIDR) STALLed Interrupt Clear Mask */ +#define DEVEPTIDR_BLK_NYETDISC_Pos 17 /**< (DEVEPTIDR) NYET Token Disable Clear Position */ +#define DEVEPTIDR_BLK_NYETDISC (_U_(0x1) << DEVEPTIDR_BLK_NYETDISC_Pos) /**< (DEVEPTIDR) NYET Token Disable Clear Mask */ +#define DEVEPTIDR_BLK_STALLRQC_Pos 19 /**< (DEVEPTIDR) STALL Request Clear Position */ +#define DEVEPTIDR_BLK_STALLRQC (_U_(0x1) << DEVEPTIDR_BLK_STALLRQC_Pos) /**< (DEVEPTIDR) STALL Request Clear Mask */ +#define DEVEPTIDR_BLK_Msk _U_(0xA005C) /**< (DEVEPTIDR_BLK) Register Mask */ + +/* INTRPT mode */ +#define DEVEPTIDR_INTRPT_RXSTPEC_Pos 2 /**< (DEVEPTIDR) Received SETUP Interrupt Clear Position */ +#define DEVEPTIDR_INTRPT_RXSTPEC (_U_(0x1) << DEVEPTIDR_INTRPT_RXSTPEC_Pos) /**< (DEVEPTIDR) Received SETUP Interrupt Clear Mask */ +#define DEVEPTIDR_INTRPT_NAKOUTEC_Pos 3 /**< (DEVEPTIDR) NAKed OUT Interrupt Clear Position */ +#define DEVEPTIDR_INTRPT_NAKOUTEC (_U_(0x1) << DEVEPTIDR_INTRPT_NAKOUTEC_Pos) /**< (DEVEPTIDR) NAKed OUT Interrupt Clear Mask */ +#define DEVEPTIDR_INTRPT_NAKINEC_Pos 4 /**< (DEVEPTIDR) NAKed IN Interrupt Clear Position */ +#define DEVEPTIDR_INTRPT_NAKINEC (_U_(0x1) << DEVEPTIDR_INTRPT_NAKINEC_Pos) /**< (DEVEPTIDR) NAKed IN Interrupt Clear Mask */ +#define DEVEPTIDR_INTRPT_STALLEDEC_Pos 6 /**< (DEVEPTIDR) STALLed Interrupt Clear Position */ +#define DEVEPTIDR_INTRPT_STALLEDEC (_U_(0x1) << DEVEPTIDR_INTRPT_STALLEDEC_Pos) /**< (DEVEPTIDR) STALLed Interrupt Clear Mask */ +#define DEVEPTIDR_INTRPT_NYETDISC_Pos 17 /**< (DEVEPTIDR) NYET Token Disable Clear Position */ +#define DEVEPTIDR_INTRPT_NYETDISC (_U_(0x1) << DEVEPTIDR_INTRPT_NYETDISC_Pos) /**< (DEVEPTIDR) NYET Token Disable Clear Mask */ +#define DEVEPTIDR_INTRPT_STALLRQC_Pos 19 /**< (DEVEPTIDR) STALL Request Clear Position */ +#define DEVEPTIDR_INTRPT_STALLRQC (_U_(0x1) << DEVEPTIDR_INTRPT_STALLRQC_Pos) /**< (DEVEPTIDR) STALL Request Clear Mask */ +#define DEVEPTIDR_INTRPT_Msk _U_(0xA005C) /**< (DEVEPTIDR_INTRPT) Register Mask */ + + +/* -------- HSTCTRL : (USBHS Offset: 0x400) (R/W 32) Host General Control Register -------- */ + +#define HSTCTRL_OFFSET (0x400) /**< (HSTCTRL) Host General Control Register Offset */ + +#define HSTCTRL_SOFE_Pos 8 /**< (HSTCTRL) Start of Frame Generation Enable Position */ +#define HSTCTRL_SOFE (_U_(0x1) << HSTCTRL_SOFE_Pos) /**< (HSTCTRL) Start of Frame Generation Enable Mask */ +#define HSTCTRL_RESET_Pos 9 /**< (HSTCTRL) Send USB Reset Position */ +#define HSTCTRL_RESET (_U_(0x1) << HSTCTRL_RESET_Pos) /**< (HSTCTRL) Send USB Reset Mask */ +#define HSTCTRL_RESUME_Pos 10 /**< (HSTCTRL) Send USB Resume Position */ +#define HSTCTRL_RESUME (_U_(0x1) << HSTCTRL_RESUME_Pos) /**< (HSTCTRL) Send USB Resume Mask */ +#define HSTCTRL_SPDCONF_Pos 12 /**< (HSTCTRL) Mode Configuration Position */ +#define HSTCTRL_SPDCONF (_U_(0x3) << HSTCTRL_SPDCONF_Pos) /**< (HSTCTRL) Mode Configuration Mask */ +#define HSTCTRL_SPDCONF_NORMAL_Val _U_(0x0) /**< (HSTCTRL) The host starts in Full-speed mode and performs a high-speed reset to switch to High-speed mode if the downstream peripheral is high-speed capable. */ +#define HSTCTRL_SPDCONF_LOW_POWER_Val _U_(0x1) /**< (HSTCTRL) For a better consumption, if high speed is not needed. */ +#define HSTCTRL_SPDCONF_HIGH_SPEED_Val _U_(0x2) /**< (HSTCTRL) Forced high speed. */ +#define HSTCTRL_SPDCONF_FORCED_FS_Val _U_(0x3) /**< (HSTCTRL) The host remains in Full-speed mode whatever the peripheral speed capability. */ +#define HSTCTRL_SPDCONF_NORMAL (HSTCTRL_SPDCONF_NORMAL_Val << HSTCTRL_SPDCONF_Pos) /**< (HSTCTRL) The host starts in Full-speed mode and performs a high-speed reset to switch to High-speed mode if the downstream peripheral is high-speed capable. Position */ +#define HSTCTRL_SPDCONF_LOW_POWER (HSTCTRL_SPDCONF_LOW_POWER_Val << HSTCTRL_SPDCONF_Pos) /**< (HSTCTRL) For a better consumption, if high speed is not needed. Position */ +#define HSTCTRL_SPDCONF_HIGH_SPEED (HSTCTRL_SPDCONF_HIGH_SPEED_Val << HSTCTRL_SPDCONF_Pos) /**< (HSTCTRL) Forced high speed. Position */ +#define HSTCTRL_SPDCONF_FORCED_FS (HSTCTRL_SPDCONF_FORCED_FS_Val << HSTCTRL_SPDCONF_Pos) /**< (HSTCTRL) The host remains in Full-speed mode whatever the peripheral speed capability. Position */ +#define HSTCTRL_Msk _U_(0x3700) /**< (HSTCTRL) Register Mask */ + + +/* -------- HSTISR : (USBHS Offset: 0x404) (R/ 32) Host Global Interrupt Status Register -------- */ + +#define HSTISR_OFFSET (0x404) /**< (HSTISR) Host Global Interrupt Status Register Offset */ + +#define HSTISR_DCONNI_Pos 0 /**< (HSTISR) Device Connection Interrupt Position */ +#define HSTISR_DCONNI (_U_(0x1) << HSTISR_DCONNI_Pos) /**< (HSTISR) Device Connection Interrupt Mask */ +#define HSTISR_DDISCI_Pos 1 /**< (HSTISR) Device Disconnection Interrupt Position */ +#define HSTISR_DDISCI (_U_(0x1) << HSTISR_DDISCI_Pos) /**< (HSTISR) Device Disconnection Interrupt Mask */ +#define HSTISR_RSTI_Pos 2 /**< (HSTISR) USB Reset Sent Interrupt Position */ +#define HSTISR_RSTI (_U_(0x1) << HSTISR_RSTI_Pos) /**< (HSTISR) USB Reset Sent Interrupt Mask */ +#define HSTISR_RSMEDI_Pos 3 /**< (HSTISR) Downstream Resume Sent Interrupt Position */ +#define HSTISR_RSMEDI (_U_(0x1) << HSTISR_RSMEDI_Pos) /**< (HSTISR) Downstream Resume Sent Interrupt Mask */ +#define HSTISR_RXRSMI_Pos 4 /**< (HSTISR) Upstream Resume Received Interrupt Position */ +#define HSTISR_RXRSMI (_U_(0x1) << HSTISR_RXRSMI_Pos) /**< (HSTISR) Upstream Resume Received Interrupt Mask */ +#define HSTISR_HSOFI_Pos 5 /**< (HSTISR) Host Start of Frame Interrupt Position */ +#define HSTISR_HSOFI (_U_(0x1) << HSTISR_HSOFI_Pos) /**< (HSTISR) Host Start of Frame Interrupt Mask */ +#define HSTISR_HWUPI_Pos 6 /**< (HSTISR) Host Wake-Up Interrupt Position */ +#define HSTISR_HWUPI (_U_(0x1) << HSTISR_HWUPI_Pos) /**< (HSTISR) Host Wake-Up Interrupt Mask */ +#define HSTISR_PEP_0_Pos 8 /**< (HSTISR) Pipe 0 Interrupt Position */ +#define HSTISR_PEP_0 (_U_(0x1) << HSTISR_PEP_0_Pos) /**< (HSTISR) Pipe 0 Interrupt Mask */ +#define HSTISR_PEP_1_Pos 9 /**< (HSTISR) Pipe 1 Interrupt Position */ +#define HSTISR_PEP_1 (_U_(0x1) << HSTISR_PEP_1_Pos) /**< (HSTISR) Pipe 1 Interrupt Mask */ +#define HSTISR_PEP_2_Pos 10 /**< (HSTISR) Pipe 2 Interrupt Position */ +#define HSTISR_PEP_2 (_U_(0x1) << HSTISR_PEP_2_Pos) /**< (HSTISR) Pipe 2 Interrupt Mask */ +#define HSTISR_PEP_3_Pos 11 /**< (HSTISR) Pipe 3 Interrupt Position */ +#define HSTISR_PEP_3 (_U_(0x1) << HSTISR_PEP_3_Pos) /**< (HSTISR) Pipe 3 Interrupt Mask */ +#define HSTISR_PEP_4_Pos 12 /**< (HSTISR) Pipe 4 Interrupt Position */ +#define HSTISR_PEP_4 (_U_(0x1) << HSTISR_PEP_4_Pos) /**< (HSTISR) Pipe 4 Interrupt Mask */ +#define HSTISR_PEP_5_Pos 13 /**< (HSTISR) Pipe 5 Interrupt Position */ +#define HSTISR_PEP_5 (_U_(0x1) << HSTISR_PEP_5_Pos) /**< (HSTISR) Pipe 5 Interrupt Mask */ +#define HSTISR_PEP_6_Pos 14 /**< (HSTISR) Pipe 6 Interrupt Position */ +#define HSTISR_PEP_6 (_U_(0x1) << HSTISR_PEP_6_Pos) /**< (HSTISR) Pipe 6 Interrupt Mask */ +#define HSTISR_PEP_7_Pos 15 /**< (HSTISR) Pipe 7 Interrupt Position */ +#define HSTISR_PEP_7 (_U_(0x1) << HSTISR_PEP_7_Pos) /**< (HSTISR) Pipe 7 Interrupt Mask */ +#define HSTISR_PEP_8_Pos 16 /**< (HSTISR) Pipe 8 Interrupt Position */ +#define HSTISR_PEP_8 (_U_(0x1) << HSTISR_PEP_8_Pos) /**< (HSTISR) Pipe 8 Interrupt Mask */ +#define HSTISR_PEP_9_Pos 17 /**< (HSTISR) Pipe 9 Interrupt Position */ +#define HSTISR_PEP_9 (_U_(0x1) << HSTISR_PEP_9_Pos) /**< (HSTISR) Pipe 9 Interrupt Mask */ +#define HSTISR_DMA_0_Pos 25 /**< (HSTISR) DMA Channel 0 Interrupt Position */ +#define HSTISR_DMA_0 (_U_(0x1) << HSTISR_DMA_0_Pos) /**< (HSTISR) DMA Channel 0 Interrupt Mask */ +#define HSTISR_DMA_1_Pos 26 /**< (HSTISR) DMA Channel 1 Interrupt Position */ +#define HSTISR_DMA_1 (_U_(0x1) << HSTISR_DMA_1_Pos) /**< (HSTISR) DMA Channel 1 Interrupt Mask */ +#define HSTISR_DMA_2_Pos 27 /**< (HSTISR) DMA Channel 2 Interrupt Position */ +#define HSTISR_DMA_2 (_U_(0x1) << HSTISR_DMA_2_Pos) /**< (HSTISR) DMA Channel 2 Interrupt Mask */ +#define HSTISR_DMA_3_Pos 28 /**< (HSTISR) DMA Channel 3 Interrupt Position */ +#define HSTISR_DMA_3 (_U_(0x1) << HSTISR_DMA_3_Pos) /**< (HSTISR) DMA Channel 3 Interrupt Mask */ +#define HSTISR_DMA_4_Pos 29 /**< (HSTISR) DMA Channel 4 Interrupt Position */ +#define HSTISR_DMA_4 (_U_(0x1) << HSTISR_DMA_4_Pos) /**< (HSTISR) DMA Channel 4 Interrupt Mask */ +#define HSTISR_DMA_5_Pos 30 /**< (HSTISR) DMA Channel 5 Interrupt Position */ +#define HSTISR_DMA_5 (_U_(0x1) << HSTISR_DMA_5_Pos) /**< (HSTISR) DMA Channel 5 Interrupt Mask */ +#define HSTISR_DMA_6_Pos 31 /**< (HSTISR) DMA Channel 6 Interrupt Position */ +#define HSTISR_DMA_6 (_U_(0x1) << HSTISR_DMA_6_Pos) /**< (HSTISR) DMA Channel 6 Interrupt Mask */ +#define HSTISR_Msk _U_(0xFE03FF7F) /**< (HSTISR) Register Mask */ + +#define HSTISR_PEP__Pos 8 /**< (HSTISR Position) Pipe x Interrupt */ +#define HSTISR_PEP_ (_U_(0x3FF) << HSTISR_PEP__Pos) /**< (HSTISR Mask) PEP_ */ +#define HSTISR_DMA__Pos 25 /**< (HSTISR Position) DMA Channel 6 Interrupt */ +#define HSTISR_DMA_ (_U_(0x7F) << HSTISR_DMA__Pos) /**< (HSTISR Mask) DMA_ */ + +/* -------- HSTICR : (USBHS Offset: 0x408) (/W 32) Host Global Interrupt Clear Register -------- */ + +#define HSTICR_OFFSET (0x408) /**< (HSTICR) Host Global Interrupt Clear Register Offset */ + +#define HSTICR_DCONNIC_Pos 0 /**< (HSTICR) Device Connection Interrupt Clear Position */ +#define HSTICR_DCONNIC (_U_(0x1) << HSTICR_DCONNIC_Pos) /**< (HSTICR) Device Connection Interrupt Clear Mask */ +#define HSTICR_DDISCIC_Pos 1 /**< (HSTICR) Device Disconnection Interrupt Clear Position */ +#define HSTICR_DDISCIC (_U_(0x1) << HSTICR_DDISCIC_Pos) /**< (HSTICR) Device Disconnection Interrupt Clear Mask */ +#define HSTICR_RSTIC_Pos 2 /**< (HSTICR) USB Reset Sent Interrupt Clear Position */ +#define HSTICR_RSTIC (_U_(0x1) << HSTICR_RSTIC_Pos) /**< (HSTICR) USB Reset Sent Interrupt Clear Mask */ +#define HSTICR_RSMEDIC_Pos 3 /**< (HSTICR) Downstream Resume Sent Interrupt Clear Position */ +#define HSTICR_RSMEDIC (_U_(0x1) << HSTICR_RSMEDIC_Pos) /**< (HSTICR) Downstream Resume Sent Interrupt Clear Mask */ +#define HSTICR_RXRSMIC_Pos 4 /**< (HSTICR) Upstream Resume Received Interrupt Clear Position */ +#define HSTICR_RXRSMIC (_U_(0x1) << HSTICR_RXRSMIC_Pos) /**< (HSTICR) Upstream Resume Received Interrupt Clear Mask */ +#define HSTICR_HSOFIC_Pos 5 /**< (HSTICR) Host Start of Frame Interrupt Clear Position */ +#define HSTICR_HSOFIC (_U_(0x1) << HSTICR_HSOFIC_Pos) /**< (HSTICR) Host Start of Frame Interrupt Clear Mask */ +#define HSTICR_HWUPIC_Pos 6 /**< (HSTICR) Host Wake-Up Interrupt Clear Position */ +#define HSTICR_HWUPIC (_U_(0x1) << HSTICR_HWUPIC_Pos) /**< (HSTICR) Host Wake-Up Interrupt Clear Mask */ +#define HSTICR_Msk _U_(0x7F) /**< (HSTICR) Register Mask */ + + +/* -------- HSTIFR : (USBHS Offset: 0x40c) (/W 32) Host Global Interrupt Set Register -------- */ + +#define HSTIFR_OFFSET (0x40C) /**< (HSTIFR) Host Global Interrupt Set Register Offset */ + +#define HSTIFR_DCONNIS_Pos 0 /**< (HSTIFR) Device Connection Interrupt Set Position */ +#define HSTIFR_DCONNIS (_U_(0x1) << HSTIFR_DCONNIS_Pos) /**< (HSTIFR) Device Connection Interrupt Set Mask */ +#define HSTIFR_DDISCIS_Pos 1 /**< (HSTIFR) Device Disconnection Interrupt Set Position */ +#define HSTIFR_DDISCIS (_U_(0x1) << HSTIFR_DDISCIS_Pos) /**< (HSTIFR) Device Disconnection Interrupt Set Mask */ +#define HSTIFR_RSTIS_Pos 2 /**< (HSTIFR) USB Reset Sent Interrupt Set Position */ +#define HSTIFR_RSTIS (_U_(0x1) << HSTIFR_RSTIS_Pos) /**< (HSTIFR) USB Reset Sent Interrupt Set Mask */ +#define HSTIFR_RSMEDIS_Pos 3 /**< (HSTIFR) Downstream Resume Sent Interrupt Set Position */ +#define HSTIFR_RSMEDIS (_U_(0x1) << HSTIFR_RSMEDIS_Pos) /**< (HSTIFR) Downstream Resume Sent Interrupt Set Mask */ +#define HSTIFR_RXRSMIS_Pos 4 /**< (HSTIFR) Upstream Resume Received Interrupt Set Position */ +#define HSTIFR_RXRSMIS (_U_(0x1) << HSTIFR_RXRSMIS_Pos) /**< (HSTIFR) Upstream Resume Received Interrupt Set Mask */ +#define HSTIFR_HSOFIS_Pos 5 /**< (HSTIFR) Host Start of Frame Interrupt Set Position */ +#define HSTIFR_HSOFIS (_U_(0x1) << HSTIFR_HSOFIS_Pos) /**< (HSTIFR) Host Start of Frame Interrupt Set Mask */ +#define HSTIFR_HWUPIS_Pos 6 /**< (HSTIFR) Host Wake-Up Interrupt Set Position */ +#define HSTIFR_HWUPIS (_U_(0x1) << HSTIFR_HWUPIS_Pos) /**< (HSTIFR) Host Wake-Up Interrupt Set Mask */ +#define HSTIFR_DMA_0_Pos 25 /**< (HSTIFR) DMA Channel 0 Interrupt Set Position */ +#define HSTIFR_DMA_0 (_U_(0x1) << HSTIFR_DMA_0_Pos) /**< (HSTIFR) DMA Channel 0 Interrupt Set Mask */ +#define HSTIFR_DMA_1_Pos 26 /**< (HSTIFR) DMA Channel 1 Interrupt Set Position */ +#define HSTIFR_DMA_1 (_U_(0x1) << HSTIFR_DMA_1_Pos) /**< (HSTIFR) DMA Channel 1 Interrupt Set Mask */ +#define HSTIFR_DMA_2_Pos 27 /**< (HSTIFR) DMA Channel 2 Interrupt Set Position */ +#define HSTIFR_DMA_2 (_U_(0x1) << HSTIFR_DMA_2_Pos) /**< (HSTIFR) DMA Channel 2 Interrupt Set Mask */ +#define HSTIFR_DMA_3_Pos 28 /**< (HSTIFR) DMA Channel 3 Interrupt Set Position */ +#define HSTIFR_DMA_3 (_U_(0x1) << HSTIFR_DMA_3_Pos) /**< (HSTIFR) DMA Channel 3 Interrupt Set Mask */ +#define HSTIFR_DMA_4_Pos 29 /**< (HSTIFR) DMA Channel 4 Interrupt Set Position */ +#define HSTIFR_DMA_4 (_U_(0x1) << HSTIFR_DMA_4_Pos) /**< (HSTIFR) DMA Channel 4 Interrupt Set Mask */ +#define HSTIFR_DMA_5_Pos 30 /**< (HSTIFR) DMA Channel 5 Interrupt Set Position */ +#define HSTIFR_DMA_5 (_U_(0x1) << HSTIFR_DMA_5_Pos) /**< (HSTIFR) DMA Channel 5 Interrupt Set Mask */ +#define HSTIFR_DMA_6_Pos 31 /**< (HSTIFR) DMA Channel 6 Interrupt Set Position */ +#define HSTIFR_DMA_6 (_U_(0x1) << HSTIFR_DMA_6_Pos) /**< (HSTIFR) DMA Channel 6 Interrupt Set Mask */ +#define HSTIFR_Msk _U_(0xFE00007F) /**< (HSTIFR) Register Mask */ + +#define HSTIFR_DMA__Pos 25 /**< (HSTIFR Position) DMA Channel 6 Interrupt Set */ +#define HSTIFR_DMA_ (_U_(0x7F) << HSTIFR_DMA__Pos) /**< (HSTIFR Mask) DMA_ */ + +/* -------- HSTIMR : (USBHS Offset: 0x410) (R/ 32) Host Global Interrupt Mask Register -------- */ + +#define HSTIMR_OFFSET (0x410) /**< (HSTIMR) Host Global Interrupt Mask Register Offset */ + +#define HSTIMR_DCONNIE_Pos 0 /**< (HSTIMR) Device Connection Interrupt Enable Position */ +#define HSTIMR_DCONNIE (_U_(0x1) << HSTIMR_DCONNIE_Pos) /**< (HSTIMR) Device Connection Interrupt Enable Mask */ +#define HSTIMR_DDISCIE_Pos 1 /**< (HSTIMR) Device Disconnection Interrupt Enable Position */ +#define HSTIMR_DDISCIE (_U_(0x1) << HSTIMR_DDISCIE_Pos) /**< (HSTIMR) Device Disconnection Interrupt Enable Mask */ +#define HSTIMR_RSTIE_Pos 2 /**< (HSTIMR) USB Reset Sent Interrupt Enable Position */ +#define HSTIMR_RSTIE (_U_(0x1) << HSTIMR_RSTIE_Pos) /**< (HSTIMR) USB Reset Sent Interrupt Enable Mask */ +#define HSTIMR_RSMEDIE_Pos 3 /**< (HSTIMR) Downstream Resume Sent Interrupt Enable Position */ +#define HSTIMR_RSMEDIE (_U_(0x1) << HSTIMR_RSMEDIE_Pos) /**< (HSTIMR) Downstream Resume Sent Interrupt Enable Mask */ +#define HSTIMR_RXRSMIE_Pos 4 /**< (HSTIMR) Upstream Resume Received Interrupt Enable Position */ +#define HSTIMR_RXRSMIE (_U_(0x1) << HSTIMR_RXRSMIE_Pos) /**< (HSTIMR) Upstream Resume Received Interrupt Enable Mask */ +#define HSTIMR_HSOFIE_Pos 5 /**< (HSTIMR) Host Start of Frame Interrupt Enable Position */ +#define HSTIMR_HSOFIE (_U_(0x1) << HSTIMR_HSOFIE_Pos) /**< (HSTIMR) Host Start of Frame Interrupt Enable Mask */ +#define HSTIMR_HWUPIE_Pos 6 /**< (HSTIMR) Host Wake-Up Interrupt Enable Position */ +#define HSTIMR_HWUPIE (_U_(0x1) << HSTIMR_HWUPIE_Pos) /**< (HSTIMR) Host Wake-Up Interrupt Enable Mask */ +#define HSTIMR_PEP_0_Pos 8 /**< (HSTIMR) Pipe 0 Interrupt Enable Position */ +#define HSTIMR_PEP_0 (_U_(0x1) << HSTIMR_PEP_0_Pos) /**< (HSTIMR) Pipe 0 Interrupt Enable Mask */ +#define HSTIMR_PEP_1_Pos 9 /**< (HSTIMR) Pipe 1 Interrupt Enable Position */ +#define HSTIMR_PEP_1 (_U_(0x1) << HSTIMR_PEP_1_Pos) /**< (HSTIMR) Pipe 1 Interrupt Enable Mask */ +#define HSTIMR_PEP_2_Pos 10 /**< (HSTIMR) Pipe 2 Interrupt Enable Position */ +#define HSTIMR_PEP_2 (_U_(0x1) << HSTIMR_PEP_2_Pos) /**< (HSTIMR) Pipe 2 Interrupt Enable Mask */ +#define HSTIMR_PEP_3_Pos 11 /**< (HSTIMR) Pipe 3 Interrupt Enable Position */ +#define HSTIMR_PEP_3 (_U_(0x1) << HSTIMR_PEP_3_Pos) /**< (HSTIMR) Pipe 3 Interrupt Enable Mask */ +#define HSTIMR_PEP_4_Pos 12 /**< (HSTIMR) Pipe 4 Interrupt Enable Position */ +#define HSTIMR_PEP_4 (_U_(0x1) << HSTIMR_PEP_4_Pos) /**< (HSTIMR) Pipe 4 Interrupt Enable Mask */ +#define HSTIMR_PEP_5_Pos 13 /**< (HSTIMR) Pipe 5 Interrupt Enable Position */ +#define HSTIMR_PEP_5 (_U_(0x1) << HSTIMR_PEP_5_Pos) /**< (HSTIMR) Pipe 5 Interrupt Enable Mask */ +#define HSTIMR_PEP_6_Pos 14 /**< (HSTIMR) Pipe 6 Interrupt Enable Position */ +#define HSTIMR_PEP_6 (_U_(0x1) << HSTIMR_PEP_6_Pos) /**< (HSTIMR) Pipe 6 Interrupt Enable Mask */ +#define HSTIMR_PEP_7_Pos 15 /**< (HSTIMR) Pipe 7 Interrupt Enable Position */ +#define HSTIMR_PEP_7 (_U_(0x1) << HSTIMR_PEP_7_Pos) /**< (HSTIMR) Pipe 7 Interrupt Enable Mask */ +#define HSTIMR_PEP_8_Pos 16 /**< (HSTIMR) Pipe 8 Interrupt Enable Position */ +#define HSTIMR_PEP_8 (_U_(0x1) << HSTIMR_PEP_8_Pos) /**< (HSTIMR) Pipe 8 Interrupt Enable Mask */ +#define HSTIMR_PEP_9_Pos 17 /**< (HSTIMR) Pipe 9 Interrupt Enable Position */ +#define HSTIMR_PEP_9 (_U_(0x1) << HSTIMR_PEP_9_Pos) /**< (HSTIMR) Pipe 9 Interrupt Enable Mask */ +#define HSTIMR_DMA_0_Pos 25 /**< (HSTIMR) DMA Channel 0 Interrupt Enable Position */ +#define HSTIMR_DMA_0 (_U_(0x1) << HSTIMR_DMA_0_Pos) /**< (HSTIMR) DMA Channel 0 Interrupt Enable Mask */ +#define HSTIMR_DMA_1_Pos 26 /**< (HSTIMR) DMA Channel 1 Interrupt Enable Position */ +#define HSTIMR_DMA_1 (_U_(0x1) << HSTIMR_DMA_1_Pos) /**< (HSTIMR) DMA Channel 1 Interrupt Enable Mask */ +#define HSTIMR_DMA_2_Pos 27 /**< (HSTIMR) DMA Channel 2 Interrupt Enable Position */ +#define HSTIMR_DMA_2 (_U_(0x1) << HSTIMR_DMA_2_Pos) /**< (HSTIMR) DMA Channel 2 Interrupt Enable Mask */ +#define HSTIMR_DMA_3_Pos 28 /**< (HSTIMR) DMA Channel 3 Interrupt Enable Position */ +#define HSTIMR_DMA_3 (_U_(0x1) << HSTIMR_DMA_3_Pos) /**< (HSTIMR) DMA Channel 3 Interrupt Enable Mask */ +#define HSTIMR_DMA_4_Pos 29 /**< (HSTIMR) DMA Channel 4 Interrupt Enable Position */ +#define HSTIMR_DMA_4 (_U_(0x1) << HSTIMR_DMA_4_Pos) /**< (HSTIMR) DMA Channel 4 Interrupt Enable Mask */ +#define HSTIMR_DMA_5_Pos 30 /**< (HSTIMR) DMA Channel 5 Interrupt Enable Position */ +#define HSTIMR_DMA_5 (_U_(0x1) << HSTIMR_DMA_5_Pos) /**< (HSTIMR) DMA Channel 5 Interrupt Enable Mask */ +#define HSTIMR_DMA_6_Pos 31 /**< (HSTIMR) DMA Channel 6 Interrupt Enable Position */ +#define HSTIMR_DMA_6 (_U_(0x1) << HSTIMR_DMA_6_Pos) /**< (HSTIMR) DMA Channel 6 Interrupt Enable Mask */ +#define HSTIMR_Msk _U_(0xFE03FF7F) /**< (HSTIMR) Register Mask */ + +#define HSTIMR_PEP__Pos 8 /**< (HSTIMR Position) Pipe x Interrupt Enable */ +#define HSTIMR_PEP_ (_U_(0x3FF) << HSTIMR_PEP__Pos) /**< (HSTIMR Mask) PEP_ */ +#define HSTIMR_DMA__Pos 25 /**< (HSTIMR Position) DMA Channel 6 Interrupt Enable */ +#define HSTIMR_DMA_ (_U_(0x7F) << HSTIMR_DMA__Pos) /**< (HSTIMR Mask) DMA_ */ + +/* -------- HSTIDR : (USBHS Offset: 0x414) (/W 32) Host Global Interrupt Disable Register -------- */ + +#define HSTIDR_OFFSET (0x414) /**< (HSTIDR) Host Global Interrupt Disable Register Offset */ + +#define HSTIDR_DCONNIEC_Pos 0 /**< (HSTIDR) Device Connection Interrupt Disable Position */ +#define HSTIDR_DCONNIEC (_U_(0x1) << HSTIDR_DCONNIEC_Pos) /**< (HSTIDR) Device Connection Interrupt Disable Mask */ +#define HSTIDR_DDISCIEC_Pos 1 /**< (HSTIDR) Device Disconnection Interrupt Disable Position */ +#define HSTIDR_DDISCIEC (_U_(0x1) << HSTIDR_DDISCIEC_Pos) /**< (HSTIDR) Device Disconnection Interrupt Disable Mask */ +#define HSTIDR_RSTIEC_Pos 2 /**< (HSTIDR) USB Reset Sent Interrupt Disable Position */ +#define HSTIDR_RSTIEC (_U_(0x1) << HSTIDR_RSTIEC_Pos) /**< (HSTIDR) USB Reset Sent Interrupt Disable Mask */ +#define HSTIDR_RSMEDIEC_Pos 3 /**< (HSTIDR) Downstream Resume Sent Interrupt Disable Position */ +#define HSTIDR_RSMEDIEC (_U_(0x1) << HSTIDR_RSMEDIEC_Pos) /**< (HSTIDR) Downstream Resume Sent Interrupt Disable Mask */ +#define HSTIDR_RXRSMIEC_Pos 4 /**< (HSTIDR) Upstream Resume Received Interrupt Disable Position */ +#define HSTIDR_RXRSMIEC (_U_(0x1) << HSTIDR_RXRSMIEC_Pos) /**< (HSTIDR) Upstream Resume Received Interrupt Disable Mask */ +#define HSTIDR_HSOFIEC_Pos 5 /**< (HSTIDR) Host Start of Frame Interrupt Disable Position */ +#define HSTIDR_HSOFIEC (_U_(0x1) << HSTIDR_HSOFIEC_Pos) /**< (HSTIDR) Host Start of Frame Interrupt Disable Mask */ +#define HSTIDR_HWUPIEC_Pos 6 /**< (HSTIDR) Host Wake-Up Interrupt Disable Position */ +#define HSTIDR_HWUPIEC (_U_(0x1) << HSTIDR_HWUPIEC_Pos) /**< (HSTIDR) Host Wake-Up Interrupt Disable Mask */ +#define HSTIDR_PEP_0_Pos 8 /**< (HSTIDR) Pipe 0 Interrupt Disable Position */ +#define HSTIDR_PEP_0 (_U_(0x1) << HSTIDR_PEP_0_Pos) /**< (HSTIDR) Pipe 0 Interrupt Disable Mask */ +#define HSTIDR_PEP_1_Pos 9 /**< (HSTIDR) Pipe 1 Interrupt Disable Position */ +#define HSTIDR_PEP_1 (_U_(0x1) << HSTIDR_PEP_1_Pos) /**< (HSTIDR) Pipe 1 Interrupt Disable Mask */ +#define HSTIDR_PEP_2_Pos 10 /**< (HSTIDR) Pipe 2 Interrupt Disable Position */ +#define HSTIDR_PEP_2 (_U_(0x1) << HSTIDR_PEP_2_Pos) /**< (HSTIDR) Pipe 2 Interrupt Disable Mask */ +#define HSTIDR_PEP_3_Pos 11 /**< (HSTIDR) Pipe 3 Interrupt Disable Position */ +#define HSTIDR_PEP_3 (_U_(0x1) << HSTIDR_PEP_3_Pos) /**< (HSTIDR) Pipe 3 Interrupt Disable Mask */ +#define HSTIDR_PEP_4_Pos 12 /**< (HSTIDR) Pipe 4 Interrupt Disable Position */ +#define HSTIDR_PEP_4 (_U_(0x1) << HSTIDR_PEP_4_Pos) /**< (HSTIDR) Pipe 4 Interrupt Disable Mask */ +#define HSTIDR_PEP_5_Pos 13 /**< (HSTIDR) Pipe 5 Interrupt Disable Position */ +#define HSTIDR_PEP_5 (_U_(0x1) << HSTIDR_PEP_5_Pos) /**< (HSTIDR) Pipe 5 Interrupt Disable Mask */ +#define HSTIDR_PEP_6_Pos 14 /**< (HSTIDR) Pipe 6 Interrupt Disable Position */ +#define HSTIDR_PEP_6 (_U_(0x1) << HSTIDR_PEP_6_Pos) /**< (HSTIDR) Pipe 6 Interrupt Disable Mask */ +#define HSTIDR_PEP_7_Pos 15 /**< (HSTIDR) Pipe 7 Interrupt Disable Position */ +#define HSTIDR_PEP_7 (_U_(0x1) << HSTIDR_PEP_7_Pos) /**< (HSTIDR) Pipe 7 Interrupt Disable Mask */ +#define HSTIDR_PEP_8_Pos 16 /**< (HSTIDR) Pipe 8 Interrupt Disable Position */ +#define HSTIDR_PEP_8 (_U_(0x1) << HSTIDR_PEP_8_Pos) /**< (HSTIDR) Pipe 8 Interrupt Disable Mask */ +#define HSTIDR_PEP_9_Pos 17 /**< (HSTIDR) Pipe 9 Interrupt Disable Position */ +#define HSTIDR_PEP_9 (_U_(0x1) << HSTIDR_PEP_9_Pos) /**< (HSTIDR) Pipe 9 Interrupt Disable Mask */ +#define HSTIDR_DMA_0_Pos 25 /**< (HSTIDR) DMA Channel 0 Interrupt Disable Position */ +#define HSTIDR_DMA_0 (_U_(0x1) << HSTIDR_DMA_0_Pos) /**< (HSTIDR) DMA Channel 0 Interrupt Disable Mask */ +#define HSTIDR_DMA_1_Pos 26 /**< (HSTIDR) DMA Channel 1 Interrupt Disable Position */ +#define HSTIDR_DMA_1 (_U_(0x1) << HSTIDR_DMA_1_Pos) /**< (HSTIDR) DMA Channel 1 Interrupt Disable Mask */ +#define HSTIDR_DMA_2_Pos 27 /**< (HSTIDR) DMA Channel 2 Interrupt Disable Position */ +#define HSTIDR_DMA_2 (_U_(0x1) << HSTIDR_DMA_2_Pos) /**< (HSTIDR) DMA Channel 2 Interrupt Disable Mask */ +#define HSTIDR_DMA_3_Pos 28 /**< (HSTIDR) DMA Channel 3 Interrupt Disable Position */ +#define HSTIDR_DMA_3 (_U_(0x1) << HSTIDR_DMA_3_Pos) /**< (HSTIDR) DMA Channel 3 Interrupt Disable Mask */ +#define HSTIDR_DMA_4_Pos 29 /**< (HSTIDR) DMA Channel 4 Interrupt Disable Position */ +#define HSTIDR_DMA_4 (_U_(0x1) << HSTIDR_DMA_4_Pos) /**< (HSTIDR) DMA Channel 4 Interrupt Disable Mask */ +#define HSTIDR_DMA_5_Pos 30 /**< (HSTIDR) DMA Channel 5 Interrupt Disable Position */ +#define HSTIDR_DMA_5 (_U_(0x1) << HSTIDR_DMA_5_Pos) /**< (HSTIDR) DMA Channel 5 Interrupt Disable Mask */ +#define HSTIDR_DMA_6_Pos 31 /**< (HSTIDR) DMA Channel 6 Interrupt Disable Position */ +#define HSTIDR_DMA_6 (_U_(0x1) << HSTIDR_DMA_6_Pos) /**< (HSTIDR) DMA Channel 6 Interrupt Disable Mask */ +#define HSTIDR_Msk _U_(0xFE03FF7F) /**< (HSTIDR) Register Mask */ + +#define HSTIDR_PEP__Pos 8 /**< (HSTIDR Position) Pipe x Interrupt Disable */ +#define HSTIDR_PEP_ (_U_(0x3FF) << HSTIDR_PEP__Pos) /**< (HSTIDR Mask) PEP_ */ +#define HSTIDR_DMA__Pos 25 /**< (HSTIDR Position) DMA Channel 6 Interrupt Disable */ +#define HSTIDR_DMA_ (_U_(0x7F) << HSTIDR_DMA__Pos) /**< (HSTIDR Mask) DMA_ */ + +/* -------- HSTIER : (USBHS Offset: 0x418) (/W 32) Host Global Interrupt Enable Register -------- */ + +#define HSTIER_OFFSET (0x418) /**< (HSTIER) Host Global Interrupt Enable Register Offset */ + +#define HSTIER_DCONNIES_Pos 0 /**< (HSTIER) Device Connection Interrupt Enable Position */ +#define HSTIER_DCONNIES (_U_(0x1) << HSTIER_DCONNIES_Pos) /**< (HSTIER) Device Connection Interrupt Enable Mask */ +#define HSTIER_DDISCIES_Pos 1 /**< (HSTIER) Device Disconnection Interrupt Enable Position */ +#define HSTIER_DDISCIES (_U_(0x1) << HSTIER_DDISCIES_Pos) /**< (HSTIER) Device Disconnection Interrupt Enable Mask */ +#define HSTIER_RSTIES_Pos 2 /**< (HSTIER) USB Reset Sent Interrupt Enable Position */ +#define HSTIER_RSTIES (_U_(0x1) << HSTIER_RSTIES_Pos) /**< (HSTIER) USB Reset Sent Interrupt Enable Mask */ +#define HSTIER_RSMEDIES_Pos 3 /**< (HSTIER) Downstream Resume Sent Interrupt Enable Position */ +#define HSTIER_RSMEDIES (_U_(0x1) << HSTIER_RSMEDIES_Pos) /**< (HSTIER) Downstream Resume Sent Interrupt Enable Mask */ +#define HSTIER_RXRSMIES_Pos 4 /**< (HSTIER) Upstream Resume Received Interrupt Enable Position */ +#define HSTIER_RXRSMIES (_U_(0x1) << HSTIER_RXRSMIES_Pos) /**< (HSTIER) Upstream Resume Received Interrupt Enable Mask */ +#define HSTIER_HSOFIES_Pos 5 /**< (HSTIER) Host Start of Frame Interrupt Enable Position */ +#define HSTIER_HSOFIES (_U_(0x1) << HSTIER_HSOFIES_Pos) /**< (HSTIER) Host Start of Frame Interrupt Enable Mask */ +#define HSTIER_HWUPIES_Pos 6 /**< (HSTIER) Host Wake-Up Interrupt Enable Position */ +#define HSTIER_HWUPIES (_U_(0x1) << HSTIER_HWUPIES_Pos) /**< (HSTIER) Host Wake-Up Interrupt Enable Mask */ +#define HSTIER_PEP_0_Pos 8 /**< (HSTIER) Pipe 0 Interrupt Enable Position */ +#define HSTIER_PEP_0 (_U_(0x1) << HSTIER_PEP_0_Pos) /**< (HSTIER) Pipe 0 Interrupt Enable Mask */ +#define HSTIER_PEP_1_Pos 9 /**< (HSTIER) Pipe 1 Interrupt Enable Position */ +#define HSTIER_PEP_1 (_U_(0x1) << HSTIER_PEP_1_Pos) /**< (HSTIER) Pipe 1 Interrupt Enable Mask */ +#define HSTIER_PEP_2_Pos 10 /**< (HSTIER) Pipe 2 Interrupt Enable Position */ +#define HSTIER_PEP_2 (_U_(0x1) << HSTIER_PEP_2_Pos) /**< (HSTIER) Pipe 2 Interrupt Enable Mask */ +#define HSTIER_PEP_3_Pos 11 /**< (HSTIER) Pipe 3 Interrupt Enable Position */ +#define HSTIER_PEP_3 (_U_(0x1) << HSTIER_PEP_3_Pos) /**< (HSTIER) Pipe 3 Interrupt Enable Mask */ +#define HSTIER_PEP_4_Pos 12 /**< (HSTIER) Pipe 4 Interrupt Enable Position */ +#define HSTIER_PEP_4 (_U_(0x1) << HSTIER_PEP_4_Pos) /**< (HSTIER) Pipe 4 Interrupt Enable Mask */ +#define HSTIER_PEP_5_Pos 13 /**< (HSTIER) Pipe 5 Interrupt Enable Position */ +#define HSTIER_PEP_5 (_U_(0x1) << HSTIER_PEP_5_Pos) /**< (HSTIER) Pipe 5 Interrupt Enable Mask */ +#define HSTIER_PEP_6_Pos 14 /**< (HSTIER) Pipe 6 Interrupt Enable Position */ +#define HSTIER_PEP_6 (_U_(0x1) << HSTIER_PEP_6_Pos) /**< (HSTIER) Pipe 6 Interrupt Enable Mask */ +#define HSTIER_PEP_7_Pos 15 /**< (HSTIER) Pipe 7 Interrupt Enable Position */ +#define HSTIER_PEP_7 (_U_(0x1) << HSTIER_PEP_7_Pos) /**< (HSTIER) Pipe 7 Interrupt Enable Mask */ +#define HSTIER_PEP_8_Pos 16 /**< (HSTIER) Pipe 8 Interrupt Enable Position */ +#define HSTIER_PEP_8 (_U_(0x1) << HSTIER_PEP_8_Pos) /**< (HSTIER) Pipe 8 Interrupt Enable Mask */ +#define HSTIER_PEP_9_Pos 17 /**< (HSTIER) Pipe 9 Interrupt Enable Position */ +#define HSTIER_PEP_9 (_U_(0x1) << HSTIER_PEP_9_Pos) /**< (HSTIER) Pipe 9 Interrupt Enable Mask */ +#define HSTIER_DMA_0_Pos 25 /**< (HSTIER) DMA Channel 0 Interrupt Enable Position */ +#define HSTIER_DMA_0 (_U_(0x1) << HSTIER_DMA_0_Pos) /**< (HSTIER) DMA Channel 0 Interrupt Enable Mask */ +#define HSTIER_DMA_1_Pos 26 /**< (HSTIER) DMA Channel 1 Interrupt Enable Position */ +#define HSTIER_DMA_1 (_U_(0x1) << HSTIER_DMA_1_Pos) /**< (HSTIER) DMA Channel 1 Interrupt Enable Mask */ +#define HSTIER_DMA_2_Pos 27 /**< (HSTIER) DMA Channel 2 Interrupt Enable Position */ +#define HSTIER_DMA_2 (_U_(0x1) << HSTIER_DMA_2_Pos) /**< (HSTIER) DMA Channel 2 Interrupt Enable Mask */ +#define HSTIER_DMA_3_Pos 28 /**< (HSTIER) DMA Channel 3 Interrupt Enable Position */ +#define HSTIER_DMA_3 (_U_(0x1) << HSTIER_DMA_3_Pos) /**< (HSTIER) DMA Channel 3 Interrupt Enable Mask */ +#define HSTIER_DMA_4_Pos 29 /**< (HSTIER) DMA Channel 4 Interrupt Enable Position */ +#define HSTIER_DMA_4 (_U_(0x1) << HSTIER_DMA_4_Pos) /**< (HSTIER) DMA Channel 4 Interrupt Enable Mask */ +#define HSTIER_DMA_5_Pos 30 /**< (HSTIER) DMA Channel 5 Interrupt Enable Position */ +#define HSTIER_DMA_5 (_U_(0x1) << HSTIER_DMA_5_Pos) /**< (HSTIER) DMA Channel 5 Interrupt Enable Mask */ +#define HSTIER_DMA_6_Pos 31 /**< (HSTIER) DMA Channel 6 Interrupt Enable Position */ +#define HSTIER_DMA_6 (_U_(0x1) << HSTIER_DMA_6_Pos) /**< (HSTIER) DMA Channel 6 Interrupt Enable Mask */ +#define HSTIER_Msk _U_(0xFE03FF7F) /**< (HSTIER) Register Mask */ + +#define HSTIER_PEP__Pos 8 /**< (HSTIER Position) Pipe x Interrupt Enable */ +#define HSTIER_PEP_ (_U_(0x3FF) << HSTIER_PEP__Pos) /**< (HSTIER Mask) PEP_ */ +#define HSTIER_DMA__Pos 25 /**< (HSTIER Position) DMA Channel 6 Interrupt Enable */ +#define HSTIER_DMA_ (_U_(0x7F) << HSTIER_DMA__Pos) /**< (HSTIER Mask) DMA_ */ + +/* -------- HSTPIP : (USBHS Offset: 0x41c) (R/W 32) Host Pipe Register -------- */ + +#define HSTPIP_OFFSET (0x41C) /**< (HSTPIP) Host Pipe Register Offset */ + +#define HSTPIP_PEN0_Pos 0 /**< (HSTPIP) Pipe 0 Enable Position */ +#define HSTPIP_PEN0 (_U_(0x1) << HSTPIP_PEN0_Pos) /**< (HSTPIP) Pipe 0 Enable Mask */ +#define HSTPIP_PEN1_Pos 1 /**< (HSTPIP) Pipe 1 Enable Position */ +#define HSTPIP_PEN1 (_U_(0x1) << HSTPIP_PEN1_Pos) /**< (HSTPIP) Pipe 1 Enable Mask */ +#define HSTPIP_PEN2_Pos 2 /**< (HSTPIP) Pipe 2 Enable Position */ +#define HSTPIP_PEN2 (_U_(0x1) << HSTPIP_PEN2_Pos) /**< (HSTPIP) Pipe 2 Enable Mask */ +#define HSTPIP_PEN3_Pos 3 /**< (HSTPIP) Pipe 3 Enable Position */ +#define HSTPIP_PEN3 (_U_(0x1) << HSTPIP_PEN3_Pos) /**< (HSTPIP) Pipe 3 Enable Mask */ +#define HSTPIP_PEN4_Pos 4 /**< (HSTPIP) Pipe 4 Enable Position */ +#define HSTPIP_PEN4 (_U_(0x1) << HSTPIP_PEN4_Pos) /**< (HSTPIP) Pipe 4 Enable Mask */ +#define HSTPIP_PEN5_Pos 5 /**< (HSTPIP) Pipe 5 Enable Position */ +#define HSTPIP_PEN5 (_U_(0x1) << HSTPIP_PEN5_Pos) /**< (HSTPIP) Pipe 5 Enable Mask */ +#define HSTPIP_PEN6_Pos 6 /**< (HSTPIP) Pipe 6 Enable Position */ +#define HSTPIP_PEN6 (_U_(0x1) << HSTPIP_PEN6_Pos) /**< (HSTPIP) Pipe 6 Enable Mask */ +#define HSTPIP_PEN7_Pos 7 /**< (HSTPIP) Pipe 7 Enable Position */ +#define HSTPIP_PEN7 (_U_(0x1) << HSTPIP_PEN7_Pos) /**< (HSTPIP) Pipe 7 Enable Mask */ +#define HSTPIP_PEN8_Pos 8 /**< (HSTPIP) Pipe 8 Enable Position */ +#define HSTPIP_PEN8 (_U_(0x1) << HSTPIP_PEN8_Pos) /**< (HSTPIP) Pipe 8 Enable Mask */ +#define HSTPIP_PRST0_Pos 16 /**< (HSTPIP) Pipe 0 Reset Position */ +#define HSTPIP_PRST0 (_U_(0x1) << HSTPIP_PRST0_Pos) /**< (HSTPIP) Pipe 0 Reset Mask */ +#define HSTPIP_PRST1_Pos 17 /**< (HSTPIP) Pipe 1 Reset Position */ +#define HSTPIP_PRST1 (_U_(0x1) << HSTPIP_PRST1_Pos) /**< (HSTPIP) Pipe 1 Reset Mask */ +#define HSTPIP_PRST2_Pos 18 /**< (HSTPIP) Pipe 2 Reset Position */ +#define HSTPIP_PRST2 (_U_(0x1) << HSTPIP_PRST2_Pos) /**< (HSTPIP) Pipe 2 Reset Mask */ +#define HSTPIP_PRST3_Pos 19 /**< (HSTPIP) Pipe 3 Reset Position */ +#define HSTPIP_PRST3 (_U_(0x1) << HSTPIP_PRST3_Pos) /**< (HSTPIP) Pipe 3 Reset Mask */ +#define HSTPIP_PRST4_Pos 20 /**< (HSTPIP) Pipe 4 Reset Position */ +#define HSTPIP_PRST4 (_U_(0x1) << HSTPIP_PRST4_Pos) /**< (HSTPIP) Pipe 4 Reset Mask */ +#define HSTPIP_PRST5_Pos 21 /**< (HSTPIP) Pipe 5 Reset Position */ +#define HSTPIP_PRST5 (_U_(0x1) << HSTPIP_PRST5_Pos) /**< (HSTPIP) Pipe 5 Reset Mask */ +#define HSTPIP_PRST6_Pos 22 /**< (HSTPIP) Pipe 6 Reset Position */ +#define HSTPIP_PRST6 (_U_(0x1) << HSTPIP_PRST6_Pos) /**< (HSTPIP) Pipe 6 Reset Mask */ +#define HSTPIP_PRST7_Pos 23 /**< (HSTPIP) Pipe 7 Reset Position */ +#define HSTPIP_PRST7 (_U_(0x1) << HSTPIP_PRST7_Pos) /**< (HSTPIP) Pipe 7 Reset Mask */ +#define HSTPIP_PRST8_Pos 24 /**< (HSTPIP) Pipe 8 Reset Position */ +#define HSTPIP_PRST8 (_U_(0x1) << HSTPIP_PRST8_Pos) /**< (HSTPIP) Pipe 8 Reset Mask */ +#define HSTPIP_Msk _U_(0x1FF01FF) /**< (HSTPIP) Register Mask */ + +#define HSTPIP_PEN_Pos 0 /**< (HSTPIP Position) Pipe x Enable */ +#define HSTPIP_PEN (_U_(0x1FF) << HSTPIP_PEN_Pos) /**< (HSTPIP Mask) PEN */ +#define HSTPIP_PRST_Pos 16 /**< (HSTPIP Position) Pipe 8 Reset */ +#define HSTPIP_PRST (_U_(0x1FF) << HSTPIP_PRST_Pos) /**< (HSTPIP Mask) PRST */ + +/* -------- HSTFNUM : (USBHS Offset: 0x420) (R/W 32) Host Frame Number Register -------- */ + +#define HSTFNUM_OFFSET (0x420) /**< (HSTFNUM) Host Frame Number Register Offset */ + +#define HSTFNUM_MFNUM_Pos 0 /**< (HSTFNUM) Micro Frame Number Position */ +#define HSTFNUM_MFNUM (_U_(0x7) << HSTFNUM_MFNUM_Pos) /**< (HSTFNUM) Micro Frame Number Mask */ +#define HSTFNUM_FNUM_Pos 3 /**< (HSTFNUM) Frame Number Position */ +#define HSTFNUM_FNUM (_U_(0x7FF) << HSTFNUM_FNUM_Pos) /**< (HSTFNUM) Frame Number Mask */ +#define HSTFNUM_FLENHIGH_Pos 16 /**< (HSTFNUM) Frame Length Position */ +#define HSTFNUM_FLENHIGH (_U_(0xFF) << HSTFNUM_FLENHIGH_Pos) /**< (HSTFNUM) Frame Length Mask */ +#define HSTFNUM_Msk _U_(0xFF3FFF) /**< (HSTFNUM) Register Mask */ + + +/* -------- HSTADDR1 : (USBHS Offset: 0x424) (R/W 32) Host Address 1 Register -------- */ + +#define HSTADDR1_OFFSET (0x424) /**< (HSTADDR1) Host Address 1 Register Offset */ + +#define HSTADDR1_HSTADDRP0_Pos 0 /**< (HSTADDR1) USB Host Address Position */ +#define HSTADDR1_HSTADDRP0 (_U_(0x7F) << HSTADDR1_HSTADDRP0_Pos) /**< (HSTADDR1) USB Host Address Mask */ +#define HSTADDR1_HSTADDRP1_Pos 8 /**< (HSTADDR1) USB Host Address Position */ +#define HSTADDR1_HSTADDRP1 (_U_(0x7F) << HSTADDR1_HSTADDRP1_Pos) /**< (HSTADDR1) USB Host Address Mask */ +#define HSTADDR1_HSTADDRP2_Pos 16 /**< (HSTADDR1) USB Host Address Position */ +#define HSTADDR1_HSTADDRP2 (_U_(0x7F) << HSTADDR1_HSTADDRP2_Pos) /**< (HSTADDR1) USB Host Address Mask */ +#define HSTADDR1_HSTADDRP3_Pos 24 /**< (HSTADDR1) USB Host Address Position */ +#define HSTADDR1_HSTADDRP3 (_U_(0x7F) << HSTADDR1_HSTADDRP3_Pos) /**< (HSTADDR1) USB Host Address Mask */ +#define HSTADDR1_Msk _U_(0x7F7F7F7F) /**< (HSTADDR1) Register Mask */ + + +/* -------- HSTADDR2 : (USBHS Offset: 0x428) (R/W 32) Host Address 2 Register -------- */ + +#define HSTADDR2_OFFSET (0x428) /**< (HSTADDR2) Host Address 2 Register Offset */ + +#define HSTADDR2_HSTADDRP4_Pos 0 /**< (HSTADDR2) USB Host Address Position */ +#define HSTADDR2_HSTADDRP4 (_U_(0x7F) << HSTADDR2_HSTADDRP4_Pos) /**< (HSTADDR2) USB Host Address Mask */ +#define HSTADDR2_HSTADDRP5_Pos 8 /**< (HSTADDR2) USB Host Address Position */ +#define HSTADDR2_HSTADDRP5 (_U_(0x7F) << HSTADDR2_HSTADDRP5_Pos) /**< (HSTADDR2) USB Host Address Mask */ +#define HSTADDR2_HSTADDRP6_Pos 16 /**< (HSTADDR2) USB Host Address Position */ +#define HSTADDR2_HSTADDRP6 (_U_(0x7F) << HSTADDR2_HSTADDRP6_Pos) /**< (HSTADDR2) USB Host Address Mask */ +#define HSTADDR2_HSTADDRP7_Pos 24 /**< (HSTADDR2) USB Host Address Position */ +#define HSTADDR2_HSTADDRP7 (_U_(0x7F) << HSTADDR2_HSTADDRP7_Pos) /**< (HSTADDR2) USB Host Address Mask */ +#define HSTADDR2_Msk _U_(0x7F7F7F7F) /**< (HSTADDR2) Register Mask */ + + +/* -------- HSTADDR3 : (USBHS Offset: 0x42c) (R/W 32) Host Address 3 Register -------- */ + +#define HSTADDR3_OFFSET (0x42C) /**< (HSTADDR3) Host Address 3 Register Offset */ + +#define HSTADDR3_HSTADDRP8_Pos 0 /**< (HSTADDR3) USB Host Address Position */ +#define HSTADDR3_HSTADDRP8 (_U_(0x7F) << HSTADDR3_HSTADDRP8_Pos) /**< (HSTADDR3) USB Host Address Mask */ +#define HSTADDR3_HSTADDRP9_Pos 8 /**< (HSTADDR3) USB Host Address Position */ +#define HSTADDR3_HSTADDRP9 (_U_(0x7F) << HSTADDR3_HSTADDRP9_Pos) /**< (HSTADDR3) USB Host Address Mask */ +#define HSTADDR3_Msk _U_(0x7F7F) /**< (HSTADDR3) Register Mask */ + + +/* -------- HSTPIPCFG : (USBHS Offset: 0x500) (R/W 32) Host Pipe Configuration Register -------- */ + +#define HSTPIPCFG_OFFSET (0x500) /**< (HSTPIPCFG) Host Pipe Configuration Register Offset */ + +#define HSTPIPCFG_ALLOC_Pos 1 /**< (HSTPIPCFG) Pipe Memory Allocate Position */ +#define HSTPIPCFG_ALLOC (_U_(0x1) << HSTPIPCFG_ALLOC_Pos) /**< (HSTPIPCFG) Pipe Memory Allocate Mask */ +#define HSTPIPCFG_PBK_Pos 2 /**< (HSTPIPCFG) Pipe Banks Position */ +#define HSTPIPCFG_PBK (_U_(0x3) << HSTPIPCFG_PBK_Pos) /**< (HSTPIPCFG) Pipe Banks Mask */ +#define HSTPIPCFG_PBK_1_BANK_Val _U_(0x0) /**< (HSTPIPCFG) Single-bank pipe */ +#define HSTPIPCFG_PBK_2_BANK_Val _U_(0x1) /**< (HSTPIPCFG) Double-bank pipe */ +#define HSTPIPCFG_PBK_3_BANK_Val _U_(0x2) /**< (HSTPIPCFG) Triple-bank pipe */ +#define HSTPIPCFG_PBK_1_BANK (HSTPIPCFG_PBK_1_BANK_Val << HSTPIPCFG_PBK_Pos) /**< (HSTPIPCFG) Single-bank pipe Position */ +#define HSTPIPCFG_PBK_2_BANK (HSTPIPCFG_PBK_2_BANK_Val << HSTPIPCFG_PBK_Pos) /**< (HSTPIPCFG) Double-bank pipe Position */ +#define HSTPIPCFG_PBK_3_BANK (HSTPIPCFG_PBK_3_BANK_Val << HSTPIPCFG_PBK_Pos) /**< (HSTPIPCFG) Triple-bank pipe Position */ +#define HSTPIPCFG_PSIZE_Pos 4 /**< (HSTPIPCFG) Pipe Size Position */ +#define HSTPIPCFG_PSIZE (_U_(0x7) << HSTPIPCFG_PSIZE_Pos) /**< (HSTPIPCFG) Pipe Size Mask */ +#define HSTPIPCFG_PSIZE_8_BYTE_Val _U_(0x0) /**< (HSTPIPCFG) 8 bytes */ +#define HSTPIPCFG_PSIZE_16_BYTE_Val _U_(0x1) /**< (HSTPIPCFG) 16 bytes */ +#define HSTPIPCFG_PSIZE_32_BYTE_Val _U_(0x2) /**< (HSTPIPCFG) 32 bytes */ +#define HSTPIPCFG_PSIZE_64_BYTE_Val _U_(0x3) /**< (HSTPIPCFG) 64 bytes */ +#define HSTPIPCFG_PSIZE_128_BYTE_Val _U_(0x4) /**< (HSTPIPCFG) 128 bytes */ +#define HSTPIPCFG_PSIZE_256_BYTE_Val _U_(0x5) /**< (HSTPIPCFG) 256 bytes */ +#define HSTPIPCFG_PSIZE_512_BYTE_Val _U_(0x6) /**< (HSTPIPCFG) 512 bytes */ +#define HSTPIPCFG_PSIZE_1024_BYTE_Val _U_(0x7) /**< (HSTPIPCFG) 1024 bytes */ +#define HSTPIPCFG_PSIZE_8_BYTE (HSTPIPCFG_PSIZE_8_BYTE_Val << HSTPIPCFG_PSIZE_Pos) /**< (HSTPIPCFG) 8 bytes Position */ +#define HSTPIPCFG_PSIZE_16_BYTE (HSTPIPCFG_PSIZE_16_BYTE_Val << HSTPIPCFG_PSIZE_Pos) /**< (HSTPIPCFG) 16 bytes Position */ +#define HSTPIPCFG_PSIZE_32_BYTE (HSTPIPCFG_PSIZE_32_BYTE_Val << HSTPIPCFG_PSIZE_Pos) /**< (HSTPIPCFG) 32 bytes Position */ +#define HSTPIPCFG_PSIZE_64_BYTE (HSTPIPCFG_PSIZE_64_BYTE_Val << HSTPIPCFG_PSIZE_Pos) /**< (HSTPIPCFG) 64 bytes Position */ +#define HSTPIPCFG_PSIZE_128_BYTE (HSTPIPCFG_PSIZE_128_BYTE_Val << HSTPIPCFG_PSIZE_Pos) /**< (HSTPIPCFG) 128 bytes Position */ +#define HSTPIPCFG_PSIZE_256_BYTE (HSTPIPCFG_PSIZE_256_BYTE_Val << HSTPIPCFG_PSIZE_Pos) /**< (HSTPIPCFG) 256 bytes Position */ +#define HSTPIPCFG_PSIZE_512_BYTE (HSTPIPCFG_PSIZE_512_BYTE_Val << HSTPIPCFG_PSIZE_Pos) /**< (HSTPIPCFG) 512 bytes Position */ +#define HSTPIPCFG_PSIZE_1024_BYTE (HSTPIPCFG_PSIZE_1024_BYTE_Val << HSTPIPCFG_PSIZE_Pos) /**< (HSTPIPCFG) 1024 bytes Position */ +#define HSTPIPCFG_PTOKEN_Pos 8 /**< (HSTPIPCFG) Pipe Token Position */ +#define HSTPIPCFG_PTOKEN (_U_(0x3) << HSTPIPCFG_PTOKEN_Pos) /**< (HSTPIPCFG) Pipe Token Mask */ +#define HSTPIPCFG_PTOKEN_SETUP_Val _U_(0x0) /**< (HSTPIPCFG) SETUP */ +#define HSTPIPCFG_PTOKEN_IN_Val _U_(0x1) /**< (HSTPIPCFG) IN */ +#define HSTPIPCFG_PTOKEN_OUT_Val _U_(0x2) /**< (HSTPIPCFG) OUT */ +#define HSTPIPCFG_PTOKEN_SETUP (HSTPIPCFG_PTOKEN_SETUP_Val << HSTPIPCFG_PTOKEN_Pos) /**< (HSTPIPCFG) SETUP Position */ +#define HSTPIPCFG_PTOKEN_IN (HSTPIPCFG_PTOKEN_IN_Val << HSTPIPCFG_PTOKEN_Pos) /**< (HSTPIPCFG) IN Position */ +#define HSTPIPCFG_PTOKEN_OUT (HSTPIPCFG_PTOKEN_OUT_Val << HSTPIPCFG_PTOKEN_Pos) /**< (HSTPIPCFG) OUT Position */ +#define HSTPIPCFG_AUTOSW_Pos 10 /**< (HSTPIPCFG) Automatic Switch Position */ +#define HSTPIPCFG_AUTOSW (_U_(0x1) << HSTPIPCFG_AUTOSW_Pos) /**< (HSTPIPCFG) Automatic Switch Mask */ +#define HSTPIPCFG_PTYPE_Pos 12 /**< (HSTPIPCFG) Pipe Type Position */ +#define HSTPIPCFG_PTYPE (_U_(0x3) << HSTPIPCFG_PTYPE_Pos) /**< (HSTPIPCFG) Pipe Type Mask */ +#define HSTPIPCFG_PTYPE_CTRL_Val _U_(0x0) /**< (HSTPIPCFG) Control */ +#define HSTPIPCFG_PTYPE_ISO_Val _U_(0x1) /**< (HSTPIPCFG) Isochronous */ +#define HSTPIPCFG_PTYPE_BLK_Val _U_(0x2) /**< (HSTPIPCFG) Bulk */ +#define HSTPIPCFG_PTYPE_INTRPT_Val _U_(0x3) /**< (HSTPIPCFG) Interrupt */ +#define HSTPIPCFG_PTYPE_CTRL (HSTPIPCFG_PTYPE_CTRL_Val << HSTPIPCFG_PTYPE_Pos) /**< (HSTPIPCFG) Control Position */ +#define HSTPIPCFG_PTYPE_ISO (HSTPIPCFG_PTYPE_ISO_Val << HSTPIPCFG_PTYPE_Pos) /**< (HSTPIPCFG) Isochronous Position */ +#define HSTPIPCFG_PTYPE_BLK (HSTPIPCFG_PTYPE_BLK_Val << HSTPIPCFG_PTYPE_Pos) /**< (HSTPIPCFG) Bulk Position */ +#define HSTPIPCFG_PTYPE_INTRPT (HSTPIPCFG_PTYPE_INTRPT_Val << HSTPIPCFG_PTYPE_Pos) /**< (HSTPIPCFG) Interrupt Position */ +#define HSTPIPCFG_PEPNUM_Pos 16 /**< (HSTPIPCFG) Pipe Endpoint Number Position */ +#define HSTPIPCFG_PEPNUM (_U_(0xF) << HSTPIPCFG_PEPNUM_Pos) /**< (HSTPIPCFG) Pipe Endpoint Number Mask */ +#define HSTPIPCFG_INTFRQ_Pos 24 /**< (HSTPIPCFG) Pipe Interrupt Request Frequency Position */ +#define HSTPIPCFG_INTFRQ (_U_(0xFF) << HSTPIPCFG_INTFRQ_Pos) /**< (HSTPIPCFG) Pipe Interrupt Request Frequency Mask */ +#define HSTPIPCFG_Msk _U_(0xFF0F377E) /**< (HSTPIPCFG) Register Mask */ + +/* CTRL_BULK mode */ +#define HSTPIPCFG_CTRL_BULK_PINGEN_Pos 20 /**< (HSTPIPCFG) Ping Enable Position */ +#define HSTPIPCFG_CTRL_BULK_PINGEN (_U_(0x1) << HSTPIPCFG_CTRL_BULK_PINGEN_Pos) /**< (HSTPIPCFG) Ping Enable Mask */ +#define HSTPIPCFG_CTRL_BULK_BINTERVAL_Pos 24 /**< (HSTPIPCFG) bInterval Parameter for the Bulk-Out/Ping Transaction Position */ +#define HSTPIPCFG_CTRL_BULK_BINTERVAL (_U_(0xFF) << HSTPIPCFG_CTRL_BULK_BINTERVAL_Pos) /**< (HSTPIPCFG) bInterval Parameter for the Bulk-Out/Ping Transaction Mask */ +#define HSTPIPCFG_CTRL_BULK_Msk _U_(0xFF100000) /**< (HSTPIPCFG_CTRL_BULK) Register Mask */ + + +/* -------- HSTPIPISR : (USBHS Offset: 0x530) (R/ 32) Host Pipe Status Register -------- */ + +#define HSTPIPISR_OFFSET (0x530) /**< (HSTPIPISR) Host Pipe Status Register Offset */ + +#define HSTPIPISR_RXINI_Pos 0 /**< (HSTPIPISR) Received IN Data Interrupt Position */ +#define HSTPIPISR_RXINI (_U_(0x1) << HSTPIPISR_RXINI_Pos) /**< (HSTPIPISR) Received IN Data Interrupt Mask */ +#define HSTPIPISR_TXOUTI_Pos 1 /**< (HSTPIPISR) Transmitted OUT Data Interrupt Position */ +#define HSTPIPISR_TXOUTI (_U_(0x1) << HSTPIPISR_TXOUTI_Pos) /**< (HSTPIPISR) Transmitted OUT Data Interrupt Mask */ +#define HSTPIPISR_PERRI_Pos 3 /**< (HSTPIPISR) Pipe Error Interrupt Position */ +#define HSTPIPISR_PERRI (_U_(0x1) << HSTPIPISR_PERRI_Pos) /**< (HSTPIPISR) Pipe Error Interrupt Mask */ +#define HSTPIPISR_NAKEDI_Pos 4 /**< (HSTPIPISR) NAKed Interrupt Position */ +#define HSTPIPISR_NAKEDI (_U_(0x1) << HSTPIPISR_NAKEDI_Pos) /**< (HSTPIPISR) NAKed Interrupt Mask */ +#define HSTPIPISR_OVERFI_Pos 5 /**< (HSTPIPISR) Overflow Interrupt Position */ +#define HSTPIPISR_OVERFI (_U_(0x1) << HSTPIPISR_OVERFI_Pos) /**< (HSTPIPISR) Overflow Interrupt Mask */ +#define HSTPIPISR_SHORTPACKETI_Pos 7 /**< (HSTPIPISR) Short Packet Interrupt Position */ +#define HSTPIPISR_SHORTPACKETI (_U_(0x1) << HSTPIPISR_SHORTPACKETI_Pos) /**< (HSTPIPISR) Short Packet Interrupt Mask */ +#define HSTPIPISR_DTSEQ_Pos 8 /**< (HSTPIPISR) Data Toggle Sequence Position */ +#define HSTPIPISR_DTSEQ (_U_(0x3) << HSTPIPISR_DTSEQ_Pos) /**< (HSTPIPISR) Data Toggle Sequence Mask */ +#define HSTPIPISR_DTSEQ_DATA0_Val _U_(0x0) /**< (HSTPIPISR) Data0 toggle sequence */ +#define HSTPIPISR_DTSEQ_DATA1_Val _U_(0x1) /**< (HSTPIPISR) Data1 toggle sequence */ +#define HSTPIPISR_DTSEQ_DATA0 (HSTPIPISR_DTSEQ_DATA0_Val << HSTPIPISR_DTSEQ_Pos) /**< (HSTPIPISR) Data0 toggle sequence Position */ +#define HSTPIPISR_DTSEQ_DATA1 (HSTPIPISR_DTSEQ_DATA1_Val << HSTPIPISR_DTSEQ_Pos) /**< (HSTPIPISR) Data1 toggle sequence Position */ +#define HSTPIPISR_NBUSYBK_Pos 12 /**< (HSTPIPISR) Number of Busy Banks Position */ +#define HSTPIPISR_NBUSYBK (_U_(0x3) << HSTPIPISR_NBUSYBK_Pos) /**< (HSTPIPISR) Number of Busy Banks Mask */ +#define HSTPIPISR_NBUSYBK_0_BUSY_Val _U_(0x0) /**< (HSTPIPISR) 0 busy bank (all banks free) */ +#define HSTPIPISR_NBUSYBK_1_BUSY_Val _U_(0x1) /**< (HSTPIPISR) 1 busy bank */ +#define HSTPIPISR_NBUSYBK_2_BUSY_Val _U_(0x2) /**< (HSTPIPISR) 2 busy banks */ +#define HSTPIPISR_NBUSYBK_3_BUSY_Val _U_(0x3) /**< (HSTPIPISR) 3 busy banks */ +#define HSTPIPISR_NBUSYBK_0_BUSY (HSTPIPISR_NBUSYBK_0_BUSY_Val << HSTPIPISR_NBUSYBK_Pos) /**< (HSTPIPISR) 0 busy bank (all banks free) Position */ +#define HSTPIPISR_NBUSYBK_1_BUSY (HSTPIPISR_NBUSYBK_1_BUSY_Val << HSTPIPISR_NBUSYBK_Pos) /**< (HSTPIPISR) 1 busy bank Position */ +#define HSTPIPISR_NBUSYBK_2_BUSY (HSTPIPISR_NBUSYBK_2_BUSY_Val << HSTPIPISR_NBUSYBK_Pos) /**< (HSTPIPISR) 2 busy banks Position */ +#define HSTPIPISR_NBUSYBK_3_BUSY (HSTPIPISR_NBUSYBK_3_BUSY_Val << HSTPIPISR_NBUSYBK_Pos) /**< (HSTPIPISR) 3 busy banks Position */ +#define HSTPIPISR_CURRBK_Pos 14 /**< (HSTPIPISR) Current Bank Position */ +#define HSTPIPISR_CURRBK (_U_(0x3) << HSTPIPISR_CURRBK_Pos) /**< (HSTPIPISR) Current Bank Mask */ +#define HSTPIPISR_CURRBK_BANK0_Val _U_(0x0) /**< (HSTPIPISR) Current bank is bank0 */ +#define HSTPIPISR_CURRBK_BANK1_Val _U_(0x1) /**< (HSTPIPISR) Current bank is bank1 */ +#define HSTPIPISR_CURRBK_BANK2_Val _U_(0x2) /**< (HSTPIPISR) Current bank is bank2 */ +#define HSTPIPISR_CURRBK_BANK0 (HSTPIPISR_CURRBK_BANK0_Val << HSTPIPISR_CURRBK_Pos) /**< (HSTPIPISR) Current bank is bank0 Position */ +#define HSTPIPISR_CURRBK_BANK1 (HSTPIPISR_CURRBK_BANK1_Val << HSTPIPISR_CURRBK_Pos) /**< (HSTPIPISR) Current bank is bank1 Position */ +#define HSTPIPISR_CURRBK_BANK2 (HSTPIPISR_CURRBK_BANK2_Val << HSTPIPISR_CURRBK_Pos) /**< (HSTPIPISR) Current bank is bank2 Position */ +#define HSTPIPISR_RWALL_Pos 16 /**< (HSTPIPISR) Read/Write Allowed Position */ +#define HSTPIPISR_RWALL (_U_(0x1) << HSTPIPISR_RWALL_Pos) /**< (HSTPIPISR) Read/Write Allowed Mask */ +#define HSTPIPISR_CFGOK_Pos 18 /**< (HSTPIPISR) Configuration OK Status Position */ +#define HSTPIPISR_CFGOK (_U_(0x1) << HSTPIPISR_CFGOK_Pos) /**< (HSTPIPISR) Configuration OK Status Mask */ +#define HSTPIPISR_PBYCT_Pos 20 /**< (HSTPIPISR) Pipe Byte Count Position */ +#define HSTPIPISR_PBYCT (_U_(0x7FF) << HSTPIPISR_PBYCT_Pos) /**< (HSTPIPISR) Pipe Byte Count Mask */ +#define HSTPIPISR_Msk _U_(0x7FF5F3BB) /**< (HSTPIPISR) Register Mask */ + +/* CTRL mode */ +#define HSTPIPISR_CTRL_TXSTPI_Pos 2 /**< (HSTPIPISR) Transmitted SETUP Interrupt Position */ +#define HSTPIPISR_CTRL_TXSTPI (_U_(0x1) << HSTPIPISR_CTRL_TXSTPI_Pos) /**< (HSTPIPISR) Transmitted SETUP Interrupt Mask */ +#define HSTPIPISR_CTRL_RXSTALLDI_Pos 6 /**< (HSTPIPISR) Received STALLed Interrupt Position */ +#define HSTPIPISR_CTRL_RXSTALLDI (_U_(0x1) << HSTPIPISR_CTRL_RXSTALLDI_Pos) /**< (HSTPIPISR) Received STALLed Interrupt Mask */ +#define HSTPIPISR_CTRL_Msk _U_(0x44) /**< (HSTPIPISR_CTRL) Register Mask */ + +/* ISO mode */ +#define HSTPIPISR_ISO_UNDERFI_Pos 2 /**< (HSTPIPISR) Underflow Interrupt Position */ +#define HSTPIPISR_ISO_UNDERFI (_U_(0x1) << HSTPIPISR_ISO_UNDERFI_Pos) /**< (HSTPIPISR) Underflow Interrupt Mask */ +#define HSTPIPISR_ISO_CRCERRI_Pos 6 /**< (HSTPIPISR) CRC Error Interrupt Position */ +#define HSTPIPISR_ISO_CRCERRI (_U_(0x1) << HSTPIPISR_ISO_CRCERRI_Pos) /**< (HSTPIPISR) CRC Error Interrupt Mask */ +#define HSTPIPISR_ISO_Msk _U_(0x44) /**< (HSTPIPISR_ISO) Register Mask */ + +/* BLK mode */ +#define HSTPIPISR_BLK_TXSTPI_Pos 2 /**< (HSTPIPISR) Transmitted SETUP Interrupt Position */ +#define HSTPIPISR_BLK_TXSTPI (_U_(0x1) << HSTPIPISR_BLK_TXSTPI_Pos) /**< (HSTPIPISR) Transmitted SETUP Interrupt Mask */ +#define HSTPIPISR_BLK_RXSTALLDI_Pos 6 /**< (HSTPIPISR) Received STALLed Interrupt Position */ +#define HSTPIPISR_BLK_RXSTALLDI (_U_(0x1) << HSTPIPISR_BLK_RXSTALLDI_Pos) /**< (HSTPIPISR) Received STALLed Interrupt Mask */ +#define HSTPIPISR_BLK_Msk _U_(0x44) /**< (HSTPIPISR_BLK) Register Mask */ + +/* INTRPT mode */ +#define HSTPIPISR_INTRPT_UNDERFI_Pos 2 /**< (HSTPIPISR) Underflow Interrupt Position */ +#define HSTPIPISR_INTRPT_UNDERFI (_U_(0x1) << HSTPIPISR_INTRPT_UNDERFI_Pos) /**< (HSTPIPISR) Underflow Interrupt Mask */ +#define HSTPIPISR_INTRPT_RXSTALLDI_Pos 6 /**< (HSTPIPISR) Received STALLed Interrupt Position */ +#define HSTPIPISR_INTRPT_RXSTALLDI (_U_(0x1) << HSTPIPISR_INTRPT_RXSTALLDI_Pos) /**< (HSTPIPISR) Received STALLed Interrupt Mask */ +#define HSTPIPISR_INTRPT_Msk _U_(0x44) /**< (HSTPIPISR_INTRPT) Register Mask */ + + +/* -------- HSTPIPICR : (USBHS Offset: 0x560) (/W 32) Host Pipe Clear Register -------- */ + +#define HSTPIPICR_OFFSET (0x560) /**< (HSTPIPICR) Host Pipe Clear Register Offset */ + +#define HSTPIPICR_RXINIC_Pos 0 /**< (HSTPIPICR) Received IN Data Interrupt Clear Position */ +#define HSTPIPICR_RXINIC (_U_(0x1) << HSTPIPICR_RXINIC_Pos) /**< (HSTPIPICR) Received IN Data Interrupt Clear Mask */ +#define HSTPIPICR_TXOUTIC_Pos 1 /**< (HSTPIPICR) Transmitted OUT Data Interrupt Clear Position */ +#define HSTPIPICR_TXOUTIC (_U_(0x1) << HSTPIPICR_TXOUTIC_Pos) /**< (HSTPIPICR) Transmitted OUT Data Interrupt Clear Mask */ +#define HSTPIPICR_NAKEDIC_Pos 4 /**< (HSTPIPICR) NAKed Interrupt Clear Position */ +#define HSTPIPICR_NAKEDIC (_U_(0x1) << HSTPIPICR_NAKEDIC_Pos) /**< (HSTPIPICR) NAKed Interrupt Clear Mask */ +#define HSTPIPICR_OVERFIC_Pos 5 /**< (HSTPIPICR) Overflow Interrupt Clear Position */ +#define HSTPIPICR_OVERFIC (_U_(0x1) << HSTPIPICR_OVERFIC_Pos) /**< (HSTPIPICR) Overflow Interrupt Clear Mask */ +#define HSTPIPICR_SHORTPACKETIC_Pos 7 /**< (HSTPIPICR) Short Packet Interrupt Clear Position */ +#define HSTPIPICR_SHORTPACKETIC (_U_(0x1) << HSTPIPICR_SHORTPACKETIC_Pos) /**< (HSTPIPICR) Short Packet Interrupt Clear Mask */ +#define HSTPIPICR_Msk _U_(0xB3) /**< (HSTPIPICR) Register Mask */ + +/* CTRL mode */ +#define HSTPIPICR_CTRL_TXSTPIC_Pos 2 /**< (HSTPIPICR) Transmitted SETUP Interrupt Clear Position */ +#define HSTPIPICR_CTRL_TXSTPIC (_U_(0x1) << HSTPIPICR_CTRL_TXSTPIC_Pos) /**< (HSTPIPICR) Transmitted SETUP Interrupt Clear Mask */ +#define HSTPIPICR_CTRL_RXSTALLDIC_Pos 6 /**< (HSTPIPICR) Received STALLed Interrupt Clear Position */ +#define HSTPIPICR_CTRL_RXSTALLDIC (_U_(0x1) << HSTPIPICR_CTRL_RXSTALLDIC_Pos) /**< (HSTPIPICR) Received STALLed Interrupt Clear Mask */ +#define HSTPIPICR_CTRL_Msk _U_(0x44) /**< (HSTPIPICR_CTRL) Register Mask */ + +/* ISO mode */ +#define HSTPIPICR_ISO_UNDERFIC_Pos 2 /**< (HSTPIPICR) Underflow Interrupt Clear Position */ +#define HSTPIPICR_ISO_UNDERFIC (_U_(0x1) << HSTPIPICR_ISO_UNDERFIC_Pos) /**< (HSTPIPICR) Underflow Interrupt Clear Mask */ +#define HSTPIPICR_ISO_CRCERRIC_Pos 6 /**< (HSTPIPICR) CRC Error Interrupt Clear Position */ +#define HSTPIPICR_ISO_CRCERRIC (_U_(0x1) << HSTPIPICR_ISO_CRCERRIC_Pos) /**< (HSTPIPICR) CRC Error Interrupt Clear Mask */ +#define HSTPIPICR_ISO_Msk _U_(0x44) /**< (HSTPIPICR_ISO) Register Mask */ + +/* BLK mode */ +#define HSTPIPICR_BLK_TXSTPIC_Pos 2 /**< (HSTPIPICR) Transmitted SETUP Interrupt Clear Position */ +#define HSTPIPICR_BLK_TXSTPIC (_U_(0x1) << HSTPIPICR_BLK_TXSTPIC_Pos) /**< (HSTPIPICR) Transmitted SETUP Interrupt Clear Mask */ +#define HSTPIPICR_BLK_RXSTALLDIC_Pos 6 /**< (HSTPIPICR) Received STALLed Interrupt Clear Position */ +#define HSTPIPICR_BLK_RXSTALLDIC (_U_(0x1) << HSTPIPICR_BLK_RXSTALLDIC_Pos) /**< (HSTPIPICR) Received STALLed Interrupt Clear Mask */ +#define HSTPIPICR_BLK_Msk _U_(0x44) /**< (HSTPIPICR_BLK) Register Mask */ + +/* INTRPT mode */ +#define HSTPIPICR_INTRPT_UNDERFIC_Pos 2 /**< (HSTPIPICR) Underflow Interrupt Clear Position */ +#define HSTPIPICR_INTRPT_UNDERFIC (_U_(0x1) << HSTPIPICR_INTRPT_UNDERFIC_Pos) /**< (HSTPIPICR) Underflow Interrupt Clear Mask */ +#define HSTPIPICR_INTRPT_RXSTALLDIC_Pos 6 /**< (HSTPIPICR) Received STALLed Interrupt Clear Position */ +#define HSTPIPICR_INTRPT_RXSTALLDIC (_U_(0x1) << HSTPIPICR_INTRPT_RXSTALLDIC_Pos) /**< (HSTPIPICR) Received STALLed Interrupt Clear Mask */ +#define HSTPIPICR_INTRPT_Msk _U_(0x44) /**< (HSTPIPICR_INTRPT) Register Mask */ + + +/* -------- HSTPIPIFR : (USBHS Offset: 0x590) (/W 32) Host Pipe Set Register -------- */ + +#define HSTPIPIFR_OFFSET (0x590) /**< (HSTPIPIFR) Host Pipe Set Register Offset */ + +#define HSTPIPIFR_RXINIS_Pos 0 /**< (HSTPIPIFR) Received IN Data Interrupt Set Position */ +#define HSTPIPIFR_RXINIS (_U_(0x1) << HSTPIPIFR_RXINIS_Pos) /**< (HSTPIPIFR) Received IN Data Interrupt Set Mask */ +#define HSTPIPIFR_TXOUTIS_Pos 1 /**< (HSTPIPIFR) Transmitted OUT Data Interrupt Set Position */ +#define HSTPIPIFR_TXOUTIS (_U_(0x1) << HSTPIPIFR_TXOUTIS_Pos) /**< (HSTPIPIFR) Transmitted OUT Data Interrupt Set Mask */ +#define HSTPIPIFR_PERRIS_Pos 3 /**< (HSTPIPIFR) Pipe Error Interrupt Set Position */ +#define HSTPIPIFR_PERRIS (_U_(0x1) << HSTPIPIFR_PERRIS_Pos) /**< (HSTPIPIFR) Pipe Error Interrupt Set Mask */ +#define HSTPIPIFR_NAKEDIS_Pos 4 /**< (HSTPIPIFR) NAKed Interrupt Set Position */ +#define HSTPIPIFR_NAKEDIS (_U_(0x1) << HSTPIPIFR_NAKEDIS_Pos) /**< (HSTPIPIFR) NAKed Interrupt Set Mask */ +#define HSTPIPIFR_OVERFIS_Pos 5 /**< (HSTPIPIFR) Overflow Interrupt Set Position */ +#define HSTPIPIFR_OVERFIS (_U_(0x1) << HSTPIPIFR_OVERFIS_Pos) /**< (HSTPIPIFR) Overflow Interrupt Set Mask */ +#define HSTPIPIFR_SHORTPACKETIS_Pos 7 /**< (HSTPIPIFR) Short Packet Interrupt Set Position */ +#define HSTPIPIFR_SHORTPACKETIS (_U_(0x1) << HSTPIPIFR_SHORTPACKETIS_Pos) /**< (HSTPIPIFR) Short Packet Interrupt Set Mask */ +#define HSTPIPIFR_NBUSYBKS_Pos 12 /**< (HSTPIPIFR) Number of Busy Banks Set Position */ +#define HSTPIPIFR_NBUSYBKS (_U_(0x1) << HSTPIPIFR_NBUSYBKS_Pos) /**< (HSTPIPIFR) Number of Busy Banks Set Mask */ +#define HSTPIPIFR_Msk _U_(0x10BB) /**< (HSTPIPIFR) Register Mask */ + +/* CTRL mode */ +#define HSTPIPIFR_CTRL_TXSTPIS_Pos 2 /**< (HSTPIPIFR) Transmitted SETUP Interrupt Set Position */ +#define HSTPIPIFR_CTRL_TXSTPIS (_U_(0x1) << HSTPIPIFR_CTRL_TXSTPIS_Pos) /**< (HSTPIPIFR) Transmitted SETUP Interrupt Set Mask */ +#define HSTPIPIFR_CTRL_RXSTALLDIS_Pos 6 /**< (HSTPIPIFR) Received STALLed Interrupt Set Position */ +#define HSTPIPIFR_CTRL_RXSTALLDIS (_U_(0x1) << HSTPIPIFR_CTRL_RXSTALLDIS_Pos) /**< (HSTPIPIFR) Received STALLed Interrupt Set Mask */ +#define HSTPIPIFR_CTRL_Msk _U_(0x44) /**< (HSTPIPIFR_CTRL) Register Mask */ + +/* ISO mode */ +#define HSTPIPIFR_ISO_UNDERFIS_Pos 2 /**< (HSTPIPIFR) Underflow Interrupt Set Position */ +#define HSTPIPIFR_ISO_UNDERFIS (_U_(0x1) << HSTPIPIFR_ISO_UNDERFIS_Pos) /**< (HSTPIPIFR) Underflow Interrupt Set Mask */ +#define HSTPIPIFR_ISO_CRCERRIS_Pos 6 /**< (HSTPIPIFR) CRC Error Interrupt Set Position */ +#define HSTPIPIFR_ISO_CRCERRIS (_U_(0x1) << HSTPIPIFR_ISO_CRCERRIS_Pos) /**< (HSTPIPIFR) CRC Error Interrupt Set Mask */ +#define HSTPIPIFR_ISO_Msk _U_(0x44) /**< (HSTPIPIFR_ISO) Register Mask */ + +/* BLK mode */ +#define HSTPIPIFR_BLK_TXSTPIS_Pos 2 /**< (HSTPIPIFR) Transmitted SETUP Interrupt Set Position */ +#define HSTPIPIFR_BLK_TXSTPIS (_U_(0x1) << HSTPIPIFR_BLK_TXSTPIS_Pos) /**< (HSTPIPIFR) Transmitted SETUP Interrupt Set Mask */ +#define HSTPIPIFR_BLK_RXSTALLDIS_Pos 6 /**< (HSTPIPIFR) Received STALLed Interrupt Set Position */ +#define HSTPIPIFR_BLK_RXSTALLDIS (_U_(0x1) << HSTPIPIFR_BLK_RXSTALLDIS_Pos) /**< (HSTPIPIFR) Received STALLed Interrupt Set Mask */ +#define HSTPIPIFR_BLK_Msk _U_(0x44) /**< (HSTPIPIFR_BLK) Register Mask */ + +/* INTRPT mode */ +#define HSTPIPIFR_INTRPT_UNDERFIS_Pos 2 /**< (HSTPIPIFR) Underflow Interrupt Set Position */ +#define HSTPIPIFR_INTRPT_UNDERFIS (_U_(0x1) << HSTPIPIFR_INTRPT_UNDERFIS_Pos) /**< (HSTPIPIFR) Underflow Interrupt Set Mask */ +#define HSTPIPIFR_INTRPT_RXSTALLDIS_Pos 6 /**< (HSTPIPIFR) Received STALLed Interrupt Set Position */ +#define HSTPIPIFR_INTRPT_RXSTALLDIS (_U_(0x1) << HSTPIPIFR_INTRPT_RXSTALLDIS_Pos) /**< (HSTPIPIFR) Received STALLed Interrupt Set Mask */ +#define HSTPIPIFR_INTRPT_Msk _U_(0x44) /**< (HSTPIPIFR_INTRPT) Register Mask */ + + +/* -------- HSTPIPIMR : (USBHS Offset: 0x5c0) (R/ 32) Host Pipe Mask Register -------- */ + +#define HSTPIPIMR_OFFSET (0x5C0) /**< (HSTPIPIMR) Host Pipe Mask Register Offset */ + +#define HSTPIPIMR_RXINE_Pos 0 /**< (HSTPIPIMR) Received IN Data Interrupt Enable Position */ +#define HSTPIPIMR_RXINE (_U_(0x1) << HSTPIPIMR_RXINE_Pos) /**< (HSTPIPIMR) Received IN Data Interrupt Enable Mask */ +#define HSTPIPIMR_TXOUTE_Pos 1 /**< (HSTPIPIMR) Transmitted OUT Data Interrupt Enable Position */ +#define HSTPIPIMR_TXOUTE (_U_(0x1) << HSTPIPIMR_TXOUTE_Pos) /**< (HSTPIPIMR) Transmitted OUT Data Interrupt Enable Mask */ +#define HSTPIPIMR_PERRE_Pos 3 /**< (HSTPIPIMR) Pipe Error Interrupt Enable Position */ +#define HSTPIPIMR_PERRE (_U_(0x1) << HSTPIPIMR_PERRE_Pos) /**< (HSTPIPIMR) Pipe Error Interrupt Enable Mask */ +#define HSTPIPIMR_NAKEDE_Pos 4 /**< (HSTPIPIMR) NAKed Interrupt Enable Position */ +#define HSTPIPIMR_NAKEDE (_U_(0x1) << HSTPIPIMR_NAKEDE_Pos) /**< (HSTPIPIMR) NAKed Interrupt Enable Mask */ +#define HSTPIPIMR_OVERFIE_Pos 5 /**< (HSTPIPIMR) Overflow Interrupt Enable Position */ +#define HSTPIPIMR_OVERFIE (_U_(0x1) << HSTPIPIMR_OVERFIE_Pos) /**< (HSTPIPIMR) Overflow Interrupt Enable Mask */ +#define HSTPIPIMR_SHORTPACKETIE_Pos 7 /**< (HSTPIPIMR) Short Packet Interrupt Enable Position */ +#define HSTPIPIMR_SHORTPACKETIE (_U_(0x1) << HSTPIPIMR_SHORTPACKETIE_Pos) /**< (HSTPIPIMR) Short Packet Interrupt Enable Mask */ +#define HSTPIPIMR_NBUSYBKE_Pos 12 /**< (HSTPIPIMR) Number of Busy Banks Interrupt Enable Position */ +#define HSTPIPIMR_NBUSYBKE (_U_(0x1) << HSTPIPIMR_NBUSYBKE_Pos) /**< (HSTPIPIMR) Number of Busy Banks Interrupt Enable Mask */ +#define HSTPIPIMR_FIFOCON_Pos 14 /**< (HSTPIPIMR) FIFO Control Position */ +#define HSTPIPIMR_FIFOCON (_U_(0x1) << HSTPIPIMR_FIFOCON_Pos) /**< (HSTPIPIMR) FIFO Control Mask */ +#define HSTPIPIMR_PDISHDMA_Pos 16 /**< (HSTPIPIMR) Pipe Interrupts Disable HDMA Request Enable Position */ +#define HSTPIPIMR_PDISHDMA (_U_(0x1) << HSTPIPIMR_PDISHDMA_Pos) /**< (HSTPIPIMR) Pipe Interrupts Disable HDMA Request Enable Mask */ +#define HSTPIPIMR_PFREEZE_Pos 17 /**< (HSTPIPIMR) Pipe Freeze Position */ +#define HSTPIPIMR_PFREEZE (_U_(0x1) << HSTPIPIMR_PFREEZE_Pos) /**< (HSTPIPIMR) Pipe Freeze Mask */ +#define HSTPIPIMR_RSTDT_Pos 18 /**< (HSTPIPIMR) Reset Data Toggle Position */ +#define HSTPIPIMR_RSTDT (_U_(0x1) << HSTPIPIMR_RSTDT_Pos) /**< (HSTPIPIMR) Reset Data Toggle Mask */ +#define HSTPIPIMR_Msk _U_(0x750BB) /**< (HSTPIPIMR) Register Mask */ + +/* CTRL mode */ +#define HSTPIPIMR_CTRL_TXSTPE_Pos 2 /**< (HSTPIPIMR) Transmitted SETUP Interrupt Enable Position */ +#define HSTPIPIMR_CTRL_TXSTPE (_U_(0x1) << HSTPIPIMR_CTRL_TXSTPE_Pos) /**< (HSTPIPIMR) Transmitted SETUP Interrupt Enable Mask */ +#define HSTPIPIMR_CTRL_RXSTALLDE_Pos 6 /**< (HSTPIPIMR) Received STALLed Interrupt Enable Position */ +#define HSTPIPIMR_CTRL_RXSTALLDE (_U_(0x1) << HSTPIPIMR_CTRL_RXSTALLDE_Pos) /**< (HSTPIPIMR) Received STALLed Interrupt Enable Mask */ +#define HSTPIPIMR_CTRL_Msk _U_(0x44) /**< (HSTPIPIMR_CTRL) Register Mask */ + +/* ISO mode */ +#define HSTPIPIMR_ISO_UNDERFIE_Pos 2 /**< (HSTPIPIMR) Underflow Interrupt Enable Position */ +#define HSTPIPIMR_ISO_UNDERFIE (_U_(0x1) << HSTPIPIMR_ISO_UNDERFIE_Pos) /**< (HSTPIPIMR) Underflow Interrupt Enable Mask */ +#define HSTPIPIMR_ISO_CRCERRE_Pos 6 /**< (HSTPIPIMR) CRC Error Interrupt Enable Position */ +#define HSTPIPIMR_ISO_CRCERRE (_U_(0x1) << HSTPIPIMR_ISO_CRCERRE_Pos) /**< (HSTPIPIMR) CRC Error Interrupt Enable Mask */ +#define HSTPIPIMR_ISO_Msk _U_(0x44) /**< (HSTPIPIMR_ISO) Register Mask */ + +/* BLK mode */ +#define HSTPIPIMR_BLK_TXSTPE_Pos 2 /**< (HSTPIPIMR) Transmitted SETUP Interrupt Enable Position */ +#define HSTPIPIMR_BLK_TXSTPE (_U_(0x1) << HSTPIPIMR_BLK_TXSTPE_Pos) /**< (HSTPIPIMR) Transmitted SETUP Interrupt Enable Mask */ +#define HSTPIPIMR_BLK_RXSTALLDE_Pos 6 /**< (HSTPIPIMR) Received STALLed Interrupt Enable Position */ +#define HSTPIPIMR_BLK_RXSTALLDE (_U_(0x1) << HSTPIPIMR_BLK_RXSTALLDE_Pos) /**< (HSTPIPIMR) Received STALLed Interrupt Enable Mask */ +#define HSTPIPIMR_BLK_Msk _U_(0x44) /**< (HSTPIPIMR_BLK) Register Mask */ + +/* INTRPT mode */ +#define HSTPIPIMR_INTRPT_UNDERFIE_Pos 2 /**< (HSTPIPIMR) Underflow Interrupt Enable Position */ +#define HSTPIPIMR_INTRPT_UNDERFIE (_U_(0x1) << HSTPIPIMR_INTRPT_UNDERFIE_Pos) /**< (HSTPIPIMR) Underflow Interrupt Enable Mask */ +#define HSTPIPIMR_INTRPT_RXSTALLDE_Pos 6 /**< (HSTPIPIMR) Received STALLed Interrupt Enable Position */ +#define HSTPIPIMR_INTRPT_RXSTALLDE (_U_(0x1) << HSTPIPIMR_INTRPT_RXSTALLDE_Pos) /**< (HSTPIPIMR) Received STALLed Interrupt Enable Mask */ +#define HSTPIPIMR_INTRPT_Msk _U_(0x44) /**< (HSTPIPIMR_INTRPT) Register Mask */ + + +/* -------- HSTPIPIER : (USBHS Offset: 0x5f0) (/W 32) Host Pipe Enable Register -------- */ + +#define HSTPIPIER_OFFSET (0x5F0) /**< (HSTPIPIER) Host Pipe Enable Register Offset */ + +#define HSTPIPIER_RXINES_Pos 0 /**< (HSTPIPIER) Received IN Data Interrupt Enable Position */ +#define HSTPIPIER_RXINES (_U_(0x1) << HSTPIPIER_RXINES_Pos) /**< (HSTPIPIER) Received IN Data Interrupt Enable Mask */ +#define HSTPIPIER_TXOUTES_Pos 1 /**< (HSTPIPIER) Transmitted OUT Data Interrupt Enable Position */ +#define HSTPIPIER_TXOUTES (_U_(0x1) << HSTPIPIER_TXOUTES_Pos) /**< (HSTPIPIER) Transmitted OUT Data Interrupt Enable Mask */ +#define HSTPIPIER_PERRES_Pos 3 /**< (HSTPIPIER) Pipe Error Interrupt Enable Position */ +#define HSTPIPIER_PERRES (_U_(0x1) << HSTPIPIER_PERRES_Pos) /**< (HSTPIPIER) Pipe Error Interrupt Enable Mask */ +#define HSTPIPIER_NAKEDES_Pos 4 /**< (HSTPIPIER) NAKed Interrupt Enable Position */ +#define HSTPIPIER_NAKEDES (_U_(0x1) << HSTPIPIER_NAKEDES_Pos) /**< (HSTPIPIER) NAKed Interrupt Enable Mask */ +#define HSTPIPIER_OVERFIES_Pos 5 /**< (HSTPIPIER) Overflow Interrupt Enable Position */ +#define HSTPIPIER_OVERFIES (_U_(0x1) << HSTPIPIER_OVERFIES_Pos) /**< (HSTPIPIER) Overflow Interrupt Enable Mask */ +#define HSTPIPIER_SHORTPACKETIES_Pos 7 /**< (HSTPIPIER) Short Packet Interrupt Enable Position */ +#define HSTPIPIER_SHORTPACKETIES (_U_(0x1) << HSTPIPIER_SHORTPACKETIES_Pos) /**< (HSTPIPIER) Short Packet Interrupt Enable Mask */ +#define HSTPIPIER_NBUSYBKES_Pos 12 /**< (HSTPIPIER) Number of Busy Banks Enable Position */ +#define HSTPIPIER_NBUSYBKES (_U_(0x1) << HSTPIPIER_NBUSYBKES_Pos) /**< (HSTPIPIER) Number of Busy Banks Enable Mask */ +#define HSTPIPIER_PDISHDMAS_Pos 16 /**< (HSTPIPIER) Pipe Interrupts Disable HDMA Request Enable Position */ +#define HSTPIPIER_PDISHDMAS (_U_(0x1) << HSTPIPIER_PDISHDMAS_Pos) /**< (HSTPIPIER) Pipe Interrupts Disable HDMA Request Enable Mask */ +#define HSTPIPIER_PFREEZES_Pos 17 /**< (HSTPIPIER) Pipe Freeze Enable Position */ +#define HSTPIPIER_PFREEZES (_U_(0x1) << HSTPIPIER_PFREEZES_Pos) /**< (HSTPIPIER) Pipe Freeze Enable Mask */ +#define HSTPIPIER_RSTDTS_Pos 18 /**< (HSTPIPIER) Reset Data Toggle Enable Position */ +#define HSTPIPIER_RSTDTS (_U_(0x1) << HSTPIPIER_RSTDTS_Pos) /**< (HSTPIPIER) Reset Data Toggle Enable Mask */ +#define HSTPIPIER_Msk _U_(0x710BB) /**< (HSTPIPIER) Register Mask */ + +/* CTRL mode */ +#define HSTPIPIER_CTRL_TXSTPES_Pos 2 /**< (HSTPIPIER) Transmitted SETUP Interrupt Enable Position */ +#define HSTPIPIER_CTRL_TXSTPES (_U_(0x1) << HSTPIPIER_CTRL_TXSTPES_Pos) /**< (HSTPIPIER) Transmitted SETUP Interrupt Enable Mask */ +#define HSTPIPIER_CTRL_RXSTALLDES_Pos 6 /**< (HSTPIPIER) Received STALLed Interrupt Enable Position */ +#define HSTPIPIER_CTRL_RXSTALLDES (_U_(0x1) << HSTPIPIER_CTRL_RXSTALLDES_Pos) /**< (HSTPIPIER) Received STALLed Interrupt Enable Mask */ +#define HSTPIPIER_CTRL_Msk _U_(0x44) /**< (HSTPIPIER_CTRL) Register Mask */ + +/* ISO mode */ +#define HSTPIPIER_ISO_UNDERFIES_Pos 2 /**< (HSTPIPIER) Underflow Interrupt Enable Position */ +#define HSTPIPIER_ISO_UNDERFIES (_U_(0x1) << HSTPIPIER_ISO_UNDERFIES_Pos) /**< (HSTPIPIER) Underflow Interrupt Enable Mask */ +#define HSTPIPIER_ISO_CRCERRES_Pos 6 /**< (HSTPIPIER) CRC Error Interrupt Enable Position */ +#define HSTPIPIER_ISO_CRCERRES (_U_(0x1) << HSTPIPIER_ISO_CRCERRES_Pos) /**< (HSTPIPIER) CRC Error Interrupt Enable Mask */ +#define HSTPIPIER_ISO_Msk _U_(0x44) /**< (HSTPIPIER_ISO) Register Mask */ + +/* BLK mode */ +#define HSTPIPIER_BLK_TXSTPES_Pos 2 /**< (HSTPIPIER) Transmitted SETUP Interrupt Enable Position */ +#define HSTPIPIER_BLK_TXSTPES (_U_(0x1) << HSTPIPIER_BLK_TXSTPES_Pos) /**< (HSTPIPIER) Transmitted SETUP Interrupt Enable Mask */ +#define HSTPIPIER_BLK_RXSTALLDES_Pos 6 /**< (HSTPIPIER) Received STALLed Interrupt Enable Position */ +#define HSTPIPIER_BLK_RXSTALLDES (_U_(0x1) << HSTPIPIER_BLK_RXSTALLDES_Pos) /**< (HSTPIPIER) Received STALLed Interrupt Enable Mask */ +#define HSTPIPIER_BLK_Msk _U_(0x44) /**< (HSTPIPIER_BLK) Register Mask */ + +/* INTRPT mode */ +#define HSTPIPIER_INTRPT_UNDERFIES_Pos 2 /**< (HSTPIPIER) Underflow Interrupt Enable Position */ +#define HSTPIPIER_INTRPT_UNDERFIES (_U_(0x1) << HSTPIPIER_INTRPT_UNDERFIES_Pos) /**< (HSTPIPIER) Underflow Interrupt Enable Mask */ +#define HSTPIPIER_INTRPT_RXSTALLDES_Pos 6 /**< (HSTPIPIER) Received STALLed Interrupt Enable Position */ +#define HSTPIPIER_INTRPT_RXSTALLDES (_U_(0x1) << HSTPIPIER_INTRPT_RXSTALLDES_Pos) /**< (HSTPIPIER) Received STALLed Interrupt Enable Mask */ +#define HSTPIPIER_INTRPT_Msk _U_(0x44) /**< (HSTPIPIER_INTRPT) Register Mask */ + + +/* -------- HSTPIPIDR : (USBHS Offset: 0x620) (/W 32) Host Pipe Disable Register -------- */ + +#define HSTPIPIDR_OFFSET (0x620) /**< (HSTPIPIDR) Host Pipe Disable Register Offset */ + +#define HSTPIPIDR_RXINEC_Pos 0 /**< (HSTPIPIDR) Received IN Data Interrupt Disable Position */ +#define HSTPIPIDR_RXINEC (_U_(0x1) << HSTPIPIDR_RXINEC_Pos) /**< (HSTPIPIDR) Received IN Data Interrupt Disable Mask */ +#define HSTPIPIDR_TXOUTEC_Pos 1 /**< (HSTPIPIDR) Transmitted OUT Data Interrupt Disable Position */ +#define HSTPIPIDR_TXOUTEC (_U_(0x1) << HSTPIPIDR_TXOUTEC_Pos) /**< (HSTPIPIDR) Transmitted OUT Data Interrupt Disable Mask */ +#define HSTPIPIDR_PERREC_Pos 3 /**< (HSTPIPIDR) Pipe Error Interrupt Disable Position */ +#define HSTPIPIDR_PERREC (_U_(0x1) << HSTPIPIDR_PERREC_Pos) /**< (HSTPIPIDR) Pipe Error Interrupt Disable Mask */ +#define HSTPIPIDR_NAKEDEC_Pos 4 /**< (HSTPIPIDR) NAKed Interrupt Disable Position */ +#define HSTPIPIDR_NAKEDEC (_U_(0x1) << HSTPIPIDR_NAKEDEC_Pos) /**< (HSTPIPIDR) NAKed Interrupt Disable Mask */ +#define HSTPIPIDR_OVERFIEC_Pos 5 /**< (HSTPIPIDR) Overflow Interrupt Disable Position */ +#define HSTPIPIDR_OVERFIEC (_U_(0x1) << HSTPIPIDR_OVERFIEC_Pos) /**< (HSTPIPIDR) Overflow Interrupt Disable Mask */ +#define HSTPIPIDR_SHORTPACKETIEC_Pos 7 /**< (HSTPIPIDR) Short Packet Interrupt Disable Position */ +#define HSTPIPIDR_SHORTPACKETIEC (_U_(0x1) << HSTPIPIDR_SHORTPACKETIEC_Pos) /**< (HSTPIPIDR) Short Packet Interrupt Disable Mask */ +#define HSTPIPIDR_NBUSYBKEC_Pos 12 /**< (HSTPIPIDR) Number of Busy Banks Disable Position */ +#define HSTPIPIDR_NBUSYBKEC (_U_(0x1) << HSTPIPIDR_NBUSYBKEC_Pos) /**< (HSTPIPIDR) Number of Busy Banks Disable Mask */ +#define HSTPIPIDR_FIFOCONC_Pos 14 /**< (HSTPIPIDR) FIFO Control Disable Position */ +#define HSTPIPIDR_FIFOCONC (_U_(0x1) << HSTPIPIDR_FIFOCONC_Pos) /**< (HSTPIPIDR) FIFO Control Disable Mask */ +#define HSTPIPIDR_PDISHDMAC_Pos 16 /**< (HSTPIPIDR) Pipe Interrupts Disable HDMA Request Disable Position */ +#define HSTPIPIDR_PDISHDMAC (_U_(0x1) << HSTPIPIDR_PDISHDMAC_Pos) /**< (HSTPIPIDR) Pipe Interrupts Disable HDMA Request Disable Mask */ +#define HSTPIPIDR_PFREEZEC_Pos 17 /**< (HSTPIPIDR) Pipe Freeze Disable Position */ +#define HSTPIPIDR_PFREEZEC (_U_(0x1) << HSTPIPIDR_PFREEZEC_Pos) /**< (HSTPIPIDR) Pipe Freeze Disable Mask */ +#define HSTPIPIDR_Msk _U_(0x350BB) /**< (HSTPIPIDR) Register Mask */ + +/* CTRL mode */ +#define HSTPIPIDR_CTRL_TXSTPEC_Pos 2 /**< (HSTPIPIDR) Transmitted SETUP Interrupt Disable Position */ +#define HSTPIPIDR_CTRL_TXSTPEC (_U_(0x1) << HSTPIPIDR_CTRL_TXSTPEC_Pos) /**< (HSTPIPIDR) Transmitted SETUP Interrupt Disable Mask */ +#define HSTPIPIDR_CTRL_RXSTALLDEC_Pos 6 /**< (HSTPIPIDR) Received STALLed Interrupt Disable Position */ +#define HSTPIPIDR_CTRL_RXSTALLDEC (_U_(0x1) << HSTPIPIDR_CTRL_RXSTALLDEC_Pos) /**< (HSTPIPIDR) Received STALLed Interrupt Disable Mask */ +#define HSTPIPIDR_CTRL_Msk _U_(0x44) /**< (HSTPIPIDR_CTRL) Register Mask */ + +/* ISO mode */ +#define HSTPIPIDR_ISO_UNDERFIEC_Pos 2 /**< (HSTPIPIDR) Underflow Interrupt Disable Position */ +#define HSTPIPIDR_ISO_UNDERFIEC (_U_(0x1) << HSTPIPIDR_ISO_UNDERFIEC_Pos) /**< (HSTPIPIDR) Underflow Interrupt Disable Mask */ +#define HSTPIPIDR_ISO_CRCERREC_Pos 6 /**< (HSTPIPIDR) CRC Error Interrupt Disable Position */ +#define HSTPIPIDR_ISO_CRCERREC (_U_(0x1) << HSTPIPIDR_ISO_CRCERREC_Pos) /**< (HSTPIPIDR) CRC Error Interrupt Disable Mask */ +#define HSTPIPIDR_ISO_Msk _U_(0x44) /**< (HSTPIPIDR_ISO) Register Mask */ + +/* BLK mode */ +#define HSTPIPIDR_BLK_TXSTPEC_Pos 2 /**< (HSTPIPIDR) Transmitted SETUP Interrupt Disable Position */ +#define HSTPIPIDR_BLK_TXSTPEC (_U_(0x1) << HSTPIPIDR_BLK_TXSTPEC_Pos) /**< (HSTPIPIDR) Transmitted SETUP Interrupt Disable Mask */ +#define HSTPIPIDR_BLK_RXSTALLDEC_Pos 6 /**< (HSTPIPIDR) Received STALLed Interrupt Disable Position */ +#define HSTPIPIDR_BLK_RXSTALLDEC (_U_(0x1) << HSTPIPIDR_BLK_RXSTALLDEC_Pos) /**< (HSTPIPIDR) Received STALLed Interrupt Disable Mask */ +#define HSTPIPIDR_BLK_Msk _U_(0x44) /**< (HSTPIPIDR_BLK) Register Mask */ + +/* INTRPT mode */ +#define HSTPIPIDR_INTRPT_UNDERFIEC_Pos 2 /**< (HSTPIPIDR) Underflow Interrupt Disable Position */ +#define HSTPIPIDR_INTRPT_UNDERFIEC (_U_(0x1) << HSTPIPIDR_INTRPT_UNDERFIEC_Pos) /**< (HSTPIPIDR) Underflow Interrupt Disable Mask */ +#define HSTPIPIDR_INTRPT_RXSTALLDEC_Pos 6 /**< (HSTPIPIDR) Received STALLed Interrupt Disable Position */ +#define HSTPIPIDR_INTRPT_RXSTALLDEC (_U_(0x1) << HSTPIPIDR_INTRPT_RXSTALLDEC_Pos) /**< (HSTPIPIDR) Received STALLed Interrupt Disable Mask */ +#define HSTPIPIDR_INTRPT_Msk _U_(0x44) /**< (HSTPIPIDR_INTRPT) Register Mask */ + + +/* -------- HSTPIPINRQ : (USBHS Offset: 0x650) (R/W 32) Host Pipe IN Request Register -------- */ + +#define HSTPIPINRQ_OFFSET (0x650) /**< (HSTPIPINRQ) Host Pipe IN Request Register Offset */ + +#define HSTPIPINRQ_INRQ_Pos 0 /**< (HSTPIPINRQ) IN Request Number before Freeze Position */ +#define HSTPIPINRQ_INRQ (_U_(0xFF) << HSTPIPINRQ_INRQ_Pos) /**< (HSTPIPINRQ) IN Request Number before Freeze Mask */ +#define HSTPIPINRQ_INMODE_Pos 8 /**< (HSTPIPINRQ) IN Request Mode Position */ +#define HSTPIPINRQ_INMODE (_U_(0x1) << HSTPIPINRQ_INMODE_Pos) /**< (HSTPIPINRQ) IN Request Mode Mask */ +#define HSTPIPINRQ_Msk _U_(0x1FF) /**< (HSTPIPINRQ) Register Mask */ + + +/* -------- HSTPIPERR : (USBHS Offset: 0x680) (R/W 32) Host Pipe Error Register -------- */ + +#define HSTPIPERR_OFFSET (0x680) /**< (HSTPIPERR) Host Pipe Error Register Offset */ + +#define HSTPIPERR_DATATGL_Pos 0 /**< (HSTPIPERR) Data Toggle Error Position */ +#define HSTPIPERR_DATATGL (_U_(0x1) << HSTPIPERR_DATATGL_Pos) /**< (HSTPIPERR) Data Toggle Error Mask */ +#define HSTPIPERR_DATAPID_Pos 1 /**< (HSTPIPERR) Data PID Error Position */ +#define HSTPIPERR_DATAPID (_U_(0x1) << HSTPIPERR_DATAPID_Pos) /**< (HSTPIPERR) Data PID Error Mask */ +#define HSTPIPERR_PID_Pos 2 /**< (HSTPIPERR) Data PID Error Position */ +#define HSTPIPERR_PID (_U_(0x1) << HSTPIPERR_PID_Pos) /**< (HSTPIPERR) Data PID Error Mask */ +#define HSTPIPERR_TIMEOUT_Pos 3 /**< (HSTPIPERR) Time-Out Error Position */ +#define HSTPIPERR_TIMEOUT (_U_(0x1) << HSTPIPERR_TIMEOUT_Pos) /**< (HSTPIPERR) Time-Out Error Mask */ +#define HSTPIPERR_CRC16_Pos 4 /**< (HSTPIPERR) CRC16 Error Position */ +#define HSTPIPERR_CRC16 (_U_(0x1) << HSTPIPERR_CRC16_Pos) /**< (HSTPIPERR) CRC16 Error Mask */ +#define HSTPIPERR_COUNTER_Pos 5 /**< (HSTPIPERR) Error Counter Position */ +#define HSTPIPERR_COUNTER (_U_(0x3) << HSTPIPERR_COUNTER_Pos) /**< (HSTPIPERR) Error Counter Mask */ +#define HSTPIPERR_Msk _U_(0x7F) /**< (HSTPIPERR) Register Mask */ + +#define HSTPIPERR_CRC_Pos 4 /**< (HSTPIPERR Position) CRCx6 Error */ +#define HSTPIPERR_CRC (_U_(0x1) << HSTPIPERR_CRC_Pos) /**< (HSTPIPERR Mask) CRC */ + +/* -------- CTRL : (USBHS Offset: 0x800) (R/W 32) General Control Register -------- */ + +#define CTRL_OFFSET (0x800) /**< (CTRL) General Control Register Offset */ + +#define CTRL_RDERRE_Pos 4 /**< (CTRL) Remote Device Connection Error Interrupt Enable Position */ +#define CTRL_RDERRE (_U_(0x1) << CTRL_RDERRE_Pos) /**< (CTRL) Remote Device Connection Error Interrupt Enable Mask */ +#define CTRL_VBUSHWC_Pos 8 /**< (CTRL) VBUS Hardware Control Position */ +#define CTRL_VBUSHWC (_U_(0x1) << CTRL_VBUSHWC_Pos) /**< (CTRL) VBUS Hardware Control Mask */ +#define CTRL_FRZCLK_Pos 14 /**< (CTRL) Freeze USB Clock Position */ +#define CTRL_FRZCLK (_U_(0x1) << CTRL_FRZCLK_Pos) /**< (CTRL) Freeze USB Clock Mask */ +#define CTRL_USBE_Pos 15 /**< (CTRL) USBHS Enable Position */ +#define CTRL_USBE (_U_(0x1) << CTRL_USBE_Pos) /**< (CTRL) USBHS Enable Mask */ +#define CTRL_UID_Pos 24 /**< (CTRL) UID Pin Enable Position */ +#define CTRL_UID (_U_(0x1) << CTRL_UID_Pos) /**< (CTRL) UID Pin Enable Mask */ +#define CTRL_UIMOD_Pos 25 /**< (CTRL) USBHS Mode Position */ +#define CTRL_UIMOD (_U_(0x1) << CTRL_UIMOD_Pos) /**< (CTRL) USBHS Mode Mask */ +#define CTRL_UIMOD_HOST_Val _U_(0x0) /**< (CTRL) The module is in USB Host mode. */ +#define CTRL_UIMOD_DEVICE_Val _U_(0x1) /**< (CTRL) The module is in USB Device mode. */ +#define CTRL_UIMOD_HOST (CTRL_UIMOD_HOST_Val << CTRL_UIMOD_Pos) /**< (CTRL) The module is in USB Host mode. Position */ +#define CTRL_UIMOD_DEVICE (CTRL_UIMOD_DEVICE_Val << CTRL_UIMOD_Pos) /**< (CTRL) The module is in USB Device mode. Position */ +#define CTRL_Msk _U_(0x300C110) /**< (CTRL) Register Mask */ + + +/* -------- SR : (USBHS Offset: 0x804) (R/ 32) General Status Register -------- */ + +#define SR_OFFSET (0x804) /**< (SR) General Status Register Offset */ + +#define SR_RDERRI_Pos 4 /**< (SR) Remote Device Connection Error Interrupt (Host mode only) Position */ +#define SR_RDERRI (_U_(0x1) << SR_RDERRI_Pos) /**< (SR) Remote Device Connection Error Interrupt (Host mode only) Mask */ +#define SR_SPEED_Pos 12 /**< (SR) Speed Status (Device mode only) Position */ +#define SR_SPEED (_U_(0x3) << SR_SPEED_Pos) /**< (SR) Speed Status (Device mode only) Mask */ +#define SR_SPEED_FULL_SPEED_Val _U_(0x0) /**< (SR) Full-Speed mode */ +#define SR_SPEED_HIGH_SPEED_Val _U_(0x1) /**< (SR) High-Speed mode */ +#define SR_SPEED_LOW_SPEED_Val _U_(0x2) /**< (SR) Low-Speed mode */ +#define SR_SPEED_FULL_SPEED (SR_SPEED_FULL_SPEED_Val << SR_SPEED_Pos) /**< (SR) Full-Speed mode Position */ +#define SR_SPEED_HIGH_SPEED (SR_SPEED_HIGH_SPEED_Val << SR_SPEED_Pos) /**< (SR) High-Speed mode Position */ +#define SR_SPEED_LOW_SPEED (SR_SPEED_LOW_SPEED_Val << SR_SPEED_Pos) /**< (SR) Low-Speed mode Position */ +#define SR_CLKUSABLE_Pos 14 /**< (SR) UTMI Clock Usable Position */ +#define SR_CLKUSABLE (_U_(0x1) << SR_CLKUSABLE_Pos) /**< (SR) UTMI Clock Usable Mask */ +#define SR_Msk _U_(0x7010) /**< (SR) Register Mask */ + + +/* -------- SCR : (USBHS Offset: 0x808) (/W 32) General Status Clear Register -------- */ + +#define SCR_OFFSET (0x808) /**< (SCR) General Status Clear Register Offset */ + +#define SCR_RDERRIC_Pos 4 /**< (SCR) Remote Device Connection Error Interrupt Clear Position */ +#define SCR_RDERRIC (_U_(0x1) << SCR_RDERRIC_Pos) /**< (SCR) Remote Device Connection Error Interrupt Clear Mask */ +#define SCR_Msk _U_(0x10) /**< (SCR) Register Mask */ + + +/* -------- SFR : (USBHS Offset: 0x80c) (/W 32) General Status Set Register -------- */ + +#define SFR_OFFSET (0x80C) /**< (SFR) General Status Set Register Offset */ + +#define SFR_RDERRIS_Pos 4 /**< (SFR) Remote Device Connection Error Interrupt Set Position */ +#define SFR_RDERRIS (_U_(0x1) << SFR_RDERRIS_Pos) /**< (SFR) Remote Device Connection Error Interrupt Set Mask */ +#define SFR_VBUSRQS_Pos 9 /**< (SFR) VBUS Request Set Position */ +#define SFR_VBUSRQS (_U_(0x1) << SFR_VBUSRQS_Pos) /**< (SFR) VBUS Request Set Mask */ +#define SFR_Msk _U_(0x210) /**< (SFR) Register Mask */ + + +/** \brief DEVDMA hardware registers */ +typedef struct +{ + __IO uint32_t DEVDMANXTDSC; /**< (DEVDMA Offset: 0x00) Device DMA Channel Next Descriptor Address Register */ + __IO uint32_t DEVDMAADDRESS; /**< (DEVDMA Offset: 0x04) Device DMA Channel Address Register */ + __IO uint32_t DEVDMACONTROL; /**< (DEVDMA Offset: 0x08) Device DMA Channel Control Register */ + __IO uint32_t DEVDMASTATUS; /**< (DEVDMA Offset: 0x0C) Device DMA Channel Status Register */ +} devdma_t; + +/** \brief HSTDMA hardware registers */ +typedef struct +{ + __IO uint32_t HSTDMANXTDSC; /**< (HSTDMA Offset: 0x00) Host DMA Channel Next Descriptor Address Register */ + __IO uint32_t HSTDMAADDRESS; /**< (HSTDMA Offset: 0x04) Host DMA Channel Address Register */ + __IO uint32_t HSTDMACONTROL; /**< (HSTDMA Offset: 0x08) Host DMA Channel Control Register */ + __IO uint32_t HSTDMASTATUS; /**< (HSTDMA Offset: 0x0C) Host DMA Channel Status Register */ +} hstdma_t; + +/** \brief USBHS hardware registers */ +typedef struct +{ + __IO uint32_t DEVCTRL; /**< (USBHS Offset: 0x00) Device General Control Register */ + __I uint32_t DEVISR; /**< (USBHS Offset: 0x04) Device Global Interrupt Status Register */ + __O uint32_t DEVICR; /**< (USBHS Offset: 0x08) Device Global Interrupt Clear Register */ + __O uint32_t DEVIFR; /**< (USBHS Offset: 0x0C) Device Global Interrupt Set Register */ + __I uint32_t DEVIMR; /**< (USBHS Offset: 0x10) Device Global Interrupt Mask Register */ + __O uint32_t DEVIDR; /**< (USBHS Offset: 0x14) Device Global Interrupt Disable Register */ + __O uint32_t DEVIER; /**< (USBHS Offset: 0x18) Device Global Interrupt Enable Register */ + __IO uint32_t DEVEPT; /**< (USBHS Offset: 0x1C) Device Endpoint Register */ + __I uint32_t DEVFNUM; /**< (USBHS Offset: 0x20) Device Frame Number Register */ + __I uint8_t Reserved1[220]; + __IO uint32_t DEVEPTCFG[10]; /**< (USBHS Offset: 0x100) Device Endpoint Configuration Register */ + __I uint8_t Reserved2[8]; + __I uint32_t DEVEPTISR[10]; /**< (USBHS Offset: 0x130) Device Endpoint Interrupt Status Register */ + __I uint8_t Reserved3[8]; + __O uint32_t DEVEPTICR[10]; /**< (USBHS Offset: 0x160) Device Endpoint Interrupt Clear Register */ + __I uint8_t Reserved4[8]; + __O uint32_t DEVEPTIFR[10]; /**< (USBHS Offset: 0x190) Device Endpoint Interrupt Set Register */ + __I uint8_t Reserved5[8]; + __I uint32_t DEVEPTIMR[10]; /**< (USBHS Offset: 0x1C0) Device Endpoint Interrupt Mask Register */ + __I uint8_t Reserved6[8]; + __O uint32_t DEVEPTIER[10]; /**< (USBHS Offset: 0x1F0) Device Endpoint Interrupt Enable Register */ + __I uint8_t Reserved7[8]; + __O uint32_t DEVEPTIDR[10]; /**< (USBHS Offset: 0x220) Device Endpoint Interrupt Disable Register */ + __I uint8_t Reserved8[200]; + devdma_t DEVDMA[7]; /**< Offset: 0x310 Device DMA Channel Next Descriptor Address Register */ + __I uint8_t Reserved9[128]; + __IO uint32_t HSTCTRL; /**< (USBHS Offset: 0x400) Host General Control Register */ + __I uint32_t HSTISR; /**< (USBHS Offset: 0x404) Host Global Interrupt Status Register */ + __O uint32_t HSTICR; /**< (USBHS Offset: 0x408) Host Global Interrupt Clear Register */ + __O uint32_t HSTIFR; /**< (USBHS Offset: 0x40C) Host Global Interrupt Set Register */ + __I uint32_t HSTIMR; /**< (USBHS Offset: 0x410) Host Global Interrupt Mask Register */ + __O uint32_t HSTIDR; /**< (USBHS Offset: 0x414) Host Global Interrupt Disable Register */ + __O uint32_t HSTIER; /**< (USBHS Offset: 0x418) Host Global Interrupt Enable Register */ + __IO uint32_t HSTPIP; /**< (USBHS Offset: 0x41C) Host Pipe Register */ + __IO uint32_t HSTFNUM; /**< (USBHS Offset: 0x420) Host Frame Number Register */ + __IO uint32_t HSTADDR1; /**< (USBHS Offset: 0x424) Host Address 1 Register */ + __IO uint32_t HSTADDR2; /**< (USBHS Offset: 0x428) Host Address 2 Register */ + __IO uint32_t HSTADDR3; /**< (USBHS Offset: 0x42C) Host Address 3 Register */ + __I uint8_t Reserved10[208]; + __IO uint32_t HSTPIPCFG[10]; /**< (USBHS Offset: 0x500) Host Pipe Configuration Register */ + __I uint8_t Reserved11[8]; + __I uint32_t HSTPIPISR[10]; /**< (USBHS Offset: 0x530) Host Pipe Status Register */ + __I uint8_t Reserved12[8]; + __O uint32_t HSTPIPICR[10]; /**< (USBHS Offset: 0x560) Host Pipe Clear Register */ + __I uint8_t Reserved13[8]; + __O uint32_t HSTPIPIFR[10]; /**< (USBHS Offset: 0x590) Host Pipe Set Register */ + __I uint8_t Reserved14[8]; + __I uint32_t HSTPIPIMR[10]; /**< (USBHS Offset: 0x5C0) Host Pipe Mask Register */ + __I uint8_t Reserved15[8]; + __O uint32_t HSTPIPIER[10]; /**< (USBHS Offset: 0x5F0) Host Pipe Enable Register */ + __I uint8_t Reserved16[8]; + __O uint32_t HSTPIPIDR[10]; /**< (USBHS Offset: 0x620) Host Pipe Disable Register */ + __I uint8_t Reserved17[8]; + __IO uint32_t HSTPIPINRQ[10]; /**< (USBHS Offset: 0x650) Host Pipe IN Request Register */ + __I uint8_t Reserved18[8]; + __IO uint32_t HSTPIPERR[10]; /**< (USBHS Offset: 0x680) Host Pipe Error Register */ + __I uint8_t Reserved19[104]; + hstdma_t HSTDMA[7]; /**< Offset: 0x710 Host DMA Channel Next Descriptor Address Register */ + __I uint8_t Reserved20[128]; + __IO uint32_t CTRL; /**< (USBHS Offset: 0x800) General Control Register */ + __I uint32_t SR; /**< (USBHS Offset: 0x804) General Status Register */ + __O uint32_t SCR; /**< (USBHS Offset: 0x808) General Status Clear Register */ + __O uint32_t SFR; /**< (USBHS Offset: 0x80C) General Status Set Register */ +} dcd_registers_t; + +#define USB_REG ((dcd_registers_t *)0x40038000U) /**< \brief (USBHS) Base Address */ + +#define EP_MAX 10 + +#define FIFO_RAM_ADDR 0xA0100000u + +// Errata: The DMA feature is not available for Pipe/Endpoint 7 +#define EP_DMA_SUPPORT(epnum) (epnum >= 1 && epnum <= 6 && CFG_TUD_SAMX7X_DMA_ENABLE) + +//------------- DCache -------------// +#if CFG_TUD_MEM_DCACHE_ENABLE || CFG_TUH_MEM_DCACHE_ENABLE + +typedef struct { + uintptr_t start; + uintptr_t end; +} mem_region_t; + +// Can be used to define additional uncached regions +#ifndef CFG_SAMX7X_MEM_UNCACHED_REGIONS +#define CFG_SAMX7X_MEM_UNCACHED_REGIONS +#endif + +static mem_region_t uncached_regions[] = { + // DTCM + {.start = 0x20000000, .end = 0x203fffff}, + CFG_SAMX7X_MEM_UNCACHED_REGIONS +}; + +TU_ATTR_ALWAYS_INLINE static inline uint32_t round_up_to_cache_line_size(uint32_t size) { + if (size & (CFG_TUSB_MEM_DCACHE_LINE_SIZE_DEFAULT-1)) { + size = (size & ~(CFG_TUSB_MEM_DCACHE_LINE_SIZE_DEFAULT-1)) + CFG_TUSB_MEM_DCACHE_LINE_SIZE_DEFAULT; + } + return size; +} + +TU_ATTR_ALWAYS_INLINE static inline bool is_cache_mem(uintptr_t addr) { + if (0 == (SCB->CCR & SCB_CCR_DC_Msk)) { + return false; // D-Cache is disabled + } + for (unsigned int i = 0; i < TU_ARRAY_SIZE(uncached_regions); i++) { + if (uncached_regions[i].start <= addr && addr <= uncached_regions[i].end) { return false; } + } + return true; +} + +TU_ATTR_ALWAYS_INLINE static inline bool samx7x_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 samx7x_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 samx7x_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 + +#else // TODO : SAM3U + + +#endif + +#endif /* _COMMON_USB_REGS_H_ */ diff --git a/src/tusb_option.h b/src/tusb_option.h index d87c2dc8b..8b4d3dcd5 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -394,6 +394,24 @@ // odd byte with byte access #endif +//------- Microchip SAMX7X -------// +// DMA mode for device +#ifndef CFG_TUD_SAMX7X_DMA_ENABLE + #ifndef CFG_TUD_SAMX7X_DMA_ENABLE_DEFAULT + #define CFG_TUD_SAMX7X_DMA_ENABLE_DEFAULT 0 + #endif + + #define CFG_TUD_SAMX7X_DMA_ENABLE CFG_TUD_SAMX7X_DMA_ENABLE_DEFAULT +#endif + +#if (CFG_TUSB_MCU == OPT_MCU_SAMX7X) + #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE 4 + #define CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE 4 + #define CFG_TUSB_FIFO_HWFIFO_DATA_ODD_16BIT_ACCESS + #define CFG_TUSB_FIFO_HWFIFO_DATA_ODD_8BIT_ACCESS + #define CFG_TUD_EDPT_DEDICATED_HWFIFO 1 +#endif + //-------------------------------------------------------------------- // RootHub Mode detection //-------------------------------------------------------------------- -- cgit v1.3.1 From eca8b0050ffef13a534d08e8c648f18c7d654e3e Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 27 Feb 2026 11:31:10 +0100 Subject: dcd/samx7x: remove buggy DMA FIFO transfer Signed-off-by: HiFiPhile --- src/portable/microchip/samx7x/dcd_samx7x.c | 70 ++---------------------------- 1 file changed, 3 insertions(+), 67 deletions(-) (limited to 'src/portable') diff --git a/src/portable/microchip/samx7x/dcd_samx7x.c b/src/portable/microchip/samx7x/dcd_samx7x.c index 979d08fe9..c1cc95d8c 100644 --- a/src/portable/microchip/samx7x/dcd_samx7x.c +++ b/src/portable/microchip/samx7x/dcd_samx7x.c @@ -76,9 +76,6 @@ typedef struct { static tusb_speed_t get_speed(void); static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix); -// DMA descriptors shouldn't be placed in ITCM ! -CFG_TUD_MEM_SECTION static dma_desc_t dma_desc[6]; - static xfer_ctl_t xfer_status[EP_MAX]; static const tusb_desc_endpoint_t ep0_desc = @@ -673,73 +670,12 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_ xfer->queued_len = 0; xfer->fifo = ff; - if (EP_DMA_SUPPORT(epnum) && total_bytes != 0) + if (dir == TUSB_DIR_OUT) { - tu_fifo_buffer_info_t info; - uint32_t udd_dma_ctrl_lin = DEVDMACONTROL_CHANN_ENB; - uint32_t udd_dma_ctrl_wrap = DEVDMACONTROL_CHANN_ENB | DEVDMACONTROL_END_BUFFIT; - if (dir == TUSB_DIR_OUT) - { - tu_fifo_get_write_info(ff, &info); - udd_dma_ctrl_lin |= DEVDMACONTROL_END_TR_IT | DEVDMACONTROL_END_TR_EN; - udd_dma_ctrl_wrap |= DEVDMACONTROL_END_TR_IT | DEVDMACONTROL_END_TR_EN; - } else { - tu_fifo_get_read_info(ff, &info); - if(info.wrapped.len == 0) - { - udd_dma_ctrl_lin |= DEVDMACONTROL_END_B_EN; - } - udd_dma_ctrl_wrap |= DEVDMACONTROL_END_B_EN; - } - - // Clean invalidate cache of linear part - CleanInValidateCache((uint32_t*) tu_align((uint32_t) info.linear.ptr, 4), info.linear.len + 31); - - USB_REG->DEVDMA[epnum - 1].DEVDMAADDRESS = (uint32_t)info.linear.ptr; - if (info.wrapped.len) - { - // Clean invalidate cache of wrapped part - CleanInValidateCache((uint32_t*) tu_align((uint32_t) info.wrapped.ptr, 4), info.wrapped.len + 31); - - dma_desc[epnum - 1].next_desc = 0; - dma_desc[epnum - 1].buff_addr = (uint32_t)info.wrapped.ptr; - dma_desc[epnum - 1].chnl_ctrl = - udd_dma_ctrl_wrap | (info.wrapped.len << DEVDMACONTROL_BUFF_LENGTH_Pos); - // Clean cache of wrapped DMA descriptor - CleanInValidateCache((uint32_t*)&dma_desc[epnum - 1], sizeof(dma_desc_t)); - - udd_dma_ctrl_lin |= DEVDMASTATUS_DESC_LDST; - USB_REG->DEVDMA[epnum - 1].DEVDMANXTDSC = (uint32_t)&dma_desc[epnum - 1]; - } else { - udd_dma_ctrl_lin |= DEVDMACONTROL_END_BUFFIT; - } - udd_dma_ctrl_lin |= (info.linear.len << DEVDMACONTROL_BUFF_LENGTH_Pos); - // Disable IRQs to have a short sequence - // between read of EOT_STA and DMA enable - uint32_t irq_state = __get_PRIMASK(); - __disable_irq(); - if (!(USB_REG->DEVDMA[epnum - 1].DEVDMASTATUS & DEVDMASTATUS_END_TR_ST)) - { - USB_REG->DEVDMA[epnum - 1].DEVDMACONTROL = udd_dma_ctrl_lin; - USB_REG->DEVIER = DEVIER_DMA_1 << (epnum - 1); - __set_PRIMASK(irq_state); - return true; - } - __set_PRIMASK(irq_state); - - // Here a ZLP has been received - // and the DMA transfer must be not started. - // It is the end of transfer - return false; + USB_REG->DEVEPTIER[epnum] = DEVEPTIER_RXOUTES; } else { - if (dir == TUSB_DIR_OUT) - { - USB_REG->DEVEPTIER[epnum] = DEVEPTIER_RXOUTES; - } else - { - dcd_transmit_packet(xfer,epnum); - } + dcd_transmit_packet(xfer,epnum); } return true; } -- cgit v1.3.1 From 84f214d33cf4f1cb2c8a6cf485d135ac2347c24b Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 27 Feb 2026 11:34:55 +0100 Subject: dcd/samx7x: reformat code Signed-off-by: HiFiPhile --- src/portable/microchip/samx7x/dcd_samx7x.c | 568 ++++++++++++----------------- 1 file changed, 236 insertions(+), 332 deletions(-) (limited to 'src/portable') diff --git a/src/portable/microchip/samx7x/dcd_samx7x.c b/src/portable/microchip/samx7x/dcd_samx7x.c index c1cc95d8c..8dd333e0f 100644 --- a/src/portable/microchip/samx7x/dcd_samx7x.c +++ b/src/portable/microchip/samx7x/dcd_samx7x.c @@ -1,134 +1,125 @@ /* -* The MIT License (MIT) -* -* Copyright (c) 2018, hathach (tinyusb.org) -* Copyright (c) 2021, HiFiPhile -* -* 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. -*/ + * The MIT License (MIT) + * + * Copyright (c) 2018, hathach (tinyusb.org) + * Copyright (c) 2021, HiFiPhile + * + * 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_TUD_ENABLED && CFG_TUSB_MCU == OPT_MCU_SAMX7X -#include "device/dcd.h" -#include "sam.h" -#include "samx7x_common.h" -//--------------------------------------------------------------------+ -// MACRO TYPEDEF CONSTANT ENUM DECLARATION -//--------------------------------------------------------------------+ - -// Since TinyUSB doesn't use SOF for now, and this interrupt too often (1ms interval) -// We disable SOF for now until needed later on -#ifndef USE_SOF -# define USE_SOF 0 -#endif - -// Dual bank can improve performance, but need 2 times bigger packet buffer -// As SAM7x has only 4KB packet buffer, use with caution ! -// Enable in FS mode as packets are smaller -#ifndef USE_DUAL_BANK -# if TUD_OPT_HIGH_SPEED -# define USE_DUAL_BANK 0 -# else -# define USE_DUAL_BANK 1 -# endif -#endif - -#define EP_GET_FIFO_PTR(ep, scale) (((TU_XSTRCAT(TU_STRCAT(uint, scale),_t) (*)[0x8000 / ((scale) / 8)])FIFO_RAM_ADDR)[(ep)]) + #include "device/dcd.h" + #include "sam.h" + #include "samx7x_common.h" + //--------------------------------------------------------------------+ + // MACRO TYPEDEF CONSTANT ENUM DECLARATION + //--------------------------------------------------------------------+ + + // Dual bank can improve performance, but need 2 times bigger packet buffer + // As SAM7x has only 4KB packet buffer, use with caution ! + // Enable in FS mode as packets are smaller + #ifndef USE_DUAL_BANK + #if TUD_OPT_HIGH_SPEED + #define USE_DUAL_BANK 0 + #else + #define USE_DUAL_BANK 1 + #endif + #endif + + #define EP_GET_FIFO_PTR(ep, scale) \ + (((TU_XSTRCAT(TU_STRCAT(uint, scale), _t)(*)[0x8000 / ((scale) / 8)]) FIFO_RAM_ADDR)[(ep)]) // DMA Channel Transfer Descriptor typedef struct { volatile uint32_t next_desc; volatile uint32_t buff_addr; volatile uint32_t chnl_ctrl; - uint32_t padding; + uint32_t padding; } dma_desc_t; // Transfer control context typedef struct { - uint8_t * buffer; - uint16_t total_len; - uint16_t queued_len; - uint16_t max_packet_size; - uint8_t interval; - tu_fifo_t * fifo; + uint8_t *buffer; + uint16_t total_len; + uint16_t queued_len; + uint16_t max_packet_size; + uint8_t interval; + tu_fifo_t *fifo; } xfer_ctl_t; static tusb_speed_t get_speed(void); -static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix); +static void dcd_transmit_packet(xfer_ctl_t *xfer, uint8_t ep_ix); static xfer_ctl_t xfer_status[EP_MAX]; -static const tusb_desc_endpoint_t ep0_desc = -{ +static const tusb_desc_endpoint_t ep0_desc = { .bEndpointAddress = 0x00, .wMaxPacketSize = CFG_TUD_ENDPOINT0_SIZE, }; -#if CFG_TUD_MEM_DCACHE_ENABLE -bool dcd_dcache_clean(const void* addr, uint32_t data_size) { + #if CFG_TUD_MEM_DCACHE_ENABLE +bool dcd_dcache_clean(const void *addr, uint32_t data_size) { TU_VERIFY(addr && data_size); return samx7x_dcache_clean(addr, data_size); } -bool dcd_dcache_invalidate(const void* addr, uint32_t data_size) { +bool dcd_dcache_invalidate(const void *addr, uint32_t data_size) { TU_VERIFY(addr && data_size); return samx7x_dcache_invalidate(addr, data_size); } -bool dcd_dcache_clean_invalidate(const void* addr, uint32_t data_size) { +bool dcd_dcache_clean_invalidate(const void *addr, uint32_t data_size) { TU_VERIFY(addr && data_size); return samx7x_dcache_clean_invalidate(addr, data_size); } -#endif + #endif //------------------------------------------------------------------ // Device API //------------------------------------------------------------------ // Initialize controller to device mode -bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { - (void) rh_init; +bool dcd_init(uint8_t rhport, const tusb_rhport_init_t *rh_init) { + (void)rh_init; dcd_connect(rhport); return true; } // Enable device interrupt -void dcd_int_enable (uint8_t rhport) -{ - (void) rhport; - NVIC_EnableIRQ((IRQn_Type) ID_USBHS); +void dcd_int_enable(uint8_t rhport) { + (void)rhport; + NVIC_EnableIRQ((IRQn_Type)ID_USBHS); } // Disable device interrupt -void dcd_int_disable (uint8_t rhport) -{ - (void) rhport; - NVIC_DisableIRQ((IRQn_Type) ID_USBHS); +void dcd_int_disable(uint8_t rhport) { + (void)rhport; + NVIC_DisableIRQ((IRQn_Type)ID_USBHS); } // Receive Set Address request, mcu port must also include status IN response -void dcd_set_address (uint8_t rhport, uint8_t dev_addr) -{ - (void) dev_addr; +void dcd_set_address(uint8_t rhport, uint8_t dev_addr) { + (void)dev_addr; // DCD can only set address after status for this request is complete // do it at dcd_edpt0_status_complete() @@ -137,30 +128,26 @@ void dcd_set_address (uint8_t rhport, uint8_t dev_addr) } // Wake up host -void dcd_remote_wakeup (uint8_t rhport) -{ - (void) rhport; +void dcd_remote_wakeup(uint8_t rhport) { + (void)rhport; USB_REG->DEVCTRL |= DEVCTRL_RMWKUP; } // Connect by enabling internal pull-up resistor on D+/D- -void dcd_connect(uint8_t rhport) -{ - (void) rhport; +void dcd_connect(uint8_t rhport) { + (void)rhport; dcd_int_disable(rhport); // Enable the USB controller in device mode USB_REG->CTRL = CTRL_UIMOD | CTRL_USBE; - while (!(USB_REG->SR & SR_CLKUSABLE)); -#if TUD_OPT_HIGH_SPEED + while (!(USB_REG->SR & SR_CLKUSABLE)) + ; + #if TUD_OPT_HIGH_SPEED USB_REG->DEVCTRL &= ~DEVCTRL_SPDCONF; -#else + #else USB_REG->DEVCTRL |= DEVCTRL_SPDCONF_LOW_POWER; -#endif + #endif // Enable the End Of Reset, Suspend & Wakeup interrupts USB_REG->DEVIER = (DEVIER_EORSTES | DEVIER_SUSPES | DEVIER_WAKEUPES); -#if USE_SOF - USB_REG->DEVIER = DEVIER_SOFES; -#endif // Clear the End Of Reset, SOF & Wakeup interrupts USB_REG->DEVICR = (DEVICR_EORSTC | DEVICR_SOFC | DEVICR_WAKEUPC); // Manually set the Suspend Interrupt @@ -174,15 +161,15 @@ void dcd_connect(uint8_t rhport) } // Disconnect by disabling internal pull-up resistor on D+/D- -void dcd_disconnect(uint8_t rhport) -{ - (void) rhport; +void dcd_disconnect(uint8_t rhport) { + (void)rhport; dcd_int_disable(rhport); // Disable all endpoints USB_REG->DEVEPT &= ~(0x3FF << DEVEPT_EPEN0_Pos); // Unfreeze USB clock USB_REG->CTRL &= ~CTRL_FRZCLK; - while (!(USB_REG->SR & SR_CLKUSABLE)); + while (!(USB_REG->SR & SR_CLKUSABLE)) + ; // Clear all the pending interrupts USB_REG->DEVICR = DEVICR_Msk; // Disable all interrupts @@ -190,124 +177,103 @@ void dcd_disconnect(uint8_t rhport) // Detach the device USB_REG->DEVCTRL |= DEVCTRL_DETACH; // Disable the device address - USB_REG->DEVCTRL &=~(DEVCTRL_ADDEN | DEVCTRL_UADD); + USB_REG->DEVCTRL &= ~(DEVCTRL_ADDEN | DEVCTRL_UADD); } -void dcd_sof_enable(uint8_t rhport, bool en) -{ - (void) rhport; - (void) en; - - // TODO implement later +void dcd_sof_enable(uint8_t rhport, bool en) { + (void)rhport; + if (en) { + USB_REG->DEVIER = DEVIER_SOFES; + } else { + USB_REG->DEVIDR = DEVIDR_SOFEC; + } } -static tusb_speed_t get_speed(void) -{ +static tusb_speed_t get_speed(void) { switch (USB_REG->SR & SR_SPEED) { - case SR_SPEED_FULL_SPEED: - default: - return TUSB_SPEED_FULL; - case SR_SPEED_HIGH_SPEED: - return TUSB_SPEED_HIGH; - case SR_SPEED_LOW_SPEED: - return TUSB_SPEED_LOW; + case SR_SPEED_FULL_SPEED: + default: + return TUSB_SPEED_FULL; + case SR_SPEED_HIGH_SPEED: + return TUSB_SPEED_HIGH; + case SR_SPEED_LOW_SPEED: + return TUSB_SPEED_LOW; } } -static void dcd_ep_handler(uint8_t ep_ix) -{ +static void dcd_ep_handler(uint8_t ep_ix) { uint32_t int_status = USB_REG->DEVEPTISR[ep_ix]; int_status &= USB_REG->DEVEPTIMR[ep_ix]; - uint16_t count = (USB_REG->DEVEPTISR[ep_ix] & - DEVEPTISR_BYCT) >> DEVEPTISR_BYCT_Pos; - xfer_ctl_t *xfer = &xfer_status[ep_ix]; + uint16_t count = (USB_REG->DEVEPTISR[ep_ix] & DEVEPTISR_BYCT) >> DEVEPTISR_BYCT_Pos; + xfer_ctl_t *xfer = &xfer_status[ep_ix]; - if (ep_ix == 0U) - { + if (ep_ix == 0U) { static uint8_t ctrl_dir; - if (int_status & DEVEPTISR_CTRL_RXSTPI) - { + if (int_status & DEVEPTISR_CTRL_RXSTPI) { ctrl_dir = (USB_REG->DEVEPTISR[0] & DEVEPTISR_CTRL_CTRLDIR) >> DEVEPTISR_CTRL_CTRLDIR_Pos; // Setup packet should always be 8 bytes. If not, ignore it, and try again. - if (count == 8) - { - uint8_t *ptr = EP_GET_FIFO_PTR(0,8); + if (count == 8) { + uint8_t *ptr = EP_GET_FIFO_PTR(0, 8); dcd_event_setup_received(0, ptr, true); } // Ack and disable SETUP interrupt USB_REG->DEVEPTICR[0] = DEVEPTICR_CTRL_RXSTPIC; USB_REG->DEVEPTIDR[0] = DEVEPTIDR_CTRL_RXSTPEC; } - if (int_status & DEVEPTISR_RXOUTI) - { - uint8_t *ptr = EP_GET_FIFO_PTR(0,8); + if (int_status & DEVEPTISR_RXOUTI) { + uint8_t *ptr = EP_GET_FIFO_PTR(0, 8); - if (count && xfer->total_len) - { + if (count && xfer->total_len) { uint16_t remain = xfer->total_len - xfer->queued_len; - if (count > remain) - { + if (count > remain) { count = remain; } - if (xfer->buffer) - { + if (xfer->buffer) { memcpy(xfer->buffer + xfer->queued_len, ptr, count); - } else - { + } else { tu_hwfifo_read_to_fifo(ptr, xfer->fifo, count, NULL); } xfer->queued_len = (uint16_t)(xfer->queued_len + count); } // Acknowledge the interrupt USB_REG->DEVEPTICR[0] = DEVEPTICR_RXOUTIC; - if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) - { + if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) { // RX COMPLETE dcd_event_xfer_complete(0, 0, xfer->queued_len, XFER_RESULT_SUCCESS, true); // Disable the interrupt USB_REG->DEVEPTIDR[0] = DEVEPTIDR_RXOUTEC; // Re-enable SETUP interrupt - if (ctrl_dir == 1) - { + if (ctrl_dir == 1) { USB_REG->DEVEPTIER[0] = DEVEPTIER_CTRL_RXSTPES; } } } - if (int_status & DEVEPTISR_TXINI) - { + if (int_status & DEVEPTISR_TXINI) { // Disable the interrupt USB_REG->DEVEPTIDR[0] = DEVEPTIDR_TXINEC; - if ((xfer->total_len != xfer->queued_len)) - { + if ((xfer->total_len != xfer->queued_len)) { // TX not complete dcd_transmit_packet(xfer, 0); - } else - { + } else { // TX complete dcd_event_xfer_complete(0, 0x80 + 0, xfer->total_len, XFER_RESULT_SUCCESS, true); // Re-enable SETUP interrupt - if (ctrl_dir == 0) - { + if (ctrl_dir == 0) { USB_REG->DEVEPTIER[0] = DEVEPTIER_CTRL_RXSTPES; } } } - } else - { - if (int_status & DEVEPTISR_RXOUTI) - { - if (count && xfer->total_len) - { + } else { + if (int_status & DEVEPTISR_RXOUTI) { + if (count && xfer->total_len) { uint16_t remain = xfer->total_len - xfer->queued_len; - if (count > remain) - { + if (count > remain) { count = remain; } - uint8_t *ptr = EP_GET_FIFO_PTR(ep_ix,8); - if (xfer->buffer) - { + uint8_t *ptr = EP_GET_FIFO_PTR(ep_ix, 8); + if (xfer->buffer) { memcpy(xfer->buffer + xfer->queued_len, ptr, count); } else { tu_hwfifo_read_to_fifo(ptr, xfer->fifo, count, NULL); @@ -318,8 +284,7 @@ static void dcd_ep_handler(uint8_t ep_ix) USB_REG->DEVEPTIDR[ep_ix] = DEVEPTIDR_FIFOCONC; // Acknowledge the interrupt USB_REG->DEVEPTICR[ep_ix] = DEVEPTICR_RXOUTIC; - if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) - { + if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) { // RX COMPLETE dcd_event_xfer_complete(0, ep_ix, xfer->queued_len, XFER_RESULT_SUCCESS, true); // Disable the interrupt @@ -327,16 +292,13 @@ static void dcd_ep_handler(uint8_t ep_ix) // Though the host could still send, we don't know. } } - if (int_status & DEVEPTISR_TXINI) - { + if (int_status & DEVEPTISR_TXINI) { // Acknowledge the interrupt USB_REG->DEVEPTICR[ep_ix] = DEVEPTICR_TXINIC; - if ((xfer->total_len != xfer->queued_len)) - { + if ((xfer->total_len != xfer->queued_len)) { // TX not complete dcd_transmit_packet(xfer, ep_ix); - } else - { + } else { // TX complete dcd_event_xfer_complete(0, 0x80 + ep_ix, xfer->total_len, XFER_RESULT_SUCCESS, true); // Disable the interrupt @@ -346,46 +308,40 @@ static void dcd_ep_handler(uint8_t ep_ix) } } -static void dcd_dma_handler(uint8_t ep_ix) -{ +static void dcd_dma_handler(uint8_t ep_ix) { uint32_t status = USB_REG->DEVDMA[ep_ix - 1].DEVDMASTATUS; - if (status & DEVDMASTATUS_CHANN_ENB) - { + if (status & DEVDMASTATUS_CHANN_ENB) { return; // Ignore EOT_STA interrupt } // Disable DMA interrupt USB_REG->DEVIDR = DEVIDR_DMA_1 << (ep_ix - 1); - xfer_ctl_t *xfer = &xfer_status[ep_ix]; - uint16_t count = xfer->total_len - ((status & DEVDMASTATUS_BUFF_COUNT) >> DEVDMASTATUS_BUFF_COUNT_Pos); - if(USB_REG->DEVEPTCFG[ep_ix] & DEVEPTCFG_EPDIR) - { + xfer_ctl_t *xfer = &xfer_status[ep_ix]; + uint16_t count = xfer->total_len - ((status & DEVDMASTATUS_BUFF_COUNT) >> DEVDMASTATUS_BUFF_COUNT_Pos); + if (USB_REG->DEVEPTCFG[ep_ix] & DEVEPTCFG_EPDIR) { dcd_event_xfer_complete(0, 0x80 + ep_ix, count, XFER_RESULT_SUCCESS, true); - } else - { + } else { dcd_dcache_invalidate(xfer->buffer, xfer->total_len); dcd_event_xfer_complete(0, ep_ix, count, XFER_RESULT_SUCCESS, true); } } -void dcd_int_handler(uint8_t rhport) -{ - (void) rhport; +void dcd_int_handler(uint8_t rhport) { + (void)rhport; uint32_t int_status = USB_REG->DEVISR; int_status &= USB_REG->DEVIMR; // End of reset interrupt - if (int_status & DEVISR_EORST) - { + if (int_status & DEVISR_EORST) { // Unfreeze USB clock USB_REG->CTRL &= ~CTRL_FRZCLK; - while(!(USB_REG->SR & SR_CLKUSABLE)); + while (!(USB_REG->SR & SR_CLKUSABLE)) + ; // Reset all endpoints - for (int ep_ix = 1; ep_ix < EP_MAX; ep_ix++) - { + for (int ep_ix = 1; ep_ix < EP_MAX; ep_ix++) { USB_REG->DEVEPT |= 1 << (DEVEPT_EPRST0_Pos + ep_ix); - USB_REG->DEVEPT &=~(1 << (DEVEPT_EPRST0_Pos + ep_ix)); + USB_REG->DEVEPT &= ~(1 << (DEVEPT_EPRST0_Pos + ep_ix)); } - dcd_edpt_open (0, &ep0_desc); + dcd_edpt_open(0, &ep0_desc); USB_REG->DEVICR = DEVICR_EORSTC; USB_REG->DEVICR = DEVICR_WAKEUPC; USB_REG->DEVICR = DEVICR_SUSPC; @@ -394,10 +350,10 @@ void dcd_int_handler(uint8_t rhport) dcd_event_bus_reset(rhport, get_speed(), true); } // End of Wakeup interrupt - if (int_status & DEVISR_WAKEUP) - { + if (int_status & DEVISR_WAKEUP) { USB_REG->CTRL &= ~CTRL_FRZCLK; - while (!(USB_REG->SR & SR_CLKUSABLE)); + while (!(USB_REG->SR & SR_CLKUSABLE)) + ; USB_REG->DEVICR = DEVICR_WAKEUPC; USB_REG->DEVIDR = DEVIDR_WAKEUPEC; USB_REG->DEVIER = DEVIER_SUSPES; @@ -405,11 +361,11 @@ void dcd_int_handler(uint8_t rhport) dcd_event_bus_signal(0, DCD_EVENT_RESUME, true); } // Suspend interrupt - if (int_status & DEVISR_SUSP) - { + if (int_status & DEVISR_SUSP) { // Unfreeze USB clock USB_REG->CTRL &= ~CTRL_FRZCLK; - while (!(USB_REG->SR & SR_CLKUSABLE)); + while (!(USB_REG->SR & SR_CLKUSABLE)) + ; USB_REG->DEVICR = DEVICR_SUSPC; USB_REG->DEVIDR = DEVIDR_SUSPEC; USB_REG->DEVIER = DEVIER_WAKEUPES; @@ -417,29 +373,21 @@ void dcd_int_handler(uint8_t rhport) dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true); } -#if USE_SOF - if(int_status & DEVISR_SOF) - { + if (int_status & DEVISR_SOF) { USB_REG->DEVICR = DEVICR_SOFC; dcd_event_bus_signal(0, DCD_EVENT_SOF, true); } -#endif // Endpoints interrupt - for (int ep_ix = 0; ep_ix < EP_MAX; ep_ix++) - { - if (int_status & (DEVISR_PEP_0 << ep_ix)) - { + for (int ep_ix = 0; ep_ix < EP_MAX; ep_ix++) { + if (int_status & (DEVISR_PEP_0 << ep_ix)) { dcd_ep_handler(ep_ix); } } // Endpoints DMA interrupt - for (int ep_ix = 0; ep_ix < EP_MAX; ep_ix++) - { - if (EP_DMA_SUPPORT(ep_ix)) - { - if (int_status & (DEVISR_DMA_1 << (ep_ix - 1))) - { + for (int ep_ix = 0; ep_ix < EP_MAX; ep_ix++) { + if (EP_DMA_SUPPORT(ep_ix)) { + if (int_status & (DEVISR_DMA_1 << (ep_ix - 1))) { dcd_dma_handler(ep_ix); } } @@ -451,35 +399,29 @@ void dcd_int_handler(uint8_t rhport) //--------------------------------------------------------------------+ // Invoked when a control transfer's status stage is complete. // May help DCD to prepare for next control transfer, this API is optional. -void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * request) -{ - (void) rhport; +void dcd_edpt0_status_complete(uint8_t rhport, const tusb_control_request_t *request) { + (void)rhport; if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE && - request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && - request->bRequest == TUSB_REQ_SET_ADDRESS ) - { - uint8_t const dev_addr = (uint8_t) request->wValue; + request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && request->bRequest == TUSB_REQ_SET_ADDRESS) { + const uint8_t dev_addr = (uint8_t)request->wValue; USB_REG->DEVCTRL |= dev_addr | DEVCTRL_ADDEN; } } // Configure endpoint's registers according to descriptor -bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) -{ - (void) rhport; - uint8_t const epnum = tu_edpt_number(ep_desc->bEndpointAddress); - uint8_t const dir = tu_edpt_dir(ep_desc->bEndpointAddress); - uint16_t const epMaxPktSize = tu_edpt_packet_size(ep_desc); - tusb_xfer_type_t const eptype = (tusb_xfer_type_t)ep_desc->bmAttributes.xfer; - uint8_t fifoSize = 0; // FIFO size - uint16_t defaultEndpointSize = 8; // Default size of Endpoint +bool dcd_edpt_open(uint8_t rhport, const tusb_desc_endpoint_t *ep_desc) { + (void)rhport; + const uint8_t epnum = tu_edpt_number(ep_desc->bEndpointAddress); + const uint8_t dir = tu_edpt_dir(ep_desc->bEndpointAddress); + const uint16_t epMaxPktSize = tu_edpt_packet_size(ep_desc); + const tusb_xfer_type_t eptype = (tusb_xfer_type_t)ep_desc->bmAttributes.xfer; + uint8_t fifoSize = 0; // FIFO size + uint16_t defaultEndpointSize = 8; // Default size of Endpoint // Find upper 2 power number of epMaxPktSize - if (epMaxPktSize) - { - while (defaultEndpointSize < epMaxPktSize) - { + if (epMaxPktSize) { + while (defaultEndpointSize < epMaxPktSize) { fifoSize++; defaultEndpointSize <<= 1; } @@ -487,121 +429,94 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) xfer_status[epnum].max_packet_size = epMaxPktSize; USB_REG->DEVEPT |= 1 << (DEVEPT_EPRST0_Pos + epnum); - USB_REG->DEVEPT &=~(1 << (DEVEPT_EPRST0_Pos + epnum)); + USB_REG->DEVEPT &= ~(1 << (DEVEPT_EPRST0_Pos + epnum)); - if (epnum == 0) - { + if (epnum == 0) { // Enable the control endpoint - Endpoint 0 USB_REG->DEVEPT |= DEVEPT_EPEN0; // Configure the Endpoint 0 configuration register - USB_REG->DEVEPTCFG[0] = - ( - (fifoSize << DEVEPTCFG_EPSIZE_Pos) | - (TUSB_XFER_CONTROL << DEVEPTCFG_EPTYPE_Pos) | - (DEVEPTCFG_EPBK_1_BANK << DEVEPTCFG_EPBK_Pos) | - DEVEPTCFG_ALLOC - ); + USB_REG->DEVEPTCFG[0] = ((fifoSize << DEVEPTCFG_EPSIZE_Pos) | (TUSB_XFER_CONTROL << DEVEPTCFG_EPTYPE_Pos) | + (DEVEPTCFG_EPBK_1_BANK << DEVEPTCFG_EPBK_Pos) | DEVEPTCFG_ALLOC); USB_REG->DEVEPTIER[0] = DEVEPTIER_RSTDTS; USB_REG->DEVEPTIDR[0] = DEVEPTIDR_CTRL_STALLRQC; - if (DEVEPTISR_CFGOK == (USB_REG->DEVEPTISR[0] & DEVEPTISR_CFGOK)) - { + if (DEVEPTISR_CFGOK == (USB_REG->DEVEPTISR[0] & DEVEPTISR_CFGOK)) { // Endpoint configuration is successful USB_REG->DEVEPTIER[0] = DEVEPTIER_CTRL_RXSTPES; // Enable Endpoint 0 Interrupts USB_REG->DEVIER = DEVIER_PEP_0; return true; - } else - { + } else { // Endpoint configuration is not successful return false; } - } else - { + } else { // Enable the endpoint USB_REG->DEVEPT |= ((0x01 << epnum) << DEVEPT_EPEN0_Pos); // Set up the maxpacket size, fifo start address fifosize // and enable the interrupt. CLear the data toggle. // AUTOSW is needed for DMA ack ! USB_REG->DEVEPTCFG[epnum] = - ( - (fifoSize << DEVEPTCFG_EPSIZE_Pos) | - (eptype << DEVEPTCFG_EPTYPE_Pos) | - (DEVEPTCFG_EPBK_1_BANK << DEVEPTCFG_EPBK_Pos) | - DEVEPTCFG_AUTOSW | - ((dir & 0x01) << DEVEPTCFG_EPDIR_Pos) - ); - if (eptype == TUSB_XFER_ISOCHRONOUS) - { + ((fifoSize << DEVEPTCFG_EPSIZE_Pos) | (eptype << DEVEPTCFG_EPTYPE_Pos) | + (DEVEPTCFG_EPBK_1_BANK << DEVEPTCFG_EPBK_Pos) | DEVEPTCFG_AUTOSW | ((dir & 0x01) << DEVEPTCFG_EPDIR_Pos)); + if (eptype == TUSB_XFER_ISOCHRONOUS) { USB_REG->DEVEPTCFG[epnum] |= DEVEPTCFG_NBTRANS_1_TRANS; } -#if USE_DUAL_BANK - if (eptype == TUSB_XFER_ISOCHRONOUS || eptype == TUSB_XFER_BULK) - { + #if USE_DUAL_BANK + if (eptype == TUSB_XFER_ISOCHRONOUS || eptype == TUSB_XFER_BULK) { USB_REG->DEVEPTCFG[epnum] |= DEVEPTCFG_EPBK_2_BANK; } -#endif + #endif USB_REG->DEVEPTCFG[epnum] |= DEVEPTCFG_ALLOC; USB_REG->DEVEPTIER[epnum] = DEVEPTIER_RSTDTS; USB_REG->DEVEPTIDR[epnum] = DEVEPTIDR_CTRL_STALLRQC; - if (DEVEPTISR_CFGOK == (USB_REG->DEVEPTISR[epnum] & DEVEPTISR_CFGOK)) - { + if (DEVEPTISR_CFGOK == (USB_REG->DEVEPTISR[epnum] & DEVEPTISR_CFGOK)) { USB_REG->DEVIER = ((0x01 << epnum) << DEVIER_PEP_0_Pos); return true; - } else - { + } else { // Endpoint configuration is not successful return false; } } } -void dcd_edpt_close_all (uint8_t rhport) -{ - (void) rhport; +void dcd_edpt_close_all(uint8_t rhport) { + (void)rhport; // TODO implement dcd_edpt_close_all() } bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { - (void) rhport; - (void) ep_addr; - (void) largest_packet_size; + (void)rhport; + (void)ep_addr; + (void)largest_packet_size; return false; } -bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep) { - (void) rhport; - (void) desc_ep; +bool dcd_edpt_iso_activate(uint8_t rhport, const tusb_desc_endpoint_t *desc_ep) { + (void)rhport; + (void)desc_ep; return false; } -static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix) -{ +static void dcd_transmit_packet(xfer_ctl_t *xfer, uint8_t ep_ix) { uint16_t len = (uint16_t)(xfer->total_len - xfer->queued_len); - if (len) - { - if (len > xfer->max_packet_size) - { + if (len) { + if (len > xfer->max_packet_size) { len = xfer->max_packet_size; } - uint8_t *ptr = EP_GET_FIFO_PTR(ep_ix,8); - if(xfer->buffer) - { + uint8_t *ptr = EP_GET_FIFO_PTR(ep_ix, 8); + if (xfer->buffer) { memcpy(ptr, xfer->buffer + xfer->queued_len, len); - } - else - { + } else { tu_hwfifo_write_from_fifo(ptr, xfer->fifo, len, NULL); } __DSB(); __ISB(); xfer->queued_len = (uint16_t)(xfer->queued_len + len); } - if (ep_ix == 0U) - { + if (ep_ix == 0U) { // Control endpoint: clear the interrupt flag to send the data USB_REG->DEVEPTICR[0] = DEVEPTICR_TXINIC; - } else - { + } else { // Other endpoint types: clear the FIFO control flag to send the data USB_REG->DEVEPTIDR[ep_ix] = DEVEPTIDR_FIFOCONC; } @@ -609,25 +524,22 @@ static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix) } // Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) -{ - (void) is_isr; - (void) rhport; - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes, bool is_isr) { + (void)is_isr; + (void)rhport; + const uint8_t epnum = tu_edpt_number(ep_addr); + const uint8_t dir = tu_edpt_dir(ep_addr); - xfer_ctl_t * xfer = &xfer_status[epnum]; + xfer_ctl_t *xfer = &xfer_status[epnum]; - xfer->buffer = buffer; - xfer->total_len = total_bytes; + xfer->buffer = buffer; + xfer->total_len = total_bytes; xfer->queued_len = 0; - xfer->fifo = NULL; + xfer->fifo = NULL; - if (EP_DMA_SUPPORT(epnum) && total_bytes != 0) - { + if (EP_DMA_SUPPORT(epnum) && total_bytes != 0) { uint32_t udd_dma_ctrl = total_bytes << DEVDMACONTROL_BUFF_LENGTH_Pos; - if (dir == TUSB_DIR_OUT) - { + if (dir == TUSB_DIR_OUT) { udd_dma_ctrl |= DEVDMACONTROL_END_TR_IT | DEVDMACONTROL_END_TR_EN; } else { udd_dma_ctrl |= DEVDMACONTROL_END_B_EN; @@ -636,15 +548,12 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t t USB_REG->DEVDMA[epnum - 1].DEVDMAADDRESS = (uint32_t)buffer; udd_dma_ctrl |= DEVDMACONTROL_END_BUFFIT | DEVDMACONTROL_CHANN_ENB; USB_REG->DEVDMA[epnum - 1].DEVDMACONTROL = udd_dma_ctrl; - USB_REG->DEVIER = DEVIER_DMA_1 << (epnum - 1); - } else - { - if (dir == TUSB_DIR_OUT) - { + USB_REG->DEVIER = DEVIER_DMA_1 << (epnum - 1); + } else { + if (dir == TUSB_DIR_OUT) { USB_REG->DEVEPTIER[epnum] = DEVEPTIER_RXOUTES; - } else - { - dcd_transmit_packet(xfer,epnum); + } else { + dcd_transmit_packet(xfer, epnum); } } return true; @@ -654,50 +563,45 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t t // bytes should be written and second to keep the return value free to give back a boolean // success message. If total_bytes is too big, the FIFO will copy only what is available // into the USB buffer! -bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes, bool is_isr) -{ - (void) is_isr; - (void) rhport; - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - xfer_ctl_t * xfer = &xfer_status[epnum]; - if(epnum == 0x80) +bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t *ff, uint16_t total_bytes, bool is_isr) { + (void)is_isr; + (void)rhport; + const uint8_t epnum = tu_edpt_number(ep_addr); + const uint8_t dir = tu_edpt_dir(ep_addr); + + xfer_ctl_t *xfer = &xfer_status[epnum]; + if (epnum == 0x80) { xfer = &xfer_status[EP_MAX]; + } - xfer->buffer = NULL; - xfer->total_len = total_bytes; + xfer->buffer = NULL; + xfer->total_len = total_bytes; xfer->queued_len = 0; - xfer->fifo = ff; + xfer->fifo = ff; - if (dir == TUSB_DIR_OUT) - { + if (dir == TUSB_DIR_OUT) { USB_REG->DEVEPTIER[epnum] = DEVEPTIER_RXOUTES; - } else - { - dcd_transmit_packet(xfer,epnum); + } else { + dcd_transmit_packet(xfer, epnum); } return true; } // Stall endpoint -void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) -{ - (void) rhport; - uint8_t const epnum = tu_edpt_number(ep_addr); +void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { + (void)rhport; + const uint8_t epnum = tu_edpt_number(ep_addr); USB_REG->DEVEPTIER[epnum] = DEVEPTIER_CTRL_STALLRQS; // Re-enable SETUP interrupt - if (epnum == 0) - { + if (epnum == 0) { USB_REG->DEVEPTIER[0] = DEVEPTIER_CTRL_RXSTPES; } } // clear stall, data toggle is also reset to DATA0 -void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) -{ - (void) rhport; - uint8_t const epnum = tu_edpt_number(ep_addr); +void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { + (void)rhport; + const uint8_t epnum = tu_edpt_number(ep_addr); USB_REG->DEVEPTIDR[epnum] = DEVEPTIDR_CTRL_STALLRQC; USB_REG->DEVEPTIER[epnum] = HSTPIPIER_RSTDTS; } -- cgit v1.3.1 From 22acfb62672b4eae27f8d6db49ac205a38c18f9e Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 27 Feb 2026 11:53:02 +0100 Subject: cleanup Signed-off-by: HiFiPhile --- src/portable/synopsys/dwc2/hcd_dwc2.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'src/portable') diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index 1bdab6a45..420b3fe4b 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -416,11 +416,6 @@ 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) {} #ifdef TUP_USBIP_DWC2_STM32 -- cgit v1.3.1 From 8444c25ab6bc841bad81fd04afc1e66a9d57a115 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 27 Feb 2026 23:51:36 +0700 Subject: replace board_millis() with tusb_time_millis_api() --- examples/device/audio_4_channel_mic/src/main.c | 4 +-- examples/device/audio_test/src/main.c | 4 +-- examples/device/audio_test_multi_rate/src/main.c | 4 +-- examples/device/board_test/src/main.c | 4 +-- examples/device/cdc_dual_ports/src/main.c | 2 +- examples/device/cdc_msc/src/main.c | 2 +- examples/device/cdc_uac2/src/uac2_app.c | 4 +-- examples/device/dfu/src/main.c | 2 +- examples/device/dfu_runtime/src/main.c | 2 +- examples/device/dynamic_configuration/src/main.c | 4 +-- examples/device/hid_boot_interface/src/main.c | 4 +-- examples/device/hid_composite/src/main.c | 4 +-- examples/device/hid_generic_inout/src/main.c | 2 +- examples/device/hid_multiple_interface/src/main.c | 4 +-- examples/device/midi_test/src/main.c | 4 +-- examples/device/msc_dual_lun/src/main.c | 2 +- examples/device/mtp/src/main.c | 2 +- examples/device/net_lwip_webserver/src/main.c | 2 +- examples/device/uac2_headset/src/main.c | 6 ++-- examples/device/uac2_speaker_fb/src/main.c | 6 ++-- examples/device/usbtmc/src/main.c | 6 ++-- examples/device/usbtmc/src/usbtmc_app.c | 8 ++--- examples/device/video_capture/src/main.c | 6 ++-- examples/device/video_capture_2ch/src/main.c | 6 ++-- examples/device/webusb_serial/src/main.c | 2 +- examples/dual/host_hid_to_device_cdc/src/main.c | 2 +- examples/dual/host_info_to_device_cdc/src/main.c | 6 ++-- examples/host/bare_api/src/main.c | 2 +- examples/host/cdc_msc_hid/src/main.c | 2 +- examples/host/device_info/src/main.c | 2 +- examples/host/hid_controller/src/hid_app.c | 2 +- examples/host/hid_controller/src/main.c | 2 +- examples/host/midi_rx/src/main.c | 2 +- examples/host/msc_file_explorer/src/main.c | 2 +- examples/typec/power_delivery/src/main.c | 2 +- hw/bsp/at32f402_405/family.c | 2 +- hw/bsp/at32f403a_407/family.c | 2 +- hw/bsp/at32f413/family.c | 2 +- hw/bsp/at32f415/family.c | 2 +- hw/bsp/at32f423/family.c | 2 +- hw/bsp/at32f425/family.c | 2 +- hw/bsp/at32f435_437/family.c | 2 +- hw/bsp/at32f45x/family.c | 2 +- hw/bsp/board.c | 4 --- hw/bsp/board_api.h | 41 ++--------------------- hw/bsp/broadcom_32bit/family.c | 2 +- hw/bsp/broadcom_64bit/family.c | 2 +- hw/bsp/brtmm90x/family.c | 2 +- hw/bsp/ch32f20x/family.c | 2 +- hw/bsp/ch32v10x/family.c | 2 +- hw/bsp/ch32v20x/family.c | 2 +- hw/bsp/ch32v30x/family.c | 2 +- hw/bsp/cxd56/family.c | 2 +- hw/bsp/da1469x/family.c | 2 +- hw/bsp/efm32/family.c | 2 +- hw/bsp/f1c100s/family.c | 2 +- hw/bsp/fomu/family.c | 2 +- hw/bsp/gd32vf103/family.c | 2 +- hw/bsp/hpmicro/family.c | 2 +- hw/bsp/imxrt/family.c | 2 +- hw/bsp/kinetis_k/family.c | 2 +- hw/bsp/kinetis_k32l2/family.c | 2 +- hw/bsp/kinetis_kl/family.c | 2 +- hw/bsp/lpc11/family.c | 2 +- hw/bsp/lpc13/family.c | 2 +- hw/bsp/lpc15/family.c | 2 +- hw/bsp/lpc17/family.c | 2 +- hw/bsp/lpc18/family.c | 2 +- hw/bsp/lpc40/family.c | 2 +- hw/bsp/lpc43/family.c | 2 +- hw/bsp/lpc51/family.c | 2 +- hw/bsp/lpc54/family.c | 2 +- hw/bsp/lpc55/family.c | 2 +- hw/bsp/maxim/family.c | 2 +- hw/bsp/mcx/family.c | 2 +- hw/bsp/mm32/family.c | 2 +- hw/bsp/msp430/family.c | 10 +++--- hw/bsp/msp432e4/family.c | 2 +- hw/bsp/nrf/family.c | 2 +- hw/bsp/nuc100_120/family.c | 2 +- hw/bsp/nuc121_125/family.c | 2 +- hw/bsp/nuc126/family.c | 2 +- hw/bsp/nuc505/family.c | 2 +- hw/bsp/pic32mz/family.c | 2 +- hw/bsp/ra/family.c | 2 +- hw/bsp/rw61x/family.c | 2 +- hw/bsp/rx/boards/gr_citrus/gr_citrus.c | 2 +- hw/bsp/rx/boards/rx65n_target/rx65n_target.c | 2 +- hw/bsp/samd11/family.c | 2 +- hw/bsp/samd2x_l2x/family.c | 2 +- hw/bsp/samd5x_e5x/family.c | 2 +- hw/bsp/same7x/family.c | 2 +- hw/bsp/samg/family.c | 2 +- hw/bsp/stm32c0/family.c | 2 +- hw/bsp/stm32f0/family.c | 2 +- hw/bsp/stm32f1/family.c | 2 +- hw/bsp/stm32f2/family.c | 2 +- hw/bsp/stm32f3/family.c | 2 +- hw/bsp/stm32f4/family.c | 2 +- hw/bsp/stm32f7/family.c | 2 +- hw/bsp/stm32g0/family.c | 2 +- hw/bsp/stm32g4/family.c | 2 +- hw/bsp/stm32h5/family.c | 2 +- hw/bsp/stm32h7/family.c | 2 +- hw/bsp/stm32h7rs/family.c | 2 +- hw/bsp/stm32l0/family.c | 2 +- hw/bsp/stm32l4/family.c | 2 +- hw/bsp/stm32n6/family.c | 2 +- hw/bsp/stm32u0/family.c | 2 +- hw/bsp/stm32u5/family.c | 2 +- hw/bsp/stm32wb/family.c | 2 +- hw/bsp/stm32wba/family.c | 2 +- hw/bsp/tm4c/family.c | 2 +- hw/bsp/xmc4000/family.c | 2 +- src/common/tusb_common.h | 6 ++++ src/host/usbh.c | 2 +- src/portable/sunxi/dcd_sunxi_musb.c | 3 -- src/tusb.c | 13 ++++--- src/tusb.h | 10 ------ 119 files changed, 158 insertions(+), 203 deletions(-) (limited to 'src/portable') diff --git a/examples/device/audio_4_channel_mic/src/main.c b/examples/device/audio_4_channel_mic/src/main.c index 5767c7453..c9c6dd46c 100644 --- a/examples/device/audio_4_channel_mic/src/main.c +++ b/examples/device/audio_4_channel_mic/src/main.c @@ -155,7 +155,7 @@ void tud_resume_cb(void) { // 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(); + uint32_t curr_ms = tusb_time_millis_api(); if (start_ms == curr_ms) { return; // not enough time } @@ -408,7 +408,7 @@ void led_blinking_task(void) { static bool led_state = false; // Blink every interval ms - if (board_millis() - start_ms < blink_interval_ms) { + if (tusb_time_millis_api() - start_ms < blink_interval_ms) { return; // not enough time } start_ms += blink_interval_ms; diff --git a/examples/device/audio_test/src/main.c b/examples/device/audio_test/src/main.c index 2441eefbc..876a41d06 100644 --- a/examples/device/audio_test/src/main.c +++ b/examples/device/audio_test/src/main.c @@ -138,7 +138,7 @@ void tud_resume_cb(void) { // 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(); + uint32_t curr_ms = tusb_time_millis_api(); if (start_ms == curr_ms) { return; // not enough time } @@ -402,7 +402,7 @@ void led_blinking_task(void) { static bool led_state = false; // Blink every interval ms - if (board_millis() - start_ms < blink_interval_ms) { + if (tusb_time_millis_api() - start_ms < blink_interval_ms) { return; // not enough time } start_ms += blink_interval_ms; diff --git a/examples/device/audio_test_multi_rate/src/main.c b/examples/device/audio_test_multi_rate/src/main.c index baeec870f..952176997 100644 --- a/examples/device/audio_test_multi_rate/src/main.c +++ b/examples/device/audio_test_multi_rate/src/main.c @@ -146,7 +146,7 @@ void tud_resume_cb(void) { // 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(); + uint32_t curr_ms = tusb_time_millis_api(); if (start_ms == curr_ms) { return; // not enough time } @@ -614,7 +614,7 @@ void led_blinking_task(void) { static bool led_state = false; // Blink every interval ms - if (board_millis() - start_ms < blink_interval_ms) { + if (tusb_time_millis_api() - start_ms < blink_interval_ms) { return; // not enough time } start_ms += blink_interval_ms; diff --git a/examples/device/board_test/src/main.c b/examples/device/board_test/src/main.c index ee0829e5b..757876ac8 100644 --- a/examples/device/board_test/src/main.c +++ b/examples/device/board_test/src/main.c @@ -58,8 +58,8 @@ int main(void) { } // Blink and print every interval ms - if (!(board_millis() - start_ms < interval_ms)) { - start_ms = board_millis(); + if (!(tusb_time_millis_api() - start_ms < interval_ms)) { + start_ms = tusb_time_millis_api(); if (ch < 0) { // skip if echoing diff --git a/examples/device/cdc_dual_ports/src/main.c b/examples/device/cdc_dual_ports/src/main.c index 5ccb06a8a..6f918218d 100644 --- a/examples/device/cdc_dual_ports/src/main.c +++ b/examples/device/cdc_dual_ports/src/main.c @@ -157,7 +157,7 @@ void led_blinking_task(void) { static bool led_state = false; // Blink every interval ms - if (board_millis() - start_ms < blink_interval_ms) { + if (tusb_time_millis_api() - start_ms < blink_interval_ms) { return; // not enough time } start_ms += blink_interval_ms; diff --git a/examples/device/cdc_msc/src/main.c b/examples/device/cdc_msc/src/main.c index 06a4f732f..b00a0e3a9 100644 --- a/examples/device/cdc_msc/src/main.c +++ b/examples/device/cdc_msc/src/main.c @@ -160,7 +160,7 @@ void led_blinking_task(void) { if (blink_enable) { // Blink every interval ms - if (board_millis() - start_ms < blink_interval_ms) { + if (tusb_time_millis_api() - start_ms < blink_interval_ms) { return; // not enough time } start_ms += blink_interval_ms; diff --git a/examples/device/cdc_uac2/src/uac2_app.c b/examples/device/cdc_uac2/src/uac2_app.c index 73a262d0c..7760c402b 100644 --- a/examples/device/cdc_uac2/src/uac2_app.c +++ b/examples/device/cdc_uac2/src/uac2_app.c @@ -66,7 +66,7 @@ uint8_t current_resolution; // 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(); + uint32_t curr_ms = tusb_time_millis_api(); if (start_ms == curr_ms) { return; // not enough time } @@ -303,7 +303,7 @@ void led_blinking_task(void) static bool led_state = false; // Blink every interval ms - if (board_millis() - start_ms < blink_interval_ms) { + if (tusb_time_millis_api() - start_ms < blink_interval_ms) { return; } start_ms += blink_interval_ms; diff --git a/examples/device/dfu/src/main.c b/examples/device/dfu/src/main.c index 77632bf1a..fb3c22630 100644 --- a/examples/device/dfu/src/main.c +++ b/examples/device/dfu/src/main.c @@ -199,7 +199,7 @@ void led_blinking_task(void) { static bool led_state = false; // Blink every interval ms - if (board_millis() - start_ms < blink_interval_ms) { + if (tusb_time_millis_api() - start_ms < blink_interval_ms) { return; // not enough time } start_ms += blink_interval_ms; diff --git a/examples/device/dfu_runtime/src/main.c b/examples/device/dfu_runtime/src/main.c index 5de651bcd..6f412e8de 100644 --- a/examples/device/dfu_runtime/src/main.c +++ b/examples/device/dfu_runtime/src/main.c @@ -132,7 +132,7 @@ void led_blinking_task(void) static bool led_state = false; // Blink every interval ms - if (board_millis() - start_ms < blink_interval_ms) { + if (tusb_time_millis_api() - start_ms < blink_interval_ms) { return; // not enough time } start_ms += blink_interval_ms; diff --git a/examples/device/dynamic_configuration/src/main.c b/examples/device/dynamic_configuration/src/main.c index dac74bb7a..8ebb42f9a 100644 --- a/examples/device/dynamic_configuration/src/main.c +++ b/examples/device/dynamic_configuration/src/main.c @@ -170,7 +170,7 @@ void midi_task(void) { while( tud_midi_available() ) tud_midi_packet_read(packet); // send note every 1000 ms - if (board_millis() - start_ms < 286) { + if (tusb_time_millis_api() - start_ms < 286) { return; // not enough time } start_ms += 286; @@ -209,7 +209,7 @@ void led_blinking_task(void) { static bool led_state = false; // Blink every interval ms - if (board_millis() - start_ms < blink_interval_ms) { + if (tusb_time_millis_api() - start_ms < blink_interval_ms) { return;// not enough time } start_ms += blink_interval_ms; diff --git a/examples/device/hid_boot_interface/src/main.c b/examples/device/hid_boot_interface/src/main.c index 44a91db67..4de319f52 100644 --- a/examples/device/hid_boot_interface/src/main.c +++ b/examples/device/hid_boot_interface/src/main.c @@ -109,7 +109,7 @@ void hid_task(void) { const uint32_t interval_ms = 10; static uint32_t start_ms = 0; - if (board_millis() - start_ms < interval_ms) { + if (tusb_time_millis_api() - start_ms < interval_ms) { return; // not enough time } start_ms += interval_ms; @@ -238,7 +238,7 @@ void led_blinking_task(void) { } // Blink every interval ms - if (board_millis() - start_ms < blink_interval_ms) { + if (tusb_time_millis_api() - start_ms < blink_interval_ms) { return; // not enough time } start_ms += blink_interval_ms; diff --git a/examples/device/hid_composite/src/main.c b/examples/device/hid_composite/src/main.c index 9693d564d..7c9d5af8d 100644 --- a/examples/device/hid_composite/src/main.c +++ b/examples/device/hid_composite/src/main.c @@ -209,7 +209,7 @@ void hid_task(void) { const uint32_t interval_ms = 10; static uint32_t start_ms = 0; - if (board_millis() - start_ms < interval_ms) { + if (tusb_time_millis_api() - start_ms < interval_ms) { return; // not enough time } start_ms += interval_ms; @@ -298,7 +298,7 @@ void led_blinking_task(void) { } // Blink every interval ms - if (board_millis() - start_ms < blink_interval_ms) { + if (tusb_time_millis_api() - start_ms < blink_interval_ms) { return; // not enough time } start_ms += blink_interval_ms; diff --git a/examples/device/hid_generic_inout/src/main.c b/examples/device/hid_generic_inout/src/main.c index 9837a47d9..2a6b91a8a 100644 --- a/examples/device/hid_generic_inout/src/main.c +++ b/examples/device/hid_generic_inout/src/main.c @@ -168,7 +168,7 @@ 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 ( tusb_time_millis_api() - start_ms < blink_interval_ms) return; // not enough time start_ms += blink_interval_ms; board_led_write(led_state); diff --git a/examples/device/hid_multiple_interface/src/main.c b/examples/device/hid_multiple_interface/src/main.c index 0bccd13c1..c71a9cbad 100644 --- a/examples/device/hid_multiple_interface/src/main.c +++ b/examples/device/hid_multiple_interface/src/main.c @@ -120,7 +120,7 @@ void hid_task(void) const uint32_t interval_ms = 10; static uint32_t start_ms = 0; - if ( board_millis() - start_ms < interval_ms) return; // not enough time + if ( tusb_time_millis_api() - start_ms < interval_ms) return; // not enough time start_ms += interval_ms; uint32_t const btn = board_button_read(); @@ -205,7 +205,7 @@ 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 ( tusb_time_millis_api() - start_ms < blink_interval_ms) return; // not enough time start_ms += blink_interval_ms; board_led_write(led_state); diff --git a/examples/device/midi_test/src/main.c b/examples/device/midi_test/src/main.c index fd58e3021..1154c1d60 100644 --- a/examples/device/midi_test/src/main.c +++ b/examples/device/midi_test/src/main.c @@ -134,7 +134,7 @@ void midi_task(void) } // send note periodically - if (board_millis() - start_ms < 286) { + if (tusb_time_millis_api() - start_ms < 286) { return; // not enough time } start_ms += 286; @@ -174,7 +174,7 @@ 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 ( tusb_time_millis_api() - start_ms < blink_interval_ms) return; // not enough time start_ms += blink_interval_ms; board_led_write(led_state); diff --git a/examples/device/msc_dual_lun/src/main.c b/examples/device/msc_dual_lun/src/main.c index 62b1c872a..b459871f7 100644 --- a/examples/device/msc_dual_lun/src/main.c +++ b/examples/device/msc_dual_lun/src/main.c @@ -103,7 +103,7 @@ 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 (tusb_time_millis_api() - start_ms < blink_interval_ms) return; // not enough time start_ms += blink_interval_ms; board_led_write(led_state); diff --git a/examples/device/mtp/src/main.c b/examples/device/mtp/src/main.c index 57d1535b2..6ffa435d1 100644 --- a/examples/device/mtp/src/main.c +++ b/examples/device/mtp/src/main.c @@ -102,7 +102,7 @@ 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 (tusb_time_millis_api() - start_ms < blink_interval_ms) return; // not enough time start_ms += blink_interval_ms; board_led_write(led_state); diff --git a/examples/device/net_lwip_webserver/src/main.c b/examples/device/net_lwip_webserver/src/main.c index 867cf2812..9f26da2ba 100644 --- a/examples/device/net_lwip_webserver/src/main.c +++ b/examples/device/net_lwip_webserver/src/main.c @@ -291,5 +291,5 @@ void sys_arch_unprotect(sys_prot_t pval) { /* lwip needs a millisecond time source, and the TinyUSB board support code has one available */ uint32_t sys_now(void) { - return board_millis(); + return tusb_time_millis_api(); } diff --git a/examples/device/uac2_headset/src/main.c b/examples/device/uac2_headset/src/main.c index 96fa66f1e..0ea63d8f7 100644 --- a/examples/device/uac2_headset/src/main.c +++ b/examples/device/uac2_headset/src/main.c @@ -559,7 +559,7 @@ bool tud_audio_set_itf_cb(uint8_t rhport, tusb_control_request_t const *p_reques // 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(); + uint32_t curr_ms = tusb_time_millis_api(); 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 @@ -605,7 +605,7 @@ 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 (tusb_time_millis_api() - start_ms < interval_ms) return;// not enough time start_ms += interval_ms; uint32_t btn = board_button_read(); @@ -644,7 +644,7 @@ void led_blinking_task(void) { static bool led_state = false; // Blink every interval ms - if (board_millis() - start_ms < blink_interval_ms) return; + if (tusb_time_millis_api() - start_ms < blink_interval_ms) return; start_ms += blink_interval_ms; board_led_write(led_state); diff --git a/examples/device/uac2_speaker_fb/src/main.c b/examples/device/uac2_speaker_fb/src/main.c index 7b4e2d64c..8323d82e8 100644 --- a/examples/device/uac2_speaker_fb/src/main.c +++ b/examples/device/uac2_speaker_fb/src/main.c @@ -583,7 +583,7 @@ bool tud_audio_rx_done_isr(uint8_t rhport, uint16_t n_bytes_received, uint8_t fu // 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(); + uint32_t curr_ms = tusb_time_millis_api(); if (start_ms == curr_ms) return;// not enough time start_ms = curr_ms; @@ -610,7 +610,7 @@ void led_blinking_task(void) { static bool led_state = false; // Blink every interval ms - if (board_millis() - start_ms < blink_interval_ms) return; + if (tusb_time_millis_api() - start_ms < blink_interval_ms) return; start_ms += blink_interval_ms; board_led_write(led_state); @@ -624,7 +624,7 @@ void led_blinking_task(void) { // Every 1ms, we will sent 1 debug information report void audio_debug_task(void) { static uint32_t start_ms = 0; - uint32_t curr_ms = board_millis(); + uint32_t curr_ms = tusb_time_millis_api(); if (start_ms == curr_ms) return;// not enough time start_ms = curr_ms; diff --git a/examples/device/usbtmc/src/main.c b/examples/device/usbtmc/src/main.c index 5cbbb85ef..b1269b117 100644 --- a/examples/device/usbtmc/src/main.c +++ b/examples/device/usbtmc/src/main.c @@ -124,12 +124,12 @@ void led_blinking_task(void) { led_state = true; board_led_write(true); - start_ms = board_millis(); + start_ms = tusb_time_millis_api(); doPulse = false; } else if (led_state == true) { - if ( board_millis() - start_ms < 750) //Spec says blink must be between 500 and 1000 ms. + if ( tusb_time_millis_api() - start_ms < 750) //Spec says blink must be between 500 and 1000 ms. { return; // not enough time } @@ -140,7 +140,7 @@ void led_blinking_task(void) else { // Blink every interval ms - if ( board_millis() - start_ms < blink_interval_ms) return; // not enough time + if ( tusb_time_millis_api() - start_ms < blink_interval_ms) return; // not enough time start_ms += blink_interval_ms; board_led_write(led_state); diff --git a/examples/device/usbtmc/src/usbtmc_app.c b/examples/device/usbtmc/src/usbtmc_app.c index 4c3724ac4..35e8618f5 100644 --- a/examples/device/usbtmc/src/usbtmc_app.c +++ b/examples/device/usbtmc/src/usbtmc_app.c @@ -209,19 +209,19 @@ void usbtmc_app_task_iter(void) { case 0: break; case 1: - queryDelayStart = board_millis(); + queryDelayStart = tusb_time_millis_api(); queryState = 2; break; case 2: - if( (board_millis() - queryDelayStart) > resp_delay) { - queryDelayStart = board_millis(); + if( (tusb_time_millis_api() - queryDelayStart) > resp_delay) { + queryDelayStart = tusb_time_millis_api(); queryState=3; status |= 0x10u; // MAV status |= 0x40u; // SRQ } break; case 3: - if( (board_millis() - queryDelayStart) > resp_delay) { + if( (tusb_time_millis_api() - queryDelayStart) > resp_delay) { queryState = 4; } break; diff --git a/examples/device/video_capture/src/main.c b/examples/device/video_capture/src/main.c index ffa2a7afa..df9f77a1c 100644 --- a/examples/device/video_capture/src/main.c +++ b/examples/device/video_capture/src/main.c @@ -231,7 +231,7 @@ static void video_send_frame(void) { if (!already_sent) { already_sent = 1; tx_busy = 1; - start_ms = board_millis(); + start_ms = tusb_time_millis_api(); #if defined(CFG_EXAMPLE_VIDEO_BUFFERLESS) tud_video_n_frame_xfer(0, 0, NULL, FRAME_WIDTH * FRAME_HEIGHT * 16 / 8); #elif defined (CFG_EXAMPLE_VIDEO_READONLY) @@ -247,7 +247,7 @@ static void video_send_frame(void) { #endif } - unsigned cur = board_millis(); + unsigned cur = tusb_time_millis_api(); if (cur - start_ms < interval_ms) { return; // not enough time } @@ -316,7 +316,7 @@ void led_blinking_task(void* param) { #if CFG_TUSB_OS == OPT_OS_FREERTOS vTaskDelay(blink_interval_ms / portTICK_PERIOD_MS); #else - if (board_millis() - start_ms < blink_interval_ms) { + if (tusb_time_millis_api() - start_ms < blink_interval_ms) { return; // not enough time } #endif diff --git a/examples/device/video_capture_2ch/src/main.c b/examples/device/video_capture_2ch/src/main.c index 79b149f2b..debd336fd 100644 --- a/examples/device/video_capture_2ch/src/main.c +++ b/examples/device/video_capture_2ch/src/main.c @@ -221,13 +221,13 @@ static void video_send_frame(uint_fast8_t ctl_idx, uint_fast8_t stm_idx) { if (!(already_sent & (1u << idx))) { already_sent |= 1u << idx; tx_busy |= 1u << idx; - start_ms[idx] = board_millis(); + start_ms[idx] = tusb_time_millis_api(); fb_size = get_framebuf(ctl_idx, stm_idx, frame_num[idx], &fp); tud_video_n_frame_xfer(ctl_idx, stm_idx, fp, fb_size); } - unsigned cur = board_millis(); + unsigned cur = tusb_time_millis_api(); if (cur - start_ms[idx] < interval_ms[idx]) return; // not enough time if (tx_busy & (1u << idx)) return; start_ms[idx] += interval_ms[idx]; @@ -280,7 +280,7 @@ void led_blinking_task(void* param) { #if CFG_TUSB_OS == OPT_OS_FREERTOS vTaskDelay(blink_interval_ms / portTICK_PERIOD_MS); #else - if (board_millis() - start_ms < blink_interval_ms) return; // not enough time + if (tusb_time_millis_api() - start_ms < blink_interval_ms) return; // not enough time #endif start_ms += blink_interval_ms; diff --git a/examples/device/webusb_serial/src/main.c b/examples/device/webusb_serial/src/main.c index 155768b76..4be5e4db4 100644 --- a/examples/device/webusb_serial/src/main.c +++ b/examples/device/webusb_serial/src/main.c @@ -257,7 +257,7 @@ void led_blinking_task(void) { static bool led_state = false; // Blink every interval ms - if (board_millis() - start_ms < blink_interval_ms) { + if (tusb_time_millis_api() - start_ms < blink_interval_ms) { return; // not enough time } start_ms += blink_interval_ms; 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 8c53588c3..ba8ba019a 100644 --- a/examples/dual/host_hid_to_device_cdc/src/main.c +++ b/examples/dual/host_hid_to_device_cdc/src/main.c @@ -284,7 +284,7 @@ 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 (tusb_time_millis_api() - start_ms < blink_interval_ms) return; // not enough time start_ms += blink_interval_ms; board_led_write(led_state); 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 fffb54d58..7cf43aef3 100644 --- a/examples/dual/host_info_to_device_cdc/src/main.c +++ b/examples/dual/host_info_to_device_cdc/src/main.c @@ -213,13 +213,13 @@ void cdc_task(void) { static uint32_t connected_ms = 0; if (!tud_cdc_connected()) { - connected_ms = board_millis(); + connected_ms = tusb_time_millis_api(); return; } // 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 - if (board_millis() - connected_ms < 100) { + if (tusb_time_millis_api() - connected_ms < 100) { return; // wait for stable connection } @@ -309,7 +309,7 @@ void led_blinking_task(void) { static bool led_state = false; // Blink every interval ms - if (board_millis() - start_ms < blink_interval_ms) { + if (tusb_time_millis_api() - start_ms < blink_interval_ms) { return;// not enough time } start_ms += blink_interval_ms; diff --git a/examples/host/bare_api/src/main.c b/examples/host/bare_api/src/main.c index c693d6b00..ced2eaa32 100644 --- a/examples/host/bare_api/src/main.c +++ b/examples/host/bare_api/src/main.c @@ -335,7 +335,7 @@ void led_blinking_task(void) { static bool led_state = false; // Blink every interval ms - if (board_millis() - start_ms < interval_ms) { + if (tusb_time_millis_api() - start_ms < interval_ms) { return; // not enough time } start_ms += interval_ms; diff --git a/examples/host/cdc_msc_hid/src/main.c b/examples/host/cdc_msc_hid/src/main.c index c309a7cae..c27ad93fe 100644 --- a/examples/host/cdc_msc_hid/src/main.c +++ b/examples/host/cdc_msc_hid/src/main.c @@ -92,7 +92,7 @@ void led_blinking_task(void) { static bool led_state = false; // Blink every interval ms - if (board_millis() - start_ms < interval_ms) { + if (tusb_time_millis_api() - start_ms < interval_ms) { return;// not enough time } start_ms += interval_ms; diff --git a/examples/host/device_info/src/main.c b/examples/host/device_info/src/main.c index ab617e989..fd4e9c3ed 100644 --- a/examples/host/device_info/src/main.c +++ b/examples/host/device_info/src/main.c @@ -246,7 +246,7 @@ void led_blinking_task(void* param) { #if CFG_TUSB_OS == OPT_OS_FREERTOS vTaskDelay(blink_interval_ms / portTICK_PERIOD_MS); #else - if (board_millis() - start_ms < blink_interval_ms) { + if (tusb_time_millis_api() - start_ms < blink_interval_ms) { return; // not enough time } #endif diff --git a/examples/host/hid_controller/src/hid_app.c b/examples/host/hid_controller/src/hid_app.c index f8c3d029b..5417811f0 100644 --- a/examples/host/hid_controller/src/hid_app.c +++ b/examples/host/hid_controller/src/hid_app.c @@ -168,7 +168,7 @@ void hid_app_task(void) const uint32_t interval_ms = 200; static uint32_t start_ms = 0; - uint32_t current_time_ms = board_millis(); + uint32_t current_time_ms = tusb_time_millis_api(); if ( current_time_ms - start_ms >= interval_ms) { start_ms = current_time_ms; diff --git a/examples/host/hid_controller/src/main.c b/examples/host/hid_controller/src/main.c index fa70d7d1a..a9eebc90b 100644 --- a/examples/host/hid_controller/src/main.c +++ b/examples/host/hid_controller/src/main.c @@ -79,7 +79,7 @@ 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 ( tusb_time_millis_api() - start_ms < interval_ms) return; // not enough time start_ms += interval_ms; board_led_write(led_state); diff --git a/examples/host/midi_rx/src/main.c b/examples/host/midi_rx/src/main.c index 78b1a11b9..f189e0864 100644 --- a/examples/host/midi_rx/src/main.c +++ b/examples/host/midi_rx/src/main.c @@ -72,7 +72,7 @@ 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 (tusb_time_millis_api() - start_ms < interval_ms) return;// not enough time start_ms += interval_ms; board_led_write(led_state); diff --git a/examples/host/msc_file_explorer/src/main.c b/examples/host/msc_file_explorer/src/main.c index f9ec0ff5f..0a8967380 100644 --- a/examples/host/msc_file_explorer/src/main.c +++ b/examples/host/msc_file_explorer/src/main.c @@ -118,7 +118,7 @@ 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 (tusb_time_millis_api() - start_ms < interval_ms) return; // not enough time start_ms += interval_ms; board_led_write(led_state); diff --git a/examples/typec/power_delivery/src/main.c b/examples/typec/power_delivery/src/main.c index de0db4721..f6191bfe8 100644 --- a/examples/typec/power_delivery/src/main.c +++ b/examples/typec/power_delivery/src/main.c @@ -184,7 +184,7 @@ 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 ( tusb_time_millis_api() - start_ms < blink_interval_ms) return; // not enough time start_ms += blink_interval_ms; board_led_write(led_state); diff --git a/hw/bsp/at32f402_405/family.c b/hw/bsp/at32f402_405/family.c index a6c2217fe..b7dbcbd98 100644 --- a/hw/bsp/at32f402_405/family.c +++ b/hw/bsp/at32f402_405/family.c @@ -258,7 +258,7 @@ size_t board_get_unique_id(uint8_t id[], size_t max_len) { system_ticks++; } - uint32_t board_millis(void) + uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/at32f403a_407/family.c b/hw/bsp/at32f403a_407/family.c index dd9b85dc5..d4a7e446d 100644 --- a/hw/bsp/at32f403a_407/family.c +++ b/hw/bsp/at32f403a_407/family.c @@ -250,7 +250,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/at32f413/family.c b/hw/bsp/at32f413/family.c index bdaed523c..adf29e097 100644 --- a/hw/bsp/at32f413/family.c +++ b/hw/bsp/at32f413/family.c @@ -250,7 +250,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/at32f415/family.c b/hw/bsp/at32f415/family.c index 2fbd4c821..b592bf6c5 100644 --- a/hw/bsp/at32f415/family.c +++ b/hw/bsp/at32f415/family.c @@ -246,7 +246,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/at32f423/family.c b/hw/bsp/at32f423/family.c index f30c6a83f..71cb559dc 100644 --- a/hw/bsp/at32f423/family.c +++ b/hw/bsp/at32f423/family.c @@ -250,7 +250,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/at32f425/family.c b/hw/bsp/at32f425/family.c index 4ff4c8d6a..7f443509e 100644 --- a/hw/bsp/at32f425/family.c +++ b/hw/bsp/at32f425/family.c @@ -254,7 +254,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/at32f435_437/family.c b/hw/bsp/at32f435_437/family.c index 01dd429f8..6c6bc4d72 100644 --- a/hw/bsp/at32f435_437/family.c +++ b/hw/bsp/at32f435_437/family.c @@ -320,7 +320,7 @@ volatile uint32_t system_ticks = 0; void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } void SVC_Handler(void) { diff --git a/hw/bsp/at32f45x/family.c b/hw/bsp/at32f45x/family.c index 0593e5115..fa0c1139f 100644 --- a/hw/bsp/at32f45x/family.c +++ b/hw/bsp/at32f45x/family.c @@ -227,7 +227,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/board.c b/hw/bsp/board.c index 483d9dc28..91e7de9fe 100644 --- a/hw/bsp/board.c +++ b/hw/bsp/board.c @@ -161,10 +161,6 @@ void board_putchar(int c) { (void) sys_write(0, (const char*)&c, 1); } -uint32_t tusb_time_millis_api(void) { - return board_millis(); -} - //-------------------------------------------------------------------- // FreeRTOS hooks //-------------------------------------------------------------------- diff --git a/hw/bsp/board_api.h b/hw/bsp/board_api.h index 606ac484f..4487871eb 100644 --- a/hw/bsp/board_api.h +++ b/hw/bsp/board_api.h @@ -98,43 +98,6 @@ int board_uart_read(uint8_t *buf, int len); // 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 -// Get current milliseconds, must be implemented when no RTOS is used -uint32_t board_millis(void); - -#elif CFG_TUSB_OS == OPT_OS_FREERTOS -static inline uint32_t board_millis(void) { - return ( ( ((uint64_t) xTaskGetTickCount()) * 1000) / configTICK_RATE_HZ ); -} - -#elif CFG_TUSB_OS == OPT_OS_MYNEWT -static inline uint32_t board_millis(void) { - return os_time_ticks_to_ms32( os_time_get() ); -} - -#elif CFG_TUSB_OS == OPT_OS_PICO -#include "pico/time.h" -static inline uint32_t board_millis(void) { - return to_ms_since_boot(get_absolute_time()); -} - -#elif CFG_TUSB_OS == OPT_OS_RTTHREAD -static inline uint32_t board_millis(void) { - return (((uint64_t)rt_tick_get()) * 1000 / RT_TICK_PER_SECOND); -} - -#elif CFG_TUSB_OS == OPT_OS_CUSTOM -// Implement your own board_millis() in any of .c file -uint32_t board_millis(void); - -#elif CFG_TUSB_OS == OPT_OS_ZEPHYR -static inline uint32_t board_millis(void) { - return k_uptime_get_32(); -} -#else - #error "board_millis() is not implemented for this OS" -#endif - //--------------------------------------------------------------------+ // Helper functions //--------------------------------------------------------------------+ @@ -175,8 +138,8 @@ static inline size_t board_usb_get_serial(uint16_t desc_str1[], size_t max_chars // TODO remove static inline void board_delay(uint32_t ms) { - uint32_t start_ms = board_millis(); - while ( board_millis() - start_ms < ms ) { + uint32_t start_ms = tusb_time_millis_api(); + while ( tusb_time_millis_api() - start_ms < ms ) { // take chance to run usb background #if CFG_TUD_ENABLED tud_task(); diff --git a/hw/bsp/broadcom_32bit/family.c b/hw/bsp/broadcom_32bit/family.c index f8f3b0b70..399397bb4 100644 --- a/hw/bsp/broadcom_32bit/family.c +++ b/hw/bsp/broadcom_32bit/family.c @@ -146,7 +146,7 @@ void TIMER_1_IRQHandler(void) { SYSTMR->CS_b.M1 = 1; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/broadcom_64bit/family.c b/hw/bsp/broadcom_64bit/family.c index f8f3b0b70..399397bb4 100644 --- a/hw/bsp/broadcom_64bit/family.c +++ b/hw/bsp/broadcom_64bit/family.c @@ -146,7 +146,7 @@ void TIMER_1_IRQHandler(void) { SYSTMR->CS_b.M1 = 1; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/brtmm90x/family.c b/hw/bsp/brtmm90x/family.c index 15ff4b8ee..ff24cfe89 100644 --- a/hw/bsp/brtmm90x/family.c +++ b/hw/bsp/brtmm90x/family.c @@ -234,7 +234,7 @@ int board_uart_write(void const *buf, int len) } // Get current milliseconds -uint32_t board_millis(void) +uint32_t tusb_time_millis_api(void) { uint32_t safe_ms; diff --git a/hw/bsp/ch32f20x/family.c b/hw/bsp/ch32f20x/family.c index 7eae62fa4..dd84b7c77 100644 --- a/hw/bsp/ch32f20x/family.c +++ b/hw/bsp/ch32f20x/family.c @@ -101,7 +101,7 @@ void SysTick_Handler(void) system_ticks++; } -uint32_t board_millis(void) +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/ch32v10x/family.c b/hw/bsp/ch32v10x/family.c index dfc041462..344dcaf0b 100644 --- a/hw/bsp/ch32v10x/family.c +++ b/hw/bsp/ch32v10x/family.c @@ -61,7 +61,7 @@ static uint32_t SysTick_Config(uint32_t ticks) { return 0; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } #endif diff --git a/hw/bsp/ch32v20x/family.c b/hw/bsp/ch32v20x/family.c index 690acee1e..4c22450f9 100644 --- a/hw/bsp/ch32v20x/family.c +++ b/hw/bsp/ch32v20x/family.c @@ -85,7 +85,7 @@ static uint32_t SysTick_Config(uint32_t ticks) { return 0; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } #endif diff --git a/hw/bsp/ch32v30x/family.c b/hw/bsp/ch32v30x/family.c index c694f1a08..6295f7723 100644 --- a/hw/bsp/ch32v30x/family.c +++ b/hw/bsp/ch32v30x/family.c @@ -144,7 +144,7 @@ __attribute__((interrupt)) void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/cxd56/family.c b/hw/bsp/cxd56/family.c index a8e2fd52b..fd92bb9d9 100644 --- a/hw/bsp/cxd56/family.c +++ b/hw/bsp/cxd56/family.c @@ -96,7 +96,7 @@ int board_uart_write(void const *buf, int len) } // Get current milliseconds -uint32_t board_millis(void) +uint32_t tusb_time_millis_api(void) { struct timespec tp; diff --git a/hw/bsp/da1469x/family.c b/hw/bsp/da1469x/family.c index a64ffce67..a4f7f2e8d 100644 --- a/hw/bsp/da1469x/family.c +++ b/hw/bsp/da1469x/family.c @@ -140,7 +140,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } #endif diff --git a/hw/bsp/efm32/family.c b/hw/bsp/efm32/family.c index 39166bc4d..d318e20d6 100644 --- a/hw/bsp/efm32/family.c +++ b/hw/bsp/efm32/family.c @@ -689,7 +689,7 @@ void SysTick_Handler(void) system_ticks++; } -uint32_t board_millis(void) +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/f1c100s/family.c b/hw/bsp/f1c100s/family.c index 9e864363f..1e71333d4 100644 --- a/hw/bsp/f1c100s/family.c +++ b/hw/bsp/f1c100s/family.c @@ -79,7 +79,7 @@ int board_uart_write(void const* buf, int len) { #if CFG_TUSB_OS == OPT_OS_NONE volatile uint32_t system_ticks = 0; -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/fomu/family.c b/hw/bsp/fomu/family.c index 9d7977bea..cf04a1f6f 100644 --- a/hw/bsp/fomu/family.c +++ b/hw/bsp/fomu/family.c @@ -117,7 +117,7 @@ int board_uart_write(void const * buf, int len) } #if CFG_TUSB_OS == OPT_OS_NONE -uint32_t board_millis(void) +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/gd32vf103/family.c b/hw/bsp/gd32vf103/family.c index 9d15755fc..4c1099317 100644 --- a/hw/bsp/gd32vf103/family.c +++ b/hw/bsp/gd32vf103/family.c @@ -179,7 +179,7 @@ void eclic_mtip_handler(void) { system_ticks++; SysTick_Reload(TIMER_TICKS); } -uint32_t board_millis(void) { return system_ticks; } +uint32_t tusb_time_millis_api(void) { return system_ticks; } #endif #ifdef USE_FULL_ASSERT diff --git a/hw/bsp/hpmicro/family.c b/hw/bsp/hpmicro/family.c index ffec2523a..a80a8d913 100644 --- a/hw/bsp/hpmicro/family.c +++ b/hw/bsp/hpmicro/family.c @@ -108,7 +108,7 @@ int board_uart_write(void const *buf, int len) { #if CFG_TUSB_OS == OPT_OS_NONE // Get current milliseconds, must be implemented when no RTOS is used -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return (hpm_csr_get_core_cycle() / clock_get_core_clock_ticks_per_ms()); } diff --git a/hw/bsp/imxrt/family.c b/hw/bsp/imxrt/family.c index d54b41bdb..c1ee34b1a 100644 --- a/hw/bsp/imxrt/family.c +++ b/hw/bsp/imxrt/family.c @@ -239,7 +239,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } #endif diff --git a/hw/bsp/kinetis_k/family.c b/hw/bsp/kinetis_k/family.c index 98ef52739..1505defe0 100644 --- a/hw/bsp/kinetis_k/family.c +++ b/hw/bsp/kinetis_k/family.c @@ -143,7 +143,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } #endif diff --git a/hw/bsp/kinetis_k32l2/family.c b/hw/bsp/kinetis_k32l2/family.c index 2062b8b18..ec8dc6ecf 100644 --- a/hw/bsp/kinetis_k32l2/family.c +++ b/hw/bsp/kinetis_k32l2/family.c @@ -148,7 +148,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/kinetis_kl/family.c b/hw/bsp/kinetis_kl/family.c index c257f4b2b..f89434d06 100644 --- a/hw/bsp/kinetis_kl/family.c +++ b/hw/bsp/kinetis_kl/family.c @@ -142,7 +142,7 @@ void SysTick_Handler(void) system_ticks++; } -uint32_t board_millis(void) +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/lpc11/family.c b/hw/bsp/lpc11/family.c index c9f18bd2f..76c2bd17c 100644 --- a/hw/bsp/lpc11/family.c +++ b/hw/bsp/lpc11/family.c @@ -130,7 +130,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/lpc13/family.c b/hw/bsp/lpc13/family.c index e212c6a63..8513f4df4 100644 --- a/hw/bsp/lpc13/family.c +++ b/hw/bsp/lpc13/family.c @@ -83,7 +83,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/lpc15/family.c b/hw/bsp/lpc15/family.c index 5f22df175..0d092d3a9 100644 --- a/hw/bsp/lpc15/family.c +++ b/hw/bsp/lpc15/family.c @@ -140,7 +140,7 @@ void SysTick_Handler (void) system_ticks++; } -uint32_t board_millis(void) +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/lpc17/family.c b/hw/bsp/lpc17/family.c index ba59fccca..f398f7e3c 100644 --- a/hw/bsp/lpc17/family.c +++ b/hw/bsp/lpc17/family.c @@ -145,7 +145,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/lpc18/family.c b/hw/bsp/lpc18/family.c index 6c02c711f..2043cef99 100644 --- a/hw/bsp/lpc18/family.c +++ b/hw/bsp/lpc18/family.c @@ -143,7 +143,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/lpc40/family.c b/hw/bsp/lpc40/family.c index 5ea95e9b8..237cd996b 100644 --- a/hw/bsp/lpc40/family.c +++ b/hw/bsp/lpc40/family.c @@ -156,7 +156,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/lpc43/family.c b/hw/bsp/lpc43/family.c index f440fb119..bade53b07 100644 --- a/hw/bsp/lpc43/family.c +++ b/hw/bsp/lpc43/family.c @@ -257,7 +257,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/lpc51/family.c b/hw/bsp/lpc51/family.c index bec86f87f..847972350 100644 --- a/hw/bsp/lpc51/family.c +++ b/hw/bsp/lpc51/family.c @@ -122,7 +122,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } #endif diff --git a/hw/bsp/lpc54/family.c b/hw/bsp/lpc54/family.c index 7bb73afbc..945e27154 100644 --- a/hw/bsp/lpc54/family.c +++ b/hw/bsp/lpc54/family.c @@ -217,7 +217,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } #endif diff --git a/hw/bsp/lpc55/family.c b/hw/bsp/lpc55/family.c index ad0e502b5..7485ed4d5 100644 --- a/hw/bsp/lpc55/family.c +++ b/hw/bsp/lpc55/family.c @@ -350,7 +350,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } #endif diff --git a/hw/bsp/maxim/family.c b/hw/bsp/maxim/family.c index 7ad7d6ff9..6ef4c12c1 100644 --- a/hw/bsp/maxim/family.c +++ b/hw/bsp/maxim/family.c @@ -202,7 +202,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } #endif diff --git a/hw/bsp/mcx/family.c b/hw/bsp/mcx/family.c index 3b91678b1..a3969c217 100644 --- a/hw/bsp/mcx/family.c +++ b/hw/bsp/mcx/family.c @@ -219,7 +219,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/mm32/family.c b/hw/bsp/mm32/family.c index 663c30818..330b01f6d 100644 --- a/hw/bsp/mm32/family.c +++ b/hw/bsp/mm32/family.c @@ -175,7 +175,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } #endif diff --git a/hw/bsp/msp430/family.c b/hw/bsp/msp430/family.c index 390a9915e..413ad7db6 100644 --- a/hw/bsp/msp430/family.c +++ b/hw/bsp/msp430/family.c @@ -102,10 +102,10 @@ static void SystemClock_Config(void) // VUSB enabled automatically. // Wait two milliseconds to stabilize, per manual recommendation. - uint32_t ms_elapsed = board_millis(); + uint32_t ms_elapsed = tusb_time_millis_api(); do { - while((board_millis() - ms_elapsed) < 2); + while((tusb_time_millis_api() - ms_elapsed) < 2); }while(!(USBPWRCTL & USBBGVBV)); // USB uses XT2 (4 MHz) directly. Enable the PLL. @@ -113,11 +113,11 @@ static void SystemClock_Config(void) USBPLLCTL |= (UPFDEN | UPLLEN); // Wait until PLL locks. Check every 2ms, per manual. - ms_elapsed = board_millis(); + ms_elapsed = tusb_time_millis_api(); do { USBPLLIR &= ~USBOOLIFG; - while((board_millis() - ms_elapsed) < 2); + while((tusb_time_millis_api() - ms_elapsed) < 2); }while(USBPLLIR & USBOOLIFG); USBKEYPID = 0; @@ -207,7 +207,7 @@ void TIMER0_A0_ISR (void) { // TAxCCR0 CCIFG resets itself as soon as interrupt is invoked. } -uint32_t board_millis(void) +uint32_t tusb_time_millis_api(void) { uint32_t systick_mirror; diff --git a/hw/bsp/msp432e4/family.c b/hw/bsp/msp432e4/family.c index 0e1b0528a..90eb945f4 100644 --- a/hw/bsp/msp432e4/family.c +++ b/hw/bsp/msp432e4/family.c @@ -202,7 +202,7 @@ void SysTick_Handler(void) system_ticks++; } -uint32_t board_millis(void) +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/nrf/family.c b/hw/bsp/nrf/family.c index ee3ac61e2..04bfbf320 100644 --- a/hw/bsp/nrf/family.c +++ b/hw/bsp/nrf/family.c @@ -296,7 +296,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } #endif diff --git a/hw/bsp/nuc100_120/family.c b/hw/bsp/nuc100_120/family.c index 752af2a56..cfe60121c 100644 --- a/hw/bsp/nuc100_120/family.c +++ b/hw/bsp/nuc100_120/family.c @@ -87,7 +87,7 @@ void SysTick_Handler (void) system_ticks++; } -uint32_t board_millis(void) +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/nuc121_125/family.c b/hw/bsp/nuc121_125/family.c index 089855207..dce5b4d62 100644 --- a/hw/bsp/nuc121_125/family.c +++ b/hw/bsp/nuc121_125/family.c @@ -86,7 +86,7 @@ void SysTick_Handler (void) system_ticks++; } -uint32_t board_millis(void) +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/nuc126/family.c b/hw/bsp/nuc126/family.c index f992fcab4..3343064e5 100644 --- a/hw/bsp/nuc126/family.c +++ b/hw/bsp/nuc126/family.c @@ -111,7 +111,7 @@ void SysTick_Handler (void) system_ticks++; } -uint32_t board_millis(void) +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/nuc505/family.c b/hw/bsp/nuc505/family.c index 00ed92310..f1a77e4a5 100644 --- a/hw/bsp/nuc505/family.c +++ b/hw/bsp/nuc505/family.c @@ -88,7 +88,7 @@ void SysTick_Handler (void) system_ticks++; } -uint32_t board_millis(void) +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/pic32mz/family.c b/hw/bsp/pic32mz/family.c index da97f67a9..2bfc876e1 100644 --- a/hw/bsp/pic32mz/family.c +++ b/hw/bsp/pic32mz/family.c @@ -106,7 +106,7 @@ TU_ATTR_WEAK int board_uart_write(void const * buf, int len) } #if CFG_TUSB_OS == OPT_OS_NONE -uint32_t board_millis(void) +uint32_t tusb_time_millis_api(void) { // COUNTER is system clock (200MHz / 2 = 100MHz) convert to ms) return _CP0_GET_COUNT() / (100000000 / 1000); diff --git a/hw/bsp/ra/family.c b/hw/bsp/ra/family.c index 1f75b47c1..f371e694b 100644 --- a/hw/bsp/ra/family.c +++ b/hw/bsp/ra/family.c @@ -169,7 +169,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } #endif diff --git a/hw/bsp/rw61x/family.c b/hw/bsp/rw61x/family.c index 265d5fcc0..fcc7fb262 100644 --- a/hw/bsp/rw61x/family.c +++ b/hw/bsp/rw61x/family.c @@ -128,7 +128,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/rx/boards/gr_citrus/gr_citrus.c b/hw/bsp/rx/boards/gr_citrus/gr_citrus.c index 26ad4a6aa..e5b24bf69 100644 --- a/hw/bsp/rx/boards/gr_citrus/gr_citrus.c +++ b/hw/bsp/rx/boards/gr_citrus/gr_citrus.c @@ -248,7 +248,7 @@ void INT_Excep_CMT0_CMI0(void) ++system_ticks; } -uint32_t board_millis(void) +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/rx/boards/rx65n_target/rx65n_target.c b/hw/bsp/rx/boards/rx65n_target/rx65n_target.c index 66a319541..d5c2de05a 100644 --- a/hw/bsp/rx/boards/rx65n_target/rx65n_target.c +++ b/hw/bsp/rx/boards/rx65n_target/rx65n_target.c @@ -299,7 +299,7 @@ void INT_Excep_CMT0_CMI0(void) ++system_ticks; } -uint32_t board_millis(void) +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/samd11/family.c b/hw/bsp/samd11/family.c index 6cbf02412..bccbac8ea 100644 --- a/hw/bsp/samd11/family.c +++ b/hw/bsp/samd11/family.c @@ -155,7 +155,7 @@ void SysTick_Handler (void) system_ticks++; } -uint32_t board_millis(void) +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/samd2x_l2x/family.c b/hw/bsp/samd2x_l2x/family.c index a2dc8a8d4..737219b6c 100644 --- a/hw/bsp/samd2x_l2x/family.c +++ b/hw/bsp/samd2x_l2x/family.c @@ -361,7 +361,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/samd5x_e5x/family.c b/hw/bsp/samd5x_e5x/family.c index 5a7105894..c008b9719 100644 --- a/hw/bsp/samd5x_e5x/family.c +++ b/hw/bsp/samd5x_e5x/family.c @@ -210,7 +210,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/same7x/family.c b/hw/bsp/same7x/family.c index 6feefa3b5..ff6ecf277 100644 --- a/hw/bsp/same7x/family.c +++ b/hw/bsp/same7x/family.c @@ -192,7 +192,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } #endif diff --git a/hw/bsp/samg/family.c b/hw/bsp/samg/family.c index 5c5fc3c14..b27134305 100644 --- a/hw/bsp/samg/family.c +++ b/hw/bsp/samg/family.c @@ -148,7 +148,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/stm32c0/family.c b/hw/bsp/stm32c0/family.c index e2ba47f45..e20c0ee15 100644 --- a/hw/bsp/stm32c0/family.c +++ b/hw/bsp/stm32c0/family.c @@ -173,7 +173,7 @@ void SysTick_Handler(void) { HAL_IncTick(); } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } #endif diff --git a/hw/bsp/stm32f0/family.c b/hw/bsp/stm32f0/family.c index b99b0a8cc..5a35a3e50 100644 --- a/hw/bsp/stm32f0/family.c +++ b/hw/bsp/stm32f0/family.c @@ -160,7 +160,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/stm32f1/family.c b/hw/bsp/stm32f1/family.c index 3147061cf..fae61ca9e 100644 --- a/hw/bsp/stm32f1/family.c +++ b/hw/bsp/stm32f1/family.c @@ -202,7 +202,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/stm32f2/family.c b/hw/bsp/stm32f2/family.c index f95128040..b901bf4cc 100644 --- a/hw/bsp/stm32f2/family.c +++ b/hw/bsp/stm32f2/family.c @@ -145,7 +145,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } #endif diff --git a/hw/bsp/stm32f3/family.c b/hw/bsp/stm32f3/family.c index 95bcc7882..fde1e9f6d 100644 --- a/hw/bsp/stm32f3/family.c +++ b/hw/bsp/stm32f3/family.c @@ -156,7 +156,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/stm32f4/family.c b/hw/bsp/stm32f4/family.c index f0e9620f2..665ea114a 100644 --- a/hw/bsp/stm32f4/family.c +++ b/hw/bsp/stm32f4/family.c @@ -251,7 +251,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/stm32f7/family.c b/hw/bsp/stm32f7/family.c index d8f0da201..ce9049abe 100644 --- a/hw/bsp/stm32f7/family.c +++ b/hw/bsp/stm32f7/family.c @@ -312,7 +312,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/stm32g0/family.c b/hw/bsp/stm32g0/family.c index 4b175b0ec..b25897264 100644 --- a/hw/bsp/stm32g0/family.c +++ b/hw/bsp/stm32g0/family.c @@ -181,7 +181,7 @@ void SysTick_Handler(void) { HAL_IncTick(); } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } #endif diff --git a/hw/bsp/stm32g4/family.c b/hw/bsp/stm32g4/family.c index d8afa0f95..2e13a1d4b 100644 --- a/hw/bsp/stm32g4/family.c +++ b/hw/bsp/stm32g4/family.c @@ -211,7 +211,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } #endif diff --git a/hw/bsp/stm32h5/family.c b/hw/bsp/stm32h5/family.c index fdb12e44f..1e8acd502 100644 --- a/hw/bsp/stm32h5/family.c +++ b/hw/bsp/stm32h5/family.c @@ -207,7 +207,7 @@ void SysTick_Handler(void) { HAL_IncTick(); } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/stm32h7/family.c b/hw/bsp/stm32h7/family.c index a320a7e72..2759dac63 100644 --- a/hw/bsp/stm32h7/family.c +++ b/hw/bsp/stm32h7/family.c @@ -295,7 +295,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/stm32h7rs/family.c b/hw/bsp/stm32h7rs/family.c index 2cc39b7ac..3bf75ba97 100644 --- a/hw/bsp/stm32h7rs/family.c +++ b/hw/bsp/stm32h7rs/family.c @@ -468,7 +468,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/stm32l0/family.c b/hw/bsp/stm32l0/family.c index 6aeab1259..192f014f4 100644 --- a/hw/bsp/stm32l0/family.c +++ b/hw/bsp/stm32l0/family.c @@ -168,7 +168,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } #endif diff --git a/hw/bsp/stm32l4/family.c b/hw/bsp/stm32l4/family.c index 65f6b9ab3..c87b643b8 100644 --- a/hw/bsp/stm32l4/family.c +++ b/hw/bsp/stm32l4/family.c @@ -231,7 +231,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/stm32n6/family.c b/hw/bsp/stm32n6/family.c index c839e6b3e..4354616c3 100644 --- a/hw/bsp/stm32n6/family.c +++ b/hw/bsp/stm32n6/family.c @@ -366,7 +366,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/stm32u0/family.c b/hw/bsp/stm32u0/family.c index 50b513d8f..0f91d1f30 100644 --- a/hw/bsp/stm32u0/family.c +++ b/hw/bsp/stm32u0/family.c @@ -174,7 +174,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } #endif diff --git a/hw/bsp/stm32u5/family.c b/hw/bsp/stm32u5/family.c index dfcf5c537..55ca25d58 100644 --- a/hw/bsp/stm32u5/family.c +++ b/hw/bsp/stm32u5/family.c @@ -270,7 +270,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/stm32wb/family.c b/hw/bsp/stm32wb/family.c index 153d10a09..de503c072 100644 --- a/hw/bsp/stm32wb/family.c +++ b/hw/bsp/stm32wb/family.c @@ -174,7 +174,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/stm32wba/family.c b/hw/bsp/stm32wba/family.c index d05415755..e058a80a1 100644 --- a/hw/bsp/stm32wba/family.c +++ b/hw/bsp/stm32wba/family.c @@ -198,7 +198,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { return system_ticks; } +uint32_t tusb_time_millis_api(void) { return system_ticks; } #endif void HardFault_Handler(void) { asm( "bkpt 1" ); } diff --git a/hw/bsp/tm4c/family.c b/hw/bsp/tm4c/family.c index ae7f22f00..503d0a8c9 100644 --- a/hw/bsp/tm4c/family.c +++ b/hw/bsp/tm4c/family.c @@ -211,7 +211,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/xmc4000/family.c b/hw/bsp/xmc4000/family.c index 6fef53025..d0acd04cb 100644 --- a/hw/bsp/xmc4000/family.c +++ b/hw/bsp/xmc4000/family.c @@ -147,7 +147,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index 9eb0a9337..6ac1405f3 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -90,6 +90,12 @@ // 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 extern void tusb_app_dcache_flush(uintptr_t addr, uint32_t data_size); diff --git a/src/host/usbh.c b/src/host/usbh.c index 60d78605f..0da5166c2 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -685,7 +685,7 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr) { has_deferred_attach = osal_queue_receive(_usbh_daq, &event, 0); } - if (!has_deferred_attach) // skip event queue to process deferred at + if (!has_deferred_attach) // skip event queue to process deferred attach #endif { if (!osal_queue_receive(_usbh_q, &event, timeout_ms)) { diff --git a/src/portable/sunxi/dcd_sunxi_musb.c b/src/portable/sunxi/dcd_sunxi_musb.c index b413121a5..9fac0bc1c 100644 --- a/src/portable/sunxi/dcd_sunxi_musb.c +++ b/src/portable/sunxi/dcd_sunxi_musb.c @@ -36,9 +36,6 @@ #include #include "musb_def.h" -//#include "bsp/board_api.h" -extern uint32_t board_millis(void); // TODO remove - typedef uint32_t u32; typedef uint16_t u16; typedef uint8_t u8; diff --git a/src/tusb.c b/src/tusb.c index 40d0e8adf..37aecf693 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -45,21 +45,24 @@ tusb_role_t _tusb_rhport_role[TUP_USBIP_CONTROLLER_NUM] = { TUSB_ROLE_INVALID }; // Weak/Default API, can be overwritten by Application //-------------------------------------------------------------------- - #if CFG_TUSB_OS != OPT_OS_NONE -uint32_t tusb_time_millis_api(void) { +#if CFG_TUSB_OS != OPT_OS_NONE +TU_ATTR_WEAK uint32_t tusb_time_millis_api(void) { return osal_time_millis(); } - #endif TU_ATTR_WEAK void tusb_time_delay_ms_api(uint32_t ms) { -#if CFG_TUSB_OS != OPT_OS_NONE osal_task_delay(ms); +} + #else +// tusb_time_millis_api() must be implemented by user application. + +TU_ATTR_WEAK void tusb_time_delay_ms_api(uint32_t ms) { // delay using millis() const uint32_t time_ms = tusb_time_millis_api(); while ((tusb_time_millis_api() - time_ms) < ms) {} -#endif } +#endif TU_ATTR_WEAK void *tusb_app_virt_to_phys(void *virt_addr) { return virt_addr; diff --git a/src/tusb.h b/src/tusb.h index 742009a2e..3876bf863 100644 --- a/src/tusb.h +++ b/src/tusb.h @@ -174,16 +174,6 @@ bool tusb_deinit(uint8_t rhport); #endif -//--------------------------------------------------------------------+ -// -//--------------------------------------------------------------------+ - -// 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); - #ifdef __cplusplus } #endif -- cgit v1.3.1 From 4fa4d39883a6328d4628525cfc163516fd919aba Mon Sep 17 00:00:00 2001 From: Tomas Rezucha Date: Mon, 2 Mar 2026 12:29:09 +0100 Subject: fix(dcd/dwc2): Do not modify FS PHY registers on HS PHY ESP32-P4 --- src/portable/synopsys/dwc2/dcd_dwc2.c | 36 +++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) (limited to 'src/portable') diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index 2e2b050bc..b52646a5d 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -527,34 +527,38 @@ void dcd_remote_wakeup(uint8_t rhport) { } void dcd_connect(uint8_t rhport) { - (void) rhport; dwc2_regs_t* dwc2 = DWC2_REG(rhport); #ifdef TUP_USBIP_DWC2_ESP32 - usb_wrap_otg_conf_reg_t conf = USB_WRAP.otg_conf; - conf.pad_pull_override = 0; - conf.dp_pullup = 0; - conf.dp_pulldown = 0; - conf.dm_pullup = 0; - conf.dm_pulldown = 0; - USB_WRAP.otg_conf = conf; + // On ESP32-P4 HS PHY, do not write to USB_WRAP register which belongs to FS PHY + if (rhport == 0) { + usb_wrap_otg_conf_reg_t conf = USB_WRAP.otg_conf; + conf.pad_pull_override = 0; + conf.dp_pullup = 0; + conf.dp_pulldown = 0; + conf.dm_pullup = 0; + conf.dm_pulldown = 0; + USB_WRAP.otg_conf = conf; + } #endif dwc2->dctl &= ~DCTL_SDIS; } void dcd_disconnect(uint8_t rhport) { - (void) rhport; dwc2_regs_t* dwc2 = DWC2_REG(rhport); #ifdef TUP_USBIP_DWC2_ESP32 - usb_wrap_otg_conf_reg_t conf = USB_WRAP.otg_conf; - conf.pad_pull_override = 1; - conf.dp_pullup = 0; - conf.dp_pulldown = 1; - conf.dm_pullup = 0; - conf.dm_pulldown = 1; - USB_WRAP.otg_conf = conf; + // On ESP32-P4 HS PHY, do not write to USB_WRAP register which belongs to FS PHY + if (rhport == 0) { + usb_wrap_otg_conf_reg_t conf = USB_WRAP.otg_conf; + conf.pad_pull_override = 1; + conf.dp_pullup = 0; + conf.dp_pulldown = 1; + conf.dm_pullup = 0; + conf.dm_pulldown = 1; + USB_WRAP.otg_conf = conf; + } #endif dwc2->dctl |= DCTL_SDIS; -- cgit v1.3.1 From 30af158af9ada161d31e02d08548f78390183920 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 4 Mar 2026 17:30:40 +0700 Subject: add PHY deinitialization support for DWC2 driver across all MCUs --- src/portable/synopsys/dwc2/dcd_dwc2.c | 6 ------ src/portable/synopsys/dwc2/dwc2_at32.h | 5 +++++ src/portable/synopsys/dwc2/dwc2_bcm.h | 6 ++++++ src/portable/synopsys/dwc2/dwc2_common.c | 27 +++++++++++++-------------- src/portable/synopsys/dwc2/dwc2_common.h | 1 + src/portable/synopsys/dwc2/dwc2_efm32.h | 8 ++++++++ src/portable/synopsys/dwc2/dwc2_esp32.h | 6 ++++++ src/portable/synopsys/dwc2/dwc2_gd32.h | 6 ++++++ src/portable/synopsys/dwc2/dwc2_nrf.h | 5 +++++ src/portable/synopsys/dwc2/dwc2_stm32.h | 14 ++++++++++++++ src/portable/synopsys/dwc2/dwc2_xmc.h | 7 +++++++ src/portable/synopsys/dwc2/hcd_dwc2.c | 16 ++++++++++++++-- 12 files changed, 85 insertions(+), 22 deletions(-) (limited to 'src/portable') diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index 2c76098a4..8685ec6dc 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -493,13 +493,7 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { } bool dcd_deinit(uint8_t rhport) { - dwc2_regs_t* dwc2 = DWC2_REG(rhport); - - // Disable global interrupt - dwc2->gahbcfg &= ~GAHBCFG_GINT; - dcd_disconnect(rhport); - dwc2_core_deinit(rhport); return true; } diff --git a/src/portable/synopsys/dwc2/dwc2_at32.h b/src/portable/synopsys/dwc2/dwc2_at32.h index 10824ae92..95ee8a8e1 100644 --- a/src/portable/synopsys/dwc2/dwc2_at32.h +++ b/src/portable/synopsys/dwc2/dwc2_at32.h @@ -112,6 +112,11 @@ TU_ATTR_ALWAYS_INLINE static inline void dwc2_phy_init(dwc2_regs_t *dwc2, uint8_ } } +// MCU specific PHY deinit, disable PHY power +TU_ATTR_ALWAYS_INLINE static inline void dwc2_phy_deinit(dwc2_regs_t *dwc2) { + dwc2->stm32_gccfg &= ~(STM32_GCCFG_PWRDWN | STM32_GCCFG_DCDEN | STM32_GCCFG_PDEN); +} + // 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; diff --git a/src/portable/synopsys/dwc2/dwc2_bcm.h b/src/portable/synopsys/dwc2/dwc2_bcm.h index df6d4a852..852db15e5 100644 --- a/src/portable/synopsys/dwc2/dwc2_bcm.h +++ b/src/portable/synopsys/dwc2/dwc2_bcm.h @@ -73,6 +73,12 @@ static inline void dwc2_phy_init(dwc2_regs_t * dwc2, uint8_t hs_phy_type) // nothing to do } +// MCU specific PHY deinit, disable PHY power +static inline void dwc2_phy_deinit(dwc2_regs_t * dwc2) { + (void) dwc2; + // nothing to do +} + // 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) { diff --git a/src/portable/synopsys/dwc2/dwc2_common.c b/src/portable/synopsys/dwc2/dwc2_common.c index a6afc3154..4e8e1ff04 100644 --- a/src/portable/synopsys/dwc2/dwc2_common.c +++ b/src/portable/synopsys/dwc2/dwc2_common.c @@ -39,14 +39,11 @@ static void reset_core(dwc2_regs_t* dwc2) { while (!(dwc2->grstctl & GRSTCTL_AHBIDL)) { } - // load gsnpsid (it is not readable after reset is asserted) - const uint32_t gsnpsid = dwc2->gsnpsid; - - // reset core - dwc2->grstctl |= GRSTCTL_CSRST; + const uint32_t gsnpsid = dwc2->gsnpsid; // preload gsnpsid which is not readable while resetting + dwc2->grstctl |= GRSTCTL_CSRST; // reset core if ((gsnpsid & DWC2_CORE_REV_MASK) < (DWC2_CORE_REV_4_20a & DWC2_CORE_REV_MASK)) { - // prior v4.20a: CSRST is self-clearing and the core clears this bit after all the necessary logic is reset in + // 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) {} @@ -88,8 +85,7 @@ static void phy_fs_init(dwc2_regs_t* dwc2) { } /* dwc2 has 2 highspeed PHYs options - * - UTMI+ is internal highspeed PHY, can be clocked at 30/60 Mhz for fullspeed or 60 Mhz for highspeed. Can be either - * 8 or 16-bit interface. + * - UTMI+ is internal highspeed PHY, can be clocked at 30 Mhz (8-bit) or 60 Mhz (16-bit). * - ULPI is external highspeed PHY, clocked at 60Mhz with 8-bit interface. * * In addition, UTMI+/ULPI can be shared to run at fullspeed mode with 48Mhz @@ -250,14 +246,17 @@ bool dwc2_core_init(uint8_t rhport, bool is_hs_phy, bool is_dma) { void dwc2_core_deinit(uint8_t rhport) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); - // Soft disconnect - dwc2->dctl |= DCTL_SDIS; - - // Reset global registers - dwc2->gotgctl = 0; + // Disable global interrupt + dwc2->gahbcfg &= ~GAHBCFG_GINT; - // Reset core + // Reset core: this also flushes FIFOs and clears all interrupt registers reset_core(dwc2); + + // Stop PHY clock and gate HCLK for power saving (per databook chapter 14) + dwc2->pcgcctl |= PCGCCTL_STOPPCLK | PCGCCTL_GATEHCLK; + + // MCU-specific PHY deinit (disable PHY power) + dwc2_phy_deinit(dwc2); } // void dwc2_core_handle_common_irq(uint8_t rhport, bool in_isr) { diff --git a/src/portable/synopsys/dwc2/dwc2_common.h b/src/portable/synopsys/dwc2/dwc2_common.h index c74ad2233..ac97ab3d5 100644 --- a/src/portable/synopsys/dwc2/dwc2_common.h +++ b/src/portable/synopsys/dwc2/dwc2_common.h @@ -42,6 +42,7 @@ // - _dwc2_controller[]: array of controllers // - DWC2_EP_MAX: largest EP counts of all controllers // - dwc2_phy_init/dwc2_phy_update: phy init called before and after core reset +// - dwc2_phy_deinit: phy deinit to disable PHY power // - dwc2_dcd_int_enable/dwc2_dcd_int_disable // - dwc2_remote_wakeup_delay diff --git a/src/portable/synopsys/dwc2/dwc2_efm32.h b/src/portable/synopsys/dwc2/dwc2_efm32.h index 0e3570cbb..f808b567c 100644 --- a/src/portable/synopsys/dwc2/dwc2_efm32.h +++ b/src/portable/synopsys/dwc2/dwc2_efm32.h @@ -72,6 +72,14 @@ static inline void dwc2_phy_init(dwc2_regs_t * dwc2, uint8_t hs_phy_type) USB->ROUTE = USB_ROUTE_PHYPEN; } +// MCU specific PHY deinit, disable PHY power +static inline void dwc2_phy_deinit(dwc2_regs_t * dwc2) { + (void) dwc2; + + // Disable PHY pin + USB->ROUTE = 0; +} + // 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) { diff --git a/src/portable/synopsys/dwc2/dwc2_esp32.h b/src/portable/synopsys/dwc2/dwc2_esp32.h index a4e0d1770..f4fa0bf8b 100644 --- a/src/portable/synopsys/dwc2/dwc2_esp32.h +++ b/src/portable/synopsys/dwc2/dwc2_esp32.h @@ -121,6 +121,12 @@ TU_ATTR_ALWAYS_INLINE static inline void dwc2_phy_init(dwc2_regs_t* dwc2, uint8_ } +// MCU specific PHY deinit, disable PHY power +TU_ATTR_ALWAYS_INLINE static inline void dwc2_phy_deinit(dwc2_regs_t* dwc2) { + (void)dwc2; + // PHY managed by ESP-IDF +} + // 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; diff --git a/src/portable/synopsys/dwc2/dwc2_gd32.h b/src/portable/synopsys/dwc2/dwc2_gd32.h index 0375fffe4..26b924161 100644 --- a/src/portable/synopsys/dwc2/dwc2_gd32.h +++ b/src/portable/synopsys/dwc2/dwc2_gd32.h @@ -85,6 +85,12 @@ static inline void dwc2_phy_init(dwc2_regs_t * dwc2, uint8_t hs_phy_type) // nothing to do } +// MCU specific PHY deinit, disable PHY power +static inline void dwc2_phy_deinit(dwc2_regs_t * dwc2) { + (void) dwc2; + // nothing to do +} + // 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) { diff --git a/src/portable/synopsys/dwc2/dwc2_nrf.h b/src/portable/synopsys/dwc2/dwc2_nrf.h index b93571f16..17d21518b 100644 --- a/src/portable/synopsys/dwc2/dwc2_nrf.h +++ b/src/portable/synopsys/dwc2/dwc2_nrf.h @@ -52,6 +52,11 @@ TU_ATTR_ALWAYS_INLINE static inline void dwc2_phy_init(dwc2_regs_t* dwc2, uint8_ (void)hs_phy_type; } +// MCU specific PHY deinit, disable PHY power +TU_ATTR_ALWAYS_INLINE static inline void dwc2_phy_deinit(dwc2_regs_t* dwc2) { + (void)dwc2; +} + // 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; diff --git a/src/portable/synopsys/dwc2/dwc2_stm32.h b/src/portable/synopsys/dwc2/dwc2_stm32.h index 753917a20..cc972e957 100644 --- a/src/portable/synopsys/dwc2/dwc2_stm32.h +++ b/src/portable/synopsys/dwc2/dwc2_stm32.h @@ -264,6 +264,20 @@ static inline void dwc2_phy_init(dwc2_regs_t* dwc2, uint8_t hs_phy_type) { } } +// MCU specific PHY deinit, disable PHY power +static inline void dwc2_phy_deinit(dwc2_regs_t* dwc2) { + // Disable on-chip FS PHY + dwc2->stm32_gccfg &= ~STM32_GCCFG_PWRDWN; + + // Disable HS PHY if present + #ifdef USB_HS_PHYC + dwc2->stm32_gccfg &= ~STM32_GCCFG_PHYHSEN; + // Disable PLL and LDO + USB_HS_PHYC->USB_HS_PHYC_PLL &= ~USB_HS_PHYC_PLL_PLLEN; + USB_HS_PHYC->USB_HS_PHYC_LDO &= ~USB_HS_PHYC_LDO_ENABLE; + #endif +} + // 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) { // used to set turnaround time for fullspeed, nothing to do in highspeed mode diff --git a/src/portable/synopsys/dwc2/dwc2_xmc.h b/src/portable/synopsys/dwc2/dwc2_xmc.h index 63419abf7..e38935e9c 100644 --- a/src/portable/synopsys/dwc2/dwc2_xmc.h +++ b/src/portable/synopsys/dwc2/dwc2_xmc.h @@ -71,6 +71,13 @@ static inline void dwc2_phy_init(dwc2_regs_t * dwc2, uint8_t hs_phy_type) //USB->ROUTE = USB_ROUTE_PHYPEN; } +// MCU specific PHY deinit, disable PHY power +static inline void dwc2_phy_deinit(dwc2_regs_t * dwc2) { + (void) dwc2; + + // nothing to do +} + // 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) { diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index 420b3fe4b..e12e44a41 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -448,8 +448,9 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { bool hcd_deinit(uint8_t rhport) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); - // Disable global interrupt - dwc2->gahbcfg &= ~GAHBCFG_GINT; + // Turn off VBUS + dwc2->hprt = HPRT_W1_MASK; // clear w1c bits without side effects + // HPRT_POWER is not set -> VBUS off dwc2_core_deinit(rhport); return true; @@ -1359,6 +1360,17 @@ static bool handle_sof_irq(uint8_t rhport, bool in_isr) { } // Config HCFG FS/LS clock and HFIR for SOF interval according to link speed (value is in PHY clock unit) +// Databook Table 2-2: System Clock Speeds +// +-----------+------------------+----------+-----------+-------------------+ +// | PHY | PHY Clock (MHz) | Width | HCFG.Sel | HFIR (clk cycles) | +// +-----------+------------------+----------+-----------+-------------------+ +// | HS UTMI+ | 30 | 16-bit | 30_60 | HS:3749 FS:29999 | +// | HS UTMI+ | 60 | 8-bit | 30_60 | HS:7499 FS:59999 | +// | HS ULPI | 60 | 8-bit | 30_60 | HS:7499 FS:59999 | +// | FS (dead.) | 48 | internal | 48 | FS:47999 | +// | LS via FS | 48 (6 effective) | internal | 6 | LS:47999 | +// +-----------+------------------+----------+-----------+-------------------+ +// HFIR = (interval_us * phy_clock) - 1, where interval is 125us (HS) or 1000us (FS/LS) static void port0_enable(dwc2_regs_t* dwc2, tusb_speed_t speed) { uint32_t hcfg = dwc2->hcfg & ~HCFG_FSLS_PHYCLK_SEL; -- cgit v1.3.1 From 1efe4cd0e84e965db7c5056f4339c83102e997ab Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 5 Mar 2026 10:01:40 +0700 Subject: add hs_phy_type parameter to dwc2_phy_deinit for selective PHY deinitialization across all MCUs --- src/portable/synopsys/dwc2/dwc2_at32.h | 3 ++- src/portable/synopsys/dwc2/dwc2_bcm.h | 3 ++- src/portable/synopsys/dwc2/dwc2_common.c | 4 +++- src/portable/synopsys/dwc2/dwc2_common.h | 2 +- src/portable/synopsys/dwc2/dwc2_efm32.h | 4 ++-- src/portable/synopsys/dwc2/dwc2_esp32.h | 3 ++- src/portable/synopsys/dwc2/dwc2_gd32.h | 3 ++- src/portable/synopsys/dwc2/dwc2_nrf.h | 3 ++- src/portable/synopsys/dwc2/dwc2_stm32.h | 24 +++++++++++++----------- src/portable/synopsys/dwc2/dwc2_xmc.h | 4 ++-- 10 files changed, 31 insertions(+), 22 deletions(-) (limited to 'src/portable') diff --git a/src/portable/synopsys/dwc2/dwc2_at32.h b/src/portable/synopsys/dwc2/dwc2_at32.h index 95ee8a8e1..fa6d10c12 100644 --- a/src/portable/synopsys/dwc2/dwc2_at32.h +++ b/src/portable/synopsys/dwc2/dwc2_at32.h @@ -113,7 +113,8 @@ TU_ATTR_ALWAYS_INLINE static inline void dwc2_phy_init(dwc2_regs_t *dwc2, uint8_ } // MCU specific PHY deinit, disable PHY power -TU_ATTR_ALWAYS_INLINE static inline void dwc2_phy_deinit(dwc2_regs_t *dwc2) { +TU_ATTR_ALWAYS_INLINE static inline void dwc2_phy_deinit(dwc2_regs_t *dwc2, uint8_t hs_phy_type) { + (void) hs_phy_type; dwc2->stm32_gccfg &= ~(STM32_GCCFG_PWRDWN | STM32_GCCFG_DCDEN | STM32_GCCFG_PDEN); } diff --git a/src/portable/synopsys/dwc2/dwc2_bcm.h b/src/portable/synopsys/dwc2/dwc2_bcm.h index 852db15e5..00842bba2 100644 --- a/src/portable/synopsys/dwc2/dwc2_bcm.h +++ b/src/portable/synopsys/dwc2/dwc2_bcm.h @@ -74,8 +74,9 @@ static inline void dwc2_phy_init(dwc2_regs_t * dwc2, uint8_t hs_phy_type) } // MCU specific PHY deinit, disable PHY power -static inline void dwc2_phy_deinit(dwc2_regs_t * dwc2) { +static inline void dwc2_phy_deinit(dwc2_regs_t * dwc2, uint8_t hs_phy_type) { (void) dwc2; + (void) hs_phy_type; // nothing to do } diff --git a/src/portable/synopsys/dwc2/dwc2_common.c b/src/portable/synopsys/dwc2/dwc2_common.c index 4e8e1ff04..33eabaeab 100644 --- a/src/portable/synopsys/dwc2/dwc2_common.c +++ b/src/portable/synopsys/dwc2/dwc2_common.c @@ -256,7 +256,9 @@ void dwc2_core_deinit(uint8_t rhport) { dwc2->pcgcctl |= PCGCCTL_STOPPCLK | PCGCCTL_GATEHCLK; // MCU-specific PHY deinit (disable PHY power) - dwc2_phy_deinit(dwc2); + const dwc2_ghwcfg2_t ghwcfg2 = {.value = dwc2->ghwcfg2}; + const uint8_t hs_phy_type = (dwc2->gusbcfg & GUSBCFG_PHYSEL) ? GHWCFG2_HSPHY_NOT_SUPPORTED : ghwcfg2.hs_phy_type; + dwc2_phy_deinit(dwc2, hs_phy_type); } // void dwc2_core_handle_common_irq(uint8_t rhport, bool in_isr) { diff --git a/src/portable/synopsys/dwc2/dwc2_common.h b/src/portable/synopsys/dwc2/dwc2_common.h index ac97ab3d5..9f28ab2e0 100644 --- a/src/portable/synopsys/dwc2/dwc2_common.h +++ b/src/portable/synopsys/dwc2/dwc2_common.h @@ -42,7 +42,7 @@ // - _dwc2_controller[]: array of controllers // - DWC2_EP_MAX: largest EP counts of all controllers // - dwc2_phy_init/dwc2_phy_update: phy init called before and after core reset -// - dwc2_phy_deinit: phy deinit to disable PHY power +// - dwc2_phy_deinit(dwc2, hs_phy_type): phy deinit to disable PHY power, only deinit the phy used by core // - dwc2_dcd_int_enable/dwc2_dcd_int_disable // - dwc2_remote_wakeup_delay diff --git a/src/portable/synopsys/dwc2/dwc2_efm32.h b/src/portable/synopsys/dwc2/dwc2_efm32.h index f808b567c..e1cb7c769 100644 --- a/src/portable/synopsys/dwc2/dwc2_efm32.h +++ b/src/portable/synopsys/dwc2/dwc2_efm32.h @@ -73,9 +73,9 @@ static inline void dwc2_phy_init(dwc2_regs_t * dwc2, uint8_t hs_phy_type) } // MCU specific PHY deinit, disable PHY power -static inline void dwc2_phy_deinit(dwc2_regs_t * dwc2) { +static inline void dwc2_phy_deinit(dwc2_regs_t * dwc2, uint8_t hs_phy_type) { (void) dwc2; - + (void) hs_phy_type; // Disable PHY pin USB->ROUTE = 0; } diff --git a/src/portable/synopsys/dwc2/dwc2_esp32.h b/src/portable/synopsys/dwc2/dwc2_esp32.h index f4fa0bf8b..ff9f216bd 100644 --- a/src/portable/synopsys/dwc2/dwc2_esp32.h +++ b/src/portable/synopsys/dwc2/dwc2_esp32.h @@ -122,8 +122,9 @@ TU_ATTR_ALWAYS_INLINE static inline void dwc2_phy_init(dwc2_regs_t* dwc2, uint8_ } // MCU specific PHY deinit, disable PHY power -TU_ATTR_ALWAYS_INLINE static inline void dwc2_phy_deinit(dwc2_regs_t* dwc2) { +TU_ATTR_ALWAYS_INLINE static inline void dwc2_phy_deinit(dwc2_regs_t* dwc2, uint8_t hs_phy_type) { (void)dwc2; + (void)hs_phy_type; // PHY managed by ESP-IDF } diff --git a/src/portable/synopsys/dwc2/dwc2_gd32.h b/src/portable/synopsys/dwc2/dwc2_gd32.h index 26b924161..ccbf93a76 100644 --- a/src/portable/synopsys/dwc2/dwc2_gd32.h +++ b/src/portable/synopsys/dwc2/dwc2_gd32.h @@ -86,8 +86,9 @@ static inline void dwc2_phy_init(dwc2_regs_t * dwc2, uint8_t hs_phy_type) } // MCU specific PHY deinit, disable PHY power -static inline void dwc2_phy_deinit(dwc2_regs_t * dwc2) { +static inline void dwc2_phy_deinit(dwc2_regs_t * dwc2, uint8_t hs_phy_type) { (void) dwc2; + (void) hs_phy_type; // nothing to do } diff --git a/src/portable/synopsys/dwc2/dwc2_nrf.h b/src/portable/synopsys/dwc2/dwc2_nrf.h index 17d21518b..51f2d684f 100644 --- a/src/portable/synopsys/dwc2/dwc2_nrf.h +++ b/src/portable/synopsys/dwc2/dwc2_nrf.h @@ -53,8 +53,9 @@ TU_ATTR_ALWAYS_INLINE static inline void dwc2_phy_init(dwc2_regs_t* dwc2, uint8_ } // MCU specific PHY deinit, disable PHY power -TU_ATTR_ALWAYS_INLINE static inline void dwc2_phy_deinit(dwc2_regs_t* dwc2) { +TU_ATTR_ALWAYS_INLINE static inline void dwc2_phy_deinit(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 diff --git a/src/portable/synopsys/dwc2/dwc2_stm32.h b/src/portable/synopsys/dwc2/dwc2_stm32.h index cc972e957..259ad21b9 100644 --- a/src/portable/synopsys/dwc2/dwc2_stm32.h +++ b/src/portable/synopsys/dwc2/dwc2_stm32.h @@ -265,17 +265,19 @@ static inline void dwc2_phy_init(dwc2_regs_t* dwc2, uint8_t hs_phy_type) { } // MCU specific PHY deinit, disable PHY power -static inline void dwc2_phy_deinit(dwc2_regs_t* dwc2) { - // Disable on-chip FS PHY - dwc2->stm32_gccfg &= ~STM32_GCCFG_PWRDWN; - - // Disable HS PHY if present - #ifdef USB_HS_PHYC - dwc2->stm32_gccfg &= ~STM32_GCCFG_PHYHSEN; - // Disable PLL and LDO - USB_HS_PHYC->USB_HS_PHYC_PLL &= ~USB_HS_PHYC_PLL_PLLEN; - USB_HS_PHYC->USB_HS_PHYC_LDO &= ~USB_HS_PHYC_LDO_ENABLE; - #endif +static inline void dwc2_phy_deinit(dwc2_regs_t* dwc2, uint8_t hs_phy_type) { + if (hs_phy_type == GHWCFG2_HSPHY_NOT_SUPPORTED) { + // Disable on-chip FS PHY + dwc2->stm32_gccfg &= ~STM32_GCCFG_PWRDWN; + } else { + // Disable HS PHY + #ifdef USB_HS_PHYC + dwc2->stm32_gccfg &= ~STM32_GCCFG_PHYHSEN; + // Disable PLL and LDO + USB_HS_PHYC->USB_HS_PHYC_PLL &= ~USB_HS_PHYC_PLL_PLLEN; + USB_HS_PHYC->USB_HS_PHYC_LDO &= ~USB_HS_PHYC_LDO_ENABLE; + #endif + } } // MCU specific PHY update, it is called AFTER init() and core reset diff --git a/src/portable/synopsys/dwc2/dwc2_xmc.h b/src/portable/synopsys/dwc2/dwc2_xmc.h index e38935e9c..aca3873df 100644 --- a/src/portable/synopsys/dwc2/dwc2_xmc.h +++ b/src/portable/synopsys/dwc2/dwc2_xmc.h @@ -72,9 +72,9 @@ static inline void dwc2_phy_init(dwc2_regs_t * dwc2, uint8_t hs_phy_type) } // MCU specific PHY deinit, disable PHY power -static inline void dwc2_phy_deinit(dwc2_regs_t * dwc2) { +static inline void dwc2_phy_deinit(dwc2_regs_t * dwc2, uint8_t hs_phy_type) { (void) dwc2; - + (void) hs_phy_type; // nothing to do } -- cgit v1.3.1 From 7088dc528bd5a89a77e06798d8b5384962748828 Mon Sep 17 00:00:00 2001 From: Zixun LI Date: Wed, 3 Dec 2025 16:26:56 +0100 Subject: ci_hs: add deinit support Signed-off-by: Zixun LI --- examples/dual/dynamic_switch/only.txt | 2 ++ hw/bsp/lpc43/family.c | 2 ++ src/portable/chipidea/ci_hs/dcd_ci_hs.c | 17 +++++++++++++++++ src/portable/chipidea/ci_hs/hcd_ci_hs.c | 12 ++++++++---- src/portable/ehci/ehci.c | 11 ++++++++--- src/portable/ehci/ehci_api.h | 3 +++ 6 files changed, 40 insertions(+), 7 deletions(-) (limited to 'src/portable') diff --git a/examples/dual/dynamic_switch/only.txt b/examples/dual/dynamic_switch/only.txt index 8508780e6..70be49b28 100644 --- a/examples/dual/dynamic_switch/only.txt +++ b/examples/dual/dynamic_switch/only.txt @@ -1,4 +1,6 @@ family:espressif +mcu:LPC43XX +mcu:MIMXRT1XXX mcu:STM32C0 mcu:STM32G0 mcu:STM32H5 diff --git a/hw/bsp/lpc43/family.c b/hw/bsp/lpc43/family.c index bade53b07..56834a1b0 100644 --- a/hw/bsp/lpc43/family.c +++ b/hw/bsp/lpc43/family.c @@ -185,8 +185,10 @@ void board_init(void) */ Chip_USB1_Init(); +#ifdef _BOARD_EA4357_H // USB0 Vbus Power: P2_3 on EA4357 channel B U20 GPIO26 active low (base board) Chip_SCU_PinMuxSet(2, 3, SCU_MODE_PULLUP | SCU_MODE_INBUFF_EN | SCU_MODE_FUNC7); +#endif #if defined(BOARD_TUD_RHPORT) && BOARD_TUD_RHPORT == 0 // P9_5 (GPIO5[18]) (GPIO28 on oem base) as USB connect, active low. diff --git a/src/portable/chipidea/ci_hs/dcd_ci_hs.c b/src/portable/chipidea/ci_hs/dcd_ci_hs.c index 2bba32ada..b9f6a8a7b 100644 --- a/src/portable/chipidea/ci_hs/dcd_ci_hs.c +++ b/src/portable/chipidea/ci_hs/dcd_ci_hs.c @@ -285,6 +285,23 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t *rh_init) { return true; } +bool dcd_deinit(uint8_t rhport) { + ci_hs_regs_t* dcd_reg = CI_HS_REG(rhport); + + // disable all interrupt + dcd_reg->USBINTR = 0; + + // unattach from bus + dcd_reg->USBCMD &= ~USBCMD_RUN_STOP; + + // flush all endpoints + while (dcd_reg->ENDPTPRIME) {} + dcd_reg->ENDPTFLUSH = 0xFFFFFFFF; + while (dcd_reg->ENDPTFLUSH) {} + + return true; +} + void dcd_int_enable(uint8_t rhport) { CI_DCD_INT_ENABLE(rhport); } diff --git a/src/portable/chipidea/ci_hs/hcd_ci_hs.c b/src/portable/chipidea/ci_hs/hcd_ci_hs.c index 29ce0cd7f..91adc06b1 100644 --- a/src/portable/chipidea/ci_hs/hcd_ci_hs.c +++ b/src/portable/chipidea/ci_hs/hcd_ci_hs.c @@ -93,14 +93,14 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t *rh_init) { hcd_reg->USBCMD |= USBCMD_RESET; while (hcd_reg->USBCMD & USBCMD_RESET) {} - // Set mode to device, must be set immediately after reset + // Set mode to host, must be set immediately after reset #if CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX // LPC18XX/43XX need to set VBUS Power Select to HIGH // RHPORT1 is fullspeed only (need external PHY for Highspeed) hcd_reg->USBMODE = USBMODE_CM_HOST | USBMODE_VBUS_POWER_SELECT; - if (rhport == 1) { - hcd_reg->PORTSC1 |= PORTSC1_FORCE_FULL_SPEED; - } + #if !TUH_OPT_HIGH_SPEED + hcd_reg->PORTSC1 = PORTSC1_FORCE_FULL_SPEED; + #endif #else hcd_reg->USBMODE = USBMODE_CM_HOST; #endif @@ -108,6 +108,10 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t *rh_init) { return ehci_init(rhport, (uint32_t)&hcd_reg->CAPLENGTH, (uint32_t)&hcd_reg->USBCMD); } +bool hcd_deinit(uint8_t rhport) { + return ehci_deinit(rhport); +} + void hcd_int_enable(uint8_t rhport) { CI_HCD_INT_ENABLE(rhport); } diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c index 9b2cf98be..03c3b91fd 100644 --- a/src/portable/ehci/ehci.c +++ b/src/portable/ehci/ehci.c @@ -411,17 +411,22 @@ bool ehci_init(uint8_t rhport, uint32_t capability_reg, uint32_t operatial_reg) return true; } -#if 0 -static void ehci_stop(uint8_t rhport) { +bool ehci_deinit(uint8_t rhport) { (void) rhport; ehci_registers_t* regs = ehci_data.regs; + + // Disable all the interrupt + regs->inten = 0; + + // Disable schedules regs->command_bm.run_stop = 0; // USB Spec: controller has to stop within 16 uframe = 2 frames while( regs->status_bm.hc_halted == 0 ) {} + + return true; } -#endif //--------------------------------------------------------------------+ // Endpoint API diff --git a/src/portable/ehci/ehci_api.h b/src/portable/ehci/ehci_api.h index 79fbe702a..e9018639f 100644 --- a/src/portable/ehci/ehci_api.h +++ b/src/portable/ehci/ehci_api.h @@ -38,6 +38,9 @@ // Initialize EHCI driver bool ehci_init(uint8_t rhport, uint32_t capability_reg, uint32_t operatial_reg); +// De-initialize EHCI driver +bool ehci_deinit(uint8_t rhport); + #ifdef __cplusplus } #endif -- cgit v1.3.1 From 4ed45cf9bc866750492210b0a14bf751d43421ab Mon Sep 17 00:00:00 2001 From: Zixun LI Date: Thu, 5 Mar 2026 16:23:24 +0100 Subject: update PORTSC1 Signed-off-by: Zixun LI --- src/portable/chipidea/ci_hs/hcd_ci_hs.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/portable') diff --git a/src/portable/chipidea/ci_hs/hcd_ci_hs.c b/src/portable/chipidea/ci_hs/hcd_ci_hs.c index 91adc06b1..c0d14fe57 100644 --- a/src/portable/chipidea/ci_hs/hcd_ci_hs.c +++ b/src/portable/chipidea/ci_hs/hcd_ci_hs.c @@ -96,15 +96,15 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t *rh_init) { // Set mode to host, must be set immediately after reset #if CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX // LPC18XX/43XX need to set VBUS Power Select to HIGH - // RHPORT1 is fullspeed only (need external PHY for Highspeed) hcd_reg->USBMODE = USBMODE_CM_HOST | USBMODE_VBUS_POWER_SELECT; - #if !TUH_OPT_HIGH_SPEED - hcd_reg->PORTSC1 = PORTSC1_FORCE_FULL_SPEED; - #endif #else hcd_reg->USBMODE = USBMODE_CM_HOST; #endif + #if !TUH_OPT_HIGH_SPEED + hcd_reg->PORTSC1 |= PORTSC1_FORCE_FULL_SPEED; + #endif + return ehci_init(rhport, (uint32_t)&hcd_reg->CAPLENGTH, (uint32_t)&hcd_reg->USBCMD); } -- cgit v1.3.1 From 94baf394686f92d9edaf109dcae30fa7b531fefc Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 6 Mar 2026 10:59:32 +0700 Subject: fix warnings --- hw/bsp/stm32f1/family.c | 4 ++-- hw/bsp/stm32l0/family.c | 3 ++- hw/bsp/stm32wba/family.c | 5 ++++- lib/networking/rndis_reports.c | 2 +- src/portable/chipidea/ci_hs/ci_hs_lpc18_43.h | 8 ++++---- 5 files changed, 13 insertions(+), 9 deletions(-) (limited to 'src/portable') diff --git a/hw/bsp/stm32f1/family.c b/hw/bsp/stm32f1/family.c index fae61ca9e..78a425453 100644 --- a/hw/bsp/stm32f1/family.c +++ b/hw/bsp/stm32f1/family.c @@ -148,12 +148,12 @@ void board_init(void) { #ifdef USB_CONNECT_PIN void dcd_disconnect(uint8_t rhport) { (void)rhport; - HAL_GPIO_WritePin(USB_CONNECT_PORT, USB_CONNECT_PIN, 1-USB_CONNECT_STATE); + HAL_GPIO_WritePin(USB_CONNECT_PORT, USB_CONNECT_PIN, (GPIO_PinState)(1 - USB_CONNECT_STATE)); } void dcd_connect(uint8_t rhport) { (void)rhport; - HAL_GPIO_WritePin(USB_CONNECT_PORT, USB_CONNECT_PIN, USB_CONNECT_STATE); + HAL_GPIO_WritePin(USB_CONNECT_PORT, USB_CONNECT_PIN, (GPIO_PinState)USB_CONNECT_STATE); } #endif diff --git a/hw/bsp/stm32l0/family.c b/hw/bsp/stm32l0/family.c index 192f014f4..7fd076dbd 100644 --- a/hw/bsp/stm32l0/family.c +++ b/hw/bsp/stm32l0/family.c @@ -123,7 +123,8 @@ void board_init(void) { //--------------------------------------------------------------------+ void board_led_write(bool state) { - HAL_GPIO_WritePin(LED_PORT, LED_PIN, state ? LED_STATE_ON : (1 - LED_STATE_ON)); + GPIO_PinState pin_state = (GPIO_PinState)(state ? LED_STATE_ON : (1 - LED_STATE_ON)); + HAL_GPIO_WritePin(LED_PORT, LED_PIN, pin_state); } uint32_t board_button_read(void) { diff --git a/hw/bsp/stm32wba/family.c b/hw/bsp/stm32wba/family.c index e058a80a1..878355b48 100644 --- a/hw/bsp/stm32wba/family.c +++ b/hw/bsp/stm32wba/family.c @@ -175,7 +175,10 @@ void board_init(void) { #endif // USB_OTG_HS } -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) { + GPIO_PinState pin_state = (GPIO_PinState)(state ? LED_STATE_ON : (1 - LED_STATE_ON)); + HAL_GPIO_WritePin(LED_PORT, LED_PIN, pin_state); +} uint32_t board_button_read(void) { return HAL_GPIO_ReadPin(BUTTON_PORT, BUTTON_PIN) == BUTTON_STATE_ACTIVE; } diff --git a/lib/networking/rndis_reports.c b/lib/networking/rndis_reports.c index e2849fb10..5e824d5a5 100644 --- a/lib/networking/rndis_reports.c +++ b/lib/networking/rndis_reports.c @@ -44,7 +44,7 @@ static const uint8_t *const permanent_hwaddr = tud_network_mac_address; static usb_eth_stat_t usb_eth_stat = { 0, 0, 0, 0 }; static uint32_t oid_packet_filter = 0x0000000; -static rndis_state_t rndis_state; +TU_ATTR_UNUSED static rndis_state_t rndis_state; static const uint32_t OIDSupportedList[] = { diff --git a/src/portable/chipidea/ci_hs/ci_hs_lpc18_43.h b/src/portable/chipidea/ci_hs/ci_hs_lpc18_43.h index 178eec419..c22aea887 100644 --- a/src/portable/chipidea/ci_hs/ci_hs_lpc18_43.h +++ b/src/portable/chipidea/ci_hs/ci_hs_lpc18_43.h @@ -47,10 +47,10 @@ static const ci_hs_controller_t _ci_controller[] = #define CI_HS_REG(_port) ((ci_hs_regs_t*) _ci_controller[_port].reg_base) -#define CI_DCD_INT_ENABLE(_p) NVIC_EnableIRQ (_ci_controller[_p].irqnum) -#define CI_DCD_INT_DISABLE(_p) NVIC_DisableIRQ(_ci_controller[_p].irqnum) +#define CI_DCD_INT_ENABLE(_p) NVIC_EnableIRQ ((IRQn_Type)_ci_controller[_p].irqnum) +#define CI_DCD_INT_DISABLE(_p) NVIC_DisableIRQ((IRQn_Type)_ci_controller[_p].irqnum) -#define CI_HCD_INT_ENABLE(_p) NVIC_EnableIRQ (_ci_controller[_p].irqnum) -#define CI_HCD_INT_DISABLE(_p) NVIC_DisableIRQ(_ci_controller[_p].irqnum) +#define CI_HCD_INT_ENABLE(_p) NVIC_EnableIRQ ((IRQn_Type)_ci_controller[_p].irqnum) +#define CI_HCD_INT_DISABLE(_p) NVIC_DisableIRQ((IRQn_Type)_ci_controller[_p].irqnum) #endif -- cgit v1.3.1 From ee6f4f6f2a1f07db7c145551b779ce8cf878c2ac Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 6 Mar 2026 11:59:20 +0100 Subject: cleanup Signed-off-by: HiFiPhile --- src/portable/microchip/samx7x/dcd_samx7x.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'src/portable') diff --git a/src/portable/microchip/samx7x/dcd_samx7x.c b/src/portable/microchip/samx7x/dcd_samx7x.c index 8dd333e0f..9f62781bb 100644 --- a/src/portable/microchip/samx7x/dcd_samx7x.c +++ b/src/portable/microchip/samx7x/dcd_samx7x.c @@ -570,9 +570,6 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t *ff, uint16_t const uint8_t dir = tu_edpt_dir(ep_addr); xfer_ctl_t *xfer = &xfer_status[epnum]; - if (epnum == 0x80) { - xfer = &xfer_status[EP_MAX]; - } xfer->buffer = NULL; xfer->total_len = total_bytes; -- cgit v1.3.1 From 6a190546e68c55f81d865dfddee6205ddc6fa941 Mon Sep 17 00:00:00 2001 From: Zixun LI Date: Fri, 6 Mar 2026 12:47:21 +0100 Subject: Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/portable/microchip/samx7x/dcd_samx7x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/portable') diff --git a/src/portable/microchip/samx7x/dcd_samx7x.c b/src/portable/microchip/samx7x/dcd_samx7x.c index 9f62781bb..bd158b47d 100644 --- a/src/portable/microchip/samx7x/dcd_samx7x.c +++ b/src/portable/microchip/samx7x/dcd_samx7x.c @@ -321,7 +321,7 @@ static void dcd_dma_handler(uint8_t ep_ix) { if (USB_REG->DEVEPTCFG[ep_ix] & DEVEPTCFG_EPDIR) { dcd_event_xfer_complete(0, 0x80 + ep_ix, count, XFER_RESULT_SUCCESS, true); } else { - dcd_dcache_invalidate(xfer->buffer, xfer->total_len); + dcd_dcache_invalidate(xfer->buffer, count); dcd_event_xfer_complete(0, ep_ix, count, XFER_RESULT_SUCCESS, true); } } @@ -600,6 +600,6 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { (void)rhport; const uint8_t epnum = tu_edpt_number(ep_addr); USB_REG->DEVEPTIDR[epnum] = DEVEPTIDR_CTRL_STALLRQC; - USB_REG->DEVEPTIER[epnum] = HSTPIPIER_RSTDTS; + USB_REG->DEVEPTIER[epnum] = DEVEPTIER_RSTDTS; } #endif -- cgit v1.3.1 From 1c53009dc70e8535347f83cd9f3024ea495a085c Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 7 Mar 2026 13:07:13 +0700 Subject: remove dma_desc_t --- src/portable/microchip/samx7x/dcd_samx7x.c | 8 -------- src/portable/microchip/samx7x/samx7x_common.h | 2 +- 2 files changed, 1 insertion(+), 9 deletions(-) (limited to 'src/portable') diff --git a/src/portable/microchip/samx7x/dcd_samx7x.c b/src/portable/microchip/samx7x/dcd_samx7x.c index bd158b47d..6da1e9778 100644 --- a/src/portable/microchip/samx7x/dcd_samx7x.c +++ b/src/portable/microchip/samx7x/dcd_samx7x.c @@ -50,14 +50,6 @@ #define EP_GET_FIFO_PTR(ep, scale) \ (((TU_XSTRCAT(TU_STRCAT(uint, scale), _t)(*)[0x8000 / ((scale) / 8)]) FIFO_RAM_ADDR)[(ep)]) -// DMA Channel Transfer Descriptor -typedef struct { - volatile uint32_t next_desc; - volatile uint32_t buff_addr; - volatile uint32_t chnl_ctrl; - uint32_t padding; -} dma_desc_t; - // Transfer control context typedef struct { uint8_t *buffer; diff --git a/src/portable/microchip/samx7x/samx7x_common.h b/src/portable/microchip/samx7x/samx7x_common.h index 4fd63b7f8..5e3c20c0f 100644 --- a/src/portable/microchip/samx7x/samx7x_common.h +++ b/src/portable/microchip/samx7x/samx7x_common.h @@ -1,4 +1,4 @@ - /* +/* * The MIT License (MIT) * * Copyright (c) 2019 Microchip Technology Inc. -- cgit v1.3.1 From 11a3c3b712eb97e5c05ed3df20dcde9451fe158d Mon Sep 17 00:00:00 2001 From: gab-k Date: Sat, 7 Mar 2026 21:53:01 +0100 Subject: Fix ep_ctrl_mask() corrupting opposite direction's ENDPTCTRL bits --- src/portable/chipidea/ci_hs/dcd_ci_hs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/portable') diff --git a/src/portable/chipidea/ci_hs/dcd_ci_hs.c b/src/portable/chipidea/ci_hs/dcd_ci_hs.c index b9f6a8a7b..9ed75ffd9 100644 --- a/src/portable/chipidea/ci_hs/dcd_ci_hs.c +++ b/src/portable/chipidea/ci_hs/dcd_ci_hs.c @@ -388,7 +388,7 @@ TU_ATTR_ALWAYS_INLINE static inline void ep_ctrl_mask(volatile uint32_t *epctrl, uint32_t or_mask) { uint32_t value = *epctrl; if (and_mask != 0) { - value &= (dir == TUSB_DIR_OUT) ? and_mask : (and_mask << 16u); + value &= (dir == TUSB_DIR_OUT) ? (and_mask | 0xFFFF0000u) : ((and_mask << 16u) | 0x0000FFFFu); } if (or_mask != 0) { value |= (dir == TUSB_DIR_OUT) ? or_mask : (or_mask << 16u); -- cgit v1.3.1 From 3eb2b1fe52cdca89be082295e5ff8c4fed43cc39 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 10 Mar 2026 17:17:59 +0700 Subject: fix typo --- src/portable/nxp/lpc_ip3516/hcd_lpc_ip3516.c | 44 +++++++++++++++++----------- src/portable/nxp/lpc_ip3516/hcd_lpc_ip3516.h | 2 +- 2 files changed, 28 insertions(+), 18 deletions(-) (limited to 'src/portable') diff --git a/src/portable/nxp/lpc_ip3516/hcd_lpc_ip3516.c b/src/portable/nxp/lpc_ip3516/hcd_lpc_ip3516.c index 32ef99418..c9810f51c 100644 --- a/src/portable/nxp/lpc_ip3516/hcd_lpc_ip3516.c +++ b/src/portable/nxp/lpc_ip3516/hcd_lpc_ip3516.c @@ -72,11 +72,15 @@ #define USBHSH_PORTSC1_W1C_MASK (USBHSH_PORTSC1_CSC_MASK | USBHSH_PORTSC1_PEDC_MASK | USBHSH_PORTSC1_OCC_MASK) +#define IP3516_PSPD_LOW 0 +#define IP3516_PSPD_FULL 1 +#define IP3516_PSPD_HIGH 2 + //--------------------------------------------------------------------+ // Proprietary Transfer Descriptor //--------------------------------------------------------------------+ -CFG_TUD_MEM_SECTION TU_ATTR_ALIGNED(1024) static ip3516_ptd_t _ptd; +CFG_TUH_MEM_SECTION TU_ATTR_ALIGNED(1024) static ip3516_ptd_t _ptd; static struct { uint32_t uframe_number; @@ -92,7 +96,7 @@ static inline bool is_ptd_free(const ptd_ctrl1_t ctrl1) { return ctrl1.mps == 0; } -static inline bool is_xfer_asyc(tusb_xfer_type_t xfer_type) { +static inline bool is_xfer_async(tusb_xfer_type_t xfer_type) { return (xfer_type == TUSB_XFER_CONTROL || xfer_type == TUSB_XFER_BULK); } @@ -132,7 +136,7 @@ static inline uint8_t ptd_find_free(tusb_xfer_type_t xfer_type) { for (uint8_t i = 0; i < max_count; i++) { // For ATL: stride is sizeof(ip3516_atl_t) = 16 bytes = 4 words // For PTL: stride is sizeof(ip3516_ptl_t) = 32 bytes = 8 words - uint8_t stride = is_xfer_asyc(xfer_type) ? sizeof(ip3516_atl_t) : sizeof(ip3516_ptl_t); + uint8_t stride = is_xfer_async(xfer_type) ? sizeof(ip3516_atl_t) : sizeof(ip3516_ptl_t); ptd_ctrl1_t *ctrl1 = (ptd_ctrl1_t *)(ptd_array + i * stride); if (is_ptd_free(*ctrl1)) { @@ -161,11 +165,14 @@ static void close_ptds_by_device(uint8_t dev_addr, intptr_t ptd_array, uint8_t m } if (skip_mask) { - // Wait 1 uframe for PTDs to be inactive + // Wait 1 uframe for PTDs to be inactive (with timeout) uint32_t start_uframe = (USBHSH->FLADJ_FRINDEX & USBHSH_FLADJ_FRINDEX_FRINDEX_MASK) >> USBHSH_FLADJ_FRINDEX_FRINDEX_SHIFT; + uint32_t timeout = 10000; while (((USBHSH->FLADJ_FRINDEX & USBHSH_FLADJ_FRINDEX_FRINDEX_MASK) >> USBHSH_FLADJ_FRINDEX_FRINDEX_SHIFT) == - start_uframe) {} + start_uframe && timeout > 0) { + timeout--; + } // Clear PTDs for (uint8_t i = 0; i < max_count; i++) { @@ -220,11 +227,14 @@ static bool find_and_close_ptd(uint8_t dev_addr, uint8_t ep_num, uint8_t ep_dir, if (skip_reg) { *skip_reg |= (1 << i); - // Wait 1 uframe for PTD to be inactive + // Wait 1 uframe for PTD to be inactive (with timeout) uint32_t start_uframe = (USBHSH->FLADJ_FRINDEX & USBHSH_FLADJ_FRINDEX_FRINDEX_MASK) >> USBHSH_FLADJ_FRINDEX_FRINDEX_SHIFT; + uint32_t timeout = 10000; while (((USBHSH->FLADJ_FRINDEX & USBHSH_FLADJ_FRINDEX_FRINDEX_MASK) >> USBHSH_FLADJ_FRINDEX_FRINDEX_SHIFT) == - start_uframe) {} + start_uframe && timeout > 0) { + timeout--; + } // Just clear state ptd_ctrl1_t *ptd_ctrl1 = (ptd_ctrl1_t *)(ptd_ptr + offsetof(ip3516_atl_t, ctrl1)); @@ -272,7 +282,7 @@ static intptr_t find_opened_ptd(uint8_t dev_addr, uint8_t ep_addr) { } } - return TUSB_INDEX_INVALID_8; + return 0; } static bool edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t *buffer, uint16_t buflen, bool is_setup) { @@ -280,7 +290,7 @@ static bool edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t *buffer, uint16 const uint8_t ep_dir = tu_edpt_dir(ep_addr); intptr_t ptd_ptr = find_opened_ptd(dev_addr, ep_addr); - TU_ASSERT(ptd_ptr != TUSB_INDEX_INVALID_8); + TU_ASSERT(ptd_ptr != 0); ptd_ctrl1_t *ptd_ctrl1 = (ptd_ctrl1_t *)(ptd_ptr + offsetof(ip3516_atl_t, ctrl1)); ptd_ctrl2_t *ptd_ctrl2 = (ptd_ctrl2_t *)(ptd_ptr + offsetof(ip3516_atl_t, ctrl2)); @@ -305,7 +315,7 @@ static bool edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t *buffer, uint16 } } - // Interrupt split transfer needs to be relauched manually if NAKed + // Interrupt split transfer needs to be relaunched manually if NAKed if (ptd_ctrl2->split && ptd_state->ep_type == TUSB_XFER_INTERRUPT) { ptd_ctrl2->reload = 0x0f; ptd_state->nak_cnt = 0x0f; @@ -422,7 +432,7 @@ void hcd_port_reset_end(uint8_t rhport) { while (USBHSH->PORTSC1 & USBHSH_PORTSC1_PR_MASK) {} #if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U)) uint32_t pspd = (USBHSH->PORTSC1 & USBHSH_PORTSC1_PSPD_MASK) >> USBHSH_PORTSC1_PSPD_SHIFT; - if (pspd == 2) { + if (pspd == IP3516_PSPD_HIGH) { // enable phy disconnection for high speed USBPHY->CTRL |= USBPHY_CTRL_ENHOSTDISCONDETECT_MASK; } @@ -440,11 +450,11 @@ tusb_speed_t hcd_port_speed_get(uint8_t rhport) { (void)rhport; uint32_t pspd = (USBHSH->PORTSC1 & USBHSH_PORTSC1_PSPD_MASK) >> USBHSH_PORTSC1_PSPD_SHIFT; switch (pspd) { - case 0: + case IP3516_PSPD_LOW: return TUSB_SPEED_LOW; - case 1: + case IP3516_PSPD_FULL: return TUSB_SPEED_FULL; - case 2: + case IP3516_PSPD_HIGH: return TUSB_SPEED_HIGH; default: return TUSB_SPEED_INVALID; @@ -473,7 +483,7 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr) { //--------------------------------------------------------------------+ static inline intptr_t get_ptd_from_index(tusb_xfer_type_t xfer_type, uint8_t ptd_index) { - if (is_xfer_asyc(xfer_type)) { + if (is_xfer_async(xfer_type)) { return (intptr_t)&_ptd.atl[ptd_index]; } else { if (xfer_type == TUSB_XFER_INTERRUPT) { @@ -522,7 +532,7 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, const tusb_desc_endpoint_t state->ep_type = (uint32_t)xfer_type; state->token = tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN ? IP3516_PTD_TOKEN_IN : IP3516_PTD_TOKEN_OUT; - if (!is_xfer_asyc(xfer_type)) { + if (!is_xfer_async(xfer_type)) { ip3516_ptl_t *ptd = (ip3516_ptl_t *)ptd_ptr; uint32_t uframe_interval; @@ -709,7 +719,7 @@ bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { (void)rhport; intptr_t ptd_ptr = find_opened_ptd(dev_addr, ep_addr); - TU_ASSERT(ptd_ptr != TUSB_INDEX_INVALID_8); + TU_ASSERT(ptd_ptr != 0); ptd_state_t *ptd_state = (ptd_state_t *)(ptd_ptr + offsetof(ip3516_atl_t, state)); ptd_clear_state(ptd_state); diff --git a/src/portable/nxp/lpc_ip3516/hcd_lpc_ip3516.h b/src/portable/nxp/lpc_ip3516/hcd_lpc_ip3516.h index 38c3a3224..5214c18ae 100644 --- a/src/portable/nxp/lpc_ip3516/hcd_lpc_ip3516.h +++ b/src/portable/nxp/lpc_ip3516/hcd_lpc_ip3516.h @@ -57,7 +57,7 @@ extern "C" { //--------------------------------------------------------------------+ -// OHCI Data Structure +// IP3516 PTD Data Structure //--------------------------------------------------------------------+ // Control Word 1 -- cgit v1.3.1 From 9b2f6f4f0cb0d7c1227c87093382a7fb9eea35c9 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 16 Mar 2026 18:01:02 +0700 Subject: Consolidate USB FSDEV register definitions for STM32, CH32, and AT32 microcontrollers. Replace vendor-specific macros with unified `U_`-prefixed equivalents, ensuring consistency and reducing duplication across all platforms. --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 116 ++++++------- src/portable/st/stm32_fsdev/fsdev_at32.h | 110 +----------- src/portable/st/stm32_fsdev/fsdev_ch32.h | 106 ------------ src/portable/st/stm32_fsdev/fsdev_common.c | 8 +- src/portable/st/stm32_fsdev/fsdev_common.h | 232 +++++++++++++++++++++----- src/portable/st/stm32_fsdev/fsdev_stm32.h | 145 ++-------------- src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c | 116 ++++++------- 7 files changed, 333 insertions(+), 500 deletions(-) (limited to 'src/portable') diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index a6abc6244..965ebbbe5 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -184,7 +184,7 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t *rh_init) { // Enable interrupts for device mode FSDEV_REG->CNTR |= - USB_CNTR_RESETM | USB_CNTR_ESOFM | USB_CNTR_CTRM | USB_CNTR_SUSPM | USB_CNTR_WKUPM | USB_CNTR_PMAOVRM; + U_CNTR_RESETM | U_CNTR_ESOFM | U_CNTR_CTRM | U_CNTR_SUSPM | U_CNTR_WKUPM | U_CNTR_PMAOVRM; handle_bus_reset(rhport); @@ -206,9 +206,9 @@ void dcd_sof_enable(uint8_t rhport, bool en) { (void)rhport; if (en) { - FSDEV_REG->CNTR |= USB_CNTR_SOFM; + FSDEV_REG->CNTR |= U_CNTR_SOFM; } else { - FSDEV_REG->CNTR &= ~USB_CNTR_SOFM; + FSDEV_REG->CNTR &= ~U_CNTR_SOFM; } } @@ -226,7 +226,7 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) { void dcd_remote_wakeup(uint8_t rhport) { (void)rhport; - FSDEV_REG->CNTR |= USB_CNTR_RESUME; + FSDEV_REG->CNTR |= U_CNTR_RESUME; remoteWakeCountdown = 4u; // required to be 1 to 15 ms, ESOF should trigger every 1ms. } @@ -246,14 +246,14 @@ static void handle_bus_reset(uint8_t rhport) { edpt0_open(rhport); // open control endpoint (both IN & OUT) - FSDEV_REG->DADDR = USB_DADDR_EF; // Enable USB Function + FSDEV_REG->DADDR = U_DADDR_EF; // Enable USB Function } // Handle CTR interrupt for the TX/IN direction static void handle_ctr_tx(uint32_t ep_id) { - uint32_t ep_reg = ep_read(ep_id) | USB_EP_CTR_TX | USB_EP_CTR_RX; + uint32_t ep_reg = ep_read(ep_id) | U_EP_CTR_TX | U_EP_CTR_RX; - const uint8_t ep_num = ep_reg & USB_EPADDR_FIELD; + const uint8_t ep_num = ep_reg & U_EPADDR_FIELD; xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, TUSB_DIR_IN); if (ep_is_iso(ep_reg)) { @@ -265,7 +265,7 @@ static void handle_ctr_tx(uint32_t ep_id) { } xfer->iso_in_sending = false; #if FSDEV_USE_SBUF_ISO == 0 - uint8_t buf_id = (ep_reg & USB_EP_DTOG_TX) ? 0 : 1; + uint8_t buf_id = (ep_reg & U_EP_DTOG_TX) ? 0 : 1; #else uint8_t buf_id = BTABLE_BUF_TX; #endif @@ -302,8 +302,8 @@ static void handle_ctr_setup(uint32_t ep_id) { // Handle CTR interrupt for the RX/OUT direction static void handle_ctr_rx(uint32_t ep_id) { - uint32_t ep_reg = ep_read(ep_id) | USB_EP_CTR_TX | USB_EP_CTR_RX; - const uint8_t ep_num = ep_reg & USB_EPADDR_FIELD; + uint32_t ep_reg = ep_read(ep_id) | U_EP_CTR_TX | U_EP_CTR_RX; + const uint8_t ep_num = ep_reg & U_EPADDR_FIELD; const bool is_iso = ep_is_iso(ep_reg); xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, TUSB_DIR_OUT); @@ -314,7 +314,7 @@ static void handle_ctr_rx(uint32_t ep_id) { bool const dbl_buf = false; #endif if (dbl_buf) { - buf_id = (ep_reg & USB_EP_DTOG_RX) ? 0 : 1; + buf_id = (ep_reg & U_EP_DTOG_RX) ? 0 : 1; } else { buf_id = BTABLE_BUF_RX; } @@ -346,7 +346,7 @@ static void handle_ctr_rx(uint32_t ep_id) { const uint16_t cnt = tu_min16(xfer->total_len - xfer->queued_len, xfer->max_packet_size); btable_set_rx_bufsize(ep_id, BTABLE_BUF_RX, cnt); } - ep_reg &= USB_EPREG_MASK | EP_STAT_MASK(TUSB_DIR_OUT); // will change RX Status, reserved other toggle bits + ep_reg &= U_EPREG_MASK | EP_STAT_MASK(TUSB_DIR_OUT); // will change RX Status, reserved other toggle bits ep_change_status(&ep_reg, TUSB_DIR_OUT, EP_STAT_VALID); ep_write(ep_id, ep_reg, false); } @@ -356,57 +356,57 @@ void dcd_int_handler(uint8_t rhport) { uint32_t int_status = FSDEV_REG->ISTR; /* Put SOF flag at the beginning of ISR in case to get least amount of jitter if it is used for timing purposes */ - if (int_status & USB_ISTR_SOF) { - FSDEV_REG->ISTR = (fsdev_bus_t)~USB_ISTR_SOF; - dcd_event_sof(0, FSDEV_REG->FNR & USB_FNR_FN, true); + if (int_status & U_ISTR_SOF) { + FSDEV_REG->ISTR = (fsdev_bus_t)~U_ISTR_SOF; + dcd_event_sof(0, FSDEV_REG->FNR & U_FNR_FN, true); } - if (int_status & USB_ISTR_RESET) { + if (int_status & U_ISTR_RESET) { // USBRST is start of reset. - FSDEV_REG->ISTR = (fsdev_bus_t)~USB_ISTR_RESET; + FSDEV_REG->ISTR = (fsdev_bus_t)~U_ISTR_RESET; handle_bus_reset(rhport); dcd_event_bus_reset(0, TUSB_SPEED_FULL, true); return; // Don't do the rest of the things here; perhaps they've been cleared? } - if (int_status & USB_ISTR_WKUP) { - FSDEV_REG->CNTR &= ~USB_CNTR_LPMODE; - FSDEV_REG->CNTR &= ~USB_CNTR_FSUSP; + if (int_status & U_ISTR_WKUP) { + FSDEV_REG->CNTR &= ~U_CNTR_LPMODE; + FSDEV_REG->CNTR &= ~U_CNTR_FSUSP; - FSDEV_REG->ISTR = (fsdev_bus_t)~USB_ISTR_WKUP; + FSDEV_REG->ISTR = (fsdev_bus_t)~U_ISTR_WKUP; dcd_event_bus_signal(0, DCD_EVENT_RESUME, true); } - if (int_status & USB_ISTR_SUSP) { + if (int_status & U_ISTR_SUSP) { /* Suspend is asserted for both suspend and unplug events. without Vbus monitoring, * these events cannot be differentiated, so we only trigger suspend. */ /* Force low-power mode in the macrocell */ - FSDEV_REG->CNTR |= USB_CNTR_FSUSP; - FSDEV_REG->CNTR |= USB_CNTR_LPMODE; + FSDEV_REG->CNTR |= U_CNTR_FSUSP; + FSDEV_REG->CNTR |= U_CNTR_LPMODE; /* clear of the ISTR bit must be done after setting of CNTR_FSUSP */ - FSDEV_REG->ISTR = (fsdev_bus_t)~USB_ISTR_SUSP; + FSDEV_REG->ISTR = (fsdev_bus_t)~U_ISTR_SUSP; dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true); } - if (int_status & USB_ISTR_ESOF) { + if (int_status & U_ISTR_ESOF) { if (remoteWakeCountdown == 1u) { - FSDEV_REG->CNTR &= ~USB_CNTR_RESUME; + FSDEV_REG->CNTR &= ~U_CNTR_RESUME; } if (remoteWakeCountdown > 0u) { remoteWakeCountdown--; } - FSDEV_REG->ISTR = (fsdev_bus_t)~USB_ISTR_ESOF; + FSDEV_REG->ISTR = (fsdev_bus_t)~U_ISTR_ESOF; } // loop to handle all pending CTR interrupts - while (FSDEV_REG->ISTR & USB_ISTR_CTR) { + while (FSDEV_REG->ISTR & U_ISTR_CTR) { // skip DIR bit, and use CTR TX/RX instead, since there is chance we have both TX/RX completed in one interrupt - const uint32_t ep_id = FSDEV_REG->ISTR & USB_ISTR_EP_ID; + const uint32_t ep_id = FSDEV_REG->ISTR & U_ISTR_EP_ID; const uint32_t ep_reg = ep_read(ep_id); - if (ep_reg & USB_EP_CTR_RX) { + if (ep_reg & U_EP_CTR_RX) { #ifdef FSDEV_BUS_32BIT /* https://www.st.com/resource/en/errata_sheet/es0561-stm32h503cbebkbrb-device-errata-stmicroelectronics.pdf * https://www.st.com/resource/en/errata_sheet/es0587-stm32u535xx-and-stm32u545xx-device-errata-stmicroelectronics.pdf @@ -429,7 +429,7 @@ void dcd_int_handler(uint8_t rhport) { } #endif - if (ep_reg & USB_EP_SETUP) { + if (ep_reg & U_EP_SETUP) { handle_ctr_setup(ep_id); // CTR will be clear after copied setup packet } else { ep_write_clear_ctr(ep_id, TUSB_DIR_OUT); @@ -437,15 +437,15 @@ void dcd_int_handler(uint8_t rhport) { } } - if (ep_reg & USB_EP_CTR_TX) { + if (ep_reg & U_EP_CTR_TX) { ep_write_clear_ctr(ep_id, TUSB_DIR_IN); handle_ctr_tx(ep_id); } } - if (int_status & USB_ISTR_PMAOVR) { + if (int_status & U_ISTR_PMAOVR) { TU_BREAKPOINT(); - FSDEV_REG->ISTR = (fsdev_bus_t)~USB_ISTR_PMAOVR; + FSDEV_REG->ISTR = (fsdev_bus_t)~U_ISTR_PMAOVR; } } @@ -461,7 +461,7 @@ void dcd_edpt0_status_complete(uint8_t rhport, const tusb_control_request_t *req if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE && request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && request->bRequest == TUSB_REQ_SET_ADDRESS) { const uint8_t dev_addr = (uint8_t)request->wValue; - FSDEV_REG->DADDR = (USB_DADDR_EF | dev_addr); + FSDEV_REG->DADDR = (U_DADDR_EF | dev_addr); } edpt0_prepare_setup(); @@ -551,8 +551,8 @@ void edpt0_open(uint8_t rhport) { btable_set_addr(0, BTABLE_BUF_RX, pma_addr0); btable_set_addr(0, BTABLE_BUF_TX, pma_addr1); - uint32_t ep_reg = ep_read(0) & ~USB_EPREG_MASK; // only get toggle bits - ep_reg |= USB_EP_CONTROL; + uint32_t ep_reg = ep_read(0) & ~U_EPREG_MASK; // only get toggle bits + ep_reg |= U_EP_CONTROL; ep_change_status(&ep_reg, TUSB_DIR_IN, EP_STAT_NAK); ep_change_status(&ep_reg, TUSB_DIR_OUT, EP_STAT_NAK); // no need to explicitly set DTOG bits since we aren't masked DTOG bit @@ -570,16 +570,16 @@ bool dcd_edpt_open(uint8_t rhport, const tusb_desc_endpoint_t *desc_ep) { const uint8_t ep_idx = dcd_ep_alloc(ep_addr, desc_ep->bmAttributes.xfer); TU_ASSERT(ep_idx < FSDEV_EP_COUNT); - uint32_t ep_reg = ep_read(ep_idx) & ~USB_EPREG_MASK; - ep_reg |= tu_edpt_number(ep_addr) | USB_EP_CTR_TX | USB_EP_CTR_RX; + uint32_t ep_reg = ep_read(ep_idx) & ~U_EPREG_MASK; + ep_reg |= tu_edpt_number(ep_addr) | U_EP_CTR_TX | U_EP_CTR_RX; // Set type switch (desc_ep->bmAttributes.xfer) { case TUSB_XFER_BULK: - ep_reg |= USB_EP_BULK; + ep_reg |= U_EP_BULK; break; case TUSB_XFER_INTERRUPT: - ep_reg |= USB_EP_INTERRUPT; + ep_reg |= U_EP_INTERRUPT; break; default: @@ -600,9 +600,9 @@ bool dcd_edpt_open(uint8_t rhport, const tusb_desc_endpoint_t *desc_ep) { // reserve other direction toggle bits if (dir == TUSB_DIR_IN) { - ep_reg &= ~(USB_EPRX_STAT | USB_EP_DTOG_RX); + ep_reg &= ~(U_EPRX_STAT | U_EP_DTOG_RX); } else { - ep_reg &= ~(USB_EPTX_STAT | USB_EP_DTOG_TX); + ep_reg &= ~(U_EPTX_STAT | U_EP_DTOG_TX); } ep_write(ep_idx, ep_reg, true); @@ -669,18 +669,18 @@ bool dcd_edpt_iso_activate(uint8_t rhport, const tusb_desc_endpoint_t *desc_ep) xfer->max_packet_size = tu_edpt_packet_size(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; + uint32_t ep_reg = ep_read(ep_idx) & ~U_EPREG_MASK; + ep_reg |= tu_edpt_number(ep_addr) | U_EP_ISOCHRONOUS | U_EP_CTR_TX | U_EP_CTR_RX; #if FSDEV_USE_SBUF_ISO != 0 - ep_reg |= USB_EP_KIND; + ep_reg |= U_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); + ep_reg &= ~(U_EPRX_STAT | U_EP_DTOG_RX); } else { - ep_reg &= ~(USB_EPTX_STAT | USB_EP_DTOG_TX); + ep_reg &= ~(U_EPTX_STAT | U_EP_DTOG_TX); } #else ep_change_status(&ep_reg, TUSB_DIR_IN, EP_STAT_DISABLED); @@ -697,7 +697,7 @@ bool dcd_edpt_iso_activate(uint8_t rhport, const tusb_desc_endpoint_t *desc_ep) // Currently, single-buffered, and only 64 bytes at a time (max) static void dcd_transmit_packet(xfer_ctl_t *xfer, uint16_t ep_ix) { uint16_t len = tu_min16(xfer->total_len - xfer->queued_len, xfer->max_packet_size); - uint32_t ep_reg = ep_read(ep_ix) | USB_EP_CTR_TX | USB_EP_CTR_RX; // reserve CTR + uint32_t ep_reg = ep_read(ep_ix) | U_EP_CTR_TX | U_EP_CTR_RX; // reserve CTR const bool is_iso = ep_is_iso(ep_reg); @@ -708,7 +708,7 @@ static void dcd_transmit_packet(xfer_ctl_t *xfer, uint16_t ep_ix) { bool const dbl_buf = false; #endif if (dbl_buf) { - buf_id = (ep_reg & USB_EP_DTOG_TX) ? 1 : 0; + buf_id = (ep_reg & U_EP_DTOG_TX) ? 1 : 0; } else { buf_id = BTABLE_BUF_TX; } @@ -728,7 +728,7 @@ static void dcd_transmit_packet(xfer_ctl_t *xfer, uint16_t ep_ix) { if (is_iso) { xfer->iso_in_sending = true; } - ep_reg &= USB_EPREG_MASK | EP_STAT_MASK(TUSB_DIR_IN); // only change TX Status, reserve other toggle bits + ep_reg &= U_EPREG_MASK | EP_STAT_MASK(TUSB_DIR_IN); // only change TX Status, reserve other toggle bits ep_write(ep_ix, ep_reg, true); } @@ -741,8 +741,8 @@ static bool edpt_xfer(uint8_t rhport, uint8_t ep_num, tusb_dir_t dir) { if (dir == TUSB_DIR_IN) { dcd_transmit_packet(xfer, ep_idx); } else { - uint32_t ep_reg = ep_read(ep_idx) | USB_EP_CTR_TX | USB_EP_CTR_RX; // reserve CTR - ep_reg &= USB_EPREG_MASK | EP_STAT_MASK(dir); + uint32_t ep_reg = ep_read(ep_idx) | U_EP_CTR_TX | U_EP_CTR_RX; // reserve CTR + ep_reg &= U_EPREG_MASK | EP_STAT_MASK(dir); uint16_t cnt = tu_min16(xfer->total_len, xfer->max_packet_size); @@ -800,8 +800,8 @@ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, dir); const uint8_t ep_idx = xfer->ep_idx; - uint32_t ep_reg = ep_read(ep_idx) | USB_EP_CTR_TX | USB_EP_CTR_RX; // reserve CTR bits - ep_reg &= USB_EPREG_MASK | EP_STAT_MASK(dir); + uint32_t ep_reg = ep_read(ep_idx) | U_EP_CTR_TX | U_EP_CTR_RX; // reserve CTR bits + ep_reg &= U_EPREG_MASK | EP_STAT_MASK(dir); ep_change_status(&ep_reg, dir, EP_STAT_STALL); ep_write(ep_idx, ep_reg, true); @@ -815,8 +815,8 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, dir); const uint8_t ep_idx = xfer->ep_idx; - uint32_t ep_reg = ep_read(ep_idx) | USB_EP_CTR_TX | USB_EP_CTR_RX; // reserve CTR bits - ep_reg &= USB_EPREG_MASK | EP_STAT_MASK(dir) | EP_DTOG_MASK(dir); + uint32_t ep_reg = ep_read(ep_idx) | U_EP_CTR_TX | U_EP_CTR_RX; // reserve CTR bits + ep_reg &= U_EPREG_MASK | EP_STAT_MASK(dir) | EP_DTOG_MASK(dir); if (!ep_is_iso(ep_reg)) { ep_change_status(&ep_reg, dir, EP_STAT_NAK); diff --git a/src/portable/st/stm32_fsdev/fsdev_at32.h b/src/portable/st/stm32_fsdev/fsdev_at32.h index e75430396..107884370 100644 --- a/src/portable/st/stm32_fsdev/fsdev_at32.h +++ b/src/portable/st/stm32_fsdev/fsdev_at32.h @@ -43,112 +43,6 @@ #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) */ -#define USB_ISTR_ERR ((uint16_t)0x2000U) /*!< ERRor (clear-only bit) */ -#define USB_ISTR_WKUP ((uint16_t)0x1000U) /*!< WaKe UP (clear-only bit) */ -#define USB_ISTR_SUSP ((uint16_t)0x0800U) /*!< SUSPend (clear-only bit) */ -#define USB_ISTR_RESET ((uint16_t)0x0400U) /*!< RESET (clear-only bit) */ -#define USB_ISTR_SOF ((uint16_t)0x0200U) /*!< Start Of Frame (clear-only bit) */ -#define USB_ISTR_ESOF ((uint16_t)0x0100U) /*!< Expected Start Of Frame (clear-only bit) */ -#define USB_ISTR_DIR ((uint16_t)0x0010U) /*!< DIRection of transaction (read-only bit) */ -#define USB_ISTR_EP_ID ((uint16_t)0x000FU) /*!< EndPoint IDentifier (read-only bit) */ - -/* Legacy defines */ -#define USB_ISTR_PMAOVRM USB_ISTR_PMAOVR - -#define USB_CLR_CTR (~USB_ISTR_CTR) /*!< clear Correct TRansfer bit */ -#define USB_CLR_PMAOVR (~USB_ISTR_PMAOVR) /*!< clear DMA OVeR/underrun bit*/ -#define USB_CLR_ERR (~USB_ISTR_ERR) /*!< clear ERRor bit */ -#define USB_CLR_WKUP (~USB_ISTR_WKUP) /*!< clear WaKe UP bit */ -#define USB_CLR_SUSP (~USB_ISTR_SUSP) /*!< clear SUSPend bit */ -#define USB_CLR_RESET (~USB_ISTR_RESET) /*!< clear RESET bit */ -#define USB_CLR_SOF (~USB_ISTR_SOF) /*!< clear Start Of Frame bit */ -#define USB_CLR_ESOF (~USB_ISTR_ESOF) /*!< clear Expected Start Of Frame bit */ - -/* Legacy defines */ -#define USB_CLR_PMAOVRM USB_CLR_PMAOVR - -/************************* CNTR control register bits definitions ***********/ -#define USB_CNTR_CTRM ((uint16_t)0x8000U) /*!< Correct TRansfer Mask */ -#define USB_CNTR_PMAOVR ((uint16_t)0x4000U) /*!< DMA OVeR/underrun Mask */ -#define USB_CNTR_ERRM ((uint16_t)0x2000U) /*!< ERRor Mask */ -#define USB_CNTR_WKUPM ((uint16_t)0x1000U) /*!< WaKe UP Mask */ -#define USB_CNTR_SUSPM ((uint16_t)0x0800U) /*!< SUSPend Mask */ -#define USB_CNTR_RESETM ((uint16_t)0x0400U) /*!< RESET Mask */ -#define USB_CNTR_SOFM ((uint16_t)0x0200U) /*!< Start Of Frame Mask */ -#define USB_CNTR_ESOFM ((uint16_t)0x0100U) /*!< Expected Start Of Frame Mask */ -#define USB_CNTR_RESUME ((uint16_t)0x0010U) /*!< RESUME request */ -#define USB_CNTR_FSUSP ((uint16_t)0x0008U) /*!< Force SUSPend */ -#define USB_CNTR_LPMODE ((uint16_t)0x0004U) /*!< Low-power MODE */ -#define USB_CNTR_PDWN ((uint16_t)0x0002U) /*!< Power DoWN */ -#define USB_CNTR_FRES ((uint16_t)0x0001U) /*!< Force USB RESet */ - -/* Legacy defines */ -#define USB_CNTR_PMAOVRM USB_CNTR_PMAOVR -#define USB_CNTR_LP_MODE USB_CNTR_LPMODE - -/******************** FNR Frame Number Register bit definitions ************/ -#define USB_FNR_RXDP ((uint16_t)0x8000U) /*!< status of D+ data line */ -#define USB_FNR_RXDM ((uint16_t)0x4000U) /*!< status of D- data line */ -#define USB_FNR_LCK ((uint16_t)0x2000U) /*!< LoCKed */ -#define USB_FNR_LSOF ((uint16_t)0x1800U) /*!< Lost SOF */ -#define USB_FNR_FN ((uint16_t)0x07FFU) /*!< Frame Number */ - -/******************** DADDR Device ADDRess bit definitions ****************/ -#define USB_DADDR_EF ((uint8_t)0x80U) /*!< USB device address Enable Function */ -#define USB_DADDR_ADD ((uint8_t)0x7FU) /*!< USB device address */ - -/****************************** Endpoint register *************************/ -#define USB_EP0R USB_BASE /*!< endpoint 0 register address */ -#define USB_EP1R (USB_BASE + 0x04U) /*!< endpoint 1 register address */ -#define USB_EP2R (USB_BASE + 0x08U) /*!< endpoint 2 register address */ -#define USB_EP3R (USB_BASE + 0x0CU) /*!< endpoint 3 register address */ -#define USB_EP4R (USB_BASE + 0x10U) /*!< endpoint 4 register address */ -#define USB_EP5R (USB_BASE + 0x14U) /*!< endpoint 5 register address */ -#define USB_EP6R (USB_BASE + 0x18U) /*!< endpoint 6 register address */ -#define USB_EP7R (USB_BASE + 0x1CU) /*!< endpoint 7 register address */ -/* bit positions */ -#define USB_EP_CTR_RX ((uint16_t)0x8000U) /*!< EndPoint Correct TRansfer RX */ -#define USB_EP_DTOG_RX ((uint16_t)0x4000U) /*!< EndPoint Data TOGGLE RX */ -#define USB_EPRX_STAT ((uint16_t)0x3000U) /*!< EndPoint RX STATus bit field */ -#define USB_EP_SETUP ((uint16_t)0x0800U) /*!< EndPoint SETUP */ -#define USB_EP_T_FIELD ((uint16_t)0x0600U) /*!< EndPoint TYPE */ -#define USB_EP_KIND ((uint16_t)0x0100U) /*!< EndPoint KIND */ -#define USB_EP_CTR_TX ((uint16_t)0x0080U) /*!< EndPoint Correct TRansfer TX */ -#define USB_EP_DTOG_TX ((uint16_t)0x0040U) /*!< EndPoint Data TOGGLE TX */ -#define USB_EPTX_STAT ((uint16_t)0x0030U) /*!< EndPoint TX STATus bit field */ -#define USB_EPADDR_FIELD ((uint16_t)0x000FU) /*!< EndPoint ADDRess FIELD */ - -/* EndPoint REGister MASK (no toggle fields) */ -#define USB_EPREG_MASK (USB_EP_CTR_RX|USB_EP_SETUP|USB_EP_T_FIELD|USB_EP_KIND|USB_EP_CTR_TX|USB_EPADDR_FIELD) - /*!< EP_TYPE[1:0] EndPoint TYPE */ -#define USB_EP_TYPE_MASK ((uint16_t)0x0600U) /*!< EndPoint TYPE Mask */ -#define USB_EP_BULK ((uint16_t)0x0000U) /*!< EndPoint BULK */ -#define USB_EP_CONTROL ((uint16_t)0x0200U) /*!< EndPoint CONTROL */ -#define USB_EP_ISOCHRONOUS ((uint16_t)0x0400U) /*!< EndPoint ISOCHRONOUS */ -#define USB_EP_INTERRUPT ((uint16_t)0x0600U) /*!< EndPoint INTERRUPT */ -#define USB_EP_T_MASK ((uint16_t) ~USB_EP_T_FIELD & USB_EPREG_MASK) - -#define USB_EPKIND_MASK ((uint16_t) ~USB_EP_KIND & USB_EPREG_MASK) /*!< EP_KIND EndPoint KIND */ - /*!< STAT_TX[1:0] STATus for TX transfer */ -#define USB_EP_TX_DIS ((uint16_t)0x0000U) /*!< EndPoint TX DISabled */ -#define USB_EP_TX_STALL ((uint16_t)0x0010U) /*!< EndPoint TX STALLed */ -#define USB_EP_TX_NAK ((uint16_t)0x0020U) /*!< EndPoint TX NAKed */ -#define USB_EP_TX_VALID ((uint16_t)0x0030U) /*!< EndPoint TX VALID */ -#define USB_EPTX_DTOG1 ((uint16_t)0x0010U) /*!< EndPoint TX Data TOGgle bit1 */ -#define USB_EPTX_DTOG2 ((uint16_t)0x0020U) /*!< EndPoint TX Data TOGgle bit2 */ -#define USB_EPTX_DTOGMASK (USB_EPTX_STAT|USB_EPREG_MASK) - /*!< STAT_RX[1:0] STATus for RX transfer */ -#define USB_EP_RX_DIS ((uint16_t)0x0000U) /*!< EndPoint RX DISabled */ -#define USB_EP_RX_STALL ((uint16_t)0x1000U) /*!< EndPoint RX STALLed */ -#define USB_EP_RX_NAK ((uint16_t)0x2000U) /*!< EndPoint RX NAKed */ -#define USB_EP_RX_VALID ((uint16_t)0x3000U) /*!< EndPoint RX VALID */ -#define USB_EPRX_DTOG1 ((uint16_t)0x1000U) /*!< EndPoint RX Data TOGgle bit1 */ -#define USB_EPRX_DTOG2 ((uint16_t)0x2000U) /*!< EndPoint RX Data TOGgle bit1 */ -#define USB_EPRX_DTOGMASK (USB_EPRX_STAT|USB_EPREG_MASK) - //--------------------------------------------------------------------+ // //--------------------------------------------------------------------+ @@ -206,7 +100,7 @@ TU_ATTR_ALWAYS_INLINE static inline void fsdev_int_disable(uint8_t rhport) { TU_ATTR_ALWAYS_INLINE static inline void fsdev_disconnect(uint8_t rhport) { (void) rhport; /* disable usb phy */ - *(volatile uint32_t*)(FSDEV_REG_BASE + 0x40) |= USB_CNTR_PDWN; + *(volatile uint32_t*)(FSDEV_REG_BASE + 0x40) |= U_CNTR_PDWN; /* D+ 1.5k pull-up disable, USB->cfg_bit.puo = TRUE; */ *(volatile uint32_t *)(FSDEV_REG_BASE+0x60) |= (1u<<1); } @@ -214,7 +108,7 @@ TU_ATTR_ALWAYS_INLINE static inline void fsdev_disconnect(uint8_t rhport) { TU_ATTR_ALWAYS_INLINE static inline void fsdev_connect(uint8_t rhport) { (void) rhport; /* enable usb phy */ - *(volatile uint32_t*)(FSDEV_REG_BASE + 0x40) &= ~USB_CNTR_PDWN; + *(volatile uint32_t*)(FSDEV_REG_BASE + 0x40) &= ~U_CNTR_PDWN; /* Dp 1.5k pull-up enable, USB->cfg_bit.puo = 0; */ *(volatile uint32_t *)(FSDEV_REG_BASE+0x60) &= ~(1u<<1); } diff --git a/src/portable/st/stm32_fsdev/fsdev_ch32.h b/src/portable/st/stm32_fsdev/fsdev_ch32.h index 37ea7808e..b92bf3f58 100644 --- a/src/portable/st/stm32_fsdev/fsdev_ch32.h +++ b/src/portable/st/stm32_fsdev/fsdev_ch32.h @@ -61,112 +61,6 @@ #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) */ -#define USB_ISTR_ERR ((uint16_t)0x2000U) /*!< ERRor (clear-only bit) */ -#define USB_ISTR_WKUP ((uint16_t)0x1000U) /*!< WaKe UP (clear-only bit) */ -#define USB_ISTR_SUSP ((uint16_t)0x0800U) /*!< SUSPend (clear-only bit) */ -#define USB_ISTR_RESET ((uint16_t)0x0400U) /*!< RESET (clear-only bit) */ -#define USB_ISTR_SOF ((uint16_t)0x0200U) /*!< Start Of Frame (clear-only bit) */ -#define USB_ISTR_ESOF ((uint16_t)0x0100U) /*!< Expected Start Of Frame (clear-only bit) */ -#define USB_ISTR_DIR ((uint16_t)0x0010U) /*!< DIRection of transaction (read-only bit) */ -#define USB_ISTR_EP_ID ((uint16_t)0x000FU) /*!< EndPoint IDentifier (read-only bit) */ - -/* Legacy defines */ -#define USB_ISTR_PMAOVRM USB_ISTR_PMAOVR - -#define USB_CLR_CTR (~USB_ISTR_CTR) /*!< clear Correct TRansfer bit */ -#define USB_CLR_PMAOVR (~USB_ISTR_PMAOVR) /*!< clear DMA OVeR/underrun bit*/ -#define USB_CLR_ERR (~USB_ISTR_ERR) /*!< clear ERRor bit */ -#define USB_CLR_WKUP (~USB_ISTR_WKUP) /*!< clear WaKe UP bit */ -#define USB_CLR_SUSP (~USB_ISTR_SUSP) /*!< clear SUSPend bit */ -#define USB_CLR_RESET (~USB_ISTR_RESET) /*!< clear RESET bit */ -#define USB_CLR_SOF (~USB_ISTR_SOF) /*!< clear Start Of Frame bit */ -#define USB_CLR_ESOF (~USB_ISTR_ESOF) /*!< clear Expected Start Of Frame bit */ - -/* Legacy defines */ -#define USB_CLR_PMAOVRM USB_CLR_PMAOVR - -/************************* CNTR control register bits definitions ***********/ -#define USB_CNTR_CTRM ((uint16_t)0x8000U) /*!< Correct TRansfer Mask */ -#define USB_CNTR_PMAOVR ((uint16_t)0x4000U) /*!< DMA OVeR/underrun Mask */ -#define USB_CNTR_ERRM ((uint16_t)0x2000U) /*!< ERRor Mask */ -#define USB_CNTR_WKUPM ((uint16_t)0x1000U) /*!< WaKe UP Mask */ -#define USB_CNTR_SUSPM ((uint16_t)0x0800U) /*!< SUSPend Mask */ -#define USB_CNTR_RESETM ((uint16_t)0x0400U) /*!< RESET Mask */ -#define USB_CNTR_SOFM ((uint16_t)0x0200U) /*!< Start Of Frame Mask */ -#define USB_CNTR_ESOFM ((uint16_t)0x0100U) /*!< Expected Start Of Frame Mask */ -#define USB_CNTR_RESUME ((uint16_t)0x0010U) /*!< RESUME request */ -#define USB_CNTR_FSUSP ((uint16_t)0x0008U) /*!< Force SUSPend */ -#define USB_CNTR_LPMODE ((uint16_t)0x0004U) /*!< Low-power MODE */ -#define USB_CNTR_PDWN ((uint16_t)0x0002U) /*!< Power DoWN */ -#define USB_CNTR_FRES ((uint16_t)0x0001U) /*!< Force USB RESet */ - -/* Legacy defines */ -#define USB_CNTR_PMAOVRM USB_CNTR_PMAOVR -#define USB_CNTR_LP_MODE USB_CNTR_LPMODE - -/******************** FNR Frame Number Register bit definitions ************/ -#define USB_FNR_RXDP ((uint16_t)0x8000U) /*!< status of D+ data line */ -#define USB_FNR_RXDM ((uint16_t)0x4000U) /*!< status of D- data line */ -#define USB_FNR_LCK ((uint16_t)0x2000U) /*!< LoCKed */ -#define USB_FNR_LSOF ((uint16_t)0x1800U) /*!< Lost SOF */ -#define USB_FNR_FN ((uint16_t)0x07FFU) /*!< Frame Number */ - -/******************** DADDR Device ADDRess bit definitions ****************/ -#define USB_DADDR_EF ((uint8_t)0x80U) /*!< USB device address Enable Function */ -#define USB_DADDR_ADD ((uint8_t)0x7FU) /*!< USB device address */ - -/****************************** Endpoint register *************************/ -#define USB_EP0R USB_BASE /*!< endpoint 0 register address */ -#define USB_EP1R (USB_BASE + 0x04U) /*!< endpoint 1 register address */ -#define USB_EP2R (USB_BASE + 0x08U) /*!< endpoint 2 register address */ -#define USB_EP3R (USB_BASE + 0x0CU) /*!< endpoint 3 register address */ -#define USB_EP4R (USB_BASE + 0x10U) /*!< endpoint 4 register address */ -#define USB_EP5R (USB_BASE + 0x14U) /*!< endpoint 5 register address */ -#define USB_EP6R (USB_BASE + 0x18U) /*!< endpoint 6 register address */ -#define USB_EP7R (USB_BASE + 0x1CU) /*!< endpoint 7 register address */ -/* bit positions */ -#define USB_EP_CTR_RX ((uint16_t)0x8000U) /*!< EndPoint Correct TRansfer RX */ -#define USB_EP_DTOG_RX ((uint16_t)0x4000U) /*!< EndPoint Data TOGGLE RX */ -#define USB_EPRX_STAT ((uint16_t)0x3000U) /*!< EndPoint RX STATus bit field */ -#define USB_EP_SETUP ((uint16_t)0x0800U) /*!< EndPoint SETUP */ -#define USB_EP_T_FIELD ((uint16_t)0x0600U) /*!< EndPoint TYPE */ -#define USB_EP_KIND ((uint16_t)0x0100U) /*!< EndPoint KIND */ -#define USB_EP_CTR_TX ((uint16_t)0x0080U) /*!< EndPoint Correct TRansfer TX */ -#define USB_EP_DTOG_TX ((uint16_t)0x0040U) /*!< EndPoint Data TOGGLE TX */ -#define USB_EPTX_STAT ((uint16_t)0x0030U) /*!< EndPoint TX STATus bit field */ -#define USB_EPADDR_FIELD ((uint16_t)0x000FU) /*!< EndPoint ADDRess FIELD */ - -/* EndPoint REGister MASK (no toggle fields) */ -#define USB_EPREG_MASK (USB_EP_CTR_RX|USB_EP_SETUP|USB_EP_T_FIELD|USB_EP_KIND|USB_EP_CTR_TX|USB_EPADDR_FIELD) - /*!< EP_TYPE[1:0] EndPoint TYPE */ -#define USB_EP_TYPE_MASK ((uint16_t)0x0600U) /*!< EndPoint TYPE Mask */ -#define USB_EP_BULK ((uint16_t)0x0000U) /*!< EndPoint BULK */ -#define USB_EP_CONTROL ((uint16_t)0x0200U) /*!< EndPoint CONTROL */ -#define USB_EP_ISOCHRONOUS ((uint16_t)0x0400U) /*!< EndPoint ISOCHRONOUS */ -#define USB_EP_INTERRUPT ((uint16_t)0x0600U) /*!< EndPoint INTERRUPT */ -#define USB_EP_T_MASK ((uint16_t) ~USB_EP_T_FIELD & USB_EPREG_MASK) - -#define USB_EPKIND_MASK ((uint16_t) ~USB_EP_KIND & USB_EPREG_MASK) /*!< EP_KIND EndPoint KIND */ - /*!< STAT_TX[1:0] STATus for TX transfer */ -#define USB_EP_TX_DIS ((uint16_t)0x0000U) /*!< EndPoint TX DISabled */ -#define USB_EP_TX_STALL ((uint16_t)0x0010U) /*!< EndPoint TX STALLed */ -#define USB_EP_TX_NAK ((uint16_t)0x0020U) /*!< EndPoint TX NAKed */ -#define USB_EP_TX_VALID ((uint16_t)0x0030U) /*!< EndPoint TX VALID */ -#define USB_EPTX_DTOG1 ((uint16_t)0x0010U) /*!< EndPoint TX Data TOGgle bit1 */ -#define USB_EPTX_DTOG2 ((uint16_t)0x0020U) /*!< EndPoint TX Data TOGgle bit2 */ -#define USB_EPTX_DTOGMASK (USB_EPTX_STAT|USB_EPREG_MASK) - /*!< STAT_RX[1:0] STATus for RX transfer */ -#define USB_EP_RX_DIS ((uint16_t)0x0000U) /*!< EndPoint RX DISabled */ -#define USB_EP_RX_STALL ((uint16_t)0x1000U) /*!< EndPoint RX STALLed */ -#define USB_EP_RX_NAK ((uint16_t)0x2000U) /*!< EndPoint RX NAKed */ -#define USB_EP_RX_VALID ((uint16_t)0x3000U) /*!< EndPoint RX VALID */ -#define USB_EPRX_DTOG1 ((uint16_t)0x1000U) /*!< EndPoint RX Data TOGgle bit1 */ -#define USB_EPRX_DTOG2 ((uint16_t)0x2000U) /*!< EndPoint RX Data TOGgle bit1 */ -#define USB_EPRX_DTOGMASK (USB_EPRX_STAT|USB_EPREG_MASK) - //--------------------------------------------------------------------+ // //--------------------------------------------------------------------+ diff --git a/src/portable/st/stm32_fsdev/fsdev_common.c b/src/portable/st/stm32_fsdev/fsdev_common.c index 4f127ae86..f63b6755a 100644 --- a/src/portable/st/stm32_fsdev/fsdev_common.c +++ b/src/portable/st/stm32_fsdev/fsdev_common.c @@ -38,12 +38,12 @@ // Reset the USB Core void fsdev_core_reset(void) { // Perform USB peripheral reset - FSDEV_REG->CNTR = USB_CNTR_FRES | USB_CNTR_PDWN; + FSDEV_REG->CNTR = U_CNTR_FRES | U_CNTR_PDWN; for (volatile uint32_t i = 0; i < 200; i++) { // should be a few us asm("NOP"); } - FSDEV_REG->CNTR &= ~USB_CNTR_PDWN; + FSDEV_REG->CNTR &= ~U_CNTR_PDWN; // Wait startup time, for F042 and F070, this is <= 1 us. for (volatile uint32_t i = 0; i < 200; i++) { // should be a few us @@ -57,13 +57,13 @@ void fsdev_core_reset(void) { // De-initialize the USB Core void fsdev_deinit(void) { // Disable all interrupts and force USB reset - FSDEV_REG->CNTR = USB_CNTR_FRES; + FSDEV_REG->CNTR = U_CNTR_FRES; // Clear pending interrupts FSDEV_REG->ISTR = 0; // Put USB peripheral in power down mode - FSDEV_REG->CNTR = USB_CNTR_FRES | USB_CNTR_PDWN; + FSDEV_REG->CNTR = U_CNTR_FRES | U_CNTR_PDWN; for (volatile uint32_t i = 0; i < 200; i++) { // should be a few us asm("NOP"); } diff --git a/src/portable/st/stm32_fsdev/fsdev_common.h b/src/portable/st/stm32_fsdev/fsdev_common.h index b749a92ff..36df4809d 100644 --- a/src/portable/st/stm32_fsdev/fsdev_common.h +++ b/src/portable/st/stm32_fsdev/fsdev_common.h @@ -39,6 +39,172 @@ #include "host/hcd.h" #endif +//--------------------------------------------------------------------+ +// FSDEV Register Bit Definitions +// Vendor-independent definitions with U_ prefix to avoid conflicts. +// Based on the common USB FSDEV IP block register layout. +// Lower 16 bits are shared across all variants (STM32, CH32, AT32). +// Upper 16 bits (DRD extensions) only exist on 32-bit DRD MCUs. +//--------------------------------------------------------------------+ + +// EPnR / CHEPnR - Endpoint/Channel Register +// DTOG and STAT bits are toggle-on-write-1. CTR bits are clear-on-write-0. +// +// 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +// CTR_RX DTOG_RX STAT_RX[1:0] SETUP EP_TYPE[1:0] KIND CTR_TX DTOG_TX STAT_TX[1:0] EA[3:0] +// +// DRD 32-bit only (C0, G0, H5, U0, U5): +// 31:27 26 25 24 23 22 21 20 19 18 17 16 +// Rsvd ERR_RX ERR_TX LSEP NAK DEVADDR[6:0] +#define U_EP_CTR_RX 0x8000u +#define U_EP_DTOG_RX 0x4000u +#define U_EPRX_STAT 0x3000u +#define U_EP_SETUP 0x0800u +#define U_EP_T_FIELD 0x0600u +#define U_EP_KIND 0x0100u +#define U_EP_CTR_TX 0x0080u +#define U_EP_DTOG_TX 0x0040u +#define U_EPTX_STAT 0x0030u +#define U_EPADDR_FIELD 0x000Fu + +// DRD 32-bit upper bits +#define U_EP_ERRRX 0x04000000u +#define U_EP_ERRTX 0x02000000u +#define U_EP_LSEP 0x01000000u +#define U_EP_NAK 0x00800000u +#define U_EP_DEVADDR 0x007F0000u +#define U_EP_DEVADDR_Pos 16u + +// Endpoint types (EP_TYPE field values) +#define U_EP_BULK 0x0000u +#define U_EP_CONTROL 0x0200u +#define U_EP_ISOCHRONOUS 0x0400u +#define U_EP_INTERRUPT 0x0600u +#define U_EP_TYPE_MASK (U_EP_T_FIELD) + +// EP register mask components (non-toggle bits preserved during read-modify-write) +// Excludes DTOG_RX, STAT_RX, DTOG_TX, STAT_TX (toggle-on-write-1) +#define U_EPREG_MASK_16 (U_EP_CTR_RX | U_EP_SETUP | U_EP_T_FIELD | U_EP_KIND | U_EP_CTR_TX | U_EPADDR_FIELD) +#define U_EPREG_MASK_32 (U_EP_ERRRX | U_EP_ERRTX | U_EP_LSEP | U_EP_NAK | U_EP_DEVADDR | U_EPREG_MASK_16) + +// EP register mask selection based on bus width +#ifdef FSDEV_BUS_32BIT + #define U_EPREG_MASK U_EPREG_MASK_32 +#else + #define U_EPREG_MASK U_EPREG_MASK_16 +#endif + +#define U_EPKIND_MASK ((uint32_t)(~U_EP_KIND) & U_EPREG_MASK) +#define U_EPTX_DTOGMASK (U_EPTX_STAT | U_EPREG_MASK) +#define U_EPRX_DTOGMASK (U_EPRX_STAT | U_EPREG_MASK) + +// Bit positions +#define U_EPTX_STAT_Pos 4u +#define U_EP_DTOG_TX_Pos 6u +#define U_EP_CTR_TX_Pos 7u + +// Data toggle helpers +#define U_EPTX_DTOG1 0x0010u +#define U_EPTX_DTOG2 0x0020u +#define U_EPRX_DTOG1 0x1000u +#define U_EPRX_DTOG2 0x2000u + +// CNTR - Control Register +// 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +// CTRM PMAOVRM ERRM WKUPM SUSPM RESETM SOFM ESOFM Rsvd Rsvd Rsvd RESUME FSUSP LPMODE PDWN FRES +// +// DRD 32-bit only: +// 31 30:16 +// HOST Rsvd +#define U_CNTR_CTRM 0x8000u +#define U_CNTR_PMAOVRM 0x4000u +#define U_CNTR_ERRM 0x2000u +#define U_CNTR_WKUPM 0x1000u +#define U_CNTR_SUSPM 0x0800u +#define U_CNTR_RESETM 0x0400u +#define U_CNTR_SOFM 0x0200u +#define U_CNTR_ESOFM 0x0100u +#define U_CNTR_RESUME 0x0010u +#define U_CNTR_FSUSP 0x0008u +#define U_CNTR_LPMODE 0x0004u +#define U_CNTR_PDWN 0x0002u +#define U_CNTR_FRES 0x0001u + +#define U_CNTR_HOST 0x80000000u // DRD: enable host mode +#define U_CNTR_DCON 0x0400u // DRD host: same bit as RESETM + +// ISTR - Interrupt Status Register +// 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +// CTR PMAOVR ERR WKUP SUSP RESET SOF ESOF Rsvd Rsvd Rsvd DIR EP_ID[3:0] +// +// DRD 32-bit only: +// 31 30 29 28:16 +// Rsvd LS_DCONN DCON_STAT Rsvd +#define U_ISTR_CTR 0x8000u +#define U_ISTR_PMAOVR 0x4000u +#define U_ISTR_ERR 0x2000u +#define U_ISTR_WKUP 0x1000u +#define U_ISTR_SUSP 0x0800u +#define U_ISTR_RESET 0x0400u +#define U_ISTR_SOF 0x0200u +#define U_ISTR_ESOF 0x0100u +#define U_ISTR_DIR 0x0010u +#define U_ISTR_EP_ID 0x000Fu + +#define U_ISTR_LS_DCONN 0x40000000u // DRD: low-speed device connected +#define U_ISTR_DCON_STAT 0x20000000u // DRD: device connection status +#define U_ISTR_DCON 0x0400u // DRD host: same bit as RESET + +// FNR - Frame Number Register (read-only) +// 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +// RXDP RXDM LCK[2:0] FN[10:0] +#define U_FNR_RXDP 0x8000u +#define U_FNR_RXDM 0x4000u +#define U_FNR_FN 0x07FFu + +// DADDR - Device Address Register +// 15:8 7 6 5 4 3 2 1 0 +// Rsvd EF ADD[6:0] +#define U_DADDR_EF 0x80u + +// LPMCSR - LPM Control and Status Register +// Supported: STM32 F0, L0, L4, G0, G4, C0, H5, U0, WB. Not on: F1, F3, AT32, CH32. +// 15:8 7 6 5 4 3 2 1 0 +// Rsvd BESL[3:0] Rsvd REMWAKE Rsvd LPMACK LMPEN +#define U_LPMCSR_LMPEN 0x0001u +#define U_LPMCSR_LPMACK 0x0002u +#define U_LPMCSR_REMWAKE 0x0008u +#define U_LPMCSR_BESL 0x00F0u + +// BCDR - Battery Charging Detector Register +// Supported: STM32 F0, L0, L4, G0, G4, C0, H5, U0, WB. Not on: F1, F3, AT32, CH32. +// 15 14:8 7 6 5 4 3 2 1 0 +// DPPU Rsvd PS2DET SDET PDET DCDET SDEN PDEN DCDEN BCDEN +#define U_BCDR_BCDEN 0x0001u +#define U_BCDR_DCDEN 0x0002u +#define U_BCDR_PDEN 0x0004u +#define U_BCDR_SDEN 0x0008u +#define U_BCDR_DCDET 0x0010u +#define U_BCDR_PDET 0x0020u +#define U_BCDR_SDET 0x0040u +#define U_BCDR_PS2DET 0x0080u +#define U_BCDR_DPPU 0x8000u + +// Channel status (DRD host mode, reuses STAT_TX/STAT_RX bit positions) +#define U_CH_TX_STTX 0x0030u +#define U_CH_TX_ACK_SBUF 0x0000u +#define U_CH_TX_STALL 0x0010u +#define U_CH_TX_NAK 0x0020u + +#define U_CH_RX_STRX 0x3000u +#define U_CH_RX_ACK_SBUF 0x0000u +#define U_CH_RX_STALL 0x1000u +#define U_CH_RX_NAK 0x2000u +#define U_CH_RX_VALID 0x3000u + +//--------------------------------------------------------------------+ +// Vendor-specific includes (after U_ definitions so they can use them) +//--------------------------------------------------------------------+ #if defined(TUP_USBIP_FSDEV_STM32) #include "fsdev_stm32.h" #elif defined(TUP_USBIP_FSDEV_CH32) @@ -49,6 +215,16 @@ #error "Unknown USB IP" #endif +// LPM support - detect from vendor header (L1REQ bit position varies) +#if defined(USB_ISTR_L1REQ) + #define U_ISTR_L1REQ USB_ISTR_L1REQ +#else + #define U_ISTR_L1REQ 0x0000u +#endif + +#define U_ISTR_ALL_EVENTS (U_ISTR_PMAOVR | U_ISTR_ERR | U_ISTR_WKUP | U_ISTR_SUSP | \ + U_ISTR_RESET | U_ISTR_SOF | U_ISTR_ESOF | U_ISTR_L1REQ) + #ifdef __cplusplus extern "C" { #endif @@ -146,9 +322,9 @@ typedef struct { _va32 fsdev_bus_t ISTR; // 44: Interrupt status register _va32 fsdev_bus_t FNR; // 48: Frame number register _va32 fsdev_bus_t DADDR; // 4C: Device address register - _va32 fsdev_bus_t BTABLE; // 50: Buffer Table address register (16-bit only) - _va32 fsdev_bus_t LPMCSR; // 54: LPM Control and Status Register (32-bit only) - _va32 fsdev_bus_t BCDR; // 58: Battery Charging Detector Register (32-bit only) + _va32 fsdev_bus_t BTABLE; // 50: Buffer Table address register + _va32 fsdev_bus_t LPMCSR; // 54: LPM Control and Status (not on F1, F3, AT32, CH32) + _va32 fsdev_bus_t BCDR; // 58: Battery Charging Detector (not on F1, F3, AT32, CH32) } fsdev_regs_t; TU_VERIFY_STATIC(offsetof(fsdev_regs_t, CNTR) == 0x40, "Wrong offset"); @@ -157,26 +333,6 @@ TU_VERIFY_STATIC(sizeof(fsdev_regs_t) == 0x5C, "Size is not correct"); #define FSDEV_REG ((fsdev_regs_t *)FSDEV_REG_BASE) -#ifndef USB_EPTX_STAT - #define USB_EPTX_STAT 0x0030U -#endif - -#ifndef USB_EPRX_STAT - #define USB_EPRX_STAT 0x3000U -#endif - -#ifndef USB_EPTX_STAT_Pos - #define USB_EPTX_STAT_Pos 4u -#endif - -#ifndef USB_EP_DTOG_TX_Pos - #define USB_EP_DTOG_TX_Pos 6u -#endif - -#ifndef USB_EP_CTR_TX_Pos - #define USB_EP_CTR_TX_Pos 7u -#endif - typedef enum { EP_STAT_DISABLED = 0, EP_STAT_STALL = 1, @@ -184,11 +340,11 @@ typedef enum { EP_STAT_VALID = 3 } ep_stat_t; -#define EP_STAT_MASK(_dir) (3u << (USB_EPTX_STAT_Pos + ((_dir) == TUSB_DIR_IN ? 0 : 8))) -#define EP_DTOG_MASK(_dir) (1u << (USB_EP_DTOG_TX_Pos + ((_dir) == TUSB_DIR_IN ? 0 : 8))) +#define EP_STAT_MASK(_dir) (3u << (U_EPTX_STAT_Pos + ((_dir) == TUSB_DIR_IN ? 0 : 8))) +#define EP_DTOG_MASK(_dir) (1u << (U_EP_DTOG_TX_Pos + ((_dir) == TUSB_DIR_IN ? 0 : 8))) -#define CH_STAT_MASK(_dir) (3u << (USB_EPTX_STAT_Pos + ((_dir) == TUSB_DIR_IN ? 8 : 0))) -#define CH_DTOG_MASK(_dir) (1u << (USB_EP_DTOG_TX_Pos + ((_dir) == TUSB_DIR_IN ? 8 : 0))) +#define CH_STAT_MASK(_dir) (3u << (U_EPTX_STAT_Pos + ((_dir) == TUSB_DIR_IN ? 8 : 0))) +#define CH_DTOG_MASK(_dir) (1u << (U_EP_DTOG_TX_Pos + ((_dir) == TUSB_DIR_IN ? 8 : 0))) //--------------------------------------------------------------------+ // Endpoint Helper @@ -214,22 +370,22 @@ TU_ATTR_ALWAYS_INLINE static inline void ep_write(uint32_t ep_id, uint32_t value TU_ATTR_ALWAYS_INLINE static inline void ep_write_clear_ctr(uint32_t ep_id, tusb_dir_t dir) { uint32_t reg = FSDEV_REG->ep[ep_id].reg; - reg |= USB_EP_CTR_TX | USB_EP_CTR_RX; - reg &= USB_EPREG_MASK; - reg &= ~(1 << (USB_EP_CTR_TX_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); + reg |= U_EP_CTR_TX | U_EP_CTR_RX; + reg &= U_EPREG_MASK; + reg &= ~(1 << (U_EP_CTR_TX_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); ep_write(ep_id, reg, false); } TU_ATTR_ALWAYS_INLINE static inline void ep_change_status(uint32_t *reg, tusb_dir_t dir, ep_stat_t state) { - *reg ^= (state << (USB_EPTX_STAT_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); + *reg ^= (state << (U_EPTX_STAT_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); } TU_ATTR_ALWAYS_INLINE static inline void ep_change_dtog(uint32_t *reg, tusb_dir_t dir, uint8_t state) { - *reg ^= (state << (USB_EP_DTOG_TX_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); + *reg ^= (state << (U_EP_DTOG_TX_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); } TU_ATTR_ALWAYS_INLINE static inline bool ep_is_iso(uint32_t reg) { - return (reg & USB_EP_TYPE_MASK) == USB_EP_ISOCHRONOUS; + return (reg & U_EP_TYPE_MASK) == U_EP_ISOCHRONOUS; } //--------------------------------------------------------------------+ @@ -247,18 +403,18 @@ TU_ATTR_ALWAYS_INLINE static inline void ch_write(uint32_t ch_id, uint32_t value TU_ATTR_ALWAYS_INLINE static inline void ch_write_clear_ctr(uint32_t ch_id, tusb_dir_t dir) { uint32_t reg = FSDEV_REG->ep[ch_id].reg; - reg |= USB_EP_CTR_TX | USB_EP_CTR_RX; - reg &= USB_EPREG_MASK; - reg &= ~(1 << (USB_EP_CTR_TX_Pos + (dir == TUSB_DIR_IN ? 8 : 0))); + reg |= U_EP_CTR_TX | U_EP_CTR_RX; + reg &= U_EPREG_MASK; + reg &= ~(1 << (U_EP_CTR_TX_Pos + (dir == TUSB_DIR_IN ? 8 : 0))); ep_write(ch_id, reg, false); } TU_ATTR_ALWAYS_INLINE static inline void ch_change_status(uint32_t *reg, tusb_dir_t dir, ep_stat_t state) { - *reg ^= (state << (USB_EPTX_STAT_Pos + (dir == TUSB_DIR_IN ? 8 : 0))); + *reg ^= (state << (U_EPTX_STAT_Pos + (dir == TUSB_DIR_IN ? 8 : 0))); } TU_ATTR_ALWAYS_INLINE static inline void ch_change_dtog(uint32_t *reg, tusb_dir_t dir, uint8_t state) { - *reg ^= (state << (USB_EP_DTOG_TX_Pos + (dir == TUSB_DIR_IN ? 8 : 0))); + *reg ^= (state << (U_EP_DTOG_TX_Pos + (dir == TUSB_DIR_IN ? 8 : 0))); } //--------------------------------------------------------------------+ diff --git a/src/portable/st/stm32_fsdev/fsdev_stm32.h b/src/portable/st/stm32_fsdev/fsdev_stm32.h index 02dba05a6..a1c5c9488 100644 --- a/src/portable/st/stm32_fsdev/fsdev_stm32.h +++ b/src/portable/st/stm32_fsdev/fsdev_stm32.h @@ -35,16 +35,6 @@ #if CFG_TUSB_MCU == OPT_MCU_STM32C0 #include "stm32c0xx.h" #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 - #define USB_EPREG_MASK USB_CHEP_REG_MASK - #define USB_CNTR_FRES USB_CNTR_USBRST - #define USB_CNTR_RESUME USB_CNTR_L2RES - #define USB_ISTR_EP_ID USB_ISTR_IDN - #define USB_EPADDR_FIELD USB_CHEP_ADDR - #define USB_CNTR_LPMODE USB_CNTR_SUSPRDY - #define USB_CNTR_FSUSP USB_CNTR_SUSPEN #elif CFG_TUSB_MCU == OPT_MCU_STM32F0 #include "stm32f0xx.h" @@ -61,9 +51,6 @@ // NO internal Pull-ups // *B, and *C: 2 x 16 bits/word - // F1 names this differently from the rest - #define USB_CNTR_LPMODE USB_CNTR_LP_MODE - #elif defined(STM32F302xB) || defined(STM32F302xC) || defined(STM32F303xB) || defined(STM32F303xC) || \ defined(STM32F373xC) #include "stm32f3xx.h" @@ -102,27 +89,7 @@ #elif CFG_TUSB_MCU == OPT_MCU_STM32G0 #include "stm32g0xx.h" - #define FSDEV_HAS_SBUF_ISO 1 - #define USB USB_DRD_FS - - #define USB_EP_CTR_RX USB_EP_VTRX - #define USB_EP_CTR_TX USB_EP_VTTX - #define USB_EP_T_FIELD USB_CHEP_UTYPE - #define USB_EPREG_MASK USB_CHEP_REG_MASK - #define USB_EPTX_DTOGMASK USB_CHEP_TX_DTOGMASK - #define USB_EPRX_DTOGMASK USB_CHEP_RX_DTOGMASK - #define USB_EPTX_DTOG1 USB_CHEP_TX_DTOG1 - #define USB_EPTX_DTOG2 USB_CHEP_TX_DTOG2 - #define USB_EPRX_DTOG1 USB_CHEP_RX_DTOG1 - #define USB_EPRX_DTOG2 USB_CHEP_RX_DTOG2 - #define USB_EPRX_STAT USB_CH_RX_VALID - #define USB_EPKIND_MASK USB_EP_KIND_MASK - #define USB_CNTR_FRES USB_CNTR_USBRST - #define USB_CNTR_RESUME USB_CNTR_L2RES - #define USB_ISTR_EP_ID USB_ISTR_IDN - #define USB_EPADDR_FIELD USB_CHEP_ADDR - #define USB_CNTR_LPMODE USB_CNTR_SUSPRDY - #define USB_CNTR_FSUSP USB_CNTR_SUSPEN + #define FSDEV_HAS_SBUF_ISO 1 #elif CFG_TUSB_MCU == OPT_MCU_STM32G4 #include "stm32g4xx.h" @@ -131,100 +98,20 @@ #elif CFG_TUSB_MCU == OPT_MCU_STM32H5 #include "stm32h5xx.h" #define FSDEV_HAS_SBUF_ISO 1 - #define USB USB_DRD_FS - - #define USB_EP_CTR_RX USB_EP_VTRX - #define USB_EP_CTR_TX USB_EP_VTTX - #define USB_EP_T_FIELD USB_CHEP_UTYPE - #define USB_EPREG_MASK USB_CHEP_REG_MASK - #define USB_EPTX_DTOGMASK USB_CHEP_TX_DTOGMASK - #define USB_EPRX_DTOGMASK USB_CHEP_RX_DTOGMASK - #define USB_EPTX_DTOG1 USB_CHEP_TX_DTOG1 - #define USB_EPTX_DTOG2 USB_CHEP_TX_DTOG2 - #define USB_EPRX_DTOG1 USB_CHEP_RX_DTOG1 - #define USB_EPRX_DTOG2 USB_CHEP_RX_DTOG2 - #define USB_EPRX_STAT USB_CH_RX_VALID - #define USB_EPKIND_MASK USB_EP_KIND_MASK - #define USB_CNTR_FRES USB_CNTR_USBRST - #define USB_CNTR_RESUME USB_CNTR_L2RES - #define USB_ISTR_EP_ID USB_ISTR_IDN - #define USB_EPADDR_FIELD USB_CHEP_ADDR - #define USB_CNTR_LPMODE USB_CNTR_SUSPRDY - #define USB_CNTR_FSUSP USB_CNTR_SUSPEN #elif CFG_TUSB_MCU == OPT_MCU_STM32U0 #include "stm32u0xx.h" #define FSDEV_BUS_32BIT #define FSDEV_HAS_SBUF_ISO 1 - #define USB USB_DRD_FS - - #define USB_EP_CTR_RX USB_EP_VTRX - #define USB_EP_CTR_TX USB_EP_VTTX - #define USB_EP_T_FIELD USB_CHEP_UTYPE - #define USB_EPREG_MASK USB_CHEP_REG_MASK - #define USB_EPTX_DTOGMASK USB_CHEP_TX_DTOGMASK - #define USB_EPRX_DTOGMASK USB_CHEP_RX_DTOGMASK - #define USB_EPTX_DTOG1 USB_CHEP_TX_DTOG1 - #define USB_EPTX_DTOG2 USB_CHEP_TX_DTOG2 - #define USB_EPRX_DTOG1 USB_CHEP_RX_DTOG1 - #define USB_EPRX_DTOG2 USB_CHEP_RX_DTOG2 - #define USB_EPRX_STAT USB_CH_RX_VALID - #define USB_EPKIND_MASK USB_EP_KIND_MASK - #define USB_CNTR_FRES USB_CNTR_USBRST - #define USB_CNTR_RESUME USB_CNTR_L2RES - #define USB_ISTR_EP_ID USB_ISTR_IDN - #define USB_EPADDR_FIELD USB_CHEP_ADDR - #define USB_CNTR_LPMODE USB_CNTR_SUSPRDY - #define USB_CNTR_FSUSP USB_CNTR_SUSPEN #elif CFG_TUSB_MCU == OPT_MCU_STM32U3 #include "stm32u3xx.h" #define FSDEV_BUS_32BIT #define FSDEV_HAS_SBUF_ISO 1 // This is assumed to work but has not been tested... - #define USB USB_DRD_FS - - #define USB_EP_CTR_RX USB_EP_VTRX - #define USB_EP_CTR_TX USB_EP_VTTX - #define USB_EP_T_FIELD USB_CHEP_UTYPE - #define USB_EPREG_MASK USB_CHEP_REG_MASK - #define USB_EPTX_DTOGMASK USB_CHEP_TX_DTOGMASK - #define USB_EPRX_DTOGMASK USB_CHEP_RX_DTOGMASK - #define USB_EPTX_DTOG1 USB_CHEP_TX_DTOG1 - #define USB_EPTX_DTOG2 USB_CHEP_TX_DTOG2 - #define USB_EPRX_DTOG1 USB_CHEP_RX_DTOG1 - #define USB_EPRX_DTOG2 USB_CHEP_RX_DTOG2 - #define USB_EPRX_STAT USB_CH_RX_VALID - #define USB_EPKIND_MASK USB_EP_KIND_MASK - #define USB_CNTR_FRES USB_CNTR_USBRST - #define USB_CNTR_RESUME USB_CNTR_L2RES - #define USB_ISTR_EP_ID USB_ISTR_IDN - #define USB_EPADDR_FIELD USB_CHEP_ADDR - #define USB_CNTR_LPMODE USB_CNTR_SUSPRDY - #define USB_CNTR_FSUSP USB_CNTR_SUSPEN #elif CFG_TUSB_MCU == OPT_MCU_STM32U5 #include "stm32u5xx.h" #define FSDEV_HAS_SBUF_ISO 1 - #define USB USB_DRD_FS - - #define USB_EP_CTR_RX USB_EP_VTRX - #define USB_EP_CTR_TX USB_EP_VTTX - #define USB_EP_T_FIELD USB_CHEP_UTYPE - #define USB_EPREG_MASK USB_CHEP_REG_MASK - #define USB_EPTX_DTOGMASK USB_CHEP_TX_DTOGMASK - #define USB_EPRX_DTOGMASK USB_CHEP_RX_DTOGMASK - #define USB_EPTX_DTOG1 USB_CHEP_TX_DTOG1 - #define USB_EPTX_DTOG2 USB_CHEP_TX_DTOG2 - #define USB_EPRX_DTOG1 USB_CHEP_RX_DTOG1 - #define USB_EPRX_DTOG2 USB_CHEP_RX_DTOG2 - #define USB_EPRX_STAT USB_CH_RX_VALID - #define USB_EPKIND_MASK USB_EP_KIND_MASK - #define USB_CNTR_FRES USB_CNTR_USBRST - #define USB_CNTR_RESUME USB_CNTR_L2RES - #define USB_ISTR_EP_ID USB_ISTR_IDN - #define USB_EPADDR_FIELD USB_CHEP_ADDR - #define USB_CNTR_LPMODE USB_CNTR_SUSPRDY - #define USB_CNTR_FSUSP USB_CNTR_SUSPEN #elif CFG_TUSB_MCU == OPT_MCU_STM32WB #include "stm32wbxx.h" @@ -234,7 +121,16 @@ #else #error You are using an untested or unimplemented STM32 variant. Please update the driver. - // This includes U0 +#endif + +//--------------------------------------------------------------------+ +// USB DRD compatibility aliases +// These MCUs use a newer USB_DRD peripheral that needs the USB macro +// mapped to USB_DRD_FS for connect/disconnect register access. +//--------------------------------------------------------------------+ +#if TU_CHECK_MCU(OPT_MCU_STM32C0, OPT_MCU_STM32G0, OPT_MCU_STM32H5, \ + OPT_MCU_STM32U0, OPT_MCU_STM32U3, OPT_MCU_STM32U5) + #define USB USB_DRD_FS #endif //--------------------------------------------------------------------+ @@ -262,16 +158,6 @@ #endif #endif -// This checks if the device has "LPM" -#if defined(USB_ISTR_L1REQ) -#define USB_ISTR_L1REQ_FORCED (USB_ISTR_L1REQ) -#else -#define USB_ISTR_L1REQ_FORCED ((uint16_t)0x0000U) -#endif - -#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 @@ -398,17 +284,20 @@ TU_ATTR_ALWAYS_INLINE static inline void fsdev_int_disable(uint8_t rhport) { // CMSIS has a membar after disabling interrupts } -// Define only on MCU with internal pull-up. BSP can define on MCU without internal PU. +//--------------------------------------------------------------------+ +// Connect / Disconnect +//--------------------------------------------------------------------+ + #if defined(USB_BCDR_DPPU) TU_ATTR_ALWAYS_INLINE static inline void fsdev_disconnect(uint8_t rhport) { (void)rhport; - USB->BCDR &= ~(USB_BCDR_DPPU); + USB->BCDR &= ~U_BCDR_DPPU; } TU_ATTR_ALWAYS_INLINE static inline void fsdev_connect(uint8_t rhport) { (void)rhport; - USB->BCDR |= USB_BCDR_DPPU; + USB->BCDR |= U_BCDR_DPPU; } #elif defined(SYSCFG_PMC_USB_PU) // works e.g. on STM32L151 diff --git a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c index 1813ef70b..dd86b052a 100644 --- a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c @@ -160,7 +160,7 @@ static inline void channel_dealloc(hcd_channel_t* ch, tusb_dir_t dir) { // Write channel state in specified direction static inline void channel_write_status(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir, ep_stat_t state, bool need_exclusive) { - ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(dir); + ch_reg &= U_EPREG_MASK | CH_STAT_MASK(dir); ch_change_status(&ch_reg, dir, state); ch_write(ch_id, ch_reg, need_exclusive); } @@ -182,7 +182,7 @@ static inline uint16_t channel_get_rx_count(uint8_t ch_id) { */ uint32_t ch_reg = ch_read(ch_id); - if (FSDEV_REG->ISTR & USB_ISTR_LS_DCONN || ch_reg & USB_CHEP_LSEP) { + if (FSDEV_REG->ISTR & U_ISTR_LS_DCONN || ch_reg & U_EP_LSEP) { // Low speed mode: 6.4 us delay -> about 2 cycles per MHz volatile uint32_t cycle_count = CPU_FREQUENCY_MHZ * 2U; while (cycle_count > 0U) { @@ -219,7 +219,7 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { fsdev_core_reset(); - FSDEV_REG->CNTR = USB_CNTR_HOST; // Enable USB in Host mode + FSDEV_REG->CNTR = U_CNTR_HOST; // Enable USB in Host mode tu_memclr(&_hcd_data, sizeof(_hcd_data)); @@ -229,7 +229,7 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { FSDEV_REG->ISTR = 0; // Enable interrupts for host mode - FSDEV_REG->CNTR |= USB_CNTR_DCON | USB_CNTR_CTRM | USB_CNTR_SOFM | USB_CNTR_ERRM | USB_CNTR_PMAOVRM; + FSDEV_REG->CNTR |= U_CNTR_DCON | U_CNTR_CTRM | U_CNTR_SOFM | U_CNTR_ERRM | U_CNTR_PMAOVRM; // Initialize port state _hcd_data.connected = false; @@ -237,7 +237,7 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { fsdev_connect(rhport); // If DCON_STAT is already set, the controller sometimes misses the initial connection interrupt - if (FSDEV_REG->ISTR & USB_ISTR_DCON_STAT) { + if (FSDEV_REG->ISTR & U_ISTR_DCON_STAT) { // Wait DP/DM stabilize time volatile uint32_t cycle_count = CPU_FREQUENCY_MHZ / 4U; while (cycle_count > 0U) { @@ -280,7 +280,7 @@ static void port_status_handler(uint8_t rhport, bool in_isr) { uint32_t const fnr_reg = FSDEV_REG->FNR; uint32_t const istr_reg = FSDEV_REG->ISTR; // SE0 detected USB Disconnected state - if ((fnr_reg & (USB_FNR_RXDP | USB_FNR_RXDM)) == 0U) { + if ((fnr_reg & (U_FNR_RXDP | U_FNR_RXDM)) == 0U) { _hcd_data.connected = false; hcd_event_device_remove(rhport, in_isr); return; @@ -288,13 +288,13 @@ static void port_status_handler(uint8_t rhport, bool in_isr) { if (!_hcd_data.connected) { // J-state or K-state detected & LastState=Disconnected - if (((fnr_reg & USB_FNR_RXDP) != 0U) || ((istr_reg & USB_ISTR_LS_DCONN) != 0U)) { + if (((fnr_reg & U_FNR_RXDP) != 0U) || ((istr_reg & U_ISTR_LS_DCONN) != 0U)) { _hcd_data.connected = true; hcd_event_device_attach(rhport, in_isr); } } else { // J-state or K-state detected & lastState=Connected: a Missed disconnection is detected - if (((fnr_reg & USB_FNR_RXDP) != 0U) || ((istr_reg & USB_ISTR_LS_DCONN) != 0U)) { + if (((fnr_reg & U_FNR_RXDP) != 0U) || ((istr_reg & U_ISTR_LS_DCONN) != 0U)) { _hcd_data.connected = false; hcd_event_device_remove(rhport, in_isr); } @@ -303,8 +303,8 @@ static void port_status_handler(uint8_t rhport, bool in_isr) { // Handle ACK response static void ch_handle_ack(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) { - uint8_t const ep_num = ch_reg & USB_EPADDR_FIELD; - uint8_t const daddr = (ch_reg & USB_CHEP_DEVADDR_Msk) >> USB_CHEP_DEVADDR_Pos; + uint8_t const ep_num = ch_reg & U_EPADDR_FIELD; + uint8_t const daddr = (ch_reg & U_EP_DEVADDR) >> U_EP_DEVADDR_Pos; uint8_t ep_id = endpoint_find(daddr, ep_num | (dir == TUSB_DIR_IN ? TUSB_DIR_IN_MASK : 0)); if (ep_id == TUSB_INDEX_INVALID_8) { @@ -328,7 +328,7 @@ static void ch_handle_ack(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) { } else { // Transfer complete channel_dealloc(channel, TUSB_DIR_OUT); - edpt->pid = (ch_reg & USB_CHEP_DTOG_TX) ? 1 : 0; + edpt->pid = (ch_reg & U_EP_DTOG_TX) ? 1 : 0; hcd_event_xfer_complete(daddr, ep_num, edpt->queued_len, XFER_RESULT_SUCCESS, true); } } else { @@ -341,7 +341,7 @@ static void ch_handle_ack(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) { if ((rx_count < edpt->max_packet_size) || (edpt->queued_len >= edpt->buflen)) { // Transfer complete (short packet or all bytes received) channel_dealloc(channel, TUSB_DIR_IN); - edpt->pid = (ch_reg & USB_CHEP_DTOG_RX) ? 1 : 0; + edpt->pid = (ch_reg & U_EP_DTOG_RX) ? 1 : 0; hcd_event_xfer_complete(daddr, ep_num | TUSB_DIR_IN_MASK, edpt->queued_len, XFER_RESULT_SUCCESS, true); } else { // More data expected @@ -355,8 +355,8 @@ static void ch_handle_ack(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) { // Handle NAK response static void ch_handle_nak(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) { - uint8_t const ep_num = ch_reg & USB_EPADDR_FIELD; - uint8_t const daddr = (ch_reg & USB_CHEP_DEVADDR_Msk) >> USB_CHEP_DEVADDR_Pos; + uint8_t const ep_num = ch_reg & U_EPADDR_FIELD; + uint8_t const daddr = (ch_reg & U_EP_DEVADDR) >> U_EP_DEVADDR_Pos; uint8_t ep_id = endpoint_find(daddr, ep_num | (dir == TUSB_DIR_IN ? TUSB_DIR_IN_MASK : 0)); if (ep_id == TUSB_INDEX_INVALID_8) return; @@ -378,8 +378,8 @@ static void ch_handle_nak(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) { // Handle STALL response static void ch_handle_stall(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) { - uint8_t const ep_num = ch_reg & USB_EPADDR_FIELD; - uint8_t const daddr = (ch_reg & USB_CHEP_DEVADDR_Msk) >> USB_CHEP_DEVADDR_Pos; + uint8_t const ep_num = ch_reg & U_EPADDR_FIELD; + uint8_t const daddr = (ch_reg & U_EP_DEVADDR) >> U_EP_DEVADDR_Pos; uint8_t ep_id = endpoint_find(daddr, ep_num | (dir == TUSB_DIR_IN ? TUSB_DIR_IN_MASK : 0)); if (ep_id == TUSB_INDEX_INVALID_8) return; @@ -396,8 +396,8 @@ static void ch_handle_stall(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) { // Handle error response static void ch_handle_error(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) { - uint8_t const ep_num = ch_reg & USB_EPADDR_FIELD; - uint8_t const daddr = (ch_reg & USB_CHEP_DEVADDR_Msk) >> USB_CHEP_DEVADDR_Pos; + uint8_t const ep_num = ch_reg & U_EPADDR_FIELD; + uint8_t const daddr = (ch_reg & U_EP_DEVADDR) >> U_EP_DEVADDR_Pos; uint8_t ep_id = endpoint_find(daddr, ep_num | (dir == TUSB_DIR_IN ? TUSB_DIR_IN_MASK : 0)); if (ep_id == TUSB_INDEX_INVALID_8) return; @@ -405,8 +405,8 @@ static void ch_handle_error(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) { hcd_endpoint_t* edpt = &_hcd_data.edpt[ep_id]; hcd_channel_t* channel = &_hcd_data.channel[ch_id]; - ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(dir); - ch_reg &= ~(dir == TUSB_DIR_OUT ? USB_CH_ERRTX : USB_CH_ERRRX); + ch_reg &= U_EPREG_MASK | CH_STAT_MASK(dir); + ch_reg &= ~(dir == TUSB_DIR_OUT ? U_EP_ERRTX : U_EP_ERRRX); hcd_channel_dir_t* channel_dir = (dir == TUSB_DIR_OUT) ? &(_hcd_data.channel[ch_id].out) : &(_hcd_data.channel[ch_id].in); @@ -426,17 +426,17 @@ static void ch_handle_error(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) { // Handle CTR interrupt for the TX/OUT direction static inline void handle_ctr_tx(uint32_t ch_id) { - uint32_t ch_reg = ch_read(ch_id) | USB_EP_CTR_TX | USB_EP_CTR_RX; + uint32_t ch_reg = ch_read(ch_id) | U_EP_CTR_TX | U_EP_CTR_RX; hcd_channel_t* channel = &_hcd_data.channel[ch_id]; TU_VERIFY(channel->out.allocated == 1,); - if ((ch_reg & USB_CH_ERRTX) == 0U) { + if ((ch_reg & U_EP_ERRTX) == 0U) { // No error - if ((ch_reg & USB_CH_TX_STTX) == USB_CH_TX_ACK_SBUF) { + if ((ch_reg & U_CH_TX_STTX) == U_CH_TX_ACK_SBUF) { ch_handle_ack(ch_id, ch_reg, TUSB_DIR_OUT); - } else if ((ch_reg & USB_CH_TX_STTX) == USB_CH_TX_NAK) { + } else if ((ch_reg & U_CH_TX_STTX) == U_CH_TX_NAK) { ch_handle_nak(ch_id, ch_reg, TUSB_DIR_OUT); - } else if ((ch_reg & USB_CH_TX_STTX) == USB_CH_TX_STALL) { + } else if ((ch_reg & U_CH_TX_STTX) == U_CH_TX_STALL) { ch_handle_stall(ch_id, ch_reg, TUSB_DIR_OUT); } } else { @@ -446,17 +446,17 @@ static inline void handle_ctr_tx(uint32_t ch_id) { // Handle CTR interrupt for the RX/IN direction static inline void handle_ctr_rx(uint32_t ch_id) { - uint32_t ch_reg = ch_read(ch_id) | USB_EP_CTR_TX | USB_EP_CTR_RX; + uint32_t ch_reg = ch_read(ch_id) | U_EP_CTR_TX | U_EP_CTR_RX; hcd_channel_t* channel = &_hcd_data.channel[ch_id]; TU_VERIFY(channel->in.allocated == 1,); - if ((ch_reg & USB_CH_ERRRX) == 0U) { + if ((ch_reg & U_EP_ERRRX) == 0U) { // No error - if ((ch_reg & USB_CH_RX_STRX) == USB_CH_RX_ACK_SBUF) { + if ((ch_reg & U_CH_RX_STRX) == U_CH_RX_ACK_SBUF) { ch_handle_ack(ch_id, ch_reg, TUSB_DIR_IN); - } else if ((ch_reg & USB_CH_RX_STRX) == USB_CH_RX_NAK) { + } else if ((ch_reg & U_CH_RX_STRX) == U_CH_RX_NAK) { ch_handle_nak(ch_id, ch_reg, TUSB_DIR_IN); - } else if ((ch_reg & USB_CH_RX_STRX) == USB_CH_RX_STALL){ + } else if ((ch_reg & U_CH_RX_STRX) == U_CH_RX_STALL){ ch_handle_stall(ch_id, ch_reg, TUSB_DIR_IN); } } else { @@ -469,41 +469,41 @@ void hcd_int_handler(uint8_t rhport, bool in_isr) { uint32_t int_status = FSDEV_REG->ISTR; // Start of Frame - if (int_status & USB_ISTR_SOF) { - FSDEV_REG->ISTR = (fsdev_bus_t)~USB_ISTR_SOF; + if (int_status & U_ISTR_SOF) { + FSDEV_REG->ISTR = (fsdev_bus_t)~U_ISTR_SOF; sof_handler(); } // Port Change Detected (Connection/Disconnection) - if (int_status & USB_ISTR_DCON) { - FSDEV_REG->ISTR = (fsdev_bus_t)~USB_ISTR_DCON; + if (int_status & U_ISTR_DCON) { + FSDEV_REG->ISTR = (fsdev_bus_t)~U_ISTR_DCON; port_status_handler(rhport, in_isr); } // Handle transfer complete (CTR) - while (FSDEV_REG->ISTR & USB_ISTR_CTR) { - uint32_t const ch_id = FSDEV_REG->ISTR & USB_ISTR_EP_ID; + while (FSDEV_REG->ISTR & U_ISTR_CTR) { + uint32_t const ch_id = FSDEV_REG->ISTR & U_ISTR_EP_ID; uint32_t const ch_reg = ch_read(ch_id); - if (ch_reg & USB_EP_CTR_RX) { + if (ch_reg & U_EP_CTR_RX) { ch_write_clear_ctr(ch_id, TUSB_DIR_IN); handle_ctr_rx(ch_id); } - if (ch_reg & USB_EP_CTR_TX) { + if (ch_reg & U_EP_CTR_TX) { ch_write_clear_ctr(ch_id, TUSB_DIR_OUT); handle_ctr_tx(ch_id); } } - if (int_status & USB_ISTR_ERR) { - FSDEV_REG->ISTR = (fsdev_bus_t)~USB_ISTR_ERR; + if (int_status & U_ISTR_ERR) { + FSDEV_REG->ISTR = (fsdev_bus_t)~U_ISTR_ERR; // TODO: Handle error } - if (int_status & USB_ISTR_PMAOVR) { + if (int_status & U_ISTR_PMAOVR) { TU_BREAKPOINT(); - FSDEV_REG->ISTR = (fsdev_bus_t)~USB_ISTR_PMAOVR; + FSDEV_REG->ISTR = (fsdev_bus_t)~U_ISTR_PMAOVR; } } @@ -520,7 +520,7 @@ void hcd_int_disable(uint8_t rhport) { // Get frame number (1ms) uint32_t hcd_frame_number(uint8_t rhport) { (void) rhport; - return FSDEV_REG->FNR & USB_FNR_FN; + return FSDEV_REG->FNR & U_FNR_FN; } //--------------------------------------------------------------------+ @@ -536,19 +536,19 @@ bool hcd_port_connect_status(uint8_t rhport) { // Reset USB bus on the port void hcd_port_reset(uint8_t rhport) { (void) rhport; - FSDEV_REG->CNTR |= USB_CNTR_FRES; + FSDEV_REG->CNTR |= U_CNTR_FRES; } // Complete bus reset sequence void hcd_port_reset_end(uint8_t rhport) { (void) rhport; - FSDEV_REG->CNTR &= ~USB_CNTR_FRES; + FSDEV_REG->CNTR &= ~U_CNTR_FRES; } // Get port link speed tusb_speed_t hcd_port_speed_get(uint8_t rhport) { (void) rhport; - if ((FSDEV_REG->ISTR & USB_ISTR_LS_DCONN) != 0U) { + if ((FSDEV_REG->ISTR & U_ISTR_LS_DCONN) != 0U) { return TUSB_SPEED_LOW; } else { return TUSB_SPEED_FULL; @@ -647,7 +647,7 @@ bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { channel->dev_addr == dev_addr && channel->ep_num == tu_edpt_number(ep_addr)) { channel_dealloc(channel, dir); - uint32_t ch_reg = ch_read(i) | USB_EP_CTR_TX | USB_EP_CTR_RX; + uint32_t ch_reg = ch_read(i) | U_EP_CTR_TX | U_EP_CTR_RX; channel_write_status(i, ch_reg, dir, EP_STAT_DISABLED, true); } } @@ -724,7 +724,7 @@ static void edpoint_close(uint8_t ep_id) { // disable active channel belong to this endpoint for (uint8_t i = 0; i < FSDEV_EP_COUNT; i++) { hcd_channel_t* channel = &_hcd_data.channel[i]; - uint32_t ch_reg = ch_read(i) | USB_EP_CTR_TX | USB_EP_CTR_RX; + uint32_t ch_reg = ch_read(i) | U_EP_CTR_TX | U_EP_CTR_RX; if (channel->out.allocated == 1 && channel->out.edpt == edpt) { channel_dealloc(channel, TUSB_DIR_OUT); channel_write_status(i, ch_reg, TUSB_DIR_OUT, EP_STAT_DISABLED, true); @@ -818,21 +818,21 @@ static bool channel_xfer_start(uint8_t ch_id, tusb_dir_t dir) { hcd_channel_t* channel = &_hcd_data.channel[ch_id]; hcd_endpoint_t* edpt = (dir == TUSB_DIR_OUT) ? channel->out.edpt : channel->in.edpt; - uint32_t ch_reg = ch_read(ch_id) & ~USB_EPREG_MASK; - ch_reg |= tu_edpt_number(edpt->ep_addr) | edpt->dev_addr << USB_CHEP_DEVADDR_Pos | - USB_EP_CTR_TX | USB_EP_CTR_RX; + uint32_t ch_reg = ch_read(ch_id) & ~U_EPREG_MASK; + ch_reg |= tu_edpt_number(edpt->ep_addr) | edpt->dev_addr << U_EP_DEVADDR_Pos | + U_EP_CTR_TX | U_EP_CTR_RX; // Set type switch (edpt->ep_type) { case TUSB_XFER_BULK: - ch_reg |= USB_EP_BULK; + ch_reg |= U_EP_BULK; break; case TUSB_XFER_INTERRUPT: - ch_reg |= USB_EP_INTERRUPT; + ch_reg |= U_EP_INTERRUPT; break; case TUSB_XFER_CONTROL: - ch_reg |= USB_EP_CONTROL; + ch_reg |= U_EP_CONTROL; break; default: @@ -855,9 +855,9 @@ static bool channel_xfer_start(uint8_t ch_id, tusb_dir_t dir) { } if (edpt->ls_pre == 1) { - ch_reg |= USB_CHEP_LSEP; + ch_reg |= U_EP_LSEP; } else { - ch_reg &= ~USB_CHEP_LSEP; + ch_reg &= ~U_EP_LSEP; } // Setup DATA/STATUS phase start with DATA1 @@ -867,13 +867,13 @@ static bool channel_xfer_start(uint8_t ch_id, tusb_dir_t dir) { if (edpt->next_setup) { edpt->next_setup = false; - ch_reg |= USB_EP_SETUP; + ch_reg |= U_EP_SETUP; edpt->pid = 0; } ch_change_status(&ch_reg, dir, EP_STAT_VALID); ch_change_dtog(&ch_reg, dir, edpt->pid); - ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(dir) | CH_DTOG_MASK(dir); + ch_reg &= U_EPREG_MASK | CH_STAT_MASK(dir) | CH_DTOG_MASK(dir); ch_write(ch_id, ch_reg, true); return true; -- cgit v1.3.1 From 741132948b10d2410692b46b227da194fefb7238 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 16 Mar 2026 22:33:25 +0700 Subject: Unify USB FSDEV driver implementation for various microcontrollers. Replace `FSDEV_BUS_32BIT` with `CFG_TUSB_FSDEV_32BIT`, adjust data/address stride macros, and refactor register/PMU access for consistency across platforms. --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 4 +- src/portable/st/stm32_fsdev/fsdev_common.c | 2 +- src/portable/st/stm32_fsdev/fsdev_common.h | 180 +++++++++++--------------- src/portable/st/stm32_fsdev/fsdev_stm32.h | 16 +-- src/tusb_option.h | 4 + test/hil/tinyusb.json | 6 +- 6 files changed, 91 insertions(+), 121 deletions(-) (limited to 'src/portable') diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 965ebbbe5..c06911177 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -177,7 +177,7 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t *rh_init) { FSDEV_REG->CNTR = 0; // Enable USB - #if !defined(FSDEV_BUS_32BIT) + #if !defined( CFG_TUSB_FSDEV_32BIT) // BTABLE register does not exist any more on 32-bit bus devices FSDEV_REG->BTABLE = FSDEV_BTABLE_BASE; #endif @@ -407,7 +407,7 @@ void dcd_int_handler(uint8_t rhport) { const uint32_t ep_reg = ep_read(ep_id); if (ep_reg & U_EP_CTR_RX) { - #ifdef FSDEV_BUS_32BIT + #ifdef CFG_TUSB_FSDEV_32BIT /* https://www.st.com/resource/en/errata_sheet/es0561-stm32h503cbebkbrb-device-errata-stmicroelectronics.pdf * https://www.st.com/resource/en/errata_sheet/es0587-stm32u535xx-and-stm32u545xx-device-errata-stmicroelectronics.pdf * From H503/U535 errata: Buffer description table update completes after CTR interrupt triggers diff --git a/src/portable/st/stm32_fsdev/fsdev_common.c b/src/portable/st/stm32_fsdev/fsdev_common.c index f63b6755a..003bcd069 100644 --- a/src/portable/st/stm32_fsdev/fsdev_common.c +++ b/src/portable/st/stm32_fsdev/fsdev_common.c @@ -104,7 +104,7 @@ void btable_set_rx_bufsize(uint32_t ep_id, uint8_t buf_id, uint16_t wCount) { bl_nb = 1 << 15; } -#ifdef FSDEV_BUS_32BIT +#ifdef CFG_TUSB_FSDEV_32BIT uint32_t count_addr = FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr; count_addr = (bl_nb << 16) | (count_addr & 0x0000FFFFu); FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr = count_addr; diff --git a/src/portable/st/stm32_fsdev/fsdev_common.h b/src/portable/st/stm32_fsdev/fsdev_common.h index 36df4809d..140ff1d61 100644 --- a/src/portable/st/stm32_fsdev/fsdev_common.h +++ b/src/portable/st/stm32_fsdev/fsdev_common.h @@ -29,6 +29,10 @@ #ifndef TUSB_FSDEV_COMMON_H #define TUSB_FSDEV_COMMON_H +#ifdef __cplusplus +extern "C" { +#endif + #include "common/tusb_common.h" #if CFG_TUD_ENABLED @@ -88,7 +92,7 @@ #define U_EPREG_MASK_32 (U_EP_ERRRX | U_EP_ERRTX | U_EP_LSEP | U_EP_NAK | U_EP_DEVADDR | U_EPREG_MASK_16) // EP register mask selection based on bus width -#ifdef FSDEV_BUS_32BIT +#ifdef CFG_TUSB_FSDEV_32BIT #define U_EPREG_MASK U_EPREG_MASK_32 #else #define U_EPREG_MASK U_EPREG_MASK_16 @@ -203,89 +207,74 @@ #define U_CH_RX_VALID 0x3000u //--------------------------------------------------------------------+ -// Vendor-specific includes (after U_ definitions so they can use them) +// Registers Typedef //--------------------------------------------------------------------+ -#if defined(TUP_USBIP_FSDEV_STM32) - #include "fsdev_stm32.h" -#elif defined(TUP_USBIP_FSDEV_CH32) - #include "fsdev_ch32.h" -#elif defined(TUP_USBIP_FSDEV_AT32) - #include "fsdev_at32.h" -#else - #error "Unknown USB IP" -#endif +// hardware limit endpoint +#define FSDEV_EP_COUNT 8 -// LPM support - detect from vendor header (L1REQ bit position varies) -#if defined(USB_ISTR_L1REQ) - #define U_ISTR_L1REQ USB_ISTR_L1REQ +// The fsdev_bus_t type can be used for both register and PMA access necessities +#ifdef CFG_TUSB_FSDEV_32BIT +typedef uint32_t fsdev_bus_t; #else - #define U_ISTR_L1REQ 0x0000u +typedef uint16_t fsdev_bus_t; #endif -#define U_ISTR_ALL_EVENTS (U_ISTR_PMAOVR | U_ISTR_ERR | U_ISTR_WKUP | U_ISTR_SUSP | \ - U_ISTR_RESET | U_ISTR_SOF | U_ISTR_ESOF | U_ISTR_L1REQ) +// volatile 32-bit aligned +#define _va32 volatile TU_ATTR_ALIGNED(4) -#ifdef __cplusplus -extern "C" { -#endif +typedef struct { + struct { + _va32 fsdev_bus_t reg; + } ep[FSDEV_EP_COUNT]; + + _va32 uint32_t RESERVED7[8]; // Reserved + _va32 fsdev_bus_t CNTR; // 40: Control register + _va32 fsdev_bus_t ISTR; // 44: Interrupt status register + _va32 fsdev_bus_t FNR; // 48: Frame number register + _va32 fsdev_bus_t DADDR; // 4C: Device address register + _va32 fsdev_bus_t BTABLE; // 50: Buffer Table address register + _va32 fsdev_bus_t LPMCSR; // 54: LPM Control and Status (not on F1, F3, AT32, CH32) + _va32 fsdev_bus_t BCDR; // 58: Battery Charging Detector (not on F1, F3, AT32, CH32) +} fsdev_regs_t; + +TU_VERIFY_STATIC(offsetof(fsdev_regs_t, CNTR) == 0x40, "Wrong offset"); +TU_VERIFY_STATIC(sizeof(fsdev_regs_t) == 0x5C, "Size is not correct"); + +#define FSDEV_REG ((fsdev_regs_t *)FSDEV_REG_BASE) + +//--------------------------------------------------------------------+ +// BTable and PMA Access +//--------------------------------------------------------------------+ // If sharing with CAN, one can set this to be non-zero to give CAN space where it wants it // Both of these MUST be a multiple of 2, and are in byte units. #ifndef FSDEV_BTABLE_BASE #define FSDEV_BTABLE_BASE 0U #endif +TU_VERIFY_STATIC((FSDEV_BTABLE_BASE & 0x7) == 0, "BTABLE base must be aligned to 8 bytes"); -TU_VERIFY_STATIC(FSDEV_BTABLE_BASE % 8 == 0, "BTABLE base must be aligned to 8 bytes"); - -// CFG_TUSB_FSDEV_PMA_SIZE is PMA buffer size in bytes. -// - 512-byte devices, access with a stride of two words (use every other 16-bit address) -// - 1024-byte devices, access with a stride of one word (use every 16-bit address) or 32-bit address -// - 2048-byte devices, access with 32-bit address -#if CFG_TUSB_FSDEV_PMA_SIZE == 2048 || TU_CHECK_MCU(OPT_MCU_STM32U0) - // 32 bit access scheme - #define FSDEV_BUS_32BIT - #define FSDEV_PMA_STRIDE 1 - #define pma_access_scheme -#elif CFG_TUSB_FSDEV_PMA_SIZE == 1024 - // 2x16 bit / word access scheme - #define FSDEV_PMA_STRIDE 1 - #define pma_access_scheme -#elif CFG_TUSB_FSDEV_PMA_SIZE == 512 - // 1x16 bit / word access scheme - #define FSDEV_PMA_STRIDE 2 - #define pma_access_scheme TU_ATTR_ALIGNED(4) -#endif +#define FSDEV_ADDR_DATA_RATIO (CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE/CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE) -// The fsdev_bus_t type can be used for both register and PMA access necessities -#ifdef FSDEV_BUS_32BIT -typedef uint32_t fsdev_bus_t; +// Need alignment when access address is 32 bit but data is only 16-bit +#if FSDEV_ADDR_DATA_RATIO == 2 + #define fsdev_addr_data_align TU_ATTR_ALIGNED(4) #else -typedef uint16_t fsdev_bus_t; + #define fsdev_addr_data_align #endif -enum { - FSDEV_BUS_SIZE = sizeof(fsdev_bus_t), -}; - -//--------------------------------------------------------------------+ -// BTable Typedef -//--------------------------------------------------------------------+ enum { BTABLE_BUF_TX = 0, BTABLE_BUF_RX = 1 }; -// hardware limit endpoint -#define FSDEV_EP_COUNT 8 - // Buffer Table is located in Packet Memory Area (PMA) and therefore its address access is forced to either -// 16-bit or 32-bit depending on FSDEV_BUS_32BIT. +// 16-bit or 32-bit depending on CFG_TUSB_FSDEV_32BIT. // 0: TX (IN), 1: RX (OUT) typedef union { // data is strictly 16-bit access (address could be 32-bit aligned) struct { - volatile pma_access_scheme uint16_t addr; - volatile pma_access_scheme uint16_t count; + volatile fsdev_addr_data_align uint16_t addr; + volatile fsdev_addr_data_align uint16_t count; } ep16[FSDEV_EP_COUNT][2]; // strictly 32-bit access @@ -294,45 +283,35 @@ typedef union { } ep32[FSDEV_EP_COUNT][2]; } fsdev_btable_t; -TU_VERIFY_STATIC(sizeof(fsdev_btable_t) == FSDEV_EP_COUNT * 8 * FSDEV_PMA_STRIDE, "size is not correct"); +TU_VERIFY_STATIC(sizeof(fsdev_btable_t) == FSDEV_EP_COUNT * 8 * FSDEV_ADDR_DATA_RATIO, "size is not correct"); TU_VERIFY_STATIC(FSDEV_BTABLE_BASE + FSDEV_EP_COUNT * 8 <= CFG_TUSB_FSDEV_PMA_SIZE, "BTABLE does not fit in PMA RAM"); -#define FSDEV_BTABLE ((volatile fsdev_btable_t *)(FSDEV_PMA_BASE + FSDEV_PMA_STRIDE * (FSDEV_BTABLE_BASE))) +#define FSDEV_BTABLE ((volatile fsdev_btable_t *)(FSDEV_PMA_BASE + FSDEV_ADDR_DATA_RATIO * FSDEV_BTABLE_BASE)) typedef struct { - volatile pma_access_scheme fsdev_bus_t value; + volatile fsdev_addr_data_align fsdev_bus_t value; } fsdev_pma_buf_t; -#define PMA_BUF_AT(_addr) ((fsdev_pma_buf_t *)(FSDEV_PMA_BASE + FSDEV_PMA_STRIDE * (_addr))) +#define PMA_BUF_AT(_addr) ((fsdev_pma_buf_t *)(FSDEV_PMA_BASE + FSDEV_ADDR_DATA_RATIO * (_addr))) //--------------------------------------------------------------------+ -// Registers Typedef +// Vendor-specific includes //--------------------------------------------------------------------+ +#if defined(TUP_USBIP_FSDEV_STM32) + #include "fsdev_stm32.h" +#elif defined(TUP_USBIP_FSDEV_CH32) + #include "fsdev_ch32.h" +#elif defined(TUP_USBIP_FSDEV_AT32) + #include "fsdev_at32.h" +#else + #error "Unknown USB IP" +#endif -// volatile 32-bit aligned -#define _va32 volatile TU_ATTR_ALIGNED(4) - -typedef struct { - struct { - _va32 fsdev_bus_t reg; - } ep[FSDEV_EP_COUNT]; - - _va32 uint32_t RESERVED7[8]; // Reserved - _va32 fsdev_bus_t CNTR; // 40: Control register - _va32 fsdev_bus_t ISTR; // 44: Interrupt status register - _va32 fsdev_bus_t FNR; // 48: Frame number register - _va32 fsdev_bus_t DADDR; // 4C: Device address register - _va32 fsdev_bus_t BTABLE; // 50: Buffer Table address register - _va32 fsdev_bus_t LPMCSR; // 54: LPM Control and Status (not on F1, F3, AT32, CH32) - _va32 fsdev_bus_t BCDR; // 58: Battery Charging Detector (not on F1, F3, AT32, CH32) -} fsdev_regs_t; - -TU_VERIFY_STATIC(offsetof(fsdev_regs_t, CNTR) == 0x40, "Wrong offset"); -TU_VERIFY_STATIC(sizeof(fsdev_regs_t) == 0x5C, "Size is not correct"); - -#define FSDEV_REG ((fsdev_regs_t *)FSDEV_REG_BASE) - - +//--------------------------------------------------------------------+ +// Endpoint Helper +// - CTR is write 0 to clear +// - DTOG and STAT are write 1 to toggle +//--------------------------------------------------------------------+ typedef enum { EP_STAT_DISABLED = 0, EP_STAT_STALL = 1, @@ -346,12 +325,6 @@ typedef enum { #define CH_STAT_MASK(_dir) (3u << (U_EPTX_STAT_Pos + ((_dir) == TUSB_DIR_IN ? 8 : 0))) #define CH_DTOG_MASK(_dir) (1u << (U_EP_DTOG_TX_Pos + ((_dir) == TUSB_DIR_IN ? 8 : 0))) -//--------------------------------------------------------------------+ -// Endpoint Helper -// - CTR is write 0 to clear -// - DTOG and STAT are write 1 to toggle -//--------------------------------------------------------------------+ - TU_ATTR_ALWAYS_INLINE static inline uint32_t ep_read(uint32_t ep_id) { return FSDEV_REG->ep[ep_id].reg; } @@ -422,7 +395,7 @@ TU_ATTR_ALWAYS_INLINE static inline void ch_change_dtog(uint32_t *reg, tusb_dir_ //--------------------------------------------------------------------+ TU_ATTR_ALWAYS_INLINE static inline uint32_t btable_get_addr(uint32_t ep_id, uint8_t buf_id) { -#ifdef FSDEV_BUS_32BIT +#ifdef CFG_TUSB_FSDEV_32BIT return FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr & 0x0000FFFFu; #else return FSDEV_BTABLE->ep16[ep_id][buf_id].addr; @@ -430,9 +403,10 @@ TU_ATTR_ALWAYS_INLINE static inline uint32_t btable_get_addr(uint32_t ep_id, uin } TU_ATTR_ALWAYS_INLINE static inline void btable_set_addr(uint32_t ep_id, uint8_t buf_id, uint16_t addr) { -#ifdef FSDEV_BUS_32BIT - uint32_t count_addr = FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr; - count_addr = (count_addr & 0xFFFF0000u) | (addr & 0x0000FFFCu); +#ifdef CFG_TUSB_FSDEV_32BIT + uint32_t count_addr = FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr; + count_addr = (count_addr & 0xFFFF0000u) | (addr & 0x0000FFFCu); + FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr = count_addr; #else FSDEV_BTABLE->ep16[ep_id][buf_id].addr = addr; @@ -441,7 +415,7 @@ TU_ATTR_ALWAYS_INLINE static inline void btable_set_addr(uint32_t ep_id, uint8_t TU_ATTR_ALWAYS_INLINE static inline uint16_t btable_get_count(uint32_t ep_id, uint8_t buf_id) { uint16_t count; -#ifdef FSDEV_BUS_32BIT +#ifdef CFG_TUSB_FSDEV_32BIT count = (FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr >> 16); #else count = FSDEV_BTABLE->ep16[ep_id][buf_id].count; @@ -450,13 +424,15 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t btable_get_count(uint32_t ep_id, ui } TU_ATTR_ALWAYS_INLINE static inline void btable_set_count(uint32_t ep_id, uint8_t buf_id, uint16_t byte_count) { -#ifdef FSDEV_BUS_32BIT - uint32_t count_addr = FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr; - count_addr = (count_addr & ~0x03FF0000u) | ((byte_count & 0x3FFu) << 16); +#ifdef CFG_TUSB_FSDEV_32BIT + uint32_t count_addr = FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr; + count_addr = (count_addr & ~0x03FF0000u) | ((byte_count & 0x3FFu) << 16); + FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr = count_addr; #else - uint16_t cnt = FSDEV_BTABLE->ep16[ep_id][buf_id].count; - cnt = (cnt & ~0x3FFU) | (byte_count & 0x3FFU); + uint16_t cnt = FSDEV_BTABLE->ep16[ep_id][buf_id].count; + cnt = (cnt & ~0x3FFU) | (byte_count & 0x3FFU); + FSDEV_BTABLE->ep16[ep_id][buf_id].count = cnt; #endif } diff --git a/src/portable/st/stm32_fsdev/fsdev_stm32.h b/src/portable/st/stm32_fsdev/fsdev_stm32.h index a1c5c9488..3bb137734 100644 --- a/src/portable/st/stm32_fsdev/fsdev_stm32.h +++ b/src/portable/st/stm32_fsdev/fsdev_stm32.h @@ -101,12 +101,10 @@ #elif CFG_TUSB_MCU == OPT_MCU_STM32U0 #include "stm32u0xx.h" - #define FSDEV_BUS_32BIT #define FSDEV_HAS_SBUF_ISO 1 #elif CFG_TUSB_MCU == OPT_MCU_STM32U3 #include "stm32u3xx.h" - #define FSDEV_BUS_32BIT #define FSDEV_HAS_SBUF_ISO 1 // This is assumed to work but has not been tested... #elif CFG_TUSB_MCU == OPT_MCU_STM32U5 @@ -123,16 +121,6 @@ #error You are using an untested or unimplemented STM32 variant. Please update the driver. #endif -//--------------------------------------------------------------------+ -// USB DRD compatibility aliases -// These MCUs use a newer USB_DRD peripheral that needs the USB macro -// mapped to USB_DRD_FS for connect/disconnect register access. -//--------------------------------------------------------------------+ -#if TU_CHECK_MCU(OPT_MCU_STM32C0, OPT_MCU_STM32G0, OPT_MCU_STM32H5, \ - OPT_MCU_STM32U0, OPT_MCU_STM32U3, OPT_MCU_STM32U5) - #define USB USB_DRD_FS -#endif - //--------------------------------------------------------------------+ // Register and PMA Base Address //--------------------------------------------------------------------+ @@ -292,12 +280,12 @@ TU_ATTR_ALWAYS_INLINE static inline void fsdev_int_disable(uint8_t rhport) { TU_ATTR_ALWAYS_INLINE static inline void fsdev_disconnect(uint8_t rhport) { (void)rhport; - USB->BCDR &= ~U_BCDR_DPPU; + FSDEV_REG->BCDR &= ~U_BCDR_DPPU; } TU_ATTR_ALWAYS_INLINE static inline void fsdev_connect(uint8_t rhport) { (void)rhport; - USB->BCDR |= U_BCDR_DPPU; + FSDEV_REG->BCDR |= U_BCDR_DPPU; } #elif defined(SYSCFG_PMC_USB_PU) // works e.g. on STM32L151 diff --git a/src/tusb_option.h b/src/tusb_option.h index 3814a4d71..9eb8ee533 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -340,12 +340,16 @@ #define CFG_TUD_EDPT_DEDICATED_HWFIFO 1 #if CFG_TUSB_FSDEV_PMA_SIZE == 2048 || TU_CHECK_MCU(OPT_MCU_STM32U0) + // 32-bit access scheme #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE 4 // 32-bit data #define CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE 4 // 32-bit address increase + #define CFG_TUSB_FSDEV_32BIT #elif CFG_TUSB_FSDEV_PMA_SIZE == 1024 + // 2 x 16-bit access scheme #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE 2 // 16-bit data #define CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE 2 // 16-bit address increase #elif CFG_TUSB_FSDEV_PMA_SIZE == 512 + // 1 x 16-bit access scheme #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE 2 // 16-bit data #define CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE 4 // 32-bit address increase #endif diff --git a/test/hil/tinyusb.json b/test/hil/tinyusb.json index 8de8c7f32..e8449ba74 100644 --- a/test/hil/tinyusb.json +++ b/test/hil/tinyusb.json @@ -182,7 +182,8 @@ "name": "jlink", "uid": "779541626", "args": "-device stm32f072rb" - } + }, + "comment": "2x16 access scheme with 1KB USB SRAM" }, { "name": "stm32f723disco", @@ -226,7 +227,8 @@ "name": "openocd", "uid": "066FFF495087534867063844", "args": "-f interface/stlink.cfg -f target/stm32g0x.cfg" - } + }, + "comment": "32-bit scheme, 2KB USB SRAM" } ], "boards-skip": [ -- cgit v1.3.1 From d63f11dbdae5da68338f78708af93ece20254d50 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 16 Mar 2026 22:59:24 +0700 Subject: clean up fsdev symbols --- src/common/tusb_mcu.h | 2 + src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 14 ----- src/portable/st/stm32_fsdev/fsdev_stm32.h | 73 ++++++++++----------------- 3 files changed, 28 insertions(+), 61 deletions(-) (limited to 'src/portable') diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index edc7ecc3e..34dd6af8d 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -241,9 +241,11 @@ #if defined(STM32F302xB) || defined(STM32F302xC) || defined(STM32F303xB) || defined(STM32F303xC) || \ defined(STM32F373xC) + // xB, and xC: 512 #define CFG_TUSB_FSDEV_PMA_SIZE 512u #elif defined(STM32F302x6) || defined(STM32F302x8) || defined(STM32F302xD) || defined(STM32F302xE) || \ defined(STM32F303xD) || defined(STM32F303xE) + // x6, x8, xD, and xE: 1024 + LPM Support #define CFG_TUSB_FSDEV_PMA_SIZE 1024u #else #error "Unsupported STM32F3 mcu" diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index c06911177..13d1a6cb4 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -59,7 +59,6 @@ * - Enable USB clock; Perhaps use __HAL_RCC_USB_CLK_ENABLE(); * - (Optionally configure GPIO HAL to tell it the USB driver is using the USB pins) * - call tusb_init(); - * - periodically call tusb_task(); * * Assumptions of the driver: * - You are not using CAN (it must share the packet buffer) @@ -87,19 +86,6 @@ * below functions could be adjusting the wrong interrupts (if they had been reconfigured) * - LPM is not used correctly, or at all? * - * USB documentation and Reference implementations - * - STM32 Reference manuals - * - STM32 USB Hardware Guidelines AN4879 - * - * - STM32 HAL (much of this driver is based on this) - * - libopencm3/lib/stm32/common/st_usbfs_core.c - * - Keil USB Device http://www.keil.com/pack/doc/mw/USB/html/group__usbd.html - * - * - YouTube OpenTechLab 011; https://www.youtube.com/watch?v=4FOkJLp_PUw - * - * Advantages over HAL driver: - * - Tiny (saves RAM, assumes a single USB peripheral) - * * Notes: * - The buffer table is allocated as endpoints are opened. The allocation is only * cleared when the device is reset. This may be bad if the USB device needs diff --git a/src/portable/st/stm32_fsdev/fsdev_stm32.h b/src/portable/st/stm32_fsdev/fsdev_stm32.h index 3bb137734..a63592c5d 100644 --- a/src/portable/st/stm32_fsdev/fsdev_stm32.h +++ b/src/portable/st/stm32_fsdev/fsdev_stm32.h @@ -38,7 +38,6 @@ #elif CFG_TUSB_MCU == OPT_MCU_STM32F0 #include "stm32f0xx.h" - #define FSDEV_REG_BASE USB_BASE #define FSDEV_HAS_SBUF_ISO 0 // F0x2 models are crystal-less // All have internal D+ pull-up @@ -51,21 +50,24 @@ // NO internal Pull-ups // *B, and *C: 2 x 16 bits/word -#elif defined(STM32F302xB) || defined(STM32F302xC) || defined(STM32F303xB) || defined(STM32F303xC) || \ - defined(STM32F373xC) +#elif CFG_TUSB_MCU == OPT_MCU_STM32F3 #include "stm32f3xx.h" #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) + // NO internal Pull-ups. PMA dedicated to USB (no sharing with CAN) + // xB, and xC: 512 bytes + // x6, x8, xD, and xE: 1024 bytes + LPM Support. When CAN clock is enabled, USB can use the first 768 bytes ONLY. -#elif defined(STM32F302x6) || defined(STM32F302x8) || defined(STM32F302xD) || defined(STM32F302xE) || \ - defined(STM32F303xD) || defined(STM32F303xE) - #include "stm32f3xx.h" +#elif CFG_TUSB_MCU == OPT_MCU_STM32G0 + #include "stm32g0xx.h" + #define FSDEV_HAS_SBUF_ISO 1 + +#elif CFG_TUSB_MCU == OPT_MCU_STM32G4 + #include "stm32g4xx.h" #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. + +#elif CFG_TUSB_MCU == OPT_MCU_STM32H5 + #include "stm32h5xx.h" + #define FSDEV_HAS_SBUF_ISO 1 #elif CFG_TUSB_MCU == OPT_MCU_STM32L0 #include "stm32l0xx.h" @@ -87,25 +89,13 @@ #define USB_PMAADDR (USB_BASE + (USB_PMAADDR_NS - USB_BASE_NS)) #endif -#elif CFG_TUSB_MCU == OPT_MCU_STM32G0 - #include "stm32g0xx.h" - #define FSDEV_HAS_SBUF_ISO 1 - -#elif CFG_TUSB_MCU == OPT_MCU_STM32G4 - #include "stm32g4xx.h" - #define FSDEV_HAS_SBUF_ISO 0 - -#elif CFG_TUSB_MCU == OPT_MCU_STM32H5 - #include "stm32h5xx.h" - #define FSDEV_HAS_SBUF_ISO 1 - #elif CFG_TUSB_MCU == OPT_MCU_STM32U0 #include "stm32u0xx.h" #define FSDEV_HAS_SBUF_ISO 1 #elif CFG_TUSB_MCU == OPT_MCU_STM32U3 #include "stm32u3xx.h" - #define FSDEV_HAS_SBUF_ISO 1 // This is assumed to work but has not been tested... + #define FSDEV_HAS_SBUF_ISO 1 #elif CFG_TUSB_MCU == OPT_MCU_STM32U5 #include "stm32u5xx.h" @@ -114,8 +104,6 @@ #elif CFG_TUSB_MCU == OPT_MCU_STM32WB #include "stm32wbxx.h" #define FSDEV_HAS_SBUF_ISO 0 - /* ST provided header has incorrect value of USB_PMAADDR */ - #define FSDEV_PMA_BASE USB1_PMAADDR #else #error You are using an untested or unimplemented STM32 variant. Please update the driver. @@ -185,42 +173,33 @@ #endif static const IRQn_Type fsdev_irq[] = { - #if TU_CHECK_MCU(OPT_MCU_STM32F0, OPT_MCU_STM32L0, OPT_MCU_STM32L4) + #if TU_CHECK_MCU(OPT_MCU_STM32F0, OPT_MCU_STM32L0, OPT_MCU_STM32L4, OPT_MCU_STM32U5) + USB_IRQn, + #elif TU_CHECK_MCU(OPT_MCU_STM32L5, OPT_MCU_STM32U3) + USB_FS_IRQn, + #elif TU_CHECK_MCU(OPT_MCU_STM32C0, OPT_MCU_STM32H5, OPT_MCU_STM32U0) + USB_DRD_FS_IRQn, + #elif CFG_TUSB_MCU == OPT_MCU_STM32G0 + #ifdef STM32G0B0xx USB_IRQn, + #else + USB_UCPD1_2_IRQn, + #endif #elif CFG_TUSB_MCU == OPT_MCU_STM32F1 USB_HP_CAN1_TX_IRQn, USB_LP_CAN1_RX0_IRQn, USBWakeUp_IRQn, #elif CFG_TUSB_MCU == OPT_MCU_STM32F3 - // USB remap handles dcd functions USB_HP_CAN_TX_IRQn, USB_LP_CAN_RX0_IRQn, USBWakeUp_IRQn, - #elif CFG_TUSB_MCU == OPT_MCU_STM32G0 - #ifdef STM32G0B0xx - USB_IRQn, - #else - USB_UCPD1_2_IRQn, - #endif - #elif CFG_TUSB_MCU == OPT_MCU_STM32C0 - USB_DRD_FS_IRQn, #elif TU_CHECK_MCU(OPT_MCU_STM32G4, OPT_MCU_STM32L1) USB_HP_IRQn, USB_LP_IRQn, USBWakeUp_IRQn, - #elif CFG_TUSB_MCU == OPT_MCU_STM32H5 - USB_DRD_FS_IRQn, - #elif CFG_TUSB_MCU == OPT_MCU_STM32L5 - USB_FS_IRQn, #elif CFG_TUSB_MCU == OPT_MCU_STM32WB USB_HP_IRQn, USB_LP_IRQn, - #elif CFG_TUSB_MCU == OPT_MCU_STM32U5 - USB_IRQn, - #elif CFG_TUSB_MCU == OPT_MCU_STM32U0 - USB_DRD_FS_IRQn, - #elif CFG_TUSB_MCU == OPT_MCU_STM32U3 - USB_FS_IRQn, #else #error Unknown arch in USB driver #endif -- cgit v1.3.1 From b7656561b86b68763e5aa2da5261e5a79e5ff53d Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 18 Mar 2026 12:56:54 +0700 Subject: fix hid_generic_inout for TUD_ENDPOINT_ONE_DIRECTION_ONLY MCUs Use separate endpoint numbers (EP1 OUT, EP2 IN) on MCUs with shared FIFO that cannot support the same endpoint number in both directions. Also add missing static qualifier to print_musb_info(). Co-Authored-By: Claude Opus 4.6 (1M context) --- examples/device/hid_generic_inout/src/usb_descriptors.c | 12 ++++++++++-- src/portable/mentor/musb/dcd_musb.c | 2 +- 2 files changed, 11 insertions(+), 3 deletions(-) (limited to 'src/portable') diff --git a/examples/device/hid_generic_inout/src/usb_descriptors.c b/examples/device/hid_generic_inout/src/usb_descriptors.c index f26333d50..929b2fd3a 100644 --- a/examples/device/hid_generic_inout/src/usb_descriptors.c +++ b/examples/device/hid_generic_inout/src/usb_descriptors.c @@ -97,7 +97,15 @@ enum #define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_HID_INOUT_DESC_LEN) -#define EPNUM_HID 0x01 +#if defined(TUD_ENDPOINT_ONE_DIRECTION_ONLY) + // MCUs that don't support a same endpoint number with different direction IN and OUT defined in tusb_mcu.h + // e.g EP1 OUT & EP1 IN cannot exist together + #define EPNUM_HID_OUT 0x01 + #define EPNUM_HID_IN 0x82 +#else + #define EPNUM_HID_OUT 0x01 + #define EPNUM_HID_IN 0x81 +#endif uint8_t const desc_configuration[] = { @@ -105,7 +113,7 @@ uint8_t const desc_configuration[] = TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), // Interface number, string index, protocol, report descriptor len, EP Out & In address, size & polling interval - TUD_HID_INOUT_DESCRIPTOR(ITF_NUM_HID, 0, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, 0x80 | EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 10) + TUD_HID_INOUT_DESCRIPTOR(ITF_NUM_HID, 0, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID_OUT, EPNUM_HID_IN, CFG_TUD_HID_EP_BUFSIZE, 10) }; // Invoked when received GET CONFIGURATION DESCRIPTOR diff --git a/src/portable/mentor/musb/dcd_musb.c b/src/portable/mentor/musb/dcd_musb.c index d329285e9..339048473 100644 --- a/src/portable/mentor/musb/dcd_musb.c +++ b/src/portable/mentor/musb/dcd_musb.c @@ -494,7 +494,7 @@ static void process_bus_reset(uint8_t rhport) { *------------------------------------------------------------------*/ #if CFG_TUSB_DEBUG >= MUSB_DEBUG -void print_musb_info(musb_regs_t* musb_regs) { +static void print_musb_info(musb_regs_t* musb_regs) { // print version, epinfo, raminfo, config_data0, fifo_size TU_LOG1("musb version = %u.%u\r\n", musb_regs->hwvers_bit.major, musb_regs->hwvers_bit.minor); TU_LOG1("Number of endpoints: %u TX, %u RX\r\n", musb_regs->epinfo_bit.tx_ep_num, musb_regs->epinfo_bit.rx_ep_num); -- cgit v1.3.1 From 6b0d20d70dbe0462fc89a92ab0c0ca04a9c625d0 Mon Sep 17 00:00:00 2001 From: alt-0191 <2223147307@qq.com> Date: Thu, 26 Feb 2026 20:46:39 +0800 Subject: add WCH CH58x (CH582/CH583) BSP and USB FS device/host driver --- hw/bsp/ch58x/boards/yd-ch582m/board.cmake | 5 + hw/bsp/ch58x/boards/yd-ch582m/board.h | 57 +++ hw/bsp/ch58x/boards/yd-ch582m/board.mk | 3 + hw/bsp/ch58x/ch58x_it.c | 37 ++ hw/bsp/ch58x/ch58x_it.h | 46 ++ hw/bsp/ch58x/debug_uart.c | 80 ++++ hw/bsp/ch58x/debug_uart.h | 36 ++ hw/bsp/ch58x/family.c | 181 ++++++++ hw/bsp/ch58x/family.cmake | 103 +++++ hw/bsp/ch58x/family.mk | 49 ++ hw/bsp/ch58x/linker/ch582.ld | 167 +++++++ hw/bsp/ch58x/system_ch58x.c | 39 ++ hw/bsp/ch58x/system_ch58x.h | 43 ++ hw/bsp/ch58x/wch-riscv.cfg | 17 + src/common/tusb_mcu.h | 14 + src/portable/wch/ch58x_usbfs_reg.h | 299 +++++++++++++ src/portable/wch/dcd_ch58x_usbfs.c | 583 ++++++++++++++++++++++++ src/portable/wch/hcd_ch58x_usbfs.c | 712 ++++++++++++++++++++++++++++++ src/tusb_option.h | 1 + 19 files changed, 2472 insertions(+) create mode 100644 hw/bsp/ch58x/boards/yd-ch582m/board.cmake create mode 100644 hw/bsp/ch58x/boards/yd-ch582m/board.h create mode 100644 hw/bsp/ch58x/boards/yd-ch582m/board.mk create mode 100644 hw/bsp/ch58x/ch58x_it.c create mode 100644 hw/bsp/ch58x/ch58x_it.h create mode 100644 hw/bsp/ch58x/debug_uart.c create mode 100644 hw/bsp/ch58x/debug_uart.h create mode 100644 hw/bsp/ch58x/family.c create mode 100644 hw/bsp/ch58x/family.cmake create mode 100644 hw/bsp/ch58x/family.mk create mode 100644 hw/bsp/ch58x/linker/ch582.ld create mode 100644 hw/bsp/ch58x/system_ch58x.c create mode 100644 hw/bsp/ch58x/system_ch58x.h create mode 100644 hw/bsp/ch58x/wch-riscv.cfg create mode 100644 src/portable/wch/ch58x_usbfs_reg.h create mode 100644 src/portable/wch/dcd_ch58x_usbfs.c create mode 100644 src/portable/wch/hcd_ch58x_usbfs.c (limited to 'src/portable') diff --git a/hw/bsp/ch58x/boards/yd-ch582m/board.cmake b/hw/bsp/ch58x/boards/yd-ch582m/board.cmake new file mode 100644 index 000000000..4129c4550 --- /dev/null +++ b/hw/bsp/ch58x/boards/yd-ch582m/board.cmake @@ -0,0 +1,5 @@ +set(LD_FLASH_SIZE 448K) +set(LD_RAM_SIZE 32K) + +function(update_board TARGET) +endfunction() diff --git a/hw/bsp/ch58x/boards/yd-ch582m/board.h b/hw/bsp/ch58x/boards/yd-ch582m/board.h new file mode 100644 index 000000000..6e25dbdd3 --- /dev/null +++ b/hw/bsp/ch58x/boards/yd-ch582m/board.h @@ -0,0 +1,57 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2024 TinyUSB contributors + * + * 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. + */ + +/* metadata: + name: yd-ch582m from vcc-gnd studio + url: http://vcc-gnd.com/ +*/ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +// LED: PB4 on yd-ch582m board +#define LED_PIN GPIO_Pin_4 +#define LED_STATE_ON 0 + +// Directly reuse BOOT pin as user button +#define BUTTON_PIN GPIO_Pin_22 +#define BUTTON_STATE_ACTIVE 0 + +// UART: UART1 TX=PA9, RX=PA8 +#define CFG_BOARD_UART_BAUDRATE 115200 + +// Dual-port: USB1 (rhport 0) = Device, USB2 (rhport 1) = Host +// Swap these two if you want the opposite assignment +#define BOARD_TUD_RHPORT 0 +#define BOARD_TUH_RHPORT 1 + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/hw/bsp/ch58x/boards/yd-ch582m/board.mk b/hw/bsp/ch58x/boards/yd-ch582m/board.mk new file mode 100644 index 000000000..a13979799 --- /dev/null +++ b/hw/bsp/ch58x/boards/yd-ch582m/board.mk @@ -0,0 +1,3 @@ +LDFLAGS += \ + -Wl,--defsym=__FLASH_SIZE=448K \ + -Wl,--defsym=__RAM_SIZE=32K \ diff --git a/hw/bsp/ch58x/ch58x_it.c b/hw/bsp/ch58x/ch58x_it.c new file mode 100644 index 000000000..2211e1eda --- /dev/null +++ b/hw/bsp/ch58x/ch58x_it.c @@ -0,0 +1,37 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2024 TinyUSB contributors + * + * 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 "ch58x_it.h" + +// NMI exception handler +__INTERRUPT __HIGH_CODE void NMI_Handler(void) { + while (1) {} +} + +// Hard Fault exception handler +__INTERRUPT __HIGH_CODE void HardFault_Handler(void) { + while (1) {} +} diff --git a/hw/bsp/ch58x/ch58x_it.h b/hw/bsp/ch58x/ch58x_it.h new file mode 100644 index 000000000..c98f732e1 --- /dev/null +++ b/hw/bsp/ch58x/ch58x_it.h @@ -0,0 +1,46 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2024 TinyUSB contributors + * + * 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 __CH58X_IT_H +#define __CH58X_IT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "CH58x_common.h" + +void NMI_Handler(void); +void HardFault_Handler(void); +void USB_IRQHandler(void); +void USB2_IRQHandler(void); +void SysTick_Handler(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __CH58X_IT_H */ diff --git a/hw/bsp/ch58x/debug_uart.c b/hw/bsp/ch58x/debug_uart.c new file mode 100644 index 000000000..e63606f33 --- /dev/null +++ b/hw/bsp/ch58x/debug_uart.c @@ -0,0 +1,80 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2024 TinyUSB contributors + * + * 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 "debug_uart.h" +#include "CH58x_common.h" + +//--------------------------------------------------------------------+ +// Ring buffer based UART TX for non-blocking writes +//--------------------------------------------------------------------+ + +#define UART_RINGBUFFER_SIZE_TX 128 +#define UART_RINGBUFFER_MASK_TX (UART_RINGBUFFER_SIZE_TX - 1) + +static char tx_buf[UART_RINGBUFFER_SIZE_TX]; +static unsigned int tx_produce; +static volatile unsigned int tx_consume; + +void uart_write(char c) { + unsigned int tx_produce_next = (tx_produce + 1) & UART_RINGBUFFER_MASK_TX; + + // If ring buffer is full, wait + while (tx_produce_next == tx_consume) {} + + // If UART TX FIFO is empty and no pending data, send directly + if ((tx_consume == tx_produce) && (R8_UART1_LSR & RB_LSR_TX_FIFO_EMP)) { + R8_UART1_THR = c; + } else { + tx_buf[tx_produce] = c; + tx_produce = tx_produce_next; + } +} + +void uart_sync(void) { + // Wait for ring buffer to drain + while (tx_consume != tx_produce) { + if (R8_UART1_LSR & RB_LSR_TX_FIFO_EMP) { + R8_UART1_THR = tx_buf[tx_consume]; + tx_consume = (tx_consume + 1) & UART_RINGBUFFER_MASK_TX; + } + } + // Wait for last byte to finish transmitting + while (!(R8_UART1_LSR & RB_LSR_TX_ALL_EMP)) {} +} + +void usart_printf_init(uint32_t baudrate) { + tx_produce = 0; + tx_consume = 0; + + // Configure UART1 pins: TX=PA9, RX=PA8 + GPIOA_SetBits(GPIO_Pin_9); + GPIOA_ModeCfg(GPIO_Pin_9, GPIO_ModeOut_PP_5mA); + GPIOA_ModeCfg(GPIO_Pin_8, GPIO_ModeIN_PU); + + // Init UART1 with specified baud rate + UART1_DefInit(); + UART1_BaudRateCfg(baudrate); +} diff --git a/hw/bsp/ch58x/debug_uart.h b/hw/bsp/ch58x/debug_uart.h new file mode 100644 index 000000000..458d838d9 --- /dev/null +++ b/hw/bsp/ch58x/debug_uart.h @@ -0,0 +1,36 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2024 TinyUSB contributors + * + * 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 DEBUG_UART_H_ +#define DEBUG_UART_H_ + +#include + +void uart_write(char c); +void uart_sync(void); +void usart_printf_init(uint32_t baudrate); + +#endif /* DEBUG_UART_H_ */ diff --git a/hw/bsp/ch58x/family.c b/hw/bsp/ch58x/family.c new file mode 100644 index 000000000..463ca5637 --- /dev/null +++ b/hw/bsp/ch58x/family.c @@ -0,0 +1,181 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2024 TinyUSB contributors + * + * 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: WCH +*/ + +// WCH SDK's DEBUG macro enables a _write() that conflicts with TinyUSB's. +// TinyUSB uses UART1 for printf via debug_uart.c, so DEBUG is not needed. +// If you need a different UART or want to keep SDK's DEBUG, modify +// debug_uart.c (TinyUSB side) or CH58x_sys.c (SDK side) to remove one _write(). +// If done, remove this #error to continue. +#ifdef DEBUG + #error "Remove the DEBUG macro from preprocessor defines to avoid " \ + "duplicate _write() between WCH SDK and TinyUSB. " \ + "TinyUSB uses UART1 by default (see debug_uart.c)." +#endif + +#include "debug_uart.h" +#include "CH58x_common.h" +#include "ch58x_it.h" + +#include "bsp/board_api.h" +#include "board.h" + +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ + +__INTERRUPT __HIGH_CODE void USB_IRQHandler(void) { + tusb_int_handler(0, true); +} + +__INTERRUPT __HIGH_CODE void USB2_IRQHandler(void) { + tusb_int_handler(1, true); +} + +//--------------------------------------------------------------------+ +// SysTick +//--------------------------------------------------------------------+ + +#if CFG_TUSB_OS == OPT_OS_NONE +volatile uint32_t system_ticks = 0; + +__INTERRUPT __HIGH_CODE void SysTick_Handler(void) { + SysTick->SR = 0; + system_ticks++; +} + +uint32_t board_millis(void) { + return system_ticks; +} +#endif + +//--------------------------------------------------------------------+ +// Board Init +//--------------------------------------------------------------------+ + +void board_init(void) { + // Disable interrupts during init + PFIC_DisableAllIRQ(); + + // Set system clock to PLL 60MHz (default for CH582) + SetSysClock(CLK_SOURCE_PLL_60MHz); + +#if CFG_TUSB_OS == OPT_OS_NONE + SysTick_Config(GetSysClock() / 1000); +#endif + + // UART1 init for debug output +#ifdef CFG_BOARD_UART_BAUDRATE + usart_printf_init(CFG_BOARD_UART_BAUDRATE); +#endif + + // LED +#ifdef LED_PORT_IS_A + GPIOA_ModeCfg(LED_PIN, GPIO_ModeOut_PP_5mA); +#else + GPIOB_ModeCfg(LED_PIN, GPIO_ModeOut_PP_5mA); +#endif + + // Button +#ifdef BUTTON_PIN + #ifdef BUTTON_PORT_IS_A + GPIOA_ModeCfg(BUTTON_PIN, GPIO_ModeIN_PU); + #else + GPIOB_ModeCfg(BUTTON_PIN, GPIO_ModeIN_PU); + #endif +#endif + + // USB pin enable: enable analog function for USB1 and USB2 D+/D- + R16_PIN_ANALOG_IE |= RB_PIN_USB_IE | RB_PIN_USB2_IE; + + // D+ pull-up is only needed for the device-role port +#if CFG_TUD_ENABLED + #if BOARD_TUD_RHPORT == 0 + R16_PIN_ANALOG_IE |= RB_PIN_USB_DP_PU; + #else + R16_PIN_ANALOG_IE |= RB_PIN_USB2_DP_PU; + #endif +#endif + + // Keep USB clock active during sleep + R8_SLP_CLK_OFF1 &= ~RB_SLP_CLK_USB; + + // Enable interrupts globally + PFIC_EnableAllIRQ(); + + board_delay(2); +} + +//--------------------------------------------------------------------+ +// Board porting API +//--------------------------------------------------------------------+ + +void board_led_write(bool state) { +#ifdef LED_PORT_IS_A + if (state ^ LED_STATE_ON) { + GPIOA_ResetBits(LED_PIN); + } else { + GPIOA_SetBits(LED_PIN); + } +#else + if (state ^ LED_STATE_ON) { + GPIOB_ResetBits(LED_PIN); + } else { + GPIOB_SetBits(LED_PIN); + } +#endif +} + +uint32_t board_button_read(void) { +#ifdef BUTTON_PIN + #ifdef BUTTON_PORT_IS_A + return BUTTON_STATE_ACTIVE == (GPIOA_ReadPortPin(BUTTON_PIN) ? 1 : 0); + #else + return BUTTON_STATE_ACTIVE == (GPIOB_ReadPortPin(BUTTON_PIN) ? 1 : 0); + #endif +#else + return 0; +#endif +} + +int board_uart_read(uint8_t* buf, int len) { + (void) buf; + (void) len; + return 0; +} + +int board_uart_write(void const* buf, int len) { + int txsize = len; + const char* bufc = (const char*) buf; + while (txsize--) { + uart_write(*bufc++); + } + uart_sync(); + return len; +} diff --git a/hw/bsp/ch58x/family.cmake b/hw/bsp/ch58x/family.cmake new file mode 100644 index 000000000..9ad158662 --- /dev/null +++ b/hw/bsp/ch58x/family.cmake @@ -0,0 +1,103 @@ +include_guard() + +set(SDK_DIR ${TOP}/hw/mcu/wch/ch58x) +set(SDK_SRC_DIR ${SDK_DIR}/EVT/EXAM/SRC) + +# include board specific +include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) + +# toolchain set up +set(CMAKE_SYSTEM_CPU rv32imac-ilp32 CACHE INTERNAL "System Processor") +set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/riscv_${TOOLCHAIN}.cmake) + +set(FAMILY_MCUS CH582 CACHE INTERNAL "") +set(OPENOCD_OPTION "-f ${CMAKE_CURRENT_LIST_DIR}/wch-riscv.cfg") + +#------------------------------------ +# Startup & Linker script +#------------------------------------ +if (NOT DEFINED LD_FILE_GNU) + set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/linker/ch582.ld) +endif () +set(LD_FILE_Clang ${LD_FILE_GNU}) +if (NOT DEFINED STARTUP_FILE_GNU) + set(STARTUP_FILE_GNU ${SDK_SRC_DIR}/Startup/startup_CH583.S) +endif () +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) + +#------------------------------------ +# Board Target +#------------------------------------ +function(family_add_board BOARD_TARGET) + add_library(${BOARD_TARGET} STATIC + ${SDK_SRC_DIR}/StdPeriphDriver/CH58x_gpio.c + ${SDK_SRC_DIR}/StdPeriphDriver/CH58x_clk.c + ${SDK_SRC_DIR}/StdPeriphDriver/CH58x_uart1.c + ${SDK_SRC_DIR}/StdPeriphDriver/CH58x_sys.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/ch58x_it.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/system_ch58x.c + ) + target_include_directories(${BOARD_TARGET} PUBLIC + ${SDK_SRC_DIR}/RVMSIS + ${SDK_SRC_DIR}/StdPeriphDriver/inc + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ) + target_compile_definitions(${BOARD_TARGET} PUBLIC + CFG_TUD_WCH_USBIP_USBFS=1 + FREQ_SYS=60000000 + ) + + update_board(${BOARD_TARGET}) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_compile_options(${BOARD_TARGET} PUBLIC + -msmall-data-limit=8 + -mno-save-restore + -fmessage-length=0 + -fsigned-char + ) + endif () +endfunction() + +#------------------------------------ +# Functions +#------------------------------------ +function(family_configure_example TARGET RTOS) + family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_CH582) + + target_sources(${TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/debug_uart.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/wch/dcd_ch58x_usbfs.c + ${TOP}/src/portable/wch/hcd_ch58x_usbfs.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} + ) + target_include_directories(${TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} + ) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + -nostartfiles + --specs=nosys.specs --specs=nano.specs + -Wl,--defsym=__FLASH_SIZE=${LD_FLASH_SIZE} + -Wl,--defsym=__RAM_SIZE=${LD_RAM_SIZE} + "LINKER:--script=${LD_FILE_GNU}" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + message(FATAL_ERROR "Clang is not supported for CH58x") + endif () + + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) + + # Flashing + family_add_bin_hex(${TARGET}) + family_flash_openocd_wch(${TARGET}) + family_flash_wlink_rs(${TARGET}) +endfunction() diff --git a/hw/bsp/ch58x/family.mk b/hw/bsp/ch58x/family.mk new file mode 100644 index 000000000..41eb36c84 --- /dev/null +++ b/hw/bsp/ch58x/family.mk @@ -0,0 +1,49 @@ +# Toolchain from https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack +CROSS_COMPILE ?= riscv-none-elf- + +SDK_DIR = hw/mcu/wch/ch58x +SDK_SRC_DIR = $(SDK_DIR)/EVT/EXAM/SRC + +include $(TOP)/$(BOARD_PATH)/board.mk +CPU_CORE ?= rv32imac-ilp32 + +CFLAGS += \ + -flto \ + -msmall-data-limit=8 \ + -mno-save-restore \ + -fmessage-length=0 \ + -fsigned-char \ + -DCFG_TUSB_MCU=OPT_MCU_CH582 \ + -DCFG_TUD_WCH_USBIP_USBFS=1 \ + -DFREQ_SYS=60000000 \ + +LDFLAGS_GCC += \ + -nostdlib -nostartfiles \ + --specs=nosys.specs --specs=nano.specs \ + +SRC_C += \ + src/portable/wch/dcd_ch58x_usbfs.c \ + src/portable/wch/hcd_ch58x_usbfs.c \ + $(SDK_SRC_DIR)/StdPeriphDriver/CH58x_gpio.c \ + $(SDK_SRC_DIR)/StdPeriphDriver/CH58x_clk.c \ + $(SDK_SRC_DIR)/StdPeriphDriver/CH58x_uart1.c \ + $(SDK_SRC_DIR)/StdPeriphDriver/CH58x_sys.c \ + $(FAMILY_PATH)/debug_uart.c \ + $(FAMILY_PATH)/ch58x_it.c \ + $(FAMILY_PATH)/system_ch58x.c \ + +SRC_S += \ + $(SDK_SRC_DIR)/Startup/startup_CH583.S + +INC += \ + $(TOP)/$(BOARD_PATH) \ + $(TOP)/$(SDK_SRC_DIR)/RVMSIS \ + $(TOP)/$(SDK_SRC_DIR)/StdPeriphDriver/inc + +LD_FILE ?= $(FAMILY_PATH)/linker/ch582.ld + +OPENOCD_WCH_OPTION=-f $(TOP)/$(FAMILY_PATH)/wch-riscv.cfg +flash: flash-openocd-wch + +# For freeRTOS port source +FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/RISC-V diff --git a/hw/bsp/ch58x/linker/ch582.ld b/hw/bsp/ch58x/linker/ch582.ld new file mode 100644 index 000000000..821998a49 --- /dev/null +++ b/hw/bsp/ch58x/linker/ch582.ld @@ -0,0 +1,167 @@ +/* CH582 Linker Script for TinyUSB + * Based on WCH CH583 SDK Link.ld + * Supports parameterized flash/ram sizes via --defsym + */ + +/* Default sizes if not provided via --defsym */ +__flash_size = DEFINED(__FLASH_SIZE) ? __FLASH_SIZE : 448K; +__ram_size = DEFINED(__RAM_SIZE) ? __RAM_SIZE : 32K; +__stack_size = DEFINED(__STACK_SIZE) ? __STACK_SIZE : 2048; + +ENTRY( _start ) + +PROVIDE( _stack_size = __stack_size ); + +MEMORY +{ + FLASH (rx) : ORIGIN = 0x00000000, LENGTH = __flash_size + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = __ram_size +} + +SECTIONS +{ + .init : + { + _sinit = .; + . = ALIGN(4); + KEEP(*(SORT_NONE(.init))) + . = ALIGN(4); + _einit = .; + } >FLASH AT>FLASH + + .highcodelalign : + { + . = ALIGN(4); + PROVIDE(_highcode_lma = .); + } >FLASH AT>FLASH + + .highcode : + { + . = ALIGN(4); + PROVIDE(_highcode_vma_start = .); + *(.vector); + KEEP(*(SORT_NONE(.vector_handler))) + *(.highcode); + *(.highcode.*); + . = ALIGN(4); + PROVIDE(_highcode_vma_end = .); + } >RAM AT>FLASH + + .text : + { + . = ALIGN(4); + KEEP(*(SORT_NONE(.handle_reset))) + *(.text) + *(.text.*) + *(.rodata) + *(.rodata*) + *(.sdata2.*) + *(.glue_7) + *(.glue_7t) + *(.gnu.linkonce.t.*) + . = ALIGN(4); + } >FLASH AT>FLASH + + .fini : + { + KEEP(*(SORT_NONE(.fini))) + . = ALIGN(4); + } >FLASH AT>FLASH + + PROVIDE( _etext = . ); + PROVIDE( _eitcm = . ); + + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } >FLASH AT>FLASH + + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) + KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) + PROVIDE_HIDDEN (__init_array_end = .); + } >FLASH AT>FLASH + + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) + KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) + PROVIDE_HIDDEN (__fini_array_end = .); + } >FLASH AT>FLASH + + .ctors : + { + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } >FLASH AT>FLASH + + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } >FLASH AT>FLASH + + .dlalign : + { + . = ALIGN(4); + PROVIDE(_data_lma = .); + } >FLASH AT>FLASH + + .data : + { + . = ALIGN(4); + PROVIDE(_data_vma = .); + *(.gnu.linkonce.r.*) + *(.data .data.*) + *(.gnu.linkonce.d.*) + . = ALIGN(8); + PROVIDE( __global_pointer$ = . + 0x800 ); + *(.sdata .sdata.*) + *(.gnu.linkonce.s.*) + . = ALIGN(8); + *(.srodata.cst16) + *(.srodata.cst8) + *(.srodata.cst4) + *(.srodata.cst2) + *(.srodata .srodata.*) + . = ALIGN(4); + PROVIDE( _edata = .); + } >RAM AT>FLASH + + .bss : + { + . = ALIGN(4); + PROVIDE( _sbss = .); + *(.sbss*) + *(.gnu.linkonce.sb.*) + *(.bss*) + *(.gnu.linkonce.b.*) + *(COMMON*) + . = ALIGN(4); + PROVIDE( _ebss = .); + } >RAM AT>FLASH + + PROVIDE( _end = _ebss); + PROVIDE( end = . ); + + .stack ORIGIN(RAM) + LENGTH(RAM) - __stack_size : + { + PROVIDE( _heap_end = . ); + . = ALIGN(4); + PROVIDE(_susrstack = . ); + . = . + __stack_size; + PROVIDE( _eusrstack = .); + __freertos_irq_stack_top = .; + } >RAM +} diff --git a/hw/bsp/ch58x/system_ch58x.c b/hw/bsp/ch58x/system_ch58x.c new file mode 100644 index 000000000..068c1a131 --- /dev/null +++ b/hw/bsp/ch58x/system_ch58x.c @@ -0,0 +1,39 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2024 TinyUSB contributors + * + * 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 "CH58x_common.h" +#include "system_ch58x.h" + +uint32_t SystemCoreClock = FREQ_SYS; + +void SystemInit(void) { + SetSysClock(CLK_SOURCE_PLL_60MHz); + SystemCoreClock = GetSysClock(); +} + +void SystemCoreClockUpdate(void) { + SystemCoreClock = GetSysClock(); +} diff --git a/hw/bsp/ch58x/system_ch58x.h b/hw/bsp/ch58x/system_ch58x.h new file mode 100644 index 000000000..ef32e603f --- /dev/null +++ b/hw/bsp/ch58x/system_ch58x.h @@ -0,0 +1,43 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2024 TinyUSB contributors + * + * 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 __SYSTEM_CH58X_H +#define __SYSTEM_CH58X_H + +#ifdef __cplusplus +extern "C" { +#endif + +extern uint32_t SystemCoreClock; // System Clock Frequency (Core Clock) + +extern void SystemInit(void); +extern void SystemCoreClockUpdate(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __SYSTEM_CH58X_H */ diff --git a/hw/bsp/ch58x/wch-riscv.cfg b/hw/bsp/ch58x/wch-riscv.cfg new file mode 100644 index 000000000..5913a2465 --- /dev/null +++ b/hw/bsp/ch58x/wch-riscv.cfg @@ -0,0 +1,17 @@ +adapter driver wlinke +adapter speed 6000 +transport select sdi + +wlink_set_address 0x00000000 +set _CHIPNAME wch_riscv +sdi newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x00001 + +set _TARGETNAME $_CHIPNAME.cpu + +target create $_TARGETNAME.0 wch_riscv -chain-position $_TARGETNAME +$_TARGETNAME.0 configure -work-area-phys 0x80000000 -work-area-size 10000 -work-area-backup 1 +set _FLASHNAME $_CHIPNAME.flash + +flash bank $_FLASHNAME wch_riscv 0x00000000 0 0 0 $_TARGETNAME.0 + +echo "Ready for Remote Connections" diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index 34dd6af8d..02364d580 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -629,6 +629,20 @@ #define TUP_DCD_EDPT_CLOSE_API #endif +#elif TU_CHECK_MCU(OPT_MCU_CH582) + // CH58x has 2 independent USBFS controllers with merged EP registers, FS only. + #define TUP_USBIP_WCH_CH58X + + #ifndef CFG_TUD_WCH_USBIP_USBFS + #define CFG_TUD_WCH_USBIP_USBFS 1 + #endif + + #ifndef CFG_TUH_WCH_USBIP_USBFS + #define CFG_TUH_WCH_USBIP_USBFS 1 + #endif + + #define TUP_DCD_ENDPOINT_MAX 8 + //--------------------------------------------------------------------+ // Analog Devices //--------------------------------------------------------------------+ diff --git a/src/portable/wch/ch58x_usbfs_reg.h b/src/portable/wch/ch58x_usbfs_reg.h new file mode 100644 index 000000000..11479a4f6 --- /dev/null +++ b/src/portable/wch/ch58x_usbfs_reg.h @@ -0,0 +1,299 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2024 TinyUSB contributors + * + * 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 CH58X_USBFS_REG_H +#define CH58X_USBFS_REG_H + +#include + +//--------------------------------------------------------------------+ +// USB Base Addresses +//--------------------------------------------------------------------+ +#define CH58X_USB_BASE 0x40008000u +#define CH58X_USB2_BASE 0x40008400u + +//--------------------------------------------------------------------+ +// Global Control / Status Registers +//--------------------------------------------------------------------+ +#define CH58X_USB_CTRL(base) (*(volatile uint8_t *)((base) + 0x00)) +#define CH58X_UDEV_CTRL(base) (*(volatile uint8_t *)((base) + 0x01)) +#define CH58X_USB_INT_EN(base) (*(volatile uint8_t *)((base) + 0x02)) +#define CH58X_USB_DEV_AD(base) (*(volatile uint8_t *)((base) + 0x03)) +#define CH58X_USB_MIS_ST(base) (*(volatile uint8_t *)((base) + 0x05)) +#define CH58X_USB_INT_FG(base) (*(volatile uint8_t *)((base) + 0x06)) +#define CH58X_USB_INT_ST(base) (*(volatile uint8_t *)((base) + 0x07)) +#define CH58X_USB_RX_LEN(base) (*(volatile uint8_t *)((base) + 0x08)) + +//--------------------------------------------------------------------+ +// Endpoint Mode Registers +//--------------------------------------------------------------------+ +#define CH58X_UEP4_1_MOD(base) (*(volatile uint8_t *)((base) + 0x0C)) +#define CH58X_UEP2_3_MOD(base) (*(volatile uint8_t *)((base) + 0x0D)) +#define CH58X_UEP567_MOD(base) (*(volatile uint8_t *)((base) + 0x0E)) + +//--------------------------------------------------------------------+ +// Endpoint DMA / T_LEN / CTRL offset lookup tables +// EP0-EP4 are at low offsets, EP5-EP7 jump to higher offsets +// EP4 shares DMA with EP0 (no independent DMA register) +//--------------------------------------------------------------------+ +static const uint8_t ch58x_ep_dma_offset[] = { + 0x10, 0x14, 0x18, 0x1C, /* EP0, EP1, EP2, EP3 */ + 0xFF, /* EP4: shares with EP0, sentinel */ + 0x54, 0x58, 0x5C /* EP5, EP6, EP7 */ +}; + +static const uint8_t ch58x_ep_tlen_offset[] = { + 0x20, 0x24, 0x28, 0x2C, 0x30, /* EP0-EP4 */ + 0x64, 0x68, 0x6C /* EP5-EP7 */ +}; + +static const uint8_t ch58x_ep_ctrl_offset[] = { + 0x22, 0x26, 0x2A, 0x2E, 0x32, /* EP0-EP4 */ + 0x66, 0x6A, 0x6E /* EP5-EP7 */ +}; + +// EP DMA is 16-bit (only low 16 bits of RAM address, high bits implied 0x2000) +#define CH58X_EP_DMA(base, ep) (*(volatile uint16_t *)((base) + ch58x_ep_dma_offset[ep])) +#define CH58X_EP_TLEN(base, ep) (*(volatile uint8_t *)((base) + ch58x_ep_tlen_offset[ep])) +#define CH58X_EP_CTRL(base, ep) (*(volatile uint8_t *)((base) + ch58x_ep_ctrl_offset[ep])) + +//--------------------------------------------------------------------+ +// USB_CTRL (R8_USB_CTRL) bit definitions +//--------------------------------------------------------------------+ +#define CH58X_UC_DMA_EN 0x01 +#define CH58X_UC_CLR_ALL 0x02 +#define CH58X_UC_RESET_SIE 0x04 +#define CH58X_UC_INT_BUSY 0x08 +#define CH58X_UC_SYS_CTRL 0x10 +#define CH58X_UC_DEV_PU_EN 0x20 +#define CH58X_UC_LOW_SPEED 0x40 +#define CH58X_UC_HOST_MODE 0x80 + +//--------------------------------------------------------------------+ +// UDEV_CTRL (R8_UDEV_CTRL) bit definitions +//--------------------------------------------------------------------+ +#define CH58X_UD_PORT_EN 0x01 +#define CH58X_UD_GP_BIT 0x02 +#define CH58X_UD_LOW_SPEED 0x04 +#define CH58X_UD_PD_DIS 0x80 + +//--------------------------------------------------------------------+ +// INT_EN (R8_USB_INT_EN) bit definitions +//--------------------------------------------------------------------+ +#define CH58X_UIE_BUS_RST 0x01 +#define CH58X_UIE_DETECT 0x01 /* host mode alias */ +#define CH58X_UIE_TRANSFER 0x02 +#define CH58X_UIE_SUSPEND 0x04 +#define CH58X_UIE_HST_SOF 0x08 +#define CH58X_UIE_FIFO_OV 0x10 + +//--------------------------------------------------------------------+ +// INT_FG (R8_USB_INT_FG) bit definitions +//--------------------------------------------------------------------+ +#define CH58X_UIF_BUS_RST 0x01 +#define CH58X_UIF_DETECT 0x01 /* host mode alias */ +#define CH58X_UIF_TRANSFER 0x02 +#define CH58X_UIF_SUSPEND 0x04 +#define CH58X_UIF_HST_SOF 0x08 +#define CH58X_UIF_FIFO_OV 0x10 +#define CH58X_U_SIE_FREE 0x20 +#define CH58X_U_TOG_OK 0x40 +#define CH58X_U_IS_NAK 0x80 + +//--------------------------------------------------------------------+ +// INT_ST (R8_USB_INT_ST) parsing +//--------------------------------------------------------------------+ +#define CH58X_INT_ST_ENDP(x) (((x) >> 0) & 0x0F) +#define CH58X_INT_ST_TOKEN(x) (((x) >> 4) & 0x03) +#define CH58X_UIS_SETUP_ACT 0x80 + +// Token PID values +#define CH58X_PID_OUT 0 +#define CH58X_PID_SOF 1 +#define CH58X_PID_IN 2 +#define CH58X_PID_SETUP 3 + +//--------------------------------------------------------------------+ +// MIS_ST (R8_USB_MIS_ST) bit definitions +//--------------------------------------------------------------------+ +#define CH58X_UMS_DEV_ATTACH 0x01 +#define CH58X_UMS_DM_LEVEL 0x02 +#define CH58X_UMS_SUSPEND 0x04 +#define CH58X_UMS_BUS_RESET 0x08 +#define CH58X_UMS_R_FIFO_RDY 0x10 +#define CH58X_UMS_SIE_FREE 0x20 +#define CH58X_UMS_SOF_ACT 0x40 +#define CH58X_UMS_SOF_PRES 0x80 + +//--------------------------------------------------------------------+ +// EP CTRL register bit definitions (merged TX+RX in single 8-bit reg) +// +// Bit 7: RB_UEP_R_TOG RX data toggle +// Bit 6: RB_UEP_T_TOG TX data toggle +// Bit 5: (reserved) +// Bit 4: RB_UEP_AUTO_TOG auto toggle (EP1/2/3 only) +// Bit 3: R_RES1 RX response high +// Bit 2: R_RES0 RX response low +// Bit 1: T_RES1 TX response high +// Bit 0: T_RES0 TX response low +//--------------------------------------------------------------------+ + +// TX response bits[1:0] +#define CH58X_EP_T_RES_MASK 0x03 +#define CH58X_EP_T_RES_ACK 0x00 +#define CH58X_EP_T_RES_TOUT 0x01 /* ISO: no handshake */ +#define CH58X_EP_T_RES_NAK 0x02 +#define CH58X_EP_T_RES_STALL 0x03 + +// RX response bits[3:2] +#define CH58X_EP_R_RES_MASK 0x0C +#define CH58X_EP_R_RES_ACK 0x00 +#define CH58X_EP_R_RES_TOUT 0x04 /* ISO: no handshake */ +#define CH58X_EP_R_RES_NAK 0x08 +#define CH58X_EP_R_RES_STALL 0x0C + +// Toggle and auto-toggle +#define CH58X_EP_AUTO_TOG 0x10 /* bit 4, shared TX/RX */ +#define CH58X_EP_T_TOG 0x40 /* bit 6, TX DATA toggle */ +#define CH58X_EP_R_TOG 0x80 /* bit 7, RX DATA toggle */ + +//--------------------------------------------------------------------+ +// EP Mode register (UEP4_1_MOD) bit definitions +//--------------------------------------------------------------------+ +// R8_UEP4_1_MOD: EP4 in bits[3:2], EP1 in bits[7:4] +#define CH58X_UEP1_BUF_MOD 0x10 +#define CH58X_UEP1_TX_EN 0x40 +#define CH58X_UEP1_RX_EN 0x80 +#define CH58X_UEP4_TX_EN 0x04 +#define CH58X_UEP4_RX_EN 0x08 + +// R8_UEP2_3_MOD: EP3 in bits[7:4], EP2 in bits[3:0] +#define CH58X_UEP2_BUF_MOD 0x01 +#define CH58X_UEP2_TX_EN 0x04 +#define CH58X_UEP2_RX_EN 0x08 +#define CH58X_UEP3_BUF_MOD 0x10 +#define CH58X_UEP3_TX_EN 0x40 +#define CH58X_UEP3_RX_EN 0x80 + +// R8_UEP567_MOD +#define CH58X_UEP5_TX_EN 0x01 +#define CH58X_UEP5_RX_EN 0x02 +#define CH58X_UEP6_TX_EN 0x04 +#define CH58X_UEP6_RX_EN 0x08 +#define CH58X_UEP7_TX_EN 0x10 +#define CH58X_UEP7_RX_EN 0x20 + +//--------------------------------------------------------------------+ +// Host-mode Register Aliases +// In host mode: EP2 -> RX, EP3 -> TX, EP1_CTRL -> SETUP +//--------------------------------------------------------------------+ +#define CH58X_UHOST_CTRL(base) (*(volatile uint8_t *)((base) + 0x01)) // = UDEV_CTRL +#define CH58X_UH_EP_MOD(base) (*(volatile uint8_t *)((base) + 0x0D)) // = UEP2_3_MOD +#define CH58X_UH_RX_DMA(base) (*(volatile uint16_t *)((base) + 0x18)) // = UEP2_DMA +#define CH58X_UH_TX_DMA(base) (*(volatile uint16_t *)((base) + 0x1C)) // = UEP3_DMA +#define CH58X_UH_SETUP(base) (*(volatile uint8_t *)((base) + 0x26)) // = UEP1_CTRL +#define CH58X_UH_EP_PID(base) (*(volatile uint8_t *)((base) + 0x28)) // = UEP2_T_LEN +#define CH58X_UH_RX_CTRL(base) (*(volatile uint8_t *)((base) + 0x2A)) // = UEP2_CTRL +#define CH58X_UH_TX_LEN(base) (*(volatile uint8_t *)((base) + 0x2C)) // = UEP3_T_LEN +#define CH58X_UH_TX_CTRL(base) (*(volatile uint8_t *)((base) + 0x2E)) // = UEP3_CTRL + +//--------------------------------------------------------------------+ +// UHOST_CTRL (R8_UHOST_CTRL) bit definitions +//--------------------------------------------------------------------+ +#define CH58X_UH_PD_DIS 0x80 +#define CH58X_UH_LOW_SPEED 0x04 +#define CH58X_UH_BUS_RESET 0x02 +#define CH58X_UH_PORT_EN 0x01 + +//--------------------------------------------------------------------+ +// UH_EP_MOD (R8_UH_EP_MOD) bit definitions +//--------------------------------------------------------------------+ +#define CH58X_UH_EP_TX_EN 0x40 +#define CH58X_UH_EP_TBUF_MOD 0x10 +#define CH58X_UH_EP_RX_EN 0x08 +#define CH58X_UH_EP_RBUF_MOD 0x01 + +//--------------------------------------------------------------------+ +// UH_SETUP (R8_UH_SETUP) bit definitions +//--------------------------------------------------------------------+ +#define CH58X_UH_PRE_PID_EN 0x80 +#define CH58X_UH_SOF_EN 0x40 + +//--------------------------------------------------------------------+ +// UH_RX_CTRL (R8_UH_RX_CTRL) bit definitions +//--------------------------------------------------------------------+ +#define CH58X_UH_R_TOG 0x80 +#define CH58X_UH_R_AUTO_TOG 0x10 +#define CH58X_UH_R_RES 0x04 + +//--------------------------------------------------------------------+ +// UH_TX_CTRL (R8_UH_TX_CTRL) bit definitions +//--------------------------------------------------------------------+ +#define CH58X_UH_T_TOG 0x40 +#define CH58X_UH_T_AUTO_TOG 0x10 +#define CH58X_UH_T_RES 0x01 + +//--------------------------------------------------------------------+ +// USB_INT_ST host-mode bits +//--------------------------------------------------------------------+ +#define CH58X_UIS_H_RES_MASK 0x0F +#define CH58X_UIS_TOG_OK 0x40 + +//--------------------------------------------------------------------+ +// USB_DEV_AD bits +//--------------------------------------------------------------------+ +#define CH58X_UDA_GP_BIT 0x80 +#define CH58X_USB_ADDR_MASK 0x7F + +//--------------------------------------------------------------------+ +// Standard USB PID values (for host token and response) +//--------------------------------------------------------------------+ +#define CH58X_USB_PID_OUT 0x01 +#define CH58X_USB_PID_IN 0x09 +#define CH58X_USB_PID_SOF 0x05 +#define CH58X_USB_PID_SETUP 0x0D +#define CH58X_USB_PID_DATA0 0x03 +#define CH58X_USB_PID_DATA1 0x0B +#define CH58X_USB_PID_ACK 0x02 +#define CH58X_USB_PID_NAK 0x0A +#define CH58X_USB_PID_STALL 0x0E + +//--------------------------------------------------------------------+ +// PIN_ANALOG_IE register +//--------------------------------------------------------------------+ +#define CH58X_PIN_ANALOG_IE (*(volatile uint16_t *)0x4000101A) +#define CH58X_PIN_USB_DP_PU 0x40 +#define CH58X_PIN_USB_IE 0x80 +#define CH58X_PIN_USB2_DP_PU 0x10 +#define CH58X_PIN_USB2_IE 0x20 + +//--------------------------------------------------------------------+ +// Sleep clock control +//--------------------------------------------------------------------+ +#define CH58X_SLP_CLK_OFF1 (*(volatile uint8_t *)0x4000100D) +#define CH58X_SLP_CLK_USB 0x10 + +#endif /* CH58X_USBFS_REG_H */ diff --git a/src/portable/wch/dcd_ch58x_usbfs.c b/src/portable/wch/dcd_ch58x_usbfs.c new file mode 100644 index 000000000..11ff2c7b1 --- /dev/null +++ b/src/portable/wch/dcd_ch58x_usbfs.c @@ -0,0 +1,583 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2024 TinyUSB contributors + * + * 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_TUD_ENABLED && defined(TUP_USBIP_WCH_CH58X) && CFG_TUD_WCH_USBIP_USBFS + +#include "device/dcd.h" +#include "ch58x_usbfs_reg.h" + +//--------------------------------------------------------------------+ +// Configuration +//--------------------------------------------------------------------+ +#define EP_MAX 8 +#define EP_BUF_SIZE 64 + +//--------------------------------------------------------------------+ +// USB base address selection by rhport +//--------------------------------------------------------------------+ +static inline uint32_t get_usb_base(uint8_t rhport) { + return (rhport == 0) ? CH58X_USB_BASE : CH58X_USB2_BASE; +} + +//--------------------------------------------------------------------+ +// Register access helpers using base address +//--------------------------------------------------------------------+ +#define USB_CTRL(base) CH58X_USB_CTRL(base) +#define USB_UDEV_CTRL(base) CH58X_UDEV_CTRL(base) +#define USB_INT_EN(base) CH58X_USB_INT_EN(base) +#define USB_DEV_AD(base) CH58X_USB_DEV_AD(base) +#define USB_MIS_ST(base) CH58X_USB_MIS_ST(base) +#define USB_INT_FG(base) CH58X_USB_INT_FG(base) +#define USB_INT_ST(base) CH58X_USB_INT_ST(base) +#define USB_RX_LEN(base) CH58X_USB_RX_LEN(base) + +#define EP_DMA(base, ep) CH58X_EP_DMA(base, ep) +#define EP_TLEN(base, ep) CH58X_EP_TLEN(base, ep) +#define EP_CTRL(base, ep) CH58X_EP_CTRL(base, ep) + +//--------------------------------------------------------------------+ +// Inline helpers for merged EP CTRL register +//--------------------------------------------------------------------+ +static inline void ep_set_tx_response(uint32_t base, uint8_t ep, uint8_t resp) { + uint8_t ctrl = EP_CTRL(base, ep); + ctrl = (ctrl & ~CH58X_EP_T_RES_MASK) | resp; + EP_CTRL(base, ep) = ctrl; +} + +static inline void ep_set_rx_response(uint32_t base, uint8_t ep, uint8_t resp) { + uint8_t ctrl = EP_CTRL(base, ep); + ctrl = (ctrl & ~CH58X_EP_R_RES_MASK) | resp; + EP_CTRL(base, ep) = ctrl; +} + +static inline void ep_set_both_response(uint32_t base, uint8_t ep, uint8_t tx_resp, uint8_t rx_resp) { + uint8_t ctrl = EP_CTRL(base, ep); + ctrl = (ctrl & ~(CH58X_EP_T_RES_MASK | CH58X_EP_R_RES_MASK)) | tx_resp | rx_resp; + EP_CTRL(base, ep) = ctrl; +} + +//--------------------------------------------------------------------+ +// Private data structures +//--------------------------------------------------------------------+ +struct usb_xfer { + bool valid; + uint8_t* buffer; + size_t len; + size_t processed_len; + size_t max_size; +}; + +typedef struct { + uint32_t usb_base; + bool ep0_tog; + bool isochronous[EP_MAX]; + struct usb_xfer xfer[EP_MAX][2]; // [ep][dir] + + // EP0 + EP4 shared buffer: EP0 OUT(64) + EP4 OUT(64) + EP4 IN(64) + TU_ATTR_ALIGNED(4) uint8_t ep0_buffer[EP_BUF_SIZE + EP_BUF_SIZE + EP_BUF_SIZE]; + + // EP1-EP3: OUT(64) + IN(64) + TU_ATTR_ALIGNED(4) uint8_t ep1_buffer[2][EP_BUF_SIZE]; + TU_ATTR_ALIGNED(4) uint8_t ep2_buffer[2][EP_BUF_SIZE]; + TU_ATTR_ALIGNED(4) uint8_t ep3_buffer[2][EP_BUF_SIZE]; + + // EP5-EP7: OUT(64) + IN(64) + TU_ATTR_ALIGNED(4) uint8_t ep5_buffer[2][EP_BUF_SIZE]; + TU_ATTR_ALIGNED(4) uint8_t ep6_buffer[2][EP_BUF_SIZE]; + TU_ATTR_ALIGNED(4) uint8_t ep7_buffer[2][EP_BUF_SIZE]; +} dcd_data_t; + +// Per-port data (support up to 2 USB ports) +static dcd_data_t _dcd_data[2]; + +//--------------------------------------------------------------------+ +// Buffer address helpers +// EP0: ep0_buffer[0..63] +// EP4 OUT: ep0_buffer[64..127] EP4 IN: ep0_buffer[128..191] +// Other EPs: epX_buffer[0] = OUT, epX_buffer[1] = IN +//--------------------------------------------------------------------+ +static uint8_t* ep_out_buffer(dcd_data_t* d, uint8_t ep) { + switch (ep) { + case 0: return &d->ep0_buffer[0]; + case 1: return d->ep1_buffer[0]; + case 2: return d->ep2_buffer[0]; + case 3: return d->ep3_buffer[0]; + case 4: return &d->ep0_buffer[EP_BUF_SIZE]; + case 5: return d->ep5_buffer[0]; + case 6: return d->ep6_buffer[0]; + case 7: return d->ep7_buffer[0]; + default: return NULL; + } +} + +static uint8_t* ep_in_buffer(dcd_data_t* d, uint8_t ep) { + switch (ep) { + case 0: return &d->ep0_buffer[0]; // EP0 IN uses same buffer as OUT + case 1: return d->ep1_buffer[1]; + case 2: return d->ep2_buffer[1]; + case 3: return d->ep3_buffer[1]; + case 4: return &d->ep0_buffer[2 * EP_BUF_SIZE]; + case 5: return d->ep5_buffer[1]; + case 6: return d->ep6_buffer[1]; + case 7: return d->ep7_buffer[1]; + default: return NULL; + } +} + +// Get DMA base pointer for endpoint (the buffer whose address is set to DMA register) +// For EP4, DMA is shared with EP0, so we return EP0 buffer +static uint8_t* ep_dma_buffer(dcd_data_t* d, uint8_t ep) { + switch (ep) { + case 0: case 4: return &d->ep0_buffer[0]; + case 1: return d->ep1_buffer[0]; + case 2: return d->ep2_buffer[0]; + case 3: return d->ep3_buffer[0]; + case 5: return d->ep5_buffer[0]; + case 6: return d->ep6_buffer[0]; + case 7: return d->ep7_buffer[0]; + default: return NULL; + } +} + +//--------------------------------------------------------------------+ +// EP has auto-toggle support? +//--------------------------------------------------------------------+ +static inline bool ep_has_auto_toggle(uint8_t ep) { + return (ep >= 1 && ep <= 3); +} + +//--------------------------------------------------------------------+ +// Private transfer helpers +//--------------------------------------------------------------------+ +static void update_in(uint8_t rhport, uint8_t ep, bool force) { + dcd_data_t* d = &_dcd_data[rhport]; + uint32_t base = d->usb_base; + struct usb_xfer* xfer = &d->xfer[ep][TUSB_DIR_IN]; + + if (xfer->valid) { + if (force || xfer->len) { + size_t len = TU_MIN(xfer->max_size, xfer->len); + + // Copy data to IN buffer + uint8_t* buf = ep_in_buffer(d, ep); + if (len > 0 && xfer->buffer != NULL) { + memcpy(buf, xfer->buffer, len); + } + + xfer->buffer += len; + xfer->len -= len; + xfer->processed_len += len; + + EP_TLEN(base, ep) = (uint8_t) len; + + if (ep == 0) { + // EP0: manual toggle + uint8_t ctrl = EP_CTRL(base, 0); + ctrl = (ctrl & ~(CH58X_EP_T_RES_MASK | CH58X_EP_T_TOG)); + ctrl |= CH58X_EP_T_RES_ACK; + if (d->ep0_tog) ctrl |= CH58X_EP_T_TOG; + EP_CTRL(base, 0) = ctrl; + d->ep0_tog = !d->ep0_tog; + } else if (d->isochronous[ep]) { + ep_set_tx_response(base, ep, CH58X_EP_T_RES_TOUT); + } else { + ep_set_tx_response(base, ep, CH58X_EP_T_RES_ACK); + } + } else { + // Transfer complete + xfer->valid = false; + ep_set_tx_response(base, ep, CH58X_EP_T_RES_NAK); + dcd_event_xfer_complete(rhport, ep | TUSB_DIR_IN_MASK, + xfer->processed_len, XFER_RESULT_SUCCESS, true); + } + } +} + +static void update_out(uint8_t rhport, uint8_t ep, size_t rx_len) { + dcd_data_t* d = &_dcd_data[rhport]; + uint32_t base = d->usb_base; + struct usb_xfer* xfer = &d->xfer[ep][TUSB_DIR_OUT]; + + if (xfer->valid) { + size_t len = TU_MIN(xfer->max_size, TU_MIN(xfer->len, rx_len)); + + // Copy from OUT buffer + if (len > 0 && xfer->buffer != NULL) { + uint8_t* buf = ep_out_buffer(d, ep); + memcpy(xfer->buffer, buf, len); + } + + xfer->buffer += len; + xfer->len -= len; + xfer->processed_len += len; + + if (xfer->len == 0 || len < xfer->max_size) { + xfer->valid = false; + dcd_event_xfer_complete(rhport, ep, xfer->processed_len, + XFER_RESULT_SUCCESS, true); + } + + if (ep == 0) { + ep_set_rx_response(base, 0, CH58X_EP_R_RES_ACK); + } + } +} + +//--------------------------------------------------------------------+ +// DCD API Implementation +//--------------------------------------------------------------------+ + +bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { + (void) rh_init; + dcd_data_t* d = &_dcd_data[rhport]; + uint32_t base = get_usb_base(rhport); + d->usb_base = base; + + // Clear state + tu_memclr(d->xfer, sizeof(d->xfer)); + tu_memclr(d->isochronous, sizeof(d->isochronous)); + d->ep0_tog = true; + + // Init control registers + USB_CTRL(base) = CH58X_UC_DEV_PU_EN | CH58X_UC_INT_BUSY | CH58X_UC_DMA_EN; + USB_UDEV_CTRL(base) = CH58X_UD_PD_DIS | CH58X_UD_PORT_EN; + USB_DEV_AD(base) = 0x00; + + // Clear all interrupt flags, then enable interrupts + USB_INT_FG(base) = 0xFF; + USB_INT_EN(base) = CH58X_UIE_BUS_RST | CH58X_UIE_TRANSFER | CH58X_UIE_SUSPEND; + + // EP0 setup (also sets EP4 DMA since they share) + EP_DMA(base, 0) = (uint16_t)(uint32_t) &d->ep0_buffer[0]; + EP_TLEN(base, 0) = 0; + EP_CTRL(base, 0) = CH58X_EP_R_RES_ACK | CH58X_EP_T_RES_NAK; + + // Enable all endpoints TX+RX + CH58X_UEP4_1_MOD(base) = CH58X_UEP1_RX_EN | CH58X_UEP1_TX_EN | + CH58X_UEP4_RX_EN | CH58X_UEP4_TX_EN; + CH58X_UEP2_3_MOD(base) = CH58X_UEP2_RX_EN | CH58X_UEP2_TX_EN | + CH58X_UEP3_RX_EN | CH58X_UEP3_TX_EN; + CH58X_UEP567_MOD(base) = CH58X_UEP5_RX_EN | CH58X_UEP5_TX_EN | + CH58X_UEP6_RX_EN | CH58X_UEP6_TX_EN | + CH58X_UEP7_RX_EN | CH58X_UEP7_TX_EN; + + // EP1-3: DMA + auto-toggle + NAK both directions + for (uint8_t ep = 1; ep <= 3; ep++) { + EP_DMA(base, ep) = (uint16_t)(uint32_t) ep_dma_buffer(d, ep); + EP_TLEN(base, ep) = 0; + EP_CTRL(base, ep) = CH58X_EP_AUTO_TOG | CH58X_EP_R_RES_NAK | CH58X_EP_T_RES_NAK; + } + + // EP4: no independent DMA, no auto-toggle + EP_TLEN(base, 4) = 0; + EP_CTRL(base, 4) = CH58X_EP_R_RES_NAK | CH58X_EP_T_RES_NAK; + + // EP5-7: DMA + no auto-toggle + for (uint8_t ep = 5; ep <= 7; ep++) { + EP_DMA(base, ep) = (uint16_t)(uint32_t) ep_dma_buffer(d, ep); + EP_TLEN(base, ep) = 0; + EP_CTRL(base, ep) = CH58X_EP_R_RES_NAK | CH58X_EP_T_RES_NAK; + } + + // Set EP0 max size + d->xfer[0][TUSB_DIR_OUT].max_size = EP_BUF_SIZE; + d->xfer[0][TUSB_DIR_IN].max_size = EP_BUF_SIZE; + + dcd_connect(rhport); + return true; +} + +void dcd_int_handler(uint8_t rhport) { + dcd_data_t* d = &_dcd_data[rhport]; + uint32_t base = d->usb_base; + uint8_t status = USB_INT_FG(base); + + if (status & CH58X_UIF_TRANSFER) { + uint8_t int_st = USB_INT_ST(base); + uint8_t ep = CH58X_INT_ST_ENDP(int_st); + uint8_t token = CH58X_INT_ST_TOKEN(int_st); + + // Check SETUP first via dedicated flag + if (int_st & CH58X_UIS_SETUP_ACT) { + // SETUP packet received on EP0 + ep_set_both_response(base, 0, CH58X_EP_T_RES_NAK, CH58X_EP_R_RES_ACK); + d->ep0_tog = true; + dcd_event_setup_received(rhport, ep_out_buffer(d, 0), true); + } else { + switch (token) { + case CH58X_PID_OUT: { + uint8_t rx_len = USB_RX_LEN(base); + if (!ep_has_auto_toggle(ep) && ep != 0) { + // Manual toggle for EP4-7 + EP_CTRL(base, ep) ^= CH58X_EP_R_TOG; + } + update_out(rhport, ep, rx_len); + break; + } + + case CH58X_PID_IN: { + if (!ep_has_auto_toggle(ep) && ep != 0) { + // Manual toggle for EP4-7 + EP_CTRL(base, ep) ^= CH58X_EP_T_TOG; + } + update_in(rhport, ep, false); + break; + } + + default: + break; + } + } + + USB_INT_FG(base) = CH58X_UIF_TRANSFER; + } else if (status & CH58X_UIF_BUS_RST) { + // Bus reset + d->ep0_tog = true; + d->xfer[0][TUSB_DIR_OUT].max_size = EP_BUF_SIZE; + d->xfer[0][TUSB_DIR_IN].max_size = EP_BUF_SIZE; + + USB_DEV_AD(base) = 0x00; + ep_set_rx_response(base, 0, CH58X_EP_R_RES_ACK); + + tusb_speed_t speed = (USB_MIS_ST(base) & CH58X_UMS_DM_LEVEL) ? + TUSB_SPEED_LOW : TUSB_SPEED_FULL; + dcd_event_bus_reset(rhport, speed, true); + + USB_INT_FG(base) = CH58X_UIF_BUS_RST; + } else if (status & CH58X_UIF_SUSPEND) { + if (USB_MIS_ST(base) & CH58X_UMS_SUSPEND) { + dcd_event_t event = {.rhport = rhport, .event_id = DCD_EVENT_SUSPEND}; + dcd_event_handler(&event, true); + } else { + dcd_event_t event = {.rhport = rhport, .event_id = DCD_EVENT_RESUME}; + dcd_event_handler(&event, true); + } + USB_INT_FG(base) = CH58X_UIF_SUSPEND; + } +} + +void dcd_int_enable(uint8_t rhport) { + (void) rhport; + // PFIC enable: USB_IRQn=22, USB2_IRQn=23 + volatile uint32_t* pfic_ienr = (volatile uint32_t*) 0xE000E100; + uint8_t irqn = (rhport == 0) ? 22 : 23; + pfic_ienr[irqn / 32] = (1u << (irqn % 32)); +} + +void dcd_int_disable(uint8_t rhport) { + (void) rhport; + volatile uint32_t* pfic_irer = (volatile uint32_t*) 0xE000E180; + uint8_t irqn = (rhport == 0) ? 22 : 23; + pfic_irer[irqn / 32] = (1u << (irqn % 32)); + __asm volatile ("fence.i"); +} + +void dcd_set_address(uint8_t rhport, uint8_t dev_addr) { + (void) dev_addr; + // Address is set in status stage complete callback + dcd_edpt_xfer(rhport, 0x80, NULL, 0, false); +} + +void dcd_remote_wakeup(uint8_t rhport) { + uint32_t base = get_usb_base(rhport); + USB_UDEV_CTRL(base) |= CH58X_UD_GP_BIT; + for (volatile int i = 0; i < 60000; i++) { } // ~1ms resume signal + USB_UDEV_CTRL(base) &= ~CH58X_UD_GP_BIT; +} + +void dcd_connect(uint8_t rhport) { + uint32_t base = get_usb_base(rhport); + USB_CTRL(base) |= CH58X_UC_DEV_PU_EN; +} + +void dcd_disconnect(uint8_t rhport) { + uint32_t base = get_usb_base(rhport); + USB_CTRL(base) &= ~CH58X_UC_DEV_PU_EN; +} + +void dcd_sof_enable(uint8_t rhport, bool en) { + uint32_t base = get_usb_base(rhport); + if (en) { + USB_INT_EN(base) |= CH58X_UIE_HST_SOF; + } else { + USB_INT_EN(base) &= ~CH58X_UIE_HST_SOF; + } +} + +void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const* request) { + dcd_data_t* d = &_dcd_data[rhport]; + uint32_t base = d->usb_base; + + if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE && + request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && + request->bRequest == TUSB_REQ_SET_ADDRESS) { + USB_DEV_AD(base) = (uint8_t) request->wValue; + } + ep_set_both_response(base, 0, CH58X_EP_T_RES_NAK, CH58X_EP_R_RES_ACK); +} + +bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const* desc_ep) { + dcd_data_t* d = &_dcd_data[rhport]; + uint32_t base = d->usb_base; + uint8_t ep = tu_edpt_number(desc_ep->bEndpointAddress); + uint8_t dir = tu_edpt_dir(desc_ep->bEndpointAddress); + TU_ASSERT(ep < EP_MAX); + + d->isochronous[ep] = (desc_ep->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS); + d->xfer[ep][dir].max_size = tu_edpt_packet_size(desc_ep); + + if (ep != 0) { + dcd_int_disable(rhport); + uint8_t ctrl = EP_CTRL(base, ep); + if (dir == TUSB_DIR_OUT) { + if (d->isochronous[ep]) { + ctrl = (ctrl & ~CH58X_EP_R_RES_MASK) | CH58X_EP_R_RES_TOUT; + } else { + // Start with NAK; dcd_edpt_xfer will set ACK when a transfer is submitted + ctrl = (ctrl & ~CH58X_EP_R_RES_MASK) | CH58X_EP_R_RES_NAK; + } + // Enable auto toggle for EP1-3 + if (ep_has_auto_toggle(ep)) { + ctrl |= CH58X_EP_AUTO_TOG; + } + } else { + EP_TLEN(base, ep) = 0; + ctrl = (ctrl & ~CH58X_EP_T_RES_MASK) | CH58X_EP_T_RES_NAK; + if (ep_has_auto_toggle(ep)) { + ctrl |= CH58X_EP_AUTO_TOG; + } + } + EP_CTRL(base, ep) = ctrl; + dcd_int_enable(rhport); + } + return true; +} + +void dcd_edpt_close_all(uint8_t rhport) { + dcd_data_t* d = &_dcd_data[rhport]; + uint32_t base = d->usb_base; + + for (uint8_t ep = 1; ep < EP_MAX; ep++) { + d->xfer[ep][TUSB_DIR_IN].valid = false; + d->xfer[ep][TUSB_DIR_OUT].valid = false; + d->isochronous[ep] = false; + EP_CTRL(base, ep) = CH58X_EP_R_RES_NAK | CH58X_EP_T_RES_NAK; + } +} + +bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { + (void) rhport; + (void) ep_addr; + (void) largest_packet_size; + return false; +} + +bool dcd_edpt_iso_activate(uint8_t rhport, const tusb_desc_endpoint_t* desc_ep) { + (void) rhport; + (void) desc_ep; + return false; +} + +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, + uint16_t total_bytes, bool is_isr) { + (void) is_isr; + uint8_t ep = tu_edpt_number(ep_addr); + uint8_t dir = tu_edpt_dir(ep_addr); + + dcd_data_t* d = &_dcd_data[rhport]; + struct usb_xfer* xfer = &d->xfer[ep][dir]; + + dcd_int_disable(rhport); + xfer->valid = true; + xfer->buffer = buffer; + xfer->len = total_bytes; + xfer->processed_len = 0; + dcd_int_enable(rhport); + + if (dir == TUSB_DIR_IN) { + update_in(rhport, ep, true); + } else { + // For OUT direction, set endpoint to ACK to start receiving data + if (ep != 0) { + if (d->isochronous[ep]) { + ep_set_rx_response(d->usb_base, ep, CH58X_EP_R_RES_TOUT); + } else { + ep_set_rx_response(d->usb_base, ep, CH58X_EP_R_RES_ACK); + } + } + } + return true; +} + +void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { + dcd_data_t* d = &_dcd_data[rhport]; + uint32_t base = d->usb_base; + uint8_t ep = tu_edpt_number(ep_addr); + uint8_t dir = tu_edpt_dir(ep_addr); + + dcd_int_disable(rhport); + if (ep == 0) { + // EP0: stall both directions + EP_CTRL(base, 0) = CH58X_EP_R_RES_STALL | CH58X_EP_T_RES_STALL | + CH58X_EP_R_TOG | CH58X_EP_T_TOG; + } else { + if (dir == TUSB_DIR_OUT) { + ep_set_rx_response(base, ep, CH58X_EP_R_RES_STALL); + } else { + ep_set_tx_response(base, ep, CH58X_EP_T_RES_STALL); + } + } + dcd_int_enable(rhport); +} + +void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { + dcd_data_t* d = &_dcd_data[rhport]; + uint32_t base = d->usb_base; + uint8_t ep = tu_edpt_number(ep_addr); + uint8_t dir = tu_edpt_dir(ep_addr); + + dcd_int_disable(rhport); + if (ep == 0) { + if (dir == TUSB_DIR_OUT) { + ep_set_rx_response(base, 0, CH58X_EP_R_RES_ACK); + } + } else { + uint8_t ctrl = EP_CTRL(base, ep); + if (dir == TUSB_DIR_OUT) { + ctrl &= ~(CH58X_EP_R_RES_MASK | CH58X_EP_R_TOG); + ctrl |= CH58X_EP_R_RES_ACK; + } else { + ctrl &= ~(CH58X_EP_T_RES_MASK | CH58X_EP_T_TOG); + ctrl |= CH58X_EP_T_RES_NAK; + } + EP_CTRL(base, ep) = ctrl; + } + dcd_int_enable(rhport); +} + +#endif /* CFG_TUD_ENABLED && TUP_USBIP_WCH_CH58X */ diff --git a/src/portable/wch/hcd_ch58x_usbfs.c b/src/portable/wch/hcd_ch58x_usbfs.c new file mode 100644 index 000000000..629c2a789 --- /dev/null +++ b/src/portable/wch/hcd_ch58x_usbfs.c @@ -0,0 +1,712 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2024 TinyUSB contributors + * + * 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_CH58X) && \ + 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" + +#include "ch58x_usbfs_reg.h" + +//--------------------------------------------------------------------+ +// Configuration +//--------------------------------------------------------------------+ +#define USBFS_MAX_PACKET_SIZE 64 + +#define LOG_CH58X_HCD(...) TU_LOG3(__VA_ARGS__) + +//--------------------------------------------------------------------+ +// RX/TX buffers (must be 4-byte aligned and in lower 64KB of RAM) +// Separate buffers for each USB port to avoid DMA conflicts +//--------------------------------------------------------------------+ +TU_ATTR_ALIGNED(4) static uint8_t _rx_buf[2][USBFS_MAX_PACKET_SIZE]; +TU_ATTR_ALIGNED(4) static uint8_t _tx_buf[2][USBFS_MAX_PACKET_SIZE]; + +//--------------------------------------------------------------------+ +// USB base address selection by rhport +//--------------------------------------------------------------------+ +static inline uint32_t _get_usb_base(uint8_t rhport) { + return (rhport == 0) ? CH58X_USB_BASE : CH58X_USB2_BASE; +} + +//--------------------------------------------------------------------+ +// Endpoint record +//--------------------------------------------------------------------+ +typedef struct { + bool configured; + uint8_t dev_addr; + uint8_t ep_addr; + uint8_t max_packet_size; + uint8_t xfer_type; + uint8_t data_toggle; // 0=DATA0, 1=DATA1 + bool is_nak_pending; + uint16_t buflen; + uint8_t* buf; +} hcd_edpt_t; + +static hcd_edpt_t _edpt_list[CFG_TUH_DEVICE_MAX * 6] = {}; + +//--------------------------------------------------------------------+ +// Current transfer state (only one transfer at a time per root port) +//--------------------------------------------------------------------+ +typedef struct { + volatile bool is_busy; + uint8_t rhport; + uint8_t dev_addr; + uint8_t ep_addr; + uint32_t start_ms; + uint8_t* buffer; + uint16_t bufferlen; + uint16_t xferred_len; + bool nak_pending; +} hcd_xfer_t; + +static volatile hcd_xfer_t _current_xfer = {}; + +//--------------------------------------------------------------------+ +// Per-port state +//--------------------------------------------------------------------+ +typedef struct { + uint32_t usb_base; + bool int_enabled; +} hcd_port_t; + +static hcd_port_t _port_data[2] = {}; + +//--------------------------------------------------------------------+ +// Endpoint record management +//--------------------------------------------------------------------+ +static hcd_edpt_t* _get_edpt(uint8_t dev_addr, uint8_t ep_addr) { + for (size_t i = 0; i < TU_ARRAY_SIZE(_edpt_list); i++) { + hcd_edpt_t* e = &_edpt_list[i]; + if (e->configured && e->dev_addr == dev_addr && e->ep_addr == ep_addr) { + return e; + } + } + return NULL; +} + +static hcd_edpt_t* _alloc_edpt(void) { + for (size_t i = 0; i < TU_ARRAY_SIZE(_edpt_list); i++) { + if (!_edpt_list[i].configured) { + return &_edpt_list[i]; + } + } + return NULL; +} + +static hcd_edpt_t* _add_edpt(uint8_t dev_addr, uint8_t ep_addr, + uint16_t max_packet_size, uint8_t xfer_type) { + hcd_edpt_t* e = _alloc_edpt(); + TU_ASSERT(e != NULL, NULL); + + e->dev_addr = dev_addr; + e->ep_addr = ep_addr; + e->max_packet_size = (uint8_t) TU_MIN(max_packet_size, USBFS_MAX_PACKET_SIZE); + e->xfer_type = xfer_type; + e->data_toggle = 0; + e->is_nak_pending = false; + e->buflen = 0; + e->buf = NULL; + e->configured = true; + + return e; +} + +static hcd_edpt_t* _get_or_add_edpt(uint8_t dev_addr, uint8_t ep_addr, + uint16_t max_packet_size, uint8_t xfer_type) { + hcd_edpt_t* e = _get_edpt(dev_addr, ep_addr); + if (e != NULL) return e; + return _add_edpt(dev_addr, ep_addr, max_packet_size, xfer_type); +} + +static void _remove_edpts_for_device(uint8_t dev_addr) { + for (size_t i = 0; i < TU_ARRAY_SIZE(_edpt_list); i++) { + if (_edpt_list[i].configured && _edpt_list[i].dev_addr == dev_addr) { + _edpt_list[i].configured = false; + } + } +} + +//--------------------------------------------------------------------+ +// Low-level hardware helpers +//--------------------------------------------------------------------+ + +// Busywait delay (approximate microseconds at ~60MHz) +TU_ATTR_ALWAYS_INLINE static inline void _delay_loops(uint32_t count) { + volatile uint32_t c = count / 3; + if (c == 0) return; + while (c-- != 0) {} +} + +static void _hw_init_host(uint8_t rhport, bool enabled) { + uint32_t base = _port_data[rhport].usb_base; + + if (!enabled) { + // Reset SIE when disabling + CH58X_USB_CTRL(base) = CH58X_UC_RESET_SIE | CH58X_UC_CLR_ALL; + _delay_loops(600); // ~10us at 60MHz + CH58X_USB_CTRL(base) = 0; + return; + } + + // host mode, pull-down enabled, clear addr + CH58X_USB_CTRL(base) = CH58X_UC_HOST_MODE; + while (!(CH58X_USB_CTRL(base) & CH58X_UC_HOST_MODE)) {} + CH58X_UHOST_CTRL(base) = 0; + CH58X_USB_DEV_AD(base) = 0x00; + + // EP2 RX (IN), EP3 TX (OUT/SETUP) + CH58X_UH_EP_MOD(base) = CH58X_UH_EP_TX_EN | CH58X_UH_EP_RX_EN; + + // DMA: 16-bit address, lower 64KB only + CH58X_UH_RX_DMA(base) = (uint16_t)(uint32_t)_rx_buf[rhport]; + CH58X_UH_TX_DMA(base) = (uint16_t)(uint32_t)_tx_buf[rhport]; + + CH58X_UH_RX_CTRL(base) = 0x00; + CH58X_UH_TX_CTRL(base) = 0x00; + + CH58X_USB_CTRL(base) = CH58X_UC_HOST_MODE | CH58X_UC_INT_BUSY | CH58X_UC_DMA_EN; + CH58X_UH_SETUP(base) = CH58X_UH_SOF_EN; + + CH58X_USB_INT_FG(base) = 0xFF; // clear all flags + CH58X_USB_INT_EN(base) = CH58X_UIE_TRANSFER | CH58X_UIE_DETECT; +} + +static bool _hw_start_xfer(uint8_t rhport, uint8_t pid, uint8_t ep_addr, uint8_t data_toggle) { + uint32_t base = _port_data[rhport].usb_base; + + LOG_CH58X_HCD("_hw_start_xfer(pid=0x%02x, ep=0x%02x, tog=%d)\r\n", pid, ep_addr, data_toggle); + + // Workaround: small delay for low-speed devices + bool is_lowspeed = tuh_speed_get(_current_xfer.dev_addr) == TUSB_SPEED_LOW; + if (is_lowspeed) { + _delay_loops(60000000 / 1000000 * 40); // ~40us at 60MHz + } + + // Set toggle controls (same as SDK: R8_UH_RX_CTRL = R8_UH_TX_CTRL = tog) + uint8_t tog_ctrl = (data_toggle != 0) ? CH58X_UH_T_TOG : 0; + CH58X_UH_TX_CTRL(base) = tog_ctrl; + CH58X_UH_RX_CTRL(base) = (data_toggle != 0) ? CH58X_UH_R_TOG : 0; + + uint8_t pid_endp = (pid << 4) | (tu_edpt_number(ep_addr) & 0x0F); + + // clear flag, enable int, then set PID to start transfer + CH58X_USB_INT_FG(base) = CH58X_UIF_TRANSFER; + CH58X_USB_INT_EN(base) |= CH58X_UIE_TRANSFER; + CH58X_UH_EP_PID(base) = pid_endp; + + return true; +} + +static void _hw_set_device_addr(uint8_t rhport, uint8_t dev_addr) { + uint32_t base = _port_data[rhport].usb_base; + CH58X_USB_DEV_AD(base) = (CH58X_USB_DEV_AD(base) & CH58X_UDA_GP_BIT) | + (dev_addr & CH58X_USB_ADDR_MASK); +} + +static void _hw_set_speed(uint8_t rhport, tusb_speed_t speed) { + uint32_t base = _port_data[rhport].usb_base; + + LOG_CH58X_HCD("_hw_set_speed(%s)\r\n", + speed == TUSB_SPEED_FULL ? "Full" : "Low"); + + if (speed == TUSB_SPEED_LOW) { + CH58X_USB_CTRL(base) |= CH58X_UC_LOW_SPEED; + CH58X_UHOST_CTRL(base) |= CH58X_UH_LOW_SPEED; + } else { + CH58X_USB_CTRL(base) &= ~CH58X_UC_LOW_SPEED; + CH58X_UHOST_CTRL(base) &= ~CH58X_UH_LOW_SPEED; + CH58X_UH_SETUP(base) &= ~CH58X_UH_PRE_PID_EN; + } +} + +static void _hw_set_addr_speed(uint8_t rhport, uint8_t dev_addr) { + _hw_set_device_addr(rhport, dev_addr); + + tusb_speed_t rhport_speed = hcd_port_speed_get(rhport); + tusb_speed_t dev_speed = tuh_speed_get(dev_addr); + _hw_set_speed(rhport, dev_speed); + + // FS root + LS device: hub uses PRE PID, clear LS on host ctrl + if (rhport_speed == TUSB_SPEED_FULL && dev_speed == TUSB_SPEED_LOW) { + uint32_t base = _port_data[rhport].usb_base; + CH58X_UHOST_CTRL(base) &= ~CH58X_UH_LOW_SPEED; + } +} + +static bool _hw_device_attached(uint8_t rhport) { + uint32_t base = _port_data[rhport].usb_base; + return (CH58X_USB_MIS_ST(base) & CH58X_UMS_DEV_ATTACH) != 0; +} + +//--------------------------------------------------------------------+ +// NAK retry callback +//--------------------------------------------------------------------+ +static void _xfer_retry(void* param) { + LOG_CH58X_HCD("_xfer_retry()\r\n"); + hcd_edpt_t* edpt = (hcd_edpt_t*)param; + + if (_current_xfer.nak_pending) { + uint8_t rhport = _current_xfer.rhport; + _current_xfer.nak_pending = false; + edpt->is_nak_pending = false; + + uint8_t dev_addr = edpt->dev_addr; + uint8_t ep_addr = edpt->ep_addr; + uint16_t buflen = edpt->buflen; + uint8_t* buf = edpt->buf; + + // Check if endpoint is still valid + hcd_edpt_t* current = _get_edpt(dev_addr, ep_addr); + if (current) { + hcd_edpt_xfer(rhport, dev_addr, ep_addr, buf, buflen); + } + } +} + +//--------------------------------------------------------------------+ +// HCD API: Controller +//--------------------------------------------------------------------+ +bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { + (void)rh_init; + + _port_data[rhport].usb_base = _get_usb_base(rhport); + _port_data[rhport].int_enabled = false; + + // Clear endpoint records + tu_memclr(_edpt_list, sizeof(_edpt_list)); + tu_memclr((void*)&_current_xfer, sizeof(_current_xfer)); + + _hw_init_host(rhport, true); + + return true; +} + +bool hcd_deinit(uint8_t rhport) { + _hw_init_host(rhport, false); + return true; +} + +uint32_t hcd_frame_number(uint8_t rhport) { + (void)rhport; + return tusb_time_millis_api(); +} + +void hcd_int_enable(uint8_t rhport) { + // PFIC interrupt enable + volatile uint32_t* pfic_ienr = (volatile uint32_t*)0xE000E100; + uint8_t irqn = (rhport == 0) ? 22 : 23; // USB_IRQn or USB2_IRQn + pfic_ienr[irqn / 32] = (1u << (irqn % 32)); + _port_data[rhport].int_enabled = true; +} + +void hcd_int_disable(uint8_t rhport) { + volatile uint32_t* pfic_irer = (volatile uint32_t*)0xE000E180; + uint8_t irqn = (rhport == 0) ? 22 : 23; + pfic_irer[irqn / 32] = (1u << (irqn % 32)); + __asm volatile("fence.i"); + _port_data[rhport].int_enabled = false; +} + +//--------------------------------------------------------------------+ +// HCD API: Port +//--------------------------------------------------------------------+ +bool hcd_port_connect_status(uint8_t rhport) { + return _hw_device_attached(rhport); +} + +tusb_speed_t hcd_port_speed_get(uint8_t rhport) { + uint32_t base = _port_data[rhport].usb_base; + // DM level high = low-speed device, low = full-speed + if (CH58X_USB_MIS_ST(base) & CH58X_UMS_DM_LEVEL) { + return TUSB_SPEED_LOW; + } + return TUSB_SPEED_FULL; +} + +static bool _int_state_before_reset = false; + +void hcd_port_reset(uint8_t rhport) { + uint32_t base = _port_data[rhport].usb_base; + + LOG_CH58X_HCD("hcd_port_reset()\r\n"); + + _int_state_before_reset = _port_data[rhport].int_enabled; + hcd_int_disable(rhport); + + _hw_set_device_addr(rhport, 0x00); + + // Disable port and default to full-speed before reset (matches SDK ResetRootHubPort) + CH58X_UHOST_CTRL(base) &= ~CH58X_UH_PORT_EN; + _hw_set_speed(rhport, TUSB_SPEED_FULL); + + // Start bus reset (clear low-speed bit simultaneously) + CH58X_UHOST_CTRL(base) = (CH58X_UHOST_CTRL(base) & ~CH58X_UH_LOW_SPEED) | CH58X_UH_BUS_RESET; +} + +void hcd_port_reset_end(uint8_t rhport) { + uint32_t base = _port_data[rhport].usb_base; + + LOG_CH58X_HCD("hcd_port_reset_end()\r\n"); + + // End bus reset + CH58X_UHOST_CTRL(base) &= ~CH58X_UH_BUS_RESET; + tusb_time_delay_ms_api(2); + + // Detect speed and configure + if ((CH58X_UHOST_CTRL(base) & CH58X_UH_PORT_EN) == 0) { + if (hcd_port_speed_get(rhport) == TUSB_SPEED_LOW) { + _hw_set_speed(rhport, TUSB_SPEED_LOW); + } + } + + // Enable port and SOF + CH58X_UHOST_CTRL(base) |= CH58X_UH_PORT_EN; + CH58X_UH_SETUP(base) |= CH58X_UH_SOF_EN; + + // Suppress stale detect event + CH58X_USB_INT_FG(base) = CH58X_UIF_DETECT; + + if (_int_state_before_reset) { + hcd_int_enable(rhport); + } +} + +void hcd_device_close(uint8_t rhport, uint8_t dev_addr) { + (void)rhport; + LOG_CH58X_HCD("hcd_device_close(dev=0x%02x)\r\n", dev_addr); + _remove_edpts_for_device(dev_addr); +} + +//--------------------------------------------------------------------+ +// HCD API: Endpoint +//--------------------------------------------------------------------+ +bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const* ep_desc) { + 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; + uint32_t base = _port_data[rhport].usb_base; + + LOG_CH58X_HCD("hcd_edpt_open(dev=0x%02x, ep=0x%02x, mps=%d, type=%d)\r\n", + dev_addr, ep_addr, max_packet_size, xfer_type); + + // Wait for any pending transfer + while (_current_xfer.is_busy) {} + + if (ep_num == 0) { + TU_ASSERT(_get_or_add_edpt(dev_addr, 0x00, max_packet_size, xfer_type) != NULL, false); + TU_ASSERT(_get_or_add_edpt(dev_addr, 0x80, max_packet_size, xfer_type) != NULL, false); + } else { + TU_ASSERT(_get_or_add_edpt(dev_addr, ep_addr, max_packet_size, xfer_type) != NULL, false); + } + + // Ensure port is enabled with SOF + CH58X_UHOST_CTRL(base) |= CH58X_UH_PORT_EN; + CH58X_UH_SETUP(base) |= CH58X_UH_SOF_EN; + + _hw_set_addr_speed(rhport, dev_addr); + + return true; +} + +bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, + uint8_t* buffer, uint16_t buflen) { + uint32_t base = _port_data[rhport].usb_base; + + LOG_CH58X_HCD("hcd_edpt_xfer(dev=0x%02x, ep=0x%02x, len=%d)\r\n", + dev_addr, ep_addr, buflen); + + // Wait for any pending transfer + while (_current_xfer.is_busy) {} + _current_xfer.is_busy = true; + + hcd_edpt_t* edpt = _get_edpt(dev_addr, ep_addr); + TU_ASSERT(edpt != NULL); + + _hw_set_addr_speed(rhport, dev_addr); + + _current_xfer.rhport = rhport; + _current_xfer.dev_addr = dev_addr; + _current_xfer.ep_addr = ep_addr; + _current_xfer.buffer = buffer; + _current_xfer.bufferlen = buflen; + _current_xfer.start_ms = tusb_time_millis_api(); + _current_xfer.xferred_len = 0; + _current_xfer.nak_pending = false; + + if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN) { + // IN transfer: host receives data + return _hw_start_xfer(rhport, CH58X_USB_PID_IN, ep_addr, edpt->data_toggle); + } else { + // OUT transfer: host sends data + uint16_t copylen = TU_MIN(edpt->max_packet_size, buflen); + CH58X_UH_TX_LEN(base) = (uint8_t)copylen; + memcpy(_tx_buf[rhport], buffer, copylen); + return _hw_start_xfer(rhport, CH58X_USB_PID_OUT, ep_addr, edpt->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; + return false; +} + +bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]) { + uint32_t base = _port_data[rhport].usb_base; + + LOG_CH58X_HCD("hcd_setup_send(dev=0x%02x)\r\n", dev_addr); + + // Wait for any pending transfer + while (_current_xfer.is_busy) {} + _current_xfer.is_busy = true; + + _hw_set_addr_speed(rhport, dev_addr); + + hcd_edpt_t* edpt_tx = _get_edpt(dev_addr, 0x00); + hcd_edpt_t* edpt_rx = _get_edpt(dev_addr, 0x80); + TU_ASSERT(edpt_tx != NULL, false); + TU_ASSERT(edpt_rx != NULL, false); + + // SETUP always starts with DATA0; after SETUP, IN data starts with DATA1 + edpt_tx->data_toggle = 0; + edpt_rx->data_toggle = 1; + + memcpy(_tx_buf[rhport], setup_packet, 8); + CH58X_UH_TX_LEN(base) = 8; + + _current_xfer.rhport = rhport; + _current_xfer.dev_addr = dev_addr; + _current_xfer.ep_addr = 0x00; // SETUP always targets EP0 OUT + _current_xfer.start_ms = tusb_time_millis_api(); + _current_xfer.buffer = _tx_buf[rhport]; + _current_xfer.bufferlen = 8; + _current_xfer.xferred_len = 0; + _current_xfer.nak_pending = false; + + _hw_start_xfer(rhport, CH58X_USB_PID_SETUP, 0, 0); + + return true; +} + +bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { + uint32_t base = _port_data[rhport].usb_base; + uint8_t ep_num = tu_edpt_number(ep_addr); + + LOG_CH58X_HCD("hcd_edpt_clear_stall(dev=0x%02x, ep=0x%02x)\r\n", dev_addr, ep_addr); + + // Send CLEAR_FEATURE(ENDPOINT_HALT) via blocking transfer + uint8_t setup[8] = { + 0x02, 0x01, 0x00, 0x00, ep_addr, 0x00, 0x00, 0x00 + }; + memcpy(_tx_buf[rhport], setup, 8); + CH58X_UH_TX_LEN(base) = 8; + + bool prev_int = _port_data[rhport].int_enabled; + hcd_int_disable(rhport); + + CH58X_UH_EP_PID(base) = (CH58X_USB_PID_SETUP << 4) | 0x00; + CH58X_USB_INT_FG(base) = CH58X_UIF_TRANSFER; + while ((CH58X_USB_INT_FG(base) & CH58X_UIF_TRANSFER) == 0) {} + CH58X_UH_EP_PID(base) = 0; + + uint8_t response = CH58X_USB_INT_ST(base) & CH58X_UIS_H_RES_MASK; + (void)response; + + LOG_CH58X_HCD("clear_stall response=0x%02x\r\n", response); + + if (prev_int) { + hcd_int_enable(rhport); + } + + return true; +} + +//--------------------------------------------------------------------+ +// Interrupt Handler +//--------------------------------------------------------------------+ +void hcd_int_handler(uint8_t rhport, bool in_isr) { + uint32_t base = _port_data[rhport].usb_base; + + //-- Device attach/detach detection -- + if (CH58X_USB_INT_FG(base) & CH58X_UIF_DETECT) { + CH58X_USB_INT_FG(base) = CH58X_UIF_DETECT; + + bool attached = _hw_device_attached(rhport); + LOG_CH58X_HCD("hcd_int: detect, attached=%d\r\n", attached); + + if (attached) { + hcd_event_device_attach(rhport, in_isr); + } else { + hcd_event_device_remove(rhport, in_isr); + } + return; + } + + //-- Transfer complete -- + if (CH58X_USB_INT_FG(base) & CH58X_UIF_TRANSFER) { + // Read PID/endpoint before stopping (must read first!) + uint8_t pid_endp = CH58X_UH_EP_PID(base); + uint8_t int_st = CH58X_USB_INT_ST(base); + uint8_t int_fg = CH58X_USB_INT_FG(base); + uint8_t dev_addr = CH58X_USB_DEV_AD(base) & CH58X_USB_ADDR_MASK; + + // Stop USB transaction immediately (SDK: R8_UH_EP_PID = 0x00) + CH58X_UH_EP_PID(base) = 0x00; + + // Disable transfer interrupt (re-enabled when next transfer starts) + CH58X_USB_INT_EN(base) &= ~CH58X_UIE_TRANSFER; + + uint8_t request_pid = pid_endp >> 4; + uint8_t response_pid = int_st & CH58X_UIS_H_RES_MASK; + uint8_t ep_addr = pid_endp & 0x0F; + if (request_pid == CH58X_USB_PID_IN) { + ep_addr |= 0x80; + } + + LOG_CH58X_HCD("hcd_int: xfer pid=0x%02x ep=0x%02x resp=0x%02x\r\n", + request_pid, ep_addr, response_pid); + + hcd_edpt_t* edpt = _get_edpt(dev_addr, ep_addr); + if (edpt == NULL) { + // Unknown endpoint, discard + LOG_CH58X_HCD("hcd_int: unknown edpt dev=0x%02x ep=0x%02x\r\n", dev_addr, ep_addr); + _current_xfer.is_busy = false; + CH58X_USB_INT_FG(base) = CH58X_UIF_TRANSFER; + return; + } + + // Check toggle match - SDK uses R8_USB_INT_ST & RB_UIS_TOG_OK + if (int_st & CH58X_UIS_TOG_OK) { + edpt->data_toggle ^= 0x01; + + switch (request_pid) { + case CH58X_USB_PID_SETUP: + case CH58X_USB_PID_OUT: { + uint8_t tx_len = CH58X_UH_TX_LEN(base); + _current_xfer.bufferlen -= tx_len; + _current_xfer.xferred_len += tx_len; + + if (_current_xfer.bufferlen == 0) { + LOG_CH58X_HCD("OUT/SETUP complete, %d bytes\r\n", _current_xfer.xferred_len); + _current_xfer.is_busy = false; + hcd_event_xfer_complete(dev_addr, ep_addr, + _current_xfer.xferred_len, XFER_RESULT_SUCCESS, in_isr); + } else { + // Multi-packet OUT: send next chunk + _current_xfer.buffer += tx_len; + uint16_t copylen = TU_MIN(edpt->max_packet_size, _current_xfer.bufferlen); + memcpy(_tx_buf[rhport], _current_xfer.buffer, copylen); + CH58X_UH_TX_LEN(base) = (uint8_t)copylen; + _hw_start_xfer(rhport, CH58X_USB_PID_OUT, ep_addr, edpt->data_toggle); + } + break; + } + + case CH58X_USB_PID_IN: { + uint8_t rx_len = CH58X_USB_RX_LEN(base); + _current_xfer.xferred_len += rx_len; + uint16_t xferred = _current_xfer.xferred_len; + + if (rx_len > 0 && _current_xfer.buffer != NULL) { + memcpy(_current_xfer.buffer, _rx_buf[rhport], rx_len); + _current_xfer.buffer += rx_len; + } + + if ((rx_len < edpt->max_packet_size) || (xferred == _current_xfer.bufferlen)) { + // Short packet or transfer complete + LOG_CH58X_HCD("IN complete, %d bytes\r\n", xferred); + _current_xfer.is_busy = false; + hcd_event_xfer_complete(dev_addr, ep_addr, xferred, + XFER_RESULT_SUCCESS, in_isr); + } else { + // More data expected + _hw_start_xfer(rhport, CH58X_USB_PID_IN, ep_addr, edpt->data_toggle); + } + break; + } + + default: { + LOG_CH58X_HCD("unexpected PID 0x%02x\r\n", request_pid); + _current_xfer.is_busy = false; + hcd_event_xfer_complete(dev_addr, ep_addr, 0, XFER_RESULT_FAILED, in_isr); + break; + } + } + } else { + // Toggle mismatch, check response PID + if (response_pid == CH58X_USB_PID_STALL) { + LOG_CH58X_HCD("STALL response\r\n"); + edpt->data_toggle = 0; + _current_xfer.is_busy = false; + hcd_event_xfer_complete(dev_addr, ep_addr, 0, XFER_RESULT_STALLED, in_isr); + } else if (response_pid == CH58X_USB_PID_NAK) { + LOG_CH58X_HCD("NAK response\r\n"); + // NAK: schedule retry via deferred callback for all endpoint types + // This avoids tight polling loops and allows other tasks to run + _current_xfer.is_busy = false; + _current_xfer.nak_pending = true; + + edpt->is_nak_pending = true; + edpt->buflen = _current_xfer.bufferlen; + edpt->buf = _current_xfer.buffer; + + hcd_event_t event = { + .rhport = rhport, + .dev_addr = dev_addr, + .event_id = USBH_EVENT_FUNC_CALL, + .func_call = { + .func = _xfer_retry, + .param = edpt + } + }; + hcd_event_handler(&event, in_isr); + } else if (response_pid == CH58X_USB_PID_DATA0 || response_pid == CH58X_USB_PID_DATA1) { + LOG_CH58X_HCD("toggle mismatch, DATA0/1 rx_len=%d\r\n", CH58X_USB_RX_LEN(base)); + _current_xfer.is_busy = false; + hcd_event_xfer_complete(dev_addr, ep_addr, 0, XFER_RESULT_FAILED, in_isr); + } else { + LOG_CH58X_HCD("unexpected response 0x%02x\r\n", response_pid); + _current_xfer.is_busy = false; + hcd_event_xfer_complete(dev_addr, ep_addr, 0, XFER_RESULT_FAILED, in_isr); + } + } + + // Clear transfer flag + CH58X_USB_INT_FG(base) = CH58X_UIF_TRANSFER; + } +} + +#endif /* CFG_TUH_ENABLED && TUP_USBIP_WCH_CH58X */ diff --git a/src/tusb_option.h b/src/tusb_option.h index 9eb8ee533..50998613a 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -193,6 +193,7 @@ #define OPT_MCU_CH32F20X 2210 ///< WCH CH32F20x #define OPT_MCU_CH32V20X 2220 ///< WCH CH32V20X #define OPT_MCU_CH32V103 2230 ///< WCH CH32V103 +#define OPT_MCU_CH58X 2240 ///< WCH CH582/CH583 // NXP LPC MCX #define OPT_MCU_MCXN9 2300 ///< NXP MCX N9 Series -- cgit v1.3.1 From 2e913256073a07a993b3d3cb9abe8e1db97686db Mon Sep 17 00:00:00 2001 From: alt-0191 <2223147307@qq.com> Date: Fri, 27 Feb 2026 01:30:39 +0800 Subject: ch58x: fix build flags and driver bugs --- hw/bsp/ch58x/family.mk | 14 ++++++-- src/portable/wch/ch58x_usbfs_reg.h | 37 ++++++++------------ src/portable/wch/dcd_ch58x_usbfs.c | 70 ++++++++++++++++++++------------------ src/portable/wch/hcd_ch58x_usbfs.c | 60 ++++++++++++++++---------------- src/tusb_option.h | 6 ++-- 5 files changed, 96 insertions(+), 91 deletions(-) (limited to 'src/portable') diff --git a/hw/bsp/ch58x/family.mk b/hw/bsp/ch58x/family.mk index 566842f93..7b62af646 100644 --- a/hw/bsp/ch58x/family.mk +++ b/hw/bsp/ch58x/family.mk @@ -1,3 +1,9 @@ +# https://www.embecosm.com/resources/tool-chain-downloads/#riscv-stable +#CROSS_COMPILE ?= riscv32-unknown-elf- + +# Toolchain from https://nucleisys.com/download.php +#CROSS_COMPILE ?= riscv-nuclei-elf- + # Toolchain from https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack CROSS_COMPILE ?= riscv-none-elf- @@ -9,17 +15,21 @@ CPU_CORE ?= rv32imac-ilp32 CFLAGS += \ -flto \ - -msmall-data-limit=8 \ + -msmall-data-limit=16 \ -mno-save-restore \ -fmessage-length=0 \ -fsigned-char \ -DCFG_TUSB_MCU=OPT_MCU_CH58X \ -DCFG_TUD_WCH_USBIP_USBFS=1 \ -DFREQ_SYS=60000000 \ + -DDISK_LIB_ENABLE=0 \ + -DINT_SOFT \ + +CFLAGS += -Wno-error=strict-prototypes LDFLAGS_GCC += \ -nostdlib -nostartfiles \ - --specs=nosys.specs --specs=nano.specs \ + --specs=nosys.specs \ SRC_C += \ src/portable/wch/dcd_ch58x_usbfs.c \ diff --git a/src/portable/wch/ch58x_usbfs_reg.h b/src/portable/wch/ch58x_usbfs_reg.h index 11479a4f6..868589729 100644 --- a/src/portable/wch/ch58x_usbfs_reg.h +++ b/src/portable/wch/ch58x_usbfs_reg.h @@ -55,30 +55,23 @@ #define CH58X_UEP567_MOD(base) (*(volatile uint8_t *)((base) + 0x0E)) //--------------------------------------------------------------------+ -// Endpoint DMA / T_LEN / CTRL offset lookup tables -// EP0-EP4 are at low offsets, EP5-EP7 jump to higher offsets -// EP4 shares DMA with EP0 (no independent DMA register) -//--------------------------------------------------------------------+ -static const uint8_t ch58x_ep_dma_offset[] = { - 0x10, 0x14, 0x18, 0x1C, /* EP0, EP1, EP2, EP3 */ - 0xFF, /* EP4: shares with EP0, sentinel */ - 0x54, 0x58, 0x5C /* EP5, EP6, EP7 */ -}; - -static const uint8_t ch58x_ep_tlen_offset[] = { - 0x20, 0x24, 0x28, 0x2C, 0x30, /* EP0-EP4 */ - 0x64, 0x68, 0x6C /* EP5-EP7 */ -}; - -static const uint8_t ch58x_ep_ctrl_offset[] = { - 0x22, 0x26, 0x2A, 0x2E, 0x32, /* EP0-EP4 */ - 0x66, 0x6A, 0x6E /* EP5-EP7 */ -}; +// Endpoint DMA / T_LEN / CTRL register accessors +// +// EP0-EP3 DMA : base + 0x10 + ep*4 (EP4 shares EP0 DMA, no own register) +// EP5-EP7 DMA : base + 0x54 + (ep-5)*4 +// EP0-EP4 TLEN: base + 0x20 + ep*4 +// EP5-EP7 TLEN: base + 0x64 + (ep-5)*4 +// EP0-EP4 CTRL: base + 0x22 + ep*4 +// EP5-EP7 CTRL: base + 0x66 + (ep-5)*4 +// +// Using computed addresses avoids per-TU copies of static lookup tables. +// EP4 DMA is not accessed directly (it shares EP0's DMA register). +//--------------------------------------------------------------------+ // EP DMA is 16-bit (only low 16 bits of RAM address, high bits implied 0x2000) -#define CH58X_EP_DMA(base, ep) (*(volatile uint16_t *)((base) + ch58x_ep_dma_offset[ep])) -#define CH58X_EP_TLEN(base, ep) (*(volatile uint8_t *)((base) + ch58x_ep_tlen_offset[ep])) -#define CH58X_EP_CTRL(base, ep) (*(volatile uint8_t *)((base) + ch58x_ep_ctrl_offset[ep])) +#define CH58X_EP_DMA(base, ep) (*(volatile uint16_t *)((base) + ((ep) <= 3 ? (0x10u + (ep)*4u) : (0x54u + ((ep)-5u)*4u)))) +#define CH58X_EP_TLEN(base, ep) (*(volatile uint8_t *)((base) + ((ep) <= 4 ? (0x20u + (ep)*4u) : (0x64u + ((ep)-5u)*4u)))) +#define CH58X_EP_CTRL(base, ep) (*(volatile uint8_t *)((base) + ((ep) <= 4 ? (0x22u + (ep)*4u) : (0x66u + ((ep)-5u)*4u)))) //--------------------------------------------------------------------+ // USB_CTRL (R8_USB_CTRL) bit definitions diff --git a/src/portable/wch/dcd_ch58x_usbfs.c b/src/portable/wch/dcd_ch58x_usbfs.c index 11ff2c7b1..ea4a5ac4a 100644 --- a/src/portable/wch/dcd_ch58x_usbfs.c +++ b/src/portable/wch/dcd_ch58x_usbfs.c @@ -165,16 +165,16 @@ static uint8_t* ep_dma_buffer(dcd_data_t* d, uint8_t ep) { } //--------------------------------------------------------------------+ -// EP has auto-toggle support? +// AUTO_TOG supported on EP1/2/3/5/6/7 (no EP0 or EP4) //--------------------------------------------------------------------+ static inline bool ep_has_auto_toggle(uint8_t ep) { - return (ep >= 1 && ep <= 3); + return (ep >= 1 && ep <= 3) || (ep >= 5 && ep <= 7); } //--------------------------------------------------------------------+ // Private transfer helpers //--------------------------------------------------------------------+ -static void update_in(uint8_t rhport, uint8_t ep, bool force) { +static void update_in(uint8_t rhport, uint8_t ep, bool force, bool in_isr) { dcd_data_t* d = &_dcd_data[rhport]; uint32_t base = d->usb_base; struct usb_xfer* xfer = &d->xfer[ep][TUSB_DIR_IN]; @@ -213,12 +213,12 @@ static void update_in(uint8_t rhport, uint8_t ep, bool force) { xfer->valid = false; ep_set_tx_response(base, ep, CH58X_EP_T_RES_NAK); dcd_event_xfer_complete(rhport, ep | TUSB_DIR_IN_MASK, - xfer->processed_len, XFER_RESULT_SUCCESS, true); + xfer->processed_len, XFER_RESULT_SUCCESS, in_isr); } } } -static void update_out(uint8_t rhport, uint8_t ep, size_t rx_len) { +static void update_out(uint8_t rhport, uint8_t ep, size_t rx_len, bool in_isr) { dcd_data_t* d = &_dcd_data[rhport]; uint32_t base = d->usb_base; struct usb_xfer* xfer = &d->xfer[ep][TUSB_DIR_OUT]; @@ -239,7 +239,7 @@ static void update_out(uint8_t rhport, uint8_t ep, size_t rx_len) { if (xfer->len == 0 || len < xfer->max_size) { xfer->valid = false; dcd_event_xfer_complete(rhport, ep, xfer->processed_len, - XFER_RESULT_SUCCESS, true); + XFER_RESULT_SUCCESS, in_isr); } if (ep == 0) { @@ -297,11 +297,11 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { EP_TLEN(base, 4) = 0; EP_CTRL(base, 4) = CH58X_EP_R_RES_NAK | CH58X_EP_T_RES_NAK; - // EP5-7: DMA + no auto-toggle + // EP5-7: DMA + auto-toggle for (uint8_t ep = 5; ep <= 7; ep++) { EP_DMA(base, ep) = (uint16_t)(uint32_t) ep_dma_buffer(d, ep); EP_TLEN(base, ep) = 0; - EP_CTRL(base, ep) = CH58X_EP_R_RES_NAK | CH58X_EP_T_RES_NAK; + EP_CTRL(base, ep) = CH58X_EP_AUTO_TOG | CH58X_EP_R_RES_NAK | CH58X_EP_T_RES_NAK; } // Set EP0 max size @@ -325,18 +325,27 @@ void dcd_int_handler(uint8_t rhport) { // Check SETUP first via dedicated flag if (int_st & CH58X_UIS_SETUP_ACT) { // SETUP packet received on EP0 - ep_set_both_response(base, 0, CH58X_EP_T_RES_NAK, CH58X_EP_R_RES_ACK); + // After SETUP, both toggle bits must be set to DATA1 (SDK reference) + EP_CTRL(base, 0) = CH58X_EP_R_TOG | CH58X_EP_T_TOG | + CH58X_EP_R_RES_ACK | CH58X_EP_T_RES_NAK; d->ep0_tog = true; dcd_event_setup_received(rhport, ep_out_buffer(d, 0), true); } else { switch (token) { case CH58X_PID_OUT: { uint8_t rx_len = USB_RX_LEN(base); - if (!ep_has_auto_toggle(ep) && ep != 0) { - // Manual toggle for EP4-7 - EP_CTRL(base, ep) ^= CH58X_EP_R_TOG; + if (ep == 0) { + // EP0: always process (toggle managed via SETUP reset) + update_out(rhport, 0, rx_len, true); + } else if (int_st & CH58X_UIS_TOG_OK) { + // Toggle matched: data is valid + if (!ep_has_auto_toggle(ep)) { + // EP4: manual toggle + EP_CTRL(base, ep) ^= CH58X_EP_R_TOG; + } + update_out(rhport, ep, rx_len, true); } - update_out(rhport, ep, rx_len); + // else: toggle mismatch, discard packet per datasheet break; } @@ -345,7 +354,7 @@ void dcd_int_handler(uint8_t rhport) { // Manual toggle for EP4-7 EP_CTRL(base, ep) ^= CH58X_EP_T_TOG; } - update_in(rhport, ep, false); + update_in(rhport, ep, false, true); break; } @@ -370,19 +379,14 @@ void dcd_int_handler(uint8_t rhport) { USB_INT_FG(base) = CH58X_UIF_BUS_RST; } else if (status & CH58X_UIF_SUSPEND) { - if (USB_MIS_ST(base) & CH58X_UMS_SUSPEND) { - dcd_event_t event = {.rhport = rhport, .event_id = DCD_EVENT_SUSPEND}; - dcd_event_handler(&event, true); - } else { - dcd_event_t event = {.rhport = rhport, .event_id = DCD_EVENT_RESUME}; - dcd_event_handler(&event, true); - } + dcd_event_bus_signal(rhport, + (USB_MIS_ST(base) & CH58X_UMS_SUSPEND) ? DCD_EVENT_SUSPEND : DCD_EVENT_RESUME, + true); USB_INT_FG(base) = CH58X_UIF_SUSPEND; } } void dcd_int_enable(uint8_t rhport) { - (void) rhport; // PFIC enable: USB_IRQn=22, USB2_IRQn=23 volatile uint32_t* pfic_ienr = (volatile uint32_t*) 0xE000E100; uint8_t irqn = (rhport == 0) ? 22 : 23; @@ -390,7 +394,6 @@ void dcd_int_enable(uint8_t rhport) { } void dcd_int_disable(uint8_t rhport) { - (void) rhport; volatile uint32_t* pfic_irer = (volatile uint32_t*) 0xE000E180; uint8_t irqn = (rhport == 0) ? 22 : 23; pfic_irer[irqn / 32] = (1u << (irqn % 32)); @@ -406,7 +409,7 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) { void dcd_remote_wakeup(uint8_t rhport) { uint32_t base = get_usb_base(rhport); USB_UDEV_CTRL(base) |= CH58X_UD_GP_BIT; - for (volatile int i = 0; i < 60000; i++) { } // ~1ms resume signal + tusb_time_delay_ms_api(1); // 1ms resume signal per USB spec USB_UDEV_CTRL(base) &= ~CH58X_UD_GP_BIT; } @@ -421,12 +424,10 @@ void dcd_disconnect(uint8_t rhport) { } void dcd_sof_enable(uint8_t rhport, bool en) { - uint32_t base = get_usb_base(rhport); - if (en) { - USB_INT_EN(base) |= CH58X_UIE_HST_SOF; - } else { - USB_INT_EN(base) &= ~CH58X_UIE_HST_SOF; - } + // CH58x has no device-mode SOF interrupt. + // RB_UIE_HST_SOF (0x08) is host-mode only and has no effect in device mode. + (void) rhport; + (void) en; } void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const* request) { @@ -436,7 +437,9 @@ void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const* req if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE && request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && request->bRequest == TUSB_REQ_SET_ADDRESS) { - USB_DEV_AD(base) = (uint8_t) request->wValue; + // Preserve GP_BIT (bit7) when setting device address + USB_DEV_AD(base) = (USB_DEV_AD(base) & CH58X_UDA_GP_BIT) | + ((uint8_t)request->wValue & CH58X_USB_ADDR_MASK); } ep_set_both_response(base, 0, CH58X_EP_T_RES_NAK, CH58X_EP_R_RES_ACK); } @@ -505,7 +508,6 @@ bool dcd_edpt_iso_activate(uint8_t rhport, const tusb_desc_endpoint_t* desc_ep) bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes, bool is_isr) { - (void) is_isr; uint8_t ep = tu_edpt_number(ep_addr); uint8_t dir = tu_edpt_dir(ep_addr); @@ -517,10 +519,9 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, xfer->buffer = buffer; xfer->len = total_bytes; xfer->processed_len = 0; - dcd_int_enable(rhport); if (dir == TUSB_DIR_IN) { - update_in(rhport, ep, true); + update_in(rhport, ep, true, is_isr); } else { // For OUT direction, set endpoint to ACK to start receiving data if (ep != 0) { @@ -531,6 +532,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, } } } + dcd_int_enable(rhport); return true; } diff --git a/src/portable/wch/hcd_ch58x_usbfs.c b/src/portable/wch/hcd_ch58x_usbfs.c index 629c2a789..8a8da9f16 100644 --- a/src/portable/wch/hcd_ch58x_usbfs.c +++ b/src/portable/wch/hcd_ch58x_usbfs.c @@ -422,7 +422,13 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const* dev_addr, ep_addr, max_packet_size, xfer_type); // Wait for any pending transfer - while (_current_xfer.is_busy) {} + uint32_t t0 = tusb_time_millis_api(); + while (_current_xfer.is_busy) { + if (tusb_time_millis_api() - t0 > 200) { + _current_xfer.is_busy = false; + break; + } + } if (ep_num == 0) { TU_ASSERT(_get_or_add_edpt(dev_addr, 0x00, max_packet_size, xfer_type) != NULL, false); @@ -447,8 +453,14 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, LOG_CH58X_HCD("hcd_edpt_xfer(dev=0x%02x, ep=0x%02x, len=%d)\r\n", dev_addr, ep_addr, buflen); - // Wait for any pending transfer - while (_current_xfer.is_busy) {} + // Wait for any pending transfer (with 200ms timeout to avoid deadlock on disconnect) + uint32_t t0 = tusb_time_millis_api(); + while (_current_xfer.is_busy) { + if (tusb_time_millis_api() - t0 > 200) { + _current_xfer.is_busy = false; + return false; + } + } _current_xfer.is_busy = true; hcd_edpt_t* edpt = _get_edpt(dev_addr, ep_addr); @@ -490,7 +502,13 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet LOG_CH58X_HCD("hcd_setup_send(dev=0x%02x)\r\n", dev_addr); // Wait for any pending transfer - while (_current_xfer.is_busy) {} + uint32_t t0 = tusb_time_millis_api(); + while (_current_xfer.is_busy) { + if (tusb_time_millis_api() - t0 > 200) { + _current_xfer.is_busy = false; + return false; + } + } _current_xfer.is_busy = true; _hw_set_addr_speed(rhport, dev_addr); @@ -522,33 +540,12 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet } bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { - uint32_t base = _port_data[rhport].usb_base; - uint8_t ep_num = tu_edpt_number(ep_addr); + (void) rhport; LOG_CH58X_HCD("hcd_edpt_clear_stall(dev=0x%02x, ep=0x%02x)\r\n", dev_addr, ep_addr); - - // Send CLEAR_FEATURE(ENDPOINT_HALT) via blocking transfer - uint8_t setup[8] = { - 0x02, 0x01, 0x00, 0x00, ep_addr, 0x00, 0x00, 0x00 - }; - memcpy(_tx_buf[rhport], setup, 8); - CH58X_UH_TX_LEN(base) = 8; - - bool prev_int = _port_data[rhport].int_enabled; - hcd_int_disable(rhport); - - CH58X_UH_EP_PID(base) = (CH58X_USB_PID_SETUP << 4) | 0x00; - CH58X_USB_INT_FG(base) = CH58X_UIF_TRANSFER; - while ((CH58X_USB_INT_FG(base) & CH58X_UIF_TRANSFER) == 0) {} - CH58X_UH_EP_PID(base) = 0; - - uint8_t response = CH58X_USB_INT_ST(base) & CH58X_UIS_H_RES_MASK; - (void)response; - - LOG_CH58X_HCD("clear_stall response=0x%02x\r\n", response); - - if (prev_int) { - hcd_int_enable(rhport); + hcd_edpt_t* edpt = _get_edpt(dev_addr, ep_addr); + if (edpt != NULL) { + edpt->data_toggle = 0; } return true; @@ -570,6 +567,10 @@ void hcd_int_handler(uint8_t rhport, bool in_isr) { if (attached) { hcd_event_device_attach(rhport, in_isr); } else { + // Stop any ongoing hardware transfer before reporting removal + CH58X_UH_EP_PID(base) = 0x00; + _current_xfer.is_busy = false; + _current_xfer.nak_pending = false; hcd_event_device_remove(rhport, in_isr); } return; @@ -580,7 +581,6 @@ void hcd_int_handler(uint8_t rhport, bool in_isr) { // Read PID/endpoint before stopping (must read first!) uint8_t pid_endp = CH58X_UH_EP_PID(base); uint8_t int_st = CH58X_USB_INT_ST(base); - uint8_t int_fg = CH58X_USB_INT_FG(base); uint8_t dev_addr = CH58X_USB_DEV_AD(base) & CH58X_USB_ADDR_MASK; // Stop USB transaction immediately (SDK: R8_UH_EP_PID = 0x00) diff --git a/src/tusb_option.h b/src/tusb_option.h index 699e3d44d..c75908e87 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -193,9 +193,9 @@ #define OPT_MCU_CH32F20X 2210 ///< WCH CH32F20x #define OPT_MCU_CH32V20X 2220 ///< WCH CH32V20X #define OPT_MCU_CH32V103 2230 ///< WCH CH32V103 -#define OPT_MCU_CH58X 2240 ///< WCH CH58x series (CH582/CH583) -#define OPT_MCU_CH582 OPT_MCU_CH58X ///< alias -#define OPT_MCU_CH583 OPT_MCU_CH58X ///< alias +#define OPT_MCU_CH58X 2240 ///< WCH CH58x +#define OPT_MCU_CH582 2240 ///< alias to CH58x series +#define OPT_MCU_CH583 2240 ///< alias to CH58x series // NXP LPC MCX #define OPT_MCU_MCXN9 2300 ///< NXP MCX N9 Series -- cgit v1.3.1 From 56f94bbb46bebf88e9be0332ebb9db03b30d1cb1 Mon Sep 17 00:00:00 2001 From: alt-0191 <2223147307@qq.com> Date: Fri, 13 Mar 2026 22:57:18 +0800 Subject: dcd_ch58x: fix toggle, SETUP race, and bus reset handling - Switch from AUTO_TOG to manual toggle for all endpoints to fix toggle mismatch after clear-stall causing bus resets - Fix SETUP race condition: track ep0_completion_pending and setup_pending to avoid arming stale EP0 transfers - Defer Set Address to ISR after status ZLP is ACK'd - Improve bus reset: reset all EPs, clear pending state - Fix EP4 DMA macro to correctly map to EP0 base (0x10) - Move CH58X_UIS_TOG_OK to common section (used by both DCD/HCD) - Add #ifndef guards for BOARD_TUD/TUH_RHPORT in board.h - Track isochronous per direction: isochronous[ep][dir] - NAK EP0 OUT on completion to prevent premature data acceptance --- hw/bsp/ch58x/boards/yd-ch582m/board.h | 4 + src/portable/wch/ch58x_usbfs_reg.h | 18 +--- src/portable/wch/dcd_ch58x_usbfs.c | 193 +++++++++++++++++++++------------- src/portable/wch/hcd_ch58x_usbfs.c | 2 +- 4 files changed, 131 insertions(+), 86 deletions(-) (limited to 'src/portable') diff --git a/hw/bsp/ch58x/boards/yd-ch582m/board.h b/hw/bsp/ch58x/boards/yd-ch582m/board.h index 6e25dbdd3..a14ffd198 100644 --- a/hw/bsp/ch58x/boards/yd-ch582m/board.h +++ b/hw/bsp/ch58x/boards/yd-ch582m/board.h @@ -47,8 +47,12 @@ extern "C" { // Dual-port: USB1 (rhport 0) = Device, USB2 (rhport 1) = Host // Swap these two if you want the opposite assignment +#ifndef BOARD_TUD_RHPORT #define BOARD_TUD_RHPORT 0 +#endif +#ifndef BOARD_TUH_RHPORT #define BOARD_TUH_RHPORT 1 +#endif #ifdef __cplusplus } diff --git a/src/portable/wch/ch58x_usbfs_reg.h b/src/portable/wch/ch58x_usbfs_reg.h index 868589729..ed9f8d0f7 100644 --- a/src/portable/wch/ch58x_usbfs_reg.h +++ b/src/portable/wch/ch58x_usbfs_reg.h @@ -56,20 +56,10 @@ //--------------------------------------------------------------------+ // Endpoint DMA / T_LEN / CTRL register accessors -// -// EP0-EP3 DMA : base + 0x10 + ep*4 (EP4 shares EP0 DMA, no own register) -// EP5-EP7 DMA : base + 0x54 + (ep-5)*4 -// EP0-EP4 TLEN: base + 0x20 + ep*4 -// EP5-EP7 TLEN: base + 0x64 + (ep-5)*4 -// EP0-EP4 CTRL: base + 0x22 + ep*4 -// EP5-EP7 CTRL: base + 0x66 + (ep-5)*4 -// -// Using computed addresses avoids per-TU copies of static lookup tables. -// EP4 DMA is not accessed directly (it shares EP0's DMA register). //--------------------------------------------------------------------+ -// EP DMA is 16-bit (only low 16 bits of RAM address, high bits implied 0x2000) -#define CH58X_EP_DMA(base, ep) (*(volatile uint16_t *)((base) + ((ep) <= 3 ? (0x10u + (ep)*4u) : (0x54u + ((ep)-5u)*4u)))) +// EP DMA is 16-bit (only low 16 bits of RAM address, high bits implied 0x2000), EP4 shares EP0's DMA register (no independent DMA), so ep==4 maps to base+0x10 +#define CH58X_EP_DMA(base, ep) (*(volatile uint16_t *)((base) + ((ep) <= 3 ? (0x10u + (ep)*4u) : ((ep) == 4 ? 0x10u : (0x54u + ((ep)-5u)*4u))))) #define CH58X_EP_TLEN(base, ep) (*(volatile uint8_t *)((base) + ((ep) <= 4 ? (0x20u + (ep)*4u) : (0x64u + ((ep)-5u)*4u)))) #define CH58X_EP_CTRL(base, ep) (*(volatile uint8_t *)((base) + ((ep) <= 4 ? (0x22u + (ep)*4u) : (0x66u + ((ep)-5u)*4u)))) @@ -121,6 +111,7 @@ //--------------------------------------------------------------------+ #define CH58X_INT_ST_ENDP(x) (((x) >> 0) & 0x0F) #define CH58X_INT_ST_TOKEN(x) (((x) >> 4) & 0x03) +#define CH58X_UIS_TOG_OK 0x40 // toggle match flag (device and host) #define CH58X_UIS_SETUP_ACT 0x80 // Token PID values @@ -147,7 +138,7 @@ // Bit 7: RB_UEP_R_TOG RX data toggle // Bit 6: RB_UEP_T_TOG TX data toggle // Bit 5: (reserved) -// Bit 4: RB_UEP_AUTO_TOG auto toggle (EP1/2/3 only) +// Bit 4: RB_UEP_AUTO_TOG auto toggle (EP1/2/3/5/6/7, not EP0/EP4) // Bit 3: R_RES1 RX response high // Bit 2: R_RES0 RX response low // Bit 1: T_RES1 TX response high @@ -253,7 +244,6 @@ // USB_INT_ST host-mode bits //--------------------------------------------------------------------+ #define CH58X_UIS_H_RES_MASK 0x0F -#define CH58X_UIS_TOG_OK 0x40 //--------------------------------------------------------------------+ // USB_DEV_AD bits diff --git a/src/portable/wch/dcd_ch58x_usbfs.c b/src/portable/wch/dcd_ch58x_usbfs.c index ea4a5ac4a..f994638c8 100644 --- a/src/portable/wch/dcd_ch58x_usbfs.c +++ b/src/portable/wch/dcd_ch58x_usbfs.c @@ -95,7 +95,10 @@ struct usb_xfer { typedef struct { uint32_t usb_base; bool ep0_tog; - bool isochronous[EP_MAX]; + volatile uint8_t setup_pending; // SETUP arrived while EP0 completion pending in queue + volatile bool ep0_completion_pending; // EP0 XFER_COMPLETE in event queue, not yet processed + uint8_t pending_addr; // Address to set in ISR after Set Address status ZLP + bool isochronous[EP_MAX][2]; // [ep][dir] struct usb_xfer xfer[EP_MAX][2]; // [ep][dir] // EP0 + EP4 shared buffer: EP0 OUT(64) + EP4 OUT(64) + EP4 IN(64) @@ -117,9 +120,6 @@ static dcd_data_t _dcd_data[2]; //--------------------------------------------------------------------+ // Buffer address helpers -// EP0: ep0_buffer[0..63] -// EP4 OUT: ep0_buffer[64..127] EP4 IN: ep0_buffer[128..191] -// Other EPs: epX_buffer[0] = OUT, epX_buffer[1] = IN //--------------------------------------------------------------------+ static uint8_t* ep_out_buffer(dcd_data_t* d, uint8_t ep) { switch (ep) { @@ -149,8 +149,7 @@ static uint8_t* ep_in_buffer(dcd_data_t* d, uint8_t ep) { } } -// Get DMA base pointer for endpoint (the buffer whose address is set to DMA register) -// For EP4, DMA is shared with EP0, so we return EP0 buffer +// DMA base pointer (EP4 shares with EP0) static uint8_t* ep_dma_buffer(dcd_data_t* d, uint8_t ep) { switch (ep) { case 0: case 4: return &d->ep0_buffer[0]; @@ -164,12 +163,9 @@ static uint8_t* ep_dma_buffer(dcd_data_t* d, uint8_t ep) { } } -//--------------------------------------------------------------------+ -// AUTO_TOG supported on EP1/2/3/5/6/7 (no EP0 or EP4) -//--------------------------------------------------------------------+ -static inline bool ep_has_auto_toggle(uint8_t ep) { - return (ep >= 1 && ep <= 3) || (ep >= 5 && ep <= 7); -} +// AUTO_TOG is not used (EP1-3/5-7 support it). When clear-stall resets T_TOG/ +// R_TOG to DATA0, the hardware internal toggle doesn't sync, causing mismatch +// and bus resets. Use manual toggle (EP_CTRL ^= TOG) in ISR instead. //--------------------------------------------------------------------+ // Private transfer helpers @@ -203,7 +199,7 @@ static void update_in(uint8_t rhport, uint8_t ep, bool force, bool in_isr) { if (d->ep0_tog) ctrl |= CH58X_EP_T_TOG; EP_CTRL(base, 0) = ctrl; d->ep0_tog = !d->ep0_tog; - } else if (d->isochronous[ep]) { + } else if (d->isochronous[ep][TUSB_DIR_IN]) { ep_set_tx_response(base, ep, CH58X_EP_T_RES_TOUT); } else { ep_set_tx_response(base, ep, CH58X_EP_T_RES_ACK); @@ -212,6 +208,7 @@ static void update_in(uint8_t rhport, uint8_t ep, bool force, bool in_isr) { // Transfer complete xfer->valid = false; ep_set_tx_response(base, ep, CH58X_EP_T_RES_NAK); + if (ep == 0) d->ep0_completion_pending = true; dcd_event_xfer_complete(rhport, ep | TUSB_DIR_IN_MASK, xfer->processed_len, XFER_RESULT_SUCCESS, in_isr); } @@ -238,11 +235,13 @@ static void update_out(uint8_t rhport, uint8_t ep, size_t rx_len, bool in_isr) { if (xfer->len == 0 || len < xfer->max_size) { xfer->valid = false; + // NAK to prevent hardware from accepting next OUT before a new xfer is queued + ep_set_rx_response(base, ep, CH58X_EP_R_RES_NAK); + if (ep == 0) d->ep0_completion_pending = true; dcd_event_xfer_complete(rhport, ep, xfer->processed_len, XFER_RESULT_SUCCESS, in_isr); - } - - if (ep == 0) { + } else if (ep == 0) { + // EP0 multi-packet: ensure ACK for next packet ep_set_rx_response(base, 0, CH58X_EP_R_RES_ACK); } } @@ -262,6 +261,12 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { tu_memclr(d->xfer, sizeof(d->xfer)); tu_memclr(d->isochronous, sizeof(d->isochronous)); d->ep0_tog = true; + d->setup_pending = 0; + d->ep0_completion_pending = false; + d->pending_addr = 0; + + // Reset USB control register first (SDK pattern) + USB_CTRL(base) = 0x00; // Init control registers USB_CTRL(base) = CH58X_UC_DEV_PU_EN | CH58X_UC_INT_BUSY | CH58X_UC_DMA_EN; @@ -286,22 +291,22 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { CH58X_UEP6_RX_EN | CH58X_UEP6_TX_EN | CH58X_UEP7_RX_EN | CH58X_UEP7_TX_EN; - // EP1-3: DMA + auto-toggle + NAK both directions + // EP1-3: DMA + manual toggle + NAK both directions for (uint8_t ep = 1; ep <= 3; ep++) { EP_DMA(base, ep) = (uint16_t)(uint32_t) ep_dma_buffer(d, ep); EP_TLEN(base, ep) = 0; - EP_CTRL(base, ep) = CH58X_EP_AUTO_TOG | CH58X_EP_R_RES_NAK | CH58X_EP_T_RES_NAK; + EP_CTRL(base, ep) = CH58X_EP_R_RES_NAK | CH58X_EP_T_RES_NAK; } // EP4: no independent DMA, no auto-toggle EP_TLEN(base, 4) = 0; EP_CTRL(base, 4) = CH58X_EP_R_RES_NAK | CH58X_EP_T_RES_NAK; - // EP5-7: DMA + auto-toggle + // EP5-7: DMA + manual toggle for (uint8_t ep = 5; ep <= 7; ep++) { EP_DMA(base, ep) = (uint16_t)(uint32_t) ep_dma_buffer(d, ep); EP_TLEN(base, ep) = 0; - EP_CTRL(base, ep) = CH58X_EP_AUTO_TOG | CH58X_EP_R_RES_NAK | CH58X_EP_T_RES_NAK; + EP_CTRL(base, ep) = CH58X_EP_R_RES_NAK | CH58X_EP_T_RES_NAK; } // Set EP0 max size @@ -322,36 +327,33 @@ void dcd_int_handler(uint8_t rhport) { uint8_t ep = CH58X_INT_ST_ENDP(int_st); uint8_t token = CH58X_INT_ST_TOKEN(int_st); - // Check SETUP first via dedicated flag - if (int_st & CH58X_UIS_SETUP_ACT) { - // SETUP packet received on EP0 - // After SETUP, both toggle bits must be set to DATA1 (SDK reference) - EP_CTRL(base, 0) = CH58X_EP_R_TOG | CH58X_EP_T_TOG | - CH58X_EP_R_RES_ACK | CH58X_EP_T_RES_NAK; - d->ep0_tog = true; - dcd_event_setup_received(rhport, ep_out_buffer(d, 0), true); - } else { + // Process regular token before SETUP to avoid losing it + if (token != CH58X_PID_SETUP) { switch (token) { case CH58X_PID_OUT: { uint8_t rx_len = USB_RX_LEN(base); if (ep == 0) { - // EP0: always process (toggle managed via SETUP reset) + // EP0: manual toggle, always process + EP_CTRL(base, 0) ^= CH58X_EP_R_TOG; update_out(rhport, 0, rx_len, true); } else if (int_st & CH58X_UIS_TOG_OK) { - // Toggle matched: data is valid - if (!ep_has_auto_toggle(ep)) { - // EP4: manual toggle - EP_CTRL(base, ep) ^= CH58X_EP_R_TOG; - } + // Toggle OK: manual toggle and process + EP_CTRL(base, ep) ^= CH58X_EP_R_TOG; update_out(rhport, ep, rx_len, true); } - // else: toggle mismatch, discard packet per datasheet + // else: toggle mismatch, discard break; } case CH58X_PID_IN: { - if (!ep_has_auto_toggle(ep) && ep != 0) { - // Manual toggle for EP4-7 + // Apply pending Set Address immediately after status ZLP + if (ep == 0 && d->pending_addr) { + USB_DEV_AD(base) = (USB_DEV_AD(base) & CH58X_UDA_GP_BIT) | + (d->pending_addr & CH58X_USB_ADDR_MASK); + d->pending_addr = 0; + } + if (ep != 0) { + // Manual toggle for all non-EP0 endpoints EP_CTRL(base, ep) ^= CH58X_EP_T_TOG; } update_in(rhport, ep, false, true); @@ -361,24 +363,61 @@ void dcd_int_handler(uint8_t rhport) { default: break; } + USB_INT_FG(base) = CH58X_UIF_TRANSFER; + } + + // SETUP_ACT is checked separately — it persists even if token field changed + if (int_st & CH58X_UIS_SETUP_ACT) { + // Reset toggles to DATA1, NAK both directions until stack is ready + EP_CTRL(base, 0) = CH58X_EP_R_TOG | CH58X_EP_T_TOG | + CH58X_EP_R_RES_NAK | CH58X_EP_T_RES_NAK; + d->ep0_tog = true; + + d->pending_addr = 0; + + // Mark stale EP0 completion so dcd_edpt_xfer can skip it + d->setup_pending = d->ep0_completion_pending ? 1 : 0; + d->ep0_completion_pending = false; + d->xfer[0][TUSB_DIR_OUT].valid = false; + d->xfer[0][TUSB_DIR_IN].valid = false; + + dcd_event_setup_received(rhport, ep_out_buffer(d, 0), true); + USB_INT_FG(base) = CH58X_UIF_TRANSFER; } + } - USB_INT_FG(base) = CH58X_UIF_TRANSFER; - } else if (status & CH58X_UIF_BUS_RST) { - // Bus reset + // Process bus reset: reset all endpoints immediately (matching WCH SDK pattern) + if (status & CH58X_UIF_BUS_RST) { d->ep0_tog = true; + d->setup_pending = 0; + d->ep0_completion_pending = false; + d->pending_addr = 0; + + // Reset EP0: ACK for RX (ready for SETUP), NAK for TX + EP_CTRL(base, 0) = CH58X_EP_R_RES_ACK | CH58X_EP_T_RES_NAK; + EP_TLEN(base, 0) = 0; d->xfer[0][TUSB_DIR_OUT].max_size = EP_BUF_SIZE; d->xfer[0][TUSB_DIR_IN].max_size = EP_BUF_SIZE; + // Reset EP1-7: NAK both directions, invalidate pending transfers + for (uint8_t ep = 1; ep < EP_MAX; ep++) { + d->xfer[ep][TUSB_DIR_IN].valid = false; + d->xfer[ep][TUSB_DIR_OUT].valid = false; + EP_CTRL(base, ep) = CH58X_EP_R_RES_NAK | CH58X_EP_T_RES_NAK; + EP_TLEN(base, ep) = 0; + } + USB_DEV_AD(base) = 0x00; - ep_set_rx_response(base, 0, CH58X_EP_R_RES_ACK); - tusb_speed_t speed = (USB_MIS_ST(base) & CH58X_UMS_DM_LEVEL) ? + tusb_speed_t speed = (USB_CTRL(base) & CH58X_UC_LOW_SPEED) ? TUSB_SPEED_LOW : TUSB_SPEED_FULL; dcd_event_bus_reset(rhport, speed, true); USB_INT_FG(base) = CH58X_UIF_BUS_RST; - } else if (status & CH58X_UIF_SUSPEND) { + } + + // Process suspend/resume + if (status & CH58X_UIF_SUSPEND) { dcd_event_bus_signal(rhport, (USB_MIS_ST(base) & CH58X_UMS_SUSPEND) ? DCD_EVENT_SUSPEND : DCD_EVENT_RESUME, true); @@ -401,16 +440,14 @@ void dcd_int_disable(uint8_t rhport) { } void dcd_set_address(uint8_t rhport, uint8_t dev_addr) { - (void) dev_addr; - // Address is set in status stage complete callback + // Defer to ISR: apply address right after status ZLP is ACK'd + _dcd_data[rhport].pending_addr = dev_addr; dcd_edpt_xfer(rhport, 0x80, NULL, 0, false); } void dcd_remote_wakeup(uint8_t rhport) { - uint32_t base = get_usb_base(rhport); - USB_UDEV_CTRL(base) |= CH58X_UD_GP_BIT; - tusb_time_delay_ms_api(1); // 1ms resume signal per USB spec - USB_UDEV_CTRL(base) &= ~CH58X_UD_GP_BIT; + (void) rhport; + // TODO: not supported } void dcd_connect(uint8_t rhport) { @@ -424,8 +461,6 @@ void dcd_disconnect(uint8_t rhport) { } void dcd_sof_enable(uint8_t rhport, bool en) { - // CH58x has no device-mode SOF interrupt. - // RB_UIE_HST_SOF (0x08) is host-mode only and has no effect in device mode. (void) rhport; (void) en; } @@ -437,11 +472,20 @@ void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const* req if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE && request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && request->bRequest == TUSB_REQ_SET_ADDRESS) { - // Preserve GP_BIT (bit7) when setting device address + // Safety net: re-apply address in case ISR path was skipped USB_DEV_AD(base) = (USB_DEV_AD(base) & CH58X_UDA_GP_BIT) | ((uint8_t)request->wValue & CH58X_USB_ADDR_MASK); } - ep_set_both_response(base, 0, CH58X_EP_T_RES_NAK, CH58X_EP_R_RES_ACK); + + dcd_int_disable(rhport); + d->ep0_completion_pending = false; + if (d->setup_pending) { + // SETUP already arrived — don't override its NAK with ACK + d->setup_pending = 0; + } else { + ep_set_both_response(base, 0, CH58X_EP_T_RES_NAK, CH58X_EP_R_RES_ACK); + } + dcd_int_enable(rhport); } bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const* desc_ep) { @@ -451,29 +495,26 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const* desc_ep) { uint8_t dir = tu_edpt_dir(desc_ep->bEndpointAddress); TU_ASSERT(ep < EP_MAX); - d->isochronous[ep] = (desc_ep->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS); + d->isochronous[ep][dir] = (desc_ep->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS); d->xfer[ep][dir].max_size = tu_edpt_packet_size(desc_ep); if (ep != 0) { dcd_int_disable(rhport); uint8_t ctrl = EP_CTRL(base, ep); if (dir == TUSB_DIR_OUT) { - if (d->isochronous[ep]) { + // Clear RX toggle to DATA0 per USB spec + ctrl &= ~CH58X_EP_R_TOG; + if (d->isochronous[ep][TUSB_DIR_OUT]) { ctrl = (ctrl & ~CH58X_EP_R_RES_MASK) | CH58X_EP_R_RES_TOUT; } else { // Start with NAK; dcd_edpt_xfer will set ACK when a transfer is submitted ctrl = (ctrl & ~CH58X_EP_R_RES_MASK) | CH58X_EP_R_RES_NAK; } - // Enable auto toggle for EP1-3 - if (ep_has_auto_toggle(ep)) { - ctrl |= CH58X_EP_AUTO_TOG; - } } else { + // Clear TX toggle to DATA0 per USB spec + ctrl &= ~CH58X_EP_T_TOG; EP_TLEN(base, ep) = 0; ctrl = (ctrl & ~CH58X_EP_T_RES_MASK) | CH58X_EP_T_RES_NAK; - if (ep_has_auto_toggle(ep)) { - ctrl |= CH58X_EP_AUTO_TOG; - } } EP_CTRL(base, ep) = ctrl; dcd_int_enable(rhport); @@ -488,7 +529,8 @@ void dcd_edpt_close_all(uint8_t rhport) { for (uint8_t ep = 1; ep < EP_MAX; ep++) { d->xfer[ep][TUSB_DIR_IN].valid = false; d->xfer[ep][TUSB_DIR_OUT].valid = false; - d->isochronous[ep] = false; + d->isochronous[ep][TUSB_DIR_OUT] = false; + d->isochronous[ep][TUSB_DIR_IN] = false; EP_CTRL(base, ep) = CH58X_EP_R_RES_NAK | CH58X_EP_T_RES_NAK; } } @@ -515,6 +557,17 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, struct usb_xfer* xfer = &d->xfer[ep][dir]; dcd_int_disable(rhport); + + // Skip stale EP0 arm if a new SETUP has already arrived + if (ep == 0) { + d->ep0_completion_pending = false; + if (d->setup_pending) { + d->setup_pending = 0; + dcd_int_enable(rhport); + return true; + } + } + xfer->valid = true; xfer->buffer = buffer; xfer->len = total_bytes; @@ -523,13 +576,11 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, if (dir == TUSB_DIR_IN) { update_in(rhport, ep, true, is_isr); } else { - // For OUT direction, set endpoint to ACK to start receiving data - if (ep != 0) { - if (d->isochronous[ep]) { - ep_set_rx_response(d->usb_base, ep, CH58X_EP_R_RES_TOUT); - } else { - ep_set_rx_response(d->usb_base, ep, CH58X_EP_R_RES_ACK); - } + + if (d->isochronous[ep][TUSB_DIR_OUT]) { + ep_set_rx_response(d->usb_base, ep, CH58X_EP_R_RES_TOUT); + } else { + ep_set_rx_response(d->usb_base, ep, CH58X_EP_R_RES_ACK); } } dcd_int_enable(rhport); diff --git a/src/portable/wch/hcd_ch58x_usbfs.c b/src/portable/wch/hcd_ch58x_usbfs.c index 8a8da9f16..2b1bd40bc 100644 --- a/src/portable/wch/hcd_ch58x_usbfs.c +++ b/src/portable/wch/hcd_ch58x_usbfs.c @@ -305,7 +305,7 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { // Clear endpoint records tu_memclr(_edpt_list, sizeof(_edpt_list)); - tu_memclr((void*)&_current_xfer, sizeof(_current_xfer)); + _current_xfer = (const hcd_xfer_t){0}; _hw_init_host(rhport, true); -- cgit v1.3.1 From dc87bab45f8123cbfa2b4b0ac6e1831c1172651f Mon Sep 17 00:00:00 2001 From: alt-0191 <2223147307@qq.com> Date: Fri, 13 Mar 2026 23:58:18 +0800 Subject: ch58x: code cleanup and minor fixes --- hw/bsp/ch58x/ch58x_it.h | 6 +- hw/bsp/ch58x/debug_uart.c | 6 +- hw/bsp/ch58x/debug_uart.h | 8 ++ hw/bsp/ch58x/system_ch58x.h | 6 +- src/portable/wch/ch58x_usbfs_reg.h | 9 ++ src/portable/wch/dcd_ch58x_usbfs.c | 30 +++--- src/portable/wch/hcd_ch58x_usbfs.c | 203 +++++++++++++++++++------------------ 7 files changed, 147 insertions(+), 121 deletions(-) (limited to 'src/portable') diff --git a/hw/bsp/ch58x/ch58x_it.h b/hw/bsp/ch58x/ch58x_it.h index c98f732e1..18ea52bc9 100644 --- a/hw/bsp/ch58x/ch58x_it.h +++ b/hw/bsp/ch58x/ch58x_it.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef __CH58X_IT_H -#define __CH58X_IT_H +#ifndef CH58X_IT_H_ +#define CH58X_IT_H_ #ifdef __cplusplus extern "C" { @@ -43,4 +43,4 @@ void SysTick_Handler(void); } #endif -#endif /* __CH58X_IT_H */ +#endif /* CH58X_IT_H_ */ diff --git a/hw/bsp/ch58x/debug_uart.c b/hw/bsp/ch58x/debug_uart.c index e63606f33..7dd133cb2 100644 --- a/hw/bsp/ch58x/debug_uart.c +++ b/hw/bsp/ch58x/debug_uart.c @@ -35,11 +35,11 @@ #define UART_RINGBUFFER_MASK_TX (UART_RINGBUFFER_SIZE_TX - 1) static char tx_buf[UART_RINGBUFFER_SIZE_TX]; -static unsigned int tx_produce; -static volatile unsigned int tx_consume; +static uint32_t tx_produce; +static volatile uint32_t tx_consume; void uart_write(char c) { - unsigned int tx_produce_next = (tx_produce + 1) & UART_RINGBUFFER_MASK_TX; + uint32_t tx_produce_next = (tx_produce + 1) & UART_RINGBUFFER_MASK_TX; // If ring buffer is full, wait while (tx_produce_next == tx_consume) {} diff --git a/hw/bsp/ch58x/debug_uart.h b/hw/bsp/ch58x/debug_uart.h index 458d838d9..44c3e7948 100644 --- a/hw/bsp/ch58x/debug_uart.h +++ b/hw/bsp/ch58x/debug_uart.h @@ -29,8 +29,16 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + void uart_write(char c); void uart_sync(void); void usart_printf_init(uint32_t baudrate); +#ifdef __cplusplus +} +#endif + #endif /* DEBUG_UART_H_ */ diff --git a/hw/bsp/ch58x/system_ch58x.h b/hw/bsp/ch58x/system_ch58x.h index ef32e603f..e96741ee8 100644 --- a/hw/bsp/ch58x/system_ch58x.h +++ b/hw/bsp/ch58x/system_ch58x.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef __SYSTEM_CH58X_H -#define __SYSTEM_CH58X_H +#ifndef SYSTEM_CH58X_H_ +#define SYSTEM_CH58X_H_ #ifdef __cplusplus extern "C" { @@ -40,4 +40,4 @@ extern void SystemCoreClockUpdate(void); } #endif -#endif /* __SYSTEM_CH58X_H */ +#endif /* SYSTEM_CH58X_H_ */ diff --git a/src/portable/wch/ch58x_usbfs_reg.h b/src/portable/wch/ch58x_usbfs_reg.h index ed9f8d0f7..67b47e0b6 100644 --- a/src/portable/wch/ch58x_usbfs_reg.h +++ b/src/portable/wch/ch58x_usbfs_reg.h @@ -279,4 +279,13 @@ #define CH58X_SLP_CLK_OFF1 (*(volatile uint8_t *)0x4000100D) #define CH58X_SLP_CLK_USB 0x10 +//--------------------------------------------------------------------+ +// PFIC (Platform-level Fast Interrupt Controller) +//--------------------------------------------------------------------+ +#define CH58X_PFIC_IENR ((volatile uint32_t *)0xE000E100) // interrupt enable +#define CH58X_PFIC_IRER ((volatile uint32_t *)0xE000E180) // interrupt reset (disable) + +#define CH58X_USB_IRQn 22 +#define CH58X_USB2_IRQn 23 + #endif /* CH58X_USBFS_REG_H */ diff --git a/src/portable/wch/dcd_ch58x_usbfs.c b/src/portable/wch/dcd_ch58x_usbfs.c index f994638c8..c6f10b801 100644 --- a/src/portable/wch/dcd_ch58x_usbfs.c +++ b/src/portable/wch/dcd_ch58x_usbfs.c @@ -84,13 +84,13 @@ static inline void ep_set_both_response(uint32_t base, uint8_t ep, uint8_t tx_re //--------------------------------------------------------------------+ // Private data structures //--------------------------------------------------------------------+ -struct usb_xfer { +typedef struct { bool valid; uint8_t* buffer; size_t len; size_t processed_len; size_t max_size; -}; +} xfer_ctl_t; typedef struct { uint32_t usb_base; @@ -99,7 +99,7 @@ typedef struct { volatile bool ep0_completion_pending; // EP0 XFER_COMPLETE in event queue, not yet processed uint8_t pending_addr; // Address to set in ISR after Set Address status ZLP bool isochronous[EP_MAX][2]; // [ep][dir] - struct usb_xfer xfer[EP_MAX][2]; // [ep][dir] + xfer_ctl_t xfer[EP_MAX][2]; // [ep][dir] // EP0 + EP4 shared buffer: EP0 OUT(64) + EP4 OUT(64) + EP4 IN(64) TU_ATTR_ALIGNED(4) uint8_t ep0_buffer[EP_BUF_SIZE + EP_BUF_SIZE + EP_BUF_SIZE]; @@ -173,7 +173,7 @@ static uint8_t* ep_dma_buffer(dcd_data_t* d, uint8_t ep) { static void update_in(uint8_t rhport, uint8_t ep, bool force, bool in_isr) { dcd_data_t* d = &_dcd_data[rhport]; uint32_t base = d->usb_base; - struct usb_xfer* xfer = &d->xfer[ep][TUSB_DIR_IN]; + xfer_ctl_t* xfer = &d->xfer[ep][TUSB_DIR_IN]; if (xfer->valid) { if (force || xfer->len) { @@ -218,7 +218,7 @@ static void update_in(uint8_t rhport, uint8_t ep, bool force, bool in_isr) { static void update_out(uint8_t rhport, uint8_t ep, size_t rx_len, bool in_isr) { dcd_data_t* d = &_dcd_data[rhport]; uint32_t base = d->usb_base; - struct usb_xfer* xfer = &d->xfer[ep][TUSB_DIR_OUT]; + xfer_ctl_t* xfer = &d->xfer[ep][TUSB_DIR_OUT]; if (xfer->valid) { size_t len = TU_MIN(xfer->max_size, TU_MIN(xfer->len, rx_len)); @@ -426,16 +426,13 @@ void dcd_int_handler(uint8_t rhport) { } void dcd_int_enable(uint8_t rhport) { - // PFIC enable: USB_IRQn=22, USB2_IRQn=23 - volatile uint32_t* pfic_ienr = (volatile uint32_t*) 0xE000E100; - uint8_t irqn = (rhport == 0) ? 22 : 23; - pfic_ienr[irqn / 32] = (1u << (irqn % 32)); + uint8_t irqn = (rhport == 0) ? CH58X_USB_IRQn : CH58X_USB2_IRQn; + CH58X_PFIC_IENR[irqn / 32] = (1u << (irqn % 32)); } void dcd_int_disable(uint8_t rhport) { - volatile uint32_t* pfic_irer = (volatile uint32_t*) 0xE000E180; - uint8_t irqn = (rhport == 0) ? 22 : 23; - pfic_irer[irqn / 32] = (1u << (irqn % 32)); + uint8_t irqn = (rhport == 0) ? CH58X_USB_IRQn : CH58X_USB2_IRQn; + CH58X_PFIC_IRER[irqn / 32] = (1u << (irqn % 32)); __asm volatile ("fence.i"); } @@ -496,7 +493,11 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const* desc_ep) { TU_ASSERT(ep < EP_MAX); d->isochronous[ep][dir] = (desc_ep->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS); - d->xfer[ep][dir].max_size = tu_edpt_packet_size(desc_ep); + uint16_t max_size = tu_edpt_packet_size(desc_ep); + if (max_size > EP_BUF_SIZE) { + max_size = EP_BUF_SIZE; + } + d->xfer[ep][dir].max_size = max_size; if (ep != 0) { dcd_int_disable(rhport); @@ -554,7 +555,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint8_t dir = tu_edpt_dir(ep_addr); dcd_data_t* d = &_dcd_data[rhport]; - struct usb_xfer* xfer = &d->xfer[ep][dir]; + xfer_ctl_t* xfer = &d->xfer[ep][dir]; dcd_int_disable(rhport); @@ -576,7 +577,6 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, if (dir == TUSB_DIR_IN) { update_in(rhport, ep, true, is_isr); } else { - if (d->isochronous[ep][TUSB_DIR_OUT]) { ep_set_rx_response(d->usb_base, ep, CH58X_EP_R_RES_TOUT); } else { diff --git a/src/portable/wch/hcd_ch58x_usbfs.c b/src/portable/wch/hcd_ch58x_usbfs.c index 2b1bd40bc..37dd08539 100644 --- a/src/portable/wch/hcd_ch58x_usbfs.c +++ b/src/portable/wch/hcd_ch58x_usbfs.c @@ -90,7 +90,8 @@ typedef struct { bool nak_pending; } hcd_xfer_t; -static volatile hcd_xfer_t _current_xfer = {}; +// One transfer state per root port (indexed by rhport). +static volatile hcd_xfer_t _current_xfer[2] = {}; //--------------------------------------------------------------------+ // Per-port state @@ -98,6 +99,7 @@ static volatile hcd_xfer_t _current_xfer = {}; typedef struct { uint32_t usb_base; bool int_enabled; + bool int_state_before_reset; } hcd_port_t; static hcd_port_t _port_data[2] = {}; @@ -208,7 +210,7 @@ static bool _hw_start_xfer(uint8_t rhport, uint8_t pid, uint8_t ep_addr, uint8_t LOG_CH58X_HCD("_hw_start_xfer(pid=0x%02x, ep=0x%02x, tog=%d)\r\n", pid, ep_addr, data_toggle); // Workaround: small delay for low-speed devices - bool is_lowspeed = tuh_speed_get(_current_xfer.dev_addr) == TUSB_SPEED_LOW; + bool is_lowspeed = tuh_speed_get(_current_xfer[rhport].dev_addr) == TUSB_SPEED_LOW; if (is_lowspeed) { _delay_loops(60000000 / 1000000 * 40); // ~40us at 60MHz } @@ -276,20 +278,23 @@ static void _xfer_retry(void* param) { LOG_CH58X_HCD("_xfer_retry()\r\n"); hcd_edpt_t* edpt = (hcd_edpt_t*)param; - if (_current_xfer.nak_pending) { - uint8_t rhport = _current_xfer.rhport; - _current_xfer.nak_pending = false; - edpt->is_nak_pending = false; - - uint8_t dev_addr = edpt->dev_addr; - uint8_t ep_addr = edpt->ep_addr; - uint16_t buflen = edpt->buflen; - uint8_t* buf = edpt->buf; - - // Check if endpoint is still valid - hcd_edpt_t* current = _get_edpt(dev_addr, ep_addr); - if (current) { - hcd_edpt_xfer(rhport, dev_addr, ep_addr, buf, buflen); + // Find which rhport this endpoint belongs to by checking both ports + for (uint8_t rp = 0; rp < 2; rp++) { + if (_current_xfer[rp].nak_pending) { + _current_xfer[rp].nak_pending = false; + edpt->is_nak_pending = false; + + uint8_t dev_addr = edpt->dev_addr; + uint8_t ep_addr = edpt->ep_addr; + uint16_t buflen = edpt->buflen; + uint8_t* buf = edpt->buf; + + // Check if endpoint is still valid + hcd_edpt_t* current = _get_edpt(dev_addr, ep_addr); + if (current) { + hcd_edpt_xfer(rp, dev_addr, ep_addr, buf, buflen); + } + break; } } } @@ -303,9 +308,13 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { _port_data[rhport].usb_base = _get_usb_base(rhport); _port_data[rhport].int_enabled = false; - // Clear endpoint records - tu_memclr(_edpt_list, sizeof(_edpt_list)); - _current_xfer = (const hcd_xfer_t){0}; + // Clear endpoint records only on first init to avoid wiping state of the other rhport + static bool _first_init = true; + if (_first_init) { + tu_memclr(_edpt_list, sizeof(_edpt_list)); + _first_init = false; + } + _current_xfer[rhport] = (const hcd_xfer_t){0}; _hw_init_host(rhport, true); @@ -323,17 +332,14 @@ uint32_t hcd_frame_number(uint8_t rhport) { } void hcd_int_enable(uint8_t rhport) { - // PFIC interrupt enable - volatile uint32_t* pfic_ienr = (volatile uint32_t*)0xE000E100; - uint8_t irqn = (rhport == 0) ? 22 : 23; // USB_IRQn or USB2_IRQn - pfic_ienr[irqn / 32] = (1u << (irqn % 32)); + uint8_t irqn = (rhport == 0) ? CH58X_USB_IRQn : CH58X_USB2_IRQn; + CH58X_PFIC_IENR[irqn / 32] = (1u << (irqn % 32)); _port_data[rhport].int_enabled = true; } void hcd_int_disable(uint8_t rhport) { - volatile uint32_t* pfic_irer = (volatile uint32_t*)0xE000E180; - uint8_t irqn = (rhport == 0) ? 22 : 23; - pfic_irer[irqn / 32] = (1u << (irqn % 32)); + uint8_t irqn = (rhport == 0) ? CH58X_USB_IRQn : CH58X_USB2_IRQn; + CH58X_PFIC_IRER[irqn / 32] = (1u << (irqn % 32)); __asm volatile("fence.i"); _port_data[rhport].int_enabled = false; } @@ -347,21 +353,18 @@ bool hcd_port_connect_status(uint8_t rhport) { tusb_speed_t hcd_port_speed_get(uint8_t rhport) { uint32_t base = _port_data[rhport].usb_base; - // DM level high = low-speed device, low = full-speed if (CH58X_USB_MIS_ST(base) & CH58X_UMS_DM_LEVEL) { return TUSB_SPEED_LOW; } return TUSB_SPEED_FULL; } -static bool _int_state_before_reset = false; - void hcd_port_reset(uint8_t rhport) { uint32_t base = _port_data[rhport].usb_base; LOG_CH58X_HCD("hcd_port_reset()\r\n"); - _int_state_before_reset = _port_data[rhport].int_enabled; + _port_data[rhport].int_state_before_reset = _port_data[rhport].int_enabled; hcd_int_disable(rhport); _hw_set_device_addr(rhport, 0x00); @@ -397,7 +400,7 @@ void hcd_port_reset_end(uint8_t rhport) { // Suppress stale detect event CH58X_USB_INT_FG(base) = CH58X_UIF_DETECT; - if (_int_state_before_reset) { + if (_port_data[rhport].int_state_before_reset) { hcd_int_enable(rhport); } } @@ -423,9 +426,9 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const* // Wait for any pending transfer uint32_t t0 = tusb_time_millis_api(); - while (_current_xfer.is_busy) { + while (_current_xfer[rhport].is_busy) { if (tusb_time_millis_api() - t0 > 200) { - _current_xfer.is_busy = false; + _current_xfer[rhport].is_busy = false; break; } } @@ -455,27 +458,27 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, // Wait for any pending transfer (with 200ms timeout to avoid deadlock on disconnect) uint32_t t0 = tusb_time_millis_api(); - while (_current_xfer.is_busy) { + while (_current_xfer[rhport].is_busy) { if (tusb_time_millis_api() - t0 > 200) { - _current_xfer.is_busy = false; + _current_xfer[rhport].is_busy = false; return false; } } - _current_xfer.is_busy = true; + _current_xfer[rhport].is_busy = true; hcd_edpt_t* edpt = _get_edpt(dev_addr, ep_addr); TU_ASSERT(edpt != NULL); _hw_set_addr_speed(rhport, dev_addr); - _current_xfer.rhport = rhport; - _current_xfer.dev_addr = dev_addr; - _current_xfer.ep_addr = ep_addr; - _current_xfer.buffer = buffer; - _current_xfer.bufferlen = buflen; - _current_xfer.start_ms = tusb_time_millis_api(); - _current_xfer.xferred_len = 0; - _current_xfer.nak_pending = false; + _current_xfer[rhport].rhport = rhport; + _current_xfer[rhport].dev_addr = dev_addr; + _current_xfer[rhport].ep_addr = ep_addr; + _current_xfer[rhport].buffer = buffer; + _current_xfer[rhport].bufferlen = buflen; + _current_xfer[rhport].start_ms = tusb_time_millis_api(); + _current_xfer[rhport].xferred_len = 0; + _current_xfer[rhport].nak_pending = false; if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN) { // IN transfer: host receives data @@ -503,13 +506,13 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet // Wait for any pending transfer uint32_t t0 = tusb_time_millis_api(); - while (_current_xfer.is_busy) { + while (_current_xfer[rhport].is_busy) { if (tusb_time_millis_api() - t0 > 200) { - _current_xfer.is_busy = false; + _current_xfer[rhport].is_busy = false; return false; } } - _current_xfer.is_busy = true; + _current_xfer[rhport].is_busy = true; _hw_set_addr_speed(rhport, dev_addr); @@ -525,14 +528,14 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet memcpy(_tx_buf[rhport], setup_packet, 8); CH58X_UH_TX_LEN(base) = 8; - _current_xfer.rhport = rhport; - _current_xfer.dev_addr = dev_addr; - _current_xfer.ep_addr = 0x00; // SETUP always targets EP0 OUT - _current_xfer.start_ms = tusb_time_millis_api(); - _current_xfer.buffer = _tx_buf[rhport]; - _current_xfer.bufferlen = 8; - _current_xfer.xferred_len = 0; - _current_xfer.nak_pending = false; + _current_xfer[rhport].rhport = rhport; + _current_xfer[rhport].dev_addr = dev_addr; + _current_xfer[rhport].ep_addr = 0x00; // SETUP always targets EP0 OUT + _current_xfer[rhport].start_ms = tusb_time_millis_api(); + _current_xfer[rhport].buffer = _tx_buf[rhport]; + _current_xfer[rhport].bufferlen = 8; + _current_xfer[rhport].xferred_len = 0; + _current_xfer[rhport].nak_pending = false; _hw_start_xfer(rhport, CH58X_USB_PID_SETUP, 0, 0); @@ -569,8 +572,8 @@ void hcd_int_handler(uint8_t rhport, bool in_isr) { } else { // Stop any ongoing hardware transfer before reporting removal CH58X_UH_EP_PID(base) = 0x00; - _current_xfer.is_busy = false; - _current_xfer.nak_pending = false; + _current_xfer[rhport].is_busy = false; + _current_xfer[rhport].nak_pending = false; hcd_event_device_remove(rhport, in_isr); } return; @@ -603,7 +606,7 @@ void hcd_int_handler(uint8_t rhport, bool in_isr) { if (edpt == NULL) { // Unknown endpoint, discard LOG_CH58X_HCD("hcd_int: unknown edpt dev=0x%02x ep=0x%02x\r\n", dev_addr, ep_addr); - _current_xfer.is_busy = false; + _current_xfer[rhport].is_busy = false; CH58X_USB_INT_FG(base) = CH58X_UIF_TRANSFER; return; } @@ -616,19 +619,19 @@ void hcd_int_handler(uint8_t rhport, bool in_isr) { case CH58X_USB_PID_SETUP: case CH58X_USB_PID_OUT: { uint8_t tx_len = CH58X_UH_TX_LEN(base); - _current_xfer.bufferlen -= tx_len; - _current_xfer.xferred_len += tx_len; + _current_xfer[rhport].bufferlen -= tx_len; + _current_xfer[rhport].xferred_len += tx_len; - if (_current_xfer.bufferlen == 0) { - LOG_CH58X_HCD("OUT/SETUP complete, %d bytes\r\n", _current_xfer.xferred_len); - _current_xfer.is_busy = false; + if (_current_xfer[rhport].bufferlen == 0) { + LOG_CH58X_HCD("OUT/SETUP complete, %d bytes\r\n", _current_xfer[rhport].xferred_len); + _current_xfer[rhport].is_busy = false; hcd_event_xfer_complete(dev_addr, ep_addr, - _current_xfer.xferred_len, XFER_RESULT_SUCCESS, in_isr); + _current_xfer[rhport].xferred_len, XFER_RESULT_SUCCESS, in_isr); } else { // Multi-packet OUT: send next chunk - _current_xfer.buffer += tx_len; - uint16_t copylen = TU_MIN(edpt->max_packet_size, _current_xfer.bufferlen); - memcpy(_tx_buf[rhport], _current_xfer.buffer, copylen); + _current_xfer[rhport].buffer += tx_len; + uint16_t copylen = TU_MIN(edpt->max_packet_size, _current_xfer[rhport].bufferlen); + memcpy(_tx_buf[rhport], _current_xfer[rhport].buffer, copylen); CH58X_UH_TX_LEN(base) = (uint8_t)copylen; _hw_start_xfer(rhport, CH58X_USB_PID_OUT, ep_addr, edpt->data_toggle); } @@ -637,18 +640,18 @@ void hcd_int_handler(uint8_t rhport, bool in_isr) { case CH58X_USB_PID_IN: { uint8_t rx_len = CH58X_USB_RX_LEN(base); - _current_xfer.xferred_len += rx_len; - uint16_t xferred = _current_xfer.xferred_len; + _current_xfer[rhport].xferred_len += rx_len; + uint16_t xferred = _current_xfer[rhport].xferred_len; - if (rx_len > 0 && _current_xfer.buffer != NULL) { - memcpy(_current_xfer.buffer, _rx_buf[rhport], rx_len); - _current_xfer.buffer += rx_len; + if (rx_len > 0 && _current_xfer[rhport].buffer != NULL) { + memcpy(_current_xfer[rhport].buffer, _rx_buf[rhport], rx_len); + _current_xfer[rhport].buffer += rx_len; } - if ((rx_len < edpt->max_packet_size) || (xferred == _current_xfer.bufferlen)) { + if ((rx_len < edpt->max_packet_size) || (xferred == _current_xfer[rhport].bufferlen)) { // Short packet or transfer complete LOG_CH58X_HCD("IN complete, %d bytes\r\n", xferred); - _current_xfer.is_busy = false; + _current_xfer[rhport].is_busy = false; hcd_event_xfer_complete(dev_addr, ep_addr, xferred, XFER_RESULT_SUCCESS, in_isr); } else { @@ -660,7 +663,7 @@ void hcd_int_handler(uint8_t rhport, bool in_isr) { default: { LOG_CH58X_HCD("unexpected PID 0x%02x\r\n", request_pid); - _current_xfer.is_busy = false; + _current_xfer[rhport].is_busy = false; hcd_event_xfer_complete(dev_addr, ep_addr, 0, XFER_RESULT_FAILED, in_isr); break; } @@ -670,36 +673,42 @@ void hcd_int_handler(uint8_t rhport, bool in_isr) { if (response_pid == CH58X_USB_PID_STALL) { LOG_CH58X_HCD("STALL response\r\n"); edpt->data_toggle = 0; - _current_xfer.is_busy = false; + _current_xfer[rhport].is_busy = false; hcd_event_xfer_complete(dev_addr, ep_addr, 0, XFER_RESULT_STALLED, in_isr); } else if (response_pid == CH58X_USB_PID_NAK) { LOG_CH58X_HCD("NAK response\r\n"); - // NAK: schedule retry via deferred callback for all endpoint types - // This avoids tight polling loops and allows other tasks to run - _current_xfer.is_busy = false; - _current_xfer.nak_pending = true; - - edpt->is_nak_pending = true; - edpt->buflen = _current_xfer.bufferlen; - edpt->buf = _current_xfer.buffer; - - hcd_event_t event = { - .rhport = rhport, - .dev_addr = dev_addr, - .event_id = USBH_EVENT_FUNC_CALL, - .func_call = { - .func = _xfer_retry, - .param = edpt - } - }; - hcd_event_handler(&event, in_isr); + // For interrupt endpoints, treat NAK as a successful 0-byte poll so + // that upper layers can reschedule based on the endpoint interval. + if (edpt->xfer_type == TUSB_XFER_INTERRUPT) { + _current_xfer[rhport].is_busy = false; + hcd_event_xfer_complete(dev_addr, ep_addr, 0, XFER_RESULT_SUCCESS, in_isr); + } else { + // For non-interrupt endpoints, schedule retry via deferred callback. + _current_xfer[rhport].is_busy = false; + _current_xfer[rhport].nak_pending = true; + + edpt->is_nak_pending = true; + edpt->buflen = _current_xfer[rhport].bufferlen; + edpt->buf = _current_xfer[rhport].buffer; + + hcd_event_t event = { + .rhport = rhport, + .dev_addr = dev_addr, + .event_id = USBH_EVENT_FUNC_CALL, + .func_call = { + .func = _xfer_retry, + .param = edpt + } + }; + hcd_event_handler(&event, in_isr); + } } else if (response_pid == CH58X_USB_PID_DATA0 || response_pid == CH58X_USB_PID_DATA1) { LOG_CH58X_HCD("toggle mismatch, DATA0/1 rx_len=%d\r\n", CH58X_USB_RX_LEN(base)); - _current_xfer.is_busy = false; + _current_xfer[rhport].is_busy = false; hcd_event_xfer_complete(dev_addr, ep_addr, 0, XFER_RESULT_FAILED, in_isr); } else { LOG_CH58X_HCD("unexpected response 0x%02x\r\n", response_pid); - _current_xfer.is_busy = false; + _current_xfer[rhport].is_busy = false; hcd_event_xfer_complete(dev_addr, ep_addr, 0, XFER_RESULT_FAILED, in_isr); } } -- cgit v1.3.1 From 88196051e8bd89b282fda8d395f4c333425a91b1 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 18 Mar 2026 19:04:13 +0700 Subject: fix bugs in fsdev hcd, dcd and midi host stream write - hcd_edpt_clear_stall: use ep_addr instead of hardcoded 0 (control endpoint) - hcd: add TUP_USBIP_FSDEV_DRD define for MCUs with host support (C0, G0, H5, U3, U5) and use it in hcd compile guard instead of enumerating MCUs - dcd_edpt_close_all: use FSDEV_EP_COUNT instead of CFG_TUD_ENDPPOINT_MAX for PMA btable offset to match handle_bus_reset - midi host tuh_midi_stream_write: add missing cable_num to system messages, SysEx, and real-time MIDI packets. Add 0xF mask for SysEx CIN checks. Aligns with midi_device.c tud_midi_n_stream_write implementation. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/class/midi/midi_host.c | 11 ++++++----- src/common/tusb_mcu.h | 5 +++++ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 2 +- src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c | 7 ++----- 4 files changed, 14 insertions(+), 11 deletions(-) (limited to 'src/portable') diff --git a/src/class/midi/midi_host.c b/src/class/midi/midi_host.c index 8d59dfc66..a53546404 100644 --- a/src/class/midi/midi_host.c +++ b/src/class/midi/midi_host.c @@ -461,7 +461,7 @@ uint32_t tuh_midi_stream_write(uint8_t idx, uint8_t cable_num, uint8_t const *bu if (data >= MIDI_STATUS_SYSREAL_TIMING_CLOCK) { // real-time messages need to be sent right away midi_driver_stream_t streamrt; - streamrt.buffer[0] = MIDI_CIN_SYSEX_END_1BYTE; + streamrt.buffer[0] = (uint8_t)((cable_num << 4) | MIDI_CIN_SYSEX_END_1BYTE); streamrt.buffer[1] = data; streamrt.index = 2; streamrt.total = 2; @@ -476,9 +476,9 @@ uint32_t tuh_midi_stream_write(uint8_t idx, uint8_t cable_num, uint8_t const *bu stream->buffer[1] = data; // Check to see if we're still in a SysEx transmit. - if (stream->buffer[0] == MIDI_CIN_SYSEX_START) { + if ((stream->buffer[0] & 0xF) == MIDI_CIN_SYSEX_START) { if (data == MIDI_STATUS_SYSEX_END) { - stream->buffer[0] = MIDI_CIN_SYSEX_END_1BYTE; + stream->buffer[0] = (uint8_t)((cable_num << 4) | MIDI_CIN_SYSEX_END_1BYTE); stream->total = 2; } else { stream->total = 4; @@ -506,6 +506,7 @@ uint32_t tuh_midi_stream_write(uint8_t idx, uint8_t cable_num, uint8_t const *bu stream->buffer[0] = MIDI_CIN_SYSEX_END_1BYTE; stream->total = 2; } + stream->buffer[0] |= (uint8_t)(cable_num << 4); } else { // Pack individual bytes if we don't support packing them into words. stream->buffer[0] = (uint8_t) (cable_num << 4 | 0xf); @@ -520,8 +521,8 @@ uint32_t tuh_midi_stream_write(uint8_t idx, uint8_t cable_num, uint8_t const *bu stream->buffer[stream->index] = data; stream->index++; // See if this byte ends a SysEx. - if (stream->buffer[0] == MIDI_CIN_SYSEX_START && data == MIDI_STATUS_SYSEX_END) { - stream->buffer[0] = MIDI_CIN_SYSEX_START + (stream->index - 1); + if ((stream->buffer[0] & 0xF) == MIDI_CIN_SYSEX_START && data == MIDI_STATUS_SYSEX_END) { + stream->buffer[0] = (uint8_t)((cable_num << 4) | (MIDI_CIN_SYSEX_START + (stream->index - 1))); stream->total = stream->index; } } diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index 34dd6af8d..b12a3177e 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -202,6 +202,7 @@ #elif TU_CHECK_MCU(OPT_MCU_STM32C0) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 + #define TUP_USBIP_FSDEV_DRD #define CFG_TUSB_FSDEV_PMA_SIZE 2048u #elif TU_CHECK_MCU(OPT_MCU_STM32F0) @@ -278,6 +279,7 @@ #elif TU_CHECK_MCU(OPT_MCU_STM32G0) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 + #define TUP_USBIP_FSDEV_DRD #define CFG_TUSB_FSDEV_PMA_SIZE 2048u #elif TU_CHECK_MCU(OPT_MCU_STM32G4) @@ -293,6 +295,7 @@ #elif TU_CHECK_MCU(OPT_MCU_STM32H5) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 + #define TUP_USBIP_FSDEV_DRD #define CFG_TUSB_FSDEV_PMA_SIZE 2048u #elif TU_CHECK_MCU(OPT_MCU_STM32H7) @@ -366,6 +369,7 @@ #elif TU_CHECK_MCU(OPT_MCU_STM32U3) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 + #define TUP_USBIP_FSDEV_DRD #define CFG_TUSB_FSDEV_PMA_SIZE 2048u #elif TU_CHECK_MCU(OPT_MCU_STM32U5) @@ -373,6 +377,7 @@ #if defined(STM32U535xx) || defined(STM32U545xx) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 + #define TUP_USBIP_FSDEV_DRD #define CFG_TUSB_FSDEV_PMA_SIZE 2048u #else #define TUP_USBIP_DWC2 diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 13d1a6cb4..8b4719b21 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -612,7 +612,7 @@ void dcd_edpt_close_all(uint8_t rhport) { dcd_int_enable(rhport); // Reset PMA allocation - ep_buf_ptr = FSDEV_BTABLE_BASE + 8 * CFG_TUD_ENDPPOINT_MAX + 2 * CFG_TUD_ENDPOINT0_SIZE; + ep_buf_ptr = FSDEV_BTABLE_BASE + 8 * FSDEV_EP_COUNT + 2 * CFG_TUD_ENDPOINT0_SIZE; } bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { diff --git a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c index dd86b052a..18685dbdc 100644 --- a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c @@ -38,8 +38,7 @@ #include "tusb_option.h" -#if CFG_TUH_ENABLED && defined(TUP_USBIP_FSDEV) && \ - TU_CHECK_MCU(OPT_MCU_STM32C0, OPT_MCU_STM32G0, OPT_MCU_STM32H5, OPT_MCU_STM32U5) +#if CFG_TUH_ENABLED && defined(TUP_USBIP_FSDEV) && defined(TUP_USBIP_FSDEV_DRD) #include "host/hcd.h" #include "host/usbh.h" @@ -672,10 +671,8 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet // 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; - uint8_t const ep_id = endpoint_find(dev_addr, 0); + uint8_t const ep_id = endpoint_find(dev_addr, ep_addr); TU_ASSERT(ep_id != TUSB_INDEX_INVALID_8); hcd_endpoint_t *edpt = &_hcd_data.edpt[ep_id]; -- cgit v1.3.1 From 9b17d55c91744ace59ad85dbb7b4ae8c6aedfb2c Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 12 Feb 2026 20:28:40 +0700 Subject: rp2 disable hwfifo --- src/portable/raspberrypi/rp2040/dcd_rp2040.c | 2 ++ src/portable/raspberrypi/rp2040/rp2040_usb.c | 18 +++++++++++++++--- src/tusb_option.h | 2 +- 3 files changed, 18 insertions(+), 4 deletions(-) (limited to 'src/portable') diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index 240e6c727..ca0e24e96 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -505,6 +505,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to return true; } +#if CFG_TUD_EDPT_DEDICATED_HWFIFO bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t *ff, uint16_t total_bytes, bool is_isr) { (void)rhport; (void)is_isr; @@ -512,6 +513,7 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t *ff, uint16_t hw_endpoint_xfer_start(ep, NULL, ff, total_bytes); return true; } +#endif void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { (void)rhport; diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index 3b65f57a4..ca83acc6b 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -53,6 +53,7 @@ static void unaligned_memcpy(uint8_t *dst, const uint8_t *src, size_t n) { } } +#if CFG_TUD_EDPT_DEDICATED_HWFIFO void tu_hwfifo_write(volatile void *hwfifo, const uint8_t *src, uint16_t len, const tu_hwfifo_access_t *access_mode) { (void)access_mode; unaligned_memcpy((uint8_t *)(uintptr_t)hwfifo, src, len); @@ -62,6 +63,7 @@ void tu_hwfifo_read(const volatile void *hwfifo, uint8_t *dest, uint16_t len, co (void)access_mode; unaligned_memcpy(dest, (const uint8_t *)(uintptr_t)hwfifo, len); } +#endif void rp2usb_init(void) { // Reset usb controller @@ -138,10 +140,13 @@ static uint32_t __tusb_irq_path_func(prepare_ep_buffer)(struct hw_endpoint *ep, if (buflen) { // Copy data from user buffer/fifo to hw buffer uint8_t *hw_buf = ep->hw_data_buf + buf_id * 64; + #if CFG_TUD_EDPT_DEDICATED_HWFIFO if (ep->is_xfer_fifo) { // not in sram, may mess up timing with E15 workaround tu_hwfifo_write_from_fifo(hw_buf, ep->user_fifo, buflen, NULL); - } else { + } else + #endif + { unaligned_memcpy(hw_buf, ep->user_buf, buflen); ep->user_buf += buflen; } @@ -227,6 +232,7 @@ void __tusb_irq_path_func(hw_endpoint_start_next_buffer)(struct hw_endpoint* ep) } void hw_endpoint_xfer_start(struct hw_endpoint *ep, uint8_t *buffer, tu_fifo_t *ff, uint16_t total_len) { + (void) ff; hw_endpoint_lock_update(ep, 1); if (ep->active) { @@ -240,10 +246,13 @@ void hw_endpoint_xfer_start(struct hw_endpoint *ep, uint8_t *buffer, tu_fifo_t * ep->xferred_len = 0; ep->active = true; +#if CFG_TUD_EDPT_DEDICATED_HWFIFO if (ff != NULL) { ep->user_fifo = ff; ep->is_xfer_fifo = true; - } else { + } else +#endif + { ep->user_buf = buffer; ep->is_xfer_fifo = false; } @@ -284,10 +293,13 @@ static uint16_t __tusb_irq_path_func(sync_ep_buffer)(hw_endpoint_t *ep, io_rw_32 assert(buf_ctrl & USB_BUF_CTRL_FULL); uint8_t *hw_buf = ep->hw_data_buf + buf_id * 64; + #if CFG_TUD_EDPT_DEDICATED_HWFIFO if (ep->is_xfer_fifo) { // not in sram, may mess up timing with E15 workaround tu_hwfifo_read_to_fifo(hw_buf, ep->user_fifo, xferred_bytes, NULL); - } else { + } else + #endif + { unaligned_memcpy(ep->user_buf, hw_buf, xferred_bytes); ep->user_buf += xferred_bytes; } diff --git a/src/tusb_option.h b/src/tusb_option.h index 9eb8ee533..74a556605 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -381,7 +381,7 @@ #endif #if (CFG_TUSB_MCU == OPT_MCU_RP2040) && !CFG_TUD_RPI_PIO_USB - #define CFG_TUD_EDPT_DEDICATED_HWFIFO 1 + #define CFG_TUD_EDPT_DEDICATED_HWFIFO 0 #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE 1 #define CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE 1 #define CFG_TUSB_FIFO_HWFIFO_CUSTOM_WRITE -- cgit v1.3.1 From 0c6fa9bd7f4d2619a538fcfd866ef6150fa2adeb Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 19 Mar 2026 22:59:22 +0700 Subject: Add EPX transfer scheduling when hcd_edpt_xfer() is called while epx is busy --- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 105 +++++++++++++++++++++++++-- src/portable/raspberrypi/rp2040/rp2040_usb.c | 12 ++- test/hil/hil_test.py | 11 ++- 3 files changed, 116 insertions(+), 12 deletions(-) (limited to 'src/portable') diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index 0a8dbe11a..b5c4422e2 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -106,6 +106,9 @@ TU_ATTR_ALWAYS_INLINE static inline bool need_pre(uint8_t dev_addr) { return hcd_port_speed_get(0) != tuh_speed_get(dev_addr); } +// forward declaration +static void __tusb_irq_path_func(edpt_schedule_next)(void); + static void __tusb_irq_path_func(hw_xfer_complete)(hw_endpoint_t *ep, xfer_result_t xfer_result) { // Mark transfer as done before we tell the tinyusb stack uint8_t dev_addr = ep->dev_addr; @@ -113,6 +116,11 @@ static void __tusb_irq_path_func(hw_xfer_complete)(hw_endpoint_t *ep, xfer_resul uint xferred_len = ep->xferred_len; hw_endpoint_reset_transfer(ep); hcd_event_xfer_complete(dev_addr, ep_addr, xferred_len, xfer_result, true); + + // Schedule next pending EPX transfer (only for non-interrupt endpoints) + if (ep == epx) { + edpt_schedule_next(); + } } static void __tusb_irq_path_func(handle_hwbuf_status_bit)(hw_endpoint_t *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg) { @@ -169,8 +177,7 @@ static void __tusb_irq_path_func(handle_hwbuf_status)(void) { } // All non-interrupt endpoints use shared EPX. -// static void edpt_scheduler(void) { -// } +// Forward declared above hw_xfer_complete, defined after edpt_xfer below. static void __tusb_irq_path_func(hcd_rp2040_irq)(void) { const uint32_t status = usb_hw->ints; @@ -206,7 +213,7 @@ static void __tusb_irq_path_func(hcd_rp2040_irq)(void) { if (status & USB_INTS_TRANS_COMPLETE_BITS) { usb_hw_clear->sie_status = USB_SIE_STATUS_TRANS_COMPLETE_BITS; - // only handle setup packet + // only handle a setup packet if (usb_hw->sie_ctrl & USB_SIE_CTRL_SEND_SETUP_BITS) { epx->xferred_len = 8; hw_xfer_complete(epx, XFER_RESULT_SUCCESS); @@ -215,6 +222,30 @@ static void __tusb_irq_path_func(hcd_rp2040_irq)(void) { } } + // if (status & USB_INTS_EP_STALL_NAK_BITS) { + // const uint32_t ep_stall_nak = usb_hw->ep_status_stall_nak; + // usb_hw->ep_status_stall_nak = ep_stall_nak; // clear by writing back (WC) + // + // // Preempt non-control EPX bulk transfer when a different ep is pending + // if (epx->active && tu_edpt_number(epx->ep_addr) != 0) { + // for (uint i = 0; i < TU_ARRAY_SIZE(ep_pool); i++) { + // hw_endpoint_t *ep = &ep_pool[i]; + // if (ep->pending && ep != epx) { + // // Stop current transaction + // usb_hw_set->sie_ctrl = USB_SIE_CTRL_STOP_TRANS_BITS; + // + // // Mark current EPX as pending to resume later + // epx->pending = 1; + // epx->active = false; + // + // // Start the next pending transfer + // edpt_schedule_next(); + // break; + // } + // } + // } + // } + if (status & USB_INTS_ERROR_RX_TIMEOUT_BITS) { usb_hw_clear->sie_status = USB_SIE_STATUS_RX_TIMEOUT_BITS; } @@ -250,7 +281,7 @@ static void hw_endpoint_init(hw_endpoint_t *ep, uint8_t dev_addr, const tusb_des // from 15 interrupt endpoints pool uint8_t int_idx; for (int_idx = 0; int_idx < USB_HOST_INTERRUPT_ENDPOINTS; int_idx++) { - if (!tu_bit_test(usb_hw_set->int_ep_ctrl, 1 + int_idx)) { + if (!tu_bit_test(usb_hw->int_ep_ctrl, 1 + int_idx)) { ep->interrupt_num = int_idx + 1; break; } @@ -313,6 +344,7 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { USB_INTE_HOST_RESUME_BITS | USB_INTE_STALL_BITS | USB_INTE_TRANS_COMPLETE_BITS | + // USB_INTE_EP_STALL_NAK_BITS | USB_INTE_ERROR_RX_TIMEOUT_BITS | USB_INTE_ERROR_DATA_SEQ_BITS ; @@ -369,6 +401,8 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr) { for (size_t i = 0; i < TU_ARRAY_SIZE(ep_pool); i++) { hw_endpoint_t *ep = &ep_pool[i]; if (ep->dev_addr == dev_addr && ep->max_packet_size > 0) { + ep->pending = 0; // clear any pending transfer + if (ep->interrupt_num) { // disable interrupt endpoint usb_hw_clear->int_ep_ctrl = 1u << ep->interrupt_num; @@ -442,10 +476,18 @@ static void edpt_xfer(hw_endpoint_t *ep, uint8_t *buffer, tu_fifo_t *ff, uint16_ const uint8_t ep_num = tu_edpt_number(ep->ep_addr); const tusb_dir_t ep_dir = tu_edpt_dir(ep->ep_addr); + // RP2040-E4: USB host writes status to upper half of buffer control in single buffered mode. + // The buffer selector toggles even in single-buffered mode, so the previous transfer's status + // may have been written to BUF1 half, leaving BUF0 with stale AVAILABLE bit. Clear it here. +#if defined(PICO_RP2040) && PICO_RP2040 == 1 + usbh_dpram->epx_buf_ctrl = 0; +#endif + // ep control const uint32_t dpram_offset = hw_data_offset(ep->dpram_buf); const uint32_t ep_ctrl = EP_CTRL_ENABLE_BITS | EP_CTRL_INTERRUPT_PER_BUFFER | - ((uint32_t)ep->transfer_type << EP_CTRL_BUFFER_TYPE_LSB) | dpram_offset; + ((uint32_t)ep->transfer_type << EP_CTRL_BUFFER_TYPE_LSB) | dpram_offset /*| + (1u << 16)*/; // INTERRUPT_ON_NAK usbh_dpram->epx_ctrl = ep_ctrl; io_rw_32 *ep_reg = &usbh_dpram->epx_ctrl; @@ -464,6 +506,40 @@ static void edpt_xfer(hw_endpoint_t *ep, uint8_t *buffer, tu_fifo_t *ff, uint16_ } } +// Schedule next pending EPX transfer from ISR context +static void __tusb_irq_path_func(edpt_schedule_next)(void) { + // EPX may already be active if the completion callback started a new transfer + if (epx->active) return; + + for (uint i = 0; i < TU_ARRAY_SIZE(ep_pool); i++) { + hw_endpoint_t *ep = &ep_pool[i]; + if (ep->pending == 0) continue; + + if (ep->pending == 2) { + // Pending setup: DPRAM already has the setup packet + ep->ep_addr = 0; + ep->remaining_len = 8; + ep->xferred_len = 0; + ep->active = true; + ep->pending = 0; + + epx = ep; + usb_hw->dev_addr_ctrl = ep->dev_addr; + + const uint32_t sie_ctrl = USB_SIE_CTRL_SEND_SETUP_BITS | + (ep->need_pre ? USB_SIE_CTRL_PREAMBLE_EN_BITS : 0); + sie_start_xfer(sie_ctrl); + } else { + // Pending data transfer: preserve partial progress from preemption + uint16_t prev_xferred = ep->xferred_len; + ep->pending = 0; + edpt_xfer(ep, ep->user_buf, NULL, ep->remaining_len); + epx->xferred_len += prev_xferred; // restore partial progress + } + return; // start only one transfer + } +} + bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *buffer, uint16_t buflen) { (void)rhport; @@ -476,6 +552,14 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *b ep->next_pid = 1; // data and status stage start with DATA1 } + // If EPX is busy with another transfer, mark as pending + if (ep->transfer_type != TUSB_XFER_INTERRUPT && epx->active) { + ep->user_buf = buffer; + ep->remaining_len = buflen; + ep->pending = 1; + return true; + } + edpt_xfer(ep, buffer, NULL, buflen); return true; @@ -492,7 +576,7 @@ 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, const uint8_t setup_packet[8]) { (void)rhport; - // Copy data into setup packet buffer + // Copy data into setup packet buffer (usbh only schedules one setup at a time) for (uint8_t i = 0; i < 8; i++) { usbh_dpram->setup_packet[i] = setup_packet[i]; } @@ -500,7 +584,14 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, const uint8_t setup_packet hw_endpoint_t *ep = edpt_find(dev_addr, 0x00); TU_ASSERT(ep); - ep->ep_addr = 0; // setup is OUT + ep->ep_addr = 0; // setup is OUT + + // If EPX is busy, mark as pending setup (DPRAM already has the packet) + if (epx->active) { + ep->pending = 2; + return true; + } + ep->remaining_len = 8; ep->xferred_len = 0; ep->active = true; diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index f2d4800e1..0f1075eda 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -110,7 +110,17 @@ void __tusb_irq_path_func(hwbuf_ctrl_update)(io_rw_32 *buf_ctrl_reg, uint32_t an value |= or_mask; if (or_mask & USB_BUF_CTRL_AVAIL) { if (buf_ctrl & USB_BUF_CTRL_AVAIL) { - panic("buf_ctrl @ 0x%lX already available", (uintptr_t)buf_ctrl_reg); + if (is_host) { +#if defined(PICO_RP2040) && PICO_RP2040 == 1 + // RP2040-E4: host buffer selector toggles in single-buffered mode, causing status + // to be written to BUF1 half and leaving stale AVAILABLE in BUF0 half. Clear it. + *buf_ctrl_reg = 0; +#else + panic("buf_ctrl @ 0x%lX already available (host)", (uintptr_t)buf_ctrl_reg); +#endif + } else { + panic("buf_ctrl @ 0x%lX already available", (uintptr_t)buf_ctrl_reg); + } } *buf_ctrl_reg = value & ~USB_BUF_CTRL_AVAIL; diff --git a/test/hil/hil_test.py b/test/hil/hil_test.py index 41e9fad88..b3458e59d 100755 --- a/test/hil/hil_test.py +++ b/test/hil/hil_test.py @@ -475,7 +475,7 @@ def test_host_cdc_msc_hid(board): cdc_devs = [d for d in dev_attached if d.get('is_cdc')] msc_devs = [d for d in dev_attached if d.get('is_msc')] if not cdc_devs and not msc_devs: - return + return 'skipped' port = get_serial_dev(flasher["uid"], None, None, 0) ser = open_serial_dev(port) @@ -568,7 +568,7 @@ def test_host_msc_file_explorer(board): flasher = board['flasher'] msc_devs = [d for d in board['tests'].get('dev_attached', []) if d.get('is_msc')] if not msc_devs: - return + return 'skipped' port = get_serial_dev(flasher["uid"], None, None, 0) ser = open_serial_dev(port) @@ -1113,8 +1113,11 @@ def test_example(board, f1, example): ret = globals()[f'flash_{board["flasher"]["name"].lower()}'](board, fw_name) if ret.returncode == 0: try: - globals()[f'test_{example.replace("/", "_")}'](board) - print(' OK', end='') + tret = globals()[f'test_{example.replace("/", "_")}'](board) + if tret == 'skipped': + print(f' {STATUS_SKIPPED}', end='') + else: + print(' OK', end='') break except Exception as e: if i == max_rety - 1: -- cgit v1.3.1 From f7d1c10b73e2f549d9727b4a8a11c1ca58906881 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 20 Mar 2026 00:50:55 +0700 Subject: Add support for EPX preemption on RP2350 during NAK conditions --- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 112 +++++++++++++++++++++------ 1 file changed, 88 insertions(+), 24 deletions(-) (limited to 'src/portable') diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index b5c4422e2..f3153d0e9 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -108,6 +108,8 @@ TU_ATTR_ALWAYS_INLINE static inline bool need_pre(uint8_t dev_addr) { // forward declaration static void __tusb_irq_path_func(edpt_schedule_next)(void); +TU_ATTR_ALWAYS_INLINE static inline void sie_start_xfer(uint32_t value); +static void edpt_xfer(hw_endpoint_t *ep, uint8_t *buffer, tu_fifo_t *ff, uint16_t total_len); static void __tusb_irq_path_func(hw_xfer_complete)(hw_endpoint_t *ep, xfer_result_t xfer_result) { // Mark transfer as done before we tell the tinyusb stack @@ -222,29 +224,79 @@ static void __tusb_irq_path_func(hcd_rp2040_irq)(void) { } } - // if (status & USB_INTS_EP_STALL_NAK_BITS) { - // const uint32_t ep_stall_nak = usb_hw->ep_status_stall_nak; - // usb_hw->ep_status_stall_nak = ep_stall_nak; // clear by writing back (WC) - // - // // Preempt non-control EPX bulk transfer when a different ep is pending - // if (epx->active && tu_edpt_number(epx->ep_addr) != 0) { - // for (uint i = 0; i < TU_ARRAY_SIZE(ep_pool); i++) { - // hw_endpoint_t *ep = &ep_pool[i]; - // if (ep->pending && ep != epx) { - // // Stop current transaction - // usb_hw_set->sie_ctrl = USB_SIE_CTRL_STOP_TRANS_BITS; - // - // // Mark current EPX as pending to resume later - // epx->pending = 1; - // epx->active = false; - // - // // Start the next pending transfer - // edpt_schedule_next(); - // break; - // } - // } - // } - // } +#if defined(PICO_RP2350) && PICO_RP2350 == 1 + if (status & USB_INTS_EPX_STOPPED_ON_NAK_BITS) { + // RP2350: EPX transfer stopped due to NAK from device. + // Clear EPX_STOPPED_ON_NAK status (WC) + usb_hw->nak_poll |= USB_NAK_POLL_EPX_STOPPED_ON_NAK_BITS; + + bool preempted = false; + + // Only preempt non-control endpoints + if (epx->active && tu_edpt_number(epx->ep_addr) != 0) { + // Find the next pending transfer (different from the current epx) + for (uint i = 0; i < TU_ARRAY_SIZE(ep_pool); i++) { + hw_endpoint_t *ep = &ep_pool[i]; + if (ep->pending && ep != epx) { + // NAK means no data transferred. Restore remaining_len from buffer control + // so edpt_schedule_next can properly resume this transfer later. + const uint16_t buf0_len = usbh_dpram->epx_buf_ctrl & USB_BUF_CTRL_LEN_MASK; + epx->remaining_len = (uint16_t)(epx->remaining_len + buf0_len); + epx->next_pid ^= 1u; // undo PID toggle from hwbuf_prepare + if (tu_edpt_dir(epx->ep_addr) == TUSB_DIR_OUT) { + epx->user_buf -= buf0_len; // undo buffer advance for OUT + } + + // Mark current EPX as pending to resume later + epx->pending = 1; + epx->active = false; + + // Clear EPX buffer control - AVAILABLE is still set from the NAK'd transfer + usbh_dpram->epx_buf_ctrl = 0; + + // Start the found pending transfer directly + if (ep->pending == 2) { + // Pending setup: DPRAM already has the setup packet + ep->ep_addr = 0; + ep->remaining_len = 8; + ep->xferred_len = 0; + ep->active = true; + ep->pending = 0; + + epx = ep; + usb_hw->dev_addr_ctrl = ep->dev_addr; + + const uint32_t sc = USB_SIE_CTRL_SEND_SETUP_BITS | + (ep->need_pre ? USB_SIE_CTRL_PREAMBLE_EN_BITS : 0); + sie_start_xfer(sc); + } else { + // Pending data transfer: preserve partial progress + uint16_t prev_xferred = ep->xferred_len; + ep->pending = 0; + edpt_xfer(ep, ep->user_buf, NULL, ep->remaining_len); + epx->xferred_len += prev_xferred; + } + + preempted = true; + break; + } + } + } + + if (!preempted && epx->active) { + // No preemption needed: disable stop-on-NAK and restart the transaction. + // Buffer control still has AVAILABLE set, just re-trigger START_TRANS. + uint32_t nak_poll = usb_hw->nak_poll; + nak_poll &= ~USB_NAK_POLL_STOP_EPX_ON_NAK_BITS; + usb_hw->nak_poll = nak_poll; + + const tusb_dir_t ep_dir = tu_edpt_dir(epx->ep_addr); + const uint32_t sie_ctrl = (ep_dir ? USB_SIE_CTRL_RECEIVE_DATA_BITS : USB_SIE_CTRL_SEND_DATA_BITS) | + (epx->need_pre ? USB_SIE_CTRL_PREAMBLE_EN_BITS : 0); + sie_start_xfer(sie_ctrl); + } + } +#endif if (status & USB_INTS_ERROR_RX_TIMEOUT_BITS) { usb_hw_clear->sie_status = USB_SIE_STATUS_RX_TIMEOUT_BITS; @@ -344,10 +396,14 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { USB_INTE_HOST_RESUME_BITS | USB_INTE_STALL_BITS | USB_INTE_TRANS_COMPLETE_BITS | - // USB_INTE_EP_STALL_NAK_BITS | USB_INTE_ERROR_RX_TIMEOUT_BITS | USB_INTE_ERROR_DATA_SEQ_BITS ; +#if defined(PICO_RP2350) && PICO_RP2350 == 1 + // RP2350: Enable EPX stopped-on-NAK interrupt (feature is enabled dynamically when transfers are pending) + usb_hw_set->inte = USB_INTE_EPX_STOPPED_ON_NAK_BITS; +#endif + return true; } @@ -557,6 +613,10 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *b ep->user_buf = buffer; ep->remaining_len = buflen; ep->pending = 1; +#if defined(PICO_RP2350) && PICO_RP2350 == 1 + // RP2350: Enable stop-on-NAK so current EPX transfer can be preempted + usb_hw_set->nak_poll = USB_NAK_POLL_STOP_EPX_ON_NAK_BITS; +#endif return true; } @@ -589,6 +649,10 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, const uint8_t setup_packet // If EPX is busy, mark as pending setup (DPRAM already has the packet) if (epx->active) { ep->pending = 2; +#if defined(PICO_RP2350) && PICO_RP2350 == 1 + // RP2350: Enable stop-on-NAK so current EPX transfer can be preempted + usb_hw_set->nak_poll = USB_NAK_POLL_STOP_EPX_ON_NAK_BITS; +#endif return true; } -- cgit v1.3.1 From f7cf6bc581c514984d3513bea8538e33e7d726d8 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 20 Mar 2026 19:36:57 +0700 Subject: clean up --- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 31 ++++++++++++++-------------- 1 file changed, 15 insertions(+), 16 deletions(-) (limited to 'src/portable') diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index f3153d0e9..3c250ae7f 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -30,11 +30,15 @@ #if CFG_TUH_ENABLED && (CFG_TUSB_MCU == OPT_MCU_RP2040) && !CFG_TUH_RPI_PIO_USB && !CFG_TUH_MAX3421 #include "pico.h" -#include "rp2040_usb.h" + +#if defined(PICO_RP2350) && PICO_RP2350 == 1 +#define HAS_STOP_EPX_ON_NAK +#endif //--------------------------------------------------------------------+ // INCLUDE //--------------------------------------------------------------------+ +#include "rp2040_usb.h" #include "osal/osal.h" #include "host/hcd.h" @@ -224,11 +228,11 @@ static void __tusb_irq_path_func(hcd_rp2040_irq)(void) { } } -#if defined(PICO_RP2350) && PICO_RP2350 == 1 +#ifdef HAS_STOP_EPX_ON_NAK if (status & USB_INTS_EPX_STOPPED_ON_NAK_BITS) { - // RP2350: EPX transfer stopped due to NAK from device. + // EPX transfer stopped due to NAK from the device. // Clear EPX_STOPPED_ON_NAK status (WC) - usb_hw->nak_poll |= USB_NAK_POLL_EPX_STOPPED_ON_NAK_BITS; + usb_hw_clear->nak_poll = USB_NAK_POLL_EPX_STOPPED_ON_NAK_BITS; bool preempted = false; @@ -286,9 +290,7 @@ static void __tusb_irq_path_func(hcd_rp2040_irq)(void) { if (!preempted && epx->active) { // No preemption needed: disable stop-on-NAK and restart the transaction. // Buffer control still has AVAILABLE set, just re-trigger START_TRANS. - uint32_t nak_poll = usb_hw->nak_poll; - nak_poll &= ~USB_NAK_POLL_STOP_EPX_ON_NAK_BITS; - usb_hw->nak_poll = nak_poll; + usb_hw_clear->nak_poll = USB_NAK_POLL_STOP_EPX_ON_NAK_BITS; const tusb_dir_t ep_dir = tu_edpt_dir(epx->ep_addr); const uint32_t sie_ctrl = (ep_dir ? USB_SIE_CTRL_RECEIVE_DATA_BITS : USB_SIE_CTRL_SEND_DATA_BITS) | @@ -399,8 +401,7 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { USB_INTE_ERROR_RX_TIMEOUT_BITS | USB_INTE_ERROR_DATA_SEQ_BITS ; -#if defined(PICO_RP2350) && PICO_RP2350 == 1 - // RP2350: Enable EPX stopped-on-NAK interrupt (feature is enabled dynamically when transfers are pending) +#ifdef HAS_STOP_EPX_ON_NAK usb_hw_set->inte = USB_INTE_EPX_STOPPED_ON_NAK_BITS; #endif @@ -613,8 +614,8 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *b ep->user_buf = buffer; ep->remaining_len = buflen; ep->pending = 1; -#if defined(PICO_RP2350) && PICO_RP2350 == 1 - // RP2350: Enable stop-on-NAK so current EPX transfer can be preempted +#ifdef HAS_STOP_EPX_ON_NAK + // Enable stop-on-NAK to round-robin when NAK usb_hw_set->nak_poll = USB_NAK_POLL_STOP_EPX_ON_NAK_BITS; #endif return true; @@ -649,8 +650,8 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, const uint8_t setup_packet // If EPX is busy, mark as pending setup (DPRAM already has the packet) if (epx->active) { ep->pending = 2; -#if defined(PICO_RP2350) && PICO_RP2350 == 1 - // RP2350: Enable stop-on-NAK so current EPX transfer can be preempted +#ifdef HAS_STOP_EPX_ON_NAK + // Enable stop-on-NAK to round-robin when NAK usb_hw_set->nak_poll = USB_NAK_POLL_STOP_EPX_ON_NAK_BITS; #endif return true; @@ -661,9 +662,7 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, const uint8_t setup_packet ep->active = true; epx = ep; - - // Set device address - usb_hw->dev_addr_ctrl = dev_addr; + usb_hw->dev_addr_ctrl = dev_addr; // Set device address // Set pre if we are a low speed device on full speed hub const uint32_t sie_ctrl = USB_SIE_CTRL_SEND_SETUP_BITS | (ep->need_pre ? USB_SIE_CTRL_PREAMBLE_EN_BITS : 0); -- cgit v1.3.1 From 15eef94df0e759adf14697197a89dddeb8fc3aeb Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 23 Mar 2026 15:49:58 +0700 Subject: add rp2040 sof + stop_trans on nak. increase nak_poll fs/ls delay to 300 us to prevent xfer is ack while stopping. --- examples/host/cdc_msc_hid/src/msc_app.c | 2 +- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 163 ++++++++++++++++----------- src/portable/raspberrypi/rp2040/rp2040_usb.c | 10 +- 3 files changed, 105 insertions(+), 70 deletions(-) (limited to 'src/portable') diff --git a/examples/host/cdc_msc_hid/src/msc_app.c b/examples/host/cdc_msc_hid/src/msc_app.c index 4a85e46d7..8181bdcb9 100644 --- a/examples/host/cdc_msc_hid/src/msc_app.c +++ b/examples/host/cdc_msc_hid/src/msc_app.c @@ -41,7 +41,7 @@ static bool inquiry_complete_cb(uint8_t dev_addr, tuh_msc_complete_data_t const } // Print out Vendor ID, Product ID and Rev - printf("%.8s %.16s rev %.4s\r\n", inquiry_resp.vendor_id, inquiry_resp.product_id, inquiry_resp.product_rev); + printf("%.8s %.16s %.4s\r\n", inquiry_resp.vendor_id, inquiry_resp.product_id, inquiry_resp.product_rev); // Get capacity of device uint32_t const block_count = tuh_msc_get_block_count(dev_addr, cbw->lun); diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index 3c250ae7f..9ee15d343 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -185,6 +185,54 @@ static void __tusb_irq_path_func(handle_hwbuf_status)(void) { // All non-interrupt endpoints use shared EPX. // Forward declared above hw_xfer_complete, defined after edpt_xfer below. +// Save current EPX context, mark pending, switch to next_ep +static void __tusb_irq_path_func(epx_switch_ep)(hw_endpoint_t *next_ep) { + const uint32_t buf_ctrl = usbh_dpram->epx_buf_ctrl; + const uint16_t buf0_len = buf_ctrl & USB_BUF_CTRL_LEN_MASK; + epx->remaining_len = (uint16_t)(epx->remaining_len + buf0_len); + epx->next_pid = (buf_ctrl & USB_BUF_CTRL_DATA1_PID) ? 1 : 0; + if (tu_edpt_dir(epx->ep_addr) == TUSB_DIR_OUT) { + epx->user_buf -= buf0_len; + } + epx->pending = 1; + epx->active = false; + usbh_dpram->epx_buf_ctrl = 0; + + if (next_ep->pending == 2) { + next_ep->ep_addr = 0; + next_ep->remaining_len = 8; + next_ep->xferred_len = 0; + next_ep->active = true; + next_ep->pending = 0; + epx = next_ep; + usb_hw->dev_addr_ctrl = next_ep->dev_addr; + const uint32_t sc = USB_SIE_CTRL_SEND_SETUP_BITS | + (next_ep->need_pre ? USB_SIE_CTRL_PREAMBLE_EN_BITS : 0); + sie_start_xfer(sc); + } else { + uint16_t prev_xferred = next_ep->xferred_len; + next_ep->pending = 0; + edpt_xfer(next_ep, next_ep->user_buf, NULL, next_ep->remaining_len); + epx->xferred_len += prev_xferred; + } +} + +// Round-robin find next pending ep after current epx +static hw_endpoint_t *__tusb_irq_path_func(epx_find_pending)(void) { + const uint start = (uint)(epx - &ep_pool[0]) + 1; + for (uint i = start; i < TU_ARRAY_SIZE(ep_pool); i++) { + if (ep_pool[i].pending) { + return &ep_pool[i]; + } + } + for (uint i = 0; i < start - 1; i++) { + if (ep_pool[i].pending) { + return &ep_pool[i]; + } + } + return NULL; +} + static void __tusb_irq_path_func(hcd_rp2040_irq)(void) { const uint32_t status = usb_hw->ints; @@ -229,73 +277,51 @@ static void __tusb_irq_path_func(hcd_rp2040_irq)(void) { } #ifdef HAS_STOP_EPX_ON_NAK + // RP2350: hardware stops EPX on NAK automatically if (status & USB_INTS_EPX_STOPPED_ON_NAK_BITS) { - // EPX transfer stopped due to NAK from the device. - // Clear EPX_STOPPED_ON_NAK status (WC) usb_hw_clear->nak_poll = USB_NAK_POLL_EPX_STOPPED_ON_NAK_BITS; - bool preempted = false; - - // Only preempt non-control endpoints + hw_endpoint_t *next_ep = NULL; if (epx->active && tu_edpt_number(epx->ep_addr) != 0) { - // Find the next pending transfer (different from the current epx) - for (uint i = 0; i < TU_ARRAY_SIZE(ep_pool); i++) { - hw_endpoint_t *ep = &ep_pool[i]; - if (ep->pending && ep != epx) { - // NAK means no data transferred. Restore remaining_len from buffer control - // so edpt_schedule_next can properly resume this transfer later. - const uint16_t buf0_len = usbh_dpram->epx_buf_ctrl & USB_BUF_CTRL_LEN_MASK; - epx->remaining_len = (uint16_t)(epx->remaining_len + buf0_len); - epx->next_pid ^= 1u; // undo PID toggle from hwbuf_prepare - if (tu_edpt_dir(epx->ep_addr) == TUSB_DIR_OUT) { - epx->user_buf -= buf0_len; // undo buffer advance for OUT - } - - // Mark current EPX as pending to resume later - epx->pending = 1; - epx->active = false; - - // Clear EPX buffer control - AVAILABLE is still set from the NAK'd transfer - usbh_dpram->epx_buf_ctrl = 0; - - // Start the found pending transfer directly - if (ep->pending == 2) { - // Pending setup: DPRAM already has the setup packet - ep->ep_addr = 0; - ep->remaining_len = 8; - ep->xferred_len = 0; - ep->active = true; - ep->pending = 0; - - epx = ep; - usb_hw->dev_addr_ctrl = ep->dev_addr; - - const uint32_t sc = USB_SIE_CTRL_SEND_SETUP_BITS | - (ep->need_pre ? USB_SIE_CTRL_PREAMBLE_EN_BITS : 0); - sie_start_xfer(sc); - } else { - // Pending data transfer: preserve partial progress - uint16_t prev_xferred = ep->xferred_len; - ep->pending = 0; - edpt_xfer(ep, ep->user_buf, NULL, ep->remaining_len); - epx->xferred_len += prev_xferred; - } - - preempted = true; - break; - } - } + next_ep = epx_find_pending(); } - - if (!preempted && epx->active) { - // No preemption needed: disable stop-on-NAK and restart the transaction. - // Buffer control still has AVAILABLE set, just re-trigger START_TRANS. + if (next_ep) { + epx_switch_ep(next_ep); + } else { + // No preemption: disable stop-on-NAK, restart current transfer usb_hw_clear->nak_poll = USB_NAK_POLL_STOP_EPX_ON_NAK_BITS; - - const tusb_dir_t ep_dir = tu_edpt_dir(epx->ep_addr); - const uint32_t sie_ctrl = (ep_dir ? USB_SIE_CTRL_RECEIVE_DATA_BITS : USB_SIE_CTRL_SEND_DATA_BITS) | - (epx->need_pre ? USB_SIE_CTRL_PREAMBLE_EN_BITS : 0); - sie_start_xfer(sie_ctrl); + if (epx->active) { + const tusb_dir_t ep_dir = tu_edpt_dir(epx->ep_addr); + const uint32_t sie_ctrl = (ep_dir ? USB_SIE_CTRL_RECEIVE_DATA_BITS : USB_SIE_CTRL_SEND_DATA_BITS) | + (epx->need_pre ? USB_SIE_CTRL_PREAMBLE_EN_BITS : 0); + sie_start_xfer(sie_ctrl); + } + } + } +#else + // RP2040: on SOF, stop and switch if there's a pending ep + if (status & USB_INTS_HOST_SOF_BITS) { + (void) usb_hw->sof_rd; // clear SOF by reading SOF_RD + if (epx->active && tu_edpt_number(epx->ep_addr) != 0) { + hw_endpoint_t *next_ep = epx_find_pending(); + if (next_ep) { + usb_hw_set->sie_ctrl = USB_SIE_CTRL_STOP_TRANS_BITS; + while (usb_hw->sie_ctrl & USB_SIE_CTRL_STOP_TRANS_BITS) {} + busy_wait_at_least_cycles(12); + if (usb_hw->buf_status & 1u) { + usb_hw->nak_poll = USB_NAK_POLL_RESET; + handle_hwbuf_status(); + } else { + epx_switch_ep(next_ep); + } + } else { + usb_hw_clear->inte = USB_INTE_HOST_SOF_BITS; + usb_hw->nak_poll = USB_NAK_POLL_RESET; + } + } else if (!epx_find_pending()) { + // EPX is on control endpoint or inactive — disable SOF if nothing pending + usb_hw_clear->inte = USB_INTE_HOST_SOF_BITS; + usb_hw->nak_poll = USB_NAK_POLL_RESET; } } #endif @@ -615,8 +641,14 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *b ep->remaining_len = buflen; ep->pending = 1; #ifdef HAS_STOP_EPX_ON_NAK - // Enable stop-on-NAK to round-robin when NAK usb_hw_set->nak_poll = USB_NAK_POLL_STOP_EPX_ON_NAK_BITS; +#else + // Only enable SOF preemption for non-control endpoints + if (tu_edpt_number(epx->ep_addr) != 0) { + usb_hw->nak_poll = (300 << USB_NAK_POLL_DELAY_FS_LSB) | + (300 << USB_NAK_POLL_DELAY_LS_LSB); + usb_hw_set->inte = USB_INTE_HOST_SOF_BITS; + } #endif return true; } @@ -651,8 +683,13 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, const uint8_t setup_packet if (epx->active) { ep->pending = 2; #ifdef HAS_STOP_EPX_ON_NAK - // Enable stop-on-NAK to round-robin when NAK usb_hw_set->nak_poll = USB_NAK_POLL_STOP_EPX_ON_NAK_BITS; +#else + if (tu_edpt_number(epx->ep_addr) != 0) { + usb_hw->nak_poll = (300 << USB_NAK_POLL_DELAY_FS_LSB) | + (300 << USB_NAK_POLL_DELAY_LS_LSB); + usb_hw_set->inte = USB_INTE_HOST_SOF_BITS; + } #endif return true; } diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index 0f1075eda..66e579c39 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -124,12 +124,10 @@ void __tusb_irq_path_func(hwbuf_ctrl_update)(io_rw_32 *buf_ctrl_reg, uint32_t an } *buf_ctrl_reg = value & ~USB_BUF_CTRL_AVAIL; - // Section 4.1.2.7.1 (rp2040) / 12.7.3.7.1 (rp2350) Concurrent access: after write to buffer control, we need to - // wait at least 1/48 mhz (usb clock), 12 cycles should be good for 48*12Mhz = 576Mhz. - // Don't need delay in host mode as host is in charge - if (!is_host) { - busy_wait_at_least_cycles(12); - } + // Section 4.1.2.7.1 (rp2040) / 12.7.3.7.1 (rp2350) Concurrent access: after write to buffer control, + // wait for USB controller to see the update before setting AVAILABLE. + // Host also needs this for continuation buffers in multi-packet transfers. + busy_wait_at_least_cycles(12); } } -- cgit v1.3.1 From 09197ed27929d03a7f16e3d67dc76fa312948316 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 24 Mar 2026 16:05:31 +0700 Subject: handle buf_status in per buffer basic (INTERRUPT_PER_BUFFER), this allows us to sync/move half data payload instead of waiting for pair complete. Refactor endpoint control and buffer handling functions for clarity and efficiency. --- src/portable/raspberrypi/rp2040/dcd_rp2040.c | 130 +++++++++++----------- src/portable/raspberrypi/rp2040/rp2040_usb.c | 154 +++++++++------------------ src/portable/raspberrypi/rp2040/rp2040_usb.h | 10 +- 3 files changed, 128 insertions(+), 166 deletions(-) (limited to 'src/portable') diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index e4d56f69a..ec73cafc1 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -69,20 +69,18 @@ TU_ATTR_ALWAYS_INLINE static inline hw_endpoint_t *hw_endpoint_get_by_addr(uint8 return hw_endpoint_get(num, dir); } -TU_ATTR_ALWAYS_INLINE static inline io_rw_32 *hwep_ctrl_reg_device(struct hw_endpoint *ep) { - const uint8_t epnum = tu_edpt_number(ep->ep_addr); - const uint8_t dir = (uint8_t)tu_edpt_dir(ep->ep_addr); +TU_ATTR_ALWAYS_INLINE static inline io_rw_32 *get_ep_ctrl(const uint8_t epnum, tusb_dir_t dir) { if (epnum == 0) { // EP0 has no endpoint control register because the buffer offsets are fixed and always enabled return NULL; } - return (dir == TUSB_DIR_IN) ? &usb_dpram->ep_ctrl[epnum - 1].in : &usb_dpram->ep_ctrl[epnum - 1].out; + struct usb_device_dpram_ep_ctrl *ep_ctrl = &usb_dpram->ep_ctrl[epnum - 1]; + return (dir == TUSB_DIR_IN) ? &ep_ctrl->in : &ep_ctrl->out; } -TU_ATTR_ALWAYS_INLINE static inline io_rw_32 *hwbuf_ctrl_reg_device(struct hw_endpoint *ep) { - const uint8_t epnum = tu_edpt_number(ep->ep_addr); - const uint8_t dir = (uint8_t)tu_edpt_dir(ep->ep_addr); - return (dir == TUSB_DIR_IN) ? &usb_dpram->ep_buf_ctrl[epnum].in : &usb_dpram->ep_buf_ctrl[epnum].out; +TU_ATTR_ALWAYS_INLINE static inline io_rw_32 *get_buf_ctrl(const uint8_t epnum, tusb_dir_t dir) { + struct usb_device_dpram_ep_buf_ctrl *buf_ctrl = &usb_dpram->ep_buf_ctrl[epnum]; + return (dir == TUSB_DIR_IN) ? &buf_ctrl->in : &buf_ctrl->out; } // main processing for dcd_edpt_iso_activate @@ -92,11 +90,12 @@ static void hw_endpoint_init(hw_endpoint_t *ep, uint8_t ep_addr, uint16_t wMaxPa ep->max_packet_size = wMaxPacketSize; // Clear existing buffer control state - io_rw_32 *buf_ctrl_reg = hwbuf_ctrl_reg_device(ep); + const uint8_t epnum = tu_edpt_number(ep_addr); + const tusb_dir_t dir = tu_edpt_dir(ep_addr); + io_rw_32 *buf_ctrl_reg = get_buf_ctrl(epnum, dir); *buf_ctrl_reg = 0; // allocated hw buffer - const uint8_t epnum = tu_edpt_number(ep_addr); if (epnum == 0) { // Buffer offset is fixed (also double buffered) ep->dpram_buf = (uint8_t *)&usb_dpram->ep0_buf_a[0]; @@ -109,7 +108,7 @@ static void hw_endpoint_init(hw_endpoint_t *ep, uint8_t ep_addr, uint16_t wMaxPa size *= 2u; #if TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX - if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN) { + if (dir == TUSB_DIR_IN) { ep->e15_bulk_in = true; } #endif @@ -124,13 +123,13 @@ static void hw_endpoint_init(hw_endpoint_t *ep, uint8_t ep_addr, uint16_t wMaxPa } } -static void hw_endpoint_enable(hw_endpoint_t *ep, uint8_t transfer_type) { - io_rw_32 *ctrl_reg = hwep_ctrl_reg_device(ep); +static void hw_endpoint_enable(uint8_t epnum, tusb_dir_t dir, uint8_t transfer_type, uint8_t *dpram_buf) { + io_rw_32 *ep_reg = get_ep_ctrl(epnum, dir); // Set endpoint control register to enable (EP0 has no endpoint control register) - if (ctrl_reg != NULL) { + if (ep_reg != NULL) { const uint32_t ctrl_value = - EP_CTRL_ENABLE_BITS | ((uint32_t)transfer_type << EP_CTRL_BUFFER_TYPE_LSB) | hw_data_offset(ep->dpram_buf); - *ctrl_reg = ctrl_value; + EP_CTRL_ENABLE_BITS | ((uint32_t)transfer_type << EP_CTRL_BUFFER_TYPE_LSB) | hw_data_offset(dpram_buf); + *ep_reg = ctrl_value; } } @@ -141,7 +140,7 @@ static void hw_endpoint_open(uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t t hw_endpoint_t *ep = hw_endpoint_get(epnum, dir); hw_endpoint_init(ep, ep_addr, wMaxPacketSize, transfer_type); - hw_endpoint_enable(ep, transfer_type); + hw_endpoint_enable(epnum, dir, transfer_type, ep->dpram_buf); } static void hw_endpoint_abort_xfer(struct hw_endpoint* ep) { @@ -162,7 +161,7 @@ static void hw_endpoint_abort_xfer(struct hw_endpoint* ep) { buf_ctrl |= USB_BUF_CTRL_DATA1_PID; } - io_rw_32 *buf_ctrl_reg = hwbuf_ctrl_reg_device(ep); + io_rw_32 *buf_ctrl_reg = get_buf_ctrl(epnum, dir); hwbuf_ctrl_set(buf_ctrl_reg, buf_ctrl); hw_endpoint_reset_transfer(ep); @@ -173,32 +172,41 @@ static void hw_endpoint_abort_xfer(struct hw_endpoint* ep) { } static void __tusb_irq_path_func(handle_hw_buff_status)(void) { - uint32_t remaining_buffers = usb_hw->buf_status; - pico_trace("buf_status = 0x%08lx\r\n", remaining_buffers); - uint bit = 1u; - for (uint8_t i = 0; remaining_buffers && i < USB_MAX_ENDPOINTS * 2; i++) { - if (remaining_buffers & bit) { - // clear this in advance + uint32_t buf_status = usb_hw->buf_status; + pico_trace("buf_status = 0x%08lx\r\n", buf_status); + while (buf_status) { + // ctz/clz is faster than loop which has only a few bit set in general + const uint8_t i = (uint8_t) __builtin_ctz(buf_status); + const uint bit = TU_BIT(i); + + // Read which buffer to handle BEFORE clearing buf_status + uint8_t buf_id = (usb_hw->buf_cpu_should_handle & bit) ? 1 : 0; + usb_hw_clear->buf_status = bit; + + // IN transfer for even i, OUT transfer for odd i + const uint8_t epnum = i >> 1u; + const tusb_dir_t dir = (i & 1u) ? TUSB_DIR_OUT : TUSB_DIR_IN; + hw_endpoint_t *ep = hw_endpoint_get(epnum, dir); + + io_rw_32 *ep_reg = get_ep_ctrl(epnum, dir); + io_rw_32 *buf_reg = get_buf_ctrl(epnum, dir); + bool done = hw_endpoint_xfer_continue(ep, ep_reg, buf_reg, buf_id); + + // Double-buffered: if both buffers completed at once, buf_status re-sets + // immediately after clearing (datasheet Table 406). Process the second buffer too. + if (!done && (usb_hw->buf_status & bit)) { + buf_id = (usb_hw->buf_cpu_should_handle & bit) ? 1 : 0; usb_hw_clear->buf_status = bit; + done = hw_endpoint_xfer_continue(ep, ep_reg, buf_reg, buf_id); + } - // IN transfer for even i, OUT transfer for odd i - const uint8_t epnum = i >> 1u; - const tusb_dir_t dir = (i & 1u) ? TUSB_DIR_OUT : TUSB_DIR_IN; - hw_endpoint_t *ep = hw_endpoint_get(epnum, dir); - - io_rw_32 *ep_reg = hwep_ctrl_reg_device(ep); - io_rw_32 *buf_reg = hwbuf_ctrl_reg_device(ep); - const bool done = hw_endpoint_xfer_continue(ep, ep_reg, buf_reg); - - if (done) { - // Notify usbd - 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; + if (done) { + 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); } - bit <<= 1u; + + buf_status &= ~bit; } } @@ -251,9 +259,9 @@ static void __tusb_irq_path_func(dcd_rp2040_irq)(void) { hw_endpoint_lock_update(ep, 1); if (ep->pending) { ep->pending = 0; - io_rw_32 *ep_reg = hwep_ctrl_reg_device(ep); - io_rw_32 *buf_reg = hwbuf_ctrl_reg_device(ep); - hw_endpoint_start_next_buffer(ep, ep_reg, buf_reg); + io_rw_32 *ep_reg = get_ep_ctrl(i, TUSB_DIR_IN); + io_rw_32 *buf_reg = get_buf_ctrl(i, TUSB_DIR_IN); + hw_endpoint_buffer_xact(ep, ep_reg, buf_reg); } hw_endpoint_lock_update(ep, -1); } @@ -361,7 +369,7 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { (void) rh_init; assert(rhport == 0); - TU_LOG(2, "Chip Version B%u\r\n", rp2040_chip_version()); + TU_LOG(1, "Chip Version B%u\r\n", rp2040_chip_version()); // Reset hardware to default state rp2usb_init(); @@ -508,7 +516,7 @@ bool dcd_edpt_iso_activate(uint8_t rhport, const tusb_desc_endpoint_t *ep_desc) } ep->max_packet_size = ep_desc->wMaxPacketSize; - hw_endpoint_enable(ep, TUSB_XFER_ISOCHRONOUS); + hw_endpoint_enable(epnum, dir, TUSB_XFER_ISOCHRONOUS, ep->dpram_buf); return true; } @@ -521,9 +529,12 @@ void dcd_edpt_close_all(uint8_t rhport) { bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes, bool is_isr) { (void)rhport; (void)is_isr; - hw_endpoint_t *ep = hw_endpoint_get_by_addr(ep_addr); - io_rw_32 *ep_reg = hwep_ctrl_reg_device(ep); - io_rw_32 *buf_reg = hwbuf_ctrl_reg_device(ep); + const uint8_t epnum = tu_edpt_number(ep_addr); + const tusb_dir_t dir = tu_edpt_dir(ep_addr); + + hw_endpoint_t *ep = hw_endpoint_get(epnum, dir); + io_rw_32 *ep_reg = get_ep_ctrl(epnum, dir); + io_rw_32 *buf_reg = get_buf_ctrl(epnum, dir); hw_endpoint_xfer_start(ep, ep_reg, buf_reg, buffer, NULL, total_bytes); return true; } @@ -532,9 +543,9 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t *ff, uint16_t total_bytes, bool is_isr) { (void)rhport; (void)is_isr; - hw_endpoint_t *ep = hw_endpoint_get_by_addr(ep_addr); - io_rw_32 *ep_reg = hwep_ctrl_reg_device(ep); - io_rw_32 *buf_reg = hwbuf_ctrl_reg_device(ep); + hw_endpoint_t *ep = hw_endpoint_get(epnum, dir); + io_rw_32 *ep_reg = get_ep_ctrl(epnum, dir); + io_rw_32 *buf_reg = get_buf_ctrl(epnum, dir); hw_endpoint_xfer_start(ep, ep_reg, buf_reg, NULL, ff, total_bytes); return true; } @@ -544,7 +555,6 @@ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { (void)rhport; const uint8_t epnum = tu_edpt_number(ep_addr); const tusb_dir_t dir = tu_edpt_dir(ep_addr); - hw_endpoint_t *ep = hw_endpoint_get(epnum, dir); if (epnum == 0) { // A stall on EP0 has to be armed so it can be cleared on the next setup packet @@ -552,19 +562,19 @@ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { } // stall and clear current pending buffer, may need to use EP_ABORT - io_rw_32 *buf_ctrl_reg = hwbuf_ctrl_reg_device(ep); + io_rw_32 *buf_ctrl_reg = get_buf_ctrl(epnum, dir); hwbuf_ctrl_set(buf_ctrl_reg, USB_BUF_CTRL_STALL); } void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { (void) rhport; + const uint8_t epnum = tu_edpt_number(ep_addr); + const tusb_dir_t dir = tu_edpt_dir(ep_addr); - if (tu_edpt_number(ep_addr)) { - struct hw_endpoint* ep = hw_endpoint_get_by_addr(ep_addr); - - // clear stall also reset toggle to DATA0, ready for next transfer - ep->next_pid = 0; - io_rw_32 *buf_ctrl_reg = hwbuf_ctrl_reg_device(ep); + if (epnum != 0) { + struct hw_endpoint* ep = hw_endpoint_get(epnum, dir); + ep->next_pid = 0; // reset data toggle + io_rw_32 *buf_ctrl_reg = get_buf_ctrl(epnum, dir); hwbuf_ctrl_clear_mask(buf_ctrl_reg, USB_BUF_CTRL_STALL); } } diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index 66e579c39..ac1536f5b 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -35,8 +35,6 @@ //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF PROTOTYPE //--------------------------------------------------------------------+ -static void sync_xfer(hw_endpoint_t *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg); - #if TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX static bool e15_is_critical_frame_period(struct hw_endpoint *ep); #else @@ -137,18 +135,18 @@ void __tusb_irq_path_func(hwbuf_ctrl_update)(io_rw_32 *buf_ctrl_reg, uint32_t an // prepare buffer, move data if tx, return buffer control static uint32_t __tusb_irq_path_func(hwbuf_prepare)(struct hw_endpoint *ep, uint8_t buf_id, bool is_rx) { const uint16_t buflen = tu_min16(ep->remaining_len, ep->max_packet_size); - ep->remaining_len = (uint16_t) (ep->remaining_len - buflen); + ep->remaining_len -= buflen; uint32_t buf_ctrl = buflen | USB_BUF_CTRL_AVAIL; - - // PID - buf_ctrl |= ep->next_pid ? USB_BUF_CTRL_DATA1_PID : USB_BUF_CTRL_DATA0_PID; + if (ep->next_pid) { + buf_ctrl |= USB_BUF_CTRL_DATA1_PID; + } ep->next_pid ^= 1u; if (!is_rx) { if (buflen) { // Copy data from user buffer/fifo to hw buffer - uint8_t *hw_buf = ep->dpram_buf + buf_id * 64; + uint8_t *hw_buf = ep->dpram_buf + (buf_id << 6); #if CFG_TUD_EDPT_DEDICATED_HWFIFO if (ep->is_xfer_fifo) { // not in sram, may mess up timing with E15 workaround @@ -161,7 +159,6 @@ static uint32_t __tusb_irq_path_func(hwbuf_prepare)(struct hw_endpoint *ep, uint } } - // Mark as full buf_ctrl |= USB_BUF_CTRL_FULL; } @@ -172,15 +169,11 @@ static uint32_t __tusb_irq_path_func(hwbuf_prepare)(struct hw_endpoint *ep, uint buf_ctrl |= USB_BUF_CTRL_LAST; } - if (buf_id) { - buf_ctrl = buf_ctrl << 16; - } - return buf_ctrl; } -// Prepare buffer control register value -void __tusb_irq_path_func(hw_endpoint_start_next_buffer)(struct hw_endpoint *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg) { +// Start transaction on hw buffer +void __tusb_irq_path_func(hw_endpoint_buffer_xact)(struct hw_endpoint *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg) { const tusb_dir_t dir = tu_edpt_dir(ep->ep_addr); const bool is_host = rp2usb_is_host_mode(); @@ -194,39 +187,34 @@ void __tusb_irq_path_func(hw_endpoint_start_next_buffer)(struct hw_endpoint *ep, // always compute and start with buffer 0 uint32_t buf_ctrl = hwbuf_prepare(ep, 0, is_rx) | USB_BUF_CTRL_SEL; - // EP0 has no endpoint control register, also usbd only schedule 1 packet at a time (single buffer) + // Device mode EP0 has no endpoint control register if (ep_reg != NULL) { - uint32_t ep_ctrl = *ep_reg; - - // For now: skip double buffered for RX e.g OUT endpoint in Device mode, since host could send < 64 bytes and cause - // short packet on buffer0 - // NOTE: this could happen to Host mode IN endpoint Also, Host mode "interrupt" endpoint hardware is only single - // buffered, - // NOTE2: Currently Host bulk is implemented using "interrupt" endpoint - const bool force_single = (!is_host && is_rx) || (is_host && tu_edpt_number(ep->ep_addr) != 0); + // Each buffer completion triggers its own IRQ. + // If both complete simultaneously, buf_status re-sets on next clock (datasheet Table 406). + uint32_t ep_ctrl = *ep_reg | EP_CTRL_INTERRUPT_PER_BUFFER; + + // Since short packet on buf0 in double-buffered RX: buf1 may already contain data from the + // NEXT transfer (host sent it before CPU processed this IRQ). Cannot safely recover. Avoid by not using double + // buffering for rx transfer + bool force_single = is_rx; + #if CFG_TUH_ENABLED + force_single |= (is_host && ep->interrupt_num != 0); // host interrupt is single only + #endif if (ep->remaining_len && !force_single) { // Use buffer 1 (double buffered) if there is still data // TODO: Isochronous for buffer1 bit-field is different than CBI (control bulk, interrupt) - - buf_ctrl |= hwbuf_prepare(ep, 1, is_rx); - - // Set endpoint control double buffered bit if needed - ep_ctrl &= ~EP_CTRL_INTERRUPT_PER_BUFFER; - ep_ctrl |= EP_CTRL_DOUBLE_BUFFERED_BITS | EP_CTRL_INTERRUPT_PER_DOUBLE_BUFFER; + buf_ctrl |= (hwbuf_prepare(ep, 1, is_rx) << 16); + ep_ctrl |= EP_CTRL_DOUBLE_BUFFERED_BITS; } else { // Single buffered since 1 is enough - ep_ctrl &= ~(EP_CTRL_DOUBLE_BUFFERED_BITS | EP_CTRL_INTERRUPT_PER_DOUBLE_BUFFER); - ep_ctrl |= EP_CTRL_INTERRUPT_PER_BUFFER; + ep_ctrl &= ~EP_CTRL_DOUBLE_BUFFERED_BITS; } *ep_reg = ep_ctrl; } - TU_LOG(3, " Prepare BufCtrl: [0] = 0x%04x [1] = 0x%04x\r\n", tu_u32_low16(buf_ctrl), tu_u32_high16(buf_ctrl)); - - // Finally, write to buffer_control which will trigger the transfer - // the next time the controller polls this dpram address + // Finally, write to buffer_control which will trigger the transfer the next time the controller polls this endpoint hwbuf_ctrl_set(buf_reg, buf_ctrl); } @@ -267,7 +255,7 @@ void hw_endpoint_xfer_start(struct hw_endpoint *ep, io_rw_32 *ep_reg, io_rw_32 * } else #endif { - hw_endpoint_start_next_buffer(ep, ep_reg, buf_reg); + hw_endpoint_buffer_xact(ep, ep_reg, buf_reg); } hw_endpoint_lock_update(ep, -1); @@ -315,91 +303,49 @@ static uint16_t __tusb_irq_path_func(hwbuf_sync)(hw_endpoint_t *ep, io_rw_32 *bu return xferred_bytes; } -// Update hw endpoint struct with info from hardware after a buff status interrupt -static void __tusb_irq_path_func(sync_xfer)(hw_endpoint_t *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg) { - // const uint8_t ep_num = tu_edpt_number(ep->ep_addr); - const tusb_dir_t dir = tu_edpt_dir(ep->ep_addr); - const bool is_host = rp2usb_is_host_mode(); - bool is_rx; - - if (is_host) { - is_rx = (dir == TUSB_DIR_IN); - } else { - is_rx = (dir == TUSB_DIR_OUT); - } - - TU_LOG(3, " Sync BufCtrl: [0] = 0x%04x [1] = 0x%04x\r\n", tu_u32_low16(*buf_reg), tu_u32_high16(*buf_reg)); - uint16_t buf0_bytes = hwbuf_sync(ep, buf_reg, 0, is_rx); // always sync buffer 0 - - // sync buffer 1 if double buffered - if (ep_reg != NULL && (*ep_reg) & EP_CTRL_DOUBLE_BUFFERED_BITS) { - if (buf0_bytes == ep->max_packet_size) { - // sync buffer 1 if not short packet - hwbuf_sync(ep, buf_reg, 1, is_rx); - } else { - // short packet on buffer 0 - // TODO couldn't figure out how to handle this case which happen with net_lwip_webserver example - // At this time (currently trigger per 2 buffer), the buffer1 is probably filled with data from - // the next transfer (not current one). For now we disable double buffered for device OUT - // NOTE this could happen to Host IN -#if 0 - uint8_t const ep_num = tu_edpt_number(ep->ep_addr); - uint8_t const dir = (uint8_t) tu_edpt_dir(ep->ep_addr); - uint8_t const ep_id = 2*ep_num + (dir ? 0 : 1); - - // abort queued transfer on buffer 1 - usb_hw->abort |= TU_BIT(ep_id); - - while ( !(usb_hw->abort_done & TU_BIT(ep_id)) ) {} - - uint32_t ep_ctrl = *ep->endpoint_control; - ep_ctrl &= ~(EP_CTRL_DOUBLE_BUFFERED_BITS | EP_CTRL_INTERRUPT_PER_DOUBLE_BUFFER); - ep_ctrl |= EP_CTRL_INTERRUPT_PER_BUFFER; - - io_rw_32 *buf_ctrl_reg = is_host ? hwbuf_ctrl_reg_host(ep) : hwbuf_ctrl_reg_device(ep); - hwbuf_ctrl_set(buf_ctrl_reg, 0); - - usb_hw->abort &= ~TU_BIT(ep_id); - - TU_LOG(3, "----SHORT PACKET buffer0 on EP %02X:\r\n", ep->ep_addr); - TU_LOG(3, " BufCtrl: [0] = 0x%04x [1] = 0x%04x\r\n", tu_u32_low16(buf_ctrl), tu_u32_high16(buf_ctrl)); -#endif - } - } -} - -// Returns true if transfer is complete -bool __tusb_irq_path_func(hw_endpoint_xfer_continue)(struct hw_endpoint *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg) { +// Returns true if transfer is complete. +// buf_id: which buffer completed (from BUFF_CPU_SHOULD_HANDLE, only used for double-buffered). +bool __tusb_irq_path_func(hw_endpoint_xfer_continue)(struct hw_endpoint *ep, io_rw_32 *ep_reg, + io_rw_32 *buf_reg, uint8_t buf_id) { hw_endpoint_lock_update(ep, 1); - // Part way through a transfer if (!ep->active) { panic("Can't continue xfer on inactive ep %02X", ep->ep_addr); } - sync_xfer(ep, ep_reg, buf_reg); // Update EP struct from hardware state + const tusb_dir_t dir = tu_edpt_dir(ep->ep_addr); + const bool is_host = rp2usb_is_host_mode(); + const bool is_rx = is_host ? (dir == TUSB_DIR_IN) : (dir == TUSB_DIR_OUT); + const bool is_double = ep_reg != NULL && ((*ep_reg) & EP_CTRL_DOUBLE_BUFFERED_BITS); + + const uint16_t xferred = hwbuf_sync(ep, buf_reg, is_double ? buf_id : 0, is_rx); + bool is_done = (ep->remaining_len == 0); + + if (is_double) { + if (xferred < ep->max_packet_size) { + // Short packet + is_done = true; + } else if (buf_id == 0) { + // buf0 done: wait for buf1, don't start new buffers + hw_endpoint_lock_update(ep, -1); + return false; + } + // buf1 done: is_done determined by remaining_len above + } - // Now we have synced our state with the hardware. Is there more data to transfer? - // If we are done then notify tinyusb - if (ep->remaining_len == 0) { - pico_trace("Completed transfer of %d bytes on ep %02X\r\n", ep->xferred_len, ep->ep_addr); - // Notify caller we are done so it can notify the tinyusb stack - hw_endpoint_lock_update(ep, -1); - return true; - } else { + if (!is_done) { #if TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX if (e15_is_critical_frame_period(ep)) { ep->pending = 1; } else #endif { - hw_endpoint_start_next_buffer(ep, ep_reg, buf_reg); + hw_endpoint_buffer_xact(ep, ep_reg, buf_reg); } } hw_endpoint_lock_update(ep, -1); - // More work to do - return false; + return is_done; } //--------------------------------------------------------------------+ diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.h b/src/portable/raspberrypi/rp2040/rp2040_usb.h index 46bd727c8..c4dd0cb98 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.h +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.h @@ -26,6 +26,8 @@ #if defined(PICO_RP2040_USB_DEVICE_UFRAME_FIX) && !defined(TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX) #define TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX PICO_RP2040_USB_DEVICE_UFRAME_FIX #endif + + #define CFG_TUSB_RP2040_ERRATA_E4_FIX 1 #endif #ifndef TUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX @@ -45,6 +47,10 @@ #define PICO_RP2040_USB_FAST_IRQ 0 #endif +#ifndef CFG_TUSB_RP2040_ERRATA_E4_FIX +#define CFG_TUSB_RP2040_ERRATA_E4_FIX 0 +#endif + #if PICO_RP2040_USB_FAST_IRQ #define __tusb_irq_path_func(x) __no_inline_not_in_flash_func(x) #else @@ -108,8 +114,8 @@ TU_ATTR_ALWAYS_INLINE static inline bool rp2usb_is_host_mode(void) { //--------------------------------------------------------------------+ void hw_endpoint_xfer_start(struct hw_endpoint *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg, uint8_t *buffer, tu_fifo_t *ff, uint16_t total_len); -bool hw_endpoint_xfer_continue(struct hw_endpoint *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg); -void hw_endpoint_start_next_buffer(struct hw_endpoint *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg); +bool hw_endpoint_xfer_continue(struct hw_endpoint *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg, uint8_t buf_id); +void hw_endpoint_buffer_xact(struct hw_endpoint *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg); void hw_endpoint_reset_transfer(struct hw_endpoint *ep); TU_ATTR_ALWAYS_INLINE static inline void hw_endpoint_lock_update(__unused struct hw_endpoint * ep, __unused int delta) { -- cgit v1.3.1 From aeac28e5171442c6aef5ec44f9043d5e74371e41 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 25 Mar 2026 11:23:50 +0700 Subject: update hcd to handle interrupt per buf --- hw/bsp/rp2040/family.c | 6 +- src/portable/raspberrypi/rp2040/dcd_rp2040.c | 7 +-- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 89 ++++++++++++++-------------- src/portable/raspberrypi/rp2040/rp2040_usb.c | 29 +++++---- test/hil/hil_test.py | 57 +++++++++++++++--- 5 files changed, 116 insertions(+), 72 deletions(-) (limited to 'src/portable') diff --git a/hw/bsp/rp2040/family.c b/hw/bsp/rp2040/family.c index adb58449d..c64025036 100644 --- a/hw/bsp/rp2040/family.c +++ b/hw/bsp/rp2040/family.c @@ -165,7 +165,11 @@ void board_init(void) { #if (CFG_TUH_ENABLED && CFG_TUH_RPI_PIO_USB) || (CFG_TUD_ENABLED && CFG_TUD_RPI_PIO_USB) // Set the system clock to a multiple of 12mhz for bit-banging USB with pico-usb - set_sys_clock_khz(120000, true); + #if defined(PICO_RP2350) && PICO_RP2350 == 1 + set_sys_clock_khz(156000, true); // rp2350 default is 150Mhz + #else + set_sys_clock_khz(120000, true); // rp2040 default is 125Mhz + #endif // set_sys_clock_khz(180000, true); // set_sys_clock_khz(192000, true); // set_sys_clock_khz(240000, true); diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index ec73cafc1..0665484a0 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -69,7 +69,7 @@ TU_ATTR_ALWAYS_INLINE static inline hw_endpoint_t *hw_endpoint_get_by_addr(uint8 return hw_endpoint_get(num, dir); } -TU_ATTR_ALWAYS_INLINE static inline io_rw_32 *get_ep_ctrl(const uint8_t epnum, tusb_dir_t dir) { +TU_ATTR_ALWAYS_INLINE static inline io_rw_32 *get_ep_ctrl(uint8_t epnum, tusb_dir_t dir) { if (epnum == 0) { // EP0 has no endpoint control register because the buffer offsets are fixed and always enabled return NULL; @@ -78,7 +78,7 @@ TU_ATTR_ALWAYS_INLINE static inline io_rw_32 *get_ep_ctrl(const uint8_t epnum, t return (dir == TUSB_DIR_IN) ? &ep_ctrl->in : &ep_ctrl->out; } -TU_ATTR_ALWAYS_INLINE static inline io_rw_32 *get_buf_ctrl(const uint8_t epnum, tusb_dir_t dir) { +TU_ATTR_ALWAYS_INLINE static inline io_rw_32 *get_buf_ctrl(uint8_t epnum, tusb_dir_t dir) { struct usb_device_dpram_ep_buf_ctrl *buf_ctrl = &usb_dpram->ep_buf_ctrl[epnum]; return (dir == TUSB_DIR_IN) ? &buf_ctrl->in : &buf_ctrl->out; } @@ -182,6 +182,7 @@ static void __tusb_irq_path_func(handle_hw_buff_status)(void) { // Read which buffer to handle BEFORE clearing buf_status uint8_t buf_id = (usb_hw->buf_cpu_should_handle & bit) ? 1 : 0; usb_hw_clear->buf_status = bit; + buf_status &= ~bit; // IN transfer for even i, OUT transfer for odd i const uint8_t epnum = i >> 1u; @@ -205,8 +206,6 @@ static void __tusb_irq_path_func(handle_hw_buff_status)(void) { hw_endpoint_reset_transfer(ep); dcd_event_xfer_complete(0, ep->ep_addr, xferred_len, XFER_RESULT_SUCCESS, true); } - - buf_status &= ~bit; } } diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index 9ee15d343..4ebdf8284 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -94,7 +94,13 @@ static hw_endpoint_t *edpt_find(uint8_t daddr, uint8_t ep_addr) { return NULL; } -// static hw_endpoint_t* epdt_find_interrupt(uint8_t ) +TU_ATTR_ALWAYS_INLINE static inline io_rw_32 *dpram_int_ep_ctrl(uint8_t int_num) { + return &usbh_dpram->int_ep_ctrl[int_num-1].ctrl; +} + +TU_ATTR_ALWAYS_INLINE static inline io_rw_32 * dpram_int_ep_buffer_ctrl(uint8_t int_num) { + return &usbh_dpram->int_ep_buffer_ctrl[int_num-1].ctrl; +} //--------------------------------------------------------------------+ // @@ -129,57 +135,53 @@ static void __tusb_irq_path_func(hw_xfer_complete)(hw_endpoint_t *ep, xfer_resul } } -static void __tusb_irq_path_func(handle_hwbuf_status_bit)(hw_endpoint_t *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg) { - const bool done = hw_endpoint_xfer_continue(ep, ep_reg, buf_reg); - if (done) { - hw_xfer_complete(ep, XFER_RESULT_SUCCESS); - } -} - static void __tusb_irq_path_func(handle_hwbuf_status)(void) { - uint32_t buf_status = usb_hw->buf_status; pico_trace("buf_status 0x%08lx\n", buf_status); + enum { + BUF_STATUS_EPX = 1u + }; - // Check EPX first - uint32_t bit = 1u; - if (buf_status & bit) { - buf_status &= ~bit; - usb_hw_clear->buf_status = bit; + // Check EPX first (bit 0). EPX is currently single-buffered, always use buf_id=0. + // Double-buffered: if both buffers completed at once, buf_status re-sets + // immediately after clearing (datasheet Table 406). Process the second buffer too. + while (usb_hw->buf_status & BUF_STATUS_EPX) { + const uint8_t buf_id = (usb_hw->buf_cpu_should_handle & BUF_STATUS_EPX) ? 1 : 0; + usb_hw_clear->buf_status = 1u; // clear io_rw_32 *ep_reg = &usbh_dpram->epx_ctrl; io_rw_32 *buf_reg = &usbh_dpram->epx_buf_ctrl; - handle_hwbuf_status_bit(epx, ep_reg, buf_reg); + if (hw_endpoint_xfer_continue(epx, ep_reg, buf_reg, buf_id)) { + hw_xfer_complete(epx, XFER_RESULT_SUCCESS); + } } // Check "interrupt" (asynchronous) endpoints for both IN and OUT - // TODO use clz for better efficiency - for (uint i = 1; i <= USB_HOST_INTERRUPT_ENDPOINTS && buf_status; i++) { - // EPX IN/OUT is bit 0, 1 + uint32_t buf_status = usb_hw->buf_status & ~1u; + while (buf_status) { + // ctz/clz is faster than loop which has only a few bit set in general + const uint8_t idx = (uint8_t) __builtin_ctz(buf_status); + const uint bit = TU_BIT(idx); + usb_hw_clear->buf_status = bit; + buf_status &= ~bit; + + // IN transfer for even i, OUT transfer for odd i + // EPX is bit 0. Bit 1 is not used // IEP1 IN/OUT is bit 2, 3 - // IEP2 IN/OUT is bit 4, 5 - // etc - for (uint j = 0; j < 2; j++) { - bit = 1 << (i * 2 + j); - if (buf_status & bit) { - buf_status &= ~bit; - usb_hw_clear->buf_status = bit; - - for (uint8_t e = 0; e < USB_MAX_ENDPOINTS; e++) { - hw_endpoint_t *ep = &ep_pool[e]; - if (ep->interrupt_num == i) { - io_rw_32 *ep_reg = &usbh_dpram->int_ep_ctrl[ep->interrupt_num - 1].ctrl; - io_rw_32 *buf_reg = &usbh_dpram->int_ep_buffer_ctrl[ep->interrupt_num - 1].ctrl; - handle_hwbuf_status_bit(ep, ep_reg, buf_reg); - break; - } + // IEP2 IN/OUT is bit 4, 5 etc + const uint8_t epnum = idx >> 1u; + for (size_t e = 0; e < TU_ARRAY_SIZE(ep_pool); e++) { + hw_endpoint_t *ep = &ep_pool[e]; + if (ep->interrupt_num == epnum) { + io_rw_32 *ep_reg = dpram_int_ep_ctrl(ep->interrupt_num); + io_rw_32 *buf_reg = dpram_int_ep_buffer_ctrl(ep->interrupt_num); + const bool done = hw_endpoint_xfer_continue(ep, ep_reg, buf_reg, 0); + if (done) { + hw_xfer_complete(ep, XFER_RESULT_SUCCESS); } + break; } } } - - if (buf_status) { - panic("Unhandled buffer %d\n", buf_status); - } } // All non-interrupt endpoints use shared EPX. @@ -491,8 +493,10 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr) { usb_hw_clear->int_ep_ctrl = 1u << ep->interrupt_num; usb_hw->int_ep_addr_ctrl[ep->interrupt_num - 1] = 0; - usbh_dpram->int_ep_buffer_ctrl[ep->interrupt_num - 1].ctrl = 0; - usbh_dpram->int_ep_ctrl[ep->interrupt_num - 1].ctrl = 0; + io_rw_32 *ep_reg = dpram_int_ep_ctrl(ep->interrupt_num); + io_rw_32 *buf_reg = dpram_int_ep_buffer_ctrl(ep->interrupt_num); + *buf_reg = 0; + *ep_reg = 0; } ep->max_packet_size = 0; // mark as unused @@ -547,13 +551,12 @@ TU_ATTR_ALWAYS_INLINE static inline void sie_start_xfer(uint32_t value) { usb_hw->sie_ctrl = value | USB_SIE_CTRL_START_TRANS_BITS; } -// xfer using epx static void edpt_xfer(hw_endpoint_t *ep, uint8_t *buffer, tu_fifo_t *ff, uint16_t total_len) { if (ep->transfer_type == TUSB_XFER_INTERRUPT) { // For interrupt endpoint control and buffer is already configured // Note: Interrupt is single buffered only - io_rw_32 *ep_reg = &usbh_dpram->int_ep_ctrl[ep->interrupt_num - 1].ctrl; - io_rw_32 *buf_reg = &usbh_dpram->int_ep_buffer_ctrl[ep->interrupt_num - 1].ctrl; + io_rw_32 *ep_reg = dpram_int_ep_ctrl(ep->interrupt_num); + io_rw_32 *buf_reg = dpram_int_ep_buffer_ctrl(ep->interrupt_num); hw_endpoint_xfer_start(ep, ep_reg, buf_reg, buffer, ff, total_len); } else { const uint8_t ep_num = tu_edpt_number(ep->ep_addr); diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index ac1536f5b..1e2c4f211 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -124,8 +124,10 @@ void __tusb_irq_path_func(hwbuf_ctrl_update)(io_rw_32 *buf_ctrl_reg, uint32_t an // Section 4.1.2.7.1 (rp2040) / 12.7.3.7.1 (rp2350) Concurrent access: after write to buffer control, // wait for USB controller to see the update before setting AVAILABLE. - // Host also needs this for continuation buffers in multi-packet transfers. - busy_wait_at_least_cycles(12); + // Don't need delay in host mode as host is in charge of when to start the transaction. + if (!is_host) { + busy_wait_at_least_cycles(12); + } } } @@ -193,13 +195,13 @@ void __tusb_irq_path_func(hw_endpoint_buffer_xact)(struct hw_endpoint *ep, io_rw // If both complete simultaneously, buf_status re-sets on next clock (datasheet Table 406). uint32_t ep_ctrl = *ep_reg | EP_CTRL_INTERRUPT_PER_BUFFER; - // Since short packet on buf0 in double-buffered RX: buf1 may already contain data from the - // NEXT transfer (host sent it before CPU processed this IRQ). Cannot safely recover. Avoid by not using double - // buffering for rx transfer - bool force_single = is_rx; - #if CFG_TUH_ENABLED - force_single |= (is_host && ep->interrupt_num != 0); // host interrupt is single only - #endif + // For now: skip double buffered for RX e.g OUT endpoint in Device mode, since host could send < 64 bytes and cause + // short packet on buffer0 + // NOTE: this could happen to Host mode IN endpoint Also, Host mode "interrupt" endpoint hardware is only single + // buffered, + // NOTE2: Currently Host bulk is implemented using "interrupt" endpoint + const bool force_single = (!is_host && is_rx) || (is_host && tu_edpt_number(ep->ep_addr) != 0); + // bool force_single = is_rx || (is_host && ep->interrupt_num != 0); if (ep->remaining_len && !force_single) { // Use buffer 1 (double buffered) if there is still data @@ -318,14 +320,11 @@ bool __tusb_irq_path_func(hw_endpoint_xfer_continue)(struct hw_endpoint *ep, io_ const bool is_rx = is_host ? (dir == TUSB_DIR_IN) : (dir == TUSB_DIR_OUT); const bool is_double = ep_reg != NULL && ((*ep_reg) & EP_CTRL_DOUBLE_BUFFERED_BITS); - const uint16_t xferred = hwbuf_sync(ep, buf_reg, is_double ? buf_id : 0, is_rx); - bool is_done = (ep->remaining_len == 0); + hwbuf_sync(ep, buf_reg, buf_id, is_rx); + const bool is_done = (ep->remaining_len == 0); if (is_double) { - if (xferred < ep->max_packet_size) { - // Short packet - is_done = true; - } else if (buf_id == 0) { + if (buf_id == 0) { // buf0 done: wait for buf1, don't start new buffers hw_endpoint_lock_update(ep, -1); return false; diff --git a/test/hil/hil_test.py b/test/hil/hil_test.py index 4b17bed54..8b0070d40 100755 --- a/test/hil/hil_test.py +++ b/test/hil/hil_test.py @@ -155,8 +155,7 @@ def read_disk_file(uid, lun, fname): def open_mtp_dev(uid): mtp = MTP() - # MTP seems to take a while to enumerate - timeout = 2 * ENUM_TIMEOUT + timeout = ENUM_TIMEOUT while timeout > 0: # unmount gio/gvfs MTP mount which blocks libmtp from accessing the device subprocess.run(f"gio mount -u mtp://TinyUsb_TinyUsb_Device_{uid}/", @@ -607,7 +606,7 @@ def test_host_msc_file_explorer(board): lines = data.decode('utf-8', errors='ignore').splitlines() check_msc_info(lines, msc_devs) - # Send "cat README.TXT" and read response + # Send "cat README.TXT" and check response (optional — file may not exist on all drives) time.sleep(1) ser.reset_input_buffer() for ch in 'cat README.TXT\r': @@ -615,24 +614,20 @@ def test_host_msc_file_explorer(board): ser.flush() time.sleep(0.002) - # Read response resp = b'' t = 10.0 while t > 0: rd = ser.read(max(1, ser.in_waiting)) if rd: resp += rd - # wait for prompt after command output if b'>' in resp and resp.rstrip().endswith(b'>'): break time.sleep(0.05) t -= 0.05 - # Verify response contains README content resp_text = resp.decode('utf-8', errors='ignore') - assert MSC_README_TXT.decode() in resp_text, (f'MSC README.TXT not found in response:\n' - f' received: {resp_text}') - print('README.TXT matched ', end='') + if MSC_README_TXT.decode() in resp_text: + print('README.TXT matched ', end='') # MSC throughput test: send dd command to read sectors time.sleep(0.5) @@ -740,6 +735,50 @@ def test_device_cdc_msc(board): data = read_disk_file(uid, 0, 'README.TXT') assert data == MSC_README_TXT, f'MSC wrong data in README.TXT\n expected: {MSC_README_TXT.decode()}\n received: {data.decode()}' + # MSC dd throughput test: read all sectors then write back same data + dev = get_disk_dev(uid, 'TinyUSB', 0) + timeout = ENUM_TIMEOUT + while timeout > 0: + if os.path.exists(dev): + break + time.sleep(1) + timeout -= 1 + assert timeout > 0, f'Disk {dev} not found for dd test' + + block_count = 16 + block_size = 512 + tmp_file = f'/tmp/msc_dd_{uid}.bin' + + # Read: dd from device to file + ret = run_cmd(f'dd if={dev} of={tmp_file} bs={block_size} count={block_count} iflag=direct 2>&1') + assert ret.returncode == 0, f'dd read failed: {ret.stdout.decode()}' + dd_out = ret.stdout.decode() + read_speed = '' + for line in dd_out.splitlines(): + m = re.search(r'(\d+[\.\d]*\s+[kMG]?B/s)', line) + if m: + read_speed = m.group(1) + break + + # Write back the same data to avoid corrupting the disk + ret = run_cmd(f'dd if={tmp_file} of={dev} bs={block_size} count={block_count} oflag=direct 2>&1') + assert ret.returncode == 0, f'dd write failed: {ret.stdout.decode()}' + dd_out = ret.stdout.decode() + write_speed = '' + for line in dd_out.splitlines(): + m = re.search(r'(\d+[\.\d]*\s+[kMG]?B/s)', line) + if m: + write_speed = m.group(1) + break + + try: + os.remove(tmp_file) + except OSError: + pass + + if read_speed and write_speed: + print(f' dd read: {read_speed}, write: {write_speed}', end='') + def test_device_cdc_msc_freertos(board): test_device_cdc_msc(board) -- cgit v1.3.1 From e81faa22af6369745e4aa0420289a335d2eaa047 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 25 Mar 2026 15:56:09 +0700 Subject: fix e4 incorrect buf with incorrect buf_id = 1 --- src/portable/raspberrypi/rp2040/dcd_rp2040.c | 2 +- src/portable/raspberrypi/rp2040/rp2040_usb.c | 85 +++++++++++++++++++--------- 2 files changed, 58 insertions(+), 29 deletions(-) (limited to 'src/portable') diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index 0665484a0..65871df05 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -368,7 +368,7 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { (void) rh_init; assert(rhport == 0); - TU_LOG(1, "Chip Version B%u\r\n", rp2040_chip_version()); + // TU_LOG(1, "Chip Version B%u\r\n", rp2040_chip_version()); // Reset hardware to default state rp2usb_init(); diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index 1e2c4f211..1d21952a8 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -135,7 +135,7 @@ void __tusb_irq_path_func(hwbuf_ctrl_update)(io_rw_32 *buf_ctrl_reg, uint32_t an } // prepare buffer, move data if tx, return buffer control -static uint32_t __tusb_irq_path_func(hwbuf_prepare)(struct hw_endpoint *ep, uint8_t buf_id, bool is_rx) { +static uint32_t __tusb_irq_path_func(hwbuf_prepare)(struct hw_endpoint *ep, uint8_t *dpram_buf, bool is_rx) { const uint16_t buflen = tu_min16(ep->remaining_len, ep->max_packet_size); ep->remaining_len -= buflen; @@ -148,15 +148,14 @@ static uint32_t __tusb_irq_path_func(hwbuf_prepare)(struct hw_endpoint *ep, uint if (!is_rx) { if (buflen) { // Copy data from user buffer/fifo to hw buffer - uint8_t *hw_buf = ep->dpram_buf + (buf_id << 6); #if CFG_TUD_EDPT_DEDICATED_HWFIFO if (ep->is_xfer_fifo) { // not in sram, may mess up timing with E15 workaround - tu_hwfifo_write_from_fifo(hw_buf, ep->user_fifo, buflen, NULL); + tu_hwfifo_write_from_fifo(dpram_buf, ep->user_fifo, buflen, NULL); } else #endif { - unaligned_memcpy(hw_buf, ep->user_buf, buflen); + unaligned_memcpy(dpram_buf, ep->user_buf, buflen); ep->user_buf += buflen; } } @@ -186,27 +185,40 @@ void __tusb_irq_path_func(hw_endpoint_buffer_xact)(struct hw_endpoint *ep, io_rw is_rx = (dir == TUSB_DIR_OUT); } + // In case short packet on buf0 in double-buffered RX, buf1 may already contain data from the + // NEXT transfer (host sent it before CPU processed this IRQ). Cannot safely recover. Avoid by not using double + // buffering for rx transfer + + // RP2040-E4 (host only): in single-buffered multi-packet transfers, the controller may write completion status to + // BUF1 half instead of BUF0. The side effect that controller can execute an extra packet after writing to BUF1 + // since it leave BUF0 intact, which can be polled before buf_status interrupt is trigger. + // Workaround for the side effect, we will enable double-buffered for rx but only prepare 1 buf at a time. + #if CFG_TUSB_RP2040_ERRATA_E4_FIX + + #endif + // always compute and start with buffer 0 - uint32_t buf_ctrl = hwbuf_prepare(ep, 0, is_rx) | USB_BUF_CTRL_SEL; + uint32_t buf_ctrl = hwbuf_prepare(ep, ep->dpram_buf, is_rx) | USB_BUF_CTRL_SEL; // Device mode EP0 has no endpoint control register if (ep_reg != NULL) { // Each buffer completion triggers its own IRQ. // If both complete simultaneously, buf_status re-sets on next clock (datasheet Table 406). uint32_t ep_ctrl = *ep_reg | EP_CTRL_INTERRUPT_PER_BUFFER; - - // For now: skip double buffered for RX e.g OUT endpoint in Device mode, since host could send < 64 bytes and cause - // short packet on buffer0 - // NOTE: this could happen to Host mode IN endpoint Also, Host mode "interrupt" endpoint hardware is only single - // buffered, - // NOTE2: Currently Host bulk is implemented using "interrupt" endpoint +#if 1 const bool force_single = (!is_host && is_rx) || (is_host && tu_edpt_number(ep->ep_addr) != 0); - // bool force_single = is_rx || (is_host && ep->interrupt_num != 0); +#else + bool force_single = false; // is_rx; + #if CFG_TUH_ENABLED + if (is_host && ep->interrupt_num != 0) { + force_single = true; + } + #endif +#endif if (ep->remaining_len && !force_single) { // Use buffer 1 (double buffered) if there is still data - // TODO: Isochronous for buffer1 bit-field is different than CBI (control bulk, interrupt) - buf_ctrl |= (hwbuf_prepare(ep, 1, is_rx) << 16); + buf_ctrl |= hwbuf_prepare(ep, ep->dpram_buf+64, is_rx) << 16; ep_ctrl |= EP_CTRL_DOUBLE_BUFFERED_BITS; } else { // Single buffered since 1 is enough @@ -216,6 +228,8 @@ void __tusb_irq_path_func(hw_endpoint_buffer_xact)(struct hw_endpoint *ep, io_rw *ep_reg = ep_ctrl; } + // TU_LOG(1, "xact: buf_ctrl = 0x%08lx\r\n", buf_ctrl); + // Finally, write to buffer_control which will trigger the transfer the next time the controller polls this endpoint hwbuf_ctrl_set(buf_reg, buf_ctrl); } @@ -264,13 +278,7 @@ void hw_endpoint_xfer_start(struct hw_endpoint *ep, io_rw_32 *ep_reg, io_rw_32 * } // sync endpoint buffer and return transferred bytes -static uint16_t __tusb_irq_path_func(hwbuf_sync)(hw_endpoint_t *ep, io_rw_32 *buf_ctrl_reg, uint8_t buf_id, - bool is_rx) { - uint32_t buf_ctrl = *buf_ctrl_reg; - if (buf_id) { - buf_ctrl = buf_ctrl >> 16; - } - +static uint16_t __tusb_irq_path_func(hwbuf_sync)(hw_endpoint_t *ep, bool is_rx, uint32_t buf_ctrl, uint8_t *dpram_buf) { const uint16_t xferred_bytes = buf_ctrl & USB_BUF_CTRL_LEN_MASK; if (!is_rx) { @@ -281,16 +289,14 @@ static uint16_t __tusb_irq_path_func(hwbuf_sync)(hw_endpoint_t *ep, io_rw_32 *bu // If we have received some data, so can increase the length // we have received AFTER we have copied it to the user buffer at the appropriate offset assert(buf_ctrl & USB_BUF_CTRL_FULL); - - uint8_t *hw_buf = ep->dpram_buf + buf_id * 64; #if CFG_TUD_EDPT_DEDICATED_HWFIFO if (ep->is_xfer_fifo) { // not in sram, may mess up timing with E15 workaround - tu_hwfifo_read_to_fifo(hw_buf, ep->user_fifo, xferred_bytes, NULL); + tu_hwfifo_read_to_fifo(dpram_buf, ep->user_fifo, xferred_bytes, NULL); } else #endif { - unaligned_memcpy(ep->user_buf, hw_buf, xferred_bytes); + unaligned_memcpy(ep->user_buf, dpram_buf, xferred_bytes); ep->user_buf += xferred_bytes; } } @@ -307,8 +313,7 @@ static uint16_t __tusb_irq_path_func(hwbuf_sync)(hw_endpoint_t *ep, io_rw_32 *bu // Returns true if transfer is complete. // buf_id: which buffer completed (from BUFF_CPU_SHOULD_HANDLE, only used for double-buffered). -bool __tusb_irq_path_func(hw_endpoint_xfer_continue)(struct hw_endpoint *ep, io_rw_32 *ep_reg, - io_rw_32 *buf_reg, uint8_t buf_id) { +bool __tusb_irq_path_func(hw_endpoint_xfer_continue)(struct hw_endpoint *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg, uint8_t buf_id) { hw_endpoint_lock_update(ep, 1); if (!ep->active) { @@ -320,7 +325,31 @@ bool __tusb_irq_path_func(hw_endpoint_xfer_continue)(struct hw_endpoint *ep, io_ const bool is_rx = is_host ? (dir == TUSB_DIR_IN) : (dir == TUSB_DIR_OUT); const bool is_double = ep_reg != NULL && ((*ep_reg) & EP_CTRL_DOUBLE_BUFFERED_BITS); - hwbuf_sync(ep, buf_reg, buf_id, is_rx); + #if CFG_TUSB_RP2040_ERRATA_E4_FIX + const bool need_e4_fix = (is_host && !is_double); + #endif + + // Double-buffered: buf_id from BUFF_CPU_SHOULD_HANDLE indicates which buffer completed. + + // RP2040-E4 (host only): in single-buffered multi-packet transfers, the controller may write completion status to + // BUF1 half instead of BUF0. The side effect that controller can execute an extra packet after writing to BUF1 + // since it leave BUF0 intact, which can be poll before buf_status interrupt is trigger. + // Workaround for the side effect, we will enable double-buffered for rx but only prepare 1 buf at a time. + uint32_t buf_ctrl = *buf_reg; + // TU_LOG(1, "sync: buf_ctrl = 0x%08lx, buf id = %u\r\n", buf_ctrl, buf_id); + + uint8_t* dpram_buf = ep->dpram_buf; + if (buf_id) { + buf_ctrl = buf_ctrl >> 16; + #if CFG_TUSB_RP2040_ERRATA_E4_FIX + if (!need_e4_fix) // incorrect buf_id, buffer pointer is still buf0 + #endif + { + dpram_buf += 64; // buf1 offset + } + } + + hwbuf_sync(ep, is_rx, buf_ctrl, dpram_buf); const bool is_done = (ep->remaining_len == 0); if (is_double) { -- cgit v1.3.1 From 94f48272c79310c5ab47c79c7b57a1be7bdee901 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 26 Mar 2026 19:33:08 +0700 Subject: implement ping-pong double buffered for both tx and rx --- src/portable/raspberrypi/rp2040/dcd_rp2040.c | 77 +++++---- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 13 +- src/portable/raspberrypi/rp2040/rp2040_usb.c | 223 ++++++++++++++++++++------- src/portable/raspberrypi/rp2040/rp2040_usb.h | 65 +++++--- test/hil/hil_test.py | 2 +- 5 files changed, 267 insertions(+), 113 deletions(-) (limited to 'src/portable') diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index 65871df05..d9c30efba 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -92,12 +92,13 @@ static void hw_endpoint_init(hw_endpoint_t *ep, uint8_t ep_addr, uint16_t wMaxPa // Clear existing buffer control state const uint8_t epnum = tu_edpt_number(ep_addr); const tusb_dir_t dir = tu_edpt_dir(ep_addr); - io_rw_32 *buf_ctrl_reg = get_buf_ctrl(epnum, dir); - *buf_ctrl_reg = 0; + io_rw_32 *buf_reg = get_buf_ctrl(epnum, dir); + + *buf_reg = 0; // allocated hw buffer if (epnum == 0) { - // Buffer offset is fixed (also double buffered) + // Buffer offset is fixed (also double buffered) TODO EP0 double buffer ep->dpram_buf = (uint8_t *)&usb_dpram->ep0_buf_a[0]; } else { // round up size to multiple of 64 @@ -107,7 +108,7 @@ static void hw_endpoint_init(hw_endpoint_t *ep, uint8_t ep_addr, uint16_t wMaxPa if (transfer_type == TUSB_XFER_BULK) { size *= 2u; - #if TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX + #if CFG_TUSB_RP2_ERRATA_E15 if (dir == TUSB_DIR_IN) { ep->e15_bulk_in = true; } @@ -127,8 +128,8 @@ static void hw_endpoint_enable(uint8_t epnum, tusb_dir_t dir, uint8_t transfer_t io_rw_32 *ep_reg = get_ep_ctrl(epnum, dir); // Set endpoint control register to enable (EP0 has no endpoint control register) if (ep_reg != NULL) { - const uint32_t ctrl_value = - EP_CTRL_ENABLE_BITS | ((uint32_t)transfer_type << EP_CTRL_BUFFER_TYPE_LSB) | hw_data_offset(dpram_buf); + const uint32_t ctrl_value = EP_CTRL_ENABLE_BITS | EP_CTRL_INTERRUPT_PER_BUFFER | + ((uint32_t)transfer_type << EP_CTRL_BUFFER_TYPE_LSB) | hw_data_offset(dpram_buf); *ep_reg = ctrl_value; } } @@ -179,32 +180,25 @@ static void __tusb_irq_path_func(handle_hw_buff_status)(void) { const uint8_t i = (uint8_t) __builtin_ctz(buf_status); const uint bit = TU_BIT(i); - // Read which buffer to handle BEFORE clearing buf_status - uint8_t buf_id = (usb_hw->buf_cpu_should_handle & bit) ? 1 : 0; - usb_hw_clear->buf_status = bit; - buf_status &= ~bit; - // IN transfer for even i, OUT transfer for odd i - const uint8_t epnum = i >> 1u; - const tusb_dir_t dir = (i & 1u) ? TUSB_DIR_OUT : TUSB_DIR_IN; - hw_endpoint_t *ep = hw_endpoint_get(epnum, dir); - - io_rw_32 *ep_reg = get_ep_ctrl(epnum, dir); - io_rw_32 *buf_reg = get_buf_ctrl(epnum, dir); - bool done = hw_endpoint_xfer_continue(ep, ep_reg, buf_reg, buf_id); + const uint8_t epnum = i >> 1u; + const tusb_dir_t dir = (i & 1u) ? TUSB_DIR_OUT : TUSB_DIR_IN; + hw_endpoint_t *ep = hw_endpoint_get(epnum, dir); + io_rw_32 *ep_reg = get_ep_ctrl(epnum, dir); + io_rw_32 *buf_reg = get_buf_ctrl(epnum, dir); // Double-buffered: if both buffers completed at once, buf_status re-sets // immediately after clearing (datasheet Table 406). Process the second buffer too. - if (!done && (usb_hw->buf_status & bit)) { - buf_id = (usb_hw->buf_cpu_should_handle & bit) ? 1 : 0; + while (usb_hw->buf_status & bit) { + const uint8_t buf_id = (usb_hw->buf_cpu_should_handle & bit) ? 1 : 0; // before clear buf_status usb_hw_clear->buf_status = bit; - done = hw_endpoint_xfer_continue(ep, ep_reg, buf_reg, buf_id); - } + buf_status &= ~bit; - if (done) { - 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); + if (hw_endpoint_xfer_continue(ep, ep_reg, buf_reg, buf_id)) { + 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); + } } } } @@ -244,7 +238,7 @@ static void __tusb_irq_path_func(dcd_rp2040_irq)(void) { handled |= USB_INTF_DEV_SOF_BITS; -#if TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX +#if CFG_TUSB_RP2_ERRATA_E15 // Errata 15 workaround for Device Bulk-In endpoint e15_last_sof = time_us_32(); @@ -260,7 +254,32 @@ static void __tusb_irq_path_func(dcd_rp2040_irq)(void) { ep->pending = 0; io_rw_32 *ep_reg = get_ep_ctrl(i, TUSB_DIR_IN); io_rw_32 *buf_reg = get_buf_ctrl(i, TUSB_DIR_IN); - hw_endpoint_buffer_xact(ep, ep_reg, buf_reg); + io_rw_16 *buf_reg16 = (io_rw_16 *)buf_reg; + + // Check each buffer half: idle when both FULL and AVAIL are clear. + // Use 16-bit writes to avoid clobbering the other half (DPSRAM concurrent access). + const uint16_t busy_mask = USB_BUF_CTRL_FULL | USB_BUF_CTRL_AVAIL; + const bool do_buf0 = !(buf_reg16[0] & busy_mask); + const bool do_buf1 = ep->remaining_len > 0 && !(buf_reg16[1] & busy_mask); + + // Set ep_ctrl BEFORE buf_ctrl (controller reads ep_ctrl to determine double-buffered mode) + if (ep_reg != NULL) { + if (do_buf1) { + *ep_reg |= EP_CTRL_DOUBLE_BUFFERED_BITS; + } else { + *ep_reg &= ~EP_CTRL_DOUBLE_BUFFERED_BITS; + } + } + + if (do_buf0) { + uint16_t buf0 = bufctrl_prepare(ep, ep->dpram_buf, false); + buf0 |= USB_BUF_CTRL_SEL; // reset buffer selector to buf0 + bufctrl_write16(buf_reg16, buf0); + } + if (do_buf1) { + uint16_t buf1 = bufctrl_prepare(ep, ep->dpram_buf + 64, false); + bufctrl_write16(buf_reg16 + 1, buf1); + } } hw_endpoint_lock_update(ep, -1); } @@ -464,7 +483,7 @@ void dcd_sof_enable(uint8_t rhport, bool en) { if (en) { usb_hw_set->inte = USB_INTS_DEV_SOF_BITS; } -#if !TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX + #if !CFG_TUSB_RP2_ERRATA_E15 else { // Don't clear immediately if the SOF workaround is in use. // The SOF handler will conditionally disable the interrupt. diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index 4ebdf8284..3f4c95422 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -351,11 +351,11 @@ static void hw_endpoint_init(hw_endpoint_t *ep, uint8_t dev_addr, const tusb_des // const uint8_t bmInterval = ep_desc->bInterval; ep->max_packet_size = wMaxPacketSize; - ep->ep_addr = ep_addr; - ep->dev_addr = dev_addr; - ep->transfer_type = transfer_type; - ep->need_pre = need_pre(dev_addr); - ep->next_pid = 0u; + ep->ep_addr = ep_addr; + ep->dev_addr = dev_addr; + ep->transfer_type = transfer_type; + ep->need_pre = need_pre(dev_addr); + ep->next_pid = 0u; if (transfer_type != TUSB_XFER_INTERRUPT) { ep->dpram_buf = usbh_dpram->epx_data; @@ -572,8 +572,7 @@ static void edpt_xfer(hw_endpoint_t *ep, uint8_t *buffer, tu_fifo_t *ff, uint16_ // ep control const uint32_t dpram_offset = hw_data_offset(ep->dpram_buf); const uint32_t ep_ctrl = EP_CTRL_ENABLE_BITS | EP_CTRL_INTERRUPT_PER_BUFFER | - ((uint32_t)ep->transfer_type << EP_CTRL_BUFFER_TYPE_LSB) | dpram_offset /*| - (1u << 16)*/; // INTERRUPT_ON_NAK + ((uint32_t)ep->transfer_type << EP_CTRL_BUFFER_TYPE_LSB) | dpram_offset; usbh_dpram->epx_ctrl = ep_ctrl; io_rw_32 *ep_reg = &usbh_dpram->epx_ctrl; diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index 1d21952a8..d0a229785 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -27,18 +27,23 @@ #include "tusb_option.h" -#if CFG_TUSB_MCU == OPT_MCU_RP2040 +#if CFG_TUSB_MCU == OPT_MCU_RP2040 && (CFG_TUD_ENABLED || CFG_TUH_ENABLED) -#include -#include "rp2040_usb.h" + #include + #include "rp2040_usb.h" + + #include "device/dcd.h" + #include "host/hcd.h" //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF PROTOTYPE //--------------------------------------------------------------------+ - #if TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX + #if CFG_TUSB_RP2_ERRATA_E15 static bool e15_is_critical_frame_period(struct hw_endpoint *ep); - #else - #define e15_is_critical_frame_period(x) (false) + #endif + + #if CFG_TUSB_RP2_ERRATA_E2 +static uint8_t rp2040_chipversion = 2; #endif //--------------------------------------------------------------------+ @@ -84,6 +89,10 @@ void rp2usb_init(void) { // Mux the controller to the onboard usb phy usb_hw->muxing = USB_USB_MUXING_TO_PHY_BITS | USB_USB_MUXING_SOFTCON_BITS; + #if CFG_TUSB_RP2_ERRATA_E2 + rp2040_chipversion = rp2040_chip_version(); + #endif + TU_LOG2_INT(sizeof(hw_endpoint_t)); } @@ -134,12 +143,46 @@ void __tusb_irq_path_func(hwbuf_ctrl_update)(io_rw_32 *buf_ctrl_reg, uint32_t an *buf_ctrl_reg = value; } +void __tusb_irq_path_func(bufctrl_write32)(io_rw_32 *buf_reg, uint32_t value) { + const uint32_t current = *buf_reg; + const uint32_t avail_mask = USB_BUF_CTRL_AVAIL | (USB_BUF_CTRL_AVAIL << 16); + if (current & value & avail_mask) { + panic("buf_ctrl @ 0x%lX already available", (uintptr_t)buf_reg); + } + *buf_reg = value & ~USB_BUF_CTRL_AVAIL; // write other bits first + + // Section 4.1.2.7.1 (rp2040) / 12.7.3.7.1 (rp2350) Concurrent access: after write to buffer control, + // wait for USB controller to see the update before setting AVAILABLE. + // Don't need delay in host mode as host is in charge of when to start the transaction. + if (!rp2usb_is_host_mode() && (value & (USB_BUF_CTRL_AVAIL | (USB_BUF_CTRL_AVAIL << 16)))) { + busy_wait_at_least_cycles(12); + } + + *buf_reg = value; // then set AVAILABLE bit (if set) last +} + +void __tusb_irq_path_func(bufctrl_write16)(io_rw_16 *buf_reg16, uint16_t value) { + const uint16_t current = *buf_reg16; + if (current & value & USB_BUF_CTRL_AVAIL) { + panic("buf_ctrl @ 0x%lX already available", (uintptr_t)buf_reg16); + } + *buf_reg16 = value & (uint16_t)~USB_BUF_CTRL_AVAIL; // write other bits first + + // Section 4.1.2.7.1 (rp2040) / 12.7.3.7.1 (rp2350) Concurrent access: after write to buffer control, + // wait for USB controller to see the update before setting AVAILABLE. + // Don't need delay in host mode as host is in charge of when to start the transaction. + if (!rp2usb_is_host_mode() && (value & USB_BUF_CTRL_AVAIL)) { + busy_wait_at_least_cycles(12); + } + *buf_reg16 = value; // then set AVAILABLE bit (if set) last +} + // prepare buffer, move data if tx, return buffer control -static uint32_t __tusb_irq_path_func(hwbuf_prepare)(struct hw_endpoint *ep, uint8_t *dpram_buf, bool is_rx) { +uint16_t __tusb_irq_path_func(bufctrl_prepare)(struct hw_endpoint *ep, uint8_t *dpram_buf, bool is_rx) { const uint16_t buflen = tu_min16(ep->remaining_len, ep->max_packet_size); ep->remaining_len -= buflen; - uint32_t buf_ctrl = buflen | USB_BUF_CTRL_AVAIL; + uint16_t buf_ctrl = buflen | USB_BUF_CTRL_AVAIL; if (ep->next_pid) { buf_ctrl |= USB_BUF_CTRL_DATA1_PID; } @@ -174,8 +217,8 @@ static uint32_t __tusb_irq_path_func(hwbuf_prepare)(struct hw_endpoint *ep, uint } // Start transaction on hw buffer -void __tusb_irq_path_func(hw_endpoint_buffer_xact)(struct hw_endpoint *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg) { - const tusb_dir_t dir = tu_edpt_dir(ep->ep_addr); +void __tusb_irq_path_func(hw_endpoint_buffer_start)(struct hw_endpoint *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg) { + const tusb_dir_t dir = tu_edpt_dir(ep->ep_addr); const bool is_host = rp2usb_is_host_mode(); bool is_rx; @@ -185,29 +228,26 @@ void __tusb_irq_path_func(hw_endpoint_buffer_xact)(struct hw_endpoint *ep, io_rw is_rx = (dir == TUSB_DIR_OUT); } - // In case short packet on buf0 in double-buffered RX, buf1 may already contain data from the - // NEXT transfer (host sent it before CPU processed this IRQ). Cannot safely recover. Avoid by not using double - // buffering for rx transfer - // RP2040-E4 (host only): in single-buffered multi-packet transfers, the controller may write completion status to // BUF1 half instead of BUF0. The side effect that controller can execute an extra packet after writing to BUF1 // since it leave BUF0 intact, which can be polled before buf_status interrupt is trigger. // Workaround for the side effect, we will enable double-buffered for rx but only prepare 1 buf at a time. - #if CFG_TUSB_RP2040_ERRATA_E4_FIX + #if CFG_TUSB_RP2_ERRATA_E4 #endif // always compute and start with buffer 0 - uint32_t buf_ctrl = hwbuf_prepare(ep, ep->dpram_buf, is_rx) | USB_BUF_CTRL_SEL; + uint32_t buf_ctrl = bufctrl_prepare(ep, ep->dpram_buf, is_rx) | USB_BUF_CTRL_SEL; // Device mode EP0 has no endpoint control register if (ep_reg != NULL) { // Each buffer completion triggers its own IRQ. // If both complete simultaneously, buf_status re-sets on next clock (datasheet Table 406). - uint32_t ep_ctrl = *ep_reg | EP_CTRL_INTERRUPT_PER_BUFFER; -#if 1 - const bool force_single = (!is_host && is_rx) || (is_host && tu_edpt_number(ep->ep_addr) != 0); -#else + uint32_t ep_ctrl = *ep_reg; + #if 1 + const bool force_single = // (!is_host && is_rx) || + (is_host && tu_edpt_number(ep->ep_addr) != 0); + #else bool force_single = false; // is_rx; #if CFG_TUH_ENABLED if (is_host && ep->interrupt_num != 0) { @@ -218,7 +258,7 @@ void __tusb_irq_path_func(hw_endpoint_buffer_xact)(struct hw_endpoint *ep, io_rw if (ep->remaining_len && !force_single) { // Use buffer 1 (double buffered) if there is still data - buf_ctrl |= hwbuf_prepare(ep, ep->dpram_buf+64, is_rx) << 16; + buf_ctrl |= (uint32_t)bufctrl_prepare(ep, ep->dpram_buf + 64, is_rx) << 16; ep_ctrl |= EP_CTRL_DOUBLE_BUFFERED_BITS; } else { // Single buffered since 1 is enough @@ -228,10 +268,8 @@ void __tusb_irq_path_func(hw_endpoint_buffer_xact)(struct hw_endpoint *ep, io_rw *ep_reg = ep_ctrl; } - // TU_LOG(1, "xact: buf_ctrl = 0x%08lx\r\n", buf_ctrl); - // Finally, write to buffer_control which will trigger the transfer the next time the controller polls this endpoint - hwbuf_ctrl_set(buf_reg, buf_ctrl); + bufctrl_write32(buf_reg, buf_ctrl); } void hw_endpoint_xfer_start(struct hw_endpoint *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg, uint8_t *buffer, tu_fifo_t *ff, @@ -261,7 +299,41 @@ void hw_endpoint_xfer_start(struct hw_endpoint *ep, io_rw_32 *ep_reg, io_rw_32 * ep->is_xfer_fifo = false; } - #if TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX + if (ep->future_len > 0) { + // only on rx endpoint + const uint8_t future_len = ep->future_len; + memcpy(ep->user_buf, ep->dpram_buf + (ep->future_bufid << 6), future_len); + ep->xferred_len += future_len; + ep->remaining_len -= future_len; + ep->user_buf += future_len; + + ep->future_len = 0; + ep->future_bufid = 0; + + if (ep->remaining_len == 0) { + // all data has been received, no need to start hw transfer + ep->active = false; + const uint16_t xferred_len = ep->xferred_len; + hw_endpoint_reset_transfer(ep); + + const bool is_host = rp2usb_is_host_mode(); + #if CFG_TUH_ENABLED + if (is_host) { + hcd_event_xfer_complete(0, ep->ep_addr, xferred_len, XFER_RESULT_SUCCESS, false); + } + #endif + #if CFG_TUD_ENABLED + if (!is_host) { + dcd_event_xfer_complete(0, ep->ep_addr, xferred_len, XFER_RESULT_SUCCESS, false); + } + #endif + + hw_endpoint_lock_update(ep, -1); + return; + } + } + + #if CFG_TUSB_RP2_ERRATA_E15 if (ep->e15_bulk_in) { usb_hw_set->inte = USB_INTS_DEV_SOF_BITS; } @@ -271,14 +343,14 @@ void hw_endpoint_xfer_start(struct hw_endpoint *ep, io_rw_32 *ep_reg, io_rw_32 * } else #endif { - hw_endpoint_buffer_xact(ep, ep_reg, buf_reg); + hw_endpoint_buffer_start(ep, ep_reg, buf_reg); } hw_endpoint_lock_update(ep, -1); } // sync endpoint buffer and return transferred bytes -static uint16_t __tusb_irq_path_func(hwbuf_sync)(hw_endpoint_t *ep, bool is_rx, uint32_t buf_ctrl, uint8_t *dpram_buf) { +static uint16_t __tusb_irq_path_func(hwbuf_sync)(hw_endpoint_t *ep, bool is_rx, uint16_t buf_ctrl, uint8_t *dpram_buf) { const uint16_t xferred_bytes = buf_ctrl & USB_BUF_CTRL_LEN_MASK; if (!is_rx) { @@ -316,16 +388,23 @@ static uint16_t __tusb_irq_path_func(hwbuf_sync)(hw_endpoint_t *ep, bool is_rx, bool __tusb_irq_path_func(hw_endpoint_xfer_continue)(struct hw_endpoint *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg, uint8_t buf_id) { hw_endpoint_lock_update(ep, 1); + const tusb_dir_t dir = tu_edpt_dir(ep->ep_addr); + const bool is_host = rp2usb_is_host_mode(); + const bool is_rx = is_host ? (dir == TUSB_DIR_IN) : (dir == TUSB_DIR_OUT); + + io_rw_16 *buf_reg16 = (io_rw_16 *)buf_reg; + uint16_t buf_ctrl16 = *(buf_reg16 + buf_id); + if (!ep->active) { - panic("Can't continue xfer on inactive ep %02X", ep->ep_addr); + // probably land here due to short packet on rx with double buffered + hw_endpoint_lock_update(ep, -1); + return false; } - const tusb_dir_t dir = tu_edpt_dir(ep->ep_addr); - const bool is_host = rp2usb_is_host_mode(); - const bool is_rx = is_host ? (dir == TUSB_DIR_IN) : (dir == TUSB_DIR_OUT); - const bool is_double = ep_reg != NULL && ((*ep_reg) & EP_CTRL_DOUBLE_BUFFERED_BITS); + const bool is_double = (ep_reg != NULL && ((*ep_reg) & EP_CTRL_DOUBLE_BUFFERED_BITS)); + (void)is_double; - #if CFG_TUSB_RP2040_ERRATA_E4_FIX + #if CFG_TUSB_RP2_ERRATA_E4 const bool need_e4_fix = (is_host && !is_double); #endif @@ -335,40 +414,73 @@ bool __tusb_irq_path_func(hw_endpoint_xfer_continue)(struct hw_endpoint *ep, io_ // BUF1 half instead of BUF0. The side effect that controller can execute an extra packet after writing to BUF1 // since it leave BUF0 intact, which can be poll before buf_status interrupt is trigger. // Workaround for the side effect, we will enable double-buffered for rx but only prepare 1 buf at a time. - uint32_t buf_ctrl = *buf_reg; - // TU_LOG(1, "sync: buf_ctrl = 0x%08lx, buf id = %u\r\n", buf_ctrl, buf_id); - uint8_t* dpram_buf = ep->dpram_buf; if (buf_id) { - buf_ctrl = buf_ctrl >> 16; - #if CFG_TUSB_RP2040_ERRATA_E4_FIX - if (!need_e4_fix) // incorrect buf_id, buffer pointer is still buf0 + #if CFG_TUSB_RP2_ERRATA_E4 + if (!need_e4_fix) // incorrect buf_id, buffer pointer is still buf0 #endif { dpram_buf += 64; // buf1 offset } } - hwbuf_sync(ep, is_rx, buf_ctrl, dpram_buf); - const bool is_done = (ep->remaining_len == 0); + const uint16_t xact_bytes = hwbuf_sync(ep, is_rx, buf_ctrl16, dpram_buf); + const bool is_last = buf_ctrl16 & USB_BUF_CTRL_LAST; + const bool is_short = xact_bytes < ep->max_packet_size; + const bool is_done = is_short || (buf_ctrl16 & USB_BUF_CTRL_LAST); + + // short packet on rx with double buffer: abort the other half (if not last) and reset double-buffer state. + // The other buffer may be: (a) still AVAIL, (b) in-progress (controller receiving), or (c) already completed. + // We must abort to safely reclaim it. If it has valid data (FULL), save as future for the next transfer. + // After abort, zero buf_ctrl + if (is_short && is_double && is_rx && !is_last) { + io_rw_16 *buf_reg16_other = buf_reg16 + (buf_id ^ 1); + const uint32_t abort_bit = TU_BIT((tu_edpt_number(ep->ep_addr) << 1) | (dir ? 0 : 1)); + + #if CFG_TUSB_RP2_ERRATA_E2 + if (rp2040_chipversion >= 2) + #endif + { + usb_hw_set->abort = abort_bit; + while ((usb_hw->abort_done & abort_bit) != abort_bit) {} + } - if (is_double) { - if (buf_id == 0) { - // buf0 done: wait for buf1, don't start new buffers - hw_endpoint_lock_update(ep, -1); - return false; + // After abort, check if the other buffer received valid data + const uint16_t buf_ctrl16_other = *buf_reg16_other; + if (buf_ctrl16_other & USB_BUF_CTRL_FULL) { + // Host already sent data into this buffer (e.g. write payload right after short CBW). + // Save it for the next transfer. + ep->future_len = (uint8_t)(buf_ctrl16_other & USB_BUF_CTRL_LEN_MASK); + ep->future_bufid = buf_id ^ 1; + // buff_status will be clear by the next run + } else { + ep->next_pid ^= 1u; + } + + *buf_reg = 0; // reset buffer control + + #if CFG_TUSB_RP2_ERRATA_E2 + if (rp2040_chipversion >= 2) + #endif + { + usb_hw_clear->abort_done = abort_bit; + usb_hw_clear->abort = abort_bit; } - // buf1 done: is_done determined by remaining_len above + + hw_endpoint_lock_update(ep, -1); + return true; } - if (!is_done) { - #if TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX + if (!is_done && ep->remaining_len > 0) { + #if CFG_TUSB_RP2_ERRATA_E15 if (e15_is_critical_frame_period(ep)) { ep->pending = 1; } else #endif { - hw_endpoint_buffer_xact(ep, ep_reg, buf_reg); + // ping-pong: do 16-bit write since controller is accessing the other half + const uint16_t buf_ctrl16_new = bufctrl_prepare(ep, dpram_buf, is_rx); + bufctrl_write16(buf_reg16 + buf_id, buf_ctrl16_new); } } @@ -380,7 +492,7 @@ bool __tusb_irq_path_func(hw_endpoint_xfer_continue)(struct hw_endpoint *ep, io_ // Errata 15 //--------------------------------------------------------------------+ -#if TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX +#if CFG_TUSB_RP2_ERRATA_E15 // E15 is fixed with RP2350 /* Don't mark IN buffers as available during the last 200us of a full-speed @@ -410,16 +522,15 @@ static bool __tusb_irq_path_func(e15_is_critical_frame_period)(struct hw_endpoin /* Avoid the last 200us (uframe 6.5-7) of a frame, up to the EOF2 point. * The device state machine cannot recover from receiving an incorrect PID - * when it is expecting an ACK. - */ + * when it is expecting an ACK. */ uint32_t delta = time_us_32() - e15_last_sof; if (delta < 800 || delta > 998) { return false; } - TU_LOG(3, "Avoiding sof %lu now %lu last %lu\r\n", (usb_hw->sof_rd + 1) & USB_SOF_RD_BITS, time_us_32(), - e15_last_sof); + // TU_LOG(3, "Avoiding sof %lu now %lu last %lu\r\n", (usb_hw->sof_rd + 1) & USB_SOF_RD_BITS, time_us_32(), + // e15_last_sof); return true; } -#endif // TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX + #endif #endif diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.h b/src/portable/raspberrypi/rp2040/rp2040_usb.h index c4dd0cb98..8b0fc83b7 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.h +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.h @@ -15,46 +15,57 @@ #error TinyUSB device and host mode not supported at the same time #endif -// E5 and E15 only apply to RP2040 #if defined(PICO_RP2040) && PICO_RP2040 == 1 - // RP2040 E5: USB device fails to exit RESET state on busy USB bus. + // RP2040-E2 USB device endpoint abort is not cleared. + #define CFG_TUSB_RP2_ERRATA_E2 1 + + // RP2040-E4: USB host writes to upper half of buffer status in single buffered mode. + #define CFG_TUSB_RP2_ERRATA_E4 1 + + // RP2040-E5: USB device fails to exit RESET state on busy USB bus. #if defined(PICO_RP2040_USB_DEVICE_ENUMERATION_FIX) && !defined(TUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX) #define TUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX PICO_RP2040_USB_DEVICE_ENUMERATION_FIX #endif - // RP2040 E15: USB Device controller will hang if certain bus errors occur during an IN transfer. - #if defined(PICO_RP2040_USB_DEVICE_UFRAME_FIX) && !defined(TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX) - #define TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX PICO_RP2040_USB_DEVICE_UFRAME_FIX + // RP2040-E15: USB Device controller will hang if certain bus errors occur during an IN transfer. + #ifndef CFG_TUSB_RP2_ERRATA_E15 + #if defined(PICO_RP2040_USB_DEVICE_UFRAME_FIX) + #define CFG_TUSB_RP2_ERRATA_E15 PICO_RP2040_USB_DEVICE_UFRAME_FIX + #elif defined(TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX) + #define CFG_TUSB_RP2_ERRATA_E15 TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX + #endif #endif +#endif - #define CFG_TUSB_RP2040_ERRATA_E4_FIX 1 +#ifndef CFG_TUSB_RP2_ERRATA_E2 + #define CFG_TUSB_RP2_ERRATA_E2 0 +#endif + +#ifndef CFG_TUSB_RP2_ERRATA_E4 + #define CFG_TUSB_RP2_ERRATA_E4 0 #endif #ifndef TUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX #define TUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX 0 #endif -#ifndef TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX - #define TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX 0 +#ifndef CFG_TUSB_RP2_ERRATA_E15 + #define CFG_TUSB_RP2_ERRATA_E15 0 #endif -#if TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX +#if CFG_TUSB_RP2_ERRATA_E15 #undef PICO_RP2040_USB_FAST_IRQ #define PICO_RP2040_USB_FAST_IRQ 1 #endif #ifndef PICO_RP2040_USB_FAST_IRQ -#define PICO_RP2040_USB_FAST_IRQ 0 -#endif - -#ifndef CFG_TUSB_RP2040_ERRATA_E4_FIX -#define CFG_TUSB_RP2040_ERRATA_E4_FIX 0 + #define PICO_RP2040_USB_FAST_IRQ 0 #endif #if PICO_RP2040_USB_FAST_IRQ -#define __tusb_irq_path_func(x) __no_inline_not_in_flash_func(x) + #define __tusb_irq_path_func(x) __no_inline_not_in_flash_func(x) #else -#define __tusb_irq_path_func(x) x + #define __tusb_irq_path_func(x) x #endif //--------------------------------------------------------------------+ @@ -66,6 +77,12 @@ #define pico_info(...) TU_LOG(2, __VA_ARGS__) #define pico_trace(...) TU_LOG(3, __VA_ARGS__) +enum { + EPSTATE_IDLE = 0, + EPSTATE_ACTIVE, + EPSTATE_PENDING, +}; + // Hardware information per endpoint typedef struct hw_endpoint { uint8_t ep_addr; @@ -74,8 +91,11 @@ typedef struct hw_endpoint { uint8_t pending; // Transfer scheduled but not active bool is_xfer_fifo; // transfer using fifo -#if TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX - bool e15_bulk_in; // Errata15 device bulk in + uint8_t future_bufid; + uint8_t future_len; + +#if CFG_TUSB_RP2_ERRATA_E15 + bool e15_bulk_in; // Errata15 device bulk in #endif #if CFG_TUH_ENABLED @@ -98,7 +118,7 @@ typedef struct hw_endpoint { } hw_endpoint_t; -#if TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX +#if CFG_TUSB_RP2_ERRATA_E15 extern volatile uint32_t e15_last_sof; #endif @@ -115,7 +135,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool rp2usb_is_host_mode(void) { void hw_endpoint_xfer_start(struct hw_endpoint *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg, uint8_t *buffer, tu_fifo_t *ff, uint16_t total_len); bool hw_endpoint_xfer_continue(struct hw_endpoint *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg, uint8_t buf_id); -void hw_endpoint_buffer_xact(struct hw_endpoint *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg); +void hw_endpoint_buffer_start(struct hw_endpoint *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg); void hw_endpoint_reset_transfer(struct hw_endpoint *ep); TU_ATTR_ALWAYS_INLINE static inline void hw_endpoint_lock_update(__unused struct hw_endpoint * ep, __unused int delta) { @@ -129,6 +149,11 @@ TU_ATTR_ALWAYS_INLINE static inline void hw_endpoint_lock_update(__unused struct //--------------------------------------------------------------------+ void hwbuf_ctrl_update(io_rw_32 *buf_ctrl_reg, uint32_t and_mask, uint32_t or_mask); +void bufctrl_write32(io_rw_32 *buf_reg, uint32_t value); +void bufctrl_write16(io_rw_16 *buf_reg16, uint16_t value); + +uint16_t bufctrl_prepare(struct hw_endpoint *ep, uint8_t *dpram_buf, bool is_rx); + TU_ATTR_ALWAYS_INLINE static inline void hwbuf_ctrl_set(io_rw_32 *buf_ctrl_reg, uint32_t value) { hwbuf_ctrl_update(buf_ctrl_reg, 0, value); } diff --git a/test/hil/hil_test.py b/test/hil/hil_test.py index 8b0070d40..154a251c1 100755 --- a/test/hil/hil_test.py +++ b/test/hil/hil_test.py @@ -50,7 +50,7 @@ import ctypes from pymtp import MTP import string -ENUM_TIMEOUT = 30 +ENUM_TIMEOUT = 10 STATUS_OK = "\033[32mOK\033[0m" STATUS_FAILED = "\033[31mFailed\033[0m" -- cgit v1.3.1 From 9b3d51790f19676c6863f3362608794eff02bfa2 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 26 Mar 2026 22:41:28 +0700 Subject: clean up hw_endpoint_open(), still has issue with E15 and ping-pong (slow read). --- src/portable/raspberrypi/rp2040/dcd_rp2040.c | 182 +++++++++++++-------------- src/portable/raspberrypi/rp2040/rp2040_usb.c | 58 ++++----- src/portable/raspberrypi/rp2040/rp2040_usb.h | 2 +- test/hil/hil_test.py | 28 ++--- 4 files changed, 126 insertions(+), 144 deletions(-) (limited to 'src/portable') diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index d9c30efba..15ac97dde 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -83,24 +83,28 @@ TU_ATTR_ALWAYS_INLINE static inline io_rw_32 *get_buf_ctrl(uint8_t epnum, tusb_d return (dir == TUSB_DIR_IN) ? &buf_ctrl->in : &buf_ctrl->out; } -// main processing for dcd_edpt_iso_activate -static void hw_endpoint_init(hw_endpoint_t *ep, uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t transfer_type) { - ep->ep_addr = ep_addr; - ep->next_pid = 0u; - ep->max_packet_size = wMaxPacketSize; - - // Clear existing buffer control state +// Init and enable endpoint +static void hw_endpoint_open(uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t transfer_type, bool ep_enabled) { const uint8_t epnum = tu_edpt_number(ep_addr); const tusb_dir_t dir = tu_edpt_dir(ep_addr); - io_rw_32 *buf_reg = get_buf_ctrl(epnum, dir); - *buf_reg = 0; + hw_endpoint_t *ep = hw_endpoint_get(epnum, dir); + ep->ep_addr = ep_addr; + ep->next_pid = 0u; + ep->max_packet_size = wMaxPacketSize; + + // Clear existing buffer control state + io_rw_32 *buf_reg = get_buf_ctrl(epnum, dir); + *buf_reg = 0; // allocated hw buffer if (epnum == 0) { - // Buffer offset is fixed (also double buffered) TODO EP0 double buffer + // Buffer offset is fixed (2 buffer allocated). + // Note: Only single buffer for EP since Double buffered RX can be troublesome with future data. ep->dpram_buf = (uint8_t *)&usb_dpram->ep0_buf_a[0]; } else { + uint32_t ep_ctrl = EP_CTRL_INTERRUPT_PER_BUFFER | ((uint32_t)transfer_type << EP_CTRL_BUFFER_TYPE_LSB); + // round up size to multiple of 64 uint16_t size = (uint16_t)tu_round_up(wMaxPacketSize, 64); @@ -119,31 +123,18 @@ static void hw_endpoint_init(hw_endpoint_t *ep, uint8_t ep_addr, uint16_t wMaxPa ep->dpram_buf = hw_buffer_ptr; hw_buffer_ptr += size; + ep_ctrl |= hw_data_offset(ep->dpram_buf); + if (ep_enabled) { + ep_ctrl |= EP_CTRL_ENABLE_BITS; + } + + *get_ep_ctrl(epnum, dir) = ep_ctrl; + hard_assert(hw_buffer_ptr < usb_dpram->epx_data + sizeof(usb_dpram->epx_data)); pico_info(" Allocated %d bytes (0x%p)\r\n", size, ep->dpram_buf); } } -static void hw_endpoint_enable(uint8_t epnum, tusb_dir_t dir, uint8_t transfer_type, uint8_t *dpram_buf) { - io_rw_32 *ep_reg = get_ep_ctrl(epnum, dir); - // Set endpoint control register to enable (EP0 has no endpoint control register) - if (ep_reg != NULL) { - const uint32_t ctrl_value = EP_CTRL_ENABLE_BITS | EP_CTRL_INTERRUPT_PER_BUFFER | - ((uint32_t)transfer_type << EP_CTRL_BUFFER_TYPE_LSB) | hw_data_offset(dpram_buf); - *ep_reg = ctrl_value; - } -} - -// Init and enable endpoint -static void hw_endpoint_open(uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t transfer_type) { - const uint8_t epnum = tu_edpt_number(ep_addr); - const tusb_dir_t dir = tu_edpt_dir(ep_addr); - hw_endpoint_t *ep = hw_endpoint_get(epnum, dir); - - hw_endpoint_init(ep, ep_addr, wMaxPacketSize, transfer_type); - hw_endpoint_enable(epnum, dir, transfer_type, ep->dpram_buf); -} - static void hw_endpoint_abort_xfer(struct hw_endpoint* ep) { // Abort any pending transfer const uint8_t dir = (uint8_t)tu_edpt_dir(ep->ep_addr); @@ -231,101 +222,101 @@ static void __tusb_irq_path_func(reset_non_control_endpoints)(void) { static void __tusb_irq_path_func(dcd_rp2040_irq)(void) { const uint32_t status = usb_hw->ints; - uint32_t handled = 0; if (status & USB_INTF_DEV_SOF_BITS) { - bool keep_sof_alive = false; + uint32_t sof_count = usb_hw->sof_rd & USB_SOF_RD_BITS; // clear interrupt by reading SOF_RD + + #if CFG_TUSB_RP2_ERRATA_E15 + e15_last_sof = time_us_32(); // timing critical + #endif + + dcd_event_sof(0, sof_count, true); + } + + // xfer events are handled before setup req. So if a transfer completes immediately + // before closing the EP, the events will be delivered in same order. + if (status & USB_INTS_BUFF_STATUS_BITS) { + handle_hw_buff_status(); + } - handled |= USB_INTF_DEV_SOF_BITS; + if (status & USB_INTS_SETUP_REQ_BITS) { + const uint8_t *setup = remove_volatile_cast(const uint8_t *, &usb_dpram->setup_packet); -#if CFG_TUSB_RP2_ERRATA_E15 - // Errata 15 workaround for Device Bulk-In endpoint - e15_last_sof = time_us_32(); + // reset pid to both 1 (data and ack) + reset_ep0(); + // Pass setup packet to tiny usb + dcd_event_setup_received(0, setup, true); + usb_hw_clear->sie_status = USB_SIE_STATUS_SETUP_REC_BITS; + } + + // Errata 15 workaround for Device Bulk-In endpoint, must be after BUF_STATUS interrupt to sync buf control first + if (status & USB_INTF_DEV_SOF_BITS) { + bool keep_sof_alive = false; + + #if CFG_TUSB_RP2_ERRATA_E15 for (uint8_t i = 0; i < USB_MAX_ENDPOINTS; i++) { struct hw_endpoint *ep = hw_endpoint_get(i, TUSB_DIR_IN); // Active Bulk IN endpoint requires SOF if (ep->e15_bulk_in && ep->active) { keep_sof_alive = true; - hw_endpoint_lock_update(ep, 1); + if (ep->pending) { - ep->pending = 0; - io_rw_32 *ep_reg = get_ep_ctrl(i, TUSB_DIR_IN); - io_rw_32 *buf_reg = get_buf_ctrl(i, TUSB_DIR_IN); - io_rw_16 *buf_reg16 = (io_rw_16 *)buf_reg; + ep->pending = 0; + io_rw_32 *buf_reg32 = (io_rw_32 *)get_buf_ctrl(i, TUSB_DIR_IN); + io_rw_16 *buf_reg16 = (io_rw_16 *)buf_reg32; // Check each buffer half: idle when both FULL and AVAIL are clear. // Use 16-bit writes to avoid clobbering the other half (DPSRAM concurrent access). - const uint16_t busy_mask = USB_BUF_CTRL_FULL | USB_BUF_CTRL_AVAIL; - const bool do_buf0 = !(buf_reg16[0] & busy_mask); - const bool do_buf1 = ep->remaining_len > 0 && !(buf_reg16[1] & busy_mask); - - // Set ep_ctrl BEFORE buf_ctrl (controller reads ep_ctrl to determine double-buffered mode) - if (ep_reg != NULL) { - if (do_buf1) { - *ep_reg |= EP_CTRL_DOUBLE_BUFFERED_BITS; - } else { - *ep_reg &= ~EP_CTRL_DOUBLE_BUFFERED_BITS; - } + enum { + BUSY_MASK = USB_BUF_CTRL_FULL | USB_BUF_CTRL_AVAIL + }; + + uint16_t buf0, buf1; + const bool use_buf0 = !(buf_reg16[0] & BUSY_MASK); + + if (use_buf0) { + buf0 = bufctrl_prepare16(ep, ep->dpram_buf, false); } - if (do_buf0) { - uint16_t buf0 = bufctrl_prepare(ep, ep->dpram_buf, false); - buf0 |= USB_BUF_CTRL_SEL; // reset buffer selector to buf0 - bufctrl_write16(buf_reg16, buf0); + const bool use_buf1 = (ep->remaining_len > 0) && !(buf_reg16[1] & BUSY_MASK); + if (use_buf1) { + buf1 = bufctrl_prepare16(ep, ep->dpram_buf + 64, false); } - if (do_buf1) { - uint16_t buf1 = bufctrl_prepare(ep, ep->dpram_buf + 64, false); + + if (use_buf0 && use_buf1) { + buf0 |= USB_BUF_CTRL_SEL; // reset to buf0 since order of complete is not guaranteed + bufctrl_write32(buf_reg32, buf0 | ((uint32_t)buf1 << 16)); + } else if (use_buf0) { + bufctrl_write16(buf_reg16, buf0); + } else if (use_buf1) { bufctrl_write16(buf_reg16 + 1, buf1); } } + hw_endpoint_lock_update(ep, -1); } } -#endif + #endif // disable SOF interrupt if it is used for RESUME in remote wakeup if (!keep_sof_alive && !_sof_enable) { usb_hw_clear->inte = USB_INTS_DEV_SOF_BITS; } - - dcd_event_sof(0, usb_hw->sof_rd & USB_SOF_RD_BITS, true); - } - - // xfer events are handled before setup req. So if a transfer completes immediately - // before closing the EP, the events will be delivered in same order. - if (status & USB_INTS_BUFF_STATUS_BITS) { - handled |= USB_INTS_BUFF_STATUS_BITS; - handle_hw_buff_status(); - } - - if (status & USB_INTS_SETUP_REQ_BITS) { - handled |= USB_INTS_SETUP_REQ_BITS; - uint8_t const* setup = remove_volatile_cast(uint8_t const*, &usb_dpram->setup_packet); - - // reset pid to both 1 (data and ack) - reset_ep0(); - - // Pass setup packet to tiny usb - dcd_event_setup_received(0, setup, true); - usb_hw_clear->sie_status = USB_SIE_STATUS_SETUP_REC_BITS; } -#if FORCE_VBUS_DETECT == 0 + #if FORCE_VBUS_DETECT == 0 // Since we force VBUS detect On, device will always think it is connected and // couldn't distinguish between disconnect and suspend if (status & USB_INTS_DEV_CONN_DIS_BITS) { - handled |= USB_INTS_DEV_CONN_DIS_BITS; - if (usb_hw->sie_status & USB_SIE_STATUS_CONNECTED_BITS) { // Connected: nothing to do } else { // Disconnected dcd_event_bus_signal(0, DCD_EVENT_UNPLUGGED, true); } - usb_hw_clear->sie_status = USB_SIE_STATUS_CONNECTED_BITS; } #endif @@ -333,9 +324,6 @@ static void __tusb_irq_path_func(dcd_rp2040_irq)(void) { // SE0 for 2.5 us or more (will last at least 10ms) if (status & USB_INTS_BUS_RESET_BITS) { pico_trace("BUS RESET\r\n"); - - handled |= USB_INTS_BUS_RESET_BITS; - usb_hw->dev_addr_ctrl = 0; reset_non_control_endpoints(); dcd_event_bus_reset(0, TUSB_SPEED_FULL, true); @@ -358,20 +346,15 @@ static void __tusb_irq_path_func(dcd_rp2040_irq)(void) { * being disconnected and suspended. */ if (status & USB_INTS_DEV_SUSPEND_BITS) { - handled |= USB_INTS_DEV_SUSPEND_BITS; dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true); usb_hw_clear->sie_status = USB_SIE_STATUS_SUSPENDED_BITS; } if (status & USB_INTS_DEV_RESUME_FROM_HOST_BITS) { - handled |= USB_INTS_DEV_RESUME_FROM_HOST_BITS; dcd_event_bus_signal(0, DCD_EVENT_RESUME, true); usb_hw_clear->sie_status = USB_SIE_STATUS_RESUME_BITS; } - if (status ^ handled) { - panic("Unhandled IRQ 0x%x\n", (uint) (status ^ handled)); - } } /*------------------------------------------------------------------*/ @@ -401,8 +384,8 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { // Init control endpoints tu_memclr(hw_endpoints[0], 2 * sizeof(hw_endpoint_t)); - hw_endpoint_open(0x0, 64, TUSB_XFER_CONTROL); - hw_endpoint_open(0x80, 64, TUSB_XFER_CONTROL); + hw_endpoint_open(0x0, 64, TUSB_XFER_CONTROL, false); + hw_endpoint_open(0x80, 64, TUSB_XFER_CONTROL, false); // Init non-control endpoints reset_non_control_endpoints(); @@ -508,7 +491,7 @@ void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const* req bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const* desc_edpt) { (void) rhport; const uint8_t xfer_type = desc_edpt->bmAttributes.xfer; - hw_endpoint_open(desc_edpt->bEndpointAddress, tu_edpt_packet_size(desc_edpt), xfer_type); + hw_endpoint_open(desc_edpt->bEndpointAddress, tu_edpt_packet_size(desc_edpt), xfer_type, true); return true; } @@ -516,8 +499,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const* desc_edpt) { // Some MCU need manual packet buffer allocation, we allocate the largest size to avoid clustering bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { (void)rhport; - struct hw_endpoint *ep = hw_endpoint_get_by_addr(ep_addr); - hw_endpoint_init(ep, ep_addr, largest_packet_size, TUSB_XFER_ISOCHRONOUS); + hw_endpoint_open(ep_addr, largest_packet_size, TUSB_XFER_ISOCHRONOUS, false); return true; } @@ -534,7 +516,11 @@ bool dcd_edpt_iso_activate(uint8_t rhport, const tusb_desc_endpoint_t *ep_desc) } ep->max_packet_size = ep_desc->wMaxPacketSize; - hw_endpoint_enable(epnum, dir, TUSB_XFER_ISOCHRONOUS, ep->dpram_buf); + // enable endpoint + io_rw_32 *ep_reg = get_ep_ctrl(epnum, dir); + if (ep_reg != NULL) { + *ep_reg |= EP_CTRL_ENABLE_BITS; + } return true; } diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index d0a229785..433bd261d 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -39,7 +39,7 @@ // MACRO CONSTANT TYPEDEF PROTOTYPE //--------------------------------------------------------------------+ #if CFG_TUSB_RP2_ERRATA_E15 -static bool e15_is_critical_frame_period(struct hw_endpoint *ep); +static bool e15_is_critical_frame_period(void); #endif #if CFG_TUSB_RP2_ERRATA_E2 @@ -178,7 +178,7 @@ void __tusb_irq_path_func(bufctrl_write16)(io_rw_16 *buf_reg16, uint16_t value) } // prepare buffer, move data if tx, return buffer control -uint16_t __tusb_irq_path_func(bufctrl_prepare)(struct hw_endpoint *ep, uint8_t *dpram_buf, bool is_rx) { +uint16_t __tusb_irq_path_func(bufctrl_prepare16)(struct hw_endpoint *ep, uint8_t *dpram_buf, bool is_rx) { const uint16_t buflen = tu_min16(ep->remaining_len, ep->max_packet_size); ep->remaining_len -= buflen; @@ -237,16 +237,12 @@ void __tusb_irq_path_func(hw_endpoint_buffer_start)(struct hw_endpoint *ep, io_r #endif // always compute and start with buffer 0 - uint32_t buf_ctrl = bufctrl_prepare(ep, ep->dpram_buf, is_rx) | USB_BUF_CTRL_SEL; + uint32_t buf_ctrl = bufctrl_prepare16(ep, ep->dpram_buf, is_rx) | USB_BUF_CTRL_SEL; - // Device mode EP0 has no endpoint control register + // Note: device EP0 does not have an endpoint control register if (ep_reg != NULL) { - // Each buffer completion triggers its own IRQ. - // If both complete simultaneously, buf_status re-sets on next clock (datasheet Table 406). - uint32_t ep_ctrl = *ep_reg; #if 1 - const bool force_single = // (!is_host && is_rx) || - (is_host && tu_edpt_number(ep->ep_addr) != 0); + const bool force_single = (is_host && tu_edpt_number(ep->ep_addr) != 0); #else bool force_single = false; // is_rx; #if CFG_TUH_ENABLED @@ -256,15 +252,15 @@ void __tusb_irq_path_func(hw_endpoint_buffer_start)(struct hw_endpoint *ep, io_r #endif #endif + uint32_t ep_ctrl = *ep_reg; if (ep->remaining_len && !force_single) { // Use buffer 1 (double buffered) if there is still data - buf_ctrl |= (uint32_t)bufctrl_prepare(ep, ep->dpram_buf + 64, is_rx) << 16; + buf_ctrl |= (uint32_t)bufctrl_prepare16(ep, ep->dpram_buf + 64, is_rx) << 16; ep_ctrl |= EP_CTRL_DOUBLE_BUFFERED_BITS; } else { - // Single buffered since 1 is enough + // Only buf0 used: clear DOUBLE_BUFFERED so controller doesn't toggle buffer selector ep_ctrl &= ~EP_CTRL_DOUBLE_BUFFERED_BITS; } - *ep_reg = ep_ctrl; } @@ -336,16 +332,17 @@ void hw_endpoint_xfer_start(struct hw_endpoint *ep, io_rw_32 *ep_reg, io_rw_32 * #if CFG_TUSB_RP2_ERRATA_E15 if (ep->e15_bulk_in) { usb_hw_set->inte = USB_INTS_DEV_SOF_BITS; - } - if (e15_is_critical_frame_period(ep)) { - ep->pending = 1; // skip transfer if we are in critical frame period - } else - #endif - { - hw_endpoint_buffer_start(ep, ep_reg, buf_reg); + // skip transfer if we are in critical frame period + if (e15_is_critical_frame_period()) { + ep->pending = 1; + hw_endpoint_lock_update(ep, -1); + return; + } } + #endif + hw_endpoint_buffer_start(ep, ep_reg, buf_reg); hw_endpoint_lock_update(ep, -1); } @@ -454,7 +451,7 @@ bool __tusb_irq_path_func(hw_endpoint_xfer_continue)(struct hw_endpoint *ep, io_ ep->future_bufid = buf_id ^ 1; // buff_status will be clear by the next run } else { - ep->next_pid ^= 1u; + ep->next_pid ^= 1u; // roll back pid if aborted } *buf_reg = 0; // reset buffer control @@ -473,13 +470,17 @@ bool __tusb_irq_path_func(hw_endpoint_xfer_continue)(struct hw_endpoint *ep, io_ if (!is_done && ep->remaining_len > 0) { #if CFG_TUSB_RP2_ERRATA_E15 - if (e15_is_critical_frame_period(ep)) { + if (ep->e15_bulk_in && e15_is_critical_frame_period()) { + // mark as pending if matches E15 condition ep->pending = 1; + } else if (ep->e15_bulk_in && ep->pending) { + // if already pending, meaning the other buf completes first, don't arm buffer, let SOF handle it + // do nothing } else #endif { - // ping-pong: do 16-bit write since controller is accessing the other half - const uint16_t buf_ctrl16_new = bufctrl_prepare(ep, dpram_buf, is_rx); + // ping-pong: arm the completed buffer with new data + const uint16_t buf_ctrl16_new = bufctrl_prepare16(ep, dpram_buf, is_rx); bufctrl_write16(buf_reg16 + buf_id, buf_ctrl16_new); } } @@ -492,7 +493,7 @@ bool __tusb_irq_path_func(hw_endpoint_xfer_continue)(struct hw_endpoint *ep, io_ // Errata 15 //--------------------------------------------------------------------+ -#if CFG_TUSB_RP2_ERRATA_E15 + #if CFG_TUSB_RP2_ERRATA_E15 // E15 is fixed with RP2350 /* Don't mark IN buffers as available during the last 200us of a full-speed @@ -513,13 +514,8 @@ bool __tusb_irq_path_func(hw_endpoint_xfer_continue)(struct hw_endpoint *ep, io_ volatile uint32_t e15_last_sof = 0; -// check if we need to apply Errata 15 workaround : i.e -// Endpoint is BULK IN and is currently in critical frame period i.e 20% of last usb frame -static bool __tusb_irq_path_func(e15_is_critical_frame_period)(struct hw_endpoint* ep) { - if (!ep->e15_bulk_in) { - return false; - } - +// check if it is currently in critical frame period i.e 20% of last usb frame +static bool __tusb_irq_path_func(e15_is_critical_frame_period)(void) { /* Avoid the last 200us (uframe 6.5-7) of a frame, up to the EOF2 point. * The device state machine cannot recover from receiving an incorrect PID * when it is expecting an ACK. */ diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.h b/src/portable/raspberrypi/rp2040/rp2040_usb.h index 8b0fc83b7..7b79cd2b1 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.h +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.h @@ -152,7 +152,7 @@ void hwbuf_ctrl_update(io_rw_32 *buf_ctrl_reg, uint32_t and_mask, uint32_t or_ma void bufctrl_write32(io_rw_32 *buf_reg, uint32_t value); void bufctrl_write16(io_rw_16 *buf_reg16, uint16_t value); -uint16_t bufctrl_prepare(struct hw_endpoint *ep, uint8_t *dpram_buf, bool is_rx); +uint16_t bufctrl_prepare16(struct hw_endpoint *ep, uint8_t *dpram_buf, bool is_rx); TU_ATTR_ALWAYS_INLINE static inline void hwbuf_ctrl_set(io_rw_32 *buf_ctrl_reg, uint32_t value) { hwbuf_ctrl_update(buf_ctrl_reg, 0, value); diff --git a/test/hil/hil_test.py b/test/hil/hil_test.py index 154a251c1..04dd4e2bc 100755 --- a/test/hil/hil_test.py +++ b/test/hil/hil_test.py @@ -749,27 +749,27 @@ def test_device_cdc_msc(board): block_size = 512 tmp_file = f'/tmp/msc_dd_{uid}.bin' + # dd reports speed based on payload only. Each block also transfers 31-byte CBW + 13-byte CSW on USB. + scsi_ratio = (block_size + 31 + 13) / block_size + + def parse_dd_speed(dd_output): + """Parse dd output, return USB-adjusted speed string""" + for line in dd_output.splitlines(): + m = re.search(r'([\d.]+)\s+([kMG]?B/s)', line) + if m: + speed_val = float(m.group(1)) * scsi_ratio + return f'{speed_val:.1f} {m.group(2)}' + return '' + # Read: dd from device to file ret = run_cmd(f'dd if={dev} of={tmp_file} bs={block_size} count={block_count} iflag=direct 2>&1') assert ret.returncode == 0, f'dd read failed: {ret.stdout.decode()}' - dd_out = ret.stdout.decode() - read_speed = '' - for line in dd_out.splitlines(): - m = re.search(r'(\d+[\.\d]*\s+[kMG]?B/s)', line) - if m: - read_speed = m.group(1) - break + read_speed = parse_dd_speed(ret.stdout.decode()) # Write back the same data to avoid corrupting the disk ret = run_cmd(f'dd if={tmp_file} of={dev} bs={block_size} count={block_count} oflag=direct 2>&1') assert ret.returncode == 0, f'dd write failed: {ret.stdout.decode()}' - dd_out = ret.stdout.decode() - write_speed = '' - for line in dd_out.splitlines(): - m = re.search(r'(\d+[\.\d]*\s+[kMG]?B/s)', line) - if m: - write_speed = m.group(1) - break + write_speed = parse_dd_speed(ret.stdout.decode()) try: os.remove(tmp_file) -- cgit v1.3.1 From dd08939f68cd5e41f45a942efee41dba85110619 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 27 Mar 2026 13:11:53 +0700 Subject: fix E15 workaround issue with out of order in double buffer. device bulk rx/tx ping-pong double buffered all working well --- src/portable/raspberrypi/rp2040/dcd_rp2040.c | 29 ++++++++++++---------------- 1 file changed, 12 insertions(+), 17 deletions(-) (limited to 'src/portable') diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index 15ac97dde..ea791f4f6 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -265,7 +265,8 @@ static void __tusb_irq_path_func(dcd_rp2040_irq)(void) { if (ep->pending) { ep->pending = 0; - io_rw_32 *buf_reg32 = (io_rw_32 *)get_buf_ctrl(i, TUSB_DIR_IN); + + io_rw_32 *buf_reg32 = get_buf_ctrl(i, TUSB_DIR_IN); io_rw_16 *buf_reg16 = (io_rw_16 *)buf_reg32; // Check each buffer half: idle when both FULL and AVAIL are clear. @@ -274,24 +275,18 @@ static void __tusb_irq_path_func(dcd_rp2040_irq)(void) { BUSY_MASK = USB_BUF_CTRL_FULL | USB_BUF_CTRL_AVAIL }; - uint16_t buf0, buf1; - const bool use_buf0 = !(buf_reg16[0] & BUSY_MASK); - - if (use_buf0) { - buf0 = bufctrl_prepare16(ep, ep->dpram_buf, false); - } - - const bool use_buf1 = (ep->remaining_len > 0) && !(buf_reg16[1] & BUSY_MASK); - if (use_buf1) { - buf1 = bufctrl_prepare16(ep, ep->dpram_buf + 64, false); - } + const bool buf0_idle = !(buf_reg16[0] & BUSY_MASK); + const bool buf1_idle = (ep->remaining_len > 0) && !(buf_reg16[1] & BUSY_MASK); - if (use_buf0 && use_buf1) { - buf0 |= USB_BUF_CTRL_SEL; // reset to buf0 since order of complete is not guaranteed - bufctrl_write32(buf_reg32, buf0 | ((uint32_t)buf1 << 16)); - } else if (use_buf0) { + if (buf0_idle && buf1_idle) { + // both are idle, start fresh + io_rw_32 *ep_reg = get_ep_ctrl(i, TUSB_DIR_IN); + hw_endpoint_buffer_start(ep, ep_reg, buf_reg32); + } else if (buf0_idle) { + uint16_t buf0 = bufctrl_prepare16(ep, ep->dpram_buf, false); bufctrl_write16(buf_reg16, buf0); - } else if (use_buf1) { + } else if (buf1_idle) { + uint16_t buf1 = bufctrl_prepare16(ep, ep->dpram_buf + 64, false); bufctrl_write16(buf_reg16 + 1, buf1); } } -- cgit v1.3.1 From d9d28b7e94aac295e08db5fff8649e1467a37399 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 27 Mar 2026 17:14:37 +0700 Subject: rename and clean up --- src/portable/raspberrypi/rp2040/dcd_rp2040.c | 33 ++-- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 235 ++++++++++++++------------- src/portable/raspberrypi/rp2040/rp2040_usb.c | 83 +++------- src/portable/raspberrypi/rp2040/rp2040_usb.h | 27 +-- 4 files changed, 159 insertions(+), 219 deletions(-) (limited to 'src/portable') diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index ea791f4f6..b52c3114f 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -148,14 +148,9 @@ static void hw_endpoint_abort_xfer(struct hw_endpoint* ep) { while ((usb_hw->abort_done & abort_mask) != abort_mask) {} } - uint32_t buf_ctrl = USB_BUF_CTRL_SEL; // reset to buffer 0 - if (ep->next_pid) { - buf_ctrl |= USB_BUF_CTRL_DATA1_PID; - } - - io_rw_32 *buf_ctrl_reg = get_buf_ctrl(epnum, dir); - hwbuf_ctrl_set(buf_ctrl_reg, buf_ctrl); - hw_endpoint_reset_transfer(ep); + io_rw_32 *buf_reg = get_buf_ctrl(epnum, dir); + *buf_reg = 0; // clear buffer control + rp2usb_reset_transfer(ep); if (rp2040_chip_version() >= 2) { usb_hw_clear->abort_done = abort_mask; @@ -185,9 +180,9 @@ static void __tusb_irq_path_func(handle_hw_buff_status)(void) { usb_hw_clear->buf_status = bit; buf_status &= ~bit; - if (hw_endpoint_xfer_continue(ep, ep_reg, buf_reg, buf_id)) { + if (rp2usb_xfer_continue(ep, ep_reg, buf_reg, buf_id)) { const uint16_t xferred_len = ep->xferred_len; - hw_endpoint_reset_transfer(ep); + rp2usb_reset_transfer(ep); dcd_event_xfer_complete(0, ep->ep_addr, xferred_len, XFER_RESULT_SUCCESS, true); } } @@ -281,7 +276,7 @@ static void __tusb_irq_path_func(dcd_rp2040_irq)(void) { if (buf0_idle && buf1_idle) { // both are idle, start fresh io_rw_32 *ep_reg = get_ep_ctrl(i, TUSB_DIR_IN); - hw_endpoint_buffer_start(ep, ep_reg, buf_reg32); + rp2usb_buffer_start(ep, ep_reg, buf_reg32); } else if (buf0_idle) { uint16_t buf0 = bufctrl_prepare16(ep, ep->dpram_buf, false); bufctrl_write16(buf_reg16, buf0); @@ -534,7 +529,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to hw_endpoint_t *ep = hw_endpoint_get(epnum, dir); io_rw_32 *ep_reg = get_ep_ctrl(epnum, dir); io_rw_32 *buf_reg = get_buf_ctrl(epnum, dir); - hw_endpoint_xfer_start(ep, ep_reg, buf_reg, buffer, NULL, total_bytes); + rp2usb_xfer_start(ep, ep_reg, buf_reg, buffer, NULL, total_bytes); return true; } @@ -545,7 +540,7 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t *ff, uint16_t hw_endpoint_t *ep = hw_endpoint_get(epnum, dir); io_rw_32 *ep_reg = get_ep_ctrl(epnum, dir); io_rw_32 *buf_reg = get_buf_ctrl(epnum, dir); - hw_endpoint_xfer_start(ep, ep_reg, buf_reg, NULL, ff, total_bytes); + rp2usb_xfer_start(ep, ep_reg, buf_reg, NULL, ff, total_bytes); return true; } #endif @@ -554,15 +549,17 @@ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { (void)rhport; const uint8_t epnum = tu_edpt_number(ep_addr); const tusb_dir_t dir = tu_edpt_dir(ep_addr); + hw_endpoint_t *ep = hw_endpoint_get(epnum, dir); if (epnum == 0) { // A stall on EP0 has to be armed so it can be cleared on the next setup packet usb_hw_set->ep_stall_arm = (dir == TUSB_DIR_IN) ? USB_EP_STALL_ARM_EP0_IN_BITS : USB_EP_STALL_ARM_EP0_OUT_BITS; } - // stall and clear current pending buffer, may need to use EP_ABORT - io_rw_32 *buf_ctrl_reg = get_buf_ctrl(epnum, dir); - hwbuf_ctrl_set(buf_ctrl_reg, USB_BUF_CTRL_STALL); + // abort first then stall and clear current pending buffer + hw_endpoint_abort_xfer(ep); + io_rw_32 *buf_reg = get_buf_ctrl(epnum, dir); + *buf_reg = USB_BUF_CTRL_STALL; } void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { @@ -573,8 +570,8 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { if (epnum != 0) { struct hw_endpoint* ep = hw_endpoint_get(epnum, dir); ep->next_pid = 0; // reset data toggle - io_rw_32 *buf_ctrl_reg = get_buf_ctrl(epnum, dir); - hwbuf_ctrl_clear_mask(buf_ctrl_reg, USB_BUF_CTRL_STALL); + io_rw_32 *buf_reg = get_buf_ctrl(epnum, dir); + *buf_reg = 0; } } diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index 3f4c95422..379ba075d 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -119,14 +119,14 @@ TU_ATTR_ALWAYS_INLINE static inline bool need_pre(uint8_t dev_addr) { // forward declaration static void __tusb_irq_path_func(edpt_schedule_next)(void); TU_ATTR_ALWAYS_INLINE static inline void sie_start_xfer(uint32_t value); -static void edpt_xfer(hw_endpoint_t *ep, uint8_t *buffer, tu_fifo_t *ff, uint16_t total_len); +static void epx_xfer(hw_endpoint_t *ep, uint8_t *buffer, tu_fifo_t *ff, uint16_t total_len); static void __tusb_irq_path_func(hw_xfer_complete)(hw_endpoint_t *ep, xfer_result_t xfer_result) { // Mark transfer as done before we tell the tinyusb stack uint8_t dev_addr = ep->dev_addr; uint8_t ep_addr = ep->ep_addr; uint xferred_len = ep->xferred_len; - hw_endpoint_reset_transfer(ep); + rp2usb_reset_transfer(ep); hcd_event_xfer_complete(dev_addr, ep_addr, xferred_len, xfer_result, true); // Schedule next pending EPX transfer (only for non-interrupt endpoints) @@ -150,7 +150,7 @@ static void __tusb_irq_path_func(handle_hwbuf_status)(void) { io_rw_32 *ep_reg = &usbh_dpram->epx_ctrl; io_rw_32 *buf_reg = &usbh_dpram->epx_buf_ctrl; - if (hw_endpoint_xfer_continue(epx, ep_reg, buf_reg, buf_id)) { + if (rp2usb_xfer_continue(epx, ep_reg, buf_reg, buf_id)) { hw_xfer_complete(epx, XFER_RESULT_SUCCESS); } } @@ -174,7 +174,7 @@ static void __tusb_irq_path_func(handle_hwbuf_status)(void) { if (ep->interrupt_num == epnum) { io_rw_32 *ep_reg = dpram_int_ep_ctrl(ep->interrupt_num); io_rw_32 *buf_reg = dpram_int_ep_buffer_ctrl(ep->interrupt_num); - const bool done = hw_endpoint_xfer_continue(ep, ep_reg, buf_reg, 0); + const bool done = rp2usb_xfer_continue(ep, ep_reg, buf_reg, 0); if (done) { hw_xfer_complete(ep, XFER_RESULT_SUCCESS); } @@ -185,8 +185,7 @@ static void __tusb_irq_path_func(handle_hwbuf_status)(void) { } // All non-interrupt endpoints use shared EPX. -// Forward declared above hw_xfer_complete, defined after edpt_xfer below. - +// Forward declared above hw_xfer_complete, defined after epx_xfer below. // Save current EPX context, mark pending, switch to next_ep static void __tusb_irq_path_func(epx_switch_ep)(hw_endpoint_t *next_ep) { const uint32_t buf_ctrl = usbh_dpram->epx_buf_ctrl; @@ -214,7 +213,7 @@ static void __tusb_irq_path_func(epx_switch_ep)(hw_endpoint_t *next_ep) { } else { uint16_t prev_xferred = next_ep->xferred_len; next_ep->pending = 0; - edpt_xfer(next_ep, next_ep->user_buf, NULL, next_ep->remaining_len); + epx_xfer(next_ep, next_ep->user_buf, NULL, next_ep->remaining_len); epx->xferred_len += prev_xferred; } } @@ -344,57 +343,6 @@ void __tusb_irq_path_func(hcd_int_handler)(uint8_t rhport, bool in_isr) { hcd_rp2040_irq(); } -static void hw_endpoint_init(hw_endpoint_t *ep, uint8_t dev_addr, const tusb_desc_endpoint_t *ep_desc) { - const uint8_t ep_addr = ep_desc->bEndpointAddress; - const uint16_t wMaxPacketSize = tu_edpt_packet_size(ep_desc); - const uint8_t transfer_type = ep_desc->bmAttributes.xfer; - // const uint8_t bmInterval = ep_desc->bInterval; - - ep->max_packet_size = wMaxPacketSize; - ep->ep_addr = ep_addr; - ep->dev_addr = dev_addr; - ep->transfer_type = transfer_type; - ep->need_pre = need_pre(dev_addr); - ep->next_pid = 0u; - - if (transfer_type != TUSB_XFER_INTERRUPT) { - ep->dpram_buf = usbh_dpram->epx_data; - } else { - // from 15 interrupt endpoints pool - uint8_t int_idx; - for (int_idx = 0; int_idx < USB_HOST_INTERRUPT_ENDPOINTS; int_idx++) { - if (!tu_bit_test(usb_hw->int_ep_ctrl, 1 + int_idx)) { - ep->interrupt_num = int_idx + 1; - break; - } - } - assert(int_idx < USB_HOST_INTERRUPT_ENDPOINTS); - assert(ep_desc->bInterval > 0); - - //------------- dpram buf -------------// - // 15x64 last bytes of DPRAM for interrupt endpoint buffers - ep->dpram_buf = (uint8_t *)(USBCTRL_DPRAM_BASE + USB_DPRAM_MAX - (int_idx + 1u) * 64u); - uint32_t ep_ctrl = EP_CTRL_ENABLE_BITS | EP_CTRL_INTERRUPT_PER_BUFFER | - (TUSB_XFER_INTERRUPT << EP_CTRL_BUFFER_TYPE_LSB) | hw_data_offset(ep->dpram_buf) | - (uint32_t)((ep_desc->bInterval - 1) << EP_CTRL_HOST_INTERRUPT_INTERVAL_LSB); - usbh_dpram->int_ep_ctrl[int_idx].ctrl = ep_ctrl; - - //------------- address control -------------// - const uint8_t epnum = tu_edpt_number(ep_addr); - uint32_t addr_ctrl = (uint32_t)(dev_addr | (epnum << USB_ADDR_ENDP1_ENDPOINT_LSB)); - if (tu_edpt_dir(ep_addr) == TUSB_DIR_OUT) { - addr_ctrl |= USB_ADDR_ENDP1_INTEP_DIR_BITS; - } - if (ep->need_pre) { - addr_ctrl |= USB_ADDR_ENDP1_INTEP_PREAMBLE_BITS; - } - usb_hw->int_ep_addr_ctrl[int_idx] = addr_ctrl; - - // Finally, activate interrupt endpoint - usb_hw_set->int_ep_ctrl = 1u << ep->interrupt_num; - } -} - //--------------------------------------------------------------------+ // HCD API //--------------------------------------------------------------------+ @@ -528,7 +476,55 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, const tusb_desc_endpoint_t pico_trace("hcd_edpt_open dev_addr %d, ep_addr %d\n", dev_addr, ep_desc->bEndpointAddress); hw_endpoint_t *ep = edpt_alloc(); TU_ASSERT(ep); - hw_endpoint_init(ep, dev_addr, ep_desc); + + const uint8_t ep_addr = ep_desc->bEndpointAddress; + const uint16_t max_packet_size = tu_edpt_packet_size(ep_desc); + const uint8_t transfer_type = ep_desc->bmAttributes.xfer; + // const uint8_t bmInterval = ep_desc->bInterval; + + ep->max_packet_size = max_packet_size; + ep->ep_addr = ep_addr; + ep->dev_addr = dev_addr; + ep->transfer_type = transfer_type; + ep->need_pre = need_pre(dev_addr); + ep->next_pid = 0u; + + if (transfer_type != TUSB_XFER_INTERRUPT) { + ep->dpram_buf = usbh_dpram->epx_data; + } else { + // from 15 interrupt endpoints pool + uint8_t int_idx; + for (int_idx = 0; int_idx < USB_HOST_INTERRUPT_ENDPOINTS; int_idx++) { + if (!tu_bit_test(usb_hw->int_ep_ctrl, 1 + int_idx)) { + ep->interrupt_num = int_idx + 1; + break; + } + } + assert(int_idx < USB_HOST_INTERRUPT_ENDPOINTS); + assert(ep_desc->bInterval > 0); + + //------------- dpram buf -------------// + // 15x64 last bytes of DPRAM for interrupt endpoint buffers + ep->dpram_buf = (uint8_t *)(USBCTRL_DPRAM_BASE + USB_DPRAM_MAX - (int_idx + 1u) * 64u); + uint32_t ep_ctrl = EP_CTRL_ENABLE_BITS | EP_CTRL_INTERRUPT_PER_BUFFER | + (TUSB_XFER_INTERRUPT << EP_CTRL_BUFFER_TYPE_LSB) | hw_data_offset(ep->dpram_buf) | + (uint32_t)((ep_desc->bInterval - 1) << EP_CTRL_HOST_INTERRUPT_INTERVAL_LSB); + usbh_dpram->int_ep_ctrl[int_idx].ctrl = ep_ctrl; + + //------------- address control -------------// + const uint8_t epnum = tu_edpt_number(ep_addr); + uint32_t addr_ctrl = (uint32_t)(dev_addr | (epnum << USB_ADDR_ENDP1_ENDPOINT_LSB)); + if (tu_edpt_dir(ep_addr) == TUSB_DIR_OUT) { + addr_ctrl |= USB_ADDR_ENDP1_INTEP_DIR_BITS; + } + if (ep->need_pre) { + addr_ctrl |= USB_ADDR_ENDP1_INTEP_PREAMBLE_BITS; + } + usb_hw->int_ep_addr_ctrl[int_idx] = addr_ctrl; + + // Finally, activate interrupt endpoint + usb_hw_set->int_ep_ctrl = 1u << ep->interrupt_num; + } return true; } @@ -551,54 +547,51 @@ TU_ATTR_ALWAYS_INLINE static inline void sie_start_xfer(uint32_t value) { usb_hw->sie_ctrl = value | USB_SIE_CTRL_START_TRANS_BITS; } -static void edpt_xfer(hw_endpoint_t *ep, uint8_t *buffer, tu_fifo_t *ff, uint16_t total_len) { - if (ep->transfer_type == TUSB_XFER_INTERRUPT) { - // For interrupt endpoint control and buffer is already configured - // Note: Interrupt is single buffered only - io_rw_32 *ep_reg = dpram_int_ep_ctrl(ep->interrupt_num); - io_rw_32 *buf_reg = dpram_int_ep_buffer_ctrl(ep->interrupt_num); - hw_endpoint_xfer_start(ep, ep_reg, buf_reg, buffer, ff, total_len); - } else { - const uint8_t ep_num = tu_edpt_number(ep->ep_addr); - const tusb_dir_t ep_dir = tu_edpt_dir(ep->ep_addr); - - // RP2040-E4: USB host writes status to upper half of buffer control in single buffered mode. - // The buffer selector toggles even in single-buffered mode, so the previous transfer's status - // may have been written to BUF1 half, leaving BUF0 with stale AVAILABLE bit. Clear it here. -#if defined(PICO_RP2040) && PICO_RP2040 == 1 - usbh_dpram->epx_buf_ctrl = 0; -#endif +// start a transfer on epx endpoint +static void epx_xfer(hw_endpoint_t *ep, uint8_t *buffer, tu_fifo_t *ff, uint16_t total_len) { + const uint8_t ep_num = tu_edpt_number(ep->ep_addr); + const tusb_dir_t ep_dir = tu_edpt_dir(ep->ep_addr); - // ep control - const uint32_t dpram_offset = hw_data_offset(ep->dpram_buf); - const uint32_t ep_ctrl = EP_CTRL_ENABLE_BITS | EP_CTRL_INTERRUPT_PER_BUFFER | - ((uint32_t)ep->transfer_type << EP_CTRL_BUFFER_TYPE_LSB) | dpram_offset; - usbh_dpram->epx_ctrl = ep_ctrl; + // RP2040-E4: USB host writes status to upper half of buffer control in single buffered mode. + // The buffer selector toggles even in single-buffered mode, so the previous transfer's status + // may have been written to BUF1 half, leaving BUF0 with stale AVAILABLE bit. Clear it here. + #if defined(PICO_RP2040) && PICO_RP2040 == 1 + usbh_dpram->epx_buf_ctrl = 0; + #endif - io_rw_32 *ep_reg = &usbh_dpram->epx_ctrl; - io_rw_32 *buf_reg = &usbh_dpram->epx_buf_ctrl; - hw_endpoint_xfer_start(ep, ep_reg, buf_reg, buffer, ff, total_len); + // ep control + const uint32_t dpram_offset = hw_data_offset(ep->dpram_buf); + const uint32_t ep_ctrl = EP_CTRL_ENABLE_BITS | EP_CTRL_INTERRUPT_PER_BUFFER | + ((uint32_t)ep->transfer_type << EP_CTRL_BUFFER_TYPE_LSB) | dpram_offset; + usbh_dpram->epx_ctrl = ep_ctrl; - // addr control - usb_hw->dev_addr_ctrl = (uint32_t)(ep->dev_addr | (ep_num << USB_ADDR_ENDP_ENDPOINT_LSB)); + io_rw_32 *ep_reg = &usbh_dpram->epx_ctrl; + io_rw_32 *buf_reg = &usbh_dpram->epx_buf_ctrl; + rp2usb_xfer_start(ep, ep_reg, buf_reg, buffer, ff, total_len); - epx = ep; + // addr control + usb_hw->dev_addr_ctrl = (uint32_t)(ep->dev_addr | (ep_num << USB_ADDR_ENDP_ENDPOINT_LSB)); - // start transfer - const uint32_t sie_ctrl = (ep_dir ? USB_SIE_CTRL_RECEIVE_DATA_BITS : USB_SIE_CTRL_SEND_DATA_BITS) | - (ep->need_pre ? USB_SIE_CTRL_PREAMBLE_EN_BITS : 0); - sie_start_xfer(sie_ctrl); - } + epx = ep; + + // start transfer + const uint32_t sie_ctrl = (ep_dir ? USB_SIE_CTRL_RECEIVE_DATA_BITS : USB_SIE_CTRL_SEND_DATA_BITS) | + (ep->need_pre ? USB_SIE_CTRL_PREAMBLE_EN_BITS : 0); + sie_start_xfer(sie_ctrl); } // Schedule next pending EPX transfer from ISR context static void __tusb_irq_path_func(edpt_schedule_next)(void) { // EPX may already be active if the completion callback started a new transfer - if (epx->active) return; + if (epx->active) { + return; + } for (uint i = 0; i < TU_ARRAY_SIZE(ep_pool); i++) { hw_endpoint_t *ep = &ep_pool[i]; - if (ep->pending == 0) continue; + if (ep->pending == 0) { + continue; + } if (ep->pending == 2) { // Pending setup: DPRAM already has the setup packet @@ -618,7 +611,7 @@ static void __tusb_irq_path_func(edpt_schedule_next)(void) { // Pending data transfer: preserve partial progress from preemption uint16_t prev_xferred = ep->xferred_len; ep->pending = 0; - edpt_xfer(ep, ep->user_buf, NULL, ep->remaining_len); + epx_xfer(ep, ep->user_buf, NULL, ep->remaining_len); epx->xferred_len += prev_xferred; // restore partial progress } return; // start only one transfer @@ -631,31 +624,39 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *b hw_endpoint_t *ep = edpt_find(dev_addr, ep_addr); TU_ASSERT(ep); - // Control endpoint can change direction 0x00 <-> 0x80 - if (ep_addr != ep->ep_addr) { - ep->ep_addr = ep_addr; - ep->next_pid = 1; // data and status stage start with DATA1 - } + if (ep->transfer_type == TUSB_XFER_INTERRUPT) { + // For interrupt endpoint control and buffer is already configured + // Note: Interrupt is single buffered only + io_rw_32 *ep_reg = dpram_int_ep_ctrl(ep->interrupt_num); + io_rw_32 *buf_reg = dpram_int_ep_buffer_ctrl(ep->interrupt_num); + rp2usb_xfer_start(ep, ep_reg, buf_reg, buffer, NULL, buflen); + } else { + // Control endpoint can change direction 0x00 <-> 0x80 when changing stages + if (ep_addr != ep->ep_addr) { + ep->ep_addr = ep_addr; + ep->next_pid = 1; // data and status stage start with DATA1 + } - // If EPX is busy with another transfer, mark as pending - if (ep->transfer_type != TUSB_XFER_INTERRUPT && epx->active) { - ep->user_buf = buffer; - ep->remaining_len = buflen; - ep->pending = 1; -#ifdef HAS_STOP_EPX_ON_NAK - usb_hw_set->nak_poll = USB_NAK_POLL_STOP_EPX_ON_NAK_BITS; -#else - // Only enable SOF preemption for non-control endpoints - if (tu_edpt_number(epx->ep_addr) != 0) { - usb_hw->nak_poll = (300 << USB_NAK_POLL_DELAY_FS_LSB) | - (300 << USB_NAK_POLL_DELAY_LS_LSB); - usb_hw_set->inte = USB_INTE_HOST_SOF_BITS; + // If EPX is busy with another transfer, mark as pending + if (epx->active) { + ep->user_buf = buffer; + ep->remaining_len = buflen; + ep->pending = 1; + + #ifdef HAS_STOP_EPX_ON_NAK + usb_hw_set->nak_poll = USB_NAK_POLL_STOP_EPX_ON_NAK_BITS; + #else + // Only enable SOF round-robin for non-control endpoints + if (tu_edpt_number(epx->ep_addr) != 0) { + usb_hw->nak_poll = (300 << USB_NAK_POLL_DELAY_FS_LSB) | (300 << USB_NAK_POLL_DELAY_LS_LSB); + usb_hw_set->inte = USB_INTE_HOST_SOF_BITS; + } + #endif + return true; } -#endif - return true; - } - edpt_xfer(ep, buffer, NULL, buflen); + epx_xfer(ep, buffer, NULL, buflen); + } return true; } diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index 433bd261d..44191092e 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -96,7 +96,7 @@ void rp2usb_init(void) { TU_LOG2_INT(sizeof(hw_endpoint_t)); } -void __tusb_irq_path_func(hw_endpoint_reset_transfer)(struct hw_endpoint* ep) { +void __tusb_irq_path_func(rp2usb_reset_transfer)(hw_endpoint_t *ep) { ep->active = false; ep->remaining_len = 0; ep->xferred_len = 0; @@ -104,61 +104,23 @@ void __tusb_irq_path_func(hw_endpoint_reset_transfer)(struct hw_endpoint* ep) { ep->is_xfer_fifo = false; } -void __tusb_irq_path_func(hwbuf_ctrl_update)(io_rw_32 *buf_ctrl_reg, uint32_t and_mask, uint32_t or_mask) { - const bool is_host = rp2usb_is_host_mode(); - uint32_t value = 0; - uint32_t buf_ctrl = *buf_ctrl_reg; - - if (and_mask) { - value = buf_ctrl & and_mask; - } - - if (or_mask) { - value |= or_mask; - if (or_mask & USB_BUF_CTRL_AVAIL) { - if (buf_ctrl & USB_BUF_CTRL_AVAIL) { - if (is_host) { -#if defined(PICO_RP2040) && PICO_RP2040 == 1 - // RP2040-E4: host buffer selector toggles in single-buffered mode, causing status - // to be written to BUF1 half and leaving stale AVAILABLE in BUF0 half. Clear it. - *buf_ctrl_reg = 0; -#else - panic("buf_ctrl @ 0x%lX already available (host)", (uintptr_t)buf_ctrl_reg); -#endif - } else { - panic("buf_ctrl @ 0x%lX already available", (uintptr_t)buf_ctrl_reg); - } - } - *buf_ctrl_reg = value & ~USB_BUF_CTRL_AVAIL; - - // Section 4.1.2.7.1 (rp2040) / 12.7.3.7.1 (rp2350) Concurrent access: after write to buffer control, - // wait for USB controller to see the update before setting AVAILABLE. - // Don't need delay in host mode as host is in charge of when to start the transaction. - if (!is_host) { - busy_wait_at_least_cycles(12); - } - } - } - - *buf_ctrl_reg = value; -} - void __tusb_irq_path_func(bufctrl_write32)(io_rw_32 *buf_reg, uint32_t value) { const uint32_t current = *buf_reg; const uint32_t avail_mask = USB_BUF_CTRL_AVAIL | (USB_BUF_CTRL_AVAIL << 16); if (current & value & avail_mask) { panic("buf_ctrl @ 0x%lX already available", (uintptr_t)buf_reg); } - *buf_reg = value & ~USB_BUF_CTRL_AVAIL; // write other bits first + *buf_reg = value & ~(USB_BUF_CTRL_AVAIL | (USB_BUF_CTRL_AVAIL << 16)); // write other bits first // Section 4.1.2.7.1 (rp2040) / 12.7.3.7.1 (rp2350) Concurrent access: after write to buffer control, // wait for USB controller to see the update before setting AVAILABLE. // Don't need delay in host mode as host is in charge of when to start the transaction. - if (!rp2usb_is_host_mode() && (value & (USB_BUF_CTRL_AVAIL | (USB_BUF_CTRL_AVAIL << 16)))) { - busy_wait_at_least_cycles(12); + if (value & (USB_BUF_CTRL_AVAIL | (USB_BUF_CTRL_AVAIL << 16))) { + if (!rp2usb_is_host_mode()) { + busy_wait_at_least_cycles(12); + } + *buf_reg = value; // then set AVAILABLE bit last } - - *buf_reg = value; // then set AVAILABLE bit (if set) last } void __tusb_irq_path_func(bufctrl_write16)(io_rw_16 *buf_reg16, uint16_t value) { @@ -171,10 +133,12 @@ void __tusb_irq_path_func(bufctrl_write16)(io_rw_16 *buf_reg16, uint16_t value) // Section 4.1.2.7.1 (rp2040) / 12.7.3.7.1 (rp2350) Concurrent access: after write to buffer control, // wait for USB controller to see the update before setting AVAILABLE. // Don't need delay in host mode as host is in charge of when to start the transaction. - if (!rp2usb_is_host_mode() && (value & USB_BUF_CTRL_AVAIL)) { - busy_wait_at_least_cycles(12); + if (value & USB_BUF_CTRL_AVAIL) { + if (!rp2usb_is_host_mode()) { + busy_wait_at_least_cycles(12); + } + *buf_reg16 = value; // then set AVAILABLE bit last } - *buf_reg16 = value; // then set AVAILABLE bit (if set) last } // prepare buffer, move data if tx, return buffer control @@ -217,7 +181,7 @@ uint16_t __tusb_irq_path_func(bufctrl_prepare16)(struct hw_endpoint *ep, uint8_t } // Start transaction on hw buffer -void __tusb_irq_path_func(hw_endpoint_buffer_start)(struct hw_endpoint *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg) { +void __tusb_irq_path_func(rp2usb_buffer_start)(hw_endpoint_t *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg) { const tusb_dir_t dir = tu_edpt_dir(ep->ep_addr); const bool is_host = rp2usb_is_host_mode(); @@ -228,14 +192,6 @@ void __tusb_irq_path_func(hw_endpoint_buffer_start)(struct hw_endpoint *ep, io_r is_rx = (dir == TUSB_DIR_OUT); } - // RP2040-E4 (host only): in single-buffered multi-packet transfers, the controller may write completion status to - // BUF1 half instead of BUF0. The side effect that controller can execute an extra packet after writing to BUF1 - // since it leave BUF0 intact, which can be polled before buf_status interrupt is trigger. - // Workaround for the side effect, we will enable double-buffered for rx but only prepare 1 buf at a time. - #if CFG_TUSB_RP2_ERRATA_E4 - - #endif - // always compute and start with buffer 0 uint32_t buf_ctrl = bufctrl_prepare16(ep, ep->dpram_buf, is_rx) | USB_BUF_CTRL_SEL; @@ -268,15 +224,15 @@ void __tusb_irq_path_func(hw_endpoint_buffer_start)(struct hw_endpoint *ep, io_r bufctrl_write32(buf_reg, buf_ctrl); } -void hw_endpoint_xfer_start(struct hw_endpoint *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg, uint8_t *buffer, tu_fifo_t *ff, - uint16_t total_len) { +void rp2usb_xfer_start(hw_endpoint_t *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg, uint8_t *buffer, tu_fifo_t *ff, + uint16_t total_len) { (void) ff; hw_endpoint_lock_update(ep, 1); if (ep->active) { // TODO: Is this acceptable for interrupt packets? TU_LOG(1, "WARN: starting new transfer on already active ep %02X\r\n", ep->ep_addr); - hw_endpoint_reset_transfer(ep); + rp2usb_reset_transfer(ep); } // Fill in info now that we're kicking off the hw @@ -310,7 +266,7 @@ void hw_endpoint_xfer_start(struct hw_endpoint *ep, io_rw_32 *ep_reg, io_rw_32 * // all data has been received, no need to start hw transfer ep->active = false; const uint16_t xferred_len = ep->xferred_len; - hw_endpoint_reset_transfer(ep); + rp2usb_reset_transfer(ep); const bool is_host = rp2usb_is_host_mode(); #if CFG_TUH_ENABLED @@ -342,7 +298,7 @@ void hw_endpoint_xfer_start(struct hw_endpoint *ep, io_rw_32 *ep_reg, io_rw_32 * } #endif - hw_endpoint_buffer_start(ep, ep_reg, buf_reg); + rp2usb_buffer_start(ep, ep_reg, buf_reg); hw_endpoint_lock_update(ep, -1); } @@ -382,7 +338,8 @@ static uint16_t __tusb_irq_path_func(hwbuf_sync)(hw_endpoint_t *ep, bool is_rx, // Returns true if transfer is complete. // buf_id: which buffer completed (from BUFF_CPU_SHOULD_HANDLE, only used for double-buffered). -bool __tusb_irq_path_func(hw_endpoint_xfer_continue)(struct hw_endpoint *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg, uint8_t buf_id) { +bool __tusb_irq_path_func(rp2usb_xfer_continue)(hw_endpoint_t *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg, + uint8_t buf_id) { hw_endpoint_lock_update(ep, 1); const tusb_dir_t dir = tu_edpt_dir(ep->ep_addr); diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.h b/src/portable/raspberrypi/rp2040/rp2040_usb.h index 7b79cd2b1..34687020f 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.h +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.h @@ -132,11 +132,11 @@ TU_ATTR_ALWAYS_INLINE static inline bool rp2usb_is_host_mode(void) { //--------------------------------------------------------------------+ // Hardware Endpoint //--------------------------------------------------------------------+ -void hw_endpoint_xfer_start(struct hw_endpoint *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg, uint8_t *buffer, tu_fifo_t *ff, - uint16_t total_len); -bool hw_endpoint_xfer_continue(struct hw_endpoint *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg, uint8_t buf_id); -void hw_endpoint_buffer_start(struct hw_endpoint *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg); -void hw_endpoint_reset_transfer(struct hw_endpoint *ep); +void rp2usb_xfer_start(hw_endpoint_t *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg, uint8_t *buffer, tu_fifo_t *ff, + uint16_t total_len); +bool rp2usb_xfer_continue(hw_endpoint_t *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg, uint8_t buf_id); +void rp2usb_buffer_start(hw_endpoint_t *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg); +void rp2usb_reset_transfer(hw_endpoint_t *ep); TU_ATTR_ALWAYS_INLINE static inline void hw_endpoint_lock_update(__unused struct hw_endpoint * ep, __unused int delta) { // todo add critsec as necessary to prevent issues between worker and IRQ... @@ -147,26 +147,11 @@ TU_ATTR_ALWAYS_INLINE static inline void hw_endpoint_lock_update(__unused struct //--------------------------------------------------------------------+ // Hardware Buffer //--------------------------------------------------------------------+ -void hwbuf_ctrl_update(io_rw_32 *buf_ctrl_reg, uint32_t and_mask, uint32_t or_mask); - void bufctrl_write32(io_rw_32 *buf_reg, uint32_t value); void bufctrl_write16(io_rw_16 *buf_reg16, uint16_t value); - uint16_t bufctrl_prepare16(struct hw_endpoint *ep, uint8_t *dpram_buf, bool is_rx); -TU_ATTR_ALWAYS_INLINE static inline void hwbuf_ctrl_set(io_rw_32 *buf_ctrl_reg, uint32_t value) { - hwbuf_ctrl_update(buf_ctrl_reg, 0, value); -} - -TU_ATTR_ALWAYS_INLINE static inline void hwbuf_ctrl_set_mask(io_rw_32 *buf_ctrl_reg, uint32_t value) { - hwbuf_ctrl_update(buf_ctrl_reg, ~value, value); -} - -TU_ATTR_ALWAYS_INLINE static inline void hwbuf_ctrl_clear_mask(io_rw_32 *buf_ctrl_reg, uint32_t value) { - hwbuf_ctrl_update(buf_ctrl_reg, ~value, 0); -} - -static inline uintptr_t hw_data_offset(uint8_t *buf) { +TU_ATTR_ALWAYS_INLINE static inline uintptr_t hw_data_offset(uint8_t *buf) { // Remove usb base from buffer pointer return (uintptr_t)buf ^ (uintptr_t)usb_dpram; } -- cgit v1.3.1 From a9eb36b0fb5ad5322cb711954c98bf172faa1e06 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 27 Mar 2026 19:01:57 +0700 Subject: refactor --- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 266 +++++++++++++-------------- 1 file changed, 133 insertions(+), 133 deletions(-) (limited to 'src/portable') diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index 379ba075d..8145cfdcc 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -116,12 +116,119 @@ TU_ATTR_ALWAYS_INLINE static inline bool need_pre(uint8_t dev_addr) { return hcd_port_speed_get(0) != tuh_speed_get(dev_addr); } -// forward declaration -static void __tusb_irq_path_func(edpt_schedule_next)(void); -TU_ATTR_ALWAYS_INLINE static inline void sie_start_xfer(uint32_t value); +//--------------------------------------------------------------------+ +// EPX +//--------------------------------------------------------------------+ + +static void __tusb_irq_path_func(epx_schedule_next)(void); static void epx_xfer(hw_endpoint_t *ep, uint8_t *buffer, tu_fifo_t *ff, uint16_t total_len); -static void __tusb_irq_path_func(hw_xfer_complete)(hw_endpoint_t *ep, xfer_result_t xfer_result) { +TU_ATTR_ALWAYS_INLINE static inline void sie_start_xfer(bool send_setup, tusb_dir_t ep_dir, bool need_pre) { + uint32_t value = usb_hw->sie_ctrl & SIE_CTRL_BASE_MASK; // preserve base bits + if (send_setup) { + value |= USB_SIE_CTRL_SEND_SETUP_BITS; + } else { + value |= (ep_dir ? USB_SIE_CTRL_RECEIVE_DATA_BITS : USB_SIE_CTRL_SEND_DATA_BITS); + } + if (need_pre) { + value |= USB_SIE_CTRL_PREAMBLE_EN_BITS; + } + + // START_TRANS bit on SIE_CTRL has the same behavior as the AVAILABLE bit + // described in RP2040 Datasheet, release 2.1, section "4.1.2.5.1. Concurrent access". + // We write everything except the START_TRANS bit first, then wait some cycles. + usb_hw->sie_ctrl = value; + busy_wait_at_least_cycles(12); + usb_hw->sie_ctrl = value | USB_SIE_CTRL_START_TRANS_BITS; +} + +// All non-interrupt endpoints use shared EPX. +// Save current EPX context, mark pending, switch to next_ep +static void __tusb_irq_path_func(epx_switch_ep)(hw_endpoint_t *next_ep) { + const uint32_t buf_ctrl = usbh_dpram->epx_buf_ctrl; + const uint16_t buf0_len = buf_ctrl & USB_BUF_CTRL_LEN_MASK; + epx->remaining_len = (uint16_t)(epx->remaining_len + buf0_len); + epx->next_pid = (buf_ctrl & USB_BUF_CTRL_DATA1_PID) ? 1 : 0; + if (tu_edpt_dir(epx->ep_addr) == TUSB_DIR_OUT) { + epx->user_buf -= buf0_len; + } + epx->pending = 1; + epx->active = false; + usbh_dpram->epx_buf_ctrl = 0; + + if (next_ep->pending == 2) { + next_ep->ep_addr = 0; + next_ep->remaining_len = 8; + next_ep->xferred_len = 0; + next_ep->active = true; + next_ep->pending = 0; + epx = next_ep; + usb_hw->dev_addr_ctrl = next_ep->dev_addr; + sie_start_xfer(true, TUSB_DIR_OUT, next_ep->need_pre); + } else { + uint16_t prev_xferred = next_ep->xferred_len; + next_ep->pending = 0; + epx_xfer(next_ep, next_ep->user_buf, NULL, next_ep->remaining_len); + epx->xferred_len += prev_xferred; + } +} + +// Round-robin find next pending ep after current epx +static hw_endpoint_t *__tusb_irq_path_func(epx_next_pending)(hw_endpoint_t *cur_ep) { + const uint cur_idx = (uint)(cur_ep - &ep_pool[0]); + for (uint i = cur_idx + 1; i < TU_ARRAY_SIZE(ep_pool); i++) { + if (ep_pool[i].pending) { + return &ep_pool[i]; + } + } + for (uint i = 0; i < cur_idx; i++) { + if (ep_pool[i].pending) { + return &ep_pool[i]; + } + } + return NULL; +} + +// Schedule next pending EPX transfer from ISR context +static void __tusb_irq_path_func(epx_schedule_next)(void) { + // EPX may already be active if the completion callback started a new transfer + // if (epx->active) { + // return; + // } + + for (uint i = 0; i < TU_ARRAY_SIZE(ep_pool); i++) { + hw_endpoint_t *ep = &ep_pool[i]; + if (ep->pending == 0) { + continue; + } + + if (ep->pending == 2) { + // Pending setup: DPRAM already has the setup packet + ep->ep_addr = 0; + ep->remaining_len = 8; + ep->xferred_len = 0; + ep->active = true; + ep->pending = 0; + + epx = ep; + usb_hw->dev_addr_ctrl = ep->dev_addr; + + sie_start_xfer(true, TUSB_DIR_OUT, ep->need_pre); + } else { + // Pending data transfer: preserve partial progress from preemption + uint16_t prev_xferred = ep->xferred_len; + ep->pending = 0; + epx_xfer(ep, ep->user_buf, NULL, ep->remaining_len); + epx->xferred_len += prev_xferred; // restore partial progress + } + return; // start only one transfer + } +} + +//--------------------------------------------------------------------+ +// Interrupt handlers +//--------------------------------------------------------------------+ +static void __tusb_irq_path_func(xfer_complete_isr)(hw_endpoint_t *ep, xfer_result_t xfer_result) { // Mark transfer as done before we tell the tinyusb stack uint8_t dev_addr = ep->dev_addr; uint8_t ep_addr = ep->ep_addr; @@ -131,17 +238,21 @@ static void __tusb_irq_path_func(hw_xfer_complete)(hw_endpoint_t *ep, xfer_resul // Schedule next pending EPX transfer (only for non-interrupt endpoints) if (ep == epx) { - edpt_schedule_next(); + epx_schedule_next(); + // hw_endpoint_t *next_ep = epx_next_pending(epx); + // if (next_ep != NULL) { + // epx_switch_ep(next_ep); + // } } } -static void __tusb_irq_path_func(handle_hwbuf_status)(void) { +static void __tusb_irq_path_func(handle_buf_status_isr)(void) { pico_trace("buf_status 0x%08lx\n", buf_status); enum { BUF_STATUS_EPX = 1u }; - // Check EPX first (bit 0). EPX is currently single-buffered, always use buf_id=0. + // Check EPX first (bit 0). EPX is currently single-buffered, always use buf_id=0.3 // Double-buffered: if both buffers completed at once, buf_status re-sets // immediately after clearing (datasheet Table 406). Process the second buffer too. while (usb_hw->buf_status & BUF_STATUS_EPX) { @@ -151,7 +262,7 @@ static void __tusb_irq_path_func(handle_hwbuf_status)(void) { io_rw_32 *ep_reg = &usbh_dpram->epx_ctrl; io_rw_32 *buf_reg = &usbh_dpram->epx_buf_ctrl; if (rp2usb_xfer_continue(epx, ep_reg, buf_reg, buf_id)) { - hw_xfer_complete(epx, XFER_RESULT_SUCCESS); + xfer_complete_isr(epx, XFER_RESULT_SUCCESS); } } @@ -176,7 +287,7 @@ static void __tusb_irq_path_func(handle_hwbuf_status)(void) { io_rw_32 *buf_reg = dpram_int_ep_buffer_ctrl(ep->interrupt_num); const bool done = rp2usb_xfer_continue(ep, ep_reg, buf_reg, 0); if (done) { - hw_xfer_complete(ep, XFER_RESULT_SUCCESS); + xfer_complete_isr(ep, XFER_RESULT_SUCCESS); } break; } @@ -184,56 +295,6 @@ static void __tusb_irq_path_func(handle_hwbuf_status)(void) { } } -// All non-interrupt endpoints use shared EPX. -// Forward declared above hw_xfer_complete, defined after epx_xfer below. -// Save current EPX context, mark pending, switch to next_ep -static void __tusb_irq_path_func(epx_switch_ep)(hw_endpoint_t *next_ep) { - const uint32_t buf_ctrl = usbh_dpram->epx_buf_ctrl; - const uint16_t buf0_len = buf_ctrl & USB_BUF_CTRL_LEN_MASK; - epx->remaining_len = (uint16_t)(epx->remaining_len + buf0_len); - epx->next_pid = (buf_ctrl & USB_BUF_CTRL_DATA1_PID) ? 1 : 0; - if (tu_edpt_dir(epx->ep_addr) == TUSB_DIR_OUT) { - epx->user_buf -= buf0_len; - } - epx->pending = 1; - epx->active = false; - usbh_dpram->epx_buf_ctrl = 0; - - if (next_ep->pending == 2) { - next_ep->ep_addr = 0; - next_ep->remaining_len = 8; - next_ep->xferred_len = 0; - next_ep->active = true; - next_ep->pending = 0; - epx = next_ep; - usb_hw->dev_addr_ctrl = next_ep->dev_addr; - const uint32_t sc = USB_SIE_CTRL_SEND_SETUP_BITS | - (next_ep->need_pre ? USB_SIE_CTRL_PREAMBLE_EN_BITS : 0); - sie_start_xfer(sc); - } else { - uint16_t prev_xferred = next_ep->xferred_len; - next_ep->pending = 0; - epx_xfer(next_ep, next_ep->user_buf, NULL, next_ep->remaining_len); - epx->xferred_len += prev_xferred; - } -} - -// Round-robin find next pending ep after current epx -static hw_endpoint_t *__tusb_irq_path_func(epx_find_pending)(void) { - const uint start = (uint)(epx - &ep_pool[0]) + 1; - for (uint i = start; i < TU_ARRAY_SIZE(ep_pool); i++) { - if (ep_pool[i].pending) { - return &ep_pool[i]; - } - } - for (uint i = 0; i < start - 1; i++) { - if (ep_pool[i].pending) { - return &ep_pool[i]; - } - } - return NULL; -} - static void __tusb_irq_path_func(hcd_rp2040_irq)(void) { const uint32_t status = usb_hw->ints; @@ -258,11 +319,11 @@ static void __tusb_irq_path_func(hcd_rp2040_irq)(void) { // AND TRANS_COMPLETE as the stall is an alternative response // to one of those events usb_hw_clear->sie_status = USB_SIE_STATUS_STALL_REC_BITS; - hw_xfer_complete(epx, XFER_RESULT_STALLED); + xfer_complete_isr(epx, XFER_RESULT_STALLED); } if (status & USB_INTS_BUFF_STATUS_BITS) { - handle_hwbuf_status(); + handle_buf_status_isr(); } if (status & USB_INTS_TRANS_COMPLETE_BITS) { @@ -271,32 +332,23 @@ static void __tusb_irq_path_func(hcd_rp2040_irq)(void) { // only handle a setup packet if (usb_hw->sie_ctrl & USB_SIE_CTRL_SEND_SETUP_BITS) { epx->xferred_len = 8; - hw_xfer_complete(epx, XFER_RESULT_SUCCESS); + xfer_complete_isr(epx, XFER_RESULT_SUCCESS); } else { // Don't care. Will handle this in buff status } } #ifdef HAS_STOP_EPX_ON_NAK - // RP2350: hardware stops EPX on NAK automatically if (status & USB_INTS_EPX_STOPPED_ON_NAK_BITS) { usb_hw_clear->nak_poll = USB_NAK_POLL_EPX_STOPPED_ON_NAK_BITS; - hw_endpoint_t *next_ep = NULL; - if (epx->active && tu_edpt_number(epx->ep_addr) != 0) { - next_ep = epx_find_pending(); - } - if (next_ep) { + hw_endpoint_t *next_ep = epx_next_pending(epx); + if (next_ep != NULL) { epx_switch_ep(next_ep); } else { - // No preemption: disable stop-on-NAK, restart current transfer + // No switch: disable stop-on-NAK, restart current transfer usb_hw_clear->nak_poll = USB_NAK_POLL_STOP_EPX_ON_NAK_BITS; - if (epx->active) { - const tusb_dir_t ep_dir = tu_edpt_dir(epx->ep_addr); - const uint32_t sie_ctrl = (ep_dir ? USB_SIE_CTRL_RECEIVE_DATA_BITS : USB_SIE_CTRL_SEND_DATA_BITS) | - (epx->need_pre ? USB_SIE_CTRL_PREAMBLE_EN_BITS : 0); - sie_start_xfer(sie_ctrl); - } + sie_start_xfer(false, tu_edpt_dir(epx->ep_addr), epx->need_pre); } } #else @@ -304,22 +356,22 @@ static void __tusb_irq_path_func(hcd_rp2040_irq)(void) { if (status & USB_INTS_HOST_SOF_BITS) { (void) usb_hw->sof_rd; // clear SOF by reading SOF_RD if (epx->active && tu_edpt_number(epx->ep_addr) != 0) { - hw_endpoint_t *next_ep = epx_find_pending(); + hw_endpoint_t *next_ep = epx_next_pending(epx); if (next_ep) { usb_hw_set->sie_ctrl = USB_SIE_CTRL_STOP_TRANS_BITS; while (usb_hw->sie_ctrl & USB_SIE_CTRL_STOP_TRANS_BITS) {} busy_wait_at_least_cycles(12); if (usb_hw->buf_status & 1u) { usb_hw->nak_poll = USB_NAK_POLL_RESET; - handle_hwbuf_status(); + handle_buf_status_isr(); } else { epx_switch_ep(next_ep); } } else { usb_hw_clear->inte = USB_INTE_HOST_SOF_BITS; - usb_hw->nak_poll = USB_NAK_POLL_RESET; + usb_hw->nak_poll = USB_NAK_POLL_RESET; } - } else if (!epx_find_pending()) { + } else if (!epx_next_pending(epx)) { // EPX is on control endpoint or inactive — disable SOF if nothing pending usb_hw_clear->inte = USB_INTE_HOST_SOF_BITS; usb_hw->nak_poll = USB_NAK_POLL_RESET; @@ -536,17 +588,6 @@ bool hcd_edpt_close(uint8_t rhport, uint8_t daddr, uint8_t ep_addr) { return false; // TODO not implemented yet } -TU_ATTR_ALWAYS_INLINE static inline void sie_start_xfer(uint32_t value) { - value |= (usb_hw->sie_ctrl & SIE_CTRL_BASE_MASK); // preserve base bits - - // START_TRANS bit on SIE_CTRL has the same behavior as the AVAILABLE bit - // described in RP2040 Datasheet, release 2.1, section "4.1.2.5.1. Concurrent access". - // We write everything except the START_TRANS bit first, then wait some cycles. - usb_hw->sie_ctrl = value; - busy_wait_at_least_cycles(12); - usb_hw->sie_ctrl = value | USB_SIE_CTRL_START_TRANS_BITS; -} - // start a transfer on epx endpoint static void epx_xfer(hw_endpoint_t *ep, uint8_t *buffer, tu_fifo_t *ff, uint16_t total_len) { const uint8_t ep_num = tu_edpt_number(ep->ep_addr); @@ -575,47 +616,7 @@ static void epx_xfer(hw_endpoint_t *ep, uint8_t *buffer, tu_fifo_t *ff, uint16_t epx = ep; // start transfer - const uint32_t sie_ctrl = (ep_dir ? USB_SIE_CTRL_RECEIVE_DATA_BITS : USB_SIE_CTRL_SEND_DATA_BITS) | - (ep->need_pre ? USB_SIE_CTRL_PREAMBLE_EN_BITS : 0); - sie_start_xfer(sie_ctrl); -} - -// Schedule next pending EPX transfer from ISR context -static void __tusb_irq_path_func(edpt_schedule_next)(void) { - // EPX may already be active if the completion callback started a new transfer - if (epx->active) { - return; - } - - for (uint i = 0; i < TU_ARRAY_SIZE(ep_pool); i++) { - hw_endpoint_t *ep = &ep_pool[i]; - if (ep->pending == 0) { - continue; - } - - if (ep->pending == 2) { - // Pending setup: DPRAM already has the setup packet - ep->ep_addr = 0; - ep->remaining_len = 8; - ep->xferred_len = 0; - ep->active = true; - ep->pending = 0; - - epx = ep; - usb_hw->dev_addr_ctrl = ep->dev_addr; - - const uint32_t sie_ctrl = USB_SIE_CTRL_SEND_SETUP_BITS | - (ep->need_pre ? USB_SIE_CTRL_PREAMBLE_EN_BITS : 0); - sie_start_xfer(sie_ctrl); - } else { - // Pending data transfer: preserve partial progress from preemption - uint16_t prev_xferred = ep->xferred_len; - ep->pending = 0; - epx_xfer(ep, ep->user_buf, NULL, ep->remaining_len); - epx->xferred_len += prev_xferred; // restore partial progress - } - return; // start only one transfer - } + sie_start_xfer(false, ep_dir, ep->need_pre); } bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *buffer, uint16_t buflen) { @@ -705,8 +706,7 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, const uint8_t setup_packet usb_hw->dev_addr_ctrl = dev_addr; // Set device address // Set pre if we are a low speed device on full speed hub - const uint32_t sie_ctrl = USB_SIE_CTRL_SEND_SETUP_BITS | (ep->need_pre ? USB_SIE_CTRL_PREAMBLE_EN_BITS : 0); - sie_start_xfer(sie_ctrl); + sie_start_xfer(true, TUSB_DIR_OUT, ep->need_pre); return true; } -- cgit v1.3.1 From 7d004257d9cb849e90166a50c0f751b162fd6a68 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 28 Mar 2026 12:12:20 +0700 Subject: host epx clean up --- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 211 +++++++++++---------------- src/portable/raspberrypi/rp2040/rp2040_usb.c | 9 +- src/portable/raspberrypi/rp2040/rp2040_usb.h | 14 +- 3 files changed, 107 insertions(+), 127 deletions(-) (limited to 'src/portable') diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index 8145cfdcc..167a80a7a 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -44,11 +44,11 @@ #include "host/hcd.h" #include "host/usbh.h" -// port 0 is native USB port, other is counted as software PIO -#define RHPORT_NATIVE 0 + // port 0 is native USB port, other is counted as software PIO + #define RHPORT_NATIVE 0 //--------------------------------------------------------------------+ -// Low level rp2040 controller functions +// //--------------------------------------------------------------------+ // Host mode uses one shared endpoint register for non-interrupt endpoint @@ -119,10 +119,6 @@ TU_ATTR_ALWAYS_INLINE static inline bool need_pre(uint8_t dev_addr) { //--------------------------------------------------------------------+ // EPX //--------------------------------------------------------------------+ - -static void __tusb_irq_path_func(epx_schedule_next)(void); -static void epx_xfer(hw_endpoint_t *ep, uint8_t *buffer, tu_fifo_t *ff, uint16_t total_len); - TU_ATTR_ALWAYS_INLINE static inline void sie_start_xfer(bool send_setup, tusb_dir_t ep_dir, bool need_pre) { uint32_t value = usb_hw->sie_ctrl & SIE_CTRL_BASE_MASK; // preserve base bits if (send_setup) { @@ -142,34 +138,59 @@ TU_ATTR_ALWAYS_INLINE static inline void sie_start_xfer(bool send_setup, tusb_di usb_hw->sie_ctrl = value | USB_SIE_CTRL_START_TRANS_BITS; } -// All non-interrupt endpoints use shared EPX. -// Save current EPX context, mark pending, switch to next_ep -static void __tusb_irq_path_func(epx_switch_ep)(hw_endpoint_t *next_ep) { +// prepare epx_ctrl register for new endpoint +TU_ATTR_ALWAYS_INLINE static inline void epx_ctrl_prepare(hw_endpoint_t *ep) { + // RP2040-E4: USB host writes status to upper half of buffer control in single buffered mode. + // The buffer selector toggles even in single-buffered mode, so the previous transfer's status + // may have been written to BUF1 half, leaving BUF0 with stale AVAILABLE bit. Clear it here. + #if defined(PICO_RP2040) && PICO_RP2040 == 1 + usbh_dpram->epx_buf_ctrl = 0; + #endif + + // ep control + const uint32_t ep_ctrl = EP_CTRL_ENABLE_BITS | EP_CTRL_INTERRUPT_PER_BUFFER | + ((uint32_t)ep->transfer_type << EP_CTRL_BUFFER_TYPE_LSB) | hw_data_offset(ep->dpram_buf); + usbh_dpram->epx_ctrl = ep_ctrl; +} + +// save on-going context +static void __tusb_irq_path_func(epx_save_context)(void) { const uint32_t buf_ctrl = usbh_dpram->epx_buf_ctrl; - const uint16_t buf0_len = buf_ctrl & USB_BUF_CTRL_LEN_MASK; + const uint16_t buf0_len = buf_ctrl & USB_BUF_CTRL_LEN_MASK; // TODO handle double buffered case epx->remaining_len = (uint16_t)(epx->remaining_len + buf0_len); epx->next_pid = (buf_ctrl & USB_BUF_CTRL_DATA1_PID) ? 1 : 0; if (tu_edpt_dir(epx->ep_addr) == TUSB_DIR_OUT) { epx->user_buf -= buf0_len; } - epx->pending = 1; - epx->active = false; + epx->pending = 1; + epx->active = false; + usbh_dpram->epx_buf_ctrl = 0; +} + +// All non-interrupt endpoints use shared EPX. +// Save current EPX context, mark pending, switch to ep +static void __tusb_irq_path_func(epx_switch_ep)(hw_endpoint_t *ep) { + const bool is_setup = (ep->pending == 2); + + epx = ep; // switch pointer + ep->pending = 0; + ep->active = true; - if (next_ep->pending == 2) { - next_ep->ep_addr = 0; - next_ep->remaining_len = 8; - next_ep->xferred_len = 0; - next_ep->active = true; - next_ep->pending = 0; - epx = next_ep; - usb_hw->dev_addr_ctrl = next_ep->dev_addr; - sie_start_xfer(true, TUSB_DIR_OUT, next_ep->need_pre); + if (is_setup) { + usb_hw->dev_addr_ctrl = ep->dev_addr; + sie_start_xfer(true, TUSB_DIR_OUT, ep->need_pre); } else { - uint16_t prev_xferred = next_ep->xferred_len; - next_ep->pending = 0; - epx_xfer(next_ep, next_ep->user_buf, NULL, next_ep->remaining_len); - epx->xferred_len += prev_xferred; + const uint8_t ep_num = tu_edpt_number(ep->ep_addr); + const tusb_dir_t ep_dir = tu_edpt_dir(ep->ep_addr); + io_rw_32 *ep_reg = &usbh_dpram->epx_ctrl; + io_rw_32 *buf_reg = &usbh_dpram->epx_buf_ctrl; + + epx_ctrl_prepare(ep); + rp2usb_buffer_start(ep, ep_reg, buf_reg); + + usb_hw->dev_addr_ctrl = (uint32_t)(ep->dev_addr | (ep_num << USB_ADDR_ENDP_ENDPOINT_LSB)); + sie_start_xfer(false, ep_dir, ep->need_pre); // start transfer } } @@ -189,41 +210,6 @@ static hw_endpoint_t *__tusb_irq_path_func(epx_next_pending)(hw_endpoint_t *cur_ return NULL; } -// Schedule next pending EPX transfer from ISR context -static void __tusb_irq_path_func(epx_schedule_next)(void) { - // EPX may already be active if the completion callback started a new transfer - // if (epx->active) { - // return; - // } - - for (uint i = 0; i < TU_ARRAY_SIZE(ep_pool); i++) { - hw_endpoint_t *ep = &ep_pool[i]; - if (ep->pending == 0) { - continue; - } - - if (ep->pending == 2) { - // Pending setup: DPRAM already has the setup packet - ep->ep_addr = 0; - ep->remaining_len = 8; - ep->xferred_len = 0; - ep->active = true; - ep->pending = 0; - - epx = ep; - usb_hw->dev_addr_ctrl = ep->dev_addr; - - sie_start_xfer(true, TUSB_DIR_OUT, ep->need_pre); - } else { - // Pending data transfer: preserve partial progress from preemption - uint16_t prev_xferred = ep->xferred_len; - ep->pending = 0; - epx_xfer(ep, ep->user_buf, NULL, ep->remaining_len); - epx->xferred_len += prev_xferred; // restore partial progress - } - return; // start only one transfer - } -} //--------------------------------------------------------------------+ // Interrupt handlers @@ -236,13 +222,12 @@ static void __tusb_irq_path_func(xfer_complete_isr)(hw_endpoint_t *ep, xfer_resu rp2usb_reset_transfer(ep); hcd_event_xfer_complete(dev_addr, ep_addr, xferred_len, xfer_result, true); - // Schedule next pending EPX transfer (only for non-interrupt endpoints) + // Carry more transfer on epx if (ep == epx) { - epx_schedule_next(); - // hw_endpoint_t *next_ep = epx_next_pending(epx); - // if (next_ep != NULL) { - // epx_switch_ep(next_ep); - // } + hw_endpoint_t *next_ep = epx_next_pending(epx); + if (next_ep != NULL) { + epx_switch_ep(next_ep); + } } } @@ -338,12 +323,13 @@ static void __tusb_irq_path_func(hcd_rp2040_irq)(void) { } } -#ifdef HAS_STOP_EPX_ON_NAK + #ifdef HAS_STOP_EPX_ON_NAK if (status & USB_INTS_EPX_STOPPED_ON_NAK_BITS) { usb_hw_clear->nak_poll = USB_NAK_POLL_EPX_STOPPED_ON_NAK_BITS; hw_endpoint_t *next_ep = epx_next_pending(epx); if (next_ep != NULL) { + epx_save_context(); epx_switch_ep(next_ep); } else { // No switch: disable stop-on-NAK, restart current transfer @@ -412,7 +398,6 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { // Remove shared irq if it was previously added so as not to fill up shared irq slots irq_remove_handler(USBCTRL_IRQ, hcd_rp2040_irq); - irq_add_shared_handler(USBCTRL_IRQ, hcd_rp2040_irq, PICO_SHARED_IRQ_HANDLER_HIGHEST_ORDER_PRIORITY); // clear epx and interrupt eps @@ -588,37 +573,6 @@ bool hcd_edpt_close(uint8_t rhport, uint8_t daddr, uint8_t ep_addr) { return false; // TODO not implemented yet } -// start a transfer on epx endpoint -static void epx_xfer(hw_endpoint_t *ep, uint8_t *buffer, tu_fifo_t *ff, uint16_t total_len) { - const uint8_t ep_num = tu_edpt_number(ep->ep_addr); - const tusb_dir_t ep_dir = tu_edpt_dir(ep->ep_addr); - - // RP2040-E4: USB host writes status to upper half of buffer control in single buffered mode. - // The buffer selector toggles even in single-buffered mode, so the previous transfer's status - // may have been written to BUF1 half, leaving BUF0 with stale AVAILABLE bit. Clear it here. - #if defined(PICO_RP2040) && PICO_RP2040 == 1 - usbh_dpram->epx_buf_ctrl = 0; - #endif - - // ep control - const uint32_t dpram_offset = hw_data_offset(ep->dpram_buf); - const uint32_t ep_ctrl = EP_CTRL_ENABLE_BITS | EP_CTRL_INTERRUPT_PER_BUFFER | - ((uint32_t)ep->transfer_type << EP_CTRL_BUFFER_TYPE_LSB) | dpram_offset; - usbh_dpram->epx_ctrl = ep_ctrl; - - io_rw_32 *ep_reg = &usbh_dpram->epx_ctrl; - io_rw_32 *buf_reg = &usbh_dpram->epx_buf_ctrl; - rp2usb_xfer_start(ep, ep_reg, buf_reg, buffer, ff, total_len); - - // addr control - usb_hw->dev_addr_ctrl = (uint32_t)(ep->dev_addr | (ep_num << USB_ADDR_ENDP_ENDPOINT_LSB)); - - epx = ep; - - // start transfer - sie_start_xfer(false, ep_dir, ep->need_pre); -} - bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *buffer, uint16_t buflen) { (void)rhport; @@ -639,6 +593,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *b } // If EPX is busy with another transfer, mark as pending + rp2usb_critical_enter(); if (epx->active) { ep->user_buf = buffer; ep->remaining_len = buflen; @@ -653,10 +608,21 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *b usb_hw_set->inte = USB_INTE_HOST_SOF_BITS; } #endif - return true; - } + } else { + const uint8_t ep_num = tu_edpt_number(ep->ep_addr); + const tusb_dir_t ep_dir = tu_edpt_dir(ep->ep_addr); + io_rw_32 *ep_reg = &usbh_dpram->epx_ctrl; + io_rw_32 *buf_reg = &usbh_dpram->epx_buf_ctrl; + + epx = ep; - epx_xfer(ep, buffer, NULL, buflen); + epx_ctrl_prepare(ep); + rp2usb_xfer_start(ep, ep_reg, buf_reg, buffer, NULL, buflen); // prepare bufctrl + + usb_hw->dev_addr_ctrl = (uint32_t)(ep->dev_addr | (ep_num << USB_ADDR_ENDP_ENDPOINT_LSB)); + sie_start_xfer(false, ep_dir, ep->need_pre); // start transfer + } + rp2usb_critical_exit(); } return true; @@ -681,33 +647,30 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, const uint8_t setup_packet hw_endpoint_t *ep = edpt_find(dev_addr, 0x00); TU_ASSERT(ep); - ep->ep_addr = 0; // setup is OUT - - // If EPX is busy, mark as pending setup (DPRAM already has the packet) - if (epx->active) { - ep->pending = 2; -#ifdef HAS_STOP_EPX_ON_NAK - usb_hw_set->nak_poll = USB_NAK_POLL_STOP_EPX_ON_NAK_BITS; -#else - if (tu_edpt_number(epx->ep_addr) != 0) { - usb_hw->nak_poll = (300 << USB_NAK_POLL_DELAY_FS_LSB) | - (300 << USB_NAK_POLL_DELAY_LS_LSB); - usb_hw_set->inte = USB_INTE_HOST_SOF_BITS; - } -#endif - return true; - } + rp2usb_critical_enter(); + ep->ep_addr = 0; // setup is OUT ep->remaining_len = 8; ep->xferred_len = 0; - ep->active = true; - epx = ep; - usb_hw->dev_addr_ctrl = dev_addr; // Set device address + // If EPX is busy, mark as pending setup (DPRAM already has the packet) + if (epx->active) { + ep->pending = 2; // setup + #ifdef HAS_STOP_EPX_ON_NAK + usb_hw_set->nak_poll = USB_NAK_POLL_STOP_EPX_ON_NAK_BITS; + #else + usb_hw->nak_poll = (300 << USB_NAK_POLL_DELAY_FS_LSB) | (300 << USB_NAK_POLL_DELAY_LS_LSB); + usb_hw_set->inte = USB_INTE_HOST_SOF_BITS; + #endif + } else { + epx = ep; + ep->active = true; - // Set pre if we are a low speed device on full speed hub - sie_start_xfer(true, TUSB_DIR_OUT, ep->need_pre); + usb_hw->dev_addr_ctrl = dev_addr; // Set device address + sie_start_xfer(true, TUSB_DIR_OUT, ep->need_pre); // start transfer + } + rp2usb_critical_exit(); return true; } diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index 44191092e..15d4d723f 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -46,6 +46,8 @@ static bool e15_is_critical_frame_period(void); static uint8_t rp2040_chipversion = 2; #endif +critical_section_t rp2usb_lock; + //--------------------------------------------------------------------+ // Implementation //--------------------------------------------------------------------+ @@ -94,6 +96,8 @@ void rp2usb_init(void) { #endif TU_LOG2_INT(sizeof(hw_endpoint_t)); + + critical_section_init(&rp2usb_lock); } void __tusb_irq_path_func(rp2usb_reset_transfer)(hw_endpoint_t *ep) { @@ -383,10 +387,11 @@ bool __tusb_irq_path_func(rp2usb_xfer_continue)(hw_endpoint_t *ep, io_rw_32 *ep_ const bool is_short = xact_bytes < ep->max_packet_size; const bool is_done = is_short || (buf_ctrl16 & USB_BUF_CTRL_LAST); - // short packet on rx with double buffer: abort the other half (if not last) and reset double-buffer state. + // Short packet on rx with double buffer: abort the other half (if not last) and reset double-buffer state. // The other buffer may be: (a) still AVAIL, (b) in-progress (controller receiving), or (c) already completed. // We must abort to safely reclaim it. If it has valid data (FULL), save as future for the next transfer. - // After abort, zero buf_ctrl + // After abort, zero buf_ctrl. + // Note: Host mode we cannot save next transfer data due to shared epx -> force single if (is_short && is_double && is_rx && !is_last) { io_rw_16 *buf_reg16_other = buf_reg16 + (buf_id ^ 1); const uint32_t abort_bit = TU_BIT((tu_edpt_number(ep->ep_addr) << 1) | (dir ? 0 : 1)); diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.h b/src/portable/raspberrypi/rp2040/rp2040_usb.h index 34687020f..3b45c7c94 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.h +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.h @@ -7,6 +7,8 @@ #include "hardware/resets.h" #include "hardware/timer.h" +#include "pico/critical_section.h" + #include "common/tusb_common.h" #include "osal/osal.h" #include "common/tusb_fifo.h" @@ -129,6 +131,15 @@ TU_ATTR_ALWAYS_INLINE static inline bool rp2usb_is_host_mode(void) { return (usb_hw->main_ctrl & USB_MAIN_CTRL_HOST_NDEVICE_BITS) ? true : false; } +extern critical_section_t rp2usb_lock; + +TU_ATTR_ALWAYS_INLINE static inline void rp2usb_critical_enter(void) { + critical_section_enter_blocking(&rp2usb_lock); +} +TU_ATTR_ALWAYS_INLINE static inline void rp2usb_critical_exit(void) { + critical_section_exit(&rp2usb_lock); +} + //--------------------------------------------------------------------+ // Hardware Endpoint //--------------------------------------------------------------------+ @@ -138,7 +149,8 @@ bool rp2usb_xfer_continue(hw_endpoint_t *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg void rp2usb_buffer_start(hw_endpoint_t *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg); void rp2usb_reset_transfer(hw_endpoint_t *ep); -TU_ATTR_ALWAYS_INLINE static inline void hw_endpoint_lock_update(__unused struct hw_endpoint * ep, __unused int delta) { + +TU_ATTR_ALWAYS_INLINE static inline void hw_endpoint_lock_update(__unused struct hw_endpoint *ep, __unused int delta) { // todo add critsec as necessary to prevent issues between worker and IRQ... // note that this is perhaps as simple as disabling IRQs because it would make // sense to have worker and IRQ on same core, however I think using critsec is about equivalent. -- cgit v1.3.1 From 194d5b21977efec268cdc5341926f279977bf061 Mon Sep 17 00:00:00 2001 From: gab-k Date: Sat, 28 Mar 2026 12:45:51 +0100 Subject: fix ISO OUT stale state on alt-setting switch with different MPS --- src/portable/synopsys/dwc2/dcd_dwc2.c | 39 +++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) (limited to 'src/portable') diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index 8685ec6dc..203077ffa 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -347,6 +347,27 @@ static void edpt_disable(uint8_t rhport, uint8_t ep_addr, bool stall) { } } +// Reset stale ISO OUT endpoint state before re-activation with a different MPS. +// Unlike edpt_disable(), this does not perform disable handshakes — the endpoint +// is being immediately re-activated by the caller. +static void edpt_iso_out_reset(uint8_t rhport, uint8_t epnum) { + dwc2_regs_t* dwc2 = DWC2_REG(rhport); + dwc2_dep_t* epout = &dwc2->epout[epnum]; + + dwc2->daintmsk &= ~TU_BIT(epnum + DAINT_SHIFT(TUSB_DIR_OUT)); + // Full register write (not |=) to clear all bits including active/enabled state + epout->doepctl = DOEPCTL_SNAK; + epout->doepint = 0xFFFFFFFFu; + epout->doeptsiz = 0; + epout->doepdma = 0; + + xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); + xfer->buffer = NULL; + xfer->ff = NULL; + xfer->total_len = 0; + xfer->iso_retry = 0; +} + // 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 @@ -631,8 +652,22 @@ bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet } bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) { - // Disable EP to clear potential incomplete transfers - edpt_disable(rhport, p_endpoint_desc->bEndpointAddress, false); + const uint8_t ep_addr = p_endpoint_desc->bEndpointAddress; + const uint8_t epnum = tu_edpt_number(ep_addr); + const uint8_t dir = tu_edpt_dir(ep_addr); + + if (dir == TUSB_DIR_OUT) { + const uint16_t new_mps = tu_edpt_packet_size(p_endpoint_desc); + xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, dir); + if (xfer->max_size != 0 && xfer->max_size != new_mps) { + edpt_iso_out_reset(rhport, epnum); + } else { + edpt_disable(rhport, ep_addr, false); + } + } else { + edpt_disable(rhport, ep_addr, false); + } + edpt_activate(rhport, p_endpoint_desc); return true; } -- cgit v1.3.1 From 7d87926dc608208ce034001c43978acc424415bf Mon Sep 17 00:00:00 2001 From: gab-k Date: Sat, 28 Mar 2026 15:43:56 +0100 Subject: Add nrf54lm20 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(-) (limited to 'src/portable') diff --git a/src/portable/synopsys/dwc2/dwc2_info.md b/src/portable/synopsys/dwc2/dwc2_info.md index f83007b8c..051c3ab1f 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 | nRF54 | ST F407/429 HS | ST F207/F407/411/429 FS | ST L476 FS | ST F412/76x FS | ST F76x HS | ST H743/H750 | ST F723/L4P5 FS | ST F723 HS | ST H7RS FS | ST U5A5/H7RS/N6 HS | XMC4500 | GD32VF103 | -|:---------------------------|:---------------|:---------------|:------------|:----------------|:-------------|:--------------|:-------------|:-------------|:-----------------|:--------------------------|:-------------|:-----------------|:-------------|:---------------|:------------------|:-------------|:-------------|:---------------------|:-------------|:------------| -| GUID | 0x00002000 | 0x00000000 | 0x00001000 | 0x2708A000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00001100 | 0x00001200 | 0x00002000 | 0x00002000 | 0x00002100 | 0x00002300 | 0x00003000 | 0x00003100 | 0x00004000 | 0x00005000 | 0x00AEC000 | 0x00001000 | -| GSNPSID | 0x4F54400A | 0x4F54400A | 0x4F54400A | 0x4F54280A | 0x4F54330A | 0x4F54400A | 0x4F54400A | 0x4F54430A | 0x4F54281A | 0x4F54281A | 0x4F54310A | 0x4F54320A | 0x4F54320A | 0x4F54330A | 0x4F54330A | 0x4F54330A | 0x4F54411A | 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.10a | 3.20a | 3.20a | 3.30a | 3.30a | 3.30a | 4.11a | 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 | 0x00000000 | -| GHWCFG2 | 0x228FDD00 | 0x229FDDD0 | 0x228DCD00 | 0x228DDD50 | 0x228F5910 | 0x224DD930 | 0x215FFFD0 | 0x228BFC72 | 0x229ED590 | 0x229DCD20 | 0x229ED520 | 0x229ED520 | 0x229FE190 | 0x229FE190 | 0x229ED520 | 0x229FE1D0 | 0x229ED522 | 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 | noHNP noSRP | HNP SRP | HNP SRP | -| - arch | Slave only | DMA internal | Slave only | DMA internal | DMA internal | DMA internal | DMA internal | DMA internal | DMA internal | Slave only | Slave only | Slave only | DMA internal | DMA internal | Slave only | 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 | n/a | hub | hub | n/a | hub | n/a | hub | n/a | hub | -| - hs_phy_type | n/a | UTMI+/ULPI | n/a | UTMI+ | n/a | n/a | UTMI+/ULPI | UTMI+ | ULPI | n/a | n/a | n/a | ULPI | ULPI | n/a | UTMI+/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 | Dedicated | n/a | Dedicated | n/a | -| - num_dev_ep | 7 | 7 | 3 | 7 | 6 | 6 | 15 | 15 | 5 | 3 | 5 | 5 | 8 | 8 | 5 | 8 | 5 | 8 | 6 | 0 | -| - num_host_ch | 15 | 15 | 7 | 7 | 13 | 7 | 15 | 15 | 11 | 7 | 11 | 11 | 15 | 15 | 11 | 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 | 1 | 0 | -| - enable_dynamic_fifo | 1 | 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 | 1 | 0 | 0 | 0 | -| - reserved21 | 0 | 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 | 8 | 2 | -| - ptx_q_depth | 8 | 8 | 8 | 8 | 8 | 8 | 4 | 8 | 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 | 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 | 0 | -| GHWCFG3 | 0x020004E8 | 0x03F006E8 | 0x020004E8 | 0x0FF000E8 | 0x01F204E8 | 0x00C804B5 | 0x03805EB5 | 0x0BEAC0E8 | 0x03F403E8 | 0x020001E8 | 0x0200D1E8 | 0x0200D1E8 | 0x03EED2E8 | 0x03B8D2E8 | 0x0200D1E8 | 0x03EED2E8 | 0x020081E8 | 0x03B882E8 | 0x027A01E5 | 0x00000000 | -| - xfer_size_width | 8 | 8 | 8 | 8 | 8 | 5 | 5 | 8 | 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 | 6 | 0 | -| - otg_enable | 1 | 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 | 1 | 0 | 1 | 0 | 1 | 0 | -| - vendor_ctrl_itf | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 0 | 0 | 1 | 1 | 0 | 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 | 0 | -| - synch_reset | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 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 | 0 | -| - otg_enable_hsic | 0 | 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 | 0 | -| - lpm_mode | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | -| - dfifo_depth | 512 | 1008 | 512 | 4080 | 498 | 200 | 896 | 3050 | 1012 | 512 | 512 | 512 | 1006 | 952 | 512 | 1006 | 512 | 952 | 634 | 0 | -| GHWCFG4 | 0x1FF0A020 | 0x1FF0A020 | 0x0000000F | 0x1FF00020 | 0x1BF08030 | 0xD3F0A030 | 0xDFF1A030 | 0x1E10AA60 | 0x17F00030 | 0x0FF08030 | 0x17F08030 | 0x17F08030 | 0x23F00030 | 0xE3F00030 | 0x17F08030 | 0x23F00030 | 0x1610B230 | 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 | 0 | -| - partial_powerdown | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 0 | 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 | 1 | 1 | 0 | -| - hibernation | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 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 | 0 | 0 | -| - reserved8 | 0 | 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 | 1 | 0 | 0 | -| - service_interval_flow | 0 | 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 | 0 | 1 | 0 | 0 | -| - acg_support | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | -| - enhanced_lpm_support | 1 | 1 | 0 | 0 | 0 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 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/16 bit | 8 bit | 8 bit | 8/16 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 | 0 | -| - iddg_filter | 1 | 1 | 0 | 1 | 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 | 0 | 1 | 0 | -| - a_valid_filter | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | 0 | -| - b_valid_filter | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | 0 | -| - session_end_filter | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | 0 | -| - dedicated_fifos | 1 | 1 | 0 | 1 | 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 | 5 | 3 | 5 | 5 | 8 | 8 | 5 | 8 | 5 | 8 | 6 | 0 | -| - dma_desc_enable | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 1 | 1 | 0 | -| - dma_desc_dynamic | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 1 | 1 | 0 | +| | AT32 F405 FS | AT32 F405 HS | AT32 F415 | BCM2711 (Pi4) | EFM32GG | ESP32-S2/S3 | ESP32-P4 | nRF54 | nRF54LM20 | ST F407/429 HS | ST F207/F407/411/429 FS | ST L476 FS | ST F412/76x FS | ST F76x HS | ST H743/H750 | ST F723/L4P5 FS | ST F723 HS | ST H7RS FS | ST U5A5/H7RS/N6 HS | XMC4500 | GD32VF103 | +|:---------------------------|:---------------|:---------------|:------------|:----------------|:-------------|:--------------|:-------------|:-------------|:-------------|:-----------------|:--------------------------|:-------------|:-----------------|:-------------|:---------------|:------------------|:-------------|:-------------|:---------------------|:-------------|:------------| +| GUID | 0x00002000 | 0x00000000 | 0x00001000 | 0x2708A000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00001100 | 0x00001200 | 0x00002000 | 0x00002000 | 0x00002100 | 0x00002300 | 0x00003000 | 0x00003100 | 0x00004000 | 0x00005000 | 0x00AEC000 | 0x00001000 | +| GSNPSID | 0x4F54400A | 0x4F54400A | 0x4F54400A | 0x4F54280A | 0x4F54330A | 0x4F54400A | 0x4F54400A | 0x4F54430A | 0x4F54500B | 0x4F54281A | 0x4F54281A | 0x4F54310A | 0x4F54320A | 0x4F54320A | 0x4F54330A | 0x4F54330A | 0x4F54330A | 0x4F54411A | 0x4F54411A | 0x4F54292A | 0x00000000 | +| - specs version | 4.00a | 4.00a | 4.00a | 2.80a | 3.30a | 4.00a | 4.00a | 4.30a | 5.00b | 2.81a | 2.81a | 3.10a | 3.20a | 3.20a | 3.30a | 3.30a | 3.30a | 4.11a | 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 | 0x00000000 | 0x00000000 | +| GHWCFG2 | 0x228FDD00 | 0x229FDDD0 | 0x228DCD00 | 0x228DDD50 | 0x228F5910 | 0x224DD930 | 0x215FFFD0 | 0x228BFC72 | 0x22AFFC52 | 0x229ED590 | 0x229DCD20 | 0x229ED520 | 0x229ED520 | 0x229FE190 | 0x229FE190 | 0x229ED520 | 0x229FE1D0 | 0x229ED522 | 0x228FE052 | 0x228F5930 | 0x00000000 | +| - op_mode | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | noHNP noSRP | noHNP noSRP | 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 | Slave only | DMA internal | Slave only | DMA internal | DMA internal | DMA internal | DMA internal | DMA internal | DMA internal | DMA internal | Slave only | Slave only | Slave only | DMA internal | DMA internal | Slave only | DMA internal | Slave only | DMA internal | DMA internal | Slave only | +| - single_point | hub | hub | hub | hub | hub | n/a | hub | n/a | hub | hub | n/a | n/a | n/a | hub | hub | n/a | hub | n/a | hub | n/a | hub | +| - hs_phy_type | n/a | UTMI+/ULPI | n/a | UTMI+ | n/a | n/a | UTMI+/ULPI | UTMI+ | UTMI+ | ULPI | n/a | n/a | n/a | ULPI | ULPI | n/a | UTMI+/ULPI | n/a | UTMI+ | n/a | n/a | +| - fs_phy_type | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | Shared ULPI | n/a | n/a | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | n/a | Dedicated | n/a | +| - num_dev_ep | 7 | 7 | 3 | 7 | 6 | 6 | 15 | 15 | 15 | 5 | 3 | 5 | 5 | 8 | 8 | 5 | 8 | 5 | 8 | 6 | 0 | +| - num_host_ch | 15 | 15 | 7 | 7 | 13 | 7 | 15 | 15 | 15 | 11 | 7 | 11 | 11 | 15 | 15 | 11 | 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 | 1 | 1 | 0 | +| - enable_dynamic_fifo | 1 | 1 | 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 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | +| - reserved21 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 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 | 8 | 8 | 2 | +| - ptx_q_depth | 8 | 8 | 8 | 8 | 8 | 8 | 4 | 8 | 8 | 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 | 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 | 0 | 0 | +| GHWCFG3 | 0x020004E8 | 0x03F006E8 | 0x020004E8 | 0x0FF000E8 | 0x01F204E8 | 0x00C804B5 | 0x03805EB5 | 0x0BEAC0E8 | 0x0BE0C0E8 | 0x03F403E8 | 0x020001E8 | 0x0200D1E8 | 0x0200D1E8 | 0x03EED2E8 | 0x03B8D2E8 | 0x0200D1E8 | 0x03EED2E8 | 0x020081E8 | 0x03B882E8 | 0x027A01E5 | 0x00000000 | +| - xfer_size_width | 8 | 8 | 8 | 8 | 8 | 5 | 5 | 8 | 8 | 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 | 6 | 6 | 0 | +| - otg_enable | 1 | 1 | 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 | 0 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | +| - vendor_ctrl_itf | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 1 | 1 | 0 | 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 | 0 | 0 | +| - synch_reset | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 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 | 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 | 0 | 0 | 0 | 0 | 0 | +| - battery_charger_support | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | +| - lpm_mode | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | +| - dfifo_depth | 512 | 1008 | 512 | 4080 | 498 | 200 | 896 | 3050 | 3040 | 1012 | 512 | 512 | 512 | 1006 | 952 | 512 | 1006 | 512 | 952 | 634 | 0 | +| GHWCFG4 | 0x1FF0A020 | 0x1FF0A020 | 0x0000000F | 0x1FF00020 | 0x1BF08030 | 0xD3F0A030 | 0xDFF1A030 | 0x1E10AA60 | 0x3E10AA60 | 0x17F00030 | 0x0FF08030 | 0x17F08030 | 0x17F08030 | 0x23F00030 | 0xE3F00030 | 0x17F08030 | 0x23F00030 | 0x1610B230 | 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 | 0 | 0 | +| - partial_powerdown | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 0 | 0 | 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 | 1 | 1 | 1 | 0 | +| - hibernation | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 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 | 0 | 0 | 0 | +| - reserved8 | 0 | 0 | 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 | 1 | 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 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | +| - ipg_isoc_support | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 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 | 0 | 0 | 1 | 1 | 0 | 0 | +| - enhanced_lpm_support | 1 | 1 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 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/16 bit | 8 bit | 8 bit | 8/16 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 | 0 | 0 | +| - iddg_filter | 1 | 1 | 0 | 1 | 1 | 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 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | 0 | +| - a_valid_filter | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | 0 | +| - b_valid_filter | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | 0 | +| - session_end_filter | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | 0 | +| - dedicated_fifos | 1 | 1 | 0 | 1 | 1 | 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 | 15 | 5 | 3 | 5 | 5 | 8 | 8 | 5 | 8 | 5 | 8 | 6 | 0 | +| - dma_desc_enable | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 1 | 1 | 0 | +| - dma_desc_dynamic | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 1 | 1 | 0 | diff --git a/src/portable/synopsys/dwc2/dwc2_info.py b/src/portable/synopsys/dwc2/dwc2_info.py index e6601f482..bdf63d590 100755 --- a/src/portable/synopsys/dwc2/dwc2_info.py +++ b/src/portable/synopsys/dwc2/dwc2_info.py @@ -16,6 +16,7 @@ dwc2_reg_value = { 'ESP32-S2/S3': [0, 0x4F54400A, 0, 0x224DD930, 0x0C804B5, 0xD3F0A030], 'ESP32-P4': [0, 0x4F54400A, 0, 0x215FFFD0, 0x03805EB5, 0xDFF1A030], 'nRF54': [0, 0x4F54430A, 0xAA555000, 0x228BFC72, 0x0BEAC0E8, 0x1E10AA60], + 'nRF54LM20': [0x00000000, 0x4F54500B, 0x00000000, 0x22AFFC52, 0x0BE0C0E8, 0x3E10AA60], # ST sort by GUID 'ST F407/429 HS': [0x1100, 0x4F54281A, 0, 0x229ED590, 0x03F403E8, 0x17F00030], 'ST F207/F407/411/429 FS': [0x1200, 0x4F54281A, 0, 0x229DCD20, 0x020001E8, 0x0FF08030], -- cgit v1.3.1 From d9b122668b71dcd94974377486e6110345cc753b Mon Sep 17 00:00:00 2001 From: gab-k Date: Sat, 28 Mar 2026 15:45:16 +0100 Subject: Minimize changes in ISO OUT reset fix --- src/portable/synopsys/dwc2/dcd_dwc2.c | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) (limited to 'src/portable') diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index 203077ffa..fe0b2492c 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -347,25 +347,10 @@ static void edpt_disable(uint8_t rhport, uint8_t ep_addr, bool stall) { } } -// Reset stale ISO OUT endpoint state before re-activation with a different MPS. -// Unlike edpt_disable(), this does not perform disable handshakes — the endpoint -// is being immediately re-activated by the caller. +// Force ISO OUT EP into NAK before re-activating it with a changed MPS. static void edpt_iso_out_reset(uint8_t rhport, uint8_t epnum) { - dwc2_regs_t* dwc2 = DWC2_REG(rhport); - dwc2_dep_t* epout = &dwc2->epout[epnum]; - - dwc2->daintmsk &= ~TU_BIT(epnum + DAINT_SHIFT(TUSB_DIR_OUT)); - // Full register write (not |=) to clear all bits including active/enabled state + dwc2_dep_t* epout = &DWC2_REG(rhport)->epout[epnum]; epout->doepctl = DOEPCTL_SNAK; - epout->doepint = 0xFFFFFFFFu; - epout->doeptsiz = 0; - epout->doepdma = 0; - - xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); - xfer->buffer = NULL; - xfer->ff = NULL; - xfer->total_len = 0; - xfer->iso_retry = 0; } // Since this function returns void, it is not possible to return a boolean success message -- cgit v1.3.1 From dfcd271400c31e15a7d38b319c65173c3e4227c7 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 28 Mar 2026 23:27:39 +0700 Subject: rp2 common refactor --- src/portable/raspberrypi/rp2040/dcd_rp2040.c | 4 +- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 54 ++++---- src/portable/raspberrypi/rp2040/rp2040_usb.c | 179 +++++++++++++-------------- src/portable/raspberrypi/rp2040/rp2040_usb.h | 6 +- 4 files changed, 117 insertions(+), 126 deletions(-) (limited to 'src/portable') diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index b52c3114f..d4c1bf708 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -180,7 +180,7 @@ static void __tusb_irq_path_func(handle_hw_buff_status)(void) { usb_hw_clear->buf_status = bit; buf_status &= ~bit; - if (rp2usb_xfer_continue(ep, ep_reg, buf_reg, buf_id)) { + if (rp2usb_xfer_continue(ep, ep_reg, buf_reg, buf_id, dir == TUSB_DIR_OUT)) { const uint16_t xferred_len = ep->xferred_len; rp2usb_reset_transfer(ep); dcd_event_xfer_complete(0, ep->ep_addr, xferred_len, XFER_RESULT_SUCCESS, true); @@ -276,7 +276,7 @@ static void __tusb_irq_path_func(dcd_rp2040_irq)(void) { if (buf0_idle && buf1_idle) { // both are idle, start fresh io_rw_32 *ep_reg = get_ep_ctrl(i, TUSB_DIR_IN); - rp2usb_buffer_start(ep, ep_reg, buf_reg32); + rp2usb_buffer_start(ep, ep_reg, buf_reg32, false, false); } else if (buf0_idle) { uint16_t buf0 = bufctrl_prepare16(ep, ep->dpram_buf, false); bufctrl_write16(buf_reg16, buf0); diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index 167a80a7a..31bbfc0be 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -35,8 +35,11 @@ #define HAS_STOP_EPX_ON_NAK #endif +// port 0 is native USB port, other is counted as software PIO + #define RHPORT_NATIVE 0 + //--------------------------------------------------------------------+ -// INCLUDE + // INCLUDE //--------------------------------------------------------------------+ #include "rp2040_usb.h" #include "osal/osal.h" @@ -44,9 +47,6 @@ #include "host/hcd.h" #include "host/usbh.h" - // port 0 is native USB port, other is counted as software PIO - #define RHPORT_NATIVE 0 - //--------------------------------------------------------------------+ // //--------------------------------------------------------------------+ @@ -119,12 +119,12 @@ TU_ATTR_ALWAYS_INLINE static inline bool need_pre(uint8_t dev_addr) { //--------------------------------------------------------------------+ // EPX //--------------------------------------------------------------------+ -TU_ATTR_ALWAYS_INLINE static inline void sie_start_xfer(bool send_setup, tusb_dir_t ep_dir, bool need_pre) { +TU_ATTR_ALWAYS_INLINE static inline void sie_start_xfer(bool send_setup, bool is_rx, bool need_pre) { uint32_t value = usb_hw->sie_ctrl & SIE_CTRL_BASE_MASK; // preserve base bits if (send_setup) { value |= USB_SIE_CTRL_SEND_SETUP_BITS; } else { - value |= (ep_dir ? USB_SIE_CTRL_RECEIVE_DATA_BITS : USB_SIE_CTRL_SEND_DATA_BITS); + value |= (is_rx ? USB_SIE_CTRL_RECEIVE_DATA_BITS : USB_SIE_CTRL_SEND_DATA_BITS); } if (need_pre) { value |= USB_SIE_CTRL_PREAMBLE_EN_BITS; @@ -179,18 +179,18 @@ static void __tusb_irq_path_func(epx_switch_ep)(hw_endpoint_t *ep) { if (is_setup) { usb_hw->dev_addr_ctrl = ep->dev_addr; - sie_start_xfer(true, TUSB_DIR_OUT, ep->need_pre); + sie_start_xfer(true, false, ep->need_pre); } else { - const uint8_t ep_num = tu_edpt_number(ep->ep_addr); - const tusb_dir_t ep_dir = tu_edpt_dir(ep->ep_addr); - io_rw_32 *ep_reg = &usbh_dpram->epx_ctrl; - io_rw_32 *buf_reg = &usbh_dpram->epx_buf_ctrl; + const uint8_t ep_num = tu_edpt_number(ep->ep_addr); + const bool is_rx = tu_edpt_dir(ep->ep_addr) == TUSB_DIR_IN; + io_rw_32 *ep_reg = &usbh_dpram->epx_ctrl; + io_rw_32 *buf_reg = &usbh_dpram->epx_buf_ctrl; epx_ctrl_prepare(ep); - rp2usb_buffer_start(ep, ep_reg, buf_reg); + rp2usb_buffer_start(ep, ep_reg, buf_reg, is_rx, is_rx || ep->transfer_type == TUSB_XFER_INTERRUPT); usb_hw->dev_addr_ctrl = (uint32_t)(ep->dev_addr | (ep_num << USB_ADDR_ENDP_ENDPOINT_LSB)); - sie_start_xfer(false, ep_dir, ep->need_pre); // start transfer + sie_start_xfer(false, is_rx, ep->need_pre); // start transfer } } @@ -246,13 +246,13 @@ static void __tusb_irq_path_func(handle_buf_status_isr)(void) { io_rw_32 *ep_reg = &usbh_dpram->epx_ctrl; io_rw_32 *buf_reg = &usbh_dpram->epx_buf_ctrl; - if (rp2usb_xfer_continue(epx, ep_reg, buf_reg, buf_id)) { + if (rp2usb_xfer_continue(epx, ep_reg, buf_reg, buf_id, tu_edpt_dir(epx->ep_addr) == TUSB_DIR_IN)) { xfer_complete_isr(epx, XFER_RESULT_SUCCESS); } } // Check "interrupt" (asynchronous) endpoints for both IN and OUT - uint32_t buf_status = usb_hw->buf_status & ~1u; + uint32_t buf_status = usb_hw->buf_status & (uint32_t)~BUF_STATUS_EPX; while (buf_status) { // ctz/clz is faster than loop which has only a few bit set in general const uint8_t idx = (uint8_t) __builtin_ctz(buf_status); @@ -268,9 +268,9 @@ static void __tusb_irq_path_func(handle_buf_status_isr)(void) { for (size_t e = 0; e < TU_ARRAY_SIZE(ep_pool); e++) { hw_endpoint_t *ep = &ep_pool[e]; if (ep->interrupt_num == epnum) { - io_rw_32 *ep_reg = dpram_int_ep_ctrl(ep->interrupt_num); - io_rw_32 *buf_reg = dpram_int_ep_buffer_ctrl(ep->interrupt_num); - const bool done = rp2usb_xfer_continue(ep, ep_reg, buf_reg, 0); + io_rw_32 *ep_reg = dpram_int_ep_ctrl(ep->interrupt_num); + io_rw_32 *buf_reg = dpram_int_ep_buffer_ctrl(ep->interrupt_num); + const bool done = rp2usb_xfer_continue(ep, ep_reg, buf_reg, 0, tu_edpt_dir(ep->ep_addr) == TUSB_DIR_IN); if (done) { xfer_complete_isr(ep, XFER_RESULT_SUCCESS); } @@ -326,21 +326,20 @@ static void __tusb_irq_path_func(hcd_rp2040_irq)(void) { #ifdef HAS_STOP_EPX_ON_NAK if (status & USB_INTS_EPX_STOPPED_ON_NAK_BITS) { usb_hw_clear->nak_poll = USB_NAK_POLL_EPX_STOPPED_ON_NAK_BITS; - hw_endpoint_t *next_ep = epx_next_pending(epx); if (next_ep != NULL) { epx_save_context(); epx_switch_ep(next_ep); } else { - // No switch: disable stop-on-NAK, restart current transfer + // No pending endpoint, this is the only active one: disable stop-on-NAK, continue current transfer usb_hw_clear->nak_poll = USB_NAK_POLL_STOP_EPX_ON_NAK_BITS; - sie_start_xfer(false, tu_edpt_dir(epx->ep_addr), epx->need_pre); + sie_start_xfer(false, TUSB_DIR_IN == tu_edpt_dir(epx->ep_addr), epx->need_pre); } } -#else + #else // RP2040: on SOF, stop and switch if there's a pending ep if (status & USB_INTS_HOST_SOF_BITS) { - (void) usb_hw->sof_rd; // clear SOF by reading SOF_RD + (void)usb_hw->sof_rd; // clear SOF by reading SOF_RD if (epx->active && tu_edpt_number(epx->ep_addr) != 0) { hw_endpoint_t *next_ep = epx_next_pending(epx); if (next_ep) { @@ -360,10 +359,10 @@ static void __tusb_irq_path_func(hcd_rp2040_irq)(void) { } else if (!epx_next_pending(epx)) { // EPX is on control endpoint or inactive — disable SOF if nothing pending usb_hw_clear->inte = USB_INTE_HOST_SOF_BITS; - usb_hw->nak_poll = USB_NAK_POLL_RESET; + usb_hw->nak_poll = USB_NAK_POLL_RESET; } } -#endif + #endif if (status & USB_INTS_ERROR_RX_TIMEOUT_BITS) { usb_hw_clear->sie_status = USB_SIE_STATUS_RX_TIMEOUT_BITS; @@ -611,6 +610,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *b } else { const uint8_t ep_num = tu_edpt_number(ep->ep_addr); const tusb_dir_t ep_dir = tu_edpt_dir(ep->ep_addr); + const bool is_rx = (ep_dir == TUSB_DIR_IN); io_rw_32 *ep_reg = &usbh_dpram->epx_ctrl; io_rw_32 *buf_reg = &usbh_dpram->epx_buf_ctrl; @@ -620,7 +620,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *b rp2usb_xfer_start(ep, ep_reg, buf_reg, buffer, NULL, buflen); // prepare bufctrl usb_hw->dev_addr_ctrl = (uint32_t)(ep->dev_addr | (ep_num << USB_ADDR_ENDP_ENDPOINT_LSB)); - sie_start_xfer(false, ep_dir, ep->need_pre); // start transfer + sie_start_xfer(false, is_rx, ep->need_pre); // start transfer } rp2usb_critical_exit(); } @@ -667,7 +667,7 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, const uint8_t setup_packet ep->active = true; usb_hw->dev_addr_ctrl = dev_addr; // Set device address - sie_start_xfer(true, TUSB_DIR_OUT, ep->need_pre); // start transfer + sie_start_xfer(true, false, ep->need_pre); // start transfer } rp2usb_critical_exit(); diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index 15d4d723f..49c948af6 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -58,7 +58,7 @@ static void unaligned_memcpy(uint8_t *dst, const uint8_t *src, size_t n) { } } -#if CFG_TUD_EDPT_DEDICATED_HWFIFO + #if CFG_TUD_EDPT_DEDICATED_HWFIFO void tu_hwfifo_write(volatile void *hwfifo, const uint8_t *src, uint16_t len, const tu_hwfifo_access_t *access_mode) { (void)access_mode; unaligned_memcpy((uint8_t *)(uintptr_t)hwfifo, src, len); @@ -68,25 +68,25 @@ void tu_hwfifo_read(const volatile void *hwfifo, uint8_t *dest, uint16_t len, co (void)access_mode; unaligned_memcpy(dest, (const uint8_t *)(uintptr_t)hwfifo, len); } -#endif + #endif void rp2usb_init(void) { // Reset usb controller reset_block(RESETS_RESET_USBCTRL_BITS); unreset_block_wait(RESETS_RESET_USBCTRL_BITS); -#ifdef __GNUC__ - // Clear any previous state just in case -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Warray-bounds" -#if __GNUC__ > 6 -#pragma GCC diagnostic ignored "-Wstringop-overflow" -#endif -#endif + #ifdef __GNUC__ + // Clear any previous state just in case + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Warray-bounds" + #if __GNUC__ > 6 + #pragma GCC diagnostic ignored "-Wstringop-overflow" + #endif + #endif memset(usb_dpram, 0, sizeof(*usb_dpram)); -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif // Mux the controller to the onboard usb phy usb_hw->muxing = USB_USB_MUXING_TO_PHY_BITS | USB_USB_MUXING_SOFTCON_BITS; @@ -101,10 +101,10 @@ void rp2usb_init(void) { } void __tusb_irq_path_func(rp2usb_reset_transfer)(hw_endpoint_t *ep) { - ep->active = false; + ep->active = false; ep->remaining_len = 0; - ep->xferred_len = 0; - ep->user_buf = 0; + ep->xferred_len = 0; + ep->user_buf = 0; ep->is_xfer_fifo = false; } @@ -134,9 +134,7 @@ void __tusb_irq_path_func(bufctrl_write16)(io_rw_16 *buf_reg16, uint16_t value) } *buf_reg16 = value & (uint16_t)~USB_BUF_CTRL_AVAIL; // write other bits first - // Section 4.1.2.7.1 (rp2040) / 12.7.3.7.1 (rp2350) Concurrent access: after write to buffer control, - // wait for USB controller to see the update before setting AVAILABLE. - // Don't need delay in host mode as host is in charge of when to start the transaction. + // Section 4.1.2.7.1 (rp2040) / 12.7.3.7.1 (rp2350) Concurrent access if (value & USB_BUF_CTRL_AVAIL) { if (!rp2usb_is_host_mode()) { busy_wait_at_least_cycles(12); @@ -146,7 +144,7 @@ void __tusb_irq_path_func(bufctrl_write16)(io_rw_16 *buf_reg16, uint16_t value) } // prepare buffer, move data if tx, return buffer control -uint16_t __tusb_irq_path_func(bufctrl_prepare16)(struct hw_endpoint *ep, uint8_t *dpram_buf, bool is_rx) { +uint16_t __tusb_irq_path_func(bufctrl_prepare16)(hw_endpoint_t *ep, uint8_t *dpram_buf, bool is_rx) { const uint16_t buflen = tu_min16(ep->remaining_len, ep->max_packet_size); ep->remaining_len -= buflen; @@ -158,13 +156,13 @@ uint16_t __tusb_irq_path_func(bufctrl_prepare16)(struct hw_endpoint *ep, uint8_t if (!is_rx) { if (buflen) { - // Copy data from user buffer/fifo to hw buffer - #if CFG_TUD_EDPT_DEDICATED_HWFIFO + // Copy data from user buffer/fifo to hw buffer + #if CFG_TUD_EDPT_DEDICATED_HWFIFO if (ep->is_xfer_fifo) { // not in sram, may mess up timing with E15 workaround tu_hwfifo_write_from_fifo(dpram_buf, ep->user_fifo, buflen, NULL); } else - #endif + #endif { unaligned_memcpy(dpram_buf, ep->user_buf, buflen); ep->user_buf += buflen; @@ -185,33 +183,13 @@ uint16_t __tusb_irq_path_func(bufctrl_prepare16)(struct hw_endpoint *ep, uint8_t } // Start transaction on hw buffer -void __tusb_irq_path_func(rp2usb_buffer_start)(hw_endpoint_t *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg) { - const tusb_dir_t dir = tu_edpt_dir(ep->ep_addr); - const bool is_host = rp2usb_is_host_mode(); - - bool is_rx; - if (is_host) { - is_rx = (dir == TUSB_DIR_IN); - } else { - is_rx = (dir == TUSB_DIR_OUT); - } - +void __tusb_irq_path_func(rp2usb_buffer_start)(hw_endpoint_t *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg, bool is_rx, + bool force_single) { // always compute and start with buffer 0 uint32_t buf_ctrl = bufctrl_prepare16(ep, ep->dpram_buf, is_rx) | USB_BUF_CTRL_SEL; // Note: device EP0 does not have an endpoint control register if (ep_reg != NULL) { - #if 1 - const bool force_single = (is_host && tu_edpt_number(ep->ep_addr) != 0); - #else - bool force_single = false; // is_rx; - #if CFG_TUH_ENABLED - if (is_host && ep->interrupt_num != 0) { - force_single = true; - } - #endif -#endif - uint32_t ep_ctrl = *ep_reg; if (ep->remaining_len && !force_single) { // Use buffer 1 (double buffered) if there is still data @@ -224,13 +202,13 @@ void __tusb_irq_path_func(rp2usb_buffer_start)(hw_endpoint_t *ep, io_rw_32 *ep_r *ep_reg = ep_ctrl; } - // Finally, write to buffer_control which will trigger the transfer the next time the controller polls this endpoint + // Finally, write to buffer control which will trigger the transfer the next time the controller polls this endpoint bufctrl_write32(buf_reg, buf_ctrl); } void rp2usb_xfer_start(hw_endpoint_t *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg, uint8_t *buffer, tu_fifo_t *ff, uint16_t total_len) { - (void) ff; + (void)ff; hw_endpoint_lock_update(ep, 1); if (ep->active) { @@ -241,20 +219,22 @@ void rp2usb_xfer_start(hw_endpoint_t *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg, u // Fill in info now that we're kicking off the hw ep->remaining_len = total_len; - ep->xferred_len = 0; - ep->active = true; + ep->xferred_len = 0; + ep->active = true; -#if CFG_TUD_EDPT_DEDICATED_HWFIFO + #if CFG_TUD_EDPT_DEDICATED_HWFIFO if (ff != NULL) { ep->user_fifo = ff; ep->is_xfer_fifo = true; } else -#endif + #endif { ep->user_buf = buffer; ep->is_xfer_fifo = false; } + const bool is_host = rp2usb_is_host_mode(); + if (ep->future_len > 0) { // only on rx endpoint const uint8_t future_len = ep->future_len; @@ -272,7 +252,6 @@ void rp2usb_xfer_start(hw_endpoint_t *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg, u const uint16_t xferred_len = ep->xferred_len; rp2usb_reset_transfer(ep); - const bool is_host = rp2usb_is_host_mode(); #if CFG_TUH_ENABLED if (is_host) { hcd_event_xfer_complete(0, ep->ep_addr, xferred_len, XFER_RESULT_SUCCESS, false); @@ -302,12 +281,20 @@ void rp2usb_xfer_start(hw_endpoint_t *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg, u } #endif - rp2usb_buffer_start(ep, ep_reg, buf_reg); + const bool is_rx = (is_host == (tu_edpt_dir(ep->ep_addr) == TUSB_DIR_IN)); + #if CFG_TUH_ENABLED + const bool force_single = (is_host && (is_rx || ep->transfer_type == TUSB_XFER_INTERRUPT)); + #else + const bool force_single = false; + #endif + + rp2usb_buffer_start(ep, ep_reg, buf_reg, is_rx, force_single); hw_endpoint_lock_update(ep, -1); } // sync endpoint buffer and return transferred bytes -static uint16_t __tusb_irq_path_func(hwbuf_sync)(hw_endpoint_t *ep, bool is_rx, uint16_t buf_ctrl, uint8_t *dpram_buf) { +static uint16_t __tusb_irq_path_func(bufctrl_sync16)(hw_endpoint_t *ep, bool is_rx, uint16_t buf_ctrl, + uint8_t *dpram_buf) { const uint16_t xferred_bytes = buf_ctrl & USB_BUF_CTRL_LEN_MASK; if (!is_rx) { @@ -342,17 +329,10 @@ static uint16_t __tusb_irq_path_func(hwbuf_sync)(hw_endpoint_t *ep, bool is_rx, // Returns true if transfer is complete. // buf_id: which buffer completed (from BUFF_CPU_SHOULD_HANDLE, only used for double-buffered). -bool __tusb_irq_path_func(rp2usb_xfer_continue)(hw_endpoint_t *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg, - uint8_t buf_id) { +bool __tusb_irq_path_func(rp2usb_xfer_continue)(hw_endpoint_t *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg, uint8_t buf_id, + bool is_rx) { hw_endpoint_lock_update(ep, 1); - const tusb_dir_t dir = tu_edpt_dir(ep->ep_addr); - const bool is_host = rp2usb_is_host_mode(); - const bool is_rx = is_host ? (dir == TUSB_DIR_IN) : (dir == TUSB_DIR_OUT); - - io_rw_16 *buf_reg16 = (io_rw_16 *)buf_reg; - uint16_t buf_ctrl16 = *(buf_reg16 + buf_id); - if (!ep->active) { // probably land here due to short packet on rx with double buffered hw_endpoint_lock_update(ep, -1); @@ -360,7 +340,7 @@ bool __tusb_irq_path_func(rp2usb_xfer_continue)(hw_endpoint_t *ep, io_rw_32 *ep_ } const bool is_double = (ep_reg != NULL && ((*ep_reg) & EP_CTRL_DOUBLE_BUFFERED_BITS)); - (void)is_double; + const bool is_host = rp2usb_is_host_mode(); #if CFG_TUSB_RP2_ERRATA_E4 const bool need_e4_fix = (is_host && !is_double); @@ -372,7 +352,7 @@ bool __tusb_irq_path_func(rp2usb_xfer_continue)(hw_endpoint_t *ep, io_rw_32 *ep_ // BUF1 half instead of BUF0. The side effect that controller can execute an extra packet after writing to BUF1 // since it leave BUF0 intact, which can be poll before buf_status interrupt is trigger. // Workaround for the side effect, we will enable double-buffered for rx but only prepare 1 buf at a time. - uint8_t* dpram_buf = ep->dpram_buf; + uint8_t *dpram_buf = ep->dpram_buf; if (buf_id) { #if CFG_TUSB_RP2_ERRATA_E4 if (!need_e4_fix) // incorrect buf_id, buffer pointer is still buf0 @@ -382,7 +362,10 @@ bool __tusb_irq_path_func(rp2usb_xfer_continue)(hw_endpoint_t *ep, io_rw_32 *ep_ } } - const uint16_t xact_bytes = hwbuf_sync(ep, is_rx, buf_ctrl16, dpram_buf); + io_rw_16 *buf_reg16 = (io_rw_16 *)buf_reg; + uint16_t buf_ctrl16 = *(buf_reg16 + buf_id); + + const uint16_t xact_bytes = bufctrl_sync16(ep, is_rx, buf_ctrl16, dpram_buf); const bool is_last = buf_ctrl16 & USB_BUF_CTRL_LAST; const bool is_short = xact_bytes < ep->max_packet_size; const bool is_done = is_short || (buf_ctrl16 & USB_BUF_CTRL_LAST); @@ -391,40 +374,48 @@ bool __tusb_irq_path_func(rp2usb_xfer_continue)(hw_endpoint_t *ep, io_rw_32 *ep_ // The other buffer may be: (a) still AVAIL, (b) in-progress (controller receiving), or (c) already completed. // We must abort to safely reclaim it. If it has valid data (FULL), save as future for the next transfer. // After abort, zero buf_ctrl. - // Note: Host mode we cannot save next transfer data due to shared epx -> force single + // Note: Host mode we cannot save next transfer data due to shared epx --> force single if (is_short && is_double && is_rx && !is_last) { - io_rw_16 *buf_reg16_other = buf_reg16 + (buf_id ^ 1); - const uint32_t abort_bit = TU_BIT((tu_edpt_number(ep->ep_addr) << 1) | (dir ? 0 : 1)); - - #if CFG_TUSB_RP2_ERRATA_E2 - if (rp2040_chipversion >= 2) + #if CFG_TUH_ENABLED + if (is_host) {} #endif - { - usb_hw_set->abort = abort_bit; - while ((usb_hw->abort_done & abort_bit) != abort_bit) {} - } - // After abort, check if the other buffer received valid data - const uint16_t buf_ctrl16_other = *buf_reg16_other; - if (buf_ctrl16_other & USB_BUF_CTRL_FULL) { - // Host already sent data into this buffer (e.g. write payload right after short CBW). - // Save it for the next transfer. - ep->future_len = (uint8_t)(buf_ctrl16_other & USB_BUF_CTRL_LEN_MASK); - ep->future_bufid = buf_id ^ 1; - // buff_status will be clear by the next run - } else { - ep->next_pid ^= 1u; // roll back pid if aborted - } + #if CFG_TUD_ENABLED + if (!is_host) { + io_rw_16 *buf_reg16_other = buf_reg16 + (buf_id ^ 1); + const uint32_t abort_bit = TU_BIT(tu_edpt_number(ep->ep_addr) << 1); // IN endpoint - *buf_reg = 0; // reset buffer control + #if CFG_TUSB_RP2_ERRATA_E2 + if (rp2040_chipversion >= 2) + #endif + { + usb_hw_set->abort = abort_bit; + while ((usb_hw->abort_done & abort_bit) != abort_bit) {} + } - #if CFG_TUSB_RP2_ERRATA_E2 - if (rp2040_chipversion >= 2) - #endif - { - usb_hw_clear->abort_done = abort_bit; - usb_hw_clear->abort = abort_bit; + // After abort, check if the other buffer received valid data + const uint16_t buf_ctrl16_other = *buf_reg16_other; + if (buf_ctrl16_other & USB_BUF_CTRL_FULL) { + // Host already sent data into this buffer (e.g. write payload right after short CBW). + // Save it for the next transfer. + ep->future_len = (uint8_t)(buf_ctrl16_other & USB_BUF_CTRL_LEN_MASK); + ep->future_bufid = buf_id ^ 1; + // buff_status will be clear by the next run + } else { + ep->next_pid ^= 1u; // roll back pid if aborted + } + + *buf_reg = 0; // reset buffer control + + #if CFG_TUSB_RP2_ERRATA_E2 + if (rp2040_chipversion >= 2) + #endif + { + usb_hw_clear->abort_done = abort_bit; + usb_hw_clear->abort = abort_bit; + } } + #endif hw_endpoint_lock_update(ep, -1); return true; diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.h b/src/portable/raspberrypi/rp2040/rp2040_usb.h index 3b45c7c94..c4c7e625e 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.h +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.h @@ -145,8 +145,8 @@ TU_ATTR_ALWAYS_INLINE static inline void rp2usb_critical_exit(void) { //--------------------------------------------------------------------+ void rp2usb_xfer_start(hw_endpoint_t *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg, uint8_t *buffer, tu_fifo_t *ff, uint16_t total_len); -bool rp2usb_xfer_continue(hw_endpoint_t *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg, uint8_t buf_id); -void rp2usb_buffer_start(hw_endpoint_t *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg); +bool rp2usb_xfer_continue(hw_endpoint_t *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg, uint8_t buf_id, bool is_rx); +void rp2usb_buffer_start(hw_endpoint_t *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg, bool is_rx, bool force_single); void rp2usb_reset_transfer(hw_endpoint_t *ep); @@ -161,7 +161,7 @@ TU_ATTR_ALWAYS_INLINE static inline void hw_endpoint_lock_update(__unused struct //--------------------------------------------------------------------+ void bufctrl_write32(io_rw_32 *buf_reg, uint32_t value); void bufctrl_write16(io_rw_16 *buf_reg16, uint16_t value); -uint16_t bufctrl_prepare16(struct hw_endpoint *ep, uint8_t *dpram_buf, bool is_rx); +uint16_t bufctrl_prepare16(hw_endpoint_t *ep, uint8_t *dpram_buf, bool is_rx); TU_ATTR_ALWAYS_INLINE static inline uintptr_t hw_data_offset(uint8_t *buf) { // Remove usb base from buffer pointer -- cgit v1.3.1 From 1ebd7ebacf98c2160654c2bcb387190b54963a03 Mon Sep 17 00:00:00 2001 From: gab-k Date: Sat, 28 Mar 2026 22:47:39 +0100 Subject: Clear DOEPCTL_USBAEP instead of setting DOEPCTL = DOEPCTL_SNAK --- hw/mcu/st/cmsis_device_h7rs | 1 + hw/mcu/st/stm32-tcpp0203 | 1 + hw/mcu/st/stm32h7rsxx_hal_driver | 1 + src/portable/synopsys/dwc2/dcd_dwc2.c | 10 ++++------ 4 files changed, 7 insertions(+), 6 deletions(-) create mode 160000 hw/mcu/st/cmsis_device_h7rs create mode 160000 hw/mcu/st/stm32-tcpp0203 create mode 160000 hw/mcu/st/stm32h7rsxx_hal_driver (limited to 'src/portable') diff --git a/hw/mcu/st/cmsis_device_h7rs b/hw/mcu/st/cmsis_device_h7rs new file mode 160000 index 000000000..57ea11f70 --- /dev/null +++ b/hw/mcu/st/cmsis_device_h7rs @@ -0,0 +1 @@ +Subproject commit 57ea11f70ebf1850e1048989d665c9070f0bb863 diff --git a/hw/mcu/st/stm32-tcpp0203 b/hw/mcu/st/stm32-tcpp0203 new file mode 160000 index 000000000..9918655bf --- /dev/null +++ b/hw/mcu/st/stm32-tcpp0203 @@ -0,0 +1 @@ +Subproject commit 9918655bff176ac3046ccf378b5c7bbbc6a38d15 diff --git a/hw/mcu/st/stm32h7rsxx_hal_driver b/hw/mcu/st/stm32h7rsxx_hal_driver new file mode 160000 index 000000000..9e83b95ae --- /dev/null +++ b/hw/mcu/st/stm32h7rsxx_hal_driver @@ -0,0 +1 @@ +Subproject commit 9e83b95ae0f70faa067eddce2da617d180937f9b diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index fe0b2492c..7a1d7dcf6 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -347,10 +347,10 @@ static void edpt_disable(uint8_t rhport, uint8_t ep_addr, bool stall) { } } -// Force ISO OUT EP into NAK before re-activating it with a changed MPS. +// Clear stale active-endpoint state before re-activating ISO OUT with a changed MPS. static void edpt_iso_out_reset(uint8_t rhport, uint8_t epnum) { dwc2_dep_t* epout = &DWC2_REG(rhport)->epout[epnum]; - epout->doepctl = DOEPCTL_SNAK; + epout->doepctl &= ~DOEPCTL_USBAEP; } // Since this function returns void, it is not possible to return a boolean success message @@ -641,16 +641,14 @@ bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * p_endpo const uint8_t epnum = tu_edpt_number(ep_addr); const uint8_t dir = tu_edpt_dir(ep_addr); + edpt_disable(rhport, ep_addr, false); + if (dir == TUSB_DIR_OUT) { const uint16_t new_mps = tu_edpt_packet_size(p_endpoint_desc); xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, dir); if (xfer->max_size != 0 && xfer->max_size != new_mps) { edpt_iso_out_reset(rhport, epnum); - } else { - edpt_disable(rhport, ep_addr, false); } - } else { - edpt_disable(rhport, ep_addr, false); } edpt_activate(rhport, p_endpoint_desc); -- cgit v1.3.1 From 31ec5a7d3afdb79c95cfc6eeaf9659066d83fd69 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 30 Mar 2026 12:19:20 +0700 Subject: hcd rp2 add double buffered for control endpoint transfers. --- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 42 ++++++++++------------------ src/portable/raspberrypi/rp2040/rp2040_usb.c | 34 +++++++++++----------- src/portable/raspberrypi/rp2040/rp2040_usb.h | 7 +++++ 3 files changed, 39 insertions(+), 44 deletions(-) (limited to 'src/portable') diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index 31bbfc0be..3a99e7275 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -55,12 +55,6 @@ static hw_endpoint_t ep_pool[USB_MAX_ENDPOINTS]; static hw_endpoint_t *epx = &ep_pool[0]; // current active endpoint -// Flags we set by default in sie_ctrl (we add other bits on top) -enum { - SIE_CTRL_BASE = USB_SIE_CTRL_PULLDOWN_EN_BITS | USB_SIE_CTRL_EP0_INT_1BUF_BITS, - SIE_CTRL_BASE_MASK = USB_SIE_CTRL_PULLDOWN_EN_BITS | USB_SIE_CTRL_EP0_INT_1BUF_BITS | USB_SIE_CTRL_SOF_EN_BITS | - USB_SIE_CTRL_KEEP_ALIVE_EN_BITS -}; enum { SIE_CTRL_SPEED_DISCONNECT = 0, @@ -187,7 +181,7 @@ static void __tusb_irq_path_func(epx_switch_ep)(hw_endpoint_t *ep) { io_rw_32 *buf_reg = &usbh_dpram->epx_buf_ctrl; epx_ctrl_prepare(ep); - rp2usb_buffer_start(ep, ep_reg, buf_reg, is_rx, is_rx || ep->transfer_type == TUSB_XFER_INTERRUPT); + rp2usb_buffer_start(ep, ep_reg, buf_reg, is_rx, ep->transfer_type == TUSB_XFER_INTERRUPT); usb_hw->dev_addr_ctrl = (uint32_t)(ep->dev_addr | (ep_num << USB_ADDR_ENDP_ENDPOINT_LSB)); sie_start_xfer(false, is_rx, ep->need_pre); // start transfer @@ -340,26 +334,20 @@ static void __tusb_irq_path_func(hcd_rp2040_irq)(void) { // RP2040: on SOF, stop and switch if there's a pending ep if (status & USB_INTS_HOST_SOF_BITS) { (void)usb_hw->sof_rd; // clear SOF by reading SOF_RD - if (epx->active && tu_edpt_number(epx->ep_addr) != 0) { - hw_endpoint_t *next_ep = epx_next_pending(epx); - if (next_ep) { + hw_endpoint_t *next_ep = epx_next_pending(epx); + if (next_ep == NULL) { + // no more pending --> disable SOF + usb_hw_clear->inte = USB_INTE_HOST_SOF_BITS; + usb_hw->nak_poll = USB_NAK_POLL_RESET; + } else { + // stop transfer if is active + if (epx->active) { usb_hw_set->sie_ctrl = USB_SIE_CTRL_STOP_TRANS_BITS; while (usb_hw->sie_ctrl & USB_SIE_CTRL_STOP_TRANS_BITS) {} - busy_wait_at_least_cycles(12); - if (usb_hw->buf_status & 1u) { - usb_hw->nak_poll = USB_NAK_POLL_RESET; - handle_buf_status_isr(); - } else { - epx_switch_ep(next_ep); - } - } else { - usb_hw_clear->inte = USB_INTE_HOST_SOF_BITS; - usb_hw->nak_poll = USB_NAK_POLL_RESET; } - } else if (!epx_next_pending(epx)) { - // EPX is on control endpoint or inactive — disable SOF if nothing pending - usb_hw_clear->inte = USB_INTE_HOST_SOF_BITS; - usb_hw->nak_poll = USB_NAK_POLL_RESET; + + epx_save_context(); + epx_switch_ep(next_ep); } } #endif @@ -602,10 +590,8 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *b usb_hw_set->nak_poll = USB_NAK_POLL_STOP_EPX_ON_NAK_BITS; #else // Only enable SOF round-robin for non-control endpoints - if (tu_edpt_number(epx->ep_addr) != 0) { - usb_hw->nak_poll = (300 << USB_NAK_POLL_DELAY_FS_LSB) | (300 << USB_NAK_POLL_DELAY_LS_LSB); - usb_hw_set->inte = USB_INTE_HOST_SOF_BITS; - } + usb_hw->nak_poll = (300 << USB_NAK_POLL_DELAY_FS_LSB) | (300 << USB_NAK_POLL_DELAY_LS_LSB); + usb_hw_set->inte = USB_INTE_HOST_SOF_BITS; #endif } else { const uint8_t ep_num = tu_edpt_number(ep->ep_addr); diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index 49c948af6..ffb5fcbc6 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -283,7 +283,7 @@ void rp2usb_xfer_start(hw_endpoint_t *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg, u const bool is_rx = (is_host == (tu_edpt_dir(ep->ep_addr) == TUSB_DIR_IN)); #if CFG_TUH_ENABLED - const bool force_single = (is_host && (is_rx || ep->transfer_type == TUSB_XFER_INTERRUPT)); + const bool force_single = (is_host && ep->transfer_type == TUSB_XFER_INTERRUPT); #else const bool force_single = false; #endif @@ -339,23 +339,17 @@ bool __tusb_irq_path_func(rp2usb_xfer_continue)(hw_endpoint_t *ep, io_rw_32 *ep_ return false; } - const bool is_double = (ep_reg != NULL && ((*ep_reg) & EP_CTRL_DOUBLE_BUFFERED_BITS)); const bool is_host = rp2usb_is_host_mode(); - - #if CFG_TUSB_RP2_ERRATA_E4 - const bool need_e4_fix = (is_host && !is_double); - #endif + const bool is_double = (ep_reg != NULL && ((*ep_reg) & EP_CTRL_DOUBLE_BUFFERED_BITS)); // Double-buffered: buf_id from BUFF_CPU_SHOULD_HANDLE indicates which buffer completed. - // RP2040-E4 (host only): in single-buffered multi-packet transfers, the controller may write completion status to - // BUF1 half instead of BUF0. The side effect that controller can execute an extra packet after writing to BUF1 - // since it leave BUF0 intact, which can be poll before buf_status interrupt is trigger. - // Workaround for the side effect, we will enable double-buffered for rx but only prepare 1 buf at a time. + // BUF1 half instead of BUF0. The side effect is that controller can execute an extra packet after writing to BUF1 + // since it leaves BUF0 intact, which can be polled before buf_status interrupt is triggered. uint8_t *dpram_buf = ep->dpram_buf; if (buf_id) { #if CFG_TUSB_RP2_ERRATA_E4 - if (!need_e4_fix) // incorrect buf_id, buffer pointer is still buf0 + if (!(is_host && !is_double)) // incorrect buf_id, buffer data is still buf0 #endif { dpram_buf += 64; // buf1 offset @@ -368,16 +362,24 @@ bool __tusb_irq_path_func(rp2usb_xfer_continue)(hw_endpoint_t *ep, io_rw_32 *ep_ const uint16_t xact_bytes = bufctrl_sync16(ep, is_rx, buf_ctrl16, dpram_buf); const bool is_last = buf_ctrl16 & USB_BUF_CTRL_LAST; const bool is_short = xact_bytes < ep->max_packet_size; - const bool is_done = is_short || (buf_ctrl16 & USB_BUF_CTRL_LAST); + const bool is_done = is_short || is_last; - // Short packet on rx with double buffer: abort the other half (if not last) and reset double-buffer state. + // Short packet on rx with double buffer: abort the other half (if not last) and reset the buffer control. // The other buffer may be: (a) still AVAIL, (b) in-progress (controller receiving), or (c) already completed. // We must abort to safely reclaim it. If it has valid data (FULL), save as future for the next transfer. - // After abort, zero buf_ctrl. - // Note: Host mode we cannot save next transfer data due to shared epx --> force single + // Note: Host mode current does not save next transfer data due to shared epx --> potential issue. However, RP2040-E4 + // causes more or less of the same issue since it write to buf1 and next time it continues to transfer on buf0 (stale) if (is_short && is_double && is_rx && !is_last) { #if CFG_TUH_ENABLED - if (is_host) {} + if (is_host) { + // stop current transfer + uint32_t sie_ctrl = usb_hw->sie_ctrl & SIE_CTRL_BASE_MASK; + sie_ctrl |= USB_SIE_CTRL_STOP_TRANS_BITS; + usb_hw->sie_ctrl = sie_ctrl; + // maybe wait until STOP_TRANS bit is clear + + *buf_reg = 0; // reset buffer control + } #endif #if CFG_TUD_ENABLED diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.h b/src/portable/raspberrypi/rp2040/rp2040_usb.h index c4c7e625e..2ba9d018e 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.h +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.h @@ -70,6 +70,13 @@ #define __tusb_irq_path_func(x) x #endif +// Flags we set by default in sie_ctrl (we add other bits on top) +enum { + SIE_CTRL_BASE = USB_SIE_CTRL_PULLDOWN_EN_BITS | USB_SIE_CTRL_EP0_INT_1BUF_BITS, + SIE_CTRL_BASE_MASK = USB_SIE_CTRL_PULLDOWN_EN_BITS | USB_SIE_CTRL_EP0_INT_1BUF_BITS | USB_SIE_CTRL_SOF_EN_BITS | + USB_SIE_CTRL_KEEP_ALIVE_EN_BITS +}; + //--------------------------------------------------------------------+ // //--------------------------------------------------------------------+ -- cgit v1.3.1 From 6740924c41f1996c92c2459ff4e926d1d6af44ae Mon Sep 17 00:00:00 2001 From: gab-k Date: Mon, 30 Mar 2026 18:51:21 +0200 Subject: Revert back to simple edpt_disable()/edpt_activate() inside dcd_edpt_iso_activate(), Clear active EP bit in edpt_disable() --- src/portable/synopsys/dwc2/dcd_dwc2.c | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) (limited to 'src/portable') diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index 7a1d7dcf6..4ac3bdcd7 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -345,12 +345,11 @@ static void edpt_disable(uint8_t rhport, uint8_t ep_addr, bool stall) { dwc2->dctl |= DCTL_CGONAK; } } -} -// Clear stale active-endpoint state before re-activating ISO OUT with a changed MPS. -static void edpt_iso_out_reset(uint8_t rhport, uint8_t epnum) { - dwc2_dep_t* epout = &DWC2_REG(rhport)->epout[epnum]; - epout->doepctl &= ~DOEPCTL_USBAEP; + // Clear ActEP + if (!stall && epnum != 0) { + dep->ctl &= ~EPCTL_USBAEP; + } } // Since this function returns void, it is not possible to return a boolean success message @@ -637,20 +636,7 @@ bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet } bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) { - const uint8_t ep_addr = p_endpoint_desc->bEndpointAddress; - const uint8_t epnum = tu_edpt_number(ep_addr); - const uint8_t dir = tu_edpt_dir(ep_addr); - - edpt_disable(rhport, ep_addr, false); - - if (dir == TUSB_DIR_OUT) { - const uint16_t new_mps = tu_edpt_packet_size(p_endpoint_desc); - xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, dir); - if (xfer->max_size != 0 && xfer->max_size != new_mps) { - edpt_iso_out_reset(rhport, epnum); - } - } - + edpt_disable(rhport, p_endpoint_desc->bEndpointAddress, false); edpt_activate(rhport, p_endpoint_desc); return true; } -- cgit v1.3.1 From 9c2600d496d02c60935ef38e68427267bdae46fe Mon Sep 17 00:00:00 2001 From: gab-k Date: Mon, 30 Mar 2026 18:56:41 +0200 Subject: Revert unintentional removal of comment --- src/portable/synopsys/dwc2/dcd_dwc2.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/portable') diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index 4ac3bdcd7..e32dedd1b 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -636,6 +636,7 @@ bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet } bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) { + // Disable EP to clear potential incomplete transfers edpt_disable(rhport, p_endpoint_desc->bEndpointAddress, false); edpt_activate(rhport, p_endpoint_desc); return true; -- cgit v1.3.1 From 660c8ca087c8006433301d9208143438f5f456a1 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 31 Mar 2026 16:01:58 +0700 Subject: host abort transfer on short packet in double buffer. --- src/portable/raspberrypi/rp2040/rp2040_usb.c | 65 +++++++++++++--------------- 1 file changed, 31 insertions(+), 34 deletions(-) (limited to 'src/portable') diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index ffb5fcbc6..21237b059 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -102,6 +102,7 @@ void rp2usb_init(void) { void __tusb_irq_path_func(rp2usb_reset_transfer)(hw_endpoint_t *ep) { ep->active = false; + ep->pending = 0; ep->remaining_len = 0; ep->xferred_len = 0; ep->user_buf = 0; @@ -172,9 +173,8 @@ uint16_t __tusb_irq_path_func(bufctrl_prepare16)(hw_endpoint_t *ep, uint8_t *dpr buf_ctrl |= USB_BUF_CTRL_FULL; } - // Is this the last buffer? Only really matters for host mode. Will trigger - // the trans complete irq but also stop it polling. We only really care about - // trans complete for setup packets being sent + // Is this the last buffer? Will trigger the trans complete irq but also stop it polling. + // This is used to detect setup packets being sent in host mode if (ep->remaining_len == 0) { buf_ctrl |= USB_BUF_CTRL_LAST; } @@ -349,7 +349,7 @@ bool __tusb_irq_path_func(rp2usb_xfer_continue)(hw_endpoint_t *ep, io_rw_32 *ep_ uint8_t *dpram_buf = ep->dpram_buf; if (buf_id) { #if CFG_TUSB_RP2_ERRATA_E4 - if (!(is_host && !is_double)) // incorrect buf_id, buffer data is still buf0 + if (!(is_host && !is_double)) // E4 bug: incorrect buf_id, buffer data is still buf0 #endif { dpram_buf += 64; // buf1 offset @@ -370,54 +370,51 @@ bool __tusb_irq_path_func(rp2usb_xfer_continue)(hw_endpoint_t *ep, io_rw_32 *ep_ // Note: Host mode current does not save next transfer data due to shared epx --> potential issue. However, RP2040-E4 // causes more or less of the same issue since it write to buf1 and next time it continues to transfer on buf0 (stale) if (is_short && is_double && is_rx && !is_last) { - #if CFG_TUH_ENABLED + const uint32_t abort_bit = TU_BIT(tu_edpt_number(ep->ep_addr) << 1); // abort is device only -> IN endpoint + if (is_host) { - // stop current transfer - uint32_t sie_ctrl = usb_hw->sie_ctrl & SIE_CTRL_BASE_MASK; - sie_ctrl |= USB_SIE_CTRL_STOP_TRANS_BITS; + // host stop current transfer, not safe, can be racing + const uint32_t sie_ctrl = (usb_hw->sie_ctrl & SIE_CTRL_BASE_MASK) | USB_SIE_CTRL_STOP_TRANS_BITS; usb_hw->sie_ctrl = sie_ctrl; - // maybe wait until STOP_TRANS bit is clear - - *buf_reg = 0; // reset buffer control - } - #endif - - #if CFG_TUD_ENABLED - if (!is_host) { - io_rw_16 *buf_reg16_other = buf_reg16 + (buf_id ^ 1); - const uint32_t abort_bit = TU_BIT(tu_edpt_number(ep->ep_addr) << 1); // IN endpoint - - #if CFG_TUSB_RP2_ERRATA_E2 + while (usb_hw->sie_ctrl & USB_SIE_CTRL_STOP_TRANS_BITS) {} + } else { + // device abort current transfer + #if CFG_TUSB_RP2_ERRATA_E2 if (rp2040_chipversion >= 2) - #endif + #endif { usb_hw_set->abort = abort_bit; while ((usb_hw->abort_done & abort_bit) != abort_bit) {} } + } - // After abort, check if the other buffer received valid data - const uint16_t buf_ctrl16_other = *buf_reg16_other; - if (buf_ctrl16_other & USB_BUF_CTRL_FULL) { - // Host already sent data into this buffer (e.g. write payload right after short CBW). - // Save it for the next transfer. - ep->future_len = (uint8_t)(buf_ctrl16_other & USB_BUF_CTRL_LEN_MASK); - ep->future_bufid = buf_id ^ 1; - // buff_status will be clear by the next run + // After abort, check if the other buffer received valid data + io_rw_16 *buf_reg16_other = buf_reg16 + (buf_id ^ 1); + const uint16_t buf_ctrl16_other = *buf_reg16_other; + if (buf_ctrl16_other & USB_BUF_CTRL_FULL) { + // Data already sent into this buffer. Save it for the next transfer. + // buff_status will be clear by the next run + if (is_host) { + // host put future_len pointer at end of epx_data } else { - ep->next_pid ^= 1u; // roll back pid if aborted + ep->future_len = (uint8_t)(buf_ctrl16_other & USB_BUF_CTRL_LEN_MASK); } + ep->future_bufid = buf_id ^ 1; + } else { + ep->next_pid ^= 1u; // roll back pid if aborted + } - *buf_reg = 0; // reset buffer control + *buf_reg = 0; // reset buffer control - #if CFG_TUSB_RP2_ERRATA_E2 + if (!is_host) { + #if CFG_TUSB_RP2_ERRATA_E2 if (rp2040_chipversion >= 2) - #endif + #endif { usb_hw_clear->abort_done = abort_bit; usb_hw_clear->abort = abort_bit; } } - #endif hw_endpoint_lock_update(ep, -1); return true; -- cgit v1.3.1 From 9ac343a0471b03b1a76166c72347e7fdbf2c4800 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 31 Mar 2026 17:41:50 +0700 Subject: finally get rp2040 host epx working with 2-sof solution for switching --- src/portable/raspberrypi/rp2040/dcd_rp2040.c | 2 +- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 314 +++++++++++++++------------ src/portable/raspberrypi/rp2040/rp2040_usb.c | 2 +- test/hil/hil_test.py | 11 +- 4 files changed, 189 insertions(+), 140 deletions(-) (limited to 'src/portable') diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index d4c1bf708..8814f95d1 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -164,7 +164,7 @@ static void __tusb_irq_path_func(handle_hw_buff_status)(void) { while (buf_status) { // ctz/clz is faster than loop which has only a few bit set in general const uint8_t i = (uint8_t) __builtin_ctz(buf_status); - const uint bit = TU_BIT(i); + const uint32_t bit = TU_BIT(i); // IN transfer for even i, OUT transfer for odd i const uint8_t epnum = i >> 1u; diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index 3a99e7275..fb1676f50 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -1,3 +1,4 @@ + /* * The MIT License (MIT) * @@ -29,23 +30,23 @@ #if CFG_TUH_ENABLED && (CFG_TUSB_MCU == OPT_MCU_RP2040) && !CFG_TUH_RPI_PIO_USB && !CFG_TUH_MAX3421 -#include "pico.h" + #include "pico.h" -#if defined(PICO_RP2350) && PICO_RP2350 == 1 -#define HAS_STOP_EPX_ON_NAK -#endif + #if defined(PICO_RP2350) && PICO_RP2350 == 1 + #define HAS_STOP_EPX_ON_NAK + #endif // port 0 is native USB port, other is counted as software PIO #define RHPORT_NATIVE 0 -//--------------------------------------------------------------------+ + //--------------------------------------------------------------------+ // INCLUDE -//--------------------------------------------------------------------+ -#include "rp2040_usb.h" -#include "osal/osal.h" + //--------------------------------------------------------------------+ + #include "rp2040_usb.h" + #include "osal/osal.h" -#include "host/hcd.h" -#include "host/usbh.h" + #include "host/hcd.h" + #include "host/usbh.h" //--------------------------------------------------------------------+ // @@ -55,6 +56,9 @@ static hw_endpoint_t ep_pool[USB_MAX_ENDPOINTS]; static hw_endpoint_t *epx = &ep_pool[0]; // current active endpoint + #ifndef HAS_STOP_EPX_ON_NAK +static volatile bool epx_switch_request = false; + #endif enum { SIE_CTRL_SPEED_DISCONNECT = 0, @@ -67,7 +71,7 @@ enum { //--------------------------------------------------------------------+ static hw_endpoint_t *edpt_alloc(void) { - for (uint i = 0; i < TU_ARRAY_SIZE(ep_pool); i++) { + for (uint i = 1; i < TU_ARRAY_SIZE(ep_pool); i++) { hw_endpoint_t *ep = &ep_pool[i]; if (ep->max_packet_size == 0) { return ep; @@ -89,11 +93,11 @@ static hw_endpoint_t *edpt_find(uint8_t daddr, uint8_t ep_addr) { } TU_ATTR_ALWAYS_INLINE static inline io_rw_32 *dpram_int_ep_ctrl(uint8_t int_num) { - return &usbh_dpram->int_ep_ctrl[int_num-1].ctrl; + return &usbh_dpram->int_ep_ctrl[int_num - 1].ctrl; } -TU_ATTR_ALWAYS_INLINE static inline io_rw_32 * dpram_int_ep_buffer_ctrl(uint8_t int_num) { - return &usbh_dpram->int_ep_buffer_ctrl[int_num-1].ctrl; +TU_ATTR_ALWAYS_INLINE static inline io_rw_32 *dpram_int_ep_buffer_ctrl(uint8_t int_num) { + return &usbh_dpram->int_ep_buffer_ctrl[int_num - 1].ctrl; } //--------------------------------------------------------------------+ @@ -113,30 +117,41 @@ TU_ATTR_ALWAYS_INLINE static inline bool need_pre(uint8_t dev_addr) { //--------------------------------------------------------------------+ // EPX //--------------------------------------------------------------------+ +TU_ATTR_ALWAYS_INLINE static inline void sie_stop_xfer(void) { + uint32_t sie_ctrl = (usb_hw->sie_ctrl & SIE_CTRL_BASE_MASK) | USB_SIE_CTRL_STOP_TRANS_BITS; + usb_hw->sie_ctrl = sie_ctrl; + while (usb_hw->sie_ctrl & USB_SIE_CTRL_STOP_TRANS_BITS) {} +} + TU_ATTR_ALWAYS_INLINE static inline void sie_start_xfer(bool send_setup, bool is_rx, bool need_pre) { - uint32_t value = usb_hw->sie_ctrl & SIE_CTRL_BASE_MASK; // preserve base bits + uint32_t sie_ctrl = usb_hw->sie_ctrl & SIE_CTRL_BASE_MASK; // preserve base bits if (send_setup) { - value |= USB_SIE_CTRL_SEND_SETUP_BITS; + sie_ctrl |= USB_SIE_CTRL_SEND_SETUP_BITS; } else { - value |= (is_rx ? USB_SIE_CTRL_RECEIVE_DATA_BITS : USB_SIE_CTRL_SEND_DATA_BITS); + sie_ctrl |= (is_rx ? USB_SIE_CTRL_RECEIVE_DATA_BITS : USB_SIE_CTRL_SEND_DATA_BITS); } if (need_pre) { - value |= USB_SIE_CTRL_PREAMBLE_EN_BITS; + sie_ctrl |= USB_SIE_CTRL_PREAMBLE_EN_BITS; } // START_TRANS bit on SIE_CTRL has the same behavior as the AVAILABLE bit // described in RP2040 Datasheet, release 2.1, section "4.1.2.5.1. Concurrent access". // We write everything except the START_TRANS bit first, then wait some cycles. - usb_hw->sie_ctrl = value; + usb_hw->sie_ctrl = sie_ctrl; busy_wait_at_least_cycles(12); - usb_hw->sie_ctrl = value | USB_SIE_CTRL_START_TRANS_BITS; + usb_hw->sie_ctrl = sie_ctrl | USB_SIE_CTRL_START_TRANS_BITS; +} + +TU_ATTR_ALWAYS_INLINE static inline void epx_start_xfer(hw_endpoint_t *ep, bool is_setup) { + usb_hw->dev_addr_ctrl = (uint32_t)(ep->dev_addr | (tu_edpt_number(ep->ep_addr) << USB_ADDR_ENDP_ENDPOINT_LSB)); + sie_start_xfer(is_setup, tu_edpt_dir(ep->ep_addr) == TUSB_DIR_IN, ep->need_pre); } // prepare epx_ctrl register for new endpoint TU_ATTR_ALWAYS_INLINE static inline void epx_ctrl_prepare(hw_endpoint_t *ep) { - // RP2040-E4: USB host writes status to upper half of buffer control in single buffered mode. + // RP2040-E4: USB host writes status to the upper half of buffer control in single buffered mode. // The buffer selector toggles even in single-buffered mode, so the previous transfer's status - // may have been written to BUF1 half, leaving BUF0 with stale AVAILABLE bit. Clear it here. + // may have been written to BUF1 half, leaving BUF0 with a stale AVAILABLE bit. Clear it here. #if defined(PICO_RP2040) && PICO_RP2040 == 1 usbh_dpram->epx_buf_ctrl = 0; #endif @@ -147,23 +162,46 @@ TU_ATTR_ALWAYS_INLINE static inline void epx_ctrl_prepare(hw_endpoint_t *ep) { usbh_dpram->epx_ctrl = ep_ctrl; } -// save on-going context -static void __tusb_irq_path_func(epx_save_context)(void) { - const uint32_t buf_ctrl = usbh_dpram->epx_buf_ctrl; - const uint16_t buf0_len = buf_ctrl & USB_BUF_CTRL_LEN_MASK; // TODO handle double buffered case - epx->remaining_len = (uint16_t)(epx->remaining_len + buf0_len); - epx->next_pid = (buf_ctrl & USB_BUF_CTRL_DATA1_PID) ? 1 : 0; - if (tu_edpt_dir(epx->ep_addr) == TUSB_DIR_OUT) { - epx->user_buf -= buf0_len; - } - epx->pending = 1; - epx->active = false; +// Save buffer context for EPX preemption (called after STOP_TRANS). +// Undo PID toggle and buffer accounting for buffers NOT completed on the wire. +// A buffer completed on wire means: controller reached STATUS phase (ACK received). +// OUT completed: FULL cleared to 0 in STATUS phase (was 1 when armed) +// IN completed: FULL set to 1 in STATUS phase (was 0 when armed) +// So undo when: AVAIL=1 (never started), or (OUT: FULL=1) or (IN: FULL=0) +static void __tusb_irq_path_func(epx_save_context)(hw_endpoint_t *ep) { + uint32_t buf_ctrl = usbh_dpram->epx_buf_ctrl; + const bool is_out = (tu_edpt_dir(ep->ep_addr) == TUSB_DIR_OUT); + + do { + const uint16_t bc16 = (uint16_t)buf_ctrl; + if (bc16) { + const bool avail = (bc16 & USB_BUF_CTRL_AVAIL); + const bool full = (bc16 & USB_BUF_CTRL_FULL); + if (avail || (is_out ? full : !full)) { + const uint16_t buf_len = bc16 & USB_BUF_CTRL_LEN_MASK; + ep->remaining_len += buf_len; + ep->next_pid ^= 1u; + if (is_out) { + ep->user_buf -= buf_len; + } + } + } + + if (usbh_dpram->epx_ctrl & EP_CTRL_DOUBLE_BUFFERED_BITS) { + buf_ctrl >>= 16; + } else { + buf_ctrl = 0; + } + } while (buf_ctrl > 0); usbh_dpram->epx_buf_ctrl = 0; + + ep->pending = 1; + ep->active = false; } // All non-interrupt endpoints use shared EPX. -// Save current EPX context, mark pending, switch to ep +// Save the current EPX context, mark pending, switch to ep static void __tusb_irq_path_func(epx_switch_ep)(hw_endpoint_t *ep) { const bool is_setup = (ep->pending == 2); @@ -172,19 +210,17 @@ static void __tusb_irq_path_func(epx_switch_ep)(hw_endpoint_t *ep) { ep->active = true; if (is_setup) { - usb_hw->dev_addr_ctrl = ep->dev_addr; - sie_start_xfer(true, false, ep->need_pre); + // panic("new setup \n"); + epx_start_xfer(ep, true); } else { - const uint8_t ep_num = tu_edpt_number(ep->ep_addr); - const bool is_rx = tu_edpt_dir(ep->ep_addr) == TUSB_DIR_IN; - io_rw_32 *ep_reg = &usbh_dpram->epx_ctrl; - io_rw_32 *buf_reg = &usbh_dpram->epx_buf_ctrl; + io_rw_32 *ep_reg = &usbh_dpram->epx_ctrl; + io_rw_32 *buf_reg = &usbh_dpram->epx_buf_ctrl; epx_ctrl_prepare(ep); - rp2usb_buffer_start(ep, ep_reg, buf_reg, is_rx, ep->transfer_type == TUSB_XFER_INTERRUPT); + rp2usb_buffer_start(ep, ep_reg, buf_reg, tu_edpt_dir(ep->ep_addr) == TUSB_DIR_IN, + ep->transfer_type == TUSB_XFER_INTERRUPT); - usb_hw->dev_addr_ctrl = (uint32_t)(ep->dev_addr | (ep_num << USB_ADDR_ENDP_ENDPOINT_LSB)); - sie_start_xfer(false, is_rx, ep->need_pre); // start transfer + epx_start_xfer(ep, false); } } @@ -208,16 +244,14 @@ static hw_endpoint_t *__tusb_irq_path_func(epx_next_pending)(hw_endpoint_t *cur_ //--------------------------------------------------------------------+ // Interrupt handlers //--------------------------------------------------------------------+ -static void __tusb_irq_path_func(xfer_complete_isr)(hw_endpoint_t *ep, xfer_result_t xfer_result) { +static void __tusb_irq_path_func(xfer_complete_isr)(hw_endpoint_t *ep, xfer_result_t xfer_result, bool is_more) { // Mark transfer as done before we tell the tinyusb stack - uint8_t dev_addr = ep->dev_addr; - uint8_t ep_addr = ep->ep_addr; - uint xferred_len = ep->xferred_len; + uint xferred_len = ep->xferred_len; rp2usb_reset_transfer(ep); - hcd_event_xfer_complete(dev_addr, ep_addr, xferred_len, xfer_result, true); + hcd_event_xfer_complete(ep->dev_addr, ep->ep_addr, xferred_len, xfer_result, true); // Carry more transfer on epx - if (ep == epx) { + if (is_more) { hw_endpoint_t *next_ep = epx_next_pending(epx); if (next_ep != NULL) { epx_switch_ep(next_ep); @@ -231,26 +265,31 @@ static void __tusb_irq_path_func(handle_buf_status_isr)(void) { BUF_STATUS_EPX = 1u }; - // Check EPX first (bit 0). EPX is currently single-buffered, always use buf_id=0.3 + // Check EPX first (bit 0). // Double-buffered: if both buffers completed at once, buf_status re-sets // immediately after clearing (datasheet Table 406). Process the second buffer too. while (usb_hw->buf_status & BUF_STATUS_EPX) { - const uint8_t buf_id = (usb_hw->buf_cpu_should_handle & BUF_STATUS_EPX) ? 1 : 0; + const uint8_t buf_id = (usb_hw->buf_cpu_should_handle & BUF_STATUS_EPX) ? 1 : 0; usb_hw_clear->buf_status = 1u; // clear io_rw_32 *ep_reg = &usbh_dpram->epx_ctrl; io_rw_32 *buf_reg = &usbh_dpram->epx_buf_ctrl; + #ifndef HAS_STOP_EPX_ON_NAK + // Any packet completion (mid-transfer or final) means data is flowing. + // Clear switch request so the 2-SOF fallback only fires for NAK-retrying endpoints. + epx_switch_request = false; + #endif if (rp2usb_xfer_continue(epx, ep_reg, buf_reg, buf_id, tu_edpt_dir(epx->ep_addr) == TUSB_DIR_IN)) { - xfer_complete_isr(epx, XFER_RESULT_SUCCESS); + xfer_complete_isr(epx, XFER_RESULT_SUCCESS, true); } } // Check "interrupt" (asynchronous) endpoints for both IN and OUT - uint32_t buf_status = usb_hw->buf_status & (uint32_t)~BUF_STATUS_EPX; + uint32_t buf_status = usb_hw->buf_status & ~(uint32_t)BUF_STATUS_EPX; while (buf_status) { // ctz/clz is faster than loop which has only a few bit set in general - const uint8_t idx = (uint8_t) __builtin_ctz(buf_status); - const uint bit = TU_BIT(idx); + const uint8_t idx = (uint8_t)__builtin_ctz(buf_status); + const uint32_t bit = TU_BIT(idx); usb_hw_clear->buf_status = bit; buf_status &= ~bit; @@ -258,7 +297,7 @@ static void __tusb_irq_path_func(handle_buf_status_isr)(void) { // EPX is bit 0. Bit 1 is not used // IEP1 IN/OUT is bit 2, 3 // IEP2 IN/OUT is bit 4, 5 etc - const uint8_t epnum = idx >> 1u; + const uint8_t epnum = idx >> 1u; for (size_t e = 0; e < TU_ARRAY_SIZE(ep_pool); e++) { hw_endpoint_t *ep = &ep_pool[e]; if (ep->interrupt_num == epnum) { @@ -266,7 +305,7 @@ static void __tusb_irq_path_func(handle_buf_status_isr)(void) { io_rw_32 *buf_reg = dpram_int_ep_buffer_ctrl(ep->interrupt_num); const bool done = rp2usb_xfer_continue(ep, ep_reg, buf_reg, 0, tu_edpt_dir(ep->ep_addr) == TUSB_DIR_IN); if (done) { - xfer_complete_isr(ep, XFER_RESULT_SUCCESS); + xfer_complete_isr(ep, XFER_RESULT_SUCCESS, false); } break; } @@ -293,69 +332,80 @@ static void __tusb_irq_path_func(hcd_rp2040_irq)(void) { } if (status & USB_INTS_STALL_BITS) { - // We have rx'd a stall from the device - // NOTE THIS SHOULD HAVE PRIORITY OVER BUFF_STATUS - // AND TRANS_COMPLETE as the stall is an alternative response - // to one of those events usb_hw_clear->sie_status = USB_SIE_STATUS_STALL_REC_BITS; - xfer_complete_isr(epx, XFER_RESULT_STALLED); + xfer_complete_isr(epx, XFER_RESULT_STALLED, true); } - if (status & USB_INTS_BUFF_STATUS_BITS) { - handle_buf_status_isr(); + if (status & USB_INTS_ERROR_RX_TIMEOUT_BITS) { + usb_hw_clear->sie_status = USB_SIE_STATUS_RX_TIMEOUT_BITS; + + const uint32_t sie_ctrl = (usb_hw->sie_ctrl & SIE_CTRL_BASE_MASK) | USB_SIE_CTRL_STOP_TRANS_BITS; + usb_hw->sie_ctrl = sie_ctrl; + // while (usb_hw->sie_ctrl & USB_SIE_CTRL_STOP_TRANS_BITS) {} + + // Even if STOP_TRANS bit is clear, controller maybe in middle of retrying and may re-raise timeout once extra time + // Only handle if epx is active, don't carry more epx transfer since STOP_TRANS is raced and not safe. + if (epx->active) { + xfer_complete_isr(epx, XFER_RESULT_FAILED, false); + } } if (status & USB_INTS_TRANS_COMPLETE_BITS) { + // only applies for epx, interrupt endpoint does not seem to raise this usb_hw_clear->sie_status = USB_SIE_STATUS_TRANS_COMPLETE_BITS; - - // only handle a setup packet if (usb_hw->sie_ctrl & USB_SIE_CTRL_SEND_SETUP_BITS) { - epx->xferred_len = 8; - xfer_complete_isr(epx, XFER_RESULT_SUCCESS); - } else { - // Don't care. Will handle this in buff status + uint32_t sie_ctrl = usb_hw->sie_ctrl & SIE_CTRL_BASE_MASK; + usb_hw->sie_ctrl = sie_ctrl; // clear setup bit + epx->xferred_len = 8; + xfer_complete_isr(epx, XFER_RESULT_SUCCESS, true); } } + if (status & USB_INTS_BUFF_STATUS_BITS) { + handle_buf_status_isr(); + } + + // SOF-based round-robin MUST run BEFORE BUFF_STATUS to avoid processing + // buf_status on the wrong EPX after a completion+switch in handle_buf_status_isr. #ifdef HAS_STOP_EPX_ON_NAK if (status & USB_INTS_EPX_STOPPED_ON_NAK_BITS) { usb_hw_clear->nak_poll = USB_NAK_POLL_EPX_STOPPED_ON_NAK_BITS; hw_endpoint_t *next_ep = epx_next_pending(epx); if (next_ep != NULL) { - epx_save_context(); + epx_save_context(epx); epx_switch_ep(next_ep); } else { - // No pending endpoint, this is the only active one: disable stop-on-NAK, continue current transfer usb_hw_clear->nak_poll = USB_NAK_POLL_STOP_EPX_ON_NAK_BITS; sie_start_xfer(false, TUSB_DIR_IN == tu_edpt_dir(epx->ep_addr), epx->need_pre); } } #else - // RP2040: on SOF, stop and switch if there's a pending ep + // RP2040: on SOF, switch EPX if another endpoint is pending. + // First SOF sets epx_switch_request. If a transfer completes before next SOF, the flag is + // cleared (data is flowing, no need to force-switch). Second SOF with flag still set means + // no data exchanged (endpoint NAK-retrying): STOP_TRANS is safe and we switch. + // This avoids stopping mid-data-transfer which corrupts double-buffered PID tracking. if (status & USB_INTS_HOST_SOF_BITS) { (void)usb_hw->sof_rd; // clear SOF by reading SOF_RD hw_endpoint_t *next_ep = epx_next_pending(epx); if (next_ep == NULL) { - // no more pending --> disable SOF usb_hw_clear->inte = USB_INTE_HOST_SOF_BITS; usb_hw->nak_poll = USB_NAK_POLL_RESET; - } else { - // stop transfer if is active - if (epx->active) { - usb_hw_set->sie_ctrl = USB_SIE_CTRL_STOP_TRANS_BITS; - while (usb_hw->sie_ctrl & USB_SIE_CTRL_STOP_TRANS_BITS) {} + epx_switch_request = false; + } else if (epx->active) { + if (epx_switch_request) { + // Second SOF with no transfer completion: endpoint is NAK-retrying, safe to switch. + epx_switch_request = false; + sie_stop_xfer(); + epx_save_context(epx); + epx_switch_ep(next_ep); + } else { + epx_switch_request = true; } - - epx_save_context(); - epx_switch_ep(next_ep); } } #endif - if (status & USB_INTS_ERROR_RX_TIMEOUT_BITS) { - usb_hw_clear->sie_status = USB_SIE_STATUS_RX_TIMEOUT_BITS; - } - if (status & USB_INTS_ERROR_DATA_SEQ_BITS) { usb_hw_clear->sie_status = USB_SIE_STATUS_DATA_SEQ_ERROR_BITS; panic("Data Seq Error \n"); @@ -371,9 +421,9 @@ void __tusb_irq_path_func(hcd_int_handler)(uint8_t rhport, bool in_isr) { //--------------------------------------------------------------------+ // HCD API //--------------------------------------------------------------------+ -bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { - (void) rhport; - (void) rh_init; +bool hcd_init(uint8_t rhport, const tusb_rhport_init_t *rh_init) { + (void)rhport; + (void)rh_init; pico_trace("hcd_init %d\n", rhport); assert(rhport == 0); @@ -392,24 +442,20 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { // Enable in host mode with SOF / Keep alive on usb_hw->main_ctrl = USB_MAIN_CTRL_CONTROLLER_EN_BITS | USB_MAIN_CTRL_HOST_NDEVICE_BITS; - usb_hw->sie_ctrl = SIE_CTRL_BASE; - usb_hw->inte = USB_INTE_BUFF_STATUS_BITS | - USB_INTE_HOST_CONN_DIS_BITS | - USB_INTE_HOST_RESUME_BITS | - USB_INTE_STALL_BITS | - USB_INTE_TRANS_COMPLETE_BITS | - USB_INTE_ERROR_RX_TIMEOUT_BITS | - USB_INTE_ERROR_DATA_SEQ_BITS ; - -#ifdef HAS_STOP_EPX_ON_NAK + usb_hw->sie_ctrl = SIE_CTRL_BASE; + usb_hw->inte = USB_INTE_BUFF_STATUS_BITS | USB_INTE_HOST_CONN_DIS_BITS | USB_INTE_HOST_RESUME_BITS | + USB_INTE_STALL_BITS | USB_INTE_TRANS_COMPLETE_BITS | USB_INTE_ERROR_RX_TIMEOUT_BITS | + USB_INTE_ERROR_DATA_SEQ_BITS; + + #ifdef HAS_STOP_EPX_ON_NAK usb_hw_set->inte = USB_INTE_EPX_STOPPED_ON_NAK_BITS; -#endif + #endif return true; } bool hcd_deinit(uint8_t rhport) { - (void) rhport; + (void)rhport; irq_remove_handler(USBCTRL_IRQ, hcd_rp2040_irq); reset_block(RESETS_RESET_USBCTRL_BITS); unreset_block_wait(RESETS_RESET_USBCTRL_BITS); @@ -417,7 +463,7 @@ bool hcd_deinit(uint8_t rhport) { } void hcd_port_reset(uint8_t rhport) { - (void) rhport; + (void)rhport; // TODO: Nothing to do here yet. Perhaps need to reset some state? } @@ -445,7 +491,10 @@ tusb_speed_t hcd_port_speed_get(uint8_t rhport) { // Close all opened endpoint belong to this device void hcd_device_close(uint8_t rhport, uint8_t dev_addr) { (void)rhport; - (void)dev_addr; + + if (dev_addr == 0) { + return; // address 0 is for device enumeration + } // reset epx if it is currently active with unplugged device if (epx->max_packet_size > 0 && epx->dev_addr == dev_addr) { @@ -462,13 +511,13 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr) { if (ep->interrupt_num) { // disable interrupt endpoint - usb_hw_clear->int_ep_ctrl = 1u << ep->interrupt_num; + usb_hw_clear->int_ep_ctrl = TU_BIT(ep->interrupt_num); usb_hw->int_ep_addr_ctrl[ep->interrupt_num - 1] = 0; io_rw_32 *ep_reg = dpram_int_ep_ctrl(ep->interrupt_num); io_rw_32 *buf_reg = dpram_int_ep_buffer_ctrl(ep->interrupt_num); - *buf_reg = 0; - *ep_reg = 0; + *buf_reg = 0; + *ep_reg = 0; } ep->max_packet_size = 0; // mark as unused @@ -498,13 +547,17 @@ void hcd_int_disable(uint8_t rhport) { bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, const tusb_desc_endpoint_t *ep_desc) { (void)rhport; pico_trace("hcd_edpt_open dev_addr %d, ep_addr %d\n", dev_addr, ep_desc->bEndpointAddress); - hw_endpoint_t *ep = edpt_alloc(); + hw_endpoint_t *ep; + if (dev_addr == 0) { + ep = &ep_pool[0]; + } else { + ep = edpt_alloc(); + } TU_ASSERT(ep); const uint8_t ep_addr = ep_desc->bEndpointAddress; const uint16_t max_packet_size = tu_edpt_packet_size(ep_desc); const uint8_t transfer_type = ep_desc->bmAttributes.xfer; - // const uint8_t bmInterval = ep_desc->bInterval; ep->max_packet_size = max_packet_size; ep->ep_addr = ep_addr; @@ -532,7 +585,7 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, const tusb_desc_endpoint_t ep->dpram_buf = (uint8_t *)(USBCTRL_DPRAM_BASE + USB_DPRAM_MAX - (int_idx + 1u) * 64u); uint32_t ep_ctrl = EP_CTRL_ENABLE_BITS | EP_CTRL_INTERRUPT_PER_BUFFER | (TUSB_XFER_INTERRUPT << EP_CTRL_BUFFER_TYPE_LSB) | hw_data_offset(ep->dpram_buf) | - (uint32_t)((ep_desc->bInterval - 1) << EP_CTRL_HOST_INTERRUPT_INTERVAL_LSB); + ((uint32_t)(ep_desc->bInterval - 1) << EP_CTRL_HOST_INTERRUPT_INTERVAL_LSB); usbh_dpram->int_ep_ctrl[int_idx].ctrl = ep_ctrl; //------------- address control -------------// @@ -547,7 +600,7 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, const tusb_desc_endpoint_t usb_hw->int_ep_addr_ctrl[int_idx] = addr_ctrl; // Finally, activate interrupt endpoint - usb_hw_set->int_ep_ctrl = 1u << ep->interrupt_num; + usb_hw_set->int_ep_ctrl = TU_BIT(ep->interrupt_num); } return true; @@ -560,6 +613,14 @@ bool hcd_edpt_close(uint8_t rhport, uint8_t daddr, uint8_t ep_addr) { return false; // TODO not implemented yet } +bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { + (void)rhport; + (void)dev_addr; + (void)ep_addr; + // TODO not implemented yet + return false; +} + bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *buffer, uint16_t buflen) { (void)rhport; @@ -594,19 +655,14 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *b usb_hw_set->inte = USB_INTE_HOST_SOF_BITS; #endif } else { - const uint8_t ep_num = tu_edpt_number(ep->ep_addr); - const tusb_dir_t ep_dir = tu_edpt_dir(ep->ep_addr); - const bool is_rx = (ep_dir == TUSB_DIR_IN); - io_rw_32 *ep_reg = &usbh_dpram->epx_ctrl; - io_rw_32 *buf_reg = &usbh_dpram->epx_buf_ctrl; + io_rw_32 *ep_reg = &usbh_dpram->epx_ctrl; + io_rw_32 *buf_reg = &usbh_dpram->epx_buf_ctrl; epx = ep; epx_ctrl_prepare(ep); rp2usb_xfer_start(ep, ep_reg, buf_reg, buffer, NULL, buflen); // prepare bufctrl - - usb_hw->dev_addr_ctrl = (uint32_t)(ep->dev_addr | (ep_num << USB_ADDR_ENDP_ENDPOINT_LSB)); - sie_start_xfer(false, is_rx, ep->need_pre); // start transfer + epx_start_xfer(ep, false); } rp2usb_critical_exit(); } @@ -614,27 +670,19 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *b return true; } -bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { - (void)rhport; - (void)dev_addr; - (void)ep_addr; - // TODO not implemented yet - return false; -} - bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, const uint8_t setup_packet[8]) { (void)rhport; - // Copy data into setup packet buffer (usbh only schedules one setup at a time) - for (uint8_t i = 0; i < 8; i++) { - usbh_dpram->setup_packet[i] = setup_packet[i]; - } - hw_endpoint_t *ep = edpt_find(dev_addr, 0x00); TU_ASSERT(ep); rp2usb_critical_enter(); + // Copy data into setup packet buffer (usbh only schedules one setup at a time) + for (uint8_t i = 0; i < 8; i++) { + usbh_dpram->setup_packet[i] = setup_packet[i]; + } + ep->ep_addr = 0; // setup is OUT ep->remaining_len = 8; ep->xferred_len = 0; @@ -651,9 +699,7 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, const uint8_t setup_packet } else { epx = ep; ep->active = true; - - usb_hw->dev_addr_ctrl = dev_addr; // Set device address - sie_start_xfer(true, false, ep->need_pre); // start transfer + epx_start_xfer(ep, true); } rp2usb_critical_exit(); diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index 21237b059..156be62e4 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -197,7 +197,7 @@ void __tusb_irq_path_func(rp2usb_buffer_start)(hw_endpoint_t *ep, io_rw_32 *ep_r ep_ctrl |= EP_CTRL_DOUBLE_BUFFERED_BITS; } else { // Only buf0 used: clear DOUBLE_BUFFERED so controller doesn't toggle buffer selector - ep_ctrl &= ~EP_CTRL_DOUBLE_BUFFERED_BITS; + ep_ctrl &= ~(uint32_t)EP_CTRL_DOUBLE_BUFFERED_BITS; } *ep_reg = ep_ctrl; } diff --git a/test/hil/hil_test.py b/test/hil/hil_test.py index 04dd4e2bc..cf3cff1a3 100755 --- a/test/hil/hil_test.py +++ b/test/hil/hil_test.py @@ -50,7 +50,7 @@ import ctypes from pymtp import MTP import string -ENUM_TIMEOUT = 10 +ENUM_TIMEOUT = 15 STATUS_OK = "\033[32mOK\033[0m" STATUS_FAILED = "\033[31mFailed\033[0m" @@ -766,10 +766,13 @@ def test_device_cdc_msc(board): assert ret.returncode == 0, f'dd read failed: {ret.stdout.decode()}' read_speed = parse_dd_speed(ret.stdout.decode()) - # Write back the same data to avoid corrupting the disk + # Write back the same data to avoid corrupting the disk (skip if read-only) ret = run_cmd(f'dd if={tmp_file} of={dev} bs={block_size} count={block_count} oflag=direct 2>&1') - assert ret.returncode == 0, f'dd write failed: {ret.stdout.decode()}' - write_speed = parse_dd_speed(ret.stdout.decode()) + if ret.returncode != 0 and 'Read-only' in ret.stdout.decode(): + write_speed = 'skip (read-only)' + else: + assert ret.returncode == 0, f'dd write failed: {ret.stdout.decode()}' + write_speed = parse_dd_speed(ret.stdout.decode()) try: os.remove(tmp_file) -- cgit v1.3.1 From 78d34d5b6488d7129530461ce1865a33a946e698 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 1 Apr 2026 15:51:31 +0700 Subject: reduce code size, use state to replace active + pending --- .claude/commands/build-doc.md | 24 ++++++ .claude/commands/hil.md | 30 ++++++++ examples/host/msc_file_explorer/README.md | 105 ++++++++++++++++++++++++++ src/portable/raspberrypi/rp2040/dcd_rp2040.c | 13 ++-- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 106 ++++++++++++--------------- src/portable/raspberrypi/rp2040/rp2040_usb.c | 78 +++++++++----------- src/portable/raspberrypi/rp2040/rp2040_usb.h | 27 ++++--- tools/metrics.py | 5 +- 8 files changed, 266 insertions(+), 122 deletions(-) create mode 100644 .claude/commands/build-doc.md create mode 100644 .claude/commands/hil.md create mode 100644 examples/host/msc_file_explorer/README.md (limited to 'src/portable') diff --git a/.claude/commands/build-doc.md b/.claude/commands/build-doc.md new file mode 100644 index 000000000..c9ad9f539 --- /dev/null +++ b/.claude/commands/build-doc.md @@ -0,0 +1,24 @@ +# build-doc + +Scan all example READMEs and build the Sphinx documentation. + +## Instructions + +1. Install docs dependencies: + ```bash + pip install -r docs/requirements.txt + ``` + +2. Build the docs from the repo root: + ```bash + sphinx-build -b html docs docs/_build + ``` + `conf.py` automatically scans all `examples/{device,host,dual}/*/README.md`, copies them into `docs/examples/`, and regenerates `examples.rst` with the toctree. + +3. Use a timeout of at least 60 seconds. + +4. After the build completes: + - Show the build output to the user. + - Report total warnings and errors. + - List which example READMEs were discovered and included. + - If there are errors, suggest fixes. diff --git a/.claude/commands/hil.md b/.claude/commands/hil.md new file mode 100644 index 000000000..2ba35ec22 --- /dev/null +++ b/.claude/commands/hil.md @@ -0,0 +1,30 @@ +# hil + +Run Hardware-in-the-Loop (HIL) tests on physical boards. + +## Arguments +- $ARGUMENTS: Optional flags (e.g. board name, extra args). If empty, runs all boards with default config. + +## Instructions + +1. Determine the HIL config file: + ```bash + HIL_CONFIG=$( (systemctl list-units --type=service --state=running 2>/dev/null; systemctl --user list-units --type=service --state=running 2>/dev/null) | grep -q 'actions\.runner' && echo tinyusb.json || echo local.json ) + ``` + Default is `local.json` for local development. + +2. Parse $ARGUMENTS: + - If $ARGUMENTS contains `-b BOARD_NAME`, run for that specific board only. + - If $ARGUMENTS is empty or has no `-b`, run for all boards in the config. + - Pass through any other flags (e.g. `-v` for verbose) directly to the command. + +3. Run the HIL test from the repo root directory: + - Specific board: `python test/hil/hil_test.py -b BOARD_NAME -B examples $HIL_CONFIG $EXTRA_ARGS` + - All boards: `python test/hil/hil_test.py -B examples $HIL_CONFIG $EXTRA_ARGS` + +4. Use a timeout of at least 20 minutes (600000ms). HIL tests take 2-5 minutes. NEVER cancel early. + +5. After the test completes: + - Show the test output to the user. + - Summarize pass/fail results per board. + - If there are failures, suggest re-running with `-v` flag for verbose output to help debug. diff --git a/examples/host/msc_file_explorer/README.md b/examples/host/msc_file_explorer/README.md new file mode 100644 index 000000000..e220bedea --- /dev/null +++ b/examples/host/msc_file_explorer/README.md @@ -0,0 +1,105 @@ +# MSC File Explorer + +This host example implements an interactive command-line file browser for USB Mass Storage devices. +When a USB flash drive is connected, the device is automatically mounted using FatFS and a shell-like +CLI is presented over the board's serial console. + +## Features + +- Automatic mount/unmount of USB storage devices +- FAT12/16/32 filesystem support via FatFS +- Interactive CLI with command history +- Read speed benchmarking with `dd` +- Support for up to 4 simultaneous USB storage devices (via hub) + +## Supported Commands + +| Command | Usage | Description | +|---------|--------------------|------------------------------------------------------| +| help | `help` | Print list of available commands | +| cat | `cat ` | Print file contents to the console | +| cd | `cd ` | Change current working directory | +| cp | `cp ` | Copy a file | +| dd | `dd [count]` | Read sectors and report speed (default 1024 sectors) | +| ls | `ls [dir]` | List directory contents | +| pwd | `pwd` | Print current working directory | +| mkdir | `mkdir ` | Create a directory | +| mv | `mv ` | Rename/move a file or directory | +| rm | `rm ` | Remove a file | + +## Build + +Build for a specific board using CMake (see [Getting Started](https://docs.tinyusb.org/en/latest/getting_started.html)): + +```bash +# Example: build for Raspberry Pi Pico +cmake -B build -DBOARD=raspberry_pi_pico -DFAMILY=rp2040 examples/host/msc_file_explorer +cmake --build build +``` + +## Usage + +1. Flash the firmware to your board. +2. Open a serial terminal (e.g. `minicom`, `screen`, `PuTTY`) at 115200 baud. +3. Plug a USB flash drive into the board's USB host port. +4. The device is auto-mounted and the prompt appears: + +``` +TinyUSB MSC File Explorer Example + +Device connected + Vendor : Kingston + Product : DataTraveler 2.0 + Rev : 1.0 + Capacity: 1.9 GB + +0:/> _ +``` + +### Browsing Files + +``` +0:/> ls +----a 1234 readme.txt +d---- 0 photos +d---- 0 docs + +0:/> cd photos +0:/photos> ls +----a 520432 vacation.jpg +----a 312088 family.png + +0:/> cat readme.txt +Hello from USB drive! +``` + +### Copying and Moving Files + +``` +0:/> cp readme.txt backup.txt +0:/> mv backup.txt docs/backup.txt +``` + +### Measuring Read Speed + +``` +0:/> dd +Reading 1024 sectors... + Data speed: 823 KB/s +``` + +### Multiple Devices + +When using a USB hub, multiple drives are mounted as `0:`, `1:`, etc. Use the drive prefix to +navigate between them: + +``` +0:/> cd 1: +1:/> ls +``` + +## Testing + +This example is part of the TinyUSB HIL (Hardware-in-the-Loop) test suite. The HIL test +automatically flashes, runs the example, and verifies MSC enumeration and file operations +against a known USB drive. diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index 8814f95d1..ca03ebf8a 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -111,7 +111,6 @@ static void hw_endpoint_open(uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t t // double buffered Bulk endpoint if (transfer_type == TUSB_XFER_BULK) { size *= 2u; - #if CFG_TUSB_RP2_ERRATA_E15 if (dir == TUSB_DIR_IN) { ep->e15_bulk_in = true; @@ -195,7 +194,7 @@ TU_ATTR_ALWAYS_INLINE static inline void reset_ep0(void) { for (uint8_t dir = 0; dir < 2; dir++) { struct hw_endpoint *ep = hw_endpoint_get(0, dir); ep->next_pid = 1u; - if (ep->active) { + if (ep->state == EPSTATE_ACTIVE) { hw_endpoint_abort_xfer(ep); // Abort any pending transfer per USB specs } } @@ -254,12 +253,12 @@ static void __tusb_irq_path_func(dcd_rp2040_irq)(void) { struct hw_endpoint *ep = hw_endpoint_get(i, TUSB_DIR_IN); // Active Bulk IN endpoint requires SOF - if (ep->e15_bulk_in && ep->active) { + if (ep->e15_bulk_in && ep->state == EPSTATE_ACTIVE) { keep_sof_alive = true; hw_endpoint_lock_update(ep, 1); - if (ep->pending) { - ep->pending = 0; + if (ep->state == EPSTATE_PENDING) { + ep->state = EPSTATE_ACTIVE; io_rw_32 *buf_reg32 = get_buf_ctrl(i, TUSB_DIR_IN); io_rw_16 *buf_reg16 = (io_rw_16 *)buf_reg32; @@ -276,7 +275,7 @@ static void __tusb_irq_path_func(dcd_rp2040_irq)(void) { if (buf0_idle && buf1_idle) { // both are idle, start fresh io_rw_32 *ep_reg = get_ep_ctrl(i, TUSB_DIR_IN); - rp2usb_buffer_start(ep, ep_reg, buf_reg32, false, false); + rp2usb_buffer_start(ep, ep_reg, buf_reg32, false); } else if (buf0_idle) { uint16_t buf0 = bufctrl_prepare16(ep, ep->dpram_buf, false); bufctrl_write16(buf_reg16, buf0); @@ -501,7 +500,7 @@ bool dcd_edpt_iso_activate(uint8_t rhport, const tusb_desc_endpoint_t *ep_desc) struct hw_endpoint *ep = hw_endpoint_get(epnum, dir); TU_ASSERT(ep->dpram_buf != NULL); // must be inited and allocated previously - if (ep->active) { + if (ep->state == EPSTATE_ACTIVE) { hw_endpoint_abort_xfer(ep); // abort any pending transfer } ep->max_packet_size = ep_desc->wMaxPacketSize; diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index fb1676f50..02a4e055e 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -66,6 +66,10 @@ enum { SIE_CTRL_SPEED_FULL = 2, }; +enum { + EPX_CTRL_DEFAULT = EP_CTRL_ENABLE_BITS | EP_CTRL_INTERRUPT_PER_BUFFER | offsetof(usb_host_dpram_t, epx_data) +}; + //--------------------------------------------------------------------+ // //--------------------------------------------------------------------+ @@ -123,7 +127,7 @@ TU_ATTR_ALWAYS_INLINE static inline void sie_stop_xfer(void) { while (usb_hw->sie_ctrl & USB_SIE_CTRL_STOP_TRANS_BITS) {} } -TU_ATTR_ALWAYS_INLINE static inline void sie_start_xfer(bool send_setup, bool is_rx, bool need_pre) { +static void __tusb_irq_path_func(sie_start_xfer)(bool send_setup, bool is_rx, bool need_pre) { uint32_t sie_ctrl = usb_hw->sie_ctrl & SIE_CTRL_BASE_MASK; // preserve base bits if (send_setup) { sie_ctrl |= USB_SIE_CTRL_SEND_SETUP_BITS; @@ -135,31 +139,16 @@ TU_ATTR_ALWAYS_INLINE static inline void sie_start_xfer(bool send_setup, bool is } // START_TRANS bit on SIE_CTRL has the same behavior as the AVAILABLE bit - // described in RP2040 Datasheet, release 2.1, section "4.1.2.5.1. Concurrent access". + // described in RP2040 Datasheet, release 2.1, section "4.1.2.5.1. Concurrent access".! // We write everything except the START_TRANS bit first, then wait some cycles. usb_hw->sie_ctrl = sie_ctrl; busy_wait_at_least_cycles(12); usb_hw->sie_ctrl = sie_ctrl | USB_SIE_CTRL_START_TRANS_BITS; } -TU_ATTR_ALWAYS_INLINE static inline void epx_start_xfer(hw_endpoint_t *ep, bool is_setup) { - usb_hw->dev_addr_ctrl = (uint32_t)(ep->dev_addr | (tu_edpt_number(ep->ep_addr) << USB_ADDR_ENDP_ENDPOINT_LSB)); - sie_start_xfer(is_setup, tu_edpt_dir(ep->ep_addr) == TUSB_DIR_IN, ep->need_pre); -} - // prepare epx_ctrl register for new endpoint -TU_ATTR_ALWAYS_INLINE static inline void epx_ctrl_prepare(hw_endpoint_t *ep) { - // RP2040-E4: USB host writes status to the upper half of buffer control in single buffered mode. - // The buffer selector toggles even in single-buffered mode, so the previous transfer's status - // may have been written to BUF1 half, leaving BUF0 with a stale AVAILABLE bit. Clear it here. - #if defined(PICO_RP2040) && PICO_RP2040 == 1 - usbh_dpram->epx_buf_ctrl = 0; - #endif - - // ep control - const uint32_t ep_ctrl = EP_CTRL_ENABLE_BITS | EP_CTRL_INTERRUPT_PER_BUFFER | - ((uint32_t)ep->transfer_type << EP_CTRL_BUFFER_TYPE_LSB) | hw_data_offset(ep->dpram_buf); - usbh_dpram->epx_ctrl = ep_ctrl; +TU_ATTR_ALWAYS_INLINE static inline void epx_ctrl_prepare(uint8_t transfer_type) { + usbh_dpram->epx_ctrl = EPX_CTRL_DEFAULT | ((uint32_t)transfer_type << EP_CTRL_BUFFER_TYPE_LSB); } // Save buffer context for EPX preemption (called after STOP_TRANS). @@ -196,31 +185,30 @@ static void __tusb_irq_path_func(epx_save_context)(hw_endpoint_t *ep) { usbh_dpram->epx_buf_ctrl = 0; - ep->pending = 1; - ep->active = false; + ep->state = EPSTATE_PENDING; } -// All non-interrupt endpoints use shared EPX. -// Save the current EPX context, mark pending, switch to ep +// switch epx to new endpoint and start the transfer static void __tusb_irq_path_func(epx_switch_ep)(hw_endpoint_t *ep) { - const bool is_setup = (ep->pending == 2); + const bool is_setup = (ep->state == EPSTATE_PENDING_SETUP); - epx = ep; // switch pointer - ep->pending = 0; - ep->active = true; + epx = ep; // switch pointer + ep->state = EPSTATE_ACTIVE; if (is_setup) { // panic("new setup \n"); - epx_start_xfer(ep, true); + usb_hw->dev_addr_ctrl = ep->dev_addr; + sie_start_xfer(true, false, ep->need_pre); } else { - io_rw_32 *ep_reg = &usbh_dpram->epx_ctrl; + const bool is_rx = (tu_edpt_dir(ep->ep_addr) == TUSB_DIR_IN); + io_rw_32 *ep_reg = &usbh_dpram->epx_ctrl; io_rw_32 *buf_reg = &usbh_dpram->epx_buf_ctrl; - epx_ctrl_prepare(ep); - rp2usb_buffer_start(ep, ep_reg, buf_reg, tu_edpt_dir(ep->ep_addr) == TUSB_DIR_IN, - ep->transfer_type == TUSB_XFER_INTERRUPT); + epx_ctrl_prepare(ep->transfer_type); + rp2usb_buffer_start(ep, ep_reg, buf_reg, is_rx); - epx_start_xfer(ep, false); + usb_hw->dev_addr_ctrl = (uint32_t)(ep->dev_addr | (tu_edpt_number(ep->ep_addr) << USB_ADDR_ENDP_ENDPOINT_LSB)); + sie_start_xfer(is_setup, is_rx, ep->need_pre); } } @@ -228,12 +216,12 @@ static void __tusb_irq_path_func(epx_switch_ep)(hw_endpoint_t *ep) { static hw_endpoint_t *__tusb_irq_path_func(epx_next_pending)(hw_endpoint_t *cur_ep) { const uint cur_idx = (uint)(cur_ep - &ep_pool[0]); for (uint i = cur_idx + 1; i < TU_ARRAY_SIZE(ep_pool); i++) { - if (ep_pool[i].pending) { + if (ep_pool[i].state >= EPSTATE_PENDING) { return &ep_pool[i]; } } for (uint i = 0; i < cur_idx; i++) { - if (ep_pool[i].pending) { + if (ep_pool[i].state >= EPSTATE_PENDING) { return &ep_pool[i]; } } @@ -246,7 +234,7 @@ static hw_endpoint_t *__tusb_irq_path_func(epx_next_pending)(hw_endpoint_t *cur_ //--------------------------------------------------------------------+ static void __tusb_irq_path_func(xfer_complete_isr)(hw_endpoint_t *ep, xfer_result_t xfer_result, bool is_more) { // Mark transfer as done before we tell the tinyusb stack - uint xferred_len = ep->xferred_len; + uint32_t xferred_len = ep->xferred_len; rp2usb_reset_transfer(ep); hcd_event_xfer_complete(ep->dev_addr, ep->ep_addr, xferred_len, xfer_result, true); @@ -345,7 +333,7 @@ static void __tusb_irq_path_func(hcd_rp2040_irq)(void) { // Even if STOP_TRANS bit is clear, controller maybe in middle of retrying and may re-raise timeout once extra time // Only handle if epx is active, don't carry more epx transfer since STOP_TRANS is raced and not safe. - if (epx->active) { + if (epx->state == EPSTATE_ACTIVE) { xfer_complete_isr(epx, XFER_RESULT_FAILED, false); } } @@ -392,7 +380,7 @@ static void __tusb_irq_path_func(hcd_rp2040_irq)(void) { usb_hw_clear->inte = USB_INTE_HOST_SOF_BITS; usb_hw->nak_poll = USB_NAK_POLL_RESET; epx_switch_request = false; - } else if (epx->active) { + } else if (epx->state == EPSTATE_ACTIVE) { if (epx_switch_request) { // Second SOF with no transfer completion: endpoint is NAK-retrying, safe to switch. epx_switch_request = false; @@ -496,20 +484,14 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr) { return; // address 0 is for device enumeration } - // reset epx if it is currently active with unplugged device - if (epx->max_packet_size > 0 && epx->dev_addr == dev_addr) { - // if (epx->active) { - // // need to abort transfer - // } - epx->max_packet_size = 0; - } + rp2usb_critical_enter(); for (size_t i = 0; i < TU_ARRAY_SIZE(ep_pool); i++) { hw_endpoint_t *ep = &ep_pool[i]; if (ep->dev_addr == dev_addr && ep->max_packet_size > 0) { - ep->pending = 0; // clear any pending transfer + ep->state = EPSTATE_IDLE; // clear any pending transfer - if (ep->interrupt_num) { + if (ep->interrupt_num > 0) { // disable interrupt endpoint usb_hw_clear->int_ep_ctrl = TU_BIT(ep->interrupt_num); usb_hw->int_ep_addr_ctrl[ep->interrupt_num - 1] = 0; @@ -523,6 +505,8 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr) { ep->max_packet_size = 0; // mark as unused } } + + rp2usb_critical_exit(); } uint32_t hcd_frame_number(uint8_t rhport) { @@ -557,16 +541,15 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, const tusb_desc_endpoint_t const uint8_t ep_addr = ep_desc->bEndpointAddress; const uint16_t max_packet_size = tu_edpt_packet_size(ep_desc); - const uint8_t transfer_type = ep_desc->bmAttributes.xfer; ep->max_packet_size = max_packet_size; ep->ep_addr = ep_addr; ep->dev_addr = dev_addr; - ep->transfer_type = transfer_type; + ep->transfer_type = ep_desc->bmAttributes.xfer; ep->need_pre = need_pre(dev_addr); ep->next_pid = 0u; - if (transfer_type != TUSB_XFER_INTERRUPT) { + if (ep->transfer_type != TUSB_XFER_INTERRUPT) { ep->dpram_buf = usbh_dpram->epx_data; } else { // from 15 interrupt endpoints pool @@ -627,7 +610,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *b hw_endpoint_t *ep = edpt_find(dev_addr, ep_addr); TU_ASSERT(ep); - if (ep->transfer_type == TUSB_XFER_INTERRUPT) { + if (ep->interrupt_num > 0) { // For interrupt endpoint control and buffer is already configured // Note: Interrupt is single buffered only io_rw_32 *ep_reg = dpram_int_ep_ctrl(ep->interrupt_num); @@ -642,10 +625,10 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *b // If EPX is busy with another transfer, mark as pending rp2usb_critical_enter(); - if (epx->active) { + if (epx->state == EPSTATE_ACTIVE) { ep->user_buf = buffer; ep->remaining_len = buflen; - ep->pending = 1; + ep->state = EPSTATE_PENDING; #ifdef HAS_STOP_EPX_ON_NAK usb_hw_set->nak_poll = USB_NAK_POLL_STOP_EPX_ON_NAK_BITS; @@ -660,9 +643,10 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *b epx = ep; - epx_ctrl_prepare(ep); + epx_ctrl_prepare(ep->transfer_type); rp2usb_xfer_start(ep, ep_reg, buf_reg, buffer, NULL, buflen); // prepare bufctrl - epx_start_xfer(ep, false); + usb_hw->dev_addr_ctrl = (uint32_t)(ep->dev_addr | (tu_edpt_number(ep->ep_addr) << USB_ADDR_ENDP_ENDPOINT_LSB)); + sie_start_xfer(false, tu_edpt_dir(ep->ep_addr) == TUSB_DIR_IN, ep->need_pre); } rp2usb_critical_exit(); } @@ -688,8 +672,8 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, const uint8_t setup_packet ep->xferred_len = 0; // If EPX is busy, mark as pending setup (DPRAM already has the packet) - if (epx->active) { - ep->pending = 2; // setup + if (epx->state == EPSTATE_ACTIVE) { + ep->state = EPSTATE_PENDING_SETUP; #ifdef HAS_STOP_EPX_ON_NAK usb_hw_set->nak_poll = USB_NAK_POLL_STOP_EPX_ON_NAK_BITS; #else @@ -697,9 +681,11 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, const uint8_t setup_packet usb_hw_set->inte = USB_INTE_HOST_SOF_BITS; #endif } else { - epx = ep; - ep->active = true; - epx_start_xfer(ep, true); + epx = ep; + ep->state = EPSTATE_ACTIVE; + + usb_hw->dev_addr_ctrl = ep->dev_addr; + sie_start_xfer(true, tu_edpt_dir(ep->ep_addr) == TUSB_DIR_IN, ep->need_pre); } rp2usb_critical_exit(); diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index 156be62e4..206da041b 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -101,12 +101,13 @@ void rp2usb_init(void) { } void __tusb_irq_path_func(rp2usb_reset_transfer)(hw_endpoint_t *ep) { - ep->active = false; - ep->pending = 0; + ep->state = EPSTATE_IDLE; ep->remaining_len = 0; ep->xferred_len = 0; ep->user_buf = 0; +#if CFG_TUD_EDPT_DEDICATED_HWFIFO ep->is_xfer_fifo = false; +#endif } void __tusb_irq_path_func(bufctrl_write32)(io_rw_32 *buf_reg, uint32_t value) { @@ -183,14 +184,19 @@ uint16_t __tusb_irq_path_func(bufctrl_prepare16)(hw_endpoint_t *ep, uint8_t *dpr } // Start transaction on hw buffer -void __tusb_irq_path_func(rp2usb_buffer_start)(hw_endpoint_t *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg, bool is_rx, - bool force_single) { +void __tusb_irq_path_func(rp2usb_buffer_start)(hw_endpoint_t *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg, bool is_rx) { // always compute and start with buffer 0 uint32_t buf_ctrl = bufctrl_prepare16(ep, ep->dpram_buf, is_rx) | USB_BUF_CTRL_SEL; // Note: device EP0 does not have an endpoint control register if (ep_reg != NULL) { uint32_t ep_ctrl = *ep_reg; + #if CFG_TUH_ENABLED + const bool force_single = (rp2usb_is_host_mode() && ep->interrupt_num > 0); + #else + const bool force_single = false; + #endif + if (ep->remaining_len && !force_single) { // Use buffer 1 (double buffered) if there is still data buf_ctrl |= (uint32_t)bufctrl_prepare16(ep, ep->dpram_buf + 64, is_rx) << 16; @@ -211,8 +217,7 @@ void rp2usb_xfer_start(hw_endpoint_t *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg, u (void)ff; hw_endpoint_lock_update(ep, 1); - if (ep->active) { - // TODO: Is this acceptable for interrupt packets? + if (ep->state == EPSTATE_ACTIVE) { TU_LOG(1, "WARN: starting new transfer on already active ep %02X\r\n", ep->ep_addr); rp2usb_reset_transfer(ep); } @@ -220,7 +225,7 @@ void rp2usb_xfer_start(hw_endpoint_t *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg, u // Fill in info now that we're kicking off the hw ep->remaining_len = total_len; ep->xferred_len = 0; - ep->active = true; + ep->state = EPSTATE_ACTIVE; #if CFG_TUD_EDPT_DEDICATED_HWFIFO if (ff != NULL) { @@ -229,66 +234,50 @@ void rp2usb_xfer_start(hw_endpoint_t *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg, u } else #endif { - ep->user_buf = buffer; + ep->user_buf = buffer; + #if CFG_TUD_EDPT_DEDICATED_HWFIFO ep->is_xfer_fifo = false; + #endif } const bool is_host = rp2usb_is_host_mode(); + const bool is_rx = (is_host == (tu_edpt_dir(ep->ep_addr) == TUSB_DIR_IN)); - if (ep->future_len > 0) { - // only on rx endpoint + #if CFG_TUD_ENABLED + if (!is_host && ep->future_len > 0) { + // Device only: previous short-packet abort saved data from the other buffer const uint8_t future_len = ep->future_len; memcpy(ep->user_buf, ep->dpram_buf + (ep->future_bufid << 6), future_len); ep->xferred_len += future_len; ep->remaining_len -= future_len; ep->user_buf += future_len; - ep->future_len = 0; ep->future_bufid = 0; if (ep->remaining_len == 0) { - // all data has been received, no need to start hw transfer - ep->active = false; const uint16_t xferred_len = ep->xferred_len; rp2usb_reset_transfer(ep); - - #if CFG_TUH_ENABLED - if (is_host) { - hcd_event_xfer_complete(0, ep->ep_addr, xferred_len, XFER_RESULT_SUCCESS, false); - } - #endif - #if CFG_TUD_ENABLED - if (!is_host) { - dcd_event_xfer_complete(0, ep->ep_addr, xferred_len, XFER_RESULT_SUCCESS, false); - } - #endif - + dcd_event_xfer_complete(0, ep->ep_addr, xferred_len, XFER_RESULT_SUCCESS, false); hw_endpoint_lock_update(ep, -1); return; } } - #if CFG_TUSB_RP2_ERRATA_E15 + #if CFG_TUSB_RP2_ERRATA_E15 if (ep->e15_bulk_in) { usb_hw_set->inte = USB_INTS_DEV_SOF_BITS; // skip transfer if we are in critical frame period if (e15_is_critical_frame_period()) { - ep->pending = 1; + ep->state = EPSTATE_PENDING; hw_endpoint_lock_update(ep, -1); return; } } - #endif + #endif // CFG_TUSB_RP2_ERRATA_E15 + #endif // CFG_TUD_ENABLED - const bool is_rx = (is_host == (tu_edpt_dir(ep->ep_addr) == TUSB_DIR_IN)); - #if CFG_TUH_ENABLED - const bool force_single = (is_host && ep->transfer_type == TUSB_XFER_INTERRUPT); - #else - const bool force_single = false; - #endif - - rp2usb_buffer_start(ep, ep_reg, buf_reg, is_rx, force_single); + rp2usb_buffer_start(ep, ep_reg, buf_reg, is_rx); hw_endpoint_lock_update(ep, -1); } @@ -333,7 +322,7 @@ bool __tusb_irq_path_func(rp2usb_xfer_continue)(hw_endpoint_t *ep, io_rw_32 *ep_ bool is_rx) { hw_endpoint_lock_update(ep, 1); - if (!ep->active) { + if (ep->state != EPSTATE_ACTIVE) { // probably land here due to short packet on rx with double buffered hw_endpoint_lock_update(ep, -1); return false; @@ -394,12 +383,12 @@ bool __tusb_irq_path_func(rp2usb_xfer_continue)(hw_endpoint_t *ep, io_rw_32 *ep_ if (buf_ctrl16_other & USB_BUF_CTRL_FULL) { // Data already sent into this buffer. Save it for the next transfer. // buff_status will be clear by the next run - if (is_host) { - // host put future_len pointer at end of epx_data - } else { + #if CFG_TUD_ENABLED + if (!is_host) { ep->future_len = (uint8_t)(buf_ctrl16_other & USB_BUF_CTRL_LEN_MASK); + ep->future_bufid = buf_id ^ 1; } - ep->future_bufid = buf_id ^ 1; + #endif } else { ep->next_pid ^= 1u; // roll back pid if aborted } @@ -422,10 +411,11 @@ bool __tusb_irq_path_func(rp2usb_xfer_continue)(hw_endpoint_t *ep, io_rw_32 *ep_ if (!is_done && ep->remaining_len > 0) { #if CFG_TUSB_RP2_ERRATA_E15 - if (ep->e15_bulk_in && e15_is_critical_frame_period()) { + const bool need_e15 = ep->e15_bulk_in; + if (need_e15 && e15_is_critical_frame_period()) { // mark as pending if matches E15 condition - ep->pending = 1; - } else if (ep->e15_bulk_in && ep->pending) { + ep->state = EPSTATE_PENDING; + } else if (need_e15 && ep->state == EPSTATE_PENDING) { // if already pending, meaning the other buf completes first, don't arm buffer, let SOF handle it // do nothing } else diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.h b/src/portable/raspberrypi/rp2040/rp2040_usb.h index 2ba9d018e..8ebc3e3fc 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.h +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.h @@ -32,9 +32,9 @@ // RP2040-E15: USB Device controller will hang if certain bus errors occur during an IN transfer. #ifndef CFG_TUSB_RP2_ERRATA_E15 #if defined(PICO_RP2040_USB_DEVICE_UFRAME_FIX) - #define CFG_TUSB_RP2_ERRATA_E15 PICO_RP2040_USB_DEVICE_UFRAME_FIX + #define CFG_TUSB_RP2_ERRATA_E15 (CFG_TUD_ENABLED && PICO_RP2040_USB_DEVICE_UFRAME_FIX) #elif defined(TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX) - #define CFG_TUSB_RP2_ERRATA_E15 TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX + #define CFG_TUSB_RP2_ERRATA_E15 (CFG_TUD_ENABLED && TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX) #endif #endif #endif @@ -90,18 +90,23 @@ enum { EPSTATE_IDLE = 0, EPSTATE_ACTIVE, EPSTATE_PENDING, + EPSTATE_PENDING_SETUP }; // Hardware information per endpoint typedef struct hw_endpoint { uint8_t ep_addr; uint8_t next_pid; - bool active; // transferring data - uint8_t pending; // Transfer scheduled but not active - bool is_xfer_fifo; // transfer using fifo + uint8_t state; - uint8_t future_bufid; - uint8_t future_len; +#if CFG_TUD_EDPT_DEDICATED_HWFIFO + bool is_xfer_fifo; // transfer using fifo +#endif + +#if CFG_TUD_ENABLED + uint8_t future_bufid; // which buffer holds next data + uint8_t future_len; // next data len +#endif #if CFG_TUSB_RP2_ERRATA_E15 bool e15_bulk_in; // Errata15 device bulk in @@ -110,8 +115,10 @@ typedef struct hw_endpoint { #if CFG_TUH_ENABLED uint8_t dev_addr; uint8_t interrupt_num; // 1-15 for interrupt endpoints - uint8_t transfer_type; - bool need_pre; // need preamble for low speed device behind full speed hub + struct TU_ATTR_PACKED { + uint8_t transfer_type : 2; + uint8_t need_pre : 1; // preamble for low-speed device behind full speed hub + }; #endif uint16_t max_packet_size; // max packet size also indicates configured @@ -153,7 +160,7 @@ TU_ATTR_ALWAYS_INLINE static inline void rp2usb_critical_exit(void) { void rp2usb_xfer_start(hw_endpoint_t *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg, uint8_t *buffer, tu_fifo_t *ff, uint16_t total_len); bool rp2usb_xfer_continue(hw_endpoint_t *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg, uint8_t buf_id, bool is_rx); -void rp2usb_buffer_start(hw_endpoint_t *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg, bool is_rx, bool force_single); +void rp2usb_buffer_start(hw_endpoint_t *ep, io_rw_32 *ep_reg, io_rw_32 *buf_reg, bool is_rx); void rp2usb_reset_transfer(hw_endpoint_t *ep); diff --git a/tools/metrics.py b/tools/metrics.py index 6b992c8f5..f624f382f 100644 --- a/tools/metrics.py +++ b/tools/metrics.py @@ -166,6 +166,9 @@ def compute_avg(all_json_data): file_accumulator[fname]["symbols"][name].append(sym.get("size", 0)) sections_map = f.get("sections") or {} for sname, ssize in sections_map.items(): + # linkermap -v produces nested dicts {subsection: size}, flatten to total + if isinstance(ssize, dict): + ssize = sum(ssize.values()) file_accumulator[fname]["sections"][sname].append(ssize) # Build json_average with averaged values @@ -209,7 +212,7 @@ def compute_avg(all_json_data): def compare_files(base_file, new_file, filters=None): - """Compare two CSV or JSON inputs and generate difference report.""" + """Compare two CSV or JSON inputs and generate a difference report.""" filters = filters or [] base_avg = compute_avg(combine_files([base_file], filters)) -- cgit v1.3.1 From 087ceb7417e6c1d72701ae491407490cfe5c6558 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 1 Apr 2026 23:50:26 +0700 Subject: fix issue caused by merging active + pending state --- src/portable/raspberrypi/rp2040/dcd_rp2040.c | 2 +- src/portable/raspberrypi/rp2040/rp2040_usb.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/portable') diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index ca03ebf8a..2b6bbc43b 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -253,7 +253,7 @@ static void __tusb_irq_path_func(dcd_rp2040_irq)(void) { struct hw_endpoint *ep = hw_endpoint_get(i, TUSB_DIR_IN); // Active Bulk IN endpoint requires SOF - if (ep->e15_bulk_in && ep->state == EPSTATE_ACTIVE) { + if (ep->e15_bulk_in && ep->state >= EPSTATE_ACTIVE) { keep_sof_alive = true; hw_endpoint_lock_update(ep, 1); diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index 206da041b..1b13934d3 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -322,7 +322,7 @@ bool __tusb_irq_path_func(rp2usb_xfer_continue)(hw_endpoint_t *ep, io_rw_32 *ep_ bool is_rx) { hw_endpoint_lock_update(ep, 1); - if (ep->state != EPSTATE_ACTIVE) { + if (ep->state == EPSTATE_IDLE) { // probably land here due to short packet on rx with double buffered hw_endpoint_lock_update(ep, -1); return false; -- cgit v1.3.1 From c0c1566bea34419a8b165a489278114363de5a5e Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 2 Apr 2026 23:50:12 +0700 Subject: rp2040: fix RP2350 hard fault in unaligned_memcpy to USB DPRAM Use volatile byte accesses to prevent the compiler from widening the byte-by-byte copy loop into 16/32-bit accesses, which cause a hard fault on RP2350 when targeting USB DPRAM (device memory). Closes #3554 --- src/portable/raspberrypi/rp2040/rp2040_usb.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src/portable') diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index 1b13934d3..f5ba81dd7 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -51,10 +51,14 @@ critical_section_t rp2usb_lock; //--------------------------------------------------------------------+ // Implementation //--------------------------------------------------------------------+ -// Provide own byte by byte memcpy as not all copies are aligned +// Provide own byte by byte memcpy as not all copies are aligned. +// Use volatile to prevent compiler from widening to 16/32-bit accesses +// which cause hard fault on RP2350 when dst/src points to USB DPRAM. static void unaligned_memcpy(uint8_t *dst, const uint8_t *src, size_t n) { + volatile uint8_t *vdst = dst; + const volatile uint8_t *vsrc = src; while (n--) { - *dst++ = *src++; + *vdst++ = *vsrc++; } } -- cgit v1.3.1 From 9515ba8e795a582f4e62955b8d4398066e2acbb1 Mon Sep 17 00:00:00 2001 From: Ha Thach Date: Thu, 2 Apr 2026 23:55:12 +0700 Subject: Apply suggestion from @Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/portable/raspberrypi/rp2040/rp2040_usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/portable') diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index f5ba81dd7..83ac48ec2 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -53,7 +53,7 @@ critical_section_t rp2usb_lock; //--------------------------------------------------------------------+ // Provide own byte by byte memcpy as not all copies are aligned. // Use volatile to prevent compiler from widening to 16/32-bit accesses -// which cause hard fault on RP2350 when dst/src points to USB DPRAM. +// which cause hard fault on RP2350 when dst/src point to USB DPRAM. static void unaligned_memcpy(uint8_t *dst, const uint8_t *src, size_t n) { volatile uint8_t *vdst = dst; const volatile uint8_t *vsrc = src; -- cgit v1.3.1 From a39e9cdf2c82401eb61b99dd35e73531bcd76cf1 Mon Sep 17 00:00:00 2001 From: gab-k Date: Fri, 27 Mar 2026 18:34:04 +0100 Subject: Add initial board support for nRF54LM20 DK --- docs/reference/boards.rst | 1 + hw/bsp/BoardPresets.json | 22 +++++++ hw/bsp/nrf/boards/nrf54lm20dk/board.cmake | 11 ++++ hw/bsp/nrf/boards/nrf54lm20dk/board.h | 58 ++++++++++++++++++ hw/bsp/nrf/boards/nrf54lm20dk/board.mk | 6 ++ hw/bsp/nrf/family.c | 69 ++++++++++++++++++++-- hw/bsp/nrf/family.cmake | 28 ++++++--- hw/bsp/nrf/family.mk | 15 ++++- .../nrf/linker/nrf54lm20a_enga_xxaa_application.ld | 13 ++++ hw/bsp/nrf/nrfx_config/nrfx_config_common.h | 3 + src/common/tusb_mcu.h | 1 + src/portable/synopsys/dwc2/dwc2_nrf.h | 27 ++++++++- 12 files changed, 238 insertions(+), 16 deletions(-) create mode 100644 hw/bsp/nrf/boards/nrf54lm20dk/board.cmake create mode 100644 hw/bsp/nrf/boards/nrf54lm20dk/board.h create mode 100644 hw/bsp/nrf/boards/nrf54lm20dk/board.mk create mode 100644 hw/bsp/nrf/linker/nrf54lm20a_enga_xxaa_application.ld (limited to 'src/portable') diff --git a/docs/reference/boards.rst b/docs/reference/boards.rst index ec91b343e..dbb5942ca 100644 --- a/docs/reference/boards.rst +++ b/docs/reference/boards.rst @@ -221,6 +221,7 @@ nrf52840dk Nordic nRF52840DK nrf ht nrf52840dongle Nordic nRF52840 Dongle nrf https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52840-Dongle nrf5340dk Nordic nRF5340 DK nrf https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF5340-DK nrf54h20dk Nordic nRF54H20 DK nrf https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF5340-DK +nrf54lm20dk Nordic nRF54LM20 DK nrf https://www.nordicsemi.com/Products/Development-hardware/nRF54LM20-DK =========================== ===================================== ======== ============================================================================== ====== Raspberry Pi diff --git a/hw/bsp/BoardPresets.json b/hw/bsp/BoardPresets.json index 5c3aaf2b4..86609d075 100644 --- a/hw/bsp/BoardPresets.json +++ b/hw/bsp/BoardPresets.json @@ -470,6 +470,10 @@ "name": "nrf54h20dk", "inherits": "default" }, + { + "name": "nrf54lm20dk", + "inherits": "default" + }, { "name": "nutiny_nuc126v", "inherits": "default" @@ -1563,6 +1567,11 @@ "description": "Build preset for the nrf54h20dk board", "configurePreset": "nrf54h20dk" }, + { + "name": "nrf54lm20dk", + "description": "Build preset for the nrf54lm20dk board", + "configurePreset": "nrf54lm20dk" + }, { "name": "nutiny_nuc126v", "description": "Build preset for the nutiny_nuc126v board", @@ -3711,6 +3720,19 @@ } ] }, + { + "name": "nrf54lm20dk", + "steps": [ + { + "type": "configure", + "name": "nrf54lm20dk" + }, + { + "type": "build", + "name": "nrf54lm20dk" + } + ] + }, { "name": "nutiny_nuc126v", "steps": [ diff --git a/hw/bsp/nrf/boards/nrf54lm20dk/board.cmake b/hw/bsp/nrf/boards/nrf54lm20dk/board.cmake new file mode 100644 index 000000000..fb0ccdfdf --- /dev/null +++ b/hw/bsp/nrf/boards/nrf54lm20dk/board.cmake @@ -0,0 +1,11 @@ +set(MCU_VARIANT nrf54lm20a_enga) +set(JLINK_DEVICE NRF54LM20A_M33) + +function(update_board TARGET) + target_compile_definitions(${TARGET} PUBLIC + CFG_EXAMPLE_VIDEO_READONLY + ) + target_sources(${TARGET} PRIVATE +# ${NRFX_PATH}/drivers/src/nrfx_usbreg.c + ) +endfunction() diff --git a/hw/bsp/nrf/boards/nrf54lm20dk/board.h b/hw/bsp/nrf/boards/nrf54lm20dk/board.h new file mode 100644 index 000000000..6bf5da891 --- /dev/null +++ b/hw/bsp/nrf/boards/nrf54lm20dk/board.h @@ -0,0 +1,58 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020, Ha Thach (tinyusb.org) + * Copyright (c) 2026, Gabriel Koppenstein + * + * 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: Nordic nRF54LM20 DK + url: https://www.nordicsemi.com/Products/Development-hardware/nRF54LM20-DK +*/ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +#define _PINNUM(port, pin) ((port)*32 + (pin)) + +// LED0 active high (MOSFET-driven) +#define LED_PIN _PINNUM(1, 22) +#define LED_STATE_ON 1 + +// Button0 active low +#define BUTTON_PIN _PINNUM(1, 26) +#define BUTTON_STATE_ACTIVE 0 + +// UART20 (VCOM via debugger) +#define UART_TX_PIN _PINNUM(1, 16) +#define UART_RX_PIN _PINNUM(1, 17) + +#ifdef __cplusplus + } +#endif + +#endif /* BOARD_H_ */ diff --git a/hw/bsp/nrf/boards/nrf54lm20dk/board.mk b/hw/bsp/nrf/boards/nrf54lm20dk/board.mk new file mode 100644 index 000000000..ad0177b40 --- /dev/null +++ b/hw/bsp/nrf/boards/nrf54lm20dk/board.mk @@ -0,0 +1,6 @@ +MCU_VARIANT = nrf54lm20a_enga +CFLAGS += -DNRF54LM20A_ENGA_XXAA + +# flash using jlink +JLINK_DEVICE = NRF54LM20A_M33 +flash: flash-jlink diff --git a/hw/bsp/nrf/family.c b/hw/bsp/nrf/family.c index f1e8b829c..10f0fc460 100644 --- a/hw/bsp/nrf/family.c +++ b/hw/bsp/nrf/family.c @@ -2,6 +2,7 @@ * The MIT License (MIT) * * Copyright (c) 2019 Ha Thach (tinyusb.org) + * Copyright (c) 2026, Gabriel Koppenstein * * 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,7 +46,7 @@ #include "nrfx.h" #include "hal/nrf_gpio.h" #include "nrfx_gpiote.h" -#if !defined(NRF54H20_XXAA) +#if !defined(NRF54H20_XXAA) && !defined(NRF54LM20A_ENGA_XXAA) #include "nrfx_power.h" #endif #include "nrfx_uarte.h" @@ -79,13 +80,17 @@ enum { }; // Forward USB interrupt events to TinyUSB IRQ Handler -#if defined(NRF54H20_XXAA) +#if defined(NRF54H20_XXAA) || defined(NRF54LM20A_ENGA_XXAA) #define USBD_IRQn USBHS_IRQn void USBHS_IRQHandler(void) { tusb_int_handler(0, true); } +#if defined(NRF54LM20A_ENGA_XXAA) +static nrfx_uarte_t _uart_id = NRFX_UARTE_INSTANCE(20); +#else static nrfx_uarte_t _uart_id = NRFX_UARTE_INSTANCE(120); +#endif #else @@ -114,7 +119,7 @@ void USBD_IRQHandler(void) { // We must call it within SD's SOC event handler, or set it as power event handler if SD is not enabled. extern void tusb_hal_nrf_power_event(uint32_t event); -#if !defined(NRF54H20_XXAA) +#if !defined(NRF54H20_XXAA) && !defined(NRF54LM20A_ENGA_XXAA) // nrf power callback, could be unused if SD is enabled or usb is disabled (board_test example) TU_ATTR_UNUSED static void power_event_handler(nrfx_power_usb_evt_t event) { tusb_hal_nrf_power_event((uint32_t) event); @@ -133,7 +138,7 @@ static nrfx_gpiote_t _gpiote = NRFX_GPIOTE_INSTANCE(0); //--------------------------------------------------------------------+ void board_init(void) { -#if !defined(NRF54H20_XXAA) +#if !defined(NRF54H20_XXAA) && !defined(NRF54LM20A_ENGA_XXAA) // stop LF clock just in case we jump from application without reset NRF_CLOCK->TASKS_LFCLKSTOP = 1UL; @@ -186,11 +191,63 @@ void board_init(void) { //------------- USB -------------// #if CFG_TUD_ENABLED + +#if defined(NRF54LM20A_ENGA_XXAA) + // Start the USB voltage regulator + NRF_VREGUSB->TASKS_START = VREGUSB_TASKS_START_TASKS_START_Trigger; + + // Request HFXO crystal clock for PCLK24M (required by USBHS core) + NRF_CLOCK->TASKS_XO24MSTART = CLOCK_TASKS_XO24MSTART_TASKS_XO24MSTART_Trigger; + while (!NRF_CLOCK->EVENTS_XO24MSTARTED) {} + NRF_CLOCK->EVENTS_XO24MSTARTED = 0; +#endif + +#if defined(NRF54H20_XXAA) + // Enable the USBHS wrapper (core + PHY) before any DWC2 register access + NRF_USBHS->ENABLE = (USBHS_ENABLE_PHY_Enabled << USBHS_ENABLE_PHY_Pos) | + (USBHS_ENABLE_CORE_Enabled << USBHS_ENABLE_CORE_Pos); + NRF_USBHS->TASKS_START = USBHS_TASKS_START_TASKS_START_Trigger; + // Brief delay for PHY PLL lock and core power-up + for (volatile int i = 0; i < 1000; i++) {} +#endif + +#if defined(NRF54LM20A_ENGA_XXAA) + // Based on Zephyr usbhs_enable_core() in drivers/usb/udc/udc_dwc2_vendor_quirks.h + // Step 1: Power up core only (PHY not yet) + NRF_USBHS->ENABLE = USBHS_ENABLE_CORE_Msk; + + // Step 2: Override ID=Device (bit 31), and temporarily override VBUSVALID + NRF_USBHS->PHY.OVERRIDEVALUES = (USBHS_PHY_OVERRIDEVALUES_ID_Device << USBHS_PHY_OVERRIDEVALUES_ID_Pos); + NRF_USBHS->PHY.INPUTOVERRIDE = USBHS_PHY_INPUTOVERRIDE_ID_Msk | USBHS_PHY_INPUTOVERRIDE_VBUSVALID_Msk; + + // Step 3: Release PHY power-on reset by enabling PHY + NRF_USBHS->ENABLE = USBHS_ENABLE_PHY_Msk | USBHS_ENABLE_CORE_Msk; + + // Step 4: Wait 45us for PHY clock to start + NRFX_DELAY_US(45); + + // Step 5: Release DWC2 reset + NRF_USBHS->TASKS_START = USBHS_TASKS_START_TASKS_START_Trigger; + + // Step 6: Wait for clock to start to avoid hang on too early register read + NRFX_DELAY_US(2); + + // Step 7: Clear VBUSVALID override (keep ID=Device override) + // DWC2 is now in Non-Driving opmode; D+ pull-up will activate when DWC2 clears DCTL SftDiscon + NRF_USBHS->PHY.INPUTOVERRIDE = USBHS_PHY_INPUTOVERRIDE_ID_Msk; + + // Barrier: USBHS wrapper (0x5005A000) and USBHSCORE (0x50020000) are separate + // peripheral blocks. Ensure the ENABLE/TASKS_START writes have propagated from + // the Cortex-M33 write buffer to hardware before anyone reads DWC2 core regs. + __DSB(); + +#endif + // Priorities 0, 1, 4 (nRF52) are reserved for SoftDevice // 2 is highest for application NVIC_SetPriority(USBD_IRQn, 2); -#if !defined(NRF54H20_XXAA) +#if !defined(NRF54H20_XXAA) && !defined(NRF54LM20A_ENGA_XXAA) // USB power may already be ready at this time -> no event generated // We need to invoke the handler based on the status initially uint32_t usb_reg; @@ -258,7 +315,7 @@ size_t board_get_unique_id(uint8_t id[], size_t max_len) { #if defined(NRF54H20_XXAA) uintptr_t did_addr = (uintptr_t) NRF_FICR->BLE.ADDR; -#elif defined(NRF5340_XXAA) +#elif defined(NRF54LM20A_ENGA_XXAA) || defined(NRF5340_XXAA) uintptr_t did_addr = (uintptr_t) NRF_FICR->INFO.DEVICEID; #else uintptr_t did_addr = (uintptr_t) NRF_FICR->DEVICEID; diff --git a/hw/bsp/nrf/family.cmake b/hw/bsp/nrf/family.cmake index 3a6e7cc8b..fba5e6e69 100644 --- a/hw/bsp/nrf/family.cmake +++ b/hw/bsp/nrf/family.cmake @@ -10,15 +10,19 @@ if (NOT board_cmake_included) endif () # toolchain set up -if (MCU_VARIANT STREQUAL nrf5340 OR MCU_VARIANT STREQUAL nrf54h20) +if (MCU_VARIANT STREQUAL nrf5340 OR MCU_VARIANT STREQUAL nrf54h20 OR MCU_VARIANT STREQUAL nrf54lm20a_enga) set(CMAKE_SYSTEM_CPU cortex-m33 CACHE INTERNAL "System Processor") - set(JLINK_DEVICE ${MCU_VARIANT}_xxaa_app) + if (NOT DEFINED JLINK_DEVICE) + set(JLINK_DEVICE ${MCU_VARIANT}_xxaa_app) + endif () else () set(CMAKE_SYSTEM_CPU cortex-m4 CACHE INTERNAL "System Processor") - set(JLINK_DEVICE ${MCU_VARIANT}_xxaa) + if (NOT DEFINED JLINK_DEVICE) + set(JLINK_DEVICE ${MCU_VARIANT}_xxaa) + endif () endif () -if (MCU_VARIANT STREQUAL "nrf54h20") +if (MCU_VARIANT STREQUAL "nrf54h20" OR MCU_VARIANT STREQUAL "nrf54lm20a_enga") set(FAMILY_MCUS NRF54 CACHE INTERNAL "") else () set(FAMILY_MCUS NRF5X CACHE INTERNAL "") @@ -29,7 +33,10 @@ set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOL #------------------------------------ # Startup & Linker script #------------------------------------ -if (MCU_VARIANT STREQUAL nrf54h20) +if (MCU_VARIANT STREQUAL nrf54lm20a_enga) + set(LD_FILE_GNU_DEFAULT ${CMAKE_CURRENT_LIST_DIR}/linker/${MCU_VARIANT}_xxaa_application.ld) + set(STARTUP_FILE_GNU ${NRFX_PATH}/mdk/gcc_startup_${MCU_VARIANT}_application.S) +elseif (MCU_VARIANT STREQUAL nrf54h20) set(LD_FILE_GNU_DEFAULT ${CMAKE_CURRENT_LIST_DIR}/linker/${MCU_VARIANT}_xxaa_application.ld) set(STARTUP_FILE_GNU ${NRFX_PATH}/mdk/gcc_startup_${MCU_VARIANT}_application.S) elseif (MCU_VARIANT STREQUAL nrf5340) @@ -52,13 +59,20 @@ function(family_add_board BOARD_TARGET) add_library(${BOARD_TARGET} STATIC ${NRFX_PATH}/helpers/nrfx_flag32_allocator.c ${NRFX_PATH}/drivers/src/nrfx_gpiote.c - ${NRFX_PATH}/drivers/src/nrfx_power.c ${NRFX_PATH}/drivers/src/nrfx_spim.c ${NRFX_PATH}/drivers/src/nrfx_uarte.c ${NRFX_PATH}/soc/nrfx_atomic.c ) - if (MCU_VARIANT STREQUAL nrf54h20) + if (NOT FAMILY_MCUS STREQUAL "NRF54") + target_sources(${BOARD_TARGET} PRIVATE ${NRFX_PATH}/drivers/src/nrfx_power.c) + endif () + + if (MCU_VARIANT STREQUAL nrf54lm20a_enga) + target_sources(${BOARD_TARGET} PRIVATE + ${NRFX_PATH}/mdk/system_nrf54l.c + ) + elseif (MCU_VARIANT STREQUAL nrf54h20) target_sources(${BOARD_TARGET} PRIVATE ${NRFX_PATH}/mdk/system_nrf54h.c ) diff --git a/hw/bsp/nrf/family.mk b/hw/bsp/nrf/family.mk index e7e9e7d0a..0cc3c81ef 100644 --- a/hw/bsp/nrf/family.mk +++ b/hw/bsp/nrf/family.mk @@ -4,6 +4,15 @@ NRFX_PATH = hw/mcu/nordic/nrfx include $(TOP)/$(BOARD_PATH)/board.mk +ifeq (${MCU_VARIANT},nrf54lm20a_enga) + CPU_CORE = cortex-m33 + CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_NRF54 + LD_FILE_DEFAULT = ${FAMILY_PATH}/linker/${MCU_VARIANT}_xxaa_application.ld + SRC_C += ${NRFX_PATH}/mdk/system_nrf54l.c + SRC_S += ${NRFX_PATH}/mdk/gcc_startup_$(MCU_VARIANT)_application.S + JLINK_DEVICE ?= $(MCU_VARIANT)_xxaa_app + +else ifeq (${MCU_VARIANT},nrf54h20) CPU_CORE = cortex-m33 CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_NRF54 @@ -32,6 +41,7 @@ else JLINK_DEVICE ?= $(MCU_VARIANT)_xxaa endif endif +endif CFLAGS += \ -DNRF_APPLICATION \ @@ -70,11 +80,14 @@ SRC_C += \ src/portable/synopsys/dwc2/hcd_dwc2.c \ ${NRFX_PATH}/helpers/nrfx_flag32_allocator.c \ ${NRFX_PATH}/drivers/src/nrfx_gpiote.c \ - ${NRFX_PATH}/drivers/src/nrfx_power.c \ ${NRFX_PATH}/drivers/src/nrfx_spim.c \ ${NRFX_PATH}/drivers/src/nrfx_uarte.c \ ${NRFX_PATH}/soc/nrfx_atomic.c +ifeq (,$(findstring OPT_MCU_NRF54,$(CFLAGS))) +SRC_C += ${NRFX_PATH}/drivers/src/nrfx_power.c +endif + INC += \ $(TOP)/$(BOARD_PATH) \ $(TOP)/$(FAMILY_PATH)/nrfx_config \ diff --git a/hw/bsp/nrf/linker/nrf54lm20a_enga_xxaa_application.ld b/hw/bsp/nrf/linker/nrf54lm20a_enga_xxaa_application.ld new file mode 100644 index 000000000..367cf6a89 --- /dev/null +++ b/hw/bsp/nrf/linker/nrf54lm20a_enga_xxaa_application.ld @@ -0,0 +1,13 @@ +/* Linker script to configure memory regions. */ + +SEARCH_DIR(.) +/*GROUP(-lgcc -lc) not compatible with clang*/ + +MEMORY +{ + FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x1FD000 /* Inside global RRAM0 */ + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x40000 + RAM1 (rwx) : ORIGIN = 0x20040000, LENGTH = 0x40000 +} + +INCLUDE "nrf_common.ld" diff --git a/hw/bsp/nrf/nrfx_config/nrfx_config_common.h b/hw/bsp/nrf/nrfx_config/nrfx_config_common.h index a5a29bb8e..02b7390e2 100644 --- a/hw/bsp/nrf/nrfx_config/nrfx_config_common.h +++ b/hw/bsp/nrf/nrfx_config/nrfx_config_common.h @@ -62,6 +62,9 @@ #if defined(NRF54H20_XXAA) #define NRFX_UARTE120_ENABLED 1 +#elif defined(NRF54LM20A_ENGA_XXAA) +#define NRFX_UARTE20_ENABLED 1 + #else #define NRFX_POWER_ENABLED 1 diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index b12a3177e..77a0bbf1d 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -166,6 +166,7 @@ #define TUP_USBIP_DWC2 #define TUP_USBIP_DWC2_NRF #define TUP_DCD_ENDPOINT_MAX 16 + #define TUP_RHPORT_HIGHSPEED 1 #define CFG_TUH_DWC2_DMA_ENABLE_DEFAULT 0 //--------------------------------------------------------------------+ diff --git a/src/portable/synopsys/dwc2/dwc2_nrf.h b/src/portable/synopsys/dwc2/dwc2_nrf.h index 51f2d684f..067bf39cc 100644 --- a/src/portable/synopsys/dwc2/dwc2_nrf.h +++ b/src/portable/synopsys/dwc2/dwc2_nrf.h @@ -2,6 +2,7 @@ * The MIT License (MIT) * * Copyright (c) 2025 Ha Thach (tinyusb.org) + * Copyright (c) 2026, Gabriel Koppenstein * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -30,14 +31,25 @@ #define DWC2_EP_MAX 16 +// Use the auto-resolving peripheral pointer (respects TrustZone secure/non-secure mapping) +#if defined(NRF54LM20A_ENGA_XXAA) + #define _DWC2_NRF_REG_BASE ((uintptr_t) NRF_USBHSCORE) +#else + #define _DWC2_NRF_REG_BASE ((uintptr_t) NRF_USBHSCORE0) +#endif + static const dwc2_controller_t _dwc2_controller[] = { - { .reg_base = NRF_USBHSCORE0_NS_BASE, .irqnum = USBHS_IRQn, .ep_count = 16, .ep_fifo_size = 12288 }, + { .reg_base = _DWC2_NRF_REG_BASE, .irqnum = USBHS_IRQn, .ep_count = 16, .ep_fifo_size = 12160 }, }; TU_ATTR_ALWAYS_INLINE static inline void dwc2_int_set(uint8_t rhport, tusb_role_t role, bool enabled) { (void) rhport; (void) role; - (void) enabled; + if (enabled) { + NVIC_EnableIRQ(USBHS_IRQn); + } else { + NVIC_DisableIRQ(USBHS_IRQn); + } } #define dwc2_dcd_int_enable(_rhport) dwc2_int_set(_rhport, TUSB_ROLE_DEVICE, true) @@ -64,4 +76,15 @@ TU_ATTR_ALWAYS_INLINE static inline void dwc2_phy_update(dwc2_regs_t* dwc2, uint (void)hs_phy_type; } +// nRF54 Cortex-M33 has no D-cache, provide no-op stubs for DMA mode +TU_ATTR_ALWAYS_INLINE static inline bool dwc2_dcache_clean(const void* addr, uint32_t data_size) { + (void)addr; (void)data_size; return true; +} +TU_ATTR_ALWAYS_INLINE static inline bool dwc2_dcache_invalidate(const void* addr, uint32_t data_size) { + (void)addr; (void)data_size; return true; +} +TU_ATTR_ALWAYS_INLINE static inline bool dwc2_dcache_clean_invalidate(const void* addr, uint32_t data_size) { + (void)addr; (void)data_size; return true; +} + #endif -- cgit v1.3.1 From d32a6521256594b41e4c54d0dbf50470573ba995 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 9 Apr 2026 10:35:01 +0000 Subject: Refactor STM32 FSDEV PMA errata delay into common helper Agent-Logs-Url: https://github.com/hathach/tinyusb/sessions/3ec0d5b6-cb8e-48ff-8606-3371beb1efcb Co-authored-by: HiFiPhile <4375114+HiFiPhile@users.noreply.github.com> --- lib/FreeRTOS-Kernel | 1 + lib/fatfs | 1 + lib/lwip | 1 + lib/threadx | 1 + src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 20 +----------- src/portable/st/stm32_fsdev/fsdev_common.c | 17 ++++++++++ src/portable/st/stm32_fsdev/fsdev_common.h | 23 ++++++++++++++ src/portable/st/stm32_fsdev/fsdev_stm32.h | 14 +++++++++ src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c | 45 ++------------------------- tools/linkermap | 1 + tools/uf2 | 1 + 11 files changed, 63 insertions(+), 62 deletions(-) create mode 160000 lib/FreeRTOS-Kernel create mode 160000 lib/fatfs create mode 160000 lib/lwip create mode 160000 lib/threadx create mode 160000 tools/linkermap create mode 160000 tools/uf2 (limited to 'src/portable') 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/fatfs b/lib/fatfs new file mode 160000 index 000000000..30ca13c62 --- /dev/null +++ b/lib/fatfs @@ -0,0 +1 @@ +Subproject commit 30ca13c62615df0d2e9104ab41256985b96590c1 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/lib/threadx b/lib/threadx new file mode 160000 index 000000000..4b6e8100d --- /dev/null +++ b/lib/threadx @@ -0,0 +1 @@ +Subproject commit 4b6e8100d932a3a67b34c6eb17f84f3bffb9e2ae diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 8b4719b21..c8bb0e827 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -394,25 +394,7 @@ void dcd_int_handler(uint8_t rhport) { if (ep_reg & U_EP_CTR_RX) { #ifdef CFG_TUSB_FSDEV_32BIT - /* https://www.st.com/resource/en/errata_sheet/es0561-stm32h503cbebkbrb-device-errata-stmicroelectronics.pdf - * https://www.st.com/resource/en/errata_sheet/es0587-stm32u535xx-and-stm32u545xx-device-errata-stmicroelectronics.pdf - * From H503/U535 errata: Buffer description table update completes after CTR interrupt triggers - * Description: - * - During OUT transfers, the correct transfer interrupt (CTR) is triggered a little before the last USB SRAM - * accesses have completed. If the software responds quickly to the interrupt, the full buffer contents may not be - * correct. Workaround: - * - Software should ensure that a small delay is included before accessing the SRAM contents. This delay - * should be 800 ns in Full Speed mode and 6.4 μs in Low Speed mode - * - Since H5 can run up to 250Mhz -> 1 cycle = 4ns. Per errata, we need to wait 200 cycles. Though executing code - * also takes time, so we'll wait 60 cycles (count = 20). - * - Since Low Speed mode is not supported/popular, we will ignore it for now. - * - * Note: this errata may also apply to G0, U5, H5 etc. - */ - volatile uint32_t cycle_count = 20; // defined as PCD_RX_PMA_CNT in stm32 hal_driver - while (cycle_count > 0U) { - cycle_count--; // each count take 3 cycles (1 for sub, jump, and compare) - } + fsdev_btable_workaround_delay(false); #endif if (ep_reg & U_EP_SETUP) { diff --git a/src/portable/st/stm32_fsdev/fsdev_common.c b/src/portable/st/stm32_fsdev/fsdev_common.c index 003bcd069..3f3973a9d 100644 --- a/src/portable/st/stm32_fsdev/fsdev_common.c +++ b/src/portable/st/stm32_fsdev/fsdev_common.c @@ -113,4 +113,21 @@ void btable_set_rx_bufsize(uint32_t ep_id, uint8_t buf_id, uint16_t wCount) { #endif } +/* STM32 FSDEV PMA Buffer Description Table errata workaround: + * - ES0561 (STM32H503), ES0587 (STM32U535/U545) + * - CTR may trigger before final PMA SRAM accesses complete on OUT transfers. + * - Insert delay before reading PMA count/data. + */ +void fsdev_btable_workaround_delay(bool low_speed) { +#if defined(TUP_USBIP_FSDEV_STM32) && defined(CFG_TUSB_FSDEV_32BIT) + uint32_t cycle_count = low_speed ? CFG_TUSB_FSDEV_BTABLE_LS_DELAY_COUNT : CFG_TUSB_FSDEV_BTABLE_FS_DELAY_COUNT; + volatile uint32_t delay_count = cycle_count; + while (delay_count > 0U) { + delay_count--; // each count take 3 cycles (1 for sub, jump, and compare) + } +#else + (void) low_speed; +#endif +} + #endif diff --git a/src/portable/st/stm32_fsdev/fsdev_common.h b/src/portable/st/stm32_fsdev/fsdev_common.h index 140ff1d61..bf4941794 100644 --- a/src/portable/st/stm32_fsdev/fsdev_common.h +++ b/src/portable/st/stm32_fsdev/fsdev_common.h @@ -307,6 +307,26 @@ typedef struct { #error "Unknown USB IP" #endif +#if defined(TUP_USBIP_FSDEV_STM32) && defined(CFG_TUSB_FSDEV_32BIT) + #ifndef CFG_TUSB_FSDEV_BTABLE_FS_DELAY_COUNT + #if defined(FSDEV_STM32_CPU_MHZ) + #define CFG_TUSB_FSDEV_BTABLE_FS_DELAY_COUNT (FSDEV_STM32_CPU_MHZ / 4U) + #else + // Keep conservative default and allow board/application override. + #define CFG_TUSB_FSDEV_BTABLE_FS_DELAY_COUNT 20U + #endif + #endif + + #ifndef CFG_TUSB_FSDEV_BTABLE_LS_DELAY_COUNT + #if defined(FSDEV_STM32_CPU_MHZ) + #define CFG_TUSB_FSDEV_BTABLE_LS_DELAY_COUNT (FSDEV_STM32_CPU_MHZ * 2U) + #else + // Keep conservative default and allow board/application override. + #define CFG_TUSB_FSDEV_BTABLE_LS_DELAY_COUNT 20U + #endif + #endif +#endif + //--------------------------------------------------------------------+ // Endpoint Helper // - CTR is write 0 to clear @@ -449,6 +469,9 @@ uint16_t pma_align_buffer_size(uint16_t size, uint8_t *blsize, uint8_t *num_bloc // Set RX buffer size void btable_set_rx_bufsize(uint32_t ep_id, uint8_t buf_id, uint16_t wCount); +// STM32 FSDEV PMA Buffer Description Table errata workaround delay. +void fsdev_btable_workaround_delay(bool low_speed); + #ifdef __cplusplus } #endif diff --git a/src/portable/st/stm32_fsdev/fsdev_stm32.h b/src/portable/st/stm32_fsdev/fsdev_stm32.h index a63592c5d..3f726c2ec 100644 --- a/src/portable/st/stm32_fsdev/fsdev_stm32.h +++ b/src/portable/st/stm32_fsdev/fsdev_stm32.h @@ -138,6 +138,20 @@ #error "FSDEV_HAS_SBUF_ISO not defined" #endif +#ifndef FSDEV_STM32_CPU_MHZ + #if CFG_TUSB_MCU == OPT_MCU_STM32H5 + #define FSDEV_STM32_CPU_MHZ 250U + #elif CFG_TUSB_MCU == OPT_MCU_STM32U5 + #define FSDEV_STM32_CPU_MHZ 160U + #elif CFG_TUSB_MCU == OPT_MCU_STM32U3 + #define FSDEV_STM32_CPU_MHZ 96U + #elif CFG_TUSB_MCU == OPT_MCU_STM32G0 + #define FSDEV_STM32_CPU_MHZ 64U + #elif CFG_TUSB_MCU == OPT_MCU_STM32C0 + #define FSDEV_STM32_CPU_MHZ 48U + #endif +#endif + #ifndef CFG_TUD_FSDEV_DOUBLE_BUFFERED_ISO_EP // Default configuration for double-buffered isochronous endpoints: // - Enable double buffering on devices with >1KB Packet Memory Area (PMA) diff --git a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c index 18685dbdc..c41228919 100644 --- a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c @@ -58,20 +58,6 @@ TU_VERIFY_STATIC(CFG_TUH_FSDEV_ENDPOINT_MAX <= 255, "currently only use 8-bit for index"); -#if CFG_TUSB_MCU == OPT_MCU_STM32H5 - #define CPU_FREQUENCY_MHZ 250U -#elif CFG_TUSB_MCU == OPT_MCU_STM32U5 - #define CPU_FREQUENCY_MHZ 160U -#elif CFG_TUSB_MCU == OPT_MCU_STM32U3 - #define CPU_FREQUENCY_MHZ 96U -#elif CFG_TUSB_MCU == OPT_MCU_STM32G0 - #define CPU_FREQUENCY_MHZ 64U -#elif CFG_TUSB_MCU == OPT_MCU_STM32C0 - #define CPU_FREQUENCY_MHZ 48U -#else - #error "CPU_FREQUENCY_MHZ not defined for this STM32 MCU" -#endif - enum { HCD_XFER_ERROR_MAX = 3, HCD_XFER_NAK_MAX = 15, @@ -165,35 +151,8 @@ static inline void channel_write_status(uint8_t ch_id, uint32_t ch_reg, tusb_dir } static inline uint16_t channel_get_rx_count(uint8_t ch_id) { - /* https://www.st.com/resource/en/errata_sheet/es0561-stm32h503cbebkbrb-device-errata-stmicroelectronics.pdf - * https://www.st.com/resource/en/errata_sheet/es0587-stm32u535xx-and-stm32u545xx-device-errata-stmicroelectronics.pdf - * From H503/U535 errata: Buffer description table update completes after CTR interrupt triggers - * Description: - * - During OUT transfers, the correct transfer interrupt (CTR) is triggered a little before the last USB SRAM accesses - * have completed. If the software responds quickly to the interrupt, the full buffer contents may not be correct. - * Workaround: - * - Software should ensure that a small delay is included before accessing the SRAM contents. This delay - * should be 800 ns in Full Speed mode and 6.4 μs in Low Speed mode - * - * Note: this errata may also apply to G0, U5, H5 etc. - * - * We choose the delay count based on max CPU frequency (in MHz) to ensure the delay is at least the required time. - */ - uint32_t ch_reg = ch_read(ch_id); - if (FSDEV_REG->ISTR & U_ISTR_LS_DCONN || ch_reg & U_EP_LSEP) { - // Low speed mode: 6.4 us delay -> about 2 cycles per MHz - volatile uint32_t cycle_count = CPU_FREQUENCY_MHZ * 2U; - while (cycle_count > 0U) { - cycle_count--; // each count take 3 cycles (1 for sub, jump, and compare) - } - } else { - // Full speed mode: 800 ns delay -> about 0.25 cycles per MHz - volatile uint32_t cycle_count = CPU_FREQUENCY_MHZ / 4U; - while (cycle_count > 0U) { - cycle_count--; // each count take 3 cycles (1 for sub, jump, and compare) - } - } + fsdev_btable_workaround_delay((FSDEV_REG->ISTR & U_ISTR_LS_DCONN) || (ch_reg & U_EP_LSEP)); return btable_get_count(ch_id, BTABLE_BUF_RX); } @@ -238,7 +197,7 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { // If DCON_STAT is already set, the controller sometimes misses the initial connection interrupt if (FSDEV_REG->ISTR & U_ISTR_DCON_STAT) { // Wait DP/DM stabilize time - volatile uint32_t cycle_count = CPU_FREQUENCY_MHZ / 4U; + volatile uint32_t cycle_count = CFG_TUSB_FSDEV_BTABLE_FS_DELAY_COUNT; while (cycle_count > 0U) { cycle_count--; } diff --git a/tools/linkermap b/tools/linkermap new file mode 160000 index 000000000..8e1f440fa --- /dev/null +++ b/tools/linkermap @@ -0,0 +1 @@ +Subproject commit 8e1f440fa15c567aceb5aa0d14f6d18c329cc67f 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 -- cgit v1.3.1 From b2c36e0000b48f05e161f76fa880b810cf9405b4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 9 Apr 2026 10:39:02 +0000 Subject: Document and polish shared FSDEV errata delay helper Agent-Logs-Url: https://github.com/hathach/tinyusb/sessions/3ec0d5b6-cb8e-48ff-8606-3371beb1efcb Co-authored-by: HiFiPhile <4375114+HiFiPhile@users.noreply.github.com> --- src/portable/st/stm32_fsdev/fsdev_common.c | 2 +- src/portable/st/stm32_fsdev/fsdev_common.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'src/portable') diff --git a/src/portable/st/stm32_fsdev/fsdev_common.c b/src/portable/st/stm32_fsdev/fsdev_common.c index 3f3973a9d..4b7c1ad5f 100644 --- a/src/portable/st/stm32_fsdev/fsdev_common.c +++ b/src/portable/st/stm32_fsdev/fsdev_common.c @@ -123,7 +123,7 @@ void fsdev_btable_workaround_delay(bool low_speed) { uint32_t cycle_count = low_speed ? CFG_TUSB_FSDEV_BTABLE_LS_DELAY_COUNT : CFG_TUSB_FSDEV_BTABLE_FS_DELAY_COUNT; volatile uint32_t delay_count = cycle_count; while (delay_count > 0U) { - delay_count--; // each count take 3 cycles (1 for sub, jump, and compare) + delay_count--; // each count takes 3 cycles (1 for sub, jump, and compare) } #else (void) low_speed; diff --git a/src/portable/st/stm32_fsdev/fsdev_common.h b/src/portable/st/stm32_fsdev/fsdev_common.h index bf4941794..2da80fd73 100644 --- a/src/portable/st/stm32_fsdev/fsdev_common.h +++ b/src/portable/st/stm32_fsdev/fsdev_common.h @@ -469,7 +469,8 @@ uint16_t pma_align_buffer_size(uint16_t size, uint8_t *blsize, uint8_t *num_bloc // Set RX buffer size void btable_set_rx_bufsize(uint32_t ep_id, uint8_t buf_id, uint16_t wCount); -// STM32 FSDEV PMA Buffer Description Table errata workaround delay. +// Delay helper for STM32 FSDEV PMA Buffer Description Table errata (ES0561/ES0587). +// Low-speed path uses CFG_TUSB_FSDEV_BTABLE_LS_DELAY_COUNT, otherwise full-speed count. void fsdev_btable_workaround_delay(bool low_speed); #ifdef __cplusplus -- cgit v1.3.1 From e03a8aa6b1005d33f6b47a7c07f21b18444627d2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 9 Apr 2026 10:40:24 +0000 Subject: Restore compile-time guard for STM32 FSDEV delay defaults Agent-Logs-Url: https://github.com/hathach/tinyusb/sessions/3ec0d5b6-cb8e-48ff-8606-3371beb1efcb Co-authored-by: HiFiPhile <4375114+HiFiPhile@users.noreply.github.com> --- src/portable/st/stm32_fsdev/fsdev_common.h | 6 ++---- src/portable/st/stm32_fsdev/fsdev_stm32.h | 4 ++++ 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'src/portable') diff --git a/src/portable/st/stm32_fsdev/fsdev_common.h b/src/portable/st/stm32_fsdev/fsdev_common.h index 2da80fd73..ab07ca0e9 100644 --- a/src/portable/st/stm32_fsdev/fsdev_common.h +++ b/src/portable/st/stm32_fsdev/fsdev_common.h @@ -312,8 +312,7 @@ typedef struct { #if defined(FSDEV_STM32_CPU_MHZ) #define CFG_TUSB_FSDEV_BTABLE_FS_DELAY_COUNT (FSDEV_STM32_CPU_MHZ / 4U) #else - // Keep conservative default and allow board/application override. - #define CFG_TUSB_FSDEV_BTABLE_FS_DELAY_COUNT 20U + #error "Define CFG_TUSB_FSDEV_BTABLE_FS_DELAY_COUNT or FSDEV_STM32_CPU_MHZ for STM32 FSDEV 32-bit" #endif #endif @@ -321,8 +320,7 @@ typedef struct { #if defined(FSDEV_STM32_CPU_MHZ) #define CFG_TUSB_FSDEV_BTABLE_LS_DELAY_COUNT (FSDEV_STM32_CPU_MHZ * 2U) #else - // Keep conservative default and allow board/application override. - #define CFG_TUSB_FSDEV_BTABLE_LS_DELAY_COUNT 20U + #error "Define CFG_TUSB_FSDEV_BTABLE_LS_DELAY_COUNT or FSDEV_STM32_CPU_MHZ for STM32 FSDEV 32-bit" #endif #endif #endif diff --git a/src/portable/st/stm32_fsdev/fsdev_stm32.h b/src/portable/st/stm32_fsdev/fsdev_stm32.h index 3f726c2ec..a6827cc60 100644 --- a/src/portable/st/stm32_fsdev/fsdev_stm32.h +++ b/src/portable/st/stm32_fsdev/fsdev_stm32.h @@ -145,10 +145,14 @@ #define FSDEV_STM32_CPU_MHZ 160U #elif CFG_TUSB_MCU == OPT_MCU_STM32U3 #define FSDEV_STM32_CPU_MHZ 96U + #elif CFG_TUSB_MCU == OPT_MCU_STM32U0 + #define FSDEV_STM32_CPU_MHZ 56U #elif CFG_TUSB_MCU == OPT_MCU_STM32G0 #define FSDEV_STM32_CPU_MHZ 64U #elif CFG_TUSB_MCU == OPT_MCU_STM32C0 #define FSDEV_STM32_CPU_MHZ 48U + #elif defined(CFG_TUSB_FSDEV_32BIT) + #error "FSDEV_STM32_CPU_MHZ not defined for this STM32 MCU" #endif #endif -- cgit v1.3.1 From 2f4792f9e1b5a6f06e6306fe0d0ebce641914791 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 9 Apr 2026 10:41:14 +0000 Subject: Decouple DCON stabilize delay from BTABLE errata macro Agent-Logs-Url: https://github.com/hathach/tinyusb/sessions/3ec0d5b6-cb8e-48ff-8606-3371beb1efcb Co-authored-by: HiFiPhile <4375114+HiFiPhile@users.noreply.github.com> --- src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/portable') diff --git a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c index c41228919..50ff975fc 100644 --- a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c @@ -197,7 +197,7 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { // If DCON_STAT is already set, the controller sometimes misses the initial connection interrupt if (FSDEV_REG->ISTR & U_ISTR_DCON_STAT) { // Wait DP/DM stabilize time - volatile uint32_t cycle_count = CFG_TUSB_FSDEV_BTABLE_FS_DELAY_COUNT; + volatile uint32_t cycle_count = FSDEV_STM32_CPU_MHZ / 4U; while (cycle_count > 0U) { cycle_count--; } -- cgit v1.3.1 From 84943dbbd54e119248f3585aa1fe9c6496af7069 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 9 Apr 2026 10:42:01 +0000 Subject: Simplify delay loop comment in shared FSDEV helper Agent-Logs-Url: https://github.com/hathach/tinyusb/sessions/3ec0d5b6-cb8e-48ff-8606-3371beb1efcb Co-authored-by: HiFiPhile <4375114+HiFiPhile@users.noreply.github.com> --- src/portable/st/stm32_fsdev/fsdev_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/portable') diff --git a/src/portable/st/stm32_fsdev/fsdev_common.c b/src/portable/st/stm32_fsdev/fsdev_common.c index 4b7c1ad5f..e6c95e12d 100644 --- a/src/portable/st/stm32_fsdev/fsdev_common.c +++ b/src/portable/st/stm32_fsdev/fsdev_common.c @@ -123,7 +123,7 @@ void fsdev_btable_workaround_delay(bool low_speed) { uint32_t cycle_count = low_speed ? CFG_TUSB_FSDEV_BTABLE_LS_DELAY_COUNT : CFG_TUSB_FSDEV_BTABLE_FS_DELAY_COUNT; volatile uint32_t delay_count = cycle_count; while (delay_count > 0U) { - delay_count--; // each count takes 3 cycles (1 for sub, jump, and compare) + delay_count--; } #else (void) low_speed; -- cgit v1.3.1 From ab32a2cd2b7472966b309521d80b15488393af0e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 9 Apr 2026 10:42:47 +0000 Subject: Clarify STM32U0 delay-default frequency usage Agent-Logs-Url: https://github.com/hathach/tinyusb/sessions/3ec0d5b6-cb8e-48ff-8606-3371beb1efcb Co-authored-by: HiFiPhile <4375114+HiFiPhile@users.noreply.github.com> --- src/portable/st/stm32_fsdev/fsdev_stm32.h | 1 + 1 file changed, 1 insertion(+) (limited to 'src/portable') diff --git a/src/portable/st/stm32_fsdev/fsdev_stm32.h b/src/portable/st/stm32_fsdev/fsdev_stm32.h index a6827cc60..5950efbe3 100644 --- a/src/portable/st/stm32_fsdev/fsdev_stm32.h +++ b/src/portable/st/stm32_fsdev/fsdev_stm32.h @@ -146,6 +146,7 @@ #elif CFG_TUSB_MCU == OPT_MCU_STM32U3 #define FSDEV_STM32_CPU_MHZ 96U #elif CFG_TUSB_MCU == OPT_MCU_STM32U0 + // Used by STM32 FSDEV PMA delay defaults as a conservative max CPU frequency. #define FSDEV_STM32_CPU_MHZ 56U #elif CFG_TUSB_MCU == OPT_MCU_STM32G0 #define FSDEV_STM32_CPU_MHZ 64U -- cgit v1.3.1 From 41575d2de943393f6cc7e5228ab904614fadce28 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 9 Apr 2026 10:44:08 +0000 Subject: Polish FSDEV delay code readability Agent-Logs-Url: https://github.com/hathach/tinyusb/sessions/3ec0d5b6-cb8e-48ff-8606-3371beb1efcb Co-authored-by: HiFiPhile <4375114+HiFiPhile@users.noreply.github.com> --- src/portable/st/stm32_fsdev/fsdev_stm32.h | 2 +- src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'src/portable') diff --git a/src/portable/st/stm32_fsdev/fsdev_stm32.h b/src/portable/st/stm32_fsdev/fsdev_stm32.h index 5950efbe3..5e383eb97 100644 --- a/src/portable/st/stm32_fsdev/fsdev_stm32.h +++ b/src/portable/st/stm32_fsdev/fsdev_stm32.h @@ -139,6 +139,7 @@ #endif #ifndef FSDEV_STM32_CPU_MHZ + // Max CPU frequency in MHz, used to derive conservative FSDEV PMA delay defaults. #if CFG_TUSB_MCU == OPT_MCU_STM32H5 #define FSDEV_STM32_CPU_MHZ 250U #elif CFG_TUSB_MCU == OPT_MCU_STM32U5 @@ -146,7 +147,6 @@ #elif CFG_TUSB_MCU == OPT_MCU_STM32U3 #define FSDEV_STM32_CPU_MHZ 96U #elif CFG_TUSB_MCU == OPT_MCU_STM32U0 - // Used by STM32 FSDEV PMA delay defaults as a conservative max CPU frequency. #define FSDEV_STM32_CPU_MHZ 56U #elif CFG_TUSB_MCU == OPT_MCU_STM32G0 #define FSDEV_STM32_CPU_MHZ 64U diff --git a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c index 50ff975fc..18cf302d8 100644 --- a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c @@ -152,7 +152,8 @@ static inline void channel_write_status(uint8_t ch_id, uint32_t ch_reg, tusb_dir static inline uint16_t channel_get_rx_count(uint8_t ch_id) { uint32_t ch_reg = ch_read(ch_id); - fsdev_btable_workaround_delay((FSDEV_REG->ISTR & U_ISTR_LS_DCONN) || (ch_reg & U_EP_LSEP)); + const bool is_low_speed = (FSDEV_REG->ISTR & U_ISTR_LS_DCONN) || (ch_reg & U_EP_LSEP); + fsdev_btable_workaround_delay(is_low_speed); return btable_get_count(ch_id, BTABLE_BUF_RX); } -- cgit v1.3.1 From 8849515a0e1d1179d20a42b7b92c0e0a4d1aa131 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 9 Apr 2026 18:22:25 +0700 Subject: rename ep_fifo_size (bytes) to otg_dfifo_depth (words) --- src/portable/synopsys/dwc2/dcd_dwc2.c | 29 ++++++++++++----------- src/portable/synopsys/dwc2/dwc2_at32.h | 20 ++++++++-------- src/portable/synopsys/dwc2/dwc2_bcm.h | 2 +- src/portable/synopsys/dwc2/dwc2_efm32.h | 2 +- src/portable/synopsys/dwc2/dwc2_esp32.h | 8 +++---- src/portable/synopsys/dwc2/dwc2_gd32.h | 2 +- src/portable/synopsys/dwc2/dwc2_info.py | 6 ++--- src/portable/synopsys/dwc2/dwc2_nrf.h | 38 +++++++++++++++++------------ src/portable/synopsys/dwc2/dwc2_stm32.h | 42 ++++++++++++++++----------------- src/portable/synopsys/dwc2/dwc2_type.h | 3 ++- src/portable/synopsys/dwc2/dwc2_xmc.h | 2 +- src/portable/synopsys/dwc2/hcd_dwc2.c | 21 +++++++++++------ 12 files changed, 96 insertions(+), 79 deletions(-) (limited to 'src/portable') diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index e32dedd1b..bdd3a59ed 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -148,22 +148,23 @@ static void dma_setup_prepare(uint8_t rhport) { /* Device Data FIFO scheme - - The FIFO is split up into - - EPInfo: for storing DMA metadata, only required when use DMA. Maximum size is called - EP_LOC_CNT = ep_fifo_size - ghwcfg3.dfifo_depth. For value less than EP_LOC_CNT, gdfifocfg must be configured before - gahbcfg.dmaen is set - - Buffer mode: 1 word per endpoint direction - - Scatter/Gather DMA: 4 words per endpoint direction + The controller has a single SPRAM of otg_dfifo_depth 32-bit words shared between all FIFOs and optional DMA metadata. + otg_dfifo_depth = ghwcfg3.dfifo_depth + EP_LOC_CNT. It is split up into: + + - EPInfo: for storing DMA address registers (DxEPDMAn), only required when DMA is used. + gdfifocfg.EPINFOBASE and gdfifocfg.GDFIFOCfg must be configured before gahbcfg.dmaen is set. + The number of words needed per endpoint direction depends on the DMA mode used at runtime: + - Buffer DMA mode: 1 word per endpoint direction + - Scatter/Gather DMA mode: 4 words per endpoint direction - TX FIFO: one fifo for each IN endpoint. Size is dynamic depending on packet size, starting from top with EP0 IN. - Shared RX FIFO: a shared fifo for all OUT endpoints. Typically, can hold up to 2 packets of the largest EP size. - We allocated TX FIFO from top to bottom (using top pointer), this to allow the RX FIFO to grow dynamically which is + We allocate TX FIFOs from top to bottom (using a top pointer), this to allow the RX FIFO to grow dynamically, which is possible since the free space is located between the RX and TX FIFOs. - ---------------- ep_fifo_size - | DxEPIDMAn | - |-------------|-- gdfifocfg.EPINFOBASE (max is ghwcfg3.dfifo_depth) + --------------- otg_dfifo_depth + | EPInfo | DxEPDMAn (DMA only, sized per runtime DMA mode) + |-------------|-- gdfifocfg.EPINFOBASE (= gdfifocfg.GDFIFOCfg) | IN FIFO 0 | control EP |-------------| | IN FIFO 1 | @@ -184,9 +185,9 @@ static void dma_setup_prepare(uint8_t rhport) { - 13 for setup packets + control words (up to 3 setup packets). - 1 for global NAK (not required/used here). - Largest-EPsize/4 + 1. (FS: 64 bytes, HS: 512 bytes). Recommended is "2 x (Largest-EPsize/4 + 1)" - - 2 for each used OUT endpoint + - 2 for each used OUT endpoint. - Therefore GRXFSIZ = 13 + 1 + 2 x (Largest-EPsize/4 + 1) + 2 x EPOUTnum + Therefore, GRXFSIZ = 13 + 1 + 2 x (Largest-EPsize/4 + 1) + 2 x EPOUTnum */ TU_ATTR_ALWAYS_INLINE static inline uint16_t calc_device_grxfsiz(uint16_t largest_ep_size, uint8_t ep_count) { @@ -249,7 +250,7 @@ static void dfifo_device_init(uint8_t rhport) { // Scatter/Gather DMA mode is not yet supported. Buffer DMA only need 1 words per endpoint direction const bool is_dma = dma_device_enabled(dwc2); - _dcd_data.dfifo_top = dwc2_controller->ep_fifo_size/4; + _dcd_data.dfifo_top = dwc2_controller->otg_dfifo_depth; if (is_dma) { _dcd_data.dfifo_top -= 2 * dwc2_controller->ep_count; } diff --git a/src/portable/synopsys/dwc2/dwc2_at32.h b/src/portable/synopsys/dwc2/dwc2_at32.h index fa6d10c12..594d350b7 100644 --- a/src/portable/synopsys/dwc2/dwc2_at32.h +++ b/src/portable/synopsys/dwc2/dwc2_at32.h @@ -32,38 +32,38 @@ #if CFG_TUSB_MCU == OPT_MCU_AT32F415 #include - #define OTG1_FIFO_SIZE 1280 + #define OTG1_DFIFO_DEPTH 320 #define OTG1_IRQn OTGFS1_IRQn #define DWC2_OTG1_REG_BASE 0x50000000UL #elif CFG_TUSB_MCU == OPT_MCU_AT32F435_437 #include - #define OTG1_FIFO_SIZE 1280 - #define OTG2_FIFO_SIZE 1280 + #define OTG1_DFIFO_DEPTH 320 + #define OTG2_DFIFO_DEPTH 320 #define OTG1_IRQn OTGFS1_IRQn #define OTG2_IRQn OTGFS2_IRQn #define DWC2_OTG1_REG_BASE 0x50000000UL #define DWC2_OTG2_REG_BASE 0x40040000UL #elif CFG_TUSB_MCU == OPT_MCU_AT32F423 #include - #define OTG1_FIFO_SIZE 1280 + #define OTG1_DFIFO_DEPTH 320 #define OTG1_IRQn OTGFS1_IRQn #define DWC2_OTG1_REG_BASE 0x50000000UL #elif CFG_TUSB_MCU == OPT_MCU_AT32F402_405 #include - #define OTG1_FIFO_SIZE 1280 - #define OTG2_FIFO_SIZE 4096 + #define OTG1_DFIFO_DEPTH 320 + #define OTG2_DFIFO_DEPTH 1024 #define OTG1_IRQn OTGFS1_IRQn #define OTG2_IRQn OTGHS_IRQn #define DWC2_OTG1_REG_BASE 0x50000000UL #define DWC2_OTG2_REG_BASE 0x40040000UL //OTGHS #elif CFG_TUSB_MCU == OPT_MCU_AT32F425 #include - #define OTG1_FIFO_SIZE 1280 + #define OTG1_DFIFO_DEPTH 320 #define OTG1_IRQn OTGFS1_IRQn #define DWC2_OTG1_REG_BASE 0x50000000UL #elif CFG_TUSB_MCU == OPT_MCU_AT32F45X #include - #define OTG1_FIFO_SIZE 1280 + #define OTG1_DFIFO_DEPTH 320 #define OTG1_IRQn OTGFS1_IRQn #define DWC2_OTG1_REG_BASE 0x50000000UL #endif @@ -73,9 +73,9 @@ 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}, + {.reg_base = DWC2_OTG1_REG_BASE, .irqnum = OTG1_IRQn, .ep_count = DWC2_EP_MAX, .otg_dfifo_depth = OTG1_DFIFO_DEPTH}, #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} + {.reg_base = DWC2_OTG2_REG_BASE, .irqnum = OTG2_IRQn, .ep_count = DWC2_EP_MAX, .otg_dfifo_depth = OTG2_DFIFO_DEPTH} #endif }; diff --git a/src/portable/synopsys/dwc2/dwc2_bcm.h b/src/portable/synopsys/dwc2/dwc2_bcm.h index 00842bba2..50f3122e8 100644 --- a/src/portable/synopsys/dwc2/dwc2_bcm.h +++ b/src/portable/synopsys/dwc2/dwc2_bcm.h @@ -39,7 +39,7 @@ static const dwc2_controller_t _dwc2_controller[] = { - { .reg_base = USB_OTG_GLOBAL_BASE, .irqnum = USB_IRQn, .ep_count = DWC2_EP_MAX, .ep_fifo_size = 16384 } + { .reg_base = USB_OTG_GLOBAL_BASE, .irqnum = USB_IRQn, .ep_count = DWC2_EP_MAX, .otg_dfifo_depth = 4096 } }; #define dcache_clean(_addr, _size) data_clean(_addr, _size) diff --git a/src/portable/synopsys/dwc2/dwc2_efm32.h b/src/portable/synopsys/dwc2/dwc2_efm32.h index e1cb7c769..167f5b4cd 100644 --- a/src/portable/synopsys/dwc2/dwc2_efm32.h +++ b/src/portable/synopsys/dwc2/dwc2_efm32.h @@ -40,7 +40,7 @@ static const dwc2_controller_t _dwc2_controller[] = { - { .reg_base = DWC2_REG_BASE, .irqnum = USB_IRQn, .ep_count = DWC2_EP_MAX, .ep_fifo_size = 2048 } + { .reg_base = DWC2_REG_BASE, .irqnum = USB_IRQn, .ep_count = DWC2_EP_MAX, .otg_dfifo_depth = 512 } }; TU_ATTR_ALWAYS_INLINE diff --git a/src/portable/synopsys/dwc2/dwc2_esp32.h b/src/portable/synopsys/dwc2/dwc2_esp32.h index ff9f216bd..99ef9456f 100644 --- a/src/portable/synopsys/dwc2/dwc2_esp32.h +++ b/src/portable/synopsys/dwc2/dwc2_esp32.h @@ -44,7 +44,7 @@ #define DWC2_EP_MAX 7 static const dwc2_controller_t _dwc2_controller[] = { - { .reg_base = DWC2_FS_REG_BASE, .irqnum = ETS_USB_INTR_SOURCE, .ep_count = 7, .ep_in_count = 5, .ep_fifo_size = 1024 } + { .reg_base = DWC2_FS_REG_BASE, .irqnum = ETS_USB_INTR_SOURCE, .ep_count = 7, .ep_in_count = 5, .otg_dfifo_depth = 256 } }; #elif TU_CHECK_MCU(OPT_MCU_ESP32H4) @@ -61,7 +61,7 @@ static const dwc2_controller_t _dwc2_controller[] = { #define DWC2_EP_MAX 7 static const dwc2_controller_t _dwc2_controller[] = { - { .reg_base = DWC2_FS_REG_BASE, .irqnum = ETS_USB_OTG11_INTR_SOURCE, .ep_count = 7, .ep_in_count = 5, .ep_fifo_size = 1024 } + { .reg_base = DWC2_FS_REG_BASE, .irqnum = ETS_USB_OTG11_INTR_SOURCE, .ep_count = 7, .ep_in_count = 5, .otg_dfifo_depth = 256 } }; #elif TU_CHECK_MCU(OPT_MCU_ESP32P4) @@ -72,8 +72,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, .otg_dfifo_depth = 256 }, + { .reg_base = DWC2_HS_REG_BASE, .irqnum = ETS_USB_OTG_INTR_SOURCE, .ep_count = 16, .ep_in_count = 8, .otg_dfifo_depth = 1024 } }; #endif diff --git a/src/portable/synopsys/dwc2/dwc2_gd32.h b/src/portable/synopsys/dwc2/dwc2_gd32.h index ccbf93a76..396d17e30 100644 --- a/src/portable/synopsys/dwc2/dwc2_gd32.h +++ b/src/portable/synopsys/dwc2/dwc2_gd32.h @@ -37,7 +37,7 @@ static const dwc2_controller_t _dwc2_controller[] = { - { .reg_base = DWC2_REG_BASE, .irqnum = 86, .ep_count = DWC2_EP_MAX, .ep_fifo_size = 1280 } + { .reg_base = DWC2_REG_BASE, .irqnum = 86, .ep_count = DWC2_EP_MAX, .otg_dfifo_depth = 320 } }; extern uint32_t SystemCoreClock; diff --git a/src/portable/synopsys/dwc2/dwc2_info.py b/src/portable/synopsys/dwc2/dwc2_info.py index bdf63d590..eab95ffe1 100755 --- a/src/portable/synopsys/dwc2/dwc2_info.py +++ b/src/portable/synopsys/dwc2/dwc2_info.py @@ -9,14 +9,14 @@ import pandas as pd 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 F405 HS': [0, 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], 'ESP32-P4': [0, 0x4F54400A, 0, 0x215FFFD0, 0x03805EB5, 0xDFF1A030], - 'nRF54': [0, 0x4F54430A, 0xAA555000, 0x228BFC72, 0x0BEAC0E8, 0x1E10AA60], - 'nRF54LM20': [0x00000000, 0x4F54500B, 0x00000000, 0x22AFFC52, 0x0BE0C0E8, 0x3E10AA60], + # 'nRF54H20': [0, 0x4F54430A, 0xAA555000, 0x228BFC72, 0x0BEAC0E8, 0x1E10AA60], + 'nRF54LM20': [0, 0x4F54500B, 0x00000000, 0x22AFFC52, 0x0BE0C0E8, 0x3E10AA60], # ST sort by GUID 'ST F407/429 HS': [0x1100, 0x4F54281A, 0, 0x229ED590, 0x03F403E8, 0x17F00030], 'ST F207/F407/411/429 FS': [0x1200, 0x4F54281A, 0, 0x229DCD20, 0x020001E8, 0x0FF08030], diff --git a/src/portable/synopsys/dwc2/dwc2_nrf.h b/src/portable/synopsys/dwc2/dwc2_nrf.h index 067bf39cc..fc9cd18bc 100644 --- a/src/portable/synopsys/dwc2/dwc2_nrf.h +++ b/src/portable/synopsys/dwc2/dwc2_nrf.h @@ -2,7 +2,6 @@ * The MIT License (MIT) * * Copyright (c) 2025 Ha Thach (tinyusb.org) - * Copyright (c) 2026, Gabriel Koppenstein * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,6 +22,9 @@ * THE SOFTWARE. * * This file is part of the TinyUSB stack. + * + * Modification + * - Gabriel Koppenstein add nRF54LM20 support */ #ifndef TUSB_DWC2_NRF_H #define TUSB_DWC2_NRF_H @@ -33,18 +35,18 @@ // Use the auto-resolving peripheral pointer (respects TrustZone secure/non-secure mapping) #if defined(NRF54LM20A_ENGA_XXAA) - #define _DWC2_NRF_REG_BASE ((uintptr_t) NRF_USBHSCORE) + #define DWC2_REG_BASE ((uintptr_t)NRF_USBHSCORE) #else - #define _DWC2_NRF_REG_BASE ((uintptr_t) NRF_USBHSCORE0) + #define DWC2_REG_BASE ((uintptr_t)NRF_USBHSCORE0) #endif static const dwc2_controller_t _dwc2_controller[] = { - { .reg_base = _DWC2_NRF_REG_BASE, .irqnum = USBHS_IRQn, .ep_count = 16, .ep_fifo_size = 12160 }, + {.reg_base = DWC2_REG_BASE, .irqnum = USBHS_IRQn, .ep_count = 16, .otg_dfifo_depth = 3072}, }; TU_ATTR_ALWAYS_INLINE static inline void dwc2_int_set(uint8_t rhport, tusb_role_t role, bool enabled) { - (void) rhport; - (void) role; + (void)rhport; + (void)role; if (enabled) { NVIC_EnableIRQ(USBHS_IRQn); } else { @@ -59,32 +61,38 @@ TU_ATTR_ALWAYS_INLINE static inline void dwc2_remote_wakeup_delay(void) { } // 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) { +TU_ATTR_ALWAYS_INLINE static inline void dwc2_phy_init(dwc2_regs_t *dwc2, uint8_t hs_phy_type) { (void)dwc2; (void)hs_phy_type; } // MCU specific PHY deinit, disable PHY power -TU_ATTR_ALWAYS_INLINE static inline void dwc2_phy_deinit(dwc2_regs_t* dwc2, uint8_t hs_phy_type) { +TU_ATTR_ALWAYS_INLINE static inline void dwc2_phy_deinit(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 -TU_ATTR_ALWAYS_INLINE static inline void dwc2_phy_update(dwc2_regs_t* dwc2, uint8_t hs_phy_type) { +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; } // nRF54 Cortex-M33 has no D-cache, provide no-op stubs for DMA mode -TU_ATTR_ALWAYS_INLINE static inline bool dwc2_dcache_clean(const void* addr, uint32_t data_size) { - (void)addr; (void)data_size; return true; +TU_ATTR_ALWAYS_INLINE static inline bool dwc2_dcache_clean(const void *addr, uint32_t data_size) { + (void)addr; + (void)data_size; + return true; } -TU_ATTR_ALWAYS_INLINE static inline bool dwc2_dcache_invalidate(const void* addr, uint32_t data_size) { - (void)addr; (void)data_size; return true; +TU_ATTR_ALWAYS_INLINE static inline bool dwc2_dcache_invalidate(const void *addr, uint32_t data_size) { + (void)addr; + (void)data_size; + return true; } -TU_ATTR_ALWAYS_INLINE static inline bool dwc2_dcache_clean_invalidate(const void* addr, uint32_t data_size) { - (void)addr; (void)data_size; return true; +TU_ATTR_ALWAYS_INLINE static inline bool dwc2_dcache_clean_invalidate(const void *addr, uint32_t data_size) { + (void)addr; + (void)data_size; + return true; } #endif diff --git a/src/portable/synopsys/dwc2/dwc2_stm32.h b/src/portable/synopsys/dwc2/dwc2_stm32.h index 259ad21b9..5f6e98224 100644 --- a/src/portable/synopsys/dwc2/dwc2_stm32.h +++ b/src/portable/synopsys/dwc2/dwc2_stm32.h @@ -31,36 +31,36 @@ extern "C" { #endif -// EP_MAX : Max number of bi-directional endpoints including EP0 -// EP_FIFO_SIZE : Size of dedicated USB SRAM +// EP_MAX : Max number of bi-directional endpoints including EP0 +// DFIFO_DEPTH_FS/HS : DFIFO depth in 32-bit words (OTG_DFIFO_DEPTH) #if CFG_TUSB_MCU == OPT_MCU_STM32F1 #include "stm32f1xx.h" #define EP_MAX_FS 4 - #define EP_FIFO_SIZE_FS 1280 + #define DFIFO_DEPTH_FS 320 #elif CFG_TUSB_MCU == OPT_MCU_STM32F2 #include "stm32f2xx.h" #define EP_MAX_FS USB_OTG_FS_MAX_IN_ENDPOINTS - #define EP_FIFO_SIZE_FS USB_OTG_FS_TOTAL_FIFO_SIZE + #define DFIFO_DEPTH_FS 320 #define EP_MAX_HS USB_OTG_HS_MAX_IN_ENDPOINTS - #define EP_FIFO_SIZE_HS USB_OTG_HS_TOTAL_FIFO_SIZE + #define DFIFO_DEPTH_HS 1024 #elif CFG_TUSB_MCU == OPT_MCU_STM32F4 #include "stm32f4xx.h" #define EP_MAX_FS USB_OTG_FS_MAX_IN_ENDPOINTS - #define EP_FIFO_SIZE_FS USB_OTG_FS_TOTAL_FIFO_SIZE + #define DFIFO_DEPTH_FS 320 #define EP_MAX_HS USB_OTG_HS_MAX_IN_ENDPOINTS - #define EP_FIFO_SIZE_HS USB_OTG_HS_TOTAL_FIFO_SIZE + #define DFIFO_DEPTH_HS 1024 #elif CFG_TUSB_MCU == OPT_MCU_STM32H7 #include "stm32h7xx.h" #define EP_MAX_FS 9 - #define EP_FIFO_SIZE_FS 4096 + #define DFIFO_DEPTH_FS 1024 #define EP_MAX_HS 9 - #define EP_FIFO_SIZE_HS 4096 + #define DFIFO_DEPTH_HS 1024 // NOTE: H7 with only 1 USB port: H72x / H73x / H7Ax / H7Bx // USB_OTG_FS_PERIPH_BASE and OTG_FS_IRQn not defined @@ -72,18 +72,18 @@ extern "C" { #elif CFG_TUSB_MCU == OPT_MCU_STM32H7RS #include "stm32h7rsxx.h" #define EP_MAX_FS 6 - #define EP_FIFO_SIZE_FS 1280 + #define DFIFO_DEPTH_FS 320 #define EP_MAX_HS 9 - #define EP_FIFO_SIZE_HS 4096 + #define DFIFO_DEPTH_HS 1024 #elif CFG_TUSB_MCU == OPT_MCU_STM32N6 #include "stm32n6xx.h" #define EP_MAX_FS 9 - #define EP_FIFO_SIZE_FS 4096 + #define DFIFO_DEPTH_FS 1024 #define EP_MAX_HS 9 - #define EP_FIFO_SIZE_HS 4096 + #define DFIFO_DEPTH_HS 1024 #define USB_OTG_FS_PERIPH_BASE USB1_OTG_HS_BASE #define OTG_FS_IRQn USB1_OTG_HS_IRQn @@ -94,15 +94,15 @@ extern "C" { #elif CFG_TUSB_MCU == OPT_MCU_STM32F7 #include "stm32f7xx.h" #define EP_MAX_FS 6 - #define EP_FIFO_SIZE_FS 1280 + #define DFIFO_DEPTH_FS 320 #define EP_MAX_HS 9 - #define EP_FIFO_SIZE_HS 4096 + #define DFIFO_DEPTH_HS 1024 #elif CFG_TUSB_MCU == OPT_MCU_STM32L4 #include "stm32l4xx.h" #define EP_MAX_FS 6 - #define EP_FIFO_SIZE_FS 1280 + #define DFIFO_DEPTH_FS 320 #elif CFG_TUSB_MCU == OPT_MCU_STM32U5 #include "stm32u5xx.h" @@ -110,11 +110,11 @@ extern "C" { #ifdef USB_OTG_FS #define USB_OTG_FS_PERIPH_BASE USB_OTG_FS_BASE #define EP_MAX_FS 6 - #define EP_FIFO_SIZE_FS 1280 + #define DFIFO_DEPTH_FS 1280 #else #define USB_OTG_HS_PERIPH_BASE USB_OTG_HS_BASE #define EP_MAX_HS 9 - #define EP_FIFO_SIZE_HS 4096 + #define DFIFO_DEPTH_HS 4096 #endif #elif CFG_TUSB_MCU == OPT_MCU_STM32WBA @@ -131,7 +131,7 @@ extern "C" { #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 + #define DFIFO_DEPTH_HS 4096 #else #error "Unsupported MCUs" #endif @@ -147,11 +147,11 @@ extern "C" { // - Port0 to OTG_FS, and Port1 to OTG_HS static const dwc2_controller_t _dwc2_controller[] = { #ifdef USB_OTG_FS_PERIPH_BASE - { .reg_base = USB_OTG_FS_PERIPH_BASE, .irqnum = OTG_FS_IRQn, .ep_count = EP_MAX_FS, .ep_fifo_size = EP_FIFO_SIZE_FS }, + { .reg_base = USB_OTG_FS_PERIPH_BASE, .irqnum = OTG_FS_IRQn, .ep_count = EP_MAX_FS, .otg_dfifo_depth = DFIFO_DEPTH_FS }, #endif #ifdef USB_OTG_HS_PERIPH_BASE - { .reg_base = USB_OTG_HS_PERIPH_BASE, .irqnum = OTG_HS_IRQn, .ep_count = EP_MAX_HS, .ep_fifo_size = EP_FIFO_SIZE_HS }, + { .reg_base = USB_OTG_HS_PERIPH_BASE, .irqnum = OTG_HS_IRQn, .ep_count = EP_MAX_HS, .otg_dfifo_depth = DFIFO_DEPTH_HS }, #endif }; diff --git a/src/portable/synopsys/dwc2/dwc2_type.h b/src/portable/synopsys/dwc2/dwc2_type.h index 596bd0b34..7c03a4a91 100644 --- a/src/portable/synopsys/dwc2/dwc2_type.h +++ b/src/portable/synopsys/dwc2/dwc2_type.h @@ -47,7 +47,7 @@ typedef struct uint32_t irqnum; uint8_t ep_count; uint8_t ep_in_count; - uint32_t ep_fifo_size; + uint16_t otg_dfifo_depth; // total SPRAM in 32-bit words = ghwcfg3.dfifo_depth + EP_LOC_CNT }dwc2_controller_t; // DWC OTG HW Release versions @@ -63,6 +63,7 @@ typedef struct #define DWC2_CORE_REV_4_00a 0x4f54400a #define DWC2_CORE_REV_4_11a 0x4f54411a #define DWC2_CORE_REV_4_20a 0x4f54420a +#define DWC2_CORE_REV_5_00b 0x4F54500b #define DWC2_FS_IOT_REV_1_00a 0x5531100a #define DWC2_HS_IOT_REV_1_00a 0x5532100a #define DWC2_CORE_REV_MASK 0x0000ffff diff --git a/src/portable/synopsys/dwc2/dwc2_xmc.h b/src/portable/synopsys/dwc2/dwc2_xmc.h index aca3873df..b946444ee 100644 --- a/src/portable/synopsys/dwc2/dwc2_xmc.h +++ b/src/portable/synopsys/dwc2/dwc2_xmc.h @@ -39,7 +39,7 @@ static const dwc2_controller_t _dwc2_controller[] = { // Note: XMC has some custom control registers before DWC registers - { .reg_base = USB0_BASE, .irqnum = USB0_0_IRQn, .ep_count = DWC2_EP_MAX, .ep_fifo_size = 2048 } + { .reg_base = USB0_BASE, .irqnum = USB0_0_IRQn, .ep_count = DWC2_EP_MAX, .otg_dfifo_depth = 512 } }; TU_ATTR_ALWAYS_INLINE diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index e12e44a41..cd2ddf572 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -323,9 +323,9 @@ TU_ATTR_ALWAYS_INLINE static inline uint8_t cal_next_pid(uint8_t pid, uint8_t pa We allocated TX FIFO from top to bottom (using top pointer), this to allow the RX FIFO to grow dynamically which is possible since the free space is located between the RX and TX FIFOs. - ----------------- ep_fifo_size - | HCDMAn | - |--------------|-- gdfifocfg.EPINFOBASE (max is ghwcfg3.dfifo_depth) + ----------------- otg_dfifo_depth + | HCDMAn | (DMA only, sized per runtime DMA mode) + |--------------|-- gdfifocfg.EPINFOBASE (= gdfifocfg.GDFIFOCfg) | Non-Periodic | | TX FIFO | |--------------|--- GNPTXFSIZ.addr (fixed size) @@ -358,15 +358,22 @@ static void dfifo_host_init(uint8_t rhport, bool is_hs_phy) { // 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; + uint16_t dfifo_top = dwc2_controller->otg_dfifo_depth; if (is_dma) { dfifo_top -= ghwcfg2.num_host_ch; } // fixed allocation for now, improve later: - // - ptx_largest is limited to 256 for FS since most FS core only has 1024 bytes total - uint32_t nptx_largest = is_hs_phy ? TUSB_EPSIZE_BULK_HS / 4 : TUSB_EPSIZE_BULK_FS / 4; - uint32_t ptx_largest = is_hs_phy ? TUSB_EPSIZE_ISO_HS_MAX / 4 : 256 / 4; + // - ptx_largest is limited to 64 words for FS since most FS core only has 256-320 words total + uint32_t nptx_largest; + uint32_t ptx_largest; + if (is_hs_phy) { + nptx_largest = TUSB_EPSIZE_BULK_HS / 4; + ptx_largest = TUSB_EPSIZE_ISO_HS_MAX / 4; + } else { + nptx_largest = TUSB_EPSIZE_BULK_FS / 4; + ptx_largest = 256 / 4; + } uint16_t nptxfsiz = 2 * nptx_largest; uint16_t rxfsiz = 2 * (ptx_largest + 2) + ghwcfg2.num_host_ch; -- cgit v1.3.1 From c96ff6b6d978bdcacc7cd49ad66ef00438cfb9f6 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 10 Apr 2026 16:52:15 +0700 Subject: add dwc2_clock_init() to have nrf54 initial sequence. currently stub for other ports. add board_uart_read() for nrf --- hw/bsp/nrf/family.c | 131 +++++++++++++++---------------- src/portable/synopsys/dwc2/dcd_dwc2.c | 4 +- src/portable/synopsys/dwc2/dwc2_at32.h | 6 ++ src/portable/synopsys/dwc2/dwc2_bcm.h | 6 ++ src/portable/synopsys/dwc2/dwc2_common.h | 16 ++-- src/portable/synopsys/dwc2/dwc2_efm32.h | 6 ++ src/portable/synopsys/dwc2/dwc2_esp32.h | 6 ++ src/portable/synopsys/dwc2/dwc2_gd32.h | 6 ++ src/portable/synopsys/dwc2/dwc2_nrf.h | 52 ++++++++++++ src/portable/synopsys/dwc2/dwc2_stm32.h | 6 ++ src/portable/synopsys/dwc2/dwc2_xmc.h | 6 ++ src/portable/synopsys/dwc2/hcd_dwc2.c | 4 +- 12 files changed, 172 insertions(+), 77 deletions(-) (limited to 'src/portable') diff --git a/hw/bsp/nrf/family.c b/hw/bsp/nrf/family.c index 10f0fc460..31a6bac9e 100644 --- a/hw/bsp/nrf/family.c +++ b/hw/bsp/nrf/family.c @@ -81,39 +81,67 @@ enum { // Forward USB interrupt events to TinyUSB IRQ Handler #if defined(NRF54H20_XXAA) || defined(NRF54LM20A_ENGA_XXAA) -#define USBD_IRQn USBHS_IRQn + #define USBD_IRQn USBHS_IRQn void USBHS_IRQHandler(void) { tusb_int_handler(0, true); } -#if defined(NRF54LM20A_ENGA_XXAA) + #if defined(NRF54LM20A_ENGA_XXAA) static nrfx_uarte_t _uart_id = NRFX_UARTE_INSTANCE(20); -#else + #else static nrfx_uarte_t _uart_id = NRFX_UARTE_INSTANCE(120); -#endif - -#else + #endif -#ifdef NRF5340_XXAA -#define LFCLK_SRC_RC CLOCK_LFCLKSRC_SRC_LFRC -#define VBUSDETECT_Msk USBREG_USBREGSTATUS_VBUSDETECT_Msk -#define OUTPUTRDY_Msk USBREG_USBREGSTATUS_OUTPUTRDY_Msk -#define GPIOTE_IRQn GPIOTE1_IRQn #else -#define LFCLK_SRC_RC CLOCK_LFCLKSRC_SRC_RC -#define VBUSDETECT_Msk POWER_USBREGSTATUS_VBUSDETECT_Msk -#define OUTPUTRDY_Msk POWER_USBREGSTATUS_OUTPUTRDY_Msk -#endif + #ifdef NRF5340_XXAA + #define LFCLK_SRC_RC CLOCK_LFCLKSRC_SRC_LFRC + #define VBUSDETECT_Msk USBREG_USBREGSTATUS_VBUSDETECT_Msk + #define OUTPUTRDY_Msk USBREG_USBREGSTATUS_OUTPUTRDY_Msk + #define GPIOTE_IRQn GPIOTE1_IRQn + #else + #define LFCLK_SRC_RC CLOCK_LFCLKSRC_SRC_RC + #define VBUSDETECT_Msk POWER_USBREGSTATUS_VBUSDETECT_Msk + #define OUTPUTRDY_Msk POWER_USBREGSTATUS_OUTPUTRDY_Msk + #endif -#if CFG_TUSB_OS != OPT_OS_ZEPHYR + #if CFG_TUSB_OS != OPT_OS_ZEPHYR static nrfx_uarte_t _uart_id = NRFX_UARTE_INSTANCE(0); -#endif + #endif void USBD_IRQHandler(void) { - tud_int_handler(0); + tusb_int_handler(0, true); } #endif +//--------------------------------------------------------------------+ +// UART RX ring buffer and event handler +//--------------------------------------------------------------------+ +#if CFG_TUSB_OS != OPT_OS_ZEPHYR + +#define UART_RX_BUFSIZE 64 + +static uint8_t rx_fifo[UART_RX_BUFSIZE]; +static volatile uint16_t rx_fifo_head = 0; +static volatile uint16_t rx_fifo_tail = 0; + +static uint8_t rx_dma_buf[1]; // 1-byte DMA target for continuous RX + +static void uart_event_handler(nrfx_uarte_event_t const* p_event, void* p_context) { + (void) p_context; + if (p_event->type == NRFX_UARTE_EVT_RX_DONE) { + for (size_t i = 0; i < p_event->data.rx.length; i++) { + uint16_t next_head = (rx_fifo_head + 1) & (UART_RX_BUFSIZE - 1); + if (next_head != rx_fifo_tail) { + rx_fifo[rx_fifo_head] = p_event->data.rx.p_buffer[i]; + rx_fifo_head = next_head; + } + } + // re-arm 1-byte RX + nrfx_uarte_rx(&_uart_id, rx_dma_buf, sizeof(rx_dma_buf)); + } +} + +#endif // tinyusb function that handles power event (detected, ready, removed) // We must call it within SD's SOC event handler, or set it as power event handler if SD is not enabled. @@ -136,7 +164,6 @@ static nrfx_gpiote_t _gpiote = NRFX_GPIOTE_INSTANCE(0); //--------------------------------------------------------------------+ // //--------------------------------------------------------------------+ - void board_init(void) { #if !defined(NRF54H20_XXAA) && !defined(NRF54LM20A_ENGA_XXAA) // stop LF clock just in case we jump from application without reset @@ -172,12 +199,14 @@ void board_init(void) { #if CFG_TUSB_OS != OPT_OS_ZEPHYR // UART + static uint8_t uart_tx_cache[64]; nrfx_uarte_config_t uart_cfg = { .txd_pin = UART_TX_PIN, .rxd_pin = UART_RX_PIN, .rts_pin = NRF_UARTE_PSEL_DISCONNECTED, .cts_pin = NRF_UARTE_PSEL_DISCONNECTED, .p_context = NULL, + .tx_cache = { .p_buffer = uart_tx_cache, .length = sizeof(uart_tx_cache) }, .baudrate = NRF_UARTE_BAUDRATE_115200, // CFG_BOARD_UART_BAUDRATE .interrupt_priority = 7, .config = { @@ -186,63 +215,21 @@ void board_init(void) { } }; - nrfx_uarte_init(&_uart_id, &uart_cfg, NULL); + nrfx_uarte_init(&_uart_id, &uart_cfg, uart_event_handler); + // start continuous 1-byte RX + nrfx_uarte_rx(&_uart_id, rx_dma_buf, sizeof(rx_dma_buf)); #endif //------------- USB -------------// #if CFG_TUD_ENABLED #if defined(NRF54LM20A_ENGA_XXAA) - // Start the USB voltage regulator - NRF_VREGUSB->TASKS_START = VREGUSB_TASKS_START_TASKS_START_Trigger; - // Request HFXO crystal clock for PCLK24M (required by USBHS core) NRF_CLOCK->TASKS_XO24MSTART = CLOCK_TASKS_XO24MSTART_TASKS_XO24MSTART_Trigger; while (!NRF_CLOCK->EVENTS_XO24MSTARTED) {} NRF_CLOCK->EVENTS_XO24MSTARTED = 0; #endif -#if defined(NRF54H20_XXAA) - // Enable the USBHS wrapper (core + PHY) before any DWC2 register access - NRF_USBHS->ENABLE = (USBHS_ENABLE_PHY_Enabled << USBHS_ENABLE_PHY_Pos) | - (USBHS_ENABLE_CORE_Enabled << USBHS_ENABLE_CORE_Pos); - NRF_USBHS->TASKS_START = USBHS_TASKS_START_TASKS_START_Trigger; - // Brief delay for PHY PLL lock and core power-up - for (volatile int i = 0; i < 1000; i++) {} -#endif - -#if defined(NRF54LM20A_ENGA_XXAA) - // Based on Zephyr usbhs_enable_core() in drivers/usb/udc/udc_dwc2_vendor_quirks.h - // Step 1: Power up core only (PHY not yet) - NRF_USBHS->ENABLE = USBHS_ENABLE_CORE_Msk; - - // Step 2: Override ID=Device (bit 31), and temporarily override VBUSVALID - NRF_USBHS->PHY.OVERRIDEVALUES = (USBHS_PHY_OVERRIDEVALUES_ID_Device << USBHS_PHY_OVERRIDEVALUES_ID_Pos); - NRF_USBHS->PHY.INPUTOVERRIDE = USBHS_PHY_INPUTOVERRIDE_ID_Msk | USBHS_PHY_INPUTOVERRIDE_VBUSVALID_Msk; - - // Step 3: Release PHY power-on reset by enabling PHY - NRF_USBHS->ENABLE = USBHS_ENABLE_PHY_Msk | USBHS_ENABLE_CORE_Msk; - - // Step 4: Wait 45us for PHY clock to start - NRFX_DELAY_US(45); - - // Step 5: Release DWC2 reset - NRF_USBHS->TASKS_START = USBHS_TASKS_START_TASKS_START_Trigger; - - // Step 6: Wait for clock to start to avoid hang on too early register read - NRFX_DELAY_US(2); - - // Step 7: Clear VBUSVALID override (keep ID=Device override) - // DWC2 is now in Non-Driving opmode; D+ pull-up will activate when DWC2 clears DCTL SftDiscon - NRF_USBHS->PHY.INPUTOVERRIDE = USBHS_PHY_INPUTOVERRIDE_ID_Msk; - - // Barrier: USBHS wrapper (0x5005A000) and USBHSCORE (0x50020000) are separate - // peripheral blocks. Ensure the ENABLE/TASKS_START writes have propagated from - // the Cortex-M33 write buffer to hardware before anyone reads DWC2 core regs. - __DSB(); - -#endif - // Priorities 0, 1, 4 (nRF52) are reserved for SoftDevice // 2 is highest for application NVIC_SetPriority(USBD_IRQn, 2); @@ -329,11 +316,18 @@ size_t board_get_unique_id(uint8_t id[], size_t max_len) { } int board_uart_read(uint8_t* buf, int len) { +#if CFG_TUSB_OS == OPT_OS_ZEPHYR (void) buf; (void) len; return -1; -// nrfx_err_t err = nrfx_uarte_rx(&_uart_id, buf, (size_t) len); -// return NRFX_SUCCESS == err ? len : 0; +#else + int count = 0; + while (count < len && rx_fifo_tail != rx_fifo_head) { + buf[count++] = rx_fifo[rx_fifo_tail]; + rx_fifo_tail = (rx_fifo_tail + 1) & (UART_RX_BUFSIZE - 1); + } + return count; +#endif } int board_uart_write(void const* buf, int len) { @@ -341,7 +335,10 @@ int board_uart_write(void const* buf, int len) { (void) buf; return len; #else - nrfx_err_t err = nrfx_uarte_tx(&_uart_id, (uint8_t const*) buf, (size_t) len ,0); + if (nrfx_uarte_tx_in_progress(&_uart_id)) { + return 0; + } + nrfx_err_t err = nrfx_uarte_tx(&_uart_id, (uint8_t const*) buf, (size_t) len, 0); return (NRFX_SUCCESS == err) ? len : 0; #endif } diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index bdd3a59ed..da6ee894a 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -442,12 +442,12 @@ bool dcd_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param) { } bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { - (void) rh_init; - dwc2_regs_t* dwc2 = DWC2_REG(rhport); + dwc2_clock_init(rhport, rh_init->role); tu_memclr(&_dcd_data, sizeof(_dcd_data)); // Core Initialization + dwc2_regs_t* dwc2 = DWC2_REG(rhport); const bool is_hs_phy = dwc2_core_is_highspeed_phy(dwc2, TUD_OPT_HIGH_SPEED); const bool is_dma = dma_device_enabled(dwc2); TU_ASSERT(dwc2_core_init(rhport, is_hs_phy, is_dma)); diff --git a/src/portable/synopsys/dwc2/dwc2_at32.h b/src/portable/synopsys/dwc2/dwc2_at32.h index 594d350b7..85fa9b20b 100644 --- a/src/portable/synopsys/dwc2/dwc2_at32.h +++ b/src/portable/synopsys/dwc2/dwc2_at32.h @@ -79,6 +79,12 @@ static const dwc2_controller_t _dwc2_controller[] = { #endif }; +// MCU specific to enable dwc2 clock/power before any access to register +TU_ATTR_ALWAYS_INLINE static inline void dwc2_clock_init(uint8_t rhport, tusb_role_t role) { + (void) rhport; + (void) role; +} + 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; diff --git a/src/portable/synopsys/dwc2/dwc2_bcm.h b/src/portable/synopsys/dwc2/dwc2_bcm.h index 50f3122e8..91cae821e 100644 --- a/src/portable/synopsys/dwc2/dwc2_bcm.h +++ b/src/portable/synopsys/dwc2/dwc2_bcm.h @@ -46,6 +46,12 @@ static const dwc2_controller_t _dwc2_controller[] = #define dcache_invalidate(_addr, _size) data_invalidate(_addr, _size) #define dcache_clean_invalidate(_addr, _size) data_clean_and_invalidate(_addr, _size) +// MCU specific to enable dwc2 clock/power before any access to register +TU_ATTR_ALWAYS_INLINE static inline void dwc2_clock_init(uint8_t rhport, tusb_role_t role) { + (void) rhport; + (void) role; +} + TU_ATTR_ALWAYS_INLINE static inline void dwc2_dcd_int_enable(uint8_t rhport) { diff --git a/src/portable/synopsys/dwc2/dwc2_common.h b/src/portable/synopsys/dwc2/dwc2_common.h index 9f28ab2e0..5c4798d21 100644 --- a/src/portable/synopsys/dwc2/dwc2_common.h +++ b/src/portable/synopsys/dwc2/dwc2_common.h @@ -38,13 +38,15 @@ #include "host/hcd.h" #endif -// Following symbols must be defined by port header -// - _dwc2_controller[]: array of controllers -// - DWC2_EP_MAX: largest EP counts of all controllers -// - dwc2_phy_init/dwc2_phy_update: phy init called before and after core reset -// - dwc2_phy_deinit(dwc2, hs_phy_type): phy deinit to disable PHY power, only deinit the phy used by core -// - dwc2_dcd_int_enable/dwc2_dcd_int_disable -// - dwc2_remote_wakeup_delay +/* Following symbols must be defined by port header + - _dwc2_controller[]: array of controllers + - DWC2_EP_MAX: largest EP counts of all controllers + - dwc2_clock_init(): clock init call before + - dwc2_phy_init/dwc2_phy_update: phy init called before and after core reset + - dwc2_phy_deinit(dwc2, hs_phy_type): phy deinit to disable PHY power, only deinit the phy used by core + - dwc2_dcd_int_enable/dwc2_dcd_int_disable + - dwc2_remote_wakeup_delay +*/ #if defined(TUP_USBIP_DWC2_STM32) #include "dwc2_stm32.h" diff --git a/src/portable/synopsys/dwc2/dwc2_efm32.h b/src/portable/synopsys/dwc2/dwc2_efm32.h index 167f5b4cd..063360873 100644 --- a/src/portable/synopsys/dwc2/dwc2_efm32.h +++ b/src/portable/synopsys/dwc2/dwc2_efm32.h @@ -43,6 +43,12 @@ static const dwc2_controller_t _dwc2_controller[] = { .reg_base = DWC2_REG_BASE, .irqnum = USB_IRQn, .ep_count = DWC2_EP_MAX, .otg_dfifo_depth = 512 } }; +// MCU specific to enable dwc2 clock/power before any access to register +TU_ATTR_ALWAYS_INLINE static inline void dwc2_clock_init(uint8_t rhport, tusb_role_t role) { + (void) rhport; + (void) role; +} + TU_ATTR_ALWAYS_INLINE static inline void dwc2_dcd_int_enable(uint8_t rhport) { diff --git a/src/portable/synopsys/dwc2/dwc2_esp32.h b/src/portable/synopsys/dwc2/dwc2_esp32.h index 99ef9456f..6a10dc7f8 100644 --- a/src/portable/synopsys/dwc2/dwc2_esp32.h +++ b/src/portable/synopsys/dwc2/dwc2_esp32.h @@ -97,6 +97,12 @@ static void dwc2_int_handler_wrap(void* arg) { #endif } +// MCU specific to enable dwc2 clock/power before any access to register +TU_ATTR_ALWAYS_INLINE static inline void dwc2_clock_init(uint8_t rhport, tusb_role_t role) { + (void) rhport; + (void) role; +} + TU_ATTR_ALWAYS_INLINE static inline void dwc2_int_set(uint8_t rhport, tusb_role_t role, bool enabled) { if (enabled) { esp_intr_alloc(_dwc2_controller[rhport].irqnum, ESP_INTR_FLAG_LOWMED, diff --git a/src/portable/synopsys/dwc2/dwc2_gd32.h b/src/portable/synopsys/dwc2/dwc2_gd32.h index 396d17e30..28c3fde5e 100644 --- a/src/portable/synopsys/dwc2/dwc2_gd32.h +++ b/src/portable/synopsys/dwc2/dwc2_gd32.h @@ -57,6 +57,12 @@ static inline void __eclic_disable_interrupt (uint32_t irq){ *(volatile uint8_t*)(ECLIC_INTERRUPT_ENABLE_BASE + (irq * 4)) = 0; } +// MCU specific to enable dwc2 clock/power before any access to register +TU_ATTR_ALWAYS_INLINE static inline void dwc2_clock_init(uint8_t rhport, tusb_role_t role) { + (void) rhport; + (void) role; +} + TU_ATTR_ALWAYS_INLINE static inline void dwc2_dcd_int_enable(uint8_t rhport) { diff --git a/src/portable/synopsys/dwc2/dwc2_nrf.h b/src/portable/synopsys/dwc2/dwc2_nrf.h index fc9cd18bc..a1bf692f8 100644 --- a/src/portable/synopsys/dwc2/dwc2_nrf.h +++ b/src/portable/synopsys/dwc2/dwc2_nrf.h @@ -29,8 +29,20 @@ #ifndef TUSB_DWC2_NRF_H #define TUSB_DWC2_NRF_H +// NRF is device only without OTG support #include "nrf.h" +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-align" +#endif + +#include + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + #define DWC2_EP_MAX 16 // Use the auto-resolving peripheral pointer (respects TrustZone secure/non-secure mapping) @@ -44,6 +56,46 @@ static const dwc2_controller_t _dwc2_controller[] = { {.reg_base = DWC2_REG_BASE, .irqnum = USBHS_IRQn, .ep_count = 16, .otg_dfifo_depth = 3072}, }; +// MCU specific to enable dwc2 clock/power before any access to register +TU_ATTR_ALWAYS_INLINE static inline void dwc2_clock_init(uint8_t rhport, tusb_role_t role) { + (void) rhport; + (void) role; + + #if defined(NRF54LM20A_ENGA_XXAA) + // Start the USB voltage regulator + NRF_VREGUSB->TASKS_START = VREGUSB_TASKS_START_TASKS_START_Trigger; + + // Based on Zephyr usbhs_enable_core() in drivers/usb/udc/udc_dwc2_vendor_quirks.h + // Step 1: Power up core only (PHY not yet) + NRF_USBHS->ENABLE = USBHS_ENABLE_CORE_Msk; + + // Step 2: Override ID=Device (bit 31), and temporarily override VBUSVALID + NRF_USBHS->PHY.OVERRIDEVALUES = (USBHS_PHY_OVERRIDEVALUES_ID_Device << USBHS_PHY_OVERRIDEVALUES_ID_Pos); + NRF_USBHS->PHY.INPUTOVERRIDE = USBHS_PHY_INPUTOVERRIDE_ID_Msk | USBHS_PHY_INPUTOVERRIDE_VBUSVALID_Msk; + + // Step 3: Release PHY power-on reset by enabling PHY + NRF_USBHS->ENABLE = USBHS_ENABLE_PHY_Msk | USBHS_ENABLE_CORE_Msk; + + // Step 4: Wait 45us for PHY clock to start + nrfx_coredep_delay_us(45); + + // Step 5: Release DWC2 reset + NRF_USBHS->TASKS_START = USBHS_TASKS_START_TASKS_START_Trigger; + + // Step 6: Wait for clock to start to avoid hang on too early register read + nrfx_coredep_delay_us(2); + + // Step 7: Clear VBUSVALID override (keep ID=Device override) + // DWC2 is now in Non-Driving opmode; D+ pull-up will activate when DWC2 clears DCTL SftDiscon + NRF_USBHS->PHY.INPUTOVERRIDE = USBHS_PHY_INPUTOVERRIDE_ID_Msk; + + // Barrier: USBHS wrapper (0x5005A000) and USBHSCORE (0x50020000) are separate + // peripheral blocks. Ensure the ENABLE/TASKS_START writes have propagated from + // the Cortex-M33 write buffer to hardware before anyone reads DWC2 core regs. + __DSB(); + #endif +} + TU_ATTR_ALWAYS_INLINE static inline void dwc2_int_set(uint8_t rhport, tusb_role_t role, bool enabled) { (void)rhport; (void)role; diff --git a/src/portable/synopsys/dwc2/dwc2_stm32.h b/src/portable/synopsys/dwc2/dwc2_stm32.h index 5f6e98224..e5379dfe3 100644 --- a/src/portable/synopsys/dwc2/dwc2_stm32.h +++ b/src/portable/synopsys/dwc2/dwc2_stm32.h @@ -162,6 +162,12 @@ static const dwc2_controller_t _dwc2_controller[] = { // SystemCoreClock is already included by family header // extern uint32_t SystemCoreClock; +// MCU specific to enable dwc2 clock/power before any access to register +TU_ATTR_ALWAYS_INLINE static inline void dwc2_clock_init(uint8_t rhport, tusb_role_t role) { + (void) rhport; + (void) role; +} + 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; diff --git a/src/portable/synopsys/dwc2/dwc2_xmc.h b/src/portable/synopsys/dwc2/dwc2_xmc.h index b946444ee..85b2a2633 100644 --- a/src/portable/synopsys/dwc2/dwc2_xmc.h +++ b/src/portable/synopsys/dwc2/dwc2_xmc.h @@ -42,6 +42,12 @@ static const dwc2_controller_t _dwc2_controller[] = { .reg_base = USB0_BASE, .irqnum = USB0_0_IRQn, .ep_count = DWC2_EP_MAX, .otg_dfifo_depth = 512 } }; +// MCU specific to enable dwc2 clock/power before any access to register +TU_ATTR_ALWAYS_INLINE static inline void dwc2_clock_init(uint8_t rhport, tusb_role_t role) { + (void) rhport; + (void) role; +} + TU_ATTR_ALWAYS_INLINE static inline void dwc2_dcd_int_enable(uint8_t rhport) { diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index cd2ddf572..6098d6eaa 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -407,10 +407,12 @@ bool hcd_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param) { // Initialize controller to host mode bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { - dwc2_regs_t* dwc2 = DWC2_REG(rhport); + dwc2_clock_init(rhport, rh_init->role); + tu_memclr(&_hcd_data, sizeof(_hcd_data)); // Core Initialization + dwc2_regs_t* dwc2 = DWC2_REG(rhport); const bool is_hs_phy = dwc2_core_is_highspeed_phy(dwc2, _tuh_cfg.use_hs_phy); const bool is_dma = dma_host_enabled(dwc2); TU_ASSERT(dwc2_core_init(rhport, is_hs_phy, is_dma)); -- cgit v1.3.1 From 048bb5ca690311a24cae69fd177bd2f4721f27b6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 10 Apr 2026 10:53:03 +0000 Subject: Make fsdev errata delay helper static inline Agent-Logs-Url: https://github.com/hathach/tinyusb/sessions/8588a09c-d4e5-4284-8944-47ae4e2a2a1f Co-authored-by: HiFiPhile <4375114+HiFiPhile@users.noreply.github.com> --- src/portable/st/stm32_fsdev/fsdev_common.c | 17 ----------------- src/portable/st/stm32_fsdev/fsdev_common.h | 12 +++++++++++- 2 files changed, 11 insertions(+), 18 deletions(-) (limited to 'src/portable') diff --git a/src/portable/st/stm32_fsdev/fsdev_common.c b/src/portable/st/stm32_fsdev/fsdev_common.c index e6c95e12d..003bcd069 100644 --- a/src/portable/st/stm32_fsdev/fsdev_common.c +++ b/src/portable/st/stm32_fsdev/fsdev_common.c @@ -113,21 +113,4 @@ void btable_set_rx_bufsize(uint32_t ep_id, uint8_t buf_id, uint16_t wCount) { #endif } -/* STM32 FSDEV PMA Buffer Description Table errata workaround: - * - ES0561 (STM32H503), ES0587 (STM32U535/U545) - * - CTR may trigger before final PMA SRAM accesses complete on OUT transfers. - * - Insert delay before reading PMA count/data. - */ -void fsdev_btable_workaround_delay(bool low_speed) { -#if defined(TUP_USBIP_FSDEV_STM32) && defined(CFG_TUSB_FSDEV_32BIT) - uint32_t cycle_count = low_speed ? CFG_TUSB_FSDEV_BTABLE_LS_DELAY_COUNT : CFG_TUSB_FSDEV_BTABLE_FS_DELAY_COUNT; - volatile uint32_t delay_count = cycle_count; - while (delay_count > 0U) { - delay_count--; - } -#else - (void) low_speed; -#endif -} - #endif diff --git a/src/portable/st/stm32_fsdev/fsdev_common.h b/src/portable/st/stm32_fsdev/fsdev_common.h index ab07ca0e9..f5cfa93c8 100644 --- a/src/portable/st/stm32_fsdev/fsdev_common.h +++ b/src/portable/st/stm32_fsdev/fsdev_common.h @@ -469,7 +469,17 @@ void btable_set_rx_bufsize(uint32_t ep_id, uint8_t buf_id, uint16_t wCount); // Delay helper for STM32 FSDEV PMA Buffer Description Table errata (ES0561/ES0587). // Low-speed path uses CFG_TUSB_FSDEV_BTABLE_LS_DELAY_COUNT, otherwise full-speed count. -void fsdev_btable_workaround_delay(bool low_speed); +TU_ATTR_ALWAYS_INLINE static inline void fsdev_btable_workaround_delay(bool low_speed) { +#if defined(TUP_USBIP_FSDEV_STM32) && defined(CFG_TUSB_FSDEV_32BIT) + uint32_t cycle_count = low_speed ? CFG_TUSB_FSDEV_BTABLE_LS_DELAY_COUNT : CFG_TUSB_FSDEV_BTABLE_FS_DELAY_COUNT; + volatile uint32_t delay_count = cycle_count; + while (delay_count > 0U) { + delay_count--; + } +#else + (void) low_speed; +#endif +} #ifdef __cplusplus } -- cgit v1.3.1 From 54e1973906c6152ffd5d650d4f8fb146b4fa9068 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 10 Apr 2026 10:53:41 +0000 Subject: Restore errata context comment on inline delay helper Agent-Logs-Url: https://github.com/hathach/tinyusb/sessions/8588a09c-d4e5-4284-8944-47ae4e2a2a1f Co-authored-by: HiFiPhile <4375114+HiFiPhile@users.noreply.github.com> --- src/portable/st/stm32_fsdev/fsdev_common.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'src/portable') diff --git a/src/portable/st/stm32_fsdev/fsdev_common.h b/src/portable/st/stm32_fsdev/fsdev_common.h index f5cfa93c8..95854d63d 100644 --- a/src/portable/st/stm32_fsdev/fsdev_common.h +++ b/src/portable/st/stm32_fsdev/fsdev_common.h @@ -467,8 +467,13 @@ uint16_t pma_align_buffer_size(uint16_t size, uint8_t *blsize, uint8_t *num_bloc // Set RX buffer size void btable_set_rx_bufsize(uint32_t ep_id, uint8_t buf_id, uint16_t wCount); -// Delay helper for STM32 FSDEV PMA Buffer Description Table errata (ES0561/ES0587). -// Low-speed path uses CFG_TUSB_FSDEV_BTABLE_LS_DELAY_COUNT, otherwise full-speed count. +/* STM32 FSDEV PMA Buffer Description Table errata workaround: + * - ES0561 (STM32H503), ES0587 (STM32U535/U545) + * - CTR may trigger before final PMA SRAM accesses complete on OUT transfers. + * - Insert delay before reading PMA count/data. + * + * Low-speed path uses CFG_TUSB_FSDEV_BTABLE_LS_DELAY_COUNT, otherwise full-speed count. + */ TU_ATTR_ALWAYS_INLINE static inline void fsdev_btable_workaround_delay(bool low_speed) { #if defined(TUP_USBIP_FSDEV_STM32) && defined(CFG_TUSB_FSDEV_32BIT) uint32_t cycle_count = low_speed ? CFG_TUSB_FSDEV_BTABLE_LS_DELAY_COUNT : CFG_TUSB_FSDEV_BTABLE_FS_DELAY_COUNT; -- cgit v1.3.1 From 37ace45508fb32568e78ba3410d708db359a46d4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 10 Apr 2026 11:11:31 +0000 Subject: Allow STM32 FSDEV delay override macros to satisfy 32-bit guard Agent-Logs-Url: https://github.com/hathach/tinyusb/sessions/b35badc2-444a-4329-b136-f314591cf693 Co-authored-by: HiFiPhile <4375114+HiFiPhile@users.noreply.github.com> --- src/portable/st/stm32_fsdev/fsdev_stm32.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/portable') diff --git a/src/portable/st/stm32_fsdev/fsdev_stm32.h b/src/portable/st/stm32_fsdev/fsdev_stm32.h index 5e383eb97..d2a7a6caa 100644 --- a/src/portable/st/stm32_fsdev/fsdev_stm32.h +++ b/src/portable/st/stm32_fsdev/fsdev_stm32.h @@ -152,8 +152,9 @@ #define FSDEV_STM32_CPU_MHZ 64U #elif CFG_TUSB_MCU == OPT_MCU_STM32C0 #define FSDEV_STM32_CPU_MHZ 48U - #elif defined(CFG_TUSB_FSDEV_32BIT) - #error "FSDEV_STM32_CPU_MHZ not defined for this STM32 MCU" + #elif defined(CFG_TUSB_FSDEV_32BIT) && \ + (!defined(CFG_TUSB_FSDEV_BTABLE_FS_DELAY_COUNT) || !defined(CFG_TUSB_FSDEV_BTABLE_LS_DELAY_COUNT)) + #error "Define FSDEV_STM32_CPU_MHZ or both CFG_TUSB_FSDEV_BTABLE_{FS,LS}_DELAY_COUNT for this STM32 MCU" #endif #endif -- cgit v1.3.1 From 35045e0346f64fe3b19e94c8e9c8d2eb908fc5d6 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 10 Apr 2026 13:33:13 +0200 Subject: debloat the workaround Signed-off-by: HiFiPhile --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 2 +- src/portable/st/stm32_fsdev/fsdev_common.h | 37 ----------------- src/portable/st/stm32_fsdev/fsdev_stm32.h | 60 ++++++++++++++++++--------- src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c | 6 +-- 4 files changed, 42 insertions(+), 63 deletions(-) (limited to 'src/portable') diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index c8bb0e827..3ef0819bd 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -393,7 +393,7 @@ void dcd_int_handler(uint8_t rhport) { const uint32_t ep_reg = ep_read(ep_id); if (ep_reg & U_EP_CTR_RX) { - #ifdef CFG_TUSB_FSDEV_32BIT + #if defined(TUP_USBIP_FSDEV_STM32) && defined(CFG_TUSB_FSDEV_32BIT) fsdev_btable_workaround_delay(false); #endif diff --git a/src/portable/st/stm32_fsdev/fsdev_common.h b/src/portable/st/stm32_fsdev/fsdev_common.h index 95854d63d..140ff1d61 100644 --- a/src/portable/st/stm32_fsdev/fsdev_common.h +++ b/src/portable/st/stm32_fsdev/fsdev_common.h @@ -307,24 +307,6 @@ typedef struct { #error "Unknown USB IP" #endif -#if defined(TUP_USBIP_FSDEV_STM32) && defined(CFG_TUSB_FSDEV_32BIT) - #ifndef CFG_TUSB_FSDEV_BTABLE_FS_DELAY_COUNT - #if defined(FSDEV_STM32_CPU_MHZ) - #define CFG_TUSB_FSDEV_BTABLE_FS_DELAY_COUNT (FSDEV_STM32_CPU_MHZ / 4U) - #else - #error "Define CFG_TUSB_FSDEV_BTABLE_FS_DELAY_COUNT or FSDEV_STM32_CPU_MHZ for STM32 FSDEV 32-bit" - #endif - #endif - - #ifndef CFG_TUSB_FSDEV_BTABLE_LS_DELAY_COUNT - #if defined(FSDEV_STM32_CPU_MHZ) - #define CFG_TUSB_FSDEV_BTABLE_LS_DELAY_COUNT (FSDEV_STM32_CPU_MHZ * 2U) - #else - #error "Define CFG_TUSB_FSDEV_BTABLE_LS_DELAY_COUNT or FSDEV_STM32_CPU_MHZ for STM32 FSDEV 32-bit" - #endif - #endif -#endif - //--------------------------------------------------------------------+ // Endpoint Helper // - CTR is write 0 to clear @@ -467,25 +449,6 @@ uint16_t pma_align_buffer_size(uint16_t size, uint8_t *blsize, uint8_t *num_bloc // Set RX buffer size void btable_set_rx_bufsize(uint32_t ep_id, uint8_t buf_id, uint16_t wCount); -/* STM32 FSDEV PMA Buffer Description Table errata workaround: - * - ES0561 (STM32H503), ES0587 (STM32U535/U545) - * - CTR may trigger before final PMA SRAM accesses complete on OUT transfers. - * - Insert delay before reading PMA count/data. - * - * Low-speed path uses CFG_TUSB_FSDEV_BTABLE_LS_DELAY_COUNT, otherwise full-speed count. - */ -TU_ATTR_ALWAYS_INLINE static inline void fsdev_btable_workaround_delay(bool low_speed) { -#if defined(TUP_USBIP_FSDEV_STM32) && defined(CFG_TUSB_FSDEV_32BIT) - uint32_t cycle_count = low_speed ? CFG_TUSB_FSDEV_BTABLE_LS_DELAY_COUNT : CFG_TUSB_FSDEV_BTABLE_FS_DELAY_COUNT; - volatile uint32_t delay_count = cycle_count; - while (delay_count > 0U) { - delay_count--; - } -#else - (void) low_speed; -#endif -} - #ifdef __cplusplus } #endif diff --git a/src/portable/st/stm32_fsdev/fsdev_stm32.h b/src/portable/st/stm32_fsdev/fsdev_stm32.h index d2a7a6caa..79052b489 100644 --- a/src/portable/st/stm32_fsdev/fsdev_stm32.h +++ b/src/portable/st/stm32_fsdev/fsdev_stm32.h @@ -138,26 +138,6 @@ #error "FSDEV_HAS_SBUF_ISO not defined" #endif -#ifndef FSDEV_STM32_CPU_MHZ - // Max CPU frequency in MHz, used to derive conservative FSDEV PMA delay defaults. - #if CFG_TUSB_MCU == OPT_MCU_STM32H5 - #define FSDEV_STM32_CPU_MHZ 250U - #elif CFG_TUSB_MCU == OPT_MCU_STM32U5 - #define FSDEV_STM32_CPU_MHZ 160U - #elif CFG_TUSB_MCU == OPT_MCU_STM32U3 - #define FSDEV_STM32_CPU_MHZ 96U - #elif CFG_TUSB_MCU == OPT_MCU_STM32U0 - #define FSDEV_STM32_CPU_MHZ 56U - #elif CFG_TUSB_MCU == OPT_MCU_STM32G0 - #define FSDEV_STM32_CPU_MHZ 64U - #elif CFG_TUSB_MCU == OPT_MCU_STM32C0 - #define FSDEV_STM32_CPU_MHZ 48U - #elif defined(CFG_TUSB_FSDEV_32BIT) && \ - (!defined(CFG_TUSB_FSDEV_BTABLE_FS_DELAY_COUNT) || !defined(CFG_TUSB_FSDEV_BTABLE_LS_DELAY_COUNT)) - #error "Define FSDEV_STM32_CPU_MHZ or both CFG_TUSB_FSDEV_BTABLE_{FS,LS}_DELAY_COUNT for this STM32 MCU" - #endif -#endif - #ifndef CFG_TUD_FSDEV_DOUBLE_BUFFERED_ISO_EP // Default configuration for double-buffered isochronous endpoints: // - Enable double buffering on devices with >1KB Packet Memory Area (PMA) @@ -271,6 +251,46 @@ TU_ATTR_ALWAYS_INLINE static inline void fsdev_int_disable(uint8_t rhport) { // CMSIS has a membar after disabling interrupts } +//--------------------------------------------------------------------+ +// STM32 FSDEV PMA Buffer Description Table errata workaround +//--------------------------------------------------------------------+ + +#ifdef CFG_TUSB_FSDEV_32BIT +// ES0561 (STM32H503), ES0587 (STM32U535/U545) +// CTR may trigger before final PMA SRAM accesses complete on OUT transfers. +// Insert delay before reading PMA count/data. +// Max CPU frequency in MHz, used to derive conservative FSDEV PMA delay defaults. +#if CFG_TUSB_MCU == OPT_MCU_STM32H5 + #define FSDEV_STM32_CPU_MHZ 250U +#elif CFG_TUSB_MCU == OPT_MCU_STM32U5 + #define FSDEV_STM32_CPU_MHZ 160U +#elif CFG_TUSB_MCU == OPT_MCU_STM32U3 + #define FSDEV_STM32_CPU_MHZ 96U +#elif CFG_TUSB_MCU == OPT_MCU_STM32U0 + #define FSDEV_STM32_CPU_MHZ 56U +#elif CFG_TUSB_MCU == OPT_MCU_STM32G0 + #define FSDEV_STM32_CPU_MHZ 64U +#elif CFG_TUSB_MCU == OPT_MCU_STM32C0 + #define FSDEV_STM32_CPU_MHZ 48U +#endif + +#ifndef CFG_TUSB_FSDEV_BTABLE_FS_DELAY_COUNT + #define CFG_TUSB_FSDEV_BTABLE_FS_DELAY_COUNT (FSDEV_STM32_CPU_MHZ / 4U) +#endif + +#ifndef CFG_TUSB_FSDEV_BTABLE_LS_DELAY_COUNT + #define CFG_TUSB_FSDEV_BTABLE_LS_DELAY_COUNT (FSDEV_STM32_CPU_MHZ * 2U) +#endif + +TU_ATTR_ALWAYS_INLINE static inline void fsdev_btable_workaround_delay(bool low_speed) { + uint32_t cycle_count = low_speed ? CFG_TUSB_FSDEV_BTABLE_LS_DELAY_COUNT : CFG_TUSB_FSDEV_BTABLE_FS_DELAY_COUNT; + volatile uint32_t delay_count = cycle_count; + while (delay_count > 0U) { + delay_count--; + } +} +#endif + //--------------------------------------------------------------------+ // Connect / Disconnect //--------------------------------------------------------------------+ diff --git a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c index 18cf302d8..f9201651a 100644 --- a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c @@ -197,11 +197,7 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { // If DCON_STAT is already set, the controller sometimes misses the initial connection interrupt if (FSDEV_REG->ISTR & U_ISTR_DCON_STAT) { - // Wait DP/DM stabilize time - volatile uint32_t cycle_count = FSDEV_STM32_CPU_MHZ / 4U; - while (cycle_count > 0U) { - cycle_count--; - } + tusb_time_delay_ms_api(2); port_status_handler(rhport, false); } -- cgit v1.3.1 From de59d95c325e9776d344e7e6272bd79335184ae2 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 10 Apr 2026 21:14:01 +0700 Subject: fix DWC2 FIFO depth values for STM32 families --- src/portable/synopsys/dwc2/dwc2_stm32.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/portable') diff --git a/src/portable/synopsys/dwc2/dwc2_stm32.h b/src/portable/synopsys/dwc2/dwc2_stm32.h index e5379dfe3..126632fec 100644 --- a/src/portable/synopsys/dwc2/dwc2_stm32.h +++ b/src/portable/synopsys/dwc2/dwc2_stm32.h @@ -110,11 +110,11 @@ extern "C" { #ifdef USB_OTG_FS #define USB_OTG_FS_PERIPH_BASE USB_OTG_FS_BASE #define EP_MAX_FS 6 - #define DFIFO_DEPTH_FS 1280 + #define DFIFO_DEPTH_FS 320 #else #define USB_OTG_HS_PERIPH_BASE USB_OTG_HS_BASE #define EP_MAX_HS 9 - #define DFIFO_DEPTH_HS 4096 + #define DFIFO_DEPTH_HS 1024 #endif #elif CFG_TUSB_MCU == OPT_MCU_STM32WBA @@ -131,7 +131,7 @@ extern "C" { #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 DFIFO_DEPTH_HS 4096 + #define DFIFO_DEPTH_HS 1024 #else #error "Unsupported MCUs" #endif -- cgit v1.3.1 From b2b498f17e403b006943ca15d9884b4f596eacfb Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 10 Apr 2026 21:17:46 +0700 Subject: clean up --- hw/bsp/nrf/boards/nrf54lm20dk/board.cmake | 3 --- src/portable/synopsys/dwc2/dwc2_info.md | 2 +- src/portable/synopsys/dwc2/dwc2_info.py | 2 +- 3 files changed, 2 insertions(+), 5 deletions(-) (limited to 'src/portable') diff --git a/hw/bsp/nrf/boards/nrf54lm20dk/board.cmake b/hw/bsp/nrf/boards/nrf54lm20dk/board.cmake index fb0ccdfdf..8c2b83346 100644 --- a/hw/bsp/nrf/boards/nrf54lm20dk/board.cmake +++ b/hw/bsp/nrf/boards/nrf54lm20dk/board.cmake @@ -5,7 +5,4 @@ function(update_board TARGET) target_compile_definitions(${TARGET} PUBLIC CFG_EXAMPLE_VIDEO_READONLY ) - target_sources(${TARGET} PRIVATE -# ${NRFX_PATH}/drivers/src/nrfx_usbreg.c - ) endfunction() diff --git a/src/portable/synopsys/dwc2/dwc2_info.md b/src/portable/synopsys/dwc2/dwc2_info.md index 051c3ab1f..205684e4b 100644 --- a/src/portable/synopsys/dwc2/dwc2_info.md +++ b/src/portable/synopsys/dwc2/dwc2_info.md @@ -1,4 +1,4 @@ -| | AT32 F405 FS | AT32 F405 HS | AT32 F415 | BCM2711 (Pi4) | EFM32GG | ESP32-S2/S3 | ESP32-P4 | nRF54 | nRF54LM20 | ST F407/429 HS | ST F207/F407/411/429 FS | ST L476 FS | ST F412/76x FS | ST F76x HS | ST H743/H750 | ST F723/L4P5 FS | ST F723 HS | ST H7RS FS | ST U5A5/H7RS/N6 HS | XMC4500 | GD32VF103 | +| | AT32 F405 FS | AT32 F405 HS | AT32 F415 | BCM2711 (Pi4) | EFM32GG | ESP32-S2/S3 | ESP32-P4 | nRF54H20 | nRF54LM20 | ST F407/429 HS | ST F207/F407/411/429 FS | ST L476 FS | ST F412/76x FS | ST F76x HS | ST H743/H750 | ST F723/L4P5 FS | ST F723 HS | ST H7RS FS | ST U5A5/H7RS/N6 HS | XMC4500 | GD32VF103 | |:---------------------------|:---------------|:---------------|:------------|:----------------|:-------------|:--------------|:-------------|:-------------|:-------------|:-----------------|:--------------------------|:-------------|:-----------------|:-------------|:---------------|:------------------|:-------------|:-------------|:---------------------|:-------------|:------------| | GUID | 0x00002000 | 0x00000000 | 0x00001000 | 0x2708A000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00001100 | 0x00001200 | 0x00002000 | 0x00002000 | 0x00002100 | 0x00002300 | 0x00003000 | 0x00003100 | 0x00004000 | 0x00005000 | 0x00AEC000 | 0x00001000 | | GSNPSID | 0x4F54400A | 0x4F54400A | 0x4F54400A | 0x4F54280A | 0x4F54330A | 0x4F54400A | 0x4F54400A | 0x4F54430A | 0x4F54500B | 0x4F54281A | 0x4F54281A | 0x4F54310A | 0x4F54320A | 0x4F54320A | 0x4F54330A | 0x4F54330A | 0x4F54330A | 0x4F54411A | 0x4F54411A | 0x4F54292A | 0x00000000 | diff --git a/src/portable/synopsys/dwc2/dwc2_info.py b/src/portable/synopsys/dwc2/dwc2_info.py index eab95ffe1..8ee04e179 100755 --- a/src/portable/synopsys/dwc2/dwc2_info.py +++ b/src/portable/synopsys/dwc2/dwc2_info.py @@ -15,7 +15,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], - # 'nRF54H20': [0, 0x4F54430A, 0xAA555000, 0x228BFC72, 0x0BEAC0E8, 0x1E10AA60], + 'nRF54H20': [0, 0x4F54430A, 0xAA555000, 0x228BFC72, 0x0BEAC0E8, 0x1E10AA60], # base on Preliminary Datasheet v0.7 'nRF54LM20': [0, 0x4F54500B, 0x00000000, 0x22AFFC52, 0x0BE0C0E8, 0x3E10AA60], # ST sort by GUID 'ST F407/429 HS': [0x1100, 0x4F54281A, 0, 0x229ED590, 0x03F403E8, 0x17F00030], -- cgit v1.3.1 From 3f3d65aabab8478ce0c6cce095c327a395eb1ab4 Mon Sep 17 00:00:00 2001 From: Ha Thach Date: Fri, 10 Apr 2026 21:20:57 +0700 Subject: Update src/portable/synopsys/dwc2/dcd_dwc2.c Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/portable/synopsys/dwc2/dcd_dwc2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/portable') diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index da6ee894a..9a9c734a0 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -164,7 +164,7 @@ static void dma_setup_prepare(uint8_t rhport) { --------------- otg_dfifo_depth | EPInfo | DxEPDMAn (DMA only, sized per runtime DMA mode) - |-------------|-- gdfifocfg.EPINFOBASE (= gdfifocfg.GDFIFOCfg) + |-------------|-- gdfifocfg.EPINFOBASE (start of EPInfo; FIFO space sized by GDFIFOCFG) | IN FIFO 0 | control EP |-------------| | IN FIFO 1 | -- cgit v1.3.1 From ed37ad8ce2c7175aacb7dbc6348b4328835a2ff2 Mon Sep 17 00:00:00 2001 From: Brent Kowal Date: Fri, 10 Apr 2026 14:25:28 -0400 Subject: Fix musb RXRDY Clearing Resolves an issue in the musb handle_xfer_out function where not all execution paths cleared the MUSB_RXCSRL1_RXRDY bit, causing the RX interface to hang and no longer communicate with the host. Signed-off-by: Brent Kowal --- src/portable/mentor/musb/dcd_musb.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'src/portable') diff --git a/src/portable/mentor/musb/dcd_musb.c b/src/portable/mentor/musb/dcd_musb.c index 339048473..64f9ebacf 100644 --- a/src/portable/mentor/musb/dcd_musb.c +++ b/src/portable/mentor/musb/dcd_musb.c @@ -230,13 +230,19 @@ static bool handle_xfer_out(uint8_t rhport, uint_fast8_t ep_addr) musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, epnum); // TU_LOG1(" RXCSRL%d = %x\r\n", epnum_minus1 + 1, ep_csr->rx_csrl); - TU_ASSERT(ep_csr->rx_csrl & MUSB_RXCSRL1_RXRDY); + //Fail gracefully. Spurious interrupt. + if (!(ep_csr->rx_csrl & MUSB_RXCSRL1_RXRDY)) return false; + + void *buf = pipe->buf; + if (buf == NULL) { + ep_csr->rx_csrl = MUSB_RXCSRL1_FLUSH; + return false; + } const unsigned mps = ep_csr->rx_maxp; const unsigned rem = pipe->remaining; const unsigned vld = ep_csr->rx_count; const unsigned len = TU_MIN(TU_MIN(rem, mps), vld); - void *buf = pipe->buf; volatile void *fifo_ptr = &musb_regs->fifo[epnum]; if (len) { if (_dcd.pipe_buf_is_fifo[TUSB_DIR_OUT] & TU_BIT(epnum_minus1)) { @@ -247,11 +253,12 @@ static bool handle_xfer_out(uint8_t rhport, uint_fast8_t ep_addr) } pipe->remaining = rem - len; } + + ep_csr->rx_csrl = 0; /* Always Clear RXRDY bit */ if ((len < mps) || (rem == len)) { pipe->buf = NULL; return NULL != buf; } - ep_csr->rx_csrl = 0; /* Clear RXRDY bit */ return false; } -- cgit v1.3.1 From a6dcc3f089bd4468949ea9e138fea9f80025577e Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 17 Apr 2026 00:10:44 +0700 Subject: fix some Wconversion warnings --- .gitignore | 1 + hw/bsp/board.c | 4 +-- hw/bsp/mm32/family.c | 6 ++-- hw/bsp/samd11/family.c | 4 ++- hw/bsp/samd2x_l2x/family.c | 2 +- hw/bsp/samg/family.c | 4 ++- hw/bsp/tm4c/family.c | 2 +- src/common/tusb_fifo.c | 8 ++--- src/common/tusb_types.h | 4 +-- src/portable/chipidea/ci_fs/dcd_ci_fs.c | 14 ++++----- src/portable/dialog/da146xx/dcd_da146xx.c | 42 +++++++++++++++------------ src/portable/mentor/musb/dcd_musb.c | 22 +++++++------- src/portable/mentor/musb/musb_type.h | 2 +- src/portable/microchip/samg/dcd_samg.c | 4 +-- src/portable/nordic/nrf5x/dcd_nrf5x.c | 4 ++- src/portable/nuvoton/nuc120/dcd_nuc120.c | 8 ++--- src/portable/nuvoton/nuc121/dcd_nuc121.c | 8 +++-- src/portable/nuvoton/nuc505/dcd_nuc505.c | 6 ++-- src/portable/nxp/lpc17_40/dcd_lpc17_40.c | 4 +-- src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c | 10 +++---- src/portable/renesas/rusb2/dcd_rusb2.c | 34 ++++++++++++---------- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 18 ++++++------ src/portable/st/stm32_fsdev/fsdev_common.c | 4 +-- src/portable/st/stm32_fsdev/fsdev_common.h | 4 +-- src/portable/synopsys/dwc2/dcd_dwc2.c | 6 ++-- 25 files changed, 122 insertions(+), 103 deletions(-) (limited to 'src/portable') diff --git a/.gitignore b/.gitignore index 162f9a019..b833191f8 100644 --- a/.gitignore +++ b/.gitignore @@ -55,3 +55,4 @@ Release BrowseInfo .cmake_build README_processed.rst +.worktrees diff --git a/hw/bsp/board.c b/hw/bsp/board.c index ae58bb5fc..65b44e5f2 100644 --- a/hw/bsp/board.c +++ b/hw/bsp/board.c @@ -51,12 +51,12 @@ int sys_read(int fhdl, char *buf, size_t count) TU_ATTR_USED; int sys_write(int fhdl, const char *buf, size_t count) { (void) fhdl; - return (int) SEGGER_RTT_Write(0, buf, (int) count); + return (int) SEGGER_RTT_Write(0, buf, (unsigned) count); } int sys_read(int fhdl, char *buf, size_t count) { (void) fhdl; - int rd = (int) SEGGER_RTT_Read(0, buf, count); + int rd = (int) SEGGER_RTT_Read(0, buf, (unsigned) count); return (rd > 0) ? rd : -1; } #endif diff --git a/hw/bsp/mm32/family.c b/hw/bsp/mm32/family.c index 651c9496e..14a17f6c5 100644 --- a/hw/bsp/mm32/family.c +++ b/hw/bsp/mm32/family.c @@ -59,11 +59,11 @@ void OTG_FS_IRQHandler(void) { void USB_DeviceClockInit(void) { /* Select USBCLK source */ // RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_Div1); - RCC->CFGR &= ~(0x3 << 22); - RCC->CFGR |= (0x1 << 22); + RCC->CFGR &= ~(0x3U << 22); + RCC->CFGR |= (0x1U << 22); /* Enable USB clock */ - RCC->AHB2ENR |= 0x1 << 7; + RCC->AHB2ENR |= 0x1U << 7; } void board_init(void) { diff --git a/hw/bsp/samd11/family.c b/hw/bsp/samd11/family.c index 0c987b85a..0864aa3dd 100644 --- a/hw/bsp/samd11/family.c +++ b/hw/bsp/samd11/family.c @@ -34,6 +34,8 @@ #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" +#pragma GCC diagnostic ignored "-Wconversion" +#pragma GCC diagnostic ignored "-Wsign-conversion" #endif #include "hal/include/hal_gpio.h" @@ -66,7 +68,7 @@ void USB_Handler(void) //--------------------------------------------------------------------+ /* Referenced GCLKs, should be initialized firstly */ -#define _GCLK_INIT_1ST (1 << 0 | 1 << 1) +#define _GCLK_INIT_1ST (1u << 0 | 1u << 1) /* Not referenced GCLKs, initialized last */ #define _GCLK_INIT_LAST (~_GCLK_INIT_1ST) diff --git a/hw/bsp/samd2x_l2x/family.c b/hw/bsp/samd2x_l2x/family.c index 11b6343cd..306ea2308 100644 --- a/hw/bsp/samd2x_l2x/family.c +++ b/hw/bsp/samd2x_l2x/family.c @@ -79,7 +79,7 @@ #ifdef SAMD21_FAMILY /* Referenced GCLKs, should be initialized firstly */ -#define _GCLK_INIT_1ST (1 << 0 | 1 << 1) +#define _GCLK_INIT_1ST (1u << 0 | 1u << 1) /* Not referenced GCLKs, initialized last */ #define _GCLK_INIT_LAST (~_GCLK_INIT_1ST) #endif diff --git a/hw/bsp/samg/family.c b/hw/bsp/samg/family.c index 519068986..9edc43b51 100644 --- a/hw/bsp/samg/family.c +++ b/hw/bsp/samg/family.c @@ -27,15 +27,17 @@ manufacturer: Microchip */ -#include "sam.h" // Suppress warning caused by mcu driver #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" #pragma GCC diagnostic ignored "-Wredundant-decls" +#pragma GCC diagnostic ignored "-Wconversion" +#pragma GCC diagnostic ignored "-Wsign-conversion" #endif +#include "sam.h" #include "peripheral_clk_config.h" #include "hal/include/hal_init.h" #include "hal/include/hpl_usart_sync.h" diff --git a/hw/bsp/tm4c/family.c b/hw/bsp/tm4c/family.c index 6988a264e..fe4737e50 100644 --- a/hw/bsp/tm4c/family.c +++ b/hw/bsp/tm4c/family.c @@ -36,7 +36,7 @@ static void board_uart_init(void) { // BAUDRATE = 115200, with SystemCoreClock = 50 Mhz refer manual for calculation // - BRDI = SystemCoreClock / (16* baud) // - BRDF = int(fraction*64 + 0.5) - UART0->CTL &= ~(1 << 0); // Disable UART0 by clearing UARTEN bit in the UARTCTL register + UART0->CTL &= ~(1U << 0); // Disable UART0 by clearing UARTEN bit in the UARTCTL register UART0->IBRD = 27; // Write the integer portion of the BRD to the UARTIRD register UART0->FBRD = 8; // Write the fractional portion of the BRD to the UARTFBRD registerer diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 06d25d131..a8ac99fd2 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -281,14 +281,14 @@ static void hwff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uin // Write full words to the linear part of the buffer const uint8_t data_stride = access_mode->data_stride; const uint32_t odd_mask = data_stride - 1; - uint16_t lin_even = lin_bytes & ~odd_mask; + uint16_t lin_even = (uint16_t)(lin_bytes & ~odd_mask); tu_hwfifo_read(hwfifo, ff_buf, lin_even, access_mode); HWFIFO_ADDR_NEXT_N(hwfifo, const, lin_even * HWFIFO_ADDR_DATA_RATIO); ff_buf += lin_even; // There could be an odd 1 byte (16bit) or 1-3 bytes (32bit) before the wrap-around boundary // combine it with the wrapped part to form a full word for data stride - const uint8_t lin_odd = lin_bytes & odd_mask; + const uint8_t lin_odd = (uint8_t)(lin_bytes & odd_mask); if (lin_odd > 0) { const uint8_t wrap_odd = (uint8_t)tu_min16(wrap_bytes, data_stride - lin_odd); uint8_t buf_temp[4]; @@ -338,13 +338,13 @@ static void hwff_pull_n(const tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t // Read full words from linear part const uint8_t data_stride = access_mode->data_stride; const uint32_t odd_mask = data_stride - 1; - uint16_t lin_even = lin_bytes & ~odd_mask; + uint16_t lin_even = (uint16_t)(lin_bytes & ~odd_mask); tu_hwfifo_write(hwfifo, ff_buf, lin_even, access_mode); HWFIFO_ADDR_NEXT_N(hwfifo, , lin_even * HWFIFO_ADDR_DATA_RATIO); ff_buf += lin_even; // There could be odd 1 byte (16bit) or 1-3 bytes (32bit) before the wrap-around boundary - const uint8_t lin_odd = lin_bytes & odd_mask; + const uint8_t lin_odd = (uint8_t)(lin_bytes & odd_mask); if (lin_odd > 0) { const uint8_t wrap_odd = (uint8_t)tu_min16(wrap_bytes, data_stride - lin_odd); diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index a18f9feb7..d8b6a8823 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -100,8 +100,8 @@ typedef enum { } tusb_xfer_type_t; typedef enum { - TUSB_DIR_OUT = 0, - TUSB_DIR_IN = 1, + TUSB_DIR_OUT = 0u, + TUSB_DIR_IN = 1u, TUSB_EPNUM_MASK = 0x0F, TUSB_DIR_IN_MASK = 0x80 diff --git a/src/portable/chipidea/ci_fs/dcd_ci_fs.c b/src/portable/chipidea/ci_fs/dcd_ci_fs.c index 312a98299..62df1a6d5 100644 --- a/src/portable/chipidea/ci_fs/dcd_ci_fs.c +++ b/src/portable/chipidea/ci_fs/dcd_ci_fs.c @@ -360,7 +360,7 @@ static bool edpt_open(uint8_t rhport, uint8_t ep_addr, uint16_t max_packet_size, unsigned val = USB_ENDPT_EPCTLDIS_MASK; val |= (xfer != TUSB_XFER_ISOCHRONOUS) ? USB_ENDPT_EPHSHK_MASK : 0; val |= dir ? USB_ENDPT_EPTXEN_MASK : USB_ENDPT_EPRXEN_MASK; - CI_REG->EP[epn].CTL |= val; + CI_REG->EP[epn].CTL |= (uint8_t)val; if (xfer != TUSB_XFER_ISOCHRONOUS) { bd[odd].dts = 1; @@ -434,11 +434,11 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t t buffer_descriptor_t *next = ep->odd ? bd - 1: bd + 1; /* When total_bytes is greater than the max packet size, * it prepares to the next transfer to avoid NAK in advance. */ - next->bc = total_bytes >= 2 * mps ? mps: total_bytes - mps; + next->bc = (total_bytes >= 2 * mps) ? mps : (total_bytes - mps); next->addr = buffer + mps; next->own = 1; } - bd->bc = total_bytes >= mps ? mps: total_bytes; + bd->bc = (total_bytes >= mps ? mps : total_bytes); bd->addr = buffer; __DSB(); bd->own = 1; /* This bit must be set last */ @@ -506,16 +506,16 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) //--------------------------------------------------------------------+ void dcd_int_handler(uint8_t rhport) { - uint32_t is = CI_REG->INT_STAT; - uint32_t msk = CI_REG->INT_EN; + uint8_t is = CI_REG->INT_STAT; + uint8_t msk = CI_REG->INT_EN; // clear non-enabled interrupts - CI_REG->INT_STAT = is & ~msk; + CI_REG->INT_STAT = (uint8_t)(is & ~msk); is &= msk; if (is & USB_ISTAT_ERROR_MASK) { /* TODO: */ - uint32_t es = CI_REG->ERR_STAT; + uint8_t es = CI_REG->ERR_STAT; CI_REG->ERR_STAT = es; CI_REG->INT_STAT = is; /* discard any pending events */ } diff --git a/src/portable/dialog/da146xx/dcd_da146xx.c b/src/portable/dialog/da146xx/dcd_da146xx.c index a283c8362..7d90b1f94 100644 --- a/src/portable/dialog/da146xx/dcd_da146xx.c +++ b/src/portable/dialog/da146xx/dcd_da146xx.c @@ -148,8 +148,8 @@ typedef struct #ifndef TU_DA146XX_DMA_RX_CHANNEL #define TU_DA146XX_DMA_RX_CHANNEL 6 #endif -#define DA146XX_DMA_USB_MUX (0x6 << (TU_DA146XX_DMA_RX_CHANNEL * 2)) -#define DA146XX_DMA_USB_MUX_MASK (0xF << (TU_DA146XX_DMA_RX_CHANNEL * 2)) +#define DA146XX_DMA_USB_MUX (0x6u << (TU_DA146XX_DMA_RX_CHANNEL * 2)) +#define DA146XX_DMA_USB_MUX_MASK (0xFu << (TU_DA146XX_DMA_RX_CHANNEL * 2)) typedef struct { @@ -311,12 +311,12 @@ static void fill_tx_fifo(xfer_ctl_t * xfer) // Max packet size is set to value greater then FIFO. Enable fifo level warning // to handle larger packets. regs->txc |= (3 << USB_USB_TXC1_REG_USB_TFWL_Pos); - USB->USB_FWMSK_REG |= 1 << (epnum - 1 + USB_USB_FWMSK_REG_USB_M_TXWARN31_Pos); + USB->USB_FWMSK_REG |= 1u << (epnum - 1 + USB_USB_FWMSK_REG_USB_M_TXWARN31_Pos); } else { regs->txc &= ~USB_USB_TXC1_REG_USB_TFWL_Msk; - USB->USB_FWMSK_REG &= ~(1 << (epnum - 1 + USB_USB_FWMSK_REG_USB_M_TXWARN31_Pos)); + USB->USB_FWMSK_REG &= ~(1u << (epnum - 1 + USB_USB_FWMSK_REG_USB_M_TXWARN31_Pos)); // Whole packet already in fifo, no need to refill it later. Mark last. regs->txc |= USB_USB_TXC1_REG_USB_LAST_Msk; } @@ -371,14 +371,14 @@ static void start_rx_packet(xfer_ctl_t *xfer) // For endpoint size greater than FIFO size enable FIFO level warning interrupt // when FIFO has less than 17 bytes free. regs->rxc |= USB_USB_RXC1_REG_USB_RFWL_Msk; - USB->USB_FWMSK_REG |= 1 << (epnum - 1 + USB_USB_FWMSK_REG_USB_M_RXWARN31_Pos); + USB->USB_FWMSK_REG |= 1u << (epnum - 1 + USB_USB_FWMSK_REG_USB_M_RXWARN31_Pos); } } else if (epnum != 0) { // If max_packet_size would fit in FIFO no need for FIFO level warning interrupt. regs->rxc &= ~USB_USB_RXC1_REG_USB_RFWL_Msk; - USB->USB_FWMSK_REG &= ~(1 << (epnum - 1 + USB_USB_FWMSK_REG_USB_M_RXWARN31_Pos)); + USB->USB_FWMSK_REG &= ~(1u << (epnum - 1 + USB_USB_FWMSK_REG_USB_M_RXWARN31_Pos)); } regs->rxc |= USB_USB_RXC1_REG_USB_RX_EN_Msk; } @@ -388,7 +388,7 @@ static void start_tx_dma(void *src, volatile void *dst, uint16_t size) // Setup SRC and DST registers TX_DMA_REGS->DMAx_A_START_REG = (uint32_t)src; TX_DMA_REGS->DMAx_B_START_REG = (uint32_t)dst; - // Interrupt not needed + // Interrupt is not needed TX_DMA_REGS->DMAx_INT_REG = size; TX_DMA_REGS->DMAx_LEN_REG = size - 1; TX_DMA_REGS->DMAx_CTRL_REG = TX_DMA_START; @@ -430,7 +430,9 @@ static uint16_t read_rx_fifo(xfer_ctl_t *xfer, uint16_t bytes_in_fifo) uint8_t *buf = xfer->buffer + xfer->transferred + xfer->last_packet_size; - for (int i = 0; i < receive_this_time; ++i) buf[i] = regs->rxd; + for (int i = 0; i < receive_this_time; ++i) { + buf[i] = (uint8_t)regs->rxd; + } xfer->last_packet_size += receive_this_time; @@ -449,7 +451,9 @@ static void handle_ep0_rx(void) { xfer_ctl_t *xfer_in = XFER_CTL_BASE(0, TUSB_DIR_IN); // Setup packet is in - for (int i = 0; i < fifo_bytes; ++i) _setup_packet[i] = USB->USB_RXD0_REG; + for (int i = 0; i < fifo_bytes; ++i) { + _setup_packet[i] = (uint8_t)USB->USB_RXD0_REG; + } xfer->stall = 0; xfer->data1 = 1; @@ -469,7 +473,7 @@ static void handle_ep0_rx(void) } else { - read_rx_fifo(xfer, fifo_bytes); + read_rx_fifo(xfer, (uint16_t)fifo_bytes); if (rxs0 & USB_USB_RXS0_REG_USB_RX_LAST_Msk) { xfer->transferred += xfer->last_packet_size; @@ -553,7 +557,7 @@ static void handle_epx_rx_ev(uint8_t ep) { // Disable DMA and update last_packet_size with what DMA reported. RX_DMA_REGS->DMAx_CTRL_REG &= ~DMA_DMA0_CTRL_REG_DMA_ON_Msk; - xfer->last_packet_size = RX_DMA_REGS->DMAx_IDX_REG; + xfer->last_packet_size = (uint16_t)RX_DMA_REGS->DMAx_IDX_REG; // When DMA did not finished (packet was smaller then MPS), DMAx_IDX_REG holds exact number of bytes transmitted. // When DMA finished value in DMAx_IDX_REG is one less then actual number of transmitted bytes. if (xfer->last_packet_size == RX_DMA_REGS->DMAx_LEN_REG) xfer->last_packet_size++; @@ -564,7 +568,7 @@ static void handle_epx_rx_ev(uint8_t ep) // FIFO maybe empty if DMA read it before or it's final iteration and function already read all that was to read. if (fifo_bytes > 0) { - fifo_bytes = read_rx_fifo(xfer, fifo_bytes); + fifo_bytes = read_rx_fifo(xfer, (uint16_t)fifo_bytes); } if (GET_BIT(rxs, USB_USB_RXS1_REG_USB_RX_LAST)) { @@ -624,7 +628,7 @@ static void handle_epx_tx_ev(xfer_ctl_t *xfer) { // Disable DMA and update last_packet_size with what DMA reported. TX_DMA_REGS->DMAx_CTRL_REG &= ~DMA_DMA1_CTRL_REG_DMA_ON_Msk; - xfer->last_packet_size = TX_DMA_REGS->DMAx_IDX_REG + 1; + xfer->last_packet_size = (uint16_t)(TX_DMA_REGS->DMAx_IDX_REG + 1); // Release DMA to used by other endpoints. _dcd.dma_ep[TUSB_DIR_IN] = 0; } @@ -954,13 +958,13 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) if (dir == TUSB_DIR_OUT) { regs->epc_out = epnum | USB_USB_EPC1_REG_USB_EP_EN_Msk | iso_mask; - USB->USB_RXMSK_REG |= 0x11 << (epnum - 1); + USB->USB_RXMSK_REG |= 0x11u << (epnum - 1); REG_SET_BIT(USB_MAMSK_REG, USB_M_RX_EV); } else { regs->epc_in = epnum | USB_USB_EPC1_REG_USB_EP_EN_Msk | iso_mask; - USB->USB_TXMSK_REG |= 0x11 << (epnum - 1); + USB->USB_TXMSK_REG |= 0x11u << (epnum - 1); REG_SET_BIT(USB_MAMSK_REG, USB_M_TX_EV); } } @@ -974,8 +978,8 @@ void dcd_edpt_close_all (uint8_t rhport) for (int epnum = 1; epnum < EP_MAX; ++epnum) { - dcd_edpt_close(0, epnum | TUSB_DIR_OUT); - dcd_edpt_close(0, epnum | TUSB_DIR_IN); + dcd_edpt_close(0, (uint8_t)(epnum | TUSB_DIR_OUT)); + dcd_edpt_close(0, (uint8_t)(epnum | TUSB_DIR_IN)); } } @@ -1001,7 +1005,7 @@ void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) { regs->rxc = USB_USB_RXC1_REG_USB_FLUSH_Msk; regs->epc_out = 0; - USB->USB_RXMSK_REG &= ~(0x11 << (epnum - 1)); + USB->USB_RXMSK_REG &= ~(0x11u << (epnum - 1)); // Release DMA if needed if (_dcd.dma_ep[TUSB_DIR_OUT] == epnum) { @@ -1013,7 +1017,7 @@ void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) { regs->txc = USB_USB_TXC1_REG_USB_FLUSH_Msk; regs->epc_in = 0; - USB->USB_TXMSK_REG &= ~(0x11 << (epnum - 1)); + USB->USB_TXMSK_REG &= ~(0x11u << (epnum - 1)); // Release DMA if needed if (_dcd.dma_ep[TUSB_DIR_IN] == epnum) { diff --git a/src/portable/mentor/musb/dcd_musb.c b/src/portable/mentor/musb/dcd_musb.c index 339048473..3111f6185 100644 --- a/src/portable/mentor/musb/dcd_musb.c +++ b/src/portable/mentor/musb/dcd_musb.c @@ -111,8 +111,8 @@ TU_ATTR_ALWAYS_INLINE static inline void hwfifo_reset(musb_regs_t* musb, unsigne TU_ATTR_ALWAYS_INLINE static inline bool hwfifo_config(musb_regs_t* musb, unsigned epnum, unsigned is_rx, unsigned mps, bool double_packet) { (void) epnum; - uint8_t ffsize = hwfifo_byte2size(mps); - mps = 8 << ffsize; // round up to the next power of 2 + uint8_t ffsize = hwfifo_byte2size((uint16_t)mps); + mps = 8u << ffsize; // round up to the next power of 2 if (double_packet) { ffsize |= MUSB_FIFOSZ_DOUBLE_PACKET; @@ -120,7 +120,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool hwfifo_config(musb_regs_t* musb, unsign } TU_ASSERT(alloced_fifo_bytes + mps <= MUSB_CFG_DYNAMIC_FIFO_SIZE); - musb->fifo_addr[is_rx] = alloced_fifo_bytes / 8; + musb->fifo_addr[is_rx] = (uint16_t)(alloced_fifo_bytes / 8); musb->fifo_size[is_rx] = ffsize; alloced_fifo_bytes += mps; @@ -157,12 +157,12 @@ TU_ATTR_ALWAYS_INLINE static inline bool hwfifo_config(musb_regs_t* musb, unsign // Flush FIFO and clear data toggle TU_ATTR_ALWAYS_INLINE static inline void hwfifo_flush(musb_regs_t* musb, unsigned epnum, unsigned is_rx, bool clear_dtog) { (void) epnum; - const uint8_t csrl_dtog = clear_dtog ? MUSB_CSRL_CLEAR_DATA_TOGGLE(is_rx) : 0; + const uint8_t csrl_dtog = clear_dtog ? (uint8_t)MUSB_CSRL_CLEAR_DATA_TOGGLE(is_rx) : 0; musb_ep_maxp_csr_t* maxp_csr = &musb->indexed_csr.maxp_csr[is_rx]; // may need to flush twice for double packet for (unsigned i=0; i<2; i++) { if (maxp_csr->csrl & MUSB_CSRL_PACKET_READY(is_rx)) { - maxp_csr->csrl = MUSB_CSRL_FLUSH_FIFO(is_rx) | csrl_dtog; + maxp_csr->csrl = (uint8_t)(MUSB_CSRL_FLUSH_FIFO(is_rx) | csrl_dtog); } } } @@ -180,7 +180,7 @@ static void process_setup_packet(uint8_t rhport) { dcd_event_setup_received(rhport, (const uint8_t*)(uintptr_t)&_dcd.setup_packet, true); const unsigned len = _dcd.setup_packet.wLength; - _dcd.remaining_ctrl = len; + _dcd.remaining_ctrl = (uint16_t)len; const unsigned dir_in = tu_edpt_dir(_dcd.setup_packet.bmRequestType); /* Clear RX FIFO and reverse the transaction direction */ if (len && dir_in) { @@ -441,14 +441,14 @@ static void process_edpt_n(uint8_t rhport, uint_fast8_t ep_addr) if (dir_in) { // TU_LOG1(" TX CSRL%d = %x\r\n", epn, ep_csr->tx_csrl); if (ep_csr->tx_csrl & MUSB_TXCSRL1_STALLED) { - ep_csr->tx_csrl &= ~(MUSB_TXCSRL1_STALLED | MUSB_TXCSRL1_UNDRN); + ep_csr->tx_csrl = (uint8_t)(ep_csr->tx_csrl & ~(MUSB_TXCSRL1_STALLED | MUSB_TXCSRL1_UNDRN)); return; } completed = handle_xfer_in(rhport, ep_addr); } else { // TU_LOG1(" RX CSRL%d = %x\r\n", epn, ep_csr->rx_csrl); if (ep_csr->rx_csrl & MUSB_RXCSRL1_STALLED) { - ep_csr->rx_csrl &= ~(MUSB_RXCSRL1_STALLED | MUSB_RXCSRL1_OVER); + ep_csr->rx_csrl = (uint8_t)(ep_csr->rx_csrl & ~(MUSB_RXCSRL1_STALLED | MUSB_RXCSRL1_OVER)); return; } completed = handle_xfer_out(rhport, ep_addr); @@ -778,7 +778,7 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, epn); const uint8_t is_rx = 1 - tu_edpt_dir(ep_addr); - ep_csr->maxp_csr[is_rx].csrl = MUSB_CSRL_CLEAR_DATA_TOGGLE(is_rx); + ep_csr->maxp_csr[is_rx].csrl = (uint8_t)MUSB_CSRL_CLEAR_DATA_TOGGLE(is_rx); if (ie) musb_dcd_int_enable(rhport); } @@ -794,8 +794,8 @@ void dcd_int_handler(uint8_t rhport) { musb_dcd_int_handler_enter(rhport); uint_fast8_t intr_usb = musb_regs->intr_usb; // a read will clear this interrupt status - uint_fast8_t intr_tx = musb_regs->intr_tx; // a read will clear this interrupt status - uint_fast8_t intr_rx = musb_regs->intr_rx; // a read will clear this interrupt status + uint_fast16_t intr_tx = musb_regs->intr_tx; // a read will clear this interrupt status + uint_fast16_t intr_rx = musb_regs->intr_rx; // a read will clear this interrupt status // TU_LOG1("D%2x T%2x R%2x\r\n", is, txis, rxis); intr_usb &= musb_regs->intr_usben; /* Clear disabled interrupts */ diff --git a/src/portable/mentor/musb/musb_type.h b/src/portable/mentor/musb/musb_type.h index b2f6492fa..176504a2f 100644 --- a/src/portable/mentor/musb/musb_type.h +++ b/src/portable/mentor/musb/musb_type.h @@ -300,7 +300,7 @@ TU_VERIFY_STATIC(sizeof(musb_regs_t) == 0x350, "size is not correct"); // Helper //--------------------------------------------------------------------+ TU_ATTR_ALWAYS_INLINE static inline musb_ep_csr_t* get_ep_csr(musb_regs_t* musb_regs, unsigned epnum) { - musb_regs->index = epnum; + musb_regs->index = (uint8_t)epnum; return &musb_regs->indexed_csr; } diff --git a/src/portable/microchip/samg/dcd_samg.c b/src/portable/microchip/samg/dcd_samg.c index 4115eecc5..f8980b775 100644 --- a/src/portable/microchip/samg/dcd_samg.c +++ b/src/portable/microchip/samg/dcd_samg.c @@ -352,8 +352,8 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) csr_clear(epnum, UDP_CSR_FORCESTALL_Msk); // must also reset EP to clear data toggle - UDP->UDP_RST_EP |= (1 << epnum); - UDP->UDP_RST_EP &= ~(1 << epnum); + UDP->UDP_RST_EP |= (1u << epnum); + UDP->UDP_RST_EP &= ~(1u << epnum); } //--------------------------------------------------------------------+ diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c index 8a41c4790..6ed5fde8e 100644 --- a/src/portable/nordic/nrf5x/dcd_nrf5x.c +++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c @@ -36,6 +36,8 @@ #pragma GCC diagnostic ignored "-Wcast-qual" #pragma GCC diagnostic ignored "-Wcast-align" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wconversion" +#pragma GCC diagnostic ignored "-Wsign-conversion" #endif #include "nrf.h" @@ -461,7 +463,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to xfer->actual_len = 0; // Control endpoint with zero-length packet and opposite direction to 1st request byte --> status stage - bool const control_status = (epnum == 0 && total_bytes == 0 && dir != tu_edpt_dir(NRF_USBD->BMREQUESTTYPE)); + bool const control_status = (epnum == 0 && total_bytes == 0 && dir != tu_edpt_dir((uint8_t)NRF_USBD->BMREQUESTTYPE)); if (control_status) { // The nRF doesn't interrupt on status transmit so we queue up a success response. diff --git a/src/portable/nuvoton/nuc120/dcd_nuc120.c b/src/portable/nuvoton/nuc120/dcd_nuc120.c index d9a0e3fa8..2edb1bc7a 100644 --- a/src/portable/nuvoton/nuc120/dcd_nuc120.c +++ b/src/portable/nuvoton/nuc120/dcd_nuc120.c @@ -253,13 +253,13 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) /* mine the data for the information we need */ int const dir = tu_edpt_dir(p_endpoint_desc->bEndpointAddress); - int const size = tu_edpt_packet_size(p_endpoint_desc); + uint16_t const size = tu_edpt_packet_size(p_endpoint_desc); tusb_xfer_type_t const type = (tusb_xfer_type_t) p_endpoint_desc->bmAttributes.xfer; struct xfer_ctl_t *xfer = &xfer_table[ep - USBD->EP]; /* allocate buffer from USB RAM */ ep->BUFSEG = bufseg_addr; - bufseg_addr += size; + bufseg_addr += (uint32_t)size; TU_ASSERT(bufseg_addr <= USBD_BUF_SIZE); /* construct USB Configuration Register value and then write it */ @@ -435,7 +435,7 @@ void dcd_int_handler(uint8_t rhport) /* given ACK from host has happened, we can now set the address (if not already done) */ if((USBD->FADDR != assigned_address) && (USBD->FADDR == 0)) USBD->FADDR = assigned_address; - uint16_t const available_bytes = USBD->EP[PERIPH_EP0].MXPLD; + uint16_t const available_bytes = (uint16_t)USBD->EP[PERIPH_EP0].MXPLD; active_ep0_xfer = (available_bytes == xfer_table[PERIPH_EP0].max_packet_size); @@ -453,7 +453,7 @@ void dcd_int_handler(uint8_t rhport) { USBD->INTSTS = mask; - uint16_t const available_bytes = ep->MXPLD; + uint16_t const available_bytes = (uint16_t)ep->MXPLD; uint8_t const ep_addr = decode_ep_addr(ep); bool const out_ep = !(ep_addr & TUSB_DIR_IN_MASK); diff --git a/src/portable/nuvoton/nuc121/dcd_nuc121.c b/src/portable/nuvoton/nuc121/dcd_nuc121.c index 42fb58a0a..008c9df6b 100644 --- a/src/portable/nuvoton/nuc121/dcd_nuc121.c +++ b/src/portable/nuvoton/nuc121/dcd_nuc121.c @@ -42,6 +42,8 @@ #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wredundant-decls" +#pragma GCC diagnostic ignored "-Wconversion" +#pragma GCC diagnostic ignored "-Wsign-conversion" #endif #include "NuMicro.h" @@ -291,7 +293,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) /* mine the data for the information we need */ int const dir = tu_edpt_dir(p_endpoint_desc->bEndpointAddress); - int const size = tu_edpt_packet_size(p_endpoint_desc); + uint16_t const size = tu_edpt_packet_size(p_endpoint_desc); tusb_xfer_type_t const type = (tusb_xfer_type_t) p_endpoint_desc->bmAttributes.xfer; struct xfer_ctl_t *xfer = &xfer_table[ep - USBD->EP]; @@ -478,7 +480,7 @@ void dcd_int_handler(uint8_t rhport) { if (status & USBD_INTSTS_EPEVT0_Msk) /* PERIPH_EP0 (EP0_IN) event: this is treated separately from the rest */ { - uint16_t const available_bytes = USBD->EP[PERIPH_EP0].MXPLD; + uint16_t const available_bytes = (uint16_t)USBD->EP[PERIPH_EP0].MXPLD; active_ep0_xfer = (available_bytes == xfer_table[PERIPH_EP0].max_packet_size); @@ -496,7 +498,7 @@ void dcd_int_handler(uint8_t rhport) { USBD->INTSTS = mask; - uint16_t const available_bytes = ep->MXPLD; + uint16_t const available_bytes = (uint16_t)ep->MXPLD; uint8_t const ep_addr = decode_ep_addr(ep); bool const out_ep = !(ep_addr & TUSB_DIR_IN_MASK); diff --git a/src/portable/nuvoton/nuc505/dcd_nuc505.c b/src/portable/nuvoton/nuc505/dcd_nuc505.c index ca17d6251..a0f3d4c3f 100644 --- a/src/portable/nuvoton/nuc505/dcd_nuc505.c +++ b/src/portable/nuvoton/nuc505/dcd_nuc505.c @@ -42,6 +42,8 @@ #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wredundant-decls" +#pragma GCC diagnostic ignored "-Wconversion" +#pragma GCC diagnostic ignored "-Wsign-conversion" #endif #include "NUC505Series.h" @@ -338,13 +340,13 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) /* mine the data for the information we need */ int const dir = tu_edpt_dir(p_endpoint_desc->bEndpointAddress); - int const size = tu_edpt_packet_size(p_endpoint_desc); + uint16_t const size = tu_edpt_packet_size(p_endpoint_desc); tusb_xfer_type_t const type = p_endpoint_desc->bmAttributes.xfer; struct xfer_ctl_t *xfer = &xfer_table[ep - USBD->EP]; /* allocate buffer from USB RAM */ ep->EPBUFSTART = bufseg_addr; - bufseg_addr += size; + bufseg_addr += (uint32_t)size; ep->EPBUFEND = bufseg_addr - 1; TU_ASSERT(bufseg_addr <= USBD_BUF_SIZE); diff --git a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c index 349229c8d..2840c6d5e 100644 --- a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c +++ b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c @@ -131,7 +131,7 @@ static uint8_t sie_read (uint8_t cmd_code) //--------------------------------------------------------------------+ static inline uint8_t ep_addr2idx(uint8_t ep_addr) { - return 2*(ep_addr & 0x0F) + ((ep_addr & TUSB_DIR_IN_MASK) ? 1 : 0); + return (uint8_t)(2*(ep_addr & 0x0F) + ((ep_addr & TUSB_DIR_IN_MASK) ? 1 : 0)); } static void set_ep_size(uint8_t ep_id, uint16_t max_packet_size) @@ -243,7 +243,7 @@ void dcd_sof_enable(uint8_t rhport, bool en) //--------------------------------------------------------------------+ static inline uint8_t byte2dword(uint8_t bytes) { - return (bytes + 3) / 4; // length in dwords + return (uint8_t)((bytes + 3) / 4); // length in dwords } static void control_ep_write(void const * buffer, uint8_t len) diff --git a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c index 5f4a441dc..8adf0f840 100644 --- a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c +++ b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c @@ -243,7 +243,7 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t get_buf_offset(void const * buffer) } TU_ATTR_ALWAYS_INLINE static inline uint8_t ep_addr2id(uint8_t ep_addr) { - return 2*(ep_addr & 0x0F) + ((ep_addr & TUSB_DIR_IN_MASK) ? 1 : 0); + return (uint8_t)(2*(ep_addr & 0x0F) + ((ep_addr & TUSB_DIR_IN_MASK) ? 1 : 0)); } TU_ATTR_ALWAYS_INLINE static inline bool ep_is_iso(ep_cmd_sts_t* ep_cs, bool is_highspeed) { @@ -539,8 +539,8 @@ static void process_xfer_isr(uint8_t rhport, uint32_t int_status) { uint16_t buf_nbytes; if ( rhport_is_highspeed(rhport) ) { - buf_offset = ep_cs->buffer_hs.offset; - buf_nbytes = ep_cs->buffer_hs.nbytes; + buf_offset = (uint16_t)ep_cs->buffer_hs.offset; + buf_nbytes = (uint16_t)ep_cs->buffer_hs.nbytes; #if TU_CHECK_MCU(OPT_MCU_LPC54) // LPC54 Errata USB.2: In USB high-speed device mode, the NBytes field is not correct after BULK IN transfer @@ -550,8 +550,8 @@ static void process_xfer_isr(uint8_t rhport, uint32_t int_status) { } #endif } else { - buf_offset = ep_cs->buffer_fs.offset; - buf_nbytes = ep_cs->buffer_fs.nbytes; + buf_offset = (uint16_t)ep_cs->buffer_fs.offset; + buf_nbytes = (uint16_t)ep_cs->buffer_fs.nbytes; } xfer_dma->xferred_bytes += xfer_dma->nbytes - buf_nbytes; diff --git a/src/portable/renesas/rusb2/dcd_rusb2.c b/src/portable/renesas/rusb2/dcd_rusb2.c index e2a51a5ca..adbb53787 100644 --- a/src/portable/renesas/rusb2/dcd_rusb2.c +++ b/src/portable/renesas/rusb2/dcd_rusb2.c @@ -93,7 +93,9 @@ static unsigned find_pipe(unsigned xfer_type) { const uint8_t idx_last = pipe_idx_arr[xfer_type][1]; for (int i = idx_last; i >= idx_first; i--) { - if (0 == _dcd.pipe[i].ep) return i; + if (0 == _dcd.pipe[i].ep) { + return (unsigned)i; + } } return 0; @@ -117,10 +119,10 @@ static volatile reg_pipetre_t* get_pipetre(rusb2_reg_t *rusb, unsigned num) { static volatile uint16_t* ep_addr_to_pipectr(uint8_t rhport, unsigned ep_addr) { rusb2_reg_t *rusb = RUSB2_REG(rhport); - const unsigned epn = tu_edpt_number(ep_addr); + const unsigned epn = tu_edpt_number((uint8_t)ep_addr); if (epn) { - const unsigned dir = tu_edpt_dir(ep_addr); + const unsigned dir = tu_edpt_dir((uint8_t)ep_addr); const unsigned num = _dcd.ep[dir][epn]; return get_pipectr(rusb, num); } else { @@ -129,11 +131,11 @@ static volatile uint16_t* ep_addr_to_pipectr(uint8_t rhport, unsigned ep_addr) { } static uint16_t edpt0_max_packet_size(rusb2_reg_t* rusb) { - return rusb->DCPMAXP_b.MXPS; + return (uint16_t)rusb->DCPMAXP_b.MXPS; } static uint16_t edpt_max_packet_size(rusb2_reg_t *rusb, unsigned num) { - rusb->PIPESEL = num; + rusb->PIPESEL = (uint16_t)num; return rusb->PIPEMAXP; } @@ -285,7 +287,7 @@ static bool pipe_xfer_out(rusb2_reg_t* rusb, unsigned num) const uint16_t mps = edpt_max_packet_size(rusb, num); pipe_wait_for_ready(rusb, num); - const uint16_t vld = rusb->D0FIFOCTR_b.DTLN; + const uint16_t vld = (uint16_t)rusb->D0FIFOCTR_b.DTLN; const uint16_t len = tu_min16(tu_min16(rem, mps), vld); void *buf = pipe->buf; @@ -498,7 +500,7 @@ static void process_bus_reset(uint8_t rhport) volatile uint16_t *ctr = (volatile uint16_t*)((uintptr_t) (&rusb->PIPE_CTR[0])); volatile uint16_t *tre = (volatile uint16_t*)((uintptr_t) (&rusb->PIPE_TR[0].E)); - for (int i = 1; i <= 5; ++i) { + for (uint16_t i = 1; i <= 5; ++i) { rusb->PIPESEL = i; rusb->PIPECFG = 0; *ctr = RUSB2_PIPE_CTR_ACLRM_Msk; @@ -508,7 +510,7 @@ static void process_bus_reset(uint8_t rhport) tre += 2; } - for (int i = 6; i <= 9; ++i) { + for (uint16_t i = 6; i <= 9; ++i) { rusb->PIPESEL = i; rusb->PIPECFG = 0; *ctr = RUSB2_PIPE_CTR_ACLRM_Msk; @@ -542,7 +544,7 @@ static void process_bus_reset(uint8_t rhport) static void process_set_address(uint8_t rhport) { rusb2_reg_t* rusb = RUSB2_REG(rhport); - const uint16_t addr = rusb->USBADDR_b.USBADDR; + const uint16_t addr = (uint16_t)rusb->USBADDR_b.USBADDR; if (!addr) { return; } @@ -706,7 +708,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) (void)rhport; rusb2_reg_t * rusb = RUSB2_REG(rhport); - const unsigned ep_addr = ep_desc->bEndpointAddress; + const uint8_t ep_addr = ep_desc->bEndpointAddress; const unsigned epn = tu_edpt_number(ep_addr); const unsigned dir = tu_edpt_dir(ep_addr); const unsigned xfer = ep_desc->bmAttributes.xfer; @@ -770,8 +772,10 @@ void dcd_edpt_close_all(uint8_t rhport) dcd_int_disable(rhport); while (--i) { /* Close all pipes except 0 */ const unsigned ep_addr = _dcd.pipe[i].ep; - if (!ep_addr) continue; - dcd_edpt_close(rhport, ep_addr); + if (!ep_addr) { + continue; + } + dcd_edpt_close(rhport, (uint8_t)ep_addr); } dcd_int_enable(rhport); } @@ -783,10 +787,10 @@ void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) const unsigned dir = tu_edpt_dir(ep_addr); const unsigned num = _dcd.ep[dir][epn]; - rusb->BRDYENB &= ~TU_BIT(num); + rusb->BRDYENB &= (uint16_t)~TU_BIT(num); volatile uint16_t *ctr = get_pipectr(rusb, num); *ctr = 0; - rusb->PIPESEL = num; + rusb->PIPESEL = (uint16_t)num; rusb->PIPECFG = 0; _dcd.pipe[num].ep = 0; _dcd.ep[dir][epn] = 0; @@ -860,7 +864,7 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) *ctr = RUSB2_PIPE_CTR_PID_BUF; } else { const unsigned num = _dcd.ep[0][tu_edpt_number(ep_addr)]; - rusb->PIPESEL = num; + rusb->PIPESEL = (uint16_t)num; if (rusb->PIPECFG_b.TYPE != 1) { *ctr = RUSB2_PIPE_CTR_PID_BUF; } diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 8b4719b21..135b4e8f6 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -259,7 +259,7 @@ static void handle_ctr_tx(uint32_t ep_id) { } if (xfer->total_len != xfer->queued_len) { - dcd_transmit_packet(xfer, ep_id); + dcd_transmit_packet(xfer, (uint16_t)ep_id); } else { dcd_event_xfer_complete(0, ep_num | TUSB_DIR_IN_MASK, xfer->queued_len, XFER_RESULT_SUCCESS, true); } @@ -267,7 +267,7 @@ static void handle_ctr_tx(uint32_t ep_id) { static void handle_ctr_setup(uint32_t ep_id) { uint16_t rx_count = btable_get_count(ep_id, BTABLE_BUF_RX); - uint16_t rx_addr = btable_get_addr(ep_id, BTABLE_BUF_RX); + uint16_t rx_addr = (uint16_t)btable_get_addr(ep_id, BTABLE_BUF_RX); uint8_t setup_packet[8] TU_ATTR_ALIGNED(4); tu_hwfifo_read(PMA_BUF_AT(rx_addr), setup_packet, rx_count, NULL); @@ -531,8 +531,8 @@ void edpt0_open(uint8_t rhport) { xfer_status[0][1].max_packet_size = CFG_TUD_ENDPOINT0_SIZE; xfer_status[0][1].ep_idx = 0; - uint16_t pma_addr0 = dcd_pma_alloc(CFG_TUD_ENDPOINT0_SIZE, false); - uint16_t pma_addr1 = dcd_pma_alloc(CFG_TUD_ENDPOINT0_SIZE, false); + uint16_t pma_addr0 = (uint16_t)dcd_pma_alloc(CFG_TUD_ENDPOINT0_SIZE, false); + uint16_t pma_addr1 = (uint16_t)dcd_pma_alloc(CFG_TUD_ENDPOINT0_SIZE, false); btable_set_addr(0, BTABLE_BUF_RX, pma_addr0); btable_set_addr(0, BTABLE_BUF_TX, pma_addr1); @@ -574,7 +574,7 @@ bool dcd_edpt_open(uint8_t rhport, const tusb_desc_endpoint_t *desc_ep) { } /* Create a packet memory buffer area. */ - uint16_t pma_addr = dcd_pma_alloc(packet_size, false); + uint16_t pma_addr = (uint16_t)dcd_pma_alloc(packet_size, false); btable_set_addr(ep_idx, dir == TUSB_DIR_IN ? BTABLE_BUF_TX : BTABLE_BUF_RX, pma_addr); xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, dir); @@ -624,17 +624,17 @@ bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet #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; + uint16_t pma_addr2 = (uint16_t)(pma_addr >> 16); #else uint32_t pma_addr = dcd_pma_alloc(largest_packet_size, false); - uint16_t pma_addr2 = pma_addr; + uint16_t pma_addr2 = (uint16_t)pma_addr; #endif #if FSDEV_USE_SBUF_ISO == 0 - btable_set_addr(ep_idx, 0, pma_addr); + btable_set_addr(ep_idx, 0, (uint16_t)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); + btable_set_addr(ep_idx, dir == TUSB_DIR_IN ? BTABLE_BUF_TX : BTABLE_BUF_RX, (uint16_t)pma_addr); (void)pma_addr2; #endif diff --git a/src/portable/st/stm32_fsdev/fsdev_common.c b/src/portable/st/stm32_fsdev/fsdev_common.c index 003bcd069..7c4572a1e 100644 --- a/src/portable/st/stm32_fsdev/fsdev_common.c +++ b/src/portable/st/stm32_fsdev/fsdev_common.c @@ -81,11 +81,11 @@ uint16_t pma_align_buffer_size(uint16_t size, uint8_t* blsize, uint8_t* num_bloc if (size > 62) { block_in_bytes = 32; *blsize = 1; - *num_block = tu_div_ceil(size, 32); + *num_block = (uint8_t)tu_div_ceil(size, 32); } else { block_in_bytes = 2; *blsize = 0; - *num_block = tu_div_ceil(size, 2); + *num_block = (uint8_t)tu_div_ceil(size, 2); } return (*num_block) * block_in_bytes; diff --git a/src/portable/st/stm32_fsdev/fsdev_common.h b/src/portable/st/stm32_fsdev/fsdev_common.h index 140ff1d61..af84b8b97 100644 --- a/src/portable/st/stm32_fsdev/fsdev_common.h +++ b/src/portable/st/stm32_fsdev/fsdev_common.h @@ -345,7 +345,7 @@ TU_ATTR_ALWAYS_INLINE static inline void ep_write_clear_ctr(uint32_t ep_id, tusb uint32_t reg = FSDEV_REG->ep[ep_id].reg; reg |= U_EP_CTR_TX | U_EP_CTR_RX; reg &= U_EPREG_MASK; - reg &= ~(1 << (U_EP_CTR_TX_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); + reg &= ~(1u << (U_EP_CTR_TX_Pos + (dir == TUSB_DIR_IN ? 0u : 8u))); ep_write(ep_id, reg, false); } @@ -378,7 +378,7 @@ TU_ATTR_ALWAYS_INLINE static inline void ch_write_clear_ctr(uint32_t ch_id, tusb uint32_t reg = FSDEV_REG->ep[ch_id].reg; reg |= U_EP_CTR_TX | U_EP_CTR_RX; reg &= U_EPREG_MASK; - reg &= ~(1 << (U_EP_CTR_TX_Pos + (dir == TUSB_DIR_IN ? 8 : 0))); + reg &= ~(1u << (U_EP_CTR_TX_Pos + (dir == TUSB_DIR_IN ? 8u : 0u))); ep_write(ch_id, reg, false); } diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index 9a9c734a0..2e5a56d08 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -191,7 +191,7 @@ static void dma_setup_prepare(uint8_t rhport) { */ TU_ATTR_ALWAYS_INLINE static inline uint16_t calc_device_grxfsiz(uint16_t largest_ep_size, uint8_t ep_count) { - return 13 + 1 + 2 * ((largest_ep_size / 4) + 1) + 2 * ep_count; + return (uint16_t)(13 + 1 + 2 * ((largest_ep_size / 4) + 1) + 2 * ep_count); } static bool dfifo_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t packet_size, bool is_bulk) { @@ -203,7 +203,7 @@ static bool dfifo_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t packet_size, b TU_ASSERT(epnum < ep_count); - uint16_t fifo_size = tu_div_ceil(packet_size, 4); + uint16_t fifo_size = (uint16_t)tu_div_ceil(packet_size, 4); if (dir == TUSB_DIR_OUT) { // Calculate required size of RX FIFO const uint16_t new_sz = calc_device_grxfsiz(4 * fifo_size, ep_count); @@ -371,7 +371,7 @@ static void edpt_schedule_packets(uint8_t rhport, const uint8_t epnum, const uin num_packets = 1; } else { total_bytes = xfer->total_len; - num_packets = tu_div_ceil(total_bytes, xfer->max_size); + num_packets = (uint16_t)tu_div_ceil(total_bytes, xfer->max_size); if (num_packets == 0) { num_packets = 1; // zero length packet still count as 1 } -- cgit v1.3.1 From 5540b2a83fb83dd7f1a477e99084b1818abc2e46 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 17 Apr 2026 19:06:56 +0700 Subject: use single volatile counter --- src/portable/st/stm32_fsdev/fsdev_stm32.h | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'src/portable') diff --git a/src/portable/st/stm32_fsdev/fsdev_stm32.h b/src/portable/st/stm32_fsdev/fsdev_stm32.h index 79052b489..070aa00ec 100644 --- a/src/portable/st/stm32_fsdev/fsdev_stm32.h +++ b/src/portable/st/stm32_fsdev/fsdev_stm32.h @@ -256,10 +256,14 @@ TU_ATTR_ALWAYS_INLINE static inline void fsdev_int_disable(uint8_t rhport) { //--------------------------------------------------------------------+ #ifdef CFG_TUSB_FSDEV_32BIT -// ES0561 (STM32H503), ES0587 (STM32U535/U545) -// CTR may trigger before final PMA SRAM accesses complete on OUT transfers. -// Insert delay before reading PMA count/data. -// Max CPU frequency in MHz, used to derive conservative FSDEV PMA delay defaults. +/* Errata: Buffer description table update completes after CTR interrupt triggers + * https://www.st.com/resource/en/errata_sheet/es0561-stm32h503cbebkbrb-device-errata-stmicroelectronics.pdf + * https://www.st.com/resource/en/errata_sheet/es0587-stm32u535xx-and-stm32u545xx-device-errata-stmicroelectronics.pdf + * + * CTR may trigger before final PMA SRAM accesses complete on OUT transfers. + * Insert delay before reading PMA count/data. + * Max CPU frequency in MHz, used to derive conservative FSDEV PMA delay defaults. + */ #if CFG_TUSB_MCU == OPT_MCU_STM32H5 #define FSDEV_STM32_CPU_MHZ 250U #elif CFG_TUSB_MCU == OPT_MCU_STM32U5 @@ -283,10 +287,9 @@ TU_ATTR_ALWAYS_INLINE static inline void fsdev_int_disable(uint8_t rhport) { #endif TU_ATTR_ALWAYS_INLINE static inline void fsdev_btable_workaround_delay(bool low_speed) { - uint32_t cycle_count = low_speed ? CFG_TUSB_FSDEV_BTABLE_LS_DELAY_COUNT : CFG_TUSB_FSDEV_BTABLE_FS_DELAY_COUNT; - volatile uint32_t delay_count = cycle_count; - while (delay_count > 0U) { - delay_count--; + volatile uint32_t cycle_count = low_speed ? CFG_TUSB_FSDEV_BTABLE_LS_DELAY_COUNT : CFG_TUSB_FSDEV_BTABLE_FS_DELAY_COUNT; + while (cycle_count > 0U) { + cycle_count--; } } #endif -- cgit v1.3.1 From ce81b01eda0f9e833bbb717e6f2cebad0030afa1 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 20 Apr 2026 16:44:25 +0700 Subject: improving transfer tracking and adding support for un-armed Rx data handling --- src/portable/mentor/musb/dcd_musb.c | 88 ++++++++++++++++++++++++------------- test/hil/tinyusb.json | 3 ++ 2 files changed, 61 insertions(+), 30 deletions(-) (limited to 'src/portable') diff --git a/src/portable/mentor/musb/dcd_musb.c b/src/portable/mentor/musb/dcd_musb.c index 64f9ebacf..ad3838a09 100644 --- a/src/portable/mentor/musb/dcd_musb.c +++ b/src/portable/mentor/musb/dcd_musb.c @@ -58,15 +58,18 @@ typedef union { volatile uint32_t u32; } hw_fifo_t; -typedef struct TU_ATTR_PACKED -{ - void *buf; /* the start address of a transfer data buffer */ +typedef struct { + union { + uint8_t *buf; /* the start address of a transfer data buffer */ + tu_fifo_t *fifo; + }; uint16_t length; /* the number of bytes in the buffer */ uint16_t remaining; /* the number of bytes remaining in the buffer */ + bool armed; /* true while a transfer is posted */ + bool use_fifo; /* true: buf is tu_fifo_t*; false: buf is plain byte pointer. */ } pipe_state_t; -typedef struct -{ +typedef struct { union { tusb_control_request_t setup_packet; uint32_t setup_buffer[2]; @@ -75,7 +78,6 @@ typedef struct int8_t status_out; pipe_state_t pipe0; pipe_state_t pipe[2][TUP_DCD_ENDPOINT_MAX-1]; /* pipe[direction][endpoint number - 1] */ - uint16_t pipe_buf_is_fifo[2]; /* Bitmap. Each bit means whether 1:TU_FIFO or 0:POD. */ } dcd_data_t; static dcd_data_t _dcd; @@ -197,6 +199,7 @@ static bool handle_xfer_in(uint8_t rhport, uint_fast8_t ep_addr) { if (rem == 0 && pipe->length > 0) { pipe->buf = NULL; + pipe->armed = false; return true; } @@ -204,15 +207,13 @@ static bool handle_xfer_in(uint8_t rhport, uint_fast8_t ep_addr) { musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, epnum); const unsigned mps = ep_csr->tx_maxp; const unsigned len = TU_MIN(mps, rem); - void *buf = pipe->buf; volatile void *fifo_ptr = &musb_regs->fifo[epnum]; - // TU_LOG1(" %p mps %d len %d rem %d\r\n", buf, mps, len, rem); if (len) { - if (_dcd.pipe_buf_is_fifo[TUSB_DIR_IN] & TU_BIT(epnum_minus1)) { - tu_hwfifo_write_from_fifo(fifo_ptr, (tu_fifo_t *)buf, len, NULL); + if (pipe->use_fifo) { + tu_hwfifo_write_from_fifo(fifo_ptr, pipe->fifo, len, NULL); } else { - tu_hwfifo_write(fifo_ptr, buf, len, NULL); - pipe->buf = (uint8_t*)buf + len; + tu_hwfifo_write(fifo_ptr, pipe->buf, len, NULL); + pipe->buf += len; } pipe->remaining = rem - len; } @@ -231,11 +232,17 @@ static bool handle_xfer_out(uint8_t rhport, uint_fast8_t ep_addr) // TU_LOG1(" RXCSRL%d = %x\r\n", epnum_minus1 + 1, ep_csr->rx_csrl); //Fail gracefully. Spurious interrupt. - if (!(ep_csr->rx_csrl & MUSB_RXCSRL1_RXRDY)) return false; + if (!(ep_csr->rx_csrl & MUSB_RXCSRL1_RXRDY)) { + return false; + } - void *buf = pipe->buf; - if (buf == NULL) { - ep_csr->rx_csrl = MUSB_RXCSRL1_FLUSH; + if (!pipe->armed) { + // Packet is already ACK'd by hardware and sitting in the Rx FIFO, but no transfer is + // posted. Do NOT flush (per MUSB spec §3.3.11 FlushFIFO) - that would silently drop + // acknowledged data. Mask this endpoint's Rx interrupt so the ISR stops re-firing; + // the FIFO stays occupied so hardware NAKs further OUT tokens (natural backpressure). + // The next dcd_edpt_xfer() on this endpoint will drain the staged packet. + musb_regs->intr_rxen &= (uint16_t) ~TU_BIT(epnum); return false; } @@ -245,11 +252,11 @@ static bool handle_xfer_out(uint8_t rhport, uint_fast8_t ep_addr) const unsigned len = TU_MIN(TU_MIN(rem, mps), vld); volatile void *fifo_ptr = &musb_regs->fifo[epnum]; if (len) { - if (_dcd.pipe_buf_is_fifo[TUSB_DIR_OUT] & TU_BIT(epnum_minus1)) { - tu_hwfifo_read_to_fifo(fifo_ptr, (tu_fifo_t *)buf, len, NULL); + if (pipe->use_fifo) { + tu_hwfifo_read_to_fifo(fifo_ptr, pipe->fifo, len, NULL); } else { - tu_hwfifo_read(fifo_ptr, buf, len, NULL); - pipe->buf = (uint8_t*)buf + len; + tu_hwfifo_read(fifo_ptr, pipe->buf, len, NULL); + pipe->buf += len; } pipe->remaining = rem - len; } @@ -257,28 +264,46 @@ static bool handle_xfer_out(uint8_t rhport, uint_fast8_t ep_addr) ep_csr->rx_csrl = 0; /* Always Clear RXRDY bit */ if ((len < mps) || (rem == len)) { pipe->buf = NULL; - return NULL != buf; + pipe->armed = false; + return true; } return false; } -static bool edpt_n_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes) +static bool edpt_n_xfer(uint8_t rhport, uint8_t ep_addr, void *buffer, uint16_t total_bytes, bool use_fifo) { unsigned epnum = tu_edpt_number(ep_addr); unsigned epnum_minus1 = epnum - 1; unsigned dir_in = tu_edpt_dir(ep_addr); pipe_state_t *pipe = &_dcd.pipe[dir_in][epnum_minus1]; - pipe->buf = buffer; + if (use_fifo) { + pipe->fifo = (tu_fifo_t *) buffer; + } else { + pipe->buf = (uint8_t *) buffer; + } pipe->length = total_bytes; pipe->remaining = total_bytes; + pipe->use_fifo = use_fifo; + pipe->armed = true; if (dir_in) { handle_xfer_in(rhport, ep_addr); } else { musb_regs_t* musb_regs = MUSB_REGS(rhport); musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, epnum); - if (ep_csr->rx_csrl & MUSB_RXCSRL1_RXRDY) ep_csr->rx_csrl = 0; + + // Re-enable Rx interrupt (may have been masked by the no-buffer path in handle_xfer_out) + musb_regs->intr_rxen |= (uint16_t) TU_BIT(epnum); + + // Drain any packet staged in the Rx FIFO from a prior no-buffer interrupt + if (ep_csr->rx_csrl & MUSB_RXCSRL1_RXRDY) { + if (handle_xfer_out(rhport, ep_addr)) { + dcd_event_xfer_complete(rhport, ep_addr, + pipe->length - pipe->remaining, + XFER_RESULT_SUCCESS, false); + } + } } return true; } @@ -411,7 +436,7 @@ static void process_ep0(uint8_t rhport) return; } - /* When CSRL0 is zero, it means that completion of sending a any length packet + /* When CSRL0 is zero, it means that completion of sending any length packet * or receiving a zero length packet. */ if (req != REQUEST_TYPE_INVALID && !tu_edpt_dir(req)) { /* STATUS IN */ @@ -611,6 +636,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) { pipe->buf = NULL; pipe->length = 0; pipe->remaining = 0; + pipe->armed = false; musb_regs_t* musb = MUSB_REGS(rhport); musb_ep_csr_t* ep_csr = get_ep_csr(musb, epn); @@ -656,6 +682,7 @@ bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const *ep_desc ) pipe->buf = NULL; pipe->length = 0; pipe->remaining = 0; + pipe->armed = false; musb_regs_t* musb = MUSB_REGS(rhport); musb_ep_csr_t* ep_csr = get_ep_csr(musb, epn); @@ -722,13 +749,14 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t t musb_dcd_int_disable(rhport); if (epnum) { - _dcd.pipe_buf_is_fifo[tu_edpt_dir(ep_addr)] &= ~TU_BIT(epnum - 1); - ret = edpt_n_xfer(rhport, ep_addr, buffer, total_bytes); + ret = edpt_n_xfer(rhport, ep_addr, buffer, total_bytes, false); } else { ret = edpt0_xfer(rhport, ep_addr, buffer, total_bytes); } - if (ie) musb_dcd_int_enable(rhport); + if (ie) { + musb_dcd_int_enable(rhport); + } return ret; } @@ -744,8 +772,7 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_ TU_ASSERT(epnum); unsigned const ie = musb_dcd_get_int_enable(rhport); musb_dcd_int_disable(rhport); - _dcd.pipe_buf_is_fifo[tu_edpt_dir(ep_addr)] |= TU_BIT(epnum - 1); - ret = edpt_n_xfer(rhport, ep_addr, (uint8_t*)ff, total_bytes); + ret = edpt_n_xfer(rhport, ep_addr, ff, total_bytes, true); if (ie) musb_dcd_int_enable(rhport); return ret; } @@ -768,6 +795,7 @@ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { } else { const uint8_t is_rx = 1 - tu_edpt_dir(ep_addr); ep_csr->maxp_csr[is_rx].csrl = MUSB_CSRL_SEND_STALL(is_rx); + _dcd.pipe[tu_edpt_dir(ep_addr)][epn - 1].armed = false; } if (ie) musb_dcd_int_enable(rhport); diff --git a/test/hil/tinyusb.json b/test/hil/tinyusb.json index 92b7b21b0..5466cd534 100644 --- a/test/hil/tinyusb.json +++ b/test/hil/tinyusb.json @@ -226,6 +226,9 @@ { "name": "stm32f072disco", "uid": "3A001A001357364230353532", + "tests": { + "device": true, "host": false, "dual": false + }, "flasher": { "name": "jlink", "uid": "779541626", -- cgit v1.3.1 From 85b967c9b0d26c8dbd16fedfc07d166b8f9b77ae Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 21 Apr 2026 11:28:29 +0700 Subject: refactor interrupt handling and add `pipe_write` to fix IN ZLP issue --- src/portable/mentor/musb/dcd_musb.c | 35 +++++++++++++++++++---------------- test/hil/hil_test.py | 31 ++++++++++++++++++++----------- 2 files changed, 39 insertions(+), 27 deletions(-) (limited to 'src/portable') diff --git a/src/portable/mentor/musb/dcd_musb.c b/src/portable/mentor/musb/dcd_musb.c index ad3838a09..acd86b9e7 100644 --- a/src/portable/mentor/musb/dcd_musb.c +++ b/src/portable/mentor/musb/dcd_musb.c @@ -191,21 +191,12 @@ static void process_setup_packet(uint8_t rhport) { } } -static bool handle_xfer_in(uint8_t rhport, uint_fast8_t ep_addr) { - unsigned epnum = tu_edpt_number(ep_addr); - unsigned epnum_minus1 = epnum - 1; - pipe_state_t *pipe = &_dcd.pipe[tu_edpt_dir(ep_addr)][epnum_minus1]; - const unsigned rem = pipe->remaining; - - if (rem == 0 && pipe->length > 0) { - pipe->buf = NULL; - pipe->armed = false; - return true; - } - - musb_regs_t* musb_regs = MUSB_REGS(rhport); +// write to txfifo using pipe_state_t info +static void pipe_write(musb_regs_t* musb_regs, uint8_t epnum) { + pipe_state_t* pipe = &_dcd.pipe[TUSB_DIR_IN][epnum - 1]; musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, epnum); const unsigned mps = ep_csr->tx_maxp; + const unsigned rem = pipe->remaining; const unsigned len = TU_MIN(mps, rem); volatile void *fifo_ptr = &musb_regs->fifo[epnum]; if (len) { @@ -218,7 +209,19 @@ static bool handle_xfer_in(uint8_t rhport, uint_fast8_t ep_addr) { pipe->remaining = rem - len; } ep_csr->tx_csrl = MUSB_TXCSRL1_TXRDY; - // TU_LOG1(" TXCSRL%d = %x %d\r\n", epnum, ep_csr->tx_csrl, rem - len); +} + +// Called from the TX interrupt. If the last queued packet finished the transfer, +// signal completion; otherwise queue the next packet. +static bool handle_xfer_in(musb_regs_t* musb_regs, uint8_t epnum) { + pipe_state_t* pipe = &_dcd.pipe[TUSB_DIR_IN][epnum - 1]; + + if (pipe->remaining == 0) { + pipe->buf = NULL; + pipe->armed = false; + return true; + } + pipe_write(musb_regs, epnum); return false; } @@ -288,7 +291,7 @@ static bool edpt_n_xfer(uint8_t rhport, uint8_t ep_addr, void *buffer, uint16_t pipe->armed = true; if (dir_in) { - handle_xfer_in(rhport, ep_addr); + pipe_write(MUSB_REGS(rhport), (uint8_t) epnum); } else { musb_regs_t* musb_regs = MUSB_REGS(rhport); musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, epnum); @@ -476,7 +479,7 @@ static void process_edpt_n(uint8_t rhport, uint_fast8_t ep_addr) ep_csr->tx_csrl &= ~(MUSB_TXCSRL1_STALLED | MUSB_TXCSRL1_UNDRN); return; } - completed = handle_xfer_in(rhport, ep_addr); + completed = handle_xfer_in(musb_regs, (uint8_t) epn); } else { // TU_LOG1(" RX CSRL%d = %x\r\n", epn, ep_csr->rx_csrl); if (ep_csr->rx_csrl & MUSB_RXCSRL1_STALLED) { diff --git a/test/hil/hil_test.py b/test/hil/hil_test.py index 6f9b70e95..dfe09bf23 100755 --- a/test/hil/hil_test.py +++ b/test/hil/hil_test.py @@ -59,6 +59,7 @@ STATUS_SKIPPED = "\033[33mSkipped\033[0m" verbose = False test_only = [] build_dir = 'cmake-build' +skip_flash = False WCH_RISCV_CONTENT = """ adapter driver wlinke @@ -1248,11 +1249,15 @@ def test_example(board, f1, example): if verbose: print(f'Flashing {fw_name}.elf') - # flash firmware. It may fail randomly, retry a few times + # flash firmware (unless --skip-flash), then run the test. Both may fail randomly, + # retry a few times. start_s = time.time() + flash_ok = True for i in range(max_retry): - ret = globals()[f'flash_{board["flasher"]["name"].lower()}'](board, fw_name) - if ret.returncode == 0: + if not skip_flash: + ret = globals()[f'flash_{board["flasher"]["name"].lower()}'](board, fw_name) + flash_ok = (ret.returncode == 0) + if flash_ok: try: tret = globals()[f'test_{example.replace("/", "_")}'](board) if tret == 'skipped': @@ -1271,7 +1276,7 @@ def test_example(board, f1, example): print(f'\n Flash failed, retry {i+2}/{max_retry}', end='') time.sleep(0.5) - if ret.returncode != 0: + if not flash_ok: err_count += 1 print(f' Flash {STATUS_FAILED}', end='') @@ -1315,8 +1320,9 @@ def test_board(board): for test in test_list: err_count += test_example(board, f1, test) - # flash board_test last to disable board's usb - test_example(board, flags_on_list[0], 'device/board_test') + # flash board_test last to disable board's usb (skipped when --skip-flash is set) + if not skip_flash: + test_example(board, flags_on_list[0], 'device/board_test') return name, err_count @@ -1329,26 +1335,29 @@ def main(): global test_only global build_dir global max_retry + global skip_flash duration = time.time() parser = argparse.ArgumentParser() parser.add_argument('config_file', help='Configuration JSON file') parser.add_argument('-b', '--board', action='append', default=[], help='Boards to test, all if not specified') - parser.add_argument('-s', '--skip', action='append', default=[], help='Skip boards from test') + parser.add_argument('-s', '--skip-board', action='append', default=[], help='Skip boards from test') + parser.add_argument('-sf', '--skip-flash', action='store_true', help='Run tests without flashing firmware (use whatever is already on the board)') parser.add_argument('-t', '--test-only', action='append', default=[], help='Tests to run, all if not specified') - parser.add_argument('-B', '--build', default='cmake-build', help='Build folder name (default: cmake-build)') + parser.add_argument('-B', '--build-dir', default='cmake-build', help='Build folder name (default: cmake-build)') parser.add_argument('-r', '--retry', type=int, default=3, help='Retry count for failed tests (default: 3)') parser.add_argument('-v', '--verbose', action='store_true', help='Verbose output') args = parser.parse_args() config_file = args.config_file boards = args.board - skip_boards = args.skip + skip_boards = args.skip_board verbose = args.verbose test_only = args.test_only - build_dir = args.build + build_dir = args.build_dir max_retry = args.retry + skip_flash = args.skip_flash # if config file is not found, try to find it in the same directory as this script if not os.path.exists(config_file): @@ -1370,7 +1379,7 @@ def main(): if err_count > 0: skip_boards += [name for name, err in mret if err == 0] with open(skip_fname, 'w') as f: - f.write(' '.join(f'-s {i}' for i in skip_boards)) + f.write(' '.join(f'--skip-board {i}' for i in skip_boards)) elif os.path.exists(skip_fname): os.remove(skip_fname) -- cgit v1.3.1 From c13864dbe49b2009f9ad3be2f912ddd80a9ecd40 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 21 Apr 2026 15:28:44 +0700 Subject: optimize pipe_state_t sram for port with CFG_TUD_ENDPOINT_ONE_DIRECTION_ONLY. separate process_edpt_n() to process_epin() and process_epout() --- src/common/tusb_types.h | 10 +- src/portable/mentor/musb/dcd_musb.c | 209 ++++++++++++++++++------------------ 2 files changed, 111 insertions(+), 108 deletions(-) (limited to 'src/portable') diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index a18f9feb7..806997866 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -100,12 +100,14 @@ typedef enum { } tusb_xfer_type_t; typedef enum { - TUSB_DIR_OUT = 0, - TUSB_DIR_IN = 1, + TUSB_DIR_OUT = 0u, + TUSB_DIR_IN = 1u, +} tusb_dir_t; - TUSB_EPNUM_MASK = 0x0F, +enum { + TUSB_EPNUM_MASK = 0x0F, TUSB_DIR_IN_MASK = 0x80 -} tusb_dir_t; +}; enum { TUSB_EPSIZE_BULK_FS = 64, diff --git a/src/portable/mentor/musb/dcd_musb.c b/src/portable/mentor/musb/dcd_musb.c index acd86b9e7..bf60adbe7 100644 --- a/src/portable/mentor/musb/dcd_musb.c +++ b/src/portable/mentor/musb/dcd_musb.c @@ -69,6 +69,19 @@ typedef struct { bool use_fifo; /* true: buf is tu_fifo_t*; false: buf is plain byte pointer. */ } pipe_state_t; +// Pipe array layout (N = TUP_DCD_ENDPOINT_MAX): +// [0] : EP0 (shared between IN/OUT control stages) +// One-direction-only IPs (CFG_TUD_ENDPOINT_ONE_DIRECTION_ONLY=1): +// [1 .. n-1] : EP1..n-1 (single slot per endpoint) +// Bidirectional-capable IPs: +// [1 .. N-1 ] : EP OUT +// [N .. 2*N-2] : EP IN +#if CFG_TUD_ENDPOINT_ONE_DIRECTION_ONLY + #define MUSB_PIPE_COUNT TUP_DCD_ENDPOINT_MAX +#else + #define MUSB_PIPE_COUNT (2u * TUP_DCD_ENDPOINT_MAX - 1u) +#endif + typedef struct { union { tusb_control_request_t setup_packet; @@ -76,12 +89,27 @@ typedef struct { }; uint16_t remaining_ctrl; /* The number of bytes remaining in data stage of control transfer. */ int8_t status_out; - pipe_state_t pipe0; - pipe_state_t pipe[2][TUP_DCD_ENDPOINT_MAX-1]; /* pipe[direction][endpoint number - 1] */ + pipe_state_t pipe[MUSB_PIPE_COUNT]; } dcd_data_t; static dcd_data_t _dcd; +TU_ATTR_ALWAYS_INLINE static inline pipe_state_t* pipe_get(uint8_t epnum, tusb_dir_t epdir) { +#if CFG_TUD_ENDPOINT_ONE_DIRECTION_ONLY + (void) epdir; + return &_dcd.pipe[epnum]; +#else + if (epnum == 0) { + return &_dcd.pipe[0]; + } + size_t idx = epnum; + if (epdir == TUSB_DIR_IN) { + idx += TUP_DCD_ENDPOINT_MAX - 1u; + } + return &_dcd.pipe[idx]; +#endif +} + //-------------------------------------------------------------------- // HW FIFO Helper // Note: Index register is already set by caller @@ -176,9 +204,10 @@ static void process_setup_packet(uint8_t rhport) { _dcd.setup_buffer[0] = musb_regs->fifo[0]; _dcd.setup_buffer[1] = musb_regs->fifo[0]; - _dcd.pipe0.buf = NULL; - _dcd.pipe0.length = 0; - _dcd.pipe0.remaining = 0; + pipe_state_t* pipe0 = pipe_get(0, TUSB_DIR_OUT); + pipe0->buf = NULL; + pipe0->length = 0; + pipe0->remaining = 0; dcd_event_setup_received(rhport, (const uint8_t*)(uintptr_t)&_dcd.setup_packet, true); const unsigned len = _dcd.setup_packet.wLength; @@ -193,7 +222,7 @@ static void process_setup_packet(uint8_t rhport) { // write to txfifo using pipe_state_t info static void pipe_write(musb_regs_t* musb_regs, uint8_t epnum) { - pipe_state_t* pipe = &_dcd.pipe[TUSB_DIR_IN][epnum - 1]; + pipe_state_t* pipe = pipe_get(epnum, TUSB_DIR_IN); musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, epnum); const unsigned mps = ep_csr->tx_maxp; const unsigned rem = pipe->remaining; @@ -213,32 +242,38 @@ static void pipe_write(musb_regs_t* musb_regs, uint8_t epnum) { // Called from the TX interrupt. If the last queued packet finished the transfer, // signal completion; otherwise queue the next packet. -static bool handle_xfer_in(musb_regs_t* musb_regs, uint8_t epnum) { - pipe_state_t* pipe = &_dcd.pipe[TUSB_DIR_IN][epnum - 1]; +static void process_epin(uint8_t rhport, musb_regs_t *musb_regs, uint8_t epnum) { + musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, epnum); + if (ep_csr->tx_csrl & MUSB_TXCSRL1_STALLED) { + ep_csr->tx_csrl &= ~(MUSB_TXCSRL1_STALLED | MUSB_TXCSRL1_UNDRN); + return; // sent STALL, do nothing + } + pipe_state_t* pipe = pipe_get(epnum, TUSB_DIR_IN); if (pipe->remaining == 0) { + const uint16_t xferred_len = pipe->length; pipe->buf = NULL; pipe->armed = false; - return true; + dcd_event_xfer_complete(rhport, tu_edpt_addr(epnum, TUSB_DIR_IN), xferred_len, XFER_RESULT_SUCCESS, true); + return; } pipe_write(musb_regs, epnum); - return false; } -static bool handle_xfer_out(uint8_t rhport, uint_fast8_t ep_addr) -{ - unsigned epnum = tu_edpt_number(ep_addr); - unsigned epnum_minus1 = epnum - 1; - pipe_state_t *pipe = &_dcd.pipe[tu_edpt_dir(ep_addr)][epnum_minus1]; - musb_regs_t* musb_regs = MUSB_REGS(rhport); +static void process_epout(uint8_t rhport, musb_regs_t *musb_regs, uint8_t epnum) { musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, epnum); - // TU_LOG1(" RXCSRL%d = %x\r\n", epnum_minus1 + 1, ep_csr->rx_csrl); + if (ep_csr->rx_csrl & MUSB_RXCSRL1_STALLED) { + ep_csr->rx_csrl &= ~(MUSB_RXCSRL1_STALLED | MUSB_RXCSRL1_OVER); + return; // sent STALL, do nothing + } //Fail gracefully. Spurious interrupt. if (!(ep_csr->rx_csrl & MUSB_RXCSRL1_RXRDY)) { - return false; + return; } + pipe_state_t *pipe = pipe_get(epnum, TUSB_DIR_OUT); + if (!pipe->armed) { // Packet is already ACK'd by hardware and sitting in the Rx FIFO, but no transfer is // posted. Do NOT flush (per MUSB spec §3.3.11 FlushFIFO) - that would silently drop @@ -246,7 +281,7 @@ static bool handle_xfer_out(uint8_t rhport, uint_fast8_t ep_addr) // the FIFO stays occupied so hardware NAKs further OUT tokens (natural backpressure). // The next dcd_edpt_xfer() on this endpoint will drain the staged packet. musb_regs->intr_rxen &= (uint16_t) ~TU_BIT(epnum); - return false; + return; } const unsigned mps = ep_csr->rx_maxp; @@ -266,20 +301,20 @@ static bool handle_xfer_out(uint8_t rhport, uint_fast8_t ep_addr) ep_csr->rx_csrl = 0; /* Always Clear RXRDY bit */ if ((len < mps) || (rem == len)) { + const uint16_t xferred_len = pipe->length - pipe->remaining; pipe->buf = NULL; pipe->armed = false; - return true; + + dcd_event_xfer_complete(rhport, tu_edpt_addr(epnum, TUSB_DIR_OUT), xferred_len, XFER_RESULT_SUCCESS, true); } - return false; } static bool edpt_n_xfer(uint8_t rhport, uint8_t ep_addr, void *buffer, uint16_t total_bytes, bool use_fifo) { unsigned epnum = tu_edpt_number(ep_addr); - unsigned epnum_minus1 = epnum - 1; unsigned dir_in = tu_edpt_dir(ep_addr); - pipe_state_t *pipe = &_dcd.pipe[dir_in][epnum_minus1]; + pipe_state_t *pipe = pipe_get(epnum, dir_in); if (use_fifo) { pipe->fifo = (tu_fifo_t *) buffer; } else { @@ -296,16 +331,13 @@ static bool edpt_n_xfer(uint8_t rhport, uint8_t ep_addr, void *buffer, uint16_t musb_regs_t* musb_regs = MUSB_REGS(rhport); musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, epnum); - // Re-enable Rx interrupt (may have been masked by the no-buffer path in handle_xfer_out) + // Re-enable Rx interrupt (may have been masked by the no-buffer path in process_epout) musb_regs->intr_rxen |= (uint16_t) TU_BIT(epnum); - // Drain any packet staged in the Rx FIFO from a prior no-buffer interrupt + // Drain any packet staged in the Rx FIFO from a prior no-buffer interrupt. + // process_epout() fires dcd_event_xfer_complete() itself if the drain completes. if (ep_csr->rx_csrl & MUSB_RXCSRL1_RXRDY) { - if (handle_xfer_out(rhport, ep_addr)) { - dcd_event_xfer_complete(rhport, ep_addr, - pipe->length - pipe->remaining, - XFER_RESULT_SUCCESS, false); - } + process_epout(rhport, musb_regs, (uint8_t) epnum); } } return true; @@ -317,6 +349,7 @@ static bool edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_ TU_ASSERT(total_bytes <= 64); /* Current implementation supports for only up to 64 bytes. */ musb_regs_t* musb_regs = MUSB_REGS(rhport); musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, 0); + pipe_state_t* pipe0 = pipe_get(0, TUSB_DIR_OUT); const unsigned req = _dcd.setup_packet.bmRequestType; TU_ASSERT(req != REQUEST_TYPE_INVALID || total_bytes == 0); @@ -347,9 +380,9 @@ static bool edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_ if (dir_in) { tu_hwfifo_write(fifo_ptr, buffer, len, NULL); - _dcd.pipe0.buf = buffer + len; - _dcd.pipe0.length = len; - _dcd.pipe0.remaining = 0; + pipe0->buf = buffer + len; + pipe0->length = len; + pipe0->remaining = 0; _dcd.remaining_ctrl = rem - len; if ((len < 64) || (rem == len)) { @@ -360,19 +393,16 @@ static bool edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_ } else { ep_csr->csr0l = MUSB_CSRL0_TXRDY; /* Flush TX FIFO to return ACK. */ } - // TU_LOG1(" IN ep_csr->csr0l = %x\r\n", ep_csr->csr0l); } else { - // TU_LOG1(" OUT ep_csr->csr0l = %x\r\n", ep_csr->csr0l); - _dcd.pipe0.buf = buffer; - _dcd.pipe0.length = len; - _dcd.pipe0.remaining = len; + pipe0->buf = buffer; + pipe0->length = len; + pipe0->remaining = len; ep_csr->csr0l = MUSB_CSRL0_RXRDYC; /* Clear RX FIFO to return ACK. */ } } else if (dir_in) { - // TU_LOG1(" STATUS IN ep_csr->csr0l = %x\r\n", ep_csr->csr0l); - _dcd.pipe0.buf = NULL; - _dcd.pipe0.length = 0; - _dcd.pipe0.remaining = 0; + pipe0->buf = NULL; + pipe0->length = 0; + pipe0->remaining = 0; /* Clear RX FIFO and reverse the transaction direction */ ep_csr->csr0l = MUSB_CSRL0_RXRDYC | MUSB_CSRL0_DATAEND; } @@ -383,9 +413,9 @@ static void process_ep0(uint8_t rhport) { musb_regs_t* musb_regs = MUSB_REGS(rhport); musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, 0); + pipe_state_t* pipe0 = pipe_get(0, TUSB_DIR_OUT); uint_fast8_t csrl = ep_csr->csr0l; - // TU_LOG1(" EP0 ep_csr->csr0l = %x\r\n", csrl); // 21.1.5: endpoint 0 service routine as peripheral if (csrl & MUSB_CSRL0_STALLED) { @@ -398,13 +428,13 @@ static void process_ep0(uint8_t rhport) if (csrl & MUSB_CSRL0_SETEND) { TU_LOG1(" ABORT by the next packets\r\n"); ep_csr->csr0l = MUSB_CSRL0_SETENDC; - if (req != REQUEST_TYPE_INVALID && _dcd.pipe0.buf) { + if (req != REQUEST_TYPE_INVALID && pipe0->buf) { /* DATA stage was aborted by receiving STATUS or SETUP packet. */ - _dcd.pipe0.buf = NULL; + pipe0->buf = NULL; _dcd.setup_packet.bmRequestType = REQUEST_TYPE_INVALID; dcd_event_xfer_complete(rhport, req & TUSB_DIR_IN_MASK, - _dcd.pipe0.length - _dcd.pipe0.remaining, + pipe0->length - pipe0->remaining, XFER_RESULT_SUCCESS, true); } req = REQUEST_TYPE_INVALID; @@ -419,21 +449,21 @@ static void process_ep0(uint8_t rhport) process_setup_packet(rhport); return; } - if (_dcd.pipe0.buf) { + if (pipe0->buf) { /* DATA OUT */ const unsigned vld = ep_csr->count0; - const unsigned rem = _dcd.pipe0.remaining; + const unsigned rem = pipe0->remaining; const unsigned len = TU_MIN(TU_MIN(rem, 64), vld); volatile void *fifo_ptr = &musb_regs->fifo[0]; - tu_hwfifo_read(fifo_ptr, _dcd.pipe0.buf, len, NULL); + tu_hwfifo_read(fifo_ptr, pipe0->buf, len, NULL); - _dcd.pipe0.remaining = rem - len; + pipe0->remaining = rem - len; _dcd.remaining_ctrl -= len; - _dcd.pipe0.buf = NULL; + pipe0->buf = NULL; dcd_event_xfer_complete(rhport, tu_edpt_addr(0, TUSB_DIR_OUT), - _dcd.pipe0.length - _dcd.pipe0.remaining, + pipe0->length - pipe0->remaining, XFER_RESULT_SUCCESS, true); } return; @@ -450,49 +480,16 @@ static void process_ep0(uint8_t rhport) _dcd.setup_packet.bmRequestType = REQUEST_TYPE_INVALID; dcd_event_xfer_complete(rhport, tu_edpt_addr(0, TUSB_DIR_IN), - _dcd.pipe0.length - _dcd.pipe0.remaining, + pipe0->length - pipe0->remaining, XFER_RESULT_SUCCESS, true); return; } - if (_dcd.pipe0.buf) { + if (pipe0->buf) { /* DATA IN */ - _dcd.pipe0.buf = NULL; + pipe0->buf = NULL; dcd_event_xfer_complete(rhport, tu_edpt_addr(0, TUSB_DIR_IN), - _dcd.pipe0.length - _dcd.pipe0.remaining, - XFER_RESULT_SUCCESS, true); - } -} - -static void process_edpt_n(uint8_t rhport, uint_fast8_t ep_addr) -{ - bool completed; - const unsigned dir_in = tu_edpt_dir(ep_addr); - const unsigned epn = tu_edpt_number(ep_addr); - const unsigned epn_minus1 = epn - 1; - - musb_regs_t* musb_regs = MUSB_REGS(rhport); - musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, epn); - if (dir_in) { - // TU_LOG1(" TX CSRL%d = %x\r\n", epn, ep_csr->tx_csrl); - if (ep_csr->tx_csrl & MUSB_TXCSRL1_STALLED) { - ep_csr->tx_csrl &= ~(MUSB_TXCSRL1_STALLED | MUSB_TXCSRL1_UNDRN); - return; - } - completed = handle_xfer_in(musb_regs, (uint8_t) epn); - } else { - // TU_LOG1(" RX CSRL%d = %x\r\n", epn, ep_csr->rx_csrl); - if (ep_csr->rx_csrl & MUSB_RXCSRL1_STALLED) { - ep_csr->rx_csrl &= ~(MUSB_RXCSRL1_STALLED | MUSB_RXCSRL1_OVER); - return; - } - completed = handle_xfer_out(rhport, ep_addr); - } - - if (completed) { - pipe_state_t *pipe = &_dcd.pipe[dir_in][epn_minus1]; - dcd_event_xfer_complete(rhport, ep_addr, - pipe->length - pipe->remaining, + pipe0->length - pipe0->remaining, XFER_RESULT_SUCCESS, true); } } @@ -509,8 +506,9 @@ static void process_bus_reset(uint8_t rhport) { /* When bmRequestType is REQUEST_TYPE_INVALID(0xFF), a control transfer state is SETUP or STATUS stage. */ _dcd.setup_packet.bmRequestType = REQUEST_TYPE_INVALID; _dcd.status_out = 0; - /* When pipe0.buf has not NULL, DATA stage works in progress. */ - _dcd.pipe0.buf = NULL; + /* When EP0 pipe buf has not NULL, DATA stage works in progress. */ + pipe_state_t* pipe0 = pipe_get(0, TUSB_DIR_OUT); + pipe0->buf = NULL; musb->intr_txen = 1; /* Enable only EP0 */ musb->intr_rxen = 0; @@ -578,10 +576,11 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) (void)dev_addr; musb_regs_t* musb_regs = MUSB_REGS(rhport); musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, 0); + pipe_state_t* pipe0 = pipe_get(0, TUSB_DIR_OUT); - _dcd.pipe0.buf = NULL; - _dcd.pipe0.length = 0; - _dcd.pipe0.remaining = 0; + pipe0->buf = NULL; + pipe0->length = 0; + pipe0->remaining = 0; /* Clear RX FIFO to return ACK. */ ep_csr->csr0l = MUSB_CSRL0_RXRDYC | MUSB_CSRL0_DATAEND; } @@ -635,7 +634,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) { const unsigned dir_in = tu_edpt_dir(ep_addr); const unsigned mps = tu_edpt_packet_size(ep_desc); - pipe_state_t *pipe = &_dcd.pipe[dir_in][epn - 1]; + pipe_state_t *pipe = pipe_get(epn, dir_in); pipe->buf = NULL; pipe->length = 0; pipe->remaining = 0; @@ -681,7 +680,7 @@ bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const *ep_desc ) unsigned const ie = musb_dcd_get_int_enable(rhport); musb_dcd_int_disable(rhport); - pipe_state_t *pipe = &_dcd.pipe[dir_in][epn - 1]; + pipe_state_t *pipe = pipe_get(epn, dir_in); pipe->buf = NULL; pipe->length = 0; pipe->remaining = 0; @@ -792,13 +791,15 @@ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { if (0 == epn) { if (!ep_addr) { /* Ignore EP80 */ _dcd.setup_packet.bmRequestType = REQUEST_TYPE_INVALID; - _dcd.pipe0.buf = NULL; + pipe_state_t* pipe0 = pipe_get(0, TUSB_DIR_OUT); + pipe0->buf = NULL; ep_csr->csr0l = MUSB_CSRL0_STALL; } } else { const uint8_t is_rx = 1 - tu_edpt_dir(ep_addr); ep_csr->maxp_csr[is_rx].csrl = MUSB_CSRL_SEND_STALL(is_rx); - _dcd.pipe[tu_edpt_dir(ep_addr)][epn - 1].armed = false; + pipe_state_t* pipe = pipe_get(epn, tu_edpt_dir(ep_addr)); + pipe->armed = false; } if (ie) musb_dcd_int_enable(rhport); @@ -858,16 +859,16 @@ void dcd_int_handler(uint8_t rhport) { intr_tx &= ~TU_BIT(0); } while (intr_tx) { - unsigned const num = __builtin_ctz(intr_tx); - process_edpt_n(rhport, tu_edpt_addr(num, TUSB_DIR_IN)); - intr_tx &= ~TU_BIT(num); + const unsigned epnum = __builtin_ctz(intr_tx); + process_epin(rhport, musb_regs, epnum); + intr_tx &= ~TU_BIT(epnum); } intr_rx &= musb_regs->intr_rxen; /* Clear disabled interrupts */ while (intr_rx) { - unsigned const num = __builtin_ctz(intr_rx); - process_edpt_n(rhport, tu_edpt_addr(num, TUSB_DIR_OUT)); - intr_rx &= ~TU_BIT(num); + unsigned const epnum = __builtin_ctz(intr_rx); + process_epout(rhport, musb_regs, epnum); + intr_rx &= ~TU_BIT(epnum); } musb_regs->index = saved_index; // restore endpoint index -- cgit v1.3.1 From 100cfd6360ddd0c94a0aaeaa2da05449c0648dc1 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 21 Apr 2026 16:36:31 +0700 Subject: minor clean up --- src/portable/mentor/musb/dcd_musb.c | 48 ++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 27 deletions(-) (limited to 'src/portable') diff --git a/src/portable/mentor/musb/dcd_musb.c b/src/portable/mentor/musb/dcd_musb.c index bf60adbe7..283d8b257 100644 --- a/src/portable/mentor/musb/dcd_musb.c +++ b/src/portable/mentor/musb/dcd_musb.c @@ -221,8 +221,7 @@ static void process_setup_packet(uint8_t rhport) { } // write to txfifo using pipe_state_t info -static void pipe_write(musb_regs_t* musb_regs, uint8_t epnum) { - pipe_state_t* pipe = pipe_get(epnum, TUSB_DIR_IN); +static void pipe_write(musb_regs_t* musb_regs, pipe_state_t* pipe, uint8_t epnum) { musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, epnum); const unsigned mps = ep_csr->tx_maxp; const unsigned rem = pipe->remaining; @@ -257,7 +256,7 @@ static void process_epin(uint8_t rhport, musb_regs_t *musb_regs, uint8_t epnum) dcd_event_xfer_complete(rhport, tu_edpt_addr(epnum, TUSB_DIR_IN), xferred_len, XFER_RESULT_SUCCESS, true); return; } - pipe_write(musb_regs, epnum); + pipe_write(musb_regs, pipe, epnum); } static void process_epout(uint8_t rhport, musb_regs_t *musb_regs, uint8_t epnum) { @@ -309,35 +308,34 @@ static void process_epout(uint8_t rhport, musb_regs_t *musb_regs, uint8_t epnum) } } -static bool edpt_n_xfer(uint8_t rhport, uint8_t ep_addr, void *buffer, uint16_t total_bytes, bool use_fifo) -{ - unsigned epnum = tu_edpt_number(ep_addr); - unsigned dir_in = tu_edpt_dir(ep_addr); +static bool edpt_n_xfer(uint8_t rhport, uint8_t ep_addr, void *buffer, uint16_t total_bytes, bool use_fifo) { + const uint8_t epnum = tu_edpt_number(ep_addr); + const unsigned dir_in = tu_edpt_dir(ep_addr); pipe_state_t *pipe = pipe_get(epnum, dir_in); if (use_fifo) { - pipe->fifo = (tu_fifo_t *) buffer; + pipe->fifo = (tu_fifo_t *)buffer; } else { - pipe->buf = (uint8_t *) buffer; + pipe->buf = (uint8_t *)buffer; } - pipe->length = total_bytes; - pipe->remaining = total_bytes; - pipe->use_fifo = use_fifo; - pipe->armed = true; + pipe->length = total_bytes; + pipe->remaining = total_bytes; + pipe->use_fifo = use_fifo; + pipe->armed = true; + + musb_regs_t *musb_regs = MUSB_REGS(rhport); + musb_ep_csr_t *ep_csr = get_ep_csr(musb_regs, epnum); if (dir_in) { - pipe_write(MUSB_REGS(rhport), (uint8_t) epnum); + pipe_write(musb_regs, pipe, epnum); } else { - musb_regs_t* musb_regs = MUSB_REGS(rhport); - musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, epnum); - // Re-enable Rx interrupt (may have been masked by the no-buffer path in process_epout) - musb_regs->intr_rxen |= (uint16_t) TU_BIT(epnum); + musb_regs->intr_rxen |= (uint16_t)TU_BIT(epnum); // Drain any packet staged in the Rx FIFO from a prior no-buffer interrupt. // process_epout() fires dcd_event_xfer_complete() itself if the drain completes. if (ep_csr->rx_csrl & MUSB_RXCSRL1_RXRDY) { - process_epout(rhport, musb_regs, (uint8_t) epnum); + process_epout(rhport, musb_regs, epnum); } } return true; @@ -622,19 +620,15 @@ void dcd_sof_enable(uint8_t rhport, bool en) //--------------------------------------------------------------------+ // Endpoint API //--------------------------------------------------------------------+ -// static void edpt_setup(musb_regs_t* musb, uint8_t ep_addr, uint8_t ep_type, uint16_t ep_size){ -// const unsigned epn = tu_edpt_number(ep_addr); -// const unsigned dir_in = tu_edpt_dir(ep_addr); -// } // Configure endpoint's registers according to descriptor bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) { const unsigned ep_addr = ep_desc->bEndpointAddress; const unsigned epn = tu_edpt_number(ep_addr); - const unsigned dir_in = tu_edpt_dir(ep_addr); + const unsigned epdir = tu_edpt_dir(ep_addr); const unsigned mps = tu_edpt_packet_size(ep_desc); - pipe_state_t *pipe = pipe_get(epn, dir_in); + pipe_state_t *pipe = pipe_get(epn, epdir); pipe->buf = NULL; pipe->length = 0; pipe->remaining = 0; @@ -642,13 +636,13 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) { musb_regs_t* musb = MUSB_REGS(rhport); musb_ep_csr_t* ep_csr = get_ep_csr(musb, epn); - const uint8_t is_rx = 1 - dir_in; + const uint8_t is_rx = (1 - epdir); musb_ep_maxp_csr_t* maxp_csr = &ep_csr->maxp_csr[is_rx]; maxp_csr->maxp = mps; maxp_csr->csrh = 0; #if MUSB_CFG_SHARED_FIFO - if (dir_in) { + if (epdir) { maxp_csr->csrh |= MUSB_CSRH_TX_MODE; } #endif -- cgit v1.3.1 From d0c550cadceff3fdf30060f4ac0ebf919e5934a1 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 21 Apr 2026 19:44:10 +0700 Subject: enable double buffer for tm4c --- hw/bsp/tm4c/family.c | 8 +++++++ src/portable/mentor/musb/dcd_musb.c | 43 ++++++++++++++++++++++++++---------- src/portable/mentor/musb/musb_type.h | 2 +- test/hil/hil_test.py | 2 +- 4 files changed, 41 insertions(+), 14 deletions(-) (limited to 'src/portable') diff --git a/hw/bsp/tm4c/family.c b/hw/bsp/tm4c/family.c index 6988a264e..c5e4bd64e 100644 --- a/hw/bsp/tm4c/family.c +++ b/hw/bsp/tm4c/family.c @@ -58,6 +58,14 @@ static void board_button_init(GPIOA_Type* port, uint8_t PinMsk) { /* Set direction */ port->DIR &= ~PinMsk; + + /* Enable internal pull so the idle state is deterministic. LaunchPad buttons + * connect the pin to GND when pressed (active-low) and require a pull-up. */ +#if BUTTON_STATE_ACTIVE == 0 + port->PUR |= PinMsk; +#else + port->PDR |= PinMsk; +#endif } static void board_led_init(GPIOA_Type* port, uint8_t PinMsk, uint8_t dirmsk) { diff --git a/src/portable/mentor/musb/dcd_musb.c b/src/portable/mentor/musb/dcd_musb.c index 283d8b257..02d9c2f66 100644 --- a/src/portable/mentor/musb/dcd_musb.c +++ b/src/portable/mentor/musb/dcd_musb.c @@ -140,7 +140,6 @@ TU_ATTR_ALWAYS_INLINE static inline void hwfifo_reset(musb_regs_t* musb, unsigne TU_ATTR_ALWAYS_INLINE static inline bool hwfifo_config(musb_regs_t* musb, unsigned epnum, unsigned is_rx, unsigned mps, bool double_packet) { - (void) epnum; uint8_t ffsize = hwfifo_byte2size(mps); mps = 8 << ffsize; // round up to the next power of 2 @@ -153,6 +152,13 @@ TU_ATTR_ALWAYS_INLINE static inline bool hwfifo_config(musb_regs_t* musb, unsign musb->fifo_addr[is_rx] = alloced_fifo_bytes / 8; musb->fifo_size[is_rx] = ffsize; + volatile uint16_t* dp_disable = is_rx ? &musb->rx_doulbe_packet_disable : &musb->tx_double_packet_disable; + if (double_packet) { + *dp_disable &= ~(1u << epnum); + } else { + *dp_disable |= (1u << epnum); + } + alloced_fifo_bytes += mps; return true; } @@ -167,17 +173,22 @@ TU_ATTR_ALWAYS_INLINE static inline void hwfifo_reset(musb_regs_t* musb, unsigne TU_ATTR_ALWAYS_INLINE static inline bool hwfifo_config(musb_regs_t* musb, unsigned epnum, unsigned is_rx, unsigned mps, bool double_packet) { (void) epnum; (void) mps; - if (!double_packet) { - #if defined(TUP_USBIP_MUSB_ADI) - musb->indexed_csr.maxp_csr[is_rx].csrh |= MUSB_CSRH_DISABLE_DOUBLE_PACKET(is_rx); - #else - if (is_rx) { - musb->rx_doulbe_packet_disable |= 1u << epnum; - } else { - musb->tx_double_packet_disable |= 1u << epnum; - } - #endif + + #if defined(TUP_USBIP_MUSB_ADI) + volatile uint8_t* csrh = &musb->indexed_csr.maxp_csr[is_rx].csrh; + if (double_packet) { + *csrh &= ~MUSB_CSRH_DISABLE_DOUBLE_PACKET; + } else { + *csrh |= MUSB_CSRH_DISABLE_DOUBLE_PACKET; } + #else + volatile uint16_t* dp_disable = is_rx ? &musb->rx_doulbe_packet_disable : &musb->tx_double_packet_disable; + if (double_packet) { + *dp_disable &= ~(1u << epnum); + } else { + *dp_disable |= (1u << epnum); + } + #endif return true; } @@ -250,6 +261,14 @@ static void process_epin(uint8_t rhport, musb_regs_t *musb_regs, uint8_t epnum) pipe_state_t* pipe = pipe_get(epnum, TUSB_DIR_IN); if (pipe->remaining == 0) { + // All bytes have been loaded into the FIFO. With double-packet buffering a + // second packet may still be waiting in the FIFO when this IRQ fires (the + // hardware signals TXRDY clear as soon as a slot frees, not when the wire + // transfer finishes). Defer completion until FIFONE == 0 so we don't emit + // a duplicate xfer_complete before the final packet has been sent. + if (ep_csr->tx_csrl & MUSB_TXCSRL1_FIFONE) { + return; + } const uint16_t xferred_len = pipe->length; pipe->buf = NULL; pipe->armed = false; @@ -649,7 +668,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) { hwfifo_flush(musb, epn, is_rx, true); - TU_ASSERT(hwfifo_config(musb, epn, is_rx, mps, false)); + TU_ASSERT(hwfifo_config(musb, epn, is_rx, mps, ep_desc->bmAttributes.xfer == TUSB_XFER_BULK)); musb->intren_ep[is_rx] |= TU_BIT(epn); return true; diff --git a/src/portable/mentor/musb/musb_type.h b/src/portable/mentor/musb/musb_type.h index b2f6492fa..6a85d2ca8 100644 --- a/src/portable/mentor/musb/musb_type.h +++ b/src/portable/mentor/musb/musb_type.h @@ -336,7 +336,7 @@ TU_ATTR_ALWAYS_INLINE static inline musb_ep_csr_t* get_ep_csr(musb_regs_t* musb_ #define MUSB_CSRL_CLEAR_DATA_TOGGLE(_rx) (1u << ((_rx) ? 7 : 6)) // 0x13, 0x17: TX/RX CSRH -#define MUSB_CSRH_DISABLE_DOUBLE_PACKET(_rx) (1u << 1) +#define MUSB_CSRH_DISABLE_DOUBLE_PACKET (1u << 1) #define MUSB_CSRH_TX_MODE (1u << 5) // 1 = TX, 0 = RX. only relevant for SHARED FIFO #define MUSB_CSRH_ISO (1u << 6) diff --git a/test/hil/hil_test.py b/test/hil/hil_test.py index dfe09bf23..58116fb67 100755 --- a/test/hil/hil_test.py +++ b/test/hil/hil_test.py @@ -1209,7 +1209,7 @@ device_tests = [ 'device/printer_to_cdc', 'device/midi_test', 'device/mtp', - # 'device/net_lwip_webserver' + 'device/net_lwip_webserver' ] dual_tests = [ -- cgit v1.3.1 From 8513c50231e1935657737b42a739e96c6d0dd154 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 22 Apr 2026 11:53:02 +0700 Subject: musb implement double buffer for tx --- examples/device/cdc_msc/src/usb_descriptors.c | 22 +++++++--- examples/device/dfu/skip.txt | 1 - .../net_lwip_webserver/src/usb_descriptors.c | 10 ++++- src/portable/mentor/musb/dcd_musb.c | 49 +++++++++++++--------- src/portable/mentor/musb/musb_type.h | 10 +++++ 5 files changed, 64 insertions(+), 28 deletions(-) (limited to 'src/portable') diff --git a/examples/device/cdc_msc/src/usb_descriptors.c b/examples/device/cdc_msc/src/usb_descriptors.c index b738e7d12..5dc80dee3 100644 --- a/examples/device/cdc_msc/src/usb_descriptors.c +++ b/examples/device/cdc_msc/src/usb_descriptors.c @@ -105,12 +105,22 @@ enum { #elif CFG_TUD_ENDPOINT_ONE_DIRECTION_ONLY // MCUs that don't support a same endpoint number with different direction IN and OUT defined in tusb_mcu.h // e.g EP1 OUT & EP1 IN cannot exist together - #define EPNUM_CDC_NOTIF 0x81 - #define EPNUM_CDC_OUT 0x02 - #define EPNUM_CDC_IN 0x83 - - #define EPNUM_MSC_OUT 0x04 - #define EPNUM_MSC_IN 0x85 + #if TU_CHECK_MCU(OPT_MCU_MAX32650, OPT_MCU_MAX32666, OPT_MCU_MAX32690, OPT_MCU_MAX78002) + // Put bulk on EP>=8 so the 2048/4096-byte FIFOs can back double packet buffering + #define EPNUM_CDC_NOTIF 0x81 + #define EPNUM_CDC_OUT 0x08 + #define EPNUM_CDC_IN 0x89 + + #define EPNUM_MSC_OUT 0x0A + #define EPNUM_MSC_IN 0x8B + #else + #define EPNUM_CDC_NOTIF 0x81 + #define EPNUM_CDC_OUT 0x02 + #define EPNUM_CDC_IN 0x83 + + #define EPNUM_MSC_OUT 0x04 + #define EPNUM_MSC_IN 0x85 + #endif #else #define EPNUM_CDC_NOTIF 0x81 diff --git a/examples/device/dfu/skip.txt b/examples/device/dfu/skip.txt index 79d3da9d2..ccff857ac 100644 --- a/examples/device/dfu/skip.txt +++ b/examples/device/dfu/skip.txt @@ -1,3 +1,2 @@ -mcu:TM4C mcu:BCM2835 family:espressif diff --git a/examples/device/net_lwip_webserver/src/usb_descriptors.c b/examples/device/net_lwip_webserver/src/usb_descriptors.c index 8cfef41a6..e97b103f9 100644 --- a/examples/device/net_lwip_webserver/src/usb_descriptors.c +++ b/examples/device/net_lwip_webserver/src/usb_descriptors.c @@ -122,11 +122,19 @@ const uint8_t *tud_descriptor_device_cb(void) { #define EPNUM_NET_IN 0x81 #elif CFG_TUD_ENDPOINT_ONE_DIRECTION_ONLY -// MCUs that don't support a same endpoint number with different direction IN and OUT defined in tusb_mcu.h +// MCUs that don't support the same endpoint number with different direction IN and OUT defined in tusb_mcu.h // e.g EP1 OUT & EP1 IN cannot exist together + +#if TU_CHECK_MCU(OPT_MCU_MAX32650, OPT_MCU_MAX32666, OPT_MCU_MAX32690, OPT_MCU_MAX78002) +// endpoint 8,9 has FIFO of 2048 bytes +#define EPNUM_NET_NOTIF 0x81 +#define EPNUM_NET_OUT 0x08 +#define EPNUM_NET_IN 0x89 +#else #define EPNUM_NET_NOTIF 0x81 #define EPNUM_NET_OUT 0x02 #define EPNUM_NET_IN 0x83 +#endif #else #define EPNUM_NET_NOTIF 0x81 diff --git a/src/portable/mentor/musb/dcd_musb.c b/src/portable/mentor/musb/dcd_musb.c index 02d9c2f66..667102bc5 100644 --- a/src/portable/mentor/musb/dcd_musb.c +++ b/src/portable/mentor/musb/dcd_musb.c @@ -172,9 +172,15 @@ TU_ATTR_ALWAYS_INLINE static inline void hwfifo_reset(musb_regs_t* musb, unsigne TU_ATTR_ALWAYS_INLINE static inline bool hwfifo_config(musb_regs_t* musb, unsigned epnum, unsigned is_rx, unsigned mps, bool double_packet) { - (void) epnum; (void) mps; + (void) mps; #if defined(TUP_USBIP_MUSB_ADI) + // AnalogDevice FIFO sizes: EP1..7 = 512 B, EP8..9 = 2048 B, EP10..11 = 4096 B. + // DPB requires FIFO >= 2 * MPS. For HS bulk (MPS=512) only EP >= 8 qualifies. + // Force single-buffered on EP < 8 even if the caller requested DPB. + if (epnum < 8 && (musb->power & MUSB_POWER_HSMODE)) { + double_packet = false; + } volatile uint8_t* csrh = &musb->indexed_csr.maxp_csr[is_rx].csrh; if (double_packet) { *csrh &= ~MUSB_CSRH_DISABLE_DOUBLE_PACKET; @@ -234,7 +240,7 @@ static void process_setup_packet(uint8_t rhport) { // write to txfifo using pipe_state_t info static void pipe_write(musb_regs_t* musb_regs, pipe_state_t* pipe, uint8_t epnum) { musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, epnum); - const unsigned mps = ep_csr->tx_maxp; + const unsigned mps = ep_csr->tx_maxp & MUSB_TXMAXP_PACKET_SIZE_MASK; const unsigned rem = pipe->remaining; const unsigned len = TU_MIN(mps, rem); volatile void *fifo_ptr = &musb_regs->fifo[epnum]; @@ -260,7 +266,9 @@ static void process_epin(uint8_t rhport, musb_regs_t *musb_regs, uint8_t epnum) } pipe_state_t* pipe = pipe_get(epnum, TUSB_DIR_IN); - if (pipe->remaining == 0) { + if (pipe->remaining > 0) { + pipe_write(musb_regs, pipe, epnum); + } else { // All bytes have been loaded into the FIFO. With double-packet buffering a // second packet may still be waiting in the FIFO when this IRQ fires (the // hardware signals TXRDY clear as soon as a slot frees, not when the wire @@ -273,12 +281,10 @@ static void process_epin(uint8_t rhport, musb_regs_t *musb_regs, uint8_t epnum) pipe->buf = NULL; pipe->armed = false; dcd_event_xfer_complete(rhport, tu_edpt_addr(epnum, TUSB_DIR_IN), xferred_len, XFER_RESULT_SUCCESS, true); - return; } - pipe_write(musb_regs, pipe, epnum); } -static void process_epout(uint8_t rhport, musb_regs_t *musb_regs, uint8_t epnum) { +static void process_epout(uint8_t rhport, musb_regs_t *musb_regs, uint8_t epnum, bool is_isr) { musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, epnum); if (ep_csr->rx_csrl & MUSB_RXCSRL1_STALLED) { ep_csr->rx_csrl &= ~(MUSB_RXCSRL1_STALLED | MUSB_RXCSRL1_OVER); @@ -302,7 +308,7 @@ static void process_epout(uint8_t rhport, musb_regs_t *musb_regs, uint8_t epnum) return; } - const unsigned mps = ep_csr->rx_maxp; + const unsigned mps = ep_csr->rx_maxp & MUSB_RXMAXP_PACKET_SIZE_MASK; const unsigned rem = pipe->remaining; const unsigned vld = ep_csr->rx_count; const unsigned len = TU_MIN(TU_MIN(rem, mps), vld); @@ -323,11 +329,11 @@ static void process_epout(uint8_t rhport, musb_regs_t *musb_regs, uint8_t epnum) pipe->buf = NULL; pipe->armed = false; - dcd_event_xfer_complete(rhport, tu_edpt_addr(epnum, TUSB_DIR_OUT), xferred_len, XFER_RESULT_SUCCESS, true); + dcd_event_xfer_complete(rhport, tu_edpt_addr(epnum, TUSB_DIR_OUT), xferred_len, XFER_RESULT_SUCCESS, is_isr); } } -static bool edpt_n_xfer(uint8_t rhport, uint8_t ep_addr, void *buffer, uint16_t total_bytes, bool use_fifo) { +static bool edpt_n_xfer(uint8_t rhport, uint8_t ep_addr, void *buffer, uint16_t total_bytes, bool use_fifo, bool is_isr) { const uint8_t epnum = tu_edpt_number(ep_addr); const unsigned dir_in = tu_edpt_dir(ep_addr); @@ -354,13 +360,13 @@ static bool edpt_n_xfer(uint8_t rhport, uint8_t ep_addr, void *buffer, uint16_t // Drain any packet staged in the Rx FIFO from a prior no-buffer interrupt. // process_epout() fires dcd_event_xfer_complete() itself if the drain completes. if (ep_csr->rx_csrl & MUSB_RXCSRL1_RXRDY) { - process_epout(rhport, musb_regs, epnum); + process_epout(rhport, musb_regs, epnum, is_isr); } } return true; } -static bool edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes) +static bool edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes, bool is_isr) { (void)rhport; TU_ASSERT(total_bytes <= 64); /* Current implementation supports for only up to 64 bytes. */ @@ -380,7 +386,7 @@ static bool edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_ // TU_LOG1(" STATUS OUT ep_csr->csr0l = %x\r\n", ep_csr->csr0l); _dcd.status_out = 0; if (req == REQUEST_TYPE_INVALID) { - dcd_event_xfer_complete(rhport, ep_addr, total_bytes, XFER_RESULT_SUCCESS, false); + dcd_event_xfer_complete(rhport, ep_addr, total_bytes, XFER_RESULT_SUCCESS, is_isr); } else { /* The next setup packet has already been received, it aborts * invoking callback function to avoid confusing TUSB stack. */ @@ -755,18 +761,16 @@ void dcd_edpt_close_all(uint8_t rhport) // Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) { - (void) is_isr; (void)rhport; bool ret; - // TU_LOG1("X %x %d\r\n", ep_addr, total_bytes); unsigned const epnum = tu_edpt_number(ep_addr); unsigned const ie = musb_dcd_get_int_enable(rhport); musb_dcd_int_disable(rhport); if (epnum) { - ret = edpt_n_xfer(rhport, ep_addr, buffer, total_bytes, false); + ret = edpt_n_xfer(rhport, ep_addr, buffer, total_bytes, false, is_isr); } else { - ret = edpt0_xfer(rhport, ep_addr, buffer, total_bytes); + ret = edpt0_xfer(rhport, ep_addr, buffer, total_bytes, is_isr); } if (ie) { @@ -779,15 +783,13 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t t // - optional, however, must be listed in usbd.c bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes, bool is_isr) { - (void) is_isr; (void)rhport; bool ret; - // TU_LOG1("X %x %d\r\n", ep_addr, total_bytes); unsigned const epnum = tu_edpt_number(ep_addr); TU_ASSERT(epnum); unsigned const ie = musb_dcd_get_int_enable(rhport); musb_dcd_int_disable(rhport); - ret = edpt_n_xfer(rhport, ep_addr, ff, total_bytes, true); + ret = edpt_n_xfer(rhport, ep_addr, ff, total_bytes, true, is_isr); if (ie) musb_dcd_int_enable(rhport); return ret; } @@ -871,16 +873,23 @@ void dcd_int_handler(uint8_t rhport) { process_ep0(rhport); intr_tx &= ~TU_BIT(0); } + while (intr_tx) { const unsigned epnum = __builtin_ctz(intr_tx); process_epin(rhport, musb_regs, epnum); intr_tx &= ~TU_BIT(epnum); + + // for Double-buffered endpoint: TxPktRdy is cleared and interrupt is generated when we write the first packet + uint_fast8_t new_intr_tx = musb_regs->intr_tx; + new_intr_tx &= musb_regs->intr_txen; + + intr_tx |= new_intr_tx; } intr_rx &= musb_regs->intr_rxen; /* Clear disabled interrupts */ while (intr_rx) { unsigned const epnum = __builtin_ctz(intr_rx); - process_epout(rhport, musb_regs, epnum); + process_epout(rhport, musb_regs, epnum, true); intr_rx &= ~TU_BIT(epnum); } diff --git a/src/portable/mentor/musb/musb_type.h b/src/portable/mentor/musb/musb_type.h index 6a85d2ca8..dd1cd6ded 100644 --- a/src/portable/mentor/musb/musb_type.h +++ b/src/portable/mentor/musb/musb_type.h @@ -566,6 +566,16 @@ TU_ATTR_ALWAYS_INLINE static inline musb_ep_csr_t* get_ep_csr(musb_regs_t* musb_ #define MUSB_NAKLMT_NAKLMT_M 0x001F // EP0 NAK Limit #define MUSB_NAKLMT_NAKLMT_S 0 +//***************************************************************************** +// +// The following are defines for the bit fields in the MUSB_O_TXMAXP / MUSB_O_RXMAXP +// registers. Bits [10:0] carry the maximum packet size; bits [15:11] carry +// numpackminus1 (HB-iso / HS-bulk multiplier - 1). +// +//***************************************************************************** +#define MUSB_TXMAXP_PACKET_SIZE_MASK 0x07FFu +#define MUSB_RXMAXP_PACKET_SIZE_MASK 0x07FFu + //***************************************************************************** // // The following are defines for the bit fields in the MUSB_O_TXCSRL1 register. -- cgit v1.3.1 From 776f613dbf9ebb14e7dab6529db96a273157a943 Mon Sep 17 00:00:00 2001 From: "igor.masar" Date: Wed, 22 Apr 2026 14:22:23 +0200 Subject: Add ESP32-S31 as a supported MCU in TinyUSB --- README.rst | 2 ++ hw/bsp/espressif/boards/family.c | 8 ++------ hw/bsp/espressif/family.cmake | 17 ++++++++++++++--- src/common/tusb_mcu.h | 18 +++++++++++++++++- src/portable/synopsys/dwc2/dcd_dwc2.c | 10 ++++++---- src/portable/synopsys/dwc2/dwc2_esp32.h | 12 ++++++++++++ src/tusb_option.h | 1 + 7 files changed, 54 insertions(+), 14 deletions(-) (limited to 'src/portable') diff --git a/README.rst b/README.rst index 6be9d4873..04998abaa 100644 --- a/README.rst +++ b/README.rst @@ -157,6 +157,8 @@ Supported CPUs | Espressif | S2, S3, H4 | ✔ | ✔ | ✖ | dwc2 | | | ESP32 +-----------------------------+--------+------+-----------+------------------------+--------------------+ | | P4 | ✔ | ✔ | ✔ | dwc2 | | +| +-----------------------------+--------+------+-----------+------------------------+--------------------+ +| | S31 | ✔ | ✔ | ✔ | dwc2 | | +--------------+-----------------------------+--------+------+-----------+------------------------+--------------------+ | GigaDevice | GD32VF103 | ✔ | | ✖ | dwc2 | | +--------------+-----------------------------+--------+------+-----------+------------------------+--------------------+ diff --git a/hw/bsp/espressif/boards/family.c b/hw/bsp/espressif/boards/family.c index 48b1253b6..4b28cecf2 100644 --- a/hw/bsp/espressif/boards/family.c +++ b/hw/bsp/espressif/boards/family.c @@ -49,7 +49,7 @@ 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_ESP32H4, OPT_MCU_ESP32P4) +#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3, OPT_MCU_ESP32H4, OPT_MCU_ESP32P4, OPT_MCU_ESP32S31) static bool usb_init(uint8_t rhport, bool is_host); #endif @@ -111,10 +111,6 @@ void board_init(void) { #endif } -#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3, OPT_MCU_ESP32H4) - -#endif - //--------------------------------------------------------------------+ // Board porting API //--------------------------------------------------------------------+ @@ -178,7 +174,7 @@ void board_reset_to_bootloader(void) { // PHY Init //-------------------------------------------------------------------- -#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3, OPT_MCU_ESP32H4, OPT_MCU_ESP32P4) +#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3, OPT_MCU_ESP32H4, OPT_MCU_ESP32P4, OPT_MCU_ESP32S31) #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 3, 0) #include "esp_private/usb_phy.h" diff --git a/hw/bsp/espressif/family.cmake b/hw/bsp/espressif/family.cmake index ca9eadaf6..30d5a6ac9 100644 --- a/hw/bsp/espressif/family.cmake +++ b/hw/bsp/espressif/family.cmake @@ -2,7 +2,10 @@ include("${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake") string(TOUPPER ${IDF_TARGET} FAMILY_MCUS) -# Device port default to Port1 for P4 (highspeed), Port0 for others (fullspeed) +# Device/host port defaults: +# - ESP32-P4 uses Port1 (highspeed) +# - ESP32-S31 uses Port0 (highspeed) +# - Other targets use Port0 and derive the default speed from RHPORT_SPEED set(RHPORT_SPEED OPT_MODE_FULL_SPEED OPT_MODE_HIGH_SPEED) if (NOT DEFINED RHPORT_DEVICE) @@ -22,10 +25,18 @@ if (NOT DEFINED RHPORT_HOST) endif() if (NOT DEFINED RHPORT_DEVICE_SPEED) - list(GET RHPORT_SPEED ${RHPORT_DEVICE} RHPORT_DEVICE_SPEED) + if (IDF_TARGET STREQUAL "esp32s31") + set(RHPORT_DEVICE_SPEED OPT_MODE_HIGH_SPEED) + else () + list(GET RHPORT_SPEED ${RHPORT_DEVICE} RHPORT_DEVICE_SPEED) + endif () endif () if (NOT DEFINED RHPORT_HOST_SPEED) - list(GET RHPORT_SPEED ${RHPORT_HOST} RHPORT_HOST_SPEED) + if (IDF_TARGET STREQUAL "esp32s31") + set(RHPORT_HOST_SPEED OPT_MODE_HIGH_SPEED) + else () + list(GET RHPORT_SPEED ${RHPORT_HOST} RHPORT_HOST_SPEED) + endif () endif () # Add example src and bsp directories diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index 77a0bbf1d..a17c76a3b 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -455,7 +455,7 @@ #define CFG_TUSB_OS_INC_PATH_DEFAULT freertos/ // clang-format on - #if CFG_TUSB_MCU == OPT_MCU_ESP32S3 + #if CFG_TUSB_MCU == OPT_MCU_ESP32S3 || CFG_TUSB_MCU == OPT_MCU_ESP32H4 #define TUP_MCU_MULTIPLE_CORE 1 #endif @@ -476,6 +476,22 @@ #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_ESP32S31) + #define TUP_USBIP_DWC2 + #define TUP_USBIP_DWC2_ESP32 + #define TUP_RHPORT_HIGHSPEED 1 + #define TUP_DCD_ENDPOINT_MAX 16 + + // clang-format off + #define CFG_TUSB_OS_INC_PATH_DEFAULT freertos/ + // clang-format on + + #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 + #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)) diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index 9a9c734a0..c30af6196 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -541,8 +541,9 @@ void dcd_remote_wakeup(uint8_t rhport) { void dcd_connect(uint8_t rhport) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); -#ifdef TUP_USBIP_DWC2_ESP32 - // On ESP32-P4 HS PHY, do not write to USB_WRAP register which belongs to FS PHY +#if defined(TUP_USBIP_DWC2_ESP32) && !TU_CHECK_MCU(OPT_MCU_ESP32S31) + // S31 is excluded at compile time (no USB_WRAP peripheral). + // On P4, the HS PHY (port 1) must not touch USB_WRAP which belongs to the FS PHY. if (rhport == 0) { usb_wrap_otg_conf_reg_t conf = USB_WRAP.otg_conf; conf.pad_pull_override = 0; @@ -560,8 +561,9 @@ void dcd_connect(uint8_t rhport) { void dcd_disconnect(uint8_t rhport) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); -#ifdef TUP_USBIP_DWC2_ESP32 - // On ESP32-P4 HS PHY, do not write to USB_WRAP register which belongs to FS PHY +#if defined(TUP_USBIP_DWC2_ESP32) && !TU_CHECK_MCU(OPT_MCU_ESP32S31) + // S31 is excluded at compile time (no USB_WRAP peripheral). + // On P4, the HS PHY (port 1) must not touch USB_WRAP which belongs to the FS PHY. if (rhport == 0) { usb_wrap_otg_conf_reg_t conf = USB_WRAP.otg_conf; conf.pad_pull_override = 1; diff --git a/src/portable/synopsys/dwc2/dwc2_esp32.h b/src/portable/synopsys/dwc2/dwc2_esp32.h index 6a10dc7f8..436f8dc30 100644 --- a/src/portable/synopsys/dwc2/dwc2_esp32.h +++ b/src/portable/synopsys/dwc2/dwc2_esp32.h @@ -37,7 +37,11 @@ #include "esp_intr_alloc.h" #include "soc/periph_defs.h" + +// ESP32-S31 does not have USB_WRAP peripheral (HS-only with UTMI PHY) +#if !TU_CHECK_MCU(OPT_MCU_ESP32S31) #include "soc/usb_wrap_struct.h" +#endif #if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) #define DWC2_FS_REG_BASE 0x60080000UL @@ -75,6 +79,14 @@ 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, .otg_dfifo_depth = 256 }, { .reg_base = DWC2_HS_REG_BASE, .irqnum = ETS_USB_OTG_INTR_SOURCE, .ep_count = 16, .ep_in_count = 8, .otg_dfifo_depth = 1024 } }; + +#elif TU_CHECK_MCU(OPT_MCU_ESP32S31) +#define DWC2_HS_REG_BASE 0x20300000UL +#define DWC2_EP_MAX 16 + +static const dwc2_controller_t _dwc2_controller[] = { + { .reg_base = DWC2_HS_REG_BASE, .irqnum = ETS_USB_OTGHS_INTR_SOURCE, .ep_count = 16, .ep_in_count = 8, .otg_dfifo_depth = 1024 } +}; #endif //--------------------------------------------------------------------+ diff --git a/src/tusb_option.h b/src/tusb_option.h index dd7af76f6..154f8e2a4 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -134,6 +134,7 @@ #define OPT_MCU_ESP32C5 908 ///< Espressif ESP32-C5 #define OPT_MCU_ESP32C61 909 ///< Espressif ESP32-C61 #define OPT_MCU_ESP32H4 910 ///< Espressif ESP32-H4 +#define OPT_MCU_ESP32S31 911 ///< Espressif ESP32-S31 // Dialog #define OPT_MCU_DA1469X 1000 ///< Dialog Semiconductor DA1469x -- cgit v1.3.1 From d808111cfd1708c25cc9ec671985f742560ebf83 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 23 Apr 2026 18:10:17 +0700 Subject: musb double packet for epout --- src/portable/mentor/musb/dcd_musb.c | 74 +++++++++++++++++++++--------------- src/portable/mentor/musb/musb_type.h | 4 +- test/hil/hil_test.py | 45 +++++++++++++++++++++- 3 files changed, 88 insertions(+), 35 deletions(-) (limited to 'src/portable') diff --git a/src/portable/mentor/musb/dcd_musb.c b/src/portable/mentor/musb/dcd_musb.c index 667102bc5..be785324c 100644 --- a/src/portable/mentor/musb/dcd_musb.c +++ b/src/portable/mentor/musb/dcd_musb.c @@ -239,19 +239,18 @@ static void process_setup_packet(uint8_t rhport) { // write to txfifo using pipe_state_t info static void pipe_write(musb_regs_t* musb_regs, pipe_state_t* pipe, uint8_t epnum) { - musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, epnum); - const unsigned mps = ep_csr->tx_maxp & MUSB_TXMAXP_PACKET_SIZE_MASK; - const unsigned rem = pipe->remaining; - const unsigned len = TU_MIN(mps, rem); - volatile void *fifo_ptr = &musb_regs->fifo[epnum]; - if (len) { + musb_ep_csr_t* ep_csr = &musb_regs->indexed_csr; + const uint16_t mps = ep_csr->tx_maxp & MUSB_TXMAXP_PACKET_SIZE_M; + const uint16_t xact_len = tu_min16(mps, pipe->remaining); + volatile void *hwfifo = &musb_regs->fifo[epnum]; + if (xact_len) { if (pipe->use_fifo) { - tu_hwfifo_write_from_fifo(fifo_ptr, pipe->fifo, len, NULL); + tu_hwfifo_write_from_fifo(hwfifo, pipe->fifo, xact_len, NULL); } else { - tu_hwfifo_write(fifo_ptr, pipe->buf, len, NULL); - pipe->buf += len; + tu_hwfifo_write(hwfifo, pipe->buf, xact_len, NULL); + pipe->buf += xact_len; } - pipe->remaining = rem - len; + pipe->remaining -= xact_len; } ep_csr->tx_csrl = MUSB_TXCSRL1_TXRDY; } @@ -284,6 +283,28 @@ static void process_epin(uint8_t rhport, musb_regs_t *musb_regs, uint8_t epnum) } } +// Drain one packet from the Rx FIFO into pipe->buf/fifo, update pipe state, and +// release the FIFO slot by clearing RXRDY. return true if short packet +static bool pipe_read(musb_regs_t* musb_regs, pipe_state_t* pipe, uint8_t epnum) { + musb_ep_csr_t* ep_csr = &musb_regs->indexed_csr; // index already set in process_epout() + const uint16_t mps = ep_csr->rx_maxp & MUSB_RXMAXP_PACKET_SIZE_M; + const uint16_t rx_count = ep_csr->rx_count; + const uint16_t xact_len = tu_min16(tu_min16(pipe->remaining, mps), rx_count); + volatile void *hwfifo = &musb_regs->fifo[epnum]; + if (xact_len) { + if (pipe->use_fifo) { + tu_hwfifo_read_to_fifo(hwfifo, pipe->fifo, xact_len, NULL); + } else { + tu_hwfifo_read(hwfifo, pipe->buf, xact_len, NULL); + pipe->buf += xact_len; + } + pipe->remaining -= xact_len; + } + ep_csr->rx_csrl = 0; /* Clear RXRDY - release this FIFO slot */ + + return (xact_len < mps); +} + static void process_epout(uint8_t rhport, musb_regs_t *musb_regs, uint8_t epnum, bool is_isr) { musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, epnum); if (ep_csr->rx_csrl & MUSB_RXCSRL1_STALLED) { @@ -291,13 +312,12 @@ static void process_epout(uint8_t rhport, musb_regs_t *musb_regs, uint8_t epnum, return; // sent STALL, do nothing } - //Fail gracefully. Spurious interrupt. + // Fail gracefully. Spurious interrupt. if (!(ep_csr->rx_csrl & MUSB_RXCSRL1_RXRDY)) { return; } pipe_state_t *pipe = pipe_get(epnum, TUSB_DIR_OUT); - if (!pipe->armed) { // Packet is already ACK'd by hardware and sitting in the Rx FIFO, but no transfer is // posted. Do NOT flush (per MUSB spec §3.3.11 FlushFIFO) - that would silently drop @@ -308,28 +328,14 @@ static void process_epout(uint8_t rhport, musb_regs_t *musb_regs, uint8_t epnum, return; } - const unsigned mps = ep_csr->rx_maxp & MUSB_RXMAXP_PACKET_SIZE_MASK; - const unsigned rem = pipe->remaining; - const unsigned vld = ep_csr->rx_count; - const unsigned len = TU_MIN(TU_MIN(rem, mps), vld); - volatile void *fifo_ptr = &musb_regs->fifo[epnum]; - if (len) { - if (pipe->use_fifo) { - tu_hwfifo_read_to_fifo(fifo_ptr, pipe->fifo, len, NULL); - } else { - tu_hwfifo_read(fifo_ptr, pipe->buf, len, NULL); - pipe->buf += len; - } - pipe->remaining = rem - len; - } + const bool is_short = pipe_read(musb_regs, pipe, epnum); - ep_csr->rx_csrl = 0; /* Always Clear RXRDY bit */ - if ((len < mps) || (rem == len)) { + // Transfer completes on a short packet or when the rx buffer is filled. + if (is_short || pipe->remaining == 0) { const uint16_t xferred_len = pipe->length - pipe->remaining; pipe->buf = NULL; pipe->armed = false; - - dcd_event_xfer_complete(rhport, tu_edpt_addr(epnum, TUSB_DIR_OUT), xferred_len, XFER_RESULT_SUCCESS, is_isr); + dcd_event_xfer_complete(rhport, epnum, xferred_len, XFER_RESULT_SUCCESS, is_isr); } } @@ -879,7 +885,7 @@ void dcd_int_handler(uint8_t rhport) { process_epin(rhport, musb_regs, epnum); intr_tx &= ~TU_BIT(epnum); - // for Double-buffered endpoint: TxPktRdy is cleared and interrupt is generated when we write the first packet + // Double packet endpoint: TxPktRdy is clear, and interrupt is generated immediately when 1st packet is written. uint_fast8_t new_intr_tx = musb_regs->intr_tx; new_intr_tx &= musb_regs->intr_txen; @@ -891,6 +897,12 @@ void dcd_int_handler(uint8_t rhport) { unsigned const epnum = __builtin_ctz(intr_rx); process_epout(rhport, musb_regs, epnum, true); intr_rx &= ~TU_BIT(epnum); + + // Double packet endpoint: RxPktRdy is set and interrupt is generated immediately if 2nd packet is received + uint_fast8_t new_intr_rx = musb_regs->intr_rx; + new_intr_rx &= musb_regs->intr_rxen; + + intr_rx |= new_intr_rx; } musb_regs->index = saved_index; // restore endpoint index diff --git a/src/portable/mentor/musb/musb_type.h b/src/portable/mentor/musb/musb_type.h index dd1cd6ded..e51634f2a 100644 --- a/src/portable/mentor/musb/musb_type.h +++ b/src/portable/mentor/musb/musb_type.h @@ -573,8 +573,8 @@ TU_ATTR_ALWAYS_INLINE static inline musb_ep_csr_t* get_ep_csr(musb_regs_t* musb_ // numpackminus1 (HB-iso / HS-bulk multiplier - 1). // //***************************************************************************** -#define MUSB_TXMAXP_PACKET_SIZE_MASK 0x07FFu -#define MUSB_RXMAXP_PACKET_SIZE_MASK 0x07FFu +#define MUSB_TXMAXP_PACKET_SIZE_M 0x07FFu +#define MUSB_RXMAXP_PACKET_SIZE_M 0x07FFu //***************************************************************************** // diff --git a/test/hil/hil_test.py b/test/hil/hil_test.py index 58116fb67..447ae10ec 100755 --- a/test/hil/hil_test.py +++ b/test/hil/hil_test.py @@ -1285,6 +1285,32 @@ def test_example(board, f1, example): return err_count +def build_board(board): + """Build firmware for this board via tools/build.py. + Honors board config's build.flags_on variants and build.args defines. + Output goes to cmake-build/cmake-build-BOARD[-f1_...]/ (tools/build.py layout).""" + name = board['name'] + bcfg = board.get('build', {}) + flags_on_list = bcfg.get('flags_on', ['']) + extra_defs = bcfg.get('args', []) + + failed = 0 + for f1 in flags_on_list: + cmd = [sys.executable, f'{TINYUSB_ROOT}/tools/build.py', '-b', name] + for d in extra_defs: + cmd += ['-D', d] + if f1: + for flag in f1.split(): + cmd += ['-f1', flag] + if verbose: + cmd.append('-v') + print(f' + {" ".join(cmd)}') + r = subprocess.run(cmd, cwd=TINYUSB_ROOT) + if r.returncode != 0: + failed += 1 + return name, failed + + def test_board(board): name = board['name'] flasher = board['flasher'] @@ -1346,6 +1372,7 @@ def main(): parser.add_argument('-sf', '--skip-flash', action='store_true', help='Run tests without flashing firmware (use whatever is already on the board)') parser.add_argument('-t', '--test-only', action='append', default=[], help='Tests to run, all if not specified') parser.add_argument('-B', '--build-dir', default='cmake-build', help='Build folder name (default: cmake-build)') + parser.add_argument('--build', action='store_true', help='Build firmware for selected boards with cmake before running tests') parser.add_argument('-r', '--retry', type=int, default=3, help='Retry count for failed tests (default: 3)') parser.add_argument('-v', '--verbose', action='store_true', help='Verbose output') args = parser.parse_args() @@ -1370,10 +1397,24 @@ def main(): else: config_boards = [e for e in config['boards'] if e['name'] in boards] - err_count = 0 + build_err = 0 + if args.build: + if build_dir != 'cmake-build': + print(f'warning: --build writes into cmake-build/, but -B is {build_dir!r}; ' + f'tests will not find the freshly built firmware') + print('-' * 30) + print(f'Build phase: {len(config_boards)} board(s)') + print('-' * 30) + for board in config_boards: + _, nfail = build_board(board) + build_err += nfail + print('-' * 30) + print(f'Build phase done: {build_err} failed') + print('-' * 30) + with Pool(processes=os.cpu_count()) as pool: mret = pool.map(test_board, config_boards) - err_count = sum(e[1] for e in mret) + err_count = build_err + sum(e[1] for e in mret) # generate skip list for next re-run if failed skip_fname = f'{config_file}.skip' if err_count > 0: -- cgit v1.3.1 From fd4279a027a2535dbe5177a962b4cac316357af9 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 24 Apr 2026 15:50:32 +0700 Subject: refactor musb ep0 xfer --- src/portable/mentor/musb/dcd_musb.c | 191 +++++++++++++++++------------------- 1 file changed, 92 insertions(+), 99 deletions(-) (limited to 'src/portable') diff --git a/src/portable/mentor/musb/dcd_musb.c b/src/portable/mentor/musb/dcd_musb.c index be785324c..7b46580cc 100644 --- a/src/portable/mentor/musb/dcd_musb.c +++ b/src/portable/mentor/musb/dcd_musb.c @@ -82,16 +82,28 @@ typedef struct { #define MUSB_PIPE_COUNT (2u * TUP_DCD_ENDPOINT_MAX - 1u) #endif +enum { + EP0_STATE_IDLE = 0, + EP0_STATE_TX, + EP0_STATE_RX, + EP0_STATE_STATUS +}; + typedef struct { union { tusb_control_request_t setup_packet; uint32_t setup_buffer[2]; }; - uint16_t remaining_ctrl; /* The number of bytes remaining in data stage of control transfer. */ - int8_t status_out; + uint8_t ep0_state; pipe_state_t pipe[MUSB_PIPE_COUNT]; } dcd_data_t; +// EP0 control-transfer state is held by usbd_control.c (request, total_xferred, +// data_len). dcd just keeps the last SETUP packet's bmRequestType so it knows +// the original direction when handling DATA/STATUS phase calls. After the +// transfer's STATUS stage completes (or a new SETUP/SETEND aborts it), the +// bmRequestType is reset to REQUEST_TYPE_INVALID. + static dcd_data_t _dcd; TU_ATTR_ALWAYS_INLINE static inline pipe_state_t* pipe_get(uint8_t epnum, tusb_dir_t epdir) { @@ -214,29 +226,6 @@ TU_ATTR_ALWAYS_INLINE static inline void hwfifo_flush(musb_regs_t* musb, unsigne } } -static void process_setup_packet(uint8_t rhport) { - musb_regs_t* musb_regs = MUSB_REGS(rhport); - - // Read setup packet - _dcd.setup_buffer[0] = musb_regs->fifo[0]; - _dcd.setup_buffer[1] = musb_regs->fifo[0]; - - pipe_state_t* pipe0 = pipe_get(0, TUSB_DIR_OUT); - pipe0->buf = NULL; - pipe0->length = 0; - pipe0->remaining = 0; - dcd_event_setup_received(rhport, (const uint8_t*)(uintptr_t)&_dcd.setup_packet, true); - - const unsigned len = _dcd.setup_packet.wLength; - _dcd.remaining_ctrl = len; - const unsigned dir_in = tu_edpt_dir(_dcd.setup_packet.bmRequestType); - /* Clear RX FIFO and reverse the transaction direction */ - if (len && dir_in) { - musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, 0); - ep_csr->csr0l = MUSB_CSRL0_RXRDYC; - } -} - // write to txfifo using pipe_state_t info static void pipe_write(musb_regs_t* musb_regs, pipe_state_t* pipe, uint8_t epnum) { musb_ep_csr_t* ep_csr = &musb_regs->indexed_csr; @@ -372,81 +361,79 @@ static bool edpt_n_xfer(uint8_t rhport, uint8_t ep_addr, void *buffer, uint16_t return true; } -static bool edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes, bool is_isr) -{ - (void)rhport; - TU_ASSERT(total_bytes <= 64); /* Current implementation supports for only up to 64 bytes. */ +// EP0 transfer dispatcher. usbd_control.c drives this with one of: +// - DATA IN : ep=0x80, buffer != NULL, total_bytes > 0 (write a chunk) +// - DATA OUT : ep=0x00, buffer != NULL, total_bytes > 0 (arm to receive) +// - STATUS IN : ep=0x80, total_bytes == 0 (zero-len ack of OUT request) +// - STATUS OUT: ep=0x00, total_bytes == 0 (zero-len ack of IN request, +// HW already auto-handled it +// when DATAEND was set on the +// last DATA IN packet) +static bool edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes, bool is_isr) { + TU_ASSERT(total_bytes <= CFG_TUD_ENDPOINT0_SIZE); musb_regs_t* musb_regs = MUSB_REGS(rhport); musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, 0); pipe_state_t* pipe0 = pipe_get(0, TUSB_DIR_OUT); + const unsigned dir_in = tu_edpt_dir(ep_addr); const unsigned req = _dcd.setup_packet.bmRequestType; - TU_ASSERT(req != REQUEST_TYPE_INVALID || total_bytes == 0); - - if (req == REQUEST_TYPE_INVALID || _dcd.status_out) { - /* STATUS OUT stage. - * MUSB controller automatically handles STATUS OUT packets without - * software helps. We do not have to do anything. And STATUS stage - * may have already finished and received the next setup packet - * without calling this function, so we have no choice but to - * invoke the callback function of status packet here. */ - // TU_LOG1(" STATUS OUT ep_csr->csr0l = %x\r\n", ep_csr->csr0l); - _dcd.status_out = 0; + + if (total_bytes == 0) { + // STATUS phase if (req == REQUEST_TYPE_INVALID) { - dcd_event_xfer_complete(rhport, ep_addr, total_bytes, XFER_RESULT_SUCCESS, is_isr); - } else { - /* The next setup packet has already been received, it aborts - * invoking callback function to avoid confusing TUSB stack. */ - TU_LOG1("Drop CONTROL_STAGE_ACK\r\n"); + // No active request — likely a stale STATUS call (e.g. new SETUP arrived + // after the previous DATA stage but before usbd reached this point). + // Suppress the complete event to avoid confusing the upper stack. + TU_LOG1("Drop stale CONTROL_STAGE_ACK\r\n"); + return true; } - return true; - } - const unsigned dir_in = tu_edpt_dir(ep_addr); - if (tu_edpt_dir(req) == dir_in) { /* DATA stage */ - TU_ASSERT(total_bytes <= _dcd.remaining_ctrl); - const unsigned rem = _dcd.remaining_ctrl; - const unsigned len = TU_MIN(TU_MIN(rem, 64), total_bytes); - volatile void *fifo_ptr = &musb_regs->fifo[0]; if (dir_in) { - tu_hwfifo_write(fifo_ptr, buffer, len, NULL); - - pipe0->buf = buffer + len; - pipe0->length = len; + // STATUS IN of an OUT request: send ZLP IN with DATAEND so HW completes + // the control transfer. + pipe0->buf = NULL; + pipe0->length = 0; pipe0->remaining = 0; - - _dcd.remaining_ctrl = rem - len; - if ((len < 64) || (rem == len)) { - _dcd.setup_packet.bmRequestType = REQUEST_TYPE_INVALID; /* Change to STATUS/SETUP stage */ - _dcd.status_out = 1; - /* Flush TX FIFO and reverse the transaction direction. */ - ep_csr->csr0l = MUSB_CSRL0_TXRDY | MUSB_CSRL0_DATAEND; - } else { - ep_csr->csr0l = MUSB_CSRL0_TXRDY; /* Flush TX FIFO to return ACK. */ - } + ep_csr->csr0l = MUSB_CSRL0_RXRDYC | MUSB_CSRL0_DATAEND; } else { - pipe0->buf = buffer; - pipe0->length = len; - pipe0->remaining = len; - ep_csr->csr0l = MUSB_CSRL0_RXRDYC; /* Clear RX FIFO to return ACK. */ + // STATUS OUT of an IN request: HW already auto-handled it via DATAEND on + // the last DATA IN packet. Just fire the complete event. + _dcd.setup_packet.bmRequestType = REQUEST_TYPE_INVALID; + dcd_event_xfer_complete(rhport, ep_addr, 0, XFER_RESULT_SUCCESS, is_isr); } - } else if (dir_in) { - pipe0->buf = NULL; - pipe0->length = 0; + return true; + } + + // DATA phase. Direction must match the original request. + TU_ASSERT(req != REQUEST_TYPE_INVALID && tu_edpt_dir(req) == dir_in); + volatile void *fifo_ptr = &musb_regs->fifo[0]; + if (dir_in) { + // DATA IN: load FIFO, set TXRDY. Set DATAEND when this is a short packet + // (USB short-packet rule => end of data stage). For multiple-of-EP0-size + // data, usbd will follow with another DATA chunk or a STATUS request, and + // the latter sends ZLP+DATAEND to terminate. + tu_hwfifo_write(fifo_ptr, buffer, total_bytes, NULL); + pipe0->buf = buffer + total_bytes; + pipe0->length = total_bytes; pipe0->remaining = 0; - /* Clear RX FIFO and reverse the transaction direction */ - ep_csr->csr0l = MUSB_CSRL0_RXRDYC | MUSB_CSRL0_DATAEND; + ep_csr->csr0l = (total_bytes < CFG_TUD_ENDPOINT0_SIZE) + ? (MUSB_CSRL0_TXRDY | MUSB_CSRL0_DATAEND) + : MUSB_CSRL0_TXRDY; + } else { + // DATA OUT: arm to receive into buffer; ack to release the EP0 RX FIFO. + pipe0->buf = buffer; + pipe0->length = total_bytes; + pipe0->remaining = total_bytes; + ep_csr->csr0l = MUSB_CSRL0_RXRDYC; } return true; } -static void process_ep0(uint8_t rhport) -{ +static void process_ep0(uint8_t rhport) { musb_regs_t* musb_regs = MUSB_REGS(rhport); musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, 0); pipe_state_t* pipe0 = pipe_get(0, TUSB_DIR_OUT); uint_fast8_t csrl = ep_csr->csr0l; // 21.1.5: endpoint 0 service routine as peripheral - if (csrl & MUSB_CSRL0_STALLED) { /* Returned STALL packet to HOST. */ ep_csr->csr0l = 0; /* Clear STALL */ @@ -455,7 +442,7 @@ static void process_ep0(uint8_t rhport) unsigned req = _dcd.setup_packet.bmRequestType; if (csrl & MUSB_CSRL0_SETEND) { - TU_LOG1(" ABORT by the next packets\r\n"); + // Host aborted the current control transfer (sent a new SETUP or premature STATUS in the middle of DATA stage ep_csr->csr0l = MUSB_CSRL0_SETENDC; if (req != REQUEST_TYPE_INVALID && pipe0->buf) { /* DATA stage was aborted by receiving STATUS or SETUP packet. */ @@ -475,20 +462,25 @@ static void process_ep0(uint8_t rhport) if (req == REQUEST_TYPE_INVALID) { /* SETUP */ TU_ASSERT(sizeof(tusb_control_request_t) == ep_csr->count0,); - process_setup_packet(rhport); + _dcd.setup_buffer[0] = musb_regs->fifo[0]; + _dcd.setup_buffer[1] = musb_regs->fifo[0]; + if (_dcd.setup_packet.wLength > 0 && tu_edpt_dir(_dcd.setup_packet.bmRequestType)) { + ep_csr->csr0l = MUSB_CSRL0_RXRDYC; + } + dcd_event_setup_received(rhport, (const uint8_t*)(uintptr_t)&_dcd.setup_packet, true); return; } - if (pipe0->buf) { - /* DATA OUT */ - const unsigned vld = ep_csr->count0; - const unsigned rem = pipe0->remaining; - const unsigned len = TU_MIN(TU_MIN(rem, 64), vld); - volatile void *fifo_ptr = &musb_regs->fifo[0]; - tu_hwfifo_read(fifo_ptr, pipe0->buf, len, NULL); - - pipe0->remaining = rem - len; - _dcd.remaining_ctrl -= len; + if (pipe0->buf) { + /* DATA OUT: pipe0 must be armed by the prior edpt0_xfer(OUT). The host + * cannot send DATA OUT until that call clears the SETUP-stage RXRDY, so + * armed is guaranteed true here. */ + const uint16_t count0 = ep_csr->count0; + const uint16_t len = tu_min16(tu_min16(pipe0->remaining, 64), count0); + if (len) { + tu_hwfifo_read(&musb_regs->fifo[0], pipe0->buf, len, NULL); + pipe0->remaining -= len; + } pipe0->buf = NULL; dcd_event_xfer_complete(rhport, tu_edpt_addr(0, TUSB_DIR_OUT), @@ -498,8 +490,9 @@ static void process_ep0(uint8_t rhport) return; } - /* When CSRL0 is zero, it means that completion of sending any length packet - * or receiving a zero length packet. */ + /* When CSRL0 is zero, it means that either + * - completion of sending any length packet TxPktRdy clear + * - or status stage is complete (ZLP) after DataEnd is set */ if (req != REQUEST_TYPE_INVALID && !tu_edpt_dir(req)) { /* STATUS IN */ if (*(const uint16_t*)(uintptr_t)&_dcd.setup_packet == 0x0500) { @@ -534,7 +527,6 @@ static void process_bus_reset(uint8_t rhport) { /* When bmRequestType is REQUEST_TYPE_INVALID(0xFF), a control transfer state is SETUP or STATUS stage. */ _dcd.setup_packet.bmRequestType = REQUEST_TYPE_INVALID; - _dcd.status_out = 0; /* When EP0 pipe buf has not NULL, DATA stage works in progress. */ pipe_state_t* pipe0 = pipe_get(0, TUSB_DIR_OUT); pipe0->buf = NULL; @@ -875,17 +867,18 @@ void dcd_int_handler(uint8_t rhport) { } intr_tx &= musb_regs->intr_txen; /* Clear disabled interrupts */ - if (intr_tx & TU_BIT(0)) { - process_ep0(rhport); - intr_tx &= ~TU_BIT(0); - } while (intr_tx) { const unsigned epnum = __builtin_ctz(intr_tx); - process_epin(rhport, musb_regs, epnum); + if (epnum == 0) { + process_ep0(rhport); // EP0 has its own state machine (control transfers) + } else { + process_epin(rhport, musb_regs, epnum); + } intr_tx &= ~TU_BIT(epnum); // Double packet endpoint: TxPktRdy is clear, and interrupt is generated immediately when 1st packet is written. + // Also catches EP0 SETUP arriving during bulk processing. uint_fast8_t new_intr_tx = musb_regs->intr_tx; new_intr_tx &= musb_regs->intr_txen; -- cgit v1.3.1 From f0305eac01ebe3df270e5ff77dca6f310de11a32 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 24 Apr 2026 22:04:10 +0700 Subject: musb migrate to ep0_state, remove setup packet from dcd data --- src/portable/mentor/musb/dcd_musb.c | 167 ++++++++++++++++++++---------------- 1 file changed, 93 insertions(+), 74 deletions(-) (limited to 'src/portable') diff --git a/src/portable/mentor/musb/dcd_musb.c b/src/portable/mentor/musb/dcd_musb.c index 7b46580cc..c646380d5 100644 --- a/src/portable/mentor/musb/dcd_musb.c +++ b/src/portable/mentor/musb/dcd_musb.c @@ -50,8 +50,6 @@ * MACRO TYPEDEF CONSTANT ENUM DECLARATION *------------------------------------------------------------------*/ -#define REQUEST_TYPE_INVALID (0xFFu) - typedef union { volatile uint8_t u8; volatile uint16_t u16; @@ -82,27 +80,25 @@ typedef struct { #define MUSB_PIPE_COUNT (2u * TUP_DCD_ENDPOINT_MAX - 1u) #endif +// EP0 control-transfer state (§21.1.4). The IRQ handler derives direction +// and phase from this state instead of the cached SETUP packet. enum { - EP0_STATE_IDLE = 0, - EP0_STATE_TX, - EP0_STATE_RX, - EP0_STATE_STATUS + EP0_STATE_IDLE = 0, // no active control transfer + EP0_STATE_SETUP_RECEIVED, // SETUP received, awaiting DATA or STATUS call from usbd + EP0_STATE_TX, // DATA IN armed (TXRDY set), awaiting send-ACK IRQ + EP0_STATE_RX, // DATA OUT armed (RXRDY cleared), awaiting host-packet IRQ + EP0_STATE_STATUS, // STATUS IN-ZLP armed (DATAEND set), awaiting confirmation IRQ }; typedef struct { - union { - tusb_control_request_t setup_packet; - uint32_t setup_buffer[2]; - }; uint8_t ep0_state; + uint8_t pending_addr; // new USB address latched by dcd_set_address, applied when STATUS IN completes pipe_state_t pipe[MUSB_PIPE_COUNT]; } dcd_data_t; // EP0 control-transfer state is held by usbd_control.c (request, total_xferred, -// data_len). dcd just keeps the last SETUP packet's bmRequestType so it knows -// the original direction when handling DATA/STATUS phase calls. After the -// transfer's STATUS stage completes (or a new SETUP/SETEND aborts it), the -// bmRequestType is reset to REQUEST_TYPE_INVALID. +// data_len). dcd tracks phase in _dcd.ep0_state. The SETUP packet is drained +// into a local in process_ep0 and dispatched upstream — never cached here. static dcd_data_t _dcd; @@ -375,140 +371,161 @@ static bool edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_ musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, 0); pipe_state_t* pipe0 = pipe_get(0, TUSB_DIR_OUT); const unsigned dir_in = tu_edpt_dir(ep_addr); - const unsigned req = _dcd.setup_packet.bmRequestType; if (total_bytes == 0) { // STATUS phase - if (req == REQUEST_TYPE_INVALID) { - // No active request — likely a stale STATUS call (e.g. new SETUP arrived - // after the previous DATA stage but before usbd reached this point). - // Suppress the complete event to avoid confusing the upper stack. + if (_dcd.ep0_state == EP0_STATE_IDLE) { + // Stale STATUS call (e.g. new SETUP arrived between DATA and STATUS). TU_LOG1("Drop stale CONTROL_STAGE_ACK\r\n"); return true; } if (dir_in) { - // STATUS IN of an OUT request: send ZLP IN with DATAEND so HW completes - // the control transfer. + // STATUS IN (Write/zero-data req): send ZLP IN with DATAEND. The + // xfer_complete event fires from process_ep0 on the confirmation IRQ. pipe0->buf = NULL; pipe0->length = 0; pipe0->remaining = 0; + _dcd.ep0_state = EP0_STATE_STATUS; ep_csr->csr0l = MUSB_CSRL0_RXRDYC | MUSB_CSRL0_DATAEND; } else { - // STATUS OUT of an IN request: HW already auto-handled it via DATAEND on - // the last DATA IN packet. Just fire the complete event. - _dcd.setup_packet.bmRequestType = REQUEST_TYPE_INVALID; + // STATUS OUT (Read req): HW already auto-handled via DATAEND on the last + // DATA IN packet. Fire complete inline; the actual OUT-ZLP IRQ that + // follows is silently absorbed in process_ep0. + _dcd.ep0_state = EP0_STATE_IDLE; dcd_event_xfer_complete(rhport, ep_addr, 0, XFER_RESULT_SUCCESS, is_isr); } return true; } - // DATA phase. Direction must match the original request. - TU_ASSERT(req != REQUEST_TYPE_INVALID && tu_edpt_dir(req) == dir_in); + // DATA phase — valid from SETUP_RECEIVED (first chunk / Write) or TX + // (subsequent Read chunk). Direction+length drives the next state. + TU_ASSERT(_dcd.ep0_state == EP0_STATE_SETUP_RECEIVED || _dcd.ep0_state == EP0_STATE_TX); volatile void *fifo_ptr = &musb_regs->fifo[0]; if (dir_in) { - // DATA IN: load FIFO, set TXRDY. Set DATAEND when this is a short packet - // (USB short-packet rule => end of data stage). For multiple-of-EP0-size - // data, usbd will follow with another DATA chunk or a STATUS request, and - // the latter sends ZLP+DATAEND to terminate. + // DATA IN: load FIFO, set TXRDY. Add DATAEND for a short packet (ends + // the data stage per USB short-packet rule). tu_hwfifo_write(fifo_ptr, buffer, total_bytes, NULL); pipe0->buf = buffer + total_bytes; pipe0->length = total_bytes; pipe0->remaining = 0; + _dcd.ep0_state = EP0_STATE_TX; ep_csr->csr0l = (total_bytes < CFG_TUD_ENDPOINT0_SIZE) ? (MUSB_CSRL0_TXRDY | MUSB_CSRL0_DATAEND) : MUSB_CSRL0_TXRDY; } else { - // DATA OUT: arm to receive into buffer; ack to release the EP0 RX FIFO. + // DATA OUT: arm, ack RXRDY so host can send DATA OUT. pipe0->buf = buffer; pipe0->length = total_bytes; pipe0->remaining = total_bytes; + _dcd.ep0_state = EP0_STATE_RX; ep_csr->csr0l = MUSB_CSRL0_RXRDYC; } return true; } +// 21.1.5: endpoint 0 service routine as peripheral. Drives the IDLE / +// SETUP_RECEIVED / TX / RX / STATUS machine; direction on each IRQ is +// implied by the state. static void process_ep0(uint8_t rhport) { musb_regs_t* musb_regs = MUSB_REGS(rhport); musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, 0); pipe_state_t* pipe0 = pipe_get(0, TUSB_DIR_OUT); uint_fast8_t csrl = ep_csr->csr0l; - // 21.1.5: endpoint 0 service routine as peripheral if (csrl & MUSB_CSRL0_STALLED) { - /* Returned STALL packet to HOST. */ - ep_csr->csr0l = 0; /* Clear STALL */ + ep_csr->csr0l = 0; + _dcd.ep0_state = EP0_STATE_IDLE; return; } - unsigned req = _dcd.setup_packet.bmRequestType; if (csrl & MUSB_CSRL0_SETEND) { - // Host aborted the current control transfer (sent a new SETUP or premature STATUS in the middle of DATA stage + // Host aborted the current control transfer (new SETUP or premature STATUS). ep_csr->csr0l = MUSB_CSRL0_SETENDC; - if (req != REQUEST_TYPE_INVALID && pipe0->buf) { - /* DATA stage was aborted by receiving STATUS or SETUP packet. */ + if (_dcd.ep0_state == EP0_STATE_TX || _dcd.ep0_state == EP0_STATE_RX) { + const uint8_t dir_ep_addr = (_dcd.ep0_state == EP0_STATE_TX) ? TUSB_DIR_IN_MASK : 0; pipe0->buf = NULL; - _dcd.setup_packet.bmRequestType = REQUEST_TYPE_INVALID; dcd_event_xfer_complete(rhport, - req & TUSB_DIR_IN_MASK, + dir_ep_addr, pipe0->length - pipe0->remaining, XFER_RESULT_SUCCESS, true); } - req = REQUEST_TYPE_INVALID; - if (!(csrl & MUSB_CSRL0_RXRDY)) return; /* Received SETUP packet */ + _dcd.ep0_state = EP0_STATE_IDLE; + if (!(csrl & MUSB_CSRL0_RXRDY)) return; /* no SETUP waiting behind it */ } if (csrl & MUSB_CSRL0_RXRDY) { - /* Received SETUP or DATA OUT packet */ - if (req == REQUEST_TYPE_INVALID) { - /* SETUP */ - TU_ASSERT(sizeof(tusb_control_request_t) == ep_csr->count0,); - _dcd.setup_buffer[0] = musb_regs->fifo[0]; - _dcd.setup_buffer[1] = musb_regs->fifo[0]; - if (_dcd.setup_packet.wLength > 0 && tu_edpt_dir(_dcd.setup_packet.bmRequestType)) { + const uint16_t count0 = ep_csr->count0; + + if (_dcd.ep0_state == EP0_STATE_IDLE) { + // SETUP token (count0 == 8). A count0 == 0 here would be a stray + // STATUS-OUT ZLP that bypassed the absorbing path below; silently ack. + if (count0 == 0) { + ep_csr->csr0l = MUSB_CSRL0_RXRDYC; + return; + } + TU_ASSERT(sizeof(tusb_control_request_t) == count0,); + union { + tusb_control_request_t req; + uint32_t u32[2]; + } setup; + setup.u32[0] = musb_regs->fifo[0]; + setup.u32[1] = musb_regs->fifo[0]; + _dcd.ep0_state = EP0_STATE_SETUP_RECEIVED; + // Ack RXRDY now for Read requests so host can start sending IN tokens. + // Write / zero-data leave it set — HW NAKs OUT tokens until edpt0_xfer + // (OUT or STATUS IN) clears it. + if (setup.req.wLength > 0 && tu_edpt_dir(setup.req.bmRequestType)) { ep_csr->csr0l = MUSB_CSRL0_RXRDYC; } - dcd_event_setup_received(rhport, (const uint8_t*)(uintptr_t)&_dcd.setup_packet, true); + dcd_event_setup_received(rhport, (const uint8_t*)&setup.req, true); return; } - if (pipe0->buf) { - /* DATA OUT: pipe0 must be armed by the prior edpt0_xfer(OUT). The host - * cannot send DATA OUT until that call clears the SETUP-stage RXRDY, so - * armed is guaranteed true here. */ - const uint16_t count0 = ep_csr->count0; + if (_dcd.ep0_state == EP0_STATE_RX) { + /* DATA OUT: drain armed buffer, complete, return to SETUP_RECEIVED for STATUS call. */ const uint16_t len = tu_min16(tu_min16(pipe0->remaining, 64), count0); if (len) { tu_hwfifo_read(&musb_regs->fifo[0], pipe0->buf, len, NULL); pipe0->remaining -= len; } pipe0->buf = NULL; + _dcd.ep0_state = EP0_STATE_SETUP_RECEIVED; + ep_csr->csr0l = MUSB_CSRL0_RXRDYC; dcd_event_xfer_complete(rhport, tu_edpt_addr(0, TUSB_DIR_OUT), pipe0->length - pipe0->remaining, XFER_RESULT_SUCCESS, true); + return; + } + + // State SETUP_RECEIVED or TX with count0 == 0: stray STATUS-OUT ZLP for + // a Read request whose inline complete already dropped state to IDLE. + if (count0 == 0) { + ep_csr->csr0l = MUSB_CSRL0_RXRDYC; } return; } - /* When CSRL0 is zero, it means that either - * - completion of sending any length packet TxPktRdy clear - * - or status stage is complete (ZLP) after DataEnd is set */ - if (req != REQUEST_TYPE_INVALID && !tu_edpt_dir(req)) { - /* STATUS IN */ - if (*(const uint16_t*)(uintptr_t)&_dcd.setup_packet == 0x0500) { - /* The address must be changed on completion of the control transfer. */ - musb_regs->faddr = (uint8_t)_dcd.setup_packet.wValue; + /* CSR0L == 0: TXRDY cleared (data sent) or STATUS confirmation. */ + if (_dcd.ep0_state == EP0_STATE_STATUS) { + // STATUS IN confirmed by host's ACK of our IN-ZLP. + if (_dcd.pending_addr) { + musb_regs->faddr = _dcd.pending_addr; + _dcd.pending_addr = 0; } - _dcd.setup_packet.bmRequestType = REQUEST_TYPE_INVALID; + _dcd.ep0_state = EP0_STATE_IDLE; dcd_event_xfer_complete(rhport, tu_edpt_addr(0, TUSB_DIR_IN), - pipe0->length - pipe0->remaining, - XFER_RESULT_SUCCESS, true); + 0, XFER_RESULT_SUCCESS, true); return; } - if (pipe0->buf) { - /* DATA IN */ + + if (_dcd.ep0_state == EP0_STATE_TX) { + /* DATA IN packet sent. For short packets DATAEND was set; the STATUS-OUT + * ZLP IRQ that follows lands in the count0==0 branch above. Return to + * SETUP_RECEIVED so usbd can post the next chunk or the STATUS call. */ pipe0->buf = NULL; + _dcd.ep0_state = EP0_STATE_SETUP_RECEIVED; dcd_event_xfer_complete(rhport, tu_edpt_addr(0, TUSB_DIR_IN), pipe0->length - pipe0->remaining, @@ -525,8 +542,7 @@ static void process_bus_reset(uint8_t rhport) { alloced_fifo_bytes = CFG_TUD_ENDPOINT0_SIZE; #endif - /* When bmRequestType is REQUEST_TYPE_INVALID(0xFF), a control transfer state is SETUP or STATUS stage. */ - _dcd.setup_packet.bmRequestType = REQUEST_TYPE_INVALID; + _dcd.ep0_state = EP0_STATE_IDLE; /* When EP0 pipe buf has not NULL, DATA stage works in progress. */ pipe_state_t* pipe0 = pipe_get(0, TUSB_DIR_OUT); pipe0->buf = NULL; @@ -591,18 +607,21 @@ void dcd_int_disable(uint8_t rhport) { musb_dcd_int_disable(rhport); } -// Receive Set Address request, mcu port must also include status IN response +// Receive Set Address request. Stash the new address here; hardware faddr is +// latched from pending_addr in process_ep0 once the STATUS IN completes (per +// USB spec, address must only take effect after the status stage). void dcd_set_address(uint8_t rhport, uint8_t dev_addr) { - (void)dev_addr; musb_regs_t* musb_regs = MUSB_REGS(rhport); musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, 0); pipe_state_t* pipe0 = pipe_get(0, TUSB_DIR_OUT); + _dcd.pending_addr = dev_addr; pipe0->buf = NULL; pipe0->length = 0; pipe0->remaining = 0; - /* Clear RX FIFO to return ACK. */ + _dcd.ep0_state = EP0_STATE_STATUS; + /* Send STATUS IN ZLP with DATAEND; host ACK fires the confirmation IRQ. */ ep_csr->csr0l = MUSB_CSRL0_RXRDYC | MUSB_CSRL0_DATAEND; } @@ -803,7 +822,7 @@ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { if (0 == epn) { if (!ep_addr) { /* Ignore EP80 */ - _dcd.setup_packet.bmRequestType = REQUEST_TYPE_INVALID; + _dcd.ep0_state = EP0_STATE_IDLE; pipe_state_t* pipe0 = pipe_get(0, TUSB_DIR_OUT); pipe0->buf = NULL; ep_csr->csr0l = MUSB_CSRL0_STALL; -- cgit v1.3.1 From 9fd6788add2223789e9ab08e99337bb96c77ba2a Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 25 Apr 2026 02:22:00 +0700 Subject: musb more ep0 refactor. add back remaining_ctrl for correct ep0 state transition. handle status out to make sure xfer_complete() not called before dcd_edpt_xfer() --- src/portable/mentor/musb/dcd_musb.c | 266 +++++++++++++++++++----------------- 1 file changed, 139 insertions(+), 127 deletions(-) (limited to 'src/portable') diff --git a/src/portable/mentor/musb/dcd_musb.c b/src/portable/mentor/musb/dcd_musb.c index c646380d5..4ef10168f 100644 --- a/src/portable/mentor/musb/dcd_musb.c +++ b/src/portable/mentor/musb/dcd_musb.c @@ -80,17 +80,21 @@ typedef struct { #define MUSB_PIPE_COUNT (2u * TUP_DCD_ENDPOINT_MAX - 1u) #endif -// EP0 control-transfer state (§21.1.4). The IRQ handler derives direction -// and phase from this state instead of the cached SETUP packet. +// EP0 control-transfer phase (§21.1.4). The phase is set from the SETUP +// packet's direction/wLength when the SETUP IRQ fires, and drives what each +// subsequent IRQ or edpt0_xfer call is allowed to do. enum { EP0_STATE_IDLE = 0, // no active control transfer - EP0_STATE_SETUP_RECEIVED, // SETUP received, awaiting DATA or STATUS call from usbd - EP0_STATE_TX, // DATA IN armed (TXRDY set), awaiting send-ACK IRQ - EP0_STATE_RX, // DATA OUT armed (RXRDY cleared), awaiting host-packet IRQ - EP0_STATE_STATUS, // STATUS IN-ZLP armed (DATAEND set), awaiting confirmation IRQ + EP0_STATE_TX, // DATA IN stage (Read req data; STATUS-OUT-ZLP absorbed here too) + EP0_STATE_RX, // DATA OUT stage (Write req data) + EP0_STATE_STATUS_IN, // STATUS IN — device sends IN-ZLP to host; awaits send-ACK IRQ + EP0_STATE_STATUS_OUT, + EP0_STATE_STATUS_OUT_REQUESTED, + EP0_STATE_STATUS_OUT_SENT }; typedef struct { + uint16_t remaining_ctrl; /* The number of bytes remaining in data stage of control transfer. */ uint8_t ep0_state; uint8_t pending_addr; // new USB address latched by dcd_set_address, applied when STATUS IN completes pipe_state_t pipe[MUSB_PIPE_COUNT]; @@ -366,65 +370,65 @@ static bool edpt_n_xfer(uint8_t rhport, uint8_t ep_addr, void *buffer, uint16_t // when DATAEND was set on the // last DATA IN packet) static bool edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes, bool is_isr) { - TU_ASSERT(total_bytes <= CFG_TUD_ENDPOINT0_SIZE); + TU_ASSERT(total_bytes <= CFG_TUD_ENDPOINT0_SIZE); /* Current implementation supports for only up to 64 bytes. */ musb_regs_t* musb_regs = MUSB_REGS(rhport); musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, 0); pipe_state_t* pipe0 = pipe_get(0, TUSB_DIR_OUT); const unsigned dir_in = tu_edpt_dir(ep_addr); - if (total_bytes == 0) { - // STATUS phase - if (_dcd.ep0_state == EP0_STATE_IDLE) { - // Stale STATUS call (e.g. new SETUP arrived between DATA and STATUS). - TU_LOG1("Drop stale CONTROL_STAGE_ACK\r\n"); - return true; + switch (_dcd.ep0_state) { + case EP0_STATE_TX: + case EP0_STATE_RX: { + TU_ASSERT(dir_in ? _dcd.ep0_state == EP0_STATE_TX : _dcd.ep0_state == EP0_STATE_RX); + volatile void *fifo_ptr = &musb_regs->fifo[0]; + if (dir_in) { + // DATA IN: load FIFO, set TXRDY. Add DATAEND for a short packet (ends + // the data stage per USB short-packet rule). + tu_hwfifo_write(fifo_ptr, buffer, total_bytes, NULL); + pipe0->buf = buffer + total_bytes; + pipe0->length = total_bytes; + pipe0->remaining = 0; + + _dcd.remaining_ctrl -= total_bytes; + if (_dcd.remaining_ctrl == 0) { + ep_csr->csr0l = MUSB_CSRL0_TXRDY | MUSB_CSRL0_DATAEND; // last packet, also set DATAEND to end the data stage + } else { + ep_csr->csr0l = MUSB_CSRL0_TXRDY; + } + } else { + // DATA OUT: arm, ack RXRDY so host can send DATA OUT. + pipe0->buf = buffer; + pipe0->length = total_bytes; + pipe0->remaining = total_bytes; + ep_csr->csr0l = MUSB_CSRL0_RXRDYC; + } + break; } - if (dir_in) { - // STATUS IN (Write/zero-data req): send ZLP IN with DATAEND. The - // xfer_complete event fires from process_ep0 on the confirmation IRQ. - pipe0->buf = NULL; - pipe0->length = 0; - pipe0->remaining = 0; - _dcd.ep0_state = EP0_STATE_STATUS; + + case EP0_STATE_STATUS_IN: + TU_ASSERT(dir_in && total_bytes == 0); // only STATUS IN allowed ep_csr->csr0l = MUSB_CSRL0_RXRDYC | MUSB_CSRL0_DATAEND; - } else { - // STATUS OUT (Read req): HW already auto-handled via DATAEND on the last - // DATA IN packet. Fire complete inline; the actual OUT-ZLP IRQ that - // follows is silently absorbed in process_ep0. + break; + + case EP0_STATE_STATUS_OUT: + TU_ASSERT(!dir_in && total_bytes == 0); // only STATUS OUT allowed + _dcd.ep0_state = EP0_STATE_STATUS_OUT_REQUESTED; + break; + + case EP0_STATE_STATUS_OUT_SENT: + // status is already sent to host, complete it here _dcd.ep0_state = EP0_STATE_IDLE; dcd_event_xfer_complete(rhport, ep_addr, 0, XFER_RESULT_SUCCESS, is_isr); - } - return true; - } + break; - // DATA phase — valid from SETUP_RECEIVED (first chunk / Write) or TX - // (subsequent Read chunk). Direction+length drives the next state. - TU_ASSERT(_dcd.ep0_state == EP0_STATE_SETUP_RECEIVED || _dcd.ep0_state == EP0_STATE_TX); - volatile void *fifo_ptr = &musb_regs->fifo[0]; - if (dir_in) { - // DATA IN: load FIFO, set TXRDY. Add DATAEND for a short packet (ends - // the data stage per USB short-packet rule). - tu_hwfifo_write(fifo_ptr, buffer, total_bytes, NULL); - pipe0->buf = buffer + total_bytes; - pipe0->length = total_bytes; - pipe0->remaining = 0; - _dcd.ep0_state = EP0_STATE_TX; - ep_csr->csr0l = (total_bytes < CFG_TUD_ENDPOINT0_SIZE) - ? (MUSB_CSRL0_TXRDY | MUSB_CSRL0_DATAEND) - : MUSB_CSRL0_TXRDY; - } else { - // DATA OUT: arm, ack RXRDY so host can send DATA OUT. - pipe0->buf = buffer; - pipe0->length = total_bytes; - pipe0->remaining = total_bytes; - _dcd.ep0_state = EP0_STATE_RX; - ep_csr->csr0l = MUSB_CSRL0_RXRDYC; + default: break; } + return true; } // 21.1.5: endpoint 0 service routine as peripheral. Drives the IDLE / -// SETUP_RECEIVED / TX / RX / STATUS machine; direction on each IRQ is +// IDLE / TX / RX / STATUS machine; direction on each IRQ is // implied by the state. static void process_ep0(uint8_t rhport) { musb_regs_t* musb_regs = MUSB_REGS(rhport); @@ -440,96 +444,103 @@ static void process_ep0(uint8_t rhport) { if (csrl & MUSB_CSRL0_SETEND) { // Host aborted the current control transfer (new SETUP or premature STATUS). + // do nothing, it is probably another setup packet, usbd will reset its state. ep_csr->csr0l = MUSB_CSRL0_SETENDC; - if (_dcd.ep0_state == EP0_STATE_TX || _dcd.ep0_state == EP0_STATE_RX) { - const uint8_t dir_ep_addr = (_dcd.ep0_state == EP0_STATE_TX) ? TUSB_DIR_IN_MASK : 0; - pipe0->buf = NULL; - dcd_event_xfer_complete(rhport, - dir_ep_addr, - pipe0->length - pipe0->remaining, - XFER_RESULT_SUCCESS, true); - } _dcd.ep0_state = EP0_STATE_IDLE; - if (!(csrl & MUSB_CSRL0_RXRDY)) return; /* no SETUP waiting behind it */ + if (!(csrl & MUSB_CSRL0_RXRDY)) { + return; /* no SETUP waiting behind it */ + } } + // Receive Data (Setup or OUT) if (csrl & MUSB_CSRL0_RXRDY) { const uint16_t count0 = ep_csr->count0; - - if (_dcd.ep0_state == EP0_STATE_IDLE) { - // SETUP token (count0 == 8). A count0 == 0 here would be a stray - // STATUS-OUT ZLP that bypassed the absorbing path below; silently ack. - if (count0 == 0) { - ep_csr->csr0l = MUSB_CSRL0_RXRDYC; - return; - } - TU_ASSERT(sizeof(tusb_control_request_t) == count0,); - union { - tusb_control_request_t req; - uint32_t u32[2]; - } setup; - setup.u32[0] = musb_regs->fifo[0]; - setup.u32[1] = musb_regs->fifo[0]; - _dcd.ep0_state = EP0_STATE_SETUP_RECEIVED; - // Ack RXRDY now for Read requests so host can start sending IN tokens. - // Write / zero-data leave it set — HW NAKs OUT tokens until edpt0_xfer - // (OUT or STATUS IN) clears it. - if (setup.req.wLength > 0 && tu_edpt_dir(setup.req.bmRequestType)) { - ep_csr->csr0l = MUSB_CSRL0_RXRDYC; + switch (_dcd.ep0_state) { + case EP0_STATE_IDLE: + TU_ASSERT(sizeof(tusb_control_request_t) == count0, ); + union { + tusb_control_request_t req; + uint32_t u32[2]; + } setup_packet; + setup_packet.u32[0] = musb_regs->fifo[0]; + setup_packet.u32[1] = musb_regs->fifo[0]; + + _dcd.remaining_ctrl = setup_packet.req.wLength; + + // Pick the next phase directly from the SETUP packet: Read → TX, + // Write → RX, zero-data → STATUS_IN. For Read, also ack SETUP's RXRDY + // now so the host can start IN tokens immediately; Write/zero-data + // leave it set so HW NAKs OUT tokens until edpt0_xfer clears it. + if (setup_packet.req.wLength == 0) { + _dcd.ep0_state = EP0_STATE_STATUS_IN; + } else if (tu_edpt_dir(setup_packet.req.bmRequestType)) { + _dcd.ep0_state = EP0_STATE_TX; + ep_csr->csr0l = MUSB_CSRL0_RXRDYC; + } else { + _dcd.ep0_state = EP0_STATE_RX; + } + dcd_event_setup_received(rhport, (const uint8_t *)&setup_packet.req, true); + break; + + case EP0_STATE_RX: { + /* DATA OUT: drain armed buffer, complete. Stay in RX — usbd posts + * edpt0_xfer(STATUS IN) next which transitions us to STATUS_IN. */ + const uint16_t len = tu_min16(tu_min16(pipe0->remaining, 64), count0); + if (len) { + tu_hwfifo_read(&musb_regs->fifo[0], pipe0->buf, len, NULL); + pipe0->remaining -= len; + _dcd.remaining_ctrl -= len; + } + + if (_dcd.remaining_ctrl == 0) { + // last packet, leave it RXRDYC to edpt0_xfer() + _dcd.ep0_state = EP0_STATE_STATUS_IN; + } else { + ep_csr->csr0l = MUSB_CSRL0_RXRDYC; + } + dcd_event_xfer_complete(rhport, tu_edpt_addr(0, TUSB_DIR_OUT), pipe0->length - pipe0->remaining, + XFER_RESULT_SUCCESS, true); + break; } - dcd_event_setup_received(rhport, (const uint8_t*)&setup.req, true); - return; - } - if (_dcd.ep0_state == EP0_STATE_RX) { - /* DATA OUT: drain armed buffer, complete, return to SETUP_RECEIVED for STATUS call. */ - const uint16_t len = tu_min16(tu_min16(pipe0->remaining, 64), count0); - if (len) { - tu_hwfifo_read(&musb_regs->fifo[0], pipe0->buf, len, NULL); - pipe0->remaining -= len; - } - pipe0->buf = NULL; - _dcd.ep0_state = EP0_STATE_SETUP_RECEIVED; - ep_csr->csr0l = MUSB_CSRL0_RXRDYC; - dcd_event_xfer_complete(rhport, - tu_edpt_addr(0, TUSB_DIR_OUT), - pipe0->length - pipe0->remaining, - XFER_RESULT_SUCCESS, true); - return; + default: break; } - // State SETUP_RECEIVED or TX with count0 == 0: stray STATUS-OUT ZLP for - // a Read request whose inline complete already dropped state to IDLE. - if (count0 == 0) { - ep_csr->csr0l = MUSB_CSRL0_RXRDYC; - } return; } - /* CSR0L == 0: TXRDY cleared (data sent) or STATUS confirmation. */ - if (_dcd.ep0_state == EP0_STATE_STATUS) { - // STATUS IN confirmed by host's ACK of our IN-ZLP. - if (_dcd.pending_addr) { - musb_regs->faddr = _dcd.pending_addr; - _dcd.pending_addr = 0; - } - _dcd.ep0_state = EP0_STATE_IDLE; - dcd_event_xfer_complete(rhport, - tu_edpt_addr(0, TUSB_DIR_IN), - 0, XFER_RESULT_SUCCESS, true); - return; - } + /* When CSRL0 is zero, it means that either + * - completion of sending any length packet TxPktRdy clear + * - or status stage is complete (ZLP) after DataEnd is set */ + switch (_dcd.ep0_state) { + case EP0_STATE_TX: + if (_dcd.remaining_ctrl == 0) { + // last packet + _dcd.ep0_state = EP0_STATE_STATUS_OUT; + } + dcd_event_xfer_complete(rhport, 0x80, pipe0->length, XFER_RESULT_SUCCESS, true); + break; + + case EP0_STATE_STATUS_OUT: + // edpt0_xfer() for this is not yet requested, let it call xfer_complete() later + _dcd.ep0_state = EP0_STATE_STATUS_OUT_SENT; + break; + + case EP0_STATE_STATUS_OUT_REQUESTED: + _dcd.ep0_state = EP0_STATE_IDLE; + dcd_event_xfer_complete(rhport, 0, 0, XFER_RESULT_SUCCESS, true); + break; + + case EP0_STATE_STATUS_IN: + if (_dcd.pending_addr) { + musb_regs->faddr = _dcd.pending_addr; + _dcd.pending_addr = 0; + } + _dcd.ep0_state = EP0_STATE_IDLE; + dcd_event_xfer_complete(rhport, 0x80, 0, XFER_RESULT_SUCCESS, true); + break; - if (_dcd.ep0_state == EP0_STATE_TX) { - /* DATA IN packet sent. For short packets DATAEND was set; the STATUS-OUT - * ZLP IRQ that follows lands in the count0==0 branch above. Return to - * SETUP_RECEIVED so usbd can post the next chunk or the STATUS call. */ - pipe0->buf = NULL; - _dcd.ep0_state = EP0_STATE_SETUP_RECEIVED; - dcd_event_xfer_complete(rhport, - tu_edpt_addr(0, TUSB_DIR_IN), - pipe0->length - pipe0->remaining, - XFER_RESULT_SUCCESS, true); + default: break; } } @@ -620,7 +631,7 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) pipe0->buf = NULL; pipe0->length = 0; pipe0->remaining = 0; - _dcd.ep0_state = EP0_STATE_STATUS; + _dcd.ep0_state = EP0_STATE_STATUS_IN; /* Send STATUS IN ZLP with DATAEND; host ACK fires the confirmation IRQ. */ ep_csr->csr0l = MUSB_CSRL0_RXRDYC | MUSB_CSRL0_DATAEND; } @@ -787,6 +798,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t t if (epnum) { ret = edpt_n_xfer(rhport, ep_addr, buffer, total_bytes, false, is_isr); } else { + (void) is_isr; ret = edpt0_xfer(rhport, ep_addr, buffer, total_bytes, is_isr); } -- cgit v1.3.1 From 0e4869a729ce32b157a60ae5730abf6f5802381b Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 25 Apr 2026 14:41:08 +0700 Subject: clean up --- src/common/tusb_types.h | 6 +++ src/device/usbd_control.c | 14 ++---- src/portable/mentor/musb/dcd_musb.c | 95 +++++++++++++++---------------------- 3 files changed, 50 insertions(+), 65 deletions(-) (limited to 'src/portable') diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index 806997866..36e72967c 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -321,6 +321,12 @@ enum { TUSB_INDEX_INVALID_8 = 0xFF }; +enum { + TU_EP0_OUT = 0x00, + TU_EP0_IN = 0x80 +}; + + //--------------------------------------------------------------------+ // //--------------------------------------------------------------------+ diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index 87593d4a7..49ecd0f16 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -44,10 +44,6 @@ TU_ATTR_WEAK void dcd_edpt0_status_complete(uint8_t rhport, const tusb_control_r // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ -enum { - EDPT_CTRL_OUT = 0x00, - EDPT_CTRL_IN = 0x80 -}; typedef struct { tusb_control_request_t request; @@ -74,7 +70,7 @@ uint8_t* usbd_get_ctrl_buf(void) { // Queue ZLP status transaction static inline bool status_stage_xact(uint8_t rhport, const tusb_control_request_t* request) { // Opposite to endpoint in Data Phase - const uint8_t ep_addr = request->bmRequestType_bit.direction ? EDPT_CTRL_OUT : EDPT_CTRL_IN; + const uint8_t ep_addr = request->bmRequestType_bit.direction ? TU_EP0_OUT : TU_EP0_IN; return usbd_edpt_xfer(rhport, ep_addr, NULL, 0, false); } @@ -93,10 +89,10 @@ bool tud_control_status(uint8_t rhport, const tusb_control_request_t* request) { // This function can also transfer an zero-length packet static bool data_stage_xact(uint8_t rhport) { const uint16_t xact_len = tu_min16(_ctrl_xfer.data_len - _ctrl_xfer.total_xferred, CFG_TUD_ENDPOINT0_BUFSIZE); - uint8_t ep_addr = EDPT_CTRL_OUT; + uint8_t ep_addr = TU_EP0_OUT; if (_ctrl_xfer.request.bmRequestType_bit.direction == TUSB_DIR_IN) { - ep_addr = EDPT_CTRL_IN; + ep_addr = TU_EP0_IN; if (0u != xact_len && _ctrl_xfer.buffer != _ctrl_epbuf.buf) { TU_VERIFY(0 == tu_memcpy_s(_ctrl_epbuf.buf, CFG_TUD_ENDPOINT0_BUFSIZE, _ctrl_xfer.buffer, xact_len)); } @@ -203,8 +199,8 @@ bool usbd_control_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, TU_ASSERT(status_stage_xact(rhport, &_ctrl_xfer.request)); } else { // Stall both IN and OUT control endpoint - dcd_edpt_stall(rhport, EDPT_CTRL_OUT); - dcd_edpt_stall(rhport, EDPT_CTRL_IN); + dcd_edpt_stall(rhport, TU_EP0_OUT); + dcd_edpt_stall(rhport, TU_EP0_IN); } } else { // More data to transfer diff --git a/src/portable/mentor/musb/dcd_musb.c b/src/portable/mentor/musb/dcd_musb.c index 4ef10168f..66fa86c77 100644 --- a/src/portable/mentor/musb/dcd_musb.c +++ b/src/portable/mentor/musb/dcd_musb.c @@ -70,40 +70,32 @@ typedef struct { // Pipe array layout (N = TUP_DCD_ENDPOINT_MAX): // [0] : EP0 (shared between IN/OUT control stages) // One-direction-only IPs (CFG_TUD_ENDPOINT_ONE_DIRECTION_ONLY=1): -// [1 .. n-1] : EP1..n-1 (single slot per endpoint) +// [1..N-1] : EP1..N-1 (single slot per endpoint) // Bidirectional-capable IPs: -// [1 .. N-1 ] : EP OUT -// [N .. 2*N-2] : EP IN +// [1..N-1 ] : EP OUT +// [N..2*N-2] : EP IN #if CFG_TUD_ENDPOINT_ONE_DIRECTION_ONLY #define MUSB_PIPE_COUNT TUP_DCD_ENDPOINT_MAX #else #define MUSB_PIPE_COUNT (2u * TUP_DCD_ENDPOINT_MAX - 1u) #endif -// EP0 control-transfer phase (§21.1.4). The phase is set from the SETUP -// packet's direction/wLength when the SETUP IRQ fires, and drives what each -// subsequent IRQ or edpt0_xfer call is allowed to do. enum { - EP0_STATE_IDLE = 0, // no active control transfer - EP0_STATE_TX, // DATA IN stage (Read req data; STATUS-OUT-ZLP absorbed here too) - EP0_STATE_RX, // DATA OUT stage (Write req data) - EP0_STATE_STATUS_IN, // STATUS IN — device sends IN-ZLP to host; awaits send-ACK IRQ - EP0_STATE_STATUS_OUT, - EP0_STATE_STATUS_OUT_REQUESTED, - EP0_STATE_STATUS_OUT_SENT + EP0_STATE_IDLE = 0, // no active control transfer + EP0_STATE_DATA, // DATA stage (IN or OUT — direction implied by CSR/dir) + EP0_STATE_STATUS_IN, // STATUS IN — device sends IN-ZLP; awaits send-ACK IRQ + EP0_STATE_STATUS_OUT, // post-DATAEND, neither edpt0_xfer(STATUS OUT) nor confirmation IRQ has happened yet + EP0_STATE_STATUS_OUT_REQUESTED, // edpt0_xfer(STATUS OUT) was called first; awaiting confirmation IRQ to fire complete + EP0_STATE_STATUS_OUT_SENT, // confirmation IRQ arrived first; awaiting edpt0_xfer(STATUS OUT) to fire complete }; typedef struct { - uint16_t remaining_ctrl; /* The number of bytes remaining in data stage of control transfer. */ + uint16_t ep0_remain_datalen; /* The number of bytes remaining in data stage of control transfer. */ uint8_t ep0_state; uint8_t pending_addr; // new USB address latched by dcd_set_address, applied when STATUS IN completes pipe_state_t pipe[MUSB_PIPE_COUNT]; } dcd_data_t; -// EP0 control-transfer state is held by usbd_control.c (request, total_xferred, -// data_len). dcd tracks phase in _dcd.ep0_state. The SETUP packet is drained -// into a local in process_ep0 and dispatched upstream — never cached here. - static dcd_data_t _dcd; TU_ATTR_ALWAYS_INLINE static inline pipe_state_t* pipe_get(uint8_t epnum, tusb_dir_t epdir) { @@ -377,21 +369,18 @@ static bool edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_ const unsigned dir_in = tu_edpt_dir(ep_addr); switch (_dcd.ep0_state) { - case EP0_STATE_TX: - case EP0_STATE_RX: { - TU_ASSERT(dir_in ? _dcd.ep0_state == EP0_STATE_TX : _dcd.ep0_state == EP0_STATE_RX); - volatile void *fifo_ptr = &musb_regs->fifo[0]; + case EP0_STATE_DATA: { if (dir_in) { - // DATA IN: load FIFO, set TXRDY. Add DATAEND for a short packet (ends - // the data stage per USB short-packet rule). - tu_hwfifo_write(fifo_ptr, buffer, total_bytes, NULL); + // DATA IN: load FIFO, set TXRDY. Add DATAEND on the last chunk + // (ep0_remain_datalen == 0 after this load) to end the data stage. + tu_hwfifo_write(&musb_regs->fifo[0], buffer, total_bytes, NULL); pipe0->buf = buffer + total_bytes; pipe0->length = total_bytes; pipe0->remaining = 0; - _dcd.remaining_ctrl -= total_bytes; - if (_dcd.remaining_ctrl == 0) { - ep_csr->csr0l = MUSB_CSRL0_TXRDY | MUSB_CSRL0_DATAEND; // last packet, also set DATAEND to end the data stage + _dcd.ep0_remain_datalen -= total_bytes; + if (_dcd.ep0_remain_datalen == 0) { + ep_csr->csr0l = MUSB_CSRL0_TXRDY | MUSB_CSRL0_DATAEND; } else { ep_csr->csr0l = MUSB_CSRL0_TXRDY; } @@ -427,9 +416,7 @@ static bool edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_ return true; } -// 21.1.5: endpoint 0 service routine as peripheral. Drives the IDLE / -// IDLE / TX / RX / STATUS machine; direction on each IRQ is -// implied by the state. +// 21.1.5: endpoint 0 service routine as peripheral static void process_ep0(uint8_t rhport) { musb_regs_t* musb_regs = MUSB_REGS(rhport); musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, 0); @@ -465,41 +452,35 @@ static void process_ep0(uint8_t rhport) { setup_packet.u32[0] = musb_regs->fifo[0]; setup_packet.u32[1] = musb_regs->fifo[0]; - _dcd.remaining_ctrl = setup_packet.req.wLength; + _dcd.ep0_remain_datalen = setup_packet.req.wLength; - // Pick the next phase directly from the SETUP packet: Read → TX, - // Write → RX, zero-data → STATUS_IN. For Read, also ack SETUP's RXRDY - // now so the host can start IN tokens immediately; Write/zero-data - // leave it set so HW NAKs OUT tokens until edpt0_xfer clears it. if (setup_packet.req.wLength == 0) { _dcd.ep0_state = EP0_STATE_STATUS_IN; - } else if (tu_edpt_dir(setup_packet.req.bmRequestType)) { - _dcd.ep0_state = EP0_STATE_TX; - ep_csr->csr0l = MUSB_CSRL0_RXRDYC; } else { - _dcd.ep0_state = EP0_STATE_RX; + _dcd.ep0_state = EP0_STATE_DATA; + // If OUT (rx) direction, let edpt0_xfer() clear RXRDY when it's ready to receive data. + if (setup_packet.req.bmRequestType & TUSB_DIR_IN_MASK) { + ep_csr->csr0l = MUSB_CSRL0_RXRDYC; + } } dcd_event_setup_received(rhport, (const uint8_t *)&setup_packet.req, true); break; - case EP0_STATE_RX: { - /* DATA OUT: drain armed buffer, complete. Stay in RX — usbd posts - * edpt0_xfer(STATUS IN) next which transitions us to STATUS_IN. */ - const uint16_t len = tu_min16(tu_min16(pipe0->remaining, 64), count0); + case EP0_STATE_DATA: { + const uint16_t len = tu_min16(pipe0->remaining, count0); if (len) { tu_hwfifo_read(&musb_regs->fifo[0], pipe0->buf, len, NULL); pipe0->remaining -= len; - _dcd.remaining_ctrl -= len; + _dcd.ep0_remain_datalen -= len; } - if (_dcd.remaining_ctrl == 0) { - // last packet, leave it RXRDYC to edpt0_xfer() + if (_dcd.ep0_remain_datalen == 0) { + // last packet: change state and leave RXRDY for edpt0_xfer(STATUS IN) to ack _dcd.ep0_state = EP0_STATE_STATUS_IN; } else { ep_csr->csr0l = MUSB_CSRL0_RXRDYC; } - dcd_event_xfer_complete(rhport, tu_edpt_addr(0, TUSB_DIR_OUT), pipe0->length - pipe0->remaining, - XFER_RESULT_SUCCESS, true); + dcd_event_xfer_complete(rhport, TU_EP0_OUT, len, XFER_RESULT_SUCCESS, true); break; } @@ -513,12 +494,14 @@ static void process_ep0(uint8_t rhport) { * - completion of sending any length packet TxPktRdy clear * - or status stage is complete (ZLP) after DataEnd is set */ switch (_dcd.ep0_state) { - case EP0_STATE_TX: - if (_dcd.remaining_ctrl == 0) { - // last packet + case EP0_STATE_DATA: + // csrl == 0 in DATA state = TXRDY just cleared, i.e. a DATA IN packet was successfully sent. If the just-sent + // packet was the last (DATAEND was set when ep0_remain_datalen hit zero), transition + // to STATUS_OUT to await the host's STATUS-OUT ZLP confirmation IRQ. + if (_dcd.ep0_remain_datalen == 0) { _dcd.ep0_state = EP0_STATE_STATUS_OUT; } - dcd_event_xfer_complete(rhport, 0x80, pipe0->length, XFER_RESULT_SUCCESS, true); + dcd_event_xfer_complete(rhport, TU_EP0_IN, pipe0->length, XFER_RESULT_SUCCESS, true); break; case EP0_STATE_STATUS_OUT: @@ -528,7 +511,7 @@ static void process_ep0(uint8_t rhport) { case EP0_STATE_STATUS_OUT_REQUESTED: _dcd.ep0_state = EP0_STATE_IDLE; - dcd_event_xfer_complete(rhport, 0, 0, XFER_RESULT_SUCCESS, true); + dcd_event_xfer_complete(rhport, TU_EP0_OUT, 0, XFER_RESULT_SUCCESS, true); break; case EP0_STATE_STATUS_IN: @@ -537,7 +520,7 @@ static void process_ep0(uint8_t rhport) { _dcd.pending_addr = 0; } _dcd.ep0_state = EP0_STATE_IDLE; - dcd_event_xfer_complete(rhport, 0x80, 0, XFER_RESULT_SUCCESS, true); + dcd_event_xfer_complete(rhport, TU_EP0_IN, 0, XFER_RESULT_SUCCESS, true); break; default: break; @@ -833,7 +816,7 @@ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, epn); if (0 == epn) { - if (!ep_addr) { /* Ignore EP80 */ + if (ep_addr == TU_EP0_OUT) { /* Ignore EP0 OUT */ _dcd.ep0_state = EP0_STATE_IDLE; pipe_state_t* pipe0 = pipe_get(0, TUSB_DIR_OUT); pipe0->buf = NULL; -- cgit v1.3.1 From b87876b2760cf265b093637205c3e72e7550f521 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 25 Apr 2026 17:03:59 +0700 Subject: separate pipe0 since it is 1 packet per transfer, merge PIPE0 STATUS PENDING --- src/portable/mentor/musb/dcd_musb.c | 185 +++++++++++++++++------------------- 1 file changed, 85 insertions(+), 100 deletions(-) (limited to 'src/portable') diff --git a/src/portable/mentor/musb/dcd_musb.c b/src/portable/mentor/musb/dcd_musb.c index 66fa86c77..56429ac1f 100644 --- a/src/portable/mentor/musb/dcd_musb.c +++ b/src/portable/mentor/musb/dcd_musb.c @@ -67,51 +67,51 @@ typedef struct { bool use_fifo; /* true: buf is tu_fifo_t*; false: buf is plain byte pointer. */ } pipe_state_t; -// Pipe array layout (N = TUP_DCD_ENDPOINT_MAX): -// [0] : EP0 (shared between IN/OUT control stages) +// Pipe array layout (N = TUP_DCD_ENDPOINT_MAX). EP0 has its own scalars in +// dcd_data_t and does not occupy a pipe slot. // One-direction-only IPs (CFG_TUD_ENDPOINT_ONE_DIRECTION_ONLY=1): -// [1..N-1] : EP1..N-1 (single slot per endpoint) +// [0..N-2] : EP1..N-1 (single slot per endpoint) // Bidirectional-capable IPs: -// [1..N-1 ] : EP OUT -// [N..2*N-2] : EP IN +// [0..N-2 ] : EP1..N-1 OUT +// [N-1..2*N-3 ] : EP1..N-1 IN #if CFG_TUD_ENDPOINT_ONE_DIRECTION_ONLY - #define MUSB_PIPE_COUNT TUP_DCD_ENDPOINT_MAX + #define MUSB_PIPE_COUNT (TUP_DCD_ENDPOINT_MAX - 1u) #else - #define MUSB_PIPE_COUNT (2u * TUP_DCD_ENDPOINT_MAX - 1u) + #define MUSB_PIPE_COUNT (2u * (TUP_DCD_ENDPOINT_MAX - 1u)) #endif enum { - EP0_STATE_IDLE = 0, // no active control transfer - EP0_STATE_DATA, // DATA stage (IN or OUT — direction implied by CSR/dir) - EP0_STATE_STATUS_IN, // STATUS IN — device sends IN-ZLP; awaits send-ACK IRQ - EP0_STATE_STATUS_OUT, // post-DATAEND, neither edpt0_xfer(STATUS OUT) nor confirmation IRQ has happened yet - EP0_STATE_STATUS_OUT_REQUESTED, // edpt0_xfer(STATUS OUT) was called first; awaiting confirmation IRQ to fire complete - EP0_STATE_STATUS_OUT_SENT, // confirmation IRQ arrived first; awaiting edpt0_xfer(STATUS OUT) to fire complete + PIPE0_STATE_IDLE = 0, // no active control transfer + PIPE0_STATE_DATA, // DATA stage (IN or OUT — direction implied by CSR/dir) + PIPE0_STATE_STATUS_IN, // STATUS IN — device sends IN-ZLP; awaits send-ACK IRQ + PIPE0_STATE_STATUS_OUT, // post-DATAEND, neither edpt0_xfer(STATUS OUT) nor confirmation IRQ has happened yet + PIPE0_STATE_STATUS_OUT_PENDING, // one of {edpt0_xfer(STATUS OUT), confirmation IRQ} has happened; the other fires xfer_complete }; typedef struct { - uint16_t ep0_remain_datalen; /* The number of bytes remaining in data stage of control transfer. */ - uint8_t ep0_state; - uint8_t pending_addr; // new USB address latched by dcd_set_address, applied when STATUS IN completes + struct { + uint8_t *buf; // DATA OUT drain target (only valid while EP0 is in DATA OUT stage) + uint16_t xact_len; // chunk length most recently armed via edpt0_xfer; reported in xfer_complete + uint16_t remain_wlength; // bytes remaining in the control transfer's DATA stage + uint8_t state; + uint8_t pending_addr; // new USB address latched by dcd_set_address; applied when STATUS IN completes + } pipe0; pipe_state_t pipe[MUSB_PIPE_COUNT]; } dcd_data_t; static dcd_data_t _dcd; +// EP0 must not call this — it has its own scalars in dcd_data_t. TU_ATTR_ALWAYS_INLINE static inline pipe_state_t* pipe_get(uint8_t epnum, tusb_dir_t epdir) { + size_t idx = epnum - 1u; #if CFG_TUD_ENDPOINT_ONE_DIRECTION_ONLY (void) epdir; - return &_dcd.pipe[epnum]; #else - if (epnum == 0) { - return &_dcd.pipe[0]; - } - size_t idx = epnum; if (epdir == TUSB_DIR_IN) { idx += TUP_DCD_ENDPOINT_MAX - 1u; } - return &_dcd.pipe[idx]; #endif + return &_dcd.pipe[idx]; } //-------------------------------------------------------------------- @@ -240,7 +240,8 @@ static void pipe_write(musb_regs_t* musb_regs, pipe_state_t* pipe, uint8_t epnum // signal completion; otherwise queue the next packet. static void process_epin(uint8_t rhport, musb_regs_t *musb_regs, uint8_t epnum) { musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, epnum); - if (ep_csr->tx_csrl & MUSB_TXCSRL1_STALLED) { + const uint_fast8_t csrl = ep_csr->tx_csrl; + if (csrl & MUSB_TXCSRL1_STALLED) { ep_csr->tx_csrl &= ~(MUSB_TXCSRL1_STALLED | MUSB_TXCSRL1_UNDRN); return; // sent STALL, do nothing } @@ -254,7 +255,7 @@ static void process_epin(uint8_t rhport, musb_regs_t *musb_regs, uint8_t epnum) // hardware signals TXRDY clear as soon as a slot frees, not when the wire // transfer finishes). Defer completion until FIFONE == 0 so we don't emit // a duplicate xfer_complete before the final packet has been sent. - if (ep_csr->tx_csrl & MUSB_TXCSRL1_FIFONE) { + if (csrl & MUSB_TXCSRL1_FIFONE) { return; } const uint16_t xferred_len = pipe->length; @@ -353,60 +354,47 @@ static bool edpt_n_xfer(uint8_t rhport, uint8_t ep_addr, void *buffer, uint16_t return true; } -// EP0 transfer dispatcher. usbd_control.c drives this with one of: -// - DATA IN : ep=0x80, buffer != NULL, total_bytes > 0 (write a chunk) -// - DATA OUT : ep=0x00, buffer != NULL, total_bytes > 0 (arm to receive) -// - STATUS IN : ep=0x80, total_bytes == 0 (zero-len ack of OUT request) -// - STATUS OUT: ep=0x00, total_bytes == 0 (zero-len ack of IN request, -// HW already auto-handled it -// when DATAEND was set on the -// last DATA IN packet) static bool edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes, bool is_isr) { - TU_ASSERT(total_bytes <= CFG_TUD_ENDPOINT0_SIZE); /* Current implementation supports for only up to 64 bytes. */ + TU_ASSERT(total_bytes <= CFG_TUD_ENDPOINT0_SIZE); /* EP0 only supports 1 packet per dcd_edpt_xfer()*/ musb_regs_t* musb_regs = MUSB_REGS(rhport); musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, 0); - pipe_state_t* pipe0 = pipe_get(0, TUSB_DIR_OUT); const unsigned dir_in = tu_edpt_dir(ep_addr); - switch (_dcd.ep0_state) { - case EP0_STATE_DATA: { + switch (_dcd.pipe0.state) { + case PIPE0_STATE_DATA: { + _dcd.pipe0.xact_len = total_bytes; if (dir_in) { // DATA IN: load FIFO, set TXRDY. Add DATAEND on the last chunk // (ep0_remain_datalen == 0 after this load) to end the data stage. tu_hwfifo_write(&musb_regs->fifo[0], buffer, total_bytes, NULL); - pipe0->buf = buffer + total_bytes; - pipe0->length = total_bytes; - pipe0->remaining = 0; - - _dcd.ep0_remain_datalen -= total_bytes; - if (_dcd.ep0_remain_datalen == 0) { + _dcd.pipe0.remain_wlength -= total_bytes; + if (_dcd.pipe0.remain_wlength == 0) { ep_csr->csr0l = MUSB_CSRL0_TXRDY | MUSB_CSRL0_DATAEND; } else { ep_csr->csr0l = MUSB_CSRL0_TXRDY; } } else { - // DATA OUT: arm, ack RXRDY so host can send DATA OUT. - pipe0->buf = buffer; - pipe0->length = total_bytes; - pipe0->remaining = total_bytes; + // DATA OUT: arm drain target, ack RXRDY so host can send DATA OUT. + _dcd.pipe0.buf = buffer; ep_csr->csr0l = MUSB_CSRL0_RXRDYC; } break; } - case EP0_STATE_STATUS_IN: + case PIPE0_STATE_STATUS_IN: TU_ASSERT(dir_in && total_bytes == 0); // only STATUS IN allowed ep_csr->csr0l = MUSB_CSRL0_RXRDYC | MUSB_CSRL0_DATAEND; break; - case EP0_STATE_STATUS_OUT: + case PIPE0_STATE_STATUS_OUT: TU_ASSERT(!dir_in && total_bytes == 0); // only STATUS OUT allowed - _dcd.ep0_state = EP0_STATE_STATUS_OUT_REQUESTED; + // First event of the STATUS OUT pair — wait for the IRQ to fire complete. + _dcd.pipe0.state = PIPE0_STATE_STATUS_OUT_PENDING; break; - case EP0_STATE_STATUS_OUT_SENT: - // status is already sent to host, complete it here - _dcd.ep0_state = EP0_STATE_IDLE; + case PIPE0_STATE_STATUS_OUT_PENDING: + // Second event — IRQ already arrived, fire complete now. + _dcd.pipe0.state = PIPE0_STATE_IDLE; dcd_event_xfer_complete(rhport, ep_addr, 0, XFER_RESULT_SUCCESS, is_isr); break; @@ -420,12 +408,11 @@ static bool edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_ static void process_ep0(uint8_t rhport) { musb_regs_t* musb_regs = MUSB_REGS(rhport); musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, 0); - pipe_state_t* pipe0 = pipe_get(0, TUSB_DIR_OUT); uint_fast8_t csrl = ep_csr->csr0l; if (csrl & MUSB_CSRL0_STALLED) { ep_csr->csr0l = 0; - _dcd.ep0_state = EP0_STATE_IDLE; + _dcd.pipe0.state = PIPE0_STATE_IDLE; return; } @@ -433,7 +420,7 @@ static void process_ep0(uint8_t rhport) { // Host aborted the current control transfer (new SETUP or premature STATUS). // do nothing, it is probably another setup packet, usbd will reset its state. ep_csr->csr0l = MUSB_CSRL0_SETENDC; - _dcd.ep0_state = EP0_STATE_IDLE; + _dcd.pipe0.state = PIPE0_STATE_IDLE; if (!(csrl & MUSB_CSRL0_RXRDY)) { return; /* no SETUP waiting behind it */ } @@ -442,8 +429,8 @@ static void process_ep0(uint8_t rhport) { // Receive Data (Setup or OUT) if (csrl & MUSB_CSRL0_RXRDY) { const uint16_t count0 = ep_csr->count0; - switch (_dcd.ep0_state) { - case EP0_STATE_IDLE: + switch (_dcd.pipe0.state) { + case PIPE0_STATE_IDLE: TU_ASSERT(sizeof(tusb_control_request_t) == count0, ); union { tusb_control_request_t req; @@ -452,12 +439,12 @@ static void process_ep0(uint8_t rhport) { setup_packet.u32[0] = musb_regs->fifo[0]; setup_packet.u32[1] = musb_regs->fifo[0]; - _dcd.ep0_remain_datalen = setup_packet.req.wLength; + _dcd.pipe0.remain_wlength = setup_packet.req.wLength; if (setup_packet.req.wLength == 0) { - _dcd.ep0_state = EP0_STATE_STATUS_IN; + _dcd.pipe0.state = PIPE0_STATE_STATUS_IN; } else { - _dcd.ep0_state = EP0_STATE_DATA; + _dcd.pipe0.state = PIPE0_STATE_DATA; // If OUT (rx) direction, let edpt0_xfer() clear RXRDY when it's ready to receive data. if (setup_packet.req.bmRequestType & TUSB_DIR_IN_MASK) { ep_csr->csr0l = MUSB_CSRL0_RXRDYC; @@ -466,21 +453,20 @@ static void process_ep0(uint8_t rhport) { dcd_event_setup_received(rhport, (const uint8_t *)&setup_packet.req, true); break; - case EP0_STATE_DATA: { - const uint16_t len = tu_min16(pipe0->remaining, count0); - if (len) { - tu_hwfifo_read(&musb_regs->fifo[0], pipe0->buf, len, NULL); - pipe0->remaining -= len; - _dcd.ep0_remain_datalen -= len; + case PIPE0_STATE_DATA: { + // EP0 OUT is single-packet (TU_ASSERT total_bytes <= EP0_SIZE in edpt0_xfer) + // so the whole packet drains in one shot. + if (count0) { + tu_hwfifo_read(&musb_regs->fifo[0], _dcd.pipe0.buf, count0, NULL); + _dcd.pipe0.remain_wlength -= count0; } - - if (_dcd.ep0_remain_datalen == 0) { + if (_dcd.pipe0.remain_wlength == 0) { // last packet: change state and leave RXRDY for edpt0_xfer(STATUS IN) to ack - _dcd.ep0_state = EP0_STATE_STATUS_IN; + _dcd.pipe0.state = PIPE0_STATE_STATUS_IN; } else { ep_csr->csr0l = MUSB_CSRL0_RXRDYC; } - dcd_event_xfer_complete(rhport, TU_EP0_OUT, len, XFER_RESULT_SUCCESS, true); + dcd_event_xfer_complete(rhport, TU_EP0_OUT, count0, XFER_RESULT_SUCCESS, true); break; } @@ -493,33 +479,34 @@ static void process_ep0(uint8_t rhport) { /* When CSRL0 is zero, it means that either * - completion of sending any length packet TxPktRdy clear * - or status stage is complete (ZLP) after DataEnd is set */ - switch (_dcd.ep0_state) { - case EP0_STATE_DATA: + switch (_dcd.pipe0.state) { + case PIPE0_STATE_DATA: // csrl == 0 in DATA state = TXRDY just cleared, i.e. a DATA IN packet was successfully sent. If the just-sent // packet was the last (DATAEND was set when ep0_remain_datalen hit zero), transition // to STATUS_OUT to await the host's STATUS-OUT ZLP confirmation IRQ. - if (_dcd.ep0_remain_datalen == 0) { - _dcd.ep0_state = EP0_STATE_STATUS_OUT; + if (_dcd.pipe0.remain_wlength == 0) { + _dcd.pipe0.state = PIPE0_STATE_STATUS_OUT; } - dcd_event_xfer_complete(rhport, TU_EP0_IN, pipe0->length, XFER_RESULT_SUCCESS, true); + dcd_event_xfer_complete(rhport, TU_EP0_IN, _dcd.pipe0.xact_len, XFER_RESULT_SUCCESS, true); break; - case EP0_STATE_STATUS_OUT: - // edpt0_xfer() for this is not yet requested, let it call xfer_complete() later - _dcd.ep0_state = EP0_STATE_STATUS_OUT_SENT; + case PIPE0_STATE_STATUS_OUT: + // First event of the STATUS OUT pair — wait for edpt0_xfer(STATUS OUT) to fire complete. + _dcd.pipe0.state = PIPE0_STATE_STATUS_OUT_PENDING; break; - case EP0_STATE_STATUS_OUT_REQUESTED: - _dcd.ep0_state = EP0_STATE_IDLE; + case PIPE0_STATE_STATUS_OUT_PENDING: + // Second event — edpt0_xfer(STATUS OUT) already called, fire complete now. + _dcd.pipe0.state = PIPE0_STATE_IDLE; dcd_event_xfer_complete(rhport, TU_EP0_OUT, 0, XFER_RESULT_SUCCESS, true); break; - case EP0_STATE_STATUS_IN: - if (_dcd.pending_addr) { - musb_regs->faddr = _dcd.pending_addr; - _dcd.pending_addr = 0; + case PIPE0_STATE_STATUS_IN: + if (_dcd.pipe0.pending_addr) { + musb_regs->faddr = _dcd.pipe0.pending_addr; + _dcd.pipe0.pending_addr = 0; } - _dcd.ep0_state = EP0_STATE_IDLE; + _dcd.pipe0.state = PIPE0_STATE_IDLE; dcd_event_xfer_complete(rhport, TU_EP0_IN, 0, XFER_RESULT_SUCCESS, true); break; @@ -536,10 +523,10 @@ static void process_bus_reset(uint8_t rhport) { alloced_fifo_bytes = CFG_TUD_ENDPOINT0_SIZE; #endif - _dcd.ep0_state = EP0_STATE_IDLE; - /* When EP0 pipe buf has not NULL, DATA stage works in progress. */ - pipe_state_t* pipe0 = pipe_get(0, TUSB_DIR_OUT); - pipe0->buf = NULL; + _dcd.pipe0.state = PIPE0_STATE_IDLE; + _dcd.pipe0.buf = NULL; + _dcd.pipe0.xact_len = 0; + _dcd.pipe0.remain_wlength = 0; musb->intr_txen = 1; /* Enable only EP0 */ musb->intr_rxen = 0; @@ -608,13 +595,11 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) { musb_regs_t* musb_regs = MUSB_REGS(rhport); musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, 0); - pipe_state_t* pipe0 = pipe_get(0, TUSB_DIR_OUT); - _dcd.pending_addr = dev_addr; - pipe0->buf = NULL; - pipe0->length = 0; - pipe0->remaining = 0; - _dcd.ep0_state = EP0_STATE_STATUS_IN; + _dcd.pipe0.pending_addr = dev_addr; + _dcd.pipe0.buf = NULL; + _dcd.pipe0.xact_len = 0; + _dcd.pipe0.state = PIPE0_STATE_STATUS_IN; /* Send STATUS IN ZLP with DATAEND; host ACK fires the confirmation IRQ. */ ep_csr->csr0l = MUSB_CSRL0_RXRDYC | MUSB_CSRL0_DATAEND; } @@ -817,15 +802,15 @@ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { if (0 == epn) { if (ep_addr == TU_EP0_OUT) { /* Ignore EP0 OUT */ - _dcd.ep0_state = EP0_STATE_IDLE; - pipe_state_t* pipe0 = pipe_get(0, TUSB_DIR_OUT); - pipe0->buf = NULL; + _dcd.pipe0.state = PIPE0_STATE_IDLE; + _dcd.pipe0.buf = NULL; ep_csr->csr0l = MUSB_CSRL0_STALL; } } else { - const uint8_t is_rx = 1 - tu_edpt_dir(ep_addr); + const tusb_dir_t ep_dir = tu_edpt_dir(ep_addr); + const uint8_t is_rx = (ep_dir == TUSB_DIR_OUT ? 1u : 0u); ep_csr->maxp_csr[is_rx].csrl = MUSB_CSRL_SEND_STALL(is_rx); - pipe_state_t* pipe = pipe_get(epn, tu_edpt_dir(ep_addr)); + pipe_state_t* pipe = pipe_get(epn, ep_dir); pipe->armed = false; } -- cgit v1.3.1 From 7258db344e99398a5e10f4c65b24d38c6b94b92b Mon Sep 17 00:00:00 2001 From: mickabrig7 Date: Tue, 28 Apr 2026 12:24:00 +0900 Subject: fix(dcd_ch32_usbfs): fix dropped bulk OUT packets by properly re-arming EP_RX_CTRL state --- src/portable/wch/dcd_ch32_usbfs.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/portable') diff --git a/src/portable/wch/dcd_ch32_usbfs.c b/src/portable/wch/dcd_ch32_usbfs.c index 5cd25e33e..39c1cfb4a 100644 --- a/src/portable/wch/dcd_ch32_usbfs.c +++ b/src/portable/wch/dcd_ch32_usbfs.c @@ -118,6 +118,9 @@ static void update_out(uint8_t rhport, uint8_t ep, size_t rx_len) { if (ep == 0) { EP_RX_CTRL(0) = USBFS_EP_R_RES_ACK; + } else { + EP_RX_CTRL(ep) = (EP_RX_CTRL(ep) & ~USBFS_EP_R_RES_MASK) | + (xfer->valid ? USBFS_EP_R_RES_ACK : USBFS_EP_R_RES_NAK); } } } @@ -312,6 +315,8 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t t if (dir == TUSB_DIR_IN) { update_in(rhport, ep, true); + } else { + EP_RX_CTRL(ep) = (EP_RX_CTRL(ep) & ~USBFS_EP_R_RES_MASK) | USBFS_EP_R_RES_ACK; } return true; } -- cgit v1.3.1 From 17d24b397f772fb475b2be6c387c3023664df0a6 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Mon, 4 May 2026 20:10:58 +0200 Subject: hcd/dwc2: fix txfifo full check Signed-off-by: HiFiPhile --- src/portable/synopsys/dwc2/hcd_dwc2.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src/portable') diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index 6098d6eaa..9ea5f33c5 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -903,9 +903,6 @@ 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) - 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]; @@ -923,6 +920,8 @@ static bool handle_txfifo_empty(dwc2_regs_t* dwc2, bool is_periodic) { // skip if there is not enough space in FIFO and RequestQueue. // Packet's last word written to FIFO will trigger a request queue + // 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)}; if ((xact_bytes > (txsts.fifo_available << 2)) || (txsts.req_queue_available == 0)) { return true; } -- cgit v1.3.1 From 6af4ee2c50da68a9bca276b69fccbacf96e2b3ce Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 8 May 2026 21:27:53 +0700 Subject: nrf5x: request HFCLK in USB_EVT_READY to fix post-SoftDevice deadlock USB_EVT_DETECTED runs hfclk_enable() which, when SoftDevice is not yet enabled, starts HFXO via direct CLOCK register access. After sd_softdevice_enable() takes over CLOCK, HFXO is physically off again and SD's HFCLK reference count is 0. If USB_EVT_READY is fired post-SD (e.g. on nRF52 via Bluefruit's usb_softdevice_post_enable() when the pre-SD nrfx_power READY callback didn't get to run before nrfx_power was uninited), the wait loop 'while (!hfclk_running()) {}' calls sd_clock_hfclk_is_running() which returns false forever -> deadlock that blocks both USB enumeration and any further app code on the calling thread. Call hfclk_enable() right before the wait so HFCLK is requested in whichever context (SD or direct) is current. hfclk_enable() is idempotent. Reproduces reliably with bleuart on Feather nRF52840 Express flashed via JLink: chip wedges in sd_clock_hfclk_is_running SVC, no USB enumeration, no BLE advertising. With the fix, USB enumerates and BLE advertises as expected. --- src/portable/nordic/nrf5x/dcd_nrf5x.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/portable') diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c index 6ed5fde8e..befbaa338 100644 --- a/src/portable/nordic/nrf5x/dcd_nrf5x.c +++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c @@ -1049,6 +1049,12 @@ void tusb_hal_nrf_power_event(uint32_t event) { NVIC_EnableIRQ(USBD_IRQn); } + // Ensure HFCLK is requested in the current context. The hfclk_enable() in + // USB_EVT_DETECTED may have been pre-SoftDevice. After Softdevice is + // enabled, HFXO is physically off again. So any caller that fires + // USB_EVT_READY post-SD would hang here. + hfclk_enable(); + // Wait for HFCLK while (!hfclk_running()) {} -- cgit v1.3.1 From cfdab2564fa5735f0a7d5653aa6eb5388456028e Mon Sep 17 00:00:00 2001 From: Alex-Schaefer <81265029+Alex-Schaefer@users.noreply.github.com> Date: Sat, 9 May 2026 09:10:47 +0200 Subject: dwc2: preserve EP0 status completion before SETUP On STM32 DWC2, SETUP phase done and EP0 OUT transfer complete can be reported together. Processing SETUP first can overwrite control state before the previous zero-length OUT status stage is acknowledged, which causes DFU DNLOAD/GETSTATUS traffic to lose the status ACK and stall. Queue the EP0 OUT zero-length transfer completion before queuing the SETUP event when the endpoint has no pending OUT data and total_len is zero. This keeps TinyUSB control-transfer ordering intact for the combined interrupt case. --- src/portable/synopsys/dwc2/dcd_dwc2.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) (limited to 'src/portable') diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index 30e24a9ad..9b8f44df8 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -946,7 +946,17 @@ static void handle_rxflvl_irq(uint8_t rhport) { } static void handle_epout_slave(uint8_t rhport, uint8_t epnum, dwc2_doepint_t doepint_bm) { + xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); + const bool ep0_status_complete_before_setup = (epnum == 0) && doepint_bm.setup_phase_done && + doepint_bm.xfer_complete && + (_dcd_data.ep0_pending[TUSB_DIR_OUT] == 0) && + (xfer->total_len == 0); + if (doepint_bm.setup_phase_done) { + if (ep0_status_complete_before_setup) { + dcd_event_xfer_complete(rhport, epnum, 0, XFER_RESULT_SUCCESS, true); + } + // Cleanup previous pending EP0 IN transfer if any dwc2_dep_t* epin0 = &DWC2_REG(rhport)->epin[0]; if (edpt_is_enabled(epin0)) { @@ -962,7 +972,6 @@ static void handle_epout_slave(uint8_t rhport, uint8_t epnum, dwc2_doepint_t doe // Note: even though (xfer_complete + status_phase_rx) is for buffered DMA only, for STM32L47x (dwc2 v3.00a) they // can is set when GRXSTS_PKTSTS_SETUP_RX is popped therefore they can bet set before/together with setup_phase_done if (!doepint_bm.status_phase_rx && !doepint_bm.setup_packet_rx) { - xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); if ((epnum == 0) && _dcd_data.ep0_pending[TUSB_DIR_OUT]) { // EP0 can only handle one packet, Schedule another packet to be received. edpt_schedule_packets(rhport, epnum, TUSB_DIR_OUT); @@ -1005,8 +1014,17 @@ static void handle_epin_slave(uint8_t rhport, uint8_t epnum, dwc2_diepint_t diep #if CFG_TUD_DWC2_DMA_ENABLE static void handle_epout_dma(uint8_t rhport, uint8_t epnum, dwc2_doepint_t doepint_bm) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); + xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); + const bool ep0_status_complete_before_setup = (epnum == 0) && doepint_bm.setup_phase_done && + doepint_bm.xfer_complete && + (_dcd_data.ep0_pending[TUSB_DIR_OUT] == 0) && + (xfer->total_len == 0); if (doepint_bm.setup_phase_done) { + if (ep0_status_complete_before_setup) { + dcd_event_xfer_complete(rhport, epnum, 0, XFER_RESULT_SUCCESS, true); + } + // Cleanup previous pending EP0 IN transfer if any dwc2_dep_t* epin0 = &DWC2_REG(rhport)->epin[0]; if (edpt_is_enabled(epin0)) { @@ -1028,7 +1046,6 @@ static void handle_epout_dma(uint8_t rhport, uint8_t epnum, dwc2_doepint_t doepi edpt_schedule_packets(rhport, epnum, TUSB_DIR_OUT); } else { dwc2_dep_t* epout = &dwc2->epout[epnum]; - xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); // determine actual received bytes const dwc2_ep_tsize_t tsiz = {.value = epout->tsiz}; -- cgit v1.3.1 From 16bc0548dc0793404a5885aa90d78100b604c227 Mon Sep 17 00:00:00 2001 From: Alex-Schaefer <81265029+Alex-Schaefer@users.noreply.github.com> Date: Sat, 9 May 2026 11:14:00 +0200 Subject: dwc2: guard EP0 status completion with armed ZLP state Track when an EP0 OUT zero-length transfer is actually armed and require that state before synthesizing a status-stage completion ahead of a co-reported SETUP event. This preserves the validated status-before-SETUP ordering fix while avoiding stale zero-length state from producing spurious EP0 OUT completions. --- src/portable/synopsys/dwc2/dcd_dwc2.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'src/portable') diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index 9b8f44df8..72beb1b80 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -62,6 +62,7 @@ static xfer_ctl_t xfer_status[DWC2_EP_MAX][2]; 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 + bool ep0_out_zlp_armed; // EP0 OUT ZLP transfer is armed and waiting for completion uint16_t dfifo_top; // top free location in DFIFO in words // Number of IN endpoints active @@ -665,6 +666,9 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to // EP0 can only handle one packet if (epnum == 0) { _dcd_data.ep0_pending[dir] = total_bytes; + if (dir == TUSB_DIR_OUT) { + _dcd_data.ep0_out_zlp_armed = (total_bytes == 0); + } } // Schedule packets to be sent within interrupt @@ -744,6 +748,9 @@ static void handle_bus_reset(uint8_t rhport) { tu_memclr(xfer_status, sizeof(xfer_status)); + _dcd_data.ep0_pending[TUSB_DIR_OUT] = 0; + _dcd_data.ep0_pending[TUSB_DIR_IN] = 0; + _dcd_data.ep0_out_zlp_armed = false; _dcd_data.sof_en = false; _dcd_data.allocated_epin_count = 0; @@ -949,12 +956,16 @@ static void handle_epout_slave(uint8_t rhport, uint8_t epnum, dwc2_doepint_t doe xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); const bool ep0_status_complete_before_setup = (epnum == 0) && doepint_bm.setup_phase_done && doepint_bm.xfer_complete && + _dcd_data.ep0_out_zlp_armed && (_dcd_data.ep0_pending[TUSB_DIR_OUT] == 0) && (xfer->total_len == 0); if (doepint_bm.setup_phase_done) { if (ep0_status_complete_before_setup) { + _dcd_data.ep0_out_zlp_armed = false; dcd_event_xfer_complete(rhport, epnum, 0, XFER_RESULT_SUCCESS, true); + } else if (epnum == 0) { + _dcd_data.ep0_out_zlp_armed = false; } // Cleanup previous pending EP0 IN transfer if any @@ -976,6 +987,9 @@ static void handle_epout_slave(uint8_t rhport, uint8_t epnum, dwc2_doepint_t doe // EP0 can only handle one packet, Schedule another packet to be received. edpt_schedule_packets(rhport, epnum, TUSB_DIR_OUT); } else { + if (epnum == 0) { + _dcd_data.ep0_out_zlp_armed = false; + } dcd_event_xfer_complete(rhport, epnum, xfer->total_len, XFER_RESULT_SUCCESS, true); } } @@ -1017,12 +1031,16 @@ 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); const bool ep0_status_complete_before_setup = (epnum == 0) && doepint_bm.setup_phase_done && doepint_bm.xfer_complete && + _dcd_data.ep0_out_zlp_armed && (_dcd_data.ep0_pending[TUSB_DIR_OUT] == 0) && (xfer->total_len == 0); if (doepint_bm.setup_phase_done) { if (ep0_status_complete_before_setup) { + _dcd_data.ep0_out_zlp_armed = false; dcd_event_xfer_complete(rhport, epnum, 0, XFER_RESULT_SUCCESS, true); + } else if (epnum == 0) { + _dcd_data.ep0_out_zlp_armed = false; } // Cleanup previous pending EP0 IN transfer if any @@ -1058,6 +1076,9 @@ static void handle_epout_dma(uint8_t rhport, uint8_t epnum, dwc2_doepint_t doepi dma_setup_prepare(rhport); } + if (epnum == 0) { + _dcd_data.ep0_out_zlp_armed = false; + } dcd_dcache_invalidate(xfer->buffer, xfer->total_len); dcd_event_xfer_complete(rhport, epnum, xfer->total_len, XFER_RESULT_SUCCESS, true); } -- cgit v1.3.1 From 5ea1979e290ed80430a5b65b56534373ecbdd56f Mon Sep 17 00:00:00 2001 From: HiFiPHile Date: Sun, 10 May 2026 01:47:21 +0200 Subject: add stm32c5 support Signed-off-by: HiFiPHile --- .github/workflows/ci_set_matrix.py | 1 + README.rst | 2 +- docs/reference/boards.rst | 1 + docs/reference/dependencies.rst | 4 +- .../device/cdc_msc_throughput/CMakePresets.json | 6 + examples/device/printer_to_cdc/CMakePresets.json | 6 + examples/dual/dynamic_switch/only.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/midi_rx/only.txt | 1 + examples/host/msc_file_explorer/only.txt | 1 + hw/bsp/BoardPresets.json | 22 + hw/bsp/stm32c5/FreeRTOSConfig/FreeRTOSConfig.h | 165 +++++ hw/bsp/stm32c5/boards/stm32c542nucleo/board.cmake | 13 + hw/bsp/stm32c5/boards/stm32c542nucleo/board.h | 83 +++ hw/bsp/stm32c5/boards/stm32c542nucleo/board.mk | 13 + hw/bsp/stm32c5/family.c | 237 +++++++ hw/bsp/stm32c5/family.cmake | 111 ++++ hw/bsp/stm32c5/family.mk | 52 ++ hw/bsp/stm32c5/stm32c5xx_hal_conf.h | 684 +++++++++++++++++++++ src/common/tusb_mcu.h | 6 + src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 1 + src/portable/st/stm32_fsdev/fsdev_stm32.h | 8 +- src/tusb_option.h | 1 + tools/get_deps.py | 8 +- 27 files changed, 1427 insertions(+), 4 deletions(-) create mode 100644 examples/device/cdc_msc_throughput/CMakePresets.json create mode 100644 examples/device/printer_to_cdc/CMakePresets.json create mode 100644 hw/bsp/stm32c5/FreeRTOSConfig/FreeRTOSConfig.h create mode 100644 hw/bsp/stm32c5/boards/stm32c542nucleo/board.cmake create mode 100644 hw/bsp/stm32c5/boards/stm32c542nucleo/board.h create mode 100644 hw/bsp/stm32c5/boards/stm32c542nucleo/board.mk create mode 100644 hw/bsp/stm32c5/family.c create mode 100644 hw/bsp/stm32c5/family.cmake create mode 100644 hw/bsp/stm32c5/family.mk create mode 100644 hw/bsp/stm32c5/stm32c5xx_hal_conf.h (limited to 'src/portable') diff --git a/.github/workflows/ci_set_matrix.py b/.github/workflows/ci_set_matrix.py index 1d35f15dd..f4d25fd37 100755 --- a/.github/workflows/ci_set_matrix.py +++ b/.github/workflows/ci_set_matrix.py @@ -68,6 +68,7 @@ family_list = { "samd5x_e5x": ["arm-gcc", "arm-clang"], "samg": ["arm-gcc", "arm-clang"], "stm32c0": ["arm-gcc", "arm-clang", "arm-iar"], + "stm32c5": ["arm-gcc", "arm-clang", "arm-iar"], "stm32f0": ["arm-gcc", "arm-clang", "arm-iar"], "stm32f1": ["arm-gcc", "arm-clang", "arm-iar"], "stm32f2": ["arm-gcc", "arm-clang", "arm-iar"], diff --git a/README.rst b/README.rst index 04998abaa..1c56a6ba0 100644 --- a/README.rst +++ b/README.rst @@ -238,7 +238,7 @@ Supported CPUs | +----+------------------------+--------+------+-----------+------------------------+--------------------+ | | F2, F4, F7, H7, H7RS | ✔ | ✔ | ✔ | dwc2 | | | +-----------------------------+--------+------+-----------+------------------------+--------------------+ -| | C0, G0, H5, U3 | ✔ | ✔ | ✖ | stm32_fsdev | 2KB USB RAM | +| | C0, C5, G0, H5, U3 | ✔ | ✔ | ✖ | stm32_fsdev | 2KB USB RAM | | +-----------------------------+--------+------+-----------+------------------------+--------------------+ | | G4 | ✔ | ✖ | ✖ | stm32_fsdev | 1KB USB RAM | | +----+------------------------+--------+------+-----------+------------------------+--------------------+ diff --git a/docs/reference/boards.rst b/docs/reference/boards.rst index e61c4f98b..b0e8bffaa 100644 --- a/docs/reference/boards.rst +++ b/docs/reference/boards.rst @@ -266,6 +266,7 @@ STMicroelectronics Board Name Family URL Note =================== ================================= ========= ================================================================= ====== stm32c071nucleo STM32C071 Nucleo stm32c0 https://www.st.com/en/evaluation-tools/nucleo-c071rb.html +stm32c542nucleo STM32C542 Nucleo stm32c5 https://www.st.com/en/evaluation-tools/nucleo-c542rc.html stm32f070rbnucleo STM32 F070 Nucleo stm32f0 https://www.st.com/en/evaluation-tools/nucleo-f070rb.html stm32f072disco STM32 F072 Discovery stm32f0 https://www.st.com/en/evaluation-tools/32f072bdiscovery.html stm32f072eval STM32 F072 Eval stm32f0 https://www.st.com/en/evaluation-tools/stm32072b-eval.html diff --git a/docs/reference/dependencies.rst b/docs/reference/dependencies.rst index c5b755577..d281e912a 100644 --- a/docs/reference/dependencies.rst +++ b/docs/reference/dependencies.rst @@ -59,6 +59,7 @@ hw/mcu/st/cmsis_device_l5 https://github.com/STMicroelectronics/ 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/stm32c5xx-dfp https://github.com/STMicroelectronics/stm32c5xx-dfp.git 6d0940882511d9430f83af9bd3da6bcb77f79239 stm32c5 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 stm32h5 stm32h7rs stm32n6 hw/mcu/st/stm32c0xx_hal_driver https://github.com/STMicroelectronics/stm32c0xx_hal_driver.git c283b143bef6bdaacf64240ee6f15eb61dad6125 stm32c0 @@ -82,13 +83,14 @@ hw/mcu/st/stm32u0xx_hal_driver https://github.com/STMicroelectronics/ 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/st/stm32c5xx-drivers https://github.com/STMicroelectronics/stm32c5xx-drivers.git 79b901285a7efeaf87c4c25db81d24cb5d8c9465 stm32c5 hw/mcu/ti https://github.com/hathach/ti_driver.git 083944907e7d08fcb1f614b47598ce45935b8da1 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 ch32v30x lib/CMSIS_5 https://github.com/ARM-software/CMSIS_5.git 2b7495b8535bdcb306dac29b9ded4cfb679d7e5c kinetis_k kinetis_kl lpc54 rw61x mm32 msp432e4 nrf samd2x_l2x lpc11 lpc13 lpc15 lpc17 lpc18 lpc40 lpc43 stm32c0 stm32f0 stm32f1 stm32f2 stm32f3 stm32f4 stm32f7 stm32g0 stm32g4 stm32h5 stm32h7 stm32h7rs stm32l0 stm32l1 stm32l4 stm32l5 stm32u0 stm32u5 stm32wb stm32wba sam3x samd11 samd21 samd51 samd5x_e5x same5x same7x samg tm4c -lib/CMSIS_6 https://github.com/ARM-software/CMSIS_6.git 6f0a58d01aa9bd2feba212097f9afe7acd991d52 imxrt kinetis_k32l ra stm32n6 lpc51 lpc55 mcx +lib/CMSIS_6 https://github.com/ARM-software/CMSIS_6.git 6f0a58d01aa9bd2feba212097f9afe7acd991d52 imxrt kinetis_k32l ra stm32n6 lpc51 lpc55 mcx stm32c5 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 diff --git a/examples/device/cdc_msc_throughput/CMakePresets.json b/examples/device/cdc_msc_throughput/CMakePresets.json new file mode 100644 index 000000000..5cd8971e9 --- /dev/null +++ b/examples/device/cdc_msc_throughput/CMakePresets.json @@ -0,0 +1,6 @@ +{ + "version": 6, + "include": [ + "../../../hw/bsp/BoardPresets.json" + ] +} diff --git a/examples/device/printer_to_cdc/CMakePresets.json b/examples/device/printer_to_cdc/CMakePresets.json new file mode 100644 index 000000000..5cd8971e9 --- /dev/null +++ b/examples/device/printer_to_cdc/CMakePresets.json @@ -0,0 +1,6 @@ +{ + "version": 6, + "include": [ + "../../../hw/bsp/BoardPresets.json" + ] +} diff --git a/examples/dual/dynamic_switch/only.txt b/examples/dual/dynamic_switch/only.txt index 70be49b28..e1038f9d4 100644 --- a/examples/dual/dynamic_switch/only.txt +++ b/examples/dual/dynamic_switch/only.txt @@ -2,6 +2,7 @@ family:espressif mcu:LPC43XX mcu:MIMXRT1XXX mcu:STM32C0 +mcu:STM32C5 mcu:STM32G0 mcu:STM32H5 mcu:STM32F2 diff --git a/examples/host/bare_api/only.txt b/examples/host/bare_api/only.txt index 1ddfc2b5c..a2ff93be5 100644 --- a/examples/host/bare_api/only.txt +++ b/examples/host/bare_api/only.txt @@ -20,6 +20,7 @@ mcu:RP2040 mcu:RW61X mcu:RX65X mcu:STM32C0 +mcu:STM32C5 mcu:STM32F4 mcu:STM32F7 mcu:STM32G0 diff --git a/examples/host/cdc_msc_hid/only.txt b/examples/host/cdc_msc_hid/only.txt index 1ddfc2b5c..a2ff93be5 100644 --- a/examples/host/cdc_msc_hid/only.txt +++ b/examples/host/cdc_msc_hid/only.txt @@ -20,6 +20,7 @@ mcu:RP2040 mcu:RW61X mcu:RX65X mcu:STM32C0 +mcu:STM32C5 mcu:STM32F4 mcu:STM32F7 mcu:STM32G0 diff --git a/examples/host/cdc_msc_hid_freertos/only.txt b/examples/host/cdc_msc_hid_freertos/only.txt index 753fa7cd3..4ab8a906e 100644 --- a/examples/host/cdc_msc_hid_freertos/only.txt +++ b/examples/host/cdc_msc_hid_freertos/only.txt @@ -16,6 +16,7 @@ mcu:MSP432E4 mcu:RW61X mcu:RX65X mcu:STM32C0 +mcu:STM32C5 mcu:STM32F4 mcu:STM32F7 mcu:STM32G0 diff --git a/examples/host/device_info/only.txt b/examples/host/device_info/only.txt index 742935dcf..4c2cb0f35 100644 --- a/examples/host/device_info/only.txt +++ b/examples/host/device_info/only.txt @@ -21,6 +21,7 @@ mcu:RP2040 mcu:RW61X mcu:RX65X mcu:STM32C0 +mcu:STM32C5 mcu:STM32F4 mcu:STM32F7 mcu:STM32G0 diff --git a/examples/host/midi_rx/only.txt b/examples/host/midi_rx/only.txt index c71aacd87..65ef8fac9 100644 --- a/examples/host/midi_rx/only.txt +++ b/examples/host/midi_rx/only.txt @@ -23,6 +23,7 @@ mcu:RP2040 mcu:RW61X mcu:RX65X mcu:STM32C0 +mcu:STM32C5 mcu:STM32F4 mcu:STM32F7 mcu:STM32G0 diff --git a/examples/host/msc_file_explorer/only.txt b/examples/host/msc_file_explorer/only.txt index 1ddfc2b5c..a2ff93be5 100644 --- a/examples/host/msc_file_explorer/only.txt +++ b/examples/host/msc_file_explorer/only.txt @@ -20,6 +20,7 @@ mcu:RP2040 mcu:RW61X mcu:RX65X mcu:STM32C0 +mcu:STM32C5 mcu:STM32F4 mcu:STM32F7 mcu:STM32G0 diff --git a/hw/bsp/BoardPresets.json b/hw/bsp/BoardPresets.json index 86609d075..1ff29f99d 100644 --- a/hw/bsp/BoardPresets.json +++ b/hw/bsp/BoardPresets.json @@ -626,6 +626,10 @@ "name": "stm32c071nucleo", "inherits": "default" }, + { + "name": "stm32c542nucleo", + "inherits": "default" + }, { "name": "stm32f070rbnucleo", "inherits": "default" @@ -1762,6 +1766,11 @@ "description": "Build preset for the stm32c071nucleo board", "configurePreset": "stm32c071nucleo" }, + { + "name": "stm32c542nucleo", + "description": "Build preset for the stm32c542nucleo board", + "configurePreset": "stm32c542nucleo" + }, { "name": "stm32f070rbnucleo", "description": "Build preset for the stm32f070rbnucleo board", @@ -4227,6 +4236,19 @@ } ] }, + { + "name": "stm32c542nucleo", + "steps": [ + { + "type": "configure", + "name": "stm32c542nucleo" + }, + { + "type": "build", + "name": "stm32c542nucleo" + } + ] + }, { "name": "stm32f070rbnucleo", "steps": [ diff --git a/hw/bsp/stm32c5/FreeRTOSConfig/FreeRTOSConfig.h b/hw/bsp/stm32c5/FreeRTOSConfig/FreeRTOSConfig.h new file mode 100644 index 000000000..732d9a5cf --- /dev/null +++ b/hw/bsp/stm32c5/FreeRTOSConfig/FreeRTOSConfig.h @@ -0,0 +1,165 @@ +/* + * 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 "stm32c5xx.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 ( 200 ) +#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 + +/* Define to trap errors during development. */ +// Halt CPU (breakpoint) when hitting error, only apply for Cortex M3, M4, M7 +#if defined(__ARM_ARCH_7M__) || defined (__ARM_ARCH_7EM__) || defined(__ARM_ARCH_8M_MAIN__) || defined(__ARM_ARCH_8_1M_MAIN__) || \ + defined(__ARM7M__) || defined (__ARM7EM__) || defined(__ARM8M_MAINLINE__) || defined(__ARM8EM_MAINLINE__) + #define configASSERT(_exp) \ + do {\ + if ( !(_exp) ) { \ + volatile uint32_t* ARM_CM_DHCSR = ((volatile uint32_t*) 0xE000EDF0UL); /* Cortex M CoreDebug->DHCSR */ \ + if ( (*ARM_CM_DHCSR) & 1UL ) { /* Only halt mcu if debugger is attached */ \ + taskDISABLE_INTERRUPTS(); \ + __asm("BKPT #0\n"); \ + }\ + }\ + } while(0) +#endif + +/* 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<instance)) +#endif + +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USB_DRD_FS_IRQHandler(void) { + tusb_int_handler(0, true); +} + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM +//--------------------------------------------------------------------+ +#ifdef UART_ID +static hal_uart_handle_t hUSART; +#endif + +void board_init(void) { + HAL_Init(); + board_clock_init(); + + // Enable peripheral clocks. + HAL_RCC_GPIOA_EnableClock(); + HAL_RCC_GPIOB_EnableClock(); + HAL_RCC_GPIOC_EnableClock(); + HAL_RCC_GPIOD_EnableClock(); + HAL_RCC_USB_EnableClock(); + +#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 from running before scheduler start + SysTick->CTRL &= ~1U; + + // If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher ) + NVIC_SetPriority(USB_DRD_FS_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY); +#endif + + // LED + { + hal_gpio_config_t gpio_config; + gpio_config.mode = HAL_GPIO_MODE_OUTPUT; + gpio_config.speed = HAL_GPIO_SPEED_FREQ_LOW; + gpio_config.pull = HAL_GPIO_PULL_NO; + gpio_config.output_type = HAL_GPIO_OUTPUT_PUSHPULL; + gpio_config.init_state = HAL_GPIO_PIN_RESET; + + HAL_GPIO_Init(LED_PORT, LED_PIN, &gpio_config); + } + + // Button + { + hal_gpio_config_t gpio_config; + gpio_config.mode = HAL_GPIO_MODE_INPUT; + gpio_config.speed = HAL_GPIO_SPEED_FREQ_LOW; + gpio_config.pull = BUTTON_STATE_ACTIVE ? HAL_GPIO_PULL_DOWN : HAL_GPIO_PULL_UP; + HAL_GPIO_Init(BUTTON_PORT, BUTTON_PIN, &gpio_config); + } + +#ifdef UART_ID + UARTn_CLK_ENABLE(); + // UART + { + hal_gpio_config_t gpio_config; + gpio_config.mode = HAL_GPIO_MODE_ALTERNATE; + gpio_config.output_type = HAL_GPIO_OUTPUT_PUSHPULL; + gpio_config.pull = HAL_GPIO_PULL_NO; + gpio_config.speed = HAL_GPIO_SPEED_FREQ_LOW; + gpio_config.alternate = UART_GPIO_AF; + HAL_GPIO_Init(UART_GPIO_PORT, UART_TX_PIN | UART_RX_PIN, &gpio_config); + } + + hal_uart_config_t uart_config; + HAL_UART_Init(&hUSART, UARTn); + uart_config.baud_rate = 115200; + uart_config.clock_prescaler = HAL_UART_PRESCALER_DIV1; + uart_config.word_length = HAL_UART_WORD_LENGTH_8_BIT; + uart_config.stop_bits = HAL_UART_STOP_BIT_1; + uart_config.parity = HAL_UART_PARITY_NONE; + uart_config.direction = HAL_UART_DIRECTION_TX_RX; + uart_config.hw_flow_ctl = HAL_UART_HW_CONTROL_NONE; + uart_config.oversampling = HAL_UART_OVERSAMPLING_16; + uart_config.one_bit_sampling = HAL_UART_ONE_BIT_SAMPLE_DISABLE; + + HAL_UART_SetConfig(&hUSART, &uart_config); + + /* Fifo configuration */ + HAL_UART_SetTxFifoThreshold(&hUSART, HAL_UART_FIFO_THRESHOLD_1_8); + HAL_UART_SetRxFifoThreshold(&hUSART, HAL_UART_FIFO_THRESHOLD_1_8); + HAL_UART_EnableFifoMode(&hUSART); + + LL_USART_Enable(UART_GET_INSTANCE(&hUSART)); +#endif +} + +//--------------------------------------------------------------------+ +// Board porting API +//--------------------------------------------------------------------+ + +void board_led_write(bool state) { + hal_gpio_pin_state_t pin_state = state ? HAL_GPIO_PIN_SET : HAL_GPIO_PIN_RESET; + HAL_GPIO_WritePin(LED_PORT, LED_PIN, pin_state); +} + +uint32_t board_button_read(void) { + return BUTTON_STATE_ACTIVE == HAL_GPIO_ReadPin(BUTTON_PORT, BUTTON_PIN); +} + +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) { +#ifdef UART_ID + int count = 0; + while (count < len) { + if (LL_USART_IsActiveFlag_RXNE_RXFNE(UART_GET_INSTANCE(&hUSART))) { + buf[count] = (uint8_t) UART_GET_INSTANCE(&hUSART)->RDR; + count++; + } else { + break; + } + } + return count; +#else + (void) buf; (void) len; + return -1; +#endif +} + +int board_uart_write(void const *buf, int len) { +#ifdef UART_ID + const uint8_t *p = (const uint8_t *) buf; + int count = 0; + while (count < len) { + if (LL_USART_IsActiveFlag_TXE_TXFNF(UART_GET_INSTANCE(&hUSART))) { + UART_GET_INSTANCE(&hUSART)->TDR = p[count]; + count++; + } else { + break; + } + } + return count; +#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++; + HAL_IncTick(); +} + +uint32_t tusb_time_millis_api(void) { + return system_ticks; +} +#endif + +void HardFault_Handler(void) { + __asm("BKPT #0\n"); +} + +#ifndef __ICCARM__ +// Implement _start() since we use linker flag '-nostartfiles'. +extern int main(void); +TU_ATTR_UNUSED void _start(void) { + // called by startup code + main(); + while (1) {} +} +#endif + +// Required by __libc_init_array in startup code if we are compiling using +// -nostdlib/-nostartfiles. +void _init(void) { + +} diff --git a/hw/bsp/stm32c5/family.cmake b/hw/bsp/stm32c5/family.cmake new file mode 100644 index 000000000..5b63b1ce4 --- /dev/null +++ b/hw/bsp/stm32c5/family.cmake @@ -0,0 +1,111 @@ +include_guard() + +set(ST_FAMILY c5) +set(ST_PREFIX stm32${ST_FAMILY}xx) + +set(ST_DRIVER ${TOP}/hw/mcu/st/stm32${ST_FAMILY}xx-drivers) +set(ST_CMSIS ${TOP}/hw/mcu/st/stm32${ST_FAMILY}xx-dfp) +set(CMSIS_6 ${TOP}/lib/CMSIS_6) + +# 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 STM32C5 CACHE INTERNAL "") +set(OPENOCD_OPTION "-f interface/stlink.cfg -f target/stm32c5x.cfg") + +#------------------------------------ +# Startup & Linker script +#------------------------------------ +set(STARTUP_FILE ${ST_CMSIS}/Source/startup_${MCU_VARIANT}.c) +set(LD_FILE_Clang ${LD_FILE_GNU}) + +#------------------------------------ +# BOARD_TARGET +#------------------------------------ +function(family_add_board BOARD_TARGET) + add_library(${BOARD_TARGET} STATIC + ${ST_CMSIS}/Source/Templates/system_${ST_PREFIX}.c + ${ST_DRIVER}/hal/${ST_PREFIX}_hal.c + ${ST_DRIVER}/hal/${ST_PREFIX}_hal_cortex.c + ${ST_DRIVER}/hal/${ST_PREFIX}_hal_flash_itf.c + ${ST_DRIVER}/hal/${ST_PREFIX}_hal_pwr.c + ${ST_DRIVER}/hal/${ST_PREFIX}_hal_rcc.c + ${ST_DRIVER}/hal/${ST_PREFIX}_hal_gpio.c + ${ST_DRIVER}/hal/${ST_PREFIX}_hal_uart.c + ${ST_DRIVER}/hal/${ST_PREFIX}_hal_dma.c + ) + target_include_directories(${BOARD_TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ${CMSIS_6}/CMSIS/Core/Include + ${ST_CMSIS}/Include + ${ST_DRIVER}/hal + ${ST_DRIVER}/ll + ) + target_compile_definitions(${BOARD_TARGET} PUBLIC + ) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_compile_options(${BOARD_TARGET} PUBLIC -Wno-redundant-decls) + endif () + + if(CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_compile_definitions(${BOARD_TARGET} PUBLIC + __STACK_LIMIT=__StackLimit + __INITIAL_SP=__StackTop + ) + endif () + + update_board(${BOARD_TARGET}) +endfunction() + +#------------------------------------ +# Functions +#------------------------------------ +function(family_configure_example TARGET RTOS) + family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_STM32C5) + + target_sources(${TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c + ${TOP}/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c + ${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c + ${STARTUP_FILE} + ) + target_include_directories(${TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} + ) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -nostartfiles + --specs=nosys.specs --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_Clang}" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + + # Flashing + family_add_bin_hex(${TARGET}) + family_flash_jlink(${TARGET}) + family_flash_stlink(${TARGET}) + #family_flash_openocd(${TARGET}) +endfunction() diff --git a/hw/bsp/stm32c5/family.mk b/hw/bsp/stm32c5/family.mk new file mode 100644 index 000000000..165ad4ad5 --- /dev/null +++ b/hw/bsp/stm32c5/family.mk @@ -0,0 +1,52 @@ +ST_FAMILY = c5 +ST_CMSIS = hw/mcu/st/stm32$(ST_FAMILY)xx-dfp +ST_DRIVER = hw/mcu/st/stm32$(ST_FAMILY)xx-drivers + +include $(TOP)/$(BOARD_PATH)/board.mk +CPU_CORE ?= cortex-m33 + +# -------------- +# Compiler Flags +# -------------- +CFLAGS += \ + -DCFG_TUSB_MCU=OPT_MCU_STM32C5 \ + +# GCC Flags +CFLAGS += \ + -flto \ + +# suppress warnings caused by vendor mcu driver +CFLAGS += -Wno-error=cast-align -Wno-error=unused-parameter -Wno-error=redundant-decls + +LDFLAGS += \ + -nostdlib -nostartfiles \ + --specs=nosys.specs --specs=nano.specs + +# ----------------- +# Sources & Include +# ----------------- + +SRC_C += \ + src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ + src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c \ + src/portable/st/stm32_fsdev/fsdev_common.c \ + $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ + $(ST_CMSIS)/Source/startup_$(MCU_VARIANT).c \ + $(ST_DRIVER)/hal/stm32$(ST_FAMILY)xx_hal.c \ + $(ST_DRIVER)/hal/stm32$(ST_FAMILY)xx_hal_cortex.c \ + $(ST_DRIVER)/hal/stm32$(ST_FAMILY)xx_hal_flash_itf.c \ + $(ST_DRIVER)/hal/stm32$(ST_FAMILY)xx_hal_pwr.c \ + $(ST_DRIVER)/hal/stm32$(ST_FAMILY)xx_hal_rcc.c \ + $(ST_DRIVER)/hal/stm32$(ST_FAMILY)xx_hal_gpio.c \ + $(ST_DRIVER)/hal/stm32$(ST_FAMILY)xx_hal_uart.c \ + $(ST_DRIVER)/hal/stm32$(ST_FAMILY)xx_hal_dma.c + +INC += \ + $(TOP)/$(BOARD_PATH) \ + $(TOP)/lib/CMSIS_6/CMSIS/Core/Include \ + $(TOP)/$(ST_CMSIS)/Include \ + $(TOP)/$(ST_DRIVER)/hal \ + $(TOP)/$(ST_DRIVER)/ll + +# flash target using on-board stlink +flash: flash-stlink diff --git a/hw/bsp/stm32c5/stm32c5xx_hal_conf.h b/hw/bsp/stm32c5/stm32c5xx_hal_conf.h new file mode 100644 index 000000000..0833fa3dd --- /dev/null +++ b/hw/bsp/stm32c5/stm32c5xx_hal_conf.h @@ -0,0 +1,684 @@ +/** + ****************************************************************************** + * @file stm32c5xx_hal_conf.h + * @brief HAL configuration file. + ****************************************************************************** + * @attention + * + * Copyright (c) 2026 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the mx_stm32c5xx_hal_drivers_license.md file + * in the same directory as the generated code. + * If no mx_stm32c5xx_hal_drivers_license.md file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef STM32C5XX_HAL_CONF_H +#define STM32C5XX_HAL_CONF_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ + +/** @defgroup HAL_Conf_How_To_Use HAL Conf How to Use + * @{ + - The STM32 HAL configuration file, stm32tnxx_hal_conf.h, is designed to customize the behaviour of the HAL modules. + - The users can utilize the provided file as-is, where all HAL modules are enabled with their default settings. + - Alternatively, users have the flexibility to customize the file based on their application's requirements. + - For example, they can enable only the necessary HAL modules or modify the predefined settings to achieve + the desired functionality. + */ + +/** + * @} + */ + +/** @defgroup HAL_Conf_Exported_Constants HAL Conf Constants + * @{ + */ + +/** @defgroup HAL_System_Configuration HAL System Configuration + * @{ + */ + +/* ########################### System Configuration ############################# */ +/** + * @brief This is the HAL system configuration section + */ +#define USE_HAL_TICK_INT_PRIORITY 15U /*!< tick interrupt priority */ +#define USE_HAL_FLASH_PREFETCH 1U /*!< Enable FLASH prefetch */ +/** + * @} + */ + +/** @defgroup HAL_MUTEX_Usage_Activation HAL MUTEX Usage Activation + * @{ + */ +/* ########################## HAL MUTEX usage activation ####################### */ +/** + * @brief Used by the HAL PPP Acquire/Release APIs when the define USE_HAL_MUTEX is set to 1 + */ +#define USE_HAL_MUTEX 0U +/** + * @} + */ + +/** @defgroup HAL_API_Parameters_Check HAL API Parameters Check + * @{ + */ +/* ########################## HAL API parameters check ##################### */ +/** + * @brief Run time parameter check activation + */ +#define USE_HAL_CHECK_PARAM 0U +#define USE_HAL_SECURE_CHECK_PARAM 0U +/** + * @} + */ + +/** @defgroup HAL_State_Transition HAL State Transition + * @{ + */ +/* ########################## State transition ################################ */ +/** + * @brief Enable protection of state transition in thread safe + */ +#define USE_HAL_CHECK_PROCESS_STATE 0U +/** + * @} + */ + +/* ########################## Peripheral configuration ######################### */ + +/** @defgroup HAL_ADC_Config HAL ADC Configuration + * @{ + */ +/* ########################## HAL_ADC Config #################################### */ +#define USE_HAL_ADC_MODULE 0U +#define USE_HAL_ADC_CLK_ENABLE_MODEL HAL_CLK_ENABLE_NO +#define USE_HAL_ADC_REGISTER_CALLBACKS 0U +#define USE_HAL_ADC_USER_DATA 0U +#define USE_HAL_ADC_GET_LAST_ERRORS 0U +#define USE_HAL_ADC_DMA 0U +/** + * @} + */ + +/** @defgroup HAL_AES_Config HAL AES Configuration + * @{ + */ +/* ########################## HAL_AES Config #################################### */ +#define USE_HAL_AES_MODULE 0U +#define USE_HAL_AES_CLK_ENABLE_MODEL HAL_CLK_ENABLE_NO +#define USE_HAL_AES_REGISTER_CALLBACKS 0U +#define USE_HAL_AES_USER_DATA 0U +#define USE_HAL_AES_GET_LAST_ERRORS 0U +#define USE_HAL_AES_DMA 0U +#define USE_HAL_AES_ECB_CBC_ALGO 0U +#define USE_HAL_AES_CTR_ALGO 0U +#define USE_HAL_AES_GCM_GMAC_ALGO 0U +#define USE_HAL_AES_CCM_ALGO 0U +#define USE_HAL_AES_SUSPEND_RESUME 0U +/** + * @} + */ + +/** @defgroup HAL_CCB_Config HAL CCB Configuration + * @{ + */ +/* ########################## HAL_CCB Config #################################### */ +#define USE_HAL_CCB_MODULE 0U +#define USE_HAL_CCB_CLK_ENABLE_MODEL HAL_CLK_ENABLE_NO +#define USE_HAL_CCB_USER_DATA 0U +#define USE_HAL_CCB_GET_LAST_ERRORS 0U +/** + * @} + */ + +/** @defgroup HAL_COMP_Config HAL COMP Configuration + * @{ + */ +/* ########################## HAL_COMP Config ################################### */ +#define USE_HAL_COMP_MODULE 0U +#define USE_HAL_COMP_CLK_ENABLE_MODEL HAL_CLK_ENABLE_NO +#define USE_HAL_COMP_REGISTER_CALLBACKS 0U +#define USE_HAL_COMP_USER_DATA 0U +/* Use comparator with EXTI (needed to generate system wake-up event and CPU event) */ +#define USE_HAL_COMP_EXTI 0U +/* Use comparators window mode feature */ +#define USE_HAL_COMP_WINDOW_MODE 0U +/** + * @} + */ + +/** @defgroup HAL_CORDIC_Config HAL CORDIC Configuration + * @{ + */ +/* ########################## HAL_CORDIC Config ################################# */ +#define USE_HAL_CORDIC_MODULE 0U +#define USE_HAL_CORDIC_CLK_ENABLE_MODEL HAL_CLK_ENABLE_NO +#define USE_HAL_CORDIC_REGISTER_CALLBACKS 0U +#define USE_HAL_CORDIC_USER_DATA 0U +#define USE_HAL_CORDIC_GET_LAST_ERRORS 0U +#define USE_HAL_CORDIC_DMA 0U +/** + * @} + */ + +/** @defgroup HAL_CORTEX_Config HAL CORTEX Configuration + * @{ + */ +/* ########################## HAL_CORTEX Config ################################# */ +#define USE_HAL_CORTEX_MODULE 1U +/** + * @} + */ + +/** @defgroup HAL_CRC_Config HAL CRC Configuration + * @{ + */ +/* ########################## HAL_CRC Config #################################### */ +#define USE_HAL_CRC_MODULE 0U +#define USE_HAL_CRC_CLK_ENABLE_MODEL HAL_CLK_ENABLE_NO +#define USE_HAL_CRC_USER_DATA 0U +/** + * @} + */ + +/** @defgroup HAL_CRS_Config HAL CRS Configuration + * @{ + */ +/* ########################## HAL_CRS Config #################################### */ +#define USE_HAL_CRS_MODULE 0U +#define USE_HAL_CRS_CLK_ENABLE_MODEL HAL_CLK_ENABLE_NO +#define USE_HAL_CRS_REGISTER_CALLBACKS 0U +#define USE_HAL_CRS_USER_DATA 0U +#define USE_HAL_CRS_GET_LAST_ERRORS 0U +/** + * @} + */ + +/** @defgroup HAL_DAC_Config HAL DAC Configuration + * @{ + */ +/* ########################## HAL_DAC Config #################################### */ +#define USE_HAL_DAC_MODULE 0U +#define USE_HAL_DAC_CLK_ENABLE_MODEL HAL_CLK_ENABLE_NO +#define USE_HAL_DAC_REGISTER_CALLBACKS 0U +#define USE_HAL_DAC_USER_DATA 0U +#define USE_HAL_DAC_GET_LAST_ERRORS 0U +#define USE_HAL_DAC_DMA 0U +#define USE_HAL_DAC_DUAL_CHANNEL 0U +/** + * @} + */ + +/** @defgroup HAL_DBGMCU_Config HAL DBGMCU Configuration + * @{ + */ +/* ########################## HAL_DBGMCU Config ################################# */ +#define USE_HAL_DBGMCU_MODULE 0U +/** + * @} + */ + +/** @defgroup HAL_DMA_Config HAL DMA Configuration + * @{ + */ +/* ########################## HAL_DMA Config #################################### */ +#define USE_HAL_DMA_MODULE 1U +#define USE_HAL_DMA_CLK_ENABLE_MODEL HAL_CLK_ENABLE_NO +#define USE_HAL_DMA_USER_DATA 0U +#define USE_HAL_DMA_GET_LAST_ERRORS 0U +#define USE_HAL_DMA_LINKEDLIST 0U +/** + * @} + */ + +/** @defgroup HAL_ETH_Config HAL ETH Configuration + * @{ + */ +/* ########################## HAL_ETH Config #################################### */ +#define USE_HAL_ETH_MODULE 0U +#define USE_HAL_ETH_REGISTER_CALLBACKS 0U +#define USE_HAL_ETH_CLK_ENABLE_MODEL HAL_CLK_ENABLE_NO +#define USE_HAL_ETH_USER_DATA 0U +#define USE_HAL_ETH_GET_LAST_ERRORS 0U +#define USE_HAL_ETH_ATOMIC_CHANNEL_LOCK 0U +#define USE_HAL_ETH_MAX_TX_CH_NB 1U +#define USE_HAL_ETH_MAX_RX_CH_NB 1U +/** + * @} + */ + +/** @defgroup HAL_EXTI_Config HAL EXTI Configuration + * @{ + */ +/* ########################## HAL_EXTI Config ################################### */ +#define USE_HAL_EXTI_MODULE 0U +#define USE_HAL_EXTI_REGISTER_CALLBACKS 0U +#define USE_HAL_EXTI_USER_DATA 0U +/** + * @} + */ + +/** @defgroup HAL_FDCAN_Config HAL FDCAN Configuration + * @{ + */ +/* ########################## HAL_FDCAN Config ################################## */ +#define USE_HAL_FDCAN_MODULE 0U +#define USE_HAL_FDCAN_CLK_ENABLE_MODEL HAL_CLK_ENABLE_NO +#define USE_HAL_FDCAN_REGISTER_CALLBACKS 0U +#define USE_HAL_FDCAN_USER_DATA 0U +#define USE_HAL_FDCAN_GET_LAST_ERRORS 0U +/** + * @} + */ + +/** @defgroup HAL_FLASH_Config HAL FLASH Configuration + * @{ + */ +/* ########################## HAL_FLASH Config ################################## */ +#define USE_HAL_FLASH_MODULE 1U +#define USE_HAL_FLASH_CLK_ENABLE_MODEL HAL_CLK_ENABLE_NO +#define USE_HAL_FLASH_REGISTER_CALLBACKS 0U +#define USE_HAL_FLASH_USER_DATA 0U +#define USE_HAL_FLASH_GET_LAST_ERRORS 0U +/* Use the FLASH program by address feature */ +#define USE_HAL_FLASH_PROGRAM_BY_ADDR 0U +/* Use the FLASH erase by address feature */ +#define USE_HAL_FLASH_ERASE_BY_ADDR 0U +/* Use the FLASH erase by PAGE feature */ +#define USE_HAL_FLASH_ERASE_PAGE 0U +/* Use the FLASH bank erase feature */ +#define USE_HAL_FLASH_ERASE_BANK 0U +/* Use the FLASH mass erase feature */ +#define USE_HAL_FLASH_MASS_ERASE 0U +/* Use ECC errors handling APIs */ +#define USE_HAL_FLASH_ECC 0U +/* Use FLASH HAL API for EDATA */ +#define USE_HAL_FLASH_OB_EDATA 0U +/** + * @} + */ + +/** @defgroup HAL_GPIO_Config HAL GPIO Configuration + * @{ + */ +/* ########################## HAL_GPIO Config ################################### */ +#define USE_HAL_GPIO_MODULE 1U +#define USE_HAL_GPIO_CLK_ENABLE_MODEL HAL_CLK_ENABLE_NO +/** + * @} + */ + +/** @defgroup HAL_HASH_Config HAL HASH Configuration + * @{ + */ +/* ########################## HAL_HASH Config ################################### */ +#define USE_HAL_HASH_MODULE 0U +#define USE_HAL_HASH_CLK_ENABLE_MODEL HAL_CLK_ENABLE_NO +#define USE_HAL_HASH_REGISTER_CALLBACKS 0U +#define USE_HAL_HASH_USER_DATA 0U +#define USE_HAL_HASH_GET_LAST_ERRORS 0U +#define USE_HAL_HASH_DMA 0U +/** + * @} + */ + +/** @defgroup HAL_HCD_Config HAL HCD Configuration + * @{ + */ +/* ########################## HAL_HCD Config #################################### */ +#define USE_HAL_HCD_MODULE 0U +#define USE_HAL_HCD_REGISTER_CALLBACKS 0U +#define USE_HAL_HCD_USER_DATA 0U +#define USE_HAL_HCD_GET_LAST_ERRORS 0U +#define USE_HAL_HCD_USB_DOUBLE_BUFFER 0U +#define USE_HAL_HCD_USB_EP_TYPE_ISOC 0U +#define USE_HAL_HCD_MAX_CHANNEL_NB 16U +/** + * @} + */ + +/** @defgroup HAL_I2C_Config HAL I2C Configuration + * @{ + */ +/* ########################## HAL_I2C Config #################################### */ +#define USE_HAL_I2C_MODULE 0U +#define USE_HAL_I2C_CLK_ENABLE_MODEL HAL_CLK_ENABLE_NO +#define USE_HAL_I2C_REGISTER_CALLBACKS 0U +#define USE_HAL_I2C_USER_DATA 0U +#define USE_HAL_I2C_GET_LAST_ERRORS 0U +#define USE_HAL_I2C_DMA 0U +/** + * @} + */ + +/** @defgroup HAL_I3C_Config HAL I3C Configuration + * @{ + */ +/* ########################## HAL_I3C Config #################################### */ +#define USE_HAL_I3C_MODULE 0U +#define USE_HAL_I3C_CLK_ENABLE_MODEL HAL_CLK_ENABLE_NO +#define USE_HAL_I3C_REGISTER_CALLBACKS 0U +#define USE_HAL_I3C_USER_DATA 0U +#define USE_HAL_I3C_GET_LAST_ERRORS 0U +#define USE_HAL_I3C_DMA 0U +/** + * @} + */ + +/** @defgroup HAL_I2S_Config HAL I2S Configuration + * @{ + */ +/* ########################## HAL_I2S Config #################################### */ +#define USE_HAL_I2S_MODULE 0U +#define USE_HAL_I2S_CLK_ENABLE_MODEL HAL_CLK_ENABLE_NO +#define USE_HAL_I2S_REGISTER_CALLBACKS 0U +#define USE_HAL_I2S_USER_DATA 0U +#define USE_HAL_I2S_GET_LAST_ERRORS 0U +#define USE_HAL_I2S_OVR_UDR_ERRORS 0U +#define USE_HAL_I2S_DMA 0U +/** + * @} + */ + +/** @defgroup HAL_ICACHE_Config HAL ICACHE Configuration + * @{ + */ +/* ########################## HAL_ICACHE Config ################################# */ +#define USE_HAL_ICACHE_MODULE 1U +#define USE_HAL_ICACHE_REGISTER_CALLBACKS 0U +#define USE_HAL_ICACHE_USER_DATA 0U +#define USE_HAL_ICACHE_GET_LAST_ERRORS 0U +/** + * @} + */ + +/** @defgroup HAL_IWDG_Config HAL IWDG Configuration + * @{ + */ +/* ########################## HAL_IWDG Config ################################### */ +#define USE_HAL_IWDG_MODULE 0U +#define USE_HAL_IWDG_REGISTER_CALLBACKS 0U +#define USE_HAL_IWDG_USER_DATA 0U +/* IWDG time unit configuration */ +#define USE_HAL_IWDG_TIME_UNIT HAL_IWDG_TIME_UNIT_MS +/* IWDG hardware start configuration + warning: In case of starting IWDG in Hardware mode, make sure that + USE_HAL_IWDG_HARDWARE_START is aligned with OB activated set for IWDG */ +#define USE_HAL_IWDG_HARDWARE_START 0U +/* User can choose the value of the LSI frequency with the USE_HAL_IWDG_LSI_FREQ define: + - 0U : Dynamic LSI to be computed and set by the user. + - LSI_VALUE : LSI value of 32KHz. + - (LSI_VALUE / 128U): LSI value of 250Hz */ +#define USE_HAL_IWDG_LSI_FREQ LSI_VALUE +/** + * @} + */ + +/** @defgroup HAL_LPTIM_Config HAL LPTIM Configuration + * @{ + */ +/* ########################## HAL_LPTIM Config ################################## */ +#define USE_HAL_LPTIM_MODULE 0U +#define USE_HAL_LPTIM_CLK_ENABLE_MODEL HAL_CLK_ENABLE_NO +#define USE_HAL_LPTIM_REGISTER_CALLBACKS 0U +#define USE_HAL_LPTIM_USER_DATA 0U +#define USE_HAL_LPTIM_GET_LAST_ERRORS 0U +#define USE_HAL_LPTIM_DMA 0U +/** + * @} + */ + +/** @defgroup HAL_OPAMP_Config HAL OPAMP Configuration + * @{ + */ +/* ########################## HAL_OPAMP Config ################################## */ +#define USE_HAL_OPAMP_MODULE 0U +#define USE_HAL_OPAMP_CLK_ENABLE_MODEL HAL_CLK_ENABLE_NO +#define USE_HAL_OPAMP_USER_DATA 0U +/** + * @} + */ + +/** @defgroup HAL_PCD_Config HAL PCD Configuration + * @{ + */ +/* ########################## HAL_PCD Config #################################### */ +#define USE_HAL_PCD_MODULE 1U +#define USE_HAL_PCD_REGISTER_CALLBACKS 0U +#define USE_HAL_PCD_USER_DATA 0U +#define USE_HAL_PCD_GET_LAST_ERRORS 0U +#define USE_HAL_PCD_USB_DOUBLE_BUFFER 0U +#define USE_HAL_PCD_USB_LPM 0U +#define USE_HAL_PCD_USB_BCD 0U +#define USE_HAL_PCD_USB_EP_TYPE_ISOC 0U +#define USE_HAL_PCD_MAX_ENDPOINT_NB 8U +/** + * @} + */ + +/** @defgroup HAL_PKA_Config HAL PKA Configuration + * @{ + */ +/* ########################## HAL_PKA Config #################################### */ +#define USE_HAL_PKA_MODULE 0U +#define USE_HAL_PKA_CLK_ENABLE_MODEL HAL_CLK_ENABLE_NO +#define USE_HAL_PKA_REGISTER_CALLBACKS 0U +#define USE_HAL_PKA_USER_DATA 0U +#define USE_HAL_PKA_GET_LAST_ERRORS 0U +/** + * @} + */ + +/** @defgroup HAL_PWR_Config HAL PWR Configuration + * @{ + */ +/* ########################## HAL_PWR Config #################################### */ +#define USE_HAL_PWR_MODULE 1U +/** + * @} + */ + +/** @defgroup HAL_RAMCFG_Config HAL RAMCFG Configuration + * @{ + */ +/* ########################## HAL_RAMCFG Config ################################# */ +#define USE_HAL_RAMCFG_MODULE 0U +/** + * @} + */ + +/** @defgroup HAL_RCC_Config HAL RCC Configuration + * @{ + */ +/* ########################## HAL_RCC Config #################################### */ +#define USE_HAL_RCC_MODULE 1U +/* Use RCC HAL API for Reset function */ +#define USE_HAL_RCC_RESET_PERIPH_CLOCK_MANAGEMENT 0U +#define USE_HAL_RCC_RESET_RTC_DOMAIN 0U +/** + * @} + */ + +/** @defgroup HAL_RNG_Config HAL RNG Configuration + * @{ + */ +/* ########################## HAL_RNG Config #################################### */ +#define USE_HAL_RNG_MODULE 0U +#define USE_HAL_RNG_CLK_ENABLE_MODEL HAL_CLK_ENABLE_NO +#define USE_HAL_RNG_REGISTER_CALLBACKS 0U +#define USE_HAL_RNG_USER_DATA 0U +#define USE_HAL_RNG_GET_LAST_ERRORS 0U +/** + * @} + */ + +/** @defgroup HAL_RTC_Config HAL RTC Configuration + * @{ + */ +/* ########################## HAL_RTC Config #################################### */ +#define USE_HAL_RTC_MODULE 0U +/** + * @} + */ + +/** @defgroup HAL_SBS_Config HAL SBS Configuration + * @{ + */ +/* ########################## HAL_SBS Config #################################### */ +#define USE_HAL_SBS_MODULE 0U +/** + * @} + */ + +/** @defgroup HAL_SMARTCARD_Config HAL SMARTCARD Configuration + * @{ + */ +/* ########################## HAL_SMARTCARD Config ############################## */ +#define USE_HAL_SMARTCARD_MODULE 0U +#define USE_HAL_SMARTCARD_CLK_ENABLE_MODEL HAL_CLK_ENABLE_NO +#define USE_HAL_SMARTCARD_REGISTER_CALLBACKS 0U +#define USE_HAL_SMARTCARD_USER_DATA 0U +#define USE_HAL_SMARTCARD_GET_LAST_ERRORS 0U +#define USE_HAL_SMARTCARD_DMA 0U +/* #################### SMARTCARD FIFO configuration ######################## */ +#define USE_HAL_SMARTCARD_FIFO 0U +/** + * @} + */ + +/** @defgroup HAL_SMBUS_Config HAL SMBUS Configuration + * @{ + */ +/* ########################## HAL_SMBUS Config ################################## */ +#define USE_HAL_SMBUS_MODULE 0U +#define USE_HAL_SMBUS_CLK_ENABLE_MODEL HAL_CLK_ENABLE_NO +#define USE_HAL_SMBUS_REGISTER_CALLBACKS 0U +#define USE_HAL_SMBUS_USER_DATA 0U +#define USE_HAL_SMBUS_GET_LAST_ERRORS 0U +/** + * @} + */ + +/** @defgroup HAL_SPI_Config HAL SPI Configuration + * @{ + */ +/* ########################## HAL_SPI Config #################################### */ +#define USE_HAL_SPI_MODULE 0U +#define USE_HAL_SPI_CLK_ENABLE_MODEL HAL_CLK_ENABLE_NO +#define USE_HAL_SPI_REGISTER_CALLBACKS 0U +#define USE_HAL_SPI_USER_DATA 0U +#define USE_HAL_SPI_GET_LAST_ERRORS 0U +#define USE_HAL_SPI_DMA 0U +/* 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_HAL_SPI_CRC 0U +/** + * @} + */ + +/** @defgroup HAL_TAMP_Config HAL TAMP Configuration + * @{ + */ +/* ########################## HAL_TAMP Config ################################### */ +#define USE_HAL_TAMP_MODULE 0U +/** + * @} + */ + +/** @defgroup HAL_TIM_Config HAL TIM Configuration + * @{ + */ +/* ########################## HAL_TIM Config #################################### */ +#define USE_HAL_TIM_MODULE 0U +#define USE_HAL_TIM_CLK_ENABLE_MODEL HAL_CLK_ENABLE_NO +#define USE_HAL_TIM_REGISTER_CALLBACKS 0U +#define USE_HAL_TIM_USER_DATA 0U +#define USE_HAL_TIM_GET_LAST_ERRORS 0U +#define USE_HAL_TIM_DMA 0U +/** + * @} + */ + +/** @defgroup HAL_UART_Config HAL UART Configuration + * @{ + */ +/* ########################## HAL_UART Config ################################### */ +#define USE_HAL_UART_MODULE 1U +#define USE_HAL_UART_CLK_ENABLE_MODEL HAL_CLK_ENABLE_NO +#define USE_HAL_UART_REGISTER_CALLBACKS 0U +#define USE_HAL_UART_USER_DATA 0U +#define USE_HAL_UART_GET_LAST_ERRORS 0U +#define USE_HAL_UART_DMA 0U +/** + * @} + */ + +/** @defgroup HAL_USART_Config HAL USART Configuration + * @{ + */ +/* ########################## HAL_USART Config ################################## */ +#define USE_HAL_USART_MODULE 0U +#define USE_HAL_USART_CLK_ENABLE_MODEL HAL_CLK_ENABLE_NO +#define USE_HAL_USART_REGISTER_CALLBACKS 0U +#define USE_HAL_USART_USER_DATA 0U +#define USE_HAL_USART_GET_LAST_ERRORS 0U +#define USE_HAL_USART_DMA 0U +#define USE_HAL_USART_FIFO 0U +/** + * @} + */ + +/** @defgroup HAL_WWDG_Config HAL WWDG Configuration + * @{ + */ +/* ########################## HAL_WWDG Config ################################### */ +#define USE_HAL_WWDG_MODULE 0U +#define USE_HAL_WWDG_CLK_ENABLE_MODEL HAL_CLK_ENABLE_NO +#define USE_HAL_WWDG_REGISTER_CALLBACKS 0U +#define USE_HAL_WWDG_USER_DATA 0U +/* WWDG time unit configuration */ +#define USE_HAL_WWDG_TIME_UNIT HAL_WWDG_TIME_UNIT_MS +/* WWDG hardware start configuration + warning: In case of starting WWDG in Hardware mode, make sure that + USE_HAL_WWDG_HARDWARE_START is aligned with OB activated set for WWDG */ +#define USE_HAL_WWDG_HARDWARE_START 0U +/** + * @} + */ + +/** @defgroup HAL_XSPI_Config HAL XSPI Configuration + * @{ + */ +/* ########################## HAL_XSPI Config ################################### */ +#define USE_HAL_XSPI_MODULE 0U +#define USE_HAL_XSPI_CLK_ENABLE_MODEL HAL_CLK_ENABLE_NO +#define USE_HAL_XSPI_REGISTER_CALLBACKS 0U +#define USE_HAL_XSPI_USER_DATA 0U +#define USE_HAL_XSPI_GET_LAST_ERRORS 0U +#define USE_HAL_XSPI_DMA 0U +#define USE_HAL_XSPI_HYPERBUS 0U +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* STM32C5XX_HAL_CONF_H */ diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index c85ade4d0..cd9b3dc27 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -206,6 +206,12 @@ #define TUP_USBIP_FSDEV_DRD #define CFG_TUSB_FSDEV_PMA_SIZE 2048u +#elif TU_CHECK_MCU(OPT_MCU_STM32C5) + #define TUP_USBIP_FSDEV + #define TUP_USBIP_FSDEV_STM32 + #define TUP_USBIP_FSDEV_DRD + #define CFG_TUSB_FSDEV_PMA_SIZE 2048u + #elif TU_CHECK_MCU(OPT_MCU_STM32F0) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 41da3ddd0..4dfd04fb4 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -41,6 +41,7 @@ * F302xB/C, F303xB/C, F373 512 byte buffer; no internal D+ pull-up * F302x6/8, F302xD/E2, F303xD/E 1024 byte buffer; no internal D+ pull-up * C0 2048 byte buffer; 32-bit bus; host mode + * C5 2048 byte buffer; 32-bit bus; host mode * G0 2048 byte buffer; 32-bit bus; host mode * G4 1024 byte buffer * H5 2048 byte buffer; 32-bit bus; host mode diff --git a/src/portable/st/stm32_fsdev/fsdev_stm32.h b/src/portable/st/stm32_fsdev/fsdev_stm32.h index 070aa00ec..74cc9d0a4 100644 --- a/src/portable/st/stm32_fsdev/fsdev_stm32.h +++ b/src/portable/st/stm32_fsdev/fsdev_stm32.h @@ -36,6 +36,10 @@ #include "stm32c0xx.h" #define FSDEV_HAS_SBUF_ISO 1 +#elif CFG_TUSB_MCU == OPT_MCU_STM32C5 + #include "stm32c5xx.h" + #define FSDEV_HAS_SBUF_ISO 1 + #elif CFG_TUSB_MCU == OPT_MCU_STM32F0 #include "stm32f0xx.h" #define FSDEV_HAS_SBUF_ISO 0 @@ -177,7 +181,7 @@ static const IRQn_Type fsdev_irq[] = { USB_IRQn, #elif TU_CHECK_MCU(OPT_MCU_STM32L5, OPT_MCU_STM32U3) USB_FS_IRQn, - #elif TU_CHECK_MCU(OPT_MCU_STM32C0, OPT_MCU_STM32H5, OPT_MCU_STM32U0) + #elif TU_CHECK_MCU(OPT_MCU_STM32C0, OPT_MCU_STM32C5, OPT_MCU_STM32H5, OPT_MCU_STM32U0) USB_DRD_FS_IRQn, #elif CFG_TUSB_MCU == OPT_MCU_STM32G0 #ifdef STM32G0B0xx @@ -276,6 +280,8 @@ TU_ATTR_ALWAYS_INLINE static inline void fsdev_int_disable(uint8_t rhport) { #define FSDEV_STM32_CPU_MHZ 64U #elif CFG_TUSB_MCU == OPT_MCU_STM32C0 #define FSDEV_STM32_CPU_MHZ 48U +#elif CFG_TUSB_MCU == OPT_MCU_STM32C5 + #define FSDEV_STM32_CPU_MHZ 144U #endif #ifndef CFG_TUSB_FSDEV_BTABLE_FS_DELAY_COUNT diff --git a/src/tusb_option.h b/src/tusb_option.h index 154f8e2a4..83b6d3e51 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -98,6 +98,7 @@ #define OPT_MCU_STM32N6 319 ///< ST N6 #define OPT_MCU_STM32WBA 320 ///< ST WBA #define OPT_MCU_STM32U3 321 ///< ST U3 +#define OPT_MCU_STM32C5 322 ///< ST C5 // Sony #define OPT_MCU_CXD56 400 ///< SONY CXD56 diff --git a/tools/get_deps.py b/tools/get_deps.py index eb87abf6e..50497fc71 100755 --- a/tools/get_deps.py +++ b/tools/get_deps.py @@ -163,6 +163,9 @@ deps_optional = { 'hw/mcu/st/cmsis-device-wba': ['https://github.com/STMicroelectronics/cmsis-device-wba.git', '647d8522e5fd15049e9a1cc30ed19d85e5911eaf', 'stm32wba'], + 'hw/mcu/st/stm32c5xx-dfp': ['https://github.com/STMicroelectronics/stm32c5xx-dfp.git', + '6d0940882511d9430f83af9bd3da6bcb77f79239', + 'stm32c5'], 'hw/mcu/st/stm32-mfxstm32l152': ['https://github.com/STMicroelectronics/stm32-mfxstm32l152.git', '7f4389efee9c6a655b55e5df3fceef5586b35f9b', 'stm32h7'], @@ -232,6 +235,9 @@ deps_optional = { 'hw/mcu/st/stm32wbaxx_hal_driver': ['https://github.com/STMicroelectronics/stm32wbaxx_hal_driver.git', '9442fbb71f855ff2e64fbf662b7726beba511a24', 'stm32wba'], + 'hw/mcu/st/stm32c5xx-drivers': ['https://github.com/STMicroelectronics/stm32c5xx-drivers.git', + '79b901285a7efeaf87c4c25db81d24cb5d8c9465', + 'stm32c5'], 'hw/mcu/ti': ['https://github.com/hathach/ti_driver.git', '083944907e7d08fcb1f614b47598ce45935b8da1', 'msp430 msp432e4 tm4c'], @@ -284,7 +290,7 @@ deps_optional = { 'tm4c '], 'lib/CMSIS_6': ['https://github.com/ARM-software/CMSIS_6.git', '6f0a58d01aa9bd2feba212097f9afe7acd991d52', - 'imxrt kinetis_k32l ra stm32n6 lpc51 lpc55 mcx'], + 'imxrt kinetis_k32l ra stm32n6 lpc51 lpc55 mcx stm32c5'], 'lib/sct_neopixel': ['https://github.com/gsteiert/sct_neopixel.git', 'e73e04ca63495672d955f9268e003cffe168fcd8', 'lpc55'], -- cgit v1.3.1 From 1f662779c44dd913f2c26f9bddc4f37ee70f16dc Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Tue, 12 May 2026 19:57:09 +0200 Subject: dcd/dwc2: fix ISO IN endpoint become disabled after incomplete transfer Signed-off-by: HiFiPhile --- src/portable/synopsys/dwc2/dcd_dwc2.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/portable') diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index 30e24a9ad..1d0ef45d2 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -1136,8 +1136,9 @@ static void handle_incomplete_iso_in(uint8_t rhport) { } epin->diepctl = depctl.value; } else { - // too many retries, give up + // too many retries, give up, but keep endpoint activated edpt_disable(rhport, epnum | TUSB_DIR_IN_MASK, false); + epin->diepctl |= DIEPCTL_USBAEP; dcd_event_xfer_complete(rhport, epnum | TUSB_DIR_IN_MASK, 0, XFER_RESULT_FAILED, true); } } -- cgit v1.3.1 From c4cd6c85e94d94345bf356f4779d7b67fb73b14b Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Thu, 14 May 2026 19:33:47 +0200 Subject: dcd/musb: defer EP0 SETUP during DATA_IN/STATUS race Handle cases where a new SETUP arrives before the previous control transfer fully completes by buffering the SETUP and replaying it after status completion. Split EP0 DATA state into DATA_IN/DATA_OUT and finalize pending status-out completion before processing deferred SETUP. Signed-off-by: HiFiPhile --- src/portable/mentor/musb/dcd_musb.c | 102 ++++++++++++++++++++++++++-------- src/portable/mentor/musb/musb_max32.h | 2 +- src/portable/mentor/musb/musb_ti.h | 2 +- 3 files changed, 80 insertions(+), 26 deletions(-) (limited to 'src/portable') diff --git a/src/portable/mentor/musb/dcd_musb.c b/src/portable/mentor/musb/dcd_musb.c index 56429ac1f..e00585068 100644 --- a/src/portable/mentor/musb/dcd_musb.c +++ b/src/portable/mentor/musb/dcd_musb.c @@ -82,7 +82,8 @@ typedef struct { enum { PIPE0_STATE_IDLE = 0, // no active control transfer - PIPE0_STATE_DATA, // DATA stage (IN or OUT — direction implied by CSR/dir) + PIPE0_STATE_DATA_IN, // DATA IN stage + PIPE0_STATE_DATA_OUT, // DATA OUT stage PIPE0_STATE_STATUS_IN, // STATUS IN — device sends IN-ZLP; awaits send-ACK IRQ PIPE0_STATE_STATUS_OUT, // post-DATAEND, neither edpt0_xfer(STATUS OUT) nor confirmation IRQ has happened yet PIPE0_STATE_STATUS_OUT_PENDING, // one of {edpt0_xfer(STATUS OUT), confirmation IRQ} has happened; the other fires xfer_complete @@ -95,12 +96,41 @@ typedef struct { uint16_t remain_wlength; // bytes remaining in the control transfer's DATA stage uint8_t state; uint8_t pending_addr; // new USB address latched by dcd_set_address; applied when STATUS IN completes + tusb_control_request_t deferred_setup; + bool deferred_setup_valid; } pipe0; pipe_state_t pipe[MUSB_PIPE_COUNT]; } dcd_data_t; static dcd_data_t _dcd; +static void pipe0_start_setup(uint8_t rhport, musb_ep_csr_t* ep_csr, + tusb_control_request_t const* req, bool is_isr) { + _dcd.pipe0.remain_wlength = req->wLength; + + if (req->wLength == 0) { + _dcd.pipe0.state = PIPE0_STATE_STATUS_IN; + } else { + if (req->bmRequestType & TUSB_DIR_IN_MASK) { + _dcd.pipe0.state = PIPE0_STATE_DATA_IN; + ep_csr->csr0l = MUSB_CSRL0_RXRDYC; + } else { + _dcd.pipe0.state = PIPE0_STATE_DATA_OUT; + } + } + + dcd_event_setup_received(rhport, (const uint8_t *) req, is_isr); +} + +static void pipe0_process_deferred_setup(uint8_t rhport, musb_ep_csr_t* ep_csr, bool is_isr) { + if (!_dcd.pipe0.deferred_setup_valid) { + return; + } + + _dcd.pipe0.deferred_setup_valid = false; + pipe0_start_setup(rhport, ep_csr, &_dcd.pipe0.deferred_setup, is_isr); +} + // EP0 must not call this — it has its own scalars in dcd_data_t. TU_ATTR_ALWAYS_INLINE static inline pipe_state_t* pipe_get(uint8_t epnum, tusb_dir_t epdir) { size_t idx = epnum - 1u; @@ -323,7 +353,7 @@ static void process_epout(uint8_t rhport, musb_regs_t *musb_regs, uint8_t epnum, static bool edpt_n_xfer(uint8_t rhport, uint8_t ep_addr, void *buffer, uint16_t total_bytes, bool use_fifo, bool is_isr) { const uint8_t epnum = tu_edpt_number(ep_addr); - const unsigned dir_in = tu_edpt_dir(ep_addr); + const tusb_dir_t dir_in = tu_edpt_dir(ep_addr); pipe_state_t *pipe = pipe_get(epnum, dir_in); if (use_fifo) { @@ -361,7 +391,8 @@ static bool edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_ const unsigned dir_in = tu_edpt_dir(ep_addr); switch (_dcd.pipe0.state) { - case PIPE0_STATE_DATA: { + case PIPE0_STATE_DATA_IN: + case PIPE0_STATE_DATA_OUT: { _dcd.pipe0.xact_len = total_bytes; if (dir_in) { // DATA IN: load FIFO, set TXRDY. Add DATAEND on the last chunk @@ -396,6 +427,7 @@ static bool edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_ // Second event — IRQ already arrived, fire complete now. _dcd.pipe0.state = PIPE0_STATE_IDLE; dcd_event_xfer_complete(rhport, ep_addr, 0, XFER_RESULT_SUCCESS, is_isr); + pipe0_process_deferred_setup(rhport, ep_csr, is_isr); break; default: break; @@ -410,9 +442,14 @@ static void process_ep0(uint8_t rhport) { musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, 0); uint_fast8_t csrl = ep_csr->csr0l; + if (csrl & MUSB_CSRL0_DATAEND) { + return; + } + if (csrl & MUSB_CSRL0_STALLED) { ep_csr->csr0l = 0; _dcd.pipe0.state = PIPE0_STATE_IDLE; + _dcd.pipe0.deferred_setup_valid = false; return; } @@ -421,6 +458,7 @@ static void process_ep0(uint8_t rhport) { // do nothing, it is probably another setup packet, usbd will reset its state. ep_csr->csr0l = MUSB_CSRL0_SETENDC; _dcd.pipe0.state = PIPE0_STATE_IDLE; + _dcd.pipe0.deferred_setup_valid = false; if (!(csrl & MUSB_CSRL0_RXRDY)) { return; /* no SETUP waiting behind it */ } @@ -430,7 +468,7 @@ static void process_ep0(uint8_t rhport) { if (csrl & MUSB_CSRL0_RXRDY) { const uint16_t count0 = ep_csr->count0; switch (_dcd.pipe0.state) { - case PIPE0_STATE_IDLE: + case PIPE0_STATE_IDLE: { TU_ASSERT(sizeof(tusb_control_request_t) == count0, ); union { tusb_control_request_t req; @@ -438,22 +476,11 @@ static void process_ep0(uint8_t rhport) { } setup_packet; setup_packet.u32[0] = musb_regs->fifo[0]; setup_packet.u32[1] = musb_regs->fifo[0]; - - _dcd.pipe0.remain_wlength = setup_packet.req.wLength; - - if (setup_packet.req.wLength == 0) { - _dcd.pipe0.state = PIPE0_STATE_STATUS_IN; - } else { - _dcd.pipe0.state = PIPE0_STATE_DATA; - // If OUT (rx) direction, let edpt0_xfer() clear RXRDY when it's ready to receive data. - if (setup_packet.req.bmRequestType & TUSB_DIR_IN_MASK) { - ep_csr->csr0l = MUSB_CSRL0_RXRDYC; - } - } - dcd_event_setup_received(rhport, (const uint8_t *)&setup_packet.req, true); + pipe0_start_setup(rhport, ep_csr, &setup_packet.req, true); break; + } - case PIPE0_STATE_DATA: { + case PIPE0_STATE_DATA_OUT: { // EP0 OUT is single-packet (TU_ASSERT total_bytes <= EP0_SIZE in edpt0_xfer) // so the whole packet drains in one shot. if (count0) { @@ -463,31 +490,54 @@ static void process_ep0(uint8_t rhport) { if (_dcd.pipe0.remain_wlength == 0) { // last packet: change state and leave RXRDY for edpt0_xfer(STATUS IN) to ack _dcd.pipe0.state = PIPE0_STATE_STATUS_IN; - } else { - ep_csr->csr0l = MUSB_CSRL0_RXRDYC; } dcd_event_xfer_complete(rhport, TU_EP0_OUT, count0, XFER_RESULT_SUCCESS, true); break; } - default: break; + // New SETUP packet arrived while old control transfer is not finished yet. This could happen in following scenarios: + // - Status IN/OUT finished, IRQ and new setup packet IRQ arrive at the same time. + // - Data IN finished and status OUT is received, both IRQs and new setup packet IRQ arrive at the same time. + // could happen when CPU load is high, save the new setup packet for later processing after current status stage complete. + case PIPE0_STATE_STATUS_OUT: + case PIPE0_STATE_STATUS_OUT_PENDING: + case PIPE0_STATE_STATUS_IN: + case PIPE0_STATE_DATA_IN: { + TU_ASSERT(sizeof(tusb_control_request_t) == count0, ); + union { + tusb_control_request_t req; + uint32_t u32[2]; + } setup_packet; + setup_packet.u32[0] = musb_regs->fifo[0]; + setup_packet.u32[1] = musb_regs->fifo[0]; + + _dcd.pipe0.deferred_setup = setup_packet.req; + _dcd.pipe0.deferred_setup_valid = true; + goto process_status; + } } return; } +process_status: /* When CSRL0 is zero, it means that either * - completion of sending any length packet TxPktRdy clear * - or status stage is complete (ZLP) after DataEnd is set */ switch (_dcd.pipe0.state) { - case PIPE0_STATE_DATA: + case PIPE0_STATE_DATA_IN: // csrl == 0 in DATA state = TXRDY just cleared, i.e. a DATA IN packet was successfully sent. If the just-sent // packet was the last (DATAEND was set when ep0_remain_datalen hit zero), transition // to STATUS_OUT to await the host's STATUS-OUT ZLP confirmation IRQ. if (_dcd.pipe0.remain_wlength == 0) { _dcd.pipe0.state = PIPE0_STATE_STATUS_OUT; + // If a new SETUP was deferred then STATUS OUT IRQ is missed, manually transition to STATUS_OUT_PENDING to allow ep0_xfer(STATUS OUT) to fire complete immediately. + if (_dcd.pipe0.deferred_setup_valid) { + _dcd.pipe0.state = PIPE0_STATE_STATUS_OUT_PENDING; + } } dcd_event_xfer_complete(rhport, TU_EP0_IN, _dcd.pipe0.xact_len, XFER_RESULT_SUCCESS, true); + break; case PIPE0_STATE_STATUS_OUT: @@ -499,6 +549,7 @@ static void process_ep0(uint8_t rhport) { // Second event — edpt0_xfer(STATUS OUT) already called, fire complete now. _dcd.pipe0.state = PIPE0_STATE_IDLE; dcd_event_xfer_complete(rhport, TU_EP0_OUT, 0, XFER_RESULT_SUCCESS, true); + pipe0_process_deferred_setup(rhport, ep_csr, true); break; case PIPE0_STATE_STATUS_IN: @@ -508,6 +559,7 @@ static void process_ep0(uint8_t rhport) { } _dcd.pipe0.state = PIPE0_STATE_IDLE; dcd_event_xfer_complete(rhport, TU_EP0_IN, 0, XFER_RESULT_SUCCESS, true); + pipe0_process_deferred_setup(rhport, ep_csr, true); break; default: break; @@ -527,6 +579,7 @@ static void process_bus_reset(uint8_t rhport) { _dcd.pipe0.buf = NULL; _dcd.pipe0.xact_len = 0; _dcd.pipe0.remain_wlength = 0; + _dcd.pipe0.deferred_setup_valid = false; musb->intr_txen = 1; /* Enable only EP0 */ musb->intr_rxen = 0; @@ -646,7 +699,7 @@ void dcd_sof_enable(uint8_t rhport, bool en) bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) { const unsigned ep_addr = ep_desc->bEndpointAddress; const unsigned epn = tu_edpt_number(ep_addr); - const unsigned epdir = tu_edpt_dir(ep_addr); + const tusb_dir_t epdir = tu_edpt_dir(ep_addr); const unsigned mps = tu_edpt_packet_size(ep_desc); pipe_state_t *pipe = pipe_get(epn, epdir); @@ -689,7 +742,7 @@ bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const *ep_desc ) { const unsigned ep_addr = ep_desc->bEndpointAddress; const unsigned epn = tu_edpt_number(ep_addr); - const unsigned dir_in = tu_edpt_dir(ep_addr); + const tusb_dir_t dir_in = tu_edpt_dir(ep_addr); const unsigned mps = tu_edpt_packet_size(ep_desc); unsigned const ie = musb_dcd_get_int_enable(rhport); @@ -804,6 +857,7 @@ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { if (ep_addr == TU_EP0_OUT) { /* Ignore EP0 OUT */ _dcd.pipe0.state = PIPE0_STATE_IDLE; _dcd.pipe0.buf = NULL; + _dcd.pipe0.deferred_setup_valid = false; ep_csr->csr0l = MUSB_CSRL0_STALL; } } else { diff --git a/src/portable/mentor/musb/musb_max32.h b/src/portable/mentor/musb/musb_max32.h index 599de2ca1..134b47122 100644 --- a/src/portable/mentor/musb/musb_max32.h +++ b/src/portable/mentor/musb/musb_max32.h @@ -47,7 +47,7 @@ extern "C" { #define MUSB_CFG_SHARED_FIFO 1 // shared FIFO for TX and RX endpoints #define MUSB_CFG_DYNAMIC_FIFO 0 // dynamic EP FIFO sizing -const uintptr_t MUSB_BASES[] = { MXC_BASE_USBHS }; +static const uintptr_t MUSB_BASES[] = { MXC_BASE_USBHS }; #if CFG_TUD_ENABLED #define USBHS_M31_CLOCK_RECOVERY diff --git a/src/portable/mentor/musb/musb_ti.h b/src/portable/mentor/musb/musb_ti.h index 68e89d77d..deaea8017 100644 --- a/src/portable/mentor/musb/musb_ti.h +++ b/src/portable/mentor/musb/musb_ti.h @@ -49,7 +49,7 @@ #define MUSB_CFG_DYNAMIC_FIFO 1 #define MUSB_CFG_DYNAMIC_FIFO_SIZE 4096 -const uintptr_t MUSB_BASES[] = { USB0_BASE }; +static const uintptr_t MUSB_BASES[] = { USB0_BASE }; // Header supports both device and host modes. Only include what's necessary #if CFG_TUD_ENABLED -- cgit v1.3.1 From 72e09788e46a8ffaaae8009a316915838927af90 Mon Sep 17 00:00:00 2001 From: Boris Dolgov Date: Fri, 15 May 2026 21:28:21 +0200 Subject: rp2040: fix host SET_REPORT (and any OUT-data control xfer) sending DATA0 instead of DATA1 hcd_edpt_xfer() previously reset ep->next_pid to 1 only when the control endpoint direction changed between stages. That handled IN-data control transfers (e.g. GET_REPORT, GET_DESCRIPTOR) where SETUP is OUT and DATA is IN, but not OUT-data class requests like SET_REPORT, where SETUP and DATA are both OUT and the direction-change check is false. ep->next_pid was left at 0 from hcd_edpt_open(), so the DATA stage went on the wire as DATA0 when the device expected DATA1. Strict devices (observed: Elgato Stream Deck) treat this as a protocol violation and disconnect. Key off "endpoint 0" instead of "direction changed", restoring the previous behavior. Interrupt/bulk endpoints take the ep->interrupt_num > 0 branch above and never reach this code, so they are unaffected. --- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'src/portable') diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index 02a4e055e..064834efb 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -617,10 +617,16 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *b io_rw_32 *buf_reg = dpram_int_ep_buffer_ctrl(ep->interrupt_num); rp2usb_xfer_start(ep, ep_reg, buf_reg, buffer, NULL, buflen); } else { - // Control endpoint can change direction 0x00 <-> 0x80 when changing stages - if (ep_addr != ep->ep_addr) { + // Control transfer data and status stages always start with DATA1, regardless of + // whether the direction changed since the previous stage. SET_REPORT (and any other + // host-to-device class request with an OUT data stage) keeps the same direction + // across SETUP -> DATA, so we cannot key off "direction changed" -- we must reset + // next_pid every time hcd_edpt_xfer is invoked on ep 0. Without this, the data stage + // of SET_REPORT goes out as DATA0 because ep->next_pid is still 0 from hcd_edpt_open(), + // which strict devices treat as a protocol violation and disconnect. + if (tu_edpt_number(ep_addr) == 0) { ep->ep_addr = ep_addr; - ep->next_pid = 1; // data and status stage start with DATA1 + ep->next_pid = 1; } // If EPX is busy with another transfer, mark as pending -- cgit v1.3.1 From 650e8a194fcfaa4b91203e9aedfecd614ea70105 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Wed, 20 May 2026 23:22:02 +0200 Subject: dwc2: handle EP0 status OUT in RXFLVL interrupt Signed-off-by: HiFiPhile --- src/portable/synopsys/dwc2/dcd_dwc2.c | 65 +++++++++++++---------------------- 1 file changed, 24 insertions(+), 41 deletions(-) (limited to 'src/portable') diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index 72beb1b80..bdab49f1b 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -62,7 +62,6 @@ static xfer_ctl_t xfer_status[DWC2_EP_MAX][2]; 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 - bool ep0_out_zlp_armed; // EP0 OUT ZLP transfer is armed and waiting for completion uint16_t dfifo_top; // top free location in DFIFO in words // Number of IN endpoints active @@ -70,6 +69,9 @@ typedef struct { // SOF enabling flag - required for SOF to not get disabled in ISR when SOF was enabled by bool sof_en; + + // EP0 status OUT flag + bool ep0_status_out; } dcd_data_t; static dcd_data_t _dcd_data; @@ -667,7 +669,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to if (epnum == 0) { _dcd_data.ep0_pending[dir] = total_bytes; if (dir == TUSB_DIR_OUT) { - _dcd_data.ep0_out_zlp_armed = (total_bytes == 0); + _dcd_data.ep0_status_out = (total_bytes == 0); } } @@ -748,11 +750,9 @@ static void handle_bus_reset(uint8_t rhport) { tu_memclr(xfer_status, sizeof(xfer_status)); - _dcd_data.ep0_pending[TUSB_DIR_OUT] = 0; - _dcd_data.ep0_pending[TUSB_DIR_IN] = 0; - _dcd_data.ep0_out_zlp_armed = false; _dcd_data.sof_en = false; _dcd_data.allocated_epin_count = 0; + _dcd_data.ep0_status_out = false; // 1. NAK for all OUT endpoints for (uint8_t n = 0; n < ep_count; n++) { @@ -907,6 +907,9 @@ static void handle_rxflvl_irq(uint8_t rhport) { // We can receive up to three setup packets in succession, but only the last one is valid. setup[0] = (*rx_fifo); setup[1] = (*rx_fifo); + + // Clear previous pending EP0 OUT if any + _dcd_data.ep0_status_out = false; break; } @@ -946,6 +949,12 @@ static void handle_rxflvl_irq(uint8_t rhport) { // Out packet done // After this entry is popped from the receive FIFO, dwc2 asserts a Transfer Completed interrupt on // the specified OUT endpoint which will be handled by handle_epout_irq() + + // EP0 status OUT is complete + if (epnum == 0 && _dcd_data.ep0_status_out) { + _dcd_data.ep0_status_out = false; + dcd_event_xfer_complete(rhport, epnum, 0, XFER_RESULT_SUCCESS, true); + } break; default: break; // nothing to do @@ -953,21 +962,7 @@ static void handle_rxflvl_irq(uint8_t rhport) { } static void handle_epout_slave(uint8_t rhport, uint8_t epnum, dwc2_doepint_t doepint_bm) { - xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); - const bool ep0_status_complete_before_setup = (epnum == 0) && doepint_bm.setup_phase_done && - doepint_bm.xfer_complete && - _dcd_data.ep0_out_zlp_armed && - (_dcd_data.ep0_pending[TUSB_DIR_OUT] == 0) && - (xfer->total_len == 0); - if (doepint_bm.setup_phase_done) { - if (ep0_status_complete_before_setup) { - _dcd_data.ep0_out_zlp_armed = false; - dcd_event_xfer_complete(rhport, epnum, 0, XFER_RESULT_SUCCESS, true); - } else if (epnum == 0) { - _dcd_data.ep0_out_zlp_armed = false; - } - // Cleanup previous pending EP0 IN transfer if any dwc2_dep_t* epin0 = &DWC2_REG(rhport)->epin[0]; if (edpt_is_enabled(epin0)) { @@ -983,13 +978,16 @@ static void handle_epout_slave(uint8_t rhport, uint8_t epnum, dwc2_doepint_t doe // Note: even though (xfer_complete + status_phase_rx) is for buffered DMA only, for STM32L47x (dwc2 v3.00a) they // can is set when GRXSTS_PKTSTS_SETUP_RX is popped therefore they can bet set before/together with setup_phase_done if (!doepint_bm.status_phase_rx && !doepint_bm.setup_packet_rx) { - if ((epnum == 0) && _dcd_data.ep0_pending[TUSB_DIR_OUT]) { - // EP0 can only handle one packet, Schedule another packet to be received. - edpt_schedule_packets(rhport, epnum, TUSB_DIR_OUT); - } else { - if (epnum == 0) { - _dcd_data.ep0_out_zlp_armed = false; + xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); + if (epnum == 0) { + if (_dcd_data.ep0_pending[TUSB_DIR_OUT]) { + // EP0 can only handle one packet, Schedule another packet to be received. + edpt_schedule_packets(rhport, epnum, TUSB_DIR_OUT); + } else if (xfer->total_len > 0) { + // EP0 status out is handled in handle_rxflvl_irq + dcd_event_xfer_complete(rhport, epnum, xfer->total_len, XFER_RESULT_SUCCESS, true); } + } else { dcd_event_xfer_complete(rhport, epnum, xfer->total_len, XFER_RESULT_SUCCESS, true); } } @@ -1028,21 +1026,8 @@ static void handle_epin_slave(uint8_t rhport, uint8_t epnum, dwc2_diepint_t diep #if CFG_TUD_DWC2_DMA_ENABLE static void handle_epout_dma(uint8_t rhport, uint8_t epnum, dwc2_doepint_t doepint_bm) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); - xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); - const bool ep0_status_complete_before_setup = (epnum == 0) && doepint_bm.setup_phase_done && - doepint_bm.xfer_complete && - _dcd_data.ep0_out_zlp_armed && - (_dcd_data.ep0_pending[TUSB_DIR_OUT] == 0) && - (xfer->total_len == 0); if (doepint_bm.setup_phase_done) { - if (ep0_status_complete_before_setup) { - _dcd_data.ep0_out_zlp_armed = false; - dcd_event_xfer_complete(rhport, epnum, 0, XFER_RESULT_SUCCESS, true); - } else if (epnum == 0) { - _dcd_data.ep0_out_zlp_armed = false; - } - // Cleanup previous pending EP0 IN transfer if any dwc2_dep_t* epin0 = &DWC2_REG(rhport)->epin[0]; if (edpt_is_enabled(epin0)) { @@ -1064,6 +1049,7 @@ static void handle_epout_dma(uint8_t rhport, uint8_t epnum, dwc2_doepint_t doepi edpt_schedule_packets(rhport, epnum, TUSB_DIR_OUT); } else { dwc2_dep_t* epout = &dwc2->epout[epnum]; + xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); // determine actual received bytes const dwc2_ep_tsize_t tsiz = {.value = epout->tsiz}; @@ -1076,9 +1062,6 @@ static void handle_epout_dma(uint8_t rhport, uint8_t epnum, dwc2_doepint_t doepi dma_setup_prepare(rhport); } - if (epnum == 0) { - _dcd_data.ep0_out_zlp_armed = false; - } dcd_dcache_invalidate(xfer->buffer, xfer->total_len); dcd_event_xfer_complete(rhport, epnum, xfer->total_len, XFER_RESULT_SUCCESS, true); } -- cgit v1.3.1 From d202477ebe0f8805bf88fcee4c0d5968d146dfbd Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 22 May 2026 18:02:23 +0200 Subject: dcd/ch32fs: reset EP regs on bus reset Signed-off-by: HiFiPhile --- src/portable/wch/dcd_ch32_usbfs.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) (limited to 'src/portable') diff --git a/src/portable/wch/dcd_ch32_usbfs.c b/src/portable/wch/dcd_ch32_usbfs.c index 39c1cfb4a..0727664c9 100644 --- a/src/portable/wch/dcd_ch32_usbfs.c +++ b/src/portable/wch/dcd_ch32_usbfs.c @@ -125,6 +125,16 @@ static void update_out(uint8_t rhport, uint8_t ep, size_t rx_len) { } } +static void reset_ep_ctrls(void) { + for (uint8_t ep = 1; ep < EP_MAX; ep++) { + EP_DMA(ep) = (uint32_t) &data.buffer[ep][0]; + EP_TX_LEN(ep) = 0; + EP_TX_CTRL(ep) = USBFS_EP_T_AUTO_TOG | USBFS_EP_T_RES_NYET; + EP_RX_CTRL(ep) = USBFS_EP_R_AUTO_TOG | USBFS_EP_R_RES_NYET; + } + EP_DMA(3) = (uint32_t) &data.ep3_buffer.out[0]; +} + /* public functions */ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { (void) rh_init; @@ -148,13 +158,7 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { USBOTG_FS->UEP5_6_MOD = 0xCC; USBOTG_FS->UEP7_MOD = 0x0C; - for (uint8_t ep = 1; ep < EP_MAX; ep++) { - EP_DMA(ep) = (uint32_t) &data.buffer[ep][0]; - EP_TX_LEN(ep) = 0; - EP_TX_CTRL(ep) = USBFS_EP_T_AUTO_TOG | USBFS_EP_T_RES_NAK; - EP_RX_CTRL(ep) = USBFS_EP_R_AUTO_TOG | USBFS_EP_R_RES_NAK; - } - EP_DMA(3) = (uint32_t) &data.ep3_buffer.out[0]; + reset_ep_ctrls(); dcd_connect(rhport); @@ -201,6 +205,8 @@ void dcd_int_handler(uint8_t rhport) { USBOTG_FS->DEV_ADDR = 0x00; EP_RX_CTRL(0) = USBFS_EP_R_RES_ACK; + reset_ep_ctrls(); + USBOTG_FS->INT_FG = USBFS_INT_FG_BUS_RST; } else if (status & USBFS_INT_FG_SUSPEND) { dcd_event_t event = {.rhport = rhport, .event_id = DCD_EVENT_SUSPEND}; -- cgit v1.3.1 From 66c5f6d45dc90f947261e2e4e62918c2ceb0ce11 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 22 May 2026 18:04:44 +0200 Subject: dcd/ch32fs: only enable EP0 ACK if no data stage, reduce race Signed-off-by: HiFiPhile --- src/portable/wch/dcd_ch32_usbfs.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src/portable') diff --git a/src/portable/wch/dcd_ch32_usbfs.c b/src/portable/wch/dcd_ch32_usbfs.c index 0727664c9..e4abbd824 100644 --- a/src/portable/wch/dcd_ch32_usbfs.c +++ b/src/portable/wch/dcd_ch32_usbfs.c @@ -186,9 +186,12 @@ void dcd_int_handler(uint8_t rhport) { case PID_SETUP: // setup clears stall EP_TX_CTRL(0) = USBFS_EP_T_RES_NAK; - EP_RX_CTRL(0) = USBFS_EP_R_RES_ACK; - data.ep0_tog = true; + + tusb_control_request_t const* setup = + (tusb_control_request_t const*) &data.buffer[0][TUSB_DIR_OUT][0]; + EP_RX_CTRL(0) = (setup->wLength == 0) ? USBFS_EP_R_RES_ACK : USBFS_EP_R_RES_NAK; + dcd_event_setup_received(rhport, &data.buffer[0][TUSB_DIR_OUT][0], true); break; } -- cgit v1.3.1 From 61a8f688c800626962cfed4022f4672b35ceb3ae Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 22 May 2026 18:13:42 +0200 Subject: dcd/ch32fs: fix ISO IN transfer OUT is still buggy Signed-off-by: HiFiPhile --- src/portable/wch/dcd_ch32_usbfs.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) (limited to 'src/portable') diff --git a/src/portable/wch/dcd_ch32_usbfs.c b/src/portable/wch/dcd_ch32_usbfs.c index e4abbd824..f6c573b47 100644 --- a/src/portable/wch/dcd_ch32_usbfs.c +++ b/src/portable/wch/dcd_ch32_usbfs.c @@ -119,8 +119,10 @@ static void update_out(uint8_t rhport, uint8_t ep, size_t rx_len) { if (ep == 0) { EP_RX_CTRL(0) = USBFS_EP_R_RES_ACK; } else { - EP_RX_CTRL(ep) = (EP_RX_CTRL(ep) & ~USBFS_EP_R_RES_MASK) | - (xfer->valid ? USBFS_EP_R_RES_ACK : USBFS_EP_R_RES_NAK); + uint8_t rx_res = data.isochronous[ep] + ? USBFS_EP_R_RES_NYET + : (xfer->valid ? USBFS_EP_R_RES_ACK : USBFS_EP_R_RES_NAK); + EP_RX_CTRL(ep) = (EP_RX_CTRL(ep) & ~USBFS_EP_R_RES_MASK) | rx_res; } } } @@ -272,18 +274,12 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const* desc_ep) { uint8_t dir = tu_edpt_dir(desc_ep->bEndpointAddress); TU_ASSERT(ep < EP_MAX); - data.isochronous[ep] = desc_ep->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS; data.xfer[ep][dir].max_size = tu_edpt_packet_size(desc_ep); if (ep != 0) { if (dir == TUSB_DIR_OUT) { - if (data.isochronous[ep]) { - EP_RX_CTRL(ep) = USBFS_EP_R_AUTO_TOG | USBFS_EP_R_RES_NYET; - } else { - EP_RX_CTRL(ep) = USBFS_EP_R_AUTO_TOG | USBFS_EP_R_RES_ACK; - } + EP_RX_CTRL(ep) = USBFS_EP_R_AUTO_TOG | USBFS_EP_T_RES_NAK; } else { - EP_TX_LEN(ep) = 0; EP_TX_CTRL(ep) = USBFS_EP_T_AUTO_TOG | USBFS_EP_T_RES_NAK; } } @@ -299,13 +295,18 @@ bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet (void) rhport; (void) ep_addr; (void)largest_packet_size; - return false; + uint8_t ep = tu_edpt_number(ep_addr); + uint8_t dir = tu_edpt_dir(ep_addr); + + data.isochronous[ep] = true; + data.xfer[ep][dir].max_size = largest_packet_size; + return true; } bool dcd_edpt_iso_activate(uint8_t rhport, const tusb_desc_endpoint_t *desc_ep) { (void)rhport; (void)desc_ep; - return false; + return true; } bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) { @@ -325,7 +326,8 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t t if (dir == TUSB_DIR_IN) { update_in(rhport, ep, true); } else { - EP_RX_CTRL(ep) = (EP_RX_CTRL(ep) & ~USBFS_EP_R_RES_MASK) | USBFS_EP_R_RES_ACK; + uint8_t rx_res = data.isochronous[ep] ? USBFS_EP_R_RES_NYET : USBFS_EP_R_RES_ACK; + EP_RX_CTRL(ep) = (EP_RX_CTRL(ep) & ~USBFS_EP_R_RES_MASK) | rx_res; } return true; } -- cgit v1.3.1 From 28d4ec5723428cbdb085ecdaa70e7fd2bf7f893d Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 22 May 2026 18:14:58 +0200 Subject: dcd/ch32fs: reset EP on clear stall Signed-off-by: HiFiPhile --- src/portable/wch/dcd_ch32_usbfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/portable') diff --git a/src/portable/wch/dcd_ch32_usbfs.c b/src/portable/wch/dcd_ch32_usbfs.c index f6c573b47..8f583510c 100644 --- a/src/portable/wch/dcd_ch32_usbfs.c +++ b/src/portable/wch/dcd_ch32_usbfs.c @@ -362,9 +362,9 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { } } else { if (dir == TUSB_DIR_OUT) { - EP_RX_CTRL(ep) = (EP_RX_CTRL(ep) & ~(USBFS_EP_R_RES_MASK | USBFS_EP_R_TOG)) | USBFS_EP_R_RES_ACK; + EP_RX_CTRL(ep) = USBFS_EP_R_AUTO_TOG | USBFS_EP_R_RES_NAK; } else { - EP_TX_CTRL(ep) = (EP_TX_CTRL(ep) & ~(USBFS_EP_T_RES_MASK | USBFS_EP_T_TOG)) | USBFS_EP_T_RES_NAK; + EP_TX_CTRL(ep) = USBFS_EP_T_AUTO_TOG | USBFS_EP_T_RES_NAK; } } } -- cgit v1.3.1 From e14b0e8514ace0043472d9cb0779152fccade1ee Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sat, 23 May 2026 13:02:53 +0200 Subject: dcd/ch32fs: set EP to NAK earlier to reduce spuroius transfer Signed-off-by: HiFiPhile --- src/portable/wch/dcd_ch32_usbfs.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) (limited to 'src/portable') diff --git a/src/portable/wch/dcd_ch32_usbfs.c b/src/portable/wch/dcd_ch32_usbfs.c index 8f583510c..3ba6eee87 100644 --- a/src/portable/wch/dcd_ch32_usbfs.c +++ b/src/portable/wch/dcd_ch32_usbfs.c @@ -66,6 +66,13 @@ static struct { static void update_in(uint8_t rhport, uint8_t ep, bool force) { struct usb_xfer* xfer = &data.xfer[ep][TUSB_DIR_IN]; if (xfer->valid) { + // Set EP to NAK to avoid spurious tramsfer + if (ep == 0) { + EP_TX_CTRL(0) = USBFS_EP_T_RES_NAK | (data.ep0_tog ? USBFS_EP_T_TOG : 0); + } else if (!data.isochronous[ep]) { + EP_TX_CTRL(ep) = (EP_TX_CTRL(ep) & ~(USBFS_EP_T_RES_MASK)) | USBFS_EP_T_RES_NAK; + } + if (force || xfer->len) { size_t len = TU_MIN(xfer->max_size, xfer->len); if (ep == 0) { @@ -101,6 +108,13 @@ static void update_in(uint8_t rhport, uint8_t ep, bool force) { static void update_out(uint8_t rhport, uint8_t ep, size_t rx_len) { struct usb_xfer* xfer = &data.xfer[ep][TUSB_DIR_OUT]; if (xfer->valid) { + // Set EP to NAK to avoid spurious tramsfer + if (ep == 0) { + EP_RX_CTRL(0) = USBFS_EP_R_RES_NAK; + } else if (!data.isochronous[ep]) { + EP_RX_CTRL(ep) = (EP_RX_CTRL(ep) & ~USBFS_EP_R_RES_MASK) | USBFS_EP_R_RES_NAK; + } + size_t len = TU_MIN(xfer->max_size, TU_MIN(xfer->len, rx_len)); if (ep == 3) { memcpy(xfer->buffer, data.ep3_buffer.out, len); @@ -116,9 +130,7 @@ static void update_out(uint8_t rhport, uint8_t ep, size_t rx_len) { dcd_event_xfer_complete(rhport, ep, xfer->processed_len, XFER_RESULT_SUCCESS, true); } - if (ep == 0) { - EP_RX_CTRL(0) = USBFS_EP_R_RES_ACK; - } else { + if (ep != 0) { uint8_t rx_res = data.isochronous[ep] ? USBFS_EP_R_RES_NYET : (xfer->valid ? USBFS_EP_R_RES_ACK : USBFS_EP_R_RES_NAK); @@ -173,10 +185,11 @@ void dcd_int_handler(uint8_t rhport) { if (status & USBFS_INT_FG_TRANSFER) { uint8_t ep = USBFS_INT_ST_MASK_UIS_ENDP(USBOTG_FS->INT_ST); uint8_t token = USBFS_INT_ST_MASK_UIS_TOKEN(USBOTG_FS->INT_ST); + uint16_t rx_len = USBOTG_FS->RX_LEN; + USBOTG_FS->INT_FG = USBFS_INT_FG_TRANSFER; switch (token) { case PID_OUT: { - uint16_t rx_len = USBOTG_FS->RX_LEN; update_out(rhport, ep, rx_len); break; } @@ -198,7 +211,6 @@ void dcd_int_handler(uint8_t rhport) { break; } - USBOTG_FS->INT_FG = USBFS_INT_FG_TRANSFER; } else if (status & USBFS_INT_FG_BUS_RST) { data.ep0_tog = true; data.xfer[0][TUSB_DIR_OUT].max_size = 64; -- cgit v1.3.1 From b66fc7e88400caf7748779c7dc0b9c90f90e626b Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sat, 23 May 2026 13:10:47 +0200 Subject: dcd/ch32x : code reformat Signed-off-by: HiFiPhile --- src/portable/wch/dcd_ch32_usbfs.c | 159 ++++++++++++++++--------------- src/portable/wch/dcd_ch32_usbhs.c | 191 +++++++++++++++++++------------------- 2 files changed, 173 insertions(+), 177 deletions(-) (limited to 'src/portable') diff --git a/src/portable/wch/dcd_ch32_usbfs.c b/src/portable/wch/dcd_ch32_usbfs.c index 3ba6eee87..37677276c 100644 --- a/src/portable/wch/dcd_ch32_usbfs.c +++ b/src/portable/wch/dcd_ch32_usbfs.c @@ -29,29 +29,29 @@ #if CFG_TUD_ENABLED && defined(TUP_USBIP_WCH_USBFS) && CFG_TUD_WCH_USBIP_USBFS -#include "device/dcd.h" -#include "ch32_usbfs_reg.h" + #include "device/dcd.h" + #include "ch32_usbfs_reg.h" -/* private defines */ -#define EP_MAX (8) + /* private defines */ + #define EP_MAX (8) -#define EP_DMA(ep) ((&USBOTG_FS->UEP0_DMA)[ep]) -#define EP_TX_LEN(ep) ((&USBOTG_FS->UEP0_TX_LEN)[2 * ep]) -#define EP_TX_CTRL(ep) ((&USBOTG_FS->UEP0_TX_CTRL)[4 * ep]) -#define EP_RX_CTRL(ep) ((&USBOTG_FS->UEP0_RX_CTRL)[4 * ep]) + #define EP_DMA(ep) ((&USBOTG_FS->UEP0_DMA)[ep]) + #define EP_TX_LEN(ep) ((&USBOTG_FS->UEP0_TX_LEN)[2 * ep]) + #define EP_TX_CTRL(ep) ((&USBOTG_FS->UEP0_TX_CTRL)[4 * ep]) + #define EP_RX_CTRL(ep) ((&USBOTG_FS->UEP0_RX_CTRL)[4 * ep]) /* private data */ struct usb_xfer { - bool valid; - uint8_t* buffer; - size_t len; - size_t processed_len; - size_t max_size; + bool valid; + uint8_t *buffer; + size_t len; + size_t processed_len; + size_t max_size; }; static struct { - bool ep0_tog; - bool isochronous[EP_MAX]; + bool ep0_tog; + bool isochronous[EP_MAX]; struct usb_xfer xfer[EP_MAX][2]; TU_ATTR_ALIGNED(4) uint8_t buffer[EP_MAX][2][64]; TU_ATTR_ALIGNED(4) struct { @@ -64,7 +64,7 @@ static struct { /* private helpers */ static void update_in(uint8_t rhport, uint8_t ep, bool force) { - struct usb_xfer* xfer = &data.xfer[ep][TUSB_DIR_IN]; + struct usb_xfer *xfer = &data.xfer[ep][TUSB_DIR_IN]; if (xfer->valid) { // Set EP to NAK to avoid spurious tramsfer if (ep == 0) { @@ -89,24 +89,22 @@ static void update_in(uint8_t rhport, uint8_t ep, bool force) { EP_TX_LEN(ep) = len; if (ep == 0) { EP_TX_CTRL(0) = USBFS_EP_T_RES_ACK | (data.ep0_tog ? USBFS_EP_T_TOG : 0); - data.ep0_tog = !data.ep0_tog; + data.ep0_tog = !data.ep0_tog; } else if (data.isochronous[ep]) { EP_TX_CTRL(ep) = (EP_TX_CTRL(ep) & ~(USBFS_EP_T_RES_MASK)) | USBFS_EP_T_RES_NYET; } else { EP_TX_CTRL(ep) = (EP_TX_CTRL(ep) & ~(USBFS_EP_T_RES_MASK)) | USBFS_EP_T_RES_ACK; } } else { - xfer->valid = false; + xfer->valid = false; EP_TX_CTRL(ep) = (EP_TX_CTRL(ep) & ~(USBFS_EP_T_RES_MASK)) | USBFS_EP_T_RES_NAK; - dcd_event_xfer_complete( - rhport, ep | TUSB_DIR_IN_MASK, xfer->processed_len, - XFER_RESULT_SUCCESS, true); + dcd_event_xfer_complete(rhport, ep | TUSB_DIR_IN_MASK, xfer->processed_len, XFER_RESULT_SUCCESS, true); } } } static void update_out(uint8_t rhport, uint8_t ep, size_t rx_len) { - struct usb_xfer* xfer = &data.xfer[ep][TUSB_DIR_OUT]; + struct usb_xfer *xfer = &data.xfer[ep][TUSB_DIR_OUT]; if (xfer->valid) { // Set EP to NAK to avoid spurious tramsfer if (ep == 0) { @@ -131,9 +129,8 @@ static void update_out(uint8_t rhport, uint8_t ep, size_t rx_len) { } if (ep != 0) { - uint8_t rx_res = data.isochronous[ep] - ? USBFS_EP_R_RES_NYET - : (xfer->valid ? USBFS_EP_R_RES_ACK : USBFS_EP_R_RES_NAK); + uint8_t rx_res = + data.isochronous[ep] ? USBFS_EP_R_RES_NYET : (xfer->valid ? USBFS_EP_R_RES_ACK : USBFS_EP_R_RES_NAK); EP_RX_CTRL(ep) = (EP_RX_CTRL(ep) & ~USBFS_EP_R_RES_MASK) | rx_res; } } @@ -141,28 +138,28 @@ static void update_out(uint8_t rhport, uint8_t ep, size_t rx_len) { static void reset_ep_ctrls(void) { for (uint8_t ep = 1; ep < EP_MAX; ep++) { - EP_DMA(ep) = (uint32_t) &data.buffer[ep][0]; - EP_TX_LEN(ep) = 0; + EP_DMA(ep) = (uint32_t)&data.buffer[ep][0]; + EP_TX_LEN(ep) = 0; EP_TX_CTRL(ep) = USBFS_EP_T_AUTO_TOG | USBFS_EP_T_RES_NYET; EP_RX_CTRL(ep) = USBFS_EP_R_AUTO_TOG | USBFS_EP_R_RES_NYET; } - EP_DMA(3) = (uint32_t) &data.ep3_buffer.out[0]; + EP_DMA(3) = (uint32_t)&data.ep3_buffer.out[0]; } /* public functions */ -bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { - (void) rh_init; +bool dcd_init(uint8_t rhport, const tusb_rhport_init_t *rh_init) { + (void)rh_init; // init registers USBOTG_FS->BASE_CTRL = USBFS_CTRL_SYS_CTRL | USBFS_CTRL_INT_BUSY | USBFS_CTRL_DMA_EN; USBOTG_FS->UDEV_CTRL = USBFS_UDEV_CTRL_PD_DIS | USBFS_UDEV_CTRL_PORT_EN; - USBOTG_FS->DEV_ADDR = 0x00; + USBOTG_FS->DEV_ADDR = 0x00; USBOTG_FS->INT_FG = 0xFF; USBOTG_FS->INT_EN = USBFS_INT_EN_BUS_RST | USBFS_INT_EN_TRANSFER | USBFS_INT_EN_SUSPEND; // setup endpoint 0 - EP_DMA(0) = (uint32_t) &data.buffer[0][0]; - EP_TX_LEN(0) = 0; + EP_DMA(0) = (uint32_t)&data.buffer[0][0]; + EP_TX_LEN(0) = 0; EP_TX_CTRL(0) = USBFS_EP_T_RES_NAK; EP_RX_CTRL(0) = USBFS_EP_R_RES_ACK; @@ -170,7 +167,7 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { USBOTG_FS->UEP4_1_MOD = 0xCC; USBOTG_FS->UEP2_3_MOD = 0xCC; USBOTG_FS->UEP5_6_MOD = 0xCC; - USBOTG_FS->UEP7_MOD = 0x0C; + USBOTG_FS->UEP7_MOD = 0x0C; reset_ep_ctrls(); @@ -180,12 +177,12 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { } void dcd_int_handler(uint8_t rhport) { - (void) rhport; + (void)rhport; uint8_t status = USBOTG_FS->INT_FG; if (status & USBFS_INT_FG_TRANSFER) { - uint8_t ep = USBFS_INT_ST_MASK_UIS_ENDP(USBOTG_FS->INT_ST); - uint8_t token = USBFS_INT_ST_MASK_UIS_TOKEN(USBOTG_FS->INT_ST); - uint16_t rx_len = USBOTG_FS->RX_LEN; + uint8_t ep = USBFS_INT_ST_MASK_UIS_ENDP(USBOTG_FS->INT_ST); + uint8_t token = USBFS_INT_ST_MASK_UIS_TOKEN(USBOTG_FS->INT_ST); + uint16_t rx_len = USBOTG_FS->RX_LEN; USBOTG_FS->INT_FG = USBFS_INT_FG_TRANSFER; switch (token) { @@ -201,26 +198,27 @@ void dcd_int_handler(uint8_t rhport) { case PID_SETUP: // setup clears stall EP_TX_CTRL(0) = USBFS_EP_T_RES_NAK; - data.ep0_tog = true; + data.ep0_tog = true; - tusb_control_request_t const* setup = - (tusb_control_request_t const*) &data.buffer[0][TUSB_DIR_OUT][0]; - EP_RX_CTRL(0) = (setup->wLength == 0) ? USBFS_EP_R_RES_ACK : USBFS_EP_R_RES_NAK; + const tusb_control_request_t *setup = (const tusb_control_request_t *)&data.buffer[0][TUSB_DIR_OUT][0]; + EP_RX_CTRL(0) = (setup->wLength == 0) ? USBFS_EP_R_RES_ACK : USBFS_EP_R_RES_NAK; dcd_event_setup_received(rhport, &data.buffer[0][TUSB_DIR_OUT][0], true); break; } } else if (status & USBFS_INT_FG_BUS_RST) { - data.ep0_tog = true; + data.ep0_tog = true; data.xfer[0][TUSB_DIR_OUT].max_size = 64; - data.xfer[0][TUSB_DIR_IN].max_size = 64; + data.xfer[0][TUSB_DIR_IN].max_size = 64; - //dcd_event_bus_reset(rhport, (USBOTG_FS->BASE_CTRL & USBFS_CTRL_LOW_SPEED) ? TUSB_SPEED_LOW : TUSB_SPEED_FULL, true); - dcd_event_bus_reset(rhport, (USBOTG_FS->UDEV_CTRL & USBFS_UDEV_CTRL_LOW_SPEED) ? TUSB_SPEED_LOW : TUSB_SPEED_FULL, true); + // dcd_event_bus_reset(rhport, (USBOTG_FS->BASE_CTRL & USBFS_CTRL_LOW_SPEED) ? TUSB_SPEED_LOW : TUSB_SPEED_FULL, + // true); + dcd_event_bus_reset(rhport, (USBOTG_FS->UDEV_CTRL & USBFS_UDEV_CTRL_LOW_SPEED) ? TUSB_SPEED_LOW : TUSB_SPEED_FULL, + true); USBOTG_FS->DEV_ADDR = 0x00; - EP_RX_CTRL(0) = USBFS_EP_R_RES_ACK; + EP_RX_CTRL(0) = USBFS_EP_R_RES_ACK; reset_ep_ctrls(); @@ -233,56 +231,55 @@ void dcd_int_handler(uint8_t rhport) { } void dcd_int_enable(uint8_t rhport) { - (void) rhport; + (void)rhport; NVIC_EnableIRQ(USBHD_IRQn); } void dcd_int_disable(uint8_t rhport) { - (void) rhport; + (void)rhport; NVIC_DisableIRQ(USBHD_IRQn); } void dcd_set_address(uint8_t rhport, uint8_t dev_addr) { - (void) dev_addr; + (void)dev_addr; dcd_edpt_xfer(rhport, 0x80, NULL, 0, false); // zlp status response } void dcd_remote_wakeup(uint8_t rhport) { - (void) rhport; + (void)rhport; // TODO optional } void dcd_connect(uint8_t rhport) { - (void) rhport; + (void)rhport; USBOTG_FS->BASE_CTRL |= USBFS_CTRL_DEV_PUEN; } void dcd_disconnect(uint8_t rhport) { - (void) rhport; + (void)rhport; USBOTG_FS->BASE_CTRL &= ~USBFS_CTRL_DEV_PUEN; } void dcd_sof_enable(uint8_t rhport, bool en) { - (void) rhport; - (void) en; + (void)rhport; + (void)en; // TODO implement later } -void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const* request) { - (void) rhport; +void dcd_edpt0_status_complete(uint8_t rhport, const tusb_control_request_t *request) { + (void)rhport; if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE && - request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && - request->bRequest == TUSB_REQ_SET_ADDRESS) { - USBOTG_FS->DEV_ADDR = (uint8_t) request->wValue; + request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && request->bRequest == TUSB_REQ_SET_ADDRESS) { + USBOTG_FS->DEV_ADDR = (uint8_t)request->wValue; } EP_TX_CTRL(0) = USBFS_EP_T_RES_NAK; EP_RX_CTRL(0) = USBFS_EP_R_RES_ACK; } -bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const* desc_ep) { - (void) rhport; - uint8_t ep = tu_edpt_number(desc_ep->bEndpointAddress); +bool dcd_edpt_open(uint8_t rhport, const tusb_desc_endpoint_t *desc_ep) { + (void)rhport; + uint8_t ep = tu_edpt_number(desc_ep->bEndpointAddress); uint8_t dir = tu_edpt_dir(desc_ep->bEndpointAddress); TU_ASSERT(ep < EP_MAX); @@ -299,18 +296,18 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const* desc_ep) { } void dcd_edpt_close_all(uint8_t rhport) { - (void) rhport; + (void)rhport; // TODO optional } bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { - (void) rhport; - (void) ep_addr; + (void)rhport; + (void)ep_addr; (void)largest_packet_size; - uint8_t ep = tu_edpt_number(ep_addr); + uint8_t ep = tu_edpt_number(ep_addr); uint8_t dir = tu_edpt_dir(ep_addr); - data.isochronous[ep] = true; + data.isochronous[ep] = true; data.xfer[ep][dir].max_size = largest_packet_size; return true; } @@ -321,17 +318,17 @@ bool dcd_edpt_iso_activate(uint8_t rhport, const tusb_desc_endpoint_t *desc_ep) return true; } -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) { - (void) is_isr; - (void) rhport; - uint8_t ep = tu_edpt_number(ep_addr); +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes, bool is_isr) { + (void)is_isr; + (void)rhport; + uint8_t ep = tu_edpt_number(ep_addr); uint8_t dir = tu_edpt_dir(ep_addr); - struct usb_xfer* xfer = &data.xfer[ep][dir]; + struct usb_xfer *xfer = &data.xfer[ep][dir]; dcd_int_disable(rhport); - xfer->valid = true; - xfer->buffer = buffer; - xfer->len = total_bytes; + xfer->valid = true; + xfer->buffer = buffer; + xfer->len = total_bytes; xfer->processed_len = 0; dcd_int_enable(rhport); @@ -345,14 +342,14 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t t } void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { - (void) rhport; - uint8_t ep = tu_edpt_number(ep_addr); + (void)rhport; + uint8_t ep = tu_edpt_number(ep_addr); uint8_t dir = tu_edpt_dir(ep_addr); if (ep == 0) { if (dir == TUSB_DIR_OUT) { EP_RX_CTRL(0) = USBFS_EP_R_RES_STALL; } else { - EP_TX_LEN(0) = 0; + EP_TX_LEN(0) = 0; EP_TX_CTRL(0) = USBFS_EP_T_RES_STALL; } } else { @@ -365,8 +362,8 @@ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { } void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { - (void) rhport; - uint8_t ep = tu_edpt_number(ep_addr); + (void)rhport; + uint8_t ep = tu_edpt_number(ep_addr); uint8_t dir = tu_edpt_dir(ep_addr); if (ep == 0) { if (dir == TUSB_DIR_OUT) { diff --git a/src/portable/wch/dcd_ch32_usbhs.c b/src/portable/wch/dcd_ch32_usbhs.c index 11734de37..01ff6eba3 100644 --- a/src/portable/wch/dcd_ch32_usbhs.c +++ b/src/portable/wch/dcd_ch32_usbhs.c @@ -37,12 +37,12 @@ #define EP_MAX 16 typedef struct { - uint8_t* buffer; + uint8_t *buffer; uint16_t total_len; uint16_t queued_len; uint16_t max_size; - bool is_last_packet; - bool is_iso; + bool is_last_packet; + bool is_iso; } xfer_ctl_t; typedef enum { @@ -50,16 +50,16 @@ typedef enum { EP_RESPONSE_NAK, } ep_response_list_t; -#define XFER_CTL_BASE(_ep, _dir) &xfer_status[_ep][_dir] + #define XFER_CTL_BASE(_ep, _dir) &xfer_status[_ep][_dir] static xfer_ctl_t xfer_status[EP_MAX][2]; -#define EP_TX_LEN(ep) *(volatile uint16_t *)((volatile uint16_t *)&(USBHSD->UEP0_TX_LEN) + (ep) * 2) -#define EP_TX_CTRL(ep) *(volatile uint8_t *)((volatile uint8_t *)&(USBHSD->UEP0_TX_CTRL) + (ep) * 4) -#define EP_RX_CTRL(ep) *(volatile uint8_t *)((volatile uint8_t *)&(USBHSD->UEP0_RX_CTRL) + (ep) * 4) -#define EP_RX_MAX_LEN(ep) *(volatile uint16_t *)((volatile uint16_t *)&(USBHSD->UEP0_MAX_LEN) + (ep) * 2) + #define EP_TX_LEN(ep) *(volatile uint16_t *)((volatile uint16_t *)&(USBHSD->UEP0_TX_LEN) + (ep) * 2) + #define EP_TX_CTRL(ep) *(volatile uint8_t *)((volatile uint8_t *)&(USBHSD->UEP0_TX_CTRL) + (ep) * 4) + #define EP_RX_CTRL(ep) *(volatile uint8_t *)((volatile uint8_t *)&(USBHSD->UEP0_RX_CTRL) + (ep) * 4) + #define EP_RX_MAX_LEN(ep) *(volatile uint16_t *)((volatile uint16_t *)&(USBHSD->UEP0_MAX_LEN) + (ep) * 2) -#define EP_TX_DMA_ADDR(ep) *(volatile uint32_t *)((volatile uint32_t *)&(USBHSD->UEP1_TX_DMA) + (ep - 1)) -#define EP_RX_DMA_ADDR(ep) *(volatile uint32_t *)((volatile uint32_t *)&(USBHSD->UEP1_RX_DMA) + (ep - 1)) + #define EP_TX_DMA_ADDR(ep) *(volatile uint32_t *)((volatile uint32_t *)&(USBHSD->UEP1_TX_DMA) + (ep - 1)) + #define EP_RX_DMA_ADDR(ep) *(volatile uint32_t *)((volatile uint32_t *)&(USBHSD->UEP1_RX_DMA) + (ep - 1)) /* Endpoint Buffer */ TU_ATTR_ALIGNED(4) static uint8_t ep0_buffer[CFG_TUD_ENDPOINT0_SIZE]; @@ -96,15 +96,15 @@ static void ep_set_response_and_toggle(uint8_t ep_num, tusb_dir_t ep_dir, ep_res } } -static void xfer_data_packet(uint8_t ep_num, tusb_dir_t ep_dir, xfer_ctl_t* xfer) { +static void xfer_data_packet(uint8_t ep_num, tusb_dir_t ep_dir, xfer_ctl_t *xfer) { if (ep_dir == TUSB_DIR_IN) { - uint16_t remaining = xfer->total_len - xfer->queued_len; + uint16_t remaining = xfer->total_len - xfer->queued_len; uint16_t next_tx_size = TU_MIN(remaining, xfer->max_size); if (ep_num == 0) { memcpy(ep0_buffer, &xfer->buffer[xfer->queued_len], next_tx_size); } else { - EP_TX_DMA_ADDR(ep_num) = (uint32_t) &xfer->buffer[xfer->queued_len]; + EP_TX_DMA_ADDR(ep_num) = (uint32_t)&xfer->buffer[xfer->queued_len]; } EP_TX_LEN(ep_num) = next_tx_size; @@ -117,7 +117,7 @@ static void xfer_data_packet(uint8_t ep_num, tusb_dir_t ep_dir, xfer_ctl_t* xfer USBHSD->ENDP_CONFIG |= (USBHS_EP0_T_EN << ep_num); } } else { /* TUSB_DIR_OUT */ - uint16_t left_to_receive = xfer->total_len - xfer->queued_len; + uint16_t left_to_receive = xfer->total_len - xfer->queued_len; uint16_t max_possible_rx_size = TU_MIN(xfer->max_size, left_to_receive); if (max_possible_rx_size == left_to_receive) { @@ -125,16 +125,16 @@ static void xfer_data_packet(uint8_t ep_num, tusb_dir_t ep_dir, xfer_ctl_t* xfer } if (ep_num > 0) { - EP_RX_DMA_ADDR(ep_num) = (uint32_t) &xfer->buffer[xfer->queued_len]; - EP_RX_MAX_LEN(ep_num) = max_possible_rx_size; + EP_RX_DMA_ADDR(ep_num) = (uint32_t)&xfer->buffer[xfer->queued_len]; + EP_RX_MAX_LEN(ep_num) = max_possible_rx_size; } } ep_set_response_and_toggle(ep_num, ep_dir, USBHS_EP_R_RES_ACK); } -bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { - (void) rhport; - (void) rh_init; +bool dcd_init(uint8_t rhport, const tusb_rhport_init_t *rh_init) { + (void)rhport; + (void)rh_init; memset(&xfer_status, 0, sizeof(xfer_status)); @@ -143,32 +143,32 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { USBHSD->CONTROL = 0; -#if TUD_OPT_HIGH_SPEED + #if TUD_OPT_HIGH_SPEED USBHSD->CONTROL = USBHS_DMA_EN | USBHS_INT_BUSY_EN | USBHS_HIGH_SPEED; -#else - #error OPT_MODE_FULL_SPEED not currently supported on CH32 + #else + #error OPT_MODE_FULL_SPEED not currently supported on CH32 USBHSD->CONTROL = USBHS_DMA_EN | USBHS_INT_BUSY_EN | USBHS_FULL_SPEED; -#endif + #endif USBHSD->INT_EN = 0; USBHSD->INT_EN = USBHS_SETUP_ACT_EN | USBHS_TRANSFER_EN | USBHS_BUS_RST_EN | USBHS_SUSPEND_EN | USBHS_ISO_ACT_EN; USBHSD->ENDP_CONFIG = USBHS_EP0_T_EN | USBHS_EP0_R_EN; - USBHSD->ENDP_TYPE = 0x00; - USBHSD->BUF_MODE = 0x00; + USBHSD->ENDP_TYPE = 0x00; + USBHSD->BUF_MODE = 0x00; for (int ep = 0; ep < EP_MAX; ep++) { - EP_TX_LEN(ep) = 0; + EP_TX_LEN(ep) = 0; EP_TX_CTRL(ep) = USBHS_EP_T_AUTOTOG | USBHS_EP_T_RES_NAK; EP_RX_CTRL(ep) = USBHS_EP_R_AUTOTOG | USBHS_EP_R_RES_NAK; EP_RX_MAX_LEN(ep) = 0; } - USBHSD->UEP0_DMA = (uint32_t) ep0_buffer; - USBHSD->UEP0_MAX_LEN = CFG_TUD_ENDPOINT0_SIZE; + USBHSD->UEP0_DMA = (uint32_t)ep0_buffer; + USBHSD->UEP0_MAX_LEN = CFG_TUD_ENDPOINT0_SIZE; xfer_status[0][TUSB_DIR_OUT].max_size = CFG_TUD_ENDPOINT0_SIZE; - xfer_status[0][TUSB_DIR_IN].max_size = CFG_TUD_ENDPOINT0_SIZE; + xfer_status[0][TUSB_DIR_IN].max_size = CFG_TUD_ENDPOINT0_SIZE; USBHSD->DEV_AD = 0; USBHSD->CONTROL |= USBHS_DEV_PU_EN; @@ -177,20 +177,20 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { } void dcd_int_enable(uint8_t rhport) { - (void) rhport; + (void)rhport; NVIC_EnableIRQ(USBHS_IRQn); } void dcd_int_disable(uint8_t rhport) { - (void) rhport; + (void)rhport; NVIC_DisableIRQ(USBHS_IRQn); } void dcd_edpt_close_all(uint8_t rhport) { - (void) rhport; + (void)rhport; for (size_t ep = 1; ep < EP_MAX; ep++) { - EP_TX_LEN(ep) = 0; + EP_TX_LEN(ep) = 0; EP_TX_CTRL(ep) = USBHS_EP_T_AUTOTOG | USBHS_EP_T_RES_NAK; EP_RX_CTRL(ep) = USBHS_EP_R_AUTOTOG | USBHS_EP_R_RES_NAK; @@ -201,18 +201,18 @@ void dcd_edpt_close_all(uint8_t rhport) { } void dcd_set_address(uint8_t rhport, uint8_t dev_addr) { - (void) dev_addr; + (void)dev_addr; // Response with zlp status dcd_edpt_xfer(rhport, 0x80, NULL, 0, false); } void dcd_remote_wakeup(uint8_t rhport) { - (void) rhport; + (void)rhport; } void dcd_sof_enable(uint8_t rhport, bool en) { - (void) rhport; + (void)rhport; if (en) { USBHSD->INT_EN |= USBHS_SOF_ACT_EN; } else { @@ -220,24 +220,23 @@ void dcd_sof_enable(uint8_t rhport, bool en) { } } -void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const* request) { - (void) rhport; +void dcd_edpt0_status_complete(uint8_t rhport, const tusb_control_request_t *request) { + (void)rhport; if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE && - request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && - request->bRequest == TUSB_REQ_SET_ADDRESS) { - USBHSD->DEV_AD = (uint8_t) request->wValue; + request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && request->bRequest == TUSB_REQ_SET_ADDRESS) { + USBHSD->DEV_AD = (uint8_t)request->wValue; } EP_TX_CTRL(0) = USBHS_EP_T_RES_NAK | USBHS_EP_T_TOG_0; EP_RX_CTRL(0) = USBHS_EP_R_RES_NAK | USBHS_EP_R_TOG_0; } -bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const* desc_edpt) { - (void) rhport; +bool dcd_edpt_open(uint8_t rhport, const tusb_desc_endpoint_t *desc_edpt) { + (void)rhport; - uint8_t const ep_num = tu_edpt_number(desc_edpt->bEndpointAddress); - tusb_dir_t const dir = tu_edpt_dir(desc_edpt->bEndpointAddress); + const uint8_t ep_num = tu_edpt_number(desc_edpt->bEndpointAddress); + const tusb_dir_t dir = tu_edpt_dir(desc_edpt->bEndpointAddress); TU_ASSERT(ep_num < EP_MAX); @@ -245,8 +244,8 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const* desc_edpt) { return true; } - xfer_ctl_t* xfer = XFER_CTL_BASE(ep_num, dir); - xfer->max_size = tu_edpt_packet_size(desc_edpt); + xfer_ctl_t *xfer = XFER_CTL_BASE(ep_num, dir); + xfer->max_size = tu_edpt_packet_size(desc_edpt); xfer->is_iso = (desc_edpt->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS); if (dir == TUSB_DIR_OUT) { @@ -263,7 +262,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const* desc_edpt) { /* Enable all types except Isochronous to avoid ISO_ACT interrupt generation */ USBHSD->ENDP_CONFIG |= (USBHS_EP0_T_EN << ep_num); } - EP_TX_LEN(ep_num) = 0; + EP_TX_LEN(ep_num) = 0; EP_TX_CTRL(ep_num) = USBHS_EP_T_AUTOTOG | USBHS_EP_T_RES_NAK | USBHS_EP_T_TOG_0; } @@ -271,19 +270,19 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const* desc_edpt) { } void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) { - (void) rhport; + (void)rhport; - uint8_t const ep_num = tu_edpt_number(ep_addr); - tusb_dir_t const dir = tu_edpt_dir(ep_addr); + const uint8_t ep_num = tu_edpt_number(ep_addr); + const tusb_dir_t dir = tu_edpt_dir(ep_addr); if (dir == TUSB_DIR_OUT) { - EP_RX_CTRL(ep_num) = USBHS_EP_R_AUTOTOG | USBHS_EP_R_RES_NAK; + EP_RX_CTRL(ep_num) = USBHS_EP_R_AUTOTOG | USBHS_EP_R_RES_NAK; EP_RX_MAX_LEN(ep_num) = 0; USBHSD->ENDP_TYPE &= ~(USBHS_EP0_R_TYP << ep_num); USBHSD->ENDP_CONFIG &= ~(USBHS_EP0_R_EN << ep_num); - } else { // TUSB_DIR_IN + } else { // TUSB_DIR_IN EP_TX_CTRL(ep_num) = USBHS_EP_T_AUTOTOG | USBHS_EP_T_RES_NAK | USBHS_EP_T_TOG_0; - EP_TX_LEN(ep_num) = 0; + EP_TX_LEN(ep_num) = 0; USBHSD->ENDP_TYPE &= ~(USBHS_EP0_T_TYP << ep_num); USBHSD->ENDP_CONFIG &= ~(USBHS_EP0_T_EN << ep_num); } @@ -305,24 +304,24 @@ bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep) #endif void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { - (void) rhport; + (void)rhport; - uint8_t const ep_num = tu_edpt_number(ep_addr); - tusb_dir_t const dir = tu_edpt_dir(ep_addr); + const uint8_t ep_num = tu_edpt_number(ep_addr); + const tusb_dir_t dir = tu_edpt_dir(ep_addr); if (dir == TUSB_DIR_OUT) { EP_RX_CTRL(ep_num) = USBHS_EP_R_RES_STALL; } else { - EP_TX_LEN(0) = 0; + EP_TX_LEN(0) = 0; EP_TX_CTRL(ep_num) = USBHS_EP_T_RES_STALL; } } void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { - (void) rhport; + (void)rhport; - uint8_t const ep_num = tu_edpt_number(ep_addr); - tusb_dir_t const dir = tu_edpt_dir(ep_addr); + const uint8_t ep_num = tu_edpt_number(ep_addr); + const tusb_dir_t dir = tu_edpt_dir(ep_addr); if (dir == TUSB_DIR_OUT) { EP_RX_CTRL(ep_num) = USBHS_EP_R_AUTOTOG | USBHS_EP_R_RES_NAK; @@ -331,16 +330,16 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { } } -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) { - (void) is_isr; - (void) rhport; - uint8_t const ep_num = tu_edpt_number(ep_addr); - tusb_dir_t const dir = tu_edpt_dir(ep_addr); +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes, bool is_isr) { + (void)is_isr; + (void)rhport; + const uint8_t ep_num = tu_edpt_number(ep_addr); + const tusb_dir_t dir = tu_edpt_dir(ep_addr); - xfer_ctl_t* xfer = XFER_CTL_BASE(ep_num, dir); - xfer->buffer = buffer; - xfer->total_len = total_bytes; - xfer->queued_len = 0; + xfer_ctl_t *xfer = XFER_CTL_BASE(ep_num, dir); + xfer->buffer = buffer; + xfer->total_len = total_bytes; + xfer->queued_len = 0; xfer->is_last_packet = false; xfer_data_packet(ep_num, dir, xfer); @@ -349,22 +348,22 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t t } void dcd_int_handler(uint8_t rhport) { - (void) rhport; + (void)rhport; - uint8_t int_flag = USBHSD->INT_FG; + uint8_t int_flag = USBHSD->INT_FG; uint8_t int_status = USBHSD->INT_ST; if (int_flag & (USBHS_ISO_ACT_FLAG | USBHS_TRANSFER_FLAG)) { - uint8_t const token = int_status & MASK_UIS_TOKEN; + const uint8_t token = int_status & MASK_UIS_TOKEN; if (token == USBHS_TOKEN_PID_SOF) { uint32_t frame_count = USBHSD->FRAME_NO & USBHS_FRAME_NO_NUM_MASK; dcd_event_sof(rhport, frame_count, true); - }else { - uint8_t const ep_num = int_status & MASK_UIS_ENDP; - tusb_dir_t const ep_dir = (token == USBHS_TOKEN_PID_IN) ? TUSB_DIR_IN : TUSB_DIR_OUT; - uint8_t const ep_addr = tu_edpt_addr(ep_num, ep_dir); - xfer_ctl_t* xfer = XFER_CTL_BASE(ep_num, ep_dir); + } else { + const uint8_t ep_num = int_status & MASK_UIS_ENDP; + const tusb_dir_t ep_dir = (token == USBHS_TOKEN_PID_IN) ? TUSB_DIR_IN : TUSB_DIR_OUT; + const uint8_t ep_addr = tu_edpt_addr(ep_num, ep_dir); + xfer_ctl_t *xfer = XFER_CTL_BASE(ep_num, ep_dir); if (token == USBHS_TOKEN_PID_OUT) { uint16_t rx_len = USBHSD->RX_LEN; @@ -405,28 +404,28 @@ void dcd_int_handler(uint8_t rhport) { } else if (int_flag & USBHS_BUS_RST_FLAG) { // TODO CH32 does not detect actual speed at this time (should be known at end of reset) // This interrupt probably triggered at start of bus reset -// tusb_speed_t actual_speed; -// switch(USBHSD->SPEED_TYPE & USBHS_SPEED_TYPE_MASK){ -// case USBHS_SPEED_TYPE_HIGH: -// actual_speed = TUSB_SPEED_HIGH; -// break; -// case USBHS_SPEED_TYPE_FULL: -// actual_speed = TUSB_SPEED_FULL; -// break; -// case USBHS_SPEED_TYPE_LOW: -// actual_speed = TUSB_SPEED_LOW; -// break; -// default: -// TU_ASSERT(0,); -// break; -// } -// dcd_event_bus_reset(0, actual_speed, true); + // tusb_speed_t actual_speed; + // switch(USBHSD->SPEED_TYPE & USBHS_SPEED_TYPE_MASK){ + // case USBHS_SPEED_TYPE_HIGH: + // actual_speed = TUSB_SPEED_HIGH; + // break; + // case USBHS_SPEED_TYPE_FULL: + // actual_speed = TUSB_SPEED_FULL; + // break; + // case USBHS_SPEED_TYPE_LOW: + // actual_speed = TUSB_SPEED_LOW; + // break; + // default: + // TU_ASSERT(0,); + // break; + // } + // dcd_event_bus_reset(0, actual_speed, true); dcd_event_bus_reset(0, TUSB_SPEED_HIGH, true); USBHSD->DEV_AD = 0; - EP_RX_CTRL(0) = USBHS_EP_R_RES_ACK | USBHS_EP_R_TOG_0; - EP_TX_CTRL(0) = USBHS_EP_T_RES_NAK | USBHS_EP_T_TOG_0; + EP_RX_CTRL(0) = USBHS_EP_R_RES_ACK | USBHS_EP_R_TOG_0; + EP_TX_CTRL(0) = USBHS_EP_T_RES_NAK | USBHS_EP_T_TOG_0; USBHSD->INT_FG = USBHS_BUS_RST_FLAG; /* Clear flag */ } else if (int_flag & USBHS_SUSPEND_FLAG) { -- cgit v1.3.1 From 08cd5c3270e79ed2e63c8941c13c84027a5c003e Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sat, 23 May 2026 17:45:16 +0200 Subject: dcd/ch32fs: clear INT flag after processing Signed-off-by: HiFiPhile --- src/portable/wch/dcd_ch32_usbfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/portable') diff --git a/src/portable/wch/dcd_ch32_usbfs.c b/src/portable/wch/dcd_ch32_usbfs.c index 37677276c..4ecaf129e 100644 --- a/src/portable/wch/dcd_ch32_usbfs.c +++ b/src/portable/wch/dcd_ch32_usbfs.c @@ -183,7 +183,6 @@ void dcd_int_handler(uint8_t rhport) { uint8_t ep = USBFS_INT_ST_MASK_UIS_ENDP(USBOTG_FS->INT_ST); uint8_t token = USBFS_INT_ST_MASK_UIS_TOKEN(USBOTG_FS->INT_ST); uint16_t rx_len = USBOTG_FS->RX_LEN; - USBOTG_FS->INT_FG = USBFS_INT_FG_TRANSFER; switch (token) { case PID_OUT: { @@ -207,6 +206,7 @@ void dcd_int_handler(uint8_t rhport) { break; } + USBOTG_FS->INT_FG = USBFS_INT_FG_TRANSFER; } else if (status & USBFS_INT_FG_BUS_RST) { data.ep0_tog = true; data.xfer[0][TUSB_DIR_OUT].max_size = 64; -- cgit v1.3.1 From c6beac24ca280ce13e538f0b9459553abc825571 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sat, 23 May 2026 19:21:59 +0200 Subject: dcd/ch32fs: do not set EP0 to ACK on status complete It would casue race condition, SETUP packet is always acked. Signed-off-by: HiFiPhile --- src/portable/wch/dcd_ch32_usbfs.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'src/portable') diff --git a/src/portable/wch/dcd_ch32_usbfs.c b/src/portable/wch/dcd_ch32_usbfs.c index 4ecaf129e..ca3ce7ba8 100644 --- a/src/portable/wch/dcd_ch32_usbfs.c +++ b/src/portable/wch/dcd_ch32_usbfs.c @@ -273,8 +273,6 @@ void dcd_edpt0_status_complete(uint8_t rhport, const tusb_control_request_t *req request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && request->bRequest == TUSB_REQ_SET_ADDRESS) { USBOTG_FS->DEV_ADDR = (uint8_t)request->wValue; } - EP_TX_CTRL(0) = USBFS_EP_T_RES_NAK; - EP_RX_CTRL(0) = USBFS_EP_R_RES_ACK; } bool dcd_edpt_open(uint8_t rhport, const tusb_desc_endpoint_t *desc_ep) { -- cgit v1.3.1 From 420de14b50dc2b9c1ed7ba587ef22eb227739eee Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sat, 23 May 2026 19:30:22 +0200 Subject: dcd/ch32hs: refactor transfer flow Refactor the driver to follow USBFS style for easier maintenance. Replace the old packet/response helpers with explicit queue and update paths for IN and OUT transfers. Introduce transfer validity tracking and per-endpoint data toggle state. Reset toggle state on init, close-all, endpoint close, clear-stall, and bus reset. Initialize endpoint controls consistently in NAK + TOG_0 mode. Tighten EP0 setup/status handling and route transfer IRQ processing through the transfer-flag path. Stop enabling ISO_ACT in INT_EN and clear unhandled interrupt flags explicitly. Signed-off-by: HiFiPhile --- src/portable/wch/dcd_ch32_usbhs.c | 282 ++++++++++++++++++++++---------------- 1 file changed, 163 insertions(+), 119 deletions(-) (limited to 'src/portable') diff --git a/src/portable/wch/dcd_ch32_usbhs.c b/src/portable/wch/dcd_ch32_usbhs.c index 01ff6eba3..cfe5e646f 100644 --- a/src/portable/wch/dcd_ch32_usbhs.c +++ b/src/portable/wch/dcd_ch32_usbhs.c @@ -24,7 +24,6 @@ * * This file is part of the TinyUSB stack. */ - #include "tusb_option.h" #if CFG_TUD_ENABLED && defined(TUP_USBIP_WCH_USBHS) && defined(CFG_TUD_WCH_USBIP_USBHS) && \ @@ -41,15 +40,10 @@ typedef struct { uint16_t total_len; uint16_t queued_len; uint16_t max_size; - bool is_last_packet; bool is_iso; + bool valid; } xfer_ctl_t; -typedef enum { - EP_RESPONSE_ACK, - EP_RESPONSE_NAK, -} ep_response_list_t; - #define XFER_CTL_BASE(_ep, _dir) &xfer_status[_ep][_dir] static xfer_ctl_t xfer_status[EP_MAX][2]; @@ -63,73 +57,127 @@ static xfer_ctl_t xfer_status[EP_MAX][2]; /* Endpoint Buffer */ TU_ATTR_ALIGNED(4) static uint8_t ep0_buffer[CFG_TUD_ENDPOINT0_SIZE]; +static bool ep0_tog; +static bool ep_data_tog[EP_MAX][2]; -static void ep_set_response_and_toggle(uint8_t ep_num, tusb_dir_t ep_dir, ep_response_list_t response_type) { +static void set_ep_toggle(uint8_t ep_num, tusb_dir_t ep_dir, bool data1) { if (ep_dir == TUSB_DIR_IN) { - uint8_t response = (response_type == EP_RESPONSE_ACK) ? USBHS_EP_T_RES_ACK : USBHS_EP_T_RES_NAK; - if (ep_num == 0) { - if (response_type == EP_RESPONSE_ACK) { - if (EP_TX_LEN(ep_num) == 0) { - EP_TX_CTRL(ep_num) |= USBHS_EP_T_TOG_1; - } else { - EP_TX_CTRL(ep_num) ^= USBHS_EP_T_TOG_1; - } - } - } - if (xfer_status[ep_num][TUSB_DIR_IN].is_iso == true) { - EP_TX_CTRL(ep_num) = USBHS_EP_T_AUTOTOG; - } else { - EP_TX_CTRL(ep_num) = (EP_TX_CTRL(ep_num) & ~(USBHS_EP_T_RES_MASK)) | response; - } + EP_TX_CTRL(ep_num) = (EP_TX_CTRL(ep_num) & ~(USBHS_EP_T_TOG_MASK)) | + (data1 ? USBHS_EP_T_TOG_1 : USBHS_EP_T_TOG_0); } else { - uint8_t response = (response_type == EP_RESPONSE_ACK) ? USBHS_EP_R_RES_ACK : USBHS_EP_R_RES_NAK; - if (ep_num == 0) { - if (response_type == EP_RESPONSE_ACK) { - if (xfer_status[ep_num][TUSB_DIR_OUT].queued_len == 0) { - EP_RX_CTRL(ep_num) |= USBHS_EP_R_TOG_1; - } - } else { - EP_RX_CTRL(ep_num) ^= USBHS_EP_R_TOG_1; - } - } - EP_RX_CTRL(ep_num) = (EP_RX_CTRL(ep_num) & ~(USBHS_EP_R_RES_MASK)) | response; + EP_RX_CTRL(ep_num) = (EP_RX_CTRL(ep_num) & ~(USBHS_EP_R_TOG_MASK)) | + (data1 ? USBHS_EP_R_TOG_1 : USBHS_EP_R_TOG_0); } } -static void xfer_data_packet(uint8_t ep_num, tusb_dir_t ep_dir, xfer_ctl_t *xfer) { - if (ep_dir == TUSB_DIR_IN) { - uint16_t remaining = xfer->total_len - xfer->queued_len; - uint16_t next_tx_size = TU_MIN(remaining, xfer->max_size); +static void queue_in_packet(uint8_t ep_num, xfer_ctl_t* xfer) { + uint16_t remaining = xfer->total_len - xfer->queued_len; + uint16_t tx_len = TU_MIN(remaining, xfer->max_size); - if (ep_num == 0) { - memcpy(ep0_buffer, &xfer->buffer[xfer->queued_len], next_tx_size); - } else { - EP_TX_DMA_ADDR(ep_num) = (uint32_t)&xfer->buffer[xfer->queued_len]; - } + if (ep_num == 0) { + memcpy(ep0_buffer, &xfer->buffer[xfer->queued_len], tx_len); + } else { + EP_TX_DMA_ADDR(ep_num) = (uint32_t) &xfer->buffer[xfer->queued_len]; + } - EP_TX_LEN(ep_num) = next_tx_size; - xfer->queued_len += next_tx_size; - if (xfer->queued_len == xfer->total_len) { - xfer->is_last_packet = true; - } - if (xfer->is_iso == true) { - /* Enable EP to generate ISA_ACT interrupt */ - USBHSD->ENDP_CONFIG |= (USBHS_EP0_T_EN << ep_num); - } - } else { /* TUSB_DIR_OUT */ - uint16_t left_to_receive = xfer->total_len - xfer->queued_len; - uint16_t max_possible_rx_size = TU_MIN(xfer->max_size, left_to_receive); + EP_TX_LEN(ep_num) = tx_len; + xfer->queued_len += tx_len; + + if (ep_num == 0) { + EP_TX_CTRL(0) = USBHS_EP_T_RES_ACK | (ep0_tog ? USBHS_EP_T_TOG_1 : USBHS_EP_T_TOG_0); + ep0_tog = !ep0_tog; + } else if (xfer->is_iso) { + EP_TX_CTRL(ep_num) = (EP_TX_CTRL(ep_num) & ~(USBHS_EP_T_RES_MASK)) | USBHS_EP_T_RES_NYET; + } else { + set_ep_toggle(ep_num, TUSB_DIR_IN, ep_data_tog[ep_num][TUSB_DIR_IN]); + EP_TX_CTRL(ep_num) = (EP_TX_CTRL(ep_num) & ~(USBHS_EP_T_RES_MASK)) | USBHS_EP_T_RES_ACK; + } +} - if (max_possible_rx_size == left_to_receive) { - xfer->is_last_packet = true; +static void queue_out_packet(uint8_t ep_num, xfer_ctl_t* xfer) { + uint16_t remaining = xfer->total_len - xfer->queued_len; + uint16_t rx_len = TU_MIN(remaining, xfer->max_size); + + if (ep_num > 0) { + EP_RX_DMA_ADDR(ep_num) = (uint32_t) &xfer->buffer[xfer->queued_len]; + EP_RX_MAX_LEN(ep_num) = rx_len; + } + + if (ep_num == 0) { + EP_RX_CTRL(0) = (EP_RX_CTRL(0) & ~(USBHS_EP_R_RES_MASK)) | USBHS_EP_R_RES_ACK; + } else if (xfer->is_iso) { + EP_RX_CTRL(ep_num) = (EP_RX_CTRL(ep_num) & ~(USBHS_EP_R_RES_MASK)) | USBHS_EP_R_RES_NYET; + } else { + set_ep_toggle(ep_num, TUSB_DIR_OUT, ep_data_tog[ep_num][TUSB_DIR_OUT]); + EP_RX_CTRL(ep_num) = (EP_RX_CTRL(ep_num) & ~(USBHS_EP_R_RES_MASK)) | USBHS_EP_R_RES_ACK; + } +} + +static void update_in(uint8_t rhport, uint8_t ep_num, bool force) { + xfer_ctl_t* xfer = XFER_CTL_BASE(ep_num, TUSB_DIR_IN); + if (!xfer->valid) { + return; + } + + if (!force && ep_num != 0 && !xfer->is_iso) { + ep_data_tog[ep_num][TUSB_DIR_IN] = !ep_data_tog[ep_num][TUSB_DIR_IN]; + } + + if (ep_num == 0) { + EP_TX_CTRL(0) = USBHS_EP_T_RES_NAK | (ep0_tog ? USBHS_EP_T_TOG_1 : USBHS_EP_T_TOG_0); + } else if (!xfer->is_iso) { + EP_TX_CTRL(ep_num) = (EP_TX_CTRL(ep_num) & ~(USBHS_EP_T_RES_MASK)) | USBHS_EP_T_RES_NAK; + } + + if (force || (xfer->total_len > xfer->queued_len)) { + queue_in_packet(ep_num, xfer); + } else { + xfer->valid = false; + if (ep_num != 0) { + EP_TX_CTRL(ep_num) = (EP_TX_CTRL(ep_num) & ~(USBHS_EP_T_RES_MASK)) | USBHS_EP_T_RES_NAK; } + dcd_event_xfer_complete(rhport, ep_num | TUSB_DIR_IN_MASK, xfer->queued_len, XFER_RESULT_SUCCESS, true); + } +} + +static void update_out(uint8_t rhport, uint8_t ep_num, uint16_t rx_len) { + xfer_ctl_t* xfer = XFER_CTL_BASE(ep_num, TUSB_DIR_OUT); + if (!xfer->valid) { + return; + } + + if (ep_num == 0) { + EP_RX_CTRL(0) = (EP_RX_CTRL(0) & ~(USBHS_EP_R_RES_MASK)) | USBHS_EP_R_RES_NAK; + } else if (!xfer->is_iso) { + EP_RX_CTRL(ep_num) = (EP_RX_CTRL(ep_num) & ~(USBHS_EP_R_RES_MASK)) | USBHS_EP_R_RES_NAK; + } - if (ep_num > 0) { - EP_RX_DMA_ADDR(ep_num) = (uint32_t)&xfer->buffer[xfer->queued_len]; - EP_RX_MAX_LEN(ep_num) = max_possible_rx_size; + uint16_t remaining = xfer->total_len - xfer->queued_len; + uint16_t len = TU_MIN(rx_len, TU_MIN(remaining, xfer->max_size)); + + if (ep_num == 0) { + memcpy(&xfer->buffer[xfer->queued_len], ep0_buffer, len); + } + + xfer->queued_len += len; + + if (ep_num != 0 && !xfer->is_iso) { + ep_data_tog[ep_num][TUSB_DIR_OUT] = !ep_data_tog[ep_num][TUSB_DIR_OUT]; + } + + if ((xfer->queued_len == xfer->total_len) || (len < xfer->max_size)) { + xfer->valid = false; + dcd_event_xfer_complete(rhport, ep_num, xfer->queued_len, XFER_RESULT_SUCCESS, true); + } + + if (ep_num != 0) { + if (xfer->valid) { + queue_out_packet(ep_num, xfer); + } else { + uint8_t rx_res = xfer->is_iso ? USBHS_EP_R_RES_NYET : USBHS_EP_R_RES_NAK; + EP_RX_CTRL(ep_num) = (EP_RX_CTRL(ep_num) & ~(USBHS_EP_R_RES_MASK)) | rx_res; } } - ep_set_response_and_toggle(ep_num, ep_dir, USBHS_EP_R_RES_ACK); } bool dcd_init(uint8_t rhport, const tusb_rhport_init_t *rh_init) { @@ -137,6 +185,8 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t *rh_init) { (void)rh_init; memset(&xfer_status, 0, sizeof(xfer_status)); + memset(ep_data_tog, 0, sizeof(ep_data_tog)); + ep0_tog = true; USBHSD->HOST_CTRL = 0x00; USBHSD->HOST_CTRL = USBHS_PHY_SUSPENDM; @@ -151,7 +201,7 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t *rh_init) { #endif USBHSD->INT_EN = 0; - USBHSD->INT_EN = USBHS_SETUP_ACT_EN | USBHS_TRANSFER_EN | USBHS_BUS_RST_EN | USBHS_SUSPEND_EN | USBHS_ISO_ACT_EN; + USBHSD->INT_EN = USBHS_SETUP_ACT_EN | USBHS_TRANSFER_EN | USBHS_BUS_RST_EN | USBHS_SUSPEND_EN; USBHSD->ENDP_CONFIG = USBHS_EP0_T_EN | USBHS_EP0_R_EN; USBHSD->ENDP_TYPE = 0x00; @@ -159,8 +209,8 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t *rh_init) { for (int ep = 0; ep < EP_MAX; ep++) { EP_TX_LEN(ep) = 0; - EP_TX_CTRL(ep) = USBHS_EP_T_AUTOTOG | USBHS_EP_T_RES_NAK; - EP_RX_CTRL(ep) = USBHS_EP_R_AUTOTOG | USBHS_EP_R_RES_NAK; + EP_TX_CTRL(ep) = USBHS_EP_T_RES_NAK | USBHS_EP_T_TOG_0; + EP_RX_CTRL(ep) = USBHS_EP_R_RES_NAK | USBHS_EP_R_TOG_0; EP_RX_MAX_LEN(ep) = 0; } @@ -189,10 +239,12 @@ void dcd_int_disable(uint8_t rhport) { void dcd_edpt_close_all(uint8_t rhport) { (void)rhport; + memset(ep_data_tog, 0, sizeof(ep_data_tog)); + for (size_t ep = 1; ep < EP_MAX; ep++) { EP_TX_LEN(ep) = 0; - EP_TX_CTRL(ep) = USBHS_EP_T_AUTOTOG | USBHS_EP_T_RES_NAK; - EP_RX_CTRL(ep) = USBHS_EP_R_AUTOTOG | USBHS_EP_R_RES_NAK; + EP_TX_CTRL(ep) = USBHS_EP_T_RES_NAK | USBHS_EP_T_TOG_0; + EP_RX_CTRL(ep) = USBHS_EP_R_RES_NAK | USBHS_EP_R_TOG_0; EP_RX_MAX_LEN(ep) = 0; } @@ -222,14 +274,10 @@ void dcd_sof_enable(uint8_t rhport, bool en) { void dcd_edpt0_status_complete(uint8_t rhport, const tusb_control_request_t *request) { (void)rhport; - if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE && request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && request->bRequest == TUSB_REQ_SET_ADDRESS) { USBHSD->DEV_AD = (uint8_t)request->wValue; } - - EP_TX_CTRL(0) = USBHS_EP_T_RES_NAK | USBHS_EP_T_TOG_0; - EP_RX_CTRL(0) = USBHS_EP_R_RES_NAK | USBHS_EP_R_TOG_0; } bool dcd_edpt_open(uint8_t rhport, const tusb_desc_endpoint_t *desc_edpt) { @@ -246,11 +294,12 @@ bool dcd_edpt_open(uint8_t rhport, const tusb_desc_endpoint_t *desc_edpt) { xfer_ctl_t *xfer = XFER_CTL_BASE(ep_num, dir); xfer->max_size = tu_edpt_packet_size(desc_edpt); + ep_data_tog[ep_num][dir] = false; xfer->is_iso = (desc_edpt->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS); if (dir == TUSB_DIR_OUT) { USBHSD->ENDP_CONFIG |= (USBHS_EP0_R_EN << ep_num); - EP_RX_CTRL(ep_num) = USBHS_EP_R_AUTOTOG | USBHS_EP_R_RES_NAK; + EP_RX_CTRL(ep_num) = USBHS_EP_R_RES_NAK | USBHS_EP_R_TOG_0; if (xfer->is_iso == true) { USBHSD->ENDP_TYPE |= (USBHS_EP0_R_TYP << ep_num); } @@ -258,12 +307,10 @@ bool dcd_edpt_open(uint8_t rhport, const tusb_desc_endpoint_t *desc_edpt) { } else { if (xfer->is_iso == true) { USBHSD->ENDP_TYPE |= (USBHS_EP0_T_TYP << ep_num); - } else { - /* Enable all types except Isochronous to avoid ISO_ACT interrupt generation */ - USBHSD->ENDP_CONFIG |= (USBHS_EP0_T_EN << ep_num); } + USBHSD->ENDP_CONFIG |= (USBHS_EP0_T_EN << ep_num); EP_TX_LEN(ep_num) = 0; - EP_TX_CTRL(ep_num) = USBHS_EP_T_AUTOTOG | USBHS_EP_T_RES_NAK | USBHS_EP_T_TOG_0; + EP_TX_CTRL(ep_num) = USBHS_EP_T_RES_NAK | USBHS_EP_T_TOG_0; } return true; @@ -276,13 +323,15 @@ void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) { const tusb_dir_t dir = tu_edpt_dir(ep_addr); if (dir == TUSB_DIR_OUT) { - EP_RX_CTRL(ep_num) = USBHS_EP_R_AUTOTOG | USBHS_EP_R_RES_NAK; + EP_RX_CTRL(ep_num) = USBHS_EP_R_RES_NAK | USBHS_EP_R_TOG_0; EP_RX_MAX_LEN(ep_num) = 0; + ep_data_tog[ep_num][TUSB_DIR_OUT] = false; USBHSD->ENDP_TYPE &= ~(USBHS_EP0_R_TYP << ep_num); USBHSD->ENDP_CONFIG &= ~(USBHS_EP0_R_EN << ep_num); } else { // TUSB_DIR_IN - EP_TX_CTRL(ep_num) = USBHS_EP_T_AUTOTOG | USBHS_EP_T_RES_NAK | USBHS_EP_T_TOG_0; + EP_TX_CTRL(ep_num) = USBHS_EP_T_RES_NAK | USBHS_EP_T_TOG_0; EP_TX_LEN(ep_num) = 0; + ep_data_tog[ep_num][TUSB_DIR_IN] = false; USBHSD->ENDP_TYPE &= ~(USBHS_EP0_T_TYP << ep_num); USBHSD->ENDP_CONFIG &= ~(USBHS_EP0_T_EN << ep_num); } @@ -324,9 +373,11 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { const tusb_dir_t dir = tu_edpt_dir(ep_addr); if (dir == TUSB_DIR_OUT) { - EP_RX_CTRL(ep_num) = USBHS_EP_R_AUTOTOG | USBHS_EP_R_RES_NAK; + EP_RX_CTRL(ep_num) = USBHS_EP_R_RES_NAK | USBHS_EP_R_TOG_0; + ep_data_tog[ep_num][TUSB_DIR_OUT] = false; } else { - EP_TX_CTRL(ep_num) = USBHS_EP_T_AUTOTOG | USBHS_EP_R_RES_NAK; + EP_TX_CTRL(ep_num) = USBHS_EP_T_RES_NAK | USBHS_EP_T_TOG_0; + ep_data_tog[ep_num][TUSB_DIR_IN] = false; } } @@ -340,9 +391,21 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to xfer->buffer = buffer; xfer->total_len = total_bytes; xfer->queued_len = 0; - xfer->is_last_packet = false; + xfer->valid = true; + + if (ep_num == 0 && dir == TUSB_DIR_OUT) { + if (total_bytes == 0) { + EP_RX_CTRL(0) = (EP_RX_CTRL(0) & ~(USBHS_EP_R_TOG_MASK)) | USBHS_EP_R_TOG_1; + } else { + EP_RX_CTRL(0) ^= USBHS_EP_R_TOG_1; + } + } - xfer_data_packet(ep_num, dir, xfer); + if (dir == TUSB_DIR_IN) { + update_in(rhport, ep_num, true); + } else { + queue_out_packet(ep_num, xfer); + } return true; } @@ -353,51 +416,27 @@ void dcd_int_handler(uint8_t rhport) { uint8_t int_flag = USBHSD->INT_FG; uint8_t int_status = USBHSD->INT_ST; - if (int_flag & (USBHS_ISO_ACT_FLAG | USBHS_TRANSFER_FLAG)) { + if (int_flag & USBHS_TRANSFER_FLAG) { const uint8_t token = int_status & MASK_UIS_TOKEN; + const uint8_t ep_num = int_status & MASK_UIS_ENDP; + const uint16_t len = USBHSD->RX_LEN; if (token == USBHS_TOKEN_PID_SOF) { uint32_t frame_count = USBHSD->FRAME_NO & USBHS_FRAME_NO_NUM_MASK; dcd_event_sof(rhport, frame_count, true); - } else { - const uint8_t ep_num = int_status & MASK_UIS_ENDP; - const tusb_dir_t ep_dir = (token == USBHS_TOKEN_PID_IN) ? TUSB_DIR_IN : TUSB_DIR_OUT; - const uint8_t ep_addr = tu_edpt_addr(ep_num, ep_dir); - xfer_ctl_t *xfer = XFER_CTL_BASE(ep_num, ep_dir); - - if (token == USBHS_TOKEN_PID_OUT) { - uint16_t rx_len = USBHSD->RX_LEN; - - if (ep_num == 0) { - memcpy(&xfer->buffer[xfer->queued_len], ep0_buffer, rx_len); - } - - xfer->queued_len += rx_len; - if (rx_len < xfer->max_size) { - xfer->is_last_packet = true; - } - } else if (token == USBHS_TOKEN_PID_IN) { - if (xfer->is_iso && xfer->is_last_packet) { - /* Disable EP to avoid ISO_ACT interrupt generation */ - USBHSD->ENDP_CONFIG &= ~(USBHS_EP0_T_EN << ep_num); - } else { - // Do nothing, no need to update xfer->is_last_packet, it is already updated in xfer_data_packet - } - } - - if (xfer->is_last_packet == true) { - ep_set_response_and_toggle(ep_num, ep_dir, EP_RESPONSE_NAK); - dcd_event_xfer_complete(0, ep_addr, xfer->queued_len, XFER_RESULT_SUCCESS, true); - } else { - /* prepare next part of packet to xref */ - xfer_data_packet(ep_num, ep_dir, xfer); - } + } else if (token == USBHS_TOKEN_PID_OUT) { + update_out(rhport, ep_num, len); + } else if (token == USBHS_TOKEN_PID_IN) { + update_in(rhport, ep_num, false); } - - USBHSD->INT_FG = (int_flag & (USBHS_ISO_ACT_FLAG | USBHS_TRANSFER_FLAG)); /* Clear flag */ + USBHSD->INT_FG = (int_flag & USBHS_TRANSFER_FLAG); /* Clear flag */ } else if (int_flag & USBHS_SETUP_FLAG) { - ep_set_response_and_toggle(0, TUSB_DIR_IN, EP_RESPONSE_NAK); - ep_set_response_and_toggle(0, TUSB_DIR_OUT, EP_RESPONSE_NAK); + tusb_control_request_t const* setup = + (tusb_control_request_t const*) ep0_buffer; + ep0_tog = true; + EP_RX_CTRL(0) = (setup->wLength == 0) ? USBHS_EP_R_RES_ACK : USBHS_EP_R_RES_NAK; + EP_TX_CTRL(0) = USBHS_EP_T_RES_NAK; + dcd_event_setup_received(0, ep0_buffer, true); USBHSD->INT_FG = USBHS_SETUP_FLAG; /* Clear flag */ @@ -424,6 +463,8 @@ void dcd_int_handler(uint8_t rhport) { dcd_event_bus_reset(0, TUSB_SPEED_HIGH, true); USBHSD->DEV_AD = 0; + memset(ep_data_tog, 0, sizeof(ep_data_tog)); + ep0_tog = true; EP_RX_CTRL(0) = USBHS_EP_R_RES_ACK | USBHS_EP_R_TOG_0; EP_TX_CTRL(0) = USBHS_EP_T_RES_NAK | USBHS_EP_T_TOG_0; @@ -433,6 +474,9 @@ void dcd_int_handler(uint8_t rhport) { dcd_event_handler(&event, true); USBHSD->INT_FG = USBHS_SUSPEND_FLAG; /* Clear flag */ + } else { + // Unhandled interrupt + USBHSD->INT_FG = int_flag; /* Clear all flags */ } } #endif -- cgit v1.3.1 From 311fb46eb2f963254af6ab206b74828a0ba0273c Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sat, 23 May 2026 20:06:50 +0200 Subject: dcd/ch32x: optmize CTRL reg writing, basically revert e14b0e85 Signed-off-by: HiFiPhile --- src/portable/wch/dcd_ch32_usbfs.c | 26 +++++++++----------------- src/portable/wch/dcd_ch32_usbhs.c | 19 ++++++------------- 2 files changed, 15 insertions(+), 30 deletions(-) (limited to 'src/portable') diff --git a/src/portable/wch/dcd_ch32_usbfs.c b/src/portable/wch/dcd_ch32_usbfs.c index ca3ce7ba8..af0f17785 100644 --- a/src/portable/wch/dcd_ch32_usbfs.c +++ b/src/portable/wch/dcd_ch32_usbfs.c @@ -66,13 +66,6 @@ static struct { static void update_in(uint8_t rhport, uint8_t ep, bool force) { struct usb_xfer *xfer = &data.xfer[ep][TUSB_DIR_IN]; if (xfer->valid) { - // Set EP to NAK to avoid spurious tramsfer - if (ep == 0) { - EP_TX_CTRL(0) = USBFS_EP_T_RES_NAK | (data.ep0_tog ? USBFS_EP_T_TOG : 0); - } else if (!data.isochronous[ep]) { - EP_TX_CTRL(ep) = (EP_TX_CTRL(ep) & ~(USBFS_EP_T_RES_MASK)) | USBFS_EP_T_RES_NAK; - } - if (force || xfer->len) { size_t len = TU_MIN(xfer->max_size, xfer->len); if (ep == 0) { @@ -96,8 +89,12 @@ static void update_in(uint8_t rhport, uint8_t ep, bool force) { EP_TX_CTRL(ep) = (EP_TX_CTRL(ep) & ~(USBFS_EP_T_RES_MASK)) | USBFS_EP_T_RES_ACK; } } else { - xfer->valid = false; - EP_TX_CTRL(ep) = (EP_TX_CTRL(ep) & ~(USBFS_EP_T_RES_MASK)) | USBFS_EP_T_RES_NAK; + xfer->valid = false; + if (ep == 0) { + EP_TX_CTRL(0) = USBFS_EP_T_RES_NAK | (data.ep0_tog ? USBFS_EP_T_TOG : 0); + } else if (!data.isochronous[ep]) { + EP_TX_CTRL(ep) = (EP_TX_CTRL(ep) & ~(USBFS_EP_T_RES_MASK)) | USBFS_EP_T_RES_NAK; + } dcd_event_xfer_complete(rhport, ep | TUSB_DIR_IN_MASK, xfer->processed_len, XFER_RESULT_SUCCESS, true); } } @@ -106,13 +103,6 @@ static void update_in(uint8_t rhport, uint8_t ep, bool force) { static void update_out(uint8_t rhport, uint8_t ep, size_t rx_len) { struct usb_xfer *xfer = &data.xfer[ep][TUSB_DIR_OUT]; if (xfer->valid) { - // Set EP to NAK to avoid spurious tramsfer - if (ep == 0) { - EP_RX_CTRL(0) = USBFS_EP_R_RES_NAK; - } else if (!data.isochronous[ep]) { - EP_RX_CTRL(ep) = (EP_RX_CTRL(ep) & ~USBFS_EP_R_RES_MASK) | USBFS_EP_R_RES_NAK; - } - size_t len = TU_MIN(xfer->max_size, TU_MIN(xfer->len, rx_len)); if (ep == 3) { memcpy(xfer->buffer, data.ep3_buffer.out, len); @@ -128,7 +118,9 @@ static void update_out(uint8_t rhport, uint8_t ep, size_t rx_len) { dcd_event_xfer_complete(rhport, ep, xfer->processed_len, XFER_RESULT_SUCCESS, true); } - if (ep != 0) { + if (ep == 0) { + EP_RX_CTRL(0) = USBFS_EP_R_RES_NAK; + } else { uint8_t rx_res = data.isochronous[ep] ? USBFS_EP_R_RES_NYET : (xfer->valid ? USBFS_EP_R_RES_ACK : USBFS_EP_R_RES_NAK); EP_RX_CTRL(ep) = (EP_RX_CTRL(ep) & ~USBFS_EP_R_RES_MASK) | rx_res; diff --git a/src/portable/wch/dcd_ch32_usbhs.c b/src/portable/wch/dcd_ch32_usbhs.c index cfe5e646f..a6dd5bb79 100644 --- a/src/portable/wch/dcd_ch32_usbhs.c +++ b/src/portable/wch/dcd_ch32_usbhs.c @@ -123,17 +123,13 @@ static void update_in(uint8_t rhport, uint8_t ep_num, bool force) { ep_data_tog[ep_num][TUSB_DIR_IN] = !ep_data_tog[ep_num][TUSB_DIR_IN]; } - if (ep_num == 0) { - EP_TX_CTRL(0) = USBHS_EP_T_RES_NAK | (ep0_tog ? USBHS_EP_T_TOG_1 : USBHS_EP_T_TOG_0); - } else if (!xfer->is_iso) { - EP_TX_CTRL(ep_num) = (EP_TX_CTRL(ep_num) & ~(USBHS_EP_T_RES_MASK)) | USBHS_EP_T_RES_NAK; - } - if (force || (xfer->total_len > xfer->queued_len)) { queue_in_packet(ep_num, xfer); } else { xfer->valid = false; - if (ep_num != 0) { + if (ep_num == 0) { + EP_TX_CTRL(0) = USBHS_EP_T_RES_NAK | (ep0_tog ? USBHS_EP_T_TOG_1 : USBHS_EP_T_TOG_0); + } else { EP_TX_CTRL(ep_num) = (EP_TX_CTRL(ep_num) & ~(USBHS_EP_T_RES_MASK)) | USBHS_EP_T_RES_NAK; } dcd_event_xfer_complete(rhport, ep_num | TUSB_DIR_IN_MASK, xfer->queued_len, XFER_RESULT_SUCCESS, true); @@ -146,12 +142,6 @@ static void update_out(uint8_t rhport, uint8_t ep_num, uint16_t rx_len) { return; } - if (ep_num == 0) { - EP_RX_CTRL(0) = (EP_RX_CTRL(0) & ~(USBHS_EP_R_RES_MASK)) | USBHS_EP_R_RES_NAK; - } else if (!xfer->is_iso) { - EP_RX_CTRL(ep_num) = (EP_RX_CTRL(ep_num) & ~(USBHS_EP_R_RES_MASK)) | USBHS_EP_R_RES_NAK; - } - uint16_t remaining = xfer->total_len - xfer->queued_len; uint16_t len = TU_MIN(rx_len, TU_MIN(remaining, xfer->max_size)); @@ -167,6 +157,9 @@ static void update_out(uint8_t rhport, uint8_t ep_num, uint16_t rx_len) { if ((xfer->queued_len == xfer->total_len) || (len < xfer->max_size)) { xfer->valid = false; + if (ep_num == 0) { + EP_RX_CTRL(0) = (EP_RX_CTRL(0) & ~(USBHS_EP_R_RES_MASK)) | USBHS_EP_R_RES_NAK; + } dcd_event_xfer_complete(rhport, ep_num, xfer->queued_len, XFER_RESULT_SUCCESS, true); } -- cgit v1.3.1 From f52d9c7b27dc0234fb4738762a8a6da01817e2bf Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Mon, 25 May 2026 22:28:39 +0200 Subject: optimize interrupt handling time Signed-off-by: HiFiPhile --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 2 +- src/portable/st/stm32_fsdev/fsdev_stm32.h | 33 +++++++++++++++++++-------- 2 files changed, 24 insertions(+), 11 deletions(-) (limited to 'src/portable') diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 4dfd04fb4..6f7f490a8 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -343,7 +343,7 @@ void dcd_int_handler(uint8_t rhport) { uint32_t int_status = FSDEV_REG->ISTR; /* Put SOF flag at the beginning of ISR in case to get least amount of jitter if it is used for timing purposes */ - if (int_status & U_ISTR_SOF) { + if ((int_status & U_ISTR_SOF) && (FSDEV_REG->CNTR & U_CNTR_SOFM)) { FSDEV_REG->ISTR = (fsdev_bus_t)~U_ISTR_SOF; dcd_event_sof(0, FSDEV_REG->FNR & U_FNR_FN, true); } diff --git a/src/portable/st/stm32_fsdev/fsdev_stm32.h b/src/portable/st/stm32_fsdev/fsdev_stm32.h index 74cc9d0a4..b15c95302 100644 --- a/src/portable/st/stm32_fsdev/fsdev_stm32.h +++ b/src/portable/st/stm32_fsdev/fsdev_stm32.h @@ -266,32 +266,45 @@ TU_ATTR_ALWAYS_INLINE static inline void fsdev_int_disable(uint8_t rhport) { * * CTR may trigger before final PMA SRAM accesses complete on OUT transfers. * Insert delay before reading PMA count/data. - * Max CPU frequency in MHz, used to derive conservative FSDEV PMA delay defaults. + * Max CPU frequency in Hz, used to derive conservative FSDEV PMA delay defaults. */ #if CFG_TUSB_MCU == OPT_MCU_STM32H5 - #define FSDEV_STM32_CPU_MHZ 250U + #define FSDEV_STM32_CPU_HZ 250000000U #elif CFG_TUSB_MCU == OPT_MCU_STM32U5 - #define FSDEV_STM32_CPU_MHZ 160U + #define FSDEV_STM32_CPU_HZ 160000000U #elif CFG_TUSB_MCU == OPT_MCU_STM32U3 - #define FSDEV_STM32_CPU_MHZ 96U + #define FSDEV_STM32_CPU_HZ 96000000U #elif CFG_TUSB_MCU == OPT_MCU_STM32U0 - #define FSDEV_STM32_CPU_MHZ 56U + #define FSDEV_STM32_CPU_HZ 56000000U #elif CFG_TUSB_MCU == OPT_MCU_STM32G0 - #define FSDEV_STM32_CPU_MHZ 64U + #define FSDEV_STM32_CPU_HZ 64000000U #elif CFG_TUSB_MCU == OPT_MCU_STM32C0 - #define FSDEV_STM32_CPU_MHZ 48U + #define FSDEV_STM32_CPU_HZ 48000000U #elif CFG_TUSB_MCU == OPT_MCU_STM32C5 - #define FSDEV_STM32_CPU_MHZ 144U + #define FSDEV_STM32_CPU_HZ 144000000U #endif +// 11 cycles / 800ns = ~13750000 cycles per second, used to derive conservative FSDEV PMA delay defaults #ifndef CFG_TUSB_FSDEV_BTABLE_FS_DELAY_COUNT - #define CFG_TUSB_FSDEV_BTABLE_FS_DELAY_COUNT (FSDEV_STM32_CPU_MHZ / 4U) + #define CFG_TUSB_FSDEV_BTABLE_FS_DELAY_COUNT (FSDEV_STM32_CPU_HZ / 13750000U) #endif +// 11 cycles / 6.4us = ~1718750 cycles per second, used to derive conservative FSDEV PMA delay defaults #ifndef CFG_TUSB_FSDEV_BTABLE_LS_DELAY_COUNT - #define CFG_TUSB_FSDEV_BTABLE_LS_DELAY_COUNT (FSDEV_STM32_CPU_MHZ * 2U) + #define CFG_TUSB_FSDEV_BTABLE_LS_DELAY_COUNT (FSDEV_STM32_CPU_HZ / 1718750U) #endif +/** + * LDR from SP-relative: 2 cycles + * SUBS: 1 cycle + * STR to SP-relative: 2 cycles + * LDR from SP-relative: 2 cycles + * CMP: 1 cycle + * BNE: + * taken: 3 cycles total (often shown as 1 + pipeline refill) + * not taken: 1 cycle + * Total cycles if delay is needed: 11 cycles + */ TU_ATTR_ALWAYS_INLINE static inline void fsdev_btable_workaround_delay(bool low_speed) { volatile uint32_t cycle_count = low_speed ? CFG_TUSB_FSDEV_BTABLE_LS_DELAY_COUNT : CFG_TUSB_FSDEV_BTABLE_FS_DELAY_COUNT; while (cycle_count > 0U) { -- cgit v1.3.1 From d63a45509fd283f5ffccc29cd8569e6efd075c59 Mon Sep 17 00:00:00 2001 From: Jie Feng Date: Thu, 21 May 2026 14:52:38 +0800 Subject: ch32_usbhs: fix endpoint stall length index and clear-stall response Fix issue in the stall handling: - dcd_edpt_stall() for an IN endpoint cleared EP_TX_LEN(0) instead of EP_TX_LEN(ep_num), clobbering endpoint 0's transmit length register when stalling any other IN endpoint. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/portable/wch/dcd_ch32_usbhs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/portable') diff --git a/src/portable/wch/dcd_ch32_usbhs.c b/src/portable/wch/dcd_ch32_usbhs.c index a6dd5bb79..ea3b052ad 100644 --- a/src/portable/wch/dcd_ch32_usbhs.c +++ b/src/portable/wch/dcd_ch32_usbhs.c @@ -354,7 +354,7 @@ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { if (dir == TUSB_DIR_OUT) { EP_RX_CTRL(ep_num) = USBHS_EP_R_RES_STALL; } else { - EP_TX_LEN(0) = 0; + EP_TX_LEN(ep_num) = 0; EP_TX_CTRL(ep_num) = USBHS_EP_T_RES_STALL; } } -- cgit v1.3.1 From e520cff090e5da57e38ef3c7af250aab6d57a186 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Wed, 27 May 2026 00:19:42 +0200 Subject: dwc2: simplify EP0 ZLP handling Signed-off-by: HiFiPhile --- src/portable/synopsys/dwc2/dcd_dwc2.c | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) (limited to 'src/portable') diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index 8997394dd..23fe671d4 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -69,9 +69,6 @@ typedef struct { // SOF enabling flag - required for SOF to not get disabled in ISR when SOF was enabled by bool sof_en; - - // EP0 status OUT flag - bool ep0_status_out; } dcd_data_t; static dcd_data_t _dcd_data; @@ -668,9 +665,6 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to // EP0 can only handle one packet if (epnum == 0) { _dcd_data.ep0_pending[dir] = total_bytes; - if (dir == TUSB_DIR_OUT) { - _dcd_data.ep0_status_out = (total_bytes == 0); - } } // Schedule packets to be sent within interrupt @@ -752,7 +746,6 @@ static void handle_bus_reset(uint8_t rhport) { _dcd_data.sof_en = false; _dcd_data.allocated_epin_count = 0; - _dcd_data.ep0_status_out = false; // 1. NAK for all OUT endpoints for (uint8_t n = 0; n < ep_count; n++) { @@ -907,9 +900,6 @@ static void handle_rxflvl_irq(uint8_t rhport) { // We can receive up to three setup packets in succession, but only the last one is valid. setup[0] = (*rx_fifo); setup[1] = (*rx_fifo); - - // Clear previous pending EP0 OUT if any - _dcd_data.ep0_status_out = false; break; } @@ -940,6 +930,10 @@ static void handle_rxflvl_irq(uint8_t rhport) { xfer->total_len -= tsiz.xfer_size; if (epnum == 0) { _dcd_data.ep0_pending[TUSB_DIR_OUT] = 0; + // Handle EP0 STATUS OUT (or ZLP) here to avoid mix with next SETUP packet received IRQ + if (xfer->total_len == 0) { + dcd_event_xfer_complete(rhport, 0, 0, XFER_RESULT_SUCCESS, true); + } } } break; @@ -949,12 +943,6 @@ static void handle_rxflvl_irq(uint8_t rhport) { // Out packet done // After this entry is popped from the receive FIFO, dwc2 asserts a Transfer Completed interrupt on // the specified OUT endpoint which will be handled by handle_epout_irq() - - // EP0 status OUT is complete - if (epnum == 0 && _dcd_data.ep0_status_out) { - _dcd_data.ep0_status_out = false; - dcd_event_xfer_complete(rhport, epnum, 0, XFER_RESULT_SUCCESS, true); - } break; default: break; // nothing to do @@ -984,7 +972,7 @@ static void handle_epout_slave(uint8_t rhport, uint8_t epnum, dwc2_doepint_t doe // EP0 can only handle one packet, Schedule another packet to be received. edpt_schedule_packets(rhport, epnum, TUSB_DIR_OUT); } else if (xfer->total_len > 0) { - // EP0 status out is handled in handle_rxflvl_irq + // EP0 STATUS OUT (or ZLP) is handled in handle_rxflvl_irq() dcd_event_xfer_complete(rhport, epnum, xfer->total_len, XFER_RESULT_SUCCESS, true); } } else { -- cgit v1.3.1 From a560281051022473c844bdb258be452da52ce5c3 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 22 May 2026 13:42:08 +0200 Subject: dwc2: fix EP0 DMA setup race condition Signed-off-by: HiFiPhile --- src/portable/synopsys/dwc2/dcd_dwc2.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) (limited to 'src/portable') diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index 23fe671d4..1c119eef4 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -73,8 +73,9 @@ typedef struct { static dcd_data_t _dcd_data; -CFG_TUD_MEM_SECTION static struct { - TUD_EPBUF_DEF(setup_packet, 8); +CFG_TUD_MEM_SECTION static union { + TUD_EPBUF_DEF(setup_buffer, 8); + tusb_control_request_t setup_packet; } _dcd_usbbuf; static tud_configure_dwc2_t _tud_cfg = CFG_TUD_CONFIGURE_DWC2_DEFAULT; @@ -138,7 +139,7 @@ static void dma_setup_prepare(uint8_t rhport) { // Receive only 1 packet dwc2->epout[0].doeptsiz = (1 << DOEPTSIZ_STUPCNT_Pos) | (1 << DOEPTSIZ_PKTCNT_Pos) | (8 << DOEPTSIZ_XFRSIZ_Pos); - dwc2->epout[0].doepdma = (uintptr_t) _dcd_usbbuf.setup_packet; + dwc2->epout[0].doepdma = (uintptr_t) _dcd_usbbuf.setup_buffer; dwc2->epout[0].doepctl |= DOEPCTL_EPENA | DOEPCTL_USBAEP; } @@ -896,7 +897,7 @@ static void handle_rxflvl_irq(uint8_t rhport) { case GRXSTS_PKTSTS_SETUP_RX: { // Setup packet received - uint32_t* setup = (uint32_t*)(uintptr_t) _dcd_usbbuf.setup_packet; + uint32_t* setup = (uint32_t*)(uintptr_t) _dcd_usbbuf.setup_buffer; // We can receive up to three setup packets in succession, but only the last one is valid. setup[0] = (*rx_fifo); setup[1] = (*rx_fifo); @@ -956,7 +957,7 @@ static void handle_epout_slave(uint8_t rhport, uint8_t epnum, dwc2_doepint_t doe if (edpt_is_enabled(epin0)) { edpt_disable(rhport, 0x80, false); } - dcd_event_setup_received(rhport, _dcd_usbbuf.setup_packet, true); + dcd_event_setup_received(rhport, _dcd_usbbuf.setup_buffer, true); return; } @@ -1021,9 +1022,13 @@ static void handle_epout_dma(uint8_t rhport, uint8_t epnum, dwc2_doepint_t doepi if (edpt_is_enabled(epin0)) { edpt_disable(rhport, 0x80, false); } - dma_setup_prepare(rhport); - dcd_dcache_invalidate(_dcd_usbbuf.setup_packet, 8); - dcd_event_setup_received(rhport, _dcd_usbbuf.setup_packet, true); + dcd_dcache_invalidate(_dcd_usbbuf.setup_buffer, 8); + dcd_event_setup_received(rhport, _dcd_usbbuf.setup_buffer, true); + + // Prepare EP0 for next setup if this setup has no data stage + if (_dcd_usbbuf.setup_packet.wLength == 0) { + dma_setup_prepare(rhport); + } return; } @@ -1044,9 +1049,8 @@ static void handle_epout_dma(uint8_t rhport, uint8_t epnum, dwc2_doepint_t doepi const uint16_t remain = tsiz.xfer_size; xfer->total_len -= remain; - // this is ZLP, so prepare EP0 for next setup - // TODO use status phase rx - if(epnum == 0 && xfer->total_len == 0) { + // prepare EP0 for next setup + if(epnum == 0) { dma_setup_prepare(rhport); } @@ -1065,9 +1069,6 @@ static void handle_epin_dma(uint8_t rhport, uint8_t epnum, dwc2_diepint_t diepin // EP0 can only handle one packet. Schedule another packet to be transmitted. edpt_schedule_packets(rhport, epnum, TUSB_DIR_IN); } else { - if(epnum == 0) { - dma_setup_prepare(rhport); - } dcd_event_xfer_complete(rhport, epnum | TUSB_DIR_IN_MASK, xfer->total_len, XFER_RESULT_SUCCESS, true); } } -- cgit v1.3.1 From dafdc5c54f34f88c963f7efc0062d0e992074b8f Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 29 May 2026 00:05:44 +0200 Subject: dwc2: move OUT transfer management into RXFLVL IRQ - GRXSTSP register has internal FIFO, receiving events won't mix up (STATUS OUT & next SETUP) - Improve efficiency, remove 2nd IRQ overhead Signed-off-by: HiFiPhile --- src/portable/synopsys/dwc2/dcd_dwc2.c | 71 ++++++++++++++--------------------- 1 file changed, 28 insertions(+), 43 deletions(-) (limited to 'src/portable') diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index 1c119eef4..233840e8b 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -794,13 +794,15 @@ static void handle_bus_reset(uint8_t rhport) { xfer_status[0][TUSB_DIR_OUT].max_size = CFG_TUD_ENDPOINT0_SIZE; xfer_status[0][TUSB_DIR_IN].max_size = CFG_TUD_ENDPOINT0_SIZE; + uint32_t oepmsk = 0; if(dma_device_enabled(dwc2)) { + oepmsk = GINTMSK_OEPINT; dma_setup_prepare(rhport); } else { dwc2->epout[0].doeptsiz |= (3 << DOEPTSIZ_STUPCNT_Pos); } - dwc2->gintmsk |= GINTMSK_OTGINT | GINTMSK_OEPINT | GINTMSK_IEPINT | GINTMSK_IISOIXFRM; + dwc2->gintmsk |= GINTMSK_OTGINT | oepmsk | GINTMSK_IEPINT | GINTMSK_IISOIXFRM; } static void handle_enum_done(uint8_t rhport) { @@ -901,13 +903,27 @@ static void handle_rxflvl_irq(uint8_t rhport) { // We can receive up to three setup packets in succession, but only the last one is valid. setup[0] = (*rx_fifo); setup[1] = (*rx_fifo); + + dwc2_dep_t* epin0 = &dwc2->epin[0]; + if (edpt_is_enabled(epin0)) { + edpt_disable(rhport, 0x80, false); + } + + // (GenID < 3.00a) Must wait SETUP_DONE before next OUT transfer, otherwise OUT data may be corrupted. + // (GenID >= 3.00a) On the other hand STUPCNT is auto reloaded and SETUP_DONE is only triggered once after bus reset. + if (dwc2->gsnpsid >= DWC2_CORE_REV_3_00a) { + dcd_event_setup_received(rhport, _dcd_usbbuf.setup_buffer, true); + } break; } case GRXSTS_PKTSTS_SETUP_DONE: // Setup packet done: - // After popping this out, dwc2 asserts a DOEPINT_SETUP interrupt which is handled by handle_epout_irq() epout->doeptsiz |= (3 << DOEPTSIZ_STUPCNT_Pos); + + if (dwc2->gsnpsid < DWC2_CORE_REV_3_00a) { + dcd_event_setup_received(rhport, _dcd_usbbuf.setup_buffer, true); + } break; case GRXSTS_PKTSTS_RX_DATA: { @@ -931,55 +947,24 @@ static void handle_rxflvl_irq(uint8_t rhport) { xfer->total_len -= tsiz.xfer_size; if (epnum == 0) { _dcd_data.ep0_pending[TUSB_DIR_OUT] = 0; - // Handle EP0 STATUS OUT (or ZLP) here to avoid mix with next SETUP packet received IRQ - if (xfer->total_len == 0) { - dcd_event_xfer_complete(rhport, 0, 0, XFER_RESULT_SUCCESS, true); - } } } break; } - case GRXSTS_PKTSTS_RX_COMPLETE: + case GRXSTS_PKTSTS_RX_COMPLETE: { // Out packet done - // After this entry is popped from the receive FIFO, dwc2 asserts a Transfer Completed interrupt on - // the specified OUT endpoint which will be handled by handle_epout_irq() - break; - - default: break; // nothing to do - } -} - -static void handle_epout_slave(uint8_t rhport, uint8_t epnum, dwc2_doepint_t doepint_bm) { - if (doepint_bm.setup_phase_done) { - // Cleanup previous pending EP0 IN transfer if any - dwc2_dep_t* epin0 = &DWC2_REG(rhport)->epin[0]; - if (edpt_is_enabled(epin0)) { - edpt_disable(rhport, 0x80, false); - } - dcd_event_setup_received(rhport, _dcd_usbbuf.setup_buffer, true); - return; - } - - // Normal OUT transfer complete - if (doepint_bm.xfer_complete) { - // only handle data skip if it is setup or status related - // Note: even though (xfer_complete + status_phase_rx) is for buffered DMA only, for STM32L47x (dwc2 v3.00a) they - // can is set when GRXSTS_PKTSTS_SETUP_RX is popped therefore they can bet set before/together with setup_phase_done - if (!doepint_bm.status_phase_rx && !doepint_bm.setup_packet_rx) { xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); - if (epnum == 0) { - if (_dcd_data.ep0_pending[TUSB_DIR_OUT]) { - // EP0 can only handle one packet, Schedule another packet to be received. - edpt_schedule_packets(rhport, epnum, TUSB_DIR_OUT); - } else if (xfer->total_len > 0) { - // EP0 STATUS OUT (or ZLP) is handled in handle_rxflvl_irq() - dcd_event_xfer_complete(rhport, epnum, xfer->total_len, XFER_RESULT_SUCCESS, true); - } + if (epnum == 0 && _dcd_data.ep0_pending[TUSB_DIR_OUT] > 0) { + // EP0 can only handle one packet, schedule another packet to be received. + edpt_schedule_packets(rhport, 0, TUSB_DIR_OUT); } else { dcd_event_xfer_complete(rhport, epnum, xfer->total_len, XFER_RESULT_SUCCESS, true); } + break; } + + default: break; // nothing to do } } @@ -1108,8 +1093,6 @@ static void handle_ep_irq(uint8_t rhport, uint8_t dir) { #if CFG_TUD_DWC2_SLAVE_ENABLE if (dir == TUSB_DIR_IN) { handle_epin_slave(rhport, epnum, intr.diepint_bm); - } else { - handle_epout_slave(rhport, epnum, intr.doepint_bm); } #endif } @@ -1217,7 +1200,7 @@ void dcd_int_handler(uint8_t rhport) { dwc2->gotgint = otg_int; } - if(gintsts & GINTSTS_SOF) { + if(gintsts & GINTSTS_SOF && dwc2->gintmsk & GINTMSK_SOFM) { dwc2->gintsts = GINTSTS_SOF; dwc2->gintmsk |= GINTMSK_USBSUSPM; const uint32_t frame = (dwc2->dsts & DSTS_FNSOF) >> DSTS_FNSOF_Pos; @@ -1244,11 +1227,13 @@ void dcd_int_handler(uint8_t rhport) { } #endif +#if CFG_TUD_DWC2_DMA_ENABLE // OUT endpoint interrupt handling. if (gintsts & GINTSTS_OEPINT) { // OEPINT is read-only, clear using DOEPINTn handle_ep_irq(rhport, TUSB_DIR_OUT); } +#endif // IN endpoint interrupt handling. if (gintsts & GINTSTS_IEPINT) { -- cgit v1.3.1 From b4e7c25c1b57a69e4c04e41d0f2203abf0d8d358 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 29 May 2026 11:42:47 +0200 Subject: dwc2: process IN EP before OUT To avoid STATUS IN completion of previous control transfer treated as next DATA IN when IRQ latency is high. Signed-off-by: HiFiPhile --- src/portable/synopsys/dwc2/dcd_dwc2.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src/portable') diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index 233840e8b..c90429a15 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -1213,6 +1213,12 @@ void dcd_int_handler(uint8_t rhport) { dcd_event_sof(rhport, frame, true); } + // IN endpoint interrupt handling. + if (gintsts & GINTSTS_IEPINT) { + // IEPINT bit read-only, clear using DIEPINTn + handle_ep_irq(rhport, TUSB_DIR_IN); + } + #if CFG_TUD_DWC2_SLAVE_ENABLE // RxFIFO non-empty interrupt handling. if (gintsts & GINTSTS_RXFLVL) { @@ -1235,12 +1241,6 @@ void dcd_int_handler(uint8_t rhport) { } #endif - // IN endpoint interrupt handling. - if (gintsts & GINTSTS_IEPINT) { - // IEPINT bit read-only, clear using DIEPINTn - handle_ep_irq(rhport, TUSB_DIR_IN); - } - // Incomplete isochronous IN transfer interrupt handling. if (gintsts & GINTSTS_IISOIXFR) { dwc2->gintsts = GINTSTS_IISOIXFR; -- cgit v1.3.1 From cc979da5163d0d407e27d90411a6d4b1a0092779 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Tue, 2 Jun 2026 22:38:57 +0200 Subject: dcd/dwc2: fix back-to-back SETUP reception in DMA mode Signed-off-by: HiFiPhile --- src/portable/synopsys/dwc2/dcd_dwc2.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'src/portable') diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index c90429a15..e6d7dc08e 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -73,9 +73,8 @@ typedef struct { static dcd_data_t _dcd_data; -CFG_TUD_MEM_SECTION static union { - TUD_EPBUF_DEF(setup_buffer, 8); - tusb_control_request_t setup_packet; +CFG_TUD_MEM_SECTION static struct { + TUD_EPBUF_DEF(setup_buffer, 24); } _dcd_usbbuf; static tud_configure_dwc2_t _tud_cfg = CFG_TUD_CONFIGURE_DWC2_DEFAULT; @@ -137,8 +136,8 @@ static void dma_setup_prepare(uint8_t rhport) { } } - // Receive only 1 packet - dwc2->epout[0].doeptsiz = (1 << DOEPTSIZ_STUPCNT_Pos) | (1 << DOEPTSIZ_PKTCNT_Pos) | (8 << DOEPTSIZ_XFRSIZ_Pos); + // Receive back-to-back setup packets + dwc2->epout[0].doeptsiz = (3 << DOEPTSIZ_STUPCNT_Pos); dwc2->epout[0].doepdma = (uintptr_t) _dcd_usbbuf.setup_buffer; dwc2->epout[0].doepctl |= DOEPCTL_EPENA | DOEPCTL_USBAEP; } @@ -1003,15 +1002,19 @@ static void handle_epout_dma(uint8_t rhport, uint8_t epnum, dwc2_doepint_t doepi if (doepint_bm.setup_phase_done) { // Cleanup previous pending EP0 IN transfer if any - dwc2_dep_t* epin0 = &DWC2_REG(rhport)->epin[0]; + dwc2_dep_t* epin0 = &dwc2->epin[0]; + dwc2_dep_t* epout0 = &dwc2->epout[0]; if (edpt_is_enabled(epin0)) { edpt_disable(rhport, 0x80, false); } - dcd_dcache_invalidate(_dcd_usbbuf.setup_buffer, 8); - dcd_event_setup_received(rhport, _dcd_usbbuf.setup_buffer, true); + + dcd_dcache_invalidate(_dcd_usbbuf.setup_buffer, sizeof(_dcd_usbbuf.setup_buffer)); + + tusb_control_request_t *setup_packet = (tusb_control_request_t *) (epout0->doepdma - 8); + dcd_event_setup_received(rhport, (uint8_t*)setup_packet, true); // Prepare EP0 for next setup if this setup has no data stage - if (_dcd_usbbuf.setup_packet.wLength == 0) { + if (setup_packet->wLength == 0) { dma_setup_prepare(rhport); } return; -- cgit v1.3.1 From 73af6494cd5defc296b91da80e2f59b8af4efa70 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 3 Jun 2026 21:44:19 +0700 Subject: dwc2: submit setup packet on SETUP_DONE and drop spurious EP0 RX_COMPLETE on core v3.10a (STM32L476) DWC2 core rev 3.10a pushes an extra EP0 RX_COMPLETE (RXFLVL PKTSTS 0x3) that is not a real OUT data completion, in two cases flagged on DOEPINT: - STPKTRX (Setup Packet Received): between SETUP_RX and SETUP_DONE - STSPHSRX (Status Phase Received, control write): after the OUT data stage when the host starts the IN status phase --- src/portable/synopsys/dwc2/dcd_dwc2.c | 64 +++++++++++++++++++++++------------ 1 file changed, 42 insertions(+), 22 deletions(-) (limited to 'src/portable') diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index c90429a15..447e64479 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -794,15 +794,15 @@ static void handle_bus_reset(uint8_t rhport) { xfer_status[0][TUSB_DIR_OUT].max_size = CFG_TUD_ENDPOINT0_SIZE; xfer_status[0][TUSB_DIR_IN].max_size = CFG_TUD_ENDPOINT0_SIZE; - uint32_t oepmsk = 0; + uint32_t gintmsk = GINTMSK_OTGINT | GINTMSK_IEPINT | GINTMSK_IISOIXFRM; if(dma_device_enabled(dwc2)) { - oepmsk = GINTMSK_OEPINT; + gintmsk |= GINTMSK_OEPINT; dma_setup_prepare(rhport); } else { dwc2->epout[0].doeptsiz |= (3 << DOEPTSIZ_STUPCNT_Pos); } - dwc2->gintmsk |= GINTMSK_OTGINT | oepmsk | GINTMSK_IEPINT | GINTMSK_IISOIXFRM; + dwc2->gintmsk |= gintmsk; } static void handle_enum_done(uint8_t rhport) { @@ -886,45 +886,50 @@ static void handle_rxflvl_irq(uint8_t rhport) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); const volatile uint32_t* rx_fifo = dwc2->fifo[0]; + // DWC2 v3.10a (e.g. STM32L476) emits an extra EP0 RX_COMPLETE that is NOT a real OUT data transfer completion, in two + // situations - each flagged by a DOEPINT bit set on that word: + // - DOEPINT.STPKTRX (Setup Packet Received): pushed between SETUP_RX and SETUP_DONE of every control transfer. + // - DOEPINT.STSPHSRX (Status Phase Received for control write): pushed after the OUT data stage when the host + // starts the IN status phase. + // Both are dropped in the RX_COMPLETE case below, clearing the flag (W1C) so a latched STSPHSRX + // does not block the core from emitting the next SETUP_DONE. usbd still processes the real OUT data + // and queues the IN status ZLP itself - the core does not auto-complete the control-write status. + const bool quirk_v310a = (dwc2->gsnpsid == DWC2_CORE_REV_3_10a); + // Pop control word off FIFO const dwc2_grxstsp_t grxstsp = {.value = dwc2->grxstsp}; + const uint8_t packet_status = grxstsp.packet_status; const uint8_t epnum = grxstsp.ep_ch_num; dwc2_dep_t* epout = &dwc2->epout[epnum]; - switch (grxstsp.packet_status) { + TU_LOG1("packet_status = %u, ep %u, doepint = 0x%04lX\r\n", packet_status, epnum, epout->doepint); + + switch (packet_status) { case GRXSTS_PKTSTS_GLOBAL_OUT_NAK: // Global OUT NAK: do nothing break; case GRXSTS_PKTSTS_SETUP_RX: { // Setup packet received - uint32_t* setup = (uint32_t*)(uintptr_t) _dcd_usbbuf.setup_buffer; + uint32_t * setup = (uint32_t*)(uintptr_t) _dcd_usbbuf.setup_buffer; // We can receive up to three setup packets in succession, but only the last one is valid. setup[0] = (*rx_fifo); setup[1] = (*rx_fifo); - - dwc2_dep_t* epin0 = &dwc2->epin[0]; - if (edpt_is_enabled(epin0)) { - edpt_disable(rhport, 0x80, false); - } - - // (GenID < 3.00a) Must wait SETUP_DONE before next OUT transfer, otherwise OUT data may be corrupted. - // (GenID >= 3.00a) On the other hand STUPCNT is auto reloaded and SETUP_DONE is only triggered once after bus reset. - if (dwc2->gsnpsid >= DWC2_CORE_REV_3_00a) { - dcd_event_setup_received(rhport, _dcd_usbbuf.setup_buffer, true); - } break; } - case GRXSTS_PKTSTS_SETUP_DONE: - // Setup packet done: + case GRXSTS_PKTSTS_SETUP_DONE: { + // Pop this word cause Setup interrupt + // TU_LOG1("\r\n"); epout->doeptsiz |= (3 << DOEPTSIZ_STUPCNT_Pos); - - if (dwc2->gsnpsid < DWC2_CORE_REV_3_00a) { - dcd_event_setup_received(rhport, _dcd_usbbuf.setup_buffer, true); + epout->doepint = DOEPINT_SETUP | DOEPINT_STPKTRX; // Clear SETUP interrupt, required for core to re-write this control word + if (edpt_is_enabled(&dwc2->epin[0])) { + edpt_disable(rhport, 0x80, false); } + dcd_event_setup_received(rhport, _dcd_usbbuf.setup_buffer, true); break; + } case GRXSTS_PKTSTS_RX_DATA: { // Out packet received @@ -953,7 +958,20 @@ static void handle_rxflvl_irq(uint8_t rhport) { } case GRXSTS_PKTSTS_RX_COMPLETE: { - // Out packet done + // Pop this word cause xfer complete interrupt + const uint32_t doepint = epout->doepint; + epout->doepint = DOEPINT_XFRC; + + // v3.10a quirk (see top of function): the extra RX_COMPLETE flagged with Setup Packet Received (STPKTRX) or + // Status Phase Received for control write (STSPHSRX) is not a real OUT completion. Drop it + if (quirk_v310a) { + if (doepint & (DOEPINT_STPKTRX | DOEPINT_STSPHSRX)) { + epout->doepint = DOEPINT_STPKTRX | DOEPINT_STSPHSRX; + break; + } + } + // TU_LOG1("\r\n"); + xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); if (epnum == 0 && _dcd_data.ep0_pending[TUSB_DIR_OUT] > 0) { // EP0 can only handle one packet, schedule another packet to be received. @@ -1093,6 +1111,8 @@ static void handle_ep_irq(uint8_t rhport, uint8_t dir) { #if CFG_TUD_DWC2_SLAVE_ENABLE if (dir == TUSB_DIR_IN) { handle_epin_slave(rhport, epnum, intr.diepint_bm); + } else { + // epout is handled in rxflv } #endif } -- cgit v1.3.1 From 6b89aea9de07f537611ddffca1183a3a958a7ee4 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 3 Jun 2026 23:18:28 +0700 Subject: dwc2: remove investigation debug logging Co-Authored-By: Claude Opus 4.8 (1M context) --- src/portable/synopsys/dwc2/dcd_dwc2.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'src/portable') diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index 447e64479..ac35eb951 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -903,8 +903,6 @@ static void handle_rxflvl_irq(uint8_t rhport) { dwc2_dep_t* epout = &dwc2->epout[epnum]; - TU_LOG1("packet_status = %u, ep %u, doepint = 0x%04lX\r\n", packet_status, epnum, epout->doepint); - switch (packet_status) { case GRXSTS_PKTSTS_GLOBAL_OUT_NAK: // Global OUT NAK: do nothing @@ -921,7 +919,6 @@ static void handle_rxflvl_irq(uint8_t rhport) { case GRXSTS_PKTSTS_SETUP_DONE: { // Pop this word cause Setup interrupt - // TU_LOG1("\r\n"); epout->doeptsiz |= (3 << DOEPTSIZ_STUPCNT_Pos); epout->doepint = DOEPINT_SETUP | DOEPINT_STPKTRX; // Clear SETUP interrupt, required for core to re-write this control word if (edpt_is_enabled(&dwc2->epin[0])) { @@ -970,7 +967,6 @@ static void handle_rxflvl_irq(uint8_t rhport) { break; } } - // TU_LOG1("\r\n"); xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); if (epnum == 0 && _dcd_data.ep0_pending[TUSB_DIR_OUT] > 0) { -- cgit v1.3.1 From 1f6236ae0788e37bb833e4b018faf10fb691bbdd Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 3 Jun 2026 23:41:19 +0700 Subject: dwc2: address Copilot review (comment grammar/typo, tinyusb.json f407 dedup) Co-Authored-By: Claude Opus 4.8 (1M context) --- src/portable/synopsys/dwc2/dcd_dwc2.c | 6 +++--- test/hil/tinyusb.json | 14 -------------- 2 files changed, 3 insertions(+), 17 deletions(-) (limited to 'src/portable') diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index ac35eb951..bab7118dd 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -918,7 +918,7 @@ static void handle_rxflvl_irq(uint8_t rhport) { } case GRXSTS_PKTSTS_SETUP_DONE: { - // Pop this word cause Setup interrupt + // Pop this word causes the Setup interrupt epout->doeptsiz |= (3 << DOEPTSIZ_STUPCNT_Pos); epout->doepint = DOEPINT_SETUP | DOEPINT_STPKTRX; // Clear SETUP interrupt, required for core to re-write this control word if (edpt_is_enabled(&dwc2->epin[0])) { @@ -955,7 +955,7 @@ static void handle_rxflvl_irq(uint8_t rhport) { } case GRXSTS_PKTSTS_RX_COMPLETE: { - // Pop this word cause xfer complete interrupt + // Pop this word causes the xfer complete interrupt const uint32_t doepint = epout->doepint; epout->doepint = DOEPINT_XFRC; @@ -1108,7 +1108,7 @@ static void handle_ep_irq(uint8_t rhport, uint8_t dir) { if (dir == TUSB_DIR_IN) { handle_epin_slave(rhport, epnum, intr.diepint_bm); } else { - // epout is handled in rxflv + // epout is handled in handle_rxflvl_irq } #endif } diff --git a/test/hil/tinyusb.json b/test/hil/tinyusb.json index c0a35ddc2..467b7378a 100644 --- a/test/hil/tinyusb.json +++ b/test/hil/tinyusb.json @@ -477,20 +477,6 @@ "uid": "EBCA8F0670AF", "args": "" } - }, - { - "name": "stm32f407disco", - "uid": "30001A000647313332353735", - "tests": { - "device": true, - "host": false, - "dual": false - }, - "flasher": { - "name": "jlink", - "uid": "000773661813", - "args": "-device stm32f407vg" - } } ] } -- cgit v1.3.1 From b5e080732e67a52afefa6966ca33474c91a53d0c Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 4 Jun 2026 17:55:44 +0700 Subject: Update setup buffer size definition based on DMA configuration --- src/portable/synopsys/dwc2/dcd_dwc2.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'src/portable') diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index c7899a354..ee52ef1e7 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -73,8 +73,15 @@ typedef struct { static dcd_data_t _dcd_data; +// DMA receives up to 3 back-to-back SETUP packets (3 x 8 bytes), Slave mode only needs 1 packet (8 bytes) +#if CFG_TUD_DWC2_DMA_ENABLE + #define DWC2_SETUP_BUFFER_SIZE 24 +#else + #define DWC2_SETUP_BUFFER_SIZE 8 +#endif + CFG_TUD_MEM_SECTION static struct { - TUD_EPBUF_DEF(setup_buffer, 24); + TUD_EPBUF_DEF(setup_buffer, DWC2_SETUP_BUFFER_SIZE); } _dcd_usbbuf; static tud_configure_dwc2_t _tud_cfg = CFG_TUD_CONFIGURE_DWC2_DEFAULT; -- cgit v1.3.1 From a900ea93db686cacde5e595dc09fdfeaa334d556 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 4 Jun 2026 20:46:49 +0700 Subject: dwc2: cleanup setup_packet pointer cast (review feedback) Cast DOEPDMA0 through uintptr_t and use sizeof(tusb_control_request_t) instead of the magic constant 8, matching project convention. Add a reference to Programming Guide v4.20a 9.1.2.1 for the DOEPDMAn-8 rule. Addresses Copilot review comment; no functional change. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/portable/synopsys/dwc2/dcd_dwc2.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/portable') diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index ee52ef1e7..e1a2f6cf2 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -1031,7 +1031,9 @@ static void handle_epout_dma(uint8_t rhport, uint8_t epnum, dwc2_doepint_t doepi dcd_dcache_invalidate(_dcd_usbbuf.setup_buffer, sizeof(_dcd_usbbuf.setup_buffer)); - tusb_control_request_t *setup_packet = (tusb_control_request_t *) (epout0->doepdma - 8); + // DOEPDMA0 has advanced past the last received SETUP packet; back up one packet to the latest valid one + // (Programming Guide v4.20a section 9.1.2.1: "DOEPDMAn-8 provides the pointer to the last valid SETUP data") + tusb_control_request_t *setup_packet = (tusb_control_request_t *) (uintptr_t) (epout0->doepdma - sizeof(tusb_control_request_t)); dcd_event_setup_received(rhport, (uint8_t*)setup_packet, true); // Prepare EP0 for next setup if this setup has no data stage -- cgit v1.3.1 From dffc57135846a4b00aca06b2f588daa6d13b67ef Mon Sep 17 00:00:00 2001 From: Ha Thach Date: Thu, 11 Jun 2026 10:17:28 +0700 Subject: Fix stm32f723disco host/cdc_msc_hid HIL: UART RX starvation + DWC2 DMA split-IN NAK storm (#3677) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix stm32f723disco host HIL: UART RX starvation + DWC2 split bulk NAK/XactErr handling (#3677) stm32f7 BSP — UART RX starvation - The host console USART shared interrupt priority with the USB OTG ISR, so a long OTG interrupt could starve RXNE and drop received bytes. Raise the USART RX IRQ above OTG_FS/OTG_HS in both the bare-metal and FreeRTOS init paths, guarded by #ifdef UART_ID so boards without a UART console keep the default OTG priority. dwc2 host — split NAK/XactErr handling - Slave mode: a persistently-NAKing split bulk/control IN poll re-armed the start-split immediately, storming the ISR and starving task context. Throttle by disabling the channel and re-arming on the resulting halt (no frame deferral). - Buffer-DMA mode: a pure split bulk-OUT NAK was unhandled, leaving the channel halted and stalling the transfer — the dominant cause of CDC echo truncation. Handle it by rewinding the buffer pointers and retrying the start-split (Programming Guide v4.20a 5.1.4.2). - Buffer-DMA mode: a split bulk-OUT XactErr was retried immediately, exhausting HCD_XFER_ERROR_MAX before the transient cleared. Throttle via channel_disable + re-arm to give the hub TT a recovery gap, mirroring slave mode. - All three are scoped to split transfers (hcsplt.split_en); non-split NAK/XactErr keep the core-handled / immediate-retry behavior. The OUT XactErr throttle also excludes periodic split, where channel_disable() is a no-op and would wedge the channel. The nak_disabled flag is generalized to retry_disabled and honors xfer->closing so an endpoint close during a throttled retry tears down cleanly. Verified on stm32f723disco HIL (slave + CFG_TUH_DWC2_DMA_ENABLE): host/cdc_msc_hid, msc_file_explorer, and device_info all pass on both variants; DMA CDC echo went from ~15-25% raw failure to 10/10 clean. --- AGENTS.md | 4 +-- hw/bsp/stm32f7/family.c | 21 +++++++++++---- src/portable/synopsys/dwc2/hcd_dwc2.c | 51 +++++++++++++++++++++++++++++++---- tools/codespell/ignore-words.txt | 1 + 4 files changed, 65 insertions(+), 12 deletions(-) (limited to 'src/portable') diff --git a/AGENTS.md b/AGENTS.md index 5c9908d19..93faa6332 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -18,7 +18,7 @@ Bias toward caution over speed. For trivial tasks, use judgment. - **Language/style:** C99, 2-space indent (no tabs), snake_case helpers, `UPPER_CASE` macros. Public APIs use `tud_`/`tuh_`; macros use `TU_`. Headers self-contained with `#if CFG_TUSB_MCU` guards. - **Safety:** no dynamic allocation; defer ISR work to task context; use `TU_ASSERT()` for error checks; always check return values; include order: C stdlib → tusb common → drivers → classes. - **Layout:** `src/` core, `hw/{mcu,bsp}/` MCU+BSP, `examples/{device,host,dual}/`, `test/{unit-test,fuzz,hil}/`, `docs/`, `tools/`. -- **Commits/PRs:** imperative mood, scoped changes, link issues, include test/build evidence. +- **Commits/PRs:** imperative mood, scoped changes, link issues, include test/build evidence. After opening a PR, monitor it and drive it to green: address automated review comments (Copilot/Codex/Claude) and fix any failing CI builds, pushing follow-up commits until checks pass and review threads are resolved. Useful: `gh pr checks --watch`, `gh pr view --comments`. - **Formatting/lint:** `clang-format` (`.clang-format`), `codespell` (`.codespellrc`), run `pre-commit run --all-files` before submitting. ## Bootstrap @@ -204,7 +204,7 @@ Device examples need real hardware to validate runtime behavior; must at least b ## References -- MCU reference manuals, datasheets, schematics: `$HOME/Documents/Calibre Library`. +- MCU reference manuals, datasheets, schematics: `$HOME/Documents/calibre-library`. - Supported MCUs/boards: `hw/bsp/` and `docs/reference/boards.rst`. - USB classes: `src/class/{cdc,hid,msc,audio,…}/` — each has `*_device.c` and `*_host.c`. - Key files: `src/tusb.h`, `src/tusb_config.h`, `tools/get_deps.py`, `tools/build.py`, `test/unit-test/project.yml`. diff --git a/hw/bsp/stm32f7/family.c b/hw/bsp/stm32f7/family.c index 7a322591b..9427ac4a6 100644 --- a/hw/bsp/stm32f7/family.c +++ b/hw/bsp/stm32f7/family.c @@ -82,8 +82,9 @@ static UART_HandleTypeDef UartHandle = {.Instance = USARTn, .OverSampling = UART_OVERSAMPLING_16, }}; -// RX ring buffer via RXNE interrupt — no HAL IT functions used (avoid HAL state conflicts) -static uint8_t uart_rx_ff_buf[32]; +// RX ring buffer via RXNE interrupt — no HAL IT functions used (avoid HAL state conflicts). +// Sized to absorb a full host-forwarding burst (>64B) when the main loop briefly stalls. +static uint8_t uart_rx_ff_buf[256]; static tu_fifo_t uart_rx_ff; void USARTn_IRQHandler(void) { @@ -142,13 +143,24 @@ void board_init(void) { // 1ms tick timer SysTick_Config(SystemCoreClock / 1000); + // Set UART interrupt higher priority than USB OTG since the F7 USART has no hardware RX FIFO, so a host example's + // UART RX must not be starved by the frequent USB host interrupts or incoming bytes overrun (ORE) and dropped. + NVIC_SetPriority(OTG_FS_IRQn, 1); + NVIC_SetPriority(OTG_HS_IRQn, 1); + #ifdef UART_ID + NVIC_SetPriority(USARTn_IRQn, 0); + #endif + #elif CFG_TUSB_OS == OPT_OS_FREERTOS // Explicitly disable systick to prevent its ISR from running before scheduler start SysTick->CTRL &= ~1U; // If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher ) - NVIC_SetPriority(OTG_FS_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY); - NVIC_SetPriority(OTG_HS_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY); + NVIC_SetPriority(OTG_FS_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY + 1); + NVIC_SetPriority(OTG_HS_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY + 1); + #ifdef UART_ID + NVIC_SetPriority(USARTn_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY); + #endif #endif #ifdef UART_ID @@ -156,7 +168,6 @@ void board_init(void) { HAL_UART_Init(&UartHandle); tu_fifo_config(&uart_rx_ff, uart_rx_ff_buf, sizeof(uart_rx_ff_buf), false); USARTn->CR1 |= USART_CR1_RXNEIE; - NVIC_SetPriority(USARTn_IRQn, (1 << __NVIC_PRIO_BITS) - 1); NVIC_EnableIRQ(USARTn_IRQn); #endif diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index 9ea5f33c5..84a0c6afd 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -104,6 +104,7 @@ typedef struct { uint16_t xferred_bytes; // bytes that accumulate transferred though USB bus for the whole hcd_edpt_xfer(), which can // be composed of multiple channel_xfer_start() (retry with NAK/NYET) uint16_t fifo_bytes; // bytes written/read from/to FIFO (may not be transferred on USB bus). + uint8_t retry_disabled; // 1: channel was disabled to throttle a split retry (NAK in / XactErr out); re-arm on its halt } hcd_xfer_t; typedef struct { @@ -1137,7 +1138,16 @@ static bool handle_channel_in_dma(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hci // TU_LOG1("in hcint = %02lX\r\n", hcint); if (hcint & HCINT_HALTED) { - if (hcint & (HCINT_XFER_COMPLETE | HCINT_STALL | HCINT_BABBLE_ERR)) { + if (xfer->retry_disabled) { + // Halt from our split-NAK throttle disable (below): re-arm the start-split, or let teardown finish + // if the endpoint is closing. Programming Guide 3.5 "Halting a Channel" (p73). + xfer->retry_disabled = 0; + if (xfer->closing) { + is_done = true; + } else { + channel_send_in_token(dwc2, channel); + } + } else if (hcint & (HCINT_XFER_COMPLETE | HCINT_STALL | HCINT_BABBLE_ERR)) { 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; @@ -1203,7 +1213,15 @@ static bool handle_channel_in_dma(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hci channel->hcintmsk &= ~(HCINT_NAK | HCINT_DATATOGGLE_ERR); hcsplt.split_compl = 0; // restart with start-split channel->hcsplt = hcsplt.value; - channel_xfer_in_retry(dwc2, ch_id, hcint); + // Persistent split bulk/control IN NAK (e.g. idle polled endpoint): re-enabling immediately storms + // the ISR and starves the task. Disable + re-arm on the resulting halt to throttle (like the slave + // path); no frame deferral. Programming Guide 3.5 (p73) Note permits disable on NAK/FrmOvrn splits. + if ((hcint & HCINT_NAK) && hcsplt.split_en && !channel_is_periodic(channel->hcchar)) { + xfer->retry_disabled = 1; + channel_disable(dwc2, channel); + } else { + channel_xfer_in_retry(dwc2, ch_id, hcint); + } } else if (hcint & HCINT_FARME_OVERRUN) { // retry start-split in next binterval channel_xfer_in_retry(dwc2, ch_id, hcint); @@ -1228,7 +1246,16 @@ static bool handle_channel_out_dma(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hc // TU_LOG1("out hcint = %02lX\r\n", hcint); if (hcint & HCINT_HALTED) { - if (hcint & (HCINT_XFER_COMPLETE | HCINT_STALL)) { + if (xfer->retry_disabled) { + // Halt from our split-XactErr throttle disable (below): re-issue the start-split (pointers already + // rewound), giving the hub TT a recovery gap. Programming Guide 3.5 "Halting a Channel" (p73). + xfer->retry_disabled = 0; + if (xfer->closing) { + is_done = true; + } else { + channel_xfer_start(dwc2, ch_id); + } + } else if (hcint & (HCINT_XFER_COMPLETE | HCINT_STALL)) { is_done = true; xfer->err_count = 0; if (hcint & HCINT_XFER_COMPLETE) { @@ -1251,9 +1278,17 @@ static bool handle_channel_out_dma(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hc xfer->result = XFER_RESULT_FAILED; is_done = true; } else { - // clean up transfer so far and start again + // Rewind, then retry the start-split. Non-periodic SPLIT throttles via channel_disable + re-arm on + // the halt (immediate re-fire exhausts the retry budget; the disable gives the hub TT a recovery + // gap, like slave). Periodic split is excluded: channel_disable() is a no-op for it, so the halt + // never fires and the channel would wedge. Non-split re-inits immediately (Programming Guide 5.1.2.3). channel_xfer_out_wrapup(dwc2, ch_id); - channel_xfer_start(dwc2, ch_id); + if (hcsplt.split_en && !channel_is_periodic(channel->hcchar)) { + xfer->retry_disabled = 1; + channel_disable(dwc2, channel); + } else { + channel_xfer_start(dwc2, ch_id); + } } } } else if (hcint & HCINT_NYET) { @@ -1271,6 +1306,12 @@ static bool handle_channel_out_dma(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hc channel->hcsplt = hcsplt.value; channel->hcchar |= HCCHAR_CHENA; } + } else if ((hcint & HCINT_NAK) && hcsplt.split_en) { + // Split OUT NAK: rewind + retry the start-split, else the channel stalls (Programming Guide 5.1.4.2). + // Non-split OUT NAK is core-handled (5.1.2.2), so this is split-only. + xfer->err_count = 0; + channel_xfer_out_wrapup(dwc2, ch_id); + channel_xfer_start(dwc2, ch_id); } if (xfer->closing == 1) { diff --git a/tools/codespell/ignore-words.txt b/tools/codespell/ignore-words.txt index 7ce778fab..0b1aa284a 100644 --- a/tools/codespell/ignore-words.txt +++ b/tools/codespell/ignore-words.txt @@ -6,6 +6,7 @@ fro hsi inout mot +ore pris ptd ser -- cgit v1.3.1 From 06b8f4f013a6ce0d91d2f713c88313569d8a722c Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 13 Jun 2026 00:17:07 +0700 Subject: dcd/musb: extract pipe0_read_setup() helper The 8-byte EP0 SETUP drain (count0 assert + two FIFO word reads via a union) was duplicated verbatim between the IDLE case and the deferral case; a future fix applied to one copy but not the other would only show up on the rare deferred-race path. Share one helper. count0 is now read inside the only remaining user (DATA OUT drain). Review follow-up for #3643 (dcd_musb.c l.507 finding). Co-Authored-By: Claude Fable 5 --- src/portable/mentor/musb/dcd_musb.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'src/portable') diff --git a/src/portable/mentor/musb/dcd_musb.c b/src/portable/mentor/musb/dcd_musb.c index e00585068..08d7dd700 100644 --- a/src/portable/mentor/musb/dcd_musb.c +++ b/src/portable/mentor/musb/dcd_musb.c @@ -104,6 +104,19 @@ typedef struct { static dcd_data_t _dcd; +// Drain a SETUP packet (8 bytes) from the EP0 FIFO. Does not ack RxPktRdy. +static bool pipe0_read_setup(musb_regs_t* musb_regs, musb_ep_csr_t* ep_csr, tusb_control_request_t* req) { + TU_ASSERT(sizeof(tusb_control_request_t) == ep_csr->count0); + union { + tusb_control_request_t req; + uint32_t u32[2]; + } setup_packet; + setup_packet.u32[0] = musb_regs->fifo[0]; + setup_packet.u32[1] = musb_regs->fifo[0]; + *req = setup_packet.req; + return true; +} + static void pipe0_start_setup(uint8_t rhport, musb_ep_csr_t* ep_csr, tusb_control_request_t const* req, bool is_isr) { _dcd.pipe0.remain_wlength = req->wLength; @@ -466,23 +479,18 @@ static void process_ep0(uint8_t rhport) { // Receive Data (Setup or OUT) if (csrl & MUSB_CSRL0_RXRDY) { - const uint16_t count0 = ep_csr->count0; switch (_dcd.pipe0.state) { case PIPE0_STATE_IDLE: { - TU_ASSERT(sizeof(tusb_control_request_t) == count0, ); - union { - tusb_control_request_t req; - uint32_t u32[2]; - } setup_packet; - setup_packet.u32[0] = musb_regs->fifo[0]; - setup_packet.u32[1] = musb_regs->fifo[0]; - pipe0_start_setup(rhport, ep_csr, &setup_packet.req, true); + tusb_control_request_t req; + TU_VERIFY(pipe0_read_setup(musb_regs, ep_csr, &req), ); + pipe0_start_setup(rhport, ep_csr, &req, true); break; } case PIPE0_STATE_DATA_OUT: { // EP0 OUT is single-packet (TU_ASSERT total_bytes <= EP0_SIZE in edpt0_xfer) // so the whole packet drains in one shot. + const uint16_t count0 = ep_csr->count0; if (count0) { tu_hwfifo_read(&musb_regs->fifo[0], _dcd.pipe0.buf, count0, NULL); _dcd.pipe0.remain_wlength -= count0; @@ -503,15 +511,7 @@ static void process_ep0(uint8_t rhport) { case PIPE0_STATE_STATUS_OUT_PENDING: case PIPE0_STATE_STATUS_IN: case PIPE0_STATE_DATA_IN: { - TU_ASSERT(sizeof(tusb_control_request_t) == count0, ); - union { - tusb_control_request_t req; - uint32_t u32[2]; - } setup_packet; - setup_packet.u32[0] = musb_regs->fifo[0]; - setup_packet.u32[1] = musb_regs->fifo[0]; - - _dcd.pipe0.deferred_setup = setup_packet.req; + TU_VERIFY(pipe0_read_setup(musb_regs, ep_csr, &_dcd.pipe0.deferred_setup), ); _dcd.pipe0.deferred_setup_valid = true; goto process_status; } -- cgit v1.3.1 From 87eeab605ff571a5ac1784c2c26e944aa0129d7e Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 13 Jun 2026 00:17:30 +0700 Subject: dcd/musb: restore EP0 OUT RXRDY flow-control comment The pre-existing comment explaining why the OUT branch does not ack RxPktRdy was dropped when the SETUP handling moved into pipe0_start_setup(). It is load-bearing: acking before edpt0_xfer() arms the drain buffer would let the host send data with nowhere to put it. Restore it with the databook-deviation rationale so the branches don't get "unified" later. Review follow-up for #3643 (dcd_musb.c l.116 finding). Co-Authored-By: Claude Fable 5 --- src/portable/mentor/musb/dcd_musb.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/portable') diff --git a/src/portable/mentor/musb/dcd_musb.c b/src/portable/mentor/musb/dcd_musb.c index 08d7dd700..fdd2eaac9 100644 --- a/src/portable/mentor/musb/dcd_musb.c +++ b/src/portable/mentor/musb/dcd_musb.c @@ -128,6 +128,9 @@ static void pipe0_start_setup(uint8_t rhport, musb_ep_csr_t* ep_csr, _dcd.pipe0.state = PIPE0_STATE_DATA_IN; ep_csr->csr0l = MUSB_CSRL0_RXRDYC; } else { + // If OUT (rx) direction, let edpt0_xfer() clear RXRDY when it's ready to receive data. + // Deliberate deviation from the databook's canonical flow (ack right after unload), + // used as NAK flow control until usbd arms the drain buffer. _dcd.pipe0.state = PIPE0_STATE_DATA_OUT; } } -- cgit v1.3.1 From b21d59f8177af967e2b2757c4ef996df00d1e617 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 13 Jun 2026 00:18:32 +0700 Subject: dcd/musb: replace deferral goto with per-state handling The goto jumped into the csrl==0 completion switch with RXRDY still set, making its "When CSRL0 is zero" guard comment untrue on that path. Handle each deferral state in a self-contained switch instead; the csrl==0 switch is now only reached with csrl==0 and its comment is truthful again. Behavior unchanged. Review follow-up for #3643 (dcd_musb.c l.523 finding). Co-Authored-By: Claude Fable 5 --- src/portable/mentor/musb/dcd_musb.c | 43 +++++++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 4 deletions(-) (limited to 'src/portable') diff --git a/src/portable/mentor/musb/dcd_musb.c b/src/portable/mentor/musb/dcd_musb.c index fdd2eaac9..9bdd6b080 100644 --- a/src/portable/mentor/musb/dcd_musb.c +++ b/src/portable/mentor/musb/dcd_musb.c @@ -510,20 +510,55 @@ static void process_ep0(uint8_t rhport) { // - Status IN/OUT finished, IRQ and new setup packet IRQ arrive at the same time. // - Data IN finished and status OUT is received, both IRQs and new setup packet IRQ arrive at the same time. // could happen when CPU load is high, save the new setup packet for later processing after current status stage complete. + case PIPE0_STATE_DATA_IN: case PIPE0_STATE_STATUS_OUT: case PIPE0_STATE_STATUS_OUT_PENDING: - case PIPE0_STATE_STATUS_IN: - case PIPE0_STATE_DATA_IN: { + case PIPE0_STATE_STATUS_IN: { TU_VERIFY(pipe0_read_setup(musb_regs, ep_csr, &_dcd.pipe0.deferred_setup), ); _dcd.pipe0.deferred_setup_valid = true; - goto process_status; + + switch (_dcd.pipe0.state) { + case PIPE0_STATE_DATA_IN: + // Last DATA IN packet sent (TXRDY-clear coalesced with the SETUP IRQ). The STATUS OUT + // confirm IRQ is missed too — promote so edpt0_xfer(STATUS OUT) fires complete immediately. + if (_dcd.pipe0.remain_wlength == 0) { + _dcd.pipe0.state = PIPE0_STATE_STATUS_OUT_PENDING; + } + dcd_event_xfer_complete(rhport, TU_EP0_IN, _dcd.pipe0.xact_len, XFER_RESULT_SUCCESS, true); + break; + + case PIPE0_STATE_STATUS_OUT: + // Status confirm IRQ coalesced with the SETUP — edpt0_xfer(STATUS OUT) fires complete. + _dcd.pipe0.state = PIPE0_STATE_STATUS_OUT_PENDING; + break; + + case PIPE0_STATE_STATUS_OUT_PENDING: + // edpt0_xfer(STATUS OUT) already called — fire complete and replay now. + _dcd.pipe0.state = PIPE0_STATE_IDLE; + dcd_event_xfer_complete(rhport, TU_EP0_OUT, 0, XFER_RESULT_SUCCESS, true); + pipe0_process_deferred_setup(rhport, ep_csr, true); + break; + + default: + // PIPE0_STATE_STATUS_IN: ZLP-sent IRQ coalesced with the SETUP. + if (_dcd.pipe0.pending_addr) { + musb_regs->faddr = _dcd.pipe0.pending_addr; + _dcd.pipe0.pending_addr = 0; + } + _dcd.pipe0.state = PIPE0_STATE_IDLE; + dcd_event_xfer_complete(rhport, TU_EP0_IN, 0, XFER_RESULT_SUCCESS, true); + pipe0_process_deferred_setup(rhport, ep_csr, true); + break; + } + break; } + + default: break; } return; } -process_status: /* When CSRL0 is zero, it means that either * - completion of sending any length packet TxPktRdy clear * - or status stage is complete (ZLP) after DataEnd is set */ -- cgit v1.3.1 From 1ea385a6c431cee759695515a4bed94c6dff65c6 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 13 Jun 2026 00:18:55 +0700 Subject: dcd/musb: check SentStall/SetupEnd before DATAEND guard MUSBMHDRC 21.1.5 requires the EP0 service routine to check SentStall and SetupEnd first; the early DATAEND return ran before both, and SentStall is most likely to fire exactly while DataEnd may still read back set (auto-STALL after DataEnd, 21.1.7), which would skip the recovery. The guard also moves below the RXRDY block so a coalesced DATAEND|RXRDY read cannot swallow a SETUP on cores where the CPU-set-only DataEnd bit reads back 1; the comment documents the vendor-dependent read-back. Review follow-up for #3643 (dcd_musb.c l.445 finding). Co-Authored-By: Claude Fable 5 --- src/portable/mentor/musb/dcd_musb.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'src/portable') diff --git a/src/portable/mentor/musb/dcd_musb.c b/src/portable/mentor/musb/dcd_musb.c index 9bdd6b080..86ae3ae9a 100644 --- a/src/portable/mentor/musb/dcd_musb.c +++ b/src/portable/mentor/musb/dcd_musb.c @@ -458,10 +458,7 @@ static void process_ep0(uint8_t rhport) { musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, 0); uint_fast8_t csrl = ep_csr->csr0l; - if (csrl & MUSB_CSRL0_DATAEND) { - return; - } - + // 21.1.5: SentStall and SetupEnd must be checked before anything else. if (csrl & MUSB_CSRL0_STALLED) { ep_csr->csr0l = 0; _dcd.pipe0.state = PIPE0_STATE_IDLE; @@ -559,6 +556,13 @@ static void process_ep0(uint8_t rhport) { return; } + if (csrl & MUSB_CSRL0_DATAEND) { + // Last DATA IN chunk / STATUS IN arm wrote TXRDY|DATAEND and the status stage has not completed + // yet — nothing to service. DataEnd is CPU-set-only per the CSR access table; whether it ever + // reads back 1 is vendor-dependent (on cores where it reads 0 this guard is dead code). + return; + } + /* When CSRL0 is zero, it means that either * - completion of sending any length packet TxPktRdy clear * - or status stage is complete (ZLP) after DataEnd is set */ -- cgit v1.3.1 From 91608e3c4f8c944674547e5c254759c1dda08379 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 13 Jun 2026 00:20:37 +0700 Subject: dcd/musb: fix deferred-SETUP replay racing usbd's status call STATUS_OUT_PENDING conflated "edpt0_xfer(STATUS OUT) called, awaiting confirm IRQ" with "confirm IRQ seen, awaiting edpt0_xfer". The deferral path completed the status and replayed the saved SETUP from the ISR in both flavors; in the IRQ-first one, usbd's still- outstanding edpt0_xfer(STATUS OUT) for the old transfer (queued via status_stage_xact) then landed in the replayed transfer's state and corrupted it: NULL pipe0.buf armed plus RXRDYC, so the host's next DATA OUT drained through a NULL pointer. usbd processes EP0 XFER_COMPLETE events unconditionally, so nothing downstream defuses it. Split the state into STATUS_OUT_PENDING_XFER / _IRQ. The deferral completes and replays only in PENDING_XFER (old transfer already retired); in PENDING_IRQ it only holds the SETUP and the usbd-driven edpt0_xfer fires the completion and replays. The DATA_IN deferral now synthesizes PENDING_IRQ (its remain==0 invariant asserted: a SETUP before DataEnd raises SetupEnd instead), which also makes the old deferred-promotion in the csrl==0 DATA_IN case unreachable - dropped. Assert the drain buffer before the DATA OUT FIFO read as a cheap backstop for this corruption class. Review follow-up for #3643 (dcd_musb.c l.503 finding). Co-Authored-By: Claude Fable 5 --- src/portable/mentor/musb/dcd_musb.c | 59 ++++++++++++++++++++++--------------- 1 file changed, 35 insertions(+), 24 deletions(-) (limited to 'src/portable') diff --git a/src/portable/mentor/musb/dcd_musb.c b/src/portable/mentor/musb/dcd_musb.c index 86ae3ae9a..2c31e3b2f 100644 --- a/src/portable/mentor/musb/dcd_musb.c +++ b/src/portable/mentor/musb/dcd_musb.c @@ -86,7 +86,8 @@ enum { PIPE0_STATE_DATA_OUT, // DATA OUT stage PIPE0_STATE_STATUS_IN, // STATUS IN — device sends IN-ZLP; awaits send-ACK IRQ PIPE0_STATE_STATUS_OUT, // post-DATAEND, neither edpt0_xfer(STATUS OUT) nor confirmation IRQ has happened yet - PIPE0_STATE_STATUS_OUT_PENDING, // one of {edpt0_xfer(STATUS OUT), confirmation IRQ} has happened; the other fires xfer_complete + PIPE0_STATE_STATUS_OUT_PENDING_XFER, // edpt0_xfer(STATUS OUT) called first; the confirmation IRQ fires xfer_complete + PIPE0_STATE_STATUS_OUT_PENDING_IRQ, // confirmation IRQ seen (or synthesized) first; edpt0_xfer(STATUS OUT) fires xfer_complete }; typedef struct { @@ -436,11 +437,12 @@ static bool edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_ case PIPE0_STATE_STATUS_OUT: TU_ASSERT(!dir_in && total_bytes == 0); // only STATUS OUT allowed // First event of the STATUS OUT pair — wait for the IRQ to fire complete. - _dcd.pipe0.state = PIPE0_STATE_STATUS_OUT_PENDING; + _dcd.pipe0.state = PIPE0_STATE_STATUS_OUT_PENDING_XFER; break; - case PIPE0_STATE_STATUS_OUT_PENDING: - // Second event — IRQ already arrived, fire complete now. + case PIPE0_STATE_STATUS_OUT_PENDING_IRQ: + // Second event — IRQ already arrived, fire complete now. The old transfer is retired here, + // so a deferred SETUP can be replayed safely. _dcd.pipe0.state = PIPE0_STATE_IDLE; dcd_event_xfer_complete(rhport, ep_addr, 0, XFER_RESULT_SUCCESS, is_isr); pipe0_process_deferred_setup(rhport, ep_csr, is_isr); @@ -492,6 +494,7 @@ static void process_ep0(uint8_t rhport) { // so the whole packet drains in one shot. const uint16_t count0 = ep_csr->count0; if (count0) { + TU_ASSERT(_dcd.pipe0.buf, ); tu_hwfifo_read(&musb_regs->fifo[0], _dcd.pipe0.buf, count0, NULL); _dcd.pipe0.remain_wlength -= count0; } @@ -503,39 +506,48 @@ static void process_ep0(uint8_t rhport) { break; } - // New SETUP packet arrived while old control transfer is not finished yet. This could happen in following scenarios: - // - Status IN/OUT finished, IRQ and new setup packet IRQ arrive at the same time. - // - Data IN finished and status OUT is received, both IRQs and new setup packet IRQ arrive at the same time. - // could happen when CPU load is high, save the new setup packet for later processing after current status stage complete. + // New SETUP packet arrived while the old control transfer's tail events are still in flight + // (IRQs coalesced under high CPU load), e.g.: + // - Status IN/OUT finished, its IRQ and the new SETUP IRQ arrive at the same time. + // - Data IN finished and status OUT is received, both IRQs and the new SETUP IRQ arrive at the same time. + // Save the SETUP; it is replayed only once the old transfer is fully retired — i.e. when usbd has + // made (or already made) its final edpt0_xfer() call for it. case PIPE0_STATE_DATA_IN: case PIPE0_STATE_STATUS_OUT: - case PIPE0_STATE_STATUS_OUT_PENDING: + case PIPE0_STATE_STATUS_OUT_PENDING_XFER: + case PIPE0_STATE_STATUS_OUT_PENDING_IRQ: case PIPE0_STATE_STATUS_IN: { TU_VERIFY(pipe0_read_setup(musb_regs, ep_csr, &_dcd.pipe0.deferred_setup), ); _dcd.pipe0.deferred_setup_valid = true; switch (_dcd.pipe0.state) { case PIPE0_STATE_DATA_IN: - // Last DATA IN packet sent (TXRDY-clear coalesced with the SETUP IRQ). The STATUS OUT - // confirm IRQ is missed too — promote so edpt0_xfer(STATUS OUT) fires complete immediately. - if (_dcd.pipe0.remain_wlength == 0) { - _dcd.pipe0.state = PIPE0_STATE_STATUS_OUT_PENDING; - } + // Coalesced: last DATA IN sent + status OUT done + new SETUP in one csrl read. Fire the + // DATA IN completion and synthesize the missed status confirm; usbd's edpt0_xfer(STATUS OUT) + // fires the status completion and replays. + TU_ASSERT(_dcd.pipe0.remain_wlength == 0, ); + _dcd.pipe0.state = PIPE0_STATE_STATUS_OUT_PENDING_IRQ; dcd_event_xfer_complete(rhport, TU_EP0_IN, _dcd.pipe0.xact_len, XFER_RESULT_SUCCESS, true); break; case PIPE0_STATE_STATUS_OUT: // Status confirm IRQ coalesced with the SETUP — edpt0_xfer(STATUS OUT) fires complete. - _dcd.pipe0.state = PIPE0_STATE_STATUS_OUT_PENDING; + _dcd.pipe0.state = PIPE0_STATE_STATUS_OUT_PENDING_IRQ; break; - case PIPE0_STATE_STATUS_OUT_PENDING: - // edpt0_xfer(STATUS OUT) already called — fire complete and replay now. + case PIPE0_STATE_STATUS_OUT_PENDING_XFER: + // edpt0_xfer(STATUS OUT) already called — old transfer retired, complete and replay now. _dcd.pipe0.state = PIPE0_STATE_IDLE; dcd_event_xfer_complete(rhport, TU_EP0_OUT, 0, XFER_RESULT_SUCCESS, true); pipe0_process_deferred_setup(rhport, ep_csr, true); break; + case PIPE0_STATE_STATUS_OUT_PENDING_IRQ: + // usbd has not called edpt0_xfer(STATUS OUT) for the old transfer yet — only hold the + // SETUP. Replaying here would let that still-outstanding call land in the replayed + // transfer's state and corrupt it (e.g. NULL DATA OUT drain buffer). + break; + default: // PIPE0_STATE_STATUS_IN: ZLP-sent IRQ coalesced with the SETUP. if (_dcd.pipe0.pending_addr) { @@ -573,27 +585,26 @@ static void process_ep0(uint8_t rhport) { // to STATUS_OUT to await the host's STATUS-OUT ZLP confirmation IRQ. if (_dcd.pipe0.remain_wlength == 0) { _dcd.pipe0.state = PIPE0_STATE_STATUS_OUT; - // If a new SETUP was deferred then STATUS OUT IRQ is missed, manually transition to STATUS_OUT_PENDING to allow ep0_xfer(STATUS OUT) to fire complete immediately. - if (_dcd.pipe0.deferred_setup_valid) { - _dcd.pipe0.state = PIPE0_STATE_STATUS_OUT_PENDING; - } } dcd_event_xfer_complete(rhport, TU_EP0_IN, _dcd.pipe0.xact_len, XFER_RESULT_SUCCESS, true); - break; case PIPE0_STATE_STATUS_OUT: // First event of the STATUS OUT pair — wait for edpt0_xfer(STATUS OUT) to fire complete. - _dcd.pipe0.state = PIPE0_STATE_STATUS_OUT_PENDING; + _dcd.pipe0.state = PIPE0_STATE_STATUS_OUT_PENDING_IRQ; break; - case PIPE0_STATE_STATUS_OUT_PENDING: + case PIPE0_STATE_STATUS_OUT_PENDING_XFER: // Second event — edpt0_xfer(STATUS OUT) already called, fire complete now. _dcd.pipe0.state = PIPE0_STATE_IDLE; dcd_event_xfer_complete(rhport, TU_EP0_OUT, 0, XFER_RESULT_SUCCESS, true); pipe0_process_deferred_setup(rhport, ep_csr, true); break; + case PIPE0_STATE_STATUS_OUT_PENDING_IRQ: + // Stale duplicate of the status confirm — already accounted for; edpt0_xfer fires complete. + break; + case PIPE0_STATE_STATUS_IN: if (_dcd.pipe0.pending_addr) { musb_regs->faddr = _dcd.pipe0.pending_addr; -- cgit v1.3.1 From 3b73ee7e926d228bfa6ea4961d15a11a0310ed44 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 13 Jun 2026 00:22:03 +0700 Subject: dcd/musb: gate stale EP0 RXRDY interrupts with rxrdy_consumed The deferral path drains the SETUP but leaves RxPktRdy set, and the SETUP's IRQ latches after the ISR's clear-on-read intr_tx read - so a second process_ep0 pass (same ISR, via the intr_tx re-read merge) is guaranteed and misreads the leftovers: count0==0 fires a spurious DATA OUT completion, the replay's RXRDYC write turns the second pass into a phantom csrl==0 DATA IN completion, and a zero-length replay re-enters the deferral case on a drained FIFO (count0 assert or garbage saved as a SETUP). The registers cannot expose the staleness: RxPktRdy and count0 read unchanged until ServicedRxPktRdy is written. Track it in software: rxrdy_consumed means "RxPktRdy is set in hw but its packet was already consumed". Set wherever a drained packet's RXRDY is intentionally left set (OUT/zero-length flow-control parks, every DATA OUT drain awaiting the next arm, the deferral path); cleared at every RXRDYC write site (edpt0_xfer arms, dcd_set_address, STALLED/SETEND recovery, bus reset). The RXRDY block returns early while parked. Replayed IN requests skip the RXRDYC in pipe0_start_setup and keep the packet parked until the edpt0_xfer(DATA IN) arm acks it (before loading the shared FIFO), so the stale pass sees RXRDY+parked instead of csrl==0. The normal IDLE path is unchanged - master never re-entered these windows because the single SETUP edge was always consumed by the pass that parked it; the deferral is what introduced a pending second pass. Review follow-up for #3643 (dcd_musb.c l.516 finding). Co-Authored-By: Claude Fable 5 --- src/portable/mentor/musb/dcd_musb.c | 36 ++++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) (limited to 'src/portable') diff --git a/src/portable/mentor/musb/dcd_musb.c b/src/portable/mentor/musb/dcd_musb.c index 2c31e3b2f..0485c4374 100644 --- a/src/portable/mentor/musb/dcd_musb.c +++ b/src/portable/mentor/musb/dcd_musb.c @@ -99,6 +99,8 @@ typedef struct { uint8_t pending_addr; // new USB address latched by dcd_set_address; applied when STATUS IN completes tusb_control_request_t deferred_setup; bool deferred_setup_valid; + bool rxrdy_consumed; // RxPktRdy left set in hw for an already-consumed packet (NAK flow control); + // RXRDY events are stale while set. Cleared when RXRDYC is written. } pipe0; pipe_state_t pipe[MUSB_PIPE_COUNT]; } dcd_data_t; @@ -123,16 +125,23 @@ static void pipe0_start_setup(uint8_t rhport, musb_ep_csr_t* ep_csr, _dcd.pipe0.remain_wlength = req->wLength; if (req->wLength == 0) { + // Leave RXRDY set; edpt0_xfer(STATUS IN) acks it together with DATAEND. _dcd.pipe0.state = PIPE0_STATE_STATUS_IN; + _dcd.pipe0.rxrdy_consumed = true; } else { if (req->bmRequestType & TUSB_DIR_IN_MASK) { _dcd.pipe0.state = PIPE0_STATE_DATA_IN; - ep_csr->csr0l = MUSB_CSRL0_RXRDYC; + // On a deferred replay the packet's RXRDY stays parked until the edpt0_xfer(DATA IN) arm + // acks it — a stale latched EP0 IRQ in between is gated by rxrdy_consumed. + if (!_dcd.pipe0.rxrdy_consumed) { + ep_csr->csr0l = MUSB_CSRL0_RXRDYC; + } } else { // If OUT (rx) direction, let edpt0_xfer() clear RXRDY when it's ready to receive data. // Deliberate deviation from the databook's canonical flow (ack right after unload), // used as NAK flow control until usbd arms the drain buffer. _dcd.pipe0.state = PIPE0_STATE_DATA_OUT; + _dcd.pipe0.rxrdy_consumed = true; } } @@ -412,6 +421,11 @@ static bool edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_ case PIPE0_STATE_DATA_OUT: { _dcd.pipe0.xact_len = total_bytes; if (dir_in) { + // Replayed SETUP keeps its RXRDY parked until here; ack it before loading the shared FIFO. + if (_dcd.pipe0.rxrdy_consumed) { + ep_csr->csr0l = MUSB_CSRL0_RXRDYC; + _dcd.pipe0.rxrdy_consumed = false; + } // DATA IN: load FIFO, set TXRDY. Add DATAEND on the last chunk // (ep0_remain_datalen == 0 after this load) to end the data stage. tu_hwfifo_write(&musb_regs->fifo[0], buffer, total_bytes, NULL); @@ -425,6 +439,7 @@ static bool edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_ // DATA OUT: arm drain target, ack RXRDY so host can send DATA OUT. _dcd.pipe0.buf = buffer; ep_csr->csr0l = MUSB_CSRL0_RXRDYC; + _dcd.pipe0.rxrdy_consumed = false; } break; } @@ -432,6 +447,7 @@ static bool edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_ case PIPE0_STATE_STATUS_IN: TU_ASSERT(dir_in && total_bytes == 0); // only STATUS IN allowed ep_csr->csr0l = MUSB_CSRL0_RXRDYC | MUSB_CSRL0_DATAEND; + _dcd.pipe0.rxrdy_consumed = false; break; case PIPE0_STATE_STATUS_OUT: @@ -465,6 +481,7 @@ static void process_ep0(uint8_t rhport) { ep_csr->csr0l = 0; _dcd.pipe0.state = PIPE0_STATE_IDLE; _dcd.pipe0.deferred_setup_valid = false; + _dcd.pipe0.rxrdy_consumed = false; return; } @@ -474,6 +491,7 @@ static void process_ep0(uint8_t rhport) { ep_csr->csr0l = MUSB_CSRL0_SETENDC; _dcd.pipe0.state = PIPE0_STATE_IDLE; _dcd.pipe0.deferred_setup_valid = false; + _dcd.pipe0.rxrdy_consumed = false; if (!(csrl & MUSB_CSRL0_RXRDY)) { return; /* no SETUP waiting behind it */ } @@ -481,6 +499,9 @@ static void process_ep0(uint8_t rhport) { // Receive Data (Setup or OUT) if (csrl & MUSB_CSRL0_RXRDY) { + if (_dcd.pipe0.rxrdy_consumed) { + return; // stale latched IRQ: this RXRDY's packet was already drained + } switch (_dcd.pipe0.state) { case PIPE0_STATE_IDLE: { tusb_control_request_t req; @@ -498,8 +519,10 @@ static void process_ep0(uint8_t rhport) { tu_hwfifo_read(&musb_regs->fifo[0], _dcd.pipe0.buf, count0, NULL); _dcd.pipe0.remain_wlength -= count0; } + // RXRDY stays set until the next edpt0_xfer arm acks it (NAK flow control): + // edpt0_xfer(DATA OUT) for a mid-stream packet, edpt0_xfer(STATUS IN) for the last. + _dcd.pipe0.rxrdy_consumed = true; if (_dcd.pipe0.remain_wlength == 0) { - // last packet: change state and leave RXRDY for edpt0_xfer(STATUS IN) to ack _dcd.pipe0.state = PIPE0_STATE_STATUS_IN; } dcd_event_xfer_complete(rhport, TU_EP0_OUT, count0, XFER_RESULT_SUCCESS, true); @@ -511,7 +534,8 @@ static void process_ep0(uint8_t rhport) { // - Status IN/OUT finished, its IRQ and the new SETUP IRQ arrive at the same time. // - Data IN finished and status OUT is received, both IRQs and the new SETUP IRQ arrive at the same time. // Save the SETUP; it is replayed only once the old transfer is fully retired — i.e. when usbd has - // made (or already made) its final edpt0_xfer() call for it. + // made (or already made) its final edpt0_xfer() call for it. Until the replayed + // packet is acked, its RXRDY stays parked so a stale latched EP0 IRQ cannot re-process it. case PIPE0_STATE_DATA_IN: case PIPE0_STATE_STATUS_OUT: case PIPE0_STATE_STATUS_OUT_PENDING_XFER: @@ -519,6 +543,7 @@ static void process_ep0(uint8_t rhport) { case PIPE0_STATE_STATUS_IN: { TU_VERIFY(pipe0_read_setup(musb_regs, ep_csr, &_dcd.pipe0.deferred_setup), ); _dcd.pipe0.deferred_setup_valid = true; + _dcd.pipe0.rxrdy_consumed = true; switch (_dcd.pipe0.state) { case PIPE0_STATE_DATA_IN: @@ -549,7 +574,8 @@ static void process_ep0(uint8_t rhport) { break; default: - // PIPE0_STATE_STATUS_IN: ZLP-sent IRQ coalesced with the SETUP. + // PIPE0_STATE_STATUS_IN: rxrdy_consumed gate + SetupEnd guarantee DATAEND was armed, i.e. + // usbd already made its status call; the ZLP-sent IRQ coalesced with the SETUP. if (_dcd.pipe0.pending_addr) { musb_regs->faddr = _dcd.pipe0.pending_addr; _dcd.pipe0.pending_addr = 0; @@ -633,6 +659,7 @@ static void process_bus_reset(uint8_t rhport) { _dcd.pipe0.xact_len = 0; _dcd.pipe0.remain_wlength = 0; _dcd.pipe0.deferred_setup_valid = false; + _dcd.pipe0.rxrdy_consumed = false; musb->intr_txen = 1; /* Enable only EP0 */ musb->intr_rxen = 0; @@ -708,6 +735,7 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) _dcd.pipe0.state = PIPE0_STATE_STATUS_IN; /* Send STATUS IN ZLP with DATAEND; host ACK fires the confirmation IRQ. */ ep_csr->csr0l = MUSB_CSRL0_RXRDYC | MUSB_CSRL0_DATAEND; + _dcd.pipe0.rxrdy_consumed = false; } // Wake up host -- cgit v1.3.1 From e47eabd49d1838dc2a4eb42b9bd167a1d24d7cf5 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 13 Jun 2026 00:22:28 +0700 Subject: dcd/musb: replay deferred SETUP instead of stalling EP0 dcd_edpt_stall(EP0 OUT) discarded the deferred SETUP and armed SendStall. A deferred SETUP can only exist once the old transfer's status stage was seen on the wire, so the request usbd is rejecting (class callback failing at CONTROL_STAGE_DATA) already succeeded host-side and the hardware already ACKed the next SETUP - the STALL would land on that innocent request, which then fails host-side without any tud callback ever seeing it. Skip the stall and replay the deferred SETUP; the rejected transfer needs no wire-level stall since it is already over. Review follow-up for #3643 (dcd_musb.c l.860 finding). Co-Authored-By: Claude Fable 5 --- src/portable/mentor/musb/dcd_musb.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'src/portable') diff --git a/src/portable/mentor/musb/dcd_musb.c b/src/portable/mentor/musb/dcd_musb.c index 0485c4374..15928ec24 100644 --- a/src/portable/mentor/musb/dcd_musb.c +++ b/src/portable/mentor/musb/dcd_musb.c @@ -534,7 +534,7 @@ static void process_ep0(uint8_t rhport) { // - Status IN/OUT finished, its IRQ and the new SETUP IRQ arrive at the same time. // - Data IN finished and status OUT is received, both IRQs and the new SETUP IRQ arrive at the same time. // Save the SETUP; it is replayed only once the old transfer is fully retired — i.e. when usbd has - // made (or already made) its final edpt0_xfer() call for it. Until the replayed + // made (or already made) its final edpt0_xfer()/dcd_edpt_stall() call for it. Until the replayed // packet is acked, its RXRDY stays parked so a stale latched EP0 IRQ cannot re-process it. case PIPE0_STATE_DATA_IN: case PIPE0_STATE_STATUS_OUT: @@ -935,11 +935,17 @@ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, epn); if (0 == epn) { - if (ep_addr == TU_EP0_OUT) { /* Ignore EP0 OUT */ + if (ep_addr == TU_EP0_OUT) { /* Ignore EP0 IN */ _dcd.pipe0.state = PIPE0_STATE_IDLE; _dcd.pipe0.buf = NULL; - _dcd.pipe0.deferred_setup_valid = false; - ep_csr->csr0l = MUSB_CSRL0_STALL; + if (_dcd.pipe0.deferred_setup_valid) { + // The transfer being stalled already completed on the wire (a deferred SETUP can only exist + // once its status stage was seen) and the host's next request was already ACKed — SendStall + // would land on that innocent request. Skip the stall and replay the deferred SETUP instead. + pipe0_process_deferred_setup(rhport, ep_csr, false); + } else { + ep_csr->csr0l = MUSB_CSRL0_STALL; + } } } else { const tusb_dir_t ep_dir = tu_edpt_dir(ep_addr); -- cgit v1.3.1 From c8c63c30617d23bb604affcad423acbb11f8d10d Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 13 Jun 2026 23:26:23 +0700 Subject: dcd/musb: clear rxrdy_consumed when stalling EP0 The actual-STALL path (no deferred SETUP) forced EP0 to IDLE but left rxrdy_consumed set if the aborted transfer had parked RXRDY via NAK flow control (e.g. a rejected OUT-data request in DATA_OUT). A subsequent SETUP IRQ would then hit the parked-gate early return and be ignored, relying on SentStall/SetupEnd to clear the flag first. Clear it here so recovery never depends on that ordering. Addresses Copilot review on #3699. Co-Authored-By: Claude Fable 5 --- src/portable/mentor/musb/dcd_musb.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/portable') diff --git a/src/portable/mentor/musb/dcd_musb.c b/src/portable/mentor/musb/dcd_musb.c index 15928ec24..5f0ac4546 100644 --- a/src/portable/mentor/musb/dcd_musb.c +++ b/src/portable/mentor/musb/dcd_musb.c @@ -944,6 +944,9 @@ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { // would land on that innocent request. Skip the stall and replay the deferred SETUP instead. pipe0_process_deferred_setup(rhport, ep_csr, false); } else { + // Forcing EP0 to IDLE: any RXRDY parked by the aborted transfer's flow control is stale, + // clear it so the next SETUP IRQ is not gated off. + _dcd.pipe0.rxrdy_consumed = false; ep_csr->csr0l = MUSB_CSRL0_STALL; } } -- cgit v1.3.1 From 3bdf52fc1ba06eb96ca28e9c3656b0d6a59cd201 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 15 Jun 2026 14:53:33 +0700 Subject: dcd/musb: name pipe0_state_t, use local pointer, group struct fields MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pure cleanup, no behavior change: - Extract the EP0 control-transfer state into a named pipe0_state_t typedef instead of an anonymous nested struct, and access it through a local pipe0_state_t* in the functions that touch it repeatedly. - Group the pipe0 fields so the two bools sit together and the larger tusb_control_request_t deferred_setup is last. - Reword the deferral comments: "coalesced" -> "combined". Note: separating the edpt0_xfer DATA_IN/DATA_OUT case (dispatch on state instead of dir_in) was attempted and reverted — it breaks ADI MUSB enumeration. usbd can arm the opposite-direction status while pipe0 is still in a DATA state, and only dir-dispatch routes that correctly; a comment on the combined case records this. Verified: HIL pass on ek_tm4c123gxl and max32666fthr (13/13 each). Co-Authored-By: Claude Fable 5 --- src/portable/mentor/musb/dcd_musb.c | 197 +++++++++++++++++++----------------- 1 file changed, 105 insertions(+), 92 deletions(-) (limited to 'src/portable') diff --git a/src/portable/mentor/musb/dcd_musb.c b/src/portable/mentor/musb/dcd_musb.c index 5f0ac4546..f52ac10e3 100644 --- a/src/portable/mentor/musb/dcd_musb.c +++ b/src/portable/mentor/musb/dcd_musb.c @@ -90,18 +90,21 @@ enum { PIPE0_STATE_STATUS_OUT_PENDING_IRQ, // confirmation IRQ seen (or synthesized) first; edpt0_xfer(STATUS OUT) fires xfer_complete }; +// EP0 control-transfer state (own scalars, not a pipe[] slot). typedef struct { - struct { - uint8_t *buf; // DATA OUT drain target (only valid while EP0 is in DATA OUT stage) - uint16_t xact_len; // chunk length most recently armed via edpt0_xfer; reported in xfer_complete - uint16_t remain_wlength; // bytes remaining in the control transfer's DATA stage - uint8_t state; - uint8_t pending_addr; // new USB address latched by dcd_set_address; applied when STATUS IN completes - tusb_control_request_t deferred_setup; - bool deferred_setup_valid; - bool rxrdy_consumed; // RxPktRdy left set in hw for an already-consumed packet (NAK flow control); - // RXRDY events are stale while set. Cleared when RXRDYC is written. - } pipe0; + uint8_t *buf; // DATA OUT drain target (only valid while EP0 is in DATA OUT stage) + uint16_t xact_len; // chunk length most recently armed via edpt0_xfer; reported in xfer_complete + uint16_t remain_wlength; // bytes remaining in the control transfer's DATA stage + uint8_t state; + uint8_t pending_addr; // new USB address latched by dcd_set_address; applied when STATUS IN completes + bool rxrdy_consumed; // RxPktRdy left set in hw for an already-consumed packet (NAK flow control); + // RXRDY events are stale while set. Cleared when RXRDYC is written. + bool deferred_setup_valid; + tusb_control_request_t deferred_setup; +} pipe0_state_t; + +typedef struct { + pipe0_state_t pipe0; pipe_state_t pipe[MUSB_PIPE_COUNT]; } dcd_data_t; @@ -122,26 +125,27 @@ static bool pipe0_read_setup(musb_regs_t* musb_regs, musb_ep_csr_t* ep_csr, tusb static void pipe0_start_setup(uint8_t rhport, musb_ep_csr_t* ep_csr, tusb_control_request_t const* req, bool is_isr) { - _dcd.pipe0.remain_wlength = req->wLength; + pipe0_state_t* pipe0 = &_dcd.pipe0; + pipe0->remain_wlength = req->wLength; if (req->wLength == 0) { // Leave RXRDY set; edpt0_xfer(STATUS IN) acks it together with DATAEND. - _dcd.pipe0.state = PIPE0_STATE_STATUS_IN; - _dcd.pipe0.rxrdy_consumed = true; + pipe0->state = PIPE0_STATE_STATUS_IN; + pipe0->rxrdy_consumed = true; } else { if (req->bmRequestType & TUSB_DIR_IN_MASK) { - _dcd.pipe0.state = PIPE0_STATE_DATA_IN; + pipe0->state = PIPE0_STATE_DATA_IN; // On a deferred replay the packet's RXRDY stays parked until the edpt0_xfer(DATA IN) arm // acks it — a stale latched EP0 IRQ in between is gated by rxrdy_consumed. - if (!_dcd.pipe0.rxrdy_consumed) { + if (!pipe0->rxrdy_consumed) { ep_csr->csr0l = MUSB_CSRL0_RXRDYC; } } else { // If OUT (rx) direction, let edpt0_xfer() clear RXRDY when it's ready to receive data. // Deliberate deviation from the databook's canonical flow (ack right after unload), // used as NAK flow control until usbd arms the drain buffer. - _dcd.pipe0.state = PIPE0_STATE_DATA_OUT; - _dcd.pipe0.rxrdy_consumed = true; + pipe0->state = PIPE0_STATE_DATA_OUT; + pipe0->rxrdy_consumed = true; } } @@ -149,12 +153,13 @@ static void pipe0_start_setup(uint8_t rhport, musb_ep_csr_t* ep_csr, } static void pipe0_process_deferred_setup(uint8_t rhport, musb_ep_csr_t* ep_csr, bool is_isr) { - if (!_dcd.pipe0.deferred_setup_valid) { + pipe0_state_t* pipe0 = &_dcd.pipe0; + if (!pipe0->deferred_setup_valid) { return; } - _dcd.pipe0.deferred_setup_valid = false; - pipe0_start_setup(rhport, ep_csr, &_dcd.pipe0.deferred_setup, is_isr); + pipe0->deferred_setup_valid = false; + pipe0_start_setup(rhport, ep_csr, &pipe0->deferred_setup, is_isr); } // EP0 must not call this — it has its own scalars in dcd_data_t. @@ -414,32 +419,36 @@ static bool edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_ TU_ASSERT(total_bytes <= CFG_TUD_ENDPOINT0_SIZE); /* EP0 only supports 1 packet per dcd_edpt_xfer()*/ musb_regs_t* musb_regs = MUSB_REGS(rhport); musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, 0); + pipe0_state_t* pipe0 = &_dcd.pipe0; const unsigned dir_in = tu_edpt_dir(ep_addr); - switch (_dcd.pipe0.state) { + switch (pipe0->state) { + // Combined: usbd can arm the opposite-direction status/ZLP while pipe0 is still in a DATA + // state, so dispatch on the call direction (dir_in), not the state. (Splitting into separate + // DATA_IN/DATA_OUT cases mis-routes those dir != state calls and breaks ADI MUSB.) case PIPE0_STATE_DATA_IN: case PIPE0_STATE_DATA_OUT: { - _dcd.pipe0.xact_len = total_bytes; + pipe0->xact_len = total_bytes; if (dir_in) { // Replayed SETUP keeps its RXRDY parked until here; ack it before loading the shared FIFO. - if (_dcd.pipe0.rxrdy_consumed) { + if (pipe0->rxrdy_consumed) { ep_csr->csr0l = MUSB_CSRL0_RXRDYC; - _dcd.pipe0.rxrdy_consumed = false; + pipe0->rxrdy_consumed = false; } // DATA IN: load FIFO, set TXRDY. Add DATAEND on the last chunk - // (ep0_remain_datalen == 0 after this load) to end the data stage. + // (remain_wlength == 0 after this load) to end the data stage. tu_hwfifo_write(&musb_regs->fifo[0], buffer, total_bytes, NULL); - _dcd.pipe0.remain_wlength -= total_bytes; - if (_dcd.pipe0.remain_wlength == 0) { + pipe0->remain_wlength -= total_bytes; + if (pipe0->remain_wlength == 0) { ep_csr->csr0l = MUSB_CSRL0_TXRDY | MUSB_CSRL0_DATAEND; } else { ep_csr->csr0l = MUSB_CSRL0_TXRDY; } } else { // DATA OUT: arm drain target, ack RXRDY so host can send DATA OUT. - _dcd.pipe0.buf = buffer; + pipe0->buf = buffer; ep_csr->csr0l = MUSB_CSRL0_RXRDYC; - _dcd.pipe0.rxrdy_consumed = false; + pipe0->rxrdy_consumed = false; } break; } @@ -447,19 +456,19 @@ static bool edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_ case PIPE0_STATE_STATUS_IN: TU_ASSERT(dir_in && total_bytes == 0); // only STATUS IN allowed ep_csr->csr0l = MUSB_CSRL0_RXRDYC | MUSB_CSRL0_DATAEND; - _dcd.pipe0.rxrdy_consumed = false; + pipe0->rxrdy_consumed = false; break; case PIPE0_STATE_STATUS_OUT: TU_ASSERT(!dir_in && total_bytes == 0); // only STATUS OUT allowed // First event of the STATUS OUT pair — wait for the IRQ to fire complete. - _dcd.pipe0.state = PIPE0_STATE_STATUS_OUT_PENDING_XFER; + pipe0->state = PIPE0_STATE_STATUS_OUT_PENDING_XFER; break; case PIPE0_STATE_STATUS_OUT_PENDING_IRQ: // Second event — IRQ already arrived, fire complete now. The old transfer is retired here, // so a deferred SETUP can be replayed safely. - _dcd.pipe0.state = PIPE0_STATE_IDLE; + pipe0->state = PIPE0_STATE_IDLE; dcd_event_xfer_complete(rhport, ep_addr, 0, XFER_RESULT_SUCCESS, is_isr); pipe0_process_deferred_setup(rhport, ep_csr, is_isr); break; @@ -474,14 +483,15 @@ static bool edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_ static void process_ep0(uint8_t rhport) { musb_regs_t* musb_regs = MUSB_REGS(rhport); musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, 0); + pipe0_state_t* pipe0 = &_dcd.pipe0; uint_fast8_t csrl = ep_csr->csr0l; // 21.1.5: SentStall and SetupEnd must be checked before anything else. if (csrl & MUSB_CSRL0_STALLED) { ep_csr->csr0l = 0; - _dcd.pipe0.state = PIPE0_STATE_IDLE; - _dcd.pipe0.deferred_setup_valid = false; - _dcd.pipe0.rxrdy_consumed = false; + pipe0->state = PIPE0_STATE_IDLE; + pipe0->deferred_setup_valid = false; + pipe0->rxrdy_consumed = false; return; } @@ -489,9 +499,9 @@ static void process_ep0(uint8_t rhport) { // Host aborted the current control transfer (new SETUP or premature STATUS). // do nothing, it is probably another setup packet, usbd will reset its state. ep_csr->csr0l = MUSB_CSRL0_SETENDC; - _dcd.pipe0.state = PIPE0_STATE_IDLE; - _dcd.pipe0.deferred_setup_valid = false; - _dcd.pipe0.rxrdy_consumed = false; + pipe0->state = PIPE0_STATE_IDLE; + pipe0->deferred_setup_valid = false; + pipe0->rxrdy_consumed = false; if (!(csrl & MUSB_CSRL0_RXRDY)) { return; /* no SETUP waiting behind it */ } @@ -499,10 +509,10 @@ static void process_ep0(uint8_t rhport) { // Receive Data (Setup or OUT) if (csrl & MUSB_CSRL0_RXRDY) { - if (_dcd.pipe0.rxrdy_consumed) { + if (pipe0->rxrdy_consumed) { return; // stale latched IRQ: this RXRDY's packet was already drained } - switch (_dcd.pipe0.state) { + switch (pipe0->state) { case PIPE0_STATE_IDLE: { tusb_control_request_t req; TU_VERIFY(pipe0_read_setup(musb_regs, ep_csr, &req), ); @@ -515,22 +525,22 @@ static void process_ep0(uint8_t rhport) { // so the whole packet drains in one shot. const uint16_t count0 = ep_csr->count0; if (count0) { - TU_ASSERT(_dcd.pipe0.buf, ); - tu_hwfifo_read(&musb_regs->fifo[0], _dcd.pipe0.buf, count0, NULL); - _dcd.pipe0.remain_wlength -= count0; + TU_ASSERT(pipe0->buf, ); + tu_hwfifo_read(&musb_regs->fifo[0], pipe0->buf, count0, NULL); + pipe0->remain_wlength -= count0; } // RXRDY stays set until the next edpt0_xfer arm acks it (NAK flow control): // edpt0_xfer(DATA OUT) for a mid-stream packet, edpt0_xfer(STATUS IN) for the last. - _dcd.pipe0.rxrdy_consumed = true; - if (_dcd.pipe0.remain_wlength == 0) { - _dcd.pipe0.state = PIPE0_STATE_STATUS_IN; + pipe0->rxrdy_consumed = true; + if (pipe0->remain_wlength == 0) { + pipe0->state = PIPE0_STATE_STATUS_IN; } dcd_event_xfer_complete(rhport, TU_EP0_OUT, count0, XFER_RESULT_SUCCESS, true); break; } // New SETUP packet arrived while the old control transfer's tail events are still in flight - // (IRQs coalesced under high CPU load), e.g.: + // (IRQs combined under high CPU load), e.g.: // - Status IN/OUT finished, its IRQ and the new SETUP IRQ arrive at the same time. // - Data IN finished and status OUT is received, both IRQs and the new SETUP IRQ arrive at the same time. // Save the SETUP; it is replayed only once the old transfer is fully retired — i.e. when usbd has @@ -541,28 +551,28 @@ static void process_ep0(uint8_t rhport) { case PIPE0_STATE_STATUS_OUT_PENDING_XFER: case PIPE0_STATE_STATUS_OUT_PENDING_IRQ: case PIPE0_STATE_STATUS_IN: { - TU_VERIFY(pipe0_read_setup(musb_regs, ep_csr, &_dcd.pipe0.deferred_setup), ); - _dcd.pipe0.deferred_setup_valid = true; - _dcd.pipe0.rxrdy_consumed = true; + TU_VERIFY(pipe0_read_setup(musb_regs, ep_csr, &pipe0->deferred_setup), ); + pipe0->deferred_setup_valid = true; + pipe0->rxrdy_consumed = true; - switch (_dcd.pipe0.state) { + switch (pipe0->state) { case PIPE0_STATE_DATA_IN: - // Coalesced: last DATA IN sent + status OUT done + new SETUP in one csrl read. Fire the + // Combined: last DATA IN sent + status OUT done + new SETUP in one csrl read. Fire the // DATA IN completion and synthesize the missed status confirm; usbd's edpt0_xfer(STATUS OUT) // fires the status completion and replays. - TU_ASSERT(_dcd.pipe0.remain_wlength == 0, ); - _dcd.pipe0.state = PIPE0_STATE_STATUS_OUT_PENDING_IRQ; - dcd_event_xfer_complete(rhport, TU_EP0_IN, _dcd.pipe0.xact_len, XFER_RESULT_SUCCESS, true); + TU_ASSERT(pipe0->remain_wlength == 0, ); + pipe0->state = PIPE0_STATE_STATUS_OUT_PENDING_IRQ; + dcd_event_xfer_complete(rhport, TU_EP0_IN, pipe0->xact_len, XFER_RESULT_SUCCESS, true); break; case PIPE0_STATE_STATUS_OUT: - // Status confirm IRQ coalesced with the SETUP — edpt0_xfer(STATUS OUT) fires complete. - _dcd.pipe0.state = PIPE0_STATE_STATUS_OUT_PENDING_IRQ; + // Status confirm IRQ combined with the SETUP — edpt0_xfer(STATUS OUT) fires complete. + pipe0->state = PIPE0_STATE_STATUS_OUT_PENDING_IRQ; break; case PIPE0_STATE_STATUS_OUT_PENDING_XFER: // edpt0_xfer(STATUS OUT) already called — old transfer retired, complete and replay now. - _dcd.pipe0.state = PIPE0_STATE_IDLE; + pipe0->state = PIPE0_STATE_IDLE; dcd_event_xfer_complete(rhport, TU_EP0_OUT, 0, XFER_RESULT_SUCCESS, true); pipe0_process_deferred_setup(rhport, ep_csr, true); break; @@ -575,12 +585,12 @@ static void process_ep0(uint8_t rhport) { default: // PIPE0_STATE_STATUS_IN: rxrdy_consumed gate + SetupEnd guarantee DATAEND was armed, i.e. - // usbd already made its status call; the ZLP-sent IRQ coalesced with the SETUP. - if (_dcd.pipe0.pending_addr) { - musb_regs->faddr = _dcd.pipe0.pending_addr; - _dcd.pipe0.pending_addr = 0; + // usbd already made its status call; the ZLP-sent IRQ combined with the SETUP. + if (pipe0->pending_addr) { + musb_regs->faddr = pipe0->pending_addr; + pipe0->pending_addr = 0; } - _dcd.pipe0.state = PIPE0_STATE_IDLE; + pipe0->state = PIPE0_STATE_IDLE; dcd_event_xfer_complete(rhport, TU_EP0_IN, 0, XFER_RESULT_SUCCESS, true); pipe0_process_deferred_setup(rhport, ep_csr, true); break; @@ -604,25 +614,25 @@ static void process_ep0(uint8_t rhport) { /* When CSRL0 is zero, it means that either * - completion of sending any length packet TxPktRdy clear * - or status stage is complete (ZLP) after DataEnd is set */ - switch (_dcd.pipe0.state) { + switch (pipe0->state) { case PIPE0_STATE_DATA_IN: - // csrl == 0 in DATA state = TXRDY just cleared, i.e. a DATA IN packet was successfully sent. If the just-sent - // packet was the last (DATAEND was set when ep0_remain_datalen hit zero), transition - // to STATUS_OUT to await the host's STATUS-OUT ZLP confirmation IRQ. - if (_dcd.pipe0.remain_wlength == 0) { - _dcd.pipe0.state = PIPE0_STATE_STATUS_OUT; + // csrl == 0 in DATA IN = TXRDY just cleared, i.e. a DATA IN packet was successfully sent. If the + // just-sent packet was the last (DATAEND set when remain_wlength hit 0), transition to STATUS_OUT + // to await the host's STATUS-OUT ZLP confirmation IRQ. + if (pipe0->remain_wlength == 0) { + pipe0->state = PIPE0_STATE_STATUS_OUT; } - dcd_event_xfer_complete(rhport, TU_EP0_IN, _dcd.pipe0.xact_len, XFER_RESULT_SUCCESS, true); + dcd_event_xfer_complete(rhport, TU_EP0_IN, pipe0->xact_len, XFER_RESULT_SUCCESS, true); break; case PIPE0_STATE_STATUS_OUT: // First event of the STATUS OUT pair — wait for edpt0_xfer(STATUS OUT) to fire complete. - _dcd.pipe0.state = PIPE0_STATE_STATUS_OUT_PENDING_IRQ; + pipe0->state = PIPE0_STATE_STATUS_OUT_PENDING_IRQ; break; case PIPE0_STATE_STATUS_OUT_PENDING_XFER: // Second event — edpt0_xfer(STATUS OUT) already called, fire complete now. - _dcd.pipe0.state = PIPE0_STATE_IDLE; + pipe0->state = PIPE0_STATE_IDLE; dcd_event_xfer_complete(rhport, TU_EP0_OUT, 0, XFER_RESULT_SUCCESS, true); pipe0_process_deferred_setup(rhport, ep_csr, true); break; @@ -632,11 +642,11 @@ static void process_ep0(uint8_t rhport) { break; case PIPE0_STATE_STATUS_IN: - if (_dcd.pipe0.pending_addr) { - musb_regs->faddr = _dcd.pipe0.pending_addr; - _dcd.pipe0.pending_addr = 0; + if (pipe0->pending_addr) { + musb_regs->faddr = pipe0->pending_addr; + pipe0->pending_addr = 0; } - _dcd.pipe0.state = PIPE0_STATE_IDLE; + pipe0->state = PIPE0_STATE_IDLE; dcd_event_xfer_complete(rhport, TU_EP0_IN, 0, XFER_RESULT_SUCCESS, true); pipe0_process_deferred_setup(rhport, ep_csr, true); break; @@ -654,12 +664,13 @@ static void process_bus_reset(uint8_t rhport) { alloced_fifo_bytes = CFG_TUD_ENDPOINT0_SIZE; #endif - _dcd.pipe0.state = PIPE0_STATE_IDLE; - _dcd.pipe0.buf = NULL; - _dcd.pipe0.xact_len = 0; - _dcd.pipe0.remain_wlength = 0; - _dcd.pipe0.deferred_setup_valid = false; - _dcd.pipe0.rxrdy_consumed = false; + pipe0_state_t* pipe0 = &_dcd.pipe0; + pipe0->state = PIPE0_STATE_IDLE; + pipe0->buf = NULL; + pipe0->xact_len = 0; + pipe0->remain_wlength = 0; + pipe0->deferred_setup_valid = false; + pipe0->rxrdy_consumed = false; musb->intr_txen = 1; /* Enable only EP0 */ musb->intr_rxen = 0; @@ -729,13 +740,14 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) musb_regs_t* musb_regs = MUSB_REGS(rhport); musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, 0); - _dcd.pipe0.pending_addr = dev_addr; - _dcd.pipe0.buf = NULL; - _dcd.pipe0.xact_len = 0; - _dcd.pipe0.state = PIPE0_STATE_STATUS_IN; + pipe0_state_t* pipe0 = &_dcd.pipe0; + pipe0->pending_addr = dev_addr; + pipe0->buf = NULL; + pipe0->xact_len = 0; + pipe0->state = PIPE0_STATE_STATUS_IN; /* Send STATUS IN ZLP with DATAEND; host ACK fires the confirmation IRQ. */ ep_csr->csr0l = MUSB_CSRL0_RXRDYC | MUSB_CSRL0_DATAEND; - _dcd.pipe0.rxrdy_consumed = false; + pipe0->rxrdy_consumed = false; } // Wake up host @@ -936,9 +948,10 @@ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { if (0 == epn) { if (ep_addr == TU_EP0_OUT) { /* Ignore EP0 IN */ - _dcd.pipe0.state = PIPE0_STATE_IDLE; - _dcd.pipe0.buf = NULL; - if (_dcd.pipe0.deferred_setup_valid) { + pipe0_state_t* pipe0 = &_dcd.pipe0; + pipe0->state = PIPE0_STATE_IDLE; + pipe0->buf = NULL; + if (pipe0->deferred_setup_valid) { // The transfer being stalled already completed on the wire (a deferred SETUP can only exist // once its status stage was seen) and the host's next request was already ACKed — SendStall // would land on that innocent request. Skip the stall and replay the deferred SETUP instead. @@ -946,7 +959,7 @@ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { } else { // Forcing EP0 to IDLE: any RXRDY parked by the aborted transfer's flow control is stale, // clear it so the next SETUP IRQ is not gated off. - _dcd.pipe0.rxrdy_consumed = false; + pipe0->rxrdy_consumed = false; ep_csr->csr0l = MUSB_CSRL0_STALL; } } -- cgit v1.3.1 From abc3114d53aee421a0a457ece561ac000ace2c67 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 15 Jun 2026 16:42:10 +0700 Subject: dcd/musb: end EP0 IN data stage on short packet, split DATA case MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A short IN control response (device sends fewer bytes than wLength — e.g. the 18-byte device descriptor answering a 64-byte GET_DESCRIPTOR) left remain_wlength != 0, so the DATA_IN -> STATUS_OUT transition never fired and pipe0 stayed in DATA_IN through the status stage. usbd then armed the status-OUT while state was still DATA_IN. Set DATAEND and transition on the last packet: remain_wlength == 0, or a short packet (incl. a terminating ZLP) which ends the data stage. With state now tracking the stage, split edpt0_xfer's DATA handling into separate DATA_IN / DATA_OUT cases dispatching on state (asserting state == call direction) instead of the combined dir_in branch. Verified: HIL pass on ek_tm4c123gxl and max32666fthr (13/13 each), including the #3643 high-CPU-load IRQ-toggle coalescing stress. Co-Authored-By: Claude Fable 5 --- src/portable/mentor/musb/dcd_musb.c | 49 +++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 27 deletions(-) (limited to 'src/portable') diff --git a/src/portable/mentor/musb/dcd_musb.c b/src/portable/mentor/musb/dcd_musb.c index f52ac10e3..261ff64e8 100644 --- a/src/portable/mentor/musb/dcd_musb.c +++ b/src/portable/mentor/musb/dcd_musb.c @@ -423,35 +423,31 @@ static bool edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_ const unsigned dir_in = tu_edpt_dir(ep_addr); switch (pipe0->state) { - // Combined: usbd can arm the opposite-direction status/ZLP while pipe0 is still in a DATA - // state, so dispatch on the call direction (dir_in), not the state. (Splitting into separate - // DATA_IN/DATA_OUT cases mis-routes those dir != state calls and breaks ADI MUSB.) + // DATA stage exits on its last packet, so state matches the call direction here. case PIPE0_STATE_DATA_IN: - case PIPE0_STATE_DATA_OUT: { + TU_ASSERT(dir_in); pipe0->xact_len = total_bytes; - if (dir_in) { - // Replayed SETUP keeps its RXRDY parked until here; ack it before loading the shared FIFO. - if (pipe0->rxrdy_consumed) { - ep_csr->csr0l = MUSB_CSRL0_RXRDYC; - pipe0->rxrdy_consumed = false; - } - // DATA IN: load FIFO, set TXRDY. Add DATAEND on the last chunk - // (remain_wlength == 0 after this load) to end the data stage. - tu_hwfifo_write(&musb_regs->fifo[0], buffer, total_bytes, NULL); - pipe0->remain_wlength -= total_bytes; - if (pipe0->remain_wlength == 0) { - ep_csr->csr0l = MUSB_CSRL0_TXRDY | MUSB_CSRL0_DATAEND; - } else { - ep_csr->csr0l = MUSB_CSRL0_TXRDY; - } - } else { - // DATA OUT: arm drain target, ack RXRDY so host can send DATA OUT. - pipe0->buf = buffer; + if (pipe0->rxrdy_consumed) { // replayed SETUP: ack its parked RXRDY before loading the FIFO ep_csr->csr0l = MUSB_CSRL0_RXRDYC; pipe0->rxrdy_consumed = false; } + tu_hwfifo_write(&musb_regs->fifo[0], buffer, total_bytes, NULL); + pipe0->remain_wlength -= total_bytes; + // DATAEND on the last packet: wLength met, or a short packet (incl. ZLP) ends the data stage. + if (pipe0->remain_wlength == 0 || total_bytes < CFG_TUD_ENDPOINT0_SIZE) { + ep_csr->csr0l = MUSB_CSRL0_TXRDY | MUSB_CSRL0_DATAEND; + } else { + ep_csr->csr0l = MUSB_CSRL0_TXRDY; + } + break; + + case PIPE0_STATE_DATA_OUT: + TU_ASSERT(!dir_in); + pipe0->xact_len = total_bytes; + pipe0->buf = buffer; // arm drain target, ack RXRDY so host can send DATA OUT + ep_csr->csr0l = MUSB_CSRL0_RXRDYC; + pipe0->rxrdy_consumed = false; break; - } case PIPE0_STATE_STATUS_IN: TU_ASSERT(dir_in && total_bytes == 0); // only STATUS IN allowed @@ -616,10 +612,9 @@ static void process_ep0(uint8_t rhport) { * - or status stage is complete (ZLP) after DataEnd is set */ switch (pipe0->state) { case PIPE0_STATE_DATA_IN: - // csrl == 0 in DATA IN = TXRDY just cleared, i.e. a DATA IN packet was successfully sent. If the - // just-sent packet was the last (DATAEND set when remain_wlength hit 0), transition to STATUS_OUT - // to await the host's STATUS-OUT ZLP confirmation IRQ. - if (pipe0->remain_wlength == 0) { + // DATA IN packet sent (TXRDY cleared). On the last packet (DATAEND condition above) move to + // STATUS_OUT to await the host's STATUS-OUT ZLP IRQ. + if (pipe0->remain_wlength == 0 || pipe0->xact_len < CFG_TUD_ENDPOINT0_SIZE) { pipe0->state = PIPE0_STATE_STATUS_OUT; } dcd_event_xfer_complete(rhport, TU_EP0_IN, pipe0->xact_len, XFER_RESULT_SUCCESS, true); -- cgit v1.3.1 From 9562f54f95da485c17192b07a9b2cc21126c8ef1 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 15 Jun 2026 16:43:10 +0700 Subject: dcd/musb: suffix ISR-context process_* handlers with _isr Rename process_ep0/process_epin/process_epout/process_bus_reset (all invoked only from dcd_int_handler) to *_isr, making their ISR context explicit at every call site. pipe0_process_deferred_setup is left as-is since it also runs from task context (dcd_edpt_stall). Co-Authored-By: Claude Fable 5 --- src/portable/mentor/musb/dcd_musb.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'src/portable') diff --git a/src/portable/mentor/musb/dcd_musb.c b/src/portable/mentor/musb/dcd_musb.c index 261ff64e8..eb5f83e73 100644 --- a/src/portable/mentor/musb/dcd_musb.c +++ b/src/portable/mentor/musb/dcd_musb.c @@ -299,7 +299,7 @@ static void pipe_write(musb_regs_t* musb_regs, pipe_state_t* pipe, uint8_t epnum // Called from the TX interrupt. If the last queued packet finished the transfer, // signal completion; otherwise queue the next packet. -static void process_epin(uint8_t rhport, musb_regs_t *musb_regs, uint8_t epnum) { +static void process_epin_isr(uint8_t rhport, musb_regs_t *musb_regs, uint8_t epnum) { musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, epnum); const uint_fast8_t csrl = ep_csr->tx_csrl; if (csrl & MUSB_TXCSRL1_STALLED) { @@ -329,7 +329,7 @@ static void process_epin(uint8_t rhport, musb_regs_t *musb_regs, uint8_t epnum) // Drain one packet from the Rx FIFO into pipe->buf/fifo, update pipe state, and // release the FIFO slot by clearing RXRDY. return true if short packet static bool pipe_read(musb_regs_t* musb_regs, pipe_state_t* pipe, uint8_t epnum) { - musb_ep_csr_t* ep_csr = &musb_regs->indexed_csr; // index already set in process_epout() + musb_ep_csr_t* ep_csr = &musb_regs->indexed_csr; // index already set in process_epout_isr() const uint16_t mps = ep_csr->rx_maxp & MUSB_RXMAXP_PACKET_SIZE_M; const uint16_t rx_count = ep_csr->rx_count; const uint16_t xact_len = tu_min16(tu_min16(pipe->remaining, mps), rx_count); @@ -348,7 +348,7 @@ static bool pipe_read(musb_regs_t* musb_regs, pipe_state_t* pipe, uint8_t epnum) return (xact_len < mps); } -static void process_epout(uint8_t rhport, musb_regs_t *musb_regs, uint8_t epnum, bool is_isr) { +static void process_epout_isr(uint8_t rhport, musb_regs_t *musb_regs, uint8_t epnum, bool is_isr) { musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, epnum); if (ep_csr->rx_csrl & MUSB_RXCSRL1_STALLED) { ep_csr->rx_csrl &= ~(MUSB_RXCSRL1_STALLED | MUSB_RXCSRL1_OVER); @@ -403,13 +403,13 @@ static bool edpt_n_xfer(uint8_t rhport, uint8_t ep_addr, void *buffer, uint16_t if (dir_in) { pipe_write(musb_regs, pipe, epnum); } else { - // Re-enable Rx interrupt (may have been masked by the no-buffer path in process_epout) + // Re-enable Rx interrupt (may have been masked by the no-buffer path in process_epout_isr) musb_regs->intr_rxen |= (uint16_t)TU_BIT(epnum); // Drain any packet staged in the Rx FIFO from a prior no-buffer interrupt. - // process_epout() fires dcd_event_xfer_complete() itself if the drain completes. + // process_epout_isr() fires dcd_event_xfer_complete() itself if the drain completes. if (ep_csr->rx_csrl & MUSB_RXCSRL1_RXRDY) { - process_epout(rhport, musb_regs, epnum, is_isr); + process_epout_isr(rhport, musb_regs, epnum, is_isr); } } return true; @@ -476,7 +476,7 @@ static bool edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_ } // 21.1.5: endpoint 0 service routine as peripheral -static void process_ep0(uint8_t rhport) { +static void process_ep0_isr(uint8_t rhport) { musb_regs_t* musb_regs = MUSB_REGS(rhport); musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, 0); pipe0_state_t* pipe0 = &_dcd.pipe0; @@ -652,7 +652,7 @@ static void process_ep0(uint8_t rhport) { // Upon BUS RESET is detected, hardware havs already done: // faddr = 0, index = 0, flushes all ep fifos, clears all ep csr, enabled all ep interrupts -static void process_bus_reset(uint8_t rhport) { +static void process_bus_reset_isr(uint8_t rhport) { musb_regs_t* musb = MUSB_REGS(rhport); #if MUSB_CFG_DYNAMIC_FIFO @@ -728,7 +728,7 @@ void dcd_int_disable(uint8_t rhport) { } // Receive Set Address request. Stash the new address here; hardware faddr is -// latched from pending_addr in process_ep0 once the STATUS IN completes (per +// latched from pending_addr in process_ep0_isr once the STATUS IN completes (per // USB spec, address must only take effect after the status stage). void dcd_set_address(uint8_t rhport, uint8_t dev_addr) { @@ -1008,7 +1008,7 @@ void dcd_int_handler(uint8_t rhport) { dcd_event_bus_signal(rhport, DCD_EVENT_SOF, true); } if (intr_usb & MUSB_IS_RESET) { - process_bus_reset(rhport); + process_bus_reset_isr(rhport); } if (intr_usb & MUSB_IS_RESUME) { dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true); @@ -1022,9 +1022,9 @@ void dcd_int_handler(uint8_t rhport) { while (intr_tx) { const unsigned epnum = __builtin_ctz(intr_tx); if (epnum == 0) { - process_ep0(rhport); // EP0 has its own state machine (control transfers) + process_ep0_isr(rhport); // EP0 has its own state machine (control transfers) } else { - process_epin(rhport, musb_regs, epnum); + process_epin_isr(rhport, musb_regs, epnum); } intr_tx &= ~TU_BIT(epnum); @@ -1039,7 +1039,7 @@ void dcd_int_handler(uint8_t rhport) { intr_rx &= musb_regs->intr_rxen; /* Clear disabled interrupts */ while (intr_rx) { unsigned const epnum = __builtin_ctz(intr_rx); - process_epout(rhport, musb_regs, epnum, true); + process_epout_isr(rhport, musb_regs, epnum, true); intr_rx &= ~TU_BIT(epnum); // Double packet endpoint: RxPktRdy is set and interrupt is generated immediately if 2nd packet is received -- cgit v1.3.1 From d4eeaf10cb1a95b6b74e18cd933c6320d31c2031 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 15 Jun 2026 16:48:40 +0700 Subject: dcd/musb: extract pipe0_process_status_isr() to de-dup EP0 tail paths The deferral (RXRDY-combined) and csrl==0 tail paths in process_ep0_isr ran the same per-state status-stage logic. Move all of it into one pipe0_process_status_isr() helper covering every state including DATA_IN, which picks STATUS_OUT vs STATUS_OUT_PENDING_IRQ from deferred_setup_valid (a deferred SETUP means the status confirm was coalesced with it). Both callers now just invoke the helper; the deferral path saves the SETUP and sets deferred_setup_valid first. Also drops the deferral path's TU_ASSERT(remain_wlength == 0), which was wrong for a short last DATA-IN packet, and renames pipe0_process_deferred_setup -> pipe0_try_deferred_setup (it no-ops when nothing is deferred). Verified: HIL pass on ek_tm4c123gxl and max32666fthr (13/13 each), including the #3643 high-CPU-load IRQ-toggle coalescing stress. Co-Authored-By: Claude Fable 5 --- src/portable/mentor/musb/dcd_musb.c | 149 ++++++++++++++---------------------- 1 file changed, 58 insertions(+), 91 deletions(-) (limited to 'src/portable') diff --git a/src/portable/mentor/musb/dcd_musb.c b/src/portable/mentor/musb/dcd_musb.c index eb5f83e73..e769b08a5 100644 --- a/src/portable/mentor/musb/dcd_musb.c +++ b/src/portable/mentor/musb/dcd_musb.c @@ -152,7 +152,8 @@ static void pipe0_start_setup(uint8_t rhport, musb_ep_csr_t* ep_csr, dcd_event_setup_received(rhport, (const uint8_t *) req, is_isr); } -static void pipe0_process_deferred_setup(uint8_t rhport, musb_ep_csr_t* ep_csr, bool is_isr) { +// Replay a previously deferred SETUP, if any. +static void pipe0_try_deferred_setup(uint8_t rhport, musb_ep_csr_t* ep_csr, bool is_isr) { pipe0_state_t* pipe0 = &_dcd.pipe0; if (!pipe0->deferred_setup_valid) { return; @@ -466,7 +467,7 @@ static bool edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_ // so a deferred SETUP can be replayed safely. pipe0->state = PIPE0_STATE_IDLE; dcd_event_xfer_complete(rhport, ep_addr, 0, XFER_RESULT_SUCCESS, is_isr); - pipe0_process_deferred_setup(rhport, ep_csr, is_isr); + pipe0_try_deferred_setup(rhport, ep_csr, is_isr); break; default: break; @@ -475,6 +476,52 @@ static bool edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_ return true; } +// Advance EP0's status-stage state machine on a tail event: the csrl==0 confirmation IRQ, or such a +// confirmation combined with a new SETUP (caller sets deferred_setup_valid first). ISR context only. +static void pipe0_process_status_isr(uint8_t rhport, musb_regs_t* musb_regs, musb_ep_csr_t* ep_csr) { + pipe0_state_t* pipe0 = &_dcd.pipe0; + switch (pipe0->state) { + case PIPE0_STATE_DATA_IN: + if (pipe0->remain_wlength == 0 || pipe0->xact_len < CFG_TUD_ENDPOINT0_SIZE) { // last DATA IN packet + if (pipe0->deferred_setup_valid) { + pipe0->state = PIPE0_STATE_STATUS_OUT_PENDING_IRQ; // status confirm coalesced with deferred SETUP + } else { + pipe0->state = PIPE0_STATE_STATUS_OUT; // await host's STATUS-OUT ZLP IRQ + } + } + dcd_event_xfer_complete(rhport, TU_EP0_IN, pipe0->xact_len, XFER_RESULT_SUCCESS, true); + break; + + case PIPE0_STATE_STATUS_OUT: + // Confirmation seen — await edpt0_xfer(STATUS OUT) to fire complete. + pipe0->state = PIPE0_STATE_STATUS_OUT_PENDING_IRQ; + break; + + case PIPE0_STATE_STATUS_OUT_PENDING_XFER: + // edpt0_xfer(STATUS OUT) already called — fire complete and replay now. + pipe0->state = PIPE0_STATE_IDLE; + dcd_event_xfer_complete(rhport, TU_EP0_OUT, 0, XFER_RESULT_SUCCESS, true); + pipe0_try_deferred_setup(rhport, ep_csr, true); + break; + + case PIPE0_STATE_STATUS_OUT_PENDING_IRQ: + // Confirmation already accounted for — the pairing edpt0_xfer(STATUS OUT) fires complete. + break; + + case PIPE0_STATE_STATUS_IN: + if (pipe0->pending_addr) { + musb_regs->faddr = pipe0->pending_addr; + pipe0->pending_addr = 0; + } + pipe0->state = PIPE0_STATE_IDLE; + dcd_event_xfer_complete(rhport, TU_EP0_IN, 0, XFER_RESULT_SUCCESS, true); + pipe0_try_deferred_setup(rhport, ep_csr, true); + break; + + default: break; + } +} + // 21.1.5: endpoint 0 service routine as peripheral static void process_ep0_isr(uint8_t rhport) { musb_regs_t* musb_regs = MUSB_REGS(rhport); @@ -535,64 +582,21 @@ static void process_ep0_isr(uint8_t rhport) { break; } - // New SETUP packet arrived while the old control transfer's tail events are still in flight - // (IRQs combined under high CPU load), e.g.: - // - Status IN/OUT finished, its IRQ and the new SETUP IRQ arrive at the same time. - // - Data IN finished and status OUT is received, both IRQs and the new SETUP IRQ arrive at the same time. - // Save the SETUP; it is replayed only once the old transfer is fully retired — i.e. when usbd has - // made (or already made) its final edpt0_xfer()/dcd_edpt_stall() call for it. Until the replayed - // packet is acked, its RXRDY stays parked so a stale latched EP0 IRQ cannot re-process it. + // New SETUP arrived while the old control transfer's tail events are still in flight (IRQs + // combined under high CPU load): the old transfer's status confirm and this SETUP land together. case PIPE0_STATE_DATA_IN: case PIPE0_STATE_STATUS_OUT: case PIPE0_STATE_STATUS_OUT_PENDING_XFER: case PIPE0_STATE_STATUS_OUT_PENDING_IRQ: - case PIPE0_STATE_STATUS_IN: { + case PIPE0_STATE_STATUS_IN: + // Save it, then finish the old transfer's tail event; deferred_setup_valid makes + // pipe0_process_status_isr() synthesize the coalesced status confirm and replay the SETUP + // once the old transfer is retired. Its RXRDY stays parked so a stale IRQ can't re-process it. TU_VERIFY(pipe0_read_setup(musb_regs, ep_csr, &pipe0->deferred_setup), ); pipe0->deferred_setup_valid = true; pipe0->rxrdy_consumed = true; - - switch (pipe0->state) { - case PIPE0_STATE_DATA_IN: - // Combined: last DATA IN sent + status OUT done + new SETUP in one csrl read. Fire the - // DATA IN completion and synthesize the missed status confirm; usbd's edpt0_xfer(STATUS OUT) - // fires the status completion and replays. - TU_ASSERT(pipe0->remain_wlength == 0, ); - pipe0->state = PIPE0_STATE_STATUS_OUT_PENDING_IRQ; - dcd_event_xfer_complete(rhport, TU_EP0_IN, pipe0->xact_len, XFER_RESULT_SUCCESS, true); - break; - - case PIPE0_STATE_STATUS_OUT: - // Status confirm IRQ combined with the SETUP — edpt0_xfer(STATUS OUT) fires complete. - pipe0->state = PIPE0_STATE_STATUS_OUT_PENDING_IRQ; - break; - - case PIPE0_STATE_STATUS_OUT_PENDING_XFER: - // edpt0_xfer(STATUS OUT) already called — old transfer retired, complete and replay now. - pipe0->state = PIPE0_STATE_IDLE; - dcd_event_xfer_complete(rhport, TU_EP0_OUT, 0, XFER_RESULT_SUCCESS, true); - pipe0_process_deferred_setup(rhport, ep_csr, true); - break; - - case PIPE0_STATE_STATUS_OUT_PENDING_IRQ: - // usbd has not called edpt0_xfer(STATUS OUT) for the old transfer yet — only hold the - // SETUP. Replaying here would let that still-outstanding call land in the replayed - // transfer's state and corrupt it (e.g. NULL DATA OUT drain buffer). - break; - - default: - // PIPE0_STATE_STATUS_IN: rxrdy_consumed gate + SetupEnd guarantee DATAEND was armed, i.e. - // usbd already made its status call; the ZLP-sent IRQ combined with the SETUP. - if (pipe0->pending_addr) { - musb_regs->faddr = pipe0->pending_addr; - pipe0->pending_addr = 0; - } - pipe0->state = PIPE0_STATE_IDLE; - dcd_event_xfer_complete(rhport, TU_EP0_IN, 0, XFER_RESULT_SUCCESS, true); - pipe0_process_deferred_setup(rhport, ep_csr, true); - break; - } + pipe0_process_status_isr(rhport, musb_regs, ep_csr); break; - } default: break; } @@ -610,44 +614,7 @@ static void process_ep0_isr(uint8_t rhport) { /* When CSRL0 is zero, it means that either * - completion of sending any length packet TxPktRdy clear * - or status stage is complete (ZLP) after DataEnd is set */ - switch (pipe0->state) { - case PIPE0_STATE_DATA_IN: - // DATA IN packet sent (TXRDY cleared). On the last packet (DATAEND condition above) move to - // STATUS_OUT to await the host's STATUS-OUT ZLP IRQ. - if (pipe0->remain_wlength == 0 || pipe0->xact_len < CFG_TUD_ENDPOINT0_SIZE) { - pipe0->state = PIPE0_STATE_STATUS_OUT; - } - dcd_event_xfer_complete(rhport, TU_EP0_IN, pipe0->xact_len, XFER_RESULT_SUCCESS, true); - break; - - case PIPE0_STATE_STATUS_OUT: - // First event of the STATUS OUT pair — wait for edpt0_xfer(STATUS OUT) to fire complete. - pipe0->state = PIPE0_STATE_STATUS_OUT_PENDING_IRQ; - break; - - case PIPE0_STATE_STATUS_OUT_PENDING_XFER: - // Second event — edpt0_xfer(STATUS OUT) already called, fire complete now. - pipe0->state = PIPE0_STATE_IDLE; - dcd_event_xfer_complete(rhport, TU_EP0_OUT, 0, XFER_RESULT_SUCCESS, true); - pipe0_process_deferred_setup(rhport, ep_csr, true); - break; - - case PIPE0_STATE_STATUS_OUT_PENDING_IRQ: - // Stale duplicate of the status confirm — already accounted for; edpt0_xfer fires complete. - break; - - case PIPE0_STATE_STATUS_IN: - if (pipe0->pending_addr) { - musb_regs->faddr = pipe0->pending_addr; - pipe0->pending_addr = 0; - } - pipe0->state = PIPE0_STATE_IDLE; - dcd_event_xfer_complete(rhport, TU_EP0_IN, 0, XFER_RESULT_SUCCESS, true); - pipe0_process_deferred_setup(rhport, ep_csr, true); - break; - - default: break; - } + pipe0_process_status_isr(rhport, musb_regs, ep_csr); } // Upon BUS RESET is detected, hardware havs already done: @@ -950,7 +917,7 @@ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { // The transfer being stalled already completed on the wire (a deferred SETUP can only exist // once its status stage was seen) and the host's next request was already ACKed — SendStall // would land on that innocent request. Skip the stall and replay the deferred SETUP instead. - pipe0_process_deferred_setup(rhport, ep_csr, false); + pipe0_try_deferred_setup(rhport, ep_csr, false); } else { // Forcing EP0 to IDLE: any RXRDY parked by the aborted transfer's flow control is stale, // clear it so the next SETUP IRQ is not gated off. -- cgit v1.3.1 From 3d9468152c44148c6881fb3f30ff3dae91a09b68 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 15 Jun 2026 22:19:34 +0700 Subject: dcd/musb: read EP0 SETUP into uint32_t[2], drop the double copy pipe0_read_setup() copied the FIFO into a local union, then copied that into the caller's struct. Read the two FIFO words straight into the caller's uint32_t[2] (one copy) and cast to tusb_control_request_t* in pipe0_start_setup(). pipe0.deferred_setup becomes uint32_t[2] so the deferral path reads directly into it as well. Verified: HIL pass on ek_tm4c123gxl and max32666fthr (13/13 each). Co-Authored-By: Claude Fable 5 --- src/portable/mentor/musb/dcd_musb.c | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) (limited to 'src/portable') diff --git a/src/portable/mentor/musb/dcd_musb.c b/src/portable/mentor/musb/dcd_musb.c index e769b08a5..5c2b80cf6 100644 --- a/src/portable/mentor/musb/dcd_musb.c +++ b/src/portable/mentor/musb/dcd_musb.c @@ -100,7 +100,7 @@ typedef struct { bool rxrdy_consumed; // RxPktRdy left set in hw for an already-consumed packet (NAK flow control); // RXRDY events are stale while set. Cleared when RXRDYC is written. bool deferred_setup_valid; - tusb_control_request_t deferred_setup; + uint32_t deferred_setup[2]; // raw SETUP words, replayed via pipe0_start_setup } pipe0_state_t; typedef struct { @@ -110,21 +110,17 @@ typedef struct { static dcd_data_t _dcd; -// Drain a SETUP packet (8 bytes) from the EP0 FIFO. Does not ack RxPktRdy. -static bool pipe0_read_setup(musb_regs_t* musb_regs, musb_ep_csr_t* ep_csr, tusb_control_request_t* req) { +// Read the 8-byte SETUP packet (2 words) from the EP0 FIFO into setup[]. Does not ack RxPktRdy. +static bool pipe0_read_setup(musb_regs_t* musb_regs, musb_ep_csr_t* ep_csr, uint32_t setup[2]) { TU_ASSERT(sizeof(tusb_control_request_t) == ep_csr->count0); - union { - tusb_control_request_t req; - uint32_t u32[2]; - } setup_packet; - setup_packet.u32[0] = musb_regs->fifo[0]; - setup_packet.u32[1] = musb_regs->fifo[0]; - *req = setup_packet.req; + setup[0] = musb_regs->fifo[0]; + setup[1] = musb_regs->fifo[0]; return true; } static void pipe0_start_setup(uint8_t rhport, musb_ep_csr_t* ep_csr, - tusb_control_request_t const* req, bool is_isr) { + const uint32_t setup[2], bool is_isr) { + tusb_control_request_t const* req = (tusb_control_request_t const*) setup; pipe0_state_t* pipe0 = &_dcd.pipe0; pipe0->remain_wlength = req->wLength; @@ -149,7 +145,7 @@ static void pipe0_start_setup(uint8_t rhport, musb_ep_csr_t* ep_csr, } } - dcd_event_setup_received(rhport, (const uint8_t *) req, is_isr); + dcd_event_setup_received(rhport, (const uint8_t *) setup, is_isr); } // Replay a previously deferred SETUP, if any. @@ -160,7 +156,7 @@ static void pipe0_try_deferred_setup(uint8_t rhport, musb_ep_csr_t* ep_csr, bool } pipe0->deferred_setup_valid = false; - pipe0_start_setup(rhport, ep_csr, &pipe0->deferred_setup, is_isr); + pipe0_start_setup(rhport, ep_csr, pipe0->deferred_setup, is_isr); } // EP0 must not call this — it has its own scalars in dcd_data_t. @@ -557,9 +553,9 @@ static void process_ep0_isr(uint8_t rhport) { } switch (pipe0->state) { case PIPE0_STATE_IDLE: { - tusb_control_request_t req; - TU_VERIFY(pipe0_read_setup(musb_regs, ep_csr, &req), ); - pipe0_start_setup(rhport, ep_csr, &req, true); + uint32_t setup[2]; + TU_VERIFY(pipe0_read_setup(musb_regs, ep_csr, setup), ); + pipe0_start_setup(rhport, ep_csr, setup, true); break; } @@ -592,7 +588,7 @@ static void process_ep0_isr(uint8_t rhport) { // Save it, then finish the old transfer's tail event; deferred_setup_valid makes // pipe0_process_status_isr() synthesize the coalesced status confirm and replay the SETUP // once the old transfer is retired. Its RXRDY stays parked so a stale IRQ can't re-process it. - TU_VERIFY(pipe0_read_setup(musb_regs, ep_csr, &pipe0->deferred_setup), ); + TU_VERIFY(pipe0_read_setup(musb_regs, ep_csr, pipe0->deferred_setup), ); pipe0->deferred_setup_valid = true; pipe0->rxrdy_consumed = true; pipe0_process_status_isr(rhport, musb_regs, ep_csr); -- cgit v1.3.1 From f1080e158aeec31faee0f3371d2d5c6f624dd4f4 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 15 Jun 2026 22:50:01 +0700 Subject: dcd/musb: harden EP0 DATA_OUT against short packet and host overrun Mirror the IN-side short-packet fix on the OUT drain: end the data stage (-> STATUS_IN) when wLength is received OR a short OUT packet (count0 < CFG_TUD_ENDPOINT0_SIZE) signals the host's end-of-data, not only when remain_wlength hits exactly 0. Also clamp the remain_wlength subtraction so a host that overruns wLength can't underflow it and strand the transfer. Without this, a control-OUT whose host sends fewer bytes than wLength left pipe0 in DATA_OUT; usbd then armed STATUS IN and tripped the split's TU_ASSERT(!dir_in). Found by /code-review; conformant hosts send exactly wLength so HIL was already green. Verified: HIL pass on ek_tm4c123gxl and max32666fthr (13/13 each). Co-Authored-By: Claude Fable 5 --- src/portable/mentor/musb/dcd_musb.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/portable') diff --git a/src/portable/mentor/musb/dcd_musb.c b/src/portable/mentor/musb/dcd_musb.c index 5c2b80cf6..0a2df3e71 100644 --- a/src/portable/mentor/musb/dcd_musb.c +++ b/src/portable/mentor/musb/dcd_musb.c @@ -566,12 +566,13 @@ static void process_ep0_isr(uint8_t rhport) { if (count0) { TU_ASSERT(pipe0->buf, ); tu_hwfifo_read(&musb_regs->fifo[0], pipe0->buf, count0, NULL); - pipe0->remain_wlength -= count0; + pipe0->remain_wlength -= tu_min16(count0, pipe0->remain_wlength); // clamp: host may overrun } // RXRDY stays set until the next edpt0_xfer arm acks it (NAK flow control): // edpt0_xfer(DATA OUT) for a mid-stream packet, edpt0_xfer(STATUS IN) for the last. pipe0->rxrdy_consumed = true; - if (pipe0->remain_wlength == 0) { + // Last packet: wLength received, or a short packet (host's end-of-data). + if (pipe0->remain_wlength == 0 || count0 < CFG_TUD_ENDPOINT0_SIZE) { pipe0->state = PIPE0_STATE_STATUS_IN; } dcd_event_xfer_complete(rhport, TU_EP0_OUT, count0, XFER_RESULT_SUCCESS, true); -- cgit v1.3.1 From 148fabb96b16fe0899004ba71d6447ec3995cf55 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 15 Jun 2026 23:24:17 +0700 Subject: dcd/musb: rename pipe0_process_status_isr -> pipe0_process_xfer_state_isr MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The helper advances the whole EP0 control state machine on a completion/confirmation IRQ — it dispatches on pipe0->state and also fires the DATA_IN completion, not just the status stage — so "process_status" undersold it. Matches the process_*_isr family. Co-Authored-By: Claude Fable 5 --- src/portable/mentor/musb/dcd_musb.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/portable') diff --git a/src/portable/mentor/musb/dcd_musb.c b/src/portable/mentor/musb/dcd_musb.c index 0a2df3e71..e8146f7a7 100644 --- a/src/portable/mentor/musb/dcd_musb.c +++ b/src/portable/mentor/musb/dcd_musb.c @@ -474,7 +474,7 @@ static bool edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_ // Advance EP0's status-stage state machine on a tail event: the csrl==0 confirmation IRQ, or such a // confirmation combined with a new SETUP (caller sets deferred_setup_valid first). ISR context only. -static void pipe0_process_status_isr(uint8_t rhport, musb_regs_t* musb_regs, musb_ep_csr_t* ep_csr) { +static void pipe0_process_xfer_state_isr(uint8_t rhport, musb_regs_t* musb_regs, musb_ep_csr_t* ep_csr) { pipe0_state_t* pipe0 = &_dcd.pipe0; switch (pipe0->state) { case PIPE0_STATE_DATA_IN: @@ -587,12 +587,12 @@ static void process_ep0_isr(uint8_t rhport) { case PIPE0_STATE_STATUS_OUT_PENDING_IRQ: case PIPE0_STATE_STATUS_IN: // Save it, then finish the old transfer's tail event; deferred_setup_valid makes - // pipe0_process_status_isr() synthesize the coalesced status confirm and replay the SETUP + // pipe0_process_xfer_state_isr() synthesize the coalesced status confirm and replay the SETUP // once the old transfer is retired. Its RXRDY stays parked so a stale IRQ can't re-process it. TU_VERIFY(pipe0_read_setup(musb_regs, ep_csr, pipe0->deferred_setup), ); pipe0->deferred_setup_valid = true; pipe0->rxrdy_consumed = true; - pipe0_process_status_isr(rhport, musb_regs, ep_csr); + pipe0_process_xfer_state_isr(rhport, musb_regs, ep_csr); break; default: break; @@ -611,7 +611,7 @@ static void process_ep0_isr(uint8_t rhport) { /* When CSRL0 is zero, it means that either * - completion of sending any length packet TxPktRdy clear * - or status stage is complete (ZLP) after DataEnd is set */ - pipe0_process_status_isr(rhport, musb_regs, ep_csr); + pipe0_process_xfer_state_isr(rhport, musb_regs, ep_csr); } // Upon BUS RESET is detected, hardware havs already done: -- cgit v1.3.1 From ba3b2453e7cbf3572663dd1b7eadafdcc6b0a912 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 16 Jun 2026 11:09:40 +0700 Subject: dcd/musb: extract pipe0_data_stage_done() and fix two EP0 comments Cleanup from a code-review pass, no behavior change: - Replace the open-coded "last DATA packet" test (remain_wlength == 0 || len < CFG_TUD_ENDPOINT0_SIZE), duplicated in the edpt0_xfer DATA IN arm, pipe0_process_xfer_state_isr, and the DATA OUT drain, with one inline pipe0_data_stage_done() so IN and OUT can't drift. - Correct the xact_len comment (only the IN path reports it; OUT reports count0) and the dcd_edpt_stall comment (a deferred SETUP means the old transfer ended on the wire, not that its status stage was "seen"). Co-Authored-By: Claude Fable 5 --- src/portable/mentor/musb/dcd_musb.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'src/portable') diff --git a/src/portable/mentor/musb/dcd_musb.c b/src/portable/mentor/musb/dcd_musb.c index e8146f7a7..1d1280bf4 100644 --- a/src/portable/mentor/musb/dcd_musb.c +++ b/src/portable/mentor/musb/dcd_musb.c @@ -93,7 +93,7 @@ enum { // EP0 control-transfer state (own scalars, not a pipe[] slot). typedef struct { uint8_t *buf; // DATA OUT drain target (only valid while EP0 is in DATA OUT stage) - uint16_t xact_len; // chunk length most recently armed via edpt0_xfer; reported in xfer_complete + uint16_t xact_len; // DATA IN chunk length armed via edpt0_xfer; reported in its xfer_complete (OUT reports count0) uint16_t remain_wlength; // bytes remaining in the control transfer's DATA stage uint8_t state; uint8_t pending_addr; // new USB address latched by dcd_set_address; applied when STATUS IN completes @@ -159,6 +159,11 @@ static void pipe0_try_deferred_setup(uint8_t rhport, musb_ep_csr_t* ep_csr, bool pipe0_start_setup(rhport, ep_csr, pipe0->deferred_setup, is_isr); } +// Last DATA packet: wLength satisfied, or a short packet (incl. ZLP) ends the stage. +TU_ATTR_ALWAYS_INLINE static inline bool pipe0_data_stage_done(uint16_t xfer_len) { + return _dcd.pipe0.remain_wlength == 0 || xfer_len < CFG_TUD_ENDPOINT0_SIZE; +} + // EP0 must not call this — it has its own scalars in dcd_data_t. TU_ATTR_ALWAYS_INLINE static inline pipe_state_t* pipe_get(uint8_t epnum, tusb_dir_t epdir) { size_t idx = epnum - 1u; @@ -430,8 +435,8 @@ static bool edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_ } tu_hwfifo_write(&musb_regs->fifo[0], buffer, total_bytes, NULL); pipe0->remain_wlength -= total_bytes; - // DATAEND on the last packet: wLength met, or a short packet (incl. ZLP) ends the data stage. - if (pipe0->remain_wlength == 0 || total_bytes < CFG_TUD_ENDPOINT0_SIZE) { + // Add DATAEND on the last packet to end the data stage. + if (pipe0_data_stage_done(total_bytes)) { ep_csr->csr0l = MUSB_CSRL0_TXRDY | MUSB_CSRL0_DATAEND; } else { ep_csr->csr0l = MUSB_CSRL0_TXRDY; @@ -478,7 +483,7 @@ static void pipe0_process_xfer_state_isr(uint8_t rhport, musb_regs_t* musb_regs, pipe0_state_t* pipe0 = &_dcd.pipe0; switch (pipe0->state) { case PIPE0_STATE_DATA_IN: - if (pipe0->remain_wlength == 0 || pipe0->xact_len < CFG_TUD_ENDPOINT0_SIZE) { // last DATA IN packet + if (pipe0_data_stage_done(pipe0->xact_len)) { if (pipe0->deferred_setup_valid) { pipe0->state = PIPE0_STATE_STATUS_OUT_PENDING_IRQ; // status confirm coalesced with deferred SETUP } else { @@ -571,8 +576,7 @@ static void process_ep0_isr(uint8_t rhport) { // RXRDY stays set until the next edpt0_xfer arm acks it (NAK flow control): // edpt0_xfer(DATA OUT) for a mid-stream packet, edpt0_xfer(STATUS IN) for the last. pipe0->rxrdy_consumed = true; - // Last packet: wLength received, or a short packet (host's end-of-data). - if (pipe0->remain_wlength == 0 || count0 < CFG_TUD_ENDPOINT0_SIZE) { + if (pipe0_data_stage_done(count0)) { pipe0->state = PIPE0_STATE_STATUS_IN; } dcd_event_xfer_complete(rhport, TU_EP0_OUT, count0, XFER_RESULT_SUCCESS, true); @@ -911,9 +915,8 @@ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { pipe0->state = PIPE0_STATE_IDLE; pipe0->buf = NULL; if (pipe0->deferred_setup_valid) { - // The transfer being stalled already completed on the wire (a deferred SETUP can only exist - // once its status stage was seen) and the host's next request was already ACKed — SendStall - // would land on that innocent request. Skip the stall and replay the deferred SETUP instead. + // A deferred SETUP means the stalled transfer already ended on the wire and the host's next + // request was ACKed — SendStall would hit that innocent request. Replay it instead of stalling. pipe0_try_deferred_setup(rhport, ep_csr, false); } else { // Forcing EP0 to IDLE: any RXRDY parked by the aborted transfer's flow control is stale, -- cgit v1.3.1 From ad8cbc4668ab8d92e2eebb834c230e9d18ad8e57 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 18 Jun 2026 10:58:58 +0700 Subject: dcd/ch32_usbfs: support CH32V103 combined endpoint control register CH32V103 uses the older USBFS IP: a single combined UEPn_CTRL register per endpoint (IN response in bits [1:0], OUT response in [3:2], shared auto-toggle, separate IN/OUT toggles) instead of the separate UEPn_TX_CTRL/UEPn_RX_CTRL bytes of the newer IP (CH32V20x/V307). The shared driver was written for the newer IP, so EP0 control transfers never worked on V103: the OUT response was written to a reserved byte and the IN write clobbered the OUT bits. - ch32_usbfs_reg.h: annotate the V103 register struct with byte offsets and add a union exposing the combined UEPn_CTRL at the UEPn_TX_CTRL offset; define CH32_USBFS_EP_CTRL_COMBINED and the combined-register bit positions. - dcd_ch32_usbfs.c: abstract EP control access behind ep_tx/rx_ctrl_set() (full write) and ep_tx/rx_set_response() (response-only RMW). The newer-IP path is unchanged; the combined path read-modify-writes the single register and arms the post-SETUP data stage at DATA1. - bsp/ch32v10x: implement board_get_unique_id() (real chip UID) and drop the CSR 0x800 writes that corrupted the QingKe V3 interrupt config and left all interrupts disabled (the USB ISR never ran). Verified on ch32v103r_r1_1v0: enumerates and passes HIL for cdc_msc, hid, msc, midi, mtp, dfu, etc. Co-Authored-By: Claude Opus 4.8 (1M context) --- hw/bsp/ch32v10x/family.c | 39 +++++------ src/portable/wch/ch32_usbfs_reg.h | 140 +++++++++++++++++++++++++------------- src/portable/wch/dcd_ch32_usbfs.c | 95 +++++++++++++++++++------- 3 files changed, 181 insertions(+), 93 deletions(-) (limited to 'src/portable') diff --git a/hw/bsp/ch32v10x/family.c b/hw/bsp/ch32v10x/family.c index 9f5dc5572..aa709b0d8 100644 --- a/hw/bsp/ch32v10x/family.c +++ b/hw/bsp/ch32v10x/family.c @@ -66,26 +66,14 @@ uint32_t tusb_time_millis_api(void) { } #endif -// 0x800 CSR register is writable in U-mode -// according to manual: https://www.wch-ic.com/downloads/QingKeV3_Processor_Manual_PDF.html -__attribute__((always_inline)) RV_STATIC_INLINE -void __wch_vendor_enable_irq(void) -{ - __asm volatile ("csrs 0x800, %0" : : "r" (0x88) ); -} - -__attribute__((always_inline)) RV_STATIC_INLINE -void __wch_vendor_disable_irq(void) -{ - __asm volatile ("csrc 0x800, %0" : : "r" (0x88) ); - __asm volatile ("fence.i"); -} - void board_init(void) { - /* __disable_irq() in CH32V103 EVT attempts to call - * `csrc mstatus, 0x88` in U-mode, which is allowed ONLY in M-mode. - * Replace this with CSR 0x800 to avoid hard-fault. */ - __wch_vendor_disable_irq(); + /* Do NOT toggle the global interrupt enable here. + * CH32V103 startup enters U-mode (mret with mstatus.MPP=0), so: + * - the SDK __disable_irq()/__enable_irq() write mstatus, which faults in U-mode; + * - writing CSR 0x800 (INTSYSCR) corrupts the QingKe V3 interrupt-mode config, + * which made the USB interrupt vector to a bad address (PC=0) and hang. + * The startup already leaves interrupts correctly configured, and machine-mode + * interrupts are globally enabled while running in U-mode regardless of mstatus.MIE. */ #if CFG_TUSB_OS == OPT_OS_NONE SysTick_Config(SystemCoreClock / 1000); @@ -142,8 +130,6 @@ void board_init(void) { USART_Init(USART1, &usart); USART_Cmd(USART1, ENABLE); - __wch_vendor_enable_irq(); - board_led_write(true); } @@ -155,6 +141,17 @@ uint32_t board_button_read(void) { return BUTTON_STATE_ACTIVE == GPIO_ReadInputDataBit(BUTTON_PORT, BUTTON_PIN); } +size_t board_get_unique_id(uint8_t id[], size_t max_len) { + (void) max_len; + volatile uint32_t* ch32_uuid = ((volatile uint32_t*) 0x1FFFF7E8UL); + uint32_t* serial_32 = (uint32_t*) (uintptr_t) id; + serial_32[0] = ch32_uuid[0]; + serial_32[1] = ch32_uuid[1]; + serial_32[2] = ch32_uuid[2]; + + return 12; +} + int board_uart_read(uint8_t *buf, int len) { (void) buf; (void) len; diff --git a/src/portable/wch/ch32_usbfs_reg.h b/src/portable/wch/ch32_usbfs_reg.h index 68be64f5e..7ffdc6cef 100644 --- a/src/portable/wch/ch32_usbfs_reg.h +++ b/src/portable/wch/ch32_usbfs_reg.h @@ -39,59 +39,92 @@ #include #elif CFG_TUSB_MCU == OPT_MCU_CH32V103 #include + // Newer-IP layout (separate UEPn_TX_CTRL/UEPn_RX_CTRL). The older IP (CH32V103) has a single + // combined control register at the UEPn_TX_CTRL offset, with UEPn_RX_CTRL reserved; the union + // exposes that same byte as UEPn_CTRL. Offsets are byte offsets from the peripheral base. + // TODO unify into a single struct shared by all WCH USBFS parts. typedef struct { - __IO uint8_t BASE_CTRL; - __IO uint8_t UDEV_CTRL; - __IO uint8_t INT_EN; - __IO uint8_t DEV_ADDR; - __IO uint8_t Reserve0; - __IO uint8_t MIS_ST; - __IO uint8_t INT_FG; - __IO uint8_t INT_ST; - __IO uint32_t RX_LEN; - __IO uint8_t UEP4_1_MOD; - __IO uint8_t UEP2_3_MOD; - __IO uint8_t UEP5_6_MOD; - __IO uint8_t UEP7_MOD; - __IO uint32_t UEP0_DMA; - __IO uint32_t UEP1_DMA; - __IO uint32_t UEP2_DMA; - __IO uint32_t UEP3_DMA; - __IO uint32_t UEP4_DMA; - __IO uint32_t UEP5_DMA; - __IO uint32_t UEP6_DMA; - __IO uint32_t UEP7_DMA; - __IO uint16_t UEP0_TX_LEN; - __IO uint8_t UEP0_TX_CTRL; - __IO uint8_t UEP0_RX_CTRL; - __IO uint16_t UEP1_TX_LEN; - __IO uint8_t UEP1_TX_CTRL; - __IO uint8_t UEP1_RX_CTRL; - __IO uint16_t UEP2_TX_LEN; - __IO uint8_t UEP2_TX_CTRL; - __IO uint8_t UEP2_RX_CTRL; - __IO uint16_t UEP3_TX_LEN; - __IO uint8_t UEP3_TX_CTRL; - __IO uint8_t UEP3_RX_CTRL; - __IO uint16_t UEP4_TX_LEN; - __IO uint8_t UEP4_TX_CTRL; - __IO uint8_t UEP4_RX_CTRL; - __IO uint16_t UEP5_TX_LEN; - __IO uint8_t UEP5_TX_CTRL; - __IO uint8_t UEP5_RX_CTRL; - __IO uint16_t UEP6_TX_LEN; - __IO uint8_t UEP6_TX_CTRL; - __IO uint8_t UEP6_RX_CTRL; - __IO uint16_t UEP7_TX_LEN; - __IO uint8_t UEP7_TX_CTRL; - __IO uint8_t UEP7_RX_CTRL; - __IO uint32_t Reserve1; - __IO uint32_t OTG_CR; - __IO uint32_t OTG_SR; + __IO uint8_t BASE_CTRL; // 0x00 + __IO uint8_t UDEV_CTRL; // 0x01 + __IO uint8_t INT_EN; // 0x02 + __IO uint8_t DEV_ADDR; // 0x03 + __IO uint8_t Reserve0; // 0x04 + __IO uint8_t MIS_ST; // 0x05 + __IO uint8_t INT_FG; // 0x06 + __IO uint8_t INT_ST; // 0x07 + __IO uint32_t RX_LEN; // 0x08 + __IO uint8_t UEP4_1_MOD; // 0x0C + __IO uint8_t UEP2_3_MOD; // 0x0D + __IO uint8_t UEP5_6_MOD; // 0x0E + __IO uint8_t UEP7_MOD; // 0x0F + __IO uint32_t UEP0_DMA; // 0x10 + __IO uint32_t UEP1_DMA; // 0x14 + __IO uint32_t UEP2_DMA; // 0x18 + __IO uint32_t UEP3_DMA; // 0x1C + __IO uint32_t UEP4_DMA; // 0x20 + __IO uint32_t UEP5_DMA; // 0x24 + __IO uint32_t UEP6_DMA; // 0x28 + __IO uint32_t UEP7_DMA; // 0x2C + __IO uint16_t UEP0_TX_LEN; // 0x30 + union { + __IO uint8_t UEP0_TX_CTRL; + __IO uint8_t UEP0_CTRL; + }; // 0x32 (TX_CTRL: IN | CTRL: combined) + __IO uint8_t UEP0_RX_CTRL; // 0x33 (OUT ctrl; reserved on combined IP) + __IO uint16_t UEP1_TX_LEN; // 0x34 + union { + __IO uint8_t UEP1_TX_CTRL; + __IO uint8_t UEP1_CTRL; + }; // 0x36 + __IO uint8_t UEP1_RX_CTRL; // 0x37 + __IO uint16_t UEP2_TX_LEN; // 0x38 + union { + __IO uint8_t UEP2_TX_CTRL; + __IO uint8_t UEP2_CTRL; + }; // 0x3A + __IO uint8_t UEP2_RX_CTRL; // 0x3B + __IO uint16_t UEP3_TX_LEN; // 0x3C + union { + __IO uint8_t UEP3_TX_CTRL; + __IO uint8_t UEP3_CTRL; + }; // 0x3E + __IO uint8_t UEP3_RX_CTRL; // 0x3F + __IO uint16_t UEP4_TX_LEN; // 0x40 + union { + __IO uint8_t UEP4_TX_CTRL; + __IO uint8_t UEP4_CTRL; + }; // 0x42 + __IO uint8_t UEP4_RX_CTRL; // 0x43 + __IO uint16_t UEP5_TX_LEN; // 0x44 + union { + __IO uint8_t UEP5_TX_CTRL; + __IO uint8_t UEP5_CTRL; + }; // 0x46 + __IO uint8_t UEP5_RX_CTRL; // 0x47 + __IO uint16_t UEP6_TX_LEN; // 0x48 + union { + __IO uint8_t UEP6_TX_CTRL; + __IO uint8_t UEP6_CTRL; + }; // 0x4A + __IO uint8_t UEP6_RX_CTRL; // 0x4B + __IO uint16_t UEP7_TX_LEN; // 0x4C + union { + __IO uint8_t UEP7_TX_CTRL; + __IO uint8_t UEP7_CTRL; + }; // 0x4E + __IO uint8_t UEP7_RX_CTRL; // 0x4F + __IO uint32_t Reserve1; // 0x50 + __IO uint32_t OTG_CR; // 0x54 + __IO uint32_t OTG_SR; // 0x58 } USBOTG_FS_TypeDef; #define USBOTG_FS ((USBOTG_FS_TypeDef *) 0x40023400) + + // CH32V103 has the older USBFS IP: a single combined control register per endpoint + // (UEPn_CTRL) instead of separate TX_CTRL/RX_CTRL bytes. The struct's UEPn_TX_CTRL field + // aliases that combined register (same address); UEPn_RX_CTRL maps to unused padding. + #define CH32_USBFS_EP_CTRL_COMBINED 1 #elif CFG_TUSB_MCU == OPT_MCU_CH32V20X #include #elif CFG_TUSB_MCU == OPT_MCU_CH32V307 @@ -166,6 +199,17 @@ #define USBFS_EP_R_RES_NAK (2 << 0) #define USBFS_EP_R_RES_STALL (3 << 0) +#ifdef CH32_USBFS_EP_CTRL_COMBINED +// Combined per-endpoint control register (older IP, e.g. CH32V103): IN response in +// bits [1:0], OUT response in bits [3:2], shared auto-toggle, separate IN/OUT toggle. +#define USBFS_EPC_T_RES_MASK 0x03 +#define USBFS_EPC_R_RES_MASK 0x0C +#define USBFS_EPC_R_RES_SHIFT 2 +#define USBFS_EPC_AUTO_TOG 0x10 +#define USBFS_EPC_T_TOG 0x40 +#define USBFS_EPC_R_TOG 0x80 +#endif + // token PID #define PID_OUT 0 #define PID_SOF 1 diff --git a/src/portable/wch/dcd_ch32_usbfs.c b/src/portable/wch/dcd_ch32_usbfs.c index af0f17785..dae31da91 100644 --- a/src/portable/wch/dcd_ch32_usbfs.c +++ b/src/portable/wch/dcd_ch32_usbfs.c @@ -40,6 +40,52 @@ #define EP_TX_CTRL(ep) ((&USBOTG_FS->UEP0_TX_CTRL)[4 * ep]) #define EP_RX_CTRL(ep) ((&USBOTG_FS->UEP0_RX_CTRL)[4 * ep]) +// Endpoint control register access. The newer USBFS IP (CH32V20x/V307/X035) has separate +// TX_CTRL and RX_CTRL bytes per endpoint; the older IP (CH32V103) has a single combined +// UEPn_CTRL register. These helpers hide the difference so the rest of the driver is shared. +// Values use the newer-IP encoding (USBFS_EP_T_*/USBFS_EP_R_*); the combined path remaps them. +#ifdef CH32_USBFS_EP_CTRL_COMBINED + #define EP_CTRL(ep) EP_TX_CTRL(ep) // UEPn_TX_CTRL field aliases the combined UEPn_CTRL register + + static inline uint8_t ep_tx_to_comb(uint8_t v) { + uint8_t c = v & USBFS_EP_T_RES_MASK; // IN response: bits [1:0] in both encodings + if (v & USBFS_EP_T_TOG) { c |= USBFS_EPC_T_TOG; } + if (v & USBFS_EP_T_AUTO_TOG) { c |= USBFS_EPC_AUTO_TOG; } + return c; + } + static inline uint8_t ep_rx_to_comb(uint8_t v) { + uint8_t c = (uint8_t) ((v & USBFS_EP_R_RES_MASK) << USBFS_EPC_R_RES_SHIFT); // OUT response -> bits [3:2] + if (v & USBFS_EP_R_TOG) { c |= USBFS_EPC_R_TOG; } + if (v & USBFS_EP_R_AUTO_TOG) { c |= USBFS_EPC_AUTO_TOG; } + return c; + } + // Set IN side (response/toggle/auto-tog), preserving the OUT response + OUT toggle. + static inline void ep_tx_ctrl_set(uint8_t ep, uint8_t v) { + EP_CTRL(ep) = (uint8_t) ((EP_CTRL(ep) & (USBFS_EPC_R_RES_MASK | USBFS_EPC_R_TOG)) | ep_tx_to_comb(v)); + } + // Set OUT side, preserving the IN response + IN toggle. + static inline void ep_rx_ctrl_set(uint8_t ep, uint8_t v) { + EP_CTRL(ep) = (uint8_t) ((EP_CTRL(ep) & (USBFS_EPC_T_RES_MASK | USBFS_EPC_T_TOG)) | ep_rx_to_comb(v)); + } + static inline void ep_tx_set_response(uint8_t ep, uint8_t res) { + EP_CTRL(ep) = (uint8_t) ((EP_CTRL(ep) & ~USBFS_EPC_T_RES_MASK) | (res & USBFS_EP_T_RES_MASK)); + } + static inline void ep_rx_set_response(uint8_t ep, uint8_t res) { + EP_CTRL(ep) = (uint8_t) ((EP_CTRL(ep) & ~USBFS_EPC_R_RES_MASK) | ((res & USBFS_EP_R_RES_MASK) << USBFS_EPC_R_RES_SHIFT)); + } + #define EP0_SETUP_RX_TOG USBFS_EP_R_TOG // combined IP: data/status stage after SETUP is DATA1 +#else + static inline void ep_tx_ctrl_set(uint8_t ep, uint8_t v) { EP_TX_CTRL(ep) = v; } + static inline void ep_rx_ctrl_set(uint8_t ep, uint8_t v) { EP_RX_CTRL(ep) = v; } + static inline void ep_tx_set_response(uint8_t ep, uint8_t res) { + EP_TX_CTRL(ep) = (uint8_t) ((EP_TX_CTRL(ep) & ~USBFS_EP_T_RES_MASK) | res); + } + static inline void ep_rx_set_response(uint8_t ep, uint8_t res) { + EP_RX_CTRL(ep) = (uint8_t) ((EP_RX_CTRL(ep) & ~USBFS_EP_R_RES_MASK) | res); + } + #define EP0_SETUP_RX_TOG 0 +#endif + /* private data */ struct usb_xfer { bool valid; @@ -81,19 +127,19 @@ static void update_in(uint8_t rhport, uint8_t ep, bool force) { EP_TX_LEN(ep) = len; if (ep == 0) { - EP_TX_CTRL(0) = USBFS_EP_T_RES_ACK | (data.ep0_tog ? USBFS_EP_T_TOG : 0); + ep_tx_ctrl_set(0, USBFS_EP_T_RES_ACK | (data.ep0_tog ? USBFS_EP_T_TOG : 0)); data.ep0_tog = !data.ep0_tog; } else if (data.isochronous[ep]) { - EP_TX_CTRL(ep) = (EP_TX_CTRL(ep) & ~(USBFS_EP_T_RES_MASK)) | USBFS_EP_T_RES_NYET; + ep_tx_set_response(ep, USBFS_EP_T_RES_NYET); } else { - EP_TX_CTRL(ep) = (EP_TX_CTRL(ep) & ~(USBFS_EP_T_RES_MASK)) | USBFS_EP_T_RES_ACK; + ep_tx_set_response(ep, USBFS_EP_T_RES_ACK); } } else { xfer->valid = false; if (ep == 0) { - EP_TX_CTRL(0) = USBFS_EP_T_RES_NAK | (data.ep0_tog ? USBFS_EP_T_TOG : 0); + ep_tx_ctrl_set(0, USBFS_EP_T_RES_NAK | (data.ep0_tog ? USBFS_EP_T_TOG : 0)); } else if (!data.isochronous[ep]) { - EP_TX_CTRL(ep) = (EP_TX_CTRL(ep) & ~(USBFS_EP_T_RES_MASK)) | USBFS_EP_T_RES_NAK; + ep_tx_set_response(ep, USBFS_EP_T_RES_NAK); } dcd_event_xfer_complete(rhport, ep | TUSB_DIR_IN_MASK, xfer->processed_len, XFER_RESULT_SUCCESS, true); } @@ -119,11 +165,11 @@ static void update_out(uint8_t rhport, uint8_t ep, size_t rx_len) { } if (ep == 0) { - EP_RX_CTRL(0) = USBFS_EP_R_RES_NAK; + ep_rx_set_response(0, USBFS_EP_R_RES_NAK); } else { uint8_t rx_res = data.isochronous[ep] ? USBFS_EP_R_RES_NYET : (xfer->valid ? USBFS_EP_R_RES_ACK : USBFS_EP_R_RES_NAK); - EP_RX_CTRL(ep) = (EP_RX_CTRL(ep) & ~USBFS_EP_R_RES_MASK) | rx_res; + ep_rx_set_response(ep, rx_res); } } } @@ -132,8 +178,8 @@ static void reset_ep_ctrls(void) { for (uint8_t ep = 1; ep < EP_MAX; ep++) { EP_DMA(ep) = (uint32_t)&data.buffer[ep][0]; EP_TX_LEN(ep) = 0; - EP_TX_CTRL(ep) = USBFS_EP_T_AUTO_TOG | USBFS_EP_T_RES_NYET; - EP_RX_CTRL(ep) = USBFS_EP_R_AUTO_TOG | USBFS_EP_R_RES_NYET; + ep_tx_ctrl_set(ep, USBFS_EP_T_AUTO_TOG | USBFS_EP_T_RES_NYET); + ep_rx_ctrl_set(ep, USBFS_EP_R_AUTO_TOG | USBFS_EP_R_RES_NYET); } EP_DMA(3) = (uint32_t)&data.ep3_buffer.out[0]; } @@ -152,8 +198,8 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t *rh_init) { // setup endpoint 0 EP_DMA(0) = (uint32_t)&data.buffer[0][0]; EP_TX_LEN(0) = 0; - EP_TX_CTRL(0) = USBFS_EP_T_RES_NAK; - EP_RX_CTRL(0) = USBFS_EP_R_RES_ACK; + ep_tx_ctrl_set(0, USBFS_EP_T_RES_NAK); + ep_rx_ctrl_set(0, USBFS_EP_R_RES_ACK); // enable other endpoints but NAK everything USBOTG_FS->UEP4_1_MOD = 0xCC; @@ -188,11 +234,12 @@ void dcd_int_handler(uint8_t rhport) { case PID_SETUP: // setup clears stall - EP_TX_CTRL(0) = USBFS_EP_T_RES_NAK; + ep_tx_ctrl_set(0, USBFS_EP_T_RES_NAK); data.ep0_tog = true; const tusb_control_request_t *setup = (const tusb_control_request_t *)&data.buffer[0][TUSB_DIR_OUT][0]; - EP_RX_CTRL(0) = (setup->wLength == 0) ? USBFS_EP_R_RES_ACK : USBFS_EP_R_RES_NAK; + // EP0_SETUP_RX_TOG arms the data/status stage at DATA1 on the combined-control IP + ep_rx_ctrl_set(0, ((setup->wLength == 0) ? USBFS_EP_R_RES_ACK : USBFS_EP_R_RES_NAK) | EP0_SETUP_RX_TOG); dcd_event_setup_received(rhport, &data.buffer[0][TUSB_DIR_OUT][0], true); break; @@ -210,7 +257,7 @@ void dcd_int_handler(uint8_t rhport) { true); USBOTG_FS->DEV_ADDR = 0x00; - EP_RX_CTRL(0) = USBFS_EP_R_RES_ACK; + ep_rx_ctrl_set(0, USBFS_EP_R_RES_ACK); reset_ep_ctrls(); @@ -277,9 +324,9 @@ bool dcd_edpt_open(uint8_t rhport, const tusb_desc_endpoint_t *desc_ep) { if (ep != 0) { if (dir == TUSB_DIR_OUT) { - EP_RX_CTRL(ep) = USBFS_EP_R_AUTO_TOG | USBFS_EP_T_RES_NAK; + ep_rx_ctrl_set(ep, USBFS_EP_R_AUTO_TOG | USBFS_EP_R_RES_NAK); } else { - EP_TX_CTRL(ep) = USBFS_EP_T_AUTO_TOG | USBFS_EP_T_RES_NAK; + ep_tx_ctrl_set(ep, USBFS_EP_T_AUTO_TOG | USBFS_EP_T_RES_NAK); } } return true; @@ -326,7 +373,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to update_in(rhport, ep, true); } else { uint8_t rx_res = data.isochronous[ep] ? USBFS_EP_R_RES_NYET : USBFS_EP_R_RES_ACK; - EP_RX_CTRL(ep) = (EP_RX_CTRL(ep) & ~USBFS_EP_R_RES_MASK) | rx_res; + ep_rx_set_response(ep, rx_res); } return true; } @@ -337,16 +384,16 @@ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { uint8_t dir = tu_edpt_dir(ep_addr); if (ep == 0) { if (dir == TUSB_DIR_OUT) { - EP_RX_CTRL(0) = USBFS_EP_R_RES_STALL; + ep_rx_ctrl_set(0, USBFS_EP_R_RES_STALL); } else { EP_TX_LEN(0) = 0; - EP_TX_CTRL(0) = USBFS_EP_T_RES_STALL; + ep_tx_ctrl_set(0, USBFS_EP_T_RES_STALL); } } else { if (dir == TUSB_DIR_OUT) { - EP_RX_CTRL(ep) = (EP_RX_CTRL(ep) & ~USBFS_EP_R_RES_MASK) | USBFS_EP_R_RES_STALL; + ep_rx_set_response(ep, USBFS_EP_R_RES_STALL); } else { - EP_TX_CTRL(ep) = (EP_TX_CTRL(ep) & ~USBFS_EP_T_RES_MASK) | USBFS_EP_T_RES_STALL; + ep_tx_set_response(ep, USBFS_EP_T_RES_STALL); } } } @@ -357,13 +404,13 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { uint8_t dir = tu_edpt_dir(ep_addr); if (ep == 0) { if (dir == TUSB_DIR_OUT) { - EP_RX_CTRL(0) = USBFS_EP_R_RES_ACK; + ep_rx_ctrl_set(0, USBFS_EP_R_RES_ACK); } } else { if (dir == TUSB_DIR_OUT) { - EP_RX_CTRL(ep) = USBFS_EP_R_AUTO_TOG | USBFS_EP_R_RES_NAK; + ep_rx_ctrl_set(ep, USBFS_EP_R_AUTO_TOG | USBFS_EP_R_RES_NAK); } else { - EP_TX_CTRL(ep) = USBFS_EP_T_AUTO_TOG | USBFS_EP_T_RES_NAK; + ep_tx_ctrl_set(ep, USBFS_EP_T_AUTO_TOG | USBFS_EP_T_RES_NAK); } } } -- cgit v1.3.1 From ea5b8d677f22f4bd1574f864fd0487dfd329c090 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 18 Jun 2026 17:59:30 +0700 Subject: dcd/ch58x: drive CH582/583 with shared dcd_ch32_usbfs.c Replace PR #3515's separate dcd_ch58x_usbfs.c / hcd_ch58x_usbfs.c with the shared WCH USBFS device driver (combined per-endpoint control, like CH32V103), adding two CH58x-specific behaviors guarded so CH32V103/V20x/V307 are unchanged: - CH32_USBFS_EP_MANUAL_TOG: CH58x's hardware AUTO_TOG does not stay in sync, so the ISR toggles DATA0/DATA1 manually and discards toggle-mismatched OUT packets. Fixes multi-packet bulk-IN (e.g. MSC READ10) that otherwise hung. - CH32_USBFS_EP4_SHARES_EP0: EP4 has no DMA register and overlays EP0's region (EP0[0:63] + EP4 OUT[64:127] + EP4 IN[128:191]); add a 192-byte shared buffer and buffer-pointer helpers (transparent for the other parts). Fixes cdc_dual_ports (Port1 is on EP4). Add the ch582m_evt board. Device only on USB0 (rhport 0): the shared hcd_ch32_usbfs.c is CH32V20x-specific and cannot drive CH58x, so host / USB2 (rhport 1) is left commented out in the BSP for easy re-add. Verified on ch582m_evt via local HIL: all device examples pass. Co-Authored-By: Claude Opus 4.8 (1M context) --- hw/bsp/ch58x/boards/ch582m_evt/board.cmake | 5 + hw/bsp/ch58x/boards/ch582m_evt/board.h | 61 +++ hw/bsp/ch58x/boards/ch582m_evt/board.mk | 3 + hw/bsp/ch58x/boards/yd-ch582m/board.h | 10 +- hw/bsp/ch58x/ch58x_it.h | 2 +- hw/bsp/ch58x/family.c | 27 +- hw/bsp/ch58x/family.cmake | 3 +- hw/bsp/ch58x/family.mk | 3 +- src/common/tusb_mcu.h | 11 +- src/portable/wch/ch32_usbfs_reg.h | 48 ++ src/portable/wch/ch58x_usbfs_reg.h | 291 ------------ src/portable/wch/dcd_ch32_usbfs.c | 125 +++-- src/portable/wch/dcd_ch58x_usbfs.c | 636 ------------------------- src/portable/wch/hcd_ch58x_usbfs.c | 721 ----------------------------- 14 files changed, 244 insertions(+), 1702 deletions(-) create mode 100644 hw/bsp/ch58x/boards/ch582m_evt/board.cmake create mode 100644 hw/bsp/ch58x/boards/ch582m_evt/board.h create mode 100644 hw/bsp/ch58x/boards/ch582m_evt/board.mk delete mode 100644 src/portable/wch/ch58x_usbfs_reg.h delete mode 100644 src/portable/wch/dcd_ch58x_usbfs.c delete mode 100644 src/portable/wch/hcd_ch58x_usbfs.c (limited to 'src/portable') diff --git a/hw/bsp/ch58x/boards/ch582m_evt/board.cmake b/hw/bsp/ch58x/boards/ch582m_evt/board.cmake new file mode 100644 index 000000000..4129c4550 --- /dev/null +++ b/hw/bsp/ch58x/boards/ch582m_evt/board.cmake @@ -0,0 +1,5 @@ +set(LD_FLASH_SIZE 448K) +set(LD_RAM_SIZE 32K) + +function(update_board TARGET) +endfunction() diff --git a/hw/bsp/ch58x/boards/ch582m_evt/board.h b/hw/bsp/ch58x/boards/ch582m_evt/board.h new file mode 100644 index 000000000..c3483bf17 --- /dev/null +++ b/hw/bsp/ch58x/boards/ch582m_evt/board.h @@ -0,0 +1,61 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2024 TinyUSB contributors + * + * 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. + */ + +/* metadata: + name: CH582M-EVT evaluation board + url: https://www.wch-ic.com/products/CH582.html +*/ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +// LED: PB4 on CH582M-EVT +#define LED_PIN GPIO_Pin_4 +#define LED_STATE_ON 0 + +// Directly reuse BOOT pin as user button +#define BUTTON_PIN GPIO_Pin_22 +#define BUTTON_STATE_ACTIVE 0 + +// UART: UART1 TX=PA9, RX=PA8 +#define CFG_BOARD_UART_BAUDRATE 115200 + +// Device only on USB1 (rhport 0). CH58x host / USB2 is not supported by the shared usbfs dcd; +// BOARD_TUH_RHPORT is kept commented out to ease re-adding host later. +#ifndef BOARD_TUD_RHPORT +#define BOARD_TUD_RHPORT 0 +#endif +// #ifndef BOARD_TUH_RHPORT +// #define BOARD_TUH_RHPORT 1 +// #endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/hw/bsp/ch58x/boards/ch582m_evt/board.mk b/hw/bsp/ch58x/boards/ch582m_evt/board.mk new file mode 100644 index 000000000..a13979799 --- /dev/null +++ b/hw/bsp/ch58x/boards/ch582m_evt/board.mk @@ -0,0 +1,3 @@ +LDFLAGS += \ + -Wl,--defsym=__FLASH_SIZE=448K \ + -Wl,--defsym=__RAM_SIZE=32K \ diff --git a/hw/bsp/ch58x/boards/yd-ch582m/board.h b/hw/bsp/ch58x/boards/yd-ch582m/board.h index a14ffd198..0da5747bc 100644 --- a/hw/bsp/ch58x/boards/yd-ch582m/board.h +++ b/hw/bsp/ch58x/boards/yd-ch582m/board.h @@ -45,14 +45,14 @@ extern "C" { // UART: UART1 TX=PA9, RX=PA8 #define CFG_BOARD_UART_BAUDRATE 115200 -// Dual-port: USB1 (rhport 0) = Device, USB2 (rhport 1) = Host -// Swap these two if you want the opposite assignment +// Device only on USB1 (rhport 0). CH58x host / USB2 is not supported by the shared usbfs dcd; +// BOARD_TUH_RHPORT is kept commented out to ease re-adding host later. #ifndef BOARD_TUD_RHPORT #define BOARD_TUD_RHPORT 0 #endif -#ifndef BOARD_TUH_RHPORT -#define BOARD_TUH_RHPORT 1 -#endif +// #ifndef BOARD_TUH_RHPORT +// #define BOARD_TUH_RHPORT 1 +// #endif #ifdef __cplusplus } diff --git a/hw/bsp/ch58x/ch58x_it.h b/hw/bsp/ch58x/ch58x_it.h index 18ea52bc9..3e050344d 100644 --- a/hw/bsp/ch58x/ch58x_it.h +++ b/hw/bsp/ch58x/ch58x_it.h @@ -36,7 +36,7 @@ extern "C" { void NMI_Handler(void); void HardFault_Handler(void); void USB_IRQHandler(void); -void USB2_IRQHandler(void); +// void USB2_IRQHandler(void); // host on USB2 (rhport 1) — re-add together with the host driver void SysTick_Handler(void); #ifdef __cplusplus diff --git a/hw/bsp/ch58x/family.c b/hw/bsp/ch58x/family.c index 3b1382e61..8e5f2826b 100644 --- a/hw/bsp/ch58x/family.c +++ b/hw/bsp/ch58x/family.c @@ -50,13 +50,16 @@ // Forward USB interrupt events to TinyUSB IRQ Handler //--------------------------------------------------------------------+ +// Device only: the shared dcd_ch32_usbfs.c drives USB0 (rhport 0). CH58x's second controller +// (USB2 / rhport 1) was driven by the now-removed ch58x host driver; its handler is kept +// commented out below to ease re-adding host support. __INTERRUPT __HIGH_CODE void USB_IRQHandler(void) { tusb_int_handler(0, true); } -__INTERRUPT __HIGH_CODE void USB2_IRQHandler(void) { - tusb_int_handler(1, true); -} +// __INTERRUPT __HIGH_CODE void USB2_IRQHandler(void) { +// tusb_int_handler(1, true); +// } //--------------------------------------------------------------------+ // SysTick @@ -111,16 +114,12 @@ void board_init(void) { #endif #endif - // USB pin enable: enable analog function for USB1 and USB2 D+/D- - R16_PIN_ANALOG_IE |= RB_PIN_USB_IE | RB_PIN_USB2_IE; - - // D+ pull-up is only needed for the device-role port + // Device only on USB0 (rhport 0): enable analog function for USB1 D+/D- and assert its D+ + // pull-up. The shared dcd_ch32_usbfs.c drives USB0; CH58x host / USB2 (rhport 1) is unsupported + // here — to re-add host, also OR in RB_PIN_USB2_IE below. + R16_PIN_ANALOG_IE |= RB_PIN_USB_IE; // | RB_PIN_USB2_IE (re-add for host on USB2) #if CFG_TUD_ENABLED - #if BOARD_TUD_RHPORT == 0 - R16_PIN_ANALOG_IE |= RB_PIN_USB_DP_PU; - #else - R16_PIN_ANALOG_IE |= RB_PIN_USB2_DP_PU; - #endif + R16_PIN_ANALOG_IE |= RB_PIN_USB_DP_PU; #endif // Keep USB clock active during sleep @@ -164,6 +163,10 @@ uint32_t board_button_read(void) { #endif } +// Note: CH58x exposes no memory-mapped unique-ID register (unlike ch32v10x/v20x at +// 0x1FFFF7E8), and the SDK's GET_UNIQUE_ID() is a BootROM stub not present in +// libISP583.a. So board_get_unique_id() falls back to the fixed default in board.c. + int board_uart_read(uint8_t* buf, int len) { (void) buf; (void) len; diff --git a/hw/bsp/ch58x/family.cmake b/hw/bsp/ch58x/family.cmake index b4835cb41..cbe1ffe72 100644 --- a/hw/bsp/ch58x/family.cmake +++ b/hw/bsp/ch58x/family.cmake @@ -77,8 +77,7 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/debug_uart.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c - ${TOP}/src/portable/wch/dcd_ch58x_usbfs.c - ${TOP}/src/portable/wch/hcd_ch58x_usbfs.c + ${TOP}/src/portable/wch/dcd_ch32_usbfs.c ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC diff --git a/hw/bsp/ch58x/family.mk b/hw/bsp/ch58x/family.mk index 71c2cada6..2ef90a8c3 100644 --- a/hw/bsp/ch58x/family.mk +++ b/hw/bsp/ch58x/family.mk @@ -33,8 +33,7 @@ LDFLAGS_GCC += \ LIBS += $(TOP)/$(SDK_SRC_DIR)/StdPeriphDriver/libISP583.a SRC_C += \ - src/portable/wch/dcd_ch58x_usbfs.c \ - src/portable/wch/hcd_ch58x_usbfs.c \ + src/portable/wch/dcd_ch32_usbfs.c \ $(SDK_SRC_DIR)/StdPeriphDriver/CH58x_gpio.c \ $(SDK_SRC_DIR)/StdPeriphDriver/CH58x_clk.c \ $(SDK_SRC_DIR)/StdPeriphDriver/CH58x_uart1.c \ diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index 8408d3ae0..f2a2d92a5 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -660,17 +660,16 @@ #endif #elif TU_CHECK_MCU(OPT_MCU_CH58X) - // CH582/583 has 2 independent USBFS controllers with merged EP registers, FS only. - #define TUP_USBIP_WCH_CH58X + // CH582/583 USBFS: older WCH USBFS IP with a single combined per-endpoint control register + // (like CH32V103), driven by the shared dcd_ch32_usbfs.c on USB0 (rhport 0). Device only: + // the shared hcd_ch32_usbfs.c is CH32V20x-specific and does not support CH58x, so host / + // USB2 (rhport 1) is not provided here. + #define TUP_USBIP_WCH_USBFS #ifndef CFG_TUD_WCH_USBIP_USBFS #define CFG_TUD_WCH_USBIP_USBFS 1 #endif - #ifndef CFG_TUH_WCH_USBIP_USBFS - #define CFG_TUH_WCH_USBIP_USBFS 1 - #endif - #define TUP_DCD_ENDPOINT_MAX 8 //--------------------------------------------------------------------+ diff --git a/src/portable/wch/ch32_usbfs_reg.h b/src/portable/wch/ch32_usbfs_reg.h index 7ffdc6cef..0d61e183c 100644 --- a/src/portable/wch/ch32_usbfs_reg.h +++ b/src/portable/wch/ch32_usbfs_reg.h @@ -130,6 +130,53 @@ #elif CFG_TUSB_MCU == OPT_MCU_CH32V307 #include #define USBHD_IRQn OTG_FS_IRQn +#elif CFG_TUSB_MCU == OPT_MCU_CH58X + #include "CH58x_common.h" + // CH582/583 USBFS device controller: same combined per-endpoint control register as + // CH32V103 (IN response bits[1:0], OUT response bits[3:2]) but a different register map - + // the EP control/length block sits lower (EP0_CTRL @ +0x22), EP5-7 are split out, EP4 + // shares EP0's DMA buffer, and EP5/6/7 mode bits live in one UEP567_MOD. The control/status + // block matches CH32. Two FS controllers exist (USB @ 0x40008000, USB2 @ 0x40008400); the + // device uses USB0. EP registers are accessed via the CH58X macros below (not the struct). + #define CH58X_USBFS_BASE 0x40008000u + typedef struct { + __IO uint8_t BASE_CTRL; // 0x00 + __IO uint8_t UDEV_CTRL; // 0x01 + __IO uint8_t INT_EN; // 0x02 + __IO uint8_t DEV_ADDR; // 0x03 + __IO uint8_t Reserve0; // 0x04 + __IO uint8_t MIS_ST; // 0x05 + __IO uint8_t INT_FG; // 0x06 + __IO uint8_t INT_ST; // 0x07 + __IO uint8_t RX_LEN; // 0x08 (8-bit on CH58X) + __IO uint8_t Reserve1[3]; // 0x09..0x0B + __IO uint8_t UEP4_1_MOD; // 0x0C + __IO uint8_t UEP2_3_MOD; // 0x0D + __IO uint8_t UEP567_MOD; // 0x0E + } USBOTG_FS_TypeDef; + #define USBOTG_FS ((USBOTG_FS_TypeDef *) CH58X_USBFS_BASE) + + #define CH32_USBFS_EP_CTRL_COMBINED 1 + #define CH32_USBFS_EP_REGS_CUSTOM 1 // EP register macros provided here, not by the driver + // CH58x's hardware AUTO_TOG does not stay in sync (notably across clear-stall and multi-packet + // bulk transfers), causing data-toggle mismatch and bus resets. Drive the toggle manually in + // the ISR instead. CH32V103/V20x/V307 keep AUTO_TOG (this macro is undefined for them). + #define CH32_USBFS_EP_MANUAL_TOG 1 + // CH58x EP4 has no DMA register of its own: it overlays EP0's DMA region as + // EP0[0:63] + EP4_OUT[64:127] + EP4_IN[128:191], so EP0 needs a 192-byte buffer. + #define CH32_USBFS_EP4_SHARES_EP0 1 + #define USBHD_IRQn USB_IRQn + #ifndef NVIC_EnableIRQ + #define NVIC_EnableIRQ(n) PFIC_EnableIRQ(n) + #define NVIC_DisableIRQ(n) PFIC_DisableIRQ(n) + #endif + + // EP register access. EP0-4: T_LEN @ +0x20+ep*4, CTRL @ +0x22+ep*4. EP5-7 split: T_LEN @ + // +0x64, CTRL @ +0x66. DMA: EP0-3 @ +0x10+ep*4, EP5-7 @ +0x54; EP4 shares EP0's buffer + // (no own DMA reg) so its slot points at a reserved word. + #define EP_TX_LEN(ep) (*(volatile uint8_t *)(CH58X_USBFS_BASE + ((ep) <= 4u ? 0x20u + (ep)*4u : 0x64u + ((ep)-5u)*4u))) + #define EP_CTRL(ep) (*(volatile uint8_t *)(CH58X_USBFS_BASE + ((ep) <= 4u ? 0x22u + (ep)*4u : 0x66u + ((ep)-5u)*4u))) + #define EP_DMA(ep) (*(volatile uint16_t *)(CH58X_USBFS_BASE + ((ep) <= 3u ? 0x10u + (ep)*4u : (ep) == 4u ? 0x40u : 0x54u + ((ep)-5u)*4u))) #endif #ifdef __GNUC__ @@ -170,6 +217,7 @@ // INT_ST #define USBFS_INT_ST_MASK_UIS_ENDP(x) (((x) >> 0) & 0x0F) #define USBFS_INT_ST_MASK_UIS_TOKEN(x) (((x) >> 4) & 0x03) +#define USBFS_INT_ST_TOG_OK (1 << 6) // received packet's data toggle matched expectation // UDEV_CTRL #define USBFS_UDEV_CTRL_PORT_EN (1 << 0) diff --git a/src/portable/wch/ch58x_usbfs_reg.h b/src/portable/wch/ch58x_usbfs_reg.h deleted file mode 100644 index 67b47e0b6..000000000 --- a/src/portable/wch/ch58x_usbfs_reg.h +++ /dev/null @@ -1,291 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2024 TinyUSB contributors - * - * 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 CH58X_USBFS_REG_H -#define CH58X_USBFS_REG_H - -#include - -//--------------------------------------------------------------------+ -// USB Base Addresses -//--------------------------------------------------------------------+ -#define CH58X_USB_BASE 0x40008000u -#define CH58X_USB2_BASE 0x40008400u - -//--------------------------------------------------------------------+ -// Global Control / Status Registers -//--------------------------------------------------------------------+ -#define CH58X_USB_CTRL(base) (*(volatile uint8_t *)((base) + 0x00)) -#define CH58X_UDEV_CTRL(base) (*(volatile uint8_t *)((base) + 0x01)) -#define CH58X_USB_INT_EN(base) (*(volatile uint8_t *)((base) + 0x02)) -#define CH58X_USB_DEV_AD(base) (*(volatile uint8_t *)((base) + 0x03)) -#define CH58X_USB_MIS_ST(base) (*(volatile uint8_t *)((base) + 0x05)) -#define CH58X_USB_INT_FG(base) (*(volatile uint8_t *)((base) + 0x06)) -#define CH58X_USB_INT_ST(base) (*(volatile uint8_t *)((base) + 0x07)) -#define CH58X_USB_RX_LEN(base) (*(volatile uint8_t *)((base) + 0x08)) - -//--------------------------------------------------------------------+ -// Endpoint Mode Registers -//--------------------------------------------------------------------+ -#define CH58X_UEP4_1_MOD(base) (*(volatile uint8_t *)((base) + 0x0C)) -#define CH58X_UEP2_3_MOD(base) (*(volatile uint8_t *)((base) + 0x0D)) -#define CH58X_UEP567_MOD(base) (*(volatile uint8_t *)((base) + 0x0E)) - -//--------------------------------------------------------------------+ -// Endpoint DMA / T_LEN / CTRL register accessors -//--------------------------------------------------------------------+ - -// EP DMA is 16-bit (only low 16 bits of RAM address, high bits implied 0x2000), EP4 shares EP0's DMA register (no independent DMA), so ep==4 maps to base+0x10 -#define CH58X_EP_DMA(base, ep) (*(volatile uint16_t *)((base) + ((ep) <= 3 ? (0x10u + (ep)*4u) : ((ep) == 4 ? 0x10u : (0x54u + ((ep)-5u)*4u))))) -#define CH58X_EP_TLEN(base, ep) (*(volatile uint8_t *)((base) + ((ep) <= 4 ? (0x20u + (ep)*4u) : (0x64u + ((ep)-5u)*4u)))) -#define CH58X_EP_CTRL(base, ep) (*(volatile uint8_t *)((base) + ((ep) <= 4 ? (0x22u + (ep)*4u) : (0x66u + ((ep)-5u)*4u)))) - -//--------------------------------------------------------------------+ -// USB_CTRL (R8_USB_CTRL) bit definitions -//--------------------------------------------------------------------+ -#define CH58X_UC_DMA_EN 0x01 -#define CH58X_UC_CLR_ALL 0x02 -#define CH58X_UC_RESET_SIE 0x04 -#define CH58X_UC_INT_BUSY 0x08 -#define CH58X_UC_SYS_CTRL 0x10 -#define CH58X_UC_DEV_PU_EN 0x20 -#define CH58X_UC_LOW_SPEED 0x40 -#define CH58X_UC_HOST_MODE 0x80 - -//--------------------------------------------------------------------+ -// UDEV_CTRL (R8_UDEV_CTRL) bit definitions -//--------------------------------------------------------------------+ -#define CH58X_UD_PORT_EN 0x01 -#define CH58X_UD_GP_BIT 0x02 -#define CH58X_UD_LOW_SPEED 0x04 -#define CH58X_UD_PD_DIS 0x80 - -//--------------------------------------------------------------------+ -// INT_EN (R8_USB_INT_EN) bit definitions -//--------------------------------------------------------------------+ -#define CH58X_UIE_BUS_RST 0x01 -#define CH58X_UIE_DETECT 0x01 /* host mode alias */ -#define CH58X_UIE_TRANSFER 0x02 -#define CH58X_UIE_SUSPEND 0x04 -#define CH58X_UIE_HST_SOF 0x08 -#define CH58X_UIE_FIFO_OV 0x10 - -//--------------------------------------------------------------------+ -// INT_FG (R8_USB_INT_FG) bit definitions -//--------------------------------------------------------------------+ -#define CH58X_UIF_BUS_RST 0x01 -#define CH58X_UIF_DETECT 0x01 /* host mode alias */ -#define CH58X_UIF_TRANSFER 0x02 -#define CH58X_UIF_SUSPEND 0x04 -#define CH58X_UIF_HST_SOF 0x08 -#define CH58X_UIF_FIFO_OV 0x10 -#define CH58X_U_SIE_FREE 0x20 -#define CH58X_U_TOG_OK 0x40 -#define CH58X_U_IS_NAK 0x80 - -//--------------------------------------------------------------------+ -// INT_ST (R8_USB_INT_ST) parsing -//--------------------------------------------------------------------+ -#define CH58X_INT_ST_ENDP(x) (((x) >> 0) & 0x0F) -#define CH58X_INT_ST_TOKEN(x) (((x) >> 4) & 0x03) -#define CH58X_UIS_TOG_OK 0x40 // toggle match flag (device and host) -#define CH58X_UIS_SETUP_ACT 0x80 - -// Token PID values -#define CH58X_PID_OUT 0 -#define CH58X_PID_SOF 1 -#define CH58X_PID_IN 2 -#define CH58X_PID_SETUP 3 - -//--------------------------------------------------------------------+ -// MIS_ST (R8_USB_MIS_ST) bit definitions -//--------------------------------------------------------------------+ -#define CH58X_UMS_DEV_ATTACH 0x01 -#define CH58X_UMS_DM_LEVEL 0x02 -#define CH58X_UMS_SUSPEND 0x04 -#define CH58X_UMS_BUS_RESET 0x08 -#define CH58X_UMS_R_FIFO_RDY 0x10 -#define CH58X_UMS_SIE_FREE 0x20 -#define CH58X_UMS_SOF_ACT 0x40 -#define CH58X_UMS_SOF_PRES 0x80 - -//--------------------------------------------------------------------+ -// EP CTRL register bit definitions (merged TX+RX in single 8-bit reg) -// -// Bit 7: RB_UEP_R_TOG RX data toggle -// Bit 6: RB_UEP_T_TOG TX data toggle -// Bit 5: (reserved) -// Bit 4: RB_UEP_AUTO_TOG auto toggle (EP1/2/3/5/6/7, not EP0/EP4) -// Bit 3: R_RES1 RX response high -// Bit 2: R_RES0 RX response low -// Bit 1: T_RES1 TX response high -// Bit 0: T_RES0 TX response low -//--------------------------------------------------------------------+ - -// TX response bits[1:0] -#define CH58X_EP_T_RES_MASK 0x03 -#define CH58X_EP_T_RES_ACK 0x00 -#define CH58X_EP_T_RES_TOUT 0x01 /* ISO: no handshake */ -#define CH58X_EP_T_RES_NAK 0x02 -#define CH58X_EP_T_RES_STALL 0x03 - -// RX response bits[3:2] -#define CH58X_EP_R_RES_MASK 0x0C -#define CH58X_EP_R_RES_ACK 0x00 -#define CH58X_EP_R_RES_TOUT 0x04 /* ISO: no handshake */ -#define CH58X_EP_R_RES_NAK 0x08 -#define CH58X_EP_R_RES_STALL 0x0C - -// Toggle and auto-toggle -#define CH58X_EP_AUTO_TOG 0x10 /* bit 4, shared TX/RX */ -#define CH58X_EP_T_TOG 0x40 /* bit 6, TX DATA toggle */ -#define CH58X_EP_R_TOG 0x80 /* bit 7, RX DATA toggle */ - -//--------------------------------------------------------------------+ -// EP Mode register (UEP4_1_MOD) bit definitions -//--------------------------------------------------------------------+ -// R8_UEP4_1_MOD: EP4 in bits[3:2], EP1 in bits[7:4] -#define CH58X_UEP1_BUF_MOD 0x10 -#define CH58X_UEP1_TX_EN 0x40 -#define CH58X_UEP1_RX_EN 0x80 -#define CH58X_UEP4_TX_EN 0x04 -#define CH58X_UEP4_RX_EN 0x08 - -// R8_UEP2_3_MOD: EP3 in bits[7:4], EP2 in bits[3:0] -#define CH58X_UEP2_BUF_MOD 0x01 -#define CH58X_UEP2_TX_EN 0x04 -#define CH58X_UEP2_RX_EN 0x08 -#define CH58X_UEP3_BUF_MOD 0x10 -#define CH58X_UEP3_TX_EN 0x40 -#define CH58X_UEP3_RX_EN 0x80 - -// R8_UEP567_MOD -#define CH58X_UEP5_TX_EN 0x01 -#define CH58X_UEP5_RX_EN 0x02 -#define CH58X_UEP6_TX_EN 0x04 -#define CH58X_UEP6_RX_EN 0x08 -#define CH58X_UEP7_TX_EN 0x10 -#define CH58X_UEP7_RX_EN 0x20 - -//--------------------------------------------------------------------+ -// Host-mode Register Aliases -// In host mode: EP2 -> RX, EP3 -> TX, EP1_CTRL -> SETUP -//--------------------------------------------------------------------+ -#define CH58X_UHOST_CTRL(base) (*(volatile uint8_t *)((base) + 0x01)) // = UDEV_CTRL -#define CH58X_UH_EP_MOD(base) (*(volatile uint8_t *)((base) + 0x0D)) // = UEP2_3_MOD -#define CH58X_UH_RX_DMA(base) (*(volatile uint16_t *)((base) + 0x18)) // = UEP2_DMA -#define CH58X_UH_TX_DMA(base) (*(volatile uint16_t *)((base) + 0x1C)) // = UEP3_DMA -#define CH58X_UH_SETUP(base) (*(volatile uint8_t *)((base) + 0x26)) // = UEP1_CTRL -#define CH58X_UH_EP_PID(base) (*(volatile uint8_t *)((base) + 0x28)) // = UEP2_T_LEN -#define CH58X_UH_RX_CTRL(base) (*(volatile uint8_t *)((base) + 0x2A)) // = UEP2_CTRL -#define CH58X_UH_TX_LEN(base) (*(volatile uint8_t *)((base) + 0x2C)) // = UEP3_T_LEN -#define CH58X_UH_TX_CTRL(base) (*(volatile uint8_t *)((base) + 0x2E)) // = UEP3_CTRL - -//--------------------------------------------------------------------+ -// UHOST_CTRL (R8_UHOST_CTRL) bit definitions -//--------------------------------------------------------------------+ -#define CH58X_UH_PD_DIS 0x80 -#define CH58X_UH_LOW_SPEED 0x04 -#define CH58X_UH_BUS_RESET 0x02 -#define CH58X_UH_PORT_EN 0x01 - -//--------------------------------------------------------------------+ -// UH_EP_MOD (R8_UH_EP_MOD) bit definitions -//--------------------------------------------------------------------+ -#define CH58X_UH_EP_TX_EN 0x40 -#define CH58X_UH_EP_TBUF_MOD 0x10 -#define CH58X_UH_EP_RX_EN 0x08 -#define CH58X_UH_EP_RBUF_MOD 0x01 - -//--------------------------------------------------------------------+ -// UH_SETUP (R8_UH_SETUP) bit definitions -//--------------------------------------------------------------------+ -#define CH58X_UH_PRE_PID_EN 0x80 -#define CH58X_UH_SOF_EN 0x40 - -//--------------------------------------------------------------------+ -// UH_RX_CTRL (R8_UH_RX_CTRL) bit definitions -//--------------------------------------------------------------------+ -#define CH58X_UH_R_TOG 0x80 -#define CH58X_UH_R_AUTO_TOG 0x10 -#define CH58X_UH_R_RES 0x04 - -//--------------------------------------------------------------------+ -// UH_TX_CTRL (R8_UH_TX_CTRL) bit definitions -//--------------------------------------------------------------------+ -#define CH58X_UH_T_TOG 0x40 -#define CH58X_UH_T_AUTO_TOG 0x10 -#define CH58X_UH_T_RES 0x01 - -//--------------------------------------------------------------------+ -// USB_INT_ST host-mode bits -//--------------------------------------------------------------------+ -#define CH58X_UIS_H_RES_MASK 0x0F - -//--------------------------------------------------------------------+ -// USB_DEV_AD bits -//--------------------------------------------------------------------+ -#define CH58X_UDA_GP_BIT 0x80 -#define CH58X_USB_ADDR_MASK 0x7F - -//--------------------------------------------------------------------+ -// Standard USB PID values (for host token and response) -//--------------------------------------------------------------------+ -#define CH58X_USB_PID_OUT 0x01 -#define CH58X_USB_PID_IN 0x09 -#define CH58X_USB_PID_SOF 0x05 -#define CH58X_USB_PID_SETUP 0x0D -#define CH58X_USB_PID_DATA0 0x03 -#define CH58X_USB_PID_DATA1 0x0B -#define CH58X_USB_PID_ACK 0x02 -#define CH58X_USB_PID_NAK 0x0A -#define CH58X_USB_PID_STALL 0x0E - -//--------------------------------------------------------------------+ -// PIN_ANALOG_IE register -//--------------------------------------------------------------------+ -#define CH58X_PIN_ANALOG_IE (*(volatile uint16_t *)0x4000101A) -#define CH58X_PIN_USB_DP_PU 0x40 -#define CH58X_PIN_USB_IE 0x80 -#define CH58X_PIN_USB2_DP_PU 0x10 -#define CH58X_PIN_USB2_IE 0x20 - -//--------------------------------------------------------------------+ -// Sleep clock control -//--------------------------------------------------------------------+ -#define CH58X_SLP_CLK_OFF1 (*(volatile uint8_t *)0x4000100D) -#define CH58X_SLP_CLK_USB 0x10 - -//--------------------------------------------------------------------+ -// PFIC (Platform-level Fast Interrupt Controller) -//--------------------------------------------------------------------+ -#define CH58X_PFIC_IENR ((volatile uint32_t *)0xE000E100) // interrupt enable -#define CH58X_PFIC_IRER ((volatile uint32_t *)0xE000E180) // interrupt reset (disable) - -#define CH58X_USB_IRQn 22 -#define CH58X_USB2_IRQn 23 - -#endif /* CH58X_USBFS_REG_H */ diff --git a/src/portable/wch/dcd_ch32_usbfs.c b/src/portable/wch/dcd_ch32_usbfs.c index dae31da91..7beb91e16 100644 --- a/src/portable/wch/dcd_ch32_usbfs.c +++ b/src/portable/wch/dcd_ch32_usbfs.c @@ -35,17 +35,23 @@ /* private defines */ #define EP_MAX (8) + // Struct-based EP register access (uniform layout). Some parts (e.g. CH58X) have a different + // register map and define EP_DMA/EP_TX_LEN/EP_CTRL themselves in ch32_usbfs_reg.h. + #ifndef CH32_USBFS_EP_REGS_CUSTOM #define EP_DMA(ep) ((&USBOTG_FS->UEP0_DMA)[ep]) #define EP_TX_LEN(ep) ((&USBOTG_FS->UEP0_TX_LEN)[2 * ep]) #define EP_TX_CTRL(ep) ((&USBOTG_FS->UEP0_TX_CTRL)[4 * ep]) #define EP_RX_CTRL(ep) ((&USBOTG_FS->UEP0_RX_CTRL)[4 * ep]) + #endif // Endpoint control register access. The newer USBFS IP (CH32V20x/V307/X035) has separate // TX_CTRL and RX_CTRL bytes per endpoint; the older IP (CH32V103) has a single combined // UEPn_CTRL register. These helpers hide the difference so the rest of the driver is shared. // Values use the newer-IP encoding (USBFS_EP_T_*/USBFS_EP_R_*); the combined path remaps them. #ifdef CH32_USBFS_EP_CTRL_COMBINED + #ifndef EP_CTRL // parts with a custom register map (CH58X) define EP_CTRL directly in reg.h #define EP_CTRL(ep) EP_TX_CTRL(ep) // UEPn_TX_CTRL field aliases the combined UEPn_CTRL register + #endif static inline uint8_t ep_tx_to_comb(uint8_t v) { uint8_t c = v & USBFS_EP_T_RES_MASK; // IN response: bits [1:0] in both encodings @@ -86,6 +92,17 @@ #define EP0_SETUP_RX_TOG 0 #endif +// Hardware auto data-toggle flag. Parts whose AUTO_TOG is reliable OR it into the EP setup so the +// controller flips DATA0/DATA1 itself; CH58x (CH32_USBFS_EP_MANUAL_TOG) leaves it clear and the +// ISR flips the toggle bit after each packet instead. +#ifdef CH32_USBFS_EP_MANUAL_TOG + #define EP_T_AUTO_TOG 0 + #define EP_R_AUTO_TOG 0 +#else + #define EP_T_AUTO_TOG USBFS_EP_T_AUTO_TOG + #define EP_R_AUTO_TOG USBFS_EP_R_AUTO_TOG +#endif + /* private data */ struct usb_xfer { bool valid; @@ -100,6 +117,12 @@ static struct { bool isochronous[EP_MAX]; struct usb_xfer xfer[EP_MAX][2]; TU_ATTR_ALIGNED(4) uint8_t buffer[EP_MAX][2][64]; +#ifdef CH32_USBFS_EP4_SHARES_EP0 + // CH58X: EP0 and EP4 share one DMA region (EP4 has no DMA register). Layout: + // EP0 [0:63] (half-duplex, OUT+IN) + EP4 OUT [64:127] + EP4 IN [128:191]. buffer[0]/buffer[4] + // are left unused for this part. + TU_ATTR_ALIGNED(4) uint8_t ep0_ep4_buffer[3 * 64]; +#endif TU_ATTR_ALIGNED(4) struct { // OUT transfers >64 bytes will overwrite queued IN data! uint8_t out[64]; @@ -108,19 +131,50 @@ static struct { } ep3_buffer; } data; +// DMA / copy buffer pointers per endpoint. The WCH USBFS buffer holds OUT (RX) at offset 0 and +// IN (TX) at +64; EP0 is half-duplex and reuses its OUT chunk for IN; EP3 has an enlarged IN +// buffer for throughput. On CH58X, EP4 overlays EP0's region (see ep0_ep4_buffer above). +static inline uint32_t ep_dma_addr(uint8_t ep) { +#ifdef CH32_USBFS_EP4_SHARES_EP0 + if (ep == 0) { return (uint32_t) &data.ep0_ep4_buffer[0]; } +#endif + if (ep == 3) { return (uint32_t) &data.ep3_buffer.out[0]; } + return (uint32_t) &data.buffer[ep][0]; +} +static inline uint8_t* ep_out_buf(uint8_t ep) { +#ifdef CH32_USBFS_EP4_SHARES_EP0 + if (ep == 0) { return &data.ep0_ep4_buffer[0]; } + if (ep == 4) { return &data.ep0_ep4_buffer[64]; } +#endif + if (ep == 3) { return data.ep3_buffer.out; } + return data.buffer[ep][TUSB_DIR_OUT]; +} +static inline uint8_t* ep_in_buf(uint8_t ep) { +#ifdef CH32_USBFS_EP4_SHARES_EP0 + if (ep == 0) { return &data.ep0_ep4_buffer[0]; } // EP0 half-duplex: IN reuses OUT chunk + if (ep == 4) { return &data.ep0_ep4_buffer[128]; } +#endif + if (ep == 0) { return data.buffer[0][TUSB_DIR_OUT]; } // EP0 half-duplex: IN reuses OUT chunk + if (ep == 3) { return data.ep3_buffer.in; } + return data.buffer[ep][TUSB_DIR_IN]; +} +// EP4 on CH58X has no DMA register (shares EP0's); skip its EP_DMA() write. +static inline bool ep_shares_ep0_dma(uint8_t ep) { +#ifdef CH32_USBFS_EP4_SHARES_EP0 + return ep == 4; +#else + (void) ep; + return false; +#endif +} + /* private helpers */ static void update_in(uint8_t rhport, uint8_t ep, bool force) { struct usb_xfer *xfer = &data.xfer[ep][TUSB_DIR_IN]; if (xfer->valid) { if (force || xfer->len) { size_t len = TU_MIN(xfer->max_size, xfer->len); - if (ep == 0) { - memcpy(data.buffer[ep][TUSB_DIR_OUT], xfer->buffer, len); // ep0 uses same chunk - } else if (ep == 3) { - memcpy(data.ep3_buffer.in, xfer->buffer, len); - } else { - memcpy(data.buffer[ep][TUSB_DIR_IN], xfer->buffer, len); - } + memcpy(ep_in_buf(ep), xfer->buffer, len); xfer->buffer += len; xfer->len -= len; xfer->processed_len += len; @@ -150,11 +204,7 @@ static void update_out(uint8_t rhport, uint8_t ep, size_t rx_len) { struct usb_xfer *xfer = &data.xfer[ep][TUSB_DIR_OUT]; if (xfer->valid) { size_t len = TU_MIN(xfer->max_size, TU_MIN(xfer->len, rx_len)); - if (ep == 3) { - memcpy(xfer->buffer, data.ep3_buffer.out, len); - } else { - memcpy(xfer->buffer, data.buffer[ep][TUSB_DIR_OUT], len); - } + memcpy(xfer->buffer, ep_out_buf(ep), len); xfer->buffer += len; xfer->len -= len; xfer->processed_len += len; @@ -176,12 +226,11 @@ static void update_out(uint8_t rhport, uint8_t ep, size_t rx_len) { static void reset_ep_ctrls(void) { for (uint8_t ep = 1; ep < EP_MAX; ep++) { - EP_DMA(ep) = (uint32_t)&data.buffer[ep][0]; + if (!ep_shares_ep0_dma(ep)) { EP_DMA(ep) = ep_dma_addr(ep); } EP_TX_LEN(ep) = 0; - ep_tx_ctrl_set(ep, USBFS_EP_T_AUTO_TOG | USBFS_EP_T_RES_NYET); - ep_rx_ctrl_set(ep, USBFS_EP_R_AUTO_TOG | USBFS_EP_R_RES_NYET); + ep_tx_ctrl_set(ep, EP_T_AUTO_TOG | USBFS_EP_T_RES_NYET); + ep_rx_ctrl_set(ep, EP_R_AUTO_TOG | USBFS_EP_R_RES_NYET); } - EP_DMA(3) = (uint32_t)&data.ep3_buffer.out[0]; } /* public functions */ @@ -195,8 +244,8 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t *rh_init) { USBOTG_FS->INT_FG = 0xFF; USBOTG_FS->INT_EN = USBFS_INT_EN_BUS_RST | USBFS_INT_EN_TRANSFER | USBFS_INT_EN_SUSPEND; - // setup endpoint 0 - EP_DMA(0) = (uint32_t)&data.buffer[0][0]; + // setup endpoint 0 (also backs EP4's buffer on CH58X via the shared DMA region) + EP_DMA(0) = ep_dma_addr(0); EP_TX_LEN(0) = 0; ep_tx_ctrl_set(0, USBFS_EP_T_RES_NAK); ep_rx_ctrl_set(0, USBFS_EP_R_RES_ACK); @@ -204,8 +253,14 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t *rh_init) { // enable other endpoints but NAK everything USBOTG_FS->UEP4_1_MOD = 0xCC; USBOTG_FS->UEP2_3_MOD = 0xCC; +#ifdef CH32_USBFS_EP_REGS_CUSTOM + // CH58X: a single mode register enables EP5/6/7 RX+TX (different bit layout than CH32). + USBOTG_FS->UEP567_MOD = RB_UEP5_RX_EN | RB_UEP5_TX_EN | RB_UEP6_RX_EN | RB_UEP6_TX_EN | + RB_UEP7_RX_EN | RB_UEP7_TX_EN; +#else USBOTG_FS->UEP5_6_MOD = 0xCC; USBOTG_FS->UEP7_MOD = 0x0C; +#endif reset_ep_ctrls(); @@ -218,17 +273,31 @@ void dcd_int_handler(uint8_t rhport) { (void)rhport; uint8_t status = USBOTG_FS->INT_FG; if (status & USBFS_INT_FG_TRANSFER) { - uint8_t ep = USBFS_INT_ST_MASK_UIS_ENDP(USBOTG_FS->INT_ST); - uint8_t token = USBFS_INT_ST_MASK_UIS_TOKEN(USBOTG_FS->INT_ST); + uint8_t int_st = USBOTG_FS->INT_ST; + uint8_t ep = USBFS_INT_ST_MASK_UIS_ENDP(int_st); + uint8_t token = USBFS_INT_ST_MASK_UIS_TOKEN(int_st); uint16_t rx_len = USBOTG_FS->RX_LEN; switch (token) { case PID_OUT: { +#ifdef CH32_USBFS_EP_MANUAL_TOG + // Manual toggle: drop OUT packets whose data toggle doesn't match (host retransmit), + // otherwise flip the expected RX toggle for the next packet. EP0 is driven by the + // SETUP/status flow below, so its toggle is left to that path. + if (ep != 0) { + if (!(int_st & USBFS_INT_ST_TOG_OK)) { break; } + EP_CTRL(ep) ^= USBFS_EPC_R_TOG; + } +#endif update_out(rhport, ep, rx_len); break; } case PID_IN: +#ifdef CH32_USBFS_EP_MANUAL_TOG + // Manual toggle: flip the TX toggle after each ACK'd IN packet (EP0 manages its own). + if (ep != 0) { EP_CTRL(ep) ^= USBFS_EPC_T_TOG; } +#endif update_in(rhport, ep, false); break; @@ -237,11 +306,12 @@ void dcd_int_handler(uint8_t rhport) { ep_tx_ctrl_set(0, USBFS_EP_T_RES_NAK); data.ep0_tog = true; - const tusb_control_request_t *setup = (const tusb_control_request_t *)&data.buffer[0][TUSB_DIR_OUT][0]; + uint8_t *ep0_out = ep_out_buf(0); + const tusb_control_request_t *setup = (const tusb_control_request_t *)ep0_out; // EP0_SETUP_RX_TOG arms the data/status stage at DATA1 on the combined-control IP ep_rx_ctrl_set(0, ((setup->wLength == 0) ? USBFS_EP_R_RES_ACK : USBFS_EP_R_RES_NAK) | EP0_SETUP_RX_TOG); - dcd_event_setup_received(rhport, &data.buffer[0][TUSB_DIR_OUT][0], true); + dcd_event_setup_received(rhport, ep0_out, true); break; } @@ -323,10 +393,12 @@ bool dcd_edpt_open(uint8_t rhport, const tusb_desc_endpoint_t *desc_ep) { data.xfer[ep][dir].max_size = tu_edpt_packet_size(desc_ep); if (ep != 0) { + // Opening clears the toggle to DATA0 (ep_*_ctrl_set writes the toggle bit clear since v has no + // R/T_TOG); with manual toggle EP_*_AUTO_TOG is 0 so the ISR owns subsequent toggling. if (dir == TUSB_DIR_OUT) { - ep_rx_ctrl_set(ep, USBFS_EP_R_AUTO_TOG | USBFS_EP_R_RES_NAK); + ep_rx_ctrl_set(ep, EP_R_AUTO_TOG | USBFS_EP_R_RES_NAK); } else { - ep_tx_ctrl_set(ep, USBFS_EP_T_AUTO_TOG | USBFS_EP_T_RES_NAK); + ep_tx_ctrl_set(ep, EP_T_AUTO_TOG | USBFS_EP_T_RES_NAK); } } return true; @@ -407,10 +479,11 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { ep_rx_ctrl_set(0, USBFS_EP_R_RES_ACK); } } else { + // clear-stall resets the toggle to DATA0 (USB spec); manual-toggle parts then re-sync via ISR if (dir == TUSB_DIR_OUT) { - ep_rx_ctrl_set(ep, USBFS_EP_R_AUTO_TOG | USBFS_EP_R_RES_NAK); + ep_rx_ctrl_set(ep, EP_R_AUTO_TOG | USBFS_EP_R_RES_NAK); } else { - ep_tx_ctrl_set(ep, USBFS_EP_T_AUTO_TOG | USBFS_EP_T_RES_NAK); + ep_tx_ctrl_set(ep, EP_T_AUTO_TOG | USBFS_EP_T_RES_NAK); } } } diff --git a/src/portable/wch/dcd_ch58x_usbfs.c b/src/portable/wch/dcd_ch58x_usbfs.c deleted file mode 100644 index c6f10b801..000000000 --- a/src/portable/wch/dcd_ch58x_usbfs.c +++ /dev/null @@ -1,636 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2024 TinyUSB contributors - * - * 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_TUD_ENABLED && defined(TUP_USBIP_WCH_CH58X) && CFG_TUD_WCH_USBIP_USBFS - -#include "device/dcd.h" -#include "ch58x_usbfs_reg.h" - -//--------------------------------------------------------------------+ -// Configuration -//--------------------------------------------------------------------+ -#define EP_MAX 8 -#define EP_BUF_SIZE 64 - -//--------------------------------------------------------------------+ -// USB base address selection by rhport -//--------------------------------------------------------------------+ -static inline uint32_t get_usb_base(uint8_t rhport) { - return (rhport == 0) ? CH58X_USB_BASE : CH58X_USB2_BASE; -} - -//--------------------------------------------------------------------+ -// Register access helpers using base address -//--------------------------------------------------------------------+ -#define USB_CTRL(base) CH58X_USB_CTRL(base) -#define USB_UDEV_CTRL(base) CH58X_UDEV_CTRL(base) -#define USB_INT_EN(base) CH58X_USB_INT_EN(base) -#define USB_DEV_AD(base) CH58X_USB_DEV_AD(base) -#define USB_MIS_ST(base) CH58X_USB_MIS_ST(base) -#define USB_INT_FG(base) CH58X_USB_INT_FG(base) -#define USB_INT_ST(base) CH58X_USB_INT_ST(base) -#define USB_RX_LEN(base) CH58X_USB_RX_LEN(base) - -#define EP_DMA(base, ep) CH58X_EP_DMA(base, ep) -#define EP_TLEN(base, ep) CH58X_EP_TLEN(base, ep) -#define EP_CTRL(base, ep) CH58X_EP_CTRL(base, ep) - -//--------------------------------------------------------------------+ -// Inline helpers for merged EP CTRL register -//--------------------------------------------------------------------+ -static inline void ep_set_tx_response(uint32_t base, uint8_t ep, uint8_t resp) { - uint8_t ctrl = EP_CTRL(base, ep); - ctrl = (ctrl & ~CH58X_EP_T_RES_MASK) | resp; - EP_CTRL(base, ep) = ctrl; -} - -static inline void ep_set_rx_response(uint32_t base, uint8_t ep, uint8_t resp) { - uint8_t ctrl = EP_CTRL(base, ep); - ctrl = (ctrl & ~CH58X_EP_R_RES_MASK) | resp; - EP_CTRL(base, ep) = ctrl; -} - -static inline void ep_set_both_response(uint32_t base, uint8_t ep, uint8_t tx_resp, uint8_t rx_resp) { - uint8_t ctrl = EP_CTRL(base, ep); - ctrl = (ctrl & ~(CH58X_EP_T_RES_MASK | CH58X_EP_R_RES_MASK)) | tx_resp | rx_resp; - EP_CTRL(base, ep) = ctrl; -} - -//--------------------------------------------------------------------+ -// Private data structures -//--------------------------------------------------------------------+ -typedef struct { - bool valid; - uint8_t* buffer; - size_t len; - size_t processed_len; - size_t max_size; -} xfer_ctl_t; - -typedef struct { - uint32_t usb_base; - bool ep0_tog; - volatile uint8_t setup_pending; // SETUP arrived while EP0 completion pending in queue - volatile bool ep0_completion_pending; // EP0 XFER_COMPLETE in event queue, not yet processed - uint8_t pending_addr; // Address to set in ISR after Set Address status ZLP - bool isochronous[EP_MAX][2]; // [ep][dir] - xfer_ctl_t xfer[EP_MAX][2]; // [ep][dir] - - // EP0 + EP4 shared buffer: EP0 OUT(64) + EP4 OUT(64) + EP4 IN(64) - TU_ATTR_ALIGNED(4) uint8_t ep0_buffer[EP_BUF_SIZE + EP_BUF_SIZE + EP_BUF_SIZE]; - - // EP1-EP3: OUT(64) + IN(64) - TU_ATTR_ALIGNED(4) uint8_t ep1_buffer[2][EP_BUF_SIZE]; - TU_ATTR_ALIGNED(4) uint8_t ep2_buffer[2][EP_BUF_SIZE]; - TU_ATTR_ALIGNED(4) uint8_t ep3_buffer[2][EP_BUF_SIZE]; - - // EP5-EP7: OUT(64) + IN(64) - TU_ATTR_ALIGNED(4) uint8_t ep5_buffer[2][EP_BUF_SIZE]; - TU_ATTR_ALIGNED(4) uint8_t ep6_buffer[2][EP_BUF_SIZE]; - TU_ATTR_ALIGNED(4) uint8_t ep7_buffer[2][EP_BUF_SIZE]; -} dcd_data_t; - -// Per-port data (support up to 2 USB ports) -static dcd_data_t _dcd_data[2]; - -//--------------------------------------------------------------------+ -// Buffer address helpers -//--------------------------------------------------------------------+ -static uint8_t* ep_out_buffer(dcd_data_t* d, uint8_t ep) { - switch (ep) { - case 0: return &d->ep0_buffer[0]; - case 1: return d->ep1_buffer[0]; - case 2: return d->ep2_buffer[0]; - case 3: return d->ep3_buffer[0]; - case 4: return &d->ep0_buffer[EP_BUF_SIZE]; - case 5: return d->ep5_buffer[0]; - case 6: return d->ep6_buffer[0]; - case 7: return d->ep7_buffer[0]; - default: return NULL; - } -} - -static uint8_t* ep_in_buffer(dcd_data_t* d, uint8_t ep) { - switch (ep) { - case 0: return &d->ep0_buffer[0]; // EP0 IN uses same buffer as OUT - case 1: return d->ep1_buffer[1]; - case 2: return d->ep2_buffer[1]; - case 3: return d->ep3_buffer[1]; - case 4: return &d->ep0_buffer[2 * EP_BUF_SIZE]; - case 5: return d->ep5_buffer[1]; - case 6: return d->ep6_buffer[1]; - case 7: return d->ep7_buffer[1]; - default: return NULL; - } -} - -// DMA base pointer (EP4 shares with EP0) -static uint8_t* ep_dma_buffer(dcd_data_t* d, uint8_t ep) { - switch (ep) { - case 0: case 4: return &d->ep0_buffer[0]; - case 1: return d->ep1_buffer[0]; - case 2: return d->ep2_buffer[0]; - case 3: return d->ep3_buffer[0]; - case 5: return d->ep5_buffer[0]; - case 6: return d->ep6_buffer[0]; - case 7: return d->ep7_buffer[0]; - default: return NULL; - } -} - -// AUTO_TOG is not used (EP1-3/5-7 support it). When clear-stall resets T_TOG/ -// R_TOG to DATA0, the hardware internal toggle doesn't sync, causing mismatch -// and bus resets. Use manual toggle (EP_CTRL ^= TOG) in ISR instead. - -//--------------------------------------------------------------------+ -// Private transfer helpers -//--------------------------------------------------------------------+ -static void update_in(uint8_t rhport, uint8_t ep, bool force, bool in_isr) { - dcd_data_t* d = &_dcd_data[rhport]; - uint32_t base = d->usb_base; - xfer_ctl_t* xfer = &d->xfer[ep][TUSB_DIR_IN]; - - if (xfer->valid) { - if (force || xfer->len) { - size_t len = TU_MIN(xfer->max_size, xfer->len); - - // Copy data to IN buffer - uint8_t* buf = ep_in_buffer(d, ep); - if (len > 0 && xfer->buffer != NULL) { - memcpy(buf, xfer->buffer, len); - } - - xfer->buffer += len; - xfer->len -= len; - xfer->processed_len += len; - - EP_TLEN(base, ep) = (uint8_t) len; - - if (ep == 0) { - // EP0: manual toggle - uint8_t ctrl = EP_CTRL(base, 0); - ctrl = (ctrl & ~(CH58X_EP_T_RES_MASK | CH58X_EP_T_TOG)); - ctrl |= CH58X_EP_T_RES_ACK; - if (d->ep0_tog) ctrl |= CH58X_EP_T_TOG; - EP_CTRL(base, 0) = ctrl; - d->ep0_tog = !d->ep0_tog; - } else if (d->isochronous[ep][TUSB_DIR_IN]) { - ep_set_tx_response(base, ep, CH58X_EP_T_RES_TOUT); - } else { - ep_set_tx_response(base, ep, CH58X_EP_T_RES_ACK); - } - } else { - // Transfer complete - xfer->valid = false; - ep_set_tx_response(base, ep, CH58X_EP_T_RES_NAK); - if (ep == 0) d->ep0_completion_pending = true; - dcd_event_xfer_complete(rhport, ep | TUSB_DIR_IN_MASK, - xfer->processed_len, XFER_RESULT_SUCCESS, in_isr); - } - } -} - -static void update_out(uint8_t rhport, uint8_t ep, size_t rx_len, bool in_isr) { - dcd_data_t* d = &_dcd_data[rhport]; - uint32_t base = d->usb_base; - xfer_ctl_t* xfer = &d->xfer[ep][TUSB_DIR_OUT]; - - if (xfer->valid) { - size_t len = TU_MIN(xfer->max_size, TU_MIN(xfer->len, rx_len)); - - // Copy from OUT buffer - if (len > 0 && xfer->buffer != NULL) { - uint8_t* buf = ep_out_buffer(d, ep); - memcpy(xfer->buffer, buf, len); - } - - xfer->buffer += len; - xfer->len -= len; - xfer->processed_len += len; - - if (xfer->len == 0 || len < xfer->max_size) { - xfer->valid = false; - // NAK to prevent hardware from accepting next OUT before a new xfer is queued - ep_set_rx_response(base, ep, CH58X_EP_R_RES_NAK); - if (ep == 0) d->ep0_completion_pending = true; - dcd_event_xfer_complete(rhport, ep, xfer->processed_len, - XFER_RESULT_SUCCESS, in_isr); - } else if (ep == 0) { - // EP0 multi-packet: ensure ACK for next packet - ep_set_rx_response(base, 0, CH58X_EP_R_RES_ACK); - } - } -} - -//--------------------------------------------------------------------+ -// DCD API Implementation -//--------------------------------------------------------------------+ - -bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { - (void) rh_init; - dcd_data_t* d = &_dcd_data[rhport]; - uint32_t base = get_usb_base(rhport); - d->usb_base = base; - - // Clear state - tu_memclr(d->xfer, sizeof(d->xfer)); - tu_memclr(d->isochronous, sizeof(d->isochronous)); - d->ep0_tog = true; - d->setup_pending = 0; - d->ep0_completion_pending = false; - d->pending_addr = 0; - - // Reset USB control register first (SDK pattern) - USB_CTRL(base) = 0x00; - - // Init control registers - USB_CTRL(base) = CH58X_UC_DEV_PU_EN | CH58X_UC_INT_BUSY | CH58X_UC_DMA_EN; - USB_UDEV_CTRL(base) = CH58X_UD_PD_DIS | CH58X_UD_PORT_EN; - USB_DEV_AD(base) = 0x00; - - // Clear all interrupt flags, then enable interrupts - USB_INT_FG(base) = 0xFF; - USB_INT_EN(base) = CH58X_UIE_BUS_RST | CH58X_UIE_TRANSFER | CH58X_UIE_SUSPEND; - - // EP0 setup (also sets EP4 DMA since they share) - EP_DMA(base, 0) = (uint16_t)(uint32_t) &d->ep0_buffer[0]; - EP_TLEN(base, 0) = 0; - EP_CTRL(base, 0) = CH58X_EP_R_RES_ACK | CH58X_EP_T_RES_NAK; - - // Enable all endpoints TX+RX - CH58X_UEP4_1_MOD(base) = CH58X_UEP1_RX_EN | CH58X_UEP1_TX_EN | - CH58X_UEP4_RX_EN | CH58X_UEP4_TX_EN; - CH58X_UEP2_3_MOD(base) = CH58X_UEP2_RX_EN | CH58X_UEP2_TX_EN | - CH58X_UEP3_RX_EN | CH58X_UEP3_TX_EN; - CH58X_UEP567_MOD(base) = CH58X_UEP5_RX_EN | CH58X_UEP5_TX_EN | - CH58X_UEP6_RX_EN | CH58X_UEP6_TX_EN | - CH58X_UEP7_RX_EN | CH58X_UEP7_TX_EN; - - // EP1-3: DMA + manual toggle + NAK both directions - for (uint8_t ep = 1; ep <= 3; ep++) { - EP_DMA(base, ep) = (uint16_t)(uint32_t) ep_dma_buffer(d, ep); - EP_TLEN(base, ep) = 0; - EP_CTRL(base, ep) = CH58X_EP_R_RES_NAK | CH58X_EP_T_RES_NAK; - } - - // EP4: no independent DMA, no auto-toggle - EP_TLEN(base, 4) = 0; - EP_CTRL(base, 4) = CH58X_EP_R_RES_NAK | CH58X_EP_T_RES_NAK; - - // EP5-7: DMA + manual toggle - for (uint8_t ep = 5; ep <= 7; ep++) { - EP_DMA(base, ep) = (uint16_t)(uint32_t) ep_dma_buffer(d, ep); - EP_TLEN(base, ep) = 0; - EP_CTRL(base, ep) = CH58X_EP_R_RES_NAK | CH58X_EP_T_RES_NAK; - } - - // Set EP0 max size - d->xfer[0][TUSB_DIR_OUT].max_size = EP_BUF_SIZE; - d->xfer[0][TUSB_DIR_IN].max_size = EP_BUF_SIZE; - - dcd_connect(rhport); - return true; -} - -void dcd_int_handler(uint8_t rhport) { - dcd_data_t* d = &_dcd_data[rhport]; - uint32_t base = d->usb_base; - uint8_t status = USB_INT_FG(base); - - if (status & CH58X_UIF_TRANSFER) { - uint8_t int_st = USB_INT_ST(base); - uint8_t ep = CH58X_INT_ST_ENDP(int_st); - uint8_t token = CH58X_INT_ST_TOKEN(int_st); - - // Process regular token before SETUP to avoid losing it - if (token != CH58X_PID_SETUP) { - switch (token) { - case CH58X_PID_OUT: { - uint8_t rx_len = USB_RX_LEN(base); - if (ep == 0) { - // EP0: manual toggle, always process - EP_CTRL(base, 0) ^= CH58X_EP_R_TOG; - update_out(rhport, 0, rx_len, true); - } else if (int_st & CH58X_UIS_TOG_OK) { - // Toggle OK: manual toggle and process - EP_CTRL(base, ep) ^= CH58X_EP_R_TOG; - update_out(rhport, ep, rx_len, true); - } - // else: toggle mismatch, discard - break; - } - - case CH58X_PID_IN: { - // Apply pending Set Address immediately after status ZLP - if (ep == 0 && d->pending_addr) { - USB_DEV_AD(base) = (USB_DEV_AD(base) & CH58X_UDA_GP_BIT) | - (d->pending_addr & CH58X_USB_ADDR_MASK); - d->pending_addr = 0; - } - if (ep != 0) { - // Manual toggle for all non-EP0 endpoints - EP_CTRL(base, ep) ^= CH58X_EP_T_TOG; - } - update_in(rhport, ep, false, true); - break; - } - - default: - break; - } - USB_INT_FG(base) = CH58X_UIF_TRANSFER; - } - - // SETUP_ACT is checked separately — it persists even if token field changed - if (int_st & CH58X_UIS_SETUP_ACT) { - // Reset toggles to DATA1, NAK both directions until stack is ready - EP_CTRL(base, 0) = CH58X_EP_R_TOG | CH58X_EP_T_TOG | - CH58X_EP_R_RES_NAK | CH58X_EP_T_RES_NAK; - d->ep0_tog = true; - - d->pending_addr = 0; - - // Mark stale EP0 completion so dcd_edpt_xfer can skip it - d->setup_pending = d->ep0_completion_pending ? 1 : 0; - d->ep0_completion_pending = false; - d->xfer[0][TUSB_DIR_OUT].valid = false; - d->xfer[0][TUSB_DIR_IN].valid = false; - - dcd_event_setup_received(rhport, ep_out_buffer(d, 0), true); - USB_INT_FG(base) = CH58X_UIF_TRANSFER; - } - } - - // Process bus reset: reset all endpoints immediately (matching WCH SDK pattern) - if (status & CH58X_UIF_BUS_RST) { - d->ep0_tog = true; - d->setup_pending = 0; - d->ep0_completion_pending = false; - d->pending_addr = 0; - - // Reset EP0: ACK for RX (ready for SETUP), NAK for TX - EP_CTRL(base, 0) = CH58X_EP_R_RES_ACK | CH58X_EP_T_RES_NAK; - EP_TLEN(base, 0) = 0; - d->xfer[0][TUSB_DIR_OUT].max_size = EP_BUF_SIZE; - d->xfer[0][TUSB_DIR_IN].max_size = EP_BUF_SIZE; - - // Reset EP1-7: NAK both directions, invalidate pending transfers - for (uint8_t ep = 1; ep < EP_MAX; ep++) { - d->xfer[ep][TUSB_DIR_IN].valid = false; - d->xfer[ep][TUSB_DIR_OUT].valid = false; - EP_CTRL(base, ep) = CH58X_EP_R_RES_NAK | CH58X_EP_T_RES_NAK; - EP_TLEN(base, ep) = 0; - } - - USB_DEV_AD(base) = 0x00; - - tusb_speed_t speed = (USB_CTRL(base) & CH58X_UC_LOW_SPEED) ? - TUSB_SPEED_LOW : TUSB_SPEED_FULL; - dcd_event_bus_reset(rhport, speed, true); - - USB_INT_FG(base) = CH58X_UIF_BUS_RST; - } - - // Process suspend/resume - if (status & CH58X_UIF_SUSPEND) { - dcd_event_bus_signal(rhport, - (USB_MIS_ST(base) & CH58X_UMS_SUSPEND) ? DCD_EVENT_SUSPEND : DCD_EVENT_RESUME, - true); - USB_INT_FG(base) = CH58X_UIF_SUSPEND; - } -} - -void dcd_int_enable(uint8_t rhport) { - uint8_t irqn = (rhport == 0) ? CH58X_USB_IRQn : CH58X_USB2_IRQn; - CH58X_PFIC_IENR[irqn / 32] = (1u << (irqn % 32)); -} - -void dcd_int_disable(uint8_t rhport) { - uint8_t irqn = (rhport == 0) ? CH58X_USB_IRQn : CH58X_USB2_IRQn; - CH58X_PFIC_IRER[irqn / 32] = (1u << (irqn % 32)); - __asm volatile ("fence.i"); -} - -void dcd_set_address(uint8_t rhport, uint8_t dev_addr) { - // Defer to ISR: apply address right after status ZLP is ACK'd - _dcd_data[rhport].pending_addr = dev_addr; - dcd_edpt_xfer(rhport, 0x80, NULL, 0, false); -} - -void dcd_remote_wakeup(uint8_t rhport) { - (void) rhport; - // TODO: not supported -} - -void dcd_connect(uint8_t rhport) { - uint32_t base = get_usb_base(rhport); - USB_CTRL(base) |= CH58X_UC_DEV_PU_EN; -} - -void dcd_disconnect(uint8_t rhport) { - uint32_t base = get_usb_base(rhport); - USB_CTRL(base) &= ~CH58X_UC_DEV_PU_EN; -} - -void dcd_sof_enable(uint8_t rhport, bool en) { - (void) rhport; - (void) en; -} - -void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const* request) { - dcd_data_t* d = &_dcd_data[rhport]; - uint32_t base = d->usb_base; - - if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE && - request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && - request->bRequest == TUSB_REQ_SET_ADDRESS) { - // Safety net: re-apply address in case ISR path was skipped - USB_DEV_AD(base) = (USB_DEV_AD(base) & CH58X_UDA_GP_BIT) | - ((uint8_t)request->wValue & CH58X_USB_ADDR_MASK); - } - - dcd_int_disable(rhport); - d->ep0_completion_pending = false; - if (d->setup_pending) { - // SETUP already arrived — don't override its NAK with ACK - d->setup_pending = 0; - } else { - ep_set_both_response(base, 0, CH58X_EP_T_RES_NAK, CH58X_EP_R_RES_ACK); - } - dcd_int_enable(rhport); -} - -bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const* desc_ep) { - dcd_data_t* d = &_dcd_data[rhport]; - uint32_t base = d->usb_base; - uint8_t ep = tu_edpt_number(desc_ep->bEndpointAddress); - uint8_t dir = tu_edpt_dir(desc_ep->bEndpointAddress); - TU_ASSERT(ep < EP_MAX); - - d->isochronous[ep][dir] = (desc_ep->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS); - uint16_t max_size = tu_edpt_packet_size(desc_ep); - if (max_size > EP_BUF_SIZE) { - max_size = EP_BUF_SIZE; - } - d->xfer[ep][dir].max_size = max_size; - - if (ep != 0) { - dcd_int_disable(rhport); - uint8_t ctrl = EP_CTRL(base, ep); - if (dir == TUSB_DIR_OUT) { - // Clear RX toggle to DATA0 per USB spec - ctrl &= ~CH58X_EP_R_TOG; - if (d->isochronous[ep][TUSB_DIR_OUT]) { - ctrl = (ctrl & ~CH58X_EP_R_RES_MASK) | CH58X_EP_R_RES_TOUT; - } else { - // Start with NAK; dcd_edpt_xfer will set ACK when a transfer is submitted - ctrl = (ctrl & ~CH58X_EP_R_RES_MASK) | CH58X_EP_R_RES_NAK; - } - } else { - // Clear TX toggle to DATA0 per USB spec - ctrl &= ~CH58X_EP_T_TOG; - EP_TLEN(base, ep) = 0; - ctrl = (ctrl & ~CH58X_EP_T_RES_MASK) | CH58X_EP_T_RES_NAK; - } - EP_CTRL(base, ep) = ctrl; - dcd_int_enable(rhport); - } - return true; -} - -void dcd_edpt_close_all(uint8_t rhport) { - dcd_data_t* d = &_dcd_data[rhport]; - uint32_t base = d->usb_base; - - for (uint8_t ep = 1; ep < EP_MAX; ep++) { - d->xfer[ep][TUSB_DIR_IN].valid = false; - d->xfer[ep][TUSB_DIR_OUT].valid = false; - d->isochronous[ep][TUSB_DIR_OUT] = false; - d->isochronous[ep][TUSB_DIR_IN] = false; - EP_CTRL(base, ep) = CH58X_EP_R_RES_NAK | CH58X_EP_T_RES_NAK; - } -} - -bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { - (void) rhport; - (void) ep_addr; - (void) largest_packet_size; - return false; -} - -bool dcd_edpt_iso_activate(uint8_t rhport, const tusb_desc_endpoint_t* desc_ep) { - (void) rhport; - (void) desc_ep; - return false; -} - -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, - uint16_t total_bytes, bool is_isr) { - uint8_t ep = tu_edpt_number(ep_addr); - uint8_t dir = tu_edpt_dir(ep_addr); - - dcd_data_t* d = &_dcd_data[rhport]; - xfer_ctl_t* xfer = &d->xfer[ep][dir]; - - dcd_int_disable(rhport); - - // Skip stale EP0 arm if a new SETUP has already arrived - if (ep == 0) { - d->ep0_completion_pending = false; - if (d->setup_pending) { - d->setup_pending = 0; - dcd_int_enable(rhport); - return true; - } - } - - xfer->valid = true; - xfer->buffer = buffer; - xfer->len = total_bytes; - xfer->processed_len = 0; - - if (dir == TUSB_DIR_IN) { - update_in(rhport, ep, true, is_isr); - } else { - if (d->isochronous[ep][TUSB_DIR_OUT]) { - ep_set_rx_response(d->usb_base, ep, CH58X_EP_R_RES_TOUT); - } else { - ep_set_rx_response(d->usb_base, ep, CH58X_EP_R_RES_ACK); - } - } - dcd_int_enable(rhport); - return true; -} - -void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { - dcd_data_t* d = &_dcd_data[rhport]; - uint32_t base = d->usb_base; - uint8_t ep = tu_edpt_number(ep_addr); - uint8_t dir = tu_edpt_dir(ep_addr); - - dcd_int_disable(rhport); - if (ep == 0) { - // EP0: stall both directions - EP_CTRL(base, 0) = CH58X_EP_R_RES_STALL | CH58X_EP_T_RES_STALL | - CH58X_EP_R_TOG | CH58X_EP_T_TOG; - } else { - if (dir == TUSB_DIR_OUT) { - ep_set_rx_response(base, ep, CH58X_EP_R_RES_STALL); - } else { - ep_set_tx_response(base, ep, CH58X_EP_T_RES_STALL); - } - } - dcd_int_enable(rhport); -} - -void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { - dcd_data_t* d = &_dcd_data[rhport]; - uint32_t base = d->usb_base; - uint8_t ep = tu_edpt_number(ep_addr); - uint8_t dir = tu_edpt_dir(ep_addr); - - dcd_int_disable(rhport); - if (ep == 0) { - if (dir == TUSB_DIR_OUT) { - ep_set_rx_response(base, 0, CH58X_EP_R_RES_ACK); - } - } else { - uint8_t ctrl = EP_CTRL(base, ep); - if (dir == TUSB_DIR_OUT) { - ctrl &= ~(CH58X_EP_R_RES_MASK | CH58X_EP_R_TOG); - ctrl |= CH58X_EP_R_RES_ACK; - } else { - ctrl &= ~(CH58X_EP_T_RES_MASK | CH58X_EP_T_TOG); - ctrl |= CH58X_EP_T_RES_NAK; - } - EP_CTRL(base, ep) = ctrl; - } - dcd_int_enable(rhport); -} - -#endif /* CFG_TUD_ENABLED && TUP_USBIP_WCH_CH58X */ diff --git a/src/portable/wch/hcd_ch58x_usbfs.c b/src/portable/wch/hcd_ch58x_usbfs.c deleted file mode 100644 index 37dd08539..000000000 --- a/src/portable/wch/hcd_ch58x_usbfs.c +++ /dev/null @@ -1,721 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2024 TinyUSB contributors - * - * 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_CH58X) && \ - 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" - -#include "ch58x_usbfs_reg.h" - -//--------------------------------------------------------------------+ -// Configuration -//--------------------------------------------------------------------+ -#define USBFS_MAX_PACKET_SIZE 64 - -#define LOG_CH58X_HCD(...) TU_LOG3(__VA_ARGS__) - -//--------------------------------------------------------------------+ -// RX/TX buffers (must be 4-byte aligned and in lower 64KB of RAM) -// Separate buffers for each USB port to avoid DMA conflicts -//--------------------------------------------------------------------+ -TU_ATTR_ALIGNED(4) static uint8_t _rx_buf[2][USBFS_MAX_PACKET_SIZE]; -TU_ATTR_ALIGNED(4) static uint8_t _tx_buf[2][USBFS_MAX_PACKET_SIZE]; - -//--------------------------------------------------------------------+ -// USB base address selection by rhport -//--------------------------------------------------------------------+ -static inline uint32_t _get_usb_base(uint8_t rhport) { - return (rhport == 0) ? CH58X_USB_BASE : CH58X_USB2_BASE; -} - -//--------------------------------------------------------------------+ -// Endpoint record -//--------------------------------------------------------------------+ -typedef struct { - bool configured; - uint8_t dev_addr; - uint8_t ep_addr; - uint8_t max_packet_size; - uint8_t xfer_type; - uint8_t data_toggle; // 0=DATA0, 1=DATA1 - bool is_nak_pending; - uint16_t buflen; - uint8_t* buf; -} hcd_edpt_t; - -static hcd_edpt_t _edpt_list[CFG_TUH_DEVICE_MAX * 6] = {}; - -//--------------------------------------------------------------------+ -// Current transfer state (only one transfer at a time per root port) -//--------------------------------------------------------------------+ -typedef struct { - volatile bool is_busy; - uint8_t rhport; - uint8_t dev_addr; - uint8_t ep_addr; - uint32_t start_ms; - uint8_t* buffer; - uint16_t bufferlen; - uint16_t xferred_len; - bool nak_pending; -} hcd_xfer_t; - -// One transfer state per root port (indexed by rhport). -static volatile hcd_xfer_t _current_xfer[2] = {}; - -//--------------------------------------------------------------------+ -// Per-port state -//--------------------------------------------------------------------+ -typedef struct { - uint32_t usb_base; - bool int_enabled; - bool int_state_before_reset; -} hcd_port_t; - -static hcd_port_t _port_data[2] = {}; - -//--------------------------------------------------------------------+ -// Endpoint record management -//--------------------------------------------------------------------+ -static hcd_edpt_t* _get_edpt(uint8_t dev_addr, uint8_t ep_addr) { - for (size_t i = 0; i < TU_ARRAY_SIZE(_edpt_list); i++) { - hcd_edpt_t* e = &_edpt_list[i]; - if (e->configured && e->dev_addr == dev_addr && e->ep_addr == ep_addr) { - return e; - } - } - return NULL; -} - -static hcd_edpt_t* _alloc_edpt(void) { - for (size_t i = 0; i < TU_ARRAY_SIZE(_edpt_list); i++) { - if (!_edpt_list[i].configured) { - return &_edpt_list[i]; - } - } - return NULL; -} - -static hcd_edpt_t* _add_edpt(uint8_t dev_addr, uint8_t ep_addr, - uint16_t max_packet_size, uint8_t xfer_type) { - hcd_edpt_t* e = _alloc_edpt(); - TU_ASSERT(e != NULL, NULL); - - e->dev_addr = dev_addr; - e->ep_addr = ep_addr; - e->max_packet_size = (uint8_t) TU_MIN(max_packet_size, USBFS_MAX_PACKET_SIZE); - e->xfer_type = xfer_type; - e->data_toggle = 0; - e->is_nak_pending = false; - e->buflen = 0; - e->buf = NULL; - e->configured = true; - - return e; -} - -static hcd_edpt_t* _get_or_add_edpt(uint8_t dev_addr, uint8_t ep_addr, - uint16_t max_packet_size, uint8_t xfer_type) { - hcd_edpt_t* e = _get_edpt(dev_addr, ep_addr); - if (e != NULL) return e; - return _add_edpt(dev_addr, ep_addr, max_packet_size, xfer_type); -} - -static void _remove_edpts_for_device(uint8_t dev_addr) { - for (size_t i = 0; i < TU_ARRAY_SIZE(_edpt_list); i++) { - if (_edpt_list[i].configured && _edpt_list[i].dev_addr == dev_addr) { - _edpt_list[i].configured = false; - } - } -} - -//--------------------------------------------------------------------+ -// Low-level hardware helpers -//--------------------------------------------------------------------+ - -// Busywait delay (approximate microseconds at ~60MHz) -TU_ATTR_ALWAYS_INLINE static inline void _delay_loops(uint32_t count) { - volatile uint32_t c = count / 3; - if (c == 0) return; - while (c-- != 0) {} -} - -static void _hw_init_host(uint8_t rhport, bool enabled) { - uint32_t base = _port_data[rhport].usb_base; - - if (!enabled) { - // Reset SIE when disabling - CH58X_USB_CTRL(base) = CH58X_UC_RESET_SIE | CH58X_UC_CLR_ALL; - _delay_loops(600); // ~10us at 60MHz - CH58X_USB_CTRL(base) = 0; - return; - } - - // host mode, pull-down enabled, clear addr - CH58X_USB_CTRL(base) = CH58X_UC_HOST_MODE; - while (!(CH58X_USB_CTRL(base) & CH58X_UC_HOST_MODE)) {} - CH58X_UHOST_CTRL(base) = 0; - CH58X_USB_DEV_AD(base) = 0x00; - - // EP2 RX (IN), EP3 TX (OUT/SETUP) - CH58X_UH_EP_MOD(base) = CH58X_UH_EP_TX_EN | CH58X_UH_EP_RX_EN; - - // DMA: 16-bit address, lower 64KB only - CH58X_UH_RX_DMA(base) = (uint16_t)(uint32_t)_rx_buf[rhport]; - CH58X_UH_TX_DMA(base) = (uint16_t)(uint32_t)_tx_buf[rhport]; - - CH58X_UH_RX_CTRL(base) = 0x00; - CH58X_UH_TX_CTRL(base) = 0x00; - - CH58X_USB_CTRL(base) = CH58X_UC_HOST_MODE | CH58X_UC_INT_BUSY | CH58X_UC_DMA_EN; - CH58X_UH_SETUP(base) = CH58X_UH_SOF_EN; - - CH58X_USB_INT_FG(base) = 0xFF; // clear all flags - CH58X_USB_INT_EN(base) = CH58X_UIE_TRANSFER | CH58X_UIE_DETECT; -} - -static bool _hw_start_xfer(uint8_t rhport, uint8_t pid, uint8_t ep_addr, uint8_t data_toggle) { - uint32_t base = _port_data[rhport].usb_base; - - LOG_CH58X_HCD("_hw_start_xfer(pid=0x%02x, ep=0x%02x, tog=%d)\r\n", pid, ep_addr, data_toggle); - - // Workaround: small delay for low-speed devices - bool is_lowspeed = tuh_speed_get(_current_xfer[rhport].dev_addr) == TUSB_SPEED_LOW; - if (is_lowspeed) { - _delay_loops(60000000 / 1000000 * 40); // ~40us at 60MHz - } - - // Set toggle controls (same as SDK: R8_UH_RX_CTRL = R8_UH_TX_CTRL = tog) - uint8_t tog_ctrl = (data_toggle != 0) ? CH58X_UH_T_TOG : 0; - CH58X_UH_TX_CTRL(base) = tog_ctrl; - CH58X_UH_RX_CTRL(base) = (data_toggle != 0) ? CH58X_UH_R_TOG : 0; - - uint8_t pid_endp = (pid << 4) | (tu_edpt_number(ep_addr) & 0x0F); - - // clear flag, enable int, then set PID to start transfer - CH58X_USB_INT_FG(base) = CH58X_UIF_TRANSFER; - CH58X_USB_INT_EN(base) |= CH58X_UIE_TRANSFER; - CH58X_UH_EP_PID(base) = pid_endp; - - return true; -} - -static void _hw_set_device_addr(uint8_t rhport, uint8_t dev_addr) { - uint32_t base = _port_data[rhport].usb_base; - CH58X_USB_DEV_AD(base) = (CH58X_USB_DEV_AD(base) & CH58X_UDA_GP_BIT) | - (dev_addr & CH58X_USB_ADDR_MASK); -} - -static void _hw_set_speed(uint8_t rhport, tusb_speed_t speed) { - uint32_t base = _port_data[rhport].usb_base; - - LOG_CH58X_HCD("_hw_set_speed(%s)\r\n", - speed == TUSB_SPEED_FULL ? "Full" : "Low"); - - if (speed == TUSB_SPEED_LOW) { - CH58X_USB_CTRL(base) |= CH58X_UC_LOW_SPEED; - CH58X_UHOST_CTRL(base) |= CH58X_UH_LOW_SPEED; - } else { - CH58X_USB_CTRL(base) &= ~CH58X_UC_LOW_SPEED; - CH58X_UHOST_CTRL(base) &= ~CH58X_UH_LOW_SPEED; - CH58X_UH_SETUP(base) &= ~CH58X_UH_PRE_PID_EN; - } -} - -static void _hw_set_addr_speed(uint8_t rhport, uint8_t dev_addr) { - _hw_set_device_addr(rhport, dev_addr); - - tusb_speed_t rhport_speed = hcd_port_speed_get(rhport); - tusb_speed_t dev_speed = tuh_speed_get(dev_addr); - _hw_set_speed(rhport, dev_speed); - - // FS root + LS device: hub uses PRE PID, clear LS on host ctrl - if (rhport_speed == TUSB_SPEED_FULL && dev_speed == TUSB_SPEED_LOW) { - uint32_t base = _port_data[rhport].usb_base; - CH58X_UHOST_CTRL(base) &= ~CH58X_UH_LOW_SPEED; - } -} - -static bool _hw_device_attached(uint8_t rhport) { - uint32_t base = _port_data[rhport].usb_base; - return (CH58X_USB_MIS_ST(base) & CH58X_UMS_DEV_ATTACH) != 0; -} - -//--------------------------------------------------------------------+ -// NAK retry callback -//--------------------------------------------------------------------+ -static void _xfer_retry(void* param) { - LOG_CH58X_HCD("_xfer_retry()\r\n"); - hcd_edpt_t* edpt = (hcd_edpt_t*)param; - - // Find which rhport this endpoint belongs to by checking both ports - for (uint8_t rp = 0; rp < 2; rp++) { - if (_current_xfer[rp].nak_pending) { - _current_xfer[rp].nak_pending = false; - edpt->is_nak_pending = false; - - uint8_t dev_addr = edpt->dev_addr; - uint8_t ep_addr = edpt->ep_addr; - uint16_t buflen = edpt->buflen; - uint8_t* buf = edpt->buf; - - // Check if endpoint is still valid - hcd_edpt_t* current = _get_edpt(dev_addr, ep_addr); - if (current) { - hcd_edpt_xfer(rp, dev_addr, ep_addr, buf, buflen); - } - break; - } - } -} - -//--------------------------------------------------------------------+ -// HCD API: Controller -//--------------------------------------------------------------------+ -bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { - (void)rh_init; - - _port_data[rhport].usb_base = _get_usb_base(rhport); - _port_data[rhport].int_enabled = false; - - // Clear endpoint records only on first init to avoid wiping state of the other rhport - static bool _first_init = true; - if (_first_init) { - tu_memclr(_edpt_list, sizeof(_edpt_list)); - _first_init = false; - } - _current_xfer[rhport] = (const hcd_xfer_t){0}; - - _hw_init_host(rhport, true); - - return true; -} - -bool hcd_deinit(uint8_t rhport) { - _hw_init_host(rhport, false); - return true; -} - -uint32_t hcd_frame_number(uint8_t rhport) { - (void)rhport; - return tusb_time_millis_api(); -} - -void hcd_int_enable(uint8_t rhport) { - uint8_t irqn = (rhport == 0) ? CH58X_USB_IRQn : CH58X_USB2_IRQn; - CH58X_PFIC_IENR[irqn / 32] = (1u << (irqn % 32)); - _port_data[rhport].int_enabled = true; -} - -void hcd_int_disable(uint8_t rhport) { - uint8_t irqn = (rhport == 0) ? CH58X_USB_IRQn : CH58X_USB2_IRQn; - CH58X_PFIC_IRER[irqn / 32] = (1u << (irqn % 32)); - __asm volatile("fence.i"); - _port_data[rhport].int_enabled = false; -} - -//--------------------------------------------------------------------+ -// HCD API: Port -//--------------------------------------------------------------------+ -bool hcd_port_connect_status(uint8_t rhport) { - return _hw_device_attached(rhport); -} - -tusb_speed_t hcd_port_speed_get(uint8_t rhport) { - uint32_t base = _port_data[rhport].usb_base; - if (CH58X_USB_MIS_ST(base) & CH58X_UMS_DM_LEVEL) { - return TUSB_SPEED_LOW; - } - return TUSB_SPEED_FULL; -} - -void hcd_port_reset(uint8_t rhport) { - uint32_t base = _port_data[rhport].usb_base; - - LOG_CH58X_HCD("hcd_port_reset()\r\n"); - - _port_data[rhport].int_state_before_reset = _port_data[rhport].int_enabled; - hcd_int_disable(rhport); - - _hw_set_device_addr(rhport, 0x00); - - // Disable port and default to full-speed before reset (matches SDK ResetRootHubPort) - CH58X_UHOST_CTRL(base) &= ~CH58X_UH_PORT_EN; - _hw_set_speed(rhport, TUSB_SPEED_FULL); - - // Start bus reset (clear low-speed bit simultaneously) - CH58X_UHOST_CTRL(base) = (CH58X_UHOST_CTRL(base) & ~CH58X_UH_LOW_SPEED) | CH58X_UH_BUS_RESET; -} - -void hcd_port_reset_end(uint8_t rhport) { - uint32_t base = _port_data[rhport].usb_base; - - LOG_CH58X_HCD("hcd_port_reset_end()\r\n"); - - // End bus reset - CH58X_UHOST_CTRL(base) &= ~CH58X_UH_BUS_RESET; - tusb_time_delay_ms_api(2); - - // Detect speed and configure - if ((CH58X_UHOST_CTRL(base) & CH58X_UH_PORT_EN) == 0) { - if (hcd_port_speed_get(rhport) == TUSB_SPEED_LOW) { - _hw_set_speed(rhport, TUSB_SPEED_LOW); - } - } - - // Enable port and SOF - CH58X_UHOST_CTRL(base) |= CH58X_UH_PORT_EN; - CH58X_UH_SETUP(base) |= CH58X_UH_SOF_EN; - - // Suppress stale detect event - CH58X_USB_INT_FG(base) = CH58X_UIF_DETECT; - - if (_port_data[rhport].int_state_before_reset) { - hcd_int_enable(rhport); - } -} - -void hcd_device_close(uint8_t rhport, uint8_t dev_addr) { - (void)rhport; - LOG_CH58X_HCD("hcd_device_close(dev=0x%02x)\r\n", dev_addr); - _remove_edpts_for_device(dev_addr); -} - -//--------------------------------------------------------------------+ -// HCD API: Endpoint -//--------------------------------------------------------------------+ -bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const* ep_desc) { - 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; - uint32_t base = _port_data[rhport].usb_base; - - LOG_CH58X_HCD("hcd_edpt_open(dev=0x%02x, ep=0x%02x, mps=%d, type=%d)\r\n", - dev_addr, ep_addr, max_packet_size, xfer_type); - - // Wait for any pending transfer - uint32_t t0 = tusb_time_millis_api(); - while (_current_xfer[rhport].is_busy) { - if (tusb_time_millis_api() - t0 > 200) { - _current_xfer[rhport].is_busy = false; - break; - } - } - - if (ep_num == 0) { - TU_ASSERT(_get_or_add_edpt(dev_addr, 0x00, max_packet_size, xfer_type) != NULL, false); - TU_ASSERT(_get_or_add_edpt(dev_addr, 0x80, max_packet_size, xfer_type) != NULL, false); - } else { - TU_ASSERT(_get_or_add_edpt(dev_addr, ep_addr, max_packet_size, xfer_type) != NULL, false); - } - - // Ensure port is enabled with SOF - CH58X_UHOST_CTRL(base) |= CH58X_UH_PORT_EN; - CH58X_UH_SETUP(base) |= CH58X_UH_SOF_EN; - - _hw_set_addr_speed(rhport, dev_addr); - - return true; -} - -bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, - uint8_t* buffer, uint16_t buflen) { - uint32_t base = _port_data[rhport].usb_base; - - LOG_CH58X_HCD("hcd_edpt_xfer(dev=0x%02x, ep=0x%02x, len=%d)\r\n", - dev_addr, ep_addr, buflen); - - // Wait for any pending transfer (with 200ms timeout to avoid deadlock on disconnect) - uint32_t t0 = tusb_time_millis_api(); - while (_current_xfer[rhport].is_busy) { - if (tusb_time_millis_api() - t0 > 200) { - _current_xfer[rhport].is_busy = false; - return false; - } - } - _current_xfer[rhport].is_busy = true; - - hcd_edpt_t* edpt = _get_edpt(dev_addr, ep_addr); - TU_ASSERT(edpt != NULL); - - _hw_set_addr_speed(rhport, dev_addr); - - _current_xfer[rhport].rhport = rhport; - _current_xfer[rhport].dev_addr = dev_addr; - _current_xfer[rhport].ep_addr = ep_addr; - _current_xfer[rhport].buffer = buffer; - _current_xfer[rhport].bufferlen = buflen; - _current_xfer[rhport].start_ms = tusb_time_millis_api(); - _current_xfer[rhport].xferred_len = 0; - _current_xfer[rhport].nak_pending = false; - - if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN) { - // IN transfer: host receives data - return _hw_start_xfer(rhport, CH58X_USB_PID_IN, ep_addr, edpt->data_toggle); - } else { - // OUT transfer: host sends data - uint16_t copylen = TU_MIN(edpt->max_packet_size, buflen); - CH58X_UH_TX_LEN(base) = (uint8_t)copylen; - memcpy(_tx_buf[rhport], buffer, copylen); - return _hw_start_xfer(rhport, CH58X_USB_PID_OUT, ep_addr, edpt->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; - return false; -} - -bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]) { - uint32_t base = _port_data[rhport].usb_base; - - LOG_CH58X_HCD("hcd_setup_send(dev=0x%02x)\r\n", dev_addr); - - // Wait for any pending transfer - uint32_t t0 = tusb_time_millis_api(); - while (_current_xfer[rhport].is_busy) { - if (tusb_time_millis_api() - t0 > 200) { - _current_xfer[rhport].is_busy = false; - return false; - } - } - _current_xfer[rhport].is_busy = true; - - _hw_set_addr_speed(rhport, dev_addr); - - hcd_edpt_t* edpt_tx = _get_edpt(dev_addr, 0x00); - hcd_edpt_t* edpt_rx = _get_edpt(dev_addr, 0x80); - TU_ASSERT(edpt_tx != NULL, false); - TU_ASSERT(edpt_rx != NULL, false); - - // SETUP always starts with DATA0; after SETUP, IN data starts with DATA1 - edpt_tx->data_toggle = 0; - edpt_rx->data_toggle = 1; - - memcpy(_tx_buf[rhport], setup_packet, 8); - CH58X_UH_TX_LEN(base) = 8; - - _current_xfer[rhport].rhport = rhport; - _current_xfer[rhport].dev_addr = dev_addr; - _current_xfer[rhport].ep_addr = 0x00; // SETUP always targets EP0 OUT - _current_xfer[rhport].start_ms = tusb_time_millis_api(); - _current_xfer[rhport].buffer = _tx_buf[rhport]; - _current_xfer[rhport].bufferlen = 8; - _current_xfer[rhport].xferred_len = 0; - _current_xfer[rhport].nak_pending = false; - - _hw_start_xfer(rhport, CH58X_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; - - LOG_CH58X_HCD("hcd_edpt_clear_stall(dev=0x%02x, ep=0x%02x)\r\n", dev_addr, ep_addr); - hcd_edpt_t* edpt = _get_edpt(dev_addr, ep_addr); - if (edpt != NULL) { - edpt->data_toggle = 0; - } - - return true; -} - -//--------------------------------------------------------------------+ -// Interrupt Handler -//--------------------------------------------------------------------+ -void hcd_int_handler(uint8_t rhport, bool in_isr) { - uint32_t base = _port_data[rhport].usb_base; - - //-- Device attach/detach detection -- - if (CH58X_USB_INT_FG(base) & CH58X_UIF_DETECT) { - CH58X_USB_INT_FG(base) = CH58X_UIF_DETECT; - - bool attached = _hw_device_attached(rhport); - LOG_CH58X_HCD("hcd_int: detect, attached=%d\r\n", attached); - - if (attached) { - hcd_event_device_attach(rhport, in_isr); - } else { - // Stop any ongoing hardware transfer before reporting removal - CH58X_UH_EP_PID(base) = 0x00; - _current_xfer[rhport].is_busy = false; - _current_xfer[rhport].nak_pending = false; - hcd_event_device_remove(rhport, in_isr); - } - return; - } - - //-- Transfer complete -- - if (CH58X_USB_INT_FG(base) & CH58X_UIF_TRANSFER) { - // Read PID/endpoint before stopping (must read first!) - uint8_t pid_endp = CH58X_UH_EP_PID(base); - uint8_t int_st = CH58X_USB_INT_ST(base); - uint8_t dev_addr = CH58X_USB_DEV_AD(base) & CH58X_USB_ADDR_MASK; - - // Stop USB transaction immediately (SDK: R8_UH_EP_PID = 0x00) - CH58X_UH_EP_PID(base) = 0x00; - - // Disable transfer interrupt (re-enabled when next transfer starts) - CH58X_USB_INT_EN(base) &= ~CH58X_UIE_TRANSFER; - - uint8_t request_pid = pid_endp >> 4; - uint8_t response_pid = int_st & CH58X_UIS_H_RES_MASK; - uint8_t ep_addr = pid_endp & 0x0F; - if (request_pid == CH58X_USB_PID_IN) { - ep_addr |= 0x80; - } - - LOG_CH58X_HCD("hcd_int: xfer pid=0x%02x ep=0x%02x resp=0x%02x\r\n", - request_pid, ep_addr, response_pid); - - hcd_edpt_t* edpt = _get_edpt(dev_addr, ep_addr); - if (edpt == NULL) { - // Unknown endpoint, discard - LOG_CH58X_HCD("hcd_int: unknown edpt dev=0x%02x ep=0x%02x\r\n", dev_addr, ep_addr); - _current_xfer[rhport].is_busy = false; - CH58X_USB_INT_FG(base) = CH58X_UIF_TRANSFER; - return; - } - - // Check toggle match - SDK uses R8_USB_INT_ST & RB_UIS_TOG_OK - if (int_st & CH58X_UIS_TOG_OK) { - edpt->data_toggle ^= 0x01; - - switch (request_pid) { - case CH58X_USB_PID_SETUP: - case CH58X_USB_PID_OUT: { - uint8_t tx_len = CH58X_UH_TX_LEN(base); - _current_xfer[rhport].bufferlen -= tx_len; - _current_xfer[rhport].xferred_len += tx_len; - - if (_current_xfer[rhport].bufferlen == 0) { - LOG_CH58X_HCD("OUT/SETUP complete, %d bytes\r\n", _current_xfer[rhport].xferred_len); - _current_xfer[rhport].is_busy = false; - hcd_event_xfer_complete(dev_addr, ep_addr, - _current_xfer[rhport].xferred_len, XFER_RESULT_SUCCESS, in_isr); - } else { - // Multi-packet OUT: send next chunk - _current_xfer[rhport].buffer += tx_len; - uint16_t copylen = TU_MIN(edpt->max_packet_size, _current_xfer[rhport].bufferlen); - memcpy(_tx_buf[rhport], _current_xfer[rhport].buffer, copylen); - CH58X_UH_TX_LEN(base) = (uint8_t)copylen; - _hw_start_xfer(rhport, CH58X_USB_PID_OUT, ep_addr, edpt->data_toggle); - } - break; - } - - case CH58X_USB_PID_IN: { - uint8_t rx_len = CH58X_USB_RX_LEN(base); - _current_xfer[rhport].xferred_len += rx_len; - uint16_t xferred = _current_xfer[rhport].xferred_len; - - if (rx_len > 0 && _current_xfer[rhport].buffer != NULL) { - memcpy(_current_xfer[rhport].buffer, _rx_buf[rhport], rx_len); - _current_xfer[rhport].buffer += rx_len; - } - - if ((rx_len < edpt->max_packet_size) || (xferred == _current_xfer[rhport].bufferlen)) { - // Short packet or transfer complete - LOG_CH58X_HCD("IN complete, %d bytes\r\n", xferred); - _current_xfer[rhport].is_busy = false; - hcd_event_xfer_complete(dev_addr, ep_addr, xferred, - XFER_RESULT_SUCCESS, in_isr); - } else { - // More data expected - _hw_start_xfer(rhport, CH58X_USB_PID_IN, ep_addr, edpt->data_toggle); - } - break; - } - - default: { - LOG_CH58X_HCD("unexpected PID 0x%02x\r\n", request_pid); - _current_xfer[rhport].is_busy = false; - hcd_event_xfer_complete(dev_addr, ep_addr, 0, XFER_RESULT_FAILED, in_isr); - break; - } - } - } else { - // Toggle mismatch, check response PID - if (response_pid == CH58X_USB_PID_STALL) { - LOG_CH58X_HCD("STALL response\r\n"); - edpt->data_toggle = 0; - _current_xfer[rhport].is_busy = false; - hcd_event_xfer_complete(dev_addr, ep_addr, 0, XFER_RESULT_STALLED, in_isr); - } else if (response_pid == CH58X_USB_PID_NAK) { - LOG_CH58X_HCD("NAK response\r\n"); - // For interrupt endpoints, treat NAK as a successful 0-byte poll so - // that upper layers can reschedule based on the endpoint interval. - if (edpt->xfer_type == TUSB_XFER_INTERRUPT) { - _current_xfer[rhport].is_busy = false; - hcd_event_xfer_complete(dev_addr, ep_addr, 0, XFER_RESULT_SUCCESS, in_isr); - } else { - // For non-interrupt endpoints, schedule retry via deferred callback. - _current_xfer[rhport].is_busy = false; - _current_xfer[rhport].nak_pending = true; - - edpt->is_nak_pending = true; - edpt->buflen = _current_xfer[rhport].bufferlen; - edpt->buf = _current_xfer[rhport].buffer; - - hcd_event_t event = { - .rhport = rhport, - .dev_addr = dev_addr, - .event_id = USBH_EVENT_FUNC_CALL, - .func_call = { - .func = _xfer_retry, - .param = edpt - } - }; - hcd_event_handler(&event, in_isr); - } - } else if (response_pid == CH58X_USB_PID_DATA0 || response_pid == CH58X_USB_PID_DATA1) { - LOG_CH58X_HCD("toggle mismatch, DATA0/1 rx_len=%d\r\n", CH58X_USB_RX_LEN(base)); - _current_xfer[rhport].is_busy = false; - hcd_event_xfer_complete(dev_addr, ep_addr, 0, XFER_RESULT_FAILED, in_isr); - } else { - LOG_CH58X_HCD("unexpected response 0x%02x\r\n", response_pid); - _current_xfer[rhport].is_busy = false; - hcd_event_xfer_complete(dev_addr, ep_addr, 0, XFER_RESULT_FAILED, in_isr); - } - } - - // Clear transfer flag - CH58X_USB_INT_FG(base) = CH58X_UIF_TRANSFER; - } -} - -#endif /* CFG_TUH_ENABLED && TUP_USBIP_WCH_CH58X */ -- cgit v1.3.1 From d0e51346cdc691624bc10da89a775a82ef86d92a Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 18 Jun 2026 17:44:16 +0700 Subject: fix(stm32_fsdev): don't enable the unused USB wakeup EXTI IRQ (F1/F3/G4/L1) The classic-USB STM32 fsdev driver enabled the EXTI-line USB wakeup interrupt (USBWakeUp_IRQn, and USBWakeUp_RMP_IRQn on the F3 remap path) in the NVIC, but never uses it: resume is serviced in-band via ISTR.WKUP in the USB_LP/HP ISR, and the driver never arms or clears that EXTI line. The wakeup EXTI interrupt is only needed to wake the core from STOP mode, which TinyUSB does not implement. Leaving its NVIC vector enabled lets it fire spuriously into an unhandled or looping vector -- the freeze reported in #3696 on STM32G473. USBWakeUp_IRQn is a valid, dedicated USB-wakeup-via-EXTI interrupt (e.g. stm32g473xx.h: =42 "USB Wakeup through EXTI line"), not an "unrelated interrupt"; it is simply unused here. - Comment out USBWakeUp_IRQn for F1/F3/G4/L1 and USBWakeUp_RMP_IRQn on the F3 remap path, kept in place so STOP-mode wakeup is a one-line re-enable. - Keep the STM32L1 USBWakeUp_IRQn -> USB_FS_WKUP_IRQn alias for that re-enable. - Document the rationale in fsdev_stm32.h with a TODO. - Comment out the matching USBWakeUp(_RMP)_IRQHandler in the F1/F3/G4 BSPs, and the FreeRTOS NVIC_SetPriority(USBWakeUp_IRQn) on F1/G4. Fixes #3696 Co-Authored-By: Claude Opus 4.8 (1M context) --- hw/bsp/stm32f1/family.c | 10 ++++++---- hw/bsp/stm32f3/family.c | 7 ++++--- hw/bsp/stm32g4/family.c | 10 ++++++---- src/portable/st/stm32_fsdev/fsdev_stm32.h | 22 +++++++++++++--------- 4 files changed, 29 insertions(+), 20 deletions(-) (limited to 'src/portable') diff --git a/hw/bsp/stm32f1/family.c b/hw/bsp/stm32f1/family.c index abde44d21..67427da1f 100644 --- a/hw/bsp/stm32f1/family.c +++ b/hw/bsp/stm32f1/family.c @@ -63,9 +63,11 @@ void USB_LP_IRQHandler(void) { tud_int_handler(0); } -void USBWakeUp_IRQHandler(void) { - tud_int_handler(0); -} +// USB wakeup EXTI IRQ is not enabled by the fsdev driver (see fsdev_stm32.h); +// restore when STOP-mode wakeup is implemented. +//void USBWakeUp_IRQHandler(void) { +// tud_int_handler(0); +//} //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM @@ -128,7 +130,7 @@ void board_init(void) { // If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher ) NVIC_SetPriority(USB_HP_CAN1_TX_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY); NVIC_SetPriority(USB_LP_CAN1_RX0_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY); - NVIC_SetPriority(USBWakeUp_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY); + //NVIC_SetPriority(USBWakeUp_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY); #endif // LED diff --git a/hw/bsp/stm32f3/family.c b/hw/bsp/stm32f3/family.c index 35e1852e8..bddf224d2 100644 --- a/hw/bsp/stm32f3/family.c +++ b/hw/bsp/stm32f3/family.c @@ -76,9 +76,10 @@ void USB_LP_IRQHandler(void) { // USB wakeup interrupt (Channel 76): Triggered by the wakeup event from the USB // Suspend mode. -void USBWakeUp_RMP_IRQHandler(void) { - tud_int_handler(0); -} +// Not enabled by the fsdev driver (see fsdev_stm32.h); restore for STOP-mode wakeup. +//void USBWakeUp_RMP_IRQHandler(void) { +// tud_int_handler(0); +//} //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM diff --git a/hw/bsp/stm32g4/family.c b/hw/bsp/stm32g4/family.c index 433f74e2a..cf7d4329b 100644 --- a/hw/bsp/stm32g4/family.c +++ b/hw/bsp/stm32g4/family.c @@ -61,9 +61,11 @@ void USB_LP_IRQHandler(void) { tud_int_handler(0); } -void USBWakeUp_IRQHandler(void) { - tud_int_handler(0); -} +// USB wakeup EXTI IRQ is not enabled by the fsdev driver (see fsdev_stm32.h); +// restore when STOP-mode wakeup is implemented. +//void USBWakeUp_IRQHandler(void) { +// tud_int_handler(0); +//} // USB PD void UCPD1_IRQHandler(void) { @@ -99,7 +101,7 @@ void board_init(void) { // If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher ) NVIC_SetPriority(USB_HP_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY); NVIC_SetPriority(USB_LP_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY); - NVIC_SetPriority(USBWakeUp_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY); + //NVIC_SetPriority(USBWakeUp_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY); #endif GPIO_InitTypeDef GPIO_InitStruct; diff --git a/src/portable/st/stm32_fsdev/fsdev_stm32.h b/src/portable/st/stm32_fsdev/fsdev_stm32.h index b15c95302..93cdac808 100644 --- a/src/portable/st/stm32_fsdev/fsdev_stm32.h +++ b/src/portable/st/stm32_fsdev/fsdev_stm32.h @@ -168,14 +168,18 @@ #define FSDEV_USE_SBUF_ISO 0 #endif -//--------------------------------------------------------------------+ -// -//--------------------------------------------------------------------+ - +// STM32L1 calls it USB_FS_WKUP_IRQn; alias so the commented USBWakeUp_IRQn below +// can be uncommented as-is. #if TU_CHECK_MCU(OPT_MCU_STM32L1) && !defined(USBWakeUp_IRQn) #define USBWakeUp_IRQn USB_FS_WKUP_IRQn #endif +// USB interrupt vectors to enable in NVIC. The EXTI-line USB wakeup interrupt +// (USBWakeUp_IRQn, and USBWakeUp_RMP_IRQn on F3) is left commented out: resume is +// handled in-band via ISTR.WKUP in the USB_LP/HP ISR; the EXTI line is only needed to +// wake the core from STOP mode, which this driver does not implement (it never arms or +// clears that EXTI line, so enabling its NVIC vector can only spuriously fire/freeze). +// TODO: uncomment USBWakeUp_IRQn (+ arm/clear its EXTI line) when adding STOP-mode wakeup. static const IRQn_Type fsdev_irq[] = { #if TU_CHECK_MCU(OPT_MCU_STM32F0, OPT_MCU_STM32L0, OPT_MCU_STM32L4, OPT_MCU_STM32U5) USB_IRQn, @@ -192,15 +196,15 @@ static const IRQn_Type fsdev_irq[] = { #elif CFG_TUSB_MCU == OPT_MCU_STM32F1 USB_HP_CAN1_TX_IRQn, USB_LP_CAN1_RX0_IRQn, - USBWakeUp_IRQn, + //USBWakeUp_IRQn, #elif CFG_TUSB_MCU == OPT_MCU_STM32F3 USB_HP_CAN_TX_IRQn, USB_LP_CAN_RX0_IRQn, - USBWakeUp_IRQn, + //USBWakeUp_IRQn, #elif TU_CHECK_MCU(OPT_MCU_STM32G4, OPT_MCU_STM32L1) USB_HP_IRQn, USB_LP_IRQn, - USBWakeUp_IRQn, + //USBWakeUp_IRQn, #elif CFG_TUSB_MCU == OPT_MCU_STM32WB USB_HP_IRQn, USB_LP_IRQn, @@ -223,7 +227,7 @@ TU_ATTR_ALWAYS_INLINE static inline void fsdev_int_enable(uint8_t rhport) { if (SYSCFG->CFGR1 & SYSCFG_CFGR1_USB_IT_RMP) { NVIC_EnableIRQ(USB_HP_IRQn); NVIC_EnableIRQ(USB_LP_IRQn); - NVIC_EnableIRQ(USBWakeUp_RMP_IRQn); + //NVIC_EnableIRQ(USBWakeUp_RMP_IRQn); } else #endif { @@ -243,7 +247,7 @@ TU_ATTR_ALWAYS_INLINE static inline void fsdev_int_disable(uint8_t rhport) { if (SYSCFG->CFGR1 & SYSCFG_CFGR1_USB_IT_RMP) { NVIC_DisableIRQ(USB_HP_IRQn); NVIC_DisableIRQ(USB_LP_IRQn); - NVIC_DisableIRQ(USBWakeUp_RMP_IRQn); + //NVIC_DisableIRQ(USBWakeUp_RMP_IRQn); } else #endif { -- cgit v1.3.1 From dcb060c894713d60ce0ab009733e5d59a32d0d23 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 19 Jun 2026 21:37:52 +0700 Subject: dcd/ch58x: complete the EP register map and right-size EP buffers Tidy the CH58x register/buffer layout the initial port left rough. Register map (USBOTG_FS_TypeDef): - Extend the struct to the full CH583/582 datasheet Table 17-2 map instead of stopping at UEP567_MOD (0x0E) with the per-endpoint registers living only in raw-address macros. - Express the per-endpoint DMA/length/control registers as arrays of 4-byte slots (ch58x_ep_dma_t / ch58x_ep_ctrl_t): EP0-3 DMA at 0x10, EP0-4 ctrl at 0x20, EP5-7 DMA/ctrl split to 0x54/0x64 (EP4 has no DMA register of its own; it shares EP0's). TU_VERIFY_STATIC pins the slot sizes and block offsets, so the EP_TX_LEN/EP_CTRL/EP_DMA macros walk each block by the 4-byte stride (pointer arithmetic off slot 0, so the unused ternary branch can't trip -Warray-bounds). - Gate the two driver sites on CFG_TUSB_MCU == OPT_MCU_CH58X directly rather than the CH32_USBFS_EP_REGS_CUSTOM alias, which was only ever defined in the CH58x branch. EP buffers (the data struct): - Replace buffer[EP_MAX][2][64] on CH58x with named per-endpoint buffers: EP0/EP4 use the dedicated 192B ep0_ep4_buffer, so the old array left buffer[0]/buffer[4] allocated-but-unused. - Drop EP3's oversized iso buffer (out[64] + in[1023]); EP3 is bulk-only on CH58x, so it uses a plain 128-byte buffer like the others. The data struct shrinks from ~2636 to 1292 bytes. - Keep the now uniformly-64-byte buffers safe: dcd_edpt_iso_alloc()/iso_activate() refuse isochronous on CH58x (no iso support; 8-bit T_LEN caps a packet at 255B), and update_in()/update_out() additionally cap each packet copy to 64 bytes so a class that ignores the iso-alloc result cannot run a memcpy past a buffer into a neighbour's. Non-CH58x parts (e.g. ch32v103) keep the struct-based macros, buffer[EP_MAX], and the iso buffer unchanged. Verified on ch582m_evt HIL (ci.lan): all device examples pass; ch32v103 build unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/portable/wch/ch32_usbfs_reg.h | 59 ++++++++++++++-------- src/portable/wch/dcd_ch32_usbfs.c | 102 +++++++++++++++++++++++++++++++------- 2 files changed, 123 insertions(+), 38 deletions(-) (limited to 'src/portable') diff --git a/src/portable/wch/ch32_usbfs_reg.h b/src/portable/wch/ch32_usbfs_reg.h index 0d61e183c..9c58c467f 100644 --- a/src/portable/wch/ch32_usbfs_reg.h +++ b/src/portable/wch/ch32_usbfs_reg.h @@ -137,27 +137,53 @@ // the EP control/length block sits lower (EP0_CTRL @ +0x22), EP5-7 are split out, EP4 // shares EP0's DMA buffer, and EP5/6/7 mode bits live in one UEP567_MOD. The control/status // block matches CH32. Two FS controllers exist (USB @ 0x40008000, USB2 @ 0x40008400); the - // device uses USB0. EP registers are accessed via the CH58X macros below (not the struct). + // device uses USB0. Full register map per CH583/582 datasheet Table 17-2; the parameterized + // EP_* macros below index off these named fields. #define CH58X_USBFS_BASE 0x40008000u + // Per-endpoint register slots, 4-byte stride each; the EP_* macros index arrays of these. typedef struct { - __IO uint8_t BASE_CTRL; // 0x00 - __IO uint8_t UDEV_CTRL; // 0x01 - __IO uint8_t INT_EN; // 0x02 - __IO uint8_t DEV_ADDR; // 0x03 + __IO uint16_t DMA; // R16_UEPn_DMA: endpoint n buffer start address + __IO uint16_t reserved; + } ch58x_ep_dma_t; + typedef struct { + __IO uint8_t T_LEN; // R8_UEPn_T_LEN (+0): transmit length + __IO uint8_t reserved0; + __IO uint8_t CTRL; // R8_UEPn_CTRL (+2): endpoint control + __IO uint8_t reserved1; + } ch58x_ep_ctrl_t; + typedef struct { + __IO uint8_t BASE_CTRL; // 0x00 R8_USB_CTRL + __IO uint8_t UDEV_CTRL; // 0x01 R8_UDEV_CTRL + __IO uint8_t INT_EN; // 0x02 R8_USB_INT_EN + __IO uint8_t DEV_ADDR; // 0x03 R8_USB_DEV_AD __IO uint8_t Reserve0; // 0x04 - __IO uint8_t MIS_ST; // 0x05 - __IO uint8_t INT_FG; // 0x06 - __IO uint8_t INT_ST; // 0x07 - __IO uint8_t RX_LEN; // 0x08 (8-bit on CH58X) + __IO uint8_t MIS_ST; // 0x05 R8_USB_MIS_ST + __IO uint8_t INT_FG; // 0x06 R8_USB_INT_FG + __IO uint8_t INT_ST; // 0x07 R8_USB_INT_ST + __IO uint8_t RX_LEN; // 0x08 R8_USB_RX_LEN (8-bit on CH58X) __IO uint8_t Reserve1[3]; // 0x09..0x0B - __IO uint8_t UEP4_1_MOD; // 0x0C - __IO uint8_t UEP2_3_MOD; // 0x0D - __IO uint8_t UEP567_MOD; // 0x0E + __IO uint8_t UEP4_1_MOD; // 0x0C R8_UEP4_1_MOD + __IO uint8_t UEP2_3_MOD; // 0x0D R8_UEP2_3_MOD + __IO uint8_t UEP567_MOD; // 0x0E R8_UEP567_MOD + __IO uint8_t Reserve2; // 0x0F + ch58x_ep_dma_t EP_DMA_0_3[4]; // 0x10 EP0-3 DMA (EP4 has no DMA reg; it shares EP0's, index 0) + ch58x_ep_ctrl_t EP_CTRL_0_4[5]; // 0x20 EP0-4 length/control + __IO uint8_t Reserve3[0x54u - 0x34u]; // 0x34..0x53 + ch58x_ep_dma_t EP_DMA_5_7[3]; // 0x54 EP5-7 DMA + __IO uint8_t Reserve4[0x64u - 0x60u]; // 0x60..0x63 + ch58x_ep_ctrl_t EP_CTRL_5_7[3]; // 0x64 EP5-7 length/control } USBOTG_FS_TypeDef; #define USBOTG_FS ((USBOTG_FS_TypeDef *) CH58X_USBFS_BASE) + // 4-byte slot stride + these block offsets pin every EP register to its datasheet address. + TU_VERIFY_STATIC(sizeof(ch58x_ep_dma_t) == 4, "CH58x EP DMA slot must be 4 bytes"); + TU_VERIFY_STATIC(sizeof(ch58x_ep_ctrl_t) == 4, "CH58x EP ctrl slot must be 4 bytes"); + TU_VERIFY_STATIC(offsetof(USBOTG_FS_TypeDef, EP_DMA_0_3) == 0x10, "CH58x EP_DMA_0_3 @0x10"); + TU_VERIFY_STATIC(offsetof(USBOTG_FS_TypeDef, EP_CTRL_0_4) == 0x20, "CH58x EP_CTRL_0_4 @0x20"); + TU_VERIFY_STATIC(offsetof(USBOTG_FS_TypeDef, EP_DMA_5_7) == 0x54, "CH58x EP_DMA_5_7 @0x54"); + TU_VERIFY_STATIC(offsetof(USBOTG_FS_TypeDef, EP_CTRL_5_7) == 0x64, "CH58x EP_CTRL_5_7 @0x64"); + #define CH32_USBFS_EP_CTRL_COMBINED 1 - #define CH32_USBFS_EP_REGS_CUSTOM 1 // EP register macros provided here, not by the driver // CH58x's hardware AUTO_TOG does not stay in sync (notably across clear-stall and multi-packet // bulk transfers), causing data-toggle mismatch and bus resets. Drive the toggle manually in // the ISR instead. CH32V103/V20x/V307 keep AUTO_TOG (this macro is undefined for them). @@ -170,13 +196,6 @@ #define NVIC_EnableIRQ(n) PFIC_EnableIRQ(n) #define NVIC_DisableIRQ(n) PFIC_DisableIRQ(n) #endif - - // EP register access. EP0-4: T_LEN @ +0x20+ep*4, CTRL @ +0x22+ep*4. EP5-7 split: T_LEN @ - // +0x64, CTRL @ +0x66. DMA: EP0-3 @ +0x10+ep*4, EP5-7 @ +0x54; EP4 shares EP0's buffer - // (no own DMA reg) so its slot points at a reserved word. - #define EP_TX_LEN(ep) (*(volatile uint8_t *)(CH58X_USBFS_BASE + ((ep) <= 4u ? 0x20u + (ep)*4u : 0x64u + ((ep)-5u)*4u))) - #define EP_CTRL(ep) (*(volatile uint8_t *)(CH58X_USBFS_BASE + ((ep) <= 4u ? 0x22u + (ep)*4u : 0x66u + ((ep)-5u)*4u))) - #define EP_DMA(ep) (*(volatile uint16_t *)(CH58X_USBFS_BASE + ((ep) <= 3u ? 0x10u + (ep)*4u : (ep) == 4u ? 0x40u : 0x54u + ((ep)-5u)*4u))) #endif #ifdef __GNUC__ diff --git a/src/portable/wch/dcd_ch32_usbfs.c b/src/portable/wch/dcd_ch32_usbfs.c index 7beb91e16..12b45c784 100644 --- a/src/portable/wch/dcd_ch32_usbfs.c +++ b/src/portable/wch/dcd_ch32_usbfs.c @@ -35,13 +35,25 @@ /* private defines */ #define EP_MAX (8) - // Struct-based EP register access (uniform layout). Some parts (e.g. CH58X) have a different - // register map and define EP_DMA/EP_TX_LEN/EP_CTRL themselves in ch32_usbfs_reg.h. - #ifndef CH32_USBFS_EP_REGS_CUSTOM - #define EP_DMA(ep) ((&USBOTG_FS->UEP0_DMA)[ep]) - #define EP_TX_LEN(ep) ((&USBOTG_FS->UEP0_TX_LEN)[2 * ep]) - #define EP_TX_CTRL(ep) ((&USBOTG_FS->UEP0_TX_CTRL)[4 * ep]) - #define EP_RX_CTRL(ep) ((&USBOTG_FS->UEP0_RX_CTRL)[4 * ep]) + // Struct-based EP register access (uniform layout). CH58X has a different register map and + // defines EP_DMA/EP_TX_LEN/EP_CTRL itself in ch32_usbfs_reg.h. + #if CFG_TUSB_MCU == OPT_MCU_CH58X + // CH58X EP registers split into a low block (EP0-4) and a high block (EP5-7). Walk from each + // block's first slot by the 4-byte slot stride (pointer arithmetic off slot 0, so the unused + // ternary branch's index can't trip -Warray-bounds). EP4 has no DMA register of its own (it + // shares EP0's, slot 0) and is never written (see ep_shares_ep0_dma()). + #define EP_TX_LEN(ep) (*((ep) <= 4u ? &USBOTG_FS->EP_CTRL_0_4[0].T_LEN + (ep) * 4u \ + : &USBOTG_FS->EP_CTRL_5_7[0].T_LEN + ((ep) - 5u) * 4u)) + #define EP_CTRL(ep) (*((ep) <= 4u ? &USBOTG_FS->EP_CTRL_0_4[0].CTRL + (ep) * 4u \ + : &USBOTG_FS->EP_CTRL_5_7[0].CTRL + ((ep) - 5u) * 4u)) + #define EP_DMA(ep) (*((ep) <= 3u ? &USBOTG_FS->EP_DMA_0_3[0].DMA + (ep) * 2u \ + : (ep) == 4u ? &USBOTG_FS->EP_DMA_0_3[0].DMA \ + : &USBOTG_FS->EP_DMA_5_7[0].DMA + ((ep) - 5u) * 2u)) + #else + #define EP_DMA(ep) ((&USBOTG_FS->UEP0_DMA)[ep]) + #define EP_TX_LEN(ep) ((&USBOTG_FS->UEP0_TX_LEN)[2 * ep]) + #define EP_TX_CTRL(ep) ((&USBOTG_FS->UEP0_TX_CTRL)[4 * ep]) + #define EP_RX_CTRL(ep) ((&USBOTG_FS->UEP0_RX_CTRL)[4 * ep]) #endif // Endpoint control register access. The newer USBFS IP (CH32V20x/V307/X035) has separate @@ -116,48 +128,82 @@ static struct { bool ep0_tog; bool isochronous[EP_MAX]; struct usb_xfer xfer[EP_MAX][2]; - TU_ATTR_ALIGNED(4) uint8_t buffer[EP_MAX][2][64]; #ifdef CH32_USBFS_EP4_SHARES_EP0 - // CH58X: EP0 and EP4 share one DMA region (EP4 has no DMA register). Layout: - // EP0 [0:63] (half-duplex, OUT+IN) + EP4 OUT [64:127] + EP4 IN [128:191]. buffer[0]/buffer[4] - // are left unused for this part. + // CH58X buffers laid out by hand so EP0/EP4 don't burn two unused buffer[] slots. EP0 and EP4 + // share one contiguous 192-byte DMA region (EP4 has no DMA register of its own): + // EP0 [0:63] (half-duplex OUT+IN) + EP4 OUT [64:127] + EP4 IN [128:191]. Every other endpoint + // (incl. EP3, which is bulk-only here — CH58X has no isochronous support) gets a plain 128-byte + // OUT+IN buffer, so no oversized EP3 buffer is needed. TU_ATTR_ALIGNED(4) uint8_t ep0_ep4_buffer[3 * 64]; -#endif + TU_ATTR_ALIGNED(4) uint8_t ep1_buffer[2][64]; + TU_ATTR_ALIGNED(4) uint8_t ep2_buffer[2][64]; + TU_ATTR_ALIGNED(4) uint8_t ep3_buffer[2][64]; + TU_ATTR_ALIGNED(4) uint8_t ep5_buffer[2][64]; + TU_ATTR_ALIGNED(4) uint8_t ep6_buffer[2][64]; + TU_ATTR_ALIGNED(4) uint8_t ep7_buffer[2][64]; +#else + TU_ATTR_ALIGNED(4) uint8_t buffer[EP_MAX][2][64]; + // EP3 IN gets an enlarged buffer for full-speed isochronous (packets up to 1023 B). TU_ATTR_ALIGNED(4) struct { // OUT transfers >64 bytes will overwrite queued IN data! uint8_t out[64]; uint8_t in[1023]; uint8_t pad; } ep3_buffer; +#endif } data; // DMA / copy buffer pointers per endpoint. The WCH USBFS buffer holds OUT (RX) at offset 0 and // IN (TX) at +64; EP0 is half-duplex and reuses its OUT chunk for IN; EP3 has an enlarged IN -// buffer for throughput. On CH58X, EP4 overlays EP0's region (see ep0_ep4_buffer above). -static inline uint32_t ep_dma_addr(uint8_t ep) { +// buffer for throughput. On CH58X, EP0/EP4 share ep0_ep4_buffer and the regular endpoints use +// their own named buffer (see the struct above). #ifdef CH32_USBFS_EP4_SHARES_EP0 - if (ep == 0) { return (uint32_t) &data.ep0_ep4_buffer[0]; } +// OUT base of the regular CH58X endpoints (EP1/2/3/5/6/7; EP0/EP4 share ep0_ep4_buffer). +static inline uint8_t* ch58x_ep_buffer(uint8_t ep) { + switch (ep) { + case 1: return data.ep1_buffer[0]; + case 2: return data.ep2_buffer[0]; + case 3: return data.ep3_buffer[0]; + case 5: return data.ep5_buffer[0]; + case 6: return data.ep6_buffer[0]; + default: return data.ep7_buffer[0]; // ep == 7 + } +} #endif + +static inline uint32_t ep_dma_addr(uint8_t ep) { +#ifdef CH32_USBFS_EP4_SHARES_EP0 + if (ep == 0 || ep == 4) { return (uint32_t) &data.ep0_ep4_buffer[0]; } // EP4 shares EP0's DMA + return (uint32_t) ch58x_ep_buffer(ep); +#else if (ep == 3) { return (uint32_t) &data.ep3_buffer.out[0]; } return (uint32_t) &data.buffer[ep][0]; +#endif } + static inline uint8_t* ep_out_buf(uint8_t ep) { #ifdef CH32_USBFS_EP4_SHARES_EP0 if (ep == 0) { return &data.ep0_ep4_buffer[0]; } if (ep == 4) { return &data.ep0_ep4_buffer[64]; } -#endif + return ch58x_ep_buffer(ep); +#else if (ep == 3) { return data.ep3_buffer.out; } return data.buffer[ep][TUSB_DIR_OUT]; +#endif } + static inline uint8_t* ep_in_buf(uint8_t ep) { #ifdef CH32_USBFS_EP4_SHARES_EP0 if (ep == 0) { return &data.ep0_ep4_buffer[0]; } // EP0 half-duplex: IN reuses OUT chunk if (ep == 4) { return &data.ep0_ep4_buffer[128]; } -#endif + return ch58x_ep_buffer(ep) + 64; // IN at +64 within the endpoint's 128-byte buffer +#else if (ep == 0) { return data.buffer[0][TUSB_DIR_OUT]; } // EP0 half-duplex: IN reuses OUT chunk if (ep == 3) { return data.ep3_buffer.in; } return data.buffer[ep][TUSB_DIR_IN]; +#endif } + // EP4 on CH58X has no DMA register (shares EP0's); skip its EP_DMA() write. static inline bool ep_shares_ep0_dma(uint8_t ep) { #ifdef CH32_USBFS_EP4_SHARES_EP0 @@ -174,6 +220,12 @@ static void update_in(uint8_t rhport, uint8_t ep, bool force) { if (xfer->valid) { if (force || xfer->len) { size_t len = TU_MIN(xfer->max_size, xfer->len); +#if CFG_TUSB_MCU == OPT_MCU_CH58X + // Every CH58x endpoint buffer is 64 bytes. Isochronous (which would push max_size up to 1023) + // is refused in dcd_edpt_iso_alloc(), but some classes (e.g. video) ignore that result, so cap + // the copy here to guarantee we never write past the buffer into a neighbouring endpoint's. + len = TU_MIN(len, 64u); +#endif memcpy(ep_in_buf(ep), xfer->buffer, len); xfer->buffer += len; xfer->len -= len; @@ -204,6 +256,9 @@ static void update_out(uint8_t rhport, uint8_t ep, size_t rx_len) { struct usb_xfer *xfer = &data.xfer[ep][TUSB_DIR_OUT]; if (xfer->valid) { size_t len = TU_MIN(xfer->max_size, TU_MIN(xfer->len, rx_len)); +#if CFG_TUSB_MCU == OPT_MCU_CH58X + len = TU_MIN(len, 64u); // cap to the 64-byte EP buffer (see update_in) +#endif memcpy(xfer->buffer, ep_out_buf(ep), len); xfer->buffer += len; xfer->len -= len; @@ -253,7 +308,7 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t *rh_init) { // enable other endpoints but NAK everything USBOTG_FS->UEP4_1_MOD = 0xCC; USBOTG_FS->UEP2_3_MOD = 0xCC; -#ifdef CH32_USBFS_EP_REGS_CUSTOM +#if CFG_TUSB_MCU == OPT_MCU_CH58X // CH58X: a single mode register enables EP5/6/7 RX+TX (different bit layout than CH32). USBOTG_FS->UEP567_MOD = RB_UEP5_RX_EN | RB_UEP5_TX_EN | RB_UEP6_RX_EN | RB_UEP6_TX_EN | RB_UEP7_RX_EN | RB_UEP7_TX_EN; @@ -413,18 +468,29 @@ bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet (void)rhport; (void)ep_addr; (void)largest_packet_size; +#if CFG_TUSB_MCU == OPT_MCU_CH58X + // No isochronous support on CH58x: its 8-bit T_LEN caps a packet at 255B and the endpoints use + // plain 64-byte buffers, so accepting an iso max_size (up to 1023) would let update_in()/ + // update_out() run off the end of the buffer into neighbouring ones. Refuse it outright. + return false; +#else uint8_t ep = tu_edpt_number(ep_addr); uint8_t dir = tu_edpt_dir(ep_addr); data.isochronous[ep] = true; data.xfer[ep][dir].max_size = largest_packet_size; return true; +#endif } bool dcd_edpt_iso_activate(uint8_t rhport, const tusb_desc_endpoint_t *desc_ep) { (void)rhport; (void)desc_ep; +#if CFG_TUSB_MCU == OPT_MCU_CH58X + return false; // CH58x has no isochronous support (see dcd_edpt_iso_alloc) +#else return true; +#endif } bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes, bool is_isr) { -- cgit v1.3.1 From 0c4c0be4589b2807abde5ef9ab156b6aaaad6616 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 19 Jun 2026 22:54:50 +0700 Subject: dcd/ch58x: keep IRQ masked across the EP-arming RMW in dcd_edpt_xfer dcd_edpt_xfer() re-enabled the USB interrupt before update_in() / ep_rx_set_response(), which read-modify-write the (combined) EP control register. On CH58x the ISR RMWs that same register to flip the manual data toggle, so a transfer interrupt landing mid-RMW could drop the toggle flip and desync the endpoint. Move dcd_int_enable() to after the arming so the whole sequence is atomic w.r.t. the ISR (matching the CH32X035 port #3703). Co-Authored-By: Claude Opus 4.8 (1M context) --- src/portable/wch/dcd_ch32_usbfs.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/portable') diff --git a/src/portable/wch/dcd_ch32_usbfs.c b/src/portable/wch/dcd_ch32_usbfs.c index 12b45c784..e8b3c86b2 100644 --- a/src/portable/wch/dcd_ch32_usbfs.c +++ b/src/portable/wch/dcd_ch32_usbfs.c @@ -500,12 +500,14 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to uint8_t dir = tu_edpt_dir(ep_addr); struct usb_xfer *xfer = &data.xfer[ep][dir]; + // Keep the IRQ masked across the whole arming sequence: update_in()/ep_rx_set_response() do a + // read-modify-write of the (combined) EP control register, which the ISR also RMWs to flip the + // manual data toggle; re-enabling before they run lets a transfer IRQ clobber that toggle. dcd_int_disable(rhport); xfer->valid = true; xfer->buffer = buffer; xfer->len = total_bytes; xfer->processed_len = 0; - dcd_int_enable(rhport); if (dir == TUSB_DIR_IN) { update_in(rhport, ep, true); @@ -513,6 +515,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to uint8_t rx_res = data.isochronous[ep] ? USBFS_EP_R_RES_NYET : USBFS_EP_R_RES_ACK; ep_rx_set_response(ep, rx_res); } + dcd_int_enable(rhport); return true; } -- cgit v1.3.1 From 58b5447b606b49c76187c48e5b76690f4a111143 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 19 Jun 2026 22:55:54 +0700 Subject: dcd/ch58x: advance EP0 OUT data toggle for multi-packet control transfers The manual-toggle ISR skipped EP0 entirely (if (ep != 0)), so EP0's RX data toggle was set to DATA1 once at SETUP and never advanced. A control-OUT whose data stage exceeds the EP0 packet size (a vendor/WebUSB OUT, a large HID SET_REPORT, or an HS DFU download) desynced on the second packet and stalled. EP0 has no hardware auto-toggle on CH58x (per the datasheet RB_UEP_AUTO_TOG applies only to EP1/2/3/5/6/7), so flip its RX toggle on every OUT and always process the packet -- restoring what the removed dcd_ch58x_usbfs.c did. The HIL examples keep their control-OUT data stages within a single packet, so this was latent. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/portable/wch/dcd_ch32_usbfs.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'src/portable') diff --git a/src/portable/wch/dcd_ch32_usbfs.c b/src/portable/wch/dcd_ch32_usbfs.c index e8b3c86b2..164b6f7bf 100644 --- a/src/portable/wch/dcd_ch32_usbfs.c +++ b/src/portable/wch/dcd_ch32_usbfs.c @@ -336,10 +336,13 @@ void dcd_int_handler(uint8_t rhport) { switch (token) { case PID_OUT: { #ifdef CH32_USBFS_EP_MANUAL_TOG - // Manual toggle: drop OUT packets whose data toggle doesn't match (host retransmit), - // otherwise flip the expected RX toggle for the next packet. EP0 is driven by the - // SETUP/status flow below, so its toggle is left to that path. - if (ep != 0) { + // Manual toggle. EP0 has no hardware auto-toggle (RB_UEP_AUTO_TOG covers only EP1/2/3/5/6/7), + // so advance its RX toggle on every OUT and always process it; a control-OUT data stage + // longer than the EP0 packet size would otherwise stall on the second packet. For the other + // endpoints, drop toggle-mismatched OUT (host retransmit) and flip the expected RX toggle. + if (ep == 0) { + EP_CTRL(0) ^= USBFS_EPC_R_TOG; + } else { if (!(int_st & USBFS_INT_ST_TOG_OK)) { break; } EP_CTRL(ep) ^= USBFS_EPC_R_TOG; } -- cgit v1.3.1 From a5292288b20abbfa3990a4dbc3acf8ff650c5e5b Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 19 Jun 2026 22:58:17 +0700 Subject: dcd/ch58x: report bus resume instead of a second suspend The USBFS SUSPEND interrupt fires on both the suspend and the resume edge, but the handler unconditionally posted DCD_EVENT_SUSPEND. On CH58x tud_resume_cb() therefore never ran, and a device that lowered clocks/power in tud_suspend_cb() was never told to restore them. Read MIS_ST's suspend bit (1 while suspended, 0 once resumed) to emit DCD_EVENT_RESUME on the wake edge -- what the removed dcd_ch58x_usbfs.c did. Scoped to CH58x via #if; the CH32 parts keep their existing behavior. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/portable/wch/ch32_usbfs_reg.h | 4 ++++ src/portable/wch/dcd_ch32_usbfs.c | 7 +++++++ 2 files changed, 11 insertions(+) (limited to 'src/portable') diff --git a/src/portable/wch/ch32_usbfs_reg.h b/src/portable/wch/ch32_usbfs_reg.h index 9c58c467f..90a477b79 100644 --- a/src/portable/wch/ch32_usbfs_reg.h +++ b/src/portable/wch/ch32_usbfs_reg.h @@ -233,6 +233,10 @@ #define USBFS_INT_FG_TOG_OK (1 << 6) #define USBFS_INT_FG_IS_NAK (1 << 7) +// MIS_ST: the SUSPEND interrupt fires on both suspend and resume; this bit (R8_USB_MIS_ST) is 1 +// while the bus is suspended and 0 once it has resumed, so it tells the two apart. +#define USBFS_MIS_ST_SUSPEND (1 << 2) + // INT_ST #define USBFS_INT_ST_MASK_UIS_ENDP(x) (((x) >> 0) & 0x0F) #define USBFS_INT_ST_MASK_UIS_TOKEN(x) (((x) >> 4) & 0x03) diff --git a/src/portable/wch/dcd_ch32_usbfs.c b/src/portable/wch/dcd_ch32_usbfs.c index 164b6f7bf..61c973062 100644 --- a/src/portable/wch/dcd_ch32_usbfs.c +++ b/src/portable/wch/dcd_ch32_usbfs.c @@ -391,7 +391,14 @@ void dcd_int_handler(uint8_t rhport) { USBOTG_FS->INT_FG = USBFS_INT_FG_BUS_RST; } else if (status & USBFS_INT_FG_SUSPEND) { +#if CFG_TUSB_MCU == OPT_MCU_CH58X + // CH58x raises this single interrupt for both suspend and resume; MIS_ST's suspend bit tells + // them apart (set while suspended, clear once resumed) so tud_resume_cb() actually fires. + dcd_event_t event = {.rhport = rhport, + .event_id = (USBOTG_FS->MIS_ST & USBFS_MIS_ST_SUSPEND) ? DCD_EVENT_SUSPEND : DCD_EVENT_RESUME}; +#else dcd_event_t event = {.rhport = rhport, .event_id = DCD_EVENT_SUSPEND}; +#endif dcd_event_handler(&event, true); USBOTG_FS->INT_FG = USBFS_INT_FG_SUSPEND; } -- cgit v1.3.1 From 9aa0ab4b675ab2c3880cb5ed440d3d04b944f77f Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 19 Jun 2026 22:59:59 +0700 Subject: dcd/ch58x: drop stale EP0 transfer state on SETUP The PID_SETUP handler armed the new control transfer but left any in-flight EP0 transfer from the previous request marked valid, so a spurious EP0 IN/OUT could run update_in()/update_out() against stale state (the removed dcd_ch58x_usbfs.c invalidated both EP0 directions on every SETUP). Clear xfer[0] IN/OUT validity when a SETUP arrives. Applies to all WCH USBFS parts -- a new SETUP always supersedes a pending control xfer. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/portable/wch/dcd_ch32_usbfs.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/portable') diff --git a/src/portable/wch/dcd_ch32_usbfs.c b/src/portable/wch/dcd_ch32_usbfs.c index 61c973062..18cc17a33 100644 --- a/src/portable/wch/dcd_ch32_usbfs.c +++ b/src/portable/wch/dcd_ch32_usbfs.c @@ -363,6 +363,10 @@ void dcd_int_handler(uint8_t rhport) { // setup clears stall ep_tx_ctrl_set(0, USBFS_EP_T_RES_NAK); data.ep0_tog = true; + // A new SETUP supersedes any control transfer still in flight; drop its stale EP0 state so a + // spurious EP0 IN/OUT can't run update_in()/update_out() against the previous request. + data.xfer[0][TUSB_DIR_OUT].valid = false; + data.xfer[0][TUSB_DIR_IN].valid = false; uint8_t *ep0_out = ep_out_buf(0); const tusb_control_request_t *setup = (const tusb_control_request_t *)ep0_out; -- cgit v1.3.1 From 31543c17a9c15c1c6e9a6c8d39be10aaa184e4f1 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 19 Jun 2026 23:00:55 +0700 Subject: dcd/ch58x: preserve the DEV_ADDR general-purpose bit on SET_ADDRESS dcd_edpt0_status_complete() wrote the full SET_ADDRESS wValue into R8_USB_DEV_AD, clobbering bit 7, which on CH58x is a user general-purpose flag (only bits [6:0] are the device address). Mask to 7 bits and preserve bit 7, matching the removed dcd_ch58x_usbfs.c. CH58x-scoped; other parts keep the full write. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/portable/wch/dcd_ch32_usbfs.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/portable') diff --git a/src/portable/wch/dcd_ch32_usbfs.c b/src/portable/wch/dcd_ch32_usbfs.c index 18cc17a33..f4cbb8ca9 100644 --- a/src/portable/wch/dcd_ch32_usbfs.c +++ b/src/portable/wch/dcd_ch32_usbfs.c @@ -449,7 +449,12 @@ void dcd_edpt0_status_complete(uint8_t rhport, const tusb_control_request_t *req (void)rhport; if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE && request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && request->bRequest == TUSB_REQ_SET_ADDRESS) { +#if CFG_TUSB_MCU == OPT_MCU_CH58X + // On CH58x R8_USB_DEV_AD bit 7 is a user general-purpose flag; only bits [6:0] are the address. + USBOTG_FS->DEV_ADDR = (uint8_t)((USBOTG_FS->DEV_ADDR & 0x80u) | (request->wValue & 0x7Fu)); +#else USBOTG_FS->DEV_ADDR = (uint8_t)request->wValue; +#endif } } -- cgit v1.3.1 From cca6fe64e95175cbefcdae1d1306ea8765a075d9 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 20 Jun 2026 08:36:25 +0700 Subject: dcd/wch: drop toggle-mismatched OUT packets on all USBFS variants The OUT data-toggle check -- drop a packet whose DATA0/DATA1 doesn't match the expected toggle (a host retransmit after a lost ACK, or a host that doesn't alternate the toggle) -- only ran on CH58x. The auto-toggle parts (V103/V20x/V307/ X035) never checked it, so a duplicate/retransmitted OUT was processed twice. HiFiPhile confirmed it: a host patched to send DATA0-only had CH32V305 accept every packet. Move the TOG_OK gate out of the CH58x-only block so it runs on every variant; the manual toggle flip stays CH58x-only. EP0 keeps its own toggle via the SETUP/status flow and is exempt. Verified on ci.lan HIL: ch582m_evt (CH58x), ch32v103r_r1_1v0 (V103), nanoch32v203 (V203) all pass. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/portable/wch/dcd_ch32_usbfs.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) (limited to 'src/portable') diff --git a/src/portable/wch/dcd_ch32_usbfs.c b/src/portable/wch/dcd_ch32_usbfs.c index f4cbb8ca9..22c7a43fa 100644 --- a/src/portable/wch/dcd_ch32_usbfs.c +++ b/src/portable/wch/dcd_ch32_usbfs.c @@ -335,17 +335,15 @@ void dcd_int_handler(uint8_t rhport) { switch (token) { case PID_OUT: { + // Drop an OUT packet whose data toggle doesn't match what we expect -- a host retransmit + // after a lost ACK, or a host that doesn't alternate DATA0/DATA1. The hardware auto-toggle + // does not reject these on its own, so the check is needed on every variant. EP0 keeps its + // own toggle via the SETUP/status flow and is exempt. + if (ep != 0 && !(int_st & USBFS_INT_ST_TOG_OK)) { break; } #ifdef CH32_USBFS_EP_MANUAL_TOG - // Manual toggle. EP0 has no hardware auto-toggle (RB_UEP_AUTO_TOG covers only EP1/2/3/5/6/7), - // so advance its RX toggle on every OUT and always process it; a control-OUT data stage - // longer than the EP0 packet size would otherwise stall on the second packet. For the other - // endpoints, drop toggle-mismatched OUT (host retransmit) and flip the expected RX toggle. - if (ep == 0) { - EP_CTRL(0) ^= USBFS_EPC_R_TOG; - } else { - if (!(int_st & USBFS_INT_ST_TOG_OK)) { break; } - EP_CTRL(ep) ^= USBFS_EPC_R_TOG; - } + // CH58x has no hardware auto-toggle: advance the expected RX toggle after each accepted packet + // (EP0 included -- it also has no auto-toggle and a control-OUT data stage can span packets). + EP_CTRL(ep) ^= USBFS_EPC_R_TOG; #endif update_out(rhport, ep, rx_len); break; -- cgit v1.3.1 From eda704ca1acef9691b51e17026765f497b1fffbe Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 22 Jun 2026 15:23:08 +0700 Subject: hw/bsp+wch: rename the CH58x family to ch583 and OPT_MCU_CH58X to OPT_MCU_CH583 The BSP family and MCU option were named "ch58x"/"CH58X", but the supported part is the CH583/CH582 (and the SDK repo is openwch/ch583); CH585 is a separate MCU family, so the CH58x umbrella was misleading. Rename to the specific family: - hw/bsp/ch58x -> hw/bsp/ch583 (dir), and the BSP-local files ch58x_it.* -> ch583_it.*, system_ch58x.* -> system_ch583.* (include guards/refs updated). The vendor SDK files (CH58x_common.h, CH58x_*.c in hw/mcu/wch/ch583) keep their names. - OPT_MCU_CH58X -> OPT_MCU_CH583 in tusb_option.h, tusb_mcu.h, and the shared WCH USBFS driver (ch32_usbfs_reg.h, dcd_ch32_usbfs.c). OPT_MCU_CH582 is kept as an alias (same value), so either name selects the same code. - FAMILY_MCUS CH58X -> CH583, CFG_TUSB_MCU=OPT_MCU_CH583, mcu:CH58X -> mcu:CH583 in the example skip lists, the CI build matrix (ci_set_matrix.py), the get_deps family tag, and docs/reference/boards.rst. Board names (ch582m_evt, yd-ch582m) are unchanged. Verified: make + cmake build for ch582m_evt, and ci.lan HIL (all device examples pass). Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/ci_set_matrix.py | 2 +- docs/reference/boards.rst | 2 +- examples/device/audio_4_channel_mic/skip.txt | 2 +- .../device/audio_4_channel_mic_freertos/skip.txt | 2 +- examples/device/audio_test/skip.txt | 2 +- examples/device/audio_test_freertos/skip.txt | 2 +- examples/device/audio_test_multi_rate/skip.txt | 2 +- examples/device/cdc_msc_freertos/skip.txt | 2 +- examples/device/cdc_uac2/skip.txt | 2 +- examples/device/dfu_runtime/skip.txt | 1 + examples/device/hid_boot_interface/skip.txt | 1 + examples/device/hid_composite/skip.txt | 1 + examples/device/hid_composite_freertos/skip.txt | 2 +- examples/device/hid_generic_inout/skip.txt | 1 + examples/device/hid_multiple_interface/skip.txt | 1 + examples/device/midi_test/skip.txt | 1 + examples/device/midi_test_freertos/skip.txt | 2 +- examples/device/uac2_headset/skip.txt | 2 +- examples/device/uac2_speaker_fb/skip.txt | 2 +- examples/device/video_capture/skip.txt | 2 +- examples/device/video_capture_2ch/skip.txt | 2 +- examples/device/webusb_serial/skip.txt | 1 + hw/bsp/ch583/boards/ch582m_evt/board.cmake | 5 + hw/bsp/ch583/boards/ch582m_evt/board.h | 61 +++++++ hw/bsp/ch583/boards/ch582m_evt/board.mk | 3 + hw/bsp/ch583/boards/yd-ch582m/board.cmake | 5 + hw/bsp/ch583/boards/yd-ch582m/board.h | 61 +++++++ hw/bsp/ch583/boards/yd-ch582m/board.mk | 3 + hw/bsp/ch583/ch583_it.c | 37 ++++ hw/bsp/ch583/ch583_it.h | 46 +++++ hw/bsp/ch583/debug_uart.c | 86 +++++++++ hw/bsp/ch583/debug_uart.h | 44 +++++ hw/bsp/ch583/family.c | 194 +++++++++++++++++++++ hw/bsp/ch583/family.cmake | 108 ++++++++++++ hw/bsp/ch583/family.mk | 59 +++++++ hw/bsp/ch583/linker/ch582.ld | 167 ++++++++++++++++++ hw/bsp/ch583/system_ch583.c | 39 +++++ hw/bsp/ch583/system_ch583.h | 43 +++++ hw/bsp/ch583/wch-riscv.cfg | 17 ++ hw/bsp/ch58x/boards/ch582m_evt/board.cmake | 5 - hw/bsp/ch58x/boards/ch582m_evt/board.h | 61 ------- hw/bsp/ch58x/boards/ch582m_evt/board.mk | 3 - hw/bsp/ch58x/boards/yd-ch582m/board.cmake | 5 - hw/bsp/ch58x/boards/yd-ch582m/board.h | 61 ------- hw/bsp/ch58x/boards/yd-ch582m/board.mk | 3 - hw/bsp/ch58x/ch58x_it.c | 37 ---- hw/bsp/ch58x/ch58x_it.h | 46 ----- hw/bsp/ch58x/debug_uart.c | 86 --------- hw/bsp/ch58x/debug_uart.h | 44 ----- hw/bsp/ch58x/family.c | 194 --------------------- hw/bsp/ch58x/family.cmake | 108 ------------ hw/bsp/ch58x/family.mk | 59 ------- hw/bsp/ch58x/linker/ch582.ld | 167 ------------------ hw/bsp/ch58x/system_ch58x.c | 39 ----- hw/bsp/ch58x/system_ch58x.h | 43 ----- hw/bsp/ch58x/wch-riscv.cfg | 17 -- src/common/tusb_mcu.h | 2 +- src/portable/wch/ch32_usbfs_reg.h | 2 +- src/portable/wch/dcd_ch32_usbfs.c | 16 +- src/tusb_option.h | 2 +- tools/get_deps.py | 2 +- 61 files changed, 1012 insertions(+), 1005 deletions(-) create mode 100644 examples/device/dfu_runtime/skip.txt create mode 100644 examples/device/hid_boot_interface/skip.txt create mode 100644 examples/device/hid_composite/skip.txt create mode 100644 examples/device/hid_generic_inout/skip.txt create mode 100644 examples/device/hid_multiple_interface/skip.txt create mode 100644 examples/device/midi_test/skip.txt create mode 100644 examples/device/webusb_serial/skip.txt create mode 100644 hw/bsp/ch583/boards/ch582m_evt/board.cmake create mode 100644 hw/bsp/ch583/boards/ch582m_evt/board.h create mode 100644 hw/bsp/ch583/boards/ch582m_evt/board.mk create mode 100644 hw/bsp/ch583/boards/yd-ch582m/board.cmake create mode 100644 hw/bsp/ch583/boards/yd-ch582m/board.h create mode 100644 hw/bsp/ch583/boards/yd-ch582m/board.mk create mode 100644 hw/bsp/ch583/ch583_it.c create mode 100644 hw/bsp/ch583/ch583_it.h create mode 100644 hw/bsp/ch583/debug_uart.c create mode 100644 hw/bsp/ch583/debug_uart.h create mode 100644 hw/bsp/ch583/family.c create mode 100644 hw/bsp/ch583/family.cmake create mode 100644 hw/bsp/ch583/family.mk create mode 100644 hw/bsp/ch583/linker/ch582.ld create mode 100644 hw/bsp/ch583/system_ch583.c create mode 100644 hw/bsp/ch583/system_ch583.h create mode 100644 hw/bsp/ch583/wch-riscv.cfg delete mode 100644 hw/bsp/ch58x/boards/ch582m_evt/board.cmake delete mode 100644 hw/bsp/ch58x/boards/ch582m_evt/board.h delete mode 100644 hw/bsp/ch58x/boards/ch582m_evt/board.mk delete mode 100644 hw/bsp/ch58x/boards/yd-ch582m/board.cmake delete mode 100644 hw/bsp/ch58x/boards/yd-ch582m/board.h delete mode 100644 hw/bsp/ch58x/boards/yd-ch582m/board.mk delete mode 100644 hw/bsp/ch58x/ch58x_it.c delete mode 100644 hw/bsp/ch58x/ch58x_it.h delete mode 100644 hw/bsp/ch58x/debug_uart.c delete mode 100644 hw/bsp/ch58x/debug_uart.h delete mode 100644 hw/bsp/ch58x/family.c delete mode 100644 hw/bsp/ch58x/family.cmake delete mode 100644 hw/bsp/ch58x/family.mk delete mode 100644 hw/bsp/ch58x/linker/ch582.ld delete mode 100644 hw/bsp/ch58x/system_ch58x.c delete mode 100644 hw/bsp/ch58x/system_ch58x.h delete mode 100644 hw/bsp/ch58x/wch-riscv.cfg (limited to 'src/portable') diff --git a/.github/workflows/ci_set_matrix.py b/.github/workflows/ci_set_matrix.py index 400f319d3..dc0d3871f 100755 --- a/.github/workflows/ci_set_matrix.py +++ b/.github/workflows/ci_set_matrix.py @@ -30,7 +30,7 @@ family_list = { "ch32v10x": ["riscv-gcc"], "ch32v20x": ["riscv-gcc"], "ch32v30x": ["riscv-gcc"], - "ch58x": ["riscv-gcc"], + "ch583": ["riscv-gcc"], "da1469x": ["arm-gcc"], "fomu": ["riscv-gcc"], "ft9xx": ["ft9xx-gcc"], diff --git a/docs/reference/boards.rst b/docs/reference/boards.rst index 7ea9c228b..8a83496a4 100644 --- a/docs/reference/boards.rst +++ b/docs/reference/boards.rst @@ -370,5 +370,5 @@ ch32v203g_r0_1v0 CH32V203G-R0-1v0 ch32v20x https://github.com/openwch/ch32v20 nanoch32v203 nanoCH32V203 ch32v20x https://github.com/wuxx/nanoCH32V203 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 -yd-ch582m yd-ch582m ch58x http://vcc-gnd.com +yd-ch582m yd-ch582m ch583 http://vcc-gnd.com ================ ================ ======== ===================================================================== ====== diff --git a/examples/device/audio_4_channel_mic/skip.txt b/examples/device/audio_4_channel_mic/skip.txt index 8c64832f7..3ca433c08 100644 --- a/examples/device/audio_4_channel_mic/skip.txt +++ b/examples/device/audio_4_channel_mic/skip.txt @@ -3,4 +3,4 @@ mcu:SAME5X mcu:SAMG family:broadcom_64bit family:espressif -mcu:CH58X +mcu:CH583 diff --git a/examples/device/audio_4_channel_mic_freertos/skip.txt b/examples/device/audio_4_channel_mic_freertos/skip.txt index dae0a5428..1fd6b4b8a 100644 --- a/examples/device/audio_4_channel_mic_freertos/skip.txt +++ b/examples/device/audio_4_channel_mic_freertos/skip.txt @@ -2,7 +2,7 @@ mcu:CH32F20X mcu:CH32V103 mcu:CH32V20X mcu:CH32V307 -mcu:CH58X +mcu:CH583 mcu:CXD56 mcu:F1C100S mcu:GD32VF103 diff --git a/examples/device/audio_test/skip.txt b/examples/device/audio_test/skip.txt index 6e3082a54..42394bb11 100644 --- a/examples/device/audio_test/skip.txt +++ b/examples/device/audio_test/skip.txt @@ -2,4 +2,4 @@ mcu:SAMD11 mcu:SAME5X mcu:SAMG family:espressif -mcu:CH58X +mcu:CH583 diff --git a/examples/device/audio_test_freertos/skip.txt b/examples/device/audio_test_freertos/skip.txt index 20deaca28..660bacd25 100644 --- a/examples/device/audio_test_freertos/skip.txt +++ b/examples/device/audio_test_freertos/skip.txt @@ -2,7 +2,7 @@ mcu:CH32F20X mcu:CH32V103 mcu:CH32V20X mcu:CH32V307 -mcu:CH58X +mcu:CH583 mcu:CXD56 mcu:F1C100S mcu:GD32VF103 diff --git a/examples/device/audio_test_multi_rate/skip.txt b/examples/device/audio_test_multi_rate/skip.txt index 6e3082a54..42394bb11 100644 --- a/examples/device/audio_test_multi_rate/skip.txt +++ b/examples/device/audio_test_multi_rate/skip.txt @@ -2,4 +2,4 @@ mcu:SAMD11 mcu:SAME5X mcu:SAMG family:espressif -mcu:CH58X +mcu:CH583 diff --git a/examples/device/cdc_msc_freertos/skip.txt b/examples/device/cdc_msc_freertos/skip.txt index 197060eeb..48781de84 100644 --- a/examples/device/cdc_msc_freertos/skip.txt +++ b/examples/device/cdc_msc_freertos/skip.txt @@ -2,7 +2,7 @@ mcu:CH32F20X mcu:CH32V103 mcu:CH32V20X mcu:CH32V307 -mcu:CH58X +mcu:CH583 mcu:CXD56 mcu:F1C100S mcu:GD32VF103 diff --git a/examples/device/cdc_uac2/skip.txt b/examples/device/cdc_uac2/skip.txt index 4222d08c6..db1d5b80b 100644 --- a/examples/device/cdc_uac2/skip.txt +++ b/examples/device/cdc_uac2/skip.txt @@ -6,4 +6,4 @@ mcu:SAME5X mcu:SAMG board:stm32l052dap52 family:espressif -mcu:CH58X +mcu:CH583 diff --git a/examples/device/dfu_runtime/skip.txt b/examples/device/dfu_runtime/skip.txt new file mode 100644 index 000000000..2c6c2a64c --- /dev/null +++ b/examples/device/dfu_runtime/skip.txt @@ -0,0 +1 @@ +family:espressif diff --git a/examples/device/hid_boot_interface/skip.txt b/examples/device/hid_boot_interface/skip.txt new file mode 100644 index 000000000..2c6c2a64c --- /dev/null +++ b/examples/device/hid_boot_interface/skip.txt @@ -0,0 +1 @@ +family:espressif diff --git a/examples/device/hid_composite/skip.txt b/examples/device/hid_composite/skip.txt new file mode 100644 index 000000000..2c6c2a64c --- /dev/null +++ b/examples/device/hid_composite/skip.txt @@ -0,0 +1 @@ +family:espressif diff --git a/examples/device/hid_composite_freertos/skip.txt b/examples/device/hid_composite_freertos/skip.txt index fccddabcd..97d8e168b 100644 --- a/examples/device/hid_composite_freertos/skip.txt +++ b/examples/device/hid_composite_freertos/skip.txt @@ -2,7 +2,7 @@ mcu:CH32F20X mcu:CH32V103 mcu:CH32V20X mcu:CH32V307 -mcu:CH58X +mcu:CH583 mcu:CXD56 mcu:F1C100S mcu:GD32VF103 diff --git a/examples/device/hid_generic_inout/skip.txt b/examples/device/hid_generic_inout/skip.txt new file mode 100644 index 000000000..2c6c2a64c --- /dev/null +++ b/examples/device/hid_generic_inout/skip.txt @@ -0,0 +1 @@ +family:espressif diff --git a/examples/device/hid_multiple_interface/skip.txt b/examples/device/hid_multiple_interface/skip.txt new file mode 100644 index 000000000..2c6c2a64c --- /dev/null +++ b/examples/device/hid_multiple_interface/skip.txt @@ -0,0 +1 @@ +family:espressif diff --git a/examples/device/midi_test/skip.txt b/examples/device/midi_test/skip.txt new file mode 100644 index 000000000..2c6c2a64c --- /dev/null +++ b/examples/device/midi_test/skip.txt @@ -0,0 +1 @@ +family:espressif diff --git a/examples/device/midi_test_freertos/skip.txt b/examples/device/midi_test_freertos/skip.txt index fccddabcd..97d8e168b 100644 --- a/examples/device/midi_test_freertos/skip.txt +++ b/examples/device/midi_test_freertos/skip.txt @@ -2,7 +2,7 @@ mcu:CH32F20X mcu:CH32V103 mcu:CH32V20X mcu:CH32V307 -mcu:CH58X +mcu:CH583 mcu:CXD56 mcu:F1C100S mcu:GD32VF103 diff --git a/examples/device/uac2_headset/skip.txt b/examples/device/uac2_headset/skip.txt index 4222d08c6..db1d5b80b 100644 --- a/examples/device/uac2_headset/skip.txt +++ b/examples/device/uac2_headset/skip.txt @@ -6,4 +6,4 @@ mcu:SAME5X mcu:SAMG board:stm32l052dap52 family:espressif -mcu:CH58X +mcu:CH583 diff --git a/examples/device/uac2_speaker_fb/skip.txt b/examples/device/uac2_speaker_fb/skip.txt index 48a484f96..0c7339c65 100644 --- a/examples/device/uac2_speaker_fb/skip.txt +++ b/examples/device/uac2_speaker_fb/skip.txt @@ -6,4 +6,4 @@ mcu:SAME5X mcu:SAMG board:stm32l052dap52 family:broadcom_64bit -mcu:CH58X +mcu:CH583 diff --git a/examples/device/video_capture/skip.txt b/examples/device/video_capture/skip.txt index 7f000d472..5a7a1d00e 100644 --- a/examples/device/video_capture/skip.txt +++ b/examples/device/video_capture/skip.txt @@ -1,6 +1,6 @@ mcu:CH32V103 mcu:CH32V20X -mcu:CH58X +mcu:CH583 mcu:MSP430x5xx mcu:NUC121 mcu:SAMD11 diff --git a/examples/device/video_capture_2ch/skip.txt b/examples/device/video_capture_2ch/skip.txt index 191edeb39..c37205b8c 100644 --- a/examples/device/video_capture_2ch/skip.txt +++ b/examples/device/video_capture_2ch/skip.txt @@ -5,7 +5,7 @@ mcu:GD32VF103 mcu:CH32V103 mcu:CH32V20X mcu:CH32V307 -mcu:CH58X +mcu:CH583 mcu:STM32L0 family:espressif board:curiosity_nano diff --git a/examples/device/webusb_serial/skip.txt b/examples/device/webusb_serial/skip.txt new file mode 100644 index 000000000..2c6c2a64c --- /dev/null +++ b/examples/device/webusb_serial/skip.txt @@ -0,0 +1 @@ +family:espressif diff --git a/hw/bsp/ch583/boards/ch582m_evt/board.cmake b/hw/bsp/ch583/boards/ch582m_evt/board.cmake new file mode 100644 index 000000000..4129c4550 --- /dev/null +++ b/hw/bsp/ch583/boards/ch582m_evt/board.cmake @@ -0,0 +1,5 @@ +set(LD_FLASH_SIZE 448K) +set(LD_RAM_SIZE 32K) + +function(update_board TARGET) +endfunction() diff --git a/hw/bsp/ch583/boards/ch582m_evt/board.h b/hw/bsp/ch583/boards/ch582m_evt/board.h new file mode 100644 index 000000000..c3483bf17 --- /dev/null +++ b/hw/bsp/ch583/boards/ch582m_evt/board.h @@ -0,0 +1,61 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2024 TinyUSB contributors + * + * 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. + */ + +/* metadata: + name: CH582M-EVT evaluation board + url: https://www.wch-ic.com/products/CH582.html +*/ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +// LED: PB4 on CH582M-EVT +#define LED_PIN GPIO_Pin_4 +#define LED_STATE_ON 0 + +// Directly reuse BOOT pin as user button +#define BUTTON_PIN GPIO_Pin_22 +#define BUTTON_STATE_ACTIVE 0 + +// UART: UART1 TX=PA9, RX=PA8 +#define CFG_BOARD_UART_BAUDRATE 115200 + +// Device only on USB1 (rhport 0). CH58x host / USB2 is not supported by the shared usbfs dcd; +// BOARD_TUH_RHPORT is kept commented out to ease re-adding host later. +#ifndef BOARD_TUD_RHPORT +#define BOARD_TUD_RHPORT 0 +#endif +// #ifndef BOARD_TUH_RHPORT +// #define BOARD_TUH_RHPORT 1 +// #endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/hw/bsp/ch583/boards/ch582m_evt/board.mk b/hw/bsp/ch583/boards/ch582m_evt/board.mk new file mode 100644 index 000000000..a13979799 --- /dev/null +++ b/hw/bsp/ch583/boards/ch582m_evt/board.mk @@ -0,0 +1,3 @@ +LDFLAGS += \ + -Wl,--defsym=__FLASH_SIZE=448K \ + -Wl,--defsym=__RAM_SIZE=32K \ diff --git a/hw/bsp/ch583/boards/yd-ch582m/board.cmake b/hw/bsp/ch583/boards/yd-ch582m/board.cmake new file mode 100644 index 000000000..4129c4550 --- /dev/null +++ b/hw/bsp/ch583/boards/yd-ch582m/board.cmake @@ -0,0 +1,5 @@ +set(LD_FLASH_SIZE 448K) +set(LD_RAM_SIZE 32K) + +function(update_board TARGET) +endfunction() diff --git a/hw/bsp/ch583/boards/yd-ch582m/board.h b/hw/bsp/ch583/boards/yd-ch582m/board.h new file mode 100644 index 000000000..0da5747bc --- /dev/null +++ b/hw/bsp/ch583/boards/yd-ch582m/board.h @@ -0,0 +1,61 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2024 TinyUSB contributors + * + * 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. + */ + +/* metadata: + name: yd-ch582m from vcc-gnd studio + url: http://vcc-gnd.com/ +*/ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +// LED: PB4 on yd-ch582m board +#define LED_PIN GPIO_Pin_4 +#define LED_STATE_ON 0 + +// Directly reuse BOOT pin as user button +#define BUTTON_PIN GPIO_Pin_22 +#define BUTTON_STATE_ACTIVE 0 + +// UART: UART1 TX=PA9, RX=PA8 +#define CFG_BOARD_UART_BAUDRATE 115200 + +// Device only on USB1 (rhport 0). CH58x host / USB2 is not supported by the shared usbfs dcd; +// BOARD_TUH_RHPORT is kept commented out to ease re-adding host later. +#ifndef BOARD_TUD_RHPORT +#define BOARD_TUD_RHPORT 0 +#endif +// #ifndef BOARD_TUH_RHPORT +// #define BOARD_TUH_RHPORT 1 +// #endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/hw/bsp/ch583/boards/yd-ch582m/board.mk b/hw/bsp/ch583/boards/yd-ch582m/board.mk new file mode 100644 index 000000000..a13979799 --- /dev/null +++ b/hw/bsp/ch583/boards/yd-ch582m/board.mk @@ -0,0 +1,3 @@ +LDFLAGS += \ + -Wl,--defsym=__FLASH_SIZE=448K \ + -Wl,--defsym=__RAM_SIZE=32K \ diff --git a/hw/bsp/ch583/ch583_it.c b/hw/bsp/ch583/ch583_it.c new file mode 100644 index 000000000..8479c537a --- /dev/null +++ b/hw/bsp/ch583/ch583_it.c @@ -0,0 +1,37 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2024 TinyUSB contributors + * + * 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 "ch583_it.h" + +// NMI exception handler +__INTERRUPT __HIGH_CODE void NMI_Handler(void) { + while (1) {} +} + +// Hard Fault exception handler +__INTERRUPT __HIGH_CODE void HardFault_Handler(void) { + while (1) {} +} diff --git a/hw/bsp/ch583/ch583_it.h b/hw/bsp/ch583/ch583_it.h new file mode 100644 index 000000000..29d175403 --- /dev/null +++ b/hw/bsp/ch583/ch583_it.h @@ -0,0 +1,46 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2024 TinyUSB contributors + * + * 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 CH583_IT_H_ +#define CH583_IT_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "CH58x_common.h" + +void NMI_Handler(void); +void HardFault_Handler(void); +void USB_IRQHandler(void); +// void USB2_IRQHandler(void); // host on USB2 (rhport 1) — re-add together with the host driver +void SysTick_Handler(void); + +#ifdef __cplusplus +} +#endif + +#endif /* CH583_IT_H_ */ diff --git a/hw/bsp/ch583/debug_uart.c b/hw/bsp/ch583/debug_uart.c new file mode 100644 index 000000000..850e40718 --- /dev/null +++ b/hw/bsp/ch583/debug_uart.c @@ -0,0 +1,86 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2024 TinyUSB contributors + * + * 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 "debug_uart.h" +#include "CH58x_common.h" + +//--------------------------------------------------------------------+ +// Ring buffer based UART TX for non-blocking writes +//--------------------------------------------------------------------+ + +#define UART_RINGBUFFER_SIZE_TX 128 +#define UART_RINGBUFFER_MASK_TX (UART_RINGBUFFER_SIZE_TX - 1) + +static char tx_buf[UART_RINGBUFFER_SIZE_TX]; +static uint32_t tx_produce; +static volatile uint32_t tx_consume; + +void uart_write(char c) { + uint32_t tx_produce_next = (tx_produce + 1) & UART_RINGBUFFER_MASK_TX; + + // If the ring buffer is full, drain it here as the FIFO frees up: nothing else advances + // tx_consume between uart_write() calls, so a plain spin would deadlock on a >buffer-size burst. + while (tx_produce_next == tx_consume) { + if (R8_UART1_LSR & RB_LSR_TX_FIFO_EMP) { + R8_UART1_THR = tx_buf[tx_consume]; + tx_consume = (tx_consume + 1) & UART_RINGBUFFER_MASK_TX; + } + } + + // If UART TX FIFO is empty and no pending data, send directly + if ((tx_consume == tx_produce) && (R8_UART1_LSR & RB_LSR_TX_FIFO_EMP)) { + R8_UART1_THR = c; + } else { + tx_buf[tx_produce] = c; + tx_produce = tx_produce_next; + } +} + +void uart_sync(void) { + // Wait for ring buffer to drain + while (tx_consume != tx_produce) { + if (R8_UART1_LSR & RB_LSR_TX_FIFO_EMP) { + R8_UART1_THR = tx_buf[tx_consume]; + tx_consume = (tx_consume + 1) & UART_RINGBUFFER_MASK_TX; + } + } + // Wait for last byte to finish transmitting + while (!(R8_UART1_LSR & RB_LSR_TX_ALL_EMP)) {} +} + +void usart_printf_init(uint32_t baudrate) { + tx_produce = 0; + tx_consume = 0; + + // Configure UART1 pins: TX=PA9, RX=PA8 + GPIOA_SetBits(GPIO_Pin_9); + GPIOA_ModeCfg(GPIO_Pin_9, GPIO_ModeOut_PP_5mA); + GPIOA_ModeCfg(GPIO_Pin_8, GPIO_ModeIN_PU); + + // Init UART1 with specified baud rate + UART1_DefInit(); + UART1_BaudRateCfg(baudrate); +} diff --git a/hw/bsp/ch583/debug_uart.h b/hw/bsp/ch583/debug_uart.h new file mode 100644 index 000000000..44c3e7948 --- /dev/null +++ b/hw/bsp/ch583/debug_uart.h @@ -0,0 +1,44 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2024 TinyUSB contributors + * + * 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 DEBUG_UART_H_ +#define DEBUG_UART_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void uart_write(char c); +void uart_sync(void); +void usart_printf_init(uint32_t baudrate); + +#ifdef __cplusplus +} +#endif + +#endif /* DEBUG_UART_H_ */ diff --git a/hw/bsp/ch583/family.c b/hw/bsp/ch583/family.c new file mode 100644 index 000000000..716e2b76b --- /dev/null +++ b/hw/bsp/ch583/family.c @@ -0,0 +1,194 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2024 TinyUSB contributors + * + * 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: WCH +*/ + +// WCH SDK's DEBUG macro enables a _write() that conflicts with TinyUSB's. +// TinyUSB uses UART1 for printf via debug_uart.c, so DEBUG is not needed. +// If you need a different UART or want to keep SDK's DEBUG, modify +// debug_uart.c (TinyUSB side) or CH58x_sys.c (SDK side) to remove one _write(). +// If done, remove this #error to continue. +#ifdef DEBUG + #error "Remove the DEBUG macro from preprocessor defines to avoid " \ + "duplicate _write() between WCH SDK and TinyUSB. " \ + "TinyUSB uses UART1 by default (see debug_uart.c)." +#endif + +#include "debug_uart.h" +#include "CH58x_common.h" +#include "ch583_it.h" + +#include "bsp/board_api.h" +#include "board.h" + +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ + +// Device only: the shared dcd_ch32_usbfs.c drives USB0 (rhport 0). CH58x's second controller +// (USB2 / rhport 1) was driven by the now-removed ch58x host driver; its handler is kept +// commented out below to ease re-adding host support. +__INTERRUPT __HIGH_CODE void USB_IRQHandler(void) { + tusb_int_handler(0, true); +} + +// __INTERRUPT __HIGH_CODE void USB2_IRQHandler(void) { +// tusb_int_handler(1, true); +// } + +//--------------------------------------------------------------------+ +// SysTick +//--------------------------------------------------------------------+ + +#if CFG_TUSB_OS == OPT_OS_NONE +volatile uint32_t system_ticks = 0; + +__INTERRUPT __HIGH_CODE void SysTick_Handler(void) { + SysTick->SR = 0; + system_ticks++; +} + +uint32_t tusb_time_millis_api(void) { + return system_ticks; +} +#endif + +//--------------------------------------------------------------------+ +// Board Init +//--------------------------------------------------------------------+ + +void board_init(void) { + // Disable interrupts during init + PFIC_DisableAllIRQ(); + + // Set system clock to PLL 60MHz (default for CH582) + SetSysClock(CLK_SOURCE_PLL_60MHz); + +#if CFG_TUSB_OS == OPT_OS_NONE + SysTick_Config(GetSysClock() / 1000); +#endif + + // UART1 init for debug output +#ifdef CFG_BOARD_UART_BAUDRATE + usart_printf_init(CFG_BOARD_UART_BAUDRATE); +#endif + + // LED +#ifdef LED_PORT_IS_A + GPIOA_ModeCfg(LED_PIN, GPIO_ModeOut_PP_5mA); +#else + GPIOB_ModeCfg(LED_PIN, GPIO_ModeOut_PP_5mA); +#endif + + // Button +#ifdef BUTTON_PIN + #ifdef BUTTON_PORT_IS_A + GPIOA_ModeCfg(BUTTON_PIN, GPIO_ModeIN_PU); + #else + GPIOB_ModeCfg(BUTTON_PIN, GPIO_ModeIN_PU); + #endif +#endif + + // Device only on USB0 (rhport 0): enable analog function for USB1 D+/D- and assert its D+ + // pull-up. The shared dcd_ch32_usbfs.c drives USB0; CH58x host / USB2 (rhport 1) is unsupported + // here — to re-add host, also OR in RB_PIN_USB2_IE below. + R16_PIN_ANALOG_IE |= RB_PIN_USB_IE; // | RB_PIN_USB2_IE (re-add for host on USB2) +#if CFG_TUD_ENABLED + R16_PIN_ANALOG_IE |= RB_PIN_USB_DP_PU; +#endif + + // Keep USB clock active during sleep + R8_SLP_CLK_OFF1 &= ~RB_SLP_CLK_USB; + + // Enable interrupts globally + PFIC_EnableAllIRQ(); + + board_delay(2); +} + +//--------------------------------------------------------------------+ +// Board porting API +//--------------------------------------------------------------------+ + +void board_led_write(bool state) { +#ifdef LED_PORT_IS_A + if (state ^ LED_STATE_ON) { + GPIOA_ResetBits(LED_PIN); + } else { + GPIOA_SetBits(LED_PIN); + } +#else + if (state ^ LED_STATE_ON) { + GPIOB_ResetBits(LED_PIN); + } else { + GPIOB_SetBits(LED_PIN); + } +#endif +} + +uint32_t board_button_read(void) { +#ifdef BUTTON_PIN + #ifdef BUTTON_PORT_IS_A + return BUTTON_STATE_ACTIVE == (GPIOA_ReadPortPin(BUTTON_PIN) ? 1 : 0); + #else + return BUTTON_STATE_ACTIVE == (GPIOB_ReadPortPin(BUTTON_PIN) ? 1 : 0); + #endif +#else + return 0; +#endif +} + +// CH58x has no memory-mapped unique-ID register (unlike ch32v10x/v20x at 0x1FFFF7E8), but the +// factory programs a unique 6-byte MAC address into FlashROM (it is a BLE part). GetMACAddress() +// reads it via the ISP ROM command FLASH_EEPROM_CMD, which is provided by libISP583.a. +size_t board_get_unique_id(uint8_t id[], size_t max_len) { + // FLASH_EEPROM_CMD writes word-granular and requires a 4-byte-aligned buffer (CH58x_flash.c); + // size 8 matches the SDK's GET_UNIQUE_ID buffer (6 MAC bytes + 2 it pads), so the read can't + // run past the end whether it returns 6 or a full 8. + TU_ATTR_ALIGNED(4) uint8_t mac[8]; + GetMACAddress(mac); + size_t len = TU_MIN(max_len, (size_t) 6); // the 6-byte MAC is the unique part + memcpy(id, mac, len); + 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) { + int txsize = len; + const char* bufc = (const char*) buf; + while (txsize--) { + uart_write(*bufc++); + } + uart_sync(); + return len; +} diff --git a/hw/bsp/ch583/family.cmake b/hw/bsp/ch583/family.cmake new file mode 100644 index 000000000..a379298e5 --- /dev/null +++ b/hw/bsp/ch583/family.cmake @@ -0,0 +1,108 @@ +include_guard() + +set(SDK_DIR ${TOP}/hw/mcu/wch/ch583) +set(SDK_SRC_DIR ${SDK_DIR}/EVT/EXAM/SRC) + +# include board specific +include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) + +# toolchain set up +set(CMAKE_SYSTEM_CPU rv32imac-ilp32 CACHE INTERNAL "System Processor") +set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/riscv_${TOOLCHAIN}.cmake) + +set(FAMILY_MCUS CH583 CACHE INTERNAL "") +set(OPENOCD_OPTION "-f ${CMAKE_CURRENT_LIST_DIR}/wch-riscv.cfg") + +#------------------------------------ +# Startup & Linker script +#------------------------------------ +if (NOT DEFINED LD_FILE_GNU) + set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/linker/ch582.ld) +endif () +set(LD_FILE_Clang ${LD_FILE_GNU}) +if (NOT DEFINED STARTUP_FILE_GNU) + set(STARTUP_FILE_GNU ${SDK_SRC_DIR}/Startup/startup_CH583.S) +endif () +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) + +#------------------------------------ +# Board Target +#------------------------------------ +function(family_add_board BOARD_TARGET) + add_library(${BOARD_TARGET} STATIC + ${SDK_SRC_DIR}/StdPeriphDriver/CH58x_gpio.c + ${SDK_SRC_DIR}/StdPeriphDriver/CH58x_clk.c + ${SDK_SRC_DIR}/StdPeriphDriver/CH58x_uart1.c + ${SDK_SRC_DIR}/StdPeriphDriver/CH58x_sys.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/ch583_it.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/system_ch583.c + ) + target_include_directories(${BOARD_TARGET} PUBLIC + ${SDK_SRC_DIR}/RVMSIS + ${SDK_SRC_DIR}/StdPeriphDriver/inc + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ) + target_link_libraries(${BOARD_TARGET} PUBLIC + ${SDK_SRC_DIR}/StdPeriphDriver/libISP583.a + ) + target_compile_definitions(${BOARD_TARGET} PUBLIC + CFG_TUD_WCH_USBIP_USBFS=1 + FREQ_SYS=60000000 + DISK_LIB_ENABLE=0 + INT_SOFT + ) + + update_board(${BOARD_TARGET}) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_compile_options(${BOARD_TARGET} PUBLIC + -flto + -msmall-data-limit=16 + -mno-save-restore + -fmessage-length=0 + -fsigned-char + -Wno-error=strict-prototypes + ) + endif () +endfunction() + +#------------------------------------ +# Functions +#------------------------------------ +function(family_configure_example TARGET RTOS) + family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_CH583) + + target_sources(${TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/debug_uart.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/wch/dcd_ch32_usbfs.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} + ) + target_include_directories(${TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} + ) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + -nostartfiles + --specs=nosys.specs --specs=nano.specs + -Wl,--defsym=__FLASH_SIZE=${LD_FLASH_SIZE} + -Wl,--defsym=__RAM_SIZE=${LD_RAM_SIZE} + "LINKER:--script=${LD_FILE_GNU}" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + message(FATAL_ERROR "Clang is not supported for CH58x") + endif () + + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) + + # Flashing + family_add_bin_hex(${TARGET}) + family_flash_openocd_wch(${TARGET}) +endfunction() diff --git a/hw/bsp/ch583/family.mk b/hw/bsp/ch583/family.mk new file mode 100644 index 000000000..98d0f9337 --- /dev/null +++ b/hw/bsp/ch583/family.mk @@ -0,0 +1,59 @@ +# https://www.embecosm.com/resources/tool-chain-downloads/#riscv-stable +#CROSS_COMPILE ?= riscv32-unknown-elf- + +# Toolchain from https://nucleisys.com/download.php +#CROSS_COMPILE ?= riscv-nuclei-elf- + +# Toolchain from https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack +CROSS_COMPILE ?= riscv-none-elf- + +SDK_DIR = hw/mcu/wch/ch583 +SDK_SRC_DIR = $(SDK_DIR)/EVT/EXAM/SRC + +include $(TOP)/$(BOARD_PATH)/board.mk +CPU_CORE ?= rv32imac-ilp32 + +CFLAGS += \ + -flto \ + -msmall-data-limit=16 \ + -mno-save-restore \ + -fmessage-length=0 \ + -fsigned-char \ + -DCFG_TUSB_MCU=OPT_MCU_CH583 \ + -DCFG_TUD_WCH_USBIP_USBFS=1 \ + -DFREQ_SYS=60000000 \ + -DDISK_LIB_ENABLE=0 \ + -DINT_SOFT \ + -Wno-error=strict-prototypes + +LDFLAGS += \ + -nostartfiles \ + --specs=nosys.specs --specs=nano.specs + +LIBS += $(TOP)/$(SDK_SRC_DIR)/StdPeriphDriver/libISP583.a + +SRC_C += \ + src/portable/wch/dcd_ch32_usbfs.c \ + $(SDK_SRC_DIR)/StdPeriphDriver/CH58x_gpio.c \ + $(SDK_SRC_DIR)/StdPeriphDriver/CH58x_clk.c \ + $(SDK_SRC_DIR)/StdPeriphDriver/CH58x_uart1.c \ + $(SDK_SRC_DIR)/StdPeriphDriver/CH58x_sys.c \ + $(FAMILY_PATH)/debug_uart.c \ + $(FAMILY_PATH)/ch583_it.c \ + $(FAMILY_PATH)/system_ch583.c + +SRC_S += \ + $(SDK_SRC_DIR)/Startup/startup_CH583.S + +INC += \ + $(TOP)/$(BOARD_PATH) \ + $(TOP)/$(SDK_SRC_DIR)/RVMSIS \ + $(TOP)/$(SDK_SRC_DIR)/StdPeriphDriver/inc + +LD_FILE ?= $(FAMILY_PATH)/linker/ch582.ld + +OPENOCD_WCH_OPTION=-f $(TOP)/$(FAMILY_PATH)/wch-riscv.cfg +flash: flash-openocd-wch + +# For freeRTOS port source +FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/RISC-V diff --git a/hw/bsp/ch583/linker/ch582.ld b/hw/bsp/ch583/linker/ch582.ld new file mode 100644 index 000000000..821998a49 --- /dev/null +++ b/hw/bsp/ch583/linker/ch582.ld @@ -0,0 +1,167 @@ +/* CH582 Linker Script for TinyUSB + * Based on WCH CH583 SDK Link.ld + * Supports parameterized flash/ram sizes via --defsym + */ + +/* Default sizes if not provided via --defsym */ +__flash_size = DEFINED(__FLASH_SIZE) ? __FLASH_SIZE : 448K; +__ram_size = DEFINED(__RAM_SIZE) ? __RAM_SIZE : 32K; +__stack_size = DEFINED(__STACK_SIZE) ? __STACK_SIZE : 2048; + +ENTRY( _start ) + +PROVIDE( _stack_size = __stack_size ); + +MEMORY +{ + FLASH (rx) : ORIGIN = 0x00000000, LENGTH = __flash_size + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = __ram_size +} + +SECTIONS +{ + .init : + { + _sinit = .; + . = ALIGN(4); + KEEP(*(SORT_NONE(.init))) + . = ALIGN(4); + _einit = .; + } >FLASH AT>FLASH + + .highcodelalign : + { + . = ALIGN(4); + PROVIDE(_highcode_lma = .); + } >FLASH AT>FLASH + + .highcode : + { + . = ALIGN(4); + PROVIDE(_highcode_vma_start = .); + *(.vector); + KEEP(*(SORT_NONE(.vector_handler))) + *(.highcode); + *(.highcode.*); + . = ALIGN(4); + PROVIDE(_highcode_vma_end = .); + } >RAM AT>FLASH + + .text : + { + . = ALIGN(4); + KEEP(*(SORT_NONE(.handle_reset))) + *(.text) + *(.text.*) + *(.rodata) + *(.rodata*) + *(.sdata2.*) + *(.glue_7) + *(.glue_7t) + *(.gnu.linkonce.t.*) + . = ALIGN(4); + } >FLASH AT>FLASH + + .fini : + { + KEEP(*(SORT_NONE(.fini))) + . = ALIGN(4); + } >FLASH AT>FLASH + + PROVIDE( _etext = . ); + PROVIDE( _eitcm = . ); + + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } >FLASH AT>FLASH + + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) + KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) + PROVIDE_HIDDEN (__init_array_end = .); + } >FLASH AT>FLASH + + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) + KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) + PROVIDE_HIDDEN (__fini_array_end = .); + } >FLASH AT>FLASH + + .ctors : + { + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } >FLASH AT>FLASH + + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } >FLASH AT>FLASH + + .dlalign : + { + . = ALIGN(4); + PROVIDE(_data_lma = .); + } >FLASH AT>FLASH + + .data : + { + . = ALIGN(4); + PROVIDE(_data_vma = .); + *(.gnu.linkonce.r.*) + *(.data .data.*) + *(.gnu.linkonce.d.*) + . = ALIGN(8); + PROVIDE( __global_pointer$ = . + 0x800 ); + *(.sdata .sdata.*) + *(.gnu.linkonce.s.*) + . = ALIGN(8); + *(.srodata.cst16) + *(.srodata.cst8) + *(.srodata.cst4) + *(.srodata.cst2) + *(.srodata .srodata.*) + . = ALIGN(4); + PROVIDE( _edata = .); + } >RAM AT>FLASH + + .bss : + { + . = ALIGN(4); + PROVIDE( _sbss = .); + *(.sbss*) + *(.gnu.linkonce.sb.*) + *(.bss*) + *(.gnu.linkonce.b.*) + *(COMMON*) + . = ALIGN(4); + PROVIDE( _ebss = .); + } >RAM AT>FLASH + + PROVIDE( _end = _ebss); + PROVIDE( end = . ); + + .stack ORIGIN(RAM) + LENGTH(RAM) - __stack_size : + { + PROVIDE( _heap_end = . ); + . = ALIGN(4); + PROVIDE(_susrstack = . ); + . = . + __stack_size; + PROVIDE( _eusrstack = .); + __freertos_irq_stack_top = .; + } >RAM +} diff --git a/hw/bsp/ch583/system_ch583.c b/hw/bsp/ch583/system_ch583.c new file mode 100644 index 000000000..d3724f0ce --- /dev/null +++ b/hw/bsp/ch583/system_ch583.c @@ -0,0 +1,39 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2024 TinyUSB contributors + * + * 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 "CH58x_common.h" +#include "system_ch583.h" + +uint32_t SystemCoreClock = FREQ_SYS; + +void SystemInit(void) { + SetSysClock(CLK_SOURCE_PLL_60MHz); + SystemCoreClock = GetSysClock(); +} + +void SystemCoreClockUpdate(void) { + SystemCoreClock = GetSysClock(); +} diff --git a/hw/bsp/ch583/system_ch583.h b/hw/bsp/ch583/system_ch583.h new file mode 100644 index 000000000..c174c9f5e --- /dev/null +++ b/hw/bsp/ch583/system_ch583.h @@ -0,0 +1,43 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2024 TinyUSB contributors + * + * 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 SYSTEM_CH583_H_ +#define SYSTEM_CH583_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +extern uint32_t SystemCoreClock; // System Clock Frequency (Core Clock) + +extern void SystemInit(void); +extern void SystemCoreClockUpdate(void); + +#ifdef __cplusplus +} +#endif + +#endif /* SYSTEM_CH583_H_ */ diff --git a/hw/bsp/ch583/wch-riscv.cfg b/hw/bsp/ch583/wch-riscv.cfg new file mode 100644 index 000000000..64d595d8e --- /dev/null +++ b/hw/bsp/ch583/wch-riscv.cfg @@ -0,0 +1,17 @@ +adapter driver wlinke +adapter speed 6000 +transport select sdi + +wlink_set_address 0x00000000 +set _CHIPNAME wch_riscv +sdi newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x00001 + +set _TARGETNAME $_CHIPNAME.cpu + +target create $_TARGETNAME.0 wch_riscv -chain-position $_TARGETNAME +$_TARGETNAME.0 configure -work-area-phys 0x20000000 -work-area-size 0x8000 -work-area-backup 1 +set _FLASHNAME $_CHIPNAME.flash + +flash bank $_FLASHNAME wch_riscv 0x00000000 0 0 0 $_TARGETNAME.0 + +echo "Ready for Remote Connections" diff --git a/hw/bsp/ch58x/boards/ch582m_evt/board.cmake b/hw/bsp/ch58x/boards/ch582m_evt/board.cmake deleted file mode 100644 index 4129c4550..000000000 --- a/hw/bsp/ch58x/boards/ch582m_evt/board.cmake +++ /dev/null @@ -1,5 +0,0 @@ -set(LD_FLASH_SIZE 448K) -set(LD_RAM_SIZE 32K) - -function(update_board TARGET) -endfunction() diff --git a/hw/bsp/ch58x/boards/ch582m_evt/board.h b/hw/bsp/ch58x/boards/ch582m_evt/board.h deleted file mode 100644 index c3483bf17..000000000 --- a/hw/bsp/ch58x/boards/ch582m_evt/board.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2024 TinyUSB contributors - * - * 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. - */ - -/* metadata: - name: CH582M-EVT evaluation board - url: https://www.wch-ic.com/products/CH582.html -*/ - -#ifndef BOARD_H_ -#define BOARD_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -// LED: PB4 on CH582M-EVT -#define LED_PIN GPIO_Pin_4 -#define LED_STATE_ON 0 - -// Directly reuse BOOT pin as user button -#define BUTTON_PIN GPIO_Pin_22 -#define BUTTON_STATE_ACTIVE 0 - -// UART: UART1 TX=PA9, RX=PA8 -#define CFG_BOARD_UART_BAUDRATE 115200 - -// Device only on USB1 (rhport 0). CH58x host / USB2 is not supported by the shared usbfs dcd; -// BOARD_TUH_RHPORT is kept commented out to ease re-adding host later. -#ifndef BOARD_TUD_RHPORT -#define BOARD_TUD_RHPORT 0 -#endif -// #ifndef BOARD_TUH_RHPORT -// #define BOARD_TUH_RHPORT 1 -// #endif - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/hw/bsp/ch58x/boards/ch582m_evt/board.mk b/hw/bsp/ch58x/boards/ch582m_evt/board.mk deleted file mode 100644 index a13979799..000000000 --- a/hw/bsp/ch58x/boards/ch582m_evt/board.mk +++ /dev/null @@ -1,3 +0,0 @@ -LDFLAGS += \ - -Wl,--defsym=__FLASH_SIZE=448K \ - -Wl,--defsym=__RAM_SIZE=32K \ diff --git a/hw/bsp/ch58x/boards/yd-ch582m/board.cmake b/hw/bsp/ch58x/boards/yd-ch582m/board.cmake deleted file mode 100644 index 4129c4550..000000000 --- a/hw/bsp/ch58x/boards/yd-ch582m/board.cmake +++ /dev/null @@ -1,5 +0,0 @@ -set(LD_FLASH_SIZE 448K) -set(LD_RAM_SIZE 32K) - -function(update_board TARGET) -endfunction() diff --git a/hw/bsp/ch58x/boards/yd-ch582m/board.h b/hw/bsp/ch58x/boards/yd-ch582m/board.h deleted file mode 100644 index 0da5747bc..000000000 --- a/hw/bsp/ch58x/boards/yd-ch582m/board.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2024 TinyUSB contributors - * - * 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. - */ - -/* metadata: - name: yd-ch582m from vcc-gnd studio - url: http://vcc-gnd.com/ -*/ - -#ifndef BOARD_H_ -#define BOARD_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -// LED: PB4 on yd-ch582m board -#define LED_PIN GPIO_Pin_4 -#define LED_STATE_ON 0 - -// Directly reuse BOOT pin as user button -#define BUTTON_PIN GPIO_Pin_22 -#define BUTTON_STATE_ACTIVE 0 - -// UART: UART1 TX=PA9, RX=PA8 -#define CFG_BOARD_UART_BAUDRATE 115200 - -// Device only on USB1 (rhport 0). CH58x host / USB2 is not supported by the shared usbfs dcd; -// BOARD_TUH_RHPORT is kept commented out to ease re-adding host later. -#ifndef BOARD_TUD_RHPORT -#define BOARD_TUD_RHPORT 0 -#endif -// #ifndef BOARD_TUH_RHPORT -// #define BOARD_TUH_RHPORT 1 -// #endif - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/hw/bsp/ch58x/boards/yd-ch582m/board.mk b/hw/bsp/ch58x/boards/yd-ch582m/board.mk deleted file mode 100644 index a13979799..000000000 --- a/hw/bsp/ch58x/boards/yd-ch582m/board.mk +++ /dev/null @@ -1,3 +0,0 @@ -LDFLAGS += \ - -Wl,--defsym=__FLASH_SIZE=448K \ - -Wl,--defsym=__RAM_SIZE=32K \ diff --git a/hw/bsp/ch58x/ch58x_it.c b/hw/bsp/ch58x/ch58x_it.c deleted file mode 100644 index 2211e1eda..000000000 --- a/hw/bsp/ch58x/ch58x_it.c +++ /dev/null @@ -1,37 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2024 TinyUSB contributors - * - * 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 "ch58x_it.h" - -// NMI exception handler -__INTERRUPT __HIGH_CODE void NMI_Handler(void) { - while (1) {} -} - -// Hard Fault exception handler -__INTERRUPT __HIGH_CODE void HardFault_Handler(void) { - while (1) {} -} diff --git a/hw/bsp/ch58x/ch58x_it.h b/hw/bsp/ch58x/ch58x_it.h deleted file mode 100644 index 3e050344d..000000000 --- a/hw/bsp/ch58x/ch58x_it.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2024 TinyUSB contributors - * - * 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 CH58X_IT_H_ -#define CH58X_IT_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "CH58x_common.h" - -void NMI_Handler(void); -void HardFault_Handler(void); -void USB_IRQHandler(void); -// void USB2_IRQHandler(void); // host on USB2 (rhport 1) — re-add together with the host driver -void SysTick_Handler(void); - -#ifdef __cplusplus -} -#endif - -#endif /* CH58X_IT_H_ */ diff --git a/hw/bsp/ch58x/debug_uart.c b/hw/bsp/ch58x/debug_uart.c deleted file mode 100644 index 850e40718..000000000 --- a/hw/bsp/ch58x/debug_uart.c +++ /dev/null @@ -1,86 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2024 TinyUSB contributors - * - * 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 "debug_uart.h" -#include "CH58x_common.h" - -//--------------------------------------------------------------------+ -// Ring buffer based UART TX for non-blocking writes -//--------------------------------------------------------------------+ - -#define UART_RINGBUFFER_SIZE_TX 128 -#define UART_RINGBUFFER_MASK_TX (UART_RINGBUFFER_SIZE_TX - 1) - -static char tx_buf[UART_RINGBUFFER_SIZE_TX]; -static uint32_t tx_produce; -static volatile uint32_t tx_consume; - -void uart_write(char c) { - uint32_t tx_produce_next = (tx_produce + 1) & UART_RINGBUFFER_MASK_TX; - - // If the ring buffer is full, drain it here as the FIFO frees up: nothing else advances - // tx_consume between uart_write() calls, so a plain spin would deadlock on a >buffer-size burst. - while (tx_produce_next == tx_consume) { - if (R8_UART1_LSR & RB_LSR_TX_FIFO_EMP) { - R8_UART1_THR = tx_buf[tx_consume]; - tx_consume = (tx_consume + 1) & UART_RINGBUFFER_MASK_TX; - } - } - - // If UART TX FIFO is empty and no pending data, send directly - if ((tx_consume == tx_produce) && (R8_UART1_LSR & RB_LSR_TX_FIFO_EMP)) { - R8_UART1_THR = c; - } else { - tx_buf[tx_produce] = c; - tx_produce = tx_produce_next; - } -} - -void uart_sync(void) { - // Wait for ring buffer to drain - while (tx_consume != tx_produce) { - if (R8_UART1_LSR & RB_LSR_TX_FIFO_EMP) { - R8_UART1_THR = tx_buf[tx_consume]; - tx_consume = (tx_consume + 1) & UART_RINGBUFFER_MASK_TX; - } - } - // Wait for last byte to finish transmitting - while (!(R8_UART1_LSR & RB_LSR_TX_ALL_EMP)) {} -} - -void usart_printf_init(uint32_t baudrate) { - tx_produce = 0; - tx_consume = 0; - - // Configure UART1 pins: TX=PA9, RX=PA8 - GPIOA_SetBits(GPIO_Pin_9); - GPIOA_ModeCfg(GPIO_Pin_9, GPIO_ModeOut_PP_5mA); - GPIOA_ModeCfg(GPIO_Pin_8, GPIO_ModeIN_PU); - - // Init UART1 with specified baud rate - UART1_DefInit(); - UART1_BaudRateCfg(baudrate); -} diff --git a/hw/bsp/ch58x/debug_uart.h b/hw/bsp/ch58x/debug_uart.h deleted file mode 100644 index 44c3e7948..000000000 --- a/hw/bsp/ch58x/debug_uart.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2024 TinyUSB contributors - * - * 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 DEBUG_UART_H_ -#define DEBUG_UART_H_ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -void uart_write(char c); -void uart_sync(void); -void usart_printf_init(uint32_t baudrate); - -#ifdef __cplusplus -} -#endif - -#endif /* DEBUG_UART_H_ */ diff --git a/hw/bsp/ch58x/family.c b/hw/bsp/ch58x/family.c deleted file mode 100644 index 64ae4a903..000000000 --- a/hw/bsp/ch58x/family.c +++ /dev/null @@ -1,194 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2024 TinyUSB contributors - * - * 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: WCH -*/ - -// WCH SDK's DEBUG macro enables a _write() that conflicts with TinyUSB's. -// TinyUSB uses UART1 for printf via debug_uart.c, so DEBUG is not needed. -// If you need a different UART or want to keep SDK's DEBUG, modify -// debug_uart.c (TinyUSB side) or CH58x_sys.c (SDK side) to remove one _write(). -// If done, remove this #error to continue. -#ifdef DEBUG - #error "Remove the DEBUG macro from preprocessor defines to avoid " \ - "duplicate _write() between WCH SDK and TinyUSB. " \ - "TinyUSB uses UART1 by default (see debug_uart.c)." -#endif - -#include "debug_uart.h" -#include "CH58x_common.h" -#include "ch58x_it.h" - -#include "bsp/board_api.h" -#include "board.h" - -//--------------------------------------------------------------------+ -// Forward USB interrupt events to TinyUSB IRQ Handler -//--------------------------------------------------------------------+ - -// Device only: the shared dcd_ch32_usbfs.c drives USB0 (rhport 0). CH58x's second controller -// (USB2 / rhport 1) was driven by the now-removed ch58x host driver; its handler is kept -// commented out below to ease re-adding host support. -__INTERRUPT __HIGH_CODE void USB_IRQHandler(void) { - tusb_int_handler(0, true); -} - -// __INTERRUPT __HIGH_CODE void USB2_IRQHandler(void) { -// tusb_int_handler(1, true); -// } - -//--------------------------------------------------------------------+ -// SysTick -//--------------------------------------------------------------------+ - -#if CFG_TUSB_OS == OPT_OS_NONE -volatile uint32_t system_ticks = 0; - -__INTERRUPT __HIGH_CODE void SysTick_Handler(void) { - SysTick->SR = 0; - system_ticks++; -} - -uint32_t tusb_time_millis_api(void) { - return system_ticks; -} -#endif - -//--------------------------------------------------------------------+ -// Board Init -//--------------------------------------------------------------------+ - -void board_init(void) { - // Disable interrupts during init - PFIC_DisableAllIRQ(); - - // Set system clock to PLL 60MHz (default for CH582) - SetSysClock(CLK_SOURCE_PLL_60MHz); - -#if CFG_TUSB_OS == OPT_OS_NONE - SysTick_Config(GetSysClock() / 1000); -#endif - - // UART1 init for debug output -#ifdef CFG_BOARD_UART_BAUDRATE - usart_printf_init(CFG_BOARD_UART_BAUDRATE); -#endif - - // LED -#ifdef LED_PORT_IS_A - GPIOA_ModeCfg(LED_PIN, GPIO_ModeOut_PP_5mA); -#else - GPIOB_ModeCfg(LED_PIN, GPIO_ModeOut_PP_5mA); -#endif - - // Button -#ifdef BUTTON_PIN - #ifdef BUTTON_PORT_IS_A - GPIOA_ModeCfg(BUTTON_PIN, GPIO_ModeIN_PU); - #else - GPIOB_ModeCfg(BUTTON_PIN, GPIO_ModeIN_PU); - #endif -#endif - - // Device only on USB0 (rhport 0): enable analog function for USB1 D+/D- and assert its D+ - // pull-up. The shared dcd_ch32_usbfs.c drives USB0; CH58x host / USB2 (rhport 1) is unsupported - // here — to re-add host, also OR in RB_PIN_USB2_IE below. - R16_PIN_ANALOG_IE |= RB_PIN_USB_IE; // | RB_PIN_USB2_IE (re-add for host on USB2) -#if CFG_TUD_ENABLED - R16_PIN_ANALOG_IE |= RB_PIN_USB_DP_PU; -#endif - - // Keep USB clock active during sleep - R8_SLP_CLK_OFF1 &= ~RB_SLP_CLK_USB; - - // Enable interrupts globally - PFIC_EnableAllIRQ(); - - board_delay(2); -} - -//--------------------------------------------------------------------+ -// Board porting API -//--------------------------------------------------------------------+ - -void board_led_write(bool state) { -#ifdef LED_PORT_IS_A - if (state ^ LED_STATE_ON) { - GPIOA_ResetBits(LED_PIN); - } else { - GPIOA_SetBits(LED_PIN); - } -#else - if (state ^ LED_STATE_ON) { - GPIOB_ResetBits(LED_PIN); - } else { - GPIOB_SetBits(LED_PIN); - } -#endif -} - -uint32_t board_button_read(void) { -#ifdef BUTTON_PIN - #ifdef BUTTON_PORT_IS_A - return BUTTON_STATE_ACTIVE == (GPIOA_ReadPortPin(BUTTON_PIN) ? 1 : 0); - #else - return BUTTON_STATE_ACTIVE == (GPIOB_ReadPortPin(BUTTON_PIN) ? 1 : 0); - #endif -#else - return 0; -#endif -} - -// CH58x has no memory-mapped unique-ID register (unlike ch32v10x/v20x at 0x1FFFF7E8), but the -// factory programs a unique 6-byte MAC address into FlashROM (it is a BLE part). GetMACAddress() -// reads it via the ISP ROM command FLASH_EEPROM_CMD, which is provided by libISP583.a. -size_t board_get_unique_id(uint8_t id[], size_t max_len) { - // FLASH_EEPROM_CMD writes word-granular and requires a 4-byte-aligned buffer (CH58x_flash.c); - // size 8 matches the SDK's GET_UNIQUE_ID buffer (6 MAC bytes + 2 it pads), so the read can't - // run past the end whether it returns 6 or a full 8. - TU_ATTR_ALIGNED(4) uint8_t mac[8]; - GetMACAddress(mac); - size_t len = TU_MIN(max_len, (size_t) 6); // the 6-byte MAC is the unique part - memcpy(id, mac, len); - 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) { - int txsize = len; - const char* bufc = (const char*) buf; - while (txsize--) { - uart_write(*bufc++); - } - uart_sync(); - return len; -} diff --git a/hw/bsp/ch58x/family.cmake b/hw/bsp/ch58x/family.cmake deleted file mode 100644 index a52309276..000000000 --- a/hw/bsp/ch58x/family.cmake +++ /dev/null @@ -1,108 +0,0 @@ -include_guard() - -set(SDK_DIR ${TOP}/hw/mcu/wch/ch583) -set(SDK_SRC_DIR ${SDK_DIR}/EVT/EXAM/SRC) - -# include board specific -include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) - -# toolchain set up -set(CMAKE_SYSTEM_CPU rv32imac-ilp32 CACHE INTERNAL "System Processor") -set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/riscv_${TOOLCHAIN}.cmake) - -set(FAMILY_MCUS CH58X CACHE INTERNAL "") -set(OPENOCD_OPTION "-f ${CMAKE_CURRENT_LIST_DIR}/wch-riscv.cfg") - -#------------------------------------ -# Startup & Linker script -#------------------------------------ -if (NOT DEFINED LD_FILE_GNU) - set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/linker/ch582.ld) -endif () -set(LD_FILE_Clang ${LD_FILE_GNU}) -if (NOT DEFINED STARTUP_FILE_GNU) - set(STARTUP_FILE_GNU ${SDK_SRC_DIR}/Startup/startup_CH583.S) -endif () -set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) - -#------------------------------------ -# Board Target -#------------------------------------ -function(family_add_board BOARD_TARGET) - add_library(${BOARD_TARGET} STATIC - ${SDK_SRC_DIR}/StdPeriphDriver/CH58x_gpio.c - ${SDK_SRC_DIR}/StdPeriphDriver/CH58x_clk.c - ${SDK_SRC_DIR}/StdPeriphDriver/CH58x_uart1.c - ${SDK_SRC_DIR}/StdPeriphDriver/CH58x_sys.c - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/ch58x_it.c - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/system_ch58x.c - ) - target_include_directories(${BOARD_TARGET} PUBLIC - ${SDK_SRC_DIR}/RVMSIS - ${SDK_SRC_DIR}/StdPeriphDriver/inc - ${CMAKE_CURRENT_FUNCTION_LIST_DIR} - ) - target_link_libraries(${BOARD_TARGET} PUBLIC - ${SDK_SRC_DIR}/StdPeriphDriver/libISP583.a - ) - target_compile_definitions(${BOARD_TARGET} PUBLIC - CFG_TUD_WCH_USBIP_USBFS=1 - FREQ_SYS=60000000 - DISK_LIB_ENABLE=0 - INT_SOFT - ) - - update_board(${BOARD_TARGET}) - - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_compile_options(${BOARD_TARGET} PUBLIC - -flto - -msmall-data-limit=16 - -mno-save-restore - -fmessage-length=0 - -fsigned-char - -Wno-error=strict-prototypes - ) - endif () -endfunction() - -#------------------------------------ -# Functions -#------------------------------------ -function(family_configure_example TARGET RTOS) - family_configure_common(${TARGET} ${RTOS}) - family_add_tinyusb(${TARGET} OPT_MCU_CH58X) - - target_sources(${TARGET} PUBLIC - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/debug_uart.c - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c - ${TOP}/src/portable/wch/dcd_ch32_usbfs.c - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} - ) - target_include_directories(${TARGET} PUBLIC - ${CMAKE_CURRENT_FUNCTION_LIST_DIR} - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} - ) - - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_link_options(${TARGET} PUBLIC - -nostartfiles - --specs=nosys.specs --specs=nano.specs - -Wl,--defsym=__FLASH_SIZE=${LD_FLASH_SIZE} - -Wl,--defsym=__RAM_SIZE=${LD_RAM_SIZE} - "LINKER:--script=${LD_FILE_GNU}" - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - message(FATAL_ERROR "Clang is not supported for CH58x") - endif () - - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES - SKIP_LINTING ON - COMPILE_OPTIONS -w) - - # Flashing - family_add_bin_hex(${TARGET}) - family_flash_openocd_wch(${TARGET}) -endfunction() diff --git a/hw/bsp/ch58x/family.mk b/hw/bsp/ch58x/family.mk deleted file mode 100644 index ac0443659..000000000 --- a/hw/bsp/ch58x/family.mk +++ /dev/null @@ -1,59 +0,0 @@ -# https://www.embecosm.com/resources/tool-chain-downloads/#riscv-stable -#CROSS_COMPILE ?= riscv32-unknown-elf- - -# Toolchain from https://nucleisys.com/download.php -#CROSS_COMPILE ?= riscv-nuclei-elf- - -# Toolchain from https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack -CROSS_COMPILE ?= riscv-none-elf- - -SDK_DIR = hw/mcu/wch/ch583 -SDK_SRC_DIR = $(SDK_DIR)/EVT/EXAM/SRC - -include $(TOP)/$(BOARD_PATH)/board.mk -CPU_CORE ?= rv32imac-ilp32 - -CFLAGS += \ - -flto \ - -msmall-data-limit=16 \ - -mno-save-restore \ - -fmessage-length=0 \ - -fsigned-char \ - -DCFG_TUSB_MCU=OPT_MCU_CH58X \ - -DCFG_TUD_WCH_USBIP_USBFS=1 \ - -DFREQ_SYS=60000000 \ - -DDISK_LIB_ENABLE=0 \ - -DINT_SOFT \ - -Wno-error=strict-prototypes - -LDFLAGS += \ - -nostartfiles \ - --specs=nosys.specs --specs=nano.specs - -LIBS += $(TOP)/$(SDK_SRC_DIR)/StdPeriphDriver/libISP583.a - -SRC_C += \ - src/portable/wch/dcd_ch32_usbfs.c \ - $(SDK_SRC_DIR)/StdPeriphDriver/CH58x_gpio.c \ - $(SDK_SRC_DIR)/StdPeriphDriver/CH58x_clk.c \ - $(SDK_SRC_DIR)/StdPeriphDriver/CH58x_uart1.c \ - $(SDK_SRC_DIR)/StdPeriphDriver/CH58x_sys.c \ - $(FAMILY_PATH)/debug_uart.c \ - $(FAMILY_PATH)/ch58x_it.c \ - $(FAMILY_PATH)/system_ch58x.c - -SRC_S += \ - $(SDK_SRC_DIR)/Startup/startup_CH583.S - -INC += \ - $(TOP)/$(BOARD_PATH) \ - $(TOP)/$(SDK_SRC_DIR)/RVMSIS \ - $(TOP)/$(SDK_SRC_DIR)/StdPeriphDriver/inc - -LD_FILE ?= $(FAMILY_PATH)/linker/ch582.ld - -OPENOCD_WCH_OPTION=-f $(TOP)/$(FAMILY_PATH)/wch-riscv.cfg -flash: flash-openocd-wch - -# For freeRTOS port source -FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/RISC-V diff --git a/hw/bsp/ch58x/linker/ch582.ld b/hw/bsp/ch58x/linker/ch582.ld deleted file mode 100644 index 821998a49..000000000 --- a/hw/bsp/ch58x/linker/ch582.ld +++ /dev/null @@ -1,167 +0,0 @@ -/* CH582 Linker Script for TinyUSB - * Based on WCH CH583 SDK Link.ld - * Supports parameterized flash/ram sizes via --defsym - */ - -/* Default sizes if not provided via --defsym */ -__flash_size = DEFINED(__FLASH_SIZE) ? __FLASH_SIZE : 448K; -__ram_size = DEFINED(__RAM_SIZE) ? __RAM_SIZE : 32K; -__stack_size = DEFINED(__STACK_SIZE) ? __STACK_SIZE : 2048; - -ENTRY( _start ) - -PROVIDE( _stack_size = __stack_size ); - -MEMORY -{ - FLASH (rx) : ORIGIN = 0x00000000, LENGTH = __flash_size - RAM (xrw) : ORIGIN = 0x20000000, LENGTH = __ram_size -} - -SECTIONS -{ - .init : - { - _sinit = .; - . = ALIGN(4); - KEEP(*(SORT_NONE(.init))) - . = ALIGN(4); - _einit = .; - } >FLASH AT>FLASH - - .highcodelalign : - { - . = ALIGN(4); - PROVIDE(_highcode_lma = .); - } >FLASH AT>FLASH - - .highcode : - { - . = ALIGN(4); - PROVIDE(_highcode_vma_start = .); - *(.vector); - KEEP(*(SORT_NONE(.vector_handler))) - *(.highcode); - *(.highcode.*); - . = ALIGN(4); - PROVIDE(_highcode_vma_end = .); - } >RAM AT>FLASH - - .text : - { - . = ALIGN(4); - KEEP(*(SORT_NONE(.handle_reset))) - *(.text) - *(.text.*) - *(.rodata) - *(.rodata*) - *(.sdata2.*) - *(.glue_7) - *(.glue_7t) - *(.gnu.linkonce.t.*) - . = ALIGN(4); - } >FLASH AT>FLASH - - .fini : - { - KEEP(*(SORT_NONE(.fini))) - . = ALIGN(4); - } >FLASH AT>FLASH - - PROVIDE( _etext = . ); - PROVIDE( _eitcm = . ); - - .preinit_array : - { - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP (*(.preinit_array)) - PROVIDE_HIDDEN (__preinit_array_end = .); - } >FLASH AT>FLASH - - .init_array : - { - PROVIDE_HIDDEN (__init_array_start = .); - KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) - KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) - PROVIDE_HIDDEN (__init_array_end = .); - } >FLASH AT>FLASH - - .fini_array : - { - PROVIDE_HIDDEN (__fini_array_start = .); - KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) - KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) - PROVIDE_HIDDEN (__fini_array_end = .); - } >FLASH AT>FLASH - - .ctors : - { - KEEP (*crtbegin.o(.ctors)) - KEEP (*crtbegin?.o(.ctors)) - KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) - KEEP (*(SORT(.ctors.*))) - KEEP (*(.ctors)) - } >FLASH AT>FLASH - - .dtors : - { - KEEP (*crtbegin.o(.dtors)) - KEEP (*crtbegin?.o(.dtors)) - KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) - KEEP (*(SORT(.dtors.*))) - KEEP (*(.dtors)) - } >FLASH AT>FLASH - - .dlalign : - { - . = ALIGN(4); - PROVIDE(_data_lma = .); - } >FLASH AT>FLASH - - .data : - { - . = ALIGN(4); - PROVIDE(_data_vma = .); - *(.gnu.linkonce.r.*) - *(.data .data.*) - *(.gnu.linkonce.d.*) - . = ALIGN(8); - PROVIDE( __global_pointer$ = . + 0x800 ); - *(.sdata .sdata.*) - *(.gnu.linkonce.s.*) - . = ALIGN(8); - *(.srodata.cst16) - *(.srodata.cst8) - *(.srodata.cst4) - *(.srodata.cst2) - *(.srodata .srodata.*) - . = ALIGN(4); - PROVIDE( _edata = .); - } >RAM AT>FLASH - - .bss : - { - . = ALIGN(4); - PROVIDE( _sbss = .); - *(.sbss*) - *(.gnu.linkonce.sb.*) - *(.bss*) - *(.gnu.linkonce.b.*) - *(COMMON*) - . = ALIGN(4); - PROVIDE( _ebss = .); - } >RAM AT>FLASH - - PROVIDE( _end = _ebss); - PROVIDE( end = . ); - - .stack ORIGIN(RAM) + LENGTH(RAM) - __stack_size : - { - PROVIDE( _heap_end = . ); - . = ALIGN(4); - PROVIDE(_susrstack = . ); - . = . + __stack_size; - PROVIDE( _eusrstack = .); - __freertos_irq_stack_top = .; - } >RAM -} diff --git a/hw/bsp/ch58x/system_ch58x.c b/hw/bsp/ch58x/system_ch58x.c deleted file mode 100644 index 068c1a131..000000000 --- a/hw/bsp/ch58x/system_ch58x.c +++ /dev/null @@ -1,39 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2024 TinyUSB contributors - * - * 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 "CH58x_common.h" -#include "system_ch58x.h" - -uint32_t SystemCoreClock = FREQ_SYS; - -void SystemInit(void) { - SetSysClock(CLK_SOURCE_PLL_60MHz); - SystemCoreClock = GetSysClock(); -} - -void SystemCoreClockUpdate(void) { - SystemCoreClock = GetSysClock(); -} diff --git a/hw/bsp/ch58x/system_ch58x.h b/hw/bsp/ch58x/system_ch58x.h deleted file mode 100644 index e96741ee8..000000000 --- a/hw/bsp/ch58x/system_ch58x.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2024 TinyUSB contributors - * - * 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 SYSTEM_CH58X_H_ -#define SYSTEM_CH58X_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -extern uint32_t SystemCoreClock; // System Clock Frequency (Core Clock) - -extern void SystemInit(void); -extern void SystemCoreClockUpdate(void); - -#ifdef __cplusplus -} -#endif - -#endif /* SYSTEM_CH58X_H_ */ diff --git a/hw/bsp/ch58x/wch-riscv.cfg b/hw/bsp/ch58x/wch-riscv.cfg deleted file mode 100644 index 64d595d8e..000000000 --- a/hw/bsp/ch58x/wch-riscv.cfg +++ /dev/null @@ -1,17 +0,0 @@ -adapter driver wlinke -adapter speed 6000 -transport select sdi - -wlink_set_address 0x00000000 -set _CHIPNAME wch_riscv -sdi newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x00001 - -set _TARGETNAME $_CHIPNAME.cpu - -target create $_TARGETNAME.0 wch_riscv -chain-position $_TARGETNAME -$_TARGETNAME.0 configure -work-area-phys 0x20000000 -work-area-size 0x8000 -work-area-backup 1 -set _FLASHNAME $_CHIPNAME.flash - -flash bank $_FLASHNAME wch_riscv 0x00000000 0 0 0 $_TARGETNAME.0 - -echo "Ready for Remote Connections" diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index f2a2d92a5..b5390a59d 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -659,7 +659,7 @@ #define TUP_DCD_EDPT_CLOSE_API #endif -#elif TU_CHECK_MCU(OPT_MCU_CH58X) +#elif TU_CHECK_MCU(OPT_MCU_CH583) // CH582/583 USBFS: older WCH USBFS IP with a single combined per-endpoint control register // (like CH32V103), driven by the shared dcd_ch32_usbfs.c on USB0 (rhport 0). Device only: // the shared hcd_ch32_usbfs.c is CH32V20x-specific and does not support CH58x, so host / diff --git a/src/portable/wch/ch32_usbfs_reg.h b/src/portable/wch/ch32_usbfs_reg.h index 90a477b79..415a015dc 100644 --- a/src/portable/wch/ch32_usbfs_reg.h +++ b/src/portable/wch/ch32_usbfs_reg.h @@ -130,7 +130,7 @@ #elif CFG_TUSB_MCU == OPT_MCU_CH32V307 #include #define USBHD_IRQn OTG_FS_IRQn -#elif CFG_TUSB_MCU == OPT_MCU_CH58X +#elif CFG_TUSB_MCU == OPT_MCU_CH583 #include "CH58x_common.h" // CH582/583 USBFS device controller: same combined per-endpoint control register as // CH32V103 (IN response bits[1:0], OUT response bits[3:2]) but a different register map - diff --git a/src/portable/wch/dcd_ch32_usbfs.c b/src/portable/wch/dcd_ch32_usbfs.c index 22c7a43fa..ece9cde07 100644 --- a/src/portable/wch/dcd_ch32_usbfs.c +++ b/src/portable/wch/dcd_ch32_usbfs.c @@ -37,7 +37,7 @@ // Struct-based EP register access (uniform layout). CH58X has a different register map and // defines EP_DMA/EP_TX_LEN/EP_CTRL itself in ch32_usbfs_reg.h. - #if CFG_TUSB_MCU == OPT_MCU_CH58X + #if CFG_TUSB_MCU == OPT_MCU_CH583 // CH58X EP registers split into a low block (EP0-4) and a high block (EP5-7). Walk from each // block's first slot by the 4-byte slot stride (pointer arithmetic off slot 0, so the unused // ternary branch's index can't trip -Warray-bounds). EP4 has no DMA register of its own (it @@ -220,7 +220,7 @@ static void update_in(uint8_t rhport, uint8_t ep, bool force) { if (xfer->valid) { if (force || xfer->len) { size_t len = TU_MIN(xfer->max_size, xfer->len); -#if CFG_TUSB_MCU == OPT_MCU_CH58X +#if CFG_TUSB_MCU == OPT_MCU_CH583 // Every CH58x endpoint buffer is 64 bytes. Isochronous (which would push max_size up to 1023) // is refused in dcd_edpt_iso_alloc(), but some classes (e.g. video) ignore that result, so cap // the copy here to guarantee we never write past the buffer into a neighbouring endpoint's. @@ -256,7 +256,7 @@ static void update_out(uint8_t rhport, uint8_t ep, size_t rx_len) { struct usb_xfer *xfer = &data.xfer[ep][TUSB_DIR_OUT]; if (xfer->valid) { size_t len = TU_MIN(xfer->max_size, TU_MIN(xfer->len, rx_len)); -#if CFG_TUSB_MCU == OPT_MCU_CH58X +#if CFG_TUSB_MCU == OPT_MCU_CH583 len = TU_MIN(len, 64u); // cap to the 64-byte EP buffer (see update_in) #endif memcpy(xfer->buffer, ep_out_buf(ep), len); @@ -308,7 +308,7 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t *rh_init) { // enable other endpoints but NAK everything USBOTG_FS->UEP4_1_MOD = 0xCC; USBOTG_FS->UEP2_3_MOD = 0xCC; -#if CFG_TUSB_MCU == OPT_MCU_CH58X +#if CFG_TUSB_MCU == OPT_MCU_CH583 // CH58X: a single mode register enables EP5/6/7 RX+TX (different bit layout than CH32). USBOTG_FS->UEP567_MOD = RB_UEP5_RX_EN | RB_UEP5_TX_EN | RB_UEP6_RX_EN | RB_UEP6_TX_EN | RB_UEP7_RX_EN | RB_UEP7_TX_EN; @@ -393,7 +393,7 @@ void dcd_int_handler(uint8_t rhport) { USBOTG_FS->INT_FG = USBFS_INT_FG_BUS_RST; } else if (status & USBFS_INT_FG_SUSPEND) { -#if CFG_TUSB_MCU == OPT_MCU_CH58X +#if CFG_TUSB_MCU == OPT_MCU_CH583 // CH58x raises this single interrupt for both suspend and resume; MIS_ST's suspend bit tells // them apart (set while suspended, clear once resumed) so tud_resume_cb() actually fires. dcd_event_t event = {.rhport = rhport, @@ -447,7 +447,7 @@ void dcd_edpt0_status_complete(uint8_t rhport, const tusb_control_request_t *req (void)rhport; if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE && request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && request->bRequest == TUSB_REQ_SET_ADDRESS) { -#if CFG_TUSB_MCU == OPT_MCU_CH58X +#if CFG_TUSB_MCU == OPT_MCU_CH583 // On CH58x R8_USB_DEV_AD bit 7 is a user general-purpose flag; only bits [6:0] are the address. USBOTG_FS->DEV_ADDR = (uint8_t)((USBOTG_FS->DEV_ADDR & 0x80u) | (request->wValue & 0x7Fu)); #else @@ -485,7 +485,7 @@ bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet (void)rhport; (void)ep_addr; (void)largest_packet_size; -#if CFG_TUSB_MCU == OPT_MCU_CH58X +#if CFG_TUSB_MCU == OPT_MCU_CH583 // No isochronous support on CH58x: its 8-bit T_LEN caps a packet at 255B and the endpoints use // plain 64-byte buffers, so accepting an iso max_size (up to 1023) would let update_in()/ // update_out() run off the end of the buffer into neighbouring ones. Refuse it outright. @@ -503,7 +503,7 @@ bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet bool dcd_edpt_iso_activate(uint8_t rhport, const tusb_desc_endpoint_t *desc_ep) { (void)rhport; (void)desc_ep; -#if CFG_TUSB_MCU == OPT_MCU_CH58X +#if CFG_TUSB_MCU == OPT_MCU_CH583 return false; // CH58x has no isochronous support (see dcd_edpt_iso_alloc) #else return true; diff --git a/src/tusb_option.h b/src/tusb_option.h index 9170d1205..cb8e3f6bd 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -195,7 +195,7 @@ #define OPT_MCU_CH32F20X 2210 ///< WCH CH32F20x #define OPT_MCU_CH32V20X 2220 ///< WCH CH32V20X #define OPT_MCU_CH32V103 2230 ///< WCH CH32V103 -#define OPT_MCU_CH58X 2240 ///< WCH CH58x +#define OPT_MCU_CH583 2240 ///< WCH CH583 #define OPT_MCU_CH582 2240 ///< alias to CH58x series #define OPT_MCU_CH583 2240 ///< alias to CH58x series diff --git a/tools/get_deps.py b/tools/get_deps.py index b31f8a0cb..ebbf9b871 100755 --- a/tools/get_deps.py +++ b/tools/get_deps.py @@ -255,7 +255,7 @@ deps_optional = { 'ch32f20x'], 'hw/mcu/wch/ch583': ['https://github.com/openwch/ch583.git', 'bd508ad7ceed48377619837051412a651952857f', - 'ch58x'], + 'ch583'], 'hw/mcu/artery/at32f403a_407': ['https://github.com/ArteryTek/AT32F403A_407_Firmware_Library.git', 'f2cb360c3d28fada76b374308b8c4c61d37a090b', 'at32f403a_407'], -- cgit v1.3.1