aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32-wpan
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-stm32-wpan')
-rw-r--r--embassy-stm32-wpan/src/wb55/mod.rs2
-rw-r--r--embassy-stm32-wpan/src/wb55/shci.rs122
-rw-r--r--embassy-stm32-wpan/src/wb55/sub/sys.rs45
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
15pub(crate) trait SealedSchiFromPacket: Sized {
16 unsafe fn from_packet(cmd_buf: *const CmdPacket) -> Result<Self, ()>;
17}
18
19#[allow(private_bounds)]
20pub trait SchiFromPacket: SealedSchiFromPacket {}
21impl<T: SealedSchiFromPacket> SchiFromPacket for T {}
22
23trait ShciFromEventSerial: TryFrom<u8, Error = ()> {}
24
25impl<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))]
17pub enum SchiCommandStatus { 39pub enum SchiCommandStatus {
@@ -25,37 +47,20 @@ pub enum SchiCommandStatus {
25 ShciFusCmdNotSupported = 0xFF, 47 ShciFusCmdNotSupported = 0xFF,
26} 48}
27 49
28impl SchiCommandStatus { 50impl 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
40impl TryFrom<u8> for SchiCommandStatus { 51impl 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))]
116pub 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
133impl ShciFromEventSerial for ShciFusGetStateErrorCode {}
134impl 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))]
159pub enum SchiSysEventReady {
160 WirelessFwRunning = 0x00,
161 FusFwRunning = 0x01,
162 NvmBackupRunning = 0x10,
163 NvmRestoreRunning = 0x11,
164}
165
166impl 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
110pub const SHCI_C2_CONFIG_EVTMASK1_BIT0_ERROR_NOTIF_ENABLE: u8 = 1 << 0; 180pub const SHCI_C2_CONFIG_EVTMASK1_BIT0_ERROR_NOTIF_ENABLE: u8 = 1 << 0;
111pub const SHCI_C2_CONFIG_EVTMASK1_BIT1_BLE_NVM_RAM_UPDATE_ENABLE: u8 = 1 << 1; 181pub const SHCI_C2_CONFIG_EVTMASK1_BIT1_BLE_NVM_RAM_UPDATE_ENABLE: u8 = 1 << 1;
112pub const SHCI_C2_CONFIG_EVTMASK1_BIT2_THREAD_NVM_RAM_UPDATE_ENABLE: u8 = 1 << 2; 182pub 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 @@
1use core::slice;
2
1use embassy_stm32::ipcc::{IpccRxChannel, IpccTxChannel}; 3use embassy_stm32::ipcc::{IpccRxChannel, IpccTxChannel};
2 4
3use crate::cmd::CmdPacket; 5use crate::cmd::CmdPacket;
@@ -5,12 +7,17 @@ use crate::consts::TlPacketType;
5use crate::evt::EvtBox; 7use crate::evt::EvtBox;
6#[cfg(feature = "wb55_ble")] 8#[cfg(feature = "wb55_ble")]
7use crate::shci::ShciBleInitCmdParam; 9use crate::shci::ShciBleInitCmdParam;
8use crate::shci::{SchiCommandStatus, ShciOpcode}; 10use crate::shci::{SchiCommandStatus, SchiFromPacket, SchiSysEventReady, ShciFusGetStateErrorCode, ShciOpcode};
9use crate::sub::mm; 11use crate::sub::mm;
10use crate::tables::{SysTable, WirelessFwInfoTable}; 12use crate::tables::{SysTable, WirelessFwInfoTable};
11use crate::unsafe_linked_list::LinkedListNode; 13use crate::unsafe_linked_list::LinkedListNode;
12use crate::wb55::{SYS_CMD_BUF, SYSTEM_EVT_QUEUE, TL_DEVICE_INFO_TABLE, TL_SYS_TABLE}; 14use crate::wb55::{SYS_CMD_BUF, SYSTEM_EVT_QUEUE, TL_DEVICE_INFO_TABLE, TL_SYS_TABLE};
13 15
16const 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.
15pub struct Sys<'a> { 22pub 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`,