diff --git a/examples/platform/silabs/display/demo-ui.c b/examples/platform/silabs/display/demo-ui.c index 68b53ba5a804c9..1c5222b06b2ce2 100644 --- a/examples/platform/silabs/display/demo-ui.c +++ b/examples/platform/silabs/display/demo-ui.c @@ -25,7 +25,7 @@ #include "glib.h" #include #include -#if (defined(EFR32MG24) && defined(WF200_WIFI)) +#if (defined(EFR32MG24) && defined(SL_WIFI)) #include "spi_multiplex.h" #endif @@ -108,11 +108,11 @@ void demoUIDisplayHeader(char * name) { GLIB_drawStringOnLine(&glibContext, name, 5, GLIB_ALIGN_CENTER, 0, 0, true); } -#if (defined(EFR32MG24) && defined(WF200_WIFI)) +#if (defined(EFR32MG24) && defined(SL_WIFI)) pre_lcd_spi_transfer(); #endif DMD_updateDisplay(); -#if (defined(EFR32MG24) && defined(WF200_WIFI)) +#if (defined(EFR32MG24) && defined(SL_WIFI)) post_lcd_spi_transfer(); #endif } @@ -121,11 +121,11 @@ void demoUIDisplayApp(bool on) { GLIB_drawBitmap(&glibContext, APP_X_POSITION, APP_Y_POSITION, APP_BITMAP_WIDTH, APP_BITMAP_HEIGHT, (on ? OnStateBitMap : OffStateBitMap)); -#if (defined(EFR32MG24) && defined(WF200_WIFI)) +#if (defined(EFR32MG24) && defined(SL_WIFI)) pre_lcd_spi_transfer(); #endif DMD_updateDisplay(); -#if (defined(EFR32MG24) && defined(WF200_WIFI)) +#if (defined(EFR32MG24) && defined(SL_WIFI)) post_lcd_spi_transfer(); #endif } @@ -138,11 +138,11 @@ void demoUIDisplayProtocol(demoUIProtocol protocol, bool isConnected) (protocol == DEMO_UI_PROTOCOL1 ? PROT1_BITMAP_HEIGHT : PROT2_BITMAP_HEIGHT), (protocol == DEMO_UI_PROTOCOL1 ? (isConnected ? PROT1_BITMAP_CONN : PROT1_BITMAP) : (isConnected ? PROT2_BITMAP_CONN : PROT2_BITMAP))); -#if (defined(EFR32MG24) && defined(WF200_WIFI)) +#if (defined(EFR32MG24) && defined(SL_WIFI)) pre_lcd_spi_transfer(); #endif DMD_updateDisplay(); -#if (defined(EFR32MG24) && defined(WF200_WIFI)) +#if (defined(EFR32MG24) && defined(SL_WIFI)) post_lcd_spi_transfer(); #endif } diff --git a/examples/platform/silabs/display/lcd.cpp b/examples/platform/silabs/display/lcd.cpp index 561c02451686ee..7c223e53c32262 100644 --- a/examples/platform/silabs/display/lcd.cpp +++ b/examples/platform/silabs/display/lcd.cpp @@ -31,7 +31,7 @@ #include "sl_board_control.h" -#if (defined(EFR32MG24) && defined(WF200_WIFI)) +#if (defined(EFR32MG24) && defined(SL_WIFI)) #include "spi_multiplex.h" #endif #define LCD_SIZE 128 @@ -71,6 +71,12 @@ CHIP_ERROR SilabsLCD::Init(uint8_t * name, bool initialState) err = CHIP_ERROR_INTERNAL; } +#if (defined(EFR32MG24) && defined(RS911X_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) @@ -121,11 +127,11 @@ int SilabsLCD::DrawPixel(void * pContext, int32_t x, int32_t y) int SilabsLCD::Update(void) { int status; -#if (defined(EFR32MG24) && defined(WF200_WIFI)) +#if (defined(EFR32MG24) && defined(SL_WIFI)) pre_lcd_spi_transfer(); #endif status = DMD_updateDisplay(); -#if (defined(EFR32MG24) && defined(WF200_WIFI)) +#if (defined(EFR32MG24) && defined(SL_WIFI)) post_lcd_spi_transfer(); #endif /* @@ -194,12 +200,12 @@ void SilabsLCD::WriteQRCode() } } } -#if (defined(EFR32MG24) && defined(WF200_WIFI)) +#if (defined(EFR32MG24) && defined(SL_WIFI)) pre_lcd_spi_transfer(); #endif DMD_updateDisplay(); -#if (defined(EFR32MG24) && defined(WF200_WIFI)) +#if (defined(EFR32MG24) && defined(SL_WIFI)) post_lcd_spi_transfer(); #endif } diff --git a/examples/platform/silabs/efr32/rs911x/hal/efx_spi.c b/examples/platform/silabs/efr32/rs911x/hal/efx_spi.c index 02ae9b2cba9b17..ff7f9864701743 100644 --- a/examples/platform/silabs/efr32/rs911x/hal/efx_spi.c +++ b/examples/platform/silabs/efr32/rs911x/hal/efx_spi.c @@ -66,14 +66,21 @@ extern SPIDRV_Handle_t sl_spidrv_exp_handle; #define SPI_HANDLE sl_spidrv_exp_handle #elif defined(EFR32MG24) #include "sl_spidrv_eusart_exp_config.h" +#include "spi_multiplex.h" +StaticSemaphore_t spi_sem_peripharal; +SemaphoreHandle_t spi_sem_sync_hdl; +peripheraltype_t pr_type = EXP_HDR; extern SPIDRV_Handle_t sl_spidrv_eusart_exp_handle; #define SPI_HANDLE sl_spidrv_eusart_exp_handle #else #error "Unknown platform" #endif +static unsigned int tx_dma_channel; +static unsigned int rx_dma_channel; + extern void rsi_gpio_irq_cb(uint8_t irqnum); -//#define RS911X_USE_LDMA +// #define RS911X_USE_LDMA /******************************************************** * @fn sl_wfx_host_gpio_init(void) @@ -88,6 +95,11 @@ void sl_wfx_host_gpio_init(void) // Enable GPIO clock. CMU_ClockEnable(cmuClock_GPIO, true); +#if defined(EFR32MG24) + // Set CS pin to high/inactive + GPIO_PinModeSet(SL_SPIDRV_EUSART_EXP_CS_PORT, SL_SPIDRV_EUSART_EXP_CS_PIN, gpioModePushPull, PINOUT_SET); +#endif + GPIO_PinModeSet(WFX_RESET_PIN.port, WFX_RESET_PIN.pin, gpioModePushPull, PINOUT_SET); GPIO_PinModeSet(WFX_SLEEP_CONFIRM_PIN.port, WFX_SLEEP_CONFIRM_PIN.pin, gpioModePushPull, PINOUT_CLEAR); @@ -139,6 +151,11 @@ void rsi_hal_board_init(void) spiTransferLock = xSemaphoreCreateBinaryStatic(&xEfxSpiIntfSemaBuffer); xSemaphoreGive(spiTransferLock); +#if defined(EFR32MG24) + spi_sem_sync_hdl = xSemaphoreCreateBinaryStatic(&spi_sem_peripharal); + xSemaphoreGive(spi_sem_sync_hdl); +#endif + /* GPIO INIT of MG12 & MG24 : Reset, Wakeup, Interrupt */ SILABS_LOG("RSI_HAL: init GPIO"); sl_wfx_host_gpio_init(); @@ -149,6 +166,34 @@ void rsi_hal_board_init(void) SILABS_LOG("RSI_HAL: Init done"); } +#if defined(EFR32MG24) +/**************************************************************************** + * @fn sl_status_t sl_wfx_host_spi_cs_assert() + * @brief + * Assert chip select. + * @param[in] None + * @return returns SL_STATUS_OK + *****************************************************************************/ +sl_status_t sl_wfx_host_spi_cs_assert() +{ + GPIO_PinOutClear(SL_SPIDRV_EUSART_EXP_CS_PORT, SL_SPIDRV_EUSART_EXP_CS_PIN); + return SL_STATUS_OK; +} + +/**************************************************************************** + * @fn sl_status_t sl_wfx_host_spi_cs_deassert() + * @brief + * De-Assert chip select. + * @param[in] None + * @return returns SL_STATUS_OK + *****************************************************************************/ +sl_status_t sl_wfx_host_spi_cs_deassert() +{ + GPIO_PinOutSet(SL_SPIDRV_EUSART_EXP_CS_PORT, SL_SPIDRV_EUSART_EXP_CS_PIN); + return SL_STATUS_OK; +} +#endif + /***************************************************************************** *@brief * Spi dma transfer is complete Callback @@ -170,6 +215,16 @@ static void spi_dmaTransfertComplete(SPIDRV_HandleData_t * pxHandle, Ecode_t tra portYIELD_FROM_ISR(xHigherPriorityTaskWoken); } +#if defined(EFR32MG24) +void rsi_update_spi(void) +{ + spi_switch(EXP_HDR); + // GPIO_PinModeSet(SL_SPIDRV_EUSART_EXP_CS_PORT, SL_SPIDRV_EUSART_EXP_CS_PIN, gpioModePushPull, PINOUT_SET); + /* MG24 + rs9116 combination uses EUSART driver */ + tx_dma_channel = sl_spidrv_eusart_exp_handle->txDMACh; + rx_dma_channel = sl_spidrv_eusart_exp_handle->rxDMACh; +} +#endif /********************************************************************* * @fn int16_t rsi_spi_transfer(uint8_t *tx_buf, uint8_t *rx_buf, uint16_t xlen, uint8_t mode) * @brief @@ -183,6 +238,19 @@ static void spi_dmaTransfertComplete(SPIDRV_HandleData_t * pxHandle, Ecode_t tra **************************************************************************/ int16_t rsi_spi_transfer(uint8_t * tx_buf, uint8_t * rx_buf, uint16_t xlen, uint8_t mode) { +#if defined(EFR32MG24) + /* In case of MG24, take multiplex synchronization semaphore to ensure SPI is + * available and then set CS of Exp Hdr SPI to low/enable */ + if (xSemaphoreTake(spi_sem_sync_hdl, portMAX_DELAY) != pdTRUE) + { + return SL_STATUS_TIMEOUT; + } + if (pr_type != EXP_HDR) + { + rsi_update_spi(); + } + GPIO_PinOutClear(SL_SPIDRV_EUSART_EXP_CS_PORT, SL_SPIDRV_EUSART_EXP_CS_PIN); +#endif if (xlen <= MIN_XLEN || (tx_buf == NULL && rx_buf == NULL)) // at least one buffer needs to be provided { return RSI_ERROR_INVALID_PARAM; @@ -238,5 +306,10 @@ int16_t rsi_spi_transfer(uint8_t * tx_buf, uint8_t * rx_buf, uint16_t xlen, uint } xSemaphoreGive(spiTransferLock); +#if defined(EFR32MG24) + /* In case of MG24, set CS of Exp Hdr SPI to high and release multiplex synchronization semaphore*/ + GPIO_PinOutSet(SL_SPIDRV_EUSART_EXP_CS_PORT, SL_SPIDRV_EUSART_EXP_CS_PIN); + xSemaphoreGive(spi_sem_sync_hdl); +#endif return rsiError; } diff --git a/examples/platform/silabs/efr32/rs911x/rs911x.gni b/examples/platform/silabs/efr32/rs911x/rs911x.gni index 0c305ce810abd1..fb725f2d395724 100644 --- a/examples/platform/silabs/efr32/rs911x/rs911x.gni +++ b/examples/platform/silabs/efr32/rs911x/rs911x.gni @@ -12,6 +12,7 @@ rs911x_src_plat = [ "${examples_plat_dir}/rs911x/hal/rsi_hal_mcu_timer.c", "${examples_plat_dir}/rs911x/hal/efx_spi.c", "${wifi_sdk_dir}/wfx_notify.cpp", + "${examples_plat_dir}/spi_multiplex.c", ] # diff --git a/examples/platform/silabs/efr32/spi_multiplex.c b/examples/platform/silabs/efr32/spi_multiplex.c index 6b8d6539d760c5..405ff8452abdea 100644 --- a/examples/platform/silabs/efr32/spi_multiplex.c +++ b/examples/platform/silabs/efr32/spi_multiplex.c @@ -26,9 +26,26 @@ #include "em_ldma.h" #include "em_usart.h" #if SL_WIFI +#include "btl_interface.h" +#include "sl_memlcd.h" #include "spi_multiplex.h" #endif /* SL_WIFI */ +#define CONCAT(A, B) (A##B) +#define SPI_CLOCK(N) CONCAT(cmuClock_USART, N) +#ifdef WF200_WIFI +#define SL_SPIDRV_FRAME_LENGTH SL_SPIDRV_EXP_FRAME_LENGTH +#else +#define SL_SPIDRV_FRAME_LENGTH 8 // default value +#endif + +const uint32_t spiBitRates[] = { [EXP_HDR] = SL_BIT_RATE_EXP_HDR, [LCD] = SL_BIT_RATE_LCD, [EXT_SPIFLASH] = SL_BIT_RATE_SPI_FLASH }; + +extern void efr32Log(const char *, ...); + +extern SPIDRV_Handle_t sl_spidrv_eusart_exp_handle; +extern SPIDRV_Init_t sl_spidrv_eusart_init_exp; + /**************************************************************************** * @fn void spi_drv_reinit() * @brief @@ -47,10 +64,14 @@ void spi_drv_reinit(uint32_t baudrate) USART_InitSync_TypeDef usartInit = USART_INITSYNC_DEFAULT; usartInit.msbf = true; usartInit.clockMode = usartClockMode0; - usartInit.baudrate = baudrate; - uint32_t databits = SL_SPIDRV_EXP_FRAME_LENGTH - 4U + _USART_FRAME_DATABITS_FOUR; - usartInit.databits = (USART_Databits_TypeDef) databits; - usartInit.autoCsEnable = true; +#ifdef WF200_WIFI + usartInit.baudrate = baudrate; +#elif RS911X_WIFI + usartInit.baudrate = spiBitRates[pr_type]; +#endif + uint32_t databits = SL_SPIDRV_FRAME_LENGTH - 4U + _USART_FRAME_DATABITS_FOUR; + usartInit.databits = (USART_Databits_TypeDef) databits; + usartInit.autoCsEnable = true; USART_InitSync(USART0, &usartInit); } @@ -95,7 +116,11 @@ void pre_bootloader_spi_transfer(void) /* * Assert CS pin for EXT SPI Flash */ +#ifdef WF200_WIFI spi_drv_reinit(SL_BIT_RATE_SPI_FLASH); +#else + spi_switch(EXT_SPIFLASH); +#endif spiflash_cs_assert(); } @@ -128,7 +153,11 @@ void pre_lcd_spi_transfer(void) { return; } +#ifdef WF200_WIFI spi_drv_reinit(SL_BIT_RATE_LCD); +#else + spi_switch(LCD); +#endif /*LCD CS is handled as part of LCD gsdk*/ } @@ -143,6 +172,78 @@ void post_lcd_spi_transfer(void) { xSemaphoreGive(spi_sem_sync_hdl); } + +#ifdef RS911X_WIFI +/**************************************************************************** + * @fn void spi_switch(pr_type) + * @brief + * Handles switching between pheripherals spi + * @param[in] prType - enum indicating type of pheripheral to switch the SPI to + * @return returns void + *****************************************************************************/ +void spi_switch(peripheraltype_t prType) +{ + efr32Log("switching spi from %u to %u", pr_type, prType); + if (pr_type != EXP_HDR && prType == EXP_HDR) + { + if (pr_type == LCD) + { + /* deinit USART of LCD*/ + USART_Enable(SL_MEMLCD_SPI_PERIPHERAL, usartDisable); + CMU_ClockEnable(SPI_CLOCK(SL_MEMLCD_SPI_PERIPHERAL_NO), false); + // USART_Reset(SL_MEMLCD_SPI_PERIPHERAL); + GPIO->USARTROUTE[SL_MEMLCD_SPI_PERIPHERAL_NO].ROUTEEN = 0; + } + else if (pr_type == EXT_SPIFLASH) + { + bootloader_deinit(); + GPIO->USARTROUTE[0].ROUTEEN = 0; + } + pr_type = EXP_HDR; + /* init EUSART of RS911x*/ + SPIDRV_Init(sl_spidrv_eusart_exp_handle, &sl_spidrv_eusart_init_exp); + } + else if (pr_type != LCD && prType == LCD) + { + if (pr_type == EXT_SPIFLASH) + { + spi_drv_reinit(SL_BIT_RATE_LCD); + pr_type = prType; + efr32Log("spi switched to %u", pr_type); + return; + } + if (pr_type == EXP_HDR) + { + efr32Log("deinited eusart of exp hdr"); + SPIDRV_DeInit(sl_spidrv_eusart_exp_handle); + GPIO->EUSARTROUTE[SL_SPIDRV_EUSART_EXP_PERIPHERAL_NO].ROUTEEN = 0; + } + pr_type = LCD; + efr32Log("inited usart for lcd"); + sl_memlcd_refresh(sl_memlcd_get()); + } + else if (pr_type != EXT_SPIFLASH && prType == EXT_SPIFLASH) + { + if (pr_type == LCD) + { + spi_drv_reinit(SL_BIT_RATE_SPI_FLASH); + pr_type = prType; + efr32Log("spi switched to %u", pr_type); + return; + } + else if (pr_type == EXP_HDR) + { + SPIDRV_DeInit(sl_spidrv_eusart_exp_handle); + GPIO->EUSARTROUTE[SL_SPIDRV_EUSART_EXP_PERIPHERAL_NO].ROUTEEN = 0; + } + pr_type = EXT_SPIFLASH; + /* init EUSART of RS911x*/ + bootloader_init(); + } + efr32Log("spi switched to %u", pr_type); +} +#endif + #if (defined(EFR32MG24) && defined(WF200_WIFI)) /**************************************************************************** * @fn void pre_uart_transfer() @@ -186,4 +287,4 @@ void post_uart_transfer(void) sl_wfx_host_enable_platform_interrupt(); sl_wfx_enable_irq(); } -#endif /* EFR32MG24 && WF200_WIFI */ +#endif /* EFR32MG24 && WF200_WIFI */ \ No newline at end of file diff --git a/examples/platform/silabs/efr32/spi_multiplex.h b/examples/platform/silabs/efr32/spi_multiplex.h index 29835962a4dd85..a4c3bf125a85bc 100644 --- a/examples/platform/silabs/efr32/spi_multiplex.h +++ b/examples/platform/silabs/efr32/spi_multiplex.h @@ -23,12 +23,24 @@ extern "C" { #include "FreeRTOS.h" #include "semphr.h" #include "sl_mx25_flash_shutdown_usart_config.h" +#ifdef WF200_WIFI #include "sl_spidrv_exp_config.h" +#endif +#ifdef RS911X_WIFI +#include "sl_spidrv_eusart_exp_config.h" +#endif +#if (defined(EFR32MG24) && defined(WF200_WIFI)) #include "sl_wfx_host_api.h" +#endif +#include "em_eusart.h" #include "spidrv.h" #define SL_BIT_RATE_LCD 1100000 +#ifdef WF200_WIFI #define SL_BIT_RATE_EXP_HDR 16000000 +#else +#define SL_BIT_RATE_EXP_HDR SL_SPIDRV_EUSART_EXP_BITRATE +#endif #define SL_BIT_RATE_SPI_FLASH 16000000 #define SL_BIT_RATE_UART_CONSOLE 16000000 @@ -37,6 +49,21 @@ extern SemaphoreHandle_t spi_sem_sync_hdl; #ifdef RS911X_WIFI extern SPIDRV_Handle_t sl_spidrv_eusart_exp_handle; #define SL_SPIDRV_HANDLE sl_spidrv_eusart_exp_handle + +typedef enum PERIPHERAL_TYPE +{ + EXP_HDR = 0, + LCD, + EXT_SPIFLASH, +} peripheraltype_t; + +extern peripheraltype_t pr_type; + +sl_status_t sl_wfx_host_spi_cs_deassert(void); +sl_status_t sl_wfx_host_spi_cs_assert(void); + +void spi_switch(peripheraltype_t); + #endif #ifdef WF200_WIFI diff --git a/src/platform/silabs/efr32/OTAImageProcessorImpl.cpp b/src/platform/silabs/efr32/OTAImageProcessorImpl.cpp index 83b815568b24fa..da26cc509c83bd 100644 --- a/src/platform/silabs/efr32/OTAImageProcessorImpl.cpp +++ b/src/platform/silabs/efr32/OTAImageProcessorImpl.cpp @@ -23,9 +23,11 @@ extern "C" { #include "btl_interface.h" #include "em_bus.h" // For CORE_CRITICAL_SECTION -#if (defined(EFR32MG24) && defined(WF200_WIFI)) -#include "sl_wfx_host_api.h" +#if (defined(EFR32MG24) && defined(SL_WIFI)) #include "spi_multiplex.h" +#ifdef WF200_WIFI +#include "sl_wfx_host_api.h" +#endif #endif } @@ -134,6 +136,9 @@ void OTAImageProcessorImpl::HandlePrepareDownload(intptr_t context) ChipLogProgress(SoftwareUpdate, "HandlePrepareDownload"); CORE_CRITICAL_SECTION(bootloader_init();) +#ifdef RS911X_WIFI + pr_type = EXT_SPIFLASH; +#endif mSlotId = 0; // Single slot until we support multiple images writeBufOffset = 0; mWriteOffset = 0; @@ -166,11 +171,11 @@ void OTAImageProcessorImpl::HandleFinalize(intptr_t context) writeBuffer[writeBufOffset] = 0; writeBufOffset++; } -#if (defined(EFR32MG24) && defined(WF200_WIFI)) +#if (defined(EFR32MG24) && defined(SL_WIFI)) pre_bootloader_spi_transfer(); #endif CORE_CRITICAL_SECTION(err = bootloader_eraseWriteStorage(mSlotId, mWriteOffset, writeBuffer, kAlignmentBytes);) -#if (defined(EFR32MG24) && defined(WF200_WIFI)) +#if (defined(EFR32MG24) && defined(SL_WIFI)) post_bootloader_spi_transfer(); #endif if (err) @@ -194,7 +199,7 @@ void OTAImageProcessorImpl::HandleApply(intptr_t context) // Force KVS to store pending keys such as data from StoreCurrentUpdateInfo() chip::DeviceLayer::PersistedStorage::KeyValueStoreMgrImpl().ForceKeyMapSave(); -#if (defined(EFR32MG24) && defined(WF200_WIFI)) +#if (defined(EFR32MG24) && defined(SL_WIFI)) pre_bootloader_spi_transfer(); #endif CORE_CRITICAL_SECTION(err = bootloader_verifyImage(mSlotId, NULL);) @@ -215,7 +220,7 @@ void OTAImageProcessorImpl::HandleApply(intptr_t context) // This reboots the device CORE_CRITICAL_SECTION(bootloader_rebootAndInstall();) -#if (defined(EFR32MG24) && defined(WF200_WIFI)) +#if (defined(EFR32MG24) && defined(SL_WIFI)) xSemaphoreGive(spi_sem_sync_hdl); #endif } @@ -268,11 +273,11 @@ void OTAImageProcessorImpl::HandleProcessBlock(intptr_t context) if (writeBufOffset == kAlignmentBytes) { writeBufOffset = 0; -#if (defined(EFR32MG24) && defined(WF200_WIFI)) +#if (defined(EFR32MG24) && defined(SL_WIFI)) pre_bootloader_spi_transfer(); #endif CORE_CRITICAL_SECTION(err = bootloader_eraseWriteStorage(mSlotId, mWriteOffset, writeBuffer, kAlignmentBytes);) -#if (defined(EFR32MG24) && defined(WF200_WIFI)) +#if (defined(EFR32MG24) && defined(SL_WIFI)) post_bootloader_spi_transfer(); #endif if (err)