Skip to content

CYW43XXX Cordio HCI driver: update BT power up sequences to remove redundant delay (500ms) during HCIDrive initialization #14988

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Aug 17, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,17 @@
#include "rtos/ThisThread.h"
#include <chrono>

// BT settling time after power on
#if !defined (CY_BT_POWER_ON_SETTLING_TIME)
#define CY_BT_POWER_ON_SETTLING_TIME (500ms)
#endif /* !defined (CY_BT_POWER_ON_SETTLING_TIME) */

// Power on reset time
#if !defined (CY_BT_POWER_ON_RESET_TIME)
#define CY_BT_POWER_ON_RESET_TIME (1ms)
#endif /* !defined (CY_BT_POWER_ON_RESET_TIME) */


namespace ble {
namespace vendor {
namespace cypress_ble {
Expand All @@ -44,7 +55,7 @@ CyH4TransportDriver::CyH4TransportDriver(PinName tx, PinName rx, PinName cts, Pi
cts(cts), rts(rts),
bt_host_wake_name(bt_host_wake_name),
bt_device_wake_name(bt_device_wake_name),
bt_power(bt_power_name, PIN_OUTPUT, PullNone, 0),
bt_power(bt_power_name, PIN_OUTPUT, PullUp, 0),
bt_host_wake(bt_host_wake_name, PIN_INPUT, PullNone, 0),
bt_device_wake(bt_device_wake_name, PIN_OUTPUT, PullNone, 1),
host_wake_irq_event(host_wake_irq),
Expand Down Expand Up @@ -153,8 +164,9 @@ void CyH4TransportDriver::initialize()
bt_host_wake_active = true;
sleep_manager_lock_deep_sleep();

// Keep the bt_power line in the low level to ensure that the device resets.
bt_power = 0;
rtos::ThisThread::sleep_for(1ms);
rtos::ThisThread::sleep_for(CY_BT_POWER_ON_RESET_TIME);

#if defined(CYW43XXX_UNBUFFERED_UART)
uart.baud(DEF_BT_BAUD_RATE);
Expand Down Expand Up @@ -186,7 +198,9 @@ void CyH4TransportDriver::initialize()
cyhal_uart_enable_event(&uart, CYHAL_UART_IRQ_RX_NOT_EMPTY, CYHAL_ISR_PRIORITY_DEFAULT, true);
#endif

// Power up BT
bt_power = 1;
rtos::ThisThread::sleep_for(CY_BT_POWER_ON_SETTLING_TIME);

#if (defined(MBED_TICKLESS) && DEVICE_SLEEP && DEVICE_LPTICKER)
if (bt_host_wake_name != NC) {
Expand Down Expand Up @@ -229,6 +243,7 @@ void CyH4TransportDriver::terminate()

deassert_bt_dev_wake();

// Power down BT
bt_power = 0; //BT_POWER is an output, should not be freed only set inactive

#if defined(CYW43XXX_UNBUFFERED_UART)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@ class CyH4TransportDriver : public CordioHCITransportDriver {
* Initialize the transport driver.
*
*/
CyH4TransportDriver(PinName tx, PinName rx, PinName cts, PinName rts, PinName bt_power_name, int baud, PinName bt_host_wake_name, PinName bt_device_wake_name,
uint8_t host_wake_irq = 0, uint8_t dev_wake_irq = 0);
CyH4TransportDriver(PinName tx, PinName rx, PinName cts, PinName rts, PinName bt_power_name, int baud);
CyH4TransportDriver(PinName tx, PinName rx, PinName cts, PinName rts, PinName bt_power_name, int baud, PinName bt_host_wake_name, PinName bt_device_wake_name,
uint8_t host_wake_irq = 0, uint8_t dev_wake_irq = 0);
CyH4TransportDriver(PinName tx, PinName rx, PinName cts, PinName rts, PinName bt_power_name, int baud);

/**
* Destructor
Expand Down
131 changes: 61 additions & 70 deletions connectivity/drivers/ble/FEATURE_BLE/COMPONENT_CYW43XXX/HCIDriver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,16 +75,13 @@ class HCIDriver : public CordioHCIDriver {
public:
HCIDriver(
ble::vendor::cypress_ble::CyH4TransportDriver& transport_driver,
PinName bt_power_name,
bool ps_enabled,
uint8_t host_wake_irq,
uint8_t dev_wake_irq
bool ps_enabled,
uint8_t host_wake_irq,
uint8_t dev_wake_irq
) : CordioHCIDriver(transport_driver),
bt_power_name(bt_power_name),
bt_power(bt_power_name, PIN_OUTPUT, PullUp, 0),
is_powersave_enabled(ps_enabled),
host_wake_irq(host_wake_irq),
dev_wake_irq(dev_wake_irq),
is_powersave_enabled(ps_enabled),
host_wake_irq(host_wake_irq),
dev_wake_irq(dev_wake_irq),
service_pack_index(0),
service_pack_ptr(0),
service_pack_length(0),
Expand All @@ -101,9 +98,6 @@ class HCIDriver : public CordioHCIDriver {

virtual void do_initialize()
{
rtos::ThisThread::sleep_for(500ms);
bt_power = 1;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it necessary to keep bt_power member variable ? It doesn't seems to be used anymore (except for initialization).
I also noticed that it is initialized differently in the transport (PullNone) from the HCI (PullUp) driver.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @pan,
I updated code according to your comment. Additionally cleaned some indentations (replaced tab to spaces)

Regards,
Nazar

rtos::ThisThread::sleep_for(500ms);
}

virtual void do_terminate() { }
Expand Down Expand Up @@ -419,68 +413,68 @@ class HCIDriver : public CordioHCIDriver {

void set_sleep_mode()
{
uint8_t *pBuf;
if ((pBuf = hciCmdAlloc(HCI_VS_CMD_SET_SLEEP_MODE, 12)) != NULL)
{
if (is_powersave_on()) {
pBuf[HCI_CMD_HDR_LEN] = 0x01; // sleep
} else {
pBuf[HCI_CMD_HDR_LEN] = 0x00; // no sleep
}
pBuf[HCI_CMD_HDR_LEN + 1] = 0x00; // no idle threshold host (N/A)
if (is_powersave_on()) {
pBuf[HCI_CMD_HDR_LEN + 2] = 0x05; // no idle threshold HC (N/A)
} else {
pBuf[HCI_CMD_HDR_LEN + 2] = 0x00; // no idle threshold HC (N/A)
}
if (is_powersave_on()) {
pBuf[HCI_CMD_HDR_LEN + 3] = dev_wake_irq; // BT WAKE
} else {
pBuf[HCI_CMD_HDR_LEN + 3] = 0x00; // BT WAKE
}
if (is_powersave_on()) {
pBuf[HCI_CMD_HDR_LEN + 4] = host_wake_irq; // HOST WAKE
} else {
pBuf[HCI_CMD_HDR_LEN + 4] = 0x00; // HOST WAKE
}
pBuf[HCI_CMD_HDR_LEN + 5] = 0x00; // Sleep during SCO
pBuf[HCI_CMD_HDR_LEN + 6] = 0x00; // Combining sleep mode and SCM
pBuf[HCI_CMD_HDR_LEN + 7] = 0x00; // Tristate TX
pBuf[HCI_CMD_HDR_LEN + 8] = 0x00; // Active connection handling on suspend
pBuf[HCI_CMD_HDR_LEN + 9] = 0x00; // resume timeout
pBuf[HCI_CMD_HDR_LEN + 10] = 0x00; // break to host
pBuf[HCI_CMD_HDR_LEN + 11] = 0x00; // Pulsed host wake
hciCmdSend(pBuf);
uint8_t *pBuf;
if ((pBuf = hciCmdAlloc(HCI_VS_CMD_SET_SLEEP_MODE, 12)) != NULL)
{
if (is_powersave_on()) {
pBuf[HCI_CMD_HDR_LEN] = 0x01; // sleep
} else {
pBuf[HCI_CMD_HDR_LEN] = 0x00; // no sleep
}
pBuf[HCI_CMD_HDR_LEN + 1] = 0x00; // no idle threshold host (N/A)
if (is_powersave_on()) {
pBuf[HCI_CMD_HDR_LEN + 2] = 0x05; // no idle threshold HC (N/A)
} else {
pBuf[HCI_CMD_HDR_LEN + 2] = 0x00; // no idle threshold HC (N/A)
}
if (is_powersave_on()) {
pBuf[HCI_CMD_HDR_LEN + 3] = dev_wake_irq; // BT WAKE
} else {
pBuf[HCI_CMD_HDR_LEN + 3] = 0x00; // no BT WAKE
}
if (is_powersave_on()) {
pBuf[HCI_CMD_HDR_LEN + 4] = host_wake_irq; // HOST WAKE
} else {
pBuf[HCI_CMD_HDR_LEN + 4] = 0x00; // no HOST WAKE
}
pBuf[HCI_CMD_HDR_LEN + 5] = 0x00; // Sleep during SCO
pBuf[HCI_CMD_HDR_LEN + 6] = 0x00; // Combining sleep mode and SCM
pBuf[HCI_CMD_HDR_LEN + 7] = 0x00; // Tristate TX
pBuf[HCI_CMD_HDR_LEN + 8] = 0x00; // Active connection handling on suspend
pBuf[HCI_CMD_HDR_LEN + 9] = 0x00; // resume timeout
pBuf[HCI_CMD_HDR_LEN + 10] = 0x00; // break to host
pBuf[HCI_CMD_HDR_LEN + 11] = 0x00; // Pulsed host wake
hciCmdSend(pBuf);
}
}

// 0x18, 0xFC, 0x06, 0x00, 0x00, 0xC0, 0xC6, 0x2D, 0x00, //update uart baudrate 3 mbp
void HciUpdateUartBaudRate()
{
uint8_t *pBuf;
if ((pBuf = hciCmdAlloc(HCI_VS_CMD_UPDATE_UART_BAUD_RATE, 6)) != NULL)
{
pBuf[HCI_CMD_HDR_LEN] = 0x00; // encoded_baud_rate
pBuf[HCI_CMD_HDR_LEN + 1] = 0x00; // use_encoded_form
pBuf[HCI_CMD_HDR_LEN + 2] = 0xC0; // explicit baud rate bit 0-7
pBuf[HCI_CMD_HDR_LEN + 3] = 0xC6; // explicit baud rate bit 8-15
pBuf[HCI_CMD_HDR_LEN + 4] = 0x2D; // explicit baud rate bit 16-23
pBuf[HCI_CMD_HDR_LEN + 5] = 0x00; // explicit baud rate bit 24-31
hciCmdSend(pBuf);
}
uint8_t *pBuf;
if ((pBuf = hciCmdAlloc(HCI_VS_CMD_UPDATE_UART_BAUD_RATE, 6)) != NULL)
{
pBuf[HCI_CMD_HDR_LEN] = 0x00; // encoded_baud_rate
pBuf[HCI_CMD_HDR_LEN + 1] = 0x00; // use_encoded_form
pBuf[HCI_CMD_HDR_LEN + 2] = 0xC0; // explicit baud rate bit 0-7
pBuf[HCI_CMD_HDR_LEN + 3] = 0xC6; // explicit baud rate bit 8-15
pBuf[HCI_CMD_HDR_LEN + 4] = 0x2D; // explicit baud rate bit 16-23
pBuf[HCI_CMD_HDR_LEN + 5] = 0x00; // explicit baud rate bit 24-31
hciCmdSend(pBuf);
}
}

static const uint16_t HCI_OPCODE_WRITE_LE_HOST_SUPPORT = 0x0C6D;

void HciWriteLeHostSupport()
{
uint8_t *pBuf;
if ((pBuf = hciCmdAlloc(HCI_OPCODE_WRITE_LE_HOST_SUPPORT, 2)) != NULL)
{
pBuf[HCI_CMD_HDR_LEN] = 0x01;
pBuf[HCI_CMD_HDR_LEN + 1] = 0x00;
hciCmdSend(pBuf);
}
uint8_t *pBuf;
if ((pBuf = hciCmdAlloc(HCI_OPCODE_WRITE_LE_HOST_SUPPORT, 2)) != NULL)
{
pBuf[HCI_CMD_HDR_LEN] = 0x01;
pBuf[HCI_CMD_HDR_LEN + 1] = 0x00;
hciCmdSend(pBuf);
}
}

void hciCoreReadResolvingListSize(void)
Expand All @@ -503,7 +497,7 @@ class HCIDriver : public CordioHCIDriver {

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) &&
(hciLeSupFeatCfg & HCI_LE_SUP_FEAT_DATA_LEN_EXT))
{
Expand All @@ -522,9 +516,6 @@ class HCIDriver : public CordioHCIDriver {
return (is_powersave_enabled);
}

PinName bt_power_name;
mbed::DigitalInOut bt_power;

bool is_powersave_enabled;
uint8_t host_wake_irq;
uint8_t dev_wake_irq;
Expand All @@ -546,12 +537,12 @@ ble::CordioHCIDriver& ble_cordio_get_hci_driver()
{
static ble::vendor::cypress_ble::CyH4TransportDriver& transport_driver =
ble_cordio_get_h4_transport_driver();

static ble::vendor::cypress::HCIDriver hci_driver(
transport_driver,
/* bt_power */ CYBSP_BT_POWER,
transport_driver.get_enabled_powersave(),
transport_driver.get_host_wake_irq_event(),
transport_driver.get_dev_wake_irq_event()
transport_driver.get_enabled_powersave(),
transport_driver.get_host_wake_irq_event(),
transport_driver.get_dev_wake_irq_event()
);
return hci_driver;
}