Skip to content

Commit 41e2da7

Browse files
authored
Merge pull request #2331 from hathach/add-featherwing-max3421e
Add featherwing max3421e support
2 parents cbd3e0b + 86f6588 commit 41e2da7

File tree

9 files changed

+120
-53
lines changed

9 files changed

+120
-53
lines changed

.idea/cmake.xml

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/host/cdc_msc_hid/src/main.c

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,17 @@
3434
// MACRO CONSTANT TYPEDEF PROTYPES
3535
//--------------------------------------------------------------------+
3636
void led_blinking_task(void);
37-
3837
extern void cdc_app_task(void);
3938
extern void hid_app_task(void);
4039

40+
#if CFG_TUH_ENABLED && CFG_TUH_MAX3421
41+
// API to read/rite MAX3421's register. Implemented by TinyUSB
42+
extern uint8_t tuh_max3421_reg_read(uint8_t rhport, uint8_t reg, bool in_isr);
43+
extern bool tuh_max3421_reg_write(uint8_t rhport, uint8_t reg, uint8_t data, bool in_isr);
44+
#endif
45+
4146
/*------------- MAIN -------------*/
42-
int main(void)
43-
{
47+
int main(void) {
4448
board_init();
4549

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

55-
while (1)
56-
{
59+
#if CFG_TUH_ENABLED && CFG_TUH_MAX3421
60+
// FeatherWing MAX3421E use MAX3421E's GPIO0 for VBUS enable
61+
enum { IOPINS1_ADDR = 20u << 3, /* 0xA0 */ };
62+
tuh_max3421_reg_write(BOARD_TUH_RHPORT, IOPINS1_ADDR, 0x01, false);
63+
#endif
64+
65+
while (1) {
5766
// tinyusb host task
5867
tuh_task();
5968

@@ -67,14 +76,12 @@ int main(void)
6776
// TinyUSB Callbacks
6877
//--------------------------------------------------------------------+
6978

70-
void tuh_mount_cb(uint8_t dev_addr)
71-
{
79+
void tuh_mount_cb(uint8_t dev_addr) {
7280
// application set-up
7381
printf("A device with address %d is mounted\r\n", dev_addr);
7482
}
7583

76-
void tuh_umount_cb(uint8_t dev_addr)
77-
{
84+
void tuh_umount_cb(uint8_t dev_addr) {
7885
// application tear-down
7986
printf("A device with address %d is unmounted \r\n", dev_addr);
8087
}
@@ -83,15 +90,14 @@ void tuh_umount_cb(uint8_t dev_addr)
8390
//--------------------------------------------------------------------+
8491
// Blinking Task
8592
//--------------------------------------------------------------------+
86-
void led_blinking_task(void)
87-
{
93+
void led_blinking_task(void) {
8894
const uint32_t interval_ms = 1000;
8995
static uint32_t start_ms = 0;
9096

9197
static bool led_state = false;
9298

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

97103
board_led_write(led_state);

examples/host/cdc_msc_hid_freertos/src/main.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,12 @@ extern void cdc_app_init(void);
8383
extern void hid_app_init(void);
8484
extern void msc_app_init(void);
8585

86+
#if CFG_TUH_ENABLED && CFG_TUH_MAX3421
87+
// API to read/rite MAX3421's register. Implemented by TinyUSB
88+
extern uint8_t tuh_max3421_reg_read(uint8_t rhport, uint8_t reg, bool in_isr);
89+
extern bool tuh_max3421_reg_write(uint8_t rhport, uint8_t reg, uint8_t data, bool in_isr);
90+
#endif
91+
8692
/*------------- MAIN -------------*/
8793
int main(void) {
8894
board_init();
@@ -126,6 +132,12 @@ static void usb_host_task(void *param) {
126132
board_init_after_tusb();
127133
}
128134

135+
#if CFG_TUH_ENABLED && CFG_TUH_MAX3421
136+
// FeatherWing MAX3421E use MAX3421E's GPIO0 for VBUS enable
137+
enum { IOPINS1_ADDR = 20u << 3, /* 0xA0 */ };
138+
tuh_max3421_reg_write(BOARD_TUH_RHPORT, IOPINS1_ADDR, 0x01, false);
139+
#endif
140+
129141
cdc_app_init();
130142
hid_app_init();
131143
msc_app_init();

hw/bsp/nrf/boards/feather_nrf52840_express/board.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@
4949
#define MAX3421_SCK_PIN 14
5050
#define MAX3421_MOSI_PIN 13
5151
#define MAX3421_MISO_PIN 15
52-
#define MAX3421_CS_PIN 27 // D10
53-
#define MAX3421_INTR_PIN 26 // D9
52+
#define MAX3421_CS_PIN 6 // D11
53+
#define MAX3421_INTR_PIN 27 // D10
5454

5555
#ifdef __cplusplus
5656
}

hw/bsp/nrf/family.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,7 @@ TU_ATTR_UNUSED static void power_event_handler(nrfx_power_usb_evt_t event) {
9595

9696
//------------- Host using MAX2341E -------------//
9797
#if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421
98-
9998
static void max3421_init(void);
100-
10199
static nrfx_spim_t _spi = NRFX_SPIM_INSTANCE(1);
102100
#endif
103101

hw/bsp/samd21/boards/feather_m0_express/board.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,21 @@
4343
#define UART_RX_PIN 4
4444
#define UART_TX_PIN 5
4545

46+
// SPI for USB host shield
47+
#define MAX3421_SERCOM_ID 4 // SERCOM4
48+
#define MAX3421_SERCOM_FUNCTION 3 // function D (Sercom Alt)
49+
50+
#define MAX3421_SCK_PIN (32+11)
51+
#define MAX3421_MOSI_PIN (32+10)
52+
#define MAX3421_MISO_PIN 12
53+
#define MAX3421_TX_PAD 1 // MOSI = PAD_2, SCK = PAD_3
54+
#define MAX3421_RX_PAD 0 // MISO = PAD_2
55+
56+
#define MAX3421_CS_PIN 16 // D11
57+
58+
#define MAX3421_INTR_PIN 18 // D10
59+
#define MAX3421_INTR_EIC_ID 2 // EIC2
60+
4661
#ifdef __cplusplus
4762
}
4863
#endif

hw/bsp/samd51/boards/feather_m4_express/board.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
extern "C" {
3232
#endif
3333

34+
#define _PINNUM(port, pin) ((port)*32 + (pin))
35+
3436
// LED
3537
#define LED_PIN 23
3638
#define LED_STATE_ON 1
@@ -43,6 +45,21 @@
4345
#define UART_TX_PIN (32 + 17)
4446
#define UART_RX_PIN (32 + 16)
4547

48+
// SPI for USB host shield
49+
#define MAX3421_SERCOM_ID 1 // SERCOM2
50+
#define MAX3421_SERCOM_FUNCTION 2 // function C
51+
52+
#define MAX3421_SCK_PIN _PINNUM(0, 17)
53+
#define MAX3421_MOSI_PIN _PINNUM(1, 23)
54+
#define MAX3421_MISO_PIN _PINNUM(1, 22)
55+
#define MAX3421_TX_PAD 2 // MOSI = PAD_3, SCK = PAD_1
56+
#define MAX3421_RX_PAD 2 // MISO = PAD_2
57+
58+
#define MAX3421_CS_PIN 21 // D11
59+
60+
#define MAX3421_INTR_PIN 20 // D10
61+
#define MAX3421_INTR_EIC_ID 4 // EIC4
62+
4663
#ifdef __cplusplus
4764
}
4865
#endif

hw/bsp/samd51/family.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -76,12 +76,12 @@ void USB_3_Handler(void) {
7676
// Implementation
7777
//--------------------------------------------------------------------+
7878

79-
#if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421
79+
#if CFG_TUH_ENABLED && CFG_TUH_MAX3421
80+
8081
#define MAX3421_SERCOM TU_XSTRCAT(SERCOM, MAX3421_SERCOM_ID)
8182
#define MAX3421_EIC_Handler TU_XSTRCAT3(EIC_, MAX3421_INTR_EIC_ID, _Handler)
8283

8384
static void max3421_init(void);
84-
8585
#endif
8686

8787
void board_init(void) {
@@ -136,11 +136,14 @@ void board_init(void) {
136136
gpio_set_pin_function(PIN_PA24, PINMUX_PA24H_USB_DM);
137137
gpio_set_pin_function(PIN_PA25, PINMUX_PA25H_USB_DP);
138138

139-
#if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421
139+
#if CFG_TUH_ENABLED && CFG_TUH_MAX3421
140140
max3421_init();
141141
#endif
142142
}
143143

144+
void board_init_after_tusb(void) {
145+
}
146+
144147
//--------------------------------------------------------------------+
145148
// Board porting API
146149
//--------------------------------------------------------------------+
@@ -182,7 +185,7 @@ uint32_t board_millis(void) {
182185
//--------------------------------------------------------------------+
183186
// API: SPI transfer with MAX3421E, must be implemented by application
184187
//--------------------------------------------------------------------+
185-
#if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421
188+
#if CFG_TUH_ENABLED && CFG_TUH_MAX3421
186189

187190
static void max3421_init(void) {
188191
//------------- SPI Init -------------//
@@ -262,7 +265,7 @@ static void max3421_init(void) {
262265

263266
// Enable the SPI module
264267
sercom->SPI.CTRLA.bit.ENABLE = 1;
265-
while (sercom->SPI.SYNCBUSY.bit.ENABLE);
268+
while (sercom->SPI.SYNCBUSY.bit.ENABLE) {}
266269

267270
//------------- External Interrupt -------------//
268271

src/portable/analog/max3421/hcd_max3421.c

Lines changed: 46 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,12 @@ enum {
5454
CPUCTL_ADDR = 16u << 3, // 0x80
5555
PINCTL_ADDR = 17u << 3, // 0x88
5656
REVISION_ADDR = 18u << 3, // 0x90
57+
// 19 is not used
58+
IOPINS1_ADDR = 20u << 3, // 0xA0
59+
IOPINS2_ADDR = 21u << 3, // 0xA8
60+
GPINIRQ_ADDR = 22u << 3, // 0xB0
61+
GPINIEN_ADDR = 23u << 3, // 0xB8
62+
GPINPOL_ADDR = 24u << 3, // 0xC0
5763
HIRQ_ADDR = 25u << 3, // 0xC8
5864
HIEN_ADDR = 26u << 3, // 0xD0
5965
MODE_ADDR = 27u << 3, // 0xD8
@@ -207,7 +213,9 @@ typedef struct {
207213
static max3421_data_t _hcd_data;
208214

209215
//--------------------------------------------------------------------+
210-
// API: SPI transfer with MAX3421E, must be implemented by application
216+
// API: SPI transfer with MAX3421E
217+
// - spi_cs_api(), spi_xfer_api(), int_api(): must be implemented by application
218+
// - reg_read(), reg_write(): is implemented by this driver, can be used by application
211219
//--------------------------------------------------------------------+
212220

213221
// API to control MAX3421 SPI CS
@@ -220,11 +228,18 @@ extern bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const* tx_buf, uint
220228
// API to enable/disable MAX3421 INTR pin interrupt
221229
extern void tuh_max3421_int_api(uint8_t rhport, bool enabled);
222230

231+
// API to read MAX3421's register. Implemented by TinyUSB
232+
uint8_t tuh_max3421_reg_read(uint8_t rhport, uint8_t reg, bool in_isr);
233+
234+
// API to write MAX3421's register. Implemented by TinyUSB
235+
bool tuh_max3421_reg_write(uint8_t rhport, uint8_t reg, uint8_t data, bool in_isr);
236+
223237
//--------------------------------------------------------------------+
224-
// SPI Helper
238+
// SPI Commands and Helper
225239
//--------------------------------------------------------------------+
226-
static void handle_connect_irq(uint8_t rhport, bool in_isr);
227-
static inline void hirq_write(uint8_t rhport, uint8_t data, bool in_isr);
240+
241+
#define reg_read tuh_max3421_reg_read
242+
#define reg_write tuh_max3421_reg_write
228243

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

251-
static void fifo_write(uint8_t rhport, uint8_t reg, uint8_t const * buffer, uint16_t len, bool in_isr) {
252-
uint8_t hirq;
253-
reg |= CMDBYTE_WRITE;
266+
uint8_t tuh_max3421_reg_read(uint8_t rhport, uint8_t reg, bool in_isr) {
267+
uint8_t tx_buf[2] = {reg, 0};
268+
uint8_t rx_buf[2] = {0, 0};
254269

255270
max3421_spi_lock(rhport, in_isr);
256-
257-
tuh_max3421_spi_xfer_api(rhport, &reg, &hirq, 1);
258-
_hcd_data.hirq = hirq;
259-
tuh_max3421_spi_xfer_api(rhport, buffer, NULL, len);
260-
271+
bool ret = tuh_max3421_spi_xfer_api(rhport, tx_buf, rx_buf, 2);
261272
max3421_spi_unlock(rhport, in_isr);
262273

274+
_hcd_data.hirq = rx_buf[0];
275+
return ret ? rx_buf[1] : 0;
263276
}
264277

265-
static void fifo_read(uint8_t rhport, uint8_t * buffer, uint16_t len, bool in_isr) {
266-
uint8_t hirq;
267-
uint8_t const reg = RCVVFIFO_ADDR;
278+
bool tuh_max3421_reg_write(uint8_t rhport, uint8_t reg, uint8_t data, bool in_isr) {
279+
uint8_t tx_buf[2] = {reg | CMDBYTE_WRITE, data};
280+
uint8_t rx_buf[2] = {0, 0};
268281

269282
max3421_spi_lock(rhport, in_isr);
283+
bool ret = tuh_max3421_spi_xfer_api(rhport, tx_buf, rx_buf, 2);
284+
max3421_spi_unlock(rhport, in_isr);
270285

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

275-
max3421_spi_unlock(rhport, in_isr);
289+
return ret;
276290
}
277291

278-
static void reg_write(uint8_t rhport, uint8_t reg, uint8_t data, bool in_isr) {
279-
uint8_t tx_buf[2] = {reg | CMDBYTE_WRITE, data};
280-
uint8_t rx_buf[2] = {0, 0};
292+
static void fifo_write(uint8_t rhport, uint8_t reg, uint8_t const * buffer, uint16_t len, bool in_isr) {
293+
uint8_t hirq;
294+
reg |= CMDBYTE_WRITE;
281295

282296
max3421_spi_lock(rhport, in_isr);
283297

284-
tuh_max3421_spi_xfer_api(rhport, tx_buf, rx_buf, 2);
298+
tuh_max3421_spi_xfer_api(rhport, &reg, &hirq, 1);
299+
_hcd_data.hirq = hirq;
300+
tuh_max3421_spi_xfer_api(rhport, buffer, NULL, len);
285301

286302
max3421_spi_unlock(rhport, in_isr);
287303

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

292-
static uint8_t reg_read(uint8_t rhport, uint8_t reg, bool in_isr) {
293-
uint8_t tx_buf[2] = {reg, 0};
294-
uint8_t rx_buf[2] = {0, 0};
306+
static void fifo_read(uint8_t rhport, uint8_t * buffer, uint16_t len, bool in_isr) {
307+
uint8_t hirq;
308+
uint8_t const reg = RCVVFIFO_ADDR;
295309

296310
max3421_spi_lock(rhport, in_isr);
297311

298-
bool ret = tuh_max3421_spi_xfer_api(rhport, tx_buf, rx_buf, 2);
312+
tuh_max3421_spi_xfer_api(rhport, &reg, &hirq, 1);
313+
_hcd_data.hirq = hirq;
314+
tuh_max3421_spi_xfer_api(rhport, NULL, buffer, len);
299315

300316
max3421_spi_unlock(rhport, in_isr);
301-
302-
_hcd_data.hirq = rx_buf[0];
303-
return ret ? rx_buf[1] : 0;
304317
}
305318

319+
//------------- register write helper -------------//
306320
static inline void hirq_write(uint8_t rhport, uint8_t data, bool in_isr) {
307321
reg_write(rhport, HIRQ_ADDR, data, in_isr);
308322
// HIRQ write 1 is clear

0 commit comments

Comments
 (0)