@@ -12,18 +12,6 @@ use crate::chips::{Chip, ChipGroup};
1212use crate :: gpio_af:: parse_signal_name;
1313use crate :: normalize_peris:: normalize_peri_name;
1414
15- fn corename ( d : & str ) -> String {
16- let m = regex ! ( r".*Cortex-M(\d+)(\+?)\s*(.*)" ) . captures ( d) . unwrap ( ) ;
17- let cm = m. get ( 1 ) . unwrap ( ) . as_str ( ) ;
18- let p = if m. get ( 2 ) . unwrap ( ) . as_str ( ) == "+" { "p" } else { "" } ;
19- let s = if m. get ( 3 ) . unwrap ( ) . as_str ( ) == "secure" {
20- "s"
21- } else {
22- ""
23- } ;
24- format ! ( "cm{cm}{p}{s}" )
25- }
26-
2715/// Merge AF information from GPIO file into peripheral pins.
2816///
2917/// `core_pins` is modified in-place and updated with AF information from `af_pins`.
@@ -110,9 +98,9 @@ fn process_group(
11098 . xml
11199 . cores
112100 . iter ( )
113- . map ( |core_xml | {
101+ . map ( |long_core_name | {
114102 process_core (
115- core_xml ,
103+ long_core_name ,
116104 h,
117105 & chip_name,
118106 & group,
@@ -135,7 +123,7 @@ fn process_group(
135123
136124#[ allow( clippy:: too_many_arguments) ]
137125fn process_core (
138- core_xml : & str ,
126+ long_core_name : & str ,
139127 h : & header:: ParsedHeader ,
140128 chip_name : & str ,
141129 group : & ChipGroup ,
@@ -145,7 +133,7 @@ fn process_core(
145133 chip_af : Option < & HashMap < String , Vec < stm32_data_serde:: chip:: core:: peripheral:: Pin > > > ,
146134 dma_channels : & dma:: DmaChannels ,
147135) -> anyhow:: Result < stm32_data_serde:: chip:: Core > {
148- let core_name = corename ( core_xml ) ;
136+ let core_name = create_short_core_name ( long_core_name ) ;
149137 let defines = h. get_defines ( & core_name) ;
150138
151139 let peri_kinds = create_peripheral_map ( chip_name, group, defines) ;
@@ -206,74 +194,10 @@ fn process_core(
206194
207195 let mut peripherals: Vec < _ > = peripherals. into_values ( ) . collect ( ) ;
208196 peripherals. sort_by_key ( |x| x. name . clone ( ) ) ;
209- // Collect DMA versions in the chip
210- let mut dmas: Vec < _ > = group
211- . ips
212- . values ( )
213- . filter_map ( |ip| {
214- let version = & ip. version ;
215- let instance = & ip. instance_name ;
216- dma_channels
217- . 0
218- . get ( version)
219- . or_else ( || dma_channels. 0 . get ( & format ! ( "{version}:{instance}" ) ) )
220- . map ( |dma| ( ip. name . clone ( ) , instance. clone ( ) , dma) )
221- } )
222- . collect ( ) ;
223- dmas. sort_by_key ( |( name, instance, _) | {
224- (
225- match name. as_str ( ) {
226- "DMA" => 1 ,
227- "BDMA" => 2 ,
228- "BDMA1" => 3 ,
229- "BDMA2" => 4 ,
230- "GPDMA" => 5 ,
231- "HPDMA" => 6 ,
232- _ => 0 ,
233- } ,
234- instance. clone ( ) ,
235- )
236- } ) ;
237-
238- // The dma_channels[xx] is generic for multiple chips. The current chip may have less DMAs,
239- // so we have to filter it.
240- static DMA_CHANNEL_COUNTS : RegexMap < usize > = RegexMap :: new ( & [
241- ( "STM32F0[37]0.*:DMA1" , 5 ) ,
242- ( "STM32G4[34]1.*:DMA1" , 6 ) ,
243- ( "STM32G4[34]1.*:DMA2" , 6 ) ,
244- ] ) ;
245- let have_peris: HashSet < _ > = peripherals. iter ( ) . map ( |p| p. name . clone ( ) ) . collect ( ) ;
246- let dma_channels = dmas
247- . iter ( )
248- . flat_map ( |( _, _, dma) | dma. channels . clone ( ) )
249- . filter ( |ch| have_peris. contains ( & ch. dma ) )
250- . filter ( |ch| {
251- DMA_CHANNEL_COUNTS
252- . get ( & format ! ( "{}:{}" , chip_name, ch. dma) )
253- . map_or_else ( || true , |& v| usize:: from ( ch. channel ) < v)
254- } )
255- . collect :: < Vec < _ > > ( ) ;
256- let have_chs: HashSet < _ > = dma_channels. iter ( ) . map ( |ch| ch. name . clone ( ) ) . collect ( ) ;
257197
258- // Process peripheral - DMA channel associations
259- for p in & mut peripherals {
260- let mut chs = Vec :: new ( ) ;
261- for ( _, _, dma) in & dmas {
262- if let Some ( peri_chs) = dma. peripherals . get ( & p. name ) {
263- chs. extend (
264- peri_chs
265- . iter ( )
266- . filter ( |ch| match & ch. channel {
267- None => true ,
268- Some ( channel) => have_chs. contains ( channel) ,
269- } )
270- . cloned ( ) ,
271- ) ;
272- }
273- }
274- chs. sort_by_key ( |ch| ( ch. channel . clone ( ) , ch. dmamux . clone ( ) , ch. request ) ) ;
275- p. dma_channels = chs;
276- }
198+ let dmas = collect_dma_instances ( group, dma_channels) ;
199+ let dma_channels = extract_relevant_dma_channels ( & peripherals, & dmas, chip_name) ;
200+ associate_peripherals_dma_channels ( & mut peripherals, dmas, & dma_channels) ;
277201
278202 let mut pins: Vec < _ > = group
279203 . pins
@@ -354,6 +278,26 @@ fn merge_i2s_into_spi_pins(
354278 Vec :: new ( )
355279}
356280
281+ /// Create a short core name from a long name.
282+ ///
283+ /// Parse a string like "ARM Cortex-M4" or "ARM Cortex-M7 secure" and return a
284+ /// string like "cm4" or "cm7s". The input string is expected to contain the
285+ /// string "Cortex-M" followed by a number, optionally followed by the string
286+ /// "+" or " secure".
287+ ///
288+ /// FIXME: "secure" does not appear the XML files in that attribute.
289+ fn create_short_core_name ( d : & str ) -> String {
290+ let m = regex ! ( r".*Cortex-M(\d+)(\+?)\s*(.*)" ) . captures ( d) . unwrap ( ) ;
291+ let cm = m. get ( 1 ) . unwrap ( ) . as_str ( ) ;
292+ let p = if m. get ( 2 ) . unwrap ( ) . as_str ( ) == "+" { "p" } else { "" } ;
293+ let s = if m. get ( 3 ) . unwrap ( ) . as_str ( ) == "secure" {
294+ "s"
295+ } else {
296+ ""
297+ } ;
298+ format ! ( "cm{cm}{p}{s}" )
299+ }
300+
357301/// Return a HashMap of peripheral names to their kind (name:version).
358302///
359303/// Some peripherals have different names in the xml files and the header files. We handle these cases here by
@@ -498,7 +442,7 @@ fn create_peripheral_map(chip_name: &str, group: &ChipGroup, defines: &header::D
498442/// It's not the full info we would want (stuff like AFIO info which comes from
499443/// the GPIO xml), but we actually need to use it because of the F1 line
500444/// which doesn't include non-remappable peripherals in the GPIO xml and some
501- /// weird edge cases like STM32F030C6 (see merge_periph_pins_info).
445+ /// weird edge cases like STM32F030C6 (see [ merge_periph_pins_info] ).
502446///
503447/// The function returns a HashMap of peripheral name to Vec of Pins.
504448/// The Pins only contain the pin and signal name, and no AF information
@@ -612,6 +556,121 @@ fn apply_family_extras(group: &ChipGroup, peripherals: &mut HashMap<String, stm3
612556 }
613557}
614558
559+ /// Collect and sort all DMA IP instances available on the current chip.
560+ ///
561+ /// Iterates over the parsed MCU IP definitions (`group.ips`), matching each IP’s `version`
562+ /// and `instance_name` against the pre-built `dma_channels` map.
563+ /// Searches first by the DMA name (e.g. "BDMA"), then by the DMA name and instance
564+ /// (e.g. "STM32H7RS_dma3_Cube:GPDMA1"). Returns a `Vec<(ip_name, instance_name, ChipDma)>`.
565+ fn collect_dma_instances < ' a > (
566+ group : & ChipGroup ,
567+ dma_channels : & ' a dma:: DmaChannels ,
568+ ) -> Vec < ( String , String , & ' a dma:: ChipDma ) > {
569+ // Collect DMA versions in the chip
570+ let mut dmas: Vec < _ > = group
571+ . ips
572+ . values ( )
573+ . filter_map ( |ip| {
574+ let version = & ip. version ;
575+ let instance = & ip. instance_name ;
576+ dma_channels
577+ . 0
578+ . get ( version)
579+ . or_else ( || dma_channels. 0 . get ( & format ! ( "{version}:{instance}" ) ) )
580+ . map ( |dma| ( ip. name . clone ( ) , instance. clone ( ) , dma) )
581+ } )
582+ . collect ( ) ;
583+ dmas. sort_by_key ( |( name, instance, _) | {
584+ (
585+ match name. as_str ( ) {
586+ "DMA" => 1 ,
587+ "BDMA" => 2 ,
588+ "BDMA1" => 3 ,
589+ "BDMA2" => 4 ,
590+ "GPDMA" => 5 ,
591+ "HPDMA" => 6 ,
592+ _ => 0 ,
593+ } ,
594+ instance. clone ( ) ,
595+ )
596+ } ) ;
597+ dmas
598+ }
599+
600+ /// Filters and returns a list of DMA channels for the current chip.
601+ ///
602+ /// It takes the DMA instances from `dmas`, which also occur in `peripherals`.
603+ /// Of these, only the first channels corresponding to the number of channels
604+ /// in this chip family are then saved.
605+ ///
606+ /// E.g. on an STM32F030CC (IP version “STM32F091_dma_v1_1”), DMA2 is removed because
607+ /// only DMA1 exists; on an STM32G431CB only the first 6 channels of each DMA block
608+ /// are kept per the hardware limit.
609+ ///
610+ /// It returns `Vec<DmaChannels>` with the valid DMA channel definitions that
611+ /// can actually be used on this specific device.
612+ fn extract_relevant_dma_channels (
613+ peripherals : & Vec < stm32_data_serde:: chip:: core:: Peripheral > ,
614+ dmas : & Vec < ( String , String , & dma:: ChipDma ) > ,
615+ chip_name : & str ,
616+ ) -> Vec < stm32_data_serde:: chip:: core:: DmaChannels > {
617+ // The dma_channels[xx] is generic for multiple chips. The current chip may have less DMAs,
618+ // so we have to filter it.
619+ static DMA_CHANNEL_COUNTS : RegexMap < usize > = RegexMap :: new ( & [
620+ ( "STM32F0[37]0.*:DMA1" , 5 ) ,
621+ ( "STM32G4[34]1.*:DMA1" , 6 ) ,
622+ ( "STM32G4[34]1.*:DMA2" , 6 ) ,
623+ ] ) ;
624+ let have_peris: HashSet < _ > = peripherals. iter ( ) . map ( |p| p. name . clone ( ) ) . collect ( ) ;
625+ let dma_channels = dmas
626+ . iter ( )
627+ . flat_map ( |( _, _, dma) | dma. channels . clone ( ) )
628+ . filter ( |ch| have_peris. contains ( & ch. dma ) )
629+ . filter ( |ch| {
630+ DMA_CHANNEL_COUNTS
631+ . get ( & format ! ( "{}:{}" , chip_name, ch. dma) )
632+ . map_or_else ( || true , |& v| usize:: from ( ch. channel ) < v)
633+ } )
634+ . collect :: < Vec < _ > > ( ) ;
635+ dma_channels
636+ }
637+
638+ /// Associates each peripheral with its available DMA channels.
639+ ///
640+ /// This is done by retrieving its mappings from `dmas`, filtering out
641+ /// channels not present in `dma_channels`, sorting them, and assigning
642+ /// the sorted list to the peripheral’s `dma_channels` field.
643+ ///
644+ /// This determines which DMA channels can be used for data transfers for each peripheral.
645+ /// Modifies each `Peripheral` in-place, setting `peripheral.dma_channels`.
646+ fn associate_peripherals_dma_channels (
647+ peripherals : & mut Vec < stm32_data_serde:: chip:: core:: Peripheral > ,
648+ dmas : Vec < ( String , String , & dma:: ChipDma ) > ,
649+ dma_channels : & Vec < stm32_data_serde:: chip:: core:: DmaChannels > ,
650+ ) {
651+ let have_chs: HashSet < _ > = dma_channels. iter ( ) . map ( |ch| ch. name . clone ( ) ) . collect ( ) ;
652+
653+ // Process peripheral - DMA channel associations
654+ for p in peripherals {
655+ let mut chs = Vec :: new ( ) ;
656+ for ( _, _, dma) in & dmas {
657+ if let Some ( peri_chs) = dma. peripherals . get ( & p. name ) {
658+ chs. extend (
659+ peri_chs
660+ . iter ( )
661+ . filter ( |ch| match & ch. channel {
662+ None => true ,
663+ Some ( channel) => have_chs. contains ( channel) ,
664+ } )
665+ . cloned ( ) ,
666+ ) ;
667+ }
668+ }
669+ chs. sort_by_key ( |ch| ( ch. channel . clone ( ) , ch. dmamux . clone ( ) , ch. request ) ) ;
670+ p. dma_channels = chs;
671+ }
672+ }
673+
615674fn process_chip (
616675 chips : & HashMap < String , Chip > ,
617676 chip_name : & str ,
0 commit comments