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.
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 #ifdef YOTTA_CFG_MBED_OS 00041 #include "mbed-drivers/mbed.h" 00042 #else 00043 #include "mbed.h" 00044 #endif 00045 #include "BlueNRGDevice.h" 00046 #include "BlueNRGGap.h" 00047 #include "BlueNRGGattServer.h" 00048 00049 #include "btle.h" 00050 #include "ble_utils.h" 00051 #include "ble_osal.h" 00052 00053 #include "ble_debug.h" 00054 #include "stm32_bluenrg_ble.h " 00055 00056 extern "C" { 00057 #include "ble_hci.h" 00058 #include "bluenrg_utils.h" 00059 } 00060 00061 #define HEADER_SIZE 5 00062 #define MAX_BUFFER_SIZE 255 00063 00064 /** 00065 * The singleton which represents the BlueNRG transport for the BLEDevice. 00066 * 00067 * See file 'x_nucleo_idb0xa1_targets.h' for details regarding the peripheral pins used! 00068 */ 00069 #include "x_nucleo_idb0xa1_targets.h" 00070 00071 BlueNRGDevice bluenrgDeviceInstance(IDB0XA1_PIN_SPI_MOSI, 00072 IDB0XA1_PIN_SPI_MISO, 00073 IDB0XA1_PIN_SPI_SCK, 00074 IDB0XA1_PIN_SPI_nCS, 00075 IDB0XA1_PIN_SPI_RESET, 00076 IDB0XA1_PIN_SPI_IRQ); 00077 00078 /** 00079 * BLE-API requires an implementation of the following function in order to 00080 * obtain its transport handle. 00081 */ 00082 BLEInstanceBase * 00083 createBLEInstance(void) 00084 { 00085 return (&bluenrgDeviceInstance); 00086 } 00087 00088 /**************************************************************************/ 00089 /** 00090 @brief Constructor 00091 * @param mosi mbed pin to use for MOSI line of SPI interface 00092 * @param miso mbed pin to use for MISO line of SPI interface 00093 * @param sck mbed pin to use for SCK line of SPI interface 00094 * @param cs mbed pin to use for not chip select line of SPI interface 00095 * @param rst mbed pin to use for BlueNRG reset 00096 * @param irq mbed pin for BlueNRG IRQ 00097 */ 00098 /**************************************************************************/ 00099 BlueNRGDevice::BlueNRGDevice(PinName mosi, 00100 PinName miso, 00101 PinName sck, 00102 PinName cs, 00103 PinName rst, 00104 PinName irq) : 00105 isInitialized(false), spi_(mosi, miso, sck), nCS_(cs), rst_(rst), irq_(irq) 00106 { 00107 // Setup the spi for 8 bit data, low clock polarity, 00108 // 1-edge phase, with an 8MHz clock rate 00109 spi_.format(8, 0); 00110 spi_.frequency(8000000); 00111 00112 // Deselect the BlueNRG chip by keeping its nCS signal high 00113 nCS_ = 1; 00114 00115 wait_us(500); 00116 00117 // Prepare communication between the host and the BlueNRG SPI interface 00118 HCI_Init(); 00119 00120 // Set the interrupt handler for the device 00121 irq_.mode(PullDown); // set irq mode 00122 irq_.rise(&HCI_Isr); 00123 } 00124 00125 /**************************************************************************/ 00126 /** 00127 @brief Destructor 00128 */ 00129 /**************************************************************************/ 00130 BlueNRGDevice::~BlueNRGDevice(void) 00131 { 00132 } 00133 00134 /** 00135 * @brief Get BlueNRG HW version in bootloader mode 00136 * @param hw_version The HW version is written to this parameter 00137 * @retval It returns BLE_STATUS_SUCCESS on success or an error code otherwise 00138 */ 00139 uint8_t BlueNRGDevice::getUpdaterHardwareVersion(uint8_t *hw_version) 00140 { 00141 uint8_t status; 00142 00143 status = getBlueNRGUpdaterHWVersion(hw_version); 00144 00145 return (status); 00146 } 00147 00148 /** 00149 * @brief Flash a new firmware using internal bootloader. 00150 * @param fw_image Pointer to the firmware image (raw binary data, 00151 * little-endian). 00152 * @param fw_size Size of the firmware image. The firmware image size shall 00153 * be multiple of 4 bytes. 00154 * @retval int It returns BLE_STATUS_SUCCESS on success, or a number 00155 * not equal to 0 in case of error 00156 * (ACI_ERROR, UNSUPPORTED_VERSION, WRONG_IMAGE_SIZE, CRC_ERROR) 00157 */ 00158 int BlueNRGDevice::updateFirmware(const uint8_t *fw_image, uint32_t fw_size) 00159 { 00160 int status = program_device(fw_image, fw_size); 00161 00162 return (status); 00163 } 00164 00165 00166 /** 00167 * @brief Initialises anything required to start using BLE 00168 * @param[in] instanceID 00169 * The ID of the instance to initialize. 00170 * @param[in] callback 00171 * A callback for when initialization completes for a BLE 00172 * instance. This is an optional parameter set to NULL when not 00173 * supplied. 00174 * 00175 * @return BLE_ERROR_NONE if the initialization procedure was started 00176 * successfully. 00177 */ 00178 ble_error_t BlueNRGDevice::init(BLE::InstanceID_t instanceID, FunctionPointerWithContext<BLE::InitializationCompleteCallbackContext *> callback) 00179 { 00180 if (isInitialized) { 00181 BLE::InitializationCompleteCallbackContext context = { 00182 BLE::Instance(instanceID), 00183 BLE_ERROR_ALREADY_INITIALIZED 00184 }; 00185 callback.call(&context); 00186 return BLE_ERROR_ALREADY_INITIALIZED; 00187 } 00188 00189 // Init the BlueNRG/BlueNRG-MS stack 00190 btleInit(); 00191 00192 isInitialized = true; 00193 BLE::InitializationCompleteCallbackContext context = { 00194 BLE::Instance(instanceID), 00195 BLE_ERROR_NONE 00196 }; 00197 callback.call(&context); 00198 00199 return BLE_ERROR_NONE; 00200 } 00201 00202 00203 /** 00204 @brief Resets the BLE HW, removing any existing services and 00205 characteristics 00206 @param[in] void 00207 @returns void 00208 */ 00209 void BlueNRGDevice::reset(void) 00210 { 00211 wait_us(500); 00212 00213 /* Reset BlueNRG SPI interface */ 00214 rst_ = 0; 00215 wait_us(5); 00216 rst_ = 1; 00217 wait_us(5); 00218 00219 /* Wait for the radio to come back up */ 00220 wait_us(500); 00221 00222 } 00223 00224 /*! 00225 @brief Wait for any BLE Event like BLE Connection, Read Request etc. 00226 @param[in] void 00227 @returns char * 00228 */ 00229 void BlueNRGDevice::waitForEvent(void) 00230 { 00231 bool must_return = false; 00232 00233 do { 00234 bluenrgDeviceInstance.processEvents(); 00235 00236 if(must_return) return; 00237 00238 __WFE(); /* it is recommended that SEVONPEND in the 00239 System Control Register is NOT set */ 00240 must_return = true; /* after returning from WFE we must guarantee 00241 that conrol is given back to main loop before next WFE */ 00242 } while(true); 00243 00244 } 00245 00246 /*! 00247 @brief get GAP version 00248 @brief Get the BLE stack version information 00249 @param[in] void 00250 @returns char * 00251 @returns char * 00252 */ 00253 const char *BlueNRGDevice::getVersion(void) 00254 { 00255 return getVersionString(); 00256 } 00257 00258 /**************************************************************************/ 00259 /*! 00260 @brief get reference to GAP object 00261 @param[in] void 00262 @returns Gap& 00263 */ 00264 /**************************************************************************/ 00265 Gap &BlueNRGDevice::getGap() 00266 { 00267 return BlueNRGGap::getInstance(); 00268 } 00269 00270 const Gap &BlueNRGDevice::getGap() const 00271 { 00272 return BlueNRGGap::getInstance(); 00273 } 00274 00275 /**************************************************************************/ 00276 /*! 00277 @brief get reference to GATT server object 00278 @param[in] void 00279 @returns GattServer& 00280 */ 00281 /**************************************************************************/ 00282 GattServer &BlueNRGDevice::getGattServer() 00283 { 00284 return BlueNRGGattServer::getInstance(); 00285 } 00286 00287 const GattServer &BlueNRGDevice::getGattServer() const 00288 { 00289 return BlueNRGGattServer::getInstance(); 00290 } 00291 00292 /**************************************************************************/ 00293 /*! 00294 @brief shut down the BLE device 00295 @param[out] error if any 00296 */ 00297 /**************************************************************************/ 00298 ble_error_t BlueNRGDevice::shutdown(void) { 00299 if (!isInitialized) { 00300 return BLE_ERROR_INITIALIZATION_INCOMPLETE; 00301 } 00302 00303 /* Reset the BlueNRG device first */ 00304 reset(); 00305 00306 /* Shutdown the BLE API and BlueNRG glue code */ 00307 ble_error_t error; 00308 00309 /* GattServer instance */ 00310 error = BlueNRGGattServer::getInstance().reset(); 00311 if (error != BLE_ERROR_NONE) { 00312 return error; 00313 } 00314 00315 /* GattClient instance */ 00316 error = BlueNRGGattClient::getInstance().reset(); 00317 if (error != BLE_ERROR_NONE) { 00318 return error; 00319 } 00320 00321 /* Gap instance */ 00322 error = BlueNRGGap::getInstance().reset(); 00323 if (error != BLE_ERROR_NONE) { 00324 return error; 00325 } 00326 00327 isInitialized = false; 00328 00329 return BLE_ERROR_NONE; 00330 00331 } 00332 00333 /** 00334 * @brief Reads from BlueNRG SPI buffer and store data into local buffer. 00335 * @param buffer : Buffer where data from SPI are stored 00336 * @param buff_size: Buffer size 00337 * @retval int32_t : Number of read bytes 00338 */ 00339 int32_t BlueNRGDevice::spiRead(uint8_t *buffer, uint8_t buff_size) 00340 { 00341 uint16_t byte_count; 00342 uint8_t len = 0; 00343 uint8_t char_ff = 0xff; 00344 volatile uint8_t read_char; 00345 00346 uint8_t i = 0; 00347 volatile uint8_t tmpreg; 00348 00349 uint8_t header_master[HEADER_SIZE] = {0x0b, 0x00, 0x00, 0x00, 0x00}; 00350 uint8_t header_slave[HEADER_SIZE]; 00351 00352 /* Select the chip */ 00353 nCS_ = 0; 00354 00355 /* Read the header */ 00356 for (i = 0; i < 5; i++) 00357 { 00358 tmpreg = spi_.write(header_master[i]); 00359 header_slave[i] = (uint8_t)(tmpreg); 00360 } 00361 00362 if (header_slave[0] == 0x02) { 00363 /* device is ready */ 00364 byte_count = (header_slave[4]<<8)|header_slave[3]; 00365 00366 if (byte_count > 0) { 00367 00368 /* avoid to read more data that size of the buffer */ 00369 if (byte_count > buff_size){ 00370 byte_count = buff_size; 00371 } 00372 00373 for (len = 0; len < byte_count; len++){ 00374 read_char = spi_.write(char_ff); 00375 buffer[len] = read_char; 00376 } 00377 } 00378 } 00379 /* Release CS line to deselect the chip */ 00380 nCS_ = 1; 00381 00382 // Add a small delay to give time to the BlueNRG to set the IRQ pin low 00383 // to avoid a useless SPI read at the end of the transaction 00384 for(volatile int i = 0; i < 2; i++)__NOP(); 00385 00386 #ifdef PRINT_CSV_FORMAT 00387 if (len > 0) { 00388 print_csv_time(); 00389 for (int i=0; i<len; i++) { 00390 PRINT_CSV(" %02x", buffer[i]); 00391 } 00392 PRINT_CSV("\n"); 00393 } 00394 #endif 00395 00396 return len; 00397 } 00398 00399 /** 00400 * @brief Writes data from local buffer to SPI. 00401 * @param data1 : First data buffer to be written 00402 * @param data2 : Second data buffer to be written 00403 * @param Nb_bytes1: Size of first data buffer to be written 00404 * @param Nb_bytes2: Size of second data buffer to be written 00405 * @retval Number of read bytes 00406 */ 00407 int32_t BlueNRGDevice::spiWrite(uint8_t* data1, 00408 uint8_t* data2, uint8_t Nb_bytes1, uint8_t Nb_bytes2) 00409 { 00410 int32_t result = 0; 00411 uint32_t i; 00412 volatile uint8_t tmpreg; 00413 00414 unsigned char header_master[HEADER_SIZE] = {0x0a, 0x00, 0x00, 0x00, 0x00}; 00415 unsigned char header_slave[HEADER_SIZE] = {0xaa, 0x00, 0x00, 0x00, 0x00}; 00416 00417 disable_irq(); 00418 00419 /* CS reset */ 00420 nCS_ = 0; 00421 00422 /* Exchange header */ 00423 for (i = 0; i < 5; i++) 00424 { 00425 tmpreg = spi_.write(header_master[i]); 00426 header_slave[i] = tmpreg; 00427 } 00428 00429 if (header_slave[0] == 0x02) { 00430 /* SPI is ready */ 00431 if (header_slave[1] >= (Nb_bytes1+Nb_bytes2)) { 00432 00433 /* Buffer is big enough */ 00434 for (i = 0; i < Nb_bytes1; i++) { 00435 spi_.write(*(data1 + i)); 00436 } 00437 for (i = 0; i < Nb_bytes2; i++) { 00438 spi_.write(*(data2 + i)); 00439 } 00440 } else { 00441 /* Buffer is too small */ 00442 result = -2; 00443 } 00444 } else { 00445 /* SPI is not ready */ 00446 result = -1; 00447 } 00448 00449 /* Release CS line */ 00450 //HAL_GPIO_WritePin(BNRG_SPI_CS_PORT, BNRG_SPI_CS_PIN, GPIO_PIN_SET); 00451 nCS_ = 1; 00452 00453 enable_irq(); 00454 00455 return result; 00456 } 00457 00458 bool BlueNRGDevice::dataPresent() 00459 { 00460 return (irq_ == 1); 00461 } 00462 00463 void BlueNRGDevice::disable_irq() 00464 { 00465 irq_.disable_irq(); 00466 } 00467 00468 void BlueNRGDevice::enable_irq() 00469 { 00470 irq_.enable_irq(); 00471 } 00472 00473 void BlueNRGDevice::processEvents() { 00474 btle_handler(); 00475 }
Generated on Tue Jul 12 2022 23:02:56 by
