mirror of https://github.com/ARMmbed/mbed-os.git
grammatical and stylistic fixes, more passive -> active
parent
f2c6d59c23
commit
739bd6605d
|
@ -1,44 +1,44 @@
|
||||||
# HCI abstraction architecture
|
# HCI abstraction architecture
|
||||||
|
|
||||||
The HCI driver is split into two interfaces:
|
The HCI driver is split into two interfaces:
|
||||||
* `CordioHCIDriver`: It is the driver for a BLE controller. It contains
|
* `CordioHCIDriver`: It is the driver for a BLE controller. It contains
|
||||||
the primitive necessary to start and initialize the controller.
|
the primitive necessary to start and initialize the controller.
|
||||||
* `CordioHCITransport`: It is the transport interface which is used by the HCI
|
* `CordioHCITransport`: It is the transport interface which is used by the HCI
|
||||||
driver to communicate with the controller.
|
driver to communicate with the controller.
|
||||||
|
|
||||||
A `CordioHCITransport` is injected into a `CordioHCIDriver` at construction
|
A `CordioHCITransport` is injected into a `CordioHCIDriver` at construction
|
||||||
time. A `CordioHCIDriver` is also injected at construction time of a `BLECordio`
|
time. A `CordioHCIDriver` is also injected at construction time of a `BLECordio`
|
||||||
instance.
|
instance.
|
||||||
|
|
||||||
This can be summarized in the following diagram:
|
This can be summarized in the following diagram:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## CordioHCITransportDriver
|
## CordioHCITransportDriver
|
||||||
|
|
||||||
The single responsabilities of this a driver is to handle the communication with
|
The single responsibility of this driver is to handle the communication with
|
||||||
the Bluetooth module. Basically, sending and reading bytes.
|
the Bluetooth module. Basically, sending and reading bytes.
|
||||||
|
|
||||||
Given that the Bluetooth specification define standard transport interface, an
|
Given that the Bluetooth specification defines standard transport interface, an
|
||||||
implementation of the H4 interface is bundled in this port. It might be extended
|
implementation of the H4 interface is bundled in this port. It might be extended
|
||||||
in the future with an implementation of the H5 interface. However there is no
|
in the future with an implementation of the H5 interface. However, there is no
|
||||||
plan to provide the SDIO implementation at the moment.
|
plan to provide the SDIO implementation at the moment.
|
||||||
|
|
||||||
This interface is defined in the header file
|
This interface is defined in the header file
|
||||||
[CordioHCITransportDriver.h](../driver/CordioHCITransportDriver.h)
|
[CordioHCITransportDriver.h](../driver/CordioHCITransportDriver.h)
|
||||||
|
|
||||||
## CordioHCIDriver
|
## CordioHCIDriver
|
||||||
|
|
||||||
The responsibilities of this driver are:
|
The responsibilities of this driver are:
|
||||||
* Provide the memory which will used by the Bluetooth stack.
|
* Provide the memory which will used by the Bluetooth stack.
|
||||||
* Initialize the bluetooth controller.
|
* Initialize the Bluetooth controller.
|
||||||
* Handle the reset/startup sequence of the bluetooth controller.
|
* Handle the reset/startup sequence of the Bluetooth controller.
|
||||||
|
|
||||||
This interface is defined in the header file
|
This interface is defined in the header file
|
||||||
[CordioHCIDriver.h](../driver/CordioHCIDriver.h)
|
[CordioHCIDriver.h](../driver/CordioHCIDriver.h)
|
||||||
|
|
||||||
A partial implementation is present in the file
|
A partial implementation is present in the file
|
||||||
[CordioHCIDriver.cpp](../driver/CordioHCIDriver.cpp). It defines the function
|
[CordioHCIDriver.cpp](../driver/CordioHCIDriver.cpp). It defines the function
|
||||||
delivering memory to the stack and a complete reset sequence. However it does
|
delivering memory to the stack and a complete reset sequence. However, it does
|
||||||
not define any initialization for the Bluetooth controller, this part being
|
not define any initialization for the Bluetooth controller, this part being
|
||||||
specific to the controller used.
|
specific to the controller used.
|
||||||
|
|
|
@ -8,11 +8,11 @@ There are two main steps to enable the Mbed BLE Cordio port:
|
||||||
|
|
||||||
## Configure the target
|
## Configure the target
|
||||||
|
|
||||||
Define all Mbed OS targets in the `targets/target.json` file:
|
1. Define all Mbed OS targets in the `targets/target.json` file:
|
||||||
|
|
||||||
* Add BLE support to the target:
|
1. Add BLE support to the target:
|
||||||
|
|
||||||
* Add the string `BLE` to the target's list of `features`. This adds the BLE API sources to the list of sources compiled for the target.
|
* Add the string `BLE` to the target's list of `features`. This adds the BLE API sources to the list of sources compiled for the target:
|
||||||
|
|
||||||
```
|
```
|
||||||
"TARGET_NAME": {
|
"TARGET_NAME": {
|
||||||
|
@ -24,7 +24,7 @@ Define all Mbed OS targets in the `targets/target.json` file:
|
||||||
|
|
||||||
Compile the BLE Cordio port sources:
|
Compile the BLE Cordio port sources:
|
||||||
|
|
||||||
* Add the string `CORDIO` to the `extra_labels` property of the JSON file.
|
* Add the string `CORDIO` to the `extra_labels` property of the JSON file:
|
||||||
|
|
||||||
```
|
```
|
||||||
"TARGET_NAME": {
|
"TARGET_NAME": {
|
||||||
|
@ -39,7 +39,7 @@ Include an HCI driver for the BLE module used by the target, and a factory funct
|
||||||
|
|
||||||
### Create source folder
|
### Create source folder
|
||||||
|
|
||||||
1. Navigate to the folder of the BLE API that hosts target port `features/FEATURE_BLE/targets`.
|
1. Navigate to the folder of the BLE API that hosts the target port `features/FEATURE_BLE/targets`.
|
||||||
|
|
||||||
1. Create a folder containing the port code to isolate it from other code. Begin this folder's name with `TARGET_` and the rest of the name in capital letters.
|
1. Create a folder containing the port code to isolate it from other code. Begin this folder's name with `TARGET_` and the rest of the name in capital letters.
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ Include an HCI driver for the BLE module used by the target, and a factory funct
|
||||||
|
|
||||||
The HCI driver is split in two entities: one which handle HCI communication with the Bluetooth module and the other handling the initialization, reset sequence and memory dedicated for the Bluetooth controller.
|
The HCI driver is split in two entities: one which handle HCI communication with the Bluetooth module and the other handling the initialization, reset sequence and memory dedicated for the Bluetooth controller.
|
||||||
|
|
||||||
More information about the architecture can be found in the [HCI abstraction architecture](HCIAbstraction.md) document.
|
More information about the architecture can be found in [HCI abstraction architecture](HCIAbstraction.md).
|
||||||
|
|
||||||
#### HCITransport
|
#### HCITransport
|
||||||
|
|
||||||
|
@ -89,7 +89,9 @@ It inherits publicly from the base class `CordioHCITransportDriver`.
|
||||||
|
|
||||||
* **Sending data**: The function `write` sends data in input to the Bluetooth controller and return the number of bytes in the `data` buffer sent. Depending on the type of transport you implement, you may need to send the packet `type` to the controller before the packet data.
|
* **Sending data**: The function `write` sends data in input to the Bluetooth controller and return the number of bytes in the `data` buffer sent. Depending on the type of transport you implement, you may need to send the packet `type` to the controller before the packet data.
|
||||||
|
|
||||||
* **Receiving data**: Inject HCI data from the Bluetooth controller to the system by invoking the function `on_data_received`. This function is a static one and is provided by the base class:
|
* **Receiving data**: Inject HCI data from the Bluetooth controller to the system by invoking the function `on_data_received`. This function is a static one and is provided by the base class.
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
|
||||||
```
|
```
|
||||||
void on_data_received(uint8_t* data_received, uint16_t length_of_data_received);
|
void on_data_received(uint8_t* data_received, uint16_t length_of_data_received);
|
||||||
|
@ -137,11 +139,11 @@ private:
|
||||||
|
|
||||||
The functions `do_initialize` and `do_terminate` handle initialization and termination processes. These functions manage the state of the Bluetooth controller.
|
The functions `do_initialize` and `do_terminate` handle initialization and termination processes. These functions manage the state of the Bluetooth controller.
|
||||||
|
|
||||||
<span class="notes">**Note:** It is unnecessary to initialize or terminate the HCI transport in those function because it is handled by the base class. The HCI transport is initialized right before the call to `do_initialize` and is terminated right after the call to `do_terminate`.</span>
|
<span class="notes">**Note:** It is unnecessary to initialize or terminate the HCI transport in these functions, because that is handled by the base class. The HCI transport is initialized right before the call to `do_initialize` and is terminated right after the call to `do_terminate`.</span>
|
||||||
|
|
||||||
##### Memory pool
|
##### Memory pool
|
||||||
|
|
||||||
The function `get_buffer_pool_description` in the base class returns a buffer of 1040 bytes divided in different memory pools:
|
The function `get_buffer_pool_description` in the base class returns a buffer of 1040 bytes divided into different memory pools:
|
||||||
|
|
||||||
| Chunk size (bytes) | Number of chunks |
|
| Chunk size (bytes) | Number of chunks |
|
||||||
|--------------------|------------------|
|
|--------------------|------------------|
|
||||||
|
@ -153,6 +155,8 @@ The function `get_buffer_pool_description` in the base class returns a buffer of
|
||||||
|
|
||||||
Porting overrides this function if the memory provided by the base class doesn't match what is required by the Bluetooth controller driver.
|
Porting overrides this function if the memory provided by the base class doesn't match what is required by the Bluetooth controller driver.
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
|
||||||
```
|
```
|
||||||
buf_pool_desc_t CordioHCIDriver::get_buffer_pool_description() {
|
buf_pool_desc_t CordioHCIDriver::get_buffer_pool_description() {
|
||||||
static uint8_t buffer[/* buffer size */];
|
static uint8_t buffer[/* buffer size */];
|
||||||
|
@ -194,17 +198,17 @@ The following parameters should be set in the controller (if supported):
|
||||||
|
|
||||||
###### Stack runtime parameters
|
###### Stack runtime parameters
|
||||||
|
|
||||||
At runtime, you can get some stack parameters from the controller:
|
At runtime, you can get stack parameters from the controller:
|
||||||
|
|
||||||
* Bluetooth address: Query this with `HciReadBdAddrCmd`. Copy the response into `hciCoreCb.bdAddr` with `BdaCpy`.
|
* Bluetooth address: Query this with `HciReadBdAddrCmd`. Copy the response into `hciCoreCb.bdAddr` with `BdaCpy`.
|
||||||
|
* Buffer size of the controller: Query this with `HciLeReadBufSizeCmd`. The return parameter `HC_ACL_Data_Packet_Length` is copied to `hciCoreCb.bufSize`. Copy the response parameter `HC_Synchronous_Data_Packet_Length` into `hciCoreCb.numBufs`. The value of `hciCoreCb.availBufs` shall be initialized with `hciCoreCb.numBufs`.
|
||||||
* Buffer size of the controller: Can be obtained by `HciLeReadBufSizeCmd`. The return parameter `HC_ACL_Data_Packet_Length` is copied to `hciCoreCb.bufSize`, and the response parameter `HC_Synchronous_Data_Packet_Length` shall be copied into `hciCoreCb.numBufs`. The value of `hciCoreCb.availBufs` shall be initialized with `hciCoreCb.numBufs`.
|
|
||||||
|
|
||||||
* Supported state: Query this with `HciLeReadSupStatesCmd`, and copy the response into `hciCoreCb.leStates`.
|
* Supported state: Query this with `HciLeReadSupStatesCmd`, and copy the response into `hciCoreCb.leStates`.
|
||||||
* Whitelist size: Query this with `HciLeReadWhiteListSizeCmd`, and copy the response into `hciCoreCb.whiteListSize`.
|
* Whitelist size: Query this with `HciLeReadWhiteListSizeCmd`, and copy the response into `hciCoreCb.whiteListSize`.
|
||||||
* LE features supported: Query this with `HciLeReadLocalSupFeatCmd`, and copy the response into `hciCoreCb.leSupFeat`.
|
* LE features supported: Query this with `HciLeReadLocalSupFeatCmd`, and copy the response into `hciCoreCb.leSupFeat`.
|
||||||
* Resolving list size: Query this with `hciCoreReadResolvingListSize`, and copy the response into `hciCoreCb.resListSize`.
|
* Resolving list size: Query this with `hciCoreReadResolvingListSize`, and copy the response into `hciCoreCb.resListSize`.
|
||||||
* Max data length: Query this with `hciCoreReadMaxDataLen`, and pass the response parameters `supportedMaxTxOctets` and `supportedMaxTxTime` to the function `HciLeWriteDefDataLen`:
|
* Max data length: Query this with `hciCoreReadMaxDataLen`, and pass the response parameters `supportedMaxTxOctets` and `supportedMaxTxTime` to the function `HciLeWriteDefDataLen`.
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
|
||||||
```
|
```
|
||||||
void HCIDriver::handle_reset_sequence(uint8_t *pMsg) {
|
void HCIDriver::handle_reset_sequence(uint8_t *pMsg) {
|
||||||
|
@ -228,90 +232,90 @@ void HCIDriver::handle_reset_sequence(uint8_t *pMsg) {
|
||||||
case HCI_OPCODE_RESET:
|
case HCI_OPCODE_RESET:
|
||||||
/* initialize rand command count */
|
/* initialize rand command count */
|
||||||
randCnt = 0;
|
randCnt = 0;
|
||||||
// set the event mask to control which events are generated by the
|
// Set the event mask to control which events are generated by the
|
||||||
// controller for the host
|
// controller for the host.
|
||||||
HciSetEventMaskCmd((uint8_t *) hciEventMask);
|
HciSetEventMaskCmd((uint8_t *) hciEventMask);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HCI_OPCODE_SET_EVENT_MASK:
|
case HCI_OPCODE_SET_EVENT_MASK:
|
||||||
// set the event mask to control which LE events are generated by
|
// Set the event mask to control which LE events are generated by
|
||||||
// the controller for the host
|
// the controller for the host.
|
||||||
HciLeSetEventMaskCmd((uint8_t *) hciLeEventMask);
|
HciLeSetEventMaskCmd((uint8_t *) hciLeEventMask);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HCI_OPCODE_LE_SET_EVENT_MASK:
|
case HCI_OPCODE_LE_SET_EVENT_MASK:
|
||||||
// set the event mask to control which events are generated by the
|
// Set the event mask to control which events are generated by the
|
||||||
// controller for the host (2nd page of flags )
|
// controller for the host (2nd page of flags).
|
||||||
HciSetEventMaskPage2Cmd((uint8_t *) hciEventMaskPage2);
|
HciSetEventMaskPage2Cmd((uint8_t *) hciEventMaskPage2);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HCI_OPCODE_SET_EVENT_MASK_PAGE2:
|
case HCI_OPCODE_SET_EVENT_MASK_PAGE2:
|
||||||
// Ask the Bluetooth address of the controller
|
// Ask the Bluetooth address of the controller.
|
||||||
HciReadBdAddrCmd();
|
HciReadBdAddrCmd();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HCI_OPCODE_READ_BD_ADDR:
|
case HCI_OPCODE_READ_BD_ADDR:
|
||||||
// Store the Bluetooth address in the stack runtime parameter
|
// Store the Bluetooth address in the stack runtime parameter.
|
||||||
BdaCpy(hciCoreCb.bdAddr, pMsg);
|
BdaCpy(hciCoreCb.bdAddr, pMsg);
|
||||||
|
|
||||||
// Read the size of the buffer of the controller
|
// Read the size of the buffer of the controller.
|
||||||
HciLeReadBufSizeCmd();
|
HciLeReadBufSizeCmd();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HCI_OPCODE_LE_READ_BUF_SIZE:
|
case HCI_OPCODE_LE_READ_BUF_SIZE:
|
||||||
// Store the buffer parameters in the stack runtime parameters
|
// Store the buffer parameters in the stack runtime 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;
|
||||||
|
|
||||||
// read the states and state combinations supported by the link
|
// Read the states and state combinations supported by the link
|
||||||
// layer of the controller
|
// layer of the controller.
|
||||||
HciLeReadSupStatesCmd();
|
HciLeReadSupStatesCmd();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HCI_OPCODE_LE_READ_SUP_STATES:
|
case HCI_OPCODE_LE_READ_SUP_STATES:
|
||||||
// store supported state and combination in the runtime parameters
|
// Store supported state and combination in the runtime parameters
|
||||||
// of the stack
|
// of the stack.
|
||||||
memcpy(hciCoreCb.leStates, pMsg, HCI_LE_STATES_LEN);
|
memcpy(hciCoreCb.leStates, pMsg, HCI_LE_STATES_LEN);
|
||||||
|
|
||||||
// read the total of whitelist entries that can be stored in the
|
// Read the total of whitelist entries that can be stored in the
|
||||||
// controller.
|
// controller.
|
||||||
HciLeReadWhiteListSizeCmd();
|
HciLeReadWhiteListSizeCmd();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HCI_OPCODE_LE_READ_WHITE_LIST_SIZE:
|
case HCI_OPCODE_LE_READ_WHITE_LIST_SIZE:
|
||||||
// store the number of whitelist entries in the stack runtime
|
// Store the number of whitelist entries in the stack runtime
|
||||||
// parameters
|
// parameters.
|
||||||
BSTREAM_TO_UINT8(hciCoreCb.whiteListSize, pMsg);
|
BSTREAM_TO_UINT8(hciCoreCb.whiteListSize, pMsg);
|
||||||
|
|
||||||
// Read the LE features supported by the controller
|
// Read the LE features supported by the controller.
|
||||||
HciLeReadLocalSupFeatCmd();
|
HciLeReadLocalSupFeatCmd();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HCI_OPCODE_LE_READ_LOCAL_SUP_FEAT:
|
case HCI_OPCODE_LE_READ_LOCAL_SUP_FEAT:
|
||||||
// Store the set of LE features supported by the controller
|
// Store the set of LE features supported by the controller.
|
||||||
BSTREAM_TO_UINT16(hciCoreCb.leSupFeat, pMsg);
|
BSTREAM_TO_UINT16(hciCoreCb.leSupFeat, pMsg);
|
||||||
|
|
||||||
// read the total number of address translation entries which can be
|
// Read the total number of address translation entries which can be
|
||||||
// stored in the controller resolving list.
|
// stored in the controller resolving list.
|
||||||
hciCoreReadResolvingListSize();
|
hciCoreReadResolvingListSize();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HCI_OPCODE_LE_READ_RES_LIST_SIZE:
|
case HCI_OPCODE_LE_READ_RES_LIST_SIZE:
|
||||||
// store the number of address translation entries in the stack
|
// Store the number of address translation entries in the stack
|
||||||
// runtime parameter
|
// runtime parameter.
|
||||||
BSTREAM_TO_UINT8(hciCoreCb.resListSize, pMsg);
|
BSTREAM_TO_UINT8(hciCoreCb.resListSize, pMsg);
|
||||||
|
|
||||||
// read the Controller’s maximum supported payload octets and packet
|
// Read the Controller’s maximum supported payload octets and packet
|
||||||
// duration times for transmission and reception
|
// duration times for transmission and reception.
|
||||||
hciCoreReadMaxDataLen();
|
hciCoreReadMaxDataLen();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HCI_OPCODE_LE_READ_MAX_DATA_LEN:
|
case HCI_OPCODE_LE_READ_MAX_DATA_LEN:
|
||||||
{
|
{
|
||||||
// store payload definition in the runtime stack parameters.
|
// Store payload definition in the runtime stack parameters.
|
||||||
uint16_t maxTxOctets;
|
uint16_t maxTxOctets;
|
||||||
uint16_t maxTxTime;
|
uint16_t maxTxTime;
|
||||||
|
|
||||||
|
@ -413,7 +417,7 @@ static void hciCoreReadResolvingListSize(void)
|
||||||
|
|
||||||
The HCI driver is injected to the `CordioBLE` class at manufacture.
|
The HCI driver is injected to the `CordioBLE` class at manufacture.
|
||||||
|
|
||||||
Given that the CordioBLE class doesn't know what class constructs the driver nor how to construct it, the port provides a function returning a reference to the HCI driver.
|
Given that the `CordioBLE` class doesn't know which class constructs the driver nor how to construct it, the port provides a function returning a reference to the HCI driver.
|
||||||
|
|
||||||
This function is in the global namespace, and you can call it with:
|
This function is in the global namespace, and you can call it with:
|
||||||
|
|
||||||
|
@ -453,6 +457,6 @@ mbed test -t <toolchain> -m <target> -n mbed-os-features-feature_ble-targets-tar
|
||||||
|
|
||||||
You can use the application [mbed-os-cordio-hci-passthrough](https://github.com/ARMmbed/mbed-os-cordio-hci-passthrough) to proxify a Bluetooth controller connected to an Mbed board.
|
You can use the application [mbed-os-cordio-hci-passthrough](https://github.com/ARMmbed/mbed-os-cordio-hci-passthrough) to proxify a Bluetooth controller connected to an Mbed board.
|
||||||
|
|
||||||
Bytes sent by the host over the board serial are forwarded to the controller with the help of the `HCITransportDriver`, while bytes sent by the controller are sent back to the host through the board serial.
|
The host sent bytes over the board serial, which the `HCITransport Driver` then forwards. Bytes sent by the controller go back to the host through the board serial.
|
||||||
|
|
||||||
This application can be used to validate the transport driver and debug the initialization process on a PC host.
|
This application can be used to validate the transport driver and debug the initialization process.
|
||||||
|
|
Loading…
Reference in New Issue