1- //! coordinate rotation digital computer (CORDIC)
1+ //! Coordinate Rotation Digital Computer (CORDIC)
22
33use embassy_hal_internal:: drop:: OnDrop ;
44use 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