Antonio Vilei / X_NUCLEO_IDB0XA1

Fork of X_NUCLEO_IDB0XA1 by ST Expansion SW Team

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 #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 }