hci_transport_h4: add workaround for flow control bug in CYW2070x, enable with ENABLE_CYPRESS_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND

This commit is contained in:
Matthias Ringwald 2019-05-14 18:10:58 +02:00
parent 7741d2d072
commit 77291b13db
3 changed files with 32 additions and 4 deletions

View File

@ -31,6 +31,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- port/stm32-f4discovery-cc256x: add support for built-in MEMS microphone - port/stm32-f4discovery-cc256x: add support for built-in MEMS microphone
- libusb: add support for nRF52840-PCA10056 running Zephyr hci_usb example - libusb: add support for nRF52840-PCA10056 running Zephyr hci_usb example
- port for Nucelo L073RZ with EM9304 DVK: stm32-l073rz-nucleo-em9304 - port for Nucelo L073RZ with EM9304 DVK: stm32-l073rz-nucleo-em9304
- hci_transport_h4: add workaround for flow control bug in CYW2070x, enable with ENABLE_CYPRESS_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND
## Changes February 2019 ## Changes February 2019

View File

@ -90,6 +90,7 @@ ENABLE_ATT_DELAYED_RESPONSE | Enable support for delayed ATT operations, se
ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE | Enable L2CAP Enhanced Retransmission Mode. Mandatory for AVRCP Browsing ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE | Enable L2CAP Enhanced Retransmission Mode. Mandatory for AVRCP Browsing
ENABLE_HCI_CONTROLLER_TO_HOST_FLOW_CONTROL | Enable HCI Controller to Host Flow Control, see below ENABLE_HCI_CONTROLLER_TO_HOST_FLOW_CONTROL | Enable HCI Controller to Host Flow Control, see below
ENABLE_CC256X_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND | Enable workaround for bug in CC256x Flow Control during baud rate change, see chipset docs. ENABLE_CC256X_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND | Enable workaround for bug in CC256x Flow Control during baud rate change, see chipset docs.
ENABLE_CYPRESS_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND | Enable workaround for bug in CYW2070x Flow Control during baud rate change, similar to CC256x.
ENABLE_TLV_FLASH_EXPLICIT_DELETE_FIELD | Enable use of explicit delete field in TLV Flash implemenation - required when flash value cannot be overwritten with zero ENABLE_TLV_FLASH_EXPLICIT_DELETE_FIELD | Enable use of explicit delete field in TLV Flash implemenation - required when flash value cannot be overwritten with zero

View File

@ -147,9 +147,22 @@ static int read_pos;
static uint8_t hci_packet_with_pre_buffer[HCI_INCOMING_PRE_BUFFER_SIZE + HCI_INCOMING_PACKET_BUFFER_SIZE + 1]; // packet type + max(acl header + acl payload, event header + event data) static uint8_t hci_packet_with_pre_buffer[HCI_INCOMING_PRE_BUFFER_SIZE + HCI_INCOMING_PACKET_BUFFER_SIZE + 1]; // packet type + max(acl header + acl payload, event header + event data)
static uint8_t * hci_packet = &hci_packet_with_pre_buffer[HCI_INCOMING_PRE_BUFFER_SIZE]; static uint8_t * hci_packet = &hci_packet_with_pre_buffer[HCI_INCOMING_PRE_BUFFER_SIZE];
// Baudrate change bugs in TI CC256x and CYW20704
#ifdef ENABLE_CC256X_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND #ifdef ENABLE_CC256X_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND
static const uint8_t local_version_event_prefix[] = { 0x04, 0x0e, 0x0c, 0x01, 0x01, 0x10}; #define ENABLE_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND
static const uint8_t baud_rate_command_prefix[] = { 0x01, 0x36, 0xff, 0x04}; static const uint8_t baud_rate_command_prefix[] = { 0x01, 0x36, 0xff, 0x04};
#endif
#ifdef ENABLE_CYPRESS_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND
#ifdef ENABLE_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND
#error "Please enable either ENABLE_CC256X_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND or ENABLE_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND"
#endif
#define ENABLE_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND
static const uint8_t baud_rate_command_prefix[] = { 0x01, 0x18, 0xfc, 0x06};
#endif
#ifdef ENABLE_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND
static const uint8_t local_version_event_prefix[] = { 0x04, 0x0e, 0x0c, 0x01, 0x01, 0x10};
static enum { static enum {
BAUDRATE_CHANGE_WORKAROUND_IDLE, BAUDRATE_CHANGE_WORKAROUND_IDLE,
BAUDRATE_CHANGE_WORKAROUND_CHIPSET_DETECTED, BAUDRATE_CHANGE_WORKAROUND_CHIPSET_DETECTED,
@ -243,9 +256,10 @@ static void hci_transport_h4_block_read(void){
break; break;
case H4_W4_PAYLOAD: case H4_W4_PAYLOAD:
#ifdef ENABLE_CC256X_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND #ifdef ENABLE_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND
if (baudrate_change_workaround_state == BAUDRATE_CHANGE_WORKAROUND_IDLE if (baudrate_change_workaround_state == BAUDRATE_CHANGE_WORKAROUND_IDLE
&& memcmp(hci_packet, local_version_event_prefix, sizeof(local_version_event_prefix)) == 0){ && memcmp(hci_packet, local_version_event_prefix, sizeof(local_version_event_prefix)) == 0){
#ifdef ENABLE_CC256X_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND
if (little_endian_read_16(hci_packet, 11) == BLUETOOTH_COMPANY_ID_TEXAS_INSTRUMENTS_INC){ if (little_endian_read_16(hci_packet, 11) == BLUETOOTH_COMPANY_ID_TEXAS_INSTRUMENTS_INC){
// detect TI CC256x controller based on manufacturer // detect TI CC256x controller based on manufacturer
log_info("Detected CC256x controller"); log_info("Detected CC256x controller");
@ -255,6 +269,18 @@ static void hci_transport_h4_block_read(void){
log_info("Bluetooth controller not by TI"); log_info("Bluetooth controller not by TI");
baudrate_change_workaround_state = BAUDRATE_CHANGE_WORKAROUND_DONE; baudrate_change_workaround_state = BAUDRATE_CHANGE_WORKAROUND_DONE;
} }
#endif
#ifdef ENABLE_CYPRESS_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND
if (little_endian_read_16(hci_packet, 11) == BLUETOOTH_COMPANY_ID_CYPRESS_SEMICONDUCTOR){
// detect Cypress controller based on manufacturer
log_info("Detected Cypress controller");
baudrate_change_workaround_state = BAUDRATE_CHANGE_WORKAROUND_CHIPSET_DETECTED;
} else {
// work around not needed
log_info("Bluetooth controller not by Cypress");
baudrate_change_workaround_state = BAUDRATE_CHANGE_WORKAROUND_DONE;
}
#endif
} }
#endif #endif
packet_handler(hci_packet[0], &hci_packet[1], read_pos-1); packet_handler(hci_packet[0], &hci_packet[1], read_pos-1);
@ -264,7 +290,7 @@ static void hci_transport_h4_block_read(void){
break; break;
} }
#ifdef ENABLE_CC256X_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND #ifdef ENABLE_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND
if (baudrate_change_workaround_state == BAUDRATE_CHANGE_WORKAROUND_BAUDRATE_COMMAND_SENT){ if (baudrate_change_workaround_state == BAUDRATE_CHANGE_WORKAROUND_BAUDRATE_COMMAND_SENT){
baudrate_change_workaround_state = BAUDRATE_CHANGE_WORKAROUND_IDLE; baudrate_change_workaround_state = BAUDRATE_CHANGE_WORKAROUND_IDLE;
// avoid flowcontrol problem by reading expected hci command complete event of 7 bytes in a single block read // avoid flowcontrol problem by reading expected hci command complete event of 7 bytes in a single block read
@ -316,7 +342,7 @@ static int hci_transport_h4_send_packet(uint8_t packet_type, uint8_t * packet, i
packet--; packet--;
*packet = packet_type; *packet = packet_type;
#ifdef ENABLE_CC256X_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND #ifdef ENABLE_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND
if ((baudrate_change_workaround_state == BAUDRATE_CHANGE_WORKAROUND_CHIPSET_DETECTED) if ((baudrate_change_workaround_state == BAUDRATE_CHANGE_WORKAROUND_CHIPSET_DETECTED)
&& (memcmp(packet, baud_rate_command_prefix, sizeof(baud_rate_command_prefix)) == 0)) { && (memcmp(packet, baud_rate_command_prefix, sizeof(baud_rate_command_prefix)) == 0)) {
log_info("Baud rate command detected, expect command complete event next"); log_info("Baud rate command detected, expect command complete event next");