COMPONENT_BlueNRG_MS cleanup

- use of json config
- add license header
- update ReadMe
- remove mbed.h
- astyle
pull/12456/head
jeromecoutant 2020-03-12 17:14:18 +01:00
parent a9135a1971
commit aa66ae52bc
4 changed files with 311 additions and 265 deletions

View File

@ -1,15 +1,43 @@
/*
* Copyright (c) 2017-2020 ARM Limited
* Copyright (c) 2017-2020 STMicroelectronics
* SPDX-License-Identifier: Apache-2.0
*
* 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.
*/
#include <stdio.h> #include <stdio.h>
// drivers
#include "drivers/DigitalOut.h"
#include "drivers/SPI.h"
#include "drivers/InterruptIn.h"
// platform
#include "platform/mbed_wait_api.h"
// FEATURE_BLE/targets/TARGET_CORDIO
#include "CordioBLE.h" #include "CordioBLE.h"
#include "CordioHCIDriver.h" #include "CordioHCIDriver.h"
#include "CordioHCITransportDriver.h" #include "CordioHCITransportDriver.h"
#include "mbed.h"
#include "hci_api.h" #include "hci_api.h"
#include "hci_cmd.h" #include "hci_cmd.h"
#include "hci_core.h" #include "hci_core.h"
#include "dm_api.h" #include "dm_api.h"
#include "bstream.h" #include "bstream.h"
#include "hci_mbed_os_adaptation.h" #include "hci_mbed_os_adaptation.h"
#include "bluenrg_targets.h"
// rtos
#include "Thread.h" #include "Thread.h"
#include "Semaphore.h" #include "Semaphore.h"
#include "Mutex.h" #include "Mutex.h"
@ -38,21 +66,21 @@ namespace bluenrg {
* BlueNRG HCI driver implementation. * BlueNRG HCI driver implementation.
* @see cordio::CordioHCIDriver * @see cordio::CordioHCIDriver
*/ */
class HCIDriver : public cordio::CordioHCIDriver class HCIDriver : public cordio::CordioHCIDriver {
{
public: public:
/** /**
* Construction of the BlueNRG HCIDriver. * Construction of the BlueNRG HCIDriver.
* @param transport: Transport of the HCI commands. * @param transport: Transport of the HCI commands.
* @param rst: Name of the reset pin * @param rst: Name of the reset pin
*/ */
HCIDriver(cordio::CordioHCITransportDriver& transport_driver, PinName rst) : HCIDriver(cordio::CordioHCITransportDriver &transport_driver, PinName rst) :
cordio::CordioHCIDriver(transport_driver), rst(rst) { } cordio::CordioHCIDriver(transport_driver), rst(rst) { }
/** /**
* @see CordioHCIDriver::do_initialize * @see CordioHCIDriver::do_initialize
*/ */
virtual void do_initialize() { virtual void do_initialize()
{
bluenrg_reset(); bluenrg_reset();
} }
@ -68,7 +96,8 @@ public:
/** /**
* @see CordioHCIDriver::start_reset_sequence * @see CordioHCIDriver::start_reset_sequence
*/ */
virtual void start_reset_sequence() { virtual void start_reset_sequence()
{
reset_received = false; reset_received = false;
bluenrg_initialized = false; bluenrg_initialized = false;
enable_link_layer_mode_ongoing = false; enable_link_layer_mode_ongoing = false;
@ -79,21 +108,21 @@ public:
/** /**
* @see CordioHCIDriver::do_terminate * @see CordioHCIDriver::do_terminate
*/ */
virtual void do_terminate() { virtual void do_terminate()
{
} }
/** /**
* @see CordioHCIDriver::handle_reset_sequence * @see CordioHCIDriver::handle_reset_sequence
*/ */
virtual void handle_reset_sequence(uint8_t *pMsg) { virtual void handle_reset_sequence(uint8_t *pMsg)
{
uint16_t opcode; uint16_t opcode;
static uint8_t randCnt; static uint8_t randCnt;
//wait_ms(5);
/* if event is a command complete event */ /* if event is a command complete event */
if (*pMsg == HCI_CMD_CMPL_EVT) if (*pMsg == HCI_CMD_CMPL_EVT) {
{
/* parse parameters */ /* parse parameters */
pMsg += HCI_EVT_HDR_LEN; pMsg += HCI_EVT_HDR_LEN;
pMsg++; /* skip num packets */ pMsg++; /* skip num packets */
@ -101,113 +130,110 @@ public:
pMsg++; /* skip status */ pMsg++; /* skip status */
/* decode opcode */ /* decode opcode */
switch (opcode) switch (opcode) {
{ case HCI_OPCODE_RESET: {
case HCI_OPCODE_RESET: { /* initialize rand command count */
/* initialize rand command count */ randCnt = 0;
randCnt = 0; reset_received = true;
reset_received = true; // bluenrg_initialized event has to come after the hci reset event
// important, the bluenrg_initialized event come after the bluenrg_initialized = false;
// hci reset event (not documented)
bluenrg_initialized = false;
} break;
// ACL packet ...
case ACI_WRITE_CONFIG_DATA_OPCODE:
if (enable_link_layer_mode_ongoing) {
enable_link_layer_mode_ongoing = false;
aciSetRole();
} else {
aciGattInit();
} }
break; break;
case ACI_GATT_INIT_OPCODE: // ACL packet
aciGapInit(); case ACI_WRITE_CONFIG_DATA_OPCODE:
break; if (enable_link_layer_mode_ongoing) {
enable_link_layer_mode_ongoing = false;
aciSetRole();
} else {
aciGattInit();
}
break;
case ACI_GAP_INIT_OPCODE: case ACI_GATT_INIT_OPCODE:
aciReadConfigParameter(RANDOM_STATIC_ADDRESS_OFFSET); aciGapInit();
break; break;
case ACI_READ_CONFIG_DATA_OPCODE: case ACI_GAP_INIT_OPCODE:
// note: will send the HCI command to send the random address aciReadConfigParameter(RANDOM_STATIC_ADDRESS_OFFSET);
set_random_static_address(pMsg); break;
break;
case HCI_OPCODE_LE_SET_RAND_ADDR: case ACI_READ_CONFIG_DATA_OPCODE:
HciSetEventMaskCmd((uint8_t *) hciEventMask); // note: will send the HCI command to send the random address
break; set_random_static_address(pMsg);
break;
case HCI_OPCODE_SET_EVENT_MASK: case HCI_OPCODE_LE_SET_RAND_ADDR:
/* send next command in sequence */ HciSetEventMaskCmd((uint8_t *) hciEventMask);
HciLeSetEventMaskCmd((uint8_t *) hciLeEventMask); break;
break;
case HCI_OPCODE_LE_SET_EVENT_MASK: case HCI_OPCODE_SET_EVENT_MASK:
// Note: the public address is not read because there is no valid public address /* send next command in sequence */
// provisioned by default on the target HciLeSetEventMaskCmd((uint8_t *) hciLeEventMask);
// Enable if the break;
#if MBED_CONF_CORDIO_BLUENRG_VALID_PUBLIC_BD_ADDRESS == 1
/* send next command in sequence */
HciReadBdAddrCmd();
break;
case HCI_OPCODE_READ_BD_ADDR: case HCI_OPCODE_LE_SET_EVENT_MASK:
/* parse and store event parameters */ // Note: the public address is not read because there is no valid public address provisioned by default on the target
BdaCpy(hciCoreCb.bdAddr, pMsg); // You can enable it thanks to json "valid-public-bd-address" config value
#if MBED_CONF_BLUENRG_MS_VALID_PUBLIC_BD_ADDRESS == 1
/* send next command in sequence */
HciReadBdAddrCmd();
break;
/* send next command in sequence */ case HCI_OPCODE_READ_BD_ADDR:
/* parse and store event parameters */
BdaCpy(hciCoreCb.bdAddr, pMsg);
/* send next command in sequence */
#endif #endif
HciLeReadBufSizeCmd(); HciLeReadBufSizeCmd();
break; break;
case HCI_OPCODE_LE_READ_BUF_SIZE: case HCI_OPCODE_LE_READ_BUF_SIZE:
/* parse and store event parameters */ /* parse and store event parameters */
BSTREAM_TO_UINT16(hciCoreCb.bufSize, pMsg); BSTREAM_TO_UINT16(hciCoreCb.bufSize, pMsg);
BSTREAM_TO_UINT8(hciCoreCb.numBufs, pMsg); BSTREAM_TO_UINT8(hciCoreCb.numBufs, pMsg);
/* initialize ACL buffer accounting */ /* initialize ACL buffer accounting */
hciCoreCb.availBufs = hciCoreCb.numBufs; hciCoreCb.availBufs = hciCoreCb.numBufs;
/* send next command in sequence */ /* send next command in sequence */
HciLeReadSupStatesCmd(); HciLeReadSupStatesCmd();
break; break;
case HCI_OPCODE_LE_READ_SUP_STATES: case HCI_OPCODE_LE_READ_SUP_STATES:
/* parse and store event parameters */ /* parse and store event parameters */
memcpy(hciCoreCb.leStates, pMsg, HCI_LE_STATES_LEN); memcpy(hciCoreCb.leStates, pMsg, HCI_LE_STATES_LEN);
/* send next command in sequence */ /* send next command in sequence */
HciLeReadWhiteListSizeCmd(); HciLeReadWhiteListSizeCmd();
break; break;
case HCI_OPCODE_LE_READ_WHITE_LIST_SIZE: case HCI_OPCODE_LE_READ_WHITE_LIST_SIZE:
/* parse and store event parameters */ /* parse and store event parameters */
BSTREAM_TO_UINT8(hciCoreCb.whiteListSize, pMsg); BSTREAM_TO_UINT8(hciCoreCb.whiteListSize, pMsg);
/* send next command in sequence */ /* send next command in sequence */
HciLeReadLocalSupFeatCmd(); HciLeReadLocalSupFeatCmd();
break; break;
case HCI_OPCODE_LE_READ_LOCAL_SUP_FEAT: case HCI_OPCODE_LE_READ_LOCAL_SUP_FEAT:
/* parse and store event parameters */ /* parse and store event parameters */
BSTREAM_TO_UINT16(hciCoreCb.leSupFeat, pMsg); BSTREAM_TO_UINT16(hciCoreCb.leSupFeat, pMsg);
/* send next command in sequence */ /* send next command in sequence */
hciCoreReadResolvingListSize(); hciCoreReadResolvingListSize();
break; break;
case HCI_OPCODE_LE_READ_RES_LIST_SIZE: case HCI_OPCODE_LE_READ_RES_LIST_SIZE:
/* parse and store event parameters */ /* parse and store event parameters */
BSTREAM_TO_UINT8(hciCoreCb.resListSize, pMsg); BSTREAM_TO_UINT8(hciCoreCb.resListSize, pMsg);
/* send next command in sequence */ /* send next command in sequence */
hciCoreReadMaxDataLen(); hciCoreReadMaxDataLen();
break; break;
case HCI_OPCODE_LE_READ_MAX_DATA_LEN: case HCI_OPCODE_LE_READ_MAX_DATA_LEN: {
{
uint16_t maxTxOctets; uint16_t maxTxOctets;
uint16_t maxTxTime; uint16_t maxTxTime;
@ -222,49 +248,42 @@ public:
} }
break; break;
case HCI_OPCODE_LE_WRITE_DEF_DATA_LEN: case HCI_OPCODE_LE_WRITE_DEF_DATA_LEN:
if (hciCoreCb.extResetSeq) if (hciCoreCb.extResetSeq) {
{ /* send first extended command */
/* send first extended command */ (*hciCoreCb.extResetSeq)(pMsg, opcode);
(*hciCoreCb.extResetSeq)(pMsg, opcode); } else {
} /* initialize extended parameters */
else hciCoreCb.maxAdvDataLen = 0;
{ hciCoreCb.numSupAdvSets = 0;
/* initialize extended parameters */ hciCoreCb.perAdvListSize = 0;
hciCoreCb.maxAdvDataLen = 0;
hciCoreCb.numSupAdvSets = 0;
hciCoreCb.perAdvListSize = 0;
/* send next command in sequence */ /* send next command in sequence */
HciLeRandCmd(); HciLeRandCmd();
} }
break; break;
case HCI_OPCODE_LE_READ_MAX_ADV_DATA_LEN: case HCI_OPCODE_LE_READ_MAX_ADV_DATA_LEN:
case HCI_OPCODE_LE_READ_NUM_SUP_ADV_SETS: case HCI_OPCODE_LE_READ_NUM_SUP_ADV_SETS:
case HCI_OPCODE_LE_READ_PER_ADV_LIST_SIZE: case HCI_OPCODE_LE_READ_PER_ADV_LIST_SIZE:
if (hciCoreCb.extResetSeq) if (hciCoreCb.extResetSeq) {
{ /* send next extended command in sequence */
/* send next extended command in sequence */ (*hciCoreCb.extResetSeq)(pMsg, opcode);
(*hciCoreCb.extResetSeq)(pMsg, opcode); }
} break;
break;
case HCI_OPCODE_LE_RAND: case HCI_OPCODE_LE_RAND:
/* check if need to send second rand command */ /* check if need to send second rand command */
if (randCnt < (HCI_RESET_RAND_CNT-1)) if (randCnt < (HCI_RESET_RAND_CNT - 1)) {
{ randCnt++;
randCnt++; HciLeRandCmd();
HciLeRandCmd(); } else {
} signal_reset_sequence_done();
else }
{ break;
signal_reset_sequence_done();
}
break;
default: default:
break; break;
} }
} else { } else {
/** /**
@ -290,20 +309,23 @@ public:
} }
private: private:
void aciEnableLinkLayerModeOnly() { void aciEnableLinkLayerModeOnly()
{
uint8_t data[1] = { 0x01 }; uint8_t data[1] = { 0x01 };
enable_link_layer_mode_ongoing = true; enable_link_layer_mode_ongoing = true;
aciWriteConfigData(LL_WITHOUT_HOST_OFFSET, data); aciWriteConfigData(LL_WITHOUT_HOST_OFFSET, data);
} }
void aciSetRole() { void aciSetRole()
{
// master and slave, simultaneous advertising and scanning // master and slave, simultaneous advertising and scanning
// (up to 4 connections) // (up to 4 connections)
uint8_t data[1] = { 0x04 }; uint8_t data[1] = { 0x04 };
aciWriteConfigData(ROLE_OFFSET, data); aciWriteConfigData(ROLE_OFFSET, data);
} }
void aciGattInit() { void aciGattInit()
{
uint8_t *pBuf = hciCmdAlloc(ACI_GATT_INIT_OPCODE, 0); uint8_t *pBuf = hciCmdAlloc(ACI_GATT_INIT_OPCODE, 0);
if (!pBuf) { if (!pBuf) {
return; return;
@ -311,7 +333,8 @@ private:
hciCmdSend(pBuf); hciCmdSend(pBuf);
} }
void aciGapInit() { void aciGapInit()
{
uint8_t *pBuf = hciCmdAlloc(ACI_GAP_INIT_OPCODE, 3); uint8_t *pBuf = hciCmdAlloc(ACI_GAP_INIT_OPCODE, 3);
if (!pBuf) { if (!pBuf) {
return; return;
@ -322,7 +345,8 @@ private:
hciCmdSend(pBuf); hciCmdSend(pBuf);
} }
void aciReadConfigParameter(uint8_t offset) { void aciReadConfigParameter(uint8_t offset)
{
uint8_t *pBuf = hciCmdAlloc(ACI_READ_CONFIG_DATA_OPCODE, 1); uint8_t *pBuf = hciCmdAlloc(ACI_READ_CONFIG_DATA_OPCODE, 1);
if (!pBuf) { if (!pBuf) {
return; return;
@ -333,7 +357,8 @@ private:
} }
template<size_t N> template<size_t N>
void aciWriteConfigData(uint8_t offset, uint8_t (&buf)[N]) { void aciWriteConfigData(uint8_t offset, uint8_t (&buf)[N])
{
uint8_t *pBuf = hciCmdAlloc(ACI_WRITE_CONFIG_DATA_OPCODE, 2 + N); uint8_t *pBuf = hciCmdAlloc(ACI_WRITE_CONFIG_DATA_OPCODE, 2 + N);
if (!pBuf) { if (!pBuf) {
return; return;
@ -349,13 +374,10 @@ private:
{ {
/* if LL Privacy is supported by Controller and included */ /* if LL Privacy is supported by Controller and included */
if ((hciCoreCb.leSupFeat & HCI_LE_SUP_FEAT_PRIVACY) && if ((hciCoreCb.leSupFeat & HCI_LE_SUP_FEAT_PRIVACY) &&
(hciLeSupFeatCfg & HCI_LE_SUP_FEAT_PRIVACY)) (hciLeSupFeatCfg & HCI_LE_SUP_FEAT_PRIVACY)) {
{
/* send next command in sequence */ /* send next command in sequence */
HciLeReadResolvingListSize(); HciLeReadResolvingListSize();
} } else {
else
{
hciCoreCb.resListSize = 0; hciCoreCb.resListSize = 0;
/* send next command in sequence */ /* send next command in sequence */
@ -365,21 +387,19 @@ private:
void hciCoreReadMaxDataLen(void) void hciCoreReadMaxDataLen(void)
{ {
/* if LE Data Packet Length Extensions is supported by Controller and included */ /* if LE Data Packet Length Extensions is supported by Controller and included */
if ((hciCoreCb.leSupFeat & HCI_LE_SUP_FEAT_DATA_LEN_EXT) && if ((hciCoreCb.leSupFeat & HCI_LE_SUP_FEAT_DATA_LEN_EXT) &&
(hciLeSupFeatCfg & HCI_LE_SUP_FEAT_DATA_LEN_EXT)) (hciLeSupFeatCfg & HCI_LE_SUP_FEAT_DATA_LEN_EXT)) {
{
/* send next command in sequence */ /* send next command in sequence */
HciLeReadMaxDataLen(); HciLeReadMaxDataLen();
} } else {
else
{
/* send next command in sequence */ /* send next command in sequence */
HciLeRandCmd(); HciLeRandCmd();
} }
} }
void bluenrg_reset() { void bluenrg_reset()
{
/* Reset BlueNRG SPI interface. Hold reset line to 0 for 1500ms */ /* Reset BlueNRG SPI interface. Hold reset line to 0 for 1500ms */
rst = 0; rst = 0;
wait_us(1500); wait_us(1500);
@ -389,7 +409,7 @@ private:
wait_us(100000); wait_us(100000);
} }
DigitalOut rst; mbed::DigitalOut rst;
bool reset_received; bool reset_received;
bool bluenrg_initialized; bool bluenrg_initialized;
bool enable_link_layer_mode_ongoing; bool enable_link_layer_mode_ongoing;
@ -425,8 +445,9 @@ public:
* @param irq Pin used by the module to signal data are available. * @param irq Pin used by the module to signal data are available.
*/ */
TransportDriver(PinName mosi, PinName miso, PinName sclk, PinName ncs, PinName irq) TransportDriver(PinName mosi, PinName miso, PinName sclk, PinName ncs, PinName irq)
: spi(mosi, miso, sclk), nCS(ncs), irq(irq), _spi_thread(osPriorityNormal, SPI_STACK_SIZE, _spi_thread_stack) { : spi(mosi, miso, sclk), nCS(ncs), irq(irq), _spi_thread(osPriorityNormal, SPI_STACK_SIZE, _spi_thread_stack)
_spi_thread.start(callback(this, &TransportDriver::spi_read_cb)); {
_spi_thread.start(mbed::callback(this, &TransportDriver::spi_read_cb));
} }
virtual ~TransportDriver() { } virtual ~TransportDriver() { }
@ -434,7 +455,8 @@ public:
/** /**
* @see CordioHCITransportDriver::initialize * @see CordioHCITransportDriver::initialize
*/ */
virtual void initialize() { virtual void initialize()
{
// Setup the spi for 8 bit data, low clock polarity, // Setup the spi for 8 bit data, low clock polarity,
// 1-edge phase, with an 8MHz clock rate // 1-edge phase, with an 8MHz clock rate
spi.format(8, 0); spi.format(8, 0);
@ -447,7 +469,7 @@ public:
// Set the interrupt handler for the device // Set the interrupt handler for the device
irq.mode(PullDown); // set irq mode irq.mode(PullDown); // set irq mode
irq.rise(callback(this, &TransportDriver::HCI_Isr)); irq.rise(mbed::callback(this, &TransportDriver::HCI_Isr));
} }
/** /**
@ -458,7 +480,8 @@ public:
/** /**
* @see CordioHCITransportDriver::write * @see CordioHCITransportDriver::write
*/ */
virtual uint16_t write(uint8_t type, uint16_t len, uint8_t *pData) { virtual uint16_t write(uint8_t type, uint16_t len, uint8_t *pData)
{
// repeat write until successfull. A number of attempt or timeout might // repeat write until successfull. A number of attempt or timeout might
// be useful // be useful
while (spiWrite(type, pData, len) == 0) { } while (spiWrite(type, pData, len) == 0) { }
@ -466,7 +489,8 @@ public:
} }
private: private:
uint16_t spiWrite(uint8_t type, const uint8_t* data, uint16_t data_length) { uint16_t spiWrite(uint8_t type, const uint8_t *data, uint16_t data_length)
{
static const uint8_t header_master[] = { static const uint8_t header_master[] = {
0x0A, 0x00, 0x00, 0x00, 0x00 0x0A, 0x00, 0x00, 0x00, 0x00
}; };
@ -501,7 +525,7 @@ private:
spi.write(data[i]); spi.write(data[i]);
} }
exit: exit:
nCS = 1; nCS = 1;
_spi_mutex.unlock(); _spi_mutex.unlock();
@ -509,7 +533,7 @@ private:
return data_written; return data_written;
} }
uint16_t spiRead(uint8_t* data_buffer, const uint16_t buffer_size) uint16_t spiRead(uint8_t *data_buffer, const uint16_t buffer_size)
{ {
static const uint8_t header_master[] = {0x0b, 0x00, 0x00, 0x00, 0x00}; static const uint8_t header_master[] = {0x0b, 0x00, 0x00, 0x00, 0x00};
uint8_t header_slave[5] = { 0xaa, 0x00, 0x00, 0x00, 0x00}; uint8_t header_slave[5] = { 0xaa, 0x00, 0x00, 0x00, 0x00};
@ -534,7 +558,7 @@ private:
data_buffer[i] = spi.write(0xFF); data_buffer[i] = spi.write(0xFF);
} }
exit: exit:
nCS = 1; nCS = 1;
return read_length; return read_length;
@ -549,13 +573,14 @@ private:
_spi_read_sem.release(); _spi_read_sem.release();
} }
void spi_read_cb() { void spi_read_cb()
{
uint8_t data_buffer[256]; uint8_t data_buffer[256];
while(true) { while (true) {
_spi_read_sem.acquire(); _spi_read_sem.acquire();
_spi_mutex.lock(); _spi_mutex.lock();
while(irq == 1) { while (irq == 1) {
uint16_t data_read = spiRead(data_buffer, sizeof(data_buffer)); uint16_t data_read = spiRead(data_buffer, sizeof(data_buffer));
on_data_received(data_buffer, data_read); on_data_received(data_buffer, data_read);
} }
@ -567,8 +592,8 @@ private:
* Unsafe SPI, does not lock when SPI access happens. * Unsafe SPI, does not lock when SPI access happens.
*/ */
::mbed::SPI spi; ::mbed::SPI spi;
DigitalOut nCS; mbed::DigitalOut nCS;
InterruptIn irq; mbed::InterruptIn irq;
rtos::Thread _spi_thread; rtos::Thread _spi_thread;
uint8_t _spi_thread_stack[SPI_STACK_SIZE]; uint8_t _spi_thread_stack[SPI_STACK_SIZE];
rtos::Semaphore _spi_read_sem; rtos::Semaphore _spi_read_sem;
@ -582,17 +607,18 @@ private:
/** /**
* Cordio HCI driver factory * Cordio HCI driver factory
*/ */
ble::vendor::cordio::CordioHCIDriver& ble_cordio_get_hci_driver() { ble::vendor::cordio::CordioHCIDriver &ble_cordio_get_hci_driver()
{
static ble::vendor::bluenrg::TransportDriver transport_driver( static ble::vendor::bluenrg::TransportDriver transport_driver(
BLUENRG_PIN_SPI_MOSI, MBED_CONF_BLUENRG_MS_SPI_MOSI,
BLUENRG_PIN_SPI_MISO, MBED_CONF_BLUENRG_MS_SPI_MISO,
BLUENRG_PIN_SPI_SCK, MBED_CONF_BLUENRG_MS_SPI_SCK,
BLUENRG_PIN_SPI_nCS, MBED_CONF_BLUENRG_MS_SPI_NCS,
BLUENRG_PIN_SPI_IRQ MBED_CONF_BLUENRG_MS_SPI_IRQ
); );
static ble::vendor::bluenrg::HCIDriver hci_driver( static ble::vendor::bluenrg::HCIDriver hci_driver(
transport_driver, transport_driver,
BLUENRG_PIN_SPI_RESET MBED_CONF_BLUENRG_MS_SPI_RESET
); );
return hci_driver; return hci_driver;
} }

View File

@ -1,13 +1,69 @@
# Cordio BLE-X-NUCLEO-IDB0XA1 # BlueNRG_MS
BLE_API wrapper Library for X-NUCLEO-IDB05A1 BlueNRG (Bluetooth Low Energy) Expansion Board. It uses ARM Cordio stack instead of the ST BlueNRG stack. BLE API wrapper Library for BlueNRG (Bluetooth Low Energy)
## Introduction Maybe a simple table like this could help:
This firmware package implements the port of BLE_API to STMicroelectronics' [X-NUCLEO-IDB05A1](https://developer.mbed.org/components/X-NUCLEO-IDB05A1-Bluetooth-Low-Energy/) Bluetooth Low Energy Nucleo Expansion Board. |Name|Type|Bluetooth compliance|Status|Used in shields & boards|Link|
|-----------|----------|-----|-|-|-|
|SPBTLE-RF |Module |v4.1 |Not recommended for new designs |X-NUCLEO-IDB05A1, DISCO-L475VG-IOT01A, DISCO-L562QE | https://www.st.com/en/wireless-transceivers-mcus-and-modules/spbtle-rf.html |
|BlueNRG-M0 |Module |v4.2 |Active (included in ST's Longevity Program) |No | https://www.st.com/en/wireless-transceivers-mcus-and-modules/bluenrg-m0.html |
|BlueNRG-MS |Processor |v4.2 |Active (included in ST's Longevity Program) |X-NUCLEO-IDB05A2 (coming soon) | https://www.st.com/en/wireless-transceivers-mcus-and-modules/bluenrg-ms.html |
It uses ARM Cordio stack instead of the ST BlueNRG stack.
## History
- deprecated ST BLE port: https://github.com/ARMmbed/ble-x-nucleo-idb0xa1
- deprecated X-NUCLEO-IDB05A1 BlueNRG : https://github.com/ARMmbed/cordio-ble-x-nucleo-idb0xa1
## Boards
### X-NUCLEO-IDB05A1
Bluetooth Low Energy Nucleo Expansion Board:
https://developer.mbed.org/components/X-NUCLEO-IDB05A1-Bluetooth-Low-Energy/
### DISCO-L475VG-IOT01A
STM32L4 Discovery kit IoT node, low-power wireless, Bluetooth V4.1 module (SPBTLE-RF)
https://os.mbed.com/platforms/ST-Discovery-L475E-IOT01A/
### DISCO-L562QE
STM32L562E-DK Discovery kit with Bluetooth V4.1 low energy module and Arm Cortex-M33 with TrustZone
https://os.mbed.com/platforms/ST-Discovery-L562QE/
## Driver configuration
In order to use the BlueNRG-MS module together with other targets,
you may need to override default settings in your local `mbed_app.json` file
### ST-DISCO boards
Default settings for `DISCO-L475VG-IOT01A` and `DISCO-L562QE` are configured
### Arduino Connector Compatibility Warning ### Arduino Connector Compatibility Warning
Default Arduino connection is using:
```
"SPI_MOSI": "D11",
"SPI_MISO": "D12",
"SPI_nCS": "A1",
"SPI_RESET": "D7",
"SPI_IRQ": "A0",
"SPI_SCK": "D3",
"valid-public-bd-address": false
```
X-NUCLEO-IDB05A1 is Arduino compatible with an exception: instead of using pin **D13** for the SPI clock, pin **D3** is used. X-NUCLEO-IDB05A1 is Arduino compatible with an exception: instead of using pin **D13** for the SPI clock, pin **D3** is used.
The default configuration for this library is having the SPI clock on pin **D3**. The default configuration for this library is having the SPI clock on pin **D3**.
@ -15,31 +71,47 @@ To be fully Arduino compatible, X-NUCLEO-IDB05A1 needs a small HW patch.
For X-NUCLEO-IDB05A1 this patch consists in removing zero resistor **R4** and instead soldering zero resistor **R6**. For X-NUCLEO-IDB05A1 this patch consists in removing zero resistor **R4** and instead soldering zero resistor **R6**.
In case you patch your board, then you also have to configure this library to use pin **D13** to drive the SPI clock. To this aim you need to compile this driver with macro `BLUENRG_PIN_SPI_SCK=D13` defined. In case you patch your board, then you also have to configure this library to use pin **D13** to drive the SPI clock.
To this aim you need to update your local mbed_app.json file with:
If you use pin **D13** for the SPI clock, please be aware that on STM32 Nucleo boards you may **not** drive the LED, otherwise you will get a conflict: the LED on STM32 Nucleo boards is connected to pin **D13**. ```
"target_overrides": {
"XXXX": {
"bluenrg_ms.SPI_SCK": "D13"
},
```
Referring to the current list of tested platforms (see [X-NUCLEO-IDB05A1](https://developer.mbed.org/components/X-NUCLEO-IDB05A1-Bluetooth-Low-Energy/) page), the patch is required by [ST-Nucleo-F103RB](https://developer.mbed.org/platforms/ST-Nucleo-F103RB/); [ST-Nucleo-F302R8](https://developer.mbed.org/platforms/ST-Nucleo-F302R8/); [ST-Nucleo-F411RE](https://developer.mbed.org/platforms/ST-Nucleo-F411RE/); [ST-Nucleo-F446RE](https://developer.mbed.org/platforms/ST-Nucleo-F446RE/); and [FRDM-K64F](https://developer.mbed.org/platforms/FRDM-K64F/). If you use pin **D13** for the SPI clock, please be aware that on some STM32 Nucleo boards you may **not** drive the LED,
otherwise you will get a conflict: the LED on STM32 Nucleo boards is connected to pin **D13**.
Referring to the current list of tested platforms (see [X-NUCLEO-IDB05A1](https://developer.mbed.org/components/X-NUCLEO-IDB05A1-Bluetooth-Low-Energy/) page),
the patch is required for
- [ST-Nucleo-F103RB](https://developer.mbed.org/platforms/ST-Nucleo-F103RB/)
- [ST-Nucleo-F302R8](https://developer.mbed.org/platforms/ST-Nucleo-F302R8/)
- [ST-Nucleo-F411RE](https://developer.mbed.org/platforms/ST-Nucleo-F411RE/)
- [ST-Nucleo-F446RE](https://developer.mbed.org/platforms/ST-Nucleo-F446RE/)
- [FRDM-K64F](https://developer.mbed.org/platforms/FRDM-K64F/)
### Driver configuration ### Target Configuration
In order to use the BlueNRG-MS module together with other targets, you need to set the macros defined in file [bluenrg_targets.h](https://github.com/ARMmbed/ble-x-nucleo-idb0xa1/blob/master/bluenrg/bluenrg_targets.h). Please, update the [mbed_lib.json](https://github.com/ARMmbed/ble-x-nucleo-idb0xa1/blob/master/mbed_lib.json) to include the list of extra macros that configure the driver for your target.
## Target Configuration
To use that library, the target requires some extra configuration in the application `mbed_app.json`. In the `target_overides` section: To use that library, the target requires some extra configuration in the application `mbed_app.json`. In the `target_overides` section:
* BLE feature has to be enabled for the target using the BlueNRG module * BLE feature has to be enabled
```json ```json
"target.features_add": ["BLE"] "target.features_add": ["BLE"]
``` ```
* BlueNRG module has to be enabled
```json
"target.components_add": ["BlueNRG_MS"]
```
* Extra labels have to be defined to include the cordio stack and this library: * Extra labels have to be defined to include the cordio stack and this library:
```json ```json
"target.extra_labels_add": ["CORDIO", "CORDIO_BLUENRG"] "target.extra_labels_add": ["CORDIO"]
``` ```
As an example, the target overide section for the `NUCLEO_F401RE` would be: As an example, the target overide section for the `NUCLEO_F401RE` would be:
@ -47,6 +119,7 @@ As an example, the target overide section for the `NUCLEO_F401RE` would be:
```json ```json
"NUCLEO_F401RE": { "NUCLEO_F401RE": {
"target.features_add": ["BLE"], "target.features_add": ["BLE"],
"target.extra_labels_add": ["CORDIO", "CORDIO_BLUENRG"] "target.components_add": ["BlueNRG_MS"],
"target.extra_labels_add": ["CORDIO"]
} }
``` ```

View File

@ -1,65 +0,0 @@
/**
******************************************************************************
* @file bluenrg_targets.h
* @author AST / EST
* @version V0.0.1
* @date 24-July-2015
* @brief This header file is intended to manage the differences between
* the different supported base-boards which might mount the
* X_NUCLEO_IDB0XA1 BlueNRG BLE Expansion Board.
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Define to prevent from recursive inclusion --------------------------------*/
#ifndef _BLUENRG_TARGETS_H_
#define _BLUENRG_TARGETS_H_
#if !defined(BLUENRG_PIN_SPI_MOSI)
#define BLUENRG_PIN_SPI_MOSI (D11)
#endif
#if !defined(BLUENRG_PIN_SPI_MISO)
#define BLUENRG_PIN_SPI_MISO (D12)
#endif
#if !defined(BLUENRG_PIN_SPI_nCS)
#define BLUENRG_PIN_SPI_nCS (A1)
#endif
#if !defined(BLUENRG_PIN_SPI_RESET)
#define BLUENRG_PIN_SPI_RESET (D7)
#endif
#if !defined(BLUENRG_PIN_SPI_IRQ)
#define BLUENRG_PIN_SPI_IRQ (A0)
#endif
/* NOTE: Refer to README for further details regarding BLUENRG_PIN_SPI_SCK */
#if !defined(BLUENRG_PIN_SPI_SCK)
#define BLUENRG_PIN_SPI_SCK (D3)
#endif
#endif // _BLUENRG_TARGTES_H_

View File

@ -1,6 +1,12 @@
{ {
"name": "cordio_bluenrg", "name": "bluenrg_ms",
"config": { "config": {
"SPI_MOSI": "D11",
"SPI_MISO": "D12",
"SPI_nCS": "A1",
"SPI_RESET": "D7",
"SPI_IRQ": "A0",
"SPI_SCK": "D3",
"valid-public-bd-address": { "valid-public-bd-address": {
"help": "Read the BD public address at startup", "help": "Read the BD public address at startup",
"value": false "value": false
@ -8,17 +14,23 @@
}, },
"target_overrides": { "target_overrides": {
"K64F": { "K64F": {
"target.macros_add": ["BLUENRG_PIN_SPI_SCK=D13"] "SPI_SCK": "D13"
}, },
"DISCO_L475VG_IOT01A": { "DISCO_L475VG_IOT01A": {
"target.macros_add": [ "SPI_MOSI": "PC_12",
"BLUENRG_PIN_SPI_MOSI=PC_12", "SPI_MISO": "PC_11",
"BLUENRG_PIN_SPI_MISO=PC_11", "SPI_nCS": "PD_13",
"BLUENRG_PIN_SPI_nCS=PD_13", "SPI_RESET": "PA_8",
"BLUENRG_PIN_SPI_RESET=PA_8", "SPI_IRQ": "PE_6",
"BLUENRG_PIN_SPI_IRQ=PE_6", "SPI_SCK": "PC_10"
"BLUENRG_PIN_SPI_SCK=PC_10" },
] "DISCO_L562QE": {
"SPI_MOSI": "PG_4",
"SPI_MISO": "PG_3",
"SPI_nCS": "PG_5",
"SPI_RESET": "PG_8",
"SPI_IRQ": "PG_6",
"SPI_SCK": "PG_2"
} }
} }
} }