Skip to content

Commit

Permalink
Merge pull request #2331 from hathach/add-featherwing-max3421e
Browse files Browse the repository at this point in the history
Add featherwing max3421e support
  • Loading branch information
hathach authored Nov 20, 2023
2 parents cbd3e0b + 86f6588 commit 41e2da7
Show file tree
Hide file tree
Showing 9 changed files with 120 additions and 53 deletions.
2 changes: 2 additions & 0 deletions .idea/cmake.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 18 additions & 12 deletions examples/host/cdc_msc_hid/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,17 @@
// MACRO CONSTANT TYPEDEF PROTYPES
//--------------------------------------------------------------------+
void led_blinking_task(void);

extern void cdc_app_task(void);
extern void hid_app_task(void);

#if CFG_TUH_ENABLED && CFG_TUH_MAX3421
// API to read/rite MAX3421's register. Implemented by TinyUSB
extern uint8_t tuh_max3421_reg_read(uint8_t rhport, uint8_t reg, bool in_isr);
extern bool tuh_max3421_reg_write(uint8_t rhport, uint8_t reg, uint8_t data, bool in_isr);
#endif

/*------------- MAIN -------------*/
int main(void)
{
int main(void) {
board_init();

printf("TinyUSB Host CDC MSC HID Example\r\n");
Expand All @@ -52,8 +56,13 @@ int main(void)
board_init_after_tusb();
}

while (1)
{
#if CFG_TUH_ENABLED && CFG_TUH_MAX3421
// FeatherWing MAX3421E use MAX3421E's GPIO0 for VBUS enable
enum { IOPINS1_ADDR = 20u << 3, /* 0xA0 */ };
tuh_max3421_reg_write(BOARD_TUH_RHPORT, IOPINS1_ADDR, 0x01, false);
#endif

while (1) {
// tinyusb host task
tuh_task();

Expand All @@ -67,14 +76,12 @@ int main(void)
// TinyUSB Callbacks
//--------------------------------------------------------------------+

void tuh_mount_cb(uint8_t dev_addr)
{
void tuh_mount_cb(uint8_t dev_addr) {
// application set-up
printf("A device with address %d is mounted\r\n", dev_addr);
}

void tuh_umount_cb(uint8_t dev_addr)
{
void tuh_umount_cb(uint8_t dev_addr) {
// application tear-down
printf("A device with address %d is unmounted \r\n", dev_addr);
}
Expand All @@ -83,15 +90,14 @@ void tuh_umount_cb(uint8_t dev_addr)
//--------------------------------------------------------------------+
// Blinking Task
//--------------------------------------------------------------------+
void led_blinking_task(void)
{
void led_blinking_task(void) {
const uint32_t interval_ms = 1000;
static uint32_t start_ms = 0;

static bool led_state = false;

// Blink every interval ms
if ( board_millis() - start_ms < interval_ms) return; // not enough time
if (board_millis() - start_ms < interval_ms) return; // not enough time
start_ms += interval_ms;

board_led_write(led_state);
Expand Down
12 changes: 12 additions & 0 deletions examples/host/cdc_msc_hid_freertos/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,12 @@ extern void cdc_app_init(void);
extern void hid_app_init(void);
extern void msc_app_init(void);

#if CFG_TUH_ENABLED && CFG_TUH_MAX3421
// API to read/rite MAX3421's register. Implemented by TinyUSB
extern uint8_t tuh_max3421_reg_read(uint8_t rhport, uint8_t reg, bool in_isr);
extern bool tuh_max3421_reg_write(uint8_t rhport, uint8_t reg, uint8_t data, bool in_isr);
#endif

/*------------- MAIN -------------*/
int main(void) {
board_init();
Expand Down Expand Up @@ -126,6 +132,12 @@ static void usb_host_task(void *param) {
board_init_after_tusb();
}

#if CFG_TUH_ENABLED && CFG_TUH_MAX3421
// FeatherWing MAX3421E use MAX3421E's GPIO0 for VBUS enable
enum { IOPINS1_ADDR = 20u << 3, /* 0xA0 */ };
tuh_max3421_reg_write(BOARD_TUH_RHPORT, IOPINS1_ADDR, 0x01, false);
#endif

cdc_app_init();
hid_app_init();
msc_app_init();
Expand Down
4 changes: 2 additions & 2 deletions hw/bsp/nrf/boards/feather_nrf52840_express/board.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@
#define MAX3421_SCK_PIN 14
#define MAX3421_MOSI_PIN 13
#define MAX3421_MISO_PIN 15
#define MAX3421_CS_PIN 27 // D10
#define MAX3421_INTR_PIN 26 // D9
#define MAX3421_CS_PIN 6 // D11
#define MAX3421_INTR_PIN 27 // D10

#ifdef __cplusplus
}
Expand Down
2 changes: 0 additions & 2 deletions hw/bsp/nrf/family.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,7 @@ TU_ATTR_UNUSED static void power_event_handler(nrfx_power_usb_evt_t event) {

//------------- Host using MAX2341E -------------//
#if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421

static void max3421_init(void);

static nrfx_spim_t _spi = NRFX_SPIM_INSTANCE(1);
#endif

Expand Down
15 changes: 15 additions & 0 deletions hw/bsp/samd21/boards/feather_m0_express/board.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,21 @@
#define UART_RX_PIN 4
#define UART_TX_PIN 5

// SPI for USB host shield
#define MAX3421_SERCOM_ID 4 // SERCOM4
#define MAX3421_SERCOM_FUNCTION 3 // function D (Sercom Alt)

#define MAX3421_SCK_PIN (32+11)
#define MAX3421_MOSI_PIN (32+10)
#define MAX3421_MISO_PIN 12
#define MAX3421_TX_PAD 1 // MOSI = PAD_2, SCK = PAD_3
#define MAX3421_RX_PAD 0 // MISO = PAD_2

#define MAX3421_CS_PIN 16 // D11

#define MAX3421_INTR_PIN 18 // D10
#define MAX3421_INTR_EIC_ID 2 // EIC2

#ifdef __cplusplus
}
#endif
Expand Down
17 changes: 17 additions & 0 deletions hw/bsp/samd51/boards/feather_m4_express/board.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
extern "C" {
#endif

#define _PINNUM(port, pin) ((port)*32 + (pin))

// LED
#define LED_PIN 23
#define LED_STATE_ON 1
Expand All @@ -43,6 +45,21 @@
#define UART_TX_PIN (32 + 17)
#define UART_RX_PIN (32 + 16)

// SPI for USB host shield
#define MAX3421_SERCOM_ID 1 // SERCOM2
#define MAX3421_SERCOM_FUNCTION 2 // function C

#define MAX3421_SCK_PIN _PINNUM(0, 17)
#define MAX3421_MOSI_PIN _PINNUM(1, 23)
#define MAX3421_MISO_PIN _PINNUM(1, 22)
#define MAX3421_TX_PAD 2 // MOSI = PAD_3, SCK = PAD_1
#define MAX3421_RX_PAD 2 // MISO = PAD_2

#define MAX3421_CS_PIN 21 // D11

#define MAX3421_INTR_PIN 20 // D10
#define MAX3421_INTR_EIC_ID 4 // EIC4

#ifdef __cplusplus
}
#endif
Expand Down
13 changes: 8 additions & 5 deletions hw/bsp/samd51/family.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,12 @@ void USB_3_Handler(void) {
// Implementation
//--------------------------------------------------------------------+

#if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421
#if CFG_TUH_ENABLED && CFG_TUH_MAX3421

#define MAX3421_SERCOM TU_XSTRCAT(SERCOM, MAX3421_SERCOM_ID)
#define MAX3421_EIC_Handler TU_XSTRCAT3(EIC_, MAX3421_INTR_EIC_ID, _Handler)

static void max3421_init(void);

#endif

void board_init(void) {
Expand Down Expand Up @@ -136,11 +136,14 @@ void board_init(void) {
gpio_set_pin_function(PIN_PA24, PINMUX_PA24H_USB_DM);
gpio_set_pin_function(PIN_PA25, PINMUX_PA25H_USB_DP);

#if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421
#if CFG_TUH_ENABLED && CFG_TUH_MAX3421
max3421_init();
#endif
}

void board_init_after_tusb(void) {
}

//--------------------------------------------------------------------+
// Board porting API
//--------------------------------------------------------------------+
Expand Down Expand Up @@ -182,7 +185,7 @@ uint32_t board_millis(void) {
//--------------------------------------------------------------------+
// API: SPI transfer with MAX3421E, must be implemented by application
//--------------------------------------------------------------------+
#if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421
#if CFG_TUH_ENABLED && CFG_TUH_MAX3421

static void max3421_init(void) {
//------------- SPI Init -------------//
Expand Down Expand Up @@ -262,7 +265,7 @@ static void max3421_init(void) {

// Enable the SPI module
sercom->SPI.CTRLA.bit.ENABLE = 1;
while (sercom->SPI.SYNCBUSY.bit.ENABLE);
while (sercom->SPI.SYNCBUSY.bit.ENABLE) {}

//------------- External Interrupt -------------//

Expand Down
78 changes: 46 additions & 32 deletions src/portable/analog/max3421/hcd_max3421.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ enum {
CPUCTL_ADDR = 16u << 3, // 0x80
PINCTL_ADDR = 17u << 3, // 0x88
REVISION_ADDR = 18u << 3, // 0x90
// 19 is not used
IOPINS1_ADDR = 20u << 3, // 0xA0
IOPINS2_ADDR = 21u << 3, // 0xA8
GPINIRQ_ADDR = 22u << 3, // 0xB0
GPINIEN_ADDR = 23u << 3, // 0xB8
GPINPOL_ADDR = 24u << 3, // 0xC0
HIRQ_ADDR = 25u << 3, // 0xC8
HIEN_ADDR = 26u << 3, // 0xD0
MODE_ADDR = 27u << 3, // 0xD8
Expand Down Expand Up @@ -207,7 +213,9 @@ typedef struct {
static max3421_data_t _hcd_data;

//--------------------------------------------------------------------+
// API: SPI transfer with MAX3421E, must be implemented by application
// 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
Expand All @@ -220,11 +228,18 @@ extern bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const* tx_buf, uint
// 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 Helper
// SPI Commands and Helper
//--------------------------------------------------------------------+
static void handle_connect_irq(uint8_t rhport, bool in_isr);
static inline void hirq_write(uint8_t rhport, uint8_t data, bool in_isr);

#define reg_read tuh_max3421_reg_read
#define reg_write tuh_max3421_reg_write

static void max3421_spi_lock(uint8_t rhport, bool in_isr) {
// disable interrupt and mutex lock (for pre-emptive RTOS) if not in_isr
Expand All @@ -248,61 +263,60 @@ static void max3421_spi_unlock(uint8_t rhport, bool in_isr) {
}
}

static void fifo_write(uint8_t rhport, uint8_t reg, uint8_t const * buffer, uint16_t len, bool in_isr) {
uint8_t hirq;
reg |= CMDBYTE_WRITE;
uint8_t tuh_max3421_reg_read(uint8_t rhport, uint8_t reg, bool in_isr) {
uint8_t tx_buf[2] = {reg, 0};
uint8_t rx_buf[2] = {0, 0};

max3421_spi_lock(rhport, in_isr);

tuh_max3421_spi_xfer_api(rhport, &reg, &hirq, 1);
_hcd_data.hirq = hirq;
tuh_max3421_spi_xfer_api(rhport, buffer, NULL, len);

bool ret = tuh_max3421_spi_xfer_api(rhport, tx_buf, rx_buf, 2);
max3421_spi_unlock(rhport, in_isr);

_hcd_data.hirq = rx_buf[0];
return ret ? rx_buf[1] : 0;
}

static void fifo_read(uint8_t rhport, uint8_t * buffer, uint16_t len, bool in_isr) {
uint8_t hirq;
uint8_t const reg = RCVVFIFO_ADDR;
bool tuh_max3421_reg_write(uint8_t rhport, uint8_t reg, uint8_t data, bool in_isr) {
uint8_t tx_buf[2] = {reg | CMDBYTE_WRITE, data};
uint8_t rx_buf[2] = {0, 0};

max3421_spi_lock(rhport, in_isr);
bool ret = tuh_max3421_spi_xfer_api(rhport, tx_buf, rx_buf, 2);
max3421_spi_unlock(rhport, in_isr);

tuh_max3421_spi_xfer_api(rhport, &reg, &hirq, 1);
_hcd_data.hirq = hirq;
tuh_max3421_spi_xfer_api(rhport, NULL, buffer, len);
// HIRQ register since we are in full-duplex mode
_hcd_data.hirq = rx_buf[0];

max3421_spi_unlock(rhport, in_isr);
return ret;
}

static void reg_write(uint8_t rhport, uint8_t reg, uint8_t data, bool in_isr) {
uint8_t tx_buf[2] = {reg | CMDBYTE_WRITE, data};
uint8_t rx_buf[2] = {0, 0};
static void fifo_write(uint8_t rhport, uint8_t reg, uint8_t const * buffer, uint16_t len, bool in_isr) {
uint8_t hirq;
reg |= CMDBYTE_WRITE;

max3421_spi_lock(rhport, in_isr);

tuh_max3421_spi_xfer_api(rhport, tx_buf, rx_buf, 2);
tuh_max3421_spi_xfer_api(rhport, &reg, &hirq, 1);
_hcd_data.hirq = hirq;
tuh_max3421_spi_xfer_api(rhport, buffer, NULL, len);

max3421_spi_unlock(rhport, in_isr);

// HIRQ register since we are in full-duplex mode
_hcd_data.hirq = rx_buf[0];
}

static uint8_t reg_read(uint8_t rhport, uint8_t reg, bool in_isr) {
uint8_t tx_buf[2] = {reg, 0};
uint8_t rx_buf[2] = {0, 0};
static void fifo_read(uint8_t rhport, uint8_t * buffer, uint16_t len, bool in_isr) {
uint8_t hirq;
uint8_t const reg = RCVVFIFO_ADDR;

max3421_spi_lock(rhport, in_isr);

bool ret = tuh_max3421_spi_xfer_api(rhport, tx_buf, rx_buf, 2);
tuh_max3421_spi_xfer_api(rhport, &reg, &hirq, 1);
_hcd_data.hirq = hirq;
tuh_max3421_spi_xfer_api(rhport, NULL, buffer, len);

max3421_spi_unlock(rhport, in_isr);

_hcd_data.hirq = rx_buf[0];
return ret ? rx_buf[1] : 0;
}

//------------- register write helper -------------//
static inline void hirq_write(uint8_t rhport, uint8_t data, bool in_isr) {
reg_write(rhport, HIRQ_ADDR, data, in_isr);
// HIRQ write 1 is clear
Expand Down

0 comments on commit 41e2da7

Please sign in to comment.