29#if CFG_TUH_ENABLED && \
30 TU_CHECK_MCU(OPT_MCU_MSP432E4, OPT_MCU_TM4C123, OPT_MCU_TM4C129)
32#if __GNUC__ > 8 && defined(__ARM_FEATURE_UNALIGNED)
35_Pragma(
"GCC diagnostic ignored \"-Waddress-of-packed-member\"");
42#if TU_CHECK_MCU(OPT_MCU_MSP432E4, OPT_MCU_TM4C123, OPT_MCU_TM4C129)
45 #error "Unsupported MCUs"
48#ifndef HCD_ATTR_ENDPOINT_MAX
49# define HCD_ATTR_ENDPOINT_MAX 8
55#define REQUEST_TYPE_INVALID (0xFFu)
125 for (; cur < end && ((addr < cur->
beg) || (cur->
end <= addr)); ++cur) ;
132 TU_ASSERT(p != blks + num, -2);
133 if (p->
beg == addr) {
135 p->
beg = addr + size;
136 if (p->
beg != p->
end)
return 0;
139 while (p + 1 < end) {
158 while (p + 1 < end) {
164 if (tmp.
beg == tmp.
end)
return 0;
172 return blk->
end - blk->
beg;
177 free_block_t free_blocks[2 * (HCD_ATTR_ENDPOINT_MAX - 1)];
178 unsigned num_blocks = 1;
181 free_blocks[0].
beg = 64 / 8;
182 free_blocks[0].end = (4 << 10) / 8;
183 for (
int i = 1; i < HCD_ATTR_ENDPOINT_MAX; ++i) {
187 addr = USB0->TXFIFOADD;
189 unsigned sz = USB0->TXFIFOSZ;
190 unsigned sft = (sz & USB_TXFIFOSZ_SIZE_M) + ((sz & USB_TXFIFOSZ_DPB) ? 1: 0);
192 TU_ASSERT(-2 < num, 0);
195 addr = USB0->RXFIFOADD;
197 unsigned sz = USB0->RXFIFOSZ;
198 unsigned sft = (sz & USB_RXFIFOSZ_SIZE_M) + ((sz & USB_RXFIFOSZ_DPB) ? 1: 0);
200 TU_ASSERT(-2 < num, 0);
206 uint_fast16_t size_in_8byte_unit = 1 << size_in_log2_minus3;
208 uint_fast16_t min_sz = 0xFFFFu;
210 for (
free_block_t const *cur = &free_blocks[0]; cur < end; ++cur) {
212 if (sz < size_in_8byte_unit)
continue;
213 if (size_in_8byte_unit == sz)
return cur->beg;
214 if (sz < min_sz) min = cur;
223 return regs + epnum_minus1;
228 unsigned const dir_tx =
tu_edpt_dir(ep_addr) ? 0: 1;
230 for (
unsigned i = 0; i <
sizeof(
_hcd.
addr)/
sizeof(
_hcd.
addr[0]); ++i, p += 2) {
240 uintptr_t addr = (uintptr_t)buf;
242 reg->
u32 = *(uint32_t
const *)addr;
247 reg->
u16 = *(uint16_t
const *)addr;
252 reg->
u8 = *(uint8_t
const *)addr;
259 uintptr_t addr = (uintptr_t)buf;
261 *(uint32_t *)addr = reg->
u32;
266 *(uint16_t *)addr = reg->
u16;
271 *(uint8_t *)addr = reg->
u8;
283 unsigned const dev_addr = USB0->TXFUNCADDR0;
285 unsigned const len = TU_MIN(rem, mps);
286 void *buf = pipe->
buf;
289 pipe->
buf = (uint8_t*)buf + len;
292 USB0->CSRL0 = USB_CSRL0_TXRDY;
300 unsigned const dev_addr = USB0->TXFUNCADDR0;
302 unsigned const vld = USB0->COUNT0;
303 unsigned const len = TU_MIN(TU_MIN(rem, mps), vld);
304 void *buf = pipe->
buf;
307 pipe->
buf = (uint8_t*)buf + len;
310 if ((len < mps) || (rem == len)) {
314 USB0->CSRL0 = USB_CSRL0_REQPKT;
323 TU_ASSERT(req != REQUEST_TYPE_INVALID);
334 USB0->CSRL0 = USB_CSRL0_REQPKT;
341 USB0->CSRL0 = USB_CSRL0_STATUS | (dir_in ? USB_CSRL0_REQPKT: USB_CSRL0_TXRDY);
355 unsigned const mps = regs->
TXMAXP;
356 unsigned const len = TU_MIN(rem, mps);
357 void *buf = pipe->
buf;
360 pipe->
buf = (uint8_t*)buf + len;
363 regs->
TXCSRL = USB_TXCSRL1_TXRDY;
372 TU_ASSERT(regs->
RXCSRL & USB_RXCSRL1_RXRDY);
374 const unsigned mps = regs->
RXMAXP;
376 const unsigned vld = regs->
RXCOUNT;
377 const unsigned len = TU_MIN(TU_MIN(rem, mps), vld);
378 void *buf = pipe->
buf;
381 pipe->
buf = buf + len;
384 if ((len < mps) || (rem == len)) {
388 regs->
RXCSRL = USB_RXCSRL1_REQPKT;
396 unsigned const dir_tx =
tu_edpt_dir(ep_addr) ? 0: 1;
405 regs->
RXCSRL = USB_RXCSRL1_REQPKT;
414 uint_fast8_t csrl = USB0->CSRL0;
417 unsigned const dev_addr = USB0->TXFUNCADDR0;
419 if (csrl & (USB_CSRL0_ERROR | USB_CSRL0_NAKTO | USB_CSRL0_STALLED)) {
421 if (csrl & (USB_CSRL0_RXRDY | USB_CSRL0_TXRDY))
422 USB0->CSRH0 = USB_CSRH0_FLUSH;
426 if (REQUEST_TYPE_INVALID == req) {
431 }
else if (csrl & USB_CSRL0_STATUS) {
446 if (csrl & USB_CSRL0_STATUS) {
448 TU_ASSERT(USB_CSRL0_RXRDY == (csrl & USB_CSRL0_RXRDY),);
449 TU_ASSERT(0 == USB0->COUNT0,);
450 USB0->CSRH0 = USB_CSRH0_FLUSH;
457 if (csrl & USB_CSRL0_RXRDY) {
459 TU_ASSERT(REQUEST_TYPE_INVALID != req,);
472 TU_ASSERT(REQUEST_TYPE_INVALID != req,);
480 if (REQUEST_TYPE_INVALID == req) {
504 unsigned const csrl = regs->
TXCSRL;
506 if (csrl & (USB_TXCSRL1_STALLED | USB_TXCSRL1_ERROR)) {
507 if (csrl & USB_TXCSRL1_TXRDY)
508 regs->
TXCSRL = (csrl & ~(USB_TXCSRL1_STALLED | USB_TXCSRL1_ERROR)) | USB_TXCSRL1_FLUSH;
510 regs->
TXCSRL = csrl & ~(USB_TXCSRL1_STALLED | USB_TXCSRL1_ERROR);
533 unsigned const csrl = regs->
RXCSRL;
535 if (csrl & (USB_RXCSRL1_STALLED | USB_RXCSRL1_ERROR)) {
536 if (csrl & USB_RXCSRL1_RXRDY)
537 regs->
RXCSRL = (csrl & ~(USB_RXCSRL1_STALLED | USB_RXCSRL1_ERROR)) | USB_RXCSRL1_FLUSH;
539 regs->
RXCSRL = csrl & ~(USB_RXCSRL1_STALLED | USB_RXCSRL1_ERROR);
563 NVIC_ClearPendingIRQ(USB0_IRQn);
565 USB0->DEVCTL |= USB_DEVCTL_SESSION;
566 USB0->IE = USB_IE_DISCON | USB_IE_CONN | USB_IE_BABBLE | USB_IE_RESUME;
573 NVIC_EnableIRQ(USB0_IRQn);
579 NVIC_DisableIRQ(USB0_IRQn);
598 unsigned devctl = USB0->DEVCTL;
599 if (!(devctl & USB_DEVCTL_HOST))
return false;
600 if (devctl & (USB_DEVCTL_LSDEV | USB_DEVCTL_FSDEV))
return true;
607 USB0->POWER |= USB_POWER_HSENAB | USB_POWER_RESET;
609 while (cnt--) __NOP();
610 USB0->POWER &= ~USB_POWER_RESET;
622 unsigned devctl = USB0->DEVCTL;
634 unsigned const ie = NVIC_GetEnableIRQ(USB0_IRQn);
635 NVIC_DisableIRQ(USB0_IRQn);
641 for (
unsigned j = 0; j < 2; ++j, ++p) {
647 USB0->TXIE &= ~TU_BIT(i + 1);
648 if (regs->TXCSRL & USB_TXCSRL1_TXRDY)
649 regs->TXCSRL = USB_TXCSRL1_CLRDT | USB_TXCSRL1_FLUSH;
651 regs->TXCSRL = USB_TXCSRL1_CLRDT;
654 regs->TXINTERVAL = 0;
661 USB0->RXIE &= ~TU_BIT(i + 1);
662 if (regs->RXCSRL & USB_RXCSRL1_RXRDY)
663 regs->RXCSRL = USB_RXCSRL1_CLRDT | USB_RXCSRL1_FLUSH;
665 regs->RXCSRL = USB_RXCSRL1_CLRDT;
668 regs->RXINTERVAL = 0;
683 if (ie) NVIC_EnableIRQ(USB0_IRQn);
700 switch (devtree.
speed) {
701 default:
return false;
706 USB0->TXHUBADDR0 = devtree.
hub_addr;
707 USB0->TXHUBPORT0 = devtree.
hub_port;
709 USB0->CSRL0 = USB_CSRL0_TXRDY | USB_CSRL0_SETUP;
724 unsigned const dir_tx =
tu_edpt_dir(ep_addr) ? 0: 1;
726 unsigned pipenum = 0;
728 for (
unsigned i = 0; i <
sizeof(
_hcd.
addr)/
sizeof(
_hcd.
addr[0]); ++i, p += 2) {
736 if (!pipenum)
return false;
746 uint8_t pipe_type = 0;
749 switch (devtree.
speed) {
750 default:
return false;
756 default:
return false;
769 regs->TXTYPE = pipe_type | epn;
771 if (regs->TXCSRL & USB_TXCSRL1_TXRDY)
772 regs->TXCSRL = USB_TXCSRL1_CLRDT | USB_TXCSRL1_FLUSH;
774 regs->TXCSRL = USB_TXCSRL1_CLRDT;
775 USB0->TXIE |= TU_BIT(pipenum);
781 regs->RXTYPE = pipe_type | epn;
783 if (regs->RXCSRL & USB_RXCSRL1_RXRDY)
784 regs->RXCSRL = USB_RXCSRL1_CLRDT | USB_RXCSRL1_FLUSH;
786 regs->RXCSRL = USB_RXCSRL1_CLRDT;
787 USB0->RXIE |= TU_BIT(pipenum);
791 int size_in_log2_minus3 = 28 - TU_MIN(28, __CLZ((uint32_t)mps));
792 if ((8u << size_in_log2_minus3) < mps) ++size_in_log2_minus3;
796 USB0->EPIDX = pipenum;
798 USB0->TXFIFOADD = addr;
799 USB0->TXFIFOSZ = size_in_log2_minus3;
801 USB0->RXFIFOADD = addr;
802 USB0->RXFIFOSZ = size_in_log2_minus3;
831 if (!pipenum)
return false;
833 unsigned const dir_tx =
tu_edpt_dir(ep_addr) ? 0: 1;
835 regs->
TXCSRL = USB_TXCSRL1_CLRDT;
837 regs->
RXCSRL = USB_RXCSRL1_CLRDT;
848 uint_fast8_t is, txis, rxis;
856 if (is & USB_IS_RESUME) {
858 if (is & USB_IS_CONN) {
862 if (is & USB_IS_DISCON) {
865 if (is & USB_IS_BABBLE) {
868 if (txis & USB_TXIE_EP0) {
875 txis &= ~TU_BIT(num);
881 rxis &= ~TU_BIT(num);
xfer_td_t xfer[EP_CBI_COUNT+1][2]
static TU_ATTR_ALWAYS_INLINE unsigned __builtin_ctz(unsigned int value)
static TU_ATTR_ALWAYS_INLINE void hcd_event_device_remove(uint8_t rhport, bool in_isr)
static TU_ATTR_ALWAYS_INLINE void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, uint32_t xferred_bytes, xfer_result_t result, bool in_isr)
static TU_ATTR_ALWAYS_INLINE void hcd_event_device_attach(uint8_t rhport, bool in_isr)
void hcd_devtree_get_info(uint8_t dev_addr, hcd_devtree_info_t *devtree_info)
bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8])
static bool pipe_xfer_in(uint_fast8_t pipenum)
struct TU_ATTR_PACKED pipe_state_t
void hcd_int_disable(uint8_t rhport)
static unsigned find_pipe(uint_fast8_t dev_addr, uint_fast8_t ep_addr)
static void process_pipe_tx(uint8_t rhport, uint_fast8_t pipenum)
static int update_free_block_list(free_block_t *blks, unsigned num, uint_fast16_t addr, uint_fast16_t size)
static void pipe_write_packet(void *buf, volatile void *fifo, unsigned len)
static free_block_t * find_containing_block(free_block_t *beg, free_block_t *end, uint_fast16_t addr)
bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr)
void hcd_int_enable(uint8_t rhport)
static volatile hw_endpoint_t * edpt_regs(unsigned epnum_minus1)
static bool edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *buffer, uint16_t buflen)
struct TU_ATTR_PACKED pipe_addr_t
bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *buffer, uint16_t buflen)
struct TU_ATTR_PACKED hw_addr_t
_Pragma("GCC diagnostic ignored \"-Waddress-of-packed-member\"")
void hcd_device_close(uint8_t rhport, uint8_t dev_addr)
bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr)
static void process_ep0(uint8_t rhport)
void hcd_port_reset_end(uint8_t rhport)
static bool edpt0_xfer_out(void)
void hcd_port_reset(uint8_t rhport)
static bool edpt0_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *buffer, uint16_t buflen)
static void pipe_read_packet(void *buf, volatile void *fifo, unsigned len)
bool hcd_port_connect_status(uint8_t rhport)
static unsigned find_free_memory(uint_fast16_t size_in_log2_minus3)
uint32_t hcd_frame_number(uint8_t rhport)
static bool pipe_xfer_out(uint_fast8_t pipenum)
tusb_speed_t hcd_port_speed_get(uint8_t rhport)
static void process_pipe_rx(uint8_t rhport, uint_fast8_t pipenum)
struct TU_ATTR_PACKED hw_endpoint_t
void hcd_int_handler(uint8_t rhport, bool in_isr)
bool hcd_init(uint8_t rhport, const tusb_rhport_init_t *rh_init)
bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const *ep_desc)
static bool edpt0_xfer_in(void)
static unsigned free_block_size(free_block_t const *blk)
TU_ATTR_PACKED_BEGIN TU_ATTR_BIT_FIELD_ORDER_BEGIN union TU_ATTR_PACKED hw_fifo_t
AUDIO Channel Cluster Descriptor (4.1)
uint8_t bmAttributes
See: audio_clock_source_attribute_t.
tusb_speed_t
defined base on EHCI specs value for Endpoint Speed
static TU_ATTR_ALWAYS_INLINE uint8_t tu_edpt_number(uint8_t addr)
static TU_ATTR_ALWAYS_INLINE uint16_t tu_edpt_packet_size(tusb_desc_endpoint_t const *desc_ep)
TU_ATTR_PACKED_END TU_ATTR_BIT_FIELD_ORDER_END static TU_ATTR_ALWAYS_INLINE tusb_dir_t tu_edpt_dir(uint8_t addr)
static TU_ATTR_ALWAYS_INLINE uint8_t tu_edpt_addr(uint8_t num, uint8_t dir)