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.
Fork of X_NUCLEO_IDB0XA1 by
BlueNRGDevice.cpp
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2006-2013 ARM Limited 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 /** 00018 ****************************************************************************** 00019 * @file BlueNRGDevice.cpp 00020 * @author STMicroelectronics 00021 * @brief Implementation of BLEDeviceInstanceBase 00022 ****************************************************************************** 00023 * @copy 00024 * 00025 * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS 00026 * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE 00027 * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY 00028 * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING 00029 * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE 00030 * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. 00031 * 00032 * <h2><center>© COPYRIGHT 2013 STMicroelectronics</center></h2> 00033 */ 00034 00035 /** @defgroup BlueNRGDevice 00036 * @brief BlueNRG BLE_API Device Adaptation 00037 * @{ 00038 */ 00039 00040 #include "mbed.h" 00041 #include "BlueNRGDevice.h" 00042 #include "BlueNRGGap.h" 00043 #include "BlueNRGGattServer.h" 00044 00045 #include "btle.h" 00046 #include "Utils.h" 00047 #include "osal.h" 00048 00049 #include "debug.h" 00050 #include "stm32_bluenrg_ble.h " 00051 00052 extern "C" { 00053 #include "hci.h" 00054 } 00055 00056 #define HEADER_SIZE 5 00057 #define MAX_BUFFER_SIZE 255 00058 00059 /** 00060 * The singleton which represents the BlueNRG transport for the BLEDevice. 00061 * 00062 * See file 'x_nucleo_idb0xa1_targets.h' for details regarding the peripheral pins used! 00063 */ 00064 #include "x_nucleo_idb0xa1_targets.h" 00065 00066 BlueNRGDevice bluenrgDeviceInstance(IDB0XA1_PIN_SPI_MOSI, 00067 IDB0XA1_PIN_SPI_MISO, 00068 IDB0XA1_PIN_SPI_SCK, 00069 IDB0XA1_PIN_SPI_nCS, 00070 IDB0XA1_PIN_SPI_RESET, 00071 IDB0XA1_PIN_SPI_IRQ); 00072 00073 /** 00074 * BLE-API requires an implementation of the following function in order to 00075 * obtain its transport handle. 00076 */ 00077 BLEInstanceBase * 00078 createBLEInstance(void) 00079 { 00080 return (&bluenrgDeviceInstance); 00081 } 00082 00083 /**************************************************************************/ 00084 /** 00085 @brief Constructor 00086 * @param mosi mbed pin to use for MOSI line of SPI interface 00087 * @param miso mbed pin to use for MISO line of SPI interface 00088 * @param sck mbed pin to use for SCK line of SPI interface 00089 * @param cs mbed pin to use for not chip select line of SPI interface 00090 * @param rst mbed pin to use for BlueNRG reset 00091 * @param irq mbed pin for BlueNRG IRQ 00092 */ 00093 /**************************************************************************/ 00094 BlueNRGDevice::BlueNRGDevice(PinName mosi, 00095 PinName miso, 00096 PinName sck, 00097 PinName cs, 00098 PinName rst, 00099 PinName irq) : 00100 isInitialized(false), spi_(mosi, miso, sck), nCS_(cs), rst_(rst), irq_(irq) 00101 { 00102 // Setup the spi for 8 bit data, low clock polarity, 00103 // 1-edge phase, with an 8MHz clock rate 00104 spi_.format(8, 0); 00105 spi_.frequency(8000000); 00106 00107 // Deselect the BlueNRG chip by keeping its nCS signal high 00108 nCS_ = 1; 00109 00110 wait_us(500); 00111 00112 // Set the interrupt handler for the device 00113 irq_.mode(PullDown); // set irq mode 00114 irq_.rise(&HCI_Isr); 00115 00116 // Prepare communication between the host and the BTLE HW device 00117 btleInitHW(); 00118 } 00119 00120 /**************************************************************************/ 00121 /** 00122 @brief Destructor 00123 */ 00124 /**************************************************************************/ 00125 BlueNRGDevice::~BlueNRGDevice(void) 00126 { 00127 } 00128 00129 /** 00130 * @brief Get BlueNRG HW updater version 00131 * @param version This parameter returns the updater HW version. 00132 * @retval Status of the call 00133 */ 00134 uint8_t BlueNRGDevice::getUpdaterHardwareVersion(uint8_t *upd_hw_version) 00135 { 00136 uint8_t status; 00137 00138 status = btleGetUpdaterHWVersion(upd_hw_version); 00139 00140 return (status); 00141 } 00142 00143 /** 00144 * @brief Flash a new firmware using internal bootloader. 00145 * @param fw_image Pointer to the firmware image (raw binary data, 00146 * little-endian). 00147 * @param fw_size Size of the firmware image. The firmware image size shall 00148 * be multiple of 4 bytes. 00149 * @retval int It returns 0 if successful, or a number not equal to 0 in 00150 * case of error (ACI_ERROR, UNSUPPORTED_VERSION, 00151 * WRONG_IMAGE_SIZE, CRC_ERROR) 00152 */ 00153 int BlueNRGDevice::updateFirmware(const uint8_t *fw_image, uint32_t fw_size) 00154 { 00155 int status = btleUpdateFirmware(fw_image, fw_size); 00156 00157 return (status); 00158 } 00159 00160 00161 /** 00162 @brief Initialises anything required to start using BLE 00163 @param[in] void 00164 @returns ble_error_t 00165 */ 00166 ble_error_t BlueNRGDevice::init(BLE::InstanceID_t instanceID, FunctionPointerWithContext<BLE::InitializationCompleteCallbackContext *> callback) 00167 { 00168 if (isInitialized) { 00169 BLE::InitializationCompleteCallbackContext context = { 00170 BLE::Instance(instanceID), 00171 BLE_ERROR_ALREADY_INITIALIZED 00172 }; 00173 callback.call(&context); 00174 return BLE_ERROR_ALREADY_INITIALIZED; 00175 } 00176 00177 /* ToDo: Clear memory contents, reset the SD, etc. */ 00178 // Start the BlueNRG/BlueNRG-MS stack 00179 // By default, we set the device GAP role to PERIPHERAL 00180 btleStart(BlueNRGGap::getInstance().getIsSetAddress(), GAP_PERIPHERAL_ROLE_IDB04A1); 00181 00182 isInitialized = true; 00183 BLE::InitializationCompleteCallbackContext context = { 00184 BLE::Instance(instanceID), 00185 BLE_ERROR_NONE 00186 }; 00187 callback.call(&context); 00188 00189 return BLE_ERROR_NONE; 00190 } 00191 00192 00193 /** 00194 @brief Resets the BLE HW, removing any existing services and 00195 characteristics 00196 @param[in] void 00197 @returns void 00198 */ 00199 void BlueNRGDevice::reset(void) 00200 { 00201 wait_us(500); 00202 00203 /* Reset BlueNRG SPI interface */ 00204 rst_ = 0; 00205 wait_us(5); 00206 rst_ = 1; 00207 wait_us(5); 00208 00209 /* Wait for the radio to come back up */ 00210 wait_us(500); 00211 00212 } 00213 00214 /*! 00215 @brief Wait for any BLE Event like BLE Connection, Read Request etc. 00216 @param[in] void 00217 @returns char * 00218 */ 00219 void BlueNRGDevice::waitForEvent(void) 00220 { 00221 bool must_return = false; 00222 00223 do { 00224 BlueNRGGap::getInstance().Process(); 00225 00226 HCI_Process(); 00227 00228 if(must_return) return; 00229 00230 __WFE(); /* it is recommended that SEVONPEND in the 00231 System Control Register is NOT set */ 00232 must_return = true; /* after returning from WFE we must guarantee 00233 that conrol is given back to main loop before next WFE */ 00234 } while(true); 00235 00236 } 00237 00238 /*! 00239 @brief get GAP version 00240 @brief Get the BLE stack version information 00241 @param[in] void 00242 @returns char * 00243 @returns char * 00244 */ 00245 const char *BlueNRGDevice::getVersion(void) 00246 { 00247 return getVersionString(); 00248 } 00249 00250 /**************************************************************************/ 00251 /*! 00252 @brief get reference to GAP object 00253 @param[in] void 00254 @returns Gap& 00255 */ 00256 /**************************************************************************/ 00257 Gap &BlueNRGDevice::getGap() 00258 { 00259 return BlueNRGGap::getInstance(); 00260 } 00261 00262 const Gap &BlueNRGDevice::getGap() const 00263 { 00264 return BlueNRGGap::getInstance(); 00265 } 00266 00267 /**************************************************************************/ 00268 /*! 00269 @brief get reference to GATT server object 00270 @param[in] void 00271 @returns GattServer& 00272 */ 00273 /**************************************************************************/ 00274 GattServer &BlueNRGDevice::getGattServer() 00275 { 00276 return BlueNRGGattServer::getInstance(); 00277 } 00278 00279 const GattServer &BlueNRGDevice::getGattServer() const 00280 { 00281 return BlueNRGGattServer::getInstance(); 00282 } 00283 00284 /**************************************************************************/ 00285 /*! 00286 @brief shut down the BLE device 00287 @param[out] error if any 00288 */ 00289 /**************************************************************************/ 00290 ble_error_t BlueNRGDevice::shutdown(void) { 00291 if (!isInitialized) { 00292 return BLE_ERROR_INITIALIZATION_INCOMPLETE; 00293 } 00294 00295 /* Reset the BlueNRG device first */ 00296 reset(); 00297 00298 /* Shutdown the BLE API and BlueNRG glue code */ 00299 ble_error_t error; 00300 00301 /* GattServer instance */ 00302 error = BlueNRGGattServer::getInstance().reset(); 00303 if (error != BLE_ERROR_NONE) { 00304 return error; 00305 } 00306 00307 /* GattClient instance */ 00308 error = BlueNRGGattClient::getInstance().reset(); 00309 if (error != BLE_ERROR_NONE) { 00310 return error; 00311 } 00312 00313 /* Gap instance */ 00314 error = BlueNRGGap::getInstance().reset(); 00315 if (error != BLE_ERROR_NONE) { 00316 return error; 00317 } 00318 00319 isInitialized = false; 00320 00321 return BLE_ERROR_NONE; 00322 00323 } 00324 00325 /** 00326 * @brief Reads from BlueNRG SPI buffer and store data into local buffer. 00327 * @param buffer : Buffer where data from SPI are stored 00328 * @param buff_size: Buffer size 00329 * @retval int32_t : Number of read bytes 00330 */ 00331 int32_t BlueNRGDevice::spiRead(uint8_t *buffer, uint8_t buff_size) 00332 { 00333 uint16_t byte_count; 00334 uint8_t len = 0; 00335 uint8_t char_ff = 0xff; 00336 volatile uint8_t read_char; 00337 00338 uint8_t i = 0; 00339 volatile uint8_t tmpreg; 00340 00341 uint8_t header_master[HEADER_SIZE] = {0x0b, 0x00, 0x00, 0x00, 0x00}; 00342 uint8_t header_slave[HEADER_SIZE]; 00343 00344 /* Select the chip */ 00345 nCS_ = 0; 00346 00347 /* Read the header */ 00348 for (i = 0; i < 5; i++) 00349 { 00350 tmpreg = spi_.write(header_master[i]); 00351 header_slave[i] = (uint8_t)(tmpreg); 00352 } 00353 00354 if (header_slave[0] == 0x02) { 00355 /* device is ready */ 00356 byte_count = (header_slave[4]<<8)|header_slave[3]; 00357 00358 if (byte_count > 0) { 00359 00360 /* avoid to read more data that size of the buffer */ 00361 if (byte_count > buff_size){ 00362 byte_count = buff_size; 00363 } 00364 00365 for (len = 0; len < byte_count; len++){ 00366 read_char = spi_.write(char_ff); 00367 buffer[len] = read_char; 00368 } 00369 } 00370 } 00371 /* Release CS line to deselect the chip */ 00372 nCS_ = 1; 00373 00374 // Add a small delay to give time to the BlueNRG to set the IRQ pin low 00375 // to avoid a useless SPI read at the end of the transaction 00376 for(volatile int i = 0; i < 2; i++)__NOP(); 00377 00378 #ifdef PRINT_CSV_FORMAT 00379 if (len > 0) { 00380 print_csv_time(); 00381 for (int i=0; i<len; i++) { 00382 PRINT_CSV(" %02x", buffer[i]); 00383 } 00384 PRINT_CSV("\n"); 00385 } 00386 #endif 00387 00388 return len; 00389 } 00390 00391 /** 00392 * @brief Writes data from local buffer to SPI. 00393 * @param data1 : First data buffer to be written 00394 * @param data2 : Second data buffer to be written 00395 * @param Nb_bytes1: Size of first data buffer to be written 00396 * @param Nb_bytes2: Size of second data buffer to be written 00397 * @retval Number of read bytes 00398 */ 00399 int32_t BlueNRGDevice::spiWrite(uint8_t* data1, 00400 uint8_t* data2, uint8_t Nb_bytes1, uint8_t Nb_bytes2) 00401 { 00402 int32_t result = 0; 00403 uint32_t i; 00404 volatile uint8_t tmpreg; 00405 00406 unsigned char header_master[HEADER_SIZE] = {0x0a, 0x00, 0x00, 0x00, 0x00}; 00407 unsigned char header_slave[HEADER_SIZE] = {0xaa, 0x00, 0x00, 0x00, 0x00}; 00408 00409 disable_irq(); 00410 00411 /* CS reset */ 00412 nCS_ = 0; 00413 00414 /* Exchange header */ 00415 for (i = 0; i < 5; i++) 00416 { 00417 tmpreg = spi_.write(header_master[i]); 00418 header_slave[i] = tmpreg; 00419 } 00420 00421 if (header_slave[0] == 0x02) { 00422 /* SPI is ready */ 00423 if (header_slave[1] >= (Nb_bytes1+Nb_bytes2)) { 00424 00425 /* Buffer is big enough */ 00426 for (i = 0; i < Nb_bytes1; i++) { 00427 spi_.write(*(data1 + i)); 00428 } 00429 for (i = 0; i < Nb_bytes2; i++) { 00430 spi_.write(*(data2 + i)); 00431 } 00432 } else { 00433 /* Buffer is too small */ 00434 result = -2; 00435 } 00436 } else { 00437 /* SPI is not ready */ 00438 result = -1; 00439 } 00440 00441 /* Release CS line */ 00442 //HAL_GPIO_WritePin(BNRG_SPI_CS_PORT, BNRG_SPI_CS_PIN, GPIO_PIN_SET); 00443 nCS_ = 1; 00444 00445 enable_irq(); 00446 00447 return result; 00448 } 00449 00450 bool BlueNRGDevice::dataPresent() 00451 { 00452 return (irq_ == 1); 00453 } 00454 00455 void BlueNRGDevice::disable_irq() 00456 { 00457 irq_.disable_irq(); 00458 } 00459 00460 void BlueNRGDevice::enable_irq() 00461 { 00462 irq_.enable_irq(); 00463 }
Generated on Tue Jul 12 2022 16:31:45 by
