mirror of
https://github.com/raspberrypi/pico-sdk.git
synced 2025-12-10 07:14:36 +01:00
Bt wifi buffer corruption (#1362)
Change from Infineon to fix the BT buffer corruption which occurs when making heavy use of BT and WIFI at the same time. Update cyw43-driver (Includes fix for BT+Wifi buffer corruption issue)
This commit is contained in:
parent
c34d3d5602
commit
8dbc6f20a3
3 changed files with 38 additions and 35 deletions
|
|
@ -1 +1 @@
|
||||||
Subproject commit 9bfca61173a94432839cd39210f1d1afdf602c42
|
Subproject commit d97664848b6da6ad6c7dc07fb8901d68cee514af
|
||||||
|
|
@ -63,6 +63,7 @@ static uint32_t last_bt_ctrl_reg;
|
||||||
#define B2H_BUF_OUT_ADDR (buf_info.bt2host_out_addr)
|
#define B2H_BUF_OUT_ADDR (buf_info.bt2host_out_addr)
|
||||||
|
|
||||||
static uint32_t wlan_ram_base_addr;
|
static uint32_t wlan_ram_base_addr;
|
||||||
|
volatile uint32_t host_ctrl_cache_reg = 0;
|
||||||
#define WLAN_RAM_BASE_ADDR (wlan_ram_base_addr)
|
#define WLAN_RAM_BASE_ADDR (wlan_ram_base_addr)
|
||||||
|
|
||||||
// In wifi host driver these are all constants
|
// In wifi host driver these are all constants
|
||||||
|
|
@ -70,8 +71,7 @@ static uint32_t wlan_ram_base_addr;
|
||||||
#define HOST_CTRL_REG_ADDR ((uint32_t)0x18000d6c)
|
#define HOST_CTRL_REG_ADDR ((uint32_t)0x18000d6c)
|
||||||
#define WLAN_RAM_BASE_REG_ADDR ((uint32_t)0x18000d68)
|
#define WLAN_RAM_BASE_REG_ADDR ((uint32_t)0x18000d68)
|
||||||
|
|
||||||
typedef struct
|
typedef struct {
|
||||||
{
|
|
||||||
uint32_t host2bt_buf_addr;
|
uint32_t host2bt_buf_addr;
|
||||||
uint32_t host2bt_in_addr;
|
uint32_t host2bt_in_addr;
|
||||||
uint32_t host2bt_out_addr;
|
uint32_t host2bt_out_addr;
|
||||||
|
|
@ -109,27 +109,19 @@ cybt_fw_membuf_info_t buf_info;
|
||||||
#define ROUNDDN(x, a) ((x) & ~((a) - 1))
|
#define ROUNDDN(x, a) ((x) & ~((a) - 1))
|
||||||
#define ISALIGNED(a, x) (((uint32_t)(a) & ((x) - 1)) == 0)
|
#define ISALIGNED(a, x) (((uint32_t)(a) & ((x) - 1)) == 0)
|
||||||
|
|
||||||
typedef struct cybt_fw_cb
|
typedef struct cybt_fw_cb {
|
||||||
{
|
|
||||||
const uint8_t *p_fw_mem_start;
|
const uint8_t *p_fw_mem_start;
|
||||||
uint32_t fw_len;
|
uint32_t fw_len;
|
||||||
const uint8_t *p_next_line_start;
|
const uint8_t *p_next_line_start;
|
||||||
} cybt_fw_cb_t;
|
} cybt_fw_cb_t;
|
||||||
|
|
||||||
typedef struct hex_file_data
|
typedef struct hex_file_data {
|
||||||
{
|
|
||||||
int addr_mode;
|
int addr_mode;
|
||||||
uint16_t hi_addr;
|
uint16_t hi_addr;
|
||||||
uint32_t dest_addr;
|
uint32_t dest_addr;
|
||||||
uint8_t *p_ds;
|
uint8_t *p_ds;
|
||||||
} hex_file_data_t;
|
} hex_file_data_t;
|
||||||
|
|
||||||
#if USE_SDIO
|
|
||||||
#define MAX_BLOCK_SIZE 16384
|
|
||||||
#else
|
|
||||||
#define MAX_BLOCK_SIZE 64
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static cyw43_ll_t *cyw43_ll = NULL;
|
static cyw43_ll_t *cyw43_ll = NULL;
|
||||||
|
|
||||||
static cybt_result_t cybt_reg_write(uint32_t reg_addr, uint32_t value);
|
static cybt_result_t cybt_reg_write(uint32_t reg_addr, uint32_t value);
|
||||||
|
|
@ -174,7 +166,7 @@ static uint32_t cybt_fw_hex_read_line(cybt_fw_cb_t *p_btfw_cb,
|
||||||
return str_len;
|
return str_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint8_t nibble_for_char(char c){
|
static inline uint8_t nibble_for_char(char c) {
|
||||||
if ((c >= '0') && (c <= '9')) return c - '0';
|
if ((c >= '0') && (c <= '9')) return c - '0';
|
||||||
if ((c >= 'A') && (c <= 'F')) return c - 'A' + 10;
|
if ((c >= 'A') && (c <= 'F')) return c - 'A' + 10;
|
||||||
return -1;
|
return -1;
|
||||||
|
|
@ -559,10 +551,17 @@ cybt_result_t cybt_get_bt_buf_index(cybt_fw_membuf_index_t *p_buf_index) {
|
||||||
static cybt_result_t cybt_reg_write(uint32_t reg_addr, uint32_t value) {
|
static cybt_result_t cybt_reg_write(uint32_t reg_addr, uint32_t value) {
|
||||||
cybt_debug("cybt_reg_write 0x%08lx 0x%08lx\n", reg_addr, value);
|
cybt_debug("cybt_reg_write 0x%08lx 0x%08lx\n", reg_addr, value);
|
||||||
cyw43_ll_write_backplane_reg(cyw43_ll, reg_addr, value);
|
cyw43_ll_write_backplane_reg(cyw43_ll, reg_addr, value);
|
||||||
|
if (reg_addr == HOST_CTRL_REG_ADDR) {
|
||||||
|
host_ctrl_cache_reg = value;
|
||||||
|
}
|
||||||
return CYBT_SUCCESS;
|
return CYBT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static cybt_result_t cybt_reg_read(uint32_t reg_addr, uint32_t *p_value) {
|
static cybt_result_t cybt_reg_read(uint32_t reg_addr, uint32_t *p_value) {
|
||||||
|
if (reg_addr == HOST_CTRL_REG_ADDR) {
|
||||||
|
*p_value = host_ctrl_cache_reg;
|
||||||
|
return CYBT_SUCCESS;
|
||||||
|
}
|
||||||
*p_value = cyw43_ll_read_backplane_reg(cyw43_ll, reg_addr);
|
*p_value = cyw43_ll_read_backplane_reg(cyw43_ll, reg_addr);
|
||||||
cybt_debug("cybt_reg_read 0x%08lx == 0x%08lx\n", reg_addr, *p_value);
|
cybt_debug("cybt_reg_read 0x%08lx == 0x%08lx\n", reg_addr, *p_value);
|
||||||
return CYBT_SUCCESS;
|
return CYBT_SUCCESS;
|
||||||
|
|
@ -579,7 +578,6 @@ static void dump_bytes(const uint8_t *bptr, uint32_t len) {
|
||||||
cybt_debug("0x%02x", bptr[i]);
|
cybt_debug("0x%02x", bptr[i]);
|
||||||
if (i != (len - 1)) {
|
if (i != (len - 1)) {
|
||||||
cybt_debug(", ");
|
cybt_debug(", ");
|
||||||
} else {
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cybt_debug("\n");
|
cybt_debug("\n");
|
||||||
|
|
@ -592,7 +590,10 @@ static void dump_bytes(const uint8_t *bptr, uint32_t len) {
|
||||||
static cybt_result_t cybt_mem_write(uint32_t mem_addr, const uint8_t *p_data, uint32_t data_len) {
|
static cybt_result_t cybt_mem_write(uint32_t mem_addr, const uint8_t *p_data, uint32_t data_len) {
|
||||||
cybt_debug("cybt_mem_write addr 0x%08lx len %ld\n", mem_addr, data_len);
|
cybt_debug("cybt_mem_write addr 0x%08lx len %ld\n", mem_addr, data_len);
|
||||||
do {
|
do {
|
||||||
uint32_t transfer_size = (data_len > MAX_BLOCK_SIZE) ? MAX_BLOCK_SIZE : data_len;
|
uint32_t transfer_size = (data_len > CYW43_BUS_MAX_BLOCK_SIZE) ? CYW43_BUS_MAX_BLOCK_SIZE : data_len;
|
||||||
|
if ((mem_addr & 0xFFF) + transfer_size > 0x1000) {
|
||||||
|
transfer_size = 0x1000 - (mem_addr & 0xFFF);
|
||||||
|
}
|
||||||
cyw43_ll_write_backplane_mem(cyw43_ll, mem_addr, transfer_size, p_data);
|
cyw43_ll_write_backplane_mem(cyw43_ll, mem_addr, transfer_size, p_data);
|
||||||
cybt_debug(" write_mem addr 0x%08lx len %ld\n", mem_addr, transfer_size);
|
cybt_debug(" write_mem addr 0x%08lx len %ld\n", mem_addr, transfer_size);
|
||||||
DUMP_BYTES(p_data, transfer_size);
|
DUMP_BYTES(p_data, transfer_size);
|
||||||
|
|
@ -607,8 +608,10 @@ static cybt_result_t cybt_mem_read(uint32_t mem_addr, uint8_t *p_data, uint32_t
|
||||||
assert(data_len >= 4);
|
assert(data_len >= 4);
|
||||||
cybt_debug("cybt_mem_read addr 0x%08lx len %ld\n", mem_addr, data_len);
|
cybt_debug("cybt_mem_read addr 0x%08lx len %ld\n", mem_addr, data_len);
|
||||||
do {
|
do {
|
||||||
uint32_t transfer_size = (data_len > MAX_BLOCK_SIZE) ? MAX_BLOCK_SIZE : data_len;
|
uint32_t transfer_size = (data_len > CYW43_BUS_MAX_BLOCK_SIZE) ? CYW43_BUS_MAX_BLOCK_SIZE : data_len;
|
||||||
/* this limitation from BT, we need to read twice when spi clock setting is more than 25MHz */
|
if ((mem_addr & 0xFFF) + transfer_size > 0x1000) {
|
||||||
|
transfer_size = 0x1000 - (mem_addr & 0xFFF);
|
||||||
|
}
|
||||||
cyw43_ll_read_backplane_mem(cyw43_ll, mem_addr, transfer_size, p_data);
|
cyw43_ll_read_backplane_mem(cyw43_ll, mem_addr, transfer_size, p_data);
|
||||||
cybt_debug(" read_mem addr 0x%08lx len %ld\n", transfer_size, mem_addr);
|
cybt_debug(" read_mem addr 0x%08lx len %ld\n", transfer_size, mem_addr);
|
||||||
DUMP_BYTES(p_data, transfer_size);
|
DUMP_BYTES(p_data, transfer_size);
|
||||||
|
|
@ -645,7 +648,6 @@ static uint32_t cybt_get_addr(cybt_addr_idx_t addr_idx) {
|
||||||
assert(0);
|
assert(0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -393,11 +393,12 @@ uint32_t read_reg_u32_swap(cyw43_int_t *self, uint32_t fn, uint32_t reg) {
|
||||||
|
|
||||||
static inline uint32_t _cyw43_read_reg(cyw43_int_t *self, uint32_t fn, uint32_t reg, uint size) {
|
static inline uint32_t _cyw43_read_reg(cyw43_int_t *self, uint32_t fn, uint32_t reg, uint size) {
|
||||||
// Padding plus max read size of 32 bits + another 4?
|
// Padding plus max read size of 32 bits + another 4?
|
||||||
static_assert(WHD_BUS_SPI_BACKPLANE_READ_PADD_SIZE % 4 == 0, "");
|
static_assert(CYW43_BACKPLANE_READ_PAD_LEN_BYTES % 4 == 0, "");
|
||||||
uint32_t buf32[WHD_BUS_SPI_BACKPLANE_READ_PADD_SIZE/4 + 1 + 1];
|
int index = (CYW43_BACKPLANE_READ_PAD_LEN_BYTES / 4) + 1 + 1;
|
||||||
|
uint32_t buf32[index];
|
||||||
uint8_t *buf = (uint8_t *)buf32;
|
uint8_t *buf = (uint8_t *)buf32;
|
||||||
const uint32_t padding = (fn == BACKPLANE_FUNCTION) ? WHD_BUS_SPI_BACKPLANE_READ_PADD_SIZE : 0; // Add response delay
|
const uint32_t padding = (fn == BACKPLANE_FUNCTION) ? CYW43_BACKPLANE_READ_PAD_LEN_BYTES : 0; // Add response delay
|
||||||
buf32[0] = make_cmd(false, true, fn, reg, size + padding);
|
buf32[0] = make_cmd(false, true, fn, reg, size);
|
||||||
|
|
||||||
if (fn == BACKPLANE_FUNCTION) {
|
if (fn == BACKPLANE_FUNCTION) {
|
||||||
logic_debug_set(pin_BACKPLANE_READ, 1);
|
logic_debug_set(pin_BACKPLANE_READ, 1);
|
||||||
|
|
@ -410,7 +411,7 @@ static inline uint32_t _cyw43_read_reg(cyw43_int_t *self, uint32_t fn, uint32_t
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
uint32_t result = buf32[padding > 0 ? 2 : 1];
|
uint32_t result = buf32[padding > 0 ? index - 1 : 1];
|
||||||
CYW43_VDEBUG("cyw43_read_reg_u%d %s 0x%lx=0x%lx\n", size * 8, func_name(fn), reg, result);
|
CYW43_VDEBUG("cyw43_read_reg_u%d %s 0x%lx=0x%lx\n", size * 8, func_name(fn), reg, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
@ -476,21 +477,21 @@ int cyw43_write_reg_u8(cyw43_int_t *self, uint32_t fn, uint32_t reg, uint32_t va
|
||||||
return _cyw43_write_reg(self, fn, reg, val, 1);
|
return _cyw43_write_reg(self, fn, reg, val, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if MAX_BLOCK_SIZE > 0x7f8
|
#if CYW43_BUS_MAX_BLOCK_SIZE > 0x7f8
|
||||||
#error Block size is wrong for SPI
|
#error Block size is wrong for SPI
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int cyw43_read_bytes(cyw43_int_t *self, uint32_t fn, uint32_t addr, size_t len, uint8_t *buf) {
|
int cyw43_read_bytes(cyw43_int_t *self, uint32_t fn, uint32_t addr, size_t len, uint8_t *buf) {
|
||||||
assert(fn != BACKPLANE_FUNCTION || (len <= 64 && (addr + len) <= 0x8000));
|
assert(fn != BACKPLANE_FUNCTION || (len <= CYW43_BUS_MAX_BLOCK_SIZE));
|
||||||
const uint32_t padding = (fn == BACKPLANE_FUNCTION) ? 4 : 0; // Add response delay
|
const uint32_t padding = (fn == BACKPLANE_FUNCTION) ? CYW43_BACKPLANE_READ_PAD_LEN_BYTES : 0; // Add response delay
|
||||||
size_t aligned_len = (len + 3) & ~3;
|
size_t aligned_len = (len + 3) & ~3;
|
||||||
assert(aligned_len > 0 && aligned_len <= 0x7f8);
|
assert(aligned_len > 0 && aligned_len <= 0x7f8);
|
||||||
assert(buf == self->spid_buf || buf < self->spid_buf || buf >= (self->spid_buf + sizeof(self->spid_buf)));
|
assert(buf == self->spid_buf || buf < self->spid_buf || buf >= (self->spid_buf + sizeof(self->spid_buf)));
|
||||||
self->spi_header[padding > 0 ? 0 : 1] = make_cmd(false, true, fn, addr, len + padding);
|
self->spi_header[padding > 0 ? 0 : (CYW43_BACKPLANE_READ_PAD_LEN_BYTES / 4)] = make_cmd(false, true, fn, addr, len);
|
||||||
if (fn == WLAN_FUNCTION) {
|
if (fn == WLAN_FUNCTION) {
|
||||||
logic_debug_set(pin_WIFI_RX, 1);
|
logic_debug_set(pin_WIFI_RX, 1);
|
||||||
}
|
}
|
||||||
int ret = cyw43_spi_transfer(self, NULL, 4, (uint8_t *)&self->spi_header[padding > 0 ? 0 : 1], aligned_len + 4 + padding);
|
int ret = cyw43_spi_transfer(self, NULL, 4, (uint8_t *)&self->spi_header[padding > 0 ? 0 : (CYW43_BACKPLANE_READ_PAD_LEN_BYTES / 4)], aligned_len + 4 + padding);
|
||||||
if (fn == WLAN_FUNCTION) {
|
if (fn == WLAN_FUNCTION) {
|
||||||
logic_debug_set(pin_WIFI_RX, 0);
|
logic_debug_set(pin_WIFI_RX, 0);
|
||||||
}
|
}
|
||||||
|
|
@ -508,8 +509,8 @@ int cyw43_read_bytes(cyw43_int_t *self, uint32_t fn, uint32_t addr, size_t len,
|
||||||
// Note, uses spid_buf if src isn't using it already
|
// Note, uses spid_buf if src isn't using it already
|
||||||
// Apart from firmware download this appears to only be used for wlan functions?
|
// Apart from firmware download this appears to only be used for wlan functions?
|
||||||
int cyw43_write_bytes(cyw43_int_t *self, uint32_t fn, uint32_t addr, size_t len, const uint8_t *src) {
|
int cyw43_write_bytes(cyw43_int_t *self, uint32_t fn, uint32_t addr, size_t len, const uint8_t *src) {
|
||||||
assert(fn != BACKPLANE_FUNCTION || (len <= 64 && (addr + len) <= 0x8000));
|
assert(fn != BACKPLANE_FUNCTION || (len <= CYW43_BUS_MAX_BLOCK_SIZE));
|
||||||
size_t aligned_len = (len + 3) & ~3u;
|
const size_t aligned_len = (len + 3) & ~3u;
|
||||||
assert(aligned_len > 0 && aligned_len <= 0x7f8);
|
assert(aligned_len > 0 && aligned_len <= 0x7f8);
|
||||||
if (fn == WLAN_FUNCTION) {
|
if (fn == WLAN_FUNCTION) {
|
||||||
// Wait for FIFO to be ready to accept data
|
// Wait for FIFO to be ready to accept data
|
||||||
|
|
@ -529,17 +530,17 @@ int cyw43_write_bytes(cyw43_int_t *self, uint32_t fn, uint32_t addr, size_t len,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (src == self->spid_buf) { // avoid a copy in the usual case just to add the header
|
if (src == self->spid_buf) { // avoid a copy in the usual case just to add the header
|
||||||
self->spi_header[1] = make_cmd(true, true, fn, addr, len);
|
self->spi_header[(CYW43_BACKPLANE_READ_PAD_LEN_BYTES / 4)] = make_cmd(true, true, fn, addr, len);
|
||||||
logic_debug_set(pin_WIFI_TX, 1);
|
logic_debug_set(pin_WIFI_TX, 1);
|
||||||
int res = cyw43_spi_transfer(self, (uint8_t *)&self->spi_header[1], aligned_len + 4, NULL, 0);
|
int res = cyw43_spi_transfer(self, (uint8_t *)&self->spi_header[(CYW43_BACKPLANE_READ_PAD_LEN_BYTES / 4)], aligned_len + 4, NULL, 0);
|
||||||
logic_debug_set(pin_WIFI_TX, 0);
|
logic_debug_set(pin_WIFI_TX, 0);
|
||||||
return res;
|
return res;
|
||||||
} else {
|
} else {
|
||||||
// todo: would be nice to get rid of this. Only used for firmware download?
|
// todo: would be nice to get rid of this. Only used for firmware download?
|
||||||
assert(src < self->spid_buf || src >= (self->spid_buf + sizeof(self->spid_buf)));
|
assert(src < self->spid_buf || src >= (self->spid_buf + sizeof(self->spid_buf)));
|
||||||
self->spi_header[1] = make_cmd(true, true, fn, addr, len);
|
self->spi_header[(CYW43_BACKPLANE_READ_PAD_LEN_BYTES / 4)] = make_cmd(true, true, fn, addr, len);
|
||||||
memcpy(self->spid_buf, src, len);
|
memcpy(self->spid_buf, src, len);
|
||||||
return cyw43_spi_transfer(self, (uint8_t *)&self->spi_header[1], aligned_len + 4, NULL, 0);
|
return cyw43_spi_transfer(self, (uint8_t *)&self->spi_header[(CYW43_BACKPLANE_READ_PAD_LEN_BYTES / 4)], aligned_len + 4, NULL, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue