From 23644a530437cbaed95411afa51fcfa66fb6cb78 Mon Sep 17 00:00:00 2001 From: Rohan Sahay Date: Fri, 23 Jun 2023 07:43:33 +0530 Subject: [PATCH] [Silabs] Adds SPI multiplex changes for rs911x (#26238) * SPI multiplex changes for rs911x * Adds intermediate changes with cleanup * Adds additional macro checks * Adds updated working logic for multiplexing expansion header and LCD * Adds missing ; * Adds fix for WF200 baudrate on SPI * Adds fix for third_party * Adds updated log statements * Adds fix for log statement * Adds conditional use of semaphore * Adds conditional EFR32MG24 semaphore logic * Adds fix for err usage * Refactor SPIDRV_ReInit * Adds SPIDRV_ReInit for EUSART * Added error logs * Added logs * Revert submodule update * Aligned the macros * Restyled * Aligned the MACRO * Adds cosmetic changes * Removes debug log * Adds sl_wfx_host_post_bootloader_spi_transfer in relevant failure outcomes * Adds re factored local function updateDisplay(void) * Removes spi_multiplex.c * Removes development debug trace and log * Renamed conflicting variable * Adds comment for technical debt and understanding * Adds changes for updateDisplay function * Adds checks for semaphore used for sync peripherals * Clean up of unreachable code due to portMAX_DELAY * Adds fix for comment alignment * Changes SPIDRV_ReInit to SPIDRV_SetBaudrate * Removes unused error variable * Clean up logs * Clean up of logs * Replace magic number * Added tickets for tracking additional rework * Clean up additional logs * Adds fix for print statements * Adds fix for MACRO * Adds fix for MATTER-1904 * Adds partial fix for MATTER-1907 * Adds for fix code compilation * Adds code to clean up MACROs * Restyled by clang-format * Removes debug log * Adds fix for MATTER-1907 * Adds use of the ECODE_EMDRV_SPIDRV status instead of generic ECODE * Adds comment for declaring the current supported family. --------- Co-authored-by: shasaicha Co-authored-by: Restyled.io --- examples/platform/silabs/display/demo-ui.c | 41 ++-- examples/platform/silabs/display/demo-ui.h | 172 +++++++------ examples/platform/silabs/display/lcd.cpp | 24 +- .../silabs/efr32/rs911x/hal/efx_spi.c | 195 +++++++++++++-- .../platform/silabs/efr32/spi_multiplex.c | 189 --------------- .../platform/silabs/efr32/spi_multiplex.h | 151 ++++++++++-- examples/platform/silabs/efr32/uart.cpp | 4 +- .../platform/silabs/efr32/wf200/efr_spi.c | 229 ++++++++++-------- .../platform/silabs/efr32/wf200/wf200.gni | 1 - .../silabs/ConnectivityManagerImpl_WIFI.cpp | 5 +- .../silabs/efr32/OTAImageProcessorImpl.cpp | 102 +++++--- 11 files changed, 625 insertions(+), 488 deletions(-) delete mode 100644 examples/platform/silabs/efr32/spi_multiplex.c diff --git a/examples/platform/silabs/display/demo-ui.c b/examples/platform/silabs/display/demo-ui.c index 68b53ba5a804c9..e430e01ddb82dd 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 @@ -92,7 +92,6 @@ static void demoUIDisplayLogo(void) GLIB_drawBitmap(&glibContext, SILICONLABS_X_POSITION, SILICONLABS_Y_POSITION, SILICONLABS_BITMAP_WIDTH, SILICONLABS_BITMAP_HEIGHT, siliconlabsBitmap); } - /******************************************************************************* ************************** GLOBAL FUNCTIONS ******************************* ******************************************************************************/ @@ -101,6 +100,20 @@ void demoUIInit(GLIB_Context_t * context) memcpy(&glibContext, context, sizeof(GLIB_Context_t)); } +sl_status_t updateDisplay(void) +{ +#if (defined(EFR32MG24) && defined(SL_WIFI)) + sl_wfx_host_pre_lcd_spi_transfer(); +#endif + sl_status_t status = DMD_updateDisplay(); +#if (defined(EFR32MG24) && defined(SL_WIFI)) + sl_wfx_host_post_lcd_spi_transfer(); +#endif + if (status != DMD_OK) + return SL_STATUS_FAIL; + return SL_STATUS_OK; +} + void demoUIDisplayHeader(char * name) { demoUIDisplayLogo(); @@ -108,26 +121,14 @@ void demoUIDisplayHeader(char * name) { GLIB_drawStringOnLine(&glibContext, name, 5, GLIB_ALIGN_CENTER, 0, 0, true); } -#if (defined(EFR32MG24) && defined(WF200_WIFI)) - pre_lcd_spi_transfer(); -#endif - DMD_updateDisplay(); -#if (defined(EFR32MG24) && defined(WF200_WIFI)) - post_lcd_spi_transfer(); -#endif + updateDisplay(); } 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)) - pre_lcd_spi_transfer(); -#endif - DMD_updateDisplay(); -#if (defined(EFR32MG24) && defined(WF200_WIFI)) - post_lcd_spi_transfer(); -#endif + updateDisplay(); } void demoUIDisplayProtocol(demoUIProtocol protocol, bool isConnected) @@ -138,13 +139,7 @@ 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)) - pre_lcd_spi_transfer(); -#endif - DMD_updateDisplay(); -#if (defined(EFR32MG24) && defined(WF200_WIFI)) - post_lcd_spi_transfer(); -#endif + updateDisplay(); } void demoUIClearMainScreen(uint8_t * name) diff --git a/examples/platform/silabs/display/demo-ui.h b/examples/platform/silabs/display/demo-ui.h index 6197a4e73c71ef..baf4902ef6184b 100644 --- a/examples/platform/silabs/display/demo-ui.h +++ b/examples/platform/silabs/display/demo-ui.h @@ -1,22 +1,23 @@ -/***************************************************************************/ /** - * @file - * @brief User Interface for demo. - ******************************************************************************* - * # License - * Copyright 2020 Silicon Laboratories Inc. - *www.silabs.com - ******************************************************************************* - * - * The licensor of this software is Silicon - *Laboratories Inc. Your use of this software is - *governed by the terms of Silicon Labs Master - *Software License Agreement (MSLA) available at - * www.silabs.com/about-us/legal/master-software-license-agreement. - *This software is distributed to you in Source Code - *format and is governed by the sections of the MSLA - *applicable to Source Code. - * - ******************************************************************************/ +/***************************************************************************/ +/** + * @file + * @brief User Interface for demo. + ******************************************************************************* + * # License + * Copyright 2020 Silicon Laboratories Inc. + *www.silabs.com + ******************************************************************************* + * + * The licensor of this software is Silicon + *Laboratories Inc. Your use of this software is + *governed by the terms of Silicon Labs Master + *Software License Agreement (MSLA) available at + * www.silabs.com/about-us/legal/master-software-license-agreement. + *This software is distributed to you in Source Code + *format and is governed by the sections of the MSLA + *applicable to Source Code. + * + ******************************************************************************/ #pragma once @@ -25,13 +26,15 @@ extern "C" { #endif #include "glib.h" -/**************************************************************************/ /** - * DEMO UI uses the underlying DMD interface and the - *GLIB and exposes several wrapper functions to - *application. These functions are used to display - * different bitmaps for the demo. - * - ******************************************************************************/ +#include "sl_status.h" +/**************************************************************************/ +/** + * DEMO UI uses the underlying DMD interface and the + *GLIB and exposes several wrapper functions to + *application. These functions are used to display + * different bitmaps for the demo. + * + ******************************************************************************/ #define APP_NAME_MAX_LENGTH 20 @@ -73,67 +76,82 @@ typedef enum ****************************** PROTOTYPES ********************************* ******************************************************************************/ -/**************************************************************************/ /** - * @brief - * Initilize the GLIB and DMD interfaces. - * - * @param[in] void - * - * @return - * void - *****************************************************************************/ +/**************************************************************************/ +/** + * @brief + * Initilize the GLIB and DMD interfaces. + * + * @param[in] void + * + * @return + * void + *****************************************************************************/ void demoUIInit(GLIB_Context_t * context); -/**************************************************************************/ /** - * @brief - * Update the display with Silicon Labs logo and - *application name. - * - * @param[in] name name of the current application. - * - * @return - * void - *****************************************************************************/ +/**************************************************************************/ +/** + * @brief + * Update the display with Silicon Labs logo and + *application name. + * + * @param[in] name name of the current application. + * + * @return + * void + *****************************************************************************/ void demoUIDisplayHeader(char * name); -/**************************************************************************/ /** - * @brief - * Update the display with App image. Bool state only - *for now. - * - * @param[in] on status of App - * - * @return - * void - *****************************************************************************/ +/**************************************************************************/ +/** + * @brief + * Update the display with App image. Bool state only + *for now. + * + * @param[in] on status of App + * + * @return + * void + *****************************************************************************/ void demoUIDisplayApp(bool on); -/**************************************************************************/ /** - * @brief - * Update the display to show if the bluetooth is - *connected to the mobile device. - * - * @param[in] bool, true if the Light is connected to - *mobile device, false otherwise. - * - * @return - * void - *****************************************************************************/ +/**************************************************************************/ +/** + * @brief + * Update the display to show if the bluetooth is + *connected to the mobile device. + * + * @param[in] bool, true if the Light is connected to + *mobile device, false otherwise. + * + * @return + * void + *****************************************************************************/ void demoUIDisplayProtocol(demoUIProtocol protocol, bool isConnected); -/**************************************************************************/ /** - * @brief - * Clear the Lcd screen and display the main screen. - * - * @param[in] name - application name - * @param[in] showPROT1 - show protocol 1 related icon. - * @param[in] showPROT2 - show protocol 2 related icon. - * - * @return - * void - *****************************************************************************/ +/**************************************************************************/ +/** + * @brief + * Clear the Lcd screen and display the main screen. + * + * @param[in] name - application name + * @param[in] showPROT1 - show protocol 1 related icon. + * @param[in] showPROT2 - show protocol 2 related icon. + * + * @return + * void + *****************************************************************************/ void demoUIClearMainScreen(uint8_t * name); +/**************************************************************************/ +/** + * @brief + * Clear the Lcd screen and display the main screen. + * + * @return + * Returns SL_STATUS_OK if successful, error otherwise. + *****************************************************************************/ +sl_status_t updateDisplay(void); + #ifdef __cplusplus } #endif diff --git a/examples/platform/silabs/display/lcd.cpp b/examples/platform/silabs/display/lcd.cpp index 561c02451686ee..6a06be1c28f6c8 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 @@ -120,18 +120,7 @@ int SilabsLCD::DrawPixel(void * pContext, int32_t x, int32_t y) int SilabsLCD::Update(void) { - int status; -#if (defined(EFR32MG24) && defined(WF200_WIFI)) - pre_lcd_spi_transfer(); -#endif - status = DMD_updateDisplay(); -#if (defined(EFR32MG24) && defined(WF200_WIFI)) - post_lcd_spi_transfer(); -#endif - /* - * TO-DO; Above logic can be optimised by writing a common API - */ - return status; + return updateDisplay(); } void SilabsLCD::WriteDemoUI(bool state) @@ -194,14 +183,7 @@ void SilabsLCD::WriteQRCode() } } } -#if (defined(EFR32MG24) && defined(WF200_WIFI)) - pre_lcd_spi_transfer(); -#endif - - DMD_updateDisplay(); -#if (defined(EFR32MG24) && defined(WF200_WIFI)) - post_lcd_spi_transfer(); -#endif + SilabsLCD::Update(); } void SilabsLCD::SetQRCode(uint8_t * str, uint32_t size) diff --git a/examples/platform/silabs/efr32/rs911x/hal/efx_spi.c b/examples/platform/silabs/efr32/rs911x/hal/efx_spi.c index 507523a2f6e03e..62b14e0bd34b51 100644 --- a/examples/platform/silabs/efr32/rs911x/hal/efx_spi.c +++ b/examples/platform/silabs/efr32/rs911x/hal/efx_spi.c @@ -40,12 +40,14 @@ #include "gpiointerrupt.h" #include "sl_device_init_clocks.h" +#include "sl_memlcd.h" #include "sl_status.h" #include "FreeRTOS.h" #include "event_groups.h" #include "task.h" +#include "btl_interface.h" #include "wfx_host_events.h" #include "wfx_rsi.h" @@ -58,6 +60,14 @@ #include "sl_power_manager.h" #endif +#define CONCAT(A, B) (A##B) +#define SPI_CLOCK(N) CONCAT(cmuClock_USART, N) + +#if defined(EFR32MG24) +StaticSemaphore_t spi_sem_peripheral; +SemaphoreHandle_t spi_sem_sync_hdl; +#endif /* EFR32MG24 */ + StaticSemaphore_t xEfxSpiIntfSemaBuffer; static SemaphoreHandle_t spiTransferLock; static TaskHandle_t spiInitiatorTaskHandle = NULL; @@ -65,17 +75,18 @@ static TaskHandle_t spiInitiatorTaskHandle = NULL; #if defined(EFR32MG12) #include "sl_spidrv_exp_config.h" extern SPIDRV_Handle_t sl_spidrv_exp_handle; -#define SPI_HANDLE sl_spidrv_exp_handle +#define SL_SPIDRV_HANDLE sl_spidrv_exp_handle #elif defined(EFR32MG24) -#include "sl_spidrv_eusart_exp_config.h" -extern SPIDRV_Handle_t sl_spidrv_eusart_exp_handle; -#define SPI_HANDLE sl_spidrv_eusart_exp_handle +#include "spi_multiplex.h" #else #error "Unknown platform" #endif +// variable to identify spi configured for expansion header +// EUSART configuration available on the SPIDRV +static bool spi_enabled = false; + extern void rsi_gpio_irq_cb(uint8_t irqnum); -//#define RS911X_USE_LDMA /******************************************************** * @fn sl_wfx_host_gpio_init(void) @@ -90,6 +101,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); @@ -105,6 +121,7 @@ void sl_wfx_host_gpio_init(void) // Change GPIO interrupt priority (FreeRTOS asserts unless this is done here!) NVIC_SetPriority(GPIO_EVEN_IRQn, WFX_SPI_NVIC_PRIORITY); NVIC_SetPriority(GPIO_ODD_IRQn, WFX_SPI_NVIC_PRIORITY); + spi_enabled = true; } /***************************************************************** @@ -141,6 +158,15 @@ void rsi_hal_board_init(void) spiTransferLock = xSemaphoreCreateBinaryStatic(&xEfxSpiIntfSemaBuffer); xSemaphoreGive(spiTransferLock); +#if defined(EFR32MG24) + if (spi_sem_sync_hdl == NULL) + { + spi_sem_sync_hdl = xSemaphoreCreateBinaryStatic(&spi_sem_peripheral); + } + configASSERT(spi_sem_sync_hdl); + xSemaphoreGive(spi_sem_sync_hdl); +#endif /* EFR32MG24 */ + /* GPIO INIT of MG12 & MG24 : Reset, Wakeup, Interrupt */ sl_wfx_host_gpio_init(); @@ -148,6 +174,132 @@ void rsi_hal_board_init(void) sl_wfx_host_reset_chip(); } +#if defined(EFR32MG24) + +void SPIDRV_SetBaudrate(uint32_t baudrate) +{ + if (EUSART_BaudrateGet(MY_USART) == baudrate) + { + // EUSART synced to baudrate already + return; + } + EUSART_BaudrateSet(MY_USART, 0, baudrate); +} + +sl_status_t sl_wfx_host_spi_cs_assert(void) +{ + xSemaphoreTake(spi_sem_sync_hdl, portMAX_DELAY); + + if (!spi_enabled) // Reduce sl_spidrv_init_instances + { + sl_spidrv_init_instances(); + spi_enabled = true; + } + GPIO_PinOutClear(SL_SPIDRV_EUSART_EXP_CS_PORT, SL_SPIDRV_EUSART_EXP_CS_PIN); + return SL_STATUS_OK; +} + +sl_status_t sl_wfx_host_spi_cs_deassert(void) +{ + if (spi_enabled) + { + if (ECODE_EMDRV_SPIDRV_OK != SPIDRV_DeInit(SL_SPIDRV_HANDLE)) + { + xSemaphoreGive(spi_sem_sync_hdl); + return SL_STATUS_FAIL; + } + spi_enabled = false; + } + GPIO_PinOutSet(SL_SPIDRV_EUSART_EXP_CS_PORT, SL_SPIDRV_EUSART_EXP_CS_PIN); + GPIO->EUSARTROUTE[SL_SPIDRV_EUSART_EXP_PERIPHERAL_NO].ROUTEEN = PINOUT_CLEAR; + xSemaphoreGive(spi_sem_sync_hdl); + return SL_STATUS_OK; +} + +sl_status_t sl_wfx_host_spiflash_cs_assert(void) +{ + GPIO_PinOutClear(SL_MX25_FLASH_SHUTDOWN_CS_PORT, SL_MX25_FLASH_SHUTDOWN_CS_PIN); + return SL_STATUS_OK; +} + +sl_status_t sl_wfx_host_spiflash_cs_deassert(void) +{ + GPIO_PinOutSet(SL_MX25_FLASH_SHUTDOWN_CS_PORT, SL_MX25_FLASH_SHUTDOWN_CS_PIN); + return SL_STATUS_OK; +} + +sl_status_t sl_wfx_host_pre_bootloader_spi_transfer(void) +{ + xSemaphoreTake(spi_sem_sync_hdl, portMAX_DELAY); + if (spi_enabled) + { + if (ECODE_EMDRV_SPIDRV_OK != SPIDRV_DeInit(SL_SPIDRV_HANDLE)) + { + xSemaphoreGive(spi_sem_sync_hdl); + return SL_STATUS_FAIL; + } + spi_enabled = false; + } + // bootloader_init takes care of SPIDRV_Init() + int32_t status = bootloader_init(); + if (status != BOOTLOADER_OK) + { + SILABS_LOG("bootloader_init error: %x", status); + xSemaphoreGive(spi_sem_sync_hdl); + return SL_STATUS_FAIL; + } + sl_wfx_host_spiflash_cs_assert(); + return SL_STATUS_OK; +} + +sl_status_t sl_wfx_host_post_bootloader_spi_transfer(void) +{ + // bootloader_deinit will do USART disable + int32_t status = bootloader_deinit(); + if (status != BOOTLOADER_OK) + { + SILABS_LOG("bootloader_deinit error: %x", status); + xSemaphoreGive(spi_sem_sync_hdl); + return SL_STATUS_FAIL; + } + GPIO->USARTROUTE[SL_MX25_FLASH_SHUTDOWN_PERIPHERAL_NO].ROUTEEN = PINOUT_CLEAR; + sl_wfx_host_spiflash_cs_deassert(); + xSemaphoreGive(spi_sem_sync_hdl); + return SL_STATUS_OK; +} + +sl_status_t sl_wfx_host_pre_lcd_spi_transfer(void) +{ + xSemaphoreTake(spi_sem_sync_hdl, portMAX_DELAY); + if (spi_enabled) + { + if (ECODE_EMDRV_SPIDRV_OK != SPIDRV_DeInit(SL_SPIDRV_HANDLE)) + { + xSemaphoreGive(spi_sem_sync_hdl); + return SL_STATUS_FAIL; + } + spi_enabled = false; + } + // sl_memlcd_refresh takes care of SPIDRV_Init() + if (SL_STATUS_OK != sl_memlcd_refresh(sl_memlcd_get())) + { + xSemaphoreGive(spi_sem_sync_hdl); + return SL_STATUS_FAIL; + } + return SL_STATUS_OK; +} + +sl_status_t sl_wfx_host_post_lcd_spi_transfer(void) +{ + USART_Enable(SL_MEMLCD_SPI_PERIPHERAL, usartDisable); + CMU_ClockEnable(SPI_CLOCK(SL_MEMLCD_SPI_PERIPHERAL_NO), false); + GPIO->USARTROUTE[SL_MEMLCD_SPI_PERIPHERAL_NO].ROUTEEN = PINOUT_CLEAR; + xSemaphoreGive(spi_sem_sync_hdl); + return SL_STATUS_OK; +} + +#endif /* EFR32MG24 */ + /***************************************************************************** *@brief * Spi dma transfer is complete Callback @@ -182,7 +334,13 @@ 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 (xlen <= MIN_XLEN || (tx_buf == NULL && rx_buf == NULL)) // at least one buffer needs to be provided +#if defined(EFR32MG24) + sl_wfx_host_spi_cs_assert(); +#endif /* EFR32MG24 */ + /* + TODO: tx_buf and rx_buf needs to be replaced with a dummy buffer of length xlen to align with SDK of WiFi + */ + if (xlen <= MIN_XLEN || (tx_buf == NULL && rx_buf == NULL)) { return RSI_ERROR_INVALID_PARAM; } @@ -190,26 +348,24 @@ int16_t rsi_spi_transfer(uint8_t * tx_buf, uint8_t * rx_buf, uint16_t xlen, uint (void) mode; // currently not used; rsi_error_t rsiError = RSI_ERROR_NONE; - if (xSemaphoreTake(spiTransferLock, portMAX_DELAY) != pdTRUE) - { - return RSI_ERROR_SPI_BUSY; - } + xSemaphoreTake(spiTransferLock, portMAX_DELAY); - configASSERT(spiInitiatorTaskHandle == NULL); // No other task should currently be waiting for the dma completion + // No other task should currently be waiting for the dma completion + configASSERT(spiInitiatorTaskHandle == NULL); spiInitiatorTaskHandle = xTaskGetCurrentTaskHandle(); Ecode_t spiError; if (tx_buf == NULL) // Rx operation only { - spiError = SPIDRV_MReceive(SPI_HANDLE, rx_buf, xlen, spi_dmaTransfertComplete); + spiError = SPIDRV_MReceive(SL_SPIDRV_HANDLE, rx_buf, xlen, spi_dmaTransfertComplete); } else if (rx_buf == NULL) // Tx operation only { - spiError = SPIDRV_MTransmit(SPI_HANDLE, tx_buf, xlen, spi_dmaTransfertComplete); + spiError = SPIDRV_MTransmit(SL_SPIDRV_HANDLE, tx_buf, xlen, spi_dmaTransfertComplete); } else // Tx and Rx operation { - spiError = SPIDRV_MTransfer(SPI_HANDLE, tx_buf, rx_buf, xlen, spi_dmaTransfertComplete); + spiError = SPIDRV_MTransfer(SL_SPIDRV_HANDLE, tx_buf, rx_buf, xlen, spi_dmaTransfertComplete); } if (spiError == ECODE_EMDRV_SPIDRV_OK) @@ -221,21 +377,24 @@ int16_t rsi_spi_transfer(uint8_t * tx_buf, uint8_t * rx_buf, uint16_t xlen, uint { int itemsTransferred = 0; int itemsRemaining = 0; - SPIDRV_GetTransferStatus(SPI_HANDLE, &itemsTransferred, &itemsRemaining); - SILABS_LOG("SPI transfert timed out %d/%d (rx%x rx%x)", itemsTransferred, itemsRemaining, (uint32_t) tx_buf, + SPIDRV_GetTransferStatus(SL_SPIDRV_HANDLE, &itemsTransferred, &itemsRemaining); + SILABS_LOG("ERR: SPI timed out %d/%d (rx%x rx%x)", itemsTransferred, itemsRemaining, (uint32_t) tx_buf, (uint32_t) rx_buf); - SPIDRV_AbortTransfer(SPI_HANDLE); + SPIDRV_AbortTransfer(SL_SPIDRV_HANDLE); rsiError = RSI_ERROR_SPI_TIMEOUT; } } else { - SILABS_LOG("SPI transfert failed with err:%x (tx%x rx%x)", spiError, (uint32_t) tx_buf, (uint32_t) rx_buf); + SILABS_LOG("ERR: SPI failed with error:%x (tx%x rx%x)", spiError, (uint32_t) tx_buf, (uint32_t) rx_buf); rsiError = RSI_ERROR_SPI_FAIL; spiInitiatorTaskHandle = NULL; // SPI operation failed. No notification to received. } xSemaphoreGive(spiTransferLock); +#if defined(EFR32MG24) + sl_wfx_host_spi_cs_deassert(); +#endif /* EFR32MG24 */ return rsiError; } diff --git a/examples/platform/silabs/efr32/spi_multiplex.c b/examples/platform/silabs/efr32/spi_multiplex.c deleted file mode 100644 index 6b8d6539d760c5..00000000000000 --- a/examples/platform/silabs/efr32/spi_multiplex.c +++ /dev/null @@ -1,189 +0,0 @@ -/* - * - * Copyright (c) 2022 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#if (defined(EFR32MG24) && defined(WF200_WIFI)) -#include "sl_wfx.h" -#endif /* EFR32MG24 && WF200_WIFI */ - -#include "dmadrv.h" -#include "em_bus.h" -#include "em_cmu.h" -#include "em_gpio.h" -#include "em_ldma.h" -#include "em_usart.h" -#if SL_WIFI -#include "spi_multiplex.h" -#endif /* SL_WIFI */ - -/**************************************************************************** - * @fn void spi_drv_reinit() - * @brief - * Re-Intializes SPI driver to required baudrate - * @param[in] None - * @return returns void - *****************************************************************************/ -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; - 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; - - USART_InitSync(USART0, &usartInit); -} - -/**************************************************************************** - * @fn void spiflash_cs_assert() - * @brief - * Assert SPI flash chip select. - * @param[in] None - * @return returns void - *****************************************************************************/ -void spiflash_cs_assert(void) -{ - GPIO_PinOutClear(SL_MX25_FLASH_SHUTDOWN_CS_PORT, SL_MX25_FLASH_SHUTDOWN_CS_PIN); -} - -/**************************************************************************** - * @fn void spiflash_cs_deassert() - * @brief - * De-Assert SPI flash chip select. - * @param[in] None - * @return returns void - *****************************************************************************/ -void spiflash_cs_deassert(void) -{ - GPIO_PinOutSet(SL_MX25_FLASH_SHUTDOWN_CS_PORT, SL_MX25_FLASH_SHUTDOWN_CS_PIN); -} - -/**************************************************************************** - * @fn void pre_bootloader_spi_transfer() - * @brief - * Take a semaphore and controlling CS pin for EXP header and SPI flash - * @param[in] None - * @return returns void - *****************************************************************************/ -void pre_bootloader_spi_transfer(void) -{ - if (xSemaphoreTake(spi_sem_sync_hdl, portMAX_DELAY) != pdTRUE) - { - return; - } - /* - * Assert CS pin for EXT SPI Flash - */ - spi_drv_reinit(SL_BIT_RATE_SPI_FLASH); - spiflash_cs_assert(); -} - -/**************************************************************************** - * @fn void post_bootloader_spi_transfer() - * @brief - * De-Assert EXT SPI flash CS pin and release semaphore - * @param[in] None - * @return returns void - *****************************************************************************/ -void post_bootloader_spi_transfer(void) -{ - /* - * De-Assert CS pin for EXT SPI Flash - */ - spiflash_cs_deassert(); - xSemaphoreGive(spi_sem_sync_hdl); -} - -/**************************************************************************** - * @fn void pre_lcd_spi_transfer() - * @brief - * Take a semaphore and setting LCD baudrate - * @param[in] None - * @return returns void - *****************************************************************************/ -void pre_lcd_spi_transfer(void) -{ - if (xSemaphoreTake(spi_sem_sync_hdl, portMAX_DELAY) != pdTRUE) - { - return; - } - spi_drv_reinit(SL_BIT_RATE_LCD); - /*LCD CS is handled as part of LCD gsdk*/ -} - -/**************************************************************************** - * @fn void post_lcd_spi_transfer() - * @brief - * Release semaphore - * @param[in] None - * @return returns void - *****************************************************************************/ -void post_lcd_spi_transfer(void) -{ - xSemaphoreGive(spi_sem_sync_hdl); -} -#if (defined(EFR32MG24) && defined(WF200_WIFI)) -/**************************************************************************** - * @fn void pre_uart_transfer() - * @brief - * Take a semaphore and setting GPIO, disable IRQ - * @param[in] None - * @return returns void - *****************************************************************************/ -void pre_uart_transfer(void) -{ - if (spi_sem_sync_hdl == NULL) - { - // UART is initialized before host SPI interface - // spi_sem_sync_hdl will not be initalized during execution - GPIO_PinModeSet(gpioPortA, 8, gpioModePushPull, 1); - return; - } - sl_wfx_disable_irq(); - sl_wfx_host_disable_platform_interrupt(); - if (xSemaphoreTake(spi_sem_sync_hdl, portMAX_DELAY) != pdTRUE) - { - return; - } - GPIO_PinModeSet(gpioPortA, 8, gpioModePushPull, 1); -} -/**************************************************************************** - * @fn void post_uart_transfer() - * @brief - * Reset GPIO, enabled IRQ, release semaphore - * @param[in] None - * @return returns void - *****************************************************************************/ -void post_uart_transfer(void) -{ - if (spi_sem_sync_hdl == NULL) - { - return; - } - GPIO_PinModeSet(gpioPortA, 8, gpioModeInputPull, 1); - xSemaphoreGive(spi_sem_sync_hdl); - sl_wfx_host_enable_platform_interrupt(); - sl_wfx_enable_irq(); -} -#endif /* EFR32MG24 && WF200_WIFI */ diff --git a/examples/platform/silabs/efr32/spi_multiplex.h b/examples/platform/silabs/efr32/spi_multiplex.h index 537061f09f9006..0c926b809fab1a 100644 --- a/examples/platform/silabs/efr32/spi_multiplex.h +++ b/examples/platform/silabs/efr32/spi_multiplex.h @@ -15,51 +15,154 @@ * limitations under the License. */ +/* + * This file contains all the functions specific to the MG24 family for + * multiplexing the SPI port with WiFi NCP and other WSTK + * devices such as External Flash and LCD. + * That can be extended to other families as well. + */ + #pragma once +#if defined(EFR32MG24) #ifdef __cplusplus extern "C" { #endif #include "FreeRTOS.h" +#include "em_eusart.h" #include "semphr.h" +#include "sl_memlcd_display.h" #include "sl_mx25_flash_shutdown_usart_config.h" -#include "sl_spidrv_exp_config.h" -#include "sl_wfx_host_api.h" +#include "sl_spidrv_instances.h" #include "spidrv.h" -#define SL_BIT_RATE_LCD 1100000 -#define SL_BIT_RATE_EXP_HDR 16000000 -#define SL_BIT_RATE_SPI_FLASH 10000000 -#define SL_BIT_RATE_UART_CONSOLE 16000000 - -extern SemaphoreHandle_t spi_sem_sync_hdl; +#define SL_SPIDRV_LCD_BITRATE SL_MEMLCD_SCLK_FREQ +#define SL_SPIDRV_MX25_FLASH_BITRATE 16000000 #ifdef RS911X_WIFI -extern SPIDRV_Handle_t sl_spidrv_eusart_exp_handle; +#include "sl_spidrv_eusart_exp_config.h" + +#define SL_SPIDRV_EXP_BITRATE_MULTIPLEXED SL_SPIDRV_EUSART_EXP_BITRATE +#define SL_SPIDRV_UART_CONSOLE_BITRATE SL_UARTDRV_EUSART_VCOM_BAUDRATE +#define SL_SPIDRV_FRAME_LENGTH SL_SPIDRV_EUSART_EXP_FRAME_LENGTH #define SL_SPIDRV_HANDLE sl_spidrv_eusart_exp_handle -#endif -#ifdef WF200_WIFI -extern SPIDRV_Handle_t sl_spidrv_exp_handle; +#elif WF200_WIFI +#include "sl_spidrv_exp_config.h" +#include "sl_wfx_host_api.h" + +// TODO: (MATTER-1906) Investigate why using SL_SPIDRV_EXP_BITRATE is causing WF200 init failure +// REF: sl_spidrv_exp_config.h +#define SL_SPIDRV_EXP_BITRATE_MULTIPLEXED 10000000 +#define SL_SPIDRV_UART_CONSOLE_BITRATE SL_UARTDRV_USART_VCOM_BAUDRATE +#define SL_SPIDRV_FRAME_LENGTH SL_SPIDRV_EXP_FRAME_LENGTH #define SL_SPIDRV_HANDLE sl_spidrv_exp_handle -#endif +#endif /* RS911X_WIFI || WF200_WIFI */ + +/**************************************************************************** + * @fn void SPIDRV_SetBaudrate() + * @brief + * Sets the SPI driver to required baudrate + * @param[in] None + * @return returns void + *****************************************************************************/ +void SPIDRV_SetBaudrate(uint32_t); + +#if defined(RS911X_WIFI) +/**************************************************************************** + * @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(void); + +/**************************************************************************** + * @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(void); +#endif /* RS911X_WIFI */ + +/**************************************************************************** + * @fn sl_status_t sl_wfx_host_spiflash_cs_assert() + * @brief + * Assert SPI flash chip select. + * @param[in] None + * @return returns SL_STATUS_OK + *****************************************************************************/ +sl_status_t sl_wfx_host_spiflash_cs_assert(void); + +/**************************************************************************** + * @fn sl_status_t sl_wfx_host_spiflash_cs_deassert() + * @brief + * De-Assert SPI flash chip select. + * @param[in] None + * @return returns SL_STATUS_OK + *****************************************************************************/ +sl_status_t sl_wfx_host_spiflash_cs_deassert(void); + +/**************************************************************************** + * @fn sl_status_t sl_wfx_host_pre_bootloader_spi_transfer() + * @brief + * Take a semaphore and controlling CS pin for EXP header and SPI flash + * @param[in] None + * @return SL_STATUS_OK + *****************************************************************************/ +sl_status_t sl_wfx_host_pre_bootloader_spi_transfer(void); -void spi_drv_reinit(uint32_t); +/**************************************************************************** + * @fn sl_status_t sl_wfx_host_post_bootloader_spi_transfer() + * @brief + * De-Assert EXT SPI flash CS pin and release semaphore + * @param[in] None + * @return SL_STATUS_OK + *****************************************************************************/ +sl_status_t sl_wfx_host_post_bootloader_spi_transfer(void); -void spiflash_cs_assert(void); -void spiflash_cs_deassert(void); +/**************************************************************************** + * @fn sl_status_t sl_wfx_host_pre_lcd_spi_transfer() + * @brief + * Take a semaphore and setting LCD baudrate + * @param[in] None + * @return SL_STATUS_OK + *****************************************************************************/ +sl_status_t sl_wfx_host_pre_lcd_spi_transfer(void); -void pre_bootloader_spi_transfer(void); -void post_bootloader_spi_transfer(void); +/**************************************************************************** + * @fn sl_status_t sl_wfx_host_post_lcd_spi_transfer() + * @brief + * Release semaphore + * @param[in] None + * @return SL_STATUS_OK + *****************************************************************************/ +sl_status_t sl_wfx_host_post_lcd_spi_transfer(void); -void pre_lcd_spi_transfer(void); -void post_lcd_spi_transfer(void); +#if defined(WF200_WIFI) +/**************************************************************************** + * @fn sl_status_t sl_wfx_host_pre_uart_transfer() + * @brief + * Take a semaphore and setting GPIO, disable IRQ + * @param[in] None + * @return SL_STATUS_OK + *****************************************************************************/ +sl_status_t sl_wfx_host_pre_uart_transfer(void); -#if (defined(EFR32MG24) && defined(WF200_WIFI)) -void pre_uart_transfer(void); -void post_uart_transfer(void); -#endif /* EFR32MG24 && WF200_WIFI */ +/**************************************************************************** + * @fn sl_status_t sl_wfx_host_post_uart_transfer() + * @brief + * Reset GPIO, enabled IRQ, release semaphore + * @param[in] None + * @return SL_STATUS_OK + *****************************************************************************/ +sl_status_t sl_wfx_host_post_uart_transfer(void); +#endif /* WF200_WIFI */ #ifdef __cplusplus } #endif +#endif /* EFR32MG24 */ diff --git a/examples/platform/silabs/efr32/uart.cpp b/examples/platform/silabs/efr32/uart.cpp index 650f482bc65346..183417b3cc128f 100644 --- a/examples/platform/silabs/efr32/uart.cpp +++ b/examples/platform/silabs/efr32/uart.cpp @@ -474,9 +474,9 @@ void uartSendBytes(uint8_t * buffer, uint16_t nbOfBytes) #if (defined(EFR32MG24) && defined(WF200_WIFI)) // Blocking transmit for the MG24 + WF200 since UART TX is multiplexed with // WF200 SPI IRQ - pre_uart_transfer(); + sl_wfx_host_pre_uart_transfer(); UARTDRV_ForceTransmit(vcom_handle, (uint8_t *) buffer, nbOfBytes); - post_uart_transfer(); + sl_wfx_host_post_uart_transfer(); #else // Non Blocking Transmit UARTDRV_Transmit(vcom_handle, (uint8_t *) buffer, nbOfBytes, UART_tx_callback); diff --git a/examples/platform/silabs/efr32/wf200/efr_spi.c b/examples/platform/silabs/efr32/wf200/efr_spi.c index 5c97a294321648..f01069f80d6f28 100644 --- a/examples/platform/silabs/efr32/wf200/efr_spi.c +++ b/examples/platform/silabs/efr32/wf200/efr_spi.c @@ -39,7 +39,6 @@ #include "gpiointerrupt.h" -#include "sl_spidrv_exp_config.h" #include "sl_wfx_board.h" #include "sl_wfx_host.h" #include "sl_wfx_task.h" @@ -49,14 +48,24 @@ #include "sl_power_manager.h" #endif -#if SL_WIFI +#if defined(EFR32MG12) +#include "sl_spidrv_exp_config.h" +extern SPIDRV_Handle_t sl_spidrv_exp_handle; +#define SL_SPIDRV_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; +#else +#error "Unknown platform" #endif #define USART SL_WFX_HOST_PINOUT_SPI_PERIPHERAL +#if defined(EFR32MG24) +StaticSemaphore_t spi_sem_peripheral; +SemaphoreHandle_t spi_sem_sync_hdl; +#endif /* EFR32MG24 */ + StaticSemaphore_t xEfrSpiSemaBuffer; static SemaphoreHandle_t spi_sem; @@ -76,13 +85,6 @@ uint8_t wirq_irq_nb = SL_WFX_HOST_PINOUT_SPI_WIRQ_PIN; // SL_WFX_HOST_PINOUT_SPI #define PIN_OUT_SET 1 #define PIN_OUT_CLEAR 0 -/**************************************************************************** - * @fn sl_status_t sl_wfx_host_init_bus(void) - * @brief - * Initialize SPI peripheral - * @param[in] None - * @return returns SL_STATUS_OK - *****************************************************************************/ sl_status_t sl_wfx_host_init_bus(void) { spi_enabled = true; @@ -112,23 +114,22 @@ sl_status_t sl_wfx_host_init_bus(void) xSemaphoreGive(spi_sem); #if defined(EFR32MG24) - spi_sem_sync_hdl = xSemaphoreCreateBinaryStatic(&spi_sem_peripharal); + if (spi_sem_sync_hdl == NULL) + { + spi_sem_sync_hdl = xSemaphoreCreateBinaryStatic(&spi_sem_peripheral); + } + configASSERT(spi_sem_sync_hdl); xSemaphoreGive(spi_sem_sync_hdl); #endif /* EFR32MG24 */ return SL_STATUS_OK; } -/**************************************************************************** - * @fn sl_status_t sl_wfx_host_deinit_bus(void) - * @brief - * De-initialize SPI peripheral and DMAs - * @param[in] None - * @return returns SL_STATUS_OK - *****************************************************************************/ sl_status_t sl_wfx_host_deinit_bus(void) { vSemaphoreDelete(spi_sem); +#if defined(EFR32MG24) vSemaphoreDelete(spi_sem_sync_hdl); +#endif /* EFR32MG24 */ // Stop DMAs. DMADRV_StopTransfer(rx_dma_channel); DMADRV_StopTransfer(tx_dma_channel); @@ -139,36 +140,22 @@ sl_status_t sl_wfx_host_deinit_bus(void) return SL_STATUS_OK; } -/**************************************************************************** - * @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() { - 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); +#if defined(EFR32MG24) + xSemaphoreTake(spi_sem_sync_hdl, portMAX_DELAY); + SPIDRV_SetBaudrate(SL_SPIDRV_EXP_BITRATE_MULTIPLEXED); +#endif /* EFR32MG24 */ GPIO_PinOutClear(SL_SPIDRV_EXP_CS_PORT, SL_SPIDRV_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_EXP_CS_PORT, SL_SPIDRV_EXP_CS_PIN); +#if defined(EFR32MG24) xSemaphoreGive(spi_sem_sync_hdl); +#endif /* EFR32MG24 */ return SL_STATUS_OK; } @@ -245,22 +232,6 @@ void transmitDMA(uint8_t * buffer, uint16_t buffer_length) dmadrvDataSize1, NULL, NULL); } -/**************************************************************************** - * @fn 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) - * @brief - * WFX SPI transfer implementation - * @param[in] type: - * @param[in] header: - * @param[in] header_length: - * @param[in] buffer: - * @param[in] buffer_length: - * @return returns SL_STATUS_OK if successful, - * SL_STATUS_FAIL otherwise - *****************************************************************************/ 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) { @@ -293,11 +264,7 @@ sl_status_t sl_wfx_host_spi_transfer_no_cs_assert(sl_wfx_host_bus_transfer_type_ MY_USART->CMD = USART_CMD_CLEARRX | USART_CMD_CLEARTX; // Reset the semaphore configASSERT(spi_sem); - if (xSemaphoreTake(spi_sem, portMAX_DELAY) != pdTRUE) - { - return SL_STATUS_TIMEOUT; - } - + xSemaphoreTake(spi_sem, portMAX_DELAY); if (is_read) { receiveDMA(buffer, buffer_length); @@ -307,64 +274,30 @@ sl_status_t sl_wfx_host_spi_transfer_no_cs_assert(sl_wfx_host_bus_transfer_type_ 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; - } + xSemaphoreTake(spi_sem, portMAX_DELAY); xSemaphoreGive(spi_sem); } return SL_STATUS_OK; } -/**************************************************************************** - * @fn void sl_wfx_host_start_platform_interrupt(void) - * @brief - * Enable WFX interrupt - * @param[in] none - * @return None - *****************************************************************************/ void sl_wfx_host_start_platform_interrupt(void) { // Enable (and clear) the bus interrupt GPIO_ExtIntConfig(SL_WFX_HOST_PINOUT_SPI_WIRQ_PORT, SL_WFX_HOST_PINOUT_SPI_WIRQ_PIN, wirq_irq_nb, true, false, true); } -/**************************************************************************** - * @fn sl_status_t sl_wfx_host_disable_platform_interrupt(void) - * @brief - * Disable WFX interrupt - * @param[in] None - * @return returns SL_STATUS_OK if successful, - * SL_STATUS_FAIL otherwise - *****************************************************************************/ sl_status_t sl_wfx_host_disable_platform_interrupt(void) { GPIO_IntDisable(1 << wirq_irq_nb); return SL_STATUS_OK; } -/**************************************************************************** - * @fn sl_status_t sl_wfx_host_enable_platform_interrupt(void) - * @brief - * enable the platform interrupt - * @param[in] None - * @return returns SL_STATUS_OK if successful, - * SL_STATUS_FAIL otherwise - *****************************************************************************/ sl_status_t sl_wfx_host_enable_platform_interrupt(void) { GPIO_IntEnable(1 << wirq_irq_nb); return SL_STATUS_OK; } -/**************************************************************************** - * @fn sl_status_t sl_wfx_host_enable_spi(void) - * @brief - * enable spi - * @param[in] None - * @return returns SL_STATUS_OK if successful, - * SL_STATUS_FAIL otherwise - *****************************************************************************/ sl_status_t sl_wfx_host_enable_spi(void) { if (spi_enabled == false) @@ -374,14 +307,6 @@ sl_status_t sl_wfx_host_enable_spi(void) return SL_STATUS_OK; } -/**************************************************************************** - * @fn sl_status_t sl_wfx_host_disable_spi(void) - * @brief - * disable spi - * @param[in] None - * @return returns SL_STATUS_OK if successful, - * SL_STATUS_FAIL otherwise - *****************************************************************************/ sl_status_t sl_wfx_host_disable_spi(void) { if (spi_enabled == true) @@ -445,3 +370,101 @@ void sl_wfx_host_gpio_init(void) NVIC_SetPriority(GPIO_EVEN_IRQn, 5); NVIC_SetPriority(GPIO_ODD_IRQn, 5); } + +#if defined(EFR32MG24) + +void SPIDRV_SetBaudrate(uint32_t baudrate) +{ + if (USART_BaudrateGet(MY_USART) == baudrate) + { + // USART synced to baudrate already + return; + } + // USART is used in MG24 + WF200 combination + USART_InitSync_TypeDef usartInit = USART_INITSYNC_DEFAULT; + usartInit.msbf = true; + usartInit.clockMode = usartClockMode0; + usartInit.baudrate = baudrate; + uint32_t databits = SL_SPIDRV_FRAME_LENGTH - 4U + _USART_FRAME_DATABITS_FOUR; + usartInit.databits = (USART_Databits_TypeDef) databits; + usartInit.autoCsEnable = true; + + USART_InitSync(MY_USART, &usartInit); +} + +sl_status_t sl_wfx_host_spiflash_cs_assert(void) +{ + GPIO_PinOutClear(SL_MX25_FLASH_SHUTDOWN_CS_PORT, SL_MX25_FLASH_SHUTDOWN_CS_PIN); + return SL_STATUS_OK; +} + +sl_status_t sl_wfx_host_spiflash_cs_deassert(void) +{ + GPIO_PinOutSet(SL_MX25_FLASH_SHUTDOWN_CS_PORT, SL_MX25_FLASH_SHUTDOWN_CS_PIN); + return SL_STATUS_OK; +} + +sl_status_t sl_wfx_host_pre_bootloader_spi_transfer(void) +{ + xSemaphoreTake(spi_sem_sync_hdl, portMAX_DELAY); + /* + * Assert CS pin for EXT SPI Flash + */ + SPIDRV_SetBaudrate(SL_SPIDRV_MX25_FLASH_BITRATE); + sl_wfx_host_spiflash_cs_assert(); + return SL_STATUS_OK; +} + +sl_status_t sl_wfx_host_post_bootloader_spi_transfer(void) +{ + /* + * De-Assert CS pin for EXT SPI Flash + */ + sl_wfx_host_spiflash_cs_deassert(); + xSemaphoreGive(spi_sem_sync_hdl); + return SL_STATUS_OK; +} + +sl_status_t sl_wfx_host_pre_lcd_spi_transfer(void) +{ + xSemaphoreTake(spi_sem_sync_hdl, portMAX_DELAY); + SPIDRV_SetBaudrate(SL_SPIDRV_LCD_BITRATE); + /*LCD CS is handled as part of LCD gsdk*/ + return SL_STATUS_OK; +} + +sl_status_t sl_wfx_host_post_lcd_spi_transfer(void) +{ + xSemaphoreGive(spi_sem_sync_hdl); + return SL_STATUS_OK; +} + +sl_status_t sl_wfx_host_pre_uart_transfer(void) +{ + if (spi_sem_sync_hdl == NULL) + { + // UART is initialized before host SPI interface + // spi_sem_sync_hdl will not be initalized during execution + GPIO_PinModeSet(gpioPortA, 8, gpioModePushPull, 1); + return SL_STATUS_OK; + } + sl_wfx_disable_irq(); + sl_wfx_host_disable_platform_interrupt(); + xSemaphoreTake(spi_sem_sync_hdl, portMAX_DELAY); + GPIO_PinModeSet(gpioPortA, 8, gpioModePushPull, 1); + return SL_STATUS_OK; +} + +sl_status_t sl_wfx_host_post_uart_transfer(void) +{ + if (spi_sem_sync_hdl == NULL) + { + return SL_STATUS_OK; + } + GPIO_PinModeSet(gpioPortA, 8, gpioModeInputPull, 1); + xSemaphoreGive(spi_sem_sync_hdl); + sl_wfx_host_enable_platform_interrupt(); + sl_wfx_enable_irq(); + return SL_STATUS_OK; +} +#endif /* EFR32MG24 */ diff --git a/examples/platform/silabs/efr32/wf200/wf200.gni b/examples/platform/silabs/efr32/wf200/wf200.gni index 372b1d0c8f3b31..4cd2943b12f8fb 100644 --- a/examples/platform/silabs/efr32/wf200/wf200.gni +++ b/examples/platform/silabs/efr32/wf200/wf200.gni @@ -10,5 +10,4 @@ wf200_plat_src = [ "${examples_plat_dir}/wf200/wf200_init.c", "${examples_plat_dir}/wf200/efr_spi.c", "${examples_plat_dir}/wf200/host_if.cpp", - "${examples_plat_dir}/spi_multiplex.c", ] diff --git a/src/platform/silabs/ConnectivityManagerImpl_WIFI.cpp b/src/platform/silabs/ConnectivityManagerImpl_WIFI.cpp index 215cfddb6d37cb..ae3bb69ea4d2b7 100644 --- a/src/platform/silabs/ConnectivityManagerImpl_WIFI.cpp +++ b/src/platform/silabs/ConnectivityManagerImpl_WIFI.cpp @@ -247,7 +247,6 @@ CHIP_ERROR ConnectivityManagerImpl::_RequestSEDActiveMode(bool onOff, bool delay void ConnectivityManagerImpl::DriveStationState() { - CHIP_ERROR err = CHIP_NO_ERROR; sl_status_t serr; bool stationConnected; @@ -260,7 +259,7 @@ void ConnectivityManagerImpl::DriveStationState() // Ensure that the WFX is started. if ((serr = wfx_wifi_start()) != SL_STATUS_OK) { - ChipLogError(DeviceLayer, "wfx_wifi_start() failed: %s", chip::ErrorStr(err)); + ChipLogError(DeviceLayer, "wfx_wifi_start() failed: %lx", serr); return; } // Ensure that station mode is enabled in the WFX WiFi layer. @@ -295,7 +294,7 @@ void ConnectivityManagerImpl::DriveStationState() serr = wfx_sta_discon(); if (serr != SL_STATUS_OK) { - ChipLogError(DeviceLayer, "wfx_wifi_disconnect() failed: %s", chip::ErrorStr(err)); + ChipLogError(DeviceLayer, "wfx_wifi_disconnect() failed: %lx", serr); } SuccessOrExit(serr); diff --git a/src/platform/silabs/efr32/OTAImageProcessorImpl.cpp b/src/platform/silabs/efr32/OTAImageProcessorImpl.cpp index 6d2bce9fdfb41b..85118f9559ac1c 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 // TODO: (MATTER-1905) clean up of MACROs +#include "sl_wfx_host_api.h" +#endif #endif } @@ -77,6 +79,7 @@ CHIP_ERROR OTAImageProcessorImpl::ProcessBlock(ByteSpan & block) if (err != CHIP_NO_ERROR) { ChipLogError(SoftwareUpdate, "Cannot set block data: %" CHIP_ERROR_FORMAT, err.Format()); + return err; } DeviceLayer::PlatformMgr().ScheduleWork(HandleProcessBlock, reinterpret_cast(this)); @@ -122,7 +125,7 @@ void OTAImageProcessorImpl::HandlePrepareDownload(intptr_t context) if (imageProcessor == nullptr) { - ChipLogError(SoftwareUpdate, "ImageProcessor context is null"); + ChipLogError(SoftwareUpdate, "imageProcessor context is null"); return; } else if (imageProcessor->mDownloader == nullptr) @@ -131,7 +134,7 @@ void OTAImageProcessorImpl::HandlePrepareDownload(intptr_t context) return; } - ChipLogProgress(SoftwareUpdate, "HandlePrepareDownload"); + ChipLogProgress(SoftwareUpdate, "HandlePrepareDownload: started"); CORE_CRITICAL_SECTION(bootloader_init();) mSlotId = 0; // Single slot until we support multiple images @@ -152,6 +155,7 @@ void OTAImageProcessorImpl::HandleFinalize(intptr_t context) auto * imageProcessor = reinterpret_cast(context); if (imageProcessor == nullptr) { + ChipLogError(SoftwareUpdate, "imageProcessor context is null"); return; } @@ -166,16 +170,26 @@ void OTAImageProcessorImpl::HandleFinalize(intptr_t context) writeBuffer[writeBufOffset] = 0; writeBufOffset++; } -#if (defined(EFR32MG24) && defined(WF200_WIFI)) - pre_bootloader_spi_transfer(); +#if (defined(EFR32MG24) && defined(SL_WIFI)) + err = sl_wfx_host_pre_bootloader_spi_transfer(); + if (err != SL_STATUS_OK) + { + ChipLogError(SoftwareUpdate, "sl_wfx_host_pre_bootloader_spi_transfer() error: %ld", err); + return; + } #endif CORE_CRITICAL_SECTION(err = bootloader_eraseWriteStorage(mSlotId, mWriteOffset, writeBuffer, kAlignmentBytes);) -#if (defined(EFR32MG24) && defined(WF200_WIFI)) - post_bootloader_spi_transfer(); +#if (defined(EFR32MG24) && defined(SL_WIFI)) + err = sl_wfx_host_post_bootloader_spi_transfer(); + if (err != SL_STATUS_OK) + { + ChipLogError(SoftwareUpdate, "sl_wfx_host_post_bootloader_spi_transfer() error: %ld", err); + return; + } #endif if (err) { - ChipLogError(SoftwareUpdate, "ERROR: In HandleFinalize bootloader_eraseWriteStorage() error %ld", err); + ChipLogError(SoftwareUpdate, "bootloader_eraseWriteStorage() error: %ld", err); imageProcessor->mDownloader->EndDownload(CHIP_ERROR_WRITE_FAILED); return; } @@ -190,38 +204,62 @@ void OTAImageProcessorImpl::HandleApply(intptr_t context) { uint32_t err = SL_BOOTLOADER_OK; - ChipLogProgress(SoftwareUpdate, "OTAImageProcessorImpl::HandleApply()"); + ChipLogProgress(SoftwareUpdate, "HandleApply: started"); // Force KVS to store pending keys such as data from StoreCurrentUpdateInfo() chip::DeviceLayer::PersistedStorage::KeyValueStoreMgrImpl().ForceKeyMapSave(); -#if (defined(EFR32MG24) && defined(WF200_WIFI)) - pre_bootloader_spi_transfer(); +#if (defined(EFR32MG24) && defined(SL_WIFI)) + err = sl_wfx_host_pre_bootloader_spi_transfer(); + if (err != SL_STATUS_OK) + { + ChipLogError(SoftwareUpdate, "sl_wfx_host_pre_bootloader_spi_transfer() error: %ld", err); + return; + } #endif CORE_CRITICAL_SECTION(err = bootloader_verifyImage(mSlotId, NULL);) if (err != SL_BOOTLOADER_OK) { - ChipLogError(SoftwareUpdate, "ERROR: bootloader_verifyImage() error %ld", err); + ChipLogError(SoftwareUpdate, "bootloader_verifyImage() error: %ld", err); // Call the OTARequestor API to reset the state GetRequestorInstance()->CancelImageUpdate(); - +#if (defined(EFR32MG24) && defined(SL_WIFI)) + err = sl_wfx_host_post_bootloader_spi_transfer(); + if (err != SL_STATUS_OK) + { + ChipLogError(SoftwareUpdate, "sl_wfx_host_post_bootloader_spi_transfer() error: %ld", err); + return; + } +#endif return; } CORE_CRITICAL_SECTION(err = bootloader_setImageToBootload(mSlotId);) if (err != SL_BOOTLOADER_OK) { - ChipLogError(SoftwareUpdate, "ERROR: bootloader_setImageToBootload() error %ld", err); + ChipLogError(SoftwareUpdate, "bootloader_setImageToBootload() error: %ld", err); // Call the OTARequestor API to reset the state GetRequestorInstance()->CancelImageUpdate(); - +#if (defined(EFR32MG24) && defined(SL_WIFI)) + err = sl_wfx_host_post_bootloader_spi_transfer(); + if (err != SL_STATUS_OK) + { + ChipLogError(SoftwareUpdate, "sl_wfx_host_post_bootloader_spi_transfer() error: %ld", err); + return; + } +#endif return; } +#if (defined(EFR32MG24) && defined(SL_WIFI)) + err = sl_wfx_host_post_bootloader_spi_transfer(); + if (err != SL_STATUS_OK) + { + ChipLogError(SoftwareUpdate, "sl_wfx_host_post_bootloader_spi_transfer() error: %ld", err); + return; + } +#endif // This reboots the device CORE_CRITICAL_SECTION(bootloader_rebootAndInstall();) -#if (defined(EFR32MG24) && defined(WF200_WIFI)) - xSemaphoreGive(spi_sem_sync_hdl); -#endif } void OTAImageProcessorImpl::HandleAbort(intptr_t context) @@ -229,9 +267,9 @@ void OTAImageProcessorImpl::HandleAbort(intptr_t context) auto * imageProcessor = reinterpret_cast(context); if (imageProcessor == nullptr) { + ChipLogError(SoftwareUpdate, "imageProcessor context is null"); return; } - // Not clearing the image storage area as it is done during each write imageProcessor->ReleaseBlock(); } @@ -242,7 +280,7 @@ void OTAImageProcessorImpl::HandleProcessBlock(intptr_t context) auto * imageProcessor = reinterpret_cast(context); if (imageProcessor == nullptr) { - ChipLogError(SoftwareUpdate, "ImageProcessor context is null"); + ChipLogError(SoftwareUpdate, "imageProcessor context is null"); return; } else if (imageProcessor->mDownloader == nullptr) @@ -256,7 +294,7 @@ void OTAImageProcessorImpl::HandleProcessBlock(intptr_t context) if (chip_error != CHIP_NO_ERROR) { - ChipLogError(SoftwareUpdate, "Matter image header parser error %s", chip::ErrorStr(chip_error)); + ChipLogError(SoftwareUpdate, "Matter image header parser error: %s", chip::ErrorStr(chip_error)); imageProcessor->mDownloader->EndDownload(CHIP_ERROR_INVALID_FILE_IDENTIFIER); return; } @@ -272,16 +310,26 @@ void OTAImageProcessorImpl::HandleProcessBlock(intptr_t context) if (writeBufOffset == kAlignmentBytes) { writeBufOffset = 0; -#if (defined(EFR32MG24) && defined(WF200_WIFI)) - pre_bootloader_spi_transfer(); +#if (defined(EFR32MG24) && defined(SL_WIFI)) + err = sl_wfx_host_pre_bootloader_spi_transfer(); + if (err != SL_STATUS_OK) + { + ChipLogError(SoftwareUpdate, "sl_wfx_host_pre_bootloader_spi_transfer() error: %ld", err); + return; + } #endif CORE_CRITICAL_SECTION(err = bootloader_eraseWriteStorage(mSlotId, mWriteOffset, writeBuffer, kAlignmentBytes);) -#if (defined(EFR32MG24) && defined(WF200_WIFI)) - post_bootloader_spi_transfer(); +#if (defined(EFR32MG24) && defined(SL_WIFI)) + err = sl_wfx_host_post_bootloader_spi_transfer(); + if (err != SL_STATUS_OK) + { + ChipLogError(SoftwareUpdate, "sl_wfx_host_post_bootloader_spi_transfer() error: %ld", err); + return; + } #endif if (err) { - ChipLogError(SoftwareUpdate, "ERROR: In HandleProcessBlock bootloader_eraseWriteStorage() error %ld", err); + ChipLogError(SoftwareUpdate, "bootloader_eraseWriteStorage() error: %ld", err); imageProcessor->mDownloader->EndDownload(CHIP_ERROR_WRITE_FAILED); return; }