test

Dependents:   BLE_HeartRate_IDB0XA1_EPUDEE_Avril2018

Fork of X_NUCLEO_IDB0XA1 by ST

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers BlueNRGDevice.cpp Source File

BlueNRGDevice.cpp

Go to the documentation of this file.
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>&copy; 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 }