BLE shield
Fork of X_NUCLEO_IDB0XA1 by
Embed:
(wiki syntax)
Show/hide line numbers
stm32_bluenrg_ble_dma_lp.c
Go to the documentation of this file.
00001 /** 00002 ****************************************************************************** 00003 * @file stm32_bluenrg_ble_dma_lp.c 00004 * @author CL 00005 * @version V1.0.0 00006 * @date 04-July-2014 00007 * @brief 00008 ****************************************************************************** 00009 * @attention 00010 * 00011 * <h2><center>© COPYRIGHT(c) 2014 STMicroelectronics</center></h2> 00012 * 00013 * Redistribution and use in source and binary forms, with or without modification, 00014 * are permitted provided that the following conditions are met: 00015 * 1. Redistributions of source code must retain the above copyright notice, 00016 * this list of conditions and the following disclaimer. 00017 * 2. Redistributions in binary form must reproduce the above copyright notice, 00018 * this list of conditions and the following disclaimer in the documentation 00019 * and/or other materials provided with the distribution. 00020 * 3. Neither the name of STMicroelectronics nor the names of its contributors 00021 * may be used to endorse or promote products derived from this software 00022 * without specific prior written permission. 00023 * 00024 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00025 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00026 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00027 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 00028 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00029 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 00030 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00031 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 00032 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00033 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00034 * 00035 ****************************************************************************** 00036 */ 00037 00038 // ANDREA -- FIXME: to exclude from building when DMA is disabled 00039 #ifdef __DMA_LP__ 00040 00041 /* Includes ------------------------------------------------------------------*/ 00042 #include "stm32_bluenrg_ble_dma_lp.h " 00043 #include "hci_const.h" 00044 00045 /** @addtogroup BSP 00046 * @{ 00047 */ 00048 00049 /** @addtogroup X-NUCLEO-IDB04A1 00050 * @{ 00051 */ 00052 00053 /** @defgroup STM32_BLUENRG_BLE_DMA_LP 00054 * @{ 00055 */ 00056 00057 /** @defgroup STM32_BLUENRG_BLE_DMA_LP_Private_Defines 00058 * @{ 00059 */ 00060 00061 #define TEST_TX_BUFFER_LIMITATION 0 00062 #define MAX_TX_BUFFER_SIZE 0x7F 00063 #define BLUENRG_READY_STATE 0x02 00064 00065 #define HEADER_SIZE 5 00066 #define MAX_BUFFER_SIZE 255 00067 00068 /** 00069 * @} 00070 */ 00071 00072 /** @defgroup STM32_BLUENRG_BLE_DMA_LP_Private_Types 00073 * @{ 00074 */ 00075 00076 typedef enum 00077 { 00078 SPI_HEADER_TRANSMIT, 00079 SPI_PAYLOAD_TRANSMIT 00080 } SPI_TRANSMIT_REQUEST_t; 00081 00082 typedef enum 00083 { 00084 SPI_HEADER_TRANSMITTED, 00085 SPI_PAYLOAD_TRANSMITTED 00086 } SPI_TRANSMIT_EVENT_t; 00087 00088 typedef enum 00089 { 00090 SPI_REQUEST_VALID_HEADER_FOR_RX, 00091 SPI_REQUEST_VALID_HEADER_FOR_TX, 00092 SPI_REQUEST_PAYLOAD 00093 } SPI_RECEIVE_REQUEST_t; 00094 00095 typedef enum 00096 { 00097 SPI_CHECK_RECEIVED_HEADER_FOR_RX, 00098 SPI_CHECK_RECEIVED_HEADER_FOR_TX, 00099 SPI_RECEIVE_END 00100 } SPI_RECEIVE_EVENT_t; 00101 00102 typedef enum 00103 { 00104 SPI_AVAILABLE, 00105 SPI_BUSY 00106 } SPI_PERIPHERAL_STATUS_t; 00107 00108 typedef struct 00109 { 00110 SPI_TRANSMIT_EVENT_t Spi_Transmit_Event; 00111 uint8_t* header_data; 00112 uint8_t* payload_data; 00113 uint8_t header_size; 00114 uint8_t payload_size; 00115 uint8_t payload_size_to_transmit; 00116 uint8_t packet_cont; 00117 uint8_t RequestPending; 00118 } SPI_Transmit_Context_t; 00119 00120 typedef struct 00121 { 00122 SPI_RECEIVE_EVENT_t Spi_Receive_Event; 00123 uint16_t payload_len; 00124 uint8_t* buffer; 00125 uint8_t buffer_size; 00126 } SPI_Receive_Context_t; 00127 00128 typedef struct 00129 { 00130 SPI_HandleTypeDef *hspi; 00131 SPI_PERIPHERAL_STATUS_t Spi_Peripheral_State; 00132 SPI_Receive_Context_t SPI_Receive_Context; 00133 SPI_Transmit_Context_t SPI_Transmit_Context; 00134 } SPI_Context_t; 00135 00136 /** 00137 * @} 00138 */ 00139 00140 /** @defgroup STM32_BLUENRG_BLE_DMA_LP_Private_Variables 00141 * @{ 00142 */ 00143 00144 SPI_HandleTypeDef SpiHandle; 00145 SPI_Context_t SPI_Context; 00146 00147 const uint8_t Write_Header_CMD[HEADER_SIZE] = {0x0a, 0x00, 0x00, 0x00, 0x00}; 00148 const uint8_t Read_Header_CMD[HEADER_SIZE] = {0x0b, 0x00, 0x00, 0x00, 0x00}; 00149 const uint8_t dummy_bytes = 0xFF; 00150 00151 uint8_t Received_Header[HEADER_SIZE]; 00152 00153 #ifdef ENABLE_SPI_FIX 00154 static uint8_t StartupTimerId; 00155 #endif 00156 static uint8_t TxRxTimerId; 00157 volatile uint8_t ubnRFresetTimerLock; 00158 pf_TIMER_TimerCallBack_t pTimerTxRxCallback; 00159 00160 /** 00161 * @} 00162 */ 00163 00164 /** @defgroup STM32_BLUENRG_BLE_DMA_LP_Extern_Variables 00165 * @{ 00166 */ 00167 extern uint8_t* HCI_read_packet; 00168 00169 /** 00170 * @} 00171 */ 00172 00173 /** @defgroup STM32_BLUENRG_BLE_DMA_LP_Private_Function_Prototypes 00174 * @{ 00175 */ 00176 00177 /* Private function prototypes -----------------------------------------------*/ 00178 static void SPI_Transmit_Manager(SPI_TRANSMIT_REQUEST_t TransmitRequest); 00179 static void SPI_Receive_Manager(SPI_RECEIVE_REQUEST_t ReceiveRequest); 00180 static void set_irq_as_output(void); 00181 static void set_irq_as_input(void); 00182 static void Disable_SPI_Receiving_Path(void); 00183 static void Enable_SPI_Receiving_Path(void); 00184 static void Enable_SPI_CS(void); 00185 static void Disable_SPI_CS(void); 00186 static void DisableEnable_SPI_CS(void); 00187 static void TransmitClosure(void); 00188 static void ReceiveClosure(void); 00189 static void ReceiveHeader(SPI_RECEIVE_EVENT_t ReceiveEvent, uint8_t * DataHeader); 00190 static void WakeupBlueNRG(void); 00191 static void TimerStartupCallback(void); 00192 static void TimerTransmitCallback(void); 00193 static void pf_nRFResetTimerCallBack(void); 00194 static void TimerTxRxCallback(void); 00195 static void ProcessEndOfReceive(void); 00196 00197 /** 00198 * @} 00199 */ 00200 00201 /** @defgroup STM32_BLUENRG_BLE_DMA_LP_Exported_Functions 00202 * @{ 00203 */ 00204 00205 /** 00206 * @brief This function notify when then BlueNRG nRESET may be released 00207 * @param None 00208 * @retval None 00209 */ 00210 static void pf_nRFResetTimerCallBack(void) 00211 { 00212 ubnRFresetTimerLock = 0; 00213 00214 return; 00215 } 00216 00217 /** 00218 * @brief Timer callback to handle RxTx Timers 00219 * @param None 00220 * @retval None 00221 */ 00222 static void TimerTxRxCallback(void) 00223 { 00224 pTimerTxRxCallback(); 00225 00226 return; 00227 } 00228 00229 /** 00230 * @brief Close the receiver path 00231 * @param None 00232 * @retval None 00233 */ 00234 static void ReceiveClosure(void) 00235 { 00236 /* 00237 * Disable both DMA 00238 */ 00239 __HAL_DMA_DISABLE(SPI_Context.hspi->hdmatx); 00240 __HAL_DMA_DISABLE(SPI_Context.hspi->hdmarx); 00241 00242 /* 00243 * Check if a command is pending 00244 */ 00245 __disable_irq(); 00246 if(SPI_Context.SPI_Transmit_Context.RequestPending == TRUE) 00247 { 00248 SPI_Context.SPI_Transmit_Context.RequestPending = FALSE; 00249 SPI_Context.Spi_Peripheral_State = SPI_BUSY; 00250 Disable_SPI_Receiving_Path(); 00251 __enable_irq(); 00252 WakeupBlueNRG(); 00253 } 00254 else 00255 { 00256 SPI_Context.Spi_Peripheral_State = SPI_AVAILABLE; 00257 __enable_irq(); 00258 } 00259 00260 return; 00261 } 00262 00263 /** 00264 * @brief Delay Notification to the App to prevent dummy event read 00265 * @param None 00266 * @retval None 00267 */ 00268 static void ProcessEndOfReceive(void) 00269 { 00270 ReceiveClosure(); 00271 00272 HCI_Isr(HCI_read_packet, SPI_Context.SPI_Receive_Context.payload_len); 00273 00274 return; 00275 } 00276 00277 /** 00278 * @brief Timer callback to apply timeout SPI FIX 00279 * @param None 00280 * @retval None 00281 */ 00282 static void TimerTransmitCallback(void) 00283 { 00284 SPI_Receive_Manager(SPI_REQUEST_VALID_HEADER_FOR_TX); /**< BlueNRG not ready for writing */ 00285 LPM_Mode_Request(eLPM_SPI_TX, eLPM_Mode_Sleep); 00286 00287 return; 00288 } 00289 00290 /** 00291 * @brief Closes the SPI when BLE is disabled by the application 00292 * Releases allocated resources 00293 * @param None 00294 * @retval None 00295 */ 00296 void BNRG_SPI_Close(void) 00297 { 00298 #ifdef ENABLE_SPI_FIX 00299 TIMER_Delete(StartupTimerId); 00300 #endif 00301 TIMER_Delete(TxRxTimerId); 00302 00303 return; 00304 } 00305 00306 /** 00307 * @brief Initializes the SPI communication with the BlueNRG Shield. 00308 * @param None 00309 * @retval None 00310 */ 00311 void BNRG_SPI_Init(void) 00312 { 00313 BNRG_MSP_SPI_Init(&SpiHandle); 00314 00315 SPI_Context.hspi = &SpiHandle; 00316 00317 SPI_Context.Spi_Peripheral_State = SPI_AVAILABLE; 00318 SPI_Context.SPI_Transmit_Context.RequestPending = FALSE; 00319 00320 __HAL_BLUENRG_SPI_ENABLE_DMAREQ(&SpiHandle, SPI_CR2_RXDMAEN | SPI_CR2_TXDMAEN); 00321 00322 __HAL_SPI_ENABLE(&SpiHandle); 00323 00324 #ifdef ENABLE_SPI_FIX 00325 TIMER_Create(eTimerModuleID_Interrupt, &StartupTimerId, eTimerMode_SingleShot, TimerStartupCallback); 00326 #endif 00327 TIMER_Create(eTimerModuleID_Interrupt, &TxRxTimerId, eTimerMode_SingleShot, TimerTxRxCallback); 00328 return; 00329 } 00330 00331 /** 00332 * @brief Initializes the SPI communication with the BlueNRG Shield 00333 * @param None 00334 * @retval None 00335 */ 00336 void BNRG_MSP_SPI_Init(SPI_HandleTypeDef * hspi) 00337 { 00338 hspi->Instance = BNRG_SPI_INSTANCE; 00339 hspi->Init.Mode = BNRG_SPI_MODE; 00340 hspi->Init.Direction = BNRG_SPI_DIRECTION; 00341 hspi->Init.DataSize = BNRG_SPI_DATASIZE; 00342 hspi->Init.CLKPolarity = BNRG_SPI_CLKPOLARITY; 00343 hspi->Init.CLKPhase = BNRG_SPI_CLKPHASE; 00344 hspi->Init.NSS = BNRG_SPI_NSS; 00345 hspi->Init.FirstBit = BNRG_SPI_FIRSTBIT; 00346 hspi->Init.TIMode = BNRG_SPI_TIMODE; 00347 hspi->Init.CRCPolynomial = BNRG_SPI_CRCPOLYNOMIAL; 00348 hspi->Init.BaudRatePrescaler = BNRG_SPI_BAUDRATEPRESCALER; 00349 hspi->Init.CRCCalculation = BNRG_SPI_CRCCALCULATION; 00350 00351 HAL_SPI_Init(hspi); 00352 00353 return; 00354 } 00355 00356 /** 00357 * @brief Resets the BlueNRG. 00358 * @param None 00359 * @retval None 00360 */ 00361 void BlueNRG_RST(void) 00362 { 00363 uint8_t ubnRFResetTimerID; 00364 00365 GPIO_InitTypeDef GPIO_InitStruct; 00366 00367 GPIO_InitStruct.Pin = BNRG_SPI_RESET_PIN; 00368 GPIO_InitStruct.Speed = BNRG_SPI_RESET_SPEED; 00369 TIMER_Create(eTimerModuleID_Interrupt, &ubnRFResetTimerID, eTimerMode_SingleShot, pf_nRFResetTimerCallBack); 00370 00371 BNRG_SPI_RESET_CLK_ENABLE(); 00372 00373 HAL_GPIO_WritePin(BNRG_SPI_RESET_PORT, BNRG_SPI_RESET_PIN, GPIO_PIN_RESET); 00374 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; 00375 GPIO_InitStruct.Pull = GPIO_NOPULL; 00376 HAL_GPIO_Init(BNRG_SPI_RESET_PORT, &GPIO_InitStruct); 00377 00378 TIMER_Start(ubnRFResetTimerID, BLUENRG_HOLD_TIME_IN_RESET); 00379 ubnRFresetTimerLock = 1; 00380 while(ubnRFresetTimerLock == 1); 00381 00382 HAL_GPIO_WritePin(BNRG_SPI_RESET_PORT, BNRG_SPI_RESET_PIN, GPIO_PIN_SET); 00383 00384 #if 1 00385 /* 00386 * Limitation in HAL V1.1.0 00387 * The HAL_GPIO_Init() is first configuring the Mode of the IO before the Pull UP configuration 00388 * To avoid glitch on the IO, the configuration shall go through an extra step OUTPUT/PULLUP 00389 * to set upfront the PULL UP configuration. 00390 */ 00391 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; 00392 GPIO_InitStruct.Pull = GPIO_PULLUP; 00393 HAL_GPIO_Init(BNRG_SPI_RESET_PORT, &GPIO_InitStruct); 00394 #endif 00395 00396 GPIO_InitStruct.Mode = GPIO_MODE_INPUT; 00397 GPIO_InitStruct.Pull = GPIO_PULLUP; 00398 HAL_GPIO_Init(BNRG_SPI_RESET_PORT, &GPIO_InitStruct); 00399 00400 TIMER_Start(ubnRFResetTimerID, BLUENRG_HOLD_TIME_AFTER_RESET); 00401 ubnRFresetTimerLock = 1; 00402 while(ubnRFresetTimerLock == 1); 00403 TIMER_Delete(ubnRFResetTimerID); 00404 00405 return; 00406 } 00407 00408 /** 00409 * @brief Writes data from local buffer to SPI. 00410 * @param hspi: SPI handle 00411 * @param header_data: First data buffer to be written 00412 * @param payload_data: Second data buffer to be written 00413 * @param header_size: Size of first data buffer to be written 00414 * @param payload_size: Size of second data buffer to be written 00415 * @retval Number of read bytes 00416 */ 00417 void BlueNRG_SPI_Write(uint8_t* header_data, uint8_t* payload_data, uint8_t header_size, uint8_t payload_size) 00418 { 00419 SPI_Context.SPI_Transmit_Context.header_data = header_data; 00420 SPI_Context.SPI_Transmit_Context.payload_data = payload_data; 00421 SPI_Context.SPI_Transmit_Context.header_size = header_size; 00422 SPI_Context.SPI_Transmit_Context.payload_size = payload_size; 00423 00424 SPI_Context.SPI_Transmit_Context.packet_cont = FALSE; 00425 00426 __disable_irq(); 00427 if(SPI_Context.Spi_Peripheral_State == SPI_AVAILABLE) 00428 { 00429 SPI_Context.Spi_Peripheral_State = SPI_BUSY; 00430 Disable_SPI_Receiving_Path(); 00431 __enable_irq(); 00432 WakeupBlueNRG(); 00433 } 00434 else 00435 { 00436 SPI_Context.SPI_Transmit_Context.RequestPending = TRUE; 00437 __enable_irq(); 00438 } 00439 00440 return; 00441 } 00442 00443 /** 00444 * @brief Set in Output mode the IRQ. 00445 * @param None 00446 * @retval None 00447 */ 00448 static void set_irq_as_output(void) 00449 { 00450 HAL_GPIO_WritePin(BNRG_SPI_IRQ_PORT, BNRG_SPI_IRQ_PIN, GPIO_PIN_SET); 00451 HAL_LPPUART_GPIO_Set_Mode(BNRG_SPI_IRQ_PORT, BNRG_SPI_IRQ_PIN_POSITION, GPIO_MODE_OUTPUT_PP); 00452 __HAL_GPIO_EXTI_CLEAR_IT(BNRG_SPI_IRQ_PIN); 00453 } 00454 00455 /** 00456 * @brief Set the IRQ in input mode. 00457 * @param None 00458 * @retval None 00459 */ 00460 static void set_irq_as_input(void) 00461 { 00462 HAL_GPIO_WritePin(BNRG_SPI_IRQ_PORT, BNRG_SPI_IRQ_PIN, GPIO_PIN_RESET); // WARNING: it may conflict with BlueNRG driving High 00463 HAL_LPPUART_GPIO_Set_Mode(BNRG_SPI_IRQ_PORT, BNRG_SPI_IRQ_PIN_POSITION, GPIO_MODE_INPUT); 00464 } 00465 00466 /** 00467 * @brief Enable SPI IRQ. 00468 * @param None 00469 * @retval None 00470 */ 00471 static void Enable_SPI_Receiving_Path(void) 00472 { 00473 __HAL_GPIO_EXTI_CLEAR_IT(BNRG_SPI_EXTI_PIN); 00474 HAL_NVIC_ClearPendingIRQ(BNRG_SPI_EXTI_IRQn); 00475 HAL_NVIC_EnableIRQ(BNRG_SPI_EXTI_IRQn); 00476 00477 if (HAL_GPIO_ReadPin(BNRG_SPI_IRQ_PORT, BNRG_SPI_IRQ_PIN) == GPIO_PIN_SET) 00478 { 00479 __HAL_GPIO_EXTI_GENERATE_SWIT(BNRG_SPI_IRQ_PIN); 00480 } 00481 } 00482 00483 /** 00484 * @brief Disable SPI IRQ. 00485 * @param None 00486 * @retval None 00487 */ 00488 static void Disable_SPI_Receiving_Path(void) 00489 { 00490 HAL_NVIC_DisableIRQ(BNRG_SPI_EXTI_IRQn); 00491 } 00492 00493 /** 00494 * @brief Enable SPI CS. 00495 * @param None 00496 * @retval None 00497 */ 00498 static void Enable_SPI_CS(void) 00499 { 00500 /* CS reset */ 00501 HAL_GPIO_WritePin(BNRG_SPI_CS_PORT, BNRG_SPI_CS_PIN, GPIO_PIN_RESET); 00502 } 00503 00504 /** 00505 * @brief Disable SPI CS. 00506 * @param None 00507 * @retval None 00508 */ 00509 static void Disable_SPI_CS(void) 00510 { 00511 while (__HAL_SPI_GET_FLAG(SPI_Context.hspi,SPI_FLAG_BSY) == SET); 00512 00513 /* CS set */ 00514 HAL_GPIO_WritePin(BNRG_SPI_CS_PORT, BNRG_SPI_CS_PIN, GPIO_PIN_SET); 00515 } 00516 00517 /** 00518 * @brief Disable and Enable SPI CS. 00519 * @param None 00520 * @retval None 00521 */ 00522 static void DisableEnable_SPI_CS(void) 00523 { 00524 while (__HAL_SPI_GET_FLAG(SPI_Context.hspi,SPI_FLAG_BSY) == SET); 00525 00526 /* CS set */ 00527 HAL_GPIO_WritePin(BNRG_SPI_CS_PORT, BNRG_SPI_CS_PIN, GPIO_PIN_SET); 00528 00529 /* CS reset */ 00530 HAL_GPIO_WritePin(BNRG_SPI_CS_PORT, BNRG_SPI_CS_PIN, GPIO_PIN_RESET); 00531 } 00532 00533 /** 00534 * @brief Tx and Rx Transfer completed callbacks 00535 * @param hspi: pointer to a SPI_HandleTypeDef structure that contains 00536 * the configuration information for SPI module. 00537 * @retval None 00538 */ 00539 void BlueNRG_DMA_RxCallback(void) 00540 { 00541 uint16_t byte_count; 00542 uint8_t ready_state; 00543 00544 __HAL_DMA_CLEAR_FLAG(SPI_Context.hspi->hdmarx, BNRG_SPI_RX_DMA_TC_FLAG); 00545 00546 /** 00547 * The TCIF shall be cleared to be able to start a new DMA transmission later on when required. 00548 * When receiving data, the TCIE is not set as there is no need to handle the interrupt 00549 * handler of the DMA_Tx. 00550 * The TCIF clearing is mandatory on STM32F4 but not on STM32L0. 00551 * In order to keep code identical across platform, the TCIF clearing may be kept as well on 00552 * the STM32L0 and all other MCUs. 00553 */ 00554 __HAL_DMA_CLEAR_FLAG(SPI_Context.hspi->hdmatx, BNRG_SPI_TX_DMA_TC_FLAG); 00555 switch (SPI_Context.SPI_Receive_Context.Spi_Receive_Event) 00556 { 00557 case SPI_CHECK_RECEIVED_HEADER_FOR_RX: 00558 byte_count = (Received_Header[4]<<8)|Received_Header[3]; 00559 ready_state = Received_Header[0]; 00560 00561 if ((byte_count == 0) || (ready_state != BLUENRG_READY_STATE)) 00562 { 00563 if (HAL_GPIO_ReadPin(BNRG_SPI_IRQ_PORT, BNRG_SPI_IRQ_PIN) == GPIO_PIN_RESET) 00564 { 00565 /** 00566 * This USE CASE shall never happen as this may break the IRQ/CS specification 00567 * The IRQ line shall never be low when CS is low to avoid BlueNRG race condition when 00568 * entering low power mode 00569 * the SPI_END_RECEIVE_FIX has been implemented to make sure this USE CASE never occurs 00570 * However, even when the behavior is not compliant to the specification, the BlueNRG 00571 * may not fail so it is increasing robustness by adding this checking just in case the 00572 * timeout define in the workaround is too short which will end up to marginally brake 00573 * the specification. 00574 * This checking will poping BluenRG for a dummy even 00575 */ 00576 00577 /* Release CS line */ 00578 Disable_SPI_CS(); 00579 00580 LPM_Mode_Request(eLPM_SPI_RX, eLPM_Mode_LP_Stop); 00581 00582 ReceiveClosure(); 00583 } 00584 else 00585 { 00586 DisableEnable_SPI_CS(); 00587 SPI_Receive_Manager(SPI_REQUEST_VALID_HEADER_FOR_RX); /**< BlueNRG not ready for reading */ 00588 } 00589 } 00590 else 00591 { 00592 SPI_Receive_Manager(SPI_REQUEST_PAYLOAD); /**< BlueNRG is ready for reading */ 00593 } 00594 break; 00595 00596 case SPI_RECEIVE_END: 00597 /* Release CS line */ 00598 Disable_SPI_CS(); 00599 00600 LPM_Mode_Request(eLPM_SPI_RX, eLPM_Mode_LP_Stop); 00601 00602 #if (SPI_END_RECEIVE_FIX == 1) 00603 pTimerTxRxCallback = ProcessEndOfReceive; 00604 TIMER_Start(TxRxTimerId, SPI_END_RECEIVE_FIX_TIMEOUT); 00605 #else 00606 ProcessEndOfReceive(); 00607 #endif 00608 break; 00609 00610 case SPI_CHECK_RECEIVED_HEADER_FOR_TX: 00611 byte_count = (Received_Header[2]<<8)|Received_Header[1]; 00612 ready_state = Received_Header[0]; 00613 00614 if ((byte_count == 0) || (ready_state != BLUENRG_READY_STATE)) 00615 { 00616 DisableEnable_SPI_CS(); 00617 SPI_Receive_Manager(SPI_REQUEST_VALID_HEADER_FOR_TX); /**< BlueNRG not ready for writing */ 00618 } 00619 else 00620 { 00621 #if (TEST_TX_BUFFER_LIMITATION == 1) 00622 if(byte_count > MAX_TX_BUFFER_SIZE) 00623 { 00624 byte_count = MAX_TX_BUFFER_SIZE; 00625 } 00626 #endif 00627 00628 if(SPI_Context.SPI_Transmit_Context.packet_cont != TRUE) 00629 { 00630 if( byte_count < (SPI_Context.SPI_Transmit_Context.header_size + SPI_Context.SPI_Transmit_Context.payload_size)) 00631 { 00632 SPI_Context.SPI_Transmit_Context.payload_size_to_transmit = byte_count - SPI_Context.SPI_Transmit_Context.header_size; 00633 SPI_Context.SPI_Transmit_Context.payload_size -= SPI_Context.SPI_Transmit_Context.payload_size_to_transmit; 00634 SPI_Context.SPI_Transmit_Context.packet_cont = TRUE; 00635 } 00636 else 00637 { 00638 SPI_Context.SPI_Transmit_Context.payload_size_to_transmit = SPI_Context.SPI_Transmit_Context.payload_size; 00639 } 00640 00641 SPI_Transmit_Manager(SPI_HEADER_TRANSMIT); 00642 } 00643 else 00644 { 00645 if( byte_count < SPI_Context.SPI_Transmit_Context.payload_size) 00646 { 00647 SPI_Context.SPI_Transmit_Context.payload_size_to_transmit = byte_count; 00648 SPI_Context.SPI_Transmit_Context.payload_size -= SPI_Context.SPI_Transmit_Context.payload_size_to_transmit; 00649 } 00650 else 00651 { 00652 SPI_Context.SPI_Transmit_Context.payload_size_to_transmit = SPI_Context.SPI_Transmit_Context.payload_size; 00653 SPI_Context.SPI_Transmit_Context.payload_size = 0; 00654 } 00655 00656 SPI_Transmit_Manager(SPI_PAYLOAD_TRANSMIT); 00657 } 00658 } 00659 00660 break; 00661 00662 default: 00663 break; 00664 } 00665 } 00666 00667 #ifdef ENABLE_SPI_FIX 00668 /** 00669 * @brief Wakeup BlueNRG 00670 * @param None 00671 * @retval None 00672 */ 00673 static void WakeupBlueNRG(void) 00674 { 00675 Disable_SPI_Receiving_Path(); 00676 pTimerTxRxCallback = TimerTransmitCallback; 00677 set_irq_as_output(); 00678 TIMER_Start(StartupTimerId, SPI_FIX_TIMEOUT); 00679 TIMER_Start(TxRxTimerId, SPI_FIX_TIMEOUT+SPI_TX_TIMEOUT); 00680 LPM_Mode_Request(eLPM_SPI_TX, eLPM_Mode_LP_Stop); 00681 00682 return; 00683 } 00684 00685 /** 00686 * @brief Timer callback to apply timeout SPI FIX 00687 * @param None 00688 * @retval None 00689 */ 00690 static void TimerStartupCallback(void) 00691 { 00692 Enable_SPI_CS(); 00693 00694 return; 00695 } 00696 00697 #else 00698 /** 00699 * @brief Wakeup BlueNRG 00700 * @param None 00701 * @retval None 00702 */ 00703 static void WakeupBlueNRG(void) 00704 { 00705 Disable_SPI_Receiving_Path(); 00706 pTimerTxRxCallback = TimerTransmitCallback; 00707 Enable_SPI_CS(); 00708 TIMER_Start(TxRxTimerId, SPI_TX_TIMEOUT); 00709 LPM_Mode_Request(eLPM_SPI_TX, eLPM_Mode_LP_Stop); 00710 00711 return; 00712 } 00713 #endif /* ENABLE_SPI_FIX */ 00714 00715 /** 00716 * @brief Tx and Rx Transfer completed callbacks 00717 * @param hspi: pointer to a SPI_HandleTypeDef structure that contains 00718 * the configuration information for SPI module. 00719 * @retval None 00720 */ 00721 void BlueNRG_DMA_TxCallback(void) 00722 { 00723 __HAL_DMA_CLEAR_FLAG(SPI_Context.hspi->hdmatx, BNRG_SPI_TX_DMA_TC_FLAG); 00724 00725 switch (SPI_Context.SPI_Transmit_Context.Spi_Transmit_Event) 00726 { 00727 case SPI_HEADER_TRANSMITTED: 00728 if(SPI_Context.SPI_Transmit_Context.payload_size_to_transmit != 0) 00729 { 00730 SPI_Transmit_Manager(SPI_PAYLOAD_TRANSMIT); 00731 } 00732 else 00733 { 00734 TransmitClosure(); 00735 } 00736 break; 00737 00738 case SPI_PAYLOAD_TRANSMITTED: 00739 if( (SPI_Context.SPI_Transmit_Context.packet_cont == TRUE) && (SPI_Context.SPI_Transmit_Context.payload_size != 0)) 00740 { 00741 SPI_Context.SPI_Transmit_Context.payload_data += SPI_Context.SPI_Transmit_Context.payload_size_to_transmit; 00742 DisableEnable_SPI_CS(); 00743 SPI_Receive_Manager(SPI_REQUEST_VALID_HEADER_FOR_TX); 00744 } 00745 else 00746 { 00747 TransmitClosure(); 00748 } 00749 break; 00750 00751 default: 00752 break; 00753 } 00754 00755 return; 00756 } 00757 00758 /** 00759 * @brief Close the transmit mechanism after packet has been sent 00760 * Wait for the event to come back 00761 * @param None 00762 * @retval None 00763 */ 00764 static void TransmitClosure(void) 00765 { 00766 LPM_Mode_Request(eLPM_SPI_TX, eLPM_Mode_LP_Stop); 00767 SPI_Context.Spi_Peripheral_State = SPI_AVAILABLE; 00768 Disable_SPI_CS(); 00769 /* 00770 * Disable both DMA 00771 */ 00772 __HAL_DMA_DISABLE(SPI_Context.hspi->hdmatx); 00773 __HAL_DMA_DISABLE(SPI_Context.hspi->hdmarx); 00774 Enable_SPI_Receiving_Path(); 00775 00776 return; 00777 } 00778 00779 /** 00780 * @brief Manage the SPI transmit 00781 * @param TransmitRequest: the transmit request 00782 * @retval None 00783 */ 00784 static void SPI_Transmit_Manager(SPI_TRANSMIT_REQUEST_t TransmitRequest) 00785 { 00786 /* 00787 * Disable both DMA 00788 */ 00789 __HAL_DMA_DISABLE(SPI_Context.hspi->hdmatx); 00790 __HAL_DMA_DISABLE(SPI_Context.hspi->hdmarx); 00791 00792 __HAL_DMA_DISABLE_IT(SPI_Context.hspi->hdmarx, DMA_IT_TC); /**< Disable Receive packet notification */ 00793 00794 __HAL_DMA_CLEAR_FLAG(SPI_Context.hspi->hdmatx, BNRG_SPI_TX_DMA_TC_FLAG); /**< Clear flag in DMA */ 00795 HAL_NVIC_ClearPendingIRQ(BNRG_SPI_DMA_TX_IRQn); /**< Clear DMA pending bit in NVIC */ 00796 __HAL_DMA_ENABLE_IT(SPI_Context.hspi->hdmatx, DMA_IT_TC); /**< Enable Transmit packet notification */ 00797 00798 __HAL_BLUENRG_DMA_SET_MINC(SPI_Context.hspi->hdmatx); /**< Configure DMA to send Tx packet */ 00799 00800 switch (TransmitRequest) 00801 { 00802 case SPI_HEADER_TRANSMIT: 00803 SPI_Context.SPI_Transmit_Context.Spi_Transmit_Event = SPI_HEADER_TRANSMITTED; 00804 00805 #ifdef ENABLE_SPI_FIX 00806 set_irq_as_input(); 00807 #endif 00808 00809 __HAL_BLUENRG_DMA_SET_COUNTER(SPI_Context.hspi->hdmatx, SPI_Context.SPI_Transmit_Context.header_size); /**< Set counter in DMA TX */ 00810 __HAL_BLUENRG_DMA_SET_MEMORY_ADDRESS(SPI_Context.hspi->hdmatx, (uint32_t)SPI_Context.SPI_Transmit_Context.header_data); /**< Set memory address in DMA TX */ 00811 break; 00812 00813 case SPI_PAYLOAD_TRANSMIT: 00814 SPI_Context.SPI_Transmit_Context.Spi_Transmit_Event = SPI_PAYLOAD_TRANSMITTED; 00815 00816 __HAL_BLUENRG_DMA_SET_COUNTER(SPI_Context.hspi->hdmatx, SPI_Context.SPI_Transmit_Context.payload_size_to_transmit); /**< Set counter in DMA TX */ 00817 __HAL_BLUENRG_DMA_SET_MEMORY_ADDRESS(SPI_Context.hspi->hdmatx, (uint32_t)SPI_Context.SPI_Transmit_Context.payload_data); /**< Set memory address in DMA TX */ 00818 break; 00819 00820 default: 00821 break; 00822 } 00823 00824 __HAL_DMA_ENABLE(SPI_Context.hspi->hdmatx); /**< Enable DMA TX */ 00825 00826 } 00827 00828 /** 00829 * @brief Manage the SPI receive 00830 * @param ReceiveRequest: the receive request 00831 * @retval None 00832 */ 00833 static void SPI_Receive_Manager(SPI_RECEIVE_REQUEST_t ReceiveRequest) 00834 { 00835 uint16_t byte_count; 00836 uint8_t localloop; 00837 00838 /* 00839 * Disable both DMA 00840 */ 00841 __HAL_DMA_DISABLE(SPI_Context.hspi->hdmatx); 00842 __HAL_DMA_DISABLE(SPI_Context.hspi->hdmarx); 00843 00844 /** 00845 * Flush the Rx register or FIFO 00846 */ 00847 for (localloop = 0 ; localloop < SPI_FIFO_RX_DEPTH ; localloop++) 00848 { 00849 *(volatile uint8_t*)__HAL_BLUENRG_SPI_GET_RX_DATA_REGISTER_ADDRESS(SPI_Context.hspi); 00850 } 00851 00852 __HAL_DMA_ENABLE_IT(SPI_Context.hspi->hdmarx, DMA_IT_TC); /**< Enable Receive packet notification */ 00853 __HAL_DMA_DISABLE_IT(SPI_Context.hspi->hdmatx, DMA_IT_TC); /**< Disable Transmit packet notification */ 00854 00855 switch (ReceiveRequest) 00856 { 00857 case SPI_REQUEST_VALID_HEADER_FOR_RX: 00858 ReceiveHeader(SPI_CHECK_RECEIVED_HEADER_FOR_RX, (uint8_t *)Read_Header_CMD); 00859 break; 00860 00861 case SPI_REQUEST_VALID_HEADER_FOR_TX: 00862 ReceiveHeader(SPI_CHECK_RECEIVED_HEADER_FOR_TX, (uint8_t *)Write_Header_CMD); 00863 break; 00864 00865 case SPI_REQUEST_PAYLOAD: 00866 SPI_Context.SPI_Receive_Context.Spi_Receive_Event = SPI_RECEIVE_END; 00867 00868 /* 00869 * Check data to received is not available buffer size 00870 */ 00871 byte_count = (Received_Header[4]<<8)|Received_Header[3]; 00872 if (byte_count > SPI_Context.SPI_Receive_Context.buffer_size) 00873 { 00874 byte_count = SPI_Context.SPI_Receive_Context.buffer_size; 00875 } 00876 SPI_Context.SPI_Receive_Context.payload_len = byte_count; 00877 00878 __HAL_BLUENRG_DMA_CLEAR_MINC(SPI_Context.hspi->hdmatx); /**< Configure DMA to send same Byte */ 00879 00880 /* 00881 * Set counter in both DMA 00882 */ 00883 __HAL_BLUENRG_DMA_SET_COUNTER(SPI_Context.hspi->hdmarx, byte_count); 00884 __HAL_BLUENRG_DMA_SET_COUNTER(SPI_Context.hspi->hdmatx, byte_count); 00885 00886 /* 00887 * Set memory address in both DMA 00888 */ 00889 __HAL_BLUENRG_DMA_SET_MEMORY_ADDRESS(SPI_Context.hspi->hdmarx, (uint32_t)SPI_Context.SPI_Receive_Context.buffer); 00890 __HAL_BLUENRG_DMA_SET_MEMORY_ADDRESS(SPI_Context.hspi->hdmatx, (uint32_t)&dummy_bytes); 00891 break; 00892 00893 default: 00894 break; 00895 } 00896 00897 /* 00898 * Enable both DMA - Rx First 00899 */ 00900 __HAL_DMA_ENABLE(SPI_Context.hspi->hdmarx); 00901 __HAL_DMA_ENABLE(SPI_Context.hspi->hdmatx); 00902 00903 return; 00904 } 00905 00906 /** 00907 * @brief Receive header 00908 * @param hspi: pointer to a SPI_HandleTypeDef structure that contains 00909 * the configuration information for SPI module. 00910 * @retval None 00911 */ 00912 static void ReceiveHeader(SPI_RECEIVE_EVENT_t ReceiveEvent, uint8_t * DataHeader) 00913 { 00914 SPI_Context.SPI_Receive_Context.Spi_Receive_Event = ReceiveEvent; 00915 00916 __HAL_BLUENRG_DMA_SET_MINC(SPI_Context.hspi->hdmatx); /**< Configure DMA to send Tx packet */ 00917 00918 /* 00919 * Set counter in both DMA 00920 */ 00921 __HAL_BLUENRG_DMA_SET_COUNTER(SPI_Context.hspi->hdmatx, HEADER_SIZE); 00922 __HAL_BLUENRG_DMA_SET_COUNTER(SPI_Context.hspi->hdmarx, HEADER_SIZE); 00923 00924 /* 00925 * Set memory address in both DMA 00926 */ 00927 __HAL_BLUENRG_DMA_SET_MEMORY_ADDRESS(SPI_Context.hspi->hdmarx, (uint32_t)Received_Header); 00928 __HAL_BLUENRG_DMA_SET_MEMORY_ADDRESS(SPI_Context.hspi->hdmatx, (uint32_t)DataHeader); 00929 00930 return; 00931 } 00932 00933 /** 00934 * @brief BlueNRG SPI request event 00935 * @param buffer: the event 00936 * @param buff_size: the event size 00937 * @retval None 00938 */ 00939 void BlueNRG_SPI_Request_Events(uint8_t *buffer, uint8_t buff_size) 00940 { 00941 SPI_Context.SPI_Receive_Context.buffer = buffer; 00942 SPI_Context.SPI_Receive_Context.buffer_size = buff_size; 00943 00944 Enable_SPI_Receiving_Path(); 00945 00946 return; 00947 } 00948 00949 /** 00950 * @brief BlueNRG SPI IRQ Callback 00951 * @param None 00952 * @retval None 00953 */ 00954 void BlueNRG_SPI_IRQ_Callback(void) 00955 { 00956 __disable_irq(); 00957 if(SPI_Context.Spi_Peripheral_State == SPI_AVAILABLE) 00958 { 00959 SPI_Context.Spi_Peripheral_State = SPI_BUSY; 00960 __enable_irq(); 00961 Enable_SPI_CS(); 00962 SPI_Receive_Manager(SPI_REQUEST_VALID_HEADER_FOR_RX); 00963 LPM_Mode_Request(eLPM_SPI_RX, eLPM_Mode_Sleep); 00964 } 00965 else 00966 { 00967 __enable_irq(); 00968 } 00969 } 00970 00971 #endif /* __DMA_LP__ */ 00972 00973 /** 00974 * @} 00975 */ 00976 00977 /** 00978 * @} 00979 */ 00980 00981 /** 00982 * @} 00983 */ 00984 00985 /** 00986 * @} 00987 */ 00988 00989 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Generated on Tue Jul 12 2022 19:27:29 by 1.7.2