Merge pull request #2276 from hathach/more-esp32-max3421

More max3421
This commit is contained in:
Ha Thach 2023-10-05 17:53:13 +07:00 committed by GitHub
commit 513ab37ec6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 112 additions and 76 deletions

18
.idea/cmake.xml generated
View File

@ -9,7 +9,7 @@
</envs> </envs>
</ADDITIONAL_GENERATION_ENVIRONMENT> </ADDITIONAL_GENERATION_ENVIRONMENT>
</configuration> </configuration>
<configuration PROFILE_NAME="kaluga" ENABLED="true" TOOLCHAIN_NAME="ESP-IDF" GENERATION_OPTIONS="-DBOARD=espressif_kaluga_1 -DMAX3421_HOST=1 -DLOG=2"> <configuration PROFILE_NAME="kaluga" ENABLED="false" TOOLCHAIN_NAME="ESP-IDF" GENERATION_OPTIONS="-DBOARD=espressif_kaluga_1 -DMAX3421_HOST=1 -DLOG=2">
<ADDITIONAL_GENERATION_ENVIRONMENT> <ADDITIONAL_GENERATION_ENVIRONMENT>
<envs> <envs>
<env name="ESPBAUD" value="1500000" /> <env name="ESPBAUD" value="1500000" />
@ -54,16 +54,16 @@
<configuration PROFILE_NAME="ra6m5 PORT0" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=ra6m5_ek -DLOG=3 -DLOGGER=RTT -DTRACE_ETM=1 -DPORT=0" /> <configuration PROFILE_NAME="ra6m5 PORT0" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=ra6m5_ek -DLOG=3 -DLOGGER=RTT -DTRACE_ETM=1 -DPORT=0" />
<configuration PROFILE_NAME="uno_r4" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=uno_r4 -DLOG=4 -DLOGGER=RTT" /> <configuration PROFILE_NAME="uno_r4" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=uno_r4 -DLOG=4 -DLOGGER=RTT" />
<configuration PROFILE_NAME="portenta_c33" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=portenta_c33 -DLOG=3" /> <configuration PROFILE_NAME="portenta_c33" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=portenta_c33 -DLOG=3" />
<configuration PROFILE_NAME="metro_m4_express" ENABLED="true" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=metro_m4_express -DLOG=3 -DLOGGER=RTT -DMAX3421_HOST=1" /> <configuration PROFILE_NAME="metro_m4_express" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=metro_m4_express -DLOG=3 -DLOGGER=RTT -DMAX3421_HOST=1" />
<configuration PROFILE_NAME="metro_m0_express" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=metro_m0_express -DLOG=3 -DLOGGER=RTT -DMAX3421_HOST=1" /> <configuration PROFILE_NAME="metro_m0_express" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=metro_m0_express -DLOG=3 -DLOGGER=RTT -DMAX3421_HOST=1" />
<configuration PROFILE_NAME="stm32u5" ENABLED="true" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=stm32u575eval" /> <configuration PROFILE_NAME="stm32u5" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=stm32u575eval" />
<configuration PROFILE_NAME="metro esp32s2" ENABLED="false" TOOLCHAIN_NAME="ESP-IDF" GENERATION_OPTIONS="-DBOARD=adafruit_metro_esp32s2 -DMAX3421_HOST=1 -DLOG=2"> <configuration PROFILE_NAME="metro esp32s2" ENABLED="false" TOOLCHAIN_NAME="ESP-IDF" GENERATION_OPTIONS="-DBOARD=adafruit_metro_esp32s2 -DMAX3421_HOST=1 -DLOG=2">
<ADDITIONAL_GENERATION_ENVIRONMENT> <ADDITIONAL_GENERATION_ENVIRONMENT>
<envs> <envs>
<env name="ESPBAUD" value="1500000" /> <env name="ESPBAUD" value="1500000" />
</envs> </envs>
</ADDITIONAL_GENERATION_ENVIRONMENT> </ADDITIONAL_GENERATION_ENVIRONMENT>
</configuration> </configuration>
</configurations> </configurations>
</component> </component>
</project> </project>

View File

@ -38,22 +38,31 @@
#if ESP_IDF_VERSION_MAJOR > 4 #if ESP_IDF_VERSION_MAJOR > 4
#include "esp_private/periph_ctrl.h" #include "esp_private/periph_ctrl.h"
#else #else
#include "driver/periph_ctrl.h" #include "driver/periph_ctrl.h"
#endif #endif
// Note; current code use UART0 can cause device to reset while monitoring
#define USE_UART 0
#define UART_ID UART_NUM_0 #define UART_ID UART_NUM_0
#ifdef NEOPIXEL_PIN #ifdef NEOPIXEL_PIN
#include "led_strip.h" #include "led_strip.h"
static led_strip_t *strip;
static led_strip_t* strip;
#endif #endif
#if CFG_TUH_ENABLED && CFG_TUH_MAX3421 #if CFG_TUH_ENABLED && CFG_TUH_MAX3421
#include "driver/spi_master.h" #include "driver/spi_master.h"
static void max3421_init(void); static void max3421_init(void);
#endif #endif
static void configure_pins(usb_hal_context_t *usb); static void configure_pins(usb_hal_context_t* usb);
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
// Implementation // Implementation
@ -61,6 +70,7 @@ static void configure_pins(usb_hal_context_t *usb);
// Initialize on-board peripherals : led, button, uart and USB // Initialize on-board peripherals : led, button, uart and USB
void board_init(void) { void board_init(void) {
#if USE_UART
// uart init // uart init
uart_config_t uart_config = { uart_config_t uart_config = {
.baud_rate = 115200, .baud_rate = 115200,
@ -71,6 +81,7 @@ void board_init(void) {
}; };
uart_driver_install(UART_ID, 1024, 0, 0, NULL, 0); uart_driver_install(UART_ID, 1024, 0, 0, NULL, 0);
uart_param_config(UART_ID, &uart_config); uart_param_config(UART_ID, &uart_config);
#endif
#ifdef NEOPIXEL_PIN #ifdef NEOPIXEL_PIN
#ifdef NEOPIXEL_POWER_PIN #ifdef NEOPIXEL_POWER_PIN
@ -111,11 +122,11 @@ void board_init(void) {
#endif #endif
} }
static void configure_pins(usb_hal_context_t *usb) { static void configure_pins(usb_hal_context_t* usb) {
/* usb_periph_iopins currently configures USB_OTG as USB Device. /* usb_periph_iopins currently configures USB_OTG as USB Device.
* Introduce additional parameters in usb_hal_context_t when adding support * Introduce additional parameters in usb_hal_context_t when adding support
* for USB Host. */ * for USB Host. */
for (const usb_iopin_dsc_t *iopin = usb_periph_iopins; iopin->pin != -1; ++iopin) { for (const usb_iopin_dsc_t* iopin = usb_periph_iopins; iopin->pin != -1; ++iopin) {
if ((usb->use_external_phy) || (iopin->ext_phy_only == 0)) { if ((usb->use_external_phy) || (iopin->ext_phy_only == 0)) {
esp_rom_gpio_pad_select_gpio(iopin->pin); esp_rom_gpio_pad_select_gpio(iopin->pin);
if (iopin->is_output) { if (iopin->is_output) {
@ -156,20 +167,24 @@ uint32_t board_button_read(void) {
} }
// Get characters from UART // Get characters from UART
int board_uart_read(uint8_t *buf, int len) { int board_uart_read(uint8_t* buf, int len) {
#if USE_UART
return uart_read_bytes(UART_ID, buf, len, 0); return uart_read_bytes(UART_ID, buf, len, 0);
#else
return -1;
#endif
} }
// Send characters to UART // Send characters to UART
int board_uart_write(void const *buf, int len) { int board_uart_write(void const* buf, int len) {
(void) buf; (void) buf;
(void) len; (void) len;
return 0; return 0;
} }
int board_getchar(void) { int board_getchar(void) {
char c; uint8_t c = 0;
return (uart_read_bytes(UART_ID, &c, 1, 0) > 0) ? (int) c : (-1); return board_uart_read(&c, 1) > 0 ? (int) c : (-1);
} }
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
@ -208,7 +223,7 @@ static void max3421_init(void) {
gpio_set_level(MAX3421_CS_PIN, 1); gpio_set_level(MAX3421_CS_PIN, 1);
// SPI // SPI
spi_bus_config_t buscfg={ spi_bus_config_t buscfg = {
.miso_io_num = MAX3421_MISO_PIN, .miso_io_num = MAX3421_MISO_PIN,
.mosi_io_num = MAX3421_MOSI_PIN, .mosi_io_num = MAX3421_MOSI_PIN,
.sclk_io_num = MAX3421_SCK_PIN, .sclk_io_num = MAX3421_SCK_PIN,
@ -220,15 +235,15 @@ static void max3421_init(void) {
.data7_io_num = -1, .data7_io_num = -1,
.max_transfer_sz = 1024 .max_transfer_sz = 1024
}; };
ESP_ERROR_CHECK( spi_bus_initialize(MAX3421_SPI_HOST, &buscfg, SPI_DMA_CH_AUTO) ); ESP_ERROR_CHECK(spi_bus_initialize(MAX3421_SPI_HOST, &buscfg, SPI_DMA_CH_AUTO));
spi_device_interface_config_t max3421_cfg = { spi_device_interface_config_t max3421_cfg = {
.mode = 0, .mode = 0,
.clock_speed_hz = 4000000, // 26000000 .clock_speed_hz = 26000000,
.spics_io_num = -1, // manual control CS .spics_io_num = -1, // manual control CS
.queue_size = 1 .queue_size = 1
}; };
ESP_ERROR_CHECK( spi_bus_add_device(MAX3421_SPI_HOST, &max3421_cfg, &max3421_spi) ); ESP_ERROR_CHECK(spi_bus_add_device(MAX3421_SPI_HOST, &max3421_cfg, &max3421_spi));
// debug // debug
gpio_set_direction(13, GPIO_MODE_OUTPUT); gpio_set_direction(13, GPIO_MODE_OUTPUT);
@ -236,7 +251,7 @@ static void max3421_init(void) {
// Interrupt pin // Interrupt pin
max3421_intr_sem = xSemaphoreCreateBinary(); max3421_intr_sem = xSemaphoreCreateBinary();
xTaskCreate(max3421_intr_task, "max3421 intr", 2048, NULL, configMAX_PRIORITIES-2, NULL); xTaskCreate(max3421_intr_task, "max3421 intr", 2048, NULL, configMAX_PRIORITIES - 2, NULL);
gpio_set_direction(MAX3421_INTR_PIN, GPIO_MODE_INPUT); gpio_set_direction(MAX3421_INTR_PIN, GPIO_MODE_INPUT);
gpio_set_intr_type(MAX3421_INTR_PIN, GPIO_INTR_NEGEDGE); gpio_set_intr_type(MAX3421_INTR_PIN, GPIO_INTR_NEGEDGE);
@ -259,18 +274,20 @@ void tuh_max3421_spi_cs_api(uint8_t rhport, bool active) {
gpio_set_level(MAX3421_CS_PIN, active ? 0 : 1); gpio_set_level(MAX3421_CS_PIN, active ? 0 : 1);
} }
bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const *tx_buf, size_t tx_len, uint8_t *rx_buf, size_t rx_len) { bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const* tx_buf, uint8_t* rx_buf, size_t xfer_bytes) {
(void) rhport; (void) rhport;
if (tx_len == 0) { if (tx_buf == NULL) {
// fifo read, transmit rx_buf as dummy // fifo read, transmit rx_buf as dummy
tx_buf = rx_buf; tx_buf = rx_buf;
tx_len = rx_len;
} }
// length in bits
size_t const len_bits = xfer_bytes << 3;
spi_transaction_t xact = { spi_transaction_t xact = {
.length = tx_len << 3, // length in bits .length = len_bits,
.rxlength = rx_len << 3, // length in bits .rxlength = rx_buf ? len_bits : 0,
.tx_buffer = tx_buf, .tx_buffer = tx_buf,
.rx_buffer = rx_buf .rx_buffer = rx_buf
}; };

View File

@ -1,6 +1,6 @@
set(MCU_VARIANT nrf52840) set(MCU_VARIANT nrf52840)
#set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/../../linker/nrf52840_s140_v6.ld) set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/../../linker/nrf52840_s140_v6.ld)
set(LD_FILE_GNU ${NRFX_DIR}/mdk/nrf52840_xxaa.ld) #set(LD_FILE_GNU ${NRFX_DIR}/mdk/nrf52840_xxaa.ld)
# enable max3421 host driver for this board # enable max3421 host driver for this board
set(MAX3421_HOST 1) set(MAX3421_HOST 1)

View File

@ -49,8 +49,8 @@
#define MAX3421_SCK_PIN 14 #define MAX3421_SCK_PIN 14
#define MAX3421_MOSI_PIN 13 #define MAX3421_MOSI_PIN 13
#define MAX3421_MISO_PIN 15 #define MAX3421_MISO_PIN 15
#define MAX3421_CS_PIN 27 #define MAX3421_CS_PIN 27 // D10
#define MAX3421_INTR_PIN 26 #define MAX3421_INTR_PIN 26 // D9
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -95,7 +95,9 @@ TU_ATTR_UNUSED static void power_event_handler(nrfx_power_usb_evt_t event) {
//------------- Host using MAX2341E -------------// //------------- Host using MAX2341E -------------//
#if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 #if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421
static void max3421_init(void); static void max3421_init(void);
static nrfx_spim_t _spi = NRFX_SPIM_INSTANCE(1); static nrfx_spim_t _spi = NRFX_SPIM_INSTANCE(1);
#endif #endif
@ -203,15 +205,15 @@ uint32_t board_button_read(void) {
return BUTTON_STATE_ACTIVE == nrf_gpio_pin_read(BUTTON_PIN); return BUTTON_STATE_ACTIVE == nrf_gpio_pin_read(BUTTON_PIN);
} }
int board_uart_read(uint8_t *buf, int len) { int board_uart_read(uint8_t* buf, int len) {
(void) buf; (void) buf;
(void) len; (void) len;
return 0; return 0;
// return NRFX_SUCCESS == nrfx_uart_rx(&_uart_id, buf, (size_t) len) ? len : 0; // return NRFX_SUCCESS == nrfx_uart_rx(&_uart_id, buf, (size_t) len) ? len : 0;
} }
int board_uart_write(void const *buf, int len) { int board_uart_write(void const* buf, int len) {
return (NRFX_SUCCESS == nrfx_uarte_tx(&_uart_id, (uint8_t const *) buf, (size_t) len)) ? len : 0; return (NRFX_SUCCESS == nrfx_uarte_tx(&_uart_id, (uint8_t const*) buf, (size_t) len)) ? len : 0;
} }
#if CFG_TUSB_OS == OPT_OS_NONE #if CFG_TUSB_OS == OPT_OS_NONE
@ -323,6 +325,7 @@ static void max3421_init(void) {
nrfx_gpiote_trigger_enable(MAX3421_INTR_PIN, true); nrfx_gpiote_trigger_enable(MAX3421_INTR_PIN, true);
} }
// API to enable/disable MAX3421 INTR pin interrupt
void tuh_max3421_int_api(uint8_t rhport, bool enabled) { void tuh_max3421_int_api(uint8_t rhport, bool enabled) {
(void) rhport; (void) rhport;
@ -335,22 +338,25 @@ void tuh_max3421_int_api(uint8_t rhport, bool enabled) {
} }
} }
// API to control MAX3421 SPI CS
void tuh_max3421_spi_cs_api(uint8_t rhport, bool active) { void tuh_max3421_spi_cs_api(uint8_t rhport, bool active) {
(void) rhport; (void) rhport;
nrf_gpio_pin_write(MAX3421_CS_PIN, active ? 0 : 1); nrf_gpio_pin_write(MAX3421_CS_PIN, active ? 0 : 1);
} }
bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const *tx_buf, size_t tx_len, uint8_t *rx_buf, size_t rx_len) { // API to transfer data with MAX3421 SPI
// Either tx_buf or rx_buf can be NULL, which means transfer is write or read only
bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const* tx_buf, uint8_t* rx_buf, size_t xfer_bytes) {
(void) rhport; (void) rhport;
nrfx_spim_xfer_desc_t xfer = { nrfx_spim_xfer_desc_t xfer = {
.p_tx_buffer = tx_buf, .p_tx_buffer = tx_buf,
.tx_length = tx_len, .tx_length = tx_buf ? xfer_bytes : 0,
.p_rx_buffer = rx_buf, .p_rx_buffer = rx_buf,
.rx_length = rx_len, .rx_length = rx_buf ? xfer_bytes : 0,
}; };
return (nrfx_spim_xfer(&_spi, &xfer, 0) == NRFX_SUCCESS); return nrfx_spim_xfer(&_spi, &xfer, 0) == NRFX_SUCCESS;
} }
#endif #endif

View File

@ -72,6 +72,7 @@ static void uart_init(void);
#define MAX3421_SERCOM TU_XSTRCAT(SERCOM, MAX3421_SERCOM_ID) #define MAX3421_SERCOM TU_XSTRCAT(SERCOM, MAX3421_SERCOM_ID)
static void max3421_init(void); static void max3421_init(void);
#endif #endif
void board_init(void) { void board_init(void) {
@ -237,13 +238,13 @@ int board_uart_write(void const * buf, int len)
static void uart_init(void) { static void uart_init(void) {
} }
int board_uart_read(uint8_t *buf, int len) { int board_uart_read(uint8_t* buf, int len) {
(void) buf; (void) buf;
(void) len; (void) len;
return 0; return 0;
} }
int board_uart_write(void const *buf, int len) { int board_uart_write(void const* buf, int len) {
(void) buf; (void) buf;
(void) len; (void) len;
return 0; return 0;
@ -261,6 +262,7 @@ void SysTick_Handler(void) {
uint32_t board_millis(void) { uint32_t board_millis(void) {
return system_ticks; return system_ticks;
} }
#endif #endif
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
@ -278,8 +280,8 @@ static void max3421_init(void) {
// Configure GCLK for SERCOM // Configure GCLK for SERCOM
// GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID_SERCOM4_CORE | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_CLKEN; // GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID_SERCOM4_CORE | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_CLKEN;
GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(GCLK_CLKCTRL_ID_SERCOM0_CORE_Val+MAX3421_SERCOM_ID) | GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(GCLK_CLKCTRL_ID_SERCOM0_CORE_Val + MAX3421_SERCOM_ID) |
GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_CLKEN; GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_CLKEN;
while (GCLK->STATUS.bit.SYNCBUSY); while (GCLK->STATUS.bit.SYNCBUSY);
Sercom* sercom = MAX3421_SERCOM; Sercom* sercom = MAX3421_SERCOM;
@ -293,7 +295,7 @@ static void max3421_init(void) {
// Set up SPI in master mode, MSB first, SPI mode 0 // Set up SPI in master mode, MSB first, SPI mode 0
sercom->SPI.CTRLA.reg = SERCOM_SPI_CTRLA_DOPO(MAX3421_TX_PAD) | SERCOM_SPI_CTRLA_DIPO(MAX3421_RX_PAD) | sercom->SPI.CTRLA.reg = SERCOM_SPI_CTRLA_DOPO(MAX3421_TX_PAD) | SERCOM_SPI_CTRLA_DIPO(MAX3421_RX_PAD) |
SERCOM_SPI_CTRLA_MODE(3); SERCOM_SPI_CTRLA_MODE(3);
sercom->SPI.CTRLB.reg = SERCOM_SPI_CTRLB_CHSIZE(0) | SERCOM_SPI_CTRLB_RXEN; sercom->SPI.CTRLB.reg = SERCOM_SPI_CTRLB_CHSIZE(0) | SERCOM_SPI_CTRLB_RXEN;
while (sercom->SPI.SYNCBUSY.bit.CTRLB == 1); while (sercom->SPI.SYNCBUSY.bit.CTRLB == 1);
@ -366,6 +368,7 @@ void EIC_Handler(void) {
tuh_int_handler(1, true); tuh_int_handler(1, true);
} }
// API to enable/disable MAX3421 INTR pin interrupt
void tuh_max3421_int_api(uint8_t rhport, bool enabled) { void tuh_max3421_int_api(uint8_t rhport, bool enabled) {
(void) rhport; (void) rhport;
@ -376,24 +379,26 @@ void tuh_max3421_int_api(uint8_t rhport, bool enabled) {
} }
} }
// API to control MAX3421 SPI CS
void tuh_max3421_spi_cs_api(uint8_t rhport, bool active) { void tuh_max3421_spi_cs_api(uint8_t rhport, bool active) {
(void) rhport; (void) rhport;
gpio_set_pin_level(MAX3421_CS_PIN, active ? 0 : 1); gpio_set_pin_level(MAX3421_CS_PIN, active ? 0 : 1);
} }
bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const *tx_buf, size_t tx_len, uint8_t *rx_buf, size_t rx_len) { // API to transfer data with MAX3421 SPI
// Either tx_buf or rx_buf can be NULL, which means transfer is write or read only
bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const* tx_buf, uint8_t* rx_buf, size_t xfer_bytes) {
(void) rhport; (void) rhport;
Sercom* sercom = MAX3421_SERCOM; Sercom* sercom = MAX3421_SERCOM;
size_t count = 0; for (size_t count = 0; count < xfer_bytes; count++) {
while (count < tx_len || count < rx_len) {
// Wait for the transmit buffer to be empty // Wait for the transmit buffer to be empty
while (!sercom->SPI.INTFLAG.bit.DRE); while (!sercom->SPI.INTFLAG.bit.DRE);
// Write data to be transmitted // Write data to be transmitted
uint8_t data = 0x00; uint8_t data = 0x00;
if (count < tx_len) { if (tx_buf) {
data = tx_buf[count]; data = tx_buf[count];
} }
@ -404,11 +409,9 @@ bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const *tx_buf, size_t tx_l
// Read received data // Read received data
data = (uint8_t) sercom->SPI.DATA.reg; data = (uint8_t) sercom->SPI.DATA.reg;
if (count < rx_len) { if (rx_buf) {
rx_buf[count] = data; rx_buf[count] = data;
} }
count++;
} }
// wait for bus idle and clear flags // wait for bus idle and clear flags

View File

@ -81,6 +81,7 @@ void USB_3_Handler(void) {
#define MAX3421_EIC_Handler TU_XSTRCAT3(EIC_, MAX3421_INTR_EIC_ID, _Handler) #define MAX3421_EIC_Handler TU_XSTRCAT3(EIC_, MAX3421_INTR_EIC_ID, _Handler)
static void max3421_init(void); static void max3421_init(void);
#endif #endif
void board_init(void) { void board_init(void) {
@ -153,13 +154,13 @@ uint32_t board_button_read(void) {
return gpio_get_pin_level(BUTTON_PIN) ? 0 : 1; return gpio_get_pin_level(BUTTON_PIN) ? 0 : 1;
} }
int board_uart_read(uint8_t *buf, int len) { int board_uart_read(uint8_t* buf, int len) {
(void) buf; (void) buf;
(void) len; (void) len;
return 0; return 0;
} }
int board_uart_write(void const *buf, int len) { int board_uart_write(void const* buf, int len) {
(void) buf; (void) buf;
(void) len; (void) len;
return 0; return 0;
@ -175,6 +176,7 @@ void SysTick_Handler(void) {
uint32_t board_millis(void) { uint32_t board_millis(void) {
return system_ticks; return system_ticks;
} }
#endif #endif
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
@ -189,7 +191,7 @@ static void max3421_init(void) {
uint32_t const baudrate = 12000000u; uint32_t const baudrate = 12000000u;
struct { struct {
volatile uint32_t *mck_apb; volatile uint32_t* mck_apb;
uint32_t mask; uint32_t mask;
uint8_t gclk_id_core; uint8_t gclk_id_core;
uint8_t gclk_id_slow; uint8_t gclk_id_slow;
@ -214,8 +216,10 @@ static void max3421_init(void) {
*sercom_clock[MAX3421_SERCOM_ID].mck_apb |= sercom_clock[MAX3421_SERCOM_ID].mask; *sercom_clock[MAX3421_SERCOM_ID].mck_apb |= sercom_clock[MAX3421_SERCOM_ID].mask;
// Configure GCLK for SERCOM // Configure GCLK for SERCOM
GCLK->PCHCTRL[sercom_clock[MAX3421_SERCOM_ID].gclk_id_core].reg = GCLK_PCHCTRL_GEN_GCLK0_Val | (1 << GCLK_PCHCTRL_CHEN_Pos); GCLK->PCHCTRL[sercom_clock[MAX3421_SERCOM_ID].gclk_id_core].reg =
GCLK->PCHCTRL[sercom_clock[MAX3421_SERCOM_ID].gclk_id_slow].reg = GCLK_PCHCTRL_GEN_GCLK3_Val | (1 << GCLK_PCHCTRL_CHEN_Pos); GCLK_PCHCTRL_GEN_GCLK0_Val | (1 << GCLK_PCHCTRL_CHEN_Pos);
GCLK->PCHCTRL[sercom_clock[MAX3421_SERCOM_ID].gclk_id_slow].reg =
GCLK_PCHCTRL_GEN_GCLK3_Val | (1 << GCLK_PCHCTRL_CHEN_Pos);
// Disable the SPI module // Disable the SPI module
sercom->SPI.CTRLA.bit.ENABLE = 0; sercom->SPI.CTRLA.bit.ENABLE = 0;
@ -226,7 +230,7 @@ static void max3421_init(void) {
// Set up SPI in master mode, MSB first, SPI mode 0 // Set up SPI in master mode, MSB first, SPI mode 0
sercom->SPI.CTRLA.reg = SERCOM_SPI_CTRLA_DOPO(MAX3421_TX_PAD) | SERCOM_SPI_CTRLA_DIPO(MAX3421_RX_PAD) | sercom->SPI.CTRLA.reg = SERCOM_SPI_CTRLA_DOPO(MAX3421_TX_PAD) | SERCOM_SPI_CTRLA_DIPO(MAX3421_RX_PAD) |
SERCOM_SPI_CTRLA_MODE(3); SERCOM_SPI_CTRLA_MODE(3);
sercom->SPI.CTRLB.reg = SERCOM_SPI_CTRLB_CHSIZE(0) | SERCOM_SPI_CTRLB_RXEN; sercom->SPI.CTRLB.reg = SERCOM_SPI_CTRLB_CHSIZE(0) | SERCOM_SPI_CTRLB_RXEN;
while (sercom->SPI.SYNCBUSY.bit.CTRLB == 1); while (sercom->SPI.SYNCBUSY.bit.CTRLB == 1);
@ -278,9 +282,9 @@ static void max3421_init(void) {
while (EIC->SYNCBUSY.bit.ENABLE); while (EIC->SYNCBUSY.bit.ENABLE);
// Configure EIC to trigger on falling edge // Configure EIC to trigger on falling edge
volatile uint32_t * eic_config; volatile uint32_t* eic_config;
uint8_t sense_shift; uint8_t sense_shift;
if ( MAX3421_INTR_EIC_ID < 8 ) { if (MAX3421_INTR_EIC_ID < 8) {
eic_config = &EIC->CONFIG[0].reg; eic_config = &EIC->CONFIG[0].reg;
sense_shift = MAX3421_INTR_EIC_ID * 4; sense_shift = MAX3421_INTR_EIC_ID * 4;
} else { } else {
@ -312,6 +316,7 @@ void MAX3421_EIC_Handler(void) {
tuh_int_handler(1, true); tuh_int_handler(1, true);
} }
// API to enable/disable MAX3421 INTR pin interrupt
void tuh_max3421_int_api(uint8_t rhport, bool enabled) { void tuh_max3421_int_api(uint8_t rhport, bool enabled) {
(void) rhport; (void) rhport;
@ -323,24 +328,26 @@ void tuh_max3421_int_api(uint8_t rhport, bool enabled) {
} }
} }
// API to control MAX3421 SPI CS
void tuh_max3421_spi_cs_api(uint8_t rhport, bool active) { void tuh_max3421_spi_cs_api(uint8_t rhport, bool active) {
(void) rhport; (void) rhport;
gpio_set_pin_level(MAX3421_CS_PIN, active ? 0 : 1); gpio_set_pin_level(MAX3421_CS_PIN, active ? 0 : 1);
} }
bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const *tx_buf, size_t tx_len, uint8_t *rx_buf, size_t rx_len) { // API to transfer data with MAX3421 SPI
// Either tx_buf or rx_buf can be NULL, which means transfer is write or read only
bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const* tx_buf, uint8_t* rx_buf, size_t xfer_bytes) {
(void) rhport; (void) rhport;
Sercom* sercom = MAX3421_SERCOM; Sercom* sercom = MAX3421_SERCOM;
size_t count = 0; for (size_t count = 0; count < xfer_bytes; count++) {
while (count < tx_len || count < rx_len) {
// Wait for the transmit buffer to be empty // Wait for the transmit buffer to be empty
while (!sercom->SPI.INTFLAG.bit.DRE); while (!sercom->SPI.INTFLAG.bit.DRE);
// Write data to be transmitted // Write data to be transmitted
uint8_t data = 0x00; uint8_t data = 0x00;
if (count < tx_len) { if (tx_buf) {
data = tx_buf[count]; data = tx_buf[count];
} }
@ -351,11 +358,9 @@ bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const *tx_buf, size_t tx_l
// Read received data // Read received data
data = (uint8_t) sercom->SPI.DATA.reg; data = (uint8_t) sercom->SPI.DATA.reg;
if (count < rx_len) { if (rx_buf) {
rx_buf[count] = data; rx_buf[count] = data;
} }
count++;
} }
// wait for bus idle and clear flags // wait for bus idle and clear flags

View File

@ -210,16 +210,21 @@ static max3421_data_t _hcd_data;
// API: SPI transfer with MAX3421E, must be implemented by application // API: SPI transfer with MAX3421E, must be implemented by application
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
void tuh_max3421_spi_cs_api(uint8_t rhport, bool active); // API to control MAX3421 SPI CS
bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const * tx_buf, size_t tx_len, uint8_t * rx_buf, size_t rx_len); extern void tuh_max3421_spi_cs_api(uint8_t rhport, bool active);
void tuh_max3421_int_api(uint8_t rhport, bool enabled);
static void handle_connect_irq(uint8_t rhport, bool in_isr); // API to transfer data with MAX3421 SPI
static inline void hirq_write(uint8_t rhport, uint8_t data, bool in_isr); // Either tx_buf or rx_buf can be NULL, which means transfer is write or read only
extern bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const* tx_buf, uint8_t* rx_buf, size_t xfer_bytes);
// API to enable/disable MAX3421 INTR pin interrupt
extern void tuh_max3421_int_api(uint8_t rhport, bool enabled);
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
// SPI Helper // SPI 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);
static void max3421_spi_lock(uint8_t rhport, bool in_isr) { static void max3421_spi_lock(uint8_t rhport, bool in_isr) {
// disable interrupt and mutex lock (for pre-emptive RTOS) if not in_isr // disable interrupt and mutex lock (for pre-emptive RTOS) if not in_isr
@ -249,9 +254,9 @@ static void fifo_write(uint8_t rhport, uint8_t reg, uint8_t const * buffer, uint
max3421_spi_lock(rhport, in_isr); max3421_spi_lock(rhport, in_isr);
tuh_max3421_spi_xfer_api(rhport, &reg, 1, &hirq, 1); tuh_max3421_spi_xfer_api(rhport, &reg, &hirq, 1);
_hcd_data.hirq = hirq; _hcd_data.hirq = hirq;
tuh_max3421_spi_xfer_api(rhport, buffer, len, NULL, 0); tuh_max3421_spi_xfer_api(rhport, buffer, NULL, len);
max3421_spi_unlock(rhport, in_isr); max3421_spi_unlock(rhport, in_isr);
@ -263,9 +268,9 @@ static void fifo_read(uint8_t rhport, uint8_t * buffer, uint16_t len, bool in_is
max3421_spi_lock(rhport, in_isr); max3421_spi_lock(rhport, in_isr);
tuh_max3421_spi_xfer_api(rhport, &reg, 1, &hirq, 1); tuh_max3421_spi_xfer_api(rhport, &reg, &hirq, 1);
_hcd_data.hirq = hirq; _hcd_data.hirq = hirq;
tuh_max3421_spi_xfer_api(rhport, NULL, 0, buffer, len); tuh_max3421_spi_xfer_api(rhport, NULL, buffer, len);
max3421_spi_unlock(rhport, in_isr); max3421_spi_unlock(rhport, in_isr);
} }
@ -276,7 +281,7 @@ static void reg_write(uint8_t rhport, uint8_t reg, uint8_t data, bool in_isr) {
max3421_spi_lock(rhport, in_isr); max3421_spi_lock(rhport, in_isr);
tuh_max3421_spi_xfer_api(rhport, tx_buf, 2, rx_buf, 2); tuh_max3421_spi_xfer_api(rhport, tx_buf, rx_buf, 2);
max3421_spi_unlock(rhport, in_isr); max3421_spi_unlock(rhport, in_isr);
@ -290,7 +295,7 @@ static uint8_t reg_read(uint8_t rhport, uint8_t reg, bool in_isr) {
max3421_spi_lock(rhport, in_isr); max3421_spi_lock(rhport, in_isr);
bool ret = tuh_max3421_spi_xfer_api(rhport, tx_buf, 2, rx_buf, 2); bool ret = tuh_max3421_spi_xfer_api(rhport, tx_buf, rx_buf, 2);
max3421_spi_unlock(rhport, in_isr); max3421_spi_unlock(rhport, in_isr);