1use portable_atomic::{AtomicBool, Ordering};
2
3use crate::{
4 asynch::AtomicWaker,
5 dma::*,
6 interrupt::Priority,
7 peripherals::{DMA_CRYPTO, Interrupt},
8};
9
10pub(super) type CryptoRegisterBlock = crate::pac::crypto_dma::RegisterBlock;
11
12#[derive(Debug)]
14#[cfg_attr(feature = "defmt", derive(defmt::Format))]
15pub struct CryptoDmaRxChannel<'d>(pub(crate) DMA_CRYPTO<'d>);
16
17impl CryptoDmaRxChannel<'_> {
18 fn regs(&self) -> &CryptoRegisterBlock {
19 self.0.register_block()
20 }
21}
22
23impl crate::private::Sealed for CryptoDmaRxChannel<'_> {}
24impl DmaRxChannel for CryptoDmaRxChannel<'_> {}
25
26#[derive(Debug)]
28#[cfg_attr(feature = "defmt", derive(defmt::Format))]
29pub struct CryptoDmaTxChannel<'d>(pub(crate) DMA_CRYPTO<'d>);
30
31impl CryptoDmaTxChannel<'_> {
32 fn regs(&self) -> &CryptoRegisterBlock {
33 self.0.register_block()
34 }
35}
36
37impl crate::private::Sealed for CryptoDmaTxChannel<'_> {}
38impl DmaTxChannel for CryptoDmaTxChannel<'_> {}
39
40impl RegisterAccess for CryptoDmaTxChannel<'_> {
41 fn reset(&self) {
42 self.regs().conf().modify(|_, w| {
43 w.out_rst().set_bit();
44 w.ahbm_rst().set_bit();
45 w.ahbm_fifo_rst().set_bit()
46 });
47 self.regs().conf().modify(|_, w| {
48 w.out_rst().clear_bit();
49 w.ahbm_rst().clear_bit();
50 w.ahbm_fifo_rst().clear_bit()
51 });
52 }
53
54 fn set_burst_mode(&self, burst_mode: BurstConfig) {
55 self.regs()
56 .conf()
57 .modify(|_, w| w.out_data_burst_en().bit(burst_mode.is_burst_enabled()));
58 }
59
60 fn set_descr_burst_mode(&self, burst_mode: bool) {
61 self.regs()
62 .conf()
63 .modify(|_, w| w.outdscr_burst_en().bit(burst_mode));
64 }
65
66 fn set_peripheral(&self, peripheral: u8) {
67 use esp32s2::crypto_dma::aes_sha_select::SELECT;
68 let peripheral = match peripheral {
69 p if p == DmaPeripheral::Aes as u8 => SELECT::Aes,
70 p if p == DmaPeripheral::Sha as u8 => SELECT::Sha,
71 _ => unreachable!(),
72 };
73 self.regs()
74 .aes_sha_select()
75 .modify(|_, w| w.select().variant(peripheral));
76 }
77
78 fn set_link_addr(&self, address: u32) {
79 self.regs()
80 .out_link()
81 .modify(|_, w| unsafe { w.outlink_addr().bits(address) });
82 }
83
84 fn start(&self) {
85 self.regs()
86 .out_link()
87 .modify(|_, w| w.outlink_start().set_bit());
88 }
89
90 fn stop(&self) {
91 self.regs()
92 .out_link()
93 .modify(|_, w| w.outlink_stop().set_bit());
94 }
95
96 fn restart(&self) {
97 self.regs()
98 .out_link()
99 .modify(|_, w| w.outlink_restart().set_bit());
100 }
101
102 fn set_check_owner(&self, check_owner: Option<bool>) {
103 if check_owner == Some(true) {
104 panic!("Crypto DMA does not support checking descriptor ownership");
105 }
106 }
107
108 fn is_compatible_with(&self, peripheral: DmaPeripheral) -> bool {
109 self.0.is_compatible_with(peripheral)
110 }
111
112 #[cfg(psram_dma)]
113 fn set_ext_mem_block_size(&self, size: DmaExtMemBKSize) {
114 self.regs()
115 .conf1()
116 .modify(|_, w| unsafe { w.ext_mem_bk_size().bits(size as u8) });
117 }
118
119 #[cfg(psram_dma)]
120 fn can_access_psram(&self) -> bool {
121 true
122 }
123}
124
125impl TxRegisterAccess for CryptoDmaTxChannel<'_> {
126 fn is_fifo_empty(&self) -> bool {
127 self.regs().state1().read().outfifo_cnt_debug().bits() == 0
128 }
129
130 fn set_auto_write_back(&self, enable: bool) {
131 self.regs()
132 .conf()
133 .modify(|_, w| w.out_auto_wrback().bit(enable));
134 }
135
136 fn last_dscr_address(&self) -> usize {
137 self.regs()
138 .out_eof_des_addr()
139 .read()
140 .out_eof_des_addr()
141 .bits() as usize
142 }
143
144 fn peripheral_interrupt(&self) -> Option<Interrupt> {
145 None
146 }
147
148 fn async_handler(&self) -> Option<InterruptHandler> {
149 None
150 }
151}
152
153impl InterruptAccess<DmaTxInterrupt> for CryptoDmaTxChannel<'_> {
154 fn enable_listen(&self, interrupts: EnumSet<DmaTxInterrupt>, enable: bool) {
155 self.regs().int_ena().modify(|_, w| {
156 for interrupt in interrupts {
157 match interrupt {
158 DmaTxInterrupt::TotalEof => w.out_total_eof().bit(enable),
159 DmaTxInterrupt::DescriptorError => w.out_dscr_err().bit(enable),
160 DmaTxInterrupt::Eof => w.out_eof().bit(enable),
161 DmaTxInterrupt::Done => w.out_done().bit(enable),
162 };
163 }
164 w
165 });
166 }
167
168 fn is_listening(&self) -> EnumSet<DmaTxInterrupt> {
169 let mut result = EnumSet::new();
170
171 let int_ena = self.regs().int_ena().read();
172 if int_ena.out_total_eof().bit_is_set() {
173 result |= DmaTxInterrupt::TotalEof;
174 }
175 if int_ena.out_dscr_err().bit_is_set() {
176 result |= DmaTxInterrupt::DescriptorError;
177 }
178 if int_ena.out_eof().bit_is_set() {
179 result |= DmaTxInterrupt::Eof;
180 }
181 if int_ena.out_done().bit_is_set() {
182 result |= DmaTxInterrupt::Done;
183 }
184
185 result
186 }
187
188 fn clear(&self, interrupts: impl Into<EnumSet<DmaTxInterrupt>>) {
189 self.regs().int_clr().write(|w| {
190 for interrupt in interrupts.into() {
191 match interrupt {
192 DmaTxInterrupt::TotalEof => w.out_total_eof().clear_bit_by_one(),
193 DmaTxInterrupt::DescriptorError => w.out_dscr_err().clear_bit_by_one(),
194 DmaTxInterrupt::Eof => w.out_eof().clear_bit_by_one(),
195 DmaTxInterrupt::Done => w.out_done().clear_bit_by_one(),
196 };
197 }
198 w
199 });
200 }
201
202 fn pending_interrupts(&self) -> EnumSet<DmaTxInterrupt> {
203 let mut result = EnumSet::new();
204
205 let int_raw = self.regs().int_raw().read();
206 if int_raw.out_total_eof().bit_is_set() {
207 result |= DmaTxInterrupt::TotalEof;
208 }
209 if int_raw.out_dscr_err().bit_is_set() {
210 result |= DmaTxInterrupt::DescriptorError;
211 }
212 if int_raw.out_eof().bit_is_set() {
213 result |= DmaTxInterrupt::Eof;
214 }
215 if int_raw.out_done().bit_is_set() {
216 result |= DmaTxInterrupt::Done;
217 }
218
219 result
220 }
221
222 fn waker(&self) -> &'static AtomicWaker {
223 self.0.tx_waker()
224 }
225
226 fn is_async(&self) -> bool {
227 self.0.tx_async_flag().load(Ordering::Acquire)
228 }
229
230 fn set_async(&self, is_async: bool) {
231 self.0.tx_async_flag().store(is_async, Ordering::Release);
232 }
233}
234
235impl RegisterAccess for CryptoDmaRxChannel<'_> {
236 fn reset(&self) {
237 self.regs().conf().modify(|_, w| {
238 w.in_rst().set_bit();
239 w.ahbm_rst().set_bit();
240 w.ahbm_fifo_rst().set_bit()
241 });
242 self.regs().conf().modify(|_, w| {
243 w.in_rst().clear_bit();
244 w.ahbm_rst().clear_bit();
245 w.ahbm_fifo_rst().clear_bit()
246 });
247 }
248
249 fn set_burst_mode(&self, _burst_mode: BurstConfig) {}
250
251 fn set_descr_burst_mode(&self, burst_mode: bool) {
252 self.regs()
253 .conf()
254 .modify(|_, w| w.indscr_burst_en().bit(burst_mode));
255 }
256
257 fn set_peripheral(&self, peripheral: u8) {
258 use esp32s2::crypto_dma::aes_sha_select::SELECT;
259 let peripheral = match peripheral {
260 p if p == DmaPeripheral::Aes as u8 => SELECT::Aes,
261 p if p == DmaPeripheral::Sha as u8 => SELECT::Sha,
262 _ => unreachable!(),
263 };
264 self.regs()
265 .aes_sha_select()
266 .modify(|_, w| w.select().variant(peripheral));
267 }
268
269 fn set_link_addr(&self, address: u32) {
270 self.regs()
271 .in_link()
272 .modify(|_, w| unsafe { w.inlink_addr().bits(address) });
273 }
274
275 fn start(&self) {
276 self.regs()
277 .in_link()
278 .modify(|_, w| w.inlink_start().set_bit());
279 }
280
281 fn stop(&self) {
282 self.regs()
283 .in_link()
284 .modify(|_, w| w.inlink_stop().set_bit());
285 }
286
287 fn restart(&self) {
288 self.regs()
289 .in_link()
290 .modify(|_, w| w.inlink_restart().set_bit());
291 }
292
293 fn set_check_owner(&self, check_owner: Option<bool>) {
294 if check_owner == Some(true) {
295 panic!("Crypto DMA does not support checking descriptor ownership");
296 }
297 }
298
299 fn is_compatible_with(&self, peripheral: DmaPeripheral) -> bool {
300 self.0.is_compatible_with(peripheral)
301 }
302
303 #[cfg(psram_dma)]
304 fn set_ext_mem_block_size(&self, size: DmaExtMemBKSize) {
305 self.regs()
306 .conf1()
307 .modify(|_, w| unsafe { w.ext_mem_bk_size().bits(size as u8) });
308 }
309
310 #[cfg(psram_dma)]
311 fn can_access_psram(&self) -> bool {
312 true
313 }
314}
315
316impl RxRegisterAccess for CryptoDmaRxChannel<'_> {
317 fn peripheral_interrupt(&self) -> Option<Interrupt> {
318 None
321 }
322
323 fn async_handler(&self) -> Option<InterruptHandler> {
324 None
325 }
326}
327
328impl InterruptAccess<DmaRxInterrupt> for CryptoDmaRxChannel<'_> {
329 fn enable_listen(&self, interrupts: EnumSet<DmaRxInterrupt>, enable: bool) {
330 self.regs().int_ena().modify(|_, w| {
331 for interrupt in interrupts {
332 match interrupt {
333 DmaRxInterrupt::SuccessfulEof => w.in_suc_eof().bit(enable),
334 DmaRxInterrupt::ErrorEof => w.in_err_eof().bit(enable),
335 DmaRxInterrupt::DescriptorError => w.in_dscr_err().bit(enable),
336 DmaRxInterrupt::DescriptorEmpty => w.in_dscr_empty().bit(enable),
337 DmaRxInterrupt::Done => w.in_done().bit(enable),
338 };
339 }
340 w
341 });
342 }
343
344 fn is_listening(&self) -> EnumSet<DmaRxInterrupt> {
345 let mut result = EnumSet::new();
346
347 let int_ena = self.regs().int_ena().read();
348 if int_ena.in_dscr_err().bit_is_set() {
349 result |= DmaRxInterrupt::DescriptorError;
350 }
351 if int_ena.in_dscr_err().bit_is_set() {
352 result |= DmaRxInterrupt::DescriptorEmpty;
353 }
354 if int_ena.in_suc_eof().bit_is_set() {
355 result |= DmaRxInterrupt::SuccessfulEof;
356 }
357 if int_ena.in_err_eof().bit_is_set() {
358 result |= DmaRxInterrupt::ErrorEof;
359 }
360 if int_ena.in_done().bit_is_set() {
361 result |= DmaRxInterrupt::Done;
362 }
363
364 result
365 }
366
367 fn clear(&self, interrupts: impl Into<EnumSet<DmaRxInterrupt>>) {
368 self.regs().int_clr().write(|w| {
369 for interrupt in interrupts.into() {
370 match interrupt {
371 DmaRxInterrupt::SuccessfulEof => w.in_suc_eof().clear_bit_by_one(),
372 DmaRxInterrupt::ErrorEof => w.in_err_eof().clear_bit_by_one(),
373 DmaRxInterrupt::DescriptorError => w.in_dscr_err().clear_bit_by_one(),
374 DmaRxInterrupt::DescriptorEmpty => w.in_dscr_empty().clear_bit_by_one(),
375 DmaRxInterrupt::Done => w.in_done().clear_bit_by_one(),
376 };
377 }
378 w
379 });
380 }
381
382 fn pending_interrupts(&self) -> EnumSet<DmaRxInterrupt> {
383 let mut result = EnumSet::new();
384
385 let int_raw = self.regs().int_raw().read();
386 if int_raw.in_dscr_err().bit_is_set() {
387 result |= DmaRxInterrupt::DescriptorError;
388 }
389 if int_raw.in_dscr_empty().bit_is_set() {
390 result |= DmaRxInterrupt::DescriptorEmpty;
391 }
392 if int_raw.in_suc_eof().bit_is_set() {
393 result |= DmaRxInterrupt::SuccessfulEof;
394 }
395 if int_raw.in_err_eof().bit_is_set() {
396 result |= DmaRxInterrupt::ErrorEof;
397 }
398 if int_raw.in_done().bit_is_set() {
399 result |= DmaRxInterrupt::Done;
400 }
401
402 result
403 }
404
405 fn waker(&self) -> &'static AtomicWaker {
406 self.0.rx_waker()
407 }
408
409 fn is_async(&self) -> bool {
410 self.0.rx_async_flag().load(Ordering::Relaxed)
411 }
412
413 fn set_async(&self, _is_async: bool) {
414 self.0.rx_async_flag().store(_is_async, Ordering::Relaxed);
415 }
416}
417
418impl<'d> DmaChannel for DMA_CRYPTO<'d> {
419 type Rx = CryptoDmaRxChannel<'d>;
420 type Tx = CryptoDmaTxChannel<'d>;
421 unsafe fn split_internal(self, _: crate::private::Internal) -> (Self::Rx, Self::Tx) {
422 (
423 CryptoDmaRxChannel(unsafe { Self::steal() }),
424 CryptoDmaTxChannel(unsafe { Self::steal() }),
425 )
426 }
427}
428impl DmaChannelExt for DMA_CRYPTO<'_> {
429 fn rx_interrupts() -> impl InterruptAccess<DmaRxInterrupt> {
430 CryptoDmaRxChannel(unsafe { Self::steal() })
431 }
432 fn tx_interrupts() -> impl InterruptAccess<DmaTxInterrupt> {
433 CryptoDmaTxChannel(unsafe { Self::steal() })
434 }
435}
436impl PdmaChannel for DMA_CRYPTO<'_> {
437 type RegisterBlock = CryptoRegisterBlock;
438 fn register_block(&self) -> &Self::RegisterBlock {
439 DMA_CRYPTO::regs()
440 }
441 fn tx_waker(&self) -> &'static AtomicWaker {
442 static WAKER: AtomicWaker = AtomicWaker::new();
443 &WAKER
444 }
445 fn rx_waker(&self) -> &'static AtomicWaker {
446 static WAKER: AtomicWaker = AtomicWaker::new();
447 &WAKER
448 }
449 fn is_compatible_with(&self, peripheral: DmaPeripheral) -> bool {
450 let compatible_peripherals = [DmaPeripheral::Aes, DmaPeripheral::Sha];
451 compatible_peripherals.contains(&peripheral)
452 }
453 fn peripheral_interrupt(&self) -> Interrupt {
454 Interrupt::CRYPTO_DMA
455 }
456 fn async_handler(&self) -> InterruptHandler {
457 pub(crate) extern "C" fn __esp_hal_internal_interrupt_handler() {
458 super::asynch::handle_in_interrupt::<DMA_CRYPTO<'static>>();
459 super::asynch::handle_out_interrupt::<DMA_CRYPTO<'static>>();
460 }
461 #[allow(non_upper_case_globals)]
462 pub(crate) static interrupt_handler: crate::interrupt::InterruptHandler =
463 crate::interrupt::InterruptHandler::new(
464 __esp_hal_internal_interrupt_handler,
465 Priority::max(),
466 );
467 interrupt_handler
468 }
469 fn rx_async_flag(&self) -> &'static AtomicBool {
470 static FLAG: AtomicBool = AtomicBool::new(false);
471 &FLAG
472 }
473 fn tx_async_flag(&self) -> &'static AtomicBool {
474 static FLAG: AtomicBool = AtomicBool::new(false);
475 &FLAG
476 }
477}
478impl<'d> DmaChannelConvert<CryptoDmaRxChannel<'d>> for DMA_CRYPTO<'d> {
479 fn degrade(self) -> CryptoDmaRxChannel<'d> {
480 CryptoDmaRxChannel(self)
481 }
482}
483impl<'d> DmaChannelConvert<CryptoDmaTxChannel<'d>> for DMA_CRYPTO<'d> {
484 fn degrade(self) -> CryptoDmaTxChannel<'d> {
485 CryptoDmaTxChannel(self)
486 }
487}