different bluetooth firmware upload process

This commit is contained in:
Brandon Ros
2023-08-21 14:28:39 -04:00
parent b6b20eda8c
commit 71a3d09419
8 changed files with 383 additions and 96 deletions

View File

@ -5,83 +5,17 @@ use crate::bus::Bus;
use crate::consts::*;
use crate::{SpiBusCyw43, CHIP};
#[derive(Debug)]
pub(crate) struct CybtFwCb<'a> {
pub p_fw_mem_start: &'a [u8],
pub fw_len: u32,
pub p_next_line_start: &'a [u8],
}
#[derive(Debug)]
pub(crate) struct HexFileData<'a> {
pub addr_mode: i32,
pub hi_addr: u16,
pub dest_addr: u32,
pub p_ds: &'a mut [u8],
}
pub(crate) fn is_aligned(a: u32, x: u32) -> bool {
fn is_aligned(a: u32, x: u32) -> bool {
(a & (x - 1)) == 0
}
pub(crate) fn round_down(x: u32, a: u32) -> u32 {
fn round_down(x: u32, a: u32) -> u32 {
x & !(a - 1)
}
pub(crate) fn cybt_fw_get_data(p_btfw_cb: &mut CybtFwCb, hfd: &mut HexFileData) -> u32 {
let mut abs_base_addr32 = 0;
loop {
let num_bytes = p_btfw_cb.p_next_line_start[0];
p_btfw_cb.p_next_line_start = &p_btfw_cb.p_next_line_start[1..];
let addr = (p_btfw_cb.p_next_line_start[0] as u16) << 8 | p_btfw_cb.p_next_line_start[1] as u16;
p_btfw_cb.p_next_line_start = &p_btfw_cb.p_next_line_start[2..];
let line_type = p_btfw_cb.p_next_line_start[0];
p_btfw_cb.p_next_line_start = &p_btfw_cb.p_next_line_start[1..];
if num_bytes == 0 {
break;
}
hfd.p_ds[..num_bytes as usize].copy_from_slice(&p_btfw_cb.p_next_line_start[..num_bytes as usize]);
p_btfw_cb.p_next_line_start = &p_btfw_cb.p_next_line_start[num_bytes as usize..];
match line_type {
BTFW_HEX_LINE_TYPE_EXTENDED_ADDRESS => {
hfd.hi_addr = (hfd.p_ds[0] as u16) << 8 | hfd.p_ds[1] as u16;
hfd.addr_mode = BTFW_ADDR_MODE_EXTENDED;
}
BTFW_HEX_LINE_TYPE_EXTENDED_SEGMENT_ADDRESS => {
hfd.hi_addr = (hfd.p_ds[0] as u16) << 8 | hfd.p_ds[1] as u16;
hfd.addr_mode = BTFW_ADDR_MODE_SEGMENT;
}
BTFW_HEX_LINE_TYPE_ABSOLUTE_32BIT_ADDRESS => {
abs_base_addr32 = (hfd.p_ds[0] as u32) << 24
| (hfd.p_ds[1] as u32) << 16
| (hfd.p_ds[2] as u32) << 8
| hfd.p_ds[3] as u32;
hfd.addr_mode = BTFW_ADDR_MODE_LINEAR32;
}
BTFW_HEX_LINE_TYPE_DATA => {
hfd.dest_addr = addr as u32;
match hfd.addr_mode {
BTFW_ADDR_MODE_EXTENDED => hfd.dest_addr += (hfd.hi_addr as u32) << 16,
BTFW_ADDR_MODE_SEGMENT => hfd.dest_addr += (hfd.hi_addr as u32) << 4,
BTFW_ADDR_MODE_LINEAR32 => hfd.dest_addr += abs_base_addr32,
_ => {}
}
return num_bytes as u32;
}
_ => {}
}
}
0
}
pub(crate) async fn upload_bluetooth_firmware<PWR: OutputPin, SPI: SpiBusCyw43>(
bus: &mut Bus<PWR, SPI>,
firmware_offsets: &[(u32, usize)],
firmware: &[u8],
) {
// read version
@ -91,26 +25,15 @@ pub(crate) async fn upload_bluetooth_firmware<PWR: OutputPin, SPI: SpiBusCyw43>(
let firmware = &firmware[version_length as usize + 2..];
// buffer
let mut data_buffer: [u8; 0x100] = [0; 0x100];
let mut aligned_data_buffer: [u8; 0x100] = [0; 0x100];
// structs
let mut btfw_cb = CybtFwCb {
p_fw_mem_start: firmware,
fw_len: firmware.len() as u32,
p_next_line_start: firmware,
};
let mut hfd = HexFileData {
addr_mode: BTFW_ADDR_MODE_UNKNOWN,
hi_addr: 0,
dest_addr: 0,
p_ds: &mut data_buffer,
};
loop {
let mut aligned_data_buffer: [u8; 0x100] = [0; 0x100];
let num_fw_bytes = cybt_fw_get_data(&mut btfw_cb, &mut hfd);
if num_fw_bytes == 0 {
break;
}
let fw_bytes = &hfd.p_ds[0..num_fw_bytes as usize];
let mut dest_start_addr = hfd.dest_addr + CHIP.bluetooth_base_address;
let mut pointer = 0;
for (index, &(dest_addr, num_fw_bytes)) in firmware_offsets.iter().enumerate() {
let fw_bytes = &firmware[(pointer)..(pointer + num_fw_bytes)];
assert!(fw_bytes.len() == num_fw_bytes);
pointer += num_fw_bytes;
debug!("index = {}/{} dest_addr = {:08x} num_fw_bytes = {} fw_bytes = {:02x}", index, firmware_offsets.len(), dest_addr, num_fw_bytes, fw_bytes);
let mut dest_start_addr = dest_addr;
let mut aligned_data_buffer_index: usize = 0;
// pad start
if !is_aligned(dest_start_addr, 4) {
@ -118,6 +41,7 @@ pub(crate) async fn upload_bluetooth_firmware<PWR: OutputPin, SPI: SpiBusCyw43>(
let padded_dest_start_addr = round_down(dest_start_addr, 4);
let mut memory_value_bytes = [0; 4];
bus.bp_read(padded_dest_start_addr, &mut memory_value_bytes).await;
debug!("pad start padded_dest_start_addr = {:08x} memory_value_bytes = {:02x}", padded_dest_start_addr, memory_value_bytes);
// Copy the previous memory value's bytes to the start
for i in 0..num_pad_bytes as usize {
aligned_data_buffer[aligned_data_buffer_index] = memory_value_bytes[i];
@ -144,6 +68,7 @@ pub(crate) async fn upload_bluetooth_firmware<PWR: OutputPin, SPI: SpiBusCyw43>(
let padded_dest_end_addr = round_down(dest_end_addr, 4);
let mut memory_value_bytes = [0; 4];
bus.bp_read(padded_dest_end_addr, &mut memory_value_bytes).await;
debug!("pad end padded_dest_end_addr = {:08x} memory_value_bytes = {:02x}", padded_dest_end_addr, memory_value_bytes);
// Append the necessary memory bytes to pad the end of aligned_data_buffer
for i in offset..4 {
aligned_data_buffer[aligned_data_buffer_index] = memory_value_bytes[i as usize];
@ -177,7 +102,7 @@ pub(crate) async fn wait_bt_ready<PWR: OutputPin, SPI: SpiBusCyw43>(bus: &mut Bu
success = true;
break;
}
Timer::after(Duration::from_millis(1)).await;
Timer::after(Duration::from_millis(100)).await;
}
assert!(success == true);
}
@ -203,6 +128,7 @@ pub(crate) async fn bt_set_host_ready<PWR: OutputPin, SPI: SpiBusCyw43>(bus: &mu
bus.bp_write32(HOST_CTRL_REG_ADDR, new_val).await;
}
// TODO: use this
pub(crate) async fn bt_set_awake<PWR: OutputPin, SPI: SpiBusCyw43>(bus: &mut Bus<PWR, SPI>) {
debug!("bt_set_awake");
let old_val = bus.bp_read32(HOST_CTRL_REG_ADDR).await;
@ -219,6 +145,7 @@ pub(crate) async fn bt_toggle_intr<PWR: OutputPin, SPI: SpiBusCyw43>(bus: &mut B
bus.bp_write32(HOST_CTRL_REG_ADDR, new_val).await;
}
// TODO: use this
pub(crate) async fn bt_set_intr<PWR: OutputPin, SPI: SpiBusCyw43>(bus: &mut Bus<PWR, SPI>) {
debug!("bt_set_intr");
let old_val = bus.bp_read32(HOST_CTRL_REG_ADDR).await;
@ -226,10 +153,10 @@ pub(crate) async fn bt_set_intr<PWR: OutputPin, SPI: SpiBusCyw43>(bus: &mut Bus<
bus.bp_write32(HOST_CTRL_REG_ADDR, new_val).await;
}
pub(crate) async fn init_bluetooth<PWR: OutputPin, SPI: SpiBusCyw43>(bus: &mut Bus<PWR, SPI>, firmware: &[u8]) {
pub(crate) async fn init_bluetooth<PWR: OutputPin, SPI: SpiBusCyw43>(bus: &mut Bus<PWR, SPI>, firmware_offsets: &[(u32, usize)], firmware: &[u8]) {
bus.bp_write32(CHIP.bluetooth_base_address + BT2WLAN_PWRUP_ADDR, BT2WLAN_PWRUP_WAKE)
.await;
upload_bluetooth_firmware(bus, firmware).await;
upload_bluetooth_firmware(bus, firmware_offsets, firmware).await;
wait_bt_ready(bus).await;
// TODO: cybt_init_buffer();
wait_bt_awake(bus).await;

View File

@ -214,6 +214,7 @@ pub async fn new<'a, PWR, SPI>(
pwr: PWR,
spi: SPI,
firmware: &[u8],
bluetooth_firmware_offsets: &[(u32, usize)],
bluetooth_firmware: &[u8],
) -> (NetDriver<'a>, Control<'a>, Runner<'a, PWR, SPI>)
where
@ -225,7 +226,7 @@ where
let mut runner = Runner::new(ch_runner, Bus::new(pwr, spi), &state.ioctl_state, &state.events);
runner.init(firmware, bluetooth_firmware).await;
runner.init(firmware, bluetooth_firmware_offsets, bluetooth_firmware).await;
(
device,

View File

@ -73,7 +73,7 @@ where
}
}
pub(crate) async fn init(&mut self, firmware: &[u8], bluetooth_firmware: &[u8]) {
pub(crate) async fn init(&mut self, firmware: &[u8], bluetooth_firmware_offsets: &[(u32, usize)], bluetooth_firmware: &[u8]) {
self.bus.init().await;
// Init ALP (Active Low Power) clock
@ -117,7 +117,7 @@ where
self.bus.bp_write(ram_addr, firmware).await;
debug!("loading bluetooth fw");
bluetooth::init_bluetooth(&mut self.bus, bluetooth_firmware).await;
bluetooth::init_bluetooth(&mut self.bus, bluetooth_firmware_offsets, bluetooth_firmware).await;
debug!("loading nvram");
// Round up to 4 bytes.