diff options
| -rw-r--r-- | embassy-stm32-wpan/src/wb55/mod.rs | 2 | ||||
| -rw-r--r-- | embassy-stm32-wpan/src/wb55/shci.rs | 122 | ||||
| -rw-r--r-- | embassy-stm32-wpan/src/wb55/sub/sys.rs | 45 |
3 files changed, 138 insertions, 31 deletions
diff --git a/embassy-stm32-wpan/src/wb55/mod.rs b/embassy-stm32-wpan/src/wb55/mod.rs index 95cfe09f1..814303a05 100644 --- a/embassy-stm32-wpan/src/wb55/mod.rs +++ b/embassy-stm32-wpan/src/wb55/mod.rs | |||
| @@ -176,7 +176,7 @@ impl<'d> TlMbox<'d> { | |||
| 176 | let mm = sub::mm::MemoryManager::new(ipcc_mm_release_buffer_channel); | 176 | let mm = sub::mm::MemoryManager::new(ipcc_mm_release_buffer_channel); |
| 177 | let mut sys = sub::sys::Sys::new(ipcc_system_cmd_rsp_channel, ipcc_system_event_channel); | 177 | let mut sys = sub::sys::Sys::new(ipcc_system_cmd_rsp_channel, ipcc_system_event_channel); |
| 178 | 178 | ||
| 179 | debug!("sys event: {}", sys.read().await.payload()); | 179 | debug!("sys event: {}", sys.read_ready().await); |
| 180 | 180 | ||
| 181 | Self { | 181 | Self { |
| 182 | sys_subsystem: sys, | 182 | sys_subsystem: sys, |
diff --git a/embassy-stm32-wpan/src/wb55/shci.rs b/embassy-stm32-wpan/src/wb55/shci.rs index 3faa79209..3eb9525d3 100644 --- a/embassy-stm32-wpan/src/wb55/shci.rs +++ b/embassy-stm32-wpan/src/wb55/shci.rs | |||
| @@ -12,6 +12,28 @@ const fn opcode(ogf: u16, ocf: u16) -> isize { | |||
| 12 | ((ogf << 10) + ocf) as isize | 12 | ((ogf << 10) + ocf) as isize |
| 13 | } | 13 | } |
| 14 | 14 | ||
| 15 | pub(crate) trait SealedSchiFromPacket: Sized { | ||
| 16 | unsafe fn from_packet(cmd_buf: *const CmdPacket) -> Result<Self, ()>; | ||
| 17 | } | ||
| 18 | |||
| 19 | #[allow(private_bounds)] | ||
| 20 | pub trait SchiFromPacket: SealedSchiFromPacket {} | ||
| 21 | impl<T: SealedSchiFromPacket> SchiFromPacket for T {} | ||
| 22 | |||
| 23 | trait ShciFromEventSerial: TryFrom<u8, Error = ()> {} | ||
| 24 | |||
| 25 | impl<T: ShciFromEventSerial> SealedSchiFromPacket for T { | ||
| 26 | unsafe fn from_packet(cmd_buf: *const CmdPacket) -> Result<Self, ()> { | ||
| 27 | let p_cmd_serial = (cmd_buf as *mut u8).add(size_of::<PacketHeader>()); | ||
| 28 | let p_evt_payload = p_cmd_serial.add(size_of::<EvtStub>()); | ||
| 29 | |||
| 30 | compiler_fence(Ordering::Acquire); | ||
| 31 | let cc_evt = ptr::read_unaligned(p_evt_payload as *const CcEvt); | ||
| 32 | |||
| 33 | cc_evt.payload[0].try_into() | ||
| 34 | } | ||
| 35 | } | ||
| 36 | |||
| 15 | #[allow(dead_code)] | 37 | #[allow(dead_code)] |
| 16 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 38 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 17 | pub enum SchiCommandStatus { | 39 | pub enum SchiCommandStatus { |
| @@ -25,37 +47,20 @@ pub enum SchiCommandStatus { | |||
| 25 | ShciFusCmdNotSupported = 0xFF, | 47 | ShciFusCmdNotSupported = 0xFF, |
| 26 | } | 48 | } |
| 27 | 49 | ||
| 28 | impl SchiCommandStatus { | 50 | impl ShciFromEventSerial for SchiCommandStatus {} |
| 29 | pub unsafe fn from_packet(cmd_buf: *const CmdPacket) -> Result<Self, ()> { | ||
| 30 | let p_cmd_serial = (cmd_buf as *mut u8).add(size_of::<PacketHeader>()); | ||
| 31 | let p_evt_payload = p_cmd_serial.add(size_of::<EvtStub>()); | ||
| 32 | |||
| 33 | compiler_fence(Ordering::Acquire); | ||
| 34 | let cc_evt = ptr::read_unaligned(p_evt_payload as *const CcEvt); | ||
| 35 | |||
| 36 | cc_evt.payload[0].try_into() | ||
| 37 | } | ||
| 38 | } | ||
| 39 | |||
| 40 | impl TryFrom<u8> for SchiCommandStatus { | 51 | impl TryFrom<u8> for SchiCommandStatus { |
| 41 | type Error = (); | 52 | type Error = (); |
| 42 | 53 | ||
| 43 | fn try_from(v: u8) -> Result<Self, Self::Error> { | 54 | fn try_from(v: u8) -> Result<Self, Self::Error> { |
| 44 | match v { | 55 | match v { |
| 45 | x if x == SchiCommandStatus::ShciSuccess as u8 => Ok(SchiCommandStatus::ShciSuccess), | 56 | 0x00 => Ok(Self::ShciSuccess), |
| 46 | x if x == SchiCommandStatus::ShciUnknownCmd as u8 => Ok(SchiCommandStatus::ShciUnknownCmd), | 57 | 0x01 => Ok(Self::ShciUnknownCmd), |
| 47 | x if x == SchiCommandStatus::ShciMemoryCapacityExceededErrCode as u8 => { | 58 | 0x07 => Ok(Self::ShciMemoryCapacityExceededErrCode), |
| 48 | Ok(SchiCommandStatus::ShciMemoryCapacityExceededErrCode) | 59 | 0x11 => Ok(Self::ShciErrUnsupportedFeature), |
| 49 | } | 60 | 0x12 => Ok(Self::ShciErrInvalidHciCmdParams), |
| 50 | x if x == SchiCommandStatus::ShciErrUnsupportedFeature as u8 => { | 61 | 0x42 => Ok(Self::ShciErrInvalidParams), /* only used for release < v1.13.0 */ |
| 51 | Ok(SchiCommandStatus::ShciErrUnsupportedFeature) | 62 | 0x92 => Ok(Self::ShciErrInvalidParamsV2), /* available for release >= v1.13.0 */ |
| 52 | } | 63 | 0xFF => Ok(Self::ShciFusCmdNotSupported), |
| 53 | x if x == SchiCommandStatus::ShciErrInvalidHciCmdParams as u8 => { | ||
| 54 | Ok(SchiCommandStatus::ShciErrInvalidHciCmdParams) | ||
| 55 | } | ||
| 56 | x if x == SchiCommandStatus::ShciErrInvalidParams as u8 => Ok(SchiCommandStatus::ShciErrInvalidParams), /* only used for release < v1.13.0 */ | ||
| 57 | x if x == SchiCommandStatus::ShciErrInvalidParamsV2 as u8 => Ok(SchiCommandStatus::ShciErrInvalidParamsV2), /* available for release >= v1.13.0 */ | ||
| 58 | x if x == SchiCommandStatus::ShciFusCmdNotSupported as u8 => Ok(SchiCommandStatus::ShciFusCmdNotSupported), | ||
| 59 | _ => Err(()), | 64 | _ => Err(()), |
| 60 | } | 65 | } |
| 61 | } | 66 | } |
| @@ -107,6 +112,71 @@ pub enum ShciOpcode { | |||
| 107 | Mac802_15_4DeInit = opcode(SHCI_OGF, 0x78), | 112 | Mac802_15_4DeInit = opcode(SHCI_OGF, 0x78), |
| 108 | } | 113 | } |
| 109 | 114 | ||
| 115 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 116 | pub enum ShciFusGetStateErrorCode { | ||
| 117 | FusStateErrorNoError = 0x00, | ||
| 118 | FusStateErrorImgNotFound = 0x01, | ||
| 119 | FusStateErrorImgCorrupt = 0x02, | ||
| 120 | FusStateErrorImgNotAuthentic = 0x03, | ||
| 121 | FusStateErrorImgNotEnoughSpace = 0x04, | ||
| 122 | FusStateErrorImageUsrAbort = 0x05, | ||
| 123 | FusStateErrorImageErsError = 0x06, | ||
| 124 | FusStateErrorImageWrtError = 0x07, | ||
| 125 | FusStateErrorAuthTagStNotFound = 0x08, | ||
| 126 | FusStateErrorAuthTagCustNotFound = 0x09, | ||
| 127 | FusStateErrorAuthKeyLocked = 0x0A, | ||
| 128 | FusStateErrorFwRollbackError = 0x11, | ||
| 129 | FusStateErrorStateNotRunning = 0xFE, | ||
| 130 | FusStateErrorErrUnknown = 0xFF, | ||
| 131 | } | ||
| 132 | |||
| 133 | impl ShciFromEventSerial for ShciFusGetStateErrorCode {} | ||
| 134 | impl TryFrom<u8> for ShciFusGetStateErrorCode { | ||
| 135 | type Error = (); | ||
| 136 | |||
| 137 | fn try_from(v: u8) -> Result<Self, Self::Error> { | ||
| 138 | match v { | ||
| 139 | 0x00 => Ok(Self::FusStateErrorNoError), | ||
| 140 | 0x01 => Ok(Self::FusStateErrorImgNotFound), | ||
| 141 | 0x02 => Ok(Self::FusStateErrorImgCorrupt), | ||
| 142 | 0x03 => Ok(Self::FusStateErrorImgNotAuthentic), | ||
| 143 | 0x04 => Ok(Self::FusStateErrorImgNotEnoughSpace), | ||
| 144 | 0x05 => Ok(Self::FusStateErrorImageUsrAbort), | ||
| 145 | 0x06 => Ok(Self::FusStateErrorImageErsError), | ||
| 146 | 0x07 => Ok(Self::FusStateErrorImageWrtError), | ||
| 147 | 0x08 => Ok(Self::FusStateErrorAuthTagStNotFound), | ||
| 148 | 0x09 => Ok(Self::FusStateErrorAuthTagCustNotFound), | ||
| 149 | 0x0A => Ok(Self::FusStateErrorAuthKeyLocked), | ||
| 150 | 0x11 => Ok(Self::FusStateErrorFwRollbackError), | ||
| 151 | 0xFE => Ok(Self::FusStateErrorStateNotRunning), | ||
| 152 | 0xFF => Ok(Self::FusStateErrorErrUnknown), | ||
| 153 | _ => Err(()), | ||
| 154 | } | ||
| 155 | } | ||
| 156 | } | ||
| 157 | |||
| 158 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 159 | pub enum SchiSysEventReady { | ||
| 160 | WirelessFwRunning = 0x00, | ||
| 161 | FusFwRunning = 0x01, | ||
| 162 | NvmBackupRunning = 0x10, | ||
| 163 | NvmRestoreRunning = 0x11, | ||
| 164 | } | ||
| 165 | |||
| 166 | impl TryFrom<u8> for SchiSysEventReady { | ||
| 167 | type Error = (); | ||
| 168 | |||
| 169 | fn try_from(v: u8) -> Result<Self, Self::Error> { | ||
| 170 | match v { | ||
| 171 | 0x00 => Ok(Self::WirelessFwRunning), | ||
| 172 | 0x01 => Ok(Self::FusFwRunning), | ||
| 173 | 0x10 => Ok(Self::NvmBackupRunning), | ||
| 174 | 0x11 => Ok(Self::NvmRestoreRunning), | ||
| 175 | _ => Err(()), | ||
| 176 | } | ||
| 177 | } | ||
| 178 | } | ||
| 179 | |||
| 110 | pub const SHCI_C2_CONFIG_EVTMASK1_BIT0_ERROR_NOTIF_ENABLE: u8 = 1 << 0; | 180 | pub const SHCI_C2_CONFIG_EVTMASK1_BIT0_ERROR_NOTIF_ENABLE: u8 = 1 << 0; |
| 111 | pub const SHCI_C2_CONFIG_EVTMASK1_BIT1_BLE_NVM_RAM_UPDATE_ENABLE: u8 = 1 << 1; | 181 | pub const SHCI_C2_CONFIG_EVTMASK1_BIT1_BLE_NVM_RAM_UPDATE_ENABLE: u8 = 1 << 1; |
| 112 | pub const SHCI_C2_CONFIG_EVTMASK1_BIT2_THREAD_NVM_RAM_UPDATE_ENABLE: u8 = 1 << 2; | 182 | pub const SHCI_C2_CONFIG_EVTMASK1_BIT2_THREAD_NVM_RAM_UPDATE_ENABLE: u8 = 1 << 2; |
diff --git a/embassy-stm32-wpan/src/wb55/sub/sys.rs b/embassy-stm32-wpan/src/wb55/sub/sys.rs index 2e625a677..3d774eeb7 100644 --- a/embassy-stm32-wpan/src/wb55/sub/sys.rs +++ b/embassy-stm32-wpan/src/wb55/sub/sys.rs | |||
| @@ -1,3 +1,5 @@ | |||
| 1 | use core::slice; | ||
| 2 | |||
| 1 | use embassy_stm32::ipcc::{IpccRxChannel, IpccTxChannel}; | 3 | use embassy_stm32::ipcc::{IpccRxChannel, IpccTxChannel}; |
| 2 | 4 | ||
| 3 | use crate::cmd::CmdPacket; | 5 | use crate::cmd::CmdPacket; |
| @@ -5,12 +7,17 @@ use crate::consts::TlPacketType; | |||
| 5 | use crate::evt::EvtBox; | 7 | use crate::evt::EvtBox; |
| 6 | #[cfg(feature = "wb55_ble")] | 8 | #[cfg(feature = "wb55_ble")] |
| 7 | use crate::shci::ShciBleInitCmdParam; | 9 | use crate::shci::ShciBleInitCmdParam; |
| 8 | use crate::shci::{SchiCommandStatus, ShciOpcode}; | 10 | use crate::shci::{SchiCommandStatus, SchiFromPacket, SchiSysEventReady, ShciFusGetStateErrorCode, ShciOpcode}; |
| 9 | use crate::sub::mm; | 11 | use crate::sub::mm; |
| 10 | use crate::tables::{SysTable, WirelessFwInfoTable}; | 12 | use crate::tables::{SysTable, WirelessFwInfoTable}; |
| 11 | use crate::unsafe_linked_list::LinkedListNode; | 13 | use crate::unsafe_linked_list::LinkedListNode; |
| 12 | use crate::wb55::{SYS_CMD_BUF, SYSTEM_EVT_QUEUE, TL_DEVICE_INFO_TABLE, TL_SYS_TABLE}; | 14 | use crate::wb55::{SYS_CMD_BUF, SYSTEM_EVT_QUEUE, TL_DEVICE_INFO_TABLE, TL_SYS_TABLE}; |
| 13 | 15 | ||
| 16 | const fn slice8_ref(x: &[u32]) -> &[u8] { | ||
| 17 | let len = x.len() * 4; | ||
| 18 | unsafe { slice::from_raw_parts(x.as_ptr() as *const u8, len) } | ||
| 19 | } | ||
| 20 | |||
| 14 | /// A guard that, once constructed, allows for sys commands to be sent to CPU2. | 21 | /// A guard that, once constructed, allows for sys commands to be sent to CPU2. |
| 15 | pub struct Sys<'a> { | 22 | pub struct Sys<'a> { |
| 16 | ipcc_system_cmd_rsp_channel: IpccTxChannel<'a>, | 23 | ipcc_system_cmd_rsp_channel: IpccTxChannel<'a>, |
| @@ -55,15 +62,15 @@ impl<'a> Sys<'a> { | |||
| 55 | } | 62 | } |
| 56 | 63 | ||
| 57 | /// `HW_IPCC_SYS_CmdEvtNot` | 64 | /// `HW_IPCC_SYS_CmdEvtNot` |
| 58 | pub async fn write_and_get_response( | 65 | pub async fn write_and_get_response<T: SchiFromPacket>( |
| 59 | &mut self, | 66 | &mut self, |
| 60 | opcode: ShciOpcode, | 67 | opcode: ShciOpcode, |
| 61 | payload: &[u8], | 68 | payload: &[u8], |
| 62 | ) -> Result<SchiCommandStatus, ()> { | 69 | ) -> Result<T, ()> { |
| 63 | self.write(opcode, payload).await; | 70 | self.write(opcode, payload).await; |
| 64 | self.ipcc_system_cmd_rsp_channel.flush().await; | 71 | self.ipcc_system_cmd_rsp_channel.flush().await; |
| 65 | 72 | ||
| 66 | unsafe { SchiCommandStatus::from_packet(SYS_CMD_BUF.as_ptr()) } | 73 | unsafe { T::from_packet(SYS_CMD_BUF.as_ptr()) } |
| 67 | } | 74 | } |
| 68 | 75 | ||
| 69 | #[cfg(feature = "wb55_mac")] | 76 | #[cfg(feature = "wb55_mac")] |
| @@ -82,6 +89,36 @@ impl<'a> Sys<'a> { | |||
| 82 | self.write_and_get_response(ShciOpcode::BleInit, param.payload()).await | 89 | self.write_and_get_response(ShciOpcode::BleInit, param.payload()).await |
| 83 | } | 90 | } |
| 84 | 91 | ||
| 92 | pub async fn shci_c2_fus_getstate(&mut self) -> Result<ShciFusGetStateErrorCode, ()> { | ||
| 93 | self.write_and_get_response(ShciOpcode::FusStartWirelessStack, &[]) | ||
| 94 | .await | ||
| 95 | } | ||
| 96 | |||
| 97 | /// Send a request to CPU2 to start the wireless stack | ||
| 98 | pub async fn shci_c2_fus_startws(&mut self) -> Result<SchiCommandStatus, ()> { | ||
| 99 | self.write_and_get_response(ShciOpcode::FusStartWirelessStack, &[]) | ||
| 100 | .await | ||
| 101 | } | ||
| 102 | |||
| 103 | /// Send a request to CPU2 to upgrade the firmware | ||
| 104 | pub async fn shci_c2_fus_fwupgrade(&mut self, fw_src_add: u32, fw_dst_add: u32) -> Result<SchiCommandStatus, ()> { | ||
| 105 | let buf = [fw_src_add, fw_dst_add]; | ||
| 106 | let len = if fw_dst_add != 0 { | ||
| 107 | 2 | ||
| 108 | } else if fw_src_add != 0 { | ||
| 109 | 1 | ||
| 110 | } else { | ||
| 111 | 0 | ||
| 112 | }; | ||
| 113 | |||
| 114 | self.write_and_get_response(ShciOpcode::FusFirmwareUpgrade, slice8_ref(&buf[..len])) | ||
| 115 | .await | ||
| 116 | } | ||
| 117 | |||
| 118 | pub async fn read_ready(&mut self) -> Result<SchiSysEventReady, ()> { | ||
| 119 | self.read().await.payload()[0].try_into() | ||
| 120 | } | ||
| 121 | |||
| 85 | /// `HW_IPCC_SYS_EvtNot` | 122 | /// `HW_IPCC_SYS_EvtNot` |
| 86 | /// | 123 | /// |
| 87 | /// This method takes the place of the `HW_IPCC_SYS_EvtNot`/`SysUserEvtRx`/`APPE_SysUserEvtRx`, | 124 | /// This method takes the place of the `HW_IPCC_SYS_EvtNot`/`SysUserEvtRx`/`APPE_SysUserEvtRx`, |
