adding connection event handling, add nrf gpio interrupt for max2341e interrupt pin

This commit is contained in:
hathach 2023-08-18 17:39:10 +07:00
parent 824e585e2b
commit cacc96b25d
No known key found for this signature in database
GPG Key ID: F5D50C6D51D17CBA
6 changed files with 184 additions and 22 deletions

View File

@ -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
}

View File

@ -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)

View File

@ -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

View File

@ -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__

View File

@ -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

View File

@ -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