diff options
Diffstat (limited to 'embassy-stm32-wpan/src/sub/mac.rs')
| -rw-r--r-- | embassy-stm32-wpan/src/sub/mac.rs | 144 |
1 files changed, 77 insertions, 67 deletions
diff --git a/embassy-stm32-wpan/src/sub/mac.rs b/embassy-stm32-wpan/src/sub/mac.rs index 93cafbc72..ce2903e61 100644 --- a/embassy-stm32-wpan/src/sub/mac.rs +++ b/embassy-stm32-wpan/src/sub/mac.rs | |||
| @@ -4,67 +4,78 @@ use core::sync::atomic::{AtomicBool, Ordering}; | |||
| 4 | use core::task::Poll; | 4 | use core::task::Poll; |
| 5 | 5 | ||
| 6 | use embassy_futures::poll_once; | 6 | use embassy_futures::poll_once; |
| 7 | use embassy_stm32::ipcc::Ipcc; | 7 | use embassy_stm32::ipcc::{Ipcc, IpccRxChannel, IpccTxChannel}; |
| 8 | use embassy_sync::waitqueue::AtomicWaker; | 8 | use embassy_sync::waitqueue::AtomicWaker; |
| 9 | 9 | ||
| 10 | use crate::cmd::CmdPacket; | 10 | use crate::cmd::CmdPacket; |
| 11 | use crate::consts::TlPacketType; | 11 | use crate::consts::TlPacketType; |
| 12 | use crate::evt; | ||
| 12 | use crate::evt::{EvtBox, EvtPacket}; | 13 | use crate::evt::{EvtBox, EvtPacket}; |
| 13 | use crate::mac::commands::MacCommand; | 14 | use crate::mac::commands::MacCommand; |
| 14 | use crate::mac::event::MacEvent; | 15 | use crate::mac::event::MacEvent; |
| 15 | use crate::mac::typedefs::MacError; | 16 | use crate::mac::typedefs::MacError; |
| 16 | use crate::tables::{MAC_802_15_4_CMD_BUFFER, MAC_802_15_4_NOTIF_RSP_EVT_BUFFER}; | 17 | use crate::tables::{MAC_802_15_4_CMD_BUFFER, MAC_802_15_4_NOTIF_RSP_EVT_BUFFER}; |
| 17 | use crate::{channels, evt}; | 18 | use crate::unsafe_linked_list::LinkedListNode; |
| 18 | 19 | ||
| 19 | static MAC_WAKER: AtomicWaker = AtomicWaker::new(); | 20 | static MAC_WAKER: AtomicWaker = AtomicWaker::new(); |
| 20 | static MAC_EVT_OUT: AtomicBool = AtomicBool::new(false); | 21 | static MAC_EVT_OUT: AtomicBool = AtomicBool::new(false); |
| 21 | 22 | ||
| 22 | pub struct Mac { | 23 | pub struct Mac<'a> { |
| 23 | _private: (), | 24 | ipcc_mac_802_15_4_cmd_rsp_channel: IpccTxChannel<'a>, |
| 25 | ipcc_mac_802_15_4_notification_ack_channel: IpccRxChannel<'a>, | ||
| 24 | } | 26 | } |
| 25 | 27 | ||
| 26 | impl Mac { | 28 | impl<'a> Mac<'a> { |
| 27 | pub(crate) fn new() -> Self { | 29 | pub(crate) fn new( |
| 28 | Self { _private: () } | 30 | ipcc_mac_802_15_4_cmd_rsp_channel: IpccTxChannel<'a>, |
| 29 | } | 31 | ipcc_mac_802_15_4_notification_ack_channel: IpccRxChannel<'a>, |
| 30 | 32 | ) -> Self { | |
| 31 | pub const fn split(self) -> (MacRx, MacTx) { | 33 | use crate::tables::{ |
| 32 | (MacRx { _private: () }, MacTx { _private: () }) | 34 | MAC_802_15_4_CMD_BUFFER, MAC_802_15_4_NOTIF_RSP_EVT_BUFFER, Mac802_15_4Table, TL_MAC_802_15_4_TABLE, |
| 33 | } | 35 | TL_TRACES_TABLE, TRACES_EVT_QUEUE, TracesTable, |
| 34 | 36 | }; | |
| 35 | pub async fn tl_write_and_get_response(&self, opcode: u16, payload: &[u8]) -> u8 { | ||
| 36 | MacTx { _private: () }.tl_write_and_get_response(opcode, payload).await | ||
| 37 | } | ||
| 38 | |||
| 39 | pub async fn tl_write(&self, opcode: u16, payload: &[u8]) { | ||
| 40 | MacTx { _private: () }.tl_write(opcode, payload).await | ||
| 41 | } | ||
| 42 | |||
| 43 | pub async fn send_command<T>(&self, cmd: &T) -> Result<(), MacError> | ||
| 44 | where | ||
| 45 | T: MacCommand, | ||
| 46 | { | ||
| 47 | MacTx { _private: () }.send_command(cmd).await | ||
| 48 | } | ||
| 49 | 37 | ||
| 50 | pub async fn tl_read(&self) -> EvtBox<Mac> { | 38 | unsafe { |
| 51 | MacRx { _private: () }.tl_read().await | 39 | LinkedListNode::init_head(TRACES_EVT_QUEUE.as_mut_ptr() as *mut _); |
| 40 | |||
| 41 | TL_TRACES_TABLE.as_mut_ptr().write_volatile(TracesTable { | ||
| 42 | traces_queue: TRACES_EVT_QUEUE.as_ptr() as *const _, | ||
| 43 | }); | ||
| 44 | |||
| 45 | TL_MAC_802_15_4_TABLE.as_mut_ptr().write_volatile(Mac802_15_4Table { | ||
| 46 | p_cmdrsp_buffer: MAC_802_15_4_CMD_BUFFER.as_mut_ptr().cast(), | ||
| 47 | p_notack_buffer: MAC_802_15_4_NOTIF_RSP_EVT_BUFFER.as_mut_ptr().cast(), | ||
| 48 | evt_queue: core::ptr::null_mut(), | ||
| 49 | }); | ||
| 50 | }; | ||
| 51 | |||
| 52 | Self { | ||
| 53 | ipcc_mac_802_15_4_cmd_rsp_channel, | ||
| 54 | ipcc_mac_802_15_4_notification_ack_channel, | ||
| 55 | } | ||
| 52 | } | 56 | } |
| 53 | 57 | ||
| 54 | pub async fn read(&self) -> Result<MacEvent<'_>, ()> { | 58 | pub const fn split(self) -> (MacRx<'a>, MacTx<'a>) { |
| 55 | MacRx { _private: () }.read().await | 59 | ( |
| 60 | MacRx { | ||
| 61 | ipcc_mac_802_15_4_notification_ack_channel: self.ipcc_mac_802_15_4_notification_ack_channel, | ||
| 62 | }, | ||
| 63 | MacTx { | ||
| 64 | ipcc_mac_802_15_4_cmd_rsp_channel: self.ipcc_mac_802_15_4_cmd_rsp_channel, | ||
| 65 | }, | ||
| 66 | ) | ||
| 56 | } | 67 | } |
| 57 | } | 68 | } |
| 58 | 69 | ||
| 59 | pub struct MacTx { | 70 | pub struct MacTx<'a> { |
| 60 | _private: (), | 71 | ipcc_mac_802_15_4_cmd_rsp_channel: IpccTxChannel<'a>, |
| 61 | } | 72 | } |
| 62 | 73 | ||
| 63 | impl MacTx { | 74 | impl<'a> MacTx<'a> { |
| 64 | /// `HW_IPCC_MAC_802_15_4_CmdEvtNot` | 75 | /// `HW_IPCC_MAC_802_15_4_CmdEvtNot` |
| 65 | pub async fn tl_write_and_get_response(&self, opcode: u16, payload: &[u8]) -> u8 { | 76 | pub async fn tl_write_and_get_response(&mut self, opcode: u16, payload: &[u8]) -> u8 { |
| 66 | self.tl_write(opcode, payload).await; | 77 | self.tl_write(opcode, payload).await; |
| 67 | Ipcc::flush(channels::cpu1::IPCC_MAC_802_15_4_CMD_RSP_CHANNEL).await; | 78 | self.ipcc_mac_802_15_4_cmd_rsp_channel.flush().await; |
| 68 | 79 | ||
| 69 | unsafe { | 80 | unsafe { |
| 70 | let p_event_packet = MAC_802_15_4_CMD_BUFFER.as_ptr() as *const EvtPacket; | 81 | let p_event_packet = MAC_802_15_4_CMD_BUFFER.as_ptr() as *const EvtPacket; |
| @@ -75,19 +86,20 @@ impl MacTx { | |||
| 75 | } | 86 | } |
| 76 | 87 | ||
| 77 | /// `TL_MAC_802_15_4_SendCmd` | 88 | /// `TL_MAC_802_15_4_SendCmd` |
| 78 | pub async fn tl_write(&self, opcode: u16, payload: &[u8]) { | 89 | pub async fn tl_write(&mut self, opcode: u16, payload: &[u8]) { |
| 79 | Ipcc::send(channels::cpu1::IPCC_MAC_802_15_4_CMD_RSP_CHANNEL, || unsafe { | 90 | self.ipcc_mac_802_15_4_cmd_rsp_channel |
| 80 | CmdPacket::write_into( | 91 | .send(|| unsafe { |
| 81 | MAC_802_15_4_CMD_BUFFER.as_mut_ptr(), | 92 | CmdPacket::write_into( |
| 82 | TlPacketType::MacCmd, | 93 | MAC_802_15_4_CMD_BUFFER.as_mut_ptr(), |
| 83 | opcode, | 94 | TlPacketType::MacCmd, |
| 84 | payload, | 95 | opcode, |
| 85 | ); | 96 | payload, |
| 86 | }) | 97 | ); |
| 87 | .await; | 98 | }) |
| 99 | .await; | ||
| 88 | } | 100 | } |
| 89 | 101 | ||
| 90 | pub async fn send_command<T>(&self, cmd: &T) -> Result<(), MacError> | 102 | pub async fn send_command<T>(&mut self, cmd: &T) -> Result<(), MacError> |
| 91 | where | 103 | where |
| 92 | T: MacCommand, | 104 | T: MacCommand, |
| 93 | { | 105 | { |
| @@ -101,19 +113,19 @@ impl MacTx { | |||
| 101 | } | 113 | } |
| 102 | } | 114 | } |
| 103 | 115 | ||
| 104 | pub struct MacRx { | 116 | pub struct MacRx<'a> { |
| 105 | _private: (), | 117 | ipcc_mac_802_15_4_notification_ack_channel: IpccRxChannel<'a>, |
| 106 | } | 118 | } |
| 107 | 119 | ||
| 108 | impl MacRx { | 120 | impl<'a> MacRx<'a> { |
| 109 | /// `HW_IPCC_MAC_802_15_4_EvtNot` | 121 | /// `HW_IPCC_MAC_802_15_4_EvtNot` |
| 110 | /// | 122 | /// |
| 111 | /// This function will stall if the previous `EvtBox` has not been dropped | 123 | /// This function will stall if the previous `EvtBox` has not been dropped |
| 112 | pub async fn tl_read(&self) -> EvtBox<Mac> { | 124 | pub async fn tl_read(&mut self) -> EvtBox<MacRx<'a>> { |
| 113 | // Wait for the last event box to be dropped | 125 | // Wait for the last event box to be dropped |
| 114 | poll_fn(|cx| { | 126 | poll_fn(|cx| { |
| 115 | MAC_WAKER.register(cx.waker()); | 127 | MAC_WAKER.register(cx.waker()); |
| 116 | if MAC_EVT_OUT.load(Ordering::SeqCst) { | 128 | if MAC_EVT_OUT.load(Ordering::Acquire) { |
| 117 | Poll::Pending | 129 | Poll::Pending |
| 118 | } else { | 130 | } else { |
| 119 | Poll::Ready(()) | 131 | Poll::Ready(()) |
| @@ -122,22 +134,23 @@ impl MacRx { | |||
| 122 | .await; | 134 | .await; |
| 123 | 135 | ||
| 124 | // Return a new event box | 136 | // Return a new event box |
| 125 | Ipcc::receive(channels::cpu2::IPCC_MAC_802_15_4_NOTIFICATION_ACK_CHANNEL, || unsafe { | 137 | self.ipcc_mac_802_15_4_notification_ack_channel |
| 126 | // The closure is not async, therefore the closure must execute to completion (cannot be dropped) | 138 | .receive(|| unsafe { |
| 127 | // Therefore, the event box is guaranteed to be cleaned up if it's not leaked | 139 | // The closure is not async, therefore the closure must execute to completion (cannot be dropped) |
| 128 | MAC_EVT_OUT.store(true, Ordering::SeqCst); | 140 | // Therefore, the event box is guaranteed to be cleaned up if it's not leaked |
| 129 | 141 | MAC_EVT_OUT.store(true, Ordering::SeqCst); | |
| 130 | Some(EvtBox::new(MAC_802_15_4_NOTIF_RSP_EVT_BUFFER.as_mut_ptr() as *mut _)) | 142 | |
| 131 | }) | 143 | Some(EvtBox::new(MAC_802_15_4_NOTIF_RSP_EVT_BUFFER.as_mut_ptr() as *mut _)) |
| 132 | .await | 144 | }) |
| 145 | .await | ||
| 133 | } | 146 | } |
| 134 | 147 | ||
| 135 | pub async fn read(&self) -> Result<MacEvent<'_>, ()> { | 148 | pub async fn read<'b>(&mut self) -> Result<MacEvent<'b>, ()> { |
| 136 | MacEvent::new(self.tl_read().await) | 149 | MacEvent::new(self.tl_read().await) |
| 137 | } | 150 | } |
| 138 | } | 151 | } |
| 139 | 152 | ||
| 140 | impl evt::MemoryManager for Mac { | 153 | impl<'a> evt::MemoryManager for MacRx<'a> { |
| 141 | /// SAFETY: passing a pointer to something other than a managed event packet is UB | 154 | /// SAFETY: passing a pointer to something other than a managed event packet is UB |
| 142 | unsafe fn drop_event_packet(_: *mut EvtPacket) { | 155 | unsafe fn drop_event_packet(_: *mut EvtPacket) { |
| 143 | trace!("mac drop event"); | 156 | trace!("mac drop event"); |
| @@ -151,13 +164,10 @@ impl evt::MemoryManager for Mac { | |||
| 151 | ); | 164 | ); |
| 152 | 165 | ||
| 153 | // Clear the rx flag | 166 | // Clear the rx flag |
| 154 | let _ = poll_once(Ipcc::receive::<()>( | 167 | let _ = poll_once(Ipcc::receive::<()>(3, || None)); |
| 155 | channels::cpu2::IPCC_MAC_802_15_4_NOTIFICATION_ACK_CHANNEL, | ||
| 156 | || None, | ||
| 157 | )); | ||
| 158 | 168 | ||
| 159 | // Allow a new read call | 169 | // Allow a new read call |
| 160 | MAC_EVT_OUT.store(false, Ordering::SeqCst); | 170 | MAC_EVT_OUT.store(false, Ordering::Release); |
| 161 | MAC_WAKER.wake(); | 171 | MAC_WAKER.wake(); |
| 162 | } | 172 | } |
| 163 | } | 173 | } |
