RT-Thread Platform Bluenrg2 Bluetooth Chip Startup Process

RTT Zephyr Polling Package Bluenrg2 Bluetooth Chip Startup Process

“Summer of Code” “Bluetooth Host Protocol Stack Zephyr Polling Improvement” personal project record

Personal record of a beginner participating in the project

Project package address: RTT_PACKAGE_zephyr_polling

The SPI interface implementation has been completed. To run zephyr_polling on Bluenrg2, the next step is to implement its special chip startup process.

Bluetooth Chip Startup Process

Before controlling the device for Bluetooth operations using standard HCI commands, it is necessary to configure the device in advance using VS Command. Only correctly configured devices can be used normally.

The chip manufacturer only sells chips and does not focus on peripheral circuits and specific product forms, which are implemented by specific ODM manufacturers. The chip manufacturer provides chips with HCI Bluetooth functionality, while ODM designs the circuit and the product, and then interacts with the chip through HCI. The actual needs of each ODM manufacturer vary, so to meet the different customer needs and reduce integration efforts with customers, the chip manufacturer must provide a series of configuration parameters based on the same code to meet the needs of different ODM manufacturers.

Configurations can include: firmware burning (some Bluetooth chips without FLASH need to be reprogrammed with the latest firmware every time they are powered on), Bluetooth address configuration, hardware interface configuration (such as RF interface, crystal type, etc., needed by some Bluetooth chips), baud rate configuration (HCI is generally UART interface, default is 115200), and other parameter configurations required by the manufacturer.

Additionally, for some chips with Flash, configuration parameters can be pre-burned into the Flash, so that no parameters need to be configured during use, and operations can be performed directly through the HCI interface.

The zephyr_polling protocol stack provides Boot and Prepare process interfaces, which can implement startup configurations based on the actual chip requirements.

RT-Thread Platform Bluenrg2 Bluetooth Chip Startup Process

Boot Process:

Complete the manufacturer’s initialization process, such as firmware download, Bluetooth address configuration, etc. Once the chipset registers the interface, the protocol stack will callboot_start()to initiate the Boot process of the chipset (referring to the startup process code under the protocol stack chipset directory, same below). Since the operation interface is HCI, a VS Command is generally issued, and subsequent actions are taken based on the VS Event. The protocol stack will report the received event to the chipset throughevent_process()callback interface, and when the chipset considers the operation complete, it will notify the protocol stack that the boot process has ended by callingbt_hci_set_boot_ready()interface.

Prepare Process:

Some manufacturers require parameter settings to be done after the HCI_Reset Command (which means their HCI_Reset Command clears configured parameters). To accommodate this type of parameter structure, the Prepare process has been added after the HCI_Reset Command. The protocol stack will call prepare_start() to initiate the chipset’s Prepare process after receiving the HCI_Reset Command Complete Event, and like the Boot process, the protocol stack will report the received event to the chipset through event_process() callback interface. When the chipset considers the operation complete, it will notify the protocol stack that the prepare process has ended by calling bt_hci_set_prepare_ready() interface.

BlueNRG-2 Startup Process

Consulting the official manuals and example materials provided by ST, one can understand the startup configuration requirements for BlueNRG-2.

For BlueNRG-2:

Boot process: no transactions.

Prepare process: disable Host functionality; Bluetooth address configuration; set TX power; GATT configuration; GAP configuration.

BlueNRG-2 Startup Process Implementation

Boot Process

The HCI_Reset Command of BlueNRG-2 will clear the configured parameters, so the actual configuration is placed in the protocol stack’s Prepare process. The Boot process callback function directly calls bt_hci_set_boot_ready() to end the process.

1void boot_start(void) {
2    state = STATE_POLLING_BOOTING;
3    // nothing to do
4    bt_hci_set_boot_ready();          //finish boot
5}

Prepare Process – Disable Host Functionality

The Bluetooth module X-NUCLEO-BNRG2A1 used for development has BLE integrated as a SOC, which includes the host protocol stack. The manufacturer ST provides a set of ACI commands to control the chip’s behavior, including the host’s interface. This means that by default, the ACL interactions of this chip are taken over, so it needs to disable host behavior via ACI commands. This requires setting aci_hal_write_config_data with CONFIG_DATA_LL_WITHOUT_HOST to disable the host.

Prepare Process Step 1: Disable Host:

1void prepare_start(void) {
2    state = STATE_POLLING_PREPARING;
3    step = 1;
4    // step 1 close host
5    bluenrg2_config_without_host(); // It can be written only if aci_hal_write_config_data() is the first command after reset.
6}

The command to disable the host has an ogf of 0x3f, ocf of 0x00c, and parameter 2c11. Here, 0x2C is the offset in CONFIG_DATA for disabling the Host.

 1#define CONFIG_DATA_LL_WITHOUT_HOST         (0x2C) /**< Switch on/off Link Layer only mode. Set to 1 to disable Host. */
 2#define CONFIG_DATA_LL_WITHOUT_HOST_LEN     (1)
 3static int bluenrg2_config_without_host()
 4{
 5    uint8_t cmd_buffer[CONFIG_DATA_LL_WITHOUT_HOST_LEN + 2];
 6    struct net_buf *buf;
 7    cmd_buffer[0] = CONFIG_DATA_LL_WITHOUT_HOST;                //offset
 8    cmd_buffer[1] = CONFIG_DATA_LL_WITHOUT_HOST_LEN;            //config len
 9    cmd_buffer[2] = 1;                                          //Set to 1 to disable Host
10    uint16_t ogf = 0x3f, ocf = 0x00c;
11    uint16_t opcode = (uint16_t)((ocf & 0x03ff)|(ogf << 10));
12    buf = bt_hci_cmd_create(opcode, sizeof(cmd_buffer));
13    if (!buf)
14    {
15        return -ENOBUFS;
16    }
17    net_buf_add_mem(buf, cmd_buffer, sizeof(cmd_buffer));
18    return bt_hci_cmd_send(opcode, buf);
19}

Prepare Process – Bluetooth Address Configuration

The Bluetooth address needs to be configured through aci_hal_write_config_data with CONFIG_DATA_PUBADDR_OFFSET.

The command for configuring the Bluetooth address has an ogf of 0x3f, ocf of 0x00c. The offset in CONFIG_DATA for the Bluetooth address configuration command is 0x00, followed by the address length and the set Bluetooth address.

 1#define BLE_MAC_ADDR                                                                               \
 2    {                                                                                              \
 3        {                                                                                          \
 4            0xf5, 0x00, 0x00, 0xe1, 0x80, 0x02                                                   \
 5        }                                                                                          \
 6    }
 7#define CONFIG_DATA_PUBADDR_OFFSET          (0x00) /**< Bluetooth public address */
 8#define CONFIG_DATA_PUBADDR_LEN             (6)
 9static int bluenrg2_config_set_public_addr()
10{
11    uint8_t cmd_buffer[CONFIG_DATA_PUBADDR_LEN + 2];
12    struct net_buf *buf;
13    bt_addr_t addr = BLE_MAC_ADDR;
14    cmd_buffer[0] = CONFIG_DATA_PUBADDR_OFFSET;                 //offset
15    cmd_buffer[1] = CONFIG_DATA_PUBADDR_LEN;                    //config len
16    memcpy(cmd_buffer + 2, addr.val, CONFIG_DATA_PUBADDR_LEN);   // addr
17    uint16_t ogf = 0x3f, ocf = 0x00c;
18    uint16_t opcode = (uint16_t)((ocf & 0x03ff)|(ogf << 10));
19    buf = bt_hci_cmd_create(opcode, sizeof(cmd_buffer));
20    if (!buf)
21    {
22        return -ENOBUFS;
23    }
24    net_buf_add_mem(buf, cmd_buffer, sizeof(cmd_buffer));
25    return bt_hci_cmd_send(opcode, buf);
26}

Prepare Process – Set Transmit Power

The command to configure transmit power has an ogf of 0x3f, ocf of 0x00f. The command parameters determine whether to enable high power mode (0x00 for normal power, 0x01 for high power) and the power amplifier output level (the allowed PA level depends on the device).

PA_Level values correspond to power

0: -14 dBm (High Power)

1: -11 dBm (High Power)

2: -8 dBm (High Power)

3: -5 dBm (High Power)

4: -2 dBm (High Power)

5: 2 dBm (High Power)

6: 4 dBm (High Power)

7: 8 dBm (High Power)

 1static int bluenrg2_set_tx_power_level(uint8_t En_High_Power, uint8_t PA_Level)
 2{
 3    uint8_t cmd_buffer[2];
 4    struct net_buf *buf;
 5    cmd_buffer[0] = En_High_Power;      //En_High_Power
 6    cmd_buffer[1] = PA_Level;           //config PA_Level
 7    uint16_t ogf = 0x3f, ocf = 0x00f;
 8    uint16_t opcode = (uint16_t)((ocf & 0x03ff)|(ogf << 10));
 9    buf = bt_hci_cmd_create(opcode, sizeof(cmd_buffer));
10    if (!buf)
11    {
12        return -ENOBUFS;
13    }
14    net_buf_add_mem(buf, cmd_buffer, sizeof(cmd_buffer));
15    return bt_hci_cmd_send(opcode, buf);
16}
Prepare Process – GATT Configuration

The command to initialize GATT has an ogf of 0x3f, ocf of 0x101, with no other parameters.

1static int  bluenrg2_gatt_init(void)
2{
3    uint16_t ogf = 0x3f, ocf = 0x101;
4    uint16_t opcode = (uint16_t)((ocf & 0x03ff)|(ogf << 10));
5    return bt_hci_cmd_send(opcode, NULL);
6}

Prepare Process – GAP Configuration

Initialize the GAP layer. Register GAP services, and set standard GAP service characteristics: device name, appearance, preferred connection parameters for peripheral devices (only for peripheral devices).

The command for GAP configuration has an ogf of 0x3f, ocf of 0x08a. It is configured for peripheral devices; if it needs to be used for other roles, this needs to be modified; privacy policy is not enabled (to protect the address from being stolen, address encryption/decryption is performed and periodically updated); set the device name length.

privacy:

0x00: Privacy disabled

0x01: Privacy host enabled

0x02: Privacy controller enabled

 1#define GAP_PERIPHERAL_ROLE                     (0x01)
 2#define GAP_BROADCASTER_ROLE                    (0x02)
 3#define GAP_CENTRAL_ROLE                        (0x04)
 4#define GAP_OBSERVER_ROLE                       (0x08)
 5#define privacy_enabled                         (0x00)
 6#define device_name_char_len                    (0x08)
 7static int bluenrg2_gap_init()
 8{
 9    uint8_t cmd_buffer[3];
10    struct net_buf *buf;
11    cmd_buffer[0] = GAP_PERIPHERAL_ROLE;    //role
12    cmd_buffer[1] = privacy_enabled;        //privacy
13    cmd_buffer[2] = device_name_char_len;   //device_name_char_len
14    uint16_t ogf = 0x3f, ocf = 0x08a;
15    uint16_t opcode = (uint16_t)((ocf & 0x03ff)|(ogf << 10));
16    buf = bt_hci_cmd_create(opcode, sizeof(cmd_buffer));
17    if (!buf)
18    {
19        return -ENOBUFS;
20    }
21    net_buf_add_mem(buf, cmd_buffer, sizeof(cmd_buffer));
22    return bt_hci_cmd_send(opcode, buf);
23}

Startup Event Handling

For the return response of the startup process, it needs to be judged and advanced by the event_process() callback. Here, for convenience, only the CMD_COMPLETE event is handled to advance the Prepare process.

Once the GAP settings are complete, bt_hci_set_prepare_ready() is called to end the process.

 1void event_process(uint8_t event, struct net_buf *buf)
 2{
 3    if(state == STATE_POLLING_PREPARING) // boot do nothing
 4    {
 5        if (event == BT_HCI_EVT_CMD_COMPLETE)  //only complete
 6        {
 7            printk("prepare_event_process, step: %d\n", step);
 8            switch (step)
 9            {
10            case 1: //close host just now
11                bluenrg2_config_set_public_addr();  //step2  set_public_addr
12                step = 2;
13                break;
14            case 2:
15                bluenrg2_set_tx_power_level(1, 4);  //step3  set_public_addr
16                step = 3;
17                break;
18            case 3:
19                bluenrg2_gatt_init();               //step4  gatt_ini
20                step = 4;
21                break;
22            case 4:
23                bluenrg2_gap_init();                //step5  gap_ini
24                step = 5;
25                break;
26            case 5:
27                bt_hci_set_prepare_ready();          //finish prepare
28                step = 0;
29                break;
30            }
31        }
32    }
33}

Startup Process Registration

Package the function pointers of the startup process implemented above into the bt_hci_chipset_driver structure for the protocol stack to call and register.

1static const struct bt_hci_chipset_driver chipset_drv = {
2        init_work, boot_start, prepare_start, event_process,
3};
4// public drv API
5const struct bt_hci_chipset_driver *bt_hci_chipset_impl_local_instance(void)
6{
7    return &chipset_drv;
8}

Verification

Although the HCI interface was successfully run with the Beacon example, the Beacon example does not require the chipset startup configuration process (the empty callback common is enabled at runtime). The startup process of the Bluenrg2 Bluetooth chip is verified by running the peripheral heart rate example.

 1 \ | /
 2- RT -     Thread Operating System
 3 / | \     5.0.1 build Sep 20 2023 22:16:27
 4 2006 - 2022 Copyright by RT-Thread team
 5do components initialization.
 6initialize rti_board_end:0 done
 7initialize stm32l4_hw_lptim_init:0 done
 8initialize finsh_system_init:0 done
 9msh >zephyr
10zephyr_polling_init 
11bt_init_hci_driver 
12SPI_init_process device_name: spi10, spi_name: spi1, rate: 1000000, databits: 8, LSB_MSB: 1, Master_Slave: 0, CPOL: 0, CPHA: 1
13SPI_init_process cs_pin_num: 1, irq_pin_num: 0
14hci_driver_open, SPI_config_finish
15I: (bt_hci_core)hci_init():3230: work start.
16msh >prepare_event_process, step: 1
17prepare_event_process, step: 2
18prepare_event_process, step: 3
19prepare_event_process, step: 4
20prepare_event_process, step: 5
21I: (bt_hci_core)hci_init_end():3205: work end.
22E: (bt_smp)smp_self_test():5695: smp_self_test start
23I: (bt_hci_core)bt_dev_show_info():3008: Identity: 02:80:e1:00:00:f5 (public)
24I: (bt_hci_core)bt_dev_show_info():3042: HCI: version 5.2 (0x0b) revision 0x1222, manufacturer 0x0030
25I: (bt_hci_core)bt_dev_show_info():3044: LMP: version 5.2 (0x0b) subver 0x0015
26Bluetooth initialized
27Advertising successfully started
28Connected
29BAS Notifications enabled
30HRS notifications enabled
prepare_event_process step log output is normal, device connection, battery service, heart rate service are normal.
———————End———————



👇 Click to read the original text on the official website

Leave a Comment