summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhathach <[email protected]>2023-08-18 17:39:10 +0700
committerhathach <[email protected]>2023-08-18 17:39:10 +0700
commitcacc96b25dc04865389357467b7a6d92d040ef36 (patch)
tree17060d96347203ce3dbc27354904ea2c54219ea2
parent824e585e2b1f62d1ed03f480439e62e5410636b6 (diff)
adding connection event handling, add nrf gpio interrupt for max2341e interrupt pin
-rw-r--r--hw/bsp/nrf/boards/feather_nrf52840_express/board.h2
-rw-r--r--hw/bsp/nrf/family.c55
-rw-r--r--hw/bsp/nrf/family.cmake2
-rw-r--r--hw/bsp/nrf/nrfx_config.h2
-rw-r--r--hw/bsp/nrf/nrfx_glue.h69
-rw-r--r--src/portable/analog/max3421e/hcd_max3421e.c76
6 files changed, 184 insertions, 22 deletions
diff --git a/hw/bsp/nrf/boards/feather_nrf52840_express/board.h b/hw/bsp/nrf/boards/feather_nrf52840_express/board.h
index e19f88a3c..7f042142e 100644
--- a/hw/bsp/nrf/boards/feather_nrf52840_express/board.h
+++ b/hw/bsp/nrf/boards/feather_nrf52840_express/board.h
@@ -50,7 +50,7 @@
#define SPI_MOSI_PIN 13
#define SPI_MISO_PIN 15
#define SPI_CS_PIN 27
-#define MAX3241E_INT_PIN 26
+#define MAX3241E_INTR_PIN 26
#ifdef __cplusplus
}
diff --git a/hw/bsp/nrf/family.c b/hw/bsp/nrf/family.c
index b6ed15122..e58ee845b 100644
--- a/hw/bsp/nrf/family.c
+++ b/hw/bsp/nrf/family.c
@@ -38,6 +38,7 @@
#include "nrfx.h"
#include "hal/nrf_gpio.h"
+#include "drivers/include/nrfx_gpiote.h"
#include "drivers/include/nrfx_power.h"
#include "drivers/include/nrfx_uarte.h"
#include "drivers/include/nrfx_spim.h"
@@ -81,18 +82,45 @@ enum {
#endif
static nrfx_uarte_t _uart_id = NRFX_UARTE_INSTANCE(0);
-static nrfx_spim_t _spi = NRFX_SPIM_INSTANCE(0);
// tinyusb function that handles power event (detected, ready, removed)
// We must call it within SD's SOC event handler, or set it as power event handler if SD is not enabled.
extern void tusb_hal_nrf_power_event(uint32_t event);
-
// nrf power callback, could be unused if SD is enabled or usb is disabled (board_test example)
TU_ATTR_UNUSED static void power_event_handler(nrfx_power_usb_evt_t event) {
tusb_hal_nrf_power_event((uint32_t) event);
}
+//------------- Host using MAX2341E -------------//
+#if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421E) && CFG_TUH_MAX3421E
+static nrfx_spim_t _spi = NRFX_SPIM_INSTANCE(0);
+
+void max2342e_int_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action) {
+ if ( !(pin == MAX3241E_INTR_PIN && action == NRF_GPIOTE_POLARITY_HITOLO) ) return;
+
+ tuh_int_handler(1);
+}
+
+// API: SPI transfer with MAX3421E, must be implemented by application
+bool tuh_max3421e_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 = {
+ .p_tx_buffer = tx_buf,
+ .tx_length = tx_len,
+ .p_rx_buffer = rx_buf,
+ .rx_length = rx_len,
+ };
+ return nrfx_spim_xfer(&_spi, &xfer, 0) == NRFX_SUCCESS;
+}
+
+#endif
+
+
+//--------------------------------------------------------------------+
+//
+//--------------------------------------------------------------------+
+
void board_init(void) {
// stop LF clock just in case we jump from application without reset
NRF_CLOCK->TASKS_LFCLKSTOP = 1UL;
@@ -174,7 +202,6 @@ void board_init(void) {
if ( usb_reg & OUTPUTRDY_Msk ) tusb_hal_nrf_power_event(USB_EVT_READY);
#endif
- (void) _spi;
#if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421E) && CFG_TUH_MAX3421E
// USB host using max3421e usb controller via SPI
nrfx_spim_config_t cfg = {
@@ -193,6 +220,14 @@ void board_init(void) {
// no handler --> blocking
nrfx_spim_init(&_spi, &cfg, NULL, NULL);
+
+ // max3421e interrupt pin
+ nrfx_gpiote_init(1);
+ nrfx_gpiote_in_config_t in_config = NRFX_GPIOTE_CONFIG_IN_SENSE_HITOLO(true);
+ in_config.pull = NRF_GPIO_PIN_PULLUP;
+
+ nrfx_gpiote_in_init(MAX3241E_INTR_PIN, &in_config, max2342e_int_handler);
+ nrfx_gpiote_in_event_enable(MAX3241E_INTR_PIN, true);
#endif
}
@@ -233,20 +268,6 @@ uint32_t board_millis(void) {
#endif
-#if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421E) && CFG_TUH_MAX3421E
-// API: SPI transfer with MAX3421E, must be implemented by application
-bool tuh_max3421e_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 = {
- .p_tx_buffer = tx_buf,
- .tx_length = tx_len,
- .p_rx_buffer = rx_buf,
- .rx_length = rx_len,
- };
- return nrfx_spim_xfer(&_spi, &xfer, 0) == NRFX_SUCCESS;
-}
-#endif
-
#ifdef SOFTDEVICE_PRESENT
// process SOC event from SD
uint32_t proc_soc(void)
diff --git a/hw/bsp/nrf/family.cmake b/hw/bsp/nrf/family.cmake
index 527251e71..8bf7bcb52 100644
--- a/hw/bsp/nrf/family.cmake
+++ b/hw/bsp/nrf/family.cmake
@@ -32,6 +32,8 @@ function(add_board_target BOARD_TARGET)
if (NOT TARGET ${BOARD_TARGET})
add_library(${BOARD_TARGET} STATIC
# driver
+ ${NRFX_DIR}/helpers/nrfx_flag32_allocator.c
+ ${NRFX_DIR}/drivers/src/nrfx_gpiote.c
${NRFX_DIR}/drivers/src/nrfx_power.c
${NRFX_DIR}/drivers/src/nrfx_spim.c
${NRFX_DIR}/drivers/src/nrfx_uarte.c
diff --git a/hw/bsp/nrf/nrfx_config.h b/hw/bsp/nrf/nrfx_config.h
index d0f718c6c..e3d0ea91b 100644
--- a/hw/bsp/nrf/nrfx_config.h
+++ b/hw/bsp/nrf/nrfx_config.h
@@ -5,6 +5,7 @@
#define NRFX_POWER_DEFAULT_CONFIG_IRQ_PRIORITY 7
#define NRFX_CLOCK_ENABLED 0
+#define NRFX_GPIOTE_ENABLED 1
#define NRFX_UARTE_ENABLED 1
#define NRFX_UARTE0_ENABLED 1
@@ -41,5 +42,4 @@
#error "Unknown device."
#endif
-
#endif // NRFX_CONFIG_H__
diff --git a/hw/bsp/nrf/nrfx_glue.h b/hw/bsp/nrf/nrfx_glue.h
index cdf49b4ab..ef756c670 100644
--- a/hw/bsp/nrf/nrfx_glue.h
+++ b/hw/bsp/nrf/nrfx_glue.h
@@ -220,6 +220,75 @@ static inline bool _NRFX_IRQ_IS_PENDING(IRQn_Type irq_number)
/** @} */
+//------------------------------------------------------------------------------
+
+#include <soc/nrfx_atomic.h>
+
+/**
+ * @brief Atomic 32 bit unsigned type.
+ */
+#define nrfx_atomic_t nrfx_atomic_u32_t
+
+/**
+ * @brief Stores value to an atomic object and returns previously stored value.
+ *
+ * @param[in] p_data Atomic memory pointer.
+ * @param[in] value Value to store.
+ *
+ * @return Old value stored into atomic object.
+ */
+#define NRFX_ATOMIC_FETCH_STORE(p_data, value) nrfx_atomic_u32_fetch_store(p_data, value)
+
+/**
+ * @brief Performs logical OR operation on an atomic object and returns previously stored value.
+ *
+ * @param[in] p_data Atomic memory pointer.
+ * @param[in] value Value of second operand of OR operation.
+ *
+ * @return Old value stored into atomic object.
+ */
+#define NRFX_ATOMIC_FETCH_OR(p_data, value) nrfx_atomic_u32_fetch_or(p_data, value)
+
+/**
+ * @brief Performs logical AND operation on an atomic object and returns previously stored value.
+ *
+ * @param[in] p_data Atomic memory pointer.
+ * @param[in] value Value of second operand of AND operation.
+ *
+ * @return Old value stored into atomic object.
+ */
+#define NRFX_ATOMIC_FETCH_AND(p_data, value) nrfx_atomic_u32_fetch_and(p_data, value)
+
+/**
+ * @brief Performs logical XOR operation on an atomic object and returns previously stored value.
+ *
+ * @param[in] p_data Atomic memory pointer.
+ * @param[in] value Value of second operand of XOR operation.
+ *
+ * @return Old value stored into atomic object.
+ */
+#define NRFX_ATOMIC_FETCH_XOR(p_data, value) nrfx_atomic_u32_fetch_xor(p_data, value)
+
+/**
+ * @brief Performs logical ADD operation on an atomic object and returns previously stored value.
+ *
+ * @param[in] p_data Atomic memory pointer.
+ * @param[in] value Value of second operand of ADD operation.
+ *
+ * @return Old value stored into atomic object.
+ */
+#define NRFX_ATOMIC_FETCH_ADD(p_data, value) nrfx_atomic_u32_fetch_add(p_data, value)
+
+/**
+ * @brief Performs logical SUB operation on an atomic object and returns previously stored value.
+ *
+ * @param[in] p_data Atomic memory pointer.
+ * @param[in] value Value of second operand of SUB operation.
+ *
+ * @return Old value stored into atomic object.
+ */
+#define NRFX_ATOMIC_FETCH_SUB(p_data, value) nrfx_atomic_u32_fetch_sub(p_data, value)
+
#ifdef __cplusplus
}
#endif
diff --git a/src/portable/analog/max3421e/hcd_max3421e.c b/src/portable/analog/max3421e/hcd_max3421e.c
index 7b9d73e4e..a89581b9c 100644
--- a/src/portable/analog/max3421e/hcd_max3421e.c
+++ b/src/portable/analog/max3421e/hcd_max3421e.c
@@ -136,6 +136,20 @@ enum {
HRSL_JSTATUS = 1u << 7,
};
+//--------------------------------------------------------------------+
+//
+//--------------------------------------------------------------------+
+
+//typedef struct {
+// uint8_t mode
+//} max2341e_data_t;
+//
+//max2341e_data_t max2341e_data;
+
+//--------------------------------------------------------------------+
+//
+//--------------------------------------------------------------------+
+
// API: SPI transfer with MAX3421E, must be implemented by application
bool tuh_max3421e_spi_xfer_api(uint8_t rhport, uint8_t const * tx_buf, size_t tx_len, uint8_t * rx_buf, size_t rx_len);
@@ -144,6 +158,7 @@ static uint8_t reg_write(uint8_t reg, uint8_t data) {
uint8_t tx_buf[2] = {reg | CMDBYTE_WRITE, data};
uint8_t rx_buf[2] = {0, 0};
tuh_max3421e_spi_xfer_api(0, tx_buf, 2, rx_buf, 2);
+ TU_LOG2("HIRQ: %02X\r\n", rx_buf[0]);
return rx_buf[0];
}
@@ -167,6 +182,48 @@ 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) {
+ (void) rhport;
+
+ uint8_t const hrsl = reg_read(HRSL_ADDR);
+ uint8_t const jk = hrsl & (HRSL_JSTATUS | HRSL_KSTATUS);
+
+ tusb_speed_t speed;
+ uint8_t new_mode = MODE_DPPULLDN | MODE_DMPULLDN | MODE_HOST;
+
+ switch(jk) {
+ case 0x00:
+ // SEO is disconnected
+ speed = TUSB_SPEED_INVALID;
+ break;
+
+ case (HRSL_JSTATUS | HRSL_KSTATUS):
+ // SE1 is illegal
+ speed = TUSB_SPEED_INVALID;
+ break;
+
+ default: {
+ // Low speed if (LS = 1 and J-state) or (LS = 0 and K-State)
+ uint8_t const mode = reg_read(MODE_ADDR);
+ uint8_t const ls_bit = mode & MODE_LOWSPEED;
+
+ 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
+
+ break;
+ }
+ }
+
+ reg_write(MODE_ADDR, new_mode);
+ return speed;
+}
+
// Initialize controller to host mode
bool hcd_init(uint8_t rhport) {
(void) rhport;
@@ -184,15 +241,28 @@ bool hcd_init(uint8_t rhport) {
// Mode: Host and DP/DM pull down
reg_write(MODE_ADDR, MODE_DPPULLDN | MODE_DMPULLDN | MODE_HOST);
- // Connection detection
- reg_write(HIEN_ADDR, HIRQ_CONDET_IRQ /*| HIRQ_FRAME_IRQ */);
+ // Enable Connection IRQ
+ reg_write(HIEN_ADDR, HIRQ_CONDET_IRQ);
- return false;
+ // Note: if device is already connected, CONDET IRQ may not be triggered. We need to detect it by sampling bus signal
+ reg_write(HCTL_ADDR, HCTL_SAMPLEBUS);
+ while( !(reg_read(HCTL_ADDR) & HCTL_SAMPLEBUS) ) {}
+
+ handle_connect_irq(rhport);
+ reg_write(HIRQ_ADDR, HIRQ_CONDET_IRQ);
+
+ // Enable Interrupt pin
+ reg_write(CPUCTL_ADDR, CPUCTL_IE);
+
+ return true;
}
// Interrupt Handler
void hcd_int_handler(uint8_t rhport) {
(void) rhport;
+
+ uint8_t hirq = reg_read(HIRQ_ADDR);
+ TU_LOG3_INT(hirq);
}
// Enable USB interrupt