From 993fc262026fbf46b22b3156f8cdb1ed5970244d Mon Sep 17 00:00:00 2001 From: Rohan Sahay Date: Fri, 14 Apr 2023 16:47:43 +0530 Subject: [PATCH] [Silabs] Adds fix for SPI corruption when SPI was multiplexed (#26080) * Adds re factored code with the use of DMA * Changes ordering of spi_cs_assert * Add logs * Reverts SPI drvier re-init from post APIs * Revert changes * Adds delay and disable autoCsEnable * Revert "Adds delay and disable autoCsEnable" This reverts commit d038bb6dd9291313faa1d4e39a0ade8bb3626866. * Adds code to make SL_SPIDRV_HANDLE available in multiplex logic * Adds working logic * Cleanup logs and comments * Adds temporary fix * Use the config provided BITRATE * Revert "Use the config provided BITRATE" This reverts commit 05574a3c137c6666559f433f824205541cf9e538. * Use MY_USART instead of USART0 * Adds guard to check for current and incoming baudrate * Revert MY_USART to USART0 * Requires multiplexing if SL_WIFI is present * Update examples/platform/silabs/efr32/spi_multiplex.c Co-authored-by: Junior Martinez <67972863+jmartinez-silabs@users.noreply.github.com> --------- Co-authored-by: Junior Martinez <67972863+jmartinez-silabs@users.noreply.github.com> --- .../platform/silabs/efr32/display/lcd.cpp | 6 -- .../platform/silabs/efr32/spi_multiplex.c | 41 ++--------- .../platform/silabs/efr32/spi_multiplex.h | 27 ++++---- .../platform/silabs/efr32/wf200/efr_spi.c | 68 ++++++++----------- 4 files changed, 50 insertions(+), 92 deletions(-) diff --git a/examples/platform/silabs/efr32/display/lcd.cpp b/examples/platform/silabs/efr32/display/lcd.cpp index 37ccb0dedbb1d5..561c02451686ee 100644 --- a/examples/platform/silabs/efr32/display/lcd.cpp +++ b/examples/platform/silabs/efr32/display/lcd.cpp @@ -71,12 +71,6 @@ CHIP_ERROR SilabsLCD::Init(uint8_t * name, bool initialState) err = CHIP_ERROR_INTERNAL; } -#if (defined(EFR32MG24) && defined(WF200_WIFI)) - if (pr_type != LCD) - { - pr_type = LCD; - } -#endif /* Initialize the DMD module for the DISPLAY device driver. */ status = DMD_init(0); if (DMD_OK != status) diff --git a/examples/platform/silabs/efr32/spi_multiplex.c b/examples/platform/silabs/efr32/spi_multiplex.c index 137c3973aa846e..6b8d6539d760c5 100644 --- a/examples/platform/silabs/efr32/spi_multiplex.c +++ b/examples/platform/silabs/efr32/spi_multiplex.c @@ -38,6 +38,11 @@ *****************************************************************************/ void spi_drv_reinit(uint32_t baudrate) { + if (USART_BaudrateGet(USART0) == baudrate) + { + // USART synced to baudrate already + return; + } // USART is used in MG24 + WF200 combination USART_InitSync_TypeDef usartInit = USART_INITSYNC_DEFAULT; usartInit.msbf = true; @@ -50,29 +55,6 @@ void spi_drv_reinit(uint32_t baudrate) USART_InitSync(USART0, &usartInit); } -/**************************************************************************** - * @fn void set_spi_baudrate() - * @brief - * Setting the appropriate SPI baudrate - * @param[in] None - * @return returns void - *****************************************************************************/ -void set_spi_baudrate(peripheraltype_t pr_type) -{ - if (pr_type == LCD) - { - spi_drv_reinit(LCD_BIT_RATE); - } - else if (pr_type == EXP_HDR) - { - spi_drv_reinit(EXP_HDR_BIT_RATE); - } - else if (pr_type == EXT_SPIFLASH) - { - spi_drv_reinit(SPI_FLASH_BIT_RATE); - } -} - /**************************************************************************** * @fn void spiflash_cs_assert() * @brief @@ -110,14 +92,10 @@ void pre_bootloader_spi_transfer(void) { return; } - /* - * CS for Expansion header controlled within GSDK, - * however we need to ensure CS for Expansion header is High/disabled before use of EXT SPI Flash - */ - sl_wfx_host_spi_cs_deassert(); /* * Assert CS pin for EXT SPI Flash */ + spi_drv_reinit(SL_BIT_RATE_SPI_FLASH); spiflash_cs_assert(); } @@ -150,11 +128,7 @@ void pre_lcd_spi_transfer(void) { return; } - if (pr_type != LCD) - { - pr_type = LCD; - set_spi_baudrate(pr_type); - } + spi_drv_reinit(SL_BIT_RATE_LCD); /*LCD CS is handled as part of LCD gsdk*/ } @@ -208,7 +182,6 @@ void post_uart_transfer(void) return; } GPIO_PinModeSet(gpioPortA, 8, gpioModeInputPull, 1); - set_spi_baudrate(EXP_HDR); xSemaphoreGive(spi_sem_sync_hdl); sl_wfx_host_enable_platform_interrupt(); sl_wfx_enable_irq(); diff --git a/examples/platform/silabs/efr32/spi_multiplex.h b/examples/platform/silabs/efr32/spi_multiplex.h index 865e93ff4d8b36..29835962a4dd85 100644 --- a/examples/platform/silabs/efr32/spi_multiplex.h +++ b/examples/platform/silabs/efr32/spi_multiplex.h @@ -25,23 +25,26 @@ extern "C" { #include "sl_mx25_flash_shutdown_usart_config.h" #include "sl_spidrv_exp_config.h" #include "sl_wfx_host_api.h" +#include "spidrv.h" -#define LCD_BIT_RATE 1100000 -#define EXP_HDR_BIT_RATE 16000000 -#define SPI_FLASH_BIT_RATE 16000000 - -typedef enum PERIPHERAL_TYPE -{ - EXP_HDR = 0, - LCD, - EXT_SPIFLASH, -} peripheraltype_t; +#define SL_BIT_RATE_LCD 1100000 +#define SL_BIT_RATE_EXP_HDR 16000000 +#define SL_BIT_RATE_SPI_FLASH 16000000 +#define SL_BIT_RATE_UART_CONSOLE 16000000 extern SemaphoreHandle_t spi_sem_sync_hdl; -extern peripheraltype_t pr_type; + +#ifdef RS911X_WIFI +extern SPIDRV_Handle_t sl_spidrv_eusart_exp_handle; +#define SL_SPIDRV_HANDLE sl_spidrv_eusart_exp_handle +#endif + +#ifdef WF200_WIFI +extern SPIDRV_Handle_t sl_spidrv_exp_handle; +#define SL_SPIDRV_HANDLE sl_spidrv_exp_handle +#endif void spi_drv_reinit(uint32_t); -void set_spi_baudrate(peripheraltype_t); void spiflash_cs_assert(void); void spiflash_cs_deassert(void); diff --git a/examples/platform/silabs/efr32/wf200/efr_spi.c b/examples/platform/silabs/efr32/wf200/efr_spi.c index 7422ec686f0b9d..927b9a5fb892fa 100644 --- a/examples/platform/silabs/efr32/wf200/efr_spi.c +++ b/examples/platform/silabs/efr32/wf200/efr_spi.c @@ -49,13 +49,11 @@ #include "sl_power_manager.h" #endif -#if defined(EFR32MG24) +#if SL_WIFI #include "spi_multiplex.h" StaticSemaphore_t spi_sem_peripharal; SemaphoreHandle_t spi_sem_sync_hdl; -peripheraltype_t pr_type = EXP_HDR; #endif -extern SPIDRV_Handle_t sl_spidrv_exp_handle; #define USART SL_WFX_HOST_PINOUT_SPI_PERIPHERAL @@ -90,8 +88,8 @@ sl_status_t sl_wfx_host_init_bus(void) spi_enabled = true; /* Assign allocated DMA channel */ - tx_dma_channel = sl_spidrv_exp_handle->txDMACh; - rx_dma_channel = sl_spidrv_exp_handle->rxDMACh; + tx_dma_channel = SL_SPIDRV_HANDLE->txDMACh; + rx_dma_channel = SL_SPIDRV_HANDLE->rxDMACh; /* * Route EUSART1 MOSI, MISO, and SCLK to the specified pins. CS is @@ -116,7 +114,7 @@ sl_status_t sl_wfx_host_init_bus(void) #if defined(EFR32MG24) spi_sem_sync_hdl = xSemaphoreCreateBinaryStatic(&spi_sem_peripharal); xSemaphoreGive(spi_sem_sync_hdl); -#endif +#endif /* EFR32MG24 */ return SL_STATUS_OK; } @@ -130,6 +128,7 @@ sl_status_t sl_wfx_host_init_bus(void) sl_status_t sl_wfx_host_deinit_bus(void) { vSemaphoreDelete(spi_sem); + vSemaphoreDelete(spi_sem_sync_hdl); // Stop DMAs. DMADRV_StopTransfer(rx_dma_channel); DMADRV_StopTransfer(tx_dma_channel); @@ -149,6 +148,12 @@ sl_status_t sl_wfx_host_deinit_bus(void) *****************************************************************************/ sl_status_t sl_wfx_host_spi_cs_assert() { + configASSERT(spi_sem_sync_hdl); + if (xSemaphoreTake(spi_sem_sync_hdl, portMAX_DELAY) != pdTRUE) + { + return SL_STATUS_TIMEOUT; + } + spi_drv_reinit(SL_BIT_RATE_EXP_HDR); GPIO_PinOutClear(SL_SPIDRV_EXP_CS_PORT, SL_SPIDRV_EXP_CS_PIN); return SL_STATUS_OK; } @@ -163,6 +168,7 @@ sl_status_t sl_wfx_host_spi_cs_assert() sl_status_t sl_wfx_host_spi_cs_deassert() { GPIO_PinOutSet(SL_SPIDRV_EXP_CS_PORT, SL_SPIDRV_EXP_CS_PIN); + xSemaphoreGive(spi_sem_sync_hdl); return SL_STATUS_OK; } @@ -258,19 +264,6 @@ void transmitDMA(uint8_t * buffer, uint16_t buffer_length) sl_status_t sl_wfx_host_spi_transfer_no_cs_assert(sl_wfx_host_bus_transfer_type_t type, uint8_t * header, uint16_t header_length, uint8_t * buffer, uint16_t buffer_length) { - sl_status_t result = SL_STATUS_FAIL; -#if defined(EFR32MG24) - if (pr_type != EXP_HDR) - { - pr_type = EXP_HDR; - set_spi_baudrate(pr_type); - } - if (xSemaphoreTake(spi_sem_sync_hdl, portMAX_DELAY) != pdTRUE) - { - return SL_STATUS_TIMEOUT; - } - sl_wfx_host_spi_cs_assert(); -#endif const bool is_read = (type == SL_WFX_BUS_READ); while (!(MY_USART->STATUS & USART_STATUS_TXBL)) @@ -298,34 +291,29 @@ sl_status_t sl_wfx_host_spi_transfer_no_cs_assert(sl_wfx_host_bus_transfer_type_ if (buffer_length > 0) { MY_USART->CMD = USART_CMD_CLEARRX | USART_CMD_CLEARTX; - if (xSemaphoreTake(spi_sem, portMAX_DELAY) == pdTRUE) + // Reset the semaphore + configASSERT(spi_sem); + if (xSemaphoreTake(spi_sem, portMAX_DELAY) != pdTRUE) { - if (is_read) - { - receiveDMA(buffer, buffer_length); - result = SL_STATUS_OK; - } - else - { - transmitDMA(buffer, buffer_length); - result = SL_STATUS_OK; - } + return SL_STATUS_TIMEOUT; + } - if (xSemaphoreTake(spi_sem, portMAX_DELAY) == pdTRUE) - { - xSemaphoreGive(spi_sem); - } + if (is_read) + { + receiveDMA(buffer, buffer_length); } else { - result = SL_STATUS_TIMEOUT; + transmitDMA(buffer, buffer_length); + } + // wait for dma_complete by using the same spi_semaphore + if (xSemaphoreTake(spi_sem, portMAX_DELAY) != pdTRUE) + { + return SL_STATUS_TIMEOUT; } + xSemaphoreGive(spi_sem); } -#if defined(EFR32MG24) - sl_wfx_host_spi_cs_deassert(); - xSemaphoreGive(spi_sem_sync_hdl); -#endif - return result; + return SL_STATUS_OK; } /****************************************************************************