mirror of
https://github.com/hathach/tinyusb.git
synced 2025-03-23 22:43:49 +00:00
update max3421 to have hcd_int_handler_ext()
This commit is contained in:
parent
f6ca86c3dd
commit
2f6592de7f
@ -167,15 +167,30 @@ int board_getchar(void) {
|
|||||||
#if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421
|
#if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421
|
||||||
|
|
||||||
static spi_device_handle_t max3421_spi;
|
static spi_device_handle_t max3421_spi;
|
||||||
|
SemaphoreHandle_t max3421_intr_sem;
|
||||||
|
|
||||||
static void IRAM_ATTR max3421_isr_handler(void* arg) {
|
static void IRAM_ATTR max3421_isr_handler(void* arg) {
|
||||||
(void) arg; // arg is gpio num
|
(void) arg; // arg is gpio num
|
||||||
//xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL);
|
|
||||||
gpio_set_level(13, 1);
|
gpio_set_level(13, 1);
|
||||||
tuh_int_handler(1);
|
|
||||||
|
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||||
|
xSemaphoreGiveFromISR(max3421_intr_sem, &xHigherPriorityTaskWoken);
|
||||||
|
if (xHigherPriorityTaskWoken) {
|
||||||
|
portYIELD_FROM_ISR();
|
||||||
|
}
|
||||||
|
|
||||||
gpio_set_level(13, 0);
|
gpio_set_level(13, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void max3421_intr_task(void* param) {
|
||||||
|
(void) param;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
xSemaphoreTake(max3421_intr_sem, portMAX_DELAY);
|
||||||
|
tuh_int_handler(BOARD_TUH_RHPORT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void max3421_init(void) {
|
static void max3421_init(void) {
|
||||||
// CS pin
|
// CS pin
|
||||||
gpio_set_direction(MAX3421_CS_PIN, GPIO_MODE_OUTPUT);
|
gpio_set_direction(MAX3421_CS_PIN, GPIO_MODE_OUTPUT);
|
||||||
@ -209,6 +224,9 @@ static void max3421_init(void) {
|
|||||||
gpio_set_level(13, 0);
|
gpio_set_level(13, 0);
|
||||||
|
|
||||||
// Interrupt pin
|
// Interrupt pin
|
||||||
|
max3421_intr_sem = xSemaphoreCreateBinary();
|
||||||
|
xTaskCreate(max3421_intr_task, "max3421 intr", 2048, NULL, configMAX_PRIORITIES-1, NULL);
|
||||||
|
|
||||||
gpio_set_direction(MAX3421_INTR_PIN, GPIO_MODE_INPUT);
|
gpio_set_direction(MAX3421_INTR_PIN, GPIO_MODE_INPUT);
|
||||||
gpio_set_intr_type(MAX3421_INTR_PIN, GPIO_INTR_NEGEDGE);
|
gpio_set_intr_type(MAX3421_INTR_PIN, GPIO_INTR_NEGEDGE);
|
||||||
|
|
||||||
|
@ -133,6 +133,9 @@ bool hcd_init(uint8_t rhport);
|
|||||||
// Interrupt Handler
|
// Interrupt Handler
|
||||||
void hcd_int_handler(uint8_t rhport);
|
void hcd_int_handler(uint8_t rhport);
|
||||||
|
|
||||||
|
// Interrupt Hanndler (extended version)
|
||||||
|
void hcd_int_handler_ext(uint8_t rhport, bool in_isr);
|
||||||
|
|
||||||
// Enable USB interrupt
|
// Enable USB interrupt
|
||||||
void hcd_int_enable (uint8_t rhport);
|
void hcd_int_enable (uint8_t rhport);
|
||||||
|
|
||||||
|
@ -428,8 +428,8 @@ bool hcd_init(uint8_t rhport) {
|
|||||||
reg_write(rhport, PINCTL_ADDR, PINCTL_FDUPSPI, false);
|
reg_write(rhport, PINCTL_ADDR, PINCTL_FDUPSPI, false);
|
||||||
|
|
||||||
// V1 is 0x01, V2 is 0x12, V3 is 0x13
|
// V1 is 0x01, V2 is 0x12, V3 is 0x13
|
||||||
// uint8_t const revision = reg_read(rhport, REVISION_ADDR, false);
|
uint8_t const revision = reg_read(rhport, REVISION_ADDR, false);
|
||||||
// TU_LOG2_HEX(revision);
|
TU_LOG2_HEX(revision);
|
||||||
|
|
||||||
// reset
|
// reset
|
||||||
reg_write(rhport, USBCTL_ADDR, USBCTL_CHIPRES, false);
|
reg_write(rhport, USBCTL_ADDR, USBCTL_CHIPRES, false);
|
||||||
@ -693,9 +693,7 @@ static void handle_connect_irq(uint8_t rhport, bool in_isr) {
|
|||||||
|
|
||||||
// port reset anyway, this will help to stable bus signal for next connection
|
// port reset anyway, this will help to stable bus signal for next connection
|
||||||
reg_write(rhport, HCTL_ADDR, HCTL_BUSRST, in_isr);
|
reg_write(rhport, HCTL_ADDR, HCTL_BUSRST, in_isr);
|
||||||
|
|
||||||
hcd_event_device_remove(rhport, in_isr);
|
hcd_event_device_remove(rhport, in_isr);
|
||||||
|
|
||||||
reg_write(rhport, HCTL_ADDR, 0, in_isr);
|
reg_write(rhport, HCTL_ADDR, 0, in_isr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -721,13 +719,12 @@ static void handle_connect_irq(uint8_t rhport, bool in_isr) {
|
|||||||
free_ep(daddr);
|
free_ep(daddr);
|
||||||
|
|
||||||
hcd_event_device_attach(rhport, in_isr);
|
hcd_event_device_attach(rhport, in_isr);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void xfer_complete_isr(uint8_t rhport, max3421_ep_t *ep, xfer_result_t result, uint8_t hrsl) {
|
static void xfer_complete_isr(uint8_t rhport, max3421_ep_t *ep, xfer_result_t result, uint8_t hrsl, bool in_isr) {
|
||||||
uint8_t const ep_addr = tu_edpt_addr(ep->ep_num, ep->ep_dir);
|
uint8_t const ep_addr = tu_edpt_addr(ep->ep_num, ep->ep_dir);
|
||||||
|
|
||||||
// save data toggle
|
// save data toggle
|
||||||
@ -738,20 +735,20 @@ static void xfer_complete_isr(uint8_t rhport, max3421_ep_t *ep, xfer_result_t re
|
|||||||
}
|
}
|
||||||
|
|
||||||
ep->xfer_pending = 0;
|
ep->xfer_pending = 0;
|
||||||
hcd_event_xfer_complete(ep->daddr, ep_addr, ep->xferred_len, result, true);
|
hcd_event_xfer_complete(ep->daddr, ep_addr, ep->xferred_len, result, in_isr);
|
||||||
|
|
||||||
// Find next pending endpoint
|
// Find next pending endpoint
|
||||||
max3421_ep_t *next_ep = find_next_pending_ep(ep);
|
max3421_ep_t *next_ep = find_next_pending_ep(ep);
|
||||||
if (next_ep) {
|
if (next_ep) {
|
||||||
xact_inout(rhport, next_ep, true, true);
|
xact_inout(rhport, next_ep, true, in_isr);
|
||||||
}else {
|
}else {
|
||||||
// no more pending
|
// no more pending
|
||||||
atomic_flag_clear(&_hcd_data.busy);
|
atomic_flag_clear(&_hcd_data.busy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_xfer_done(uint8_t rhport) {
|
static void handle_xfer_done(uint8_t rhport, bool in_isr) {
|
||||||
uint8_t const hrsl = reg_read(rhport, HRSL_ADDR, true);
|
uint8_t const hrsl = reg_read(rhport, HRSL_ADDR, in_isr);
|
||||||
uint8_t const hresult = hrsl & HRSL_RESULT_MASK;
|
uint8_t const hresult = hrsl & HRSL_RESULT_MASK;
|
||||||
|
|
||||||
uint8_t const ep_num = _hcd_data.hxfr & HXFR_EPNUM_MASK;
|
uint8_t const ep_num = _hcd_data.hxfr & HXFR_EPNUM_MASK;
|
||||||
@ -774,17 +771,17 @@ static void handle_xfer_done(uint8_t rhport) {
|
|||||||
case HRSL_NAK:
|
case HRSL_NAK:
|
||||||
if (ep_num == 0) {
|
if (ep_num == 0) {
|
||||||
// NAK on control, retry immediately
|
// NAK on control, retry immediately
|
||||||
hxfr_write(rhport, _hcd_data.hxfr, true);
|
hxfr_write(rhport, _hcd_data.hxfr, in_isr);
|
||||||
}else {
|
}else {
|
||||||
// NAK on non-control, find next pending to switch
|
// NAK on non-control, find next pending to switch
|
||||||
max3421_ep_t *next_ep = find_next_pending_ep(ep);
|
max3421_ep_t *next_ep = find_next_pending_ep(ep);
|
||||||
|
|
||||||
if (ep == next_ep) {
|
if (ep == next_ep) {
|
||||||
// this endpoint is only one pending, retry immediately
|
// this endpoint is only one pending, retry immediately
|
||||||
hxfr_write(rhport, _hcd_data.hxfr, true);
|
hxfr_write(rhport, _hcd_data.hxfr, in_isr);
|
||||||
}else if (next_ep) {
|
}else if (next_ep) {
|
||||||
// switch to next pending TODO could have issue with double buffered if not clear previously out data
|
// switch to next pending TODO could have issue with double buffered if not clear previously out data
|
||||||
xact_inout(rhport, next_ep, true, true);
|
xact_inout(rhport, next_ep, true, in_isr);
|
||||||
}else {
|
}else {
|
||||||
TU_ASSERT(false,);
|
TU_ASSERT(false,);
|
||||||
}
|
}
|
||||||
@ -802,7 +799,7 @@ static void handle_xfer_done(uint8_t rhport) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (xfer_result != XFER_RESULT_SUCCESS) {
|
if (xfer_result != XFER_RESULT_SUCCESS) {
|
||||||
xfer_complete_isr(rhport, ep, xfer_result, hrsl);
|
xfer_complete_isr(rhport, ep, xfer_result, hrsl, in_isr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -814,10 +811,10 @@ static void handle_xfer_done(uint8_t rhport) {
|
|||||||
|
|
||||||
// short packet or all bytes transferred
|
// short packet or all bytes transferred
|
||||||
if ( ep->xfer_complete ) {
|
if ( ep->xfer_complete ) {
|
||||||
xfer_complete_isr(rhport, ep, xfer_result, hrsl);
|
xfer_complete_isr(rhport, ep, xfer_result, hrsl, in_isr);
|
||||||
}else {
|
}else {
|
||||||
// more to transfer
|
// more to transfer
|
||||||
hxfr_write(rhport, _hcd_data.hxfr, true);
|
hxfr_write(rhport, _hcd_data.hxfr, in_isr);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// SETUP or OUT transfer
|
// SETUP or OUT transfer
|
||||||
@ -835,10 +832,10 @@ static void handle_xfer_done(uint8_t rhport) {
|
|||||||
ep->buf += xact_len;
|
ep->buf += xact_len;
|
||||||
|
|
||||||
if (xact_len < ep->packet_size || ep->xferred_len >= ep->total_len) {
|
if (xact_len < ep->packet_size || ep->xferred_len >= ep->total_len) {
|
||||||
xfer_complete_isr(rhport, ep, xfer_result, hrsl);
|
xfer_complete_isr(rhport, ep, xfer_result, hrsl, in_isr);
|
||||||
} else {
|
} else {
|
||||||
// more to transfer
|
// more to transfer
|
||||||
xact_out(rhport, ep, false, true);
|
xact_out(rhport, ep, false, in_isr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -862,9 +859,9 @@ void print_hirq(uint8_t hirq) {
|
|||||||
#define print_hirq(hirq)
|
#define print_hirq(hirq)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Interrupt Handler
|
// Interrupt handler (extended)
|
||||||
void hcd_int_handler(uint8_t rhport) {
|
void hcd_int_handler_ext(uint8_t rhport, bool in_isr) {
|
||||||
uint8_t hirq = reg_read(rhport, HIRQ_ADDR, true) & _hcd_data.hien;
|
uint8_t hirq = reg_read(rhport, HIRQ_ADDR, in_isr) & _hcd_data.hien;
|
||||||
if (!hirq) return;
|
if (!hirq) return;
|
||||||
// print_hirq(hirq);
|
// print_hirq(hirq);
|
||||||
|
|
||||||
@ -873,7 +870,7 @@ void hcd_int_handler(uint8_t rhport) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (hirq & HIRQ_CONDET_IRQ) {
|
if (hirq & HIRQ_CONDET_IRQ) {
|
||||||
handle_connect_irq(rhport, true);
|
handle_connect_irq(rhport, in_isr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// queue more transfer in handle_xfer_done() can cause hirq to be set again while external IRQ may not catch and/or
|
// queue more transfer in handle_xfer_done() can cause hirq to be set again while external IRQ may not catch and/or
|
||||||
@ -886,17 +883,17 @@ void hcd_int_handler(uint8_t rhport) {
|
|||||||
|
|
||||||
// RCVDAV_IRQ can trigger 2 times (dual buffered)
|
// RCVDAV_IRQ can trigger 2 times (dual buffered)
|
||||||
while ( hirq & HIRQ_RCVDAV_IRQ ) {
|
while ( hirq & HIRQ_RCVDAV_IRQ ) {
|
||||||
uint8_t rcvbc = reg_read(rhport, RCVBC_ADDR, true);
|
uint8_t rcvbc = reg_read(rhport, RCVBC_ADDR, in_isr);
|
||||||
xact_len = (uint8_t) tu_min16(rcvbc, ep->total_len - ep->xferred_len);
|
xact_len = (uint8_t) tu_min16(rcvbc, ep->total_len - ep->xferred_len);
|
||||||
if ( xact_len ) {
|
if ( xact_len ) {
|
||||||
fifo_read(rhport, ep->buf, xact_len, true);
|
fifo_read(rhport, ep->buf, xact_len, in_isr);
|
||||||
ep->buf += xact_len;
|
ep->buf += xact_len;
|
||||||
ep->xferred_len += xact_len;
|
ep->xferred_len += xact_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ack RCVDVAV IRQ
|
// ack RCVDVAV IRQ
|
||||||
hirq_write(rhport, HIRQ_RCVDAV_IRQ, true);
|
hirq_write(rhport, HIRQ_RCVDAV_IRQ, in_isr);
|
||||||
hirq = reg_read(rhport, HIRQ_ADDR, true);
|
hirq = reg_read(rhport, HIRQ_ADDR, in_isr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( xact_len < ep->packet_size || ep->xferred_len >= ep->total_len ) {
|
if ( xact_len < ep->packet_size || ep->xferred_len >= ep->total_len ) {
|
||||||
@ -905,18 +902,23 @@ void hcd_int_handler(uint8_t rhport) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ( hirq & HIRQ_HXFRDN_IRQ ) {
|
if ( hirq & HIRQ_HXFRDN_IRQ ) {
|
||||||
hirq_write(rhport, HIRQ_HXFRDN_IRQ, true);
|
hirq_write(rhport, HIRQ_HXFRDN_IRQ, in_isr);
|
||||||
handle_xfer_done(rhport);
|
handle_xfer_done(rhport, in_isr);
|
||||||
}
|
}
|
||||||
|
|
||||||
hirq = reg_read(rhport, HIRQ_ADDR, true);
|
hirq = reg_read(rhport, HIRQ_ADDR, in_isr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// clear all interrupt except SNDBAV_IRQ (never clear by us). Note RCVDAV_IRQ, HXFRDN_IRQ already clear while processing
|
// clear all interrupt except SNDBAV_IRQ (never clear by us). Note RCVDAV_IRQ, HXFRDN_IRQ already clear while processing
|
||||||
hirq &= ~HIRQ_SNDBAV_IRQ;
|
hirq &= ~HIRQ_SNDBAV_IRQ;
|
||||||
if ( hirq ) {
|
if ( hirq ) {
|
||||||
hirq_write(rhport, hirq, true);
|
hirq_write(rhport, hirq, in_isr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Interrupt Handler
|
||||||
|
void hcd_int_handler(uint8_t rhport) {
|
||||||
|
hcd_int_handler_ext(rhport, true);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user