mirror of
https://github.com/hathach/tinyusb.git
synced 2025-01-17 05:32:55 +08:00
adding connection event handling, add nrf gpio interrupt for max2341e interrupt pin
This commit is contained in:
parent
824e585e2b
commit
cacc96b25d
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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__
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user