bluetooth blinky example
This commit is contained in:
		| @@ -177,7 +177,10 @@ where | |||||||
|         let read_bits = read.len() * 32 + 32 - 1; |         let read_bits = read.len() * 32 + 32 - 1; | ||||||
|  |  | ||||||
|         #[cfg(feature = "defmt")] |         #[cfg(feature = "defmt")] | ||||||
|         defmt::trace!("write={} read={}", write_bits, read_bits); |         defmt::trace!("cmd_read write={} read={}", write_bits, read_bits); | ||||||
|  |  | ||||||
|  |         #[cfg(feature = "defmt")] | ||||||
|  |         defmt::trace!("cmd_read cmd = {:02x} len = {}", cmd, read.len()); | ||||||
|  |  | ||||||
|         unsafe { |         unsafe { | ||||||
|             pio_instr_util::set_y(&mut self.sm, read_bits as u32); |             pio_instr_util::set_y(&mut self.sm, read_bits as u32); | ||||||
| @@ -197,6 +200,10 @@ where | |||||||
|             .rx() |             .rx() | ||||||
|             .dma_pull(self.dma.reborrow(), slice::from_mut(&mut status)) |             .dma_pull(self.dma.reborrow(), slice::from_mut(&mut status)) | ||||||
|             .await; |             .await; | ||||||
|  |  | ||||||
|  |         #[cfg(feature = "defmt")] | ||||||
|  |         defmt::trace!("cmd_read cmd = {:02x} len = {} read = {:08x}", cmd, read.len(), read); | ||||||
|  |  | ||||||
|         status |         status | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -21,21 +21,20 @@ pub(crate) async fn upload_bluetooth_firmware<PWR: OutputPin, SPI: SpiBusCyw43>( | |||||||
|     // buffer |     // buffer | ||||||
|     let mut aligned_data_buffer: [u8; 0x100] = [0; 0x100]; |     let mut aligned_data_buffer: [u8; 0x100] = [0; 0x100]; | ||||||
|     // structs |     // structs | ||||||
|     let mut pointer = 0; |     let mut fw_bytes_pointer = 0; | ||||||
|     for (index, &(dest_addr, num_fw_bytes)) in firmware_offsets.iter().enumerate() { |     for (index, &(dest_addr, num_fw_bytes)) in firmware_offsets.iter().enumerate() { | ||||||
|         let fw_bytes = &firmware[(pointer)..(pointer + num_fw_bytes)]; |         let fw_bytes = &firmware[(fw_bytes_pointer)..(fw_bytes_pointer + num_fw_bytes)]; | ||||||
|         assert!(fw_bytes.len() == num_fw_bytes); |         assert!(fw_bytes.len() == 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); |         debug!("index = {}/{} dest_addr = {:08x} num_fw_bytes = {} fw_bytes_pointer = {} fw_bytes = {:02x}", index, firmware_offsets.len(), dest_addr, num_fw_bytes, fw_bytes_pointer, fw_bytes); | ||||||
|         //debug!("index = {}/{} dest_addr = {:08x} num_fw_bytes = {} pointer = {}", index, firmware_offsets.len(), dest_addr, num_fw_bytes, pointer); |  | ||||||
|         let mut dest_start_addr = dest_addr; |         let mut dest_start_addr = dest_addr; | ||||||
|         let mut aligned_data_buffer_index: usize = 0; |         let mut aligned_data_buffer_index: usize = 0; | ||||||
|         // pad start |         // pad start | ||||||
|         if !is_aligned(dest_start_addr, 4) { |         if !is_aligned(dest_start_addr, 4) { | ||||||
|             let num_pad_bytes = dest_start_addr % 4; |             let num_pad_bytes = dest_start_addr % 4; | ||||||
|             let padded_dest_start_addr = round_down(dest_start_addr, 4); |             let padded_dest_start_addr = round_down(dest_start_addr, 4); | ||||||
|             let mut memory_value_bytes = [0; 4]; |             let memory_value = bus.bp_read32(padded_dest_start_addr).await; | ||||||
|             bus.bp_read(padded_dest_start_addr, &mut memory_value_bytes).await; |             let memory_value_bytes = memory_value.to_le_bytes(); // TODO: le or be | ||||||
|             //debug!("pad start padded_dest_start_addr = {:08x} memory_value_bytes = {:02x}", padded_dest_start_addr, memory_value_bytes); |             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 |             // Copy the previous memory value's bytes to the start | ||||||
|             for i in 0..num_pad_bytes as usize { |             for i in 0..num_pad_bytes as usize { | ||||||
|                 aligned_data_buffer[aligned_data_buffer_index] = memory_value_bytes[i]; |                 aligned_data_buffer[aligned_data_buffer_index] = memory_value_bytes[i]; | ||||||
| @@ -60,9 +59,9 @@ pub(crate) async fn upload_bluetooth_firmware<PWR: OutputPin, SPI: SpiBusCyw43>( | |||||||
|             let offset = dest_end_addr % 4; |             let offset = dest_end_addr % 4; | ||||||
|             let num_pad_bytes_end = 4 - offset; |             let num_pad_bytes_end = 4 - offset; | ||||||
|             let padded_dest_end_addr = round_down(dest_end_addr, 4); |             let padded_dest_end_addr = round_down(dest_end_addr, 4); | ||||||
|             let mut memory_value_bytes = [0; 4]; |             let memory_value = bus.bp_read32(padded_dest_end_addr).await; | ||||||
|             bus.bp_read(padded_dest_end_addr, &mut memory_value_bytes).await; |             let memory_value_bytes = memory_value.to_le_bytes(); // TODO: le or be | ||||||
|             //debug!("pad end padded_dest_end_addr = {:08x} memory_value_bytes = {:02x}", padded_dest_end_addr, memory_value_bytes); |             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 |             // Append the necessary memory bytes to pad the end of aligned_data_buffer | ||||||
|             for i in offset..4 { |             for i in offset..4 { | ||||||
|                 aligned_data_buffer[aligned_data_buffer_index] = memory_value_bytes[i as usize]; |                 aligned_data_buffer[aligned_data_buffer_index] = memory_value_bytes[i as usize]; | ||||||
| @@ -77,9 +76,16 @@ pub(crate) async fn upload_bluetooth_firmware<PWR: OutputPin, SPI: SpiBusCyw43>( | |||||||
|         assert!(dest_start_addr % 4 == 0); |         assert!(dest_start_addr % 4 == 0); | ||||||
|         assert!(dest_end_addr % 4 == 0); |         assert!(dest_end_addr % 4 == 0); | ||||||
|         assert!(aligned_data_buffer_index % 4 == 0); |         assert!(aligned_data_buffer_index % 4 == 0); | ||||||
|         bus.bp_write(dest_start_addr, buffer_to_write).await; |         // write in 0x40 chunks TODO: is this needed | ||||||
|         // increment pointer |         let chunk_size = 0x40; | ||||||
|         pointer += num_fw_bytes; |         for (i, chunk) in buffer_to_write.chunks(chunk_size).enumerate() { | ||||||
|  |             let offset = i * chunk_size; | ||||||
|  |             bus.bp_write(dest_start_addr + (offset as u32), chunk).await; | ||||||
|  |         } | ||||||
|  |         // increment fw_bytes_pointer | ||||||
|  |         fw_bytes_pointer += num_fw_bytes; | ||||||
|  |         // sleep TODO: is this needed | ||||||
|  |         Timer::after(Duration::from_millis(1)).await; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -90,30 +96,29 @@ pub(crate) async fn wait_bt_ready<PWR: OutputPin, SPI: SpiBusCyw43>(bus: &mut Bu | |||||||
|         let val = bus.bp_read32(BT_CTRL_REG_ADDR).await; |         let val = bus.bp_read32(BT_CTRL_REG_ADDR).await; | ||||||
|         // TODO: do we need to swap endianness on this read? |         // TODO: do we need to swap endianness on this read? | ||||||
|         debug!("BT_CTRL_REG_ADDR = {:08x}", val); |         debug!("BT_CTRL_REG_ADDR = {:08x}", val); | ||||||
|         /*if val & BTSDIO_REG_FW_RDY_BITMASK != 0 { |         if val & BTSDIO_REG_FW_RDY_BITMASK != 0 { | ||||||
|             break; |  | ||||||
|         }*/ |  | ||||||
|         // TODO: should be 00000000 until it is 0x01000100 |  | ||||||
|         if val == 0x01000100 { |  | ||||||
|             success = true; |             success = true; | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|         Timer::after(Duration::from_millis(100)).await; |         Timer::after(Duration::from_millis(1)).await; | ||||||
|     } |     } | ||||||
|     assert!(success == true); |     assert!(success == true); | ||||||
| } | } | ||||||
|  |  | ||||||
| pub(crate) async fn wait_bt_awake<PWR: OutputPin, SPI: SpiBusCyw43>(bus: &mut Bus<PWR, SPI>) { | pub(crate) async fn wait_bt_awake<PWR: OutputPin, SPI: SpiBusCyw43>(bus: &mut Bus<PWR, SPI>) { | ||||||
|    debug!("wait_bt_awake"); |    debug!("wait_bt_awake"); | ||||||
|     loop { |    let mut success = false; | ||||||
|  |     for _ in 0..300 { | ||||||
|         let val = bus.bp_read32(BT_CTRL_REG_ADDR).await; |         let val = bus.bp_read32(BT_CTRL_REG_ADDR).await; | ||||||
|         // TODO: do we need to swap endianness on this read? |         // TODO: do we need to swap endianness on this read? | ||||||
|         debug!("BT_CTRL_REG_ADDR = {:08x}", val); |         debug!("BT_CTRL_REG_ADDR = {:08x}", val); | ||||||
|         if val & BTSDIO_REG_BT_AWAKE_BITMASK != 0 { |         if val & BTSDIO_REG_BT_AWAKE_BITMASK != 0 { | ||||||
|  |             success = true; | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|         Timer::after(Duration::from_millis(100)).await; |         Timer::after(Duration::from_millis(1)).await; | ||||||
|     } |     } | ||||||
|  |     assert!(success == true); | ||||||
| } | } | ||||||
|  |  | ||||||
| pub(crate) async fn bt_set_host_ready<PWR: OutputPin, SPI: SpiBusCyw43>(bus: &mut Bus<PWR, SPI>) { | pub(crate) async fn bt_set_host_ready<PWR: OutputPin, SPI: SpiBusCyw43>(bus: &mut Bus<PWR, SPI>) { | ||||||
| @@ -150,8 +155,12 @@ pub(crate) async fn bt_set_intr<PWR: OutputPin, SPI: SpiBusCyw43>(bus: &mut Bus< | |||||||
| } | } | ||||||
|  |  | ||||||
| pub(crate) async fn init_bluetooth<PWR: OutputPin, SPI: SpiBusCyw43>(bus: &mut Bus<PWR, SPI>, firmware_offsets: &[(u32, usize)], firmware: &[u8]) { | pub(crate) async fn init_bluetooth<PWR: OutputPin, SPI: SpiBusCyw43>(bus: &mut Bus<PWR, SPI>, firmware_offsets: &[(u32, usize)], firmware: &[u8]) { | ||||||
|  |     Timer::after(Duration::from_millis(100)).await; | ||||||
|  |     debug!("init_bluetooth"); | ||||||
|  |     Timer::after(Duration::from_millis(100)).await; | ||||||
|     bus.bp_write32(CHIP.bluetooth_base_address + BT2WLAN_PWRUP_ADDR, BT2WLAN_PWRUP_WAKE) |     bus.bp_write32(CHIP.bluetooth_base_address + BT2WLAN_PWRUP_ADDR, BT2WLAN_PWRUP_WAKE) | ||||||
|         .await; |         .await; | ||||||
|  |     Timer::after(Duration::from_millis(2)).await; | ||||||
|     upload_bluetooth_firmware(bus, firmware_offsets, firmware).await; |     upload_bluetooth_firmware(bus, firmware_offsets, firmware).await; | ||||||
|     wait_bt_ready(bus).await; |     wait_bt_ready(bus).await; | ||||||
|     // TODO: cybt_init_buffer(); |     // TODO: cybt_init_buffer(); | ||||||
|   | |||||||
| @@ -50,34 +50,35 @@ where | |||||||
|  |  | ||||||
|     pub async fn init(&mut self) { |     pub async fn init(&mut self) { | ||||||
|         // Reset |         // Reset | ||||||
|         debug!("WL_REG off/on"); |         defmt::debug!("WL_REG off/on"); | ||||||
|         self.pwr.set_low().unwrap(); |         self.pwr.set_low().unwrap(); | ||||||
|         Timer::after(Duration::from_millis(20)).await; |         Timer::after(Duration::from_millis(20)).await; | ||||||
|         self.pwr.set_high().unwrap(); |         self.pwr.set_high().unwrap(); | ||||||
|         Timer::after(Duration::from_millis(250)).await; |         Timer::after(Duration::from_millis(250)).await; | ||||||
|  |  | ||||||
|         debug!("read REG_BUS_TEST_RO"); |         defmt::debug!("read REG_BUS_TEST_RO"); | ||||||
|         while self |         while self | ||||||
|             .read32_swapped(REG_BUS_TEST_RO) |             .read32_swapped(FUNC_BUS, REG_BUS_TEST_RO) | ||||||
|             .inspect(|v| trace!("{:#x}", v)) |             .inspect(|v| trace!("{:#x}", v)) | ||||||
|             .await |             .await | ||||||
|             != FEEDBEAD |             != FEEDBEAD | ||||||
|         {} |         {} | ||||||
|  |  | ||||||
|         debug!("write REG_BUS_TEST_RW"); |         defmt::debug!("write REG_BUS_TEST_RW"); | ||||||
|         self.write32_swapped(REG_BUS_TEST_RW, TEST_PATTERN).await; |         self.write32_swapped(FUNC_BUS, REG_BUS_TEST_RW, TEST_PATTERN).await; | ||||||
|         let val = self.read32_swapped(REG_BUS_TEST_RW).await; |         let val = self.read32_swapped(FUNC_BUS, REG_BUS_TEST_RW).await; | ||||||
|         trace!("{:#x}", val); |         trace!("{:#x}", val); | ||||||
|         assert_eq!(val, TEST_PATTERN); |         assert_eq!(val, TEST_PATTERN); | ||||||
|  |  | ||||||
|         debug!("read REG_BUS_CTRL"); |         defmt::debug!("read REG_BUS_CTRL"); | ||||||
|         let val = self.read32_swapped(REG_BUS_CTRL).await; |         let val = self.read32_swapped(FUNC_BUS, REG_BUS_CTRL).await; | ||||||
|         trace!("{:#010b}", (val & 0xff)); |         trace!("{:#010b}", (val & 0xff)); | ||||||
|  |  | ||||||
|         // 32-bit word length, little endian (which is the default endianess). |         // 32-bit word length, little endian (which is the default endianess). | ||||||
|         // TODO: C library is uint32_t val = WORD_LENGTH_32 | HIGH_SPEED_MODE| ENDIAN_BIG | INTERRUPT_POLARITY_HIGH | WAKE_UP | 0x4 << (8 * SPI_RESPONSE_DELAY) | INTR_WITH_STATUS << (8 * SPI_STATUS_ENABLE); |         // TODO: C library is uint32_t val = WORD_LENGTH_32 | HIGH_SPEED_MODE| ENDIAN_BIG | INTERRUPT_POLARITY_HIGH | WAKE_UP | 0x4 << (8 * SPI_RESPONSE_DELAY) | INTR_WITH_STATUS << (8 * SPI_STATUS_ENABLE); | ||||||
|         debug!("write REG_BUS_CTRL"); |         defmt::debug!("write REG_BUS_CTRL"); | ||||||
|         self.write32_swapped( |         self.write32_swapped( | ||||||
|  |             FUNC_BUS, | ||||||
|             REG_BUS_CTRL, |             REG_BUS_CTRL, | ||||||
|             WORD_LENGTH_32 |             WORD_LENGTH_32 | ||||||
|                 | HIGH_SPEED |                 | HIGH_SPEED | ||||||
| @@ -88,30 +89,29 @@ where | |||||||
|         ) |         ) | ||||||
|         .await; |         .await; | ||||||
|  |  | ||||||
|         debug!("read REG_BUS_CTRL"); |         defmt::debug!("read REG_BUS_CTRL"); | ||||||
|         let val = self.read8(FUNC_BUS, REG_BUS_CTRL).await; |         let val = self.read8(FUNC_BUS, REG_BUS_CTRL).await; | ||||||
|         trace!("{:#b}", val); |         trace!("{:#b}", val); | ||||||
|  |  | ||||||
|         // TODO: C doesn't do this? i doubt it messes anything up |         // TODO: C doesn't do this? i doubt it messes anything up | ||||||
|         debug!("read REG_BUS_TEST_RO"); |         defmt::debug!("read REG_BUS_TEST_RO"); | ||||||
|         let val = self.read32(FUNC_BUS, REG_BUS_TEST_RO).await; |         let val = self.read32(FUNC_BUS, REG_BUS_TEST_RO).await; | ||||||
|         trace!("{:#x}", val); |         trace!("{:#x}", val); | ||||||
|         assert_eq!(val, FEEDBEAD); |         assert_eq!(val, FEEDBEAD); | ||||||
|  |  | ||||||
|         // TODO: C doesn't do this? i doubt it messes anything up |         // TODO: C doesn't do this? i doubt it messes anything up | ||||||
|         debug!("read REG_BUS_TEST_RW"); |         defmt::debug!("read REG_BUS_TEST_RW"); | ||||||
|         let val = self.read32(FUNC_BUS, REG_BUS_TEST_RW).await; |         let val = self.read32(FUNC_BUS, REG_BUS_TEST_RW).await; | ||||||
|         trace!("{:#x}", val); |         trace!("{:#x}", val); | ||||||
|         assert_eq!(val, TEST_PATTERN); |         assert_eq!(val, TEST_PATTERN); | ||||||
|  |  | ||||||
|         // TODO: setting this causes total failure (watermark read test fails) |         defmt::debug!("write SPI_RESP_DELAY_F1 CYW43_BACKPLANE_READ_PAD_LEN_BYTES"); | ||||||
|         debug!("write SPI_RESP_DELAY_F1 CYW43_BACKPLANE_READ_PAD_LEN_BYTES"); |  | ||||||
|         self.write8(FUNC_BUS, SPI_RESP_DELAY_F1, WHD_BUS_SPI_BACKPLANE_READ_PADD_SIZE) |         self.write8(FUNC_BUS, SPI_RESP_DELAY_F1, WHD_BUS_SPI_BACKPLANE_READ_PADD_SIZE) | ||||||
|             .await; |             .await; | ||||||
|  |  | ||||||
|         // TODO: Make sure error interrupt bits are clear? |         // TODO: Make sure error interrupt bits are clear? | ||||||
|         // cyw43_write_reg_u8(self, BUS_FUNCTION, SPI_INTERRUPT_REGISTER, DATA_UNAVAILABLE | COMMAND_ERROR | DATA_ERROR | F1_OVERFLOW) != 0) |         // cyw43_write_reg_u8(self, BUS_FUNCTION, SPI_INTERRUPT_REGISTER, DATA_UNAVAILABLE | COMMAND_ERROR | DATA_ERROR | F1_OVERFLOW) != 0) | ||||||
|         debug!("Make sure error interrupt bits are clear"); |         defmt::debug!("Make sure error interrupt bits are clear"); | ||||||
|         self.write8( |         self.write8( | ||||||
|             FUNC_BUS, |             FUNC_BUS, | ||||||
|             REG_BUS_INTERRUPT, |             REG_BUS_INTERRUPT, | ||||||
| @@ -121,7 +121,7 @@ where | |||||||
|  |  | ||||||
|         // Enable a selection of interrupts |         // Enable a selection of interrupts | ||||||
|         // TODO: why not all of these F2_F3_FIFO_RD_UNDERFLOW | F2_F3_FIFO_WR_OVERFLOW | COMMAND_ERROR | DATA_ERROR | F2_PACKET_AVAILABLE | F1_OVERFLOW | F1_INTR |         // TODO: why not all of these F2_F3_FIFO_RD_UNDERFLOW | F2_F3_FIFO_WR_OVERFLOW | COMMAND_ERROR | DATA_ERROR | F2_PACKET_AVAILABLE | F1_OVERFLOW | F1_INTR | ||||||
|         debug!("enable a selection of interrupts"); |         defmt::debug!("enable a selection of interrupts"); | ||||||
|         self.write16( |         self.write16( | ||||||
|             FUNC_BUS, |             FUNC_BUS, | ||||||
|             REG_BUS_INTERRUPT_ENABLE, |             REG_BUS_INTERRUPT_ENABLE, | ||||||
| @@ -244,28 +244,45 @@ where | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     async fn backplane_readn(&mut self, addr: u32, len: u32) -> u32 { |     async fn backplane_readn(&mut self, addr: u32, len: u32) -> u32 { | ||||||
|  |         defmt::debug!("backplane_readn addr = {:08x} len = {}", addr, len); | ||||||
|  |  | ||||||
|         self.backplane_set_window(addr).await; |         self.backplane_set_window(addr).await; | ||||||
|  |  | ||||||
|         let mut bus_addr = addr & BACKPLANE_ADDRESS_MASK; |         let mut bus_addr = addr & BACKPLANE_ADDRESS_MASK; | ||||||
|         if len == 4 { |         if len == 4 { | ||||||
|             bus_addr |= BACKPLANE_ADDRESS_32BIT_FLAG |             bus_addr |= BACKPLANE_ADDRESS_32BIT_FLAG; | ||||||
|         } |         } | ||||||
|         self.readn(FUNC_BACKPLANE, bus_addr, len).await |          | ||||||
|  |         let val = self.readn(FUNC_BACKPLANE, bus_addr, len).await; | ||||||
|  |  | ||||||
|  |         defmt::debug!("backplane_readn addr = {:08x} len = {} val = {:08x}", addr, len, val); | ||||||
|  |  | ||||||
|  |         self.backplane_set_window(0x18000000).await; // CHIPCOMMON_BASE_ADDRESS | ||||||
|  |  | ||||||
|  |         return val | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     async fn backplane_writen(&mut self, addr: u32, val: u32, len: u32) { |     async fn backplane_writen(&mut self, addr: u32, val: u32, len: u32) { | ||||||
|  |         defmt::debug!("backplane_writen addr = {:08x} len = {} val = {:08x}", addr, len, val); | ||||||
|  |  | ||||||
|         self.backplane_set_window(addr).await; |         self.backplane_set_window(addr).await; | ||||||
|  |  | ||||||
|         let mut bus_addr = addr & BACKPLANE_ADDRESS_MASK; |         let mut bus_addr = addr & BACKPLANE_ADDRESS_MASK; | ||||||
|         if len == 4 { |         if len == 4 { | ||||||
|             bus_addr |= BACKPLANE_ADDRESS_32BIT_FLAG |             bus_addr |= BACKPLANE_ADDRESS_32BIT_FLAG; | ||||||
|         } |         } | ||||||
|         self.writen(FUNC_BACKPLANE, bus_addr, val, len).await |         self.writen(FUNC_BACKPLANE, bus_addr, val, len).await; | ||||||
|  |  | ||||||
|  |         self.backplane_set_window(0x18000000).await; // CHIPCOMMON_BASE_ADDRESS | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     async fn backplane_set_window(&mut self, addr: u32) { |     async fn backplane_set_window(&mut self, addr: u32) { | ||||||
|         let new_window = addr & !BACKPLANE_ADDRESS_MASK; |         let new_window = addr & !BACKPLANE_ADDRESS_MASK; | ||||||
|  |  | ||||||
|  |         if new_window == self.backplane_window { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|         if (new_window >> 24) as u8 != (self.backplane_window >> 24) as u8 { |         if (new_window >> 24) as u8 != (self.backplane_window >> 24) as u8 { | ||||||
|             self.write8( |             self.write8( | ||||||
|                 FUNC_BACKPLANE, |                 FUNC_BACKPLANE, | ||||||
| @@ -290,6 +307,7 @@ where | |||||||
|             ) |             ) | ||||||
|             .await; |             .await; | ||||||
|         } |         } | ||||||
|  |          | ||||||
|         self.backplane_window = new_window; |         self.backplane_window = new_window; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -327,6 +345,8 @@ where | |||||||
|  |  | ||||||
|         self.status = self.spi.cmd_read(cmd, &mut buf[..len]).await; |         self.status = self.spi.cmd_read(cmd, &mut buf[..len]).await; | ||||||
|  |  | ||||||
|  |         defmt::debug!("readn cmd = {:08x} addr = {:08x} len = {} buf = {:08x}", cmd, addr, len, buf); | ||||||
|  |  | ||||||
|         // if we read from the backplane, the result is in the second word, after the response delay |         // if we read from the backplane, the result is in the second word, after the response delay | ||||||
|         if func == FUNC_BACKPLANE { |         if func == FUNC_BACKPLANE { | ||||||
|             buf[1] |             buf[1] | ||||||
| @@ -341,8 +361,8 @@ where | |||||||
|         self.status = self.spi.cmd_write(&[cmd, val]).await; |         self.status = self.spi.cmd_write(&[cmd, val]).await; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     async fn read32_swapped(&mut self, addr: u32) -> u32 { |     async fn read32_swapped(&mut self, func: u32, addr: u32) -> u32 { | ||||||
|         let cmd = cmd_word(READ, INC_ADDR, FUNC_BUS, addr, 4); |         let cmd = cmd_word(READ, INC_ADDR, func, addr, 4); | ||||||
|         let cmd = swap16(cmd); |         let cmd = swap16(cmd); | ||||||
|         let mut buf = [0; 1]; |         let mut buf = [0; 1]; | ||||||
|  |  | ||||||
| @@ -351,7 +371,7 @@ where | |||||||
|         swap16(buf[0]) |         swap16(buf[0]) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     async fn write32_swapped(&mut self, addr: u32, val: u32) { |     async fn write32_swapped(&mut self, func: u32, addr: u32, val: u32) { | ||||||
|         let cmd = cmd_word(WRITE, INC_ADDR, FUNC_BUS, addr, 4); |         let cmd = cmd_word(WRITE, INC_ADDR, FUNC_BUS, addr, 4); | ||||||
|         let buf = [swap16(cmd), swap16(val)]; |         let buf = [swap16(cmd), swap16(val)]; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -214,8 +214,8 @@ pub async fn new<'a, PWR, SPI>( | |||||||
|     pwr: PWR, |     pwr: PWR, | ||||||
|     spi: SPI, |     spi: SPI, | ||||||
|     firmware: &[u8], |     firmware: &[u8], | ||||||
|     bluetooth_firmware_offsets: &[(u32, usize)], |     bluetooth_firmware_offsets: Option<&[(u32, usize)]>, | ||||||
|     bluetooth_firmware: &[u8], |     bluetooth_firmware: Option<&[u8]>, | ||||||
| ) -> (NetDriver<'a>, Control<'a>, Runner<'a, PWR, SPI>) | ) -> (NetDriver<'a>, Control<'a>, Runner<'a, PWR, SPI>) | ||||||
| where | where | ||||||
|     PWR: OutputPin, |     PWR: OutputPin, | ||||||
|   | |||||||
| @@ -73,7 +73,7 @@ where | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     pub(crate) async fn init(&mut self, firmware: &[u8], bluetooth_firmware_offsets: &[(u32, usize)], bluetooth_firmware: &[u8]) { |     pub(crate) async fn init(&mut self, firmware: &[u8], bluetooth_firmware_offsets: Option<&[(u32, usize)]>, bluetooth_firmware: Option<&[u8]>) { | ||||||
|         self.bus.init().await; |         self.bus.init().await; | ||||||
|  |  | ||||||
|         // Init ALP (Active Low Power) clock |         // Init ALP (Active Low Power) clock | ||||||
| @@ -116,8 +116,11 @@ where | |||||||
|         debug!("loading fw"); |         debug!("loading fw"); | ||||||
|         self.bus.bp_write(ram_addr, firmware).await; |         self.bus.bp_write(ram_addr, firmware).await; | ||||||
|  |  | ||||||
|  |         // Optionally load Bluetooth fimrware into RAM. | ||||||
|  |         if bluetooth_firmware_offsets.is_some() && bluetooth_firmware.is_some() { | ||||||
|             debug!("loading bluetooth fw"); |             debug!("loading bluetooth fw"); | ||||||
|         bluetooth::init_bluetooth(&mut self.bus, bluetooth_firmware_offsets, bluetooth_firmware).await; |             bluetooth::init_bluetooth(&mut self.bus, bluetooth_firmware_offsets.unwrap(), bluetooth_firmware.unwrap()).await; | ||||||
|  |         } | ||||||
|  |  | ||||||
|         debug!("loading nvram"); |         debug!("loading nvram"); | ||||||
|         // Round up to 4 bytes. |         // Round up to 4 bytes. | ||||||
|   | |||||||
| @@ -22,7 +22,7 @@ lorawan-device = { version = "0.10.0", default-features = false, features = ["as | |||||||
| lorawan = { version = "0.7.3", default-features = false, features = ["default-crypto"] } | lorawan = { version = "0.7.3", default-features = false, features = ["default-crypto"] } | ||||||
| cyw43 = { path = "../../cyw43", features = ["defmt", "firmware-logs"] } | cyw43 = { path = "../../cyw43", features = ["defmt", "firmware-logs"] } | ||||||
| cyw43-firmware = { path = "../../cyw43-firmware" } | cyw43-firmware = { path = "../../cyw43-firmware" } | ||||||
| cyw43-pio = { path = "../../cyw43-pio", features = ["defmt", "overclock"] } | cyw43-pio = { path = "../../cyw43-pio", features = ["defmt"] } | ||||||
|  |  | ||||||
| defmt = "0.3" | defmt = "0.3" | ||||||
| defmt-rtt = "0.4" | defmt-rtt = "0.4" | ||||||
|   | |||||||
							
								
								
									
										70
									
								
								examples/rp/src/bin/bluetooth_blinky.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								examples/rp/src/bin/bluetooth_blinky.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,70 @@ | |||||||
|  | //! This example test the RP Pico W on board LED. | ||||||
|  | //! | ||||||
|  | //! It does not work with the RP Pico board. See blinky.rs. | ||||||
|  |  | ||||||
|  | #![no_std] | ||||||
|  | #![no_main] | ||||||
|  | #![feature(type_alias_impl_trait)] | ||||||
|  |  | ||||||
|  | use cyw43_pio::PioSpi; | ||||||
|  | use defmt::*; | ||||||
|  | use embassy_executor::Spawner; | ||||||
|  | use embassy_rp::bind_interrupts; | ||||||
|  | use embassy_rp::gpio::{Level, Output}; | ||||||
|  | use embassy_rp::peripherals::{DMA_CH0, PIN_23, PIN_25, PIO0}; | ||||||
|  | use embassy_rp::pio::{InterruptHandler, Pio}; | ||||||
|  | use embassy_time::{Duration, Timer}; | ||||||
|  | use static_cell::make_static; | ||||||
|  | use {defmt_rtt as _, panic_probe as _}; | ||||||
|  |  | ||||||
|  | bind_interrupts!(struct Irqs { | ||||||
|  |     PIO0_IRQ_0 => InterruptHandler<PIO0>; | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | #[embassy_executor::task] | ||||||
|  | async fn cyw43_runner_task( | ||||||
|  |     runner: cyw43::Runner<'static, Output<'static, PIN_23>, PioSpi<'static, PIN_25, PIO0, 0, DMA_CH0>>, | ||||||
|  | ) -> ! { | ||||||
|  |     runner.run().await | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #[embassy_executor::main] | ||||||
|  | async fn main(spawner: Spawner) { | ||||||
|  |     let p = embassy_rp::init(Default::default()); | ||||||
|  |     let fw = include_bytes!("../../../../cyw43-firmware/43439A0.bin"); | ||||||
|  |     let clm = include_bytes!("../../../../cyw43-firmware/43439A0_clm.bin"); | ||||||
|  |  | ||||||
|  |     // To make flashing faster for development, you may want to flash the firmwares independently | ||||||
|  |     // at hardcoded addresses, instead of baking them into the program with `include_bytes!`: | ||||||
|  |     //     probe-rs download 43439A0.bin --format bin --chip RP2040 --base-address 0x10100000 | ||||||
|  |     //     probe-rs download 43439A0_clm.bin --format bin --chip RP2040 --base-address 0x10140000 | ||||||
|  |     //let fw = unsafe { core::slice::from_raw_parts(0x10100000 as *const u8, 224190) }; | ||||||
|  |     //let clm = unsafe { core::slice::from_raw_parts(0x10140000 as *const u8, 4752) }; | ||||||
|  |  | ||||||
|  |     let pwr = Output::new(p.PIN_23, Level::Low); | ||||||
|  |     let cs = Output::new(p.PIN_25, Level::High); | ||||||
|  |     let mut pio = Pio::new(p.PIO0, Irqs); | ||||||
|  |     let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0); | ||||||
|  |  | ||||||
|  |     let state = make_static!(cyw43::State::new()); | ||||||
|  |     let bluetooth_firmware_offsets = &cyw43_firmware::BLUETOOTH_FIRMWARE_OFFSETS; | ||||||
|  |     let bluetooth_firmware = &cyw43_firmware::BLUETOOTH_FIRMWARE; | ||||||
|  |     let (_net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw, Some(bluetooth_firmware_offsets), Some(bluetooth_firmware)).await; | ||||||
|  |     unwrap!(spawner.spawn(cyw43_runner_task(runner))); | ||||||
|  |  | ||||||
|  |     control.init(clm).await; | ||||||
|  |     control | ||||||
|  |         .set_power_management(cyw43::PowerManagementMode::PowerSave) | ||||||
|  |         .await; | ||||||
|  |  | ||||||
|  |     let delay = Duration::from_secs(1); | ||||||
|  |     loop { | ||||||
|  |         info!("led on!"); | ||||||
|  |         control.gpio_set(0, true).await; | ||||||
|  |         Timer::after(delay).await; | ||||||
|  |  | ||||||
|  |         info!("led off!"); | ||||||
|  |         control.gpio_set(0, false).await; | ||||||
|  |         Timer::after(delay).await; | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -31,8 +31,6 @@ async fn wifi_task( | |||||||
| #[embassy_executor::main] | #[embassy_executor::main] | ||||||
| async fn main(spawner: Spawner) { | async fn main(spawner: Spawner) { | ||||||
|     let p = embassy_rp::init(Default::default()); |     let p = embassy_rp::init(Default::default()); | ||||||
|     let bluetooth_firmware_offsets = &cyw43_firmware::BLUETOOTH_FIRMWARE_OFFSETS; |  | ||||||
|     let bluetooth_firmware = &cyw43_firmware::BLUETOOTH_FIRMWARE; |  | ||||||
|     let fw = include_bytes!("../../../../cyw43-firmware/43439A0.bin"); |     let fw = include_bytes!("../../../../cyw43-firmware/43439A0.bin"); | ||||||
|     let clm = include_bytes!("../../../../cyw43-firmware/43439A0_clm.bin"); |     let clm = include_bytes!("../../../../cyw43-firmware/43439A0_clm.bin"); | ||||||
|  |  | ||||||
| @@ -49,7 +47,7 @@ async fn main(spawner: Spawner) { | |||||||
|     let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0); |     let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0); | ||||||
|  |  | ||||||
|     let state = make_static!(cyw43::State::new()); |     let state = make_static!(cyw43::State::new()); | ||||||
|     let (_net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw, bluetooth_firmware_offsets, bluetooth_firmware).await; |     let (_net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; | ||||||
|     unwrap!(spawner.spawn(wifi_task(runner))); |     unwrap!(spawner.spawn(wifi_task(runner))); | ||||||
|  |  | ||||||
|     control.init(clm).await; |     control.init(clm).await; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user