diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/class/hid/hid_device.c | 4 | ||||
| -rw-r--r-- | src/common/tusb_compiler.h | 3 | ||||
| -rw-r--r-- | src/device/usbd.c | 6 | ||||
| -rw-r--r-- | src/osal/osal_freertos.h | 8 | ||||
| -rw-r--r-- | src/portable/dialog/da146xx/dcd_da146xx.c | 154 | ||||
| -rw-r--r-- | src/tusb_option.h | 6 |
6 files changed, 122 insertions, 59 deletions
diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 2ee80750a..55071a5ce 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -282,7 +282,7 @@ bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t uint8_t const report_id = tu_u16_low(request->wValue); uint8_t* report_buf = p_hid->epin_buf; - uint16_t req_len = request->wLength; + uint16_t req_len = tu_min16(request->wLength, CFG_TUD_HID_EP_BUFSIZE); uint16_t xferlen = 0; @@ -314,7 +314,7 @@ bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t uint8_t const report_id = tu_u16_low(request->wValue); uint8_t const* report_buf = p_hid->epout_buf; - uint16_t report_len = request->wLength; + uint16_t report_len = tu_min16(request->wLength, CFG_TUD_HID_EP_BUFSIZE); // If host request a specific Report ID, extract report ID in buffer before invoking callback if ( (report_id != HID_REPORT_TYPE_INVALID) && (report_len > 1) && (report_id == report_buf[0]) ) diff --git a/src/common/tusb_compiler.h b/src/common/tusb_compiler.h index d3adbbc2d..3e85939b0 100644 --- a/src/common/tusb_compiler.h +++ b/src/common/tusb_compiler.h @@ -32,6 +32,7 @@ #ifndef _TUSB_COMPILER_H_ #define _TUSB_COMPILER_H_ +#define TU_TOKEN(x) x #define TU_STRING(x) #x ///< stringify without expand #define TU_XSTRING(x) TU_STRING(x) ///< expand then stringify @@ -41,6 +42,8 @@ #define TU_XSTRCAT(a, b) TU_STRCAT(a, b) ///< expand then concat #define TU_XSTRCAT3(a, b, c) TU_STRCAT3(a, b, c) ///< expand then concat 3 tokens +#define TU_INCLUDE_PATH(_dir,_file) TU_XSTRING( TU_TOKEN(_dir)TU_TOKEN(_file) ) + #if defined __COUNTER__ && __COUNTER__ != __COUNTER__ #define _TU_COUNTER_ __COUNTER__ #else diff --git a/src/device/usbd.c b/src/device/usbd.c index 3043fc7bc..cf3ecea42 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -971,9 +971,11 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const uint16_t len = sizeof(tusb_desc_device_t); - // Only send up to EP0 Packet Size if not addressed + // Only send up to EP0 Packet Size if not addressed and host requested more data + // that device descriptor has. // This only happens with the very first get device descriptor and EP0 size = 8 or 16. - if ((CFG_TUD_ENDPOINT0_SIZE < sizeof(tusb_desc_device_t)) && !_usbd_dev.addressed) + if ((CFG_TUD_ENDPOINT0_SIZE < sizeof(tusb_desc_device_t)) && !_usbd_dev.addressed && + ((tusb_control_request_t*) p_request)->wLength > sizeof(tusb_desc_device_t)) { len = CFG_TUD_ENDPOINT0_SIZE; diff --git a/src/osal/osal_freertos.h b/src/osal/osal_freertos.h index 66070c273..4573e01f5 100644 --- a/src/osal/osal_freertos.h +++ b/src/osal/osal_freertos.h @@ -28,10 +28,10 @@ #define _TUSB_OSAL_FREERTOS_H_ // FreeRTOS Headers -#include "FreeRTOS.h" -#include "semphr.h" -#include "queue.h" -#include "task.h" +#include TU_INCLUDE_PATH(CFG_TUSB_OS_INC_PATH,FreeRTOS.h) +#include TU_INCLUDE_PATH(CFG_TUSB_OS_INC_PATH,semphr.h) +#include TU_INCLUDE_PATH(CFG_TUSB_OS_INC_PATH,queue.h) +#include TU_INCLUDE_PATH(CFG_TUSB_OS_INC_PATH,task.h) #ifdef __cplusplus extern "C" { diff --git a/src/portable/dialog/da146xx/dcd_da146xx.c b/src/portable/dialog/da146xx/dcd_da146xx.c index 7b0d8f86c..07e0ddd9b 100644 --- a/src/portable/dialog/da146xx/dcd_da146xx.c +++ b/src/portable/dialog/da146xx/dcd_da146xx.c @@ -193,8 +193,14 @@ typedef struct #define REG_CLR_BIT(reg, field) USB->reg &= ~USB_ ## reg ## _ ## field ## _Msk #define REG_SET_VAL(reg, field, val) USB->reg = (USB->reg & ~USB_ ## reg ## _ ## field ## _Msk) | (val << USB_ ## reg ## _ ## field ## _Pos) +static EPx_REGS * const ep_regs[EP_MAX] = { + EP_REGS(USB_EPC0_REG), + EP_REGS(USB_EPC1_REG), + EP_REGS(USB_EPC3_REG), + EP_REGS(USB_EPC5_REG), +}; + typedef struct { - EPx_REGS * regs; uint8_t * buffer; // Total length of current transfer uint16_t total_len; @@ -217,6 +223,7 @@ typedef struct { static struct { bool vbus_present; + bool init_called; bool in_reset; xfer_ctl_t xfer_status[EP_MAX][2]; // Endpoints that use DMA, one for each direction @@ -224,15 +231,16 @@ static struct } _dcd = { .vbus_present = false, - .xfer_status = - { - { { .regs = EP_REGS(USB_EPC0_REG) }, { .regs = EP_REGS(USB_EPC0_REG) } }, - { { .regs = EP_REGS(USB_EPC1_REG) }, { .regs = EP_REGS(USB_EPC1_REG) } }, - { { .regs = EP_REGS(USB_EPC3_REG) }, { .regs = EP_REGS(USB_EPC3_REG) } }, - { { .regs = EP_REGS(USB_EPC5_REG) }, { .regs = EP_REGS(USB_EPC5_REG) } }, - } + .init_called = false, }; +// Converts xfer pointer to epnum (0,1,2,3) regardless of xfer direction +#define XFER_EPNUM(xfer) ((xfer - &_dcd.xfer_status[0][0]) >> 1) +// Converts xfer pinter to EPx_REGS pointer (returns same pointer for IN and OUT with same endpoint number) +#define XFER_REGS(xfer) ep_regs[XFER_EPNUM(xfer)] +// Converts epnum (0,1,2,3) to EPx_REGS pointer +#define EPNUM_REGS(epnum) ep_regs[epnum] + // Two endpoint 0 descriptor definition for unified dcd_edpt_open() static const tusb_desc_endpoint_t ep0OUT_desc = { @@ -262,8 +270,8 @@ static void fill_tx_fifo(xfer_ctl_t * xfer) { int left_to_send; uint8_t const *src; - EPx_REGS *regs = xfer->regs; uint8_t const epnum = tu_edpt_number(xfer->ep_addr); + EPx_REGS *regs = EPNUM_REGS(epnum); src = &xfer->buffer[xfer->transferred]; left_to_send = xfer->total_len - xfer->transferred; @@ -291,7 +299,7 @@ static void fill_tx_fifo(xfer_ctl_t * xfer) } else { - xfer->regs->txc &= ~USB_USB_TXC1_REG_USB_TFWL_Msk; + regs->txc &= ~USB_USB_TXC1_REG_USB_TFWL_Msk; USB->USB_FWMSK_REG &= ~(1 << (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; @@ -332,30 +340,31 @@ static void start_rx_packet(xfer_ctl_t *xfer) uint8_t const epnum = tu_edpt_number(xfer->ep_addr); uint16_t remaining = xfer->total_len - xfer->transferred; uint16_t size = tu_min16(remaining, xfer->max_packet_size); + EPx_REGS *regs = XFER_REGS(xfer); xfer->last_packet_size = 0; if (xfer->max_packet_size > FIFO_SIZE && remaining > FIFO_SIZE) { if (try_allocate_dma(epnum, TUSB_DIR_OUT)) { - start_rx_dma(&xfer->regs->rxd, xfer->buffer + xfer->transferred, size); + start_rx_dma(®s->rxd, xfer->buffer + xfer->transferred, size); } else { // Other endpoint is using DMA in that direction, fall back to interrupts. // For endpoint size greater then FIFO size enable FIFO level warning interrupt // when FIFO has less then 17 bytes free. - xfer->regs->rxc |= USB_USB_RXC1_REG_USB_RFWL_Msk; + regs->rxc |= USB_USB_RXC1_REG_USB_RFWL_Msk; USB->USB_FWMSK_REG |= 1 << (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. - xfer->regs->rxc &= ~USB_USB_RXC1_REG_USB_RFWL_Msk; + regs->rxc &= ~USB_USB_RXC1_REG_USB_RFWL_Msk; USB->USB_FWMSK_REG &= ~(1 << (epnum - 1 + USB_USB_FWMSK_REG_USB_M_RXWARN31_Pos)); } - xfer->regs->rxc |= USB_USB_RXC1_REG_USB_RX_EN_Msk; + regs->rxc |= USB_USB_RXC1_REG_USB_RX_EN_Msk; } static void start_tx_dma(void *src, volatile void *dst, uint16_t size) @@ -374,13 +383,13 @@ static void start_tx_packet(xfer_ctl_t *xfer) uint8_t const epnum = tu_edpt_number(xfer->ep_addr); uint16_t remaining = xfer->total_len - xfer->transferred; uint16_t size = tu_min16(remaining, xfer->max_packet_size); - EPx_REGS *regs = xfer->regs; + EPx_REGS *regs = EPNUM_REGS(epnum); xfer->last_packet_size = 0; regs->txc = USB_USB_TXC1_REG_USB_FLUSH_Msk; regs->txc = USB_USB_TXC1_REG_USB_IGN_ISOMSK_Msk; - if (xfer->data1) xfer->regs->txc |= USB_USB_TXC1_REG_USB_TOGGLE_TX_Msk; + if (xfer->data1) regs->txc |= USB_USB_TXC1_REG_USB_TOGGLE_TX_Msk; if (xfer->max_packet_size > FIFO_SIZE && remaining > FIFO_SIZE && try_allocate_dma(epnum, TUSB_DIR_IN)) { @@ -397,7 +406,7 @@ static void start_tx_packet(xfer_ctl_t *xfer) static void read_rx_fifo(xfer_ctl_t *xfer, uint16_t bytes_in_fifo) { - EPx_REGS *regs = xfer->regs; + EPx_REGS *regs = XFER_REGS(xfer); uint16_t remaining = xfer->total_len - xfer->transferred - xfer->last_packet_size; uint16_t receive_this_time = bytes_in_fifo; @@ -467,7 +476,7 @@ static void handle_ep0_tx(void) { uint32_t txs0; xfer_ctl_t *xfer = XFER_CTL_BASE(0, TUSB_DIR_IN); - EPx_REGS *regs = xfer->regs; + EPx_REGS *regs = XFER_REGS(xfer); txs0 = regs->USB_TXS0_REG; @@ -501,7 +510,7 @@ static void handle_epx_rx_ev(uint8_t ep) int fifo_bytes; xfer_ctl_t *xfer = XFER_CTL_BASE(ep, TUSB_DIR_OUT); - EPx_REGS *regs = xfer->regs; + EPx_REGS *regs = EPNUM_REGS(ep); do { @@ -580,7 +589,7 @@ static void handle_epx_tx_ev(xfer_ctl_t *xfer) { uint8_t const epnum = tu_edpt_number(xfer->ep_addr); uint32_t txs; - EPx_REGS *regs = xfer->regs; + EPx_REGS *regs = EPNUM_REGS(epnum); txs = regs->txs; @@ -735,19 +744,13 @@ static void handle_ep0_nak(void) *------------------------------------------------------------------*/ void dcd_init(uint8_t rhport) { - USB->USB_MCTRL_REG = USB_USB_MCTRL_REG_USBEN_Msk; - USB->USB_NFSR_REG = 0; - USB->USB_FAR_REG = 0x80; - USB->USB_NFSR_REG = NFSR_NODE_RESET; - USB->USB_TXMSK_REG = 0; - USB->USB_RXMSK_REG = 0; - - USB->USB_MAMSK_REG = USB_USB_MAMSK_REG_USB_M_INTR_Msk | - USB_USB_MAMSK_REG_USB_M_ALT_Msk | - USB_USB_MAMSK_REG_USB_M_WARN_Msk; - USB->USB_ALTMSK_REG = USB_USB_ALTMSK_REG_USB_M_RESET_Msk; + (void) rhport; - dcd_connect(rhport); + _dcd.init_called = true; + if (_dcd.vbus_present) + { + dcd_connect(rhport); + } } void dcd_int_enable(uint8_t rhport) @@ -783,10 +786,25 @@ void dcd_connect(uint8_t rhport) { (void)rhport; - REG_SET_BIT(USB_MCTRL_REG, USB_NAT); + if (GET_BIT(USB->USB_MCTRL_REG, USB_USB_MCTRL_REG_USB_NAT) == 0) + { + USB->USB_MCTRL_REG = USB_USB_MCTRL_REG_USBEN_Msk; + USB->USB_NFSR_REG = 0; + USB->USB_FAR_REG = 0x80; + USB->USB_NFSR_REG = NFSR_NODE_RESET; + USB->USB_TXMSK_REG = 0; + USB->USB_RXMSK_REG = 0; + + USB->USB_MAMSK_REG = USB_USB_MAMSK_REG_USB_M_INTR_Msk | + USB_USB_MAMSK_REG_USB_M_ALT_Msk | + USB_USB_MAMSK_REG_USB_M_WARN_Msk; + USB->USB_ALTMSK_REG = USB_USB_ALTMSK_REG_USB_M_RESET_Msk; - // Select chosen DMA to be triggered by USB. - DMA->DMA_REQ_MUX_REG = (DMA->DMA_REQ_MUX_REG & ~DA146XX_DMA_USB_MUX_MASK) | DA146XX_DMA_USB_MUX; + REG_SET_BIT(USB_MCTRL_REG, USB_NAT); + + // Select chosen DMA to be triggered by USB. + DMA->DMA_REQ_MUX_REG = (DMA->DMA_REQ_MUX_REG & ~DA146XX_DMA_USB_MUX_MASK) | DA146XX_DMA_USB_MUX; + } } void dcd_disconnect(uint8_t rhport) @@ -796,6 +814,30 @@ void dcd_disconnect(uint8_t rhport) REG_CLR_BIT(USB_MCTRL_REG, USB_NAT); } +TU_ATTR_ALWAYS_INLINE static inline bool is_in_isr(void) +{ + return (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) != 0; +} + +void tusb_vbus_changed(bool present) +{ + if (present && !_dcd.vbus_present) + { + _dcd.vbus_present = true; + // If power event happened before USB started, delay dcd_connect + // until dcd_init is called. + if (_dcd.init_called) + { + dcd_connect(0); + } + } + else if (!present && _dcd.vbus_present) + { + _dcd.vbus_present = false; + USB->USB_MCTRL_REG = 0; + dcd_event_bus_signal(0, DCD_EVENT_UNPLUGGED, is_in_isr()); + } +} /*------------------------------------------------------------------*/ /* DCD Endpoint port @@ -808,6 +850,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) uint8_t const epnum = tu_edpt_number(desc_edpt->bEndpointAddress); uint8_t const dir = tu_edpt_dir(desc_edpt->bEndpointAddress); xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); + EPx_REGS *regs = EPNUM_REGS(epnum); uint8_t iso_mask = 0; TU_ASSERT(epnum < EP_MAX); @@ -832,13 +875,13 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) { if (dir == TUSB_DIR_OUT) { - xfer->regs->epc_out = epnum | USB_USB_EPC1_REG_USB_EP_EN_Msk | iso_mask; + regs->epc_out = epnum | USB_USB_EPC1_REG_USB_EP_EN_Msk | iso_mask; USB->USB_RXMSK_REG |= 0x101 << (epnum - 1); REG_SET_BIT(USB_MAMSK_REG, USB_M_RX_EV); } else { - xfer->regs->epc_in = epnum | USB_USB_EPC1_REG_USB_EP_EN_Msk | iso_mask; + regs->epc_in = epnum | USB_USB_EPC1_REG_USB_EP_EN_Msk | iso_mask; USB->USB_TXMSK_REG |= 0x101 << (epnum - 1); REG_SET_BIT(USB_MAMSK_REG, USB_M_TX_EV); } @@ -850,13 +893,19 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) void dcd_edpt_close_all (uint8_t rhport) { (void) rhport; - // TODO implement dcd_edpt_close_all() + + for (int epnum = 1; epnum < EP_MAX; ++epnum) + { + dcd_edpt_close(0, epnum | TUSB_DIR_OUT); + dcd_edpt_close(0, epnum | TUSB_DIR_IN); + } } 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); + EPx_REGS *regs = EPNUM_REGS(epnum); xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); (void)rhport; @@ -872,8 +921,8 @@ void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) { if (dir == TUSB_DIR_OUT) { - xfer->regs->rxc = USB_USB_RXC1_REG_USB_FLUSH_Msk; - xfer->regs->epc_out = 0; + regs->rxc = USB_USB_RXC1_REG_USB_FLUSH_Msk; + regs->epc_out = 0; USB->USB_RXMSK_REG &= ~(0x101 << (epnum - 1)); // Release DMA if needed if (_dcd.dma_ep[TUSB_DIR_OUT] == epnum) @@ -884,8 +933,8 @@ void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) } else { - xfer->regs->txc = USB_USB_TXC1_REG_USB_FLUSH_Msk; - xfer->regs->epc_in = 0; + regs->txc = USB_USB_TXC1_REG_USB_FLUSH_Msk; + regs->epc_in = 0; USB->USB_TXMSK_REG &= ~(0x101 << (epnum - 1)); // Release DMA if needed if (_dcd.dma_ep[TUSB_DIR_IN] == epnum) @@ -895,6 +944,7 @@ 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) @@ -930,6 +980,7 @@ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) (void)rhport; xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); + EPx_REGS *regs = EPNUM_REGS(epnum); xfer->stall = 1; if (epnum == 0) @@ -938,11 +989,11 @@ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) REG_SET_BIT(USB_EPC0_REG, USB_STALL); if (dir == TUSB_DIR_OUT) { - xfer->regs->USB_RXC0_REG = USB_USB_RXC0_REG_USB_RX_EN_Msk; + regs->USB_RXC0_REG = USB_USB_RXC0_REG_USB_RX_EN_Msk; } else { - if (xfer->regs->USB_RXC0_REG & USB_USB_RXC0_REG_USB_RX_EN_Msk) + if (regs->USB_RXC0_REG & USB_USB_RXC0_REG_USB_RX_EN_Msk) { // If RX is also enabled TX will not be stalled since RX has // higher priority. Enable NAK interrupt to handle stall. @@ -950,7 +1001,7 @@ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) } else { - xfer->regs->USB_TXC0_REG |= USB_USB_TXC0_REG_USB_TX_EN_Msk; + regs->USB_TXC0_REG |= USB_USB_TXC0_REG_USB_TX_EN_Msk; } } } @@ -958,13 +1009,13 @@ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { if (dir == TUSB_DIR_OUT) { - xfer->regs->epc_out |= USB_USB_EPC1_REG_USB_STALL_Msk; - xfer->regs->rxc |= USB_USB_RXC1_REG_USB_RX_EN_Msk; + regs->epc_out |= USB_USB_EPC1_REG_USB_STALL_Msk; + regs->rxc |= USB_USB_RXC1_REG_USB_RX_EN_Msk; } else { - xfer->regs->epc_in |= USB_USB_EPC1_REG_USB_STALL_Msk; - xfer->regs->txc |= USB_USB_TXC1_REG_USB_TX_EN_Msk | USB_USB_TXC1_REG_USB_LAST_Msk; + regs->epc_in |= USB_USB_EPC1_REG_USB_STALL_Msk; + regs->txc |= USB_USB_TXC1_REG_USB_TX_EN_Msk | USB_USB_TXC1_REG_USB_LAST_Msk; } } } @@ -977,6 +1028,7 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) (void)rhport; xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); + EPx_REGS *regs = EPNUM_REGS(epnum); // Clear stall is called in response to Clear Feature ENDPOINT_HALT, reset toggle xfer->data1 = 0; @@ -984,11 +1036,11 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) if (dir == TUSB_DIR_OUT) { - xfer->regs->epc_out &= ~USB_USB_EPC1_REG_USB_STALL_Msk; + regs->epc_out &= ~USB_USB_EPC1_REG_USB_STALL_Msk; } else { - xfer->regs->epc_in &= ~USB_USB_EPC1_REG_USB_STALL_Msk; + regs->epc_in &= ~USB_USB_EPC1_REG_USB_STALL_Msk; } if (epnum == 0) { diff --git a/src/tusb_option.h b/src/tusb_option.h index a00f3489f..ad2a26a66 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -203,14 +203,20 @@ #define CFG_TUSB_MEM_SECTION #endif +// alignment requirement of buffer used for endpoint transferring #ifndef CFG_TUSB_MEM_ALIGN #define CFG_TUSB_MEM_ALIGN TU_ATTR_ALIGNED(4) #endif +// OS selection #ifndef CFG_TUSB_OS #define CFG_TUSB_OS OPT_OS_NONE #endif +#ifndef CFG_TUSB_OS_INC_PATH + #define CFG_TUSB_OS_INC_PATH +#endif + //-------------------------------------------------------------------- // DEVICE OPTIONS //-------------------------------------------------------------------- |
