different bluetooth firmware upload process
This commit is contained in:
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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.
|
||||
|
Reference in New Issue
Block a user