/** ****************************************************************************** * @file es_wifi_io.c * @author MCD Application Team * @brief This file implments the IO operations to deal with the es-wifi * module. It mainly Inits and Deinits the SPI interface. Send and * receive data over it. ****************************************************************************** * @attention * *

© Copyright (c) 2017 STMicroelectronics International N.V. * All rights reserved.

* * Redistribution and use in source and binary forms, with or without * modification, are permitted, provided that the following conditions are met: * * 1. Redistribution of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. Neither the name of STMicroelectronics nor the names of other * contributors to this software may be used to endorse or promote products * derived from this software without specific written permission. * 4. This software, including modifications and/or derivative works of this * software, must execute solely and exclusively on microcontroller or * microprocessor devices manufactured by or for STMicroelectronics. * 5. Redistribution and use of this software other than as permitted under * this license is void and will automatically terminate your rights under * this license. * * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "es_wifi.h" #include "es_wifi_io.h" #include #include "es_wifi_conf.h" #include /* Private define ------------------------------------------------------------*/ #define MIN(a, b) ((a) < (b) ? (a) : (b)) /* Private typedef -----------------------------------------------------------*/ /* Private macro -------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ SPI_HandleTypeDef hspi; static int volatile spi_rx_event=0; static int volatile spi_tx_event=0; static int volatile cmddata_rdy_rising_event=0; #ifdef WIFI_USE_CMSIS_OS osMutexId es_wifi_mutex; osMutexDef(es_wifi_mutex); static osMutexId spi_mutex; osMutexDef(spi_mutex); static osSemaphoreId spi_rx_sem; osSemaphoreDef(spi_rx_sem); static osSemaphoreId spi_tx_sem; osSemaphoreDef(spi_tx_sem); static osSemaphoreId cmddata_rdy_rising_sem; osSemaphoreDef(cmddata_rdy_rising_sem); #endif /* Private function prototypes -----------------------------------------------*/ static int wait_cmddata_rdy_high(int timeout); static int wait_cmddata_rdy_rising_event(int timeout); static int wait_spi_tx_event(int timeout); static int wait_spi_rx_event(int timeout); static void SPI_WIFI_DelayUs(uint32_t); /* Private functions ---------------------------------------------------------*/ /******************************************************************************* COM Driver Interface (SPI) *******************************************************************************/ /** * @brief Initialize SPI MSP * @param hspi: SPI handle * @retval None */ void SPI_WIFI_MspInit(SPI_HandleTypeDef* hspi) { GPIO_InitTypeDef GPIO_Init; __HAL_RCC_SPI3_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOE_CLK_ENABLE(); /* configure Wake up pin */ HAL_GPIO_WritePin(GPIOB,GPIO_PIN_13, GPIO_PIN_RESET ); GPIO_Init.Pin = GPIO_PIN_13; GPIO_Init.Mode = GPIO_MODE_OUTPUT_PP; GPIO_Init.Pull = GPIO_NOPULL; GPIO_Init.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOB, &GPIO_Init ); /* configure Data ready pin */ GPIO_Init.Pin = GPIO_PIN_1; GPIO_Init.Mode = GPIO_MODE_IT_RISING; GPIO_Init.Pull = GPIO_NOPULL; GPIO_Init.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOE, &GPIO_Init ); /* configure Reset pin */ GPIO_Init.Pin = GPIO_PIN_8; GPIO_Init.Mode = GPIO_MODE_OUTPUT_PP; GPIO_Init.Pull = GPIO_NOPULL; GPIO_Init.Speed = GPIO_SPEED_FREQ_LOW; GPIO_Init.Alternate = 0; HAL_GPIO_Init(GPIOE, &GPIO_Init ); /* configure SPI NSS pin pin */ HAL_GPIO_WritePin( GPIOE , GPIO_PIN_0, GPIO_PIN_SET ); GPIO_Init.Pin = GPIO_PIN_0; GPIO_Init.Mode = GPIO_MODE_OUTPUT_PP; GPIO_Init.Pull = GPIO_NOPULL; GPIO_Init.Speed = GPIO_SPEED_FREQ_MEDIUM; HAL_GPIO_Init( GPIOE, &GPIO_Init ); /* configure SPI CLK pin */ GPIO_Init.Pin = GPIO_PIN_10; GPIO_Init.Mode = GPIO_MODE_AF_PP; GPIO_Init.Pull = GPIO_NOPULL; GPIO_Init.Speed = GPIO_SPEED_FREQ_MEDIUM; GPIO_Init.Alternate = GPIO_AF6_SPI3; HAL_GPIO_Init(GPIOC, &GPIO_Init ); /* configure SPI MOSI pin */ GPIO_Init.Pin = GPIO_PIN_12; GPIO_Init.Mode = GPIO_MODE_AF_PP; GPIO_Init.Pull = GPIO_NOPULL; GPIO_Init.Speed = GPIO_SPEED_FREQ_MEDIUM; GPIO_Init.Alternate = GPIO_AF6_SPI3; HAL_GPIO_Init( GPIOC, &GPIO_Init ); /* configure SPI MISO pin */ GPIO_Init.Pin = GPIO_PIN_11; GPIO_Init.Mode = GPIO_MODE_AF_PP; GPIO_Init.Pull = GPIO_PULLUP; GPIO_Init.Speed = GPIO_SPEED_FREQ_MEDIUM; GPIO_Init.Alternate = GPIO_AF6_SPI3; HAL_GPIO_Init( GPIOC,&GPIO_Init ); } /** * @brief Initialize the SPI3 * @param None * @retval None */ int8_t SPI_WIFI_Init(uint16_t mode) { int8_t rc=0; if (mode == ES_WIFI_INIT) { hspi.Instance = SPI3; SPI_WIFI_MspInit(&hspi); hspi.Init.Mode = SPI_MODE_MASTER; hspi.Init.Direction = SPI_DIRECTION_2LINES; hspi.Init.DataSize = SPI_DATASIZE_16BIT; hspi.Init.CLKPolarity = SPI_POLARITY_LOW; hspi.Init.CLKPhase = SPI_PHASE_1EDGE; hspi.Init.NSS = SPI_NSS_SOFT; hspi.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8; /* 80/8= 10MHz (Inventek WIFI module supportes up to 20MHz)*/ hspi.Init.FirstBit = SPI_FIRSTBIT_MSB; hspi.Init.TIMode = SPI_TIMODE_DISABLE; hspi.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; hspi.Init.CRCPolynomial = 0; if(HAL_SPI_Init( &hspi ) != HAL_OK) { return -1; } // Enable Interrupt for Data Ready pin , GPIO_PIN1 HAL_NVIC_SetPriority((IRQn_Type)EXTI1_IRQn, 0x0F, 0x00); HAL_NVIC_EnableIRQ((IRQn_Type)EXTI1_IRQn); // Enable Interrupt for SPI tx and rx HAL_NVIC_SetPriority((IRQn_Type)SPI3_IRQn, 1, 0); HAL_NVIC_EnableIRQ((IRQn_Type)SPI3_IRQn); #ifdef WIFI_USE_CMSIS_OS es_wifi_mutex = osRecursiveMutexCreate(osMutex(es_wifi_mutex)); spi_mutex = osRecursiveMutexCreate(osMutex(spi_mutex)); spi_rx_sem = osSemaphoreCreate(osSemaphore(spi_rx_sem) , 1 ); spi_tx_sem = osSemaphoreCreate(osSemaphore(spi_tx_sem) , 1 ); cmddata_rdy_rising_sem = osSemaphoreCreate(osSemaphore(cmddata_rdy_rising_sem) , 1 ); #endif // first call used for calibration SPI_WIFI_DelayUs(10); } rc= SPI_WIFI_ResetModule(); return rc; } int8_t SPI_WIFI_ResetModule(void) { uint32_t tickstart = HAL_GetTick(); uint8_t Prompt[6]; uint8_t count = 0; HAL_StatusTypeDef Status; WIFI_RESET_MODULE(); WIFI_ENABLE_NSS(); SPI_WIFI_DelayUs(15); while (WIFI_IS_CMDDATA_READY()) { Status = HAL_SPI_Receive(&hspi , &Prompt[count], 1, 0xFFFF); count += 2; if(((HAL_GetTick() - tickstart ) > 0xFFFF) || (Status != HAL_OK)) { WIFI_DISABLE_NSS(); return -1; } } WIFI_DISABLE_NSS(); if((Prompt[0] != 0x15) ||(Prompt[1] != 0x15) ||(Prompt[2] != '\r')|| (Prompt[3] != '\n') ||(Prompt[4] != '>') ||(Prompt[5] != ' ')) { return -1; } return 0; } /** * @brief DeInitialize the SPI * @param None * @retval None */ int8_t SPI_WIFI_DeInit(void) { HAL_SPI_DeInit( &hspi ); #ifdef WIFI_USE_CMSIS_OS osMutexDelete(spi_mutex); osMutexDelete(es_wifi_mutex); osSemaphoreDelete(spi_tx_sem); osSemaphoreDelete(spi_rx_sem); osSemaphoreDelete(cmddata_rdy_rising_sem); #endif return 0; } /** * @brief Receive wifi Data from SPI * @param pdata : pointer to data * @param len : Data length * @param timeout : send timeout in mS * @retval Length of received data (payload) */ int wait_cmddata_rdy_high(int timeout) { int tickstart = HAL_GetTick(); while (WIFI_IS_CMDDATA_READY()==0) { if((HAL_GetTick() - tickstart ) > timeout) { return -1; } } return 0; } int wait_cmddata_rdy_rising_event(int timeout) { #ifdef SEM_WAIT return SEM_WAIT(cmddata_rdy_rising_sem, timeout); #else int tickstart = HAL_GetTick(); while (cmddata_rdy_rising_event==1) { if((HAL_GetTick() - tickstart ) > timeout) { return -1; } } return 0; #endif } int wait_spi_rx_event(int timeout) { #ifdef SEM_WAIT return SEM_WAIT(spi_rx_sem, timeout); #else int tickstart = HAL_GetTick(); while (spi_rx_event==1) { if((HAL_GetTick() - tickstart ) > timeout) { return -1; } } return 0; #endif } int wait_spi_tx_event(int timeout) { #ifdef SEM_WAIT return SEM_WAIT(spi_tx_sem, timeout); #else int tickstart = HAL_GetTick(); while (spi_tx_event==1) { if((HAL_GetTick() - tickstart ) > timeout) { return -1; } } return 0; #endif } int16_t SPI_WIFI_ReceiveData(uint8_t *pData, uint16_t len, uint32_t timeout) { int16_t length = 0; uint8_t tmp[2]; WIFI_DISABLE_NSS(); UNLOCK_SPI(); SPI_WIFI_DelayUs(3); if (wait_cmddata_rdy_rising_event(timeout)<0) { return ES_WIFI_ERROR_WAITING_DRDY_FALLING; } LOCK_SPI(); WIFI_ENABLE_NSS(); SPI_WIFI_DelayUs(15); while (WIFI_IS_CMDDATA_READY()) { if((length < len) || (!len)) { spi_rx_event=1; if (HAL_SPI_Receive_IT(&hspi, tmp, 1) != HAL_OK) { WIFI_DISABLE_NSS(); UNLOCK_SPI(); return ES_WIFI_ERROR_SPI_FAILED; } wait_spi_rx_event(timeout); pData[0] = tmp[0]; pData[1] = tmp[1]; length += 2; pData += 2; if (length >= ES_WIFI_DATA_SIZE) { WIFI_DISABLE_NSS(); SPI_WIFI_ResetModule(); UNLOCK_SPI(); return ES_WIFI_ERROR_STUFFING_FOREVER; } } else { break; } } WIFI_DISABLE_NSS(); UNLOCK_SPI(); return length; } /** * @brief Send wifi Data thru SPI * @param pdata : pointer to data * @param len : Data length * @param timeout : send timeout in mS * @retval Length of sent data */ int16_t SPI_WIFI_SendData( uint8_t *pdata, uint16_t len, uint32_t timeout) { uint8_t Padding[2]; if (wait_cmddata_rdy_high(timeout)<0) { return ES_WIFI_ERROR_SPI_FAILED; } // arm to detect rising event cmddata_rdy_rising_event=1; LOCK_SPI(); WIFI_ENABLE_NSS(); SPI_WIFI_DelayUs(15); if (len > 1) { spi_tx_event=1; if( HAL_SPI_Transmit_IT(&hspi, (uint8_t *)pdata , len/2) != HAL_OK) { WIFI_DISABLE_NSS(); UNLOCK_SPI(); return ES_WIFI_ERROR_SPI_FAILED; } wait_spi_tx_event(timeout); } if ( len & 1) { Padding[0] = pdata[len-1]; Padding[1] = '\n'; spi_tx_event=1; if( HAL_SPI_Transmit_IT(&hspi, Padding, 1) != HAL_OK) { WIFI_DISABLE_NSS(); UNLOCK_SPI(); return ES_WIFI_ERROR_SPI_FAILED; } wait_spi_tx_event(timeout); } return len; } /** * @brief Delay * @param Delay in ms * @retval None */ void SPI_WIFI_Delay(uint32_t Delay) { HAL_Delay(Delay); } /** * @brief Delay * @param Delay in us * @retval None */ void SPI_WIFI_DelayUs(uint32_t n) { volatile uint32_t ct; uint32_t loop_per_us; static uint32_t cycle_per_loop=0; // calibration happen on first call for a duration of 1 ms * nbcycle per loop // 10 cycle for STM32L4 if (cycle_per_loop == 0 ) { uint32_t cycle_per_ms = (SystemCoreClock/1000L); uint32_t t; ct=cycle_per_ms; t=HAL_GetTick(); while(ct) ct--; cycle_per_loop=HAL_GetTick()-t; if (cycle_per_loop==0) cycle_per_loop=1; } loop_per_us = SystemCoreClock/1000000/cycle_per_loop; ct = n * loop_per_us; while(ct) ct--; return; } /** * @brief Rx Transfer completed callback. * @param hspi: pointer to a SPI_HandleTypeDef structure that contains * the configuration information for SPI module. * @retval None */ void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi) { if (spi_rx_event) { SEM_SIGNAL(spi_rx_sem); spi_rx_event=0; } } /** * @brief Tx Transfer completed callback. * @param hspi: pointer to a SPI_HandleTypeDef structure that contains * the configuration information for SPI module. * @retval None */ void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi) { if (spi_tx_event) { SEM_SIGNAL(spi_tx_sem); spi_tx_event=0; } } /** * @brief Interrupt handler for Data RDY signal * @param None * @retval None */ void SPI_WIFI_ISR(void) { if (cmddata_rdy_rising_event==1) { SEM_SIGNAL(cmddata_rdy_rising_sem); cmddata_rdy_rising_event=0; } } /** * @} */ /** * @} */ /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/