aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src/ipcc.rs
diff options
context:
space:
mode:
authorgoueslati <[email protected]>2023-06-12 12:27:51 +0100
committergoueslati <[email protected]>2023-06-12 12:27:51 +0100
commitca8957da435eb91242fa33eb986e80a33bbc4da0 (patch)
tree89b66bdff52630cd4ef1d609122c2b04417ccd73 /embassy-stm32/src/ipcc.rs
parentce1d72c609ae1e04410e68458ec3d6c36c7dae27 (diff)
stm32/ipcc: move tl_mbox into `embassy-stm32-wpan`
Diffstat (limited to 'embassy-stm32/src/ipcc.rs')
-rw-r--r--embassy-stm32/src/ipcc.rs234
1 files changed, 234 insertions, 0 deletions
diff --git a/embassy-stm32/src/ipcc.rs b/embassy-stm32/src/ipcc.rs
new file mode 100644
index 000000000..8bb0774b8
--- /dev/null
+++ b/embassy-stm32/src/ipcc.rs
@@ -0,0 +1,234 @@
1use self::sealed::Instance;
2use crate::peripherals::IPCC;
3use crate::rcc::sealed::RccPeripheral;
4
5#[non_exhaustive]
6#[derive(Clone, Copy, Default)]
7pub struct Config {
8 // TODO: add IPCC peripheral configuration, if any, here
9 // reserved for future use
10}
11
12#[derive(Debug, Clone, Copy)]
13#[repr(C)]
14pub enum IpccChannel {
15 Channel1 = 0,
16 Channel2 = 1,
17 Channel3 = 2,
18 Channel4 = 3,
19 Channel5 = 4,
20 Channel6 = 5,
21}
22
23pub mod sealed {
24 pub trait Instance: crate::rcc::RccPeripheral {
25 fn regs() -> crate::pac::ipcc::Ipcc;
26 fn set_cpu2(enabled: bool);
27 }
28}
29
30pub struct Ipcc;
31
32impl Ipcc {
33 pub fn enable(_config: Config) {
34 IPCC::enable();
35 IPCC::reset();
36 IPCC::set_cpu2(true);
37
38 unsafe { _configure_pwr() };
39
40 let regs = IPCC::regs();
41
42 unsafe {
43 regs.cpu(0).cr().modify(|w| {
44 w.set_rxoie(true);
45 w.set_txfie(true);
46 })
47 }
48 }
49
50 pub fn c1_set_rx_channel(channel: IpccChannel, enabled: bool) {
51 let regs = IPCC::regs();
52
53 // If bit is set to 1 then interrupt is disabled
54 unsafe { regs.cpu(0).mr().modify(|w| w.set_chom(channel as usize, !enabled)) }
55 }
56
57 pub fn c1_get_rx_channel(channel: IpccChannel) -> bool {
58 let regs = IPCC::regs();
59
60 // If bit is set to 1 then interrupt is disabled
61 unsafe { !regs.cpu(0).mr().read().chom(channel as usize) }
62 }
63
64 #[allow(dead_code)]
65 pub fn c2_set_rx_channel(channel: IpccChannel, enabled: bool) {
66 let regs = IPCC::regs();
67
68 // If bit is set to 1 then interrupt is disabled
69 unsafe { regs.cpu(1).mr().modify(|w| w.set_chom(channel as usize, !enabled)) }
70 }
71
72 #[allow(dead_code)]
73 pub fn c2_get_rx_channel(channel: IpccChannel) -> bool {
74 let regs = IPCC::regs();
75
76 // If bit is set to 1 then interrupt is disabled
77 unsafe { !regs.cpu(1).mr().read().chom(channel as usize) }
78 }
79
80 pub fn c1_set_tx_channel(channel: IpccChannel, enabled: bool) {
81 let regs = IPCC::regs();
82
83 // If bit is set to 1 then interrupt is disabled
84 unsafe { regs.cpu(0).mr().modify(|w| w.set_chfm(channel as usize, !enabled)) }
85 }
86
87 pub fn c1_get_tx_channel(channel: IpccChannel) -> bool {
88 let regs = IPCC::regs();
89
90 // If bit is set to 1 then interrupt is disabled
91 unsafe { !regs.cpu(0).mr().read().chfm(channel as usize) }
92 }
93
94 #[allow(dead_code)]
95 pub fn c2_set_tx_channel(channel: IpccChannel, enabled: bool) {
96 let regs = IPCC::regs();
97
98 // If bit is set to 1 then interrupt is disabled
99 unsafe { regs.cpu(1).mr().modify(|w| w.set_chfm(channel as usize, !enabled)) }
100 }
101
102 #[allow(dead_code)]
103 pub fn c2_get_tx_channel(channel: IpccChannel) -> bool {
104 let regs = IPCC::regs();
105
106 // If bit is set to 1 then interrupt is disabled
107 unsafe { !regs.cpu(1).mr().read().chfm(channel as usize) }
108 }
109
110 /// clears IPCC receive channel status for CPU1
111 pub fn c1_clear_flag_channel(channel: IpccChannel) {
112 let regs = IPCC::regs();
113
114 unsafe { regs.cpu(0).scr().write(|w| w.set_chc(channel as usize, true)) }
115 }
116
117 #[allow(dead_code)]
118 /// clears IPCC receive channel status for CPU2
119 pub fn c2_clear_flag_channel(channel: IpccChannel) {
120 let regs = IPCC::regs();
121
122 unsafe { regs.cpu(1).scr().write(|w| w.set_chc(channel as usize, true)) }
123 }
124
125 pub fn c1_set_flag_channel(channel: IpccChannel) {
126 let regs = IPCC::regs();
127
128 unsafe { regs.cpu(0).scr().write(|w| w.set_chs(channel as usize, true)) }
129 }
130
131 #[allow(dead_code)]
132 pub fn c2_set_flag_channel(channel: IpccChannel) {
133 let regs = IPCC::regs();
134
135 unsafe { regs.cpu(1).scr().write(|w| w.set_chs(channel as usize, true)) }
136 }
137
138 pub fn c1_is_active_flag(channel: IpccChannel) -> bool {
139 let regs = IPCC::regs();
140
141 unsafe { regs.cpu(0).sr().read().chf(channel as usize) }
142 }
143
144 pub fn c2_is_active_flag(channel: IpccChannel) -> bool {
145 let regs = IPCC::regs();
146
147 unsafe { regs.cpu(1).sr().read().chf(channel as usize) }
148 }
149
150 pub fn is_tx_pending(channel: IpccChannel) -> bool {
151 !Self::c1_is_active_flag(channel) && Self::c1_get_tx_channel(channel)
152 }
153
154 pub fn is_rx_pending(channel: IpccChannel) -> bool {
155 Self::c2_is_active_flag(channel) && Self::c1_get_rx_channel(channel)
156 }
157}
158
159impl sealed::Instance for crate::peripherals::IPCC {
160 fn regs() -> crate::pac::ipcc::Ipcc {
161 crate::pac::IPCC
162 }
163
164 fn set_cpu2(enabled: bool) {
165 unsafe { crate::pac::PWR.cr4().modify(|w| w.set_c2boot(enabled)) }
166 }
167}
168
169unsafe fn _configure_pwr() {
170 let pwr = crate::pac::PWR;
171 let rcc = crate::pac::RCC;
172
173 rcc.cfgr().modify(|w| w.set_stopwuck(true));
174
175 pwr.cr1().modify(|w| w.set_dbp(true));
176 pwr.cr1().modify(|w| w.set_dbp(true));
177
178 // configure LSE
179 rcc.bdcr().modify(|w| w.set_lseon(true));
180
181 // select system clock source = PLL
182 // set PLL coefficients
183 // m: 2,
184 // n: 12,
185 // r: 3,
186 // q: 4,
187 // p: 3,
188 let src_bits = 0b11;
189 let pllp = (3 - 1) & 0b11111;
190 let pllq = (4 - 1) & 0b111;
191 let pllr = (3 - 1) & 0b111;
192 let plln = 12 & 0b1111111;
193 let pllm = (2 - 1) & 0b111;
194 rcc.pllcfgr().modify(|w| {
195 w.set_pllsrc(src_bits);
196 w.set_pllm(pllm);
197 w.set_plln(plln);
198 w.set_pllr(pllr);
199 w.set_pllp(pllp);
200 w.set_pllpen(true);
201 w.set_pllq(pllq);
202 w.set_pllqen(true);
203 });
204 // enable PLL
205 rcc.cr().modify(|w| w.set_pllon(true));
206 rcc.cr().write(|w| w.set_hsion(false));
207 // while !rcc.cr().read().pllrdy() {}
208
209 // configure SYSCLK mux to use PLL clocl
210 rcc.cfgr().modify(|w| w.set_sw(0b11));
211
212 // configure CPU1 & CPU2 dividers
213 rcc.cfgr().modify(|w| w.set_hpre(0)); // not divided
214 rcc.extcfgr().modify(|w| {
215 w.set_c2hpre(0b1000); // div2
216 w.set_shdhpre(0); // not divided
217 });
218
219 // apply APB1 / APB2 values
220 rcc.cfgr().modify(|w| {
221 w.set_ppre1(0b000); // not divided
222 w.set_ppre2(0b000); // not divided
223 });
224
225 // TODO: required
226 // set RF wake-up clock = LSE
227 rcc.csr().modify(|w| w.set_rfwkpsel(0b01));
228
229 // set LPTIM1 & LPTIM2 clock source
230 rcc.ccipr().modify(|w| {
231 w.set_lptim1sel(0b00); // PCLK
232 w.set_lptim2sel(0b00); // PCLK
233 });
234}