improve connection & disconnection detection. But there is still issue when CONDETIRQ occurs but we are disabled interrupt (for osal queue access).

This commit is contained in:
hathach 2023-08-31 16:52:09 +07:00
parent 41493426b3
commit 3b7d5aa042
No known key found for this signature in database
GPG Key ID: F5D50C6D51D17CBA
4 changed files with 74 additions and 92 deletions

View File

@ -44,17 +44,16 @@
// If using SES IDE, use the Syscalls/SEGGER_RTT_Syscalls_SES.c instead // If using SES IDE, use the Syscalls/SEGGER_RTT_Syscalls_SES.c instead
#if !(defined __SES_ARM) && !(defined __SES_RISCV) && !(defined __CROSSWORKS_ARM) #if !(defined __SES_ARM) && !(defined __SES_RISCV) && !(defined __CROSSWORKS_ARM)
#include "SEGGER_RTT.h" #include "SEGGER_RTT.h"
TU_ATTR_USED int sys_write (int fhdl, const void *buf, size_t count) TU_ATTR_USED int sys_write(int fhdl, const void *buf, size_t count) {
{
(void) fhdl; (void) fhdl;
SEGGER_RTT_Write(0, (const char*) buf, (int) count); SEGGER_RTT_Write(0, (const char *) buf, (int) count);
return count; return count;
} }
TU_ATTR_USED int sys_read (int fhdl, char *buf, size_t count) TU_ATTR_USED int sys_read(int fhdl, char *buf, size_t count) {
{
(void) fhdl; (void) fhdl;
int rd = (int) SEGGER_RTT_Read(0, buf, count); int rd = (int) SEGGER_RTT_Read(0, buf, count);
return (rd > 0) ? rd : -1; return (rd > 0) ? rd : -1;
@ -67,8 +66,7 @@ TU_ATTR_USED int sys_read (int fhdl, char *buf, size_t count)
#include "board_mcu.h" #include "board_mcu.h"
TU_ATTR_USED int sys_write (int fhdl, const void *buf, size_t count) TU_ATTR_USED int sys_write (int fhdl, const void *buf, size_t count) {
{
(void) fhdl; (void) fhdl;
uint8_t const* buf8 = (uint8_t const*) buf; uint8_t const* buf8 = (uint8_t const*) buf;
@ -79,8 +77,7 @@ TU_ATTR_USED int sys_write (int fhdl, const void *buf, size_t count)
return (int) count; return (int) count;
} }
TU_ATTR_USED int sys_read (int fhdl, char *buf, size_t count) TU_ATTR_USED int sys_read (int fhdl, char *buf, size_t count) {
{
(void) fhdl; (void) fhdl;
(void) buf; (void) buf;
(void) count; (void) count;
@ -90,14 +87,12 @@ TU_ATTR_USED int sys_read (int fhdl, char *buf, size_t count)
#else #else
// Default logging with on-board UART // Default logging with on-board UART
TU_ATTR_USED int sys_write (int fhdl, const void *buf, size_t count) TU_ATTR_USED int sys_write (int fhdl, const void *buf, size_t count) {
{
(void) fhdl; (void) fhdl;
return board_uart_write(buf, (int) count); return board_uart_write(buf, (int) count);
} }
TU_ATTR_USED int sys_read (int fhdl, char *buf, size_t count) TU_ATTR_USED int sys_read (int fhdl, char *buf, size_t count) {
{
(void) fhdl; (void) fhdl;
int rd = board_uart_read((uint8_t*) buf, (int) count); int rd = board_uart_read((uint8_t*) buf, (int) count);
return (rd > 0) ? rd : -1; return (rd > 0) ? rd : -1;
@ -105,8 +100,7 @@ TU_ATTR_USED int sys_read (int fhdl, char *buf, size_t count)
#endif #endif
int board_getchar(void) int board_getchar(void) {
{
char c; char c;
return ( sys_read(0, &c, 1) > 0 ) ? (int) c : (-1); return (sys_read(0, &c, 1) > 0) ? (int) c : (-1);
} }

View File

@ -98,7 +98,7 @@ TU_ATTR_UNUSED static void power_event_handler(nrfx_power_usb_evt_t event) {
static nrfx_spim_t _spi = NRFX_SPIM_INSTANCE(1); static nrfx_spim_t _spi = NRFX_SPIM_INSTANCE(1);
void max3421e_int_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action) { void max3421e_int_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action) {
if ( !(pin == MAX3241E_INTR_PIN && action == NRF_GPIOTE_POLARITY_HITOLO) ) return; if (!(pin == MAX3241E_INTR_PIN && action == NRF_GPIOTE_POLARITY_HITOLO)) return;
tuh_int_handler(1); tuh_int_handler(1);
} }
@ -111,7 +111,7 @@ void tuh_max3421e_int_api(uint8_t rhport, bool enabled) {
if (enabled) { if (enabled) {
nrfx_gpiote_trigger_enable(MAX3241E_INTR_PIN, true); nrfx_gpiote_trigger_enable(MAX3241E_INTR_PIN, true);
}else { } else {
nrfx_gpiote_trigger_disable(MAX3241E_INTR_PIN); nrfx_gpiote_trigger_disable(MAX3241E_INTR_PIN);
} }
} }
@ -121,7 +121,7 @@ void tuh_max3421_spi_cs_api(uint8_t rhport, bool active) {
nrf_gpio_pin_write(MAX3421E_CS_PIN, active ? 0 : 1); nrf_gpio_pin_write(MAX3421E_CS_PIN, active ? 0 : 1);
} }
bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const * tx_buf, size_t tx_len, uint8_t * rx_buf, size_t rx_len) { bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const *tx_buf, size_t tx_len, uint8_t *rx_buf, size_t rx_len) {
(void) rhport; (void) rhport;
nrfx_spim_xfer_desc_t xfer = { nrfx_spim_xfer_desc_t xfer = {
@ -157,21 +157,21 @@ void board_init(void) {
nrf_gpio_cfg_input(BUTTON_PIN, NRF_GPIO_PIN_PULLUP); nrf_gpio_cfg_input(BUTTON_PIN, NRF_GPIO_PIN_PULLUP);
// 1ms tick timer // 1ms tick timer
SysTick_Config(SystemCoreClock/1000); SysTick_Config(SystemCoreClock / 1000);
// UART // UART
nrfx_uarte_config_t uart_cfg = { nrfx_uarte_config_t uart_cfg = {
.pseltxd = UART_TX_PIN, .pseltxd = UART_TX_PIN,
.pselrxd = UART_RX_PIN, .pselrxd = UART_RX_PIN,
.pselcts = NRF_UARTE_PSEL_DISCONNECTED, .pselcts = NRF_UARTE_PSEL_DISCONNECTED,
.pselrts = NRF_UARTE_PSEL_DISCONNECTED, .pselrts = NRF_UARTE_PSEL_DISCONNECTED,
.p_context = NULL, .p_context = NULL,
.baudrate = NRF_UARTE_BAUDRATE_115200, // CFG_BOARD_UART_BAUDRATE .baudrate = NRF_UARTE_BAUDRATE_115200, // CFG_BOARD_UART_BAUDRATE
.interrupt_priority = 7, .interrupt_priority = 7,
.hal_cfg = { .hal_cfg = {
.hwfc = NRF_UARTE_HWFC_DISABLED, .hwfc = NRF_UARTE_HWFC_DISABLED,
.parity = NRF_UARTE_PARITY_EXCLUDED, .parity = NRF_UARTE_PARITY_EXCLUDED,
} }
}; };
nrfx_uarte_init(&_uart_id, &uart_cfg, NULL); //uart_handler); nrfx_uarte_init(&_uart_id, &uart_cfg, NULL); //uart_handler);
@ -211,11 +211,11 @@ void board_init(void) {
// USB power may already be ready at this time -> no event generated // USB power may already be ready at this time -> no event generated
// We need to invoke the handler based on the status initially // We need to invoke the handler based on the status initially
#ifdef NRF5340_XXAA #ifdef NRF5340_XXAA
usb_reg = NRF_USBREGULATOR->USBREGSTATUS; usb_reg = NRF_USBREGULATOR->USBREGSTATUS;
#else #else
usb_reg = NRF_POWER->USBREGSTATUS; usb_reg = NRF_POWER->USBREGSTATUS;
#endif #endif
} }
if ( usb_reg & VBUSDETECT_Msk ) tusb_hal_nrf_power_event(USB_EVT_DETECTED); if ( usb_reg & VBUSDETECT_Msk ) tusb_hal_nrf_power_event(USB_EVT_DETECTED);
@ -308,8 +308,7 @@ uint32_t board_millis(void) {
#ifdef SOFTDEVICE_PRESENT #ifdef SOFTDEVICE_PRESENT
// process SOC event from SD // process SOC event from SD
uint32_t proc_soc(void) uint32_t proc_soc(void) {
{
uint32_t soc_evt; uint32_t soc_evt;
uint32_t err = sd_evt_get(&soc_evt); uint32_t err = sd_evt_get(&soc_evt);
@ -326,18 +325,14 @@ uint32_t proc_soc(void)
return err; return err;
} }
uint32_t proc_ble(void) uint32_t proc_ble(void) {
{
// do nothing with ble // do nothing with ble
return NRF_ERROR_NOT_FOUND; return NRF_ERROR_NOT_FOUND;
} }
void SD_EVT_IRQHandler(void) void SD_EVT_IRQHandler(void) {
{
// process BLE and SOC until there is no more events // process BLE and SOC until there is no more events
while( (NRF_ERROR_NOT_FOUND != proc_ble()) || (NRF_ERROR_NOT_FOUND != proc_soc()) ) while( (NRF_ERROR_NOT_FOUND != proc_ble()) || (NRF_ERROR_NOT_FOUND != proc_soc()) ) {
{
} }
} }

View File

@ -852,7 +852,7 @@ bool usbh_edpt_xfer_with_callback(uint8_t dev_addr, uint8_t ep_addr, uint8_t * b
ep_state->busy = 0; ep_state->busy = 0;
ep_state->claimed = 0; ep_state->claimed = 0;
TU_LOG1("Failed\r\n"); TU_LOG1("Failed\r\n");
TU_BREAKPOINT(); // TU_BREAKPOINT();
return false; return false;
} }
} }

View File

@ -405,45 +405,46 @@ bool hcd_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param) {
return false; return false;
} }
tusb_speed_t handle_connect_irq(uint8_t rhport) { static void handle_connect_irq(uint8_t rhport) {
uint8_t const hrsl = reg_read(rhport, HRSL_ADDR, true); uint8_t const hrsl = reg_read(rhport, HRSL_ADDR, true);
uint8_t const jk = hrsl & (HRSL_JSTATUS | HRSL_KSTATUS); uint8_t const jk = hrsl & (HRSL_JSTATUS | HRSL_KSTATUS);
tusb_speed_t speed;
uint8_t new_mode = MODE_DPPULLDN | MODE_DMPULLDN | MODE_HOST; uint8_t new_mode = MODE_DPPULLDN | MODE_DMPULLDN | MODE_HOST;
TU_LOG2_HEX(jk);
switch(jk) { switch(jk) {
case 0x00: case 0x00: // SEO is disconnected
// SEO is disconnected case (HRSL_JSTATUS | HRSL_KSTATUS): // SE1 is illegal
speed = TUSB_SPEED_INVALID; mode_write(rhport, new_mode, true);
break; hcd_event_device_remove(rhport, true);
case (HRSL_JSTATUS | HRSL_KSTATUS):
// SE1 is illegal
speed = TUSB_SPEED_INVALID;
break; break;
default: { default: {
// Low speed if (LS = 1 and J-state) or (LS = 0 and K-State) // Bus Reset also cause CONDET IRQ, skip if we are already connected and doing bus reset
uint8_t const mode = reg_read(rhport, MODE_ADDR, true); if ((_hcd_data.hirq & HIRQ_BUSEVENT_IRQ) && (_hcd_data.mode & MODE_SOFKAENAB)) {
uint8_t const ls_bit = mode & MODE_LOWSPEED; break;
if ( (ls_bit && (jk == HRSL_JSTATUS)) || (!ls_bit && (jk == HRSL_KSTATUS)) ) {
speed = TUSB_SPEED_LOW;
new_mode |= MODE_LOWSPEED;
} else {
speed = TUSB_SPEED_FULL;
} }
new_mode |= MODE_SOFKAENAB; // enable SOF since there is new device // Low speed if (LS = 1 and J-state) or (LS = 0 and K-State)
// However, since we are always in full speed mode, we can just check J-state
if (jk == HRSL_KSTATUS) {
new_mode |= MODE_LOWSPEED;
TU_LOG3("Low speed\n");
}else {
TU_LOG3("Full speed\n");
}
new_mode |= MODE_SOFKAENAB;
mode_write(rhport, new_mode, true);
// FIXME multiple MAX3421 rootdevice address is not 1
uint8_t const daddr = 1;
free_ep(daddr);
hcd_event_device_attach(rhport, true);
break; break;
} }
} }
mode_write(rhport, new_mode, true);
TU_LOG2_INT(speed);
return speed;
} }
// Initialize controller to host mode // Initialize controller to host mode
@ -500,8 +501,9 @@ bool hcd_init(uint8_t rhport) {
// Enable USB interrupt // Enable USB interrupt
// Not actually enable GPIO interrupt, just set variable to prevent handler to process // Not actually enable GPIO interrupt, just set variable to prevent handler to process
void hcd_int_enable (uint8_t rhport) { void hcd_int_enable (uint8_t rhport) {
// tuh_max3421e_int_api(rhport, true);
(void) rhport; (void) rhport;
// tuh_max3421e_int_api(rhport, true);
if (_hcd_data.intr_disable_count) { if (_hcd_data.intr_disable_count) {
_hcd_data.intr_disable_count--; _hcd_data.intr_disable_count--;
} }
@ -510,8 +512,8 @@ void hcd_int_enable (uint8_t rhport) {
// Disable USB interrupt // Disable USB interrupt
// Not actually disable GPIO interrupt, just set variable to prevent handler to process // Not actually disable GPIO interrupt, just set variable to prevent handler to process
void hcd_int_disable(uint8_t rhport) { void hcd_int_disable(uint8_t rhport) {
(void) rhport;
//tuh_max3421e_int_api(rhport, false); //tuh_max3421e_int_api(rhport, false);
(void) rhport;
_hcd_data.intr_disable_count++; _hcd_data.intr_disable_count++;
} }
@ -534,20 +536,12 @@ bool hcd_port_connect_status(uint8_t rhport) {
// Reset USB bus on the port. Return immediately, bus reset sequence may not be complete. // 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. // 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 hcd_port_reset(uint8_t rhport) {
// Bus reset will also trigger CONDET IRQ, disable it
uint8_t const hien = DEFAULT_HIEN & ~HIRQ_CONDET_IRQ;
hien_write(rhport, hien, false);
reg_write(rhport, HCTL_ADDR, HCTL_BUSRST, false); reg_write(rhport, HCTL_ADDR, HCTL_BUSRST, false);
} }
// Complete bus reset sequence, may be required by some controllers // Complete bus reset sequence, may be required by some controllers
void hcd_port_reset_end(uint8_t rhport) { void hcd_port_reset_end(uint8_t rhport) {
reg_write(rhport, HCTL_ADDR, 0, false); reg_write(rhport, HCTL_ADDR, 0, false);
// Bus reset will also trigger CONDET IRQ, clear and re-enable it after reset
hirq_write(rhport, HIRQ_CONDET_IRQ, false);
hien_write(rhport, DEFAULT_HIEN, false);
} }
// Get port link speed // Get port link speed
@ -660,7 +654,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t daddr, uint8_t ep_addr, uint8_t * buf
uint8_t const ep_dir = tu_edpt_dir(ep_addr); uint8_t const ep_dir = tu_edpt_dir(ep_addr);
max3421_ep_t* ep = find_opened_ep(daddr, ep_num, ep_dir); max3421_ep_t* ep = find_opened_ep(daddr, ep_num, ep_dir);
TU_ASSERT(ep); TU_VERIFY(ep);
// control transfer can switch direction // control transfer can switch direction
ep->ep_dir = ep_dir; ep->ep_dir = ep_dir;
@ -767,8 +761,6 @@ static void handle_xfer_done(uint8_t rhport) {
TU_ASSERT(ep, ); TU_ASSERT(ep, );
xfer_result_t xfer_result; xfer_result_t xfer_result;
// TU_LOG3("HRSL: %02X\r\n", hrsl);
switch(hresult) { switch(hresult) {
case HRSL_SUCCESS: case HRSL_SUCCESS:
xfer_result = XFER_RESULT_SUCCESS; xfer_result = XFER_RESULT_SUCCESS;
@ -803,6 +795,7 @@ static void handle_xfer_done(uint8_t rhport) {
return; return;
default: default:
TU_LOG3("HRSL: %02X\r\n", hrsl);
xfer_result = XFER_RESULT_FAILED; xfer_result = XFER_RESULT_FAILED;
break; break;
} }
@ -875,30 +868,30 @@ void hcd_int_handler(uint8_t rhport) {
if (!hirq) return; if (!hirq) return;
// print_hirq(hirq); // print_hirq(hirq);
// uint8_t hirq = reg_read(rhport, HIRQ_ADDR, true);
if (hirq & HIRQ_FRAME_IRQ) { if (hirq & HIRQ_FRAME_IRQ) {
_hcd_data.frame_count++; _hcd_data.frame_count++;
} }
#if 1
// interrupt is disabled, only ack FRAME IRQ and skip the rest // interrupt is disabled, only ack FRAME IRQ and skip the rest
if (_hcd_data.intr_disable_count) { if (_hcd_data.intr_disable_count) {
if (hirq & HIRQ_FRAME_IRQ) { if (hirq & HIRQ_FRAME_IRQ) {
hirq_write(rhport, HIRQ_FRAME_IRQ, true); hirq_write(rhport, HIRQ_FRAME_IRQ, true);
} }
if ((hirq & HIRQ_CONDET_IRQ) && !(_hcd_data.mode & MODE_SOFKAENAB)) {
// connection when interrupt is disabled
TU_LOG3_INT(_hcd_data.intr_disable_count);
return;
}
return; return;
} }
#endif
if (hirq & HIRQ_CONDET_IRQ) { if (hirq & HIRQ_CONDET_IRQ) {
tusb_speed_t speed = handle_connect_irq(rhport); handle_connect_irq(rhport);
if (speed == TUSB_SPEED_INVALID) {
hcd_event_device_remove(rhport, true);
}else {
// FIXME multiple MAX3421 rootdevice address is not 1
uint8_t const daddr = 1;
free_ep(daddr);
hcd_event_device_attach(rhport, true);
}
} }
// 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