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 'bluenrg_targets.h' for details regarding the peripheral pins used! 00068 */ 00069 #include "bluenrg_targets.h" 00070 00071 BlueNRGDevice bluenrgDeviceInstance(BLUENRG_PIN_SPI_MOSI, 00072 BLUENRG_PIN_SPI_MISO, 00073 BLUENRG_PIN_SPI_SCK, 00074 BLUENRG_PIN_SPI_nCS, 00075 BLUENRG_PIN_SPI_RESET, 00076 BLUENRG_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 /* Reset BlueNRG SPI interface. Hold reset line to 0 for 1500us */ 00212 rst_ = 0; 00213 wait_us(1500); 00214 rst_ = 1; 00215 00216 /* Wait for the radio to come back up */ 00217 wait_us(5000); 00218 } 00219 00220 /*! 00221 @brief Wait for any BLE Event like BLE Connection, Read Request etc. 00222 @param[in] void 00223 @returns char * 00224 */ 00225 void BlueNRGDevice::waitForEvent(void) 00226 { 00227 bool must_return = false; 00228 00229 do { 00230 bluenrgDeviceInstance.processEvents(); 00231 00232 if(must_return) return; 00233 00234 __WFE(); /* it is recommended that SEVONPEND in the 00235 System Control Register is NOT set */ 00236 must_return = true; /* after returning from WFE we must guarantee 00237 that conrol is given back to main loop before next WFE */ 00238 } while(true); 00239 00240 } 00241 00242 /*! 00243 @brief get GAP version 00244 @brief Get the BLE stack version information 00245 @param[in] void 00246 @returns char * 00247 @returns char * 00248 */ 00249 const char *BlueNRGDevice::getVersion(void) 00250 { 00251 return getVersionString(); 00252 } 00253 00254 /**************************************************************************/ 00255 /*! 00256 @brief get reference to GAP object 00257 @param[in] void 00258 @returns Gap& 00259 */ 00260 /**************************************************************************/ 00261 Gap &BlueNRGDevice::getGap() 00262 { 00263 return BlueNRGGap::getInstance(); 00264 } 00265 00266 const Gap &BlueNRGDevice::getGap() const 00267 { 00268 return BlueNRGGap::getInstance(); 00269 } 00270 00271 /**************************************************************************/ 00272 /*! 00273 @brief get reference to GATT server object 00274 @param[in] void 00275 @returns GattServer& 00276 */ 00277 /**************************************************************************/ 00278 GattServer &BlueNRGDevice::getGattServer() 00279 { 00280 return BlueNRGGattServer::getInstance(); 00281 } 00282 00283 const GattServer &BlueNRGDevice::getGattServer() const 00284 { 00285 return BlueNRGGattServer::getInstance(); 00286 } 00287 00288 /**************************************************************************/ 00289 /*! 00290 @brief shut down the BLE device 00291 @param[out] error if any 00292 */ 00293 /**************************************************************************/ 00294 ble_error_t BlueNRGDevice::shutdown(void) { 00295 PRINTF("BlueNRGDevice::reset\n"); 00296 00297 if (!isInitialized) { 00298 return BLE_ERROR_INITIALIZATION_INCOMPLETE; 00299 } 00300 00301 /* Reset the BlueNRG device first */ 00302 reset(); 00303 00304 /* Shutdown the BLE API and BlueNRG glue code */ 00305 ble_error_t error; 00306 00307 /* GattServer instance */ 00308 error = BlueNRGGattServer::getInstance().reset(); 00309 if (error != BLE_ERROR_NONE) { 00310 return error; 00311 } 00312 00313 /* GattClient instance */ 00314 error = BlueNRGGattClient::getInstance().reset(); 00315 if (error != BLE_ERROR_NONE) { 00316 return error; 00317 } 00318 00319 /* Gap instance */ 00320 error = BlueNRGGap::getInstance().reset(); 00321 if (error != BLE_ERROR_NONE) { 00322 return error; 00323 } 00324 00325 isInitialized = false; 00326 00327 PRINTF("BlueNRGDevice::reset complete\n"); 00328 return BLE_ERROR_NONE; 00329 00330 } 00331 00332 /** 00333 * @brief Reads from BlueNRG SPI buffer and store data into local buffer. 00334 * @param buffer : Buffer where data from SPI are stored 00335 * @param buff_size: Buffer size 00336 * @retval int32_t : Number of read bytes 00337 */ 00338 int32_t BlueNRGDevice::spiRead(uint8_t *buffer, uint8_t buff_size) 00339 { 00340 uint16_t byte_count; 00341 uint8_t len = 0; 00342 uint8_t char_ff = 0xff; 00343 volatile uint8_t read_char; 00344 00345 uint8_t i = 0; 00346 volatile uint8_t tmpreg; 00347 00348 uint8_t header_master[HEADER_SIZE] = {0x0b, 0x00, 0x00, 0x00, 0x00}; 00349 uint8_t header_slave[HEADER_SIZE]; 00350 00351 /* Select the chip */ 00352 nCS_ = 0; 00353 00354 /* Read the header */ 00355 for (i = 0; i < 5; i++) 00356 { 00357 tmpreg = spi_.write(header_master[i]); 00358 header_slave[i] = (uint8_t)(tmpreg); 00359 } 00360 00361 if (header_slave[0] == 0x02) { 00362 /* device is ready */ 00363 byte_count = (header_slave[4]<<8)|header_slave[3]; 00364 00365 if (byte_count > 0) { 00366 00367 /* avoid to read more data that size of the buffer */ 00368 if (byte_count > buff_size){ 00369 byte_count = buff_size; 00370 } 00371 00372 for (len = 0; len < byte_count; len++){ 00373 read_char = spi_.write(char_ff); 00374 buffer[len] = read_char; 00375 } 00376 } 00377 } 00378 /* Release CS line to deselect the chip */ 00379 nCS_ = 1; 00380 00381 // Add a small delay to give time to the BlueNRG to set the IRQ pin low 00382 // to avoid a useless SPI read at the end of the transaction 00383 for(volatile int i = 0; i < 2; i++)__NOP(); 00384 00385 #ifdef PRINT_CSV_FORMAT 00386 if (len > 0) { 00387 print_csv_time(); 00388 for (int i=0; i<len; i++) { 00389 PRINT_CSV(" %02x", buffer[i]); 00390 } 00391 PRINT_CSV("\n"); 00392 } 00393 #endif 00394 00395 return len; 00396 } 00397 00398 /** 00399 * @brief Writes data from local buffer to SPI. 00400 * @param data1 : First data buffer to be written 00401 * @param data2 : Second data buffer to be written 00402 * @param Nb_bytes1: Size of first data buffer to be written 00403 * @param Nb_bytes2: Size of second data buffer to be written 00404 * @retval Number of read bytes 00405 */ 00406 int32_t BlueNRGDevice::spiWrite(uint8_t* data1, 00407 uint8_t* data2, uint8_t Nb_bytes1, uint8_t Nb_bytes2) 00408 { 00409 int32_t result = 0; 00410 uint32_t i; 00411 volatile uint8_t tmpreg; 00412 00413 unsigned char header_master[HEADER_SIZE] = {0x0a, 0x00, 0x00, 0x00, 0x00}; 00414 unsigned char header_slave[HEADER_SIZE] = {0xaa, 0x00, 0x00, 0x00, 0x00}; 00415 00416 disable_irq(); 00417 00418 /* CS reset */ 00419 nCS_ = 0; 00420 00421 /* Exchange header */ 00422 for (i = 0; i < 5; i++) 00423 { 00424 tmpreg = spi_.write(header_master[i]); 00425 header_slave[i] = tmpreg; 00426 } 00427 00428 if (header_slave[0] == 0x02) { 00429 /* SPI is ready */ 00430 if (header_slave[1] >= (Nb_bytes1+Nb_bytes2)) { 00431 00432 /* Buffer is big enough */ 00433 for (i = 0; i < Nb_bytes1; i++) { 00434 spi_.write(*(data1 + i)); 00435 } 00436 for (i = 0; i < Nb_bytes2; i++) { 00437 spi_.write(*(data2 + i)); 00438 } 00439 } else { 00440 /* Buffer is too small */ 00441 result = -2; 00442 } 00443 } else { 00444 /* SPI is not ready */ 00445 result = -1; 00446 } 00447 00448 /* Release CS line */ 00449 //HAL_GPIO_WritePin(BNRG_SPI_CS_PORT, BNRG_SPI_CS_PIN, GPIO_PIN_SET); 00450 nCS_ = 1; 00451 00452 enable_irq(); 00453 00454 return result; 00455 } 00456 00457 bool BlueNRGDevice::dataPresent() 00458 { 00459 return (irq_ == 1); 00460 } 00461 00462 void BlueNRGDevice::disable_irq() 00463 { 00464 irq_.disable_irq(); 00465 } 00466 00467 void BlueNRGDevice::enable_irq() 00468 { 00469 irq_.enable_irq(); 00470 } 00471 00472 void BlueNRGDevice::processEvents() { 00473 btle_handler(); 00474 }
Generated on Tue Jul 12 2022 21:43:59 by
1.7.2