aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src/ipcc.rs
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-stm32/src/ipcc.rs')
-rw-r--r--embassy-stm32/src/ipcc.rs178
1 files changed, 178 insertions, 0 deletions
diff --git a/embassy-stm32/src/ipcc.rs b/embassy-stm32/src/ipcc.rs
new file mode 100644
index 000000000..903aeca30
--- /dev/null
+++ b/embassy-stm32/src/ipcc.rs
@@ -0,0 +1,178 @@
1use embassy_hal_common::{into_ref, Peripheral, PeripheralRef};
2
3use crate::ipcc::sealed::Instance;
4use crate::peripherals::IPCC;
5use crate::rcc::sealed::RccPeripheral;
6
7#[non_exhaustive]
8#[derive(Clone, Copy, Default)]
9pub struct Config {
10 // TODO: add IPCC peripheral configuration, if any, here
11 // reserved for future use
12}
13
14#[derive(Debug, Clone, Copy)]
15#[repr(C)]
16pub enum IpccChannel {
17 Channel1 = 0,
18 Channel2 = 1,
19 Channel3 = 2,
20 Channel4 = 3,
21 Channel5 = 4,
22 Channel6 = 5,
23}
24
25pub(crate) mod sealed {
26 pub trait Instance: crate::rcc::RccPeripheral {
27 fn regs() -> crate::pac::ipcc::Ipcc;
28 fn set_cpu2(enabled: bool);
29 }
30}
31
32pub struct Ipcc<'d> {
33 _peri: PeripheralRef<'d, IPCC>,
34}
35
36impl<'d> Ipcc<'d> {
37 pub fn new(peri: impl Peripheral<P = IPCC> + 'd, _config: Config) -> Self {
38 into_ref!(peri);
39
40 Self { _peri: peri }
41 }
42
43 pub fn init(&mut self) {
44 IPCC::enable();
45 IPCC::reset();
46 IPCC::set_cpu2(true);
47
48 unsafe { _configure_pwr() };
49
50 let regs = IPCC::regs();
51
52 unsafe {
53 regs.cpu(0).cr().modify(|w| {
54 w.set_rxoie(true);
55 w.set_txfie(true);
56 })
57 }
58 }
59
60 pub fn c1_set_rx_channel(&mut self, channel: IpccChannel, enabled: bool) {
61 let regs = IPCC::regs();
62
63 // If bit is set to 1 then interrupt is disabled
64 unsafe { regs.cpu(0).mr().modify(|w| w.set_chom(channel as usize, !enabled)) }
65 }
66
67 pub fn c1_get_rx_channel(&self, channel: IpccChannel) -> bool {
68 let regs = IPCC::regs();
69
70 // If bit is set to 1 then interrupt is disabled
71 unsafe { !regs.cpu(0).mr().read().chom(channel as usize) }
72 }
73
74 pub fn c2_set_rx_channel(&mut self, channel: IpccChannel, enabled: bool) {
75 let regs = IPCC::regs();
76
77 // If bit is set to 1 then interrupt is disabled
78 unsafe { regs.cpu(1).mr().modify(|w| w.set_chom(channel as usize, !enabled)) }
79 }
80
81 pub fn c2_get_rx_channel(&self, channel: IpccChannel) -> bool {
82 let regs = IPCC::regs();
83
84 // If bit is set to 1 then interrupt is disabled
85 unsafe { !regs.cpu(1).mr().read().chom(channel as usize) }
86 }
87
88 pub fn c1_set_tx_channel(&mut self, channel: IpccChannel, enabled: bool) {
89 let regs = IPCC::regs();
90
91 // If bit is set to 1 then interrupt is disabled
92 unsafe { regs.cpu(0).mr().modify(|w| w.set_chfm(channel as usize, !enabled)) }
93 }
94
95 pub fn c1_get_tx_channel(&self, channel: IpccChannel) -> bool {
96 let regs = IPCC::regs();
97
98 // If bit is set to 1 then interrupt is disabled
99 unsafe { !regs.cpu(0).mr().read().chfm(channel as usize) }
100 }
101
102 pub fn c2_set_tx_channel(&mut self, channel: IpccChannel, enabled: bool) {
103 let regs = IPCC::regs();
104
105 // If bit is set to 1 then interrupt is disabled
106 unsafe { regs.cpu(1).mr().modify(|w| w.set_chfm(channel as usize, !enabled)) }
107 }
108
109 pub fn c2_get_tx_channel(&self, channel: IpccChannel) -> bool {
110 let regs = IPCC::regs();
111
112 // If bit is set to 1 then interrupt is disabled
113 unsafe { !regs.cpu(1).mr().read().chfm(channel as usize) }
114 }
115
116 /// clears IPCC receive channel status for CPU1
117 pub fn c1_clear_flag_channel(&mut self, channel: IpccChannel) {
118 let regs = IPCC::regs();
119
120 unsafe { regs.cpu(0).scr().write(|w| w.set_chc(channel as usize, true)) }
121 }
122
123 /// clears IPCC receive channel status for CPU2
124 pub fn c2_clear_flag_channel(&mut self, channel: IpccChannel) {
125 let regs = IPCC::regs();
126
127 unsafe { regs.cpu(1).scr().write(|w| w.set_chc(channel as usize, true)) }
128 }
129
130 pub fn c1_set_flag_channel(&mut self, channel: IpccChannel) {
131 let regs = IPCC::regs();
132
133 unsafe { regs.cpu(0).scr().write(|w| w.set_chs(channel as usize, true)) }
134 }
135
136 pub fn c2_set_flag_channel(&mut self, channel: IpccChannel) {
137 let regs = IPCC::regs();
138
139 unsafe { regs.cpu(1).scr().write(|w| w.set_chs(channel as usize, true)) }
140 }
141
142 pub fn c1_is_active_flag(&self, channel: IpccChannel) -> bool {
143 let regs = IPCC::regs();
144
145 unsafe { regs.cpu(0).sr().read().chf(channel as usize) }
146 }
147
148 pub fn c2_is_active_flag(&self, channel: IpccChannel) -> bool {
149 let regs = IPCC::regs();
150
151 unsafe { regs.cpu(1).sr().read().chf(channel as usize) }
152 }
153
154 pub fn is_tx_pending(&self, channel: IpccChannel) -> bool {
155 !self.c1_is_active_flag(channel) && self.c1_get_tx_channel(channel)
156 }
157
158 pub fn is_rx_pending(&self, channel: IpccChannel) -> bool {
159 self.c2_is_active_flag(channel) && self.c1_get_rx_channel(channel)
160 }
161}
162
163impl sealed::Instance for crate::peripherals::IPCC {
164 fn regs() -> crate::pac::ipcc::Ipcc {
165 crate::pac::IPCC
166 }
167
168 fn set_cpu2(enabled: bool) {
169 unsafe { crate::pac::PWR.cr4().modify(|w| w.set_c2boot(enabled)) }
170 }
171}
172
173unsafe fn _configure_pwr() {
174 let rcc = crate::pac::RCC;
175
176 // set RF wake-up clock = LSE
177 rcc.csr().modify(|w| w.set_rfwkpsel(0b01));
178}