summaryrefslogtreecommitdiff
path: root/src/portable/analog/max3421/hcd_max3421.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/portable/analog/max3421/hcd_max3421.c')
-rw-r--r--src/portable/analog/max3421/hcd_max3421.c109
1 files changed, 70 insertions, 39 deletions
diff --git a/src/portable/analog/max3421/hcd_max3421.c b/src/portable/analog/max3421/hcd_max3421.c
index c5e924266..971dbd62e 100644
--- a/src/portable/analog/max3421/hcd_max3421.c
+++ b/src/portable/analog/max3421/hcd_max3421.c
@@ -28,9 +28,9 @@
#if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421
-#include <stdatomic.h>
#include "host/hcd.h"
#include "host/usbh.h"
+#include "host/usbh_pvt.h"
//--------------------------------------------------------------------+
//
@@ -233,7 +233,7 @@ typedef struct {
uint8_t hxfr;
}sndfifo_owner;
- atomic_flag busy; // busy transferring
+ bool busy_lock; // busy transferring
#if OSAL_MUTEX_REQUIRED
OSAL_MUTEX_DEF(spi_mutexdef);
@@ -253,28 +253,6 @@ static tuh_configure_max3421_t _tuh_cfg = {
};
//--------------------------------------------------------------------+
-// API: SPI transfer with MAX3421E
-// - spi_cs_api(), spi_xfer_api(), int_api(): must be implemented by application
-// - reg_read(), reg_write(): is implemented by this driver, can be used by application
-//--------------------------------------------------------------------+
-
-// API to control MAX3421 SPI CS
-extern void tuh_max3421_spi_cs_api(uint8_t rhport, bool active);
-
-// API to transfer data with MAX3421 SPI
-// Either tx_buf or rx_buf can be NULL, which means transfer is write or read only
-extern bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const* tx_buf, uint8_t* rx_buf, size_t xfer_bytes);
-
-// API to enable/disable MAX3421 INTR pin interrupt
-extern void tuh_max3421_int_api(uint8_t rhport, bool enabled);
-
-// API to read MAX3421's register. Implemented by TinyUSB
-uint8_t tuh_max3421_reg_read(uint8_t rhport, uint8_t reg, bool in_isr);
-
-// API to write MAX3421's register. Implemented by TinyUSB
-bool tuh_max3421_reg_write(uint8_t rhport, uint8_t reg, uint8_t data, bool in_isr);
-
-//--------------------------------------------------------------------+
// SPI Commands and Helper
//--------------------------------------------------------------------+
@@ -349,7 +327,9 @@ TU_ATTR_ALWAYS_INLINE static inline void mode_write(uint8_t rhport, uint8_t data
}
TU_ATTR_ALWAYS_INLINE static inline void peraddr_write(uint8_t rhport, uint8_t data, bool in_isr) {
- if ( _hcd_data.peraddr == data ) return; // no need to change address
+ if (_hcd_data.peraddr == data) {
+ return; // no need to change address
+ }
_hcd_data.peraddr = data;
reg_write(rhport, PERADDR_ADDR, data, in_isr);
@@ -395,7 +375,7 @@ TU_ATTR_ALWAYS_INLINE static inline void hwfifo_setup(uint8_t rhport, const uint
static void hwfifo_receive(uint8_t rhport, uint8_t * buffer, uint16_t len, bool in_isr) {
uint8_t hirq;
- uint8_t const reg = RCVVFIFO_ADDR;
+ const uint8_t reg = RCVVFIFO_ADDR;
max3421_spi_lock(rhport, in_isr);
@@ -411,7 +391,7 @@ static void hwfifo_receive(uint8_t rhport, uint8_t * buffer, uint16_t len, bool
//--------------------------------------------------------------------+
static max3421_ep_t* find_ep_not_addr0(uint8_t daddr, uint8_t ep_num, uint8_t ep_dir) {
- uint8_t const is_out = 1-ep_dir;
+ const uint8_t is_out = 1-ep_dir;
for(size_t i=1; i<CFG_TUH_MAX3421_ENDPOINT_TOTAL; i++) {
max3421_ep_t* ep = &_hcd_data.ep[i];
// control endpoint is bi-direction (skip check)
@@ -632,6 +612,9 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t daddr, tusb_desc_endpoint_t const * e
if (daddr == 0 && ep_num == 0) {
ep = &_hcd_data.ep[0];
}else {
+ if (NULL != find_ep_not_addr0(daddr, ep_num, ep_dir)) {
+ return true; // already opened
+ }
ep = allocate_ep();
TU_ASSERT(ep);
ep->daddr = daddr;
@@ -645,6 +628,21 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t daddr, tusb_desc_endpoint_t const * e
return true;
}
+bool hcd_edpt_close(uint8_t rhport, uint8_t daddr, uint8_t ep_addr) {
+ (void) rhport;
+ uint8_t const ep_num = tu_edpt_number(ep_addr);
+ tusb_dir_t const ep_dir = tu_edpt_dir(ep_addr);
+ max3421_ep_t * ep = find_ep_not_addr0(daddr, ep_num, ep_dir);
+
+ if (!ep) {
+ return false; // not opened
+ }
+
+ tu_memclr(ep, sizeof(max3421_ep_t));
+
+ return true;
+}
+
/* The microcontroller repeatedly writes the SNDFIFO register R2 to load the FIFO with up to 64 data bytes.
* Then the microcontroller writes the SNDBC register, which this does three things:
* 1. Tells the MAX3421E SIE (Serial Interface Engine) how many bytes in the FIFO to send.
@@ -731,8 +729,8 @@ static void xact_generic(uint8_t rhport, max3421_ep_t *ep, bool switch_ep, bool
// Submit a transfer, when complete hcd_event_xfer_complete() must be invoked
bool hcd_edpt_xfer(uint8_t rhport, uint8_t daddr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen) {
- uint8_t const ep_num = tu_edpt_number(ep_addr);
- uint8_t const ep_dir = (uint8_t) tu_edpt_dir(ep_addr);
+ const uint8_t ep_num = tu_edpt_number(ep_addr);
+ const uint8_t ep_dir = (uint8_t) tu_edpt_dir(ep_addr);
max3421_ep_t* ep = find_opened_ep(daddr, ep_num, ep_dir);
TU_VERIFY(ep);
@@ -748,8 +746,17 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t daddr, uint8_t ep_addr, uint8_t * buf
ep->xferred_len = 0;
ep->state = EP_STATE_ATTEMPT_1;
+ bool has_xfer = false;
+
+ usbh_spin_lock(false);
+ if (!_hcd_data.busy_lock) {
+ _hcd_data.busy_lock = true;
+ has_xfer = true;
+ }
+ usbh_spin_unlock(false);
+
// carry out transfer if not busy
- if (!atomic_flag_test_and_set(&_hcd_data.busy)) {
+ if (has_xfer) {
xact_generic(rhport, ep, true, false);
}
@@ -785,8 +792,17 @@ bool hcd_setup_send(uint8_t rhport, uint8_t daddr, uint8_t const setup_packet[8]
ep->xferred_len = 0;
ep->state = EP_STATE_ATTEMPT_1;
+ bool has_xfer = false;
+
+ usbh_spin_lock(false);
+ if (!_hcd_data.busy_lock) {
+ _hcd_data.busy_lock = true;
+ has_xfer = true;
+ }
+ usbh_spin_unlock(false);
+
// carry out transfer if not busy
- if (!atomic_flag_test_and_set(&_hcd_data.busy)) {
+ if (has_xfer) {
xact_setup(rhport, ep, false);
}
@@ -852,8 +868,8 @@ static void handle_connect_irq(uint8_t rhport, bool in_isr) {
}
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_dir = 1-ep->hxfr_bm.is_out;
- uint8_t const ep_addr = tu_edpt_addr(ep->hxfr_bm.ep_num, ep_dir);
+ const uint8_t ep_dir = 1 - ep->hxfr_bm.is_out;
+ const uint8_t ep_addr = tu_edpt_addr(ep->hxfr_bm.ep_num, ep_dir);
// save data toggle
if (ep_dir) {
@@ -871,7 +887,9 @@ static void xfer_complete_isr(uint8_t rhport, max3421_ep_t *ep, xfer_result_t re
xact_generic(rhport, next_ep, true, in_isr);
}else {
// no more pending
- atomic_flag_clear(&_hcd_data.busy);
+ usbh_spin_lock(in_isr);
+ _hcd_data.busy_lock = false;
+ usbh_spin_unlock(in_isr);
}
}
@@ -910,7 +928,9 @@ static void handle_xfer_done(uint8_t rhport, bool in_isr) {
xact_generic(rhport, next_ep, true, in_isr);
} else {
// no more pending in this frame -> clear busy
- atomic_flag_clear(&_hcd_data.busy);
+ usbh_spin_lock(in_isr);
+ _hcd_data.busy_lock = false;
+ usbh_spin_unlock(in_isr);
}
return;
@@ -1001,8 +1021,8 @@ void print_hirq(uint8_t hirq) {
// Interrupt handler
void hcd_int_handler(uint8_t rhport, bool in_isr) {
uint8_t hirq = reg_read(rhport, HIRQ_ADDR, in_isr) & _hcd_data.hien;
- if (!hirq) return;
-// print_hirq(hirq);
+ if (!hirq) { return; }
+ // print_hirq(hirq);
if (hirq & HIRQ_FRAME_IRQ) {
_hcd_data.frame_count++;
@@ -1021,8 +1041,19 @@ void hcd_int_handler(uint8_t rhport, bool in_isr) {
}
// start usb transfer if not busy
- if (ep_retry != NULL && !atomic_flag_test_and_set(&_hcd_data.busy)) {
- xact_generic(rhport, ep_retry, true, in_isr);
+ if (ep_retry != NULL) {
+ bool has_xfer = false;
+
+ usbh_spin_lock(in_isr);
+ if (!_hcd_data.busy_lock) {
+ _hcd_data.busy_lock = true;
+ has_xfer = true;
+ }
+ usbh_spin_unlock(in_isr);
+
+ if (has_xfer) {
+ xact_generic(rhport, ep_retry, true, in_isr);
+ }
}
}