diff --git a/features/FEATURE_BLE/targets/TARGET_Cypress/TARGET_CYW43XXX/CyH4TransportDriver.cpp b/features/FEATURE_BLE/targets/TARGET_Cypress/TARGET_CYW43XXX/CyH4TransportDriver.cpp index db9277ea76..bbfe456b44 100644 --- a/features/FEATURE_BLE/targets/TARGET_Cypress/TARGET_CYW43XXX/CyH4TransportDriver.cpp +++ b/features/FEATURE_BLE/targets/TARGET_Cypress/TARGET_CYW43XXX/CyH4TransportDriver.cpp @@ -29,7 +29,7 @@ CyH4TransportDriver::CyH4TransportDriver(PinName tx, PinName rx, PinName cts, Pi 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, PullNone, 1), host_wake_irq_event(host_wake_irq), dev_wake_irq_event(dev_wake_irq) { @@ -61,9 +61,10 @@ CyH4TransportDriver::~CyH4TransportDriver() void CyH4TransportDriver::bt_host_wake_irq_handler(void) { - sleep_manager_lock_deep_sleep(); - CyH4TransportDriver::on_controller_irq(); - sleep_manager_unlock_deep_sleep(); + uart.attach( + callback(this, &CyH4TransportDriver::on_controller_irq), + SerialBase::RxIrq + ); } void CyH4TransportDriver::initialize() @@ -72,6 +73,8 @@ void CyH4TransportDriver::initialize() InterruptIn *host_wake_pin; #endif + sleep_manager_lock_deep_sleep(); + uart.format( /* bits */ 8, /* parity */ SerialBase::None, @@ -90,12 +93,14 @@ 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); - 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)); + if (bt_host_wake_name != NC) { + //Register IRQ for Host WAKE + host_wake_pin = new InterruptIn(bt_host_wake_name); + 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 @@ -106,6 +111,7 @@ void CyH4TransportDriver::initialize() if (bt_device_wake_name != NC) bt_device_wake = WAKE_EVENT_ACTIVE_HIGH; } + sleep_manager_unlock_deep_sleep(); rtos::ThisThread::sleep_for(500); } @@ -115,6 +121,7 @@ uint16_t CyH4TransportDriver::write(uint8_t type, uint16_t len, uint8_t *pData) { uint16_t i = 0; + sleep_manager_lock_deep_sleep(); assert_bt_dev_wake(); while (i < len + 1) { @@ -125,28 +132,42 @@ uint16_t CyH4TransportDriver::write(uint8_t type, uint16_t len, uint8_t *pData) } deassert_bt_dev_wake(); + sleep_manager_unlock_deep_sleep(); return len; } +#if (defined(MBED_TICKLESS) && DEVICE_SLEEP && DEVICE_LPTICKER) +void CyH4TransportDriver::on_host_stack_inactivity() +{ + if (enabled_powersave) { + uart.attach(NULL, SerialBase::RxIrq); + } +} +#endif + void CyH4TransportDriver::on_controller_irq() { - assert_bt_dev_wake(); + sleep_manager_lock_deep_sleep(); + assert_bt_dev_wake(); - while (uart.readable()) { + while (uart.readable()) { uint8_t char_received = uart.getc(); on_data_received(&char_received, 1); } - deassert_bt_dev_wake(); + deassert_bt_dev_wake(); + sleep_manager_unlock_deep_sleep(); } void CyH4TransportDriver::assert_bt_dev_wake() { #if (defined(MBED_TICKLESS) && DEVICE_SLEEP && DEVICE_LPTICKER) - if (dev_wake_irq_event == WAKE_EVENT_ACTIVE_LOW) { - bt_device_wake = WAKE_EVENT_ACTIVE_LOW; - } else { - bt_device_wake = WAKE_EVENT_ACTIVE_HIGH; + if (enabled_powersave) { + 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 } @@ -154,15 +175,24 @@ void CyH4TransportDriver::assert_bt_dev_wake() void CyH4TransportDriver::deassert_bt_dev_wake() { #if (defined(MBED_TICKLESS) && DEVICE_SLEEP && DEVICE_LPTICKER) - //De-assert bt_device_wake - if (dev_wake_irq_event == WAKE_EVENT_ACTIVE_LOW) { - bt_device_wake = WAKE_EVENT_ACTIVE_HIGH; - } else { - bt_device_wake = WAKE_EVENT_ACTIVE_LOW; + if (enabled_powersave) { + wait_us(5000); /* remove and replace when uart tx transmit complete api is available */ + //De-assert bt_device_wake + 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 } + +void CyH4TransportDriver::update_uart_baud_rate(int baud) +{ + uart.baud(baud); +} + bool CyH4TransportDriver::get_enabled_powersave() { return (enabled_powersave); diff --git a/features/FEATURE_BLE/targets/TARGET_Cypress/TARGET_CYW43XXX/CyH4TransportDriver.h b/features/FEATURE_BLE/targets/TARGET_Cypress/TARGET_CYW43XXX/CyH4TransportDriver.h index 46b71148cc..da94932481 100644 --- a/features/FEATURE_BLE/targets/TARGET_Cypress/TARGET_CYW43XXX/CyH4TransportDriver.h +++ b/features/FEATURE_BLE/targets/TARGET_Cypress/TARGET_CYW43XXX/CyH4TransportDriver.h @@ -66,6 +66,12 @@ public: void bt_host_wake_irq_handler(); +#if (defined(MBED_TICKLESS) && DEVICE_SLEEP && DEVICE_LPTICKER) + void on_host_stack_inactivity(); +#endif + + void update_uart_baud_rate(int baud); + bool get_enabled_powersave(); uint8_t get_host_wake_irq_event(); uint8_t get_dev_wake_irq_event(); @@ -101,10 +107,15 @@ private: } // namespace ble #define DEF_BT_BAUD_RATE (115200) +#define DEF_BT_3M_BAUD_RATE (3000000) /* Both Host and BT device have to be adapt to this */ #define WAKE_EVENT_ACTIVE_HIGH ( 1 ) /* Interrupt Rising Edge */ #define WAKE_EVENT_ACTIVE_LOW ( 0 ) /* Interrupt Falling Edge */ +#if (defined(TARGET_CY8CPROTO_062_4343W)) +#define BT_UART_NO_3M_SUPPORT ( 1 ) +#endif + ble::vendor::cypress_ble::CyH4TransportDriver& ble_cordio_get_default_h4_transport_driver(); ble::vendor::cypress_ble::CyH4TransportDriver& ble_cordio_get_h4_transport_driver(); #endif diff --git a/features/FEATURE_BLE/targets/TARGET_Cypress/TARGET_CYW43XXX/HCIDriver.cpp b/features/FEATURE_BLE/targets/TARGET_Cypress/TARGET_CYW43XXX/HCIDriver.cpp index 5f7d82d17f..2c1d941f83 100644 --- a/features/FEATURE_BLE/targets/TARGET_Cypress/TARGET_CYW43XXX/HCIDriver.cpp +++ b/features/FEATURE_BLE/targets/TARGET_Cypress/TARGET_CYW43XXX/HCIDriver.cpp @@ -29,20 +29,35 @@ extern const int brcm_patch_ram_length; extern const uint8_t brcm_patchram_buf[]; +#ifndef BT_UART_NO_3M_SUPPORT static const uint8_t pre_brcm_patchram_buf[] = { - // RESET followed by download mini driver cmd + // RESET followed by update uart baudrate 0x03, 0x0C, 0x00, + 0x18, 0xFC, 0x06, 0x00, 0x00, 0xC0, 0xC6, 0x2D, 0x00, //update uart baudrate 3 mbp +}; +#else /* BT_UART_NO_3M_SUPPORT */ +static const uint8_t pre_brcm_patchram_buf[] = { + // RESET cmd + 0x03, 0x0C, 0x00, +}; +#endif /* BT_UART_NO_3M_SUPPORT */ + +static const uint8_t pre_brcm_patchram_buf2[] = { + //download mini driver 0x2E, 0xFC, 0x00, }; + static const uint8_t post_brcm_patchram_buf[] = { // RESET cmd 0x03, 0x0C, 0x00, }; static const int pre_brcm_patch_ram_length = sizeof(pre_brcm_patchram_buf); +static const int pre_brcm_patch_ram_length2 = sizeof(pre_brcm_patchram_buf2); static const int post_brcm_patch_ram_length = sizeof(post_brcm_patchram_buf); #define HCI_RESET_RAND_CNT 4 +#define HCI_VS_CMD_UPDATE_UART_BAUD_RATE 0xFC18 #define HCI_VS_CMD_SET_SLEEP_MODE 0xFC27 @@ -55,7 +70,7 @@ namespace cypress { class HCIDriver : public cordio::CordioHCIDriver { public: HCIDriver( - cordio::CordioHCITransportDriver& transport_driver, + ble::vendor::cypress_ble::CyH4TransportDriver& transport_driver, PinName bt_power_name, bool ps_enabled, uint8_t host_wake_irq, @@ -70,7 +85,8 @@ public: service_pack_ptr(0), service_pack_length(0), service_pack_next(), - service_pack_transfered(false) { + service_pack_transfered(false), + cy_transport_driver(transport_driver) { } virtual cordio::buf_pool_desc_t get_buffer_pool_description() @@ -81,6 +97,9 @@ public: virtual void do_initialize() { + //Prevent PSoC6 to enter deep-sleep till BT initialization is complete + sleep_manager_lock_deep_sleep(); + rtos::ThisThread::sleep_for(500); bt_power = 1; rtos::ThisThread::sleep_for(500); } @@ -113,6 +132,42 @@ public: /* decode opcode */ switch (opcode) { + case HCI_VS_CMD_UPDATE_UART_BAUD_RATE: +#ifndef BT_UART_NO_3M_SUPPORT + cy_transport_driver.update_uart_baud_rate(DEF_BT_3M_BAUD_RATE); +#endif /* BT_UART_NO_3M_SUPPORT */ +#ifdef CY_DEBUG + HciReadLocalVerInfoCmd(); +#else + set_sleep_mode(); +#endif + break; + +#ifdef CY_DEBUG + case HCI_OPCODE_READ_LOCAL_VER_INFO: + uint8_t hci_version; + uint8_t hci_revision; + uint8_t lmp_revision; + uint16_t manufacturer_name; + + BSTREAM_TO_UINT8(hci_version, pMsg); + BSTREAM_TO_UINT8(hci_revision, pMsg); + BSTREAM_TO_UINT8(lmp_revision, pMsg); + BSTREAM_TO_UINT16(manufacturer_name, pMsg); + + if(hci_revision == 0 || manufacturer_name == 0xF) + { + printf("bt firmware download failed, rom code is being used\n"); + } + else + { + printf("bt firmware download success\n"); + } + + set_sleep_mode(); + break; +#endif + // Note: Reset is handled by ack_service_pack. case HCI_VS_CMD_SET_SLEEP_MODE: HciWriteLeHostSupport(); @@ -263,20 +318,42 @@ public: } } +#if (defined(MBED_TICKLESS) && DEVICE_SLEEP && DEVICE_LPTICKER) + virtual void on_host_stack_inactivity(void) + { + cy_transport_driver.on_host_stack_inactivity(); + } +#endif + private: - // send pre_brcm_patchram_buf + // send pre_brcm_patchram_buf issue hci reset and update baud rate on 43012 void prepare_service_pack_transfert(void) { service_pack_ptr = pre_brcm_patchram_buf; service_pack_length = pre_brcm_patch_ram_length; + service_pack_next = &HCIDriver::prepare_service_pack_transfert2; + service_pack_index = 0; + service_pack_transfered = false; + send_service_pack_command(); + } + + // Called one pre_brcm_patchram_buf has been transferred; send pre_brcm_patchram_buf2 update uart baudrate + // on PSoC6 to send hci download minidriver + void prepare_service_pack_transfert2(void) + { +#ifndef BT_UART_NO_3M_SUPPORT + cy_transport_driver.update_uart_baud_rate(DEF_BT_3M_BAUD_RATE); +#endif /* BT_UART_NO_3M_SUPPORT */ + service_pack_ptr = pre_brcm_patchram_buf2; + service_pack_length = pre_brcm_patch_ram_length2; service_pack_next = &HCIDriver::start_service_pack_transfert; service_pack_index = 0; service_pack_transfered = false; send_service_pack_command(); } - // Called once pre_brcm_patchram_buf has been transferred; send brcm_patchram_buf + // Called once pre_brcm_patchram_buf2 has been transferred; send brcm_patchram_buf void start_service_pack_transfert(void) { service_pack_ptr = brcm_patchram_buf; @@ -290,6 +367,7 @@ private: // Called once brcm_patchram_buf has been transferred; send post_brcm_patchram_buf void post_service_pack_transfert(void) { + cy_transport_driver.update_uart_baud_rate(DEF_BT_BAUD_RATE); service_pack_ptr = post_brcm_patchram_buf; service_pack_length = post_brcm_patch_ram_length; service_pack_next = &HCIDriver::terminate_service_pack_transfert;; @@ -307,7 +385,12 @@ private: service_pack_next = NULL; service_pack_index = 0; service_pack_transfered = true; +#ifndef BT_UART_NO_3M_SUPPORT + HciUpdateUartBaudRate(); +#else /* BT_UART_NO_3M_SUPPORT */ set_sleep_mode(); +#endif /* BT_UART_NO_3M_SUPPORT */ + sleep_manager_unlock_deep_sleep(); } void send_service_pack_command(void) @@ -354,7 +437,11 @@ private: 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) + 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 { @@ -363,7 +450,7 @@ private: 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 + 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 @@ -371,7 +458,23 @@ private: 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 + 10] = 0x00; // Pulsed host wake + 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); } } @@ -440,6 +543,7 @@ private: int service_pack_length; void (HCIDriver::*service_pack_next)(); bool service_pack_transfered; + ble::vendor::cypress_ble::CyH4TransportDriver& cy_transport_driver; };