Skip to content

Commit

Permalink
improve connection & disconnection detection. But there is still issu…
Browse files Browse the repository at this point in the history
…e when CONDETIRQ occurs but we are disabled interrupt (for osal queue access).
  • Loading branch information
hathach committed Aug 31, 2023
1 parent 4149342 commit 3b7d5aa
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 90 deletions.
26 changes: 10 additions & 16 deletions hw/bsp/board.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,17 +44,16 @@

// If using SES IDE, use the Syscalls/SEGGER_RTT_Syscalls_SES.c instead
#if !(defined __SES_ARM) && !(defined __SES_RISCV) && !(defined __CROSSWORKS_ARM)

#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;
SEGGER_RTT_Write(0, (const char*) buf, (int) count);
SEGGER_RTT_Write(0, (const char *) buf, (int) 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;
int rd = (int) SEGGER_RTT_Read(0, buf, count);
return (rd > 0) ? rd : -1;
Expand All @@ -67,8 +66,7 @@ TU_ATTR_USED int sys_read (int fhdl, char *buf, size_t count)

#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;
uint8_t const* buf8 = (uint8_t const*) buf;

Expand All @@ -79,8 +77,7 @@ TU_ATTR_USED int sys_write (int fhdl, const void *buf, size_t 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) buf;
(void) count;
Expand All @@ -90,23 +87,20 @@ TU_ATTR_USED int sys_read (int fhdl, char *buf, size_t count)
#else

// 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;
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;
int rd = board_uart_read((uint8_t*) buf, (int) count);
return (rd > 0) ? rd : -1;
}

#endif

int board_getchar(void)
{
int board_getchar(void) {
char c;
return ( sys_read(0, &c, 1) > 0 ) ? (int) c : (-1);
return (sys_read(0, &c, 1) > 0) ? (int) c : (-1);
}
49 changes: 22 additions & 27 deletions hw/bsp/nrf/family.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

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);
}
Expand All @@ -111,7 +111,7 @@ void tuh_max3421e_int_api(uint8_t rhport, bool enabled) {

if (enabled) {
nrfx_gpiote_trigger_enable(MAX3241E_INTR_PIN, true);
}else {
} else {
nrfx_gpiote_trigger_disable(MAX3241E_INTR_PIN);
}
}
Expand All @@ -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);
}

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;

nrfx_spim_xfer_desc_t xfer = {
Expand Down Expand Up @@ -157,21 +157,21 @@ void board_init(void) {
nrf_gpio_cfg_input(BUTTON_PIN, NRF_GPIO_PIN_PULLUP);

// 1ms tick timer
SysTick_Config(SystemCoreClock/1000);
SysTick_Config(SystemCoreClock / 1000);

// UART
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,
}
.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,
}
};

nrfx_uarte_init(&_uart_id, &uart_cfg, NULL); //uart_handler);
Expand Down Expand Up @@ -211,11 +211,11 @@ void board_init(void) {

// USB power may already be ready at this time -> no event generated
// We need to invoke the handler based on the status initially
#ifdef NRF5340_XXAA
#ifdef NRF5340_XXAA
usb_reg = NRF_USBREGULATOR->USBREGSTATUS;
#else
#else
usb_reg = NRF_POWER->USBREGSTATUS;
#endif
#endif
}

if ( usb_reg & VBUSDETECT_Msk ) tusb_hal_nrf_power_event(USB_EVT_DETECTED);
Expand Down Expand Up @@ -308,8 +308,7 @@ uint32_t board_millis(void) {

#ifdef SOFTDEVICE_PRESENT
// process SOC event from SD
uint32_t proc_soc(void)
{
uint32_t proc_soc(void) {
uint32_t soc_evt;
uint32_t err = sd_evt_get(&soc_evt);

Expand All @@ -326,18 +325,14 @@ uint32_t proc_soc(void)
return err;
}

uint32_t proc_ble(void)
{
uint32_t proc_ble(void) {
// do nothing with ble
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
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()) ) {
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/host/usbh.c
Original file line number Diff line number Diff line change
Expand Up @@ -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->claimed = 0;
TU_LOG1("Failed\r\n");
TU_BREAKPOINT();
// TU_BREAKPOINT();
return false;
}
}
Expand Down
85 changes: 39 additions & 46 deletions src/portable/analog/max3421/hcd_max3421.c
Original file line number Diff line number Diff line change
Expand Up @@ -405,45 +405,46 @@ bool hcd_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param) {
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 jk = hrsl & (HRSL_JSTATUS | HRSL_KSTATUS);

tusb_speed_t speed;
uint8_t new_mode = MODE_DPPULLDN | MODE_DMPULLDN | MODE_HOST;
TU_LOG2_HEX(jk);

switch(jk) {
case 0x00:
// SEO is disconnected
speed = TUSB_SPEED_INVALID;
break;

case (HRSL_JSTATUS | HRSL_KSTATUS):
// SE1 is illegal
speed = TUSB_SPEED_INVALID;
case 0x00: // SEO is disconnected
case (HRSL_JSTATUS | HRSL_KSTATUS): // SE1 is illegal
mode_write(rhport, new_mode, true);
hcd_event_device_remove(rhport, true);
break;

default: {
// Low speed if (LS = 1 and J-state) or (LS = 0 and K-State)
uint8_t const mode = reg_read(rhport, MODE_ADDR, true);
uint8_t const ls_bit = mode & MODE_LOWSPEED;
// Bus Reset also cause CONDET IRQ, skip if we are already connected and doing bus reset
if ((_hcd_data.hirq & HIRQ_BUSEVENT_IRQ) && (_hcd_data.mode & MODE_SOFKAENAB)) {
break;
}

if ( (ls_bit && (jk == HRSL_JSTATUS)) || (!ls_bit && (jk == HRSL_KSTATUS)) ) {
speed = TUSB_SPEED_LOW;
// 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;
} else {
speed = TUSB_SPEED_FULL;
TU_LOG3("Low speed\n");
}else {
TU_LOG3("Full speed\n");
}
new_mode |= MODE_SOFKAENAB;
mode_write(rhport, new_mode, true);

new_mode |= MODE_SOFKAENAB; // enable SOF since there is new device
// FIXME multiple MAX3421 rootdevice address is not 1
uint8_t const daddr = 1;
free_ep(daddr);

hcd_event_device_attach(rhport, true);

break;
}
}

mode_write(rhport, new_mode, true);
TU_LOG2_INT(speed);
return speed;
}

// Initialize controller to host mode
Expand Down Expand Up @@ -500,8 +501,9 @@ bool hcd_init(uint8_t rhport) {
// Enable USB interrupt
// Not actually enable GPIO interrupt, just set variable to prevent handler to process
void hcd_int_enable (uint8_t rhport) {
// tuh_max3421e_int_api(rhport, true);

(void) rhport;
// tuh_max3421e_int_api(rhport, true);
if (_hcd_data.intr_disable_count) {
_hcd_data.intr_disable_count--;
}
Expand All @@ -510,8 +512,8 @@ void hcd_int_enable (uint8_t rhport) {
// Disable USB interrupt
// Not actually disable GPIO interrupt, just set variable to prevent handler to process
void hcd_int_disable(uint8_t rhport) {
(void) rhport;
//tuh_max3421e_int_api(rhport, false);
(void) rhport;
_hcd_data.intr_disable_count++;
}

Expand All @@ -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.
// 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) {
// 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);
}

// Complete bus reset sequence, may be required by some controllers
void hcd_port_reset_end(uint8_t rhport) {
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
Expand Down Expand Up @@ -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);

max3421_ep_t* ep = find_opened_ep(daddr, ep_num, ep_dir);
TU_ASSERT(ep);
TU_VERIFY(ep);

// control transfer can switch direction
ep->ep_dir = ep_dir;
Expand Down Expand Up @@ -767,8 +761,6 @@ static void handle_xfer_done(uint8_t rhport) {
TU_ASSERT(ep, );

xfer_result_t xfer_result;

// TU_LOG3("HRSL: %02X\r\n", hrsl);
switch(hresult) {
case HRSL_SUCCESS:
xfer_result = XFER_RESULT_SUCCESS;
Expand Down Expand Up @@ -803,6 +795,7 @@ static void handle_xfer_done(uint8_t rhport) {
return;

default:
TU_LOG3("HRSL: %02X\r\n", hrsl);
xfer_result = XFER_RESULT_FAILED;
break;
}
Expand Down Expand Up @@ -875,30 +868,30 @@ void hcd_int_handler(uint8_t rhport) {
if (!hirq) return;
// print_hirq(hirq);

// uint8_t hirq = reg_read(rhport, HIRQ_ADDR, true);

if (hirq & HIRQ_FRAME_IRQ) {
_hcd_data.frame_count++;
}

#if 1
// interrupt is disabled, only ack FRAME IRQ and skip the rest
if (_hcd_data.intr_disable_count) {
if (hirq & HIRQ_FRAME_IRQ) {
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;
}
#endif

if (hirq & HIRQ_CONDET_IRQ) {
tusb_speed_t speed = 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);
}
handle_connect_irq(rhport);
}

// queue more transfer in handle_xfer_done() can cause hirq to be set again while external IRQ may not catch and/or
Expand Down

0 comments on commit 3b7d5aa

Please sign in to comment.