Skip to content

Commit

Permalink
[Silabs] Adds fix for SPI corruption when SPI was multiplexed (#26080)
Browse files Browse the repository at this point in the history
* 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 d038bb6.

* 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 05574a3.

* 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 <[email protected]>

---------

Co-authored-by: Junior Martinez <[email protected]>
  • Loading branch information
2 people authored and pull[bot] committed Sep 21, 2023
1 parent 7c60f6b commit 4350740
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 92 deletions.
6 changes: 0 additions & 6 deletions examples/platform/silabs/efr32/display/lcd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
41 changes: 7 additions & 34 deletions examples/platform/silabs/efr32/spi_multiplex.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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
Expand Down Expand Up @@ -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();
}

Expand Down Expand Up @@ -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*/
}

Expand Down Expand Up @@ -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();
Expand Down
27 changes: 15 additions & 12 deletions examples/platform/silabs/efr32/spi_multiplex.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
68 changes: 28 additions & 40 deletions examples/platform/silabs/efr32/wf200/efr_spi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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
Expand All @@ -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;
}

Expand All @@ -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);
Expand All @@ -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;
}
Expand All @@ -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;
}

Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -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;
}

/****************************************************************************
Expand Down

0 comments on commit 4350740

Please sign in to comment.