Skip to content

Commit 3f364bc

Browse files
committed
stm32: cordic: merge per-call CSR writes into single register access
1 parent 17f06ca commit 3f364bc

File tree

1 file changed

+80
-148
lines changed
  • embassy-stm32/src/cordic

1 file changed

+80
-148
lines changed

embassy-stm32/src/cordic/mod.rs

Lines changed: 80 additions & 148 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//! coordinate rotation digital computer (CORDIC)
1+
//! Coordinate Rotation Digital Computer (CORDIC)
22
33
use embassy_hal_internal::drop::OnDrop;
44
use embassy_hal_internal::{Peri, PeripheralType};
@@ -25,100 +25,6 @@ trait SealedInstance {
2525
/// Get access to CORDIC registers
2626
fn regs() -> crate::pac::cordic::Cordic;
2727

28-
/// Set Function value
29-
fn set_func(&self, func: Function) {
30-
Self::regs()
31-
.csr()
32-
.modify(|v| v.set_func(vals::Func::from_bits(func as u8)));
33-
}
34-
35-
/// Set Precision value
36-
fn set_precision(&self, precision: Precision) {
37-
Self::regs()
38-
.csr()
39-
.modify(|v| v.set_precision(vals::Precision::from_bits(precision as u8)))
40-
}
41-
42-
/// Set Scale value
43-
fn set_scale(&self, scale: Scale) {
44-
Self::regs()
45-
.csr()
46-
.modify(|v| v.set_scale(vals::Scale::from_bits(scale as u8)))
47-
}
48-
49-
/// Enable global interrupt
50-
#[allow(unused)]
51-
fn enable_irq(&self) {
52-
Self::regs().csr().modify(|v| v.set_ien(true))
53-
}
54-
55-
/// Disable global interrupt
56-
fn disable_irq(&self) {
57-
Self::regs().csr().modify(|v| v.set_ien(false))
58-
}
59-
60-
/// Enable Read DMA
61-
fn enable_read_dma(&self) {
62-
Self::regs().csr().modify(|v| {
63-
v.set_dmaren(true);
64-
})
65-
}
66-
67-
/// Disable Read DMA
68-
fn disable_read_dma(&self) {
69-
Self::regs().csr().modify(|v| {
70-
v.set_dmaren(false);
71-
})
72-
}
73-
74-
/// Enable Write DMA
75-
fn enable_write_dma(&self) {
76-
Self::regs().csr().modify(|v| {
77-
v.set_dmawen(true);
78-
})
79-
}
80-
81-
/// Disable Write DMA
82-
fn disable_write_dma(&self) {
83-
Self::regs().csr().modify(|v| {
84-
v.set_dmawen(false);
85-
})
86-
}
87-
88-
/// Set NARGS value
89-
fn set_argument_count(&self, n: AccessCount) {
90-
Self::regs().csr().modify(|v| {
91-
v.set_nargs(match n {
92-
AccessCount::One => vals::Num::NUM1,
93-
AccessCount::Two => vals::Num::NUM2,
94-
})
95-
})
96-
}
97-
98-
/// Set NRES value
99-
fn set_result_count(&self, n: AccessCount) {
100-
Self::regs().csr().modify(|v| {
101-
v.set_nres(match n {
102-
AccessCount::One => vals::Num::NUM1,
103-
AccessCount::Two => vals::Num::NUM2,
104-
});
105-
})
106-
}
107-
108-
/// Set ARGSIZE and RESSIZE value
109-
fn set_data_width(&self, arg: Width, res: Width) {
110-
Self::regs().csr().modify(|v| {
111-
v.set_argsize(match arg {
112-
Width::Bits32 => vals::Size::BITS32,
113-
Width::Bits16 => vals::Size::BITS16,
114-
});
115-
v.set_ressize(match res {
116-
Width::Bits32 => vals::Size::BITS32,
117-
Width::Bits16 => vals::Size::BITS16,
118-
})
119-
})
120-
}
121-
12228
/// Read RRDY flag
12329
fn ready_to_read(&self) -> bool {
12430
Self::regs().csr().read().rrdy()
@@ -216,8 +122,20 @@ impl<'d, T: Instance> Cordic<'d, T> {
216122

217123
/// Set extra config for data count and data width.
218124
pub fn extra_config(&mut self, arg_cnt: AccessCount, arg_width: Width, res_width: Width) {
219-
self.peri.set_argument_count(arg_cnt);
220-
self.peri.set_data_width(arg_width, res_width);
125+
T::regs().csr().modify(|v| {
126+
v.set_nargs(match arg_cnt {
127+
AccessCount::One => vals::Num::NUM1,
128+
AccessCount::Two => vals::Num::NUM2,
129+
});
130+
v.set_argsize(match arg_width {
131+
Width::Bits32 => vals::Size::BITS32,
132+
Width::Bits16 => vals::Size::BITS16,
133+
});
134+
v.set_ressize(match res_width {
135+
Width::Bits32 => vals::Size::BITS32,
136+
Width::Bits16 => vals::Size::BITS16,
137+
});
138+
});
221139
}
222140

223141
fn clean_rrdy_flag(&mut self) {
@@ -228,27 +146,33 @@ impl<'d, T: Instance> Cordic<'d, T> {
228146

229147
/// Disable IRQ and DMA, clean RRDY, and set ARG2 to +1 (0x7FFFFFFF)
230148
pub fn reconfigure(&mut self) {
231-
// reset ARG2 to +1
232-
{
233-
self.peri.disable_irq();
234-
self.peri.disable_read_dma();
235-
self.peri.disable_write_dma();
236-
self.clean_rrdy_flag();
237-
238-
self.peri.set_func(Function::Cos);
239-
self.peri.set_precision(Precision::Iters4);
240-
self.peri.set_scale(Scale::Arg1Res1);
241-
self.peri.set_argument_count(AccessCount::Two);
242-
self.peri.set_data_width(Width::Bits32, Width::Bits32);
243-
self.peri.write_argument(0x0u32);
244-
self.peri.write_argument(0x7FFFFFFFu32);
245-
246-
self.clean_rrdy_flag();
247-
}
248-
249-
self.peri.set_func(self.config.function);
250-
self.peri.set_precision(self.config.precision);
251-
self.peri.set_scale(self.config.scale);
149+
// Disable IRQ and DMA first
150+
T::regs().csr().modify(|v| {
151+
v.set_ien(false);
152+
v.set_dmaren(false);
153+
v.set_dmawen(false);
154+
});
155+
self.clean_rrdy_flag();
156+
157+
// Reset ARG2 to +1: configure for 2-arg Cos with minimal precision, feed dummy args.
158+
T::regs().csr().modify(|v| {
159+
v.set_func(vals::Func::from_bits(Function::Cos as u8));
160+
v.set_precision(vals::Precision::from_bits(Precision::Iters4 as u8));
161+
v.set_scale(vals::Scale::from_bits(Scale::Arg1Res1 as u8));
162+
v.set_nargs(vals::Num::NUM2);
163+
v.set_argsize(vals::Size::BITS32);
164+
v.set_ressize(vals::Size::BITS32);
165+
});
166+
self.peri.write_argument(0x0u32);
167+
self.peri.write_argument(0x7FFFFFFFu32);
168+
self.clean_rrdy_flag();
169+
170+
// Apply user configuration (func, precision, scale).
171+
T::regs().csr().modify(|v| {
172+
v.set_func(vals::Func::from_bits(self.config.function as u8));
173+
v.set_precision(vals::Precision::from_bits(self.config.precision as u8));
174+
v.set_scale(vals::Scale::from_bits(self.config.scale as u8));
175+
});
252176

253177
// we don't set NRES in here, but to make sure NRES is set each time user call "calc"-ish functions,
254178
// since each "calc"-ish functions can have different ARGSIZE and RESSIZE, thus NRES should be change accordingly.
@@ -282,13 +206,12 @@ impl<'d, T: Instance> Cordic<'d, T> {
282206

283207
let res_cnt = Self::check_arg_res_length_32bit(arg.len(), res.len(), arg1_only, res1_only)?;
284208

285-
self.peri
286-
.set_argument_count(if arg1_only { AccessCount::One } else { AccessCount::Two });
287-
288-
self.peri
289-
.set_result_count(if res1_only { AccessCount::One } else { AccessCount::Two });
290-
291-
self.peri.set_data_width(Width::Bits32, Width::Bits32);
209+
T::regs().csr().modify(|v| {
210+
v.set_nargs(if arg1_only { vals::Num::NUM1 } else { vals::Num::NUM2 });
211+
v.set_nres(if res1_only { vals::Num::NUM1 } else { vals::Num::NUM2 });
212+
v.set_argsize(vals::Size::BITS32);
213+
v.set_ressize(vals::Size::BITS32);
214+
});
292215

293216
let mut cnt = 0;
294217

@@ -398,23 +321,25 @@ impl<'d, T: Instance> Cordic<'d, T> {
398321

399322
let active_res_buf = &mut res[..res_cnt];
400323

401-
self.peri
402-
.set_argument_count(if arg1_only { AccessCount::One } else { AccessCount::Two });
403-
404-
self.peri
405-
.set_result_count(if res1_only { AccessCount::One } else { AccessCount::Two });
406-
407-
self.peri.set_data_width(Width::Bits32, Width::Bits32);
324+
T::regs().csr().modify(|v| {
325+
v.set_nargs(if arg1_only { vals::Num::NUM1 } else { vals::Num::NUM2 });
326+
v.set_nres(if res1_only { vals::Num::NUM1 } else { vals::Num::NUM2 });
327+
v.set_argsize(vals::Size::BITS32);
328+
v.set_ressize(vals::Size::BITS32);
329+
});
408330

409331
let write_req = write_dma.request();
410332
let read_req = read_dma.request();
411333

412-
self.peri.enable_write_dma();
413-
self.peri.enable_read_dma();
334+
// DMAWEN and DMAREN must be set in separate register writes;
335+
// setting both in a single write hangs the CORDIC+DMA on STM32H563.
336+
T::regs().csr().modify(|v| v.set_dmawen(true));
337+
T::regs().csr().modify(|v| v.set_dmaren(true));
414338

339+
// Same H563 constraint: clear DMAWEN and DMAREN in separate writes.
415340
let _on_drop = OnDrop::new(|| {
416-
self.peri.disable_write_dma();
417-
self.peri.disable_read_dma();
341+
T::regs().csr().modify(|v| v.set_dmawen(false));
342+
T::regs().csr().modify(|v| v.set_dmaren(false));
418343
});
419344

420345
unsafe {
@@ -482,10 +407,12 @@ impl<'d, T: Instance> Cordic<'d, T> {
482407
let res_cnt = arg.len();
483408

484409
// In q1.15 mode, 1 write/read to access 2 arguments/results
485-
self.peri.set_argument_count(AccessCount::One);
486-
self.peri.set_result_count(AccessCount::One);
487-
488-
self.peri.set_data_width(Width::Bits16, Width::Bits16);
410+
T::regs().csr().modify(|v| {
411+
v.set_nargs(vals::Num::NUM1);
412+
v.set_nres(vals::Num::NUM1);
413+
v.set_argsize(vals::Size::BITS16);
414+
v.set_ressize(vals::Size::BITS16);
415+
});
489416

490417
// To use cordic preload function, the first value is special.
491418
// It is loaded to CORDIC WDATA register out side of loop
@@ -543,20 +470,25 @@ impl<'d, T: Instance> Cordic<'d, T> {
543470
let active_res_buf = &mut res[..res_cnt];
544471

545472
// In q1.15 mode, 1 write/read to access 2 arguments/results
546-
self.peri.set_argument_count(AccessCount::One);
547-
self.peri.set_result_count(AccessCount::One);
548-
549-
self.peri.set_data_width(Width::Bits16, Width::Bits16);
473+
T::regs().csr().modify(|v| {
474+
v.set_nargs(vals::Num::NUM1);
475+
v.set_nres(vals::Num::NUM1);
476+
v.set_argsize(vals::Size::BITS16);
477+
v.set_ressize(vals::Size::BITS16);
478+
});
550479

551480
let write_req = write_dma.request();
552481
let read_req = read_dma.request();
553482

554-
self.peri.enable_write_dma();
555-
self.peri.enable_read_dma();
483+
// DMAWEN and DMAREN must be set in separate register writes;
484+
// setting both in a single write hangs the CORDIC+DMA on STM32H563.
485+
T::regs().csr().modify(|v| v.set_dmawen(true));
486+
T::regs().csr().modify(|v| v.set_dmaren(true));
556487

488+
// Same H563 constraint: clear DMAWEN and DMAREN in separate writes.
557489
let _on_drop = OnDrop::new(|| {
558-
self.peri.disable_write_dma();
559-
self.peri.disable_read_dma();
490+
T::regs().csr().modify(|v| v.set_dmawen(false));
491+
T::regs().csr().modify(|v| v.set_dmaren(false));
560492
});
561493

562494
unsafe {

0 commit comments

Comments
 (0)