Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
stm32_bluenrg_ble.c
00001 /** 00002 ****************************************************************************** 00003 * @file stm32_bluenrg_ble.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 /* Includes ------------------------------------------------------------------*/ 00039 #include "stm32_bluenrg_ble.h " 00040 #include "gp_timer.h" 00041 #include "debug.h" 00042 00043 #define HEADER_SIZE 5 00044 #define MAX_BUFFER_SIZE 255 00045 #define TIMEOUT_DURATION 15 00046 00047 SPI_HandleTypeDef SpiHandle; 00048 00049 /* Private function prototypes -----------------------------------------------*/ 00050 static void us150Delay(void); 00051 void set_irq_as_output(void); 00052 void set_irq_as_input(void); 00053 00054 /** 00055 * @brief This function is used for low level initialization of the SPI 00056 * communication with the BlueNRG Expansion Board. 00057 * @param Pointer to the handle of the STM32Cube HAL SPI interface. 00058 * @retval None 00059 */ 00060 void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi) 00061 { 00062 GPIO_InitTypeDef GPIO_InitStruct; 00063 if(hspi->Instance==BNRG_SPI_INSTANCE) 00064 { 00065 /* Enable peripherals clock */ 00066 00067 /* Enable GPIO Ports Clock */ 00068 BNRG_SPI_RESET_CLK_ENABLE(); 00069 BNRG_SPI_SCLK_CLK_ENABLE(); 00070 BNRG_SPI_MISO_CLK_ENABLE(); 00071 BNRG_SPI_MOSI_CLK_ENABLE(); 00072 BNRG_SPI_CS_CLK_ENABLE(); 00073 BNRG_SPI_IRQ_CLK_ENABLE(); 00074 00075 /* Enable SPI clock */ 00076 BNRG_SPI_CLK_ENABLE(); 00077 00078 /* Reset */ 00079 GPIO_InitStruct.Pin = BNRG_SPI_RESET_PIN; 00080 GPIO_InitStruct.Mode = BNRG_SPI_RESET_MODE; 00081 GPIO_InitStruct.Pull = BNRG_SPI_RESET_PULL; 00082 GPIO_InitStruct.Speed = BNRG_SPI_RESET_SPEED; 00083 GPIO_InitStruct.Alternate = BNRG_SPI_RESET_ALTERNATE; 00084 HAL_GPIO_Init(BNRG_SPI_RESET_PORT, &GPIO_InitStruct); 00085 HAL_GPIO_WritePin(BNRG_SPI_RESET_PORT, BNRG_SPI_RESET_PIN, GPIO_PIN_RESET); /*Added to avoid spurious interrupt from the BlueNRG */ 00086 00087 /* SCLK */ 00088 GPIO_InitStruct.Pin = BNRG_SPI_SCLK_PIN; 00089 GPIO_InitStruct.Mode = BNRG_SPI_SCLK_MODE; 00090 GPIO_InitStruct.Pull = BNRG_SPI_SCLK_PULL; 00091 GPIO_InitStruct.Speed = BNRG_SPI_SCLK_SPEED; 00092 GPIO_InitStruct.Alternate = BNRG_SPI_SCLK_ALTERNATE; 00093 HAL_GPIO_Init(BNRG_SPI_SCLK_PORT, &GPIO_InitStruct); 00094 00095 /* MISO */ 00096 GPIO_InitStruct.Pin = BNRG_SPI_MISO_PIN; 00097 GPIO_InitStruct.Mode = BNRG_SPI_MISO_MODE; 00098 GPIO_InitStruct.Pull = BNRG_SPI_MISO_PULL; 00099 GPIO_InitStruct.Speed = BNRG_SPI_MISO_SPEED; 00100 GPIO_InitStruct.Alternate = BNRG_SPI_MISO_ALTERNATE; 00101 HAL_GPIO_Init(BNRG_SPI_MISO_PORT, &GPIO_InitStruct); 00102 00103 /* MOSI */ 00104 GPIO_InitStruct.Pin = BNRG_SPI_MOSI_PIN; 00105 GPIO_InitStruct.Mode = BNRG_SPI_MOSI_MODE; 00106 GPIO_InitStruct.Pull = BNRG_SPI_MOSI_PULL; 00107 GPIO_InitStruct.Speed = BNRG_SPI_MOSI_SPEED; 00108 GPIO_InitStruct.Alternate = BNRG_SPI_MOSI_ALTERNATE; 00109 HAL_GPIO_Init(BNRG_SPI_MOSI_PORT, &GPIO_InitStruct); 00110 00111 /* NSS/CSN/CS */ 00112 GPIO_InitStruct.Pin = BNRG_SPI_CS_PIN; 00113 GPIO_InitStruct.Mode = BNRG_SPI_CS_MODE; 00114 GPIO_InitStruct.Pull = BNRG_SPI_CS_PULL; 00115 GPIO_InitStruct.Speed = BNRG_SPI_CS_SPEED; 00116 GPIO_InitStruct.Alternate = BNRG_SPI_CS_ALTERNATE; 00117 HAL_GPIO_Init(BNRG_SPI_CS_PORT, &GPIO_InitStruct); 00118 HAL_GPIO_WritePin(BNRG_SPI_CS_PORT, BNRG_SPI_CS_PIN, GPIO_PIN_SET); 00119 00120 /* IRQ -- INPUT */ 00121 GPIO_InitStruct.Pin = BNRG_SPI_IRQ_PIN; 00122 GPIO_InitStruct.Mode = BNRG_SPI_IRQ_MODE; 00123 GPIO_InitStruct.Pull = BNRG_SPI_IRQ_PULL; 00124 GPIO_InitStruct.Speed = BNRG_SPI_IRQ_SPEED; 00125 GPIO_InitStruct.Alternate = BNRG_SPI_IRQ_ALTERNATE; 00126 HAL_GPIO_Init(BNRG_SPI_IRQ_PORT, &GPIO_InitStruct); 00127 00128 /* Configure the NVIC for SPI */ 00129 HAL_NVIC_SetPriority(BNRG_SPI_EXTI_IRQn, 4, 0); 00130 HAL_NVIC_EnableIRQ(BNRG_SPI_EXTI_IRQn); 00131 } 00132 } 00133 00134 /** 00135 * @brief Writes data to a serial interface. 00136 * @param data1 : 1st buffer 00137 * @param data2 : 2nd buffer 00138 * @param n_bytes1: number of bytes in 1st buffer 00139 * @param n_bytes2: number of bytes in 2nd buffer 00140 * @retval None 00141 */ 00142 void Hal_Write_Serial(const void* data1, const void* data2, int32_t n_bytes1, 00143 int32_t n_bytes2) 00144 { 00145 struct timer t; 00146 00147 Timer_Set(&t, CLOCK_SECOND/10); 00148 00149 #ifdef PRINT_CSV_FORMAT 00150 PRINT_CSV("00:00:00.000"); 00151 for (int i=0; i<n_bytes1; i++) { 00152 PRINT_CSV(" %02x", ((uint8_t *)data1)[i]); 00153 } 00154 for (int i=0; i<n_bytes2; i++) { 00155 PRINT_CSV(" %02x", ((uint8_t *)data2)[i]); 00156 } 00157 PRINT_CSV("\n"); 00158 #endif 00159 00160 while(1){ 00161 if(BlueNRG_SPI_Write(&SpiHandle, (uint8_t *)data1,(uint8_t *)data2, n_bytes1, n_bytes2)==0) break; 00162 if(Timer_Expired(&t)){ 00163 break; 00164 } 00165 } 00166 } 00167 00168 /** 00169 * @brief Initializes the SPI communication with the BlueNRG 00170 * Expansion Board. 00171 * @param None 00172 * @retval None 00173 */ 00174 void BNRG_SPI_Init(void) 00175 { 00176 SpiHandle.Instance = BNRG_SPI_INSTANCE; 00177 SpiHandle.Init.Mode = BNRG_SPI_MODE; 00178 SpiHandle.Init.Direction = BNRG_SPI_DIRECTION; 00179 SpiHandle.Init.DataSize = BNRG_SPI_DATASIZE; 00180 SpiHandle.Init.CLKPolarity = BNRG_SPI_CLKPOLARITY; 00181 SpiHandle.Init.CLKPhase = BNRG_SPI_CLKPHASE; 00182 SpiHandle.Init.NSS = BNRG_SPI_NSS; 00183 SpiHandle.Init.FirstBit = BNRG_SPI_FIRSTBIT; 00184 SpiHandle.Init.TIMode = BNRG_SPI_TIMODE; 00185 SpiHandle.Init.CRCPolynomial = BNRG_SPI_CRCPOLYNOMIAL; 00186 SpiHandle.Init.BaudRatePrescaler = BNRG_SPI_BAUDRATEPRESCALER; 00187 SpiHandle.Init.CRCCalculation = BNRG_SPI_CRCCALCULATION; 00188 00189 HAL_SPI_Init(&SpiHandle); 00190 } 00191 00192 /** 00193 * @brief Resets the BlueNRG. 00194 * @param None 00195 * @retval None 00196 */ 00197 void BlueNRG_RST(void) 00198 { 00199 HAL_GPIO_WritePin(BNRG_SPI_RESET_PORT, BNRG_SPI_RESET_PIN, GPIO_PIN_RESET); 00200 HAL_Delay(5); 00201 HAL_GPIO_WritePin(BNRG_SPI_RESET_PORT, BNRG_SPI_RESET_PIN, GPIO_PIN_SET); 00202 HAL_Delay(5); 00203 } 00204 00205 00206 /** 00207 * @brief Reports if the BlueNRG has data for the host micro. 00208 * @param None 00209 * @retval 1 if data are present, 0 otherwise 00210 */ 00211 // FIXME: find a better way to handle this return value (bool type? TRUE and FALSE) 00212 uint8_t BlueNRG_DataPresent(void) 00213 { 00214 if (HAL_GPIO_ReadPin(BNRG_SPI_EXTI_PORT, BNRG_SPI_EXTI_PIN) == GPIO_PIN_SET) 00215 return 1; 00216 else 00217 return 0; 00218 } /* end BlueNRG_DataPresent() */ 00219 00220 /** 00221 * @brief Activate internal bootloader using pin. 00222 * @param None 00223 * @retval None 00224 */ 00225 void BlueNRG_HW_Bootloader(void) 00226 { 00227 set_irq_as_output(); 00228 BlueNRG_RST(); 00229 set_irq_as_input(); 00230 } 00231 00232 /** 00233 * @brief Reads from BlueNRG SPI buffer and store data into local buffer. 00234 * @param hspi : Handle of the STM32Cube HAL SPI interface 00235 * @param buffer : Buffer where data from SPI are stored 00236 * @param buff_size: Buffer size 00237 * @retval int32_t : Number of read bytes 00238 */ 00239 int32_t BlueNRG_SPI_Read_All(SPI_HandleTypeDef *hspi, uint8_t *buffer, 00240 uint8_t buff_size) 00241 { 00242 uint16_t byte_count; 00243 uint8_t len = 0; 00244 uint8_t char_ff = 0xff; 00245 volatile uint8_t read_char; 00246 00247 uint8_t header_master[HEADER_SIZE] = {0x0b, 0x00, 0x00, 0x00, 0x00}; 00248 uint8_t header_slave[HEADER_SIZE]; 00249 00250 /* CS reset */ 00251 HAL_GPIO_WritePin(BNRG_SPI_CS_PORT, BNRG_SPI_CS_PIN, GPIO_PIN_RESET); 00252 00253 /* Read the header */ 00254 HAL_SPI_TransmitReceive(hspi, header_master, header_slave, HEADER_SIZE, TIMEOUT_DURATION); 00255 00256 if (header_slave[0] == 0x02) { 00257 /* device is ready */ 00258 byte_count = (header_slave[4]<<8)|header_slave[3]; 00259 00260 if (byte_count > 0) { 00261 00262 /* avoid to read more data that size of the buffer */ 00263 if (byte_count > buff_size){ 00264 byte_count = buff_size; 00265 } 00266 00267 for (len = 0; len < byte_count; len++){ 00268 HAL_SPI_TransmitReceive(hspi, &char_ff, (uint8_t*)&read_char, 1, TIMEOUT_DURATION); 00269 buffer[len] = read_char; 00270 } 00271 } 00272 } 00273 /* Release CS line */ 00274 HAL_GPIO_WritePin(BNRG_SPI_CS_PORT, BNRG_SPI_CS_PIN, GPIO_PIN_SET); 00275 00276 // Add a small delay to give time to the BlueNRG to set the IRQ pin low 00277 // to avoid a useless SPI read at the end of the transaction 00278 for(volatile int i = 0; i < 2; i++)__NOP(); 00279 00280 #ifdef PRINT_CSV_FORMAT 00281 if (len > 0) { 00282 PRINT_CSV("00:00:00.000"); 00283 for (int i=0; i<len; i++) { 00284 PRINT_CSV(" %02x", buffer[i]); 00285 } 00286 PRINT_CSV("\n"); 00287 } 00288 #endif 00289 00290 return len; 00291 } 00292 00293 /** 00294 * @brief Writes data from local buffer to SPI. 00295 * @param hspi : Handle of the STM32Cube HAL SPI interface 00296 * @param data1 : First data buffer to be written 00297 * @param data2 : Second data buffer to be written 00298 * @param Nb_bytes1: Size of first data buffer to be written 00299 * @param Nb_bytes2: Size of second data buffer to be written 00300 * @retval Number of read bytes 00301 */ 00302 int32_t BlueNRG_SPI_Write(SPI_HandleTypeDef *hspi, uint8_t* data1, 00303 uint8_t* data2, uint8_t Nb_bytes1, uint8_t Nb_bytes2) 00304 { 00305 int32_t result = 0; 00306 00307 int32_t spi_fix_enabled = 0; 00308 00309 #ifdef ENABLE_SPI_FIX 00310 spi_fix_enabled = 1; 00311 #endif //ENABLE_SPI_FIX 00312 00313 unsigned char header_master[HEADER_SIZE] = {0x0a, 0x00, 0x00, 0x00, 0x00}; 00314 unsigned char header_slave[HEADER_SIZE] = {0xaa, 0x00, 0x00, 0x00, 0x00}; 00315 00316 unsigned char read_char_buf[MAX_BUFFER_SIZE]; 00317 00318 Disable_SPI_IRQ(); 00319 00320 /* 00321 If the SPI_FIX is enabled the IRQ is set in Output mode, then it is pulled 00322 high and, after a delay of at least 112us, the CS line is asserted and the 00323 header transmit/receive operations are started. 00324 After these transmit/receive operations the IRQ is reset in input mode. 00325 */ 00326 if (spi_fix_enabled) { 00327 set_irq_as_output(); 00328 00329 /* Assert CS line after at least 112us */ 00330 us150Delay(); 00331 } 00332 00333 /* CS reset */ 00334 HAL_GPIO_WritePin(BNRG_SPI_CS_PORT, BNRG_SPI_CS_PIN, GPIO_PIN_RESET); 00335 00336 /* Exchange header */ 00337 HAL_SPI_TransmitReceive(hspi, header_master, header_slave, HEADER_SIZE, TIMEOUT_DURATION); 00338 00339 if (spi_fix_enabled) { 00340 set_irq_as_input(); 00341 } 00342 00343 if (header_slave[0] == 0x02) { 00344 /* SPI is ready */ 00345 if (header_slave[1] >= (Nb_bytes1+Nb_bytes2)) { 00346 00347 /* Buffer is big enough */ 00348 if (Nb_bytes1 > 0) { 00349 HAL_SPI_TransmitReceive(hspi, data1, read_char_buf, Nb_bytes1, TIMEOUT_DURATION); 00350 } 00351 if (Nb_bytes2 > 0) { 00352 HAL_SPI_TransmitReceive(hspi, data2, read_char_buf, Nb_bytes2, TIMEOUT_DURATION); 00353 } 00354 00355 } else { 00356 /* Buffer is too small */ 00357 result = -2; 00358 } 00359 } else { 00360 /* SPI is not ready */ 00361 result = -1; 00362 } 00363 00364 /* Release CS line */ 00365 HAL_GPIO_WritePin(BNRG_SPI_CS_PORT, BNRG_SPI_CS_PIN, GPIO_PIN_SET); 00366 00367 Enable_SPI_IRQ(); 00368 00369 return result; 00370 } 00371 00372 /** 00373 * @brief Set in Output mode the IRQ. 00374 * @param None 00375 * @retval None 00376 */ 00377 void set_irq_as_output() 00378 { 00379 GPIO_InitTypeDef GPIO_InitStructure; 00380 00381 /* Pull IRQ high */ 00382 GPIO_InitStructure.Pin = BNRG_SPI_IRQ_PIN; 00383 GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; 00384 GPIO_InitStructure.Speed = BNRG_SPI_IRQ_SPEED; 00385 GPIO_InitStructure.Pull = GPIO_NOPULL; 00386 HAL_GPIO_Init(BNRG_SPI_IRQ_PORT, &GPIO_InitStructure); 00387 HAL_GPIO_WritePin(BNRG_SPI_IRQ_PORT, BNRG_SPI_IRQ_PIN, GPIO_PIN_SET); 00388 } 00389 00390 /** 00391 * @brief Set the IRQ in input mode. 00392 * @param None 00393 * @retval None 00394 */ 00395 void set_irq_as_input() 00396 { 00397 GPIO_InitTypeDef GPIO_InitStructure; 00398 00399 /* IRQ input */ 00400 GPIO_InitStructure.Pin = BNRG_SPI_IRQ_PIN; 00401 GPIO_InitStructure.Mode = BNRG_SPI_IRQ_MODE; 00402 GPIO_InitStructure.Pull = GPIO_PULLDOWN; 00403 GPIO_InitStructure.Speed = BNRG_SPI_IRQ_SPEED; 00404 GPIO_InitStructure.Alternate = BNRG_SPI_IRQ_ALTERNATE; 00405 HAL_GPIO_Init(BNRG_SPI_IRQ_PORT, &GPIO_InitStructure); 00406 00407 GPIO_InitStructure.Pull = BNRG_SPI_IRQ_PULL; 00408 HAL_GPIO_Init(BNRG_SPI_IRQ_PORT, &GPIO_InitStructure); 00409 } 00410 00411 /** 00412 * @brief Utility function for delay 00413 * @param None 00414 * @retval None 00415 * NOTE: TODO: implement with clock-independent function. 00416 */ 00417 static void us150Delay() 00418 { 00419 #if SYSCLK_FREQ == 4000000 00420 for(volatile int i = 0; i < 35; i++)__NOP(); 00421 #elif SYSCLK_FREQ == 32000000 00422 for(volatile int i = 0; i < 420; i++)__NOP(); 00423 #elif SYSCLK_FREQ == 84000000 00424 for(volatile int i = 0; i < 1125; i++)__NOP(); 00425 #else 00426 #error Implement delay function. 00427 #endif 00428 } 00429 00430 /** 00431 * @brief Enable SPI IRQ. 00432 * @param None 00433 * @retval None 00434 */ 00435 void Enable_SPI_IRQ(void) 00436 { 00437 HAL_NVIC_EnableIRQ(BNRG_SPI_EXTI_IRQn); 00438 } 00439 00440 /** 00441 * @brief Disable SPI IRQ. 00442 * @param None 00443 * @retval None 00444 */ 00445 void Disable_SPI_IRQ(void) 00446 { 00447 HAL_NVIC_DisableIRQ(BNRG_SPI_EXTI_IRQn); 00448 } 00449 00450 /** 00451 * @brief Clear Pending SPI IRQ. 00452 * @param None 00453 * @retval None 00454 */ 00455 void Clear_SPI_IRQ(void) 00456 { 00457 HAL_NVIC_ClearPendingIRQ(BNRG_SPI_EXTI_IRQn); 00458 } 00459 00460 /** 00461 * @brief Clear EXTI (External Interrupt) line for SPI IRQ. 00462 * @param None 00463 * @retval None 00464 */ 00465 void Clear_SPI_EXTI_Flag(void) 00466 { 00467 __HAL_GPIO_EXTI_CLEAR_IT(BNRG_SPI_EXTI_PIN); 00468 } 00469 00470 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 00471
Generated on Tue Jul 12 2022 17:28:29 by
1.7.2