ver:init

Revision:
0:88b85febcb45
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/source/BlueNRGDevice.cpp	Sun Jun 18 16:10:28 2017 +0000
@@ -0,0 +1,475 @@
+/* mbed Microcontroller Library
+* Copyright (c) 2006-2013 ARM Limited
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/**
+  ******************************************************************************
+  * @file    BlueNRGDevice.cpp
+  * @author  STMicroelectronics
+  * @brief   Implementation of BLEDeviceInstanceBase
+  ******************************************************************************
+  * @copy
+  *
+  * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
+  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
+  * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
+  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
+  * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
+  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+  *
+  * <h2><center>&copy; COPYRIGHT 2013 STMicroelectronics</center></h2>
+  */
+
+/** @defgroup BlueNRGDevice
+ *  @brief BlueNRG BLE_API Device Adaptation
+ *  @{
+ */
+ 
+#ifdef YOTTA_CFG_MBED_OS
+    #include "mbed-drivers/mbed.h"
+#else
+    #include "mbed.h"
+#endif
+#include "BlueNRGDevice.h"
+#include "BlueNRGGap.h"
+#include "BlueNRGGattServer.h"
+
+#include "btle.h"
+#include "ble_utils.h"
+#include "ble_osal.h"
+
+#include "ble_debug.h"
+#include "stm32_bluenrg_ble.h"
+
+extern "C" {
+    #include "ble_hci.h"
+    #include "bluenrg_utils.h"
+}
+
+#define HEADER_SIZE 5
+#define MAX_BUFFER_SIZE 255
+
+/**
+ * The singleton which represents the BlueNRG transport for the BLEDevice.
+ *
+ * See file 'x_nucleo_idb0xa1_targets.h' for details regarding the peripheral pins used!
+ */
+#include "x_nucleo_idb0xa1_targets.h"
+
+BlueNRGDevice bluenrgDeviceInstance(IDB0XA1_PIN_SPI_MOSI,
+                                    IDB0XA1_PIN_SPI_MISO,
+                                    IDB0XA1_PIN_SPI_SCK,
+                                    IDB0XA1_PIN_SPI_nCS,
+                                    IDB0XA1_PIN_SPI_RESET,
+                                    IDB0XA1_PIN_SPI_IRQ);
+
+/**
+* BLE-API requires an implementation of the following function in order to
+* obtain its transport handle.
+*/
+BLEInstanceBase *
+createBLEInstance(void)
+{
+    return (&bluenrgDeviceInstance);
+}
+
+/**************************************************************************/
+/**
+    @brief  Constructor
+     * @param mosi mbed pin to use for MOSI line of SPI interface
+     * @param miso mbed pin to use for MISO line of SPI interface
+     * @param sck mbed pin to use for SCK line of SPI interface
+     * @param cs mbed pin to use for not chip select line of SPI interface
+     * @param rst mbed pin to use for BlueNRG reset
+     * @param irq mbed pin for BlueNRG IRQ
+*/
+/**************************************************************************/
+BlueNRGDevice::BlueNRGDevice(PinName mosi,
+                             PinName miso,
+                             PinName sck,
+                             PinName cs,
+                             PinName rst,
+                             PinName irq) :
+	isInitialized(false), spi_(mosi, miso, sck), nCS_(cs), rst_(rst), irq_(irq)
+{
+    // Setup the spi for 8 bit data, low clock polarity,
+    // 1-edge phase, with an 8MHz clock rate
+    spi_.format(8, 0);
+    spi_.frequency(8000000);
+
+    // Deselect the BlueNRG chip by keeping its nCS signal high
+    nCS_ = 1;
+
+    wait_us(500);
+
+    // Prepare communication between the host and the BlueNRG SPI interface
+    HCI_Init();
+
+    // Set the interrupt handler for the device
+    irq_.mode(PullDown); // set irq mode
+    irq_.rise(&HCI_Isr);
+}
+
+/**************************************************************************/
+/**
+    @brief  Destructor
+*/
+/**************************************************************************/
+BlueNRGDevice::~BlueNRGDevice(void)
+{
+}
+
+/**
+  * @brief  Get BlueNRG HW version in bootloader mode
+  * @param  hw_version The HW version is written to this parameter
+  * @retval It returns BLE_STATUS_SUCCESS on success or an error code otherwise
+  */
+uint8_t BlueNRGDevice::getUpdaterHardwareVersion(uint8_t *hw_version)
+{
+	uint8_t status;
+
+	status = getBlueNRGUpdaterHWVersion(hw_version);
+
+	return (status);
+}
+
+/**
+  * @brief  Flash a new firmware using internal bootloader.
+  * @param  fw_image     Pointer to the firmware image (raw binary data,
+  *                      little-endian).
+  * @param  fw_size      Size of the firmware image. The firmware image size shall
+  *                      be multiple of 4 bytes.
+  * @retval int      It returns BLE_STATUS_SUCCESS on success, or a number
+  *                  not equal to 0 in case of error
+  *                  (ACI_ERROR, UNSUPPORTED_VERSION, WRONG_IMAGE_SIZE, CRC_ERROR)
+  */
+int BlueNRGDevice::updateFirmware(const uint8_t *fw_image, uint32_t fw_size)
+{
+	int status = program_device(fw_image, fw_size);
+
+	return (status);
+}
+
+
+/**
+  * @brief  Initialises anything required to start using BLE
+  * @param[in] instanceID
+  *              The ID of the instance to initialize.
+  * @param[in] callback
+  *              A callback for when initialization completes for a BLE
+  *              instance. This is an optional parameter set to NULL when not
+  *              supplied.
+  *
+  * @return BLE_ERROR_NONE if the initialization procedure was started
+  *         successfully.
+  */
+ble_error_t BlueNRGDevice::init(BLE::InstanceID_t instanceID, FunctionPointerWithContext<BLE::InitializationCompleteCallbackContext *> callback)
+{
+	if (isInitialized) {
+        	BLE::InitializationCompleteCallbackContext context = {
+        	    BLE::Instance(instanceID),
+        	    BLE_ERROR_ALREADY_INITIALIZED
+        	};
+        	callback.call(&context);
+        	return BLE_ERROR_ALREADY_INITIALIZED;
+    	}
+
+	// Init the BlueNRG/BlueNRG-MS stack
+	btleInit();
+
+	isInitialized = true;
+	BLE::InitializationCompleteCallbackContext context = {
+	        BLE::Instance(instanceID),
+	        BLE_ERROR_NONE
+	};
+	callback.call(&context);
+
+	return BLE_ERROR_NONE;
+}
+
+
+/**
+    @brief  Resets the BLE HW, removing any existing services and
+            characteristics
+    @param[in] void
+    @returns    void
+*/
+void BlueNRGDevice::reset(void)
+{
+    wait_us(500);
+
+    /* Reset BlueNRG SPI interface */
+	  rst_ = 0;
+  	wait_us(5);
+	  rst_ = 1;
+  	wait_us(5);
+
+    /* Wait for the radio to come back up */
+    wait_us(500);
+
+}
+
+/*!
+  @brief  Wait for any BLE Event like BLE Connection, Read Request etc.
+  @param[in] void
+  @returns    char *
+*/
+void BlueNRGDevice::waitForEvent(void)
+{
+	bool must_return = false;
+
+	do {
+        bluenrgDeviceInstance.processEvents();
+
+		if(must_return) return;
+
+		__WFE(); /* it is recommended that SEVONPEND in the
+			    System Control Register is NOT set */
+		must_return = true; /* after returning from WFE we must guarantee
+				       that conrol is given back to main loop before next WFE */
+	} while(true);
+
+}
+
+/*!
+    @brief  get GAP version
+    @brief Get the BLE stack version information
+    @param[in] void
+    @returns    char *
+    @returns char *
+*/
+const char *BlueNRGDevice::getVersion(void)
+{
+    return getVersionString();
+}
+
+/**************************************************************************/
+/*!
+    @brief  get reference to GAP object
+    @param[in] void
+    @returns    Gap&
+*/
+/**************************************************************************/
+Gap        &BlueNRGDevice::getGap()
+{
+    return BlueNRGGap::getInstance();
+}
+
+const Gap  &BlueNRGDevice::getGap() const
+{
+    return BlueNRGGap::getInstance();
+}
+
+/**************************************************************************/
+/*!
+    @brief  get reference to GATT server object
+    @param[in] void
+    @returns    GattServer&
+*/
+/**************************************************************************/
+GattServer &BlueNRGDevice::getGattServer()
+{
+    return BlueNRGGattServer::getInstance();
+}
+
+const GattServer &BlueNRGDevice::getGattServer() const
+{
+    return BlueNRGGattServer::getInstance();
+}
+
+/**************************************************************************/
+/*!
+    @brief  shut down the BLE device
+    @param[out] error if any
+*/
+/**************************************************************************/
+ble_error_t  BlueNRGDevice::shutdown(void) {
+    if (!isInitialized) {
+        return BLE_ERROR_INITIALIZATION_INCOMPLETE;
+    }
+
+    /* Reset the BlueNRG device first */
+    reset();
+
+    /* Shutdown the BLE API and BlueNRG glue code */
+    ble_error_t error;
+
+    /* GattServer instance */
+    error = BlueNRGGattServer::getInstance().reset();
+    if (error != BLE_ERROR_NONE) {
+       return error;
+    }
+
+    /* GattClient instance */
+    error = BlueNRGGattClient::getInstance().reset();
+    if (error != BLE_ERROR_NONE) {
+        return error;
+    }
+
+    /* Gap instance */
+    error = BlueNRGGap::getInstance().reset();
+    if (error != BLE_ERROR_NONE) {
+        return error;
+    }
+
+    isInitialized = false;
+
+    return BLE_ERROR_NONE;
+
+}
+
+/**
+ * @brief  Reads from BlueNRG SPI buffer and store data into local buffer.
+ * @param  buffer   : Buffer where data from SPI are stored
+ * @param  buff_size: Buffer size
+ * @retval int32_t  : Number of read bytes
+ */
+int32_t BlueNRGDevice::spiRead(uint8_t *buffer, uint8_t buff_size)
+{
+  uint16_t byte_count;
+  uint8_t len = 0;
+  uint8_t char_ff = 0xff;
+  volatile uint8_t read_char;
+
+	uint8_t i = 0;
+	volatile uint8_t tmpreg;
+
+  uint8_t header_master[HEADER_SIZE] = {0x0b, 0x00, 0x00, 0x00, 0x00};
+  uint8_t header_slave[HEADER_SIZE];
+
+  /* Select the chip */
+  nCS_ = 0;
+
+  /* Read the header */
+  for (i = 0; i < 5; i++)
+  {
+		tmpreg = spi_.write(header_master[i]);
+		header_slave[i] = (uint8_t)(tmpreg);
+  }
+
+  if (header_slave[0] == 0x02) {
+    /* device is ready */
+    byte_count = (header_slave[4]<<8)|header_slave[3];
+
+    if (byte_count > 0) {
+
+      /* avoid to read more data that size of the buffer */
+      if (byte_count > buff_size){
+        byte_count = buff_size;
+      }
+
+      for (len = 0; len < byte_count; len++){
+        read_char = spi_.write(char_ff);
+				buffer[len] = read_char;
+      }
+    }
+  }
+  /* Release CS line to deselect the chip */
+  nCS_ = 1;
+
+  // Add a small delay to give time to the BlueNRG to set the IRQ pin low
+  // to avoid a useless SPI read at the end of the transaction
+  for(volatile int i = 0; i < 2; i++)__NOP();
+
+#ifdef PRINT_CSV_FORMAT
+  if (len > 0) {
+    print_csv_time();
+    for (int i=0; i<len; i++) {
+      PRINT_CSV(" %02x", buffer[i]);
+    }
+    PRINT_CSV("\n");
+  }
+#endif
+
+  return len;
+}
+
+/**
+ * @brief  Writes data from local buffer to SPI.
+ * @param  data1    : First data buffer to be written
+ * @param  data2    : Second data buffer to be written
+ * @param  Nb_bytes1: Size of first data buffer to be written
+ * @param  Nb_bytes2: Size of second data buffer to be written
+ * @retval Number of read bytes
+ */
+int32_t BlueNRGDevice::spiWrite(uint8_t* data1,
+				uint8_t* data2, uint8_t Nb_bytes1, uint8_t Nb_bytes2)
+{
+	int32_t result = 0;
+	uint32_t i;
+	volatile uint8_t tmpreg;
+
+  unsigned char header_master[HEADER_SIZE] = {0x0a, 0x00, 0x00, 0x00, 0x00};
+  unsigned char header_slave[HEADER_SIZE]  = {0xaa, 0x00, 0x00, 0x00, 0x00};
+
+  disable_irq();
+
+  /* CS reset */
+  nCS_ = 0;
+
+  /* Exchange header */
+  for (i = 0; i < 5; i++)
+  {
+		tmpreg = spi_.write(header_master[i]);
+		header_slave[i] = tmpreg;
+  }
+
+  if (header_slave[0] == 0x02) {
+    /* SPI is ready */
+    if (header_slave[1] >= (Nb_bytes1+Nb_bytes2)) {
+
+      /*  Buffer is big enough */
+			for (i = 0; i < Nb_bytes1; i++) {
+				spi_.write(*(data1 + i));
+      }
+      for (i = 0; i < Nb_bytes2; i++) {
+				spi_.write(*(data2 + i));
+      }
+    } else {
+      /* Buffer is too small */
+      result = -2;
+    }
+  } else {
+    /* SPI is not ready */
+    result = -1;
+  }
+
+  /* Release CS line */
+  //HAL_GPIO_WritePin(BNRG_SPI_CS_PORT, BNRG_SPI_CS_PIN, GPIO_PIN_SET);
+  nCS_ = 1;
+
+  enable_irq();
+
+  return result;
+}
+
+bool BlueNRGDevice::dataPresent()
+{
+    return (irq_ == 1);
+}
+
+void BlueNRGDevice::disable_irq()
+{
+    irq_.disable_irq();
+}
+
+void BlueNRGDevice::enable_irq()
+{
+    irq_.enable_irq();
+}
+
+void BlueNRGDevice::processEvents() {
+    btle_handler();
+}