Improve Cordio low power assist

Allow more flexibile configuration for BLE radio pins
pull/11367/head
Mukund 2019-08-14 19:22:41 -05:00 committed by Kyle Kearney
parent e8f325fe33
commit 41dded9ec5
4 changed files with 283 additions and 26 deletions

View File

@ -18,31 +18,59 @@
#if DEVICE_SERIAL && DEVICE_SERIAL_FC
#include "CyH4TransportDriver.h"
#include "cycfg_pins.h"
namespace ble {
namespace vendor {
namespace cypress_ble {
CyH4TransportDriver::CyH4TransportDriver(PinName tx, PinName rx, PinName cts, PinName rts, int baud, PinName bt_host_wake_name, PinName bt_device_wake_name) :
CyH4TransportDriver::CyH4TransportDriver(PinName tx, PinName rx, PinName cts, PinName rts, int baud, PinName bt_host_wake_name, PinName bt_device_wake_name, uint8_t host_wake_irq, uint8_t dev_wake_irq) :
uart(tx, rx, baud), cts(cts), rts(rts),
bt_host_wake_name(bt_host_wake_name),
bt_device_wake_name(bt_device_wake_name),
bt_host_wake(bt_host_wake_name, PIN_INPUT, PullNone, 0),
bt_device_wake(bt_device_wake_name, PIN_OUTPUT, PullDefault, 1)
bt_device_wake(bt_device_wake_name, PIN_OUTPUT, PullDefault, 1),
host_wake_irq_event(host_wake_irq),
dev_wake_irq_event(dev_wake_irq)
{
enabled_powersave = true;
}
CyH4TransportDriver::CyH4TransportDriver(PinName tx, PinName rx, PinName cts, PinName rts, int baud) :
uart(tx, rx, baud),
cts(cts),
rts(rts),
bt_host_wake_name(NC),
bt_device_wake_name(NC),
bt_host_wake(bt_host_wake_name),
bt_device_wake(bt_device_wake_name)
{
enabled_powersave = false;
sleep_manager_lock_deep_sleep();
holding_deep_sleep_lock = true;
}
CyH4TransportDriver::~CyH4TransportDriver()
{
if (holding_deep_sleep_lock)
{
sleep_manager_unlock_deep_sleep();
holding_deep_sleep_lock = false;
}
}
void CyH4TransportDriver::bt_host_wake_irq_handler(void)
{
sleep_manager_lock_deep_sleep();
CyH4TransportDriver::on_controller_irq();
sleep_manager_unlock_deep_sleep();
sleep_manager_lock_deep_sleep();
CyH4TransportDriver::on_controller_irq();
sleep_manager_unlock_deep_sleep();
}
void CyH4TransportDriver::initialize()
{
#if (defined(MBED_TICKLESS) && DEVICE_SLEEP && DEVICE_LPTICKER)
InterruptIn *host_wake_pin;
#endif
uart.format(
/* bits */ 8,
@ -64,10 +92,20 @@ void CyH4TransportDriver::initialize()
#if (defined(MBED_TICKLESS) && DEVICE_SLEEP && DEVICE_LPTICKER)
//Register IRQ for Host WAKE
host_wake_pin = new InterruptIn(bt_host_wake_name);
host_wake_pin->fall(callback(this, &CyH4TransportDriver::bt_host_wake_irq_handler));
if (host_wake_irq_event == WAKE_EVENT_ACTIVE_LOW) {
host_wake_pin->fall(callback(this, &CyH4TransportDriver::bt_host_wake_irq_handler));
} else {
host_wake_pin->rise(callback(this, &CyH4TransportDriver::bt_host_wake_irq_handler));
}
#endif
bt_device_wake = 0;
if (dev_wake_irq_event == WAKE_EVENT_ACTIVE_LOW) {
if (bt_device_wake_name != NC)
bt_device_wake = WAKE_EVENT_ACTIVE_LOW;
} else {
if (bt_device_wake_name != NC)
bt_device_wake = WAKE_EVENT_ACTIVE_HIGH;
}
wait_ms(500);
}
@ -105,7 +143,11 @@ void CyH4TransportDriver::on_controller_irq()
void CyH4TransportDriver::assert_bt_dev_wake()
{
#if (defined(MBED_TICKLESS) && DEVICE_SLEEP && DEVICE_LPTICKER)
bt_device_wake = 0;
if (dev_wake_irq_event == WAKE_EVENT_ACTIVE_LOW) {
bt_device_wake = WAKE_EVENT_ACTIVE_LOW;
} else {
bt_device_wake = WAKE_EVENT_ACTIVE_HIGH;
}
#endif
}
@ -113,12 +155,55 @@ void CyH4TransportDriver::deassert_bt_dev_wake()
{
#if (defined(MBED_TICKLESS) && DEVICE_SLEEP && DEVICE_LPTICKER)
//De-assert bt_device_wake
bt_device_wake = 1;
if (dev_wake_irq_event == WAKE_EVENT_ACTIVE_LOW) {
bt_device_wake = WAKE_EVENT_ACTIVE_HIGH;
} else {
bt_device_wake = WAKE_EVENT_ACTIVE_LOW;
}
#endif
}
bool CyH4TransportDriver::get_enabled_powersave()
{
return (enabled_powersave);
}
uint8_t CyH4TransportDriver::get_host_wake_irq_event()
{
return (host_wake_irq_event);
}
uint8_t CyH4TransportDriver::get_dev_wake_irq_event()
{
return (dev_wake_irq_event);
}
} // namespace cypress_ble
} // namespace vendor
} // namespace ble
ble::vendor::cypress_ble::CyH4TransportDriver& ble_cordio_get_default_h4_transport_driver()
{
#if (defined(CYBSP_BT_HOST_WAKE) && defined(CYBSP_BT_DEVICE_WAKE))
static ble::vendor::cypress_ble::CyH4TransportDriver s_transport_driver(
/* TX */ CYBSP_BT_UART_TX, /* RX */ CYBSP_BT_UART_RX,
/* cts */ CYBSP_BT_UART_CTS, /* rts */ CYBSP_BT_UART_RTS, DEF_BT_BAUD_RATE,
CYBSP_BT_HOST_WAKE, CYBSP_BT_DEVICE_WAKE
);
#else
static ble::vendor::cypress_ble::CyH4TransportDriver s_transport_driver(
/* TX */ CYBSP_BT_UART_TX, /* RX */ CYBSP_BT_UART_RX,
/* cts */ CYBSP_BT_UART_CTS, /* rts */ CYBSP_BT_UART_RTS, DEF_BT_BAUD_RATE);
#endif
return s_transport_driver;
}
MBED_WEAK
ble::vendor::cypress_ble::CyH4TransportDriver& ble_cordio_get_h4_transport_driver()
{
return (ble_cordio_get_default_h4_transport_driver());
}
#endif

View File

@ -25,7 +25,6 @@
#include "CordioHCITransportDriver.h"
#include "drivers/DigitalInOut.h"
namespace ble {
namespace vendor {
namespace cypress_ble {
@ -41,12 +40,14 @@ public:
* Initialize the transport driver.
*
*/
CyH4TransportDriver(PinName tx, PinName rx, PinName cts, PinName rts, int baud, PinName bt_host_wake_name, PinName bt_device_wake_name);
CyH4TransportDriver(PinName tx, PinName rx, PinName cts, PinName rts, 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, int baud);
/**
* Destructor
*/
virtual ~CyH4TransportDriver() { }
virtual ~CyH4TransportDriver();
/**
* @see CordioHCITransportDriver::initialize
@ -65,7 +66,10 @@ public:
void bt_host_wake_irq_handler();
private:
bool get_enabled_powersave();
uint8_t get_host_wake_irq_event();
uint8_t get_dev_wake_irq_event();
private:
void on_controller_irq();
void assert_bt_dev_wake();
@ -80,13 +84,28 @@ private:
PinName rts;
PinName bt_host_wake_name;
PinName bt_device_wake_name;
DigitalInOut bt_host_wake;
DigitalInOut bt_device_wake;
bool enabled_powersave;
uint8_t host_wake_irq_event;
uint8_t dev_wake_irq_event;
bool holding_deep_sleep_lock;
};
} // namespace cypress
} // namespace vendor
} // namespace ble
#define DEF_BT_BAUD_RATE (115200)
#define WAKE_EVENT_ACTIVE_HIGH ( 1 ) /* Interrupt Rising Edge */
#define WAKE_EVENT_ACTIVE_LOW ( 0 ) /* Interrupt Falling Edge */
ble::vendor::cypress_ble::CyH4TransportDriver& ble_cordio_get_default_h4_transport_driver();
ble::vendor::cypress_ble::CyH4TransportDriver& ble_cordio_get_h4_transport_driver();
#endif
#endif /* CY_H4TRANSPORT_DRIVER_H_ */

View File

@ -25,7 +25,6 @@
#include <stdbool.h>
#include "hci_mbed_os_adaptation.h"
#include "CyH4TransportDriver.h"
#include "cycfg_pins.h"
extern const int brcm_patch_ram_length;
extern const uint8_t brcm_patchram_buf[];
@ -57,10 +56,16 @@ class HCIDriver : public cordio::CordioHCIDriver {
public:
HCIDriver(
cordio::CordioHCITransportDriver& transport_driver,
PinName bt_power_name
PinName bt_power_name,
bool ps_enabled,
uint8_t host_wake_irq,
uint8_t dev_wake_irq
) : cordio::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),
service_pack_index(0),
service_pack_ptr(0),
service_pack_length(0),
@ -343,11 +348,23 @@ private:
uint8_t *pBuf;
if ((pBuf = hciCmdAlloc(HCI_VS_CMD_SET_SLEEP_MODE, 12)) != NULL)
{
pBuf[HCI_CMD_HDR_LEN] = 0x00; // no sleep
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)
pBuf[HCI_CMD_HDR_LEN + 2] = 0x00; // no idle threshold HC (N/A)
pBuf[HCI_CMD_HDR_LEN + 3] = 0x00; // BT WAKE
pBuf[HCI_CMD_HDR_LEN + 4] = 0x00; // HOST WAKE
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 + 3] = 0x00; // BT 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
@ -406,8 +423,18 @@ private:
}
}
bool is_powersave_on(void)
{
return (is_powersave_enabled);
}
PinName bt_power_name;
DigitalInOut bt_power;
bool is_powersave_enabled;
uint8_t host_wake_irq;
uint8_t dev_wake_irq;
size_t service_pack_index;
const uint8_t* service_pack_ptr;
int service_pack_length;
@ -420,15 +447,16 @@ private:
} // namespace vendor
} // namespace ble
ble::vendor::cordio::CordioHCIDriver& ble_cordio_get_hci_driver() {
static ble::vendor::cypress_ble::CyH4TransportDriver transport_driver(
/* TX */ CYBSP_BT_UART_TX, /* RX */ CYBSP_BT_UART_RX,
/* cts */ CYBSP_BT_UART_CTS, /* rts */ CYBSP_BT_UART_RTS, 115200,
CYBSP_BT_HOST_WAKE, CYBSP_BT_DEVICE_WAKE
);
ble::vendor::cordio::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
/* bt_power */ CYBSP_BT_POWER,
transport_driver.get_enabled_powersave(),
transport_driver.get_host_wake_irq_event(),
transport_driver.get_dev_wake_irq_event()
);
return hci_driver;
}

View File

@ -0,0 +1,125 @@
/*******************************************************************************
* \file cy_bt_cordio_cfg.cpp
* \version 1.0
*
*
* Low Power Assist BT Pin configuration implementation.
*
********************************************************************************
* \copyright
* Copyright 2019 Cypress Semiconductor Corporation
* 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 "CordioBLE.h"
#include "CordioHCIDriver.h"
#include "hci_api.h"
#include "hci_cmd.h"
#include "hci_core.h"
#include "bstream.h"
#include "assert.h"
#include <stdbool.h>
#include "hci_mbed_os_adaptation.h"
#include "CyH4TransportDriver.h"
#include "cycfg.h"
/* Sanity Checks for Pin Configuration. Fail compilation if Sanity Check is enabled
* and configuration is incorrect
*/
#if (defined(MBED_TICKLESS) && DEVICE_SLEEP && DEVICE_LPTICKER)
#if ((defined(CYCFG_BT_LP_ENABLED)) && (CYCFG_BT_LP_ENABLED != 0))
#if (!defined(CY_BT_SKIP_CONFIGURATION_CHECKS))
#if ((!defined(CYCFG_BT_HOST_WAKE_GPIO)) || (!defined(CYCFG_BT_DEV_WAKE_GPIO)))
#error "configurator host-wake and dev-wake pins must be configured when deep-sleep is enabled"
#endif
static_assert(((CYCFG_BT_HOST_WAKE_GPIO != NC) && (CYCFG_BT_DEV_WAKE_GPIO != NC)), \
"configurator host-wake and dev-wake pins must not be NC (no connect) when deep-sleep is enabled");
#endif /* (!defined(CY_BT_SKIP_CONFIGURATION_CHECKS)) */
#else /* ((defined(CYCFG_BT_LP_ENABLED)) && (CYCFG_BT_LP_ENABLED != 0)) */
#if (!defined(CY_BT_SKIP_CONFIGURATION_CHECKS))
#if ((!defined(CYBSP_BT_HOST_WAKE)) || (!defined(CYBSP_BT_DEVICE_WAKE)))
#error "BSP configuration host-wake and dev-wake pin must be configured when deep-sleep is enabled"
#endif
static_assert(((CYBSP_BT_HOST_WAKE != NC) && (CYBSP_BT_DEVICE_WAKE != NC)), \
"BSP configuration host-wake and dev-wake pin must not be NC (no connect) when deep-sleep is enabled");
#endif /* (!defined(CY_BT_SKIP_CONFIGURATION_CHECKS)) */
#endif /* ((defined(CYCFG_BT_LP_ENABLED)) && (CYCFG_BT_LP_ENABLED != 0)) */
#endif /* (defined(MBED_TICKLESS) && DEVICE_SLEEP && DEVICE_LPTICKER) */
/*******************************************************************************
* Function Name: ble_cordio_get_h4_transport_driver
********************************************************************************
*
* Strong implementation of function which calls CyH4TransportDriver constructor and return it
*
* \param none
*
* \return
* Returns the transport driver object
*******************************************************************************/
ble::vendor::cypress_ble::CyH4TransportDriver& ble_cordio_get_h4_transport_driver()
{
#if (defined(MBED_TICKLESS) && DEVICE_SLEEP && DEVICE_LPTICKER)
#if (defined(CYCFG_BT_LP_ENABLED))
if (CYCFG_BT_LP_ENABLED) {
static ble::vendor::cypress_ble::CyH4TransportDriver s_transport_driver(
/* TX */ cyhal_gpio_to_rtos(CYBSP_BT_UART_TX),
/* RX */ cyhal_gpio_to_rtos(CYBSP_BT_UART_RX),
/* cts */ cyhal_gpio_to_rtos(CYBSP_BT_UART_CTS),
/* rts */ cyhal_gpio_to_rtos(CYBSP_BT_UART_RTS), DEF_BT_BAUD_RATE,
cyhal_gpio_to_rtos(CYCFG_BT_HOST_WAKE_GPIO),
cyhal_gpio_to_rtos(CYCFG_BT_DEV_WAKE_GPIO),
CYCFG_BT_HOST_WAKE_IRQ_EVENT,
CYCFG_BT_DEV_WAKE_POLARITY
);
return s_transport_driver;
} else { /* CYCFG_BT_LP_ENABLED */
static ble::vendor::cypress_ble::CyH4TransportDriver s_transport_driver(
/* TX */ cyhal_gpio_to_rtos(CYBSP_BT_UART_TX),
/* RX */ cyhal_gpio_to_rtos(CYBSP_BT_UART_RX),
/* cts */ cyhal_gpio_to_rtos(CYBSP_BT_UART_CTS),
/* rts */ cyhal_gpio_to_rtos(CYBSP_BT_UART_RTS), DEF_BT_BAUD_RATE);
return s_transport_driver;
}
#else /* (defined(CYCFG_BT_LP_ENABLED)) */
static ble::vendor::cypress_ble::CyH4TransportDriver s_transport_driver(
/* TX */ cyhal_gpio_to_rtos(CYBSP_BT_UART_TX),
/* RX */ cyhal_gpio_to_rtos(CYBSP_BT_UART_RX),
/* cts */ cyhal_gpio_to_rtos(CYBSP_BT_UART_CTS),
/* rts */ cyhal_gpio_to_rtos(CYBSP_BT_UART_RTS), DEF_BT_BAUD_RATE,
cyhal_gpio_to_rtos(CYBSP_BT_HOST_WAKE), cyhal_gpio_to_rtos(CYBSP_BT_DEVICE_WAKE)
);
return s_transport_driver;
#endif /* (defined(CYCFG_BT_LP_ENABLED)) */
#else /* (defined(MBED_TICKLESS) && DEVICE_SLEEP && DEVICE_LPTICKER) */
static ble::vendor::cypress_ble::CyH4TransportDriver s_transport_driver(
/* TX */ cyhal_gpio_to_rtos(CYBSP_BT_UART_TX),
/* RX */ cyhal_gpio_to_rtos(CYBSP_BT_UART_RX),
/* cts */ cyhal_gpio_to_rtos(CYBSP_BT_UART_CTS),
/* rts */ cyhal_gpio_to_rtos(CYBSP_BT_UART_RTS), DEF_BT_BAUD_RATE);
return s_transport_driver;
#endif /* (defined(MBED_TICKLESS) && DEVICE_SLEEP && DEVICE_LPTICKER) */
}