diff options
Diffstat (limited to 'embassy-stm32/build.rs')
| -rw-r--r-- | embassy-stm32/build.rs | 575 |
1 files changed, 397 insertions, 178 deletions
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index b5f1261fe..a3b863340 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs | |||
| @@ -9,8 +9,8 @@ use proc_macro2::{Ident, TokenStream}; | |||
| 9 | use quote::{format_ident, quote}; | 9 | use quote::{format_ident, quote}; |
| 10 | use stm32_metapac::metadata::ir::BitOffset; | 10 | use stm32_metapac::metadata::ir::BitOffset; |
| 11 | use stm32_metapac::metadata::{ | 11 | use stm32_metapac::metadata::{ |
| 12 | MemoryRegion, MemoryRegionKind, PeripheralRccKernelClock, PeripheralRccRegister, PeripheralRegisters, StopMode, | 12 | ALL_CHIPS, ALL_PERIPHERAL_VERSIONS, METADATA, MemoryRegion, MemoryRegionKind, Peripheral, PeripheralRccKernelClock, |
| 13 | ALL_CHIPS, ALL_PERIPHERAL_VERSIONS, METADATA, | 13 | PeripheralRccRegister, PeripheralRegisters, StopMode, |
| 14 | }; | 14 | }; |
| 15 | 15 | ||
| 16 | #[path = "./build_common.rs"] | 16 | #[path = "./build_common.rs"] |
| @@ -105,13 +105,17 @@ fn main() { | |||
| 105 | } | 105 | } |
| 106 | (false, false) => { | 106 | (false, false) => { |
| 107 | if METADATA.memory.len() != 1 { | 107 | if METADATA.memory.len() != 1 { |
| 108 | panic!("Chip supports single and dual bank configuration. No Cargo feature to select one is enabled. Use the 'single-bank' or 'dual-bank' feature to make your selection") | 108 | panic!( |
| 109 | "Chip supports single and dual bank configuration. No Cargo feature to select one is enabled. Use the 'single-bank' or 'dual-bank' feature to make your selection" | ||
| 110 | ) | ||
| 109 | } | 111 | } |
| 110 | METADATA.memory[0] | 112 | METADATA.memory[0] |
| 111 | } | 113 | } |
| 112 | } | 114 | } |
| 113 | }; | 115 | }; |
| 114 | 116 | ||
| 117 | let has_bkpsram = memory.iter().any(|m| m.name == "BKPSRAM"); | ||
| 118 | |||
| 115 | // ======== | 119 | // ======== |
| 116 | // Generate singletons | 120 | // Generate singletons |
| 117 | 121 | ||
| @@ -122,6 +126,16 @@ fn main() { | |||
| 122 | singletons.push(p.name.to_string()); | 126 | singletons.push(p.name.to_string()); |
| 123 | } | 127 | } |
| 124 | 128 | ||
| 129 | cfgs.declare("backup_sram"); | ||
| 130 | |||
| 131 | if has_bkpsram { | ||
| 132 | singletons.push("BKPSRAM".to_string()); | ||
| 133 | cfgs.enable("backup_sram") | ||
| 134 | } | ||
| 135 | |||
| 136 | // compile a map of peripherals | ||
| 137 | let peripheral_map: BTreeMap<&str, &Peripheral> = METADATA.peripherals.iter().map(|p| (p.name, p)).collect(); | ||
| 138 | |||
| 125 | // generate one singleton per peripheral (with many exceptions...) | 139 | // generate one singleton per peripheral (with many exceptions...) |
| 126 | for p in METADATA.peripherals { | 140 | for p in METADATA.peripherals { |
| 127 | if let Some(r) = &p.registers { | 141 | if let Some(r) = &p.registers { |
| @@ -159,6 +173,11 @@ fn main() { | |||
| 159 | } | 173 | } |
| 160 | singletons.push(p.name.to_string()); | 174 | singletons.push(p.name.to_string()); |
| 161 | } | 175 | } |
| 176 | |||
| 177 | "eth" => { | ||
| 178 | singletons.push(p.name.to_string()); | ||
| 179 | singletons.push("ETH_SMA".to_string()); | ||
| 180 | } | ||
| 162 | //"dbgmcu" => {} | 181 | //"dbgmcu" => {} |
| 163 | //"syscfg" => {} | 182 | //"syscfg" => {} |
| 164 | //"dma" => {} | 183 | //"dma" => {} |
| @@ -303,9 +322,33 @@ fn main() { | |||
| 303 | _ => panic!("unknown time_driver {:?}", time_driver), | 322 | _ => panic!("unknown time_driver {:?}", time_driver), |
| 304 | }; | 323 | }; |
| 305 | 324 | ||
| 306 | if !time_driver_singleton.is_empty() { | 325 | let time_driver_irq_decl = if !time_driver_singleton.is_empty() { |
| 307 | cfgs.enable(format!("time_driver_{}", time_driver_singleton.to_lowercase())); | 326 | cfgs.enable(format!("time_driver_{}", time_driver_singleton.to_lowercase())); |
| 308 | } | 327 | |
| 328 | let p = peripheral_map.get(time_driver_singleton).unwrap(); | ||
| 329 | let irqs: BTreeSet<_> = p | ||
| 330 | .interrupts | ||
| 331 | .iter() | ||
| 332 | .filter(|i| i.signal == "CC" || i.signal == "UP") | ||
| 333 | .map(|i| i.interrupt.to_ascii_uppercase()) | ||
| 334 | .collect(); | ||
| 335 | |||
| 336 | irqs.iter() | ||
| 337 | .map(|i| { | ||
| 338 | let irq = format_ident!("{}", i); | ||
| 339 | quote! { | ||
| 340 | #[cfg(feature = "rt")] | ||
| 341 | #[interrupt] | ||
| 342 | fn #irq() { | ||
| 343 | crate::time_driver::get_driver().on_interrupt(); | ||
| 344 | } | ||
| 345 | } | ||
| 346 | }) | ||
| 347 | .collect() | ||
| 348 | } else { | ||
| 349 | TokenStream::new() | ||
| 350 | }; | ||
| 351 | |||
| 309 | for tim in [ | 352 | for tim in [ |
| 310 | "tim1", "tim2", "tim3", "tim4", "tim5", "tim8", "tim9", "tim12", "tim15", "tim20", "tim21", "tim22", "tim23", | 353 | "tim1", "tim2", "tim3", "tim4", "tim5", "tim8", "tim9", "tim12", "tim15", "tim20", "tim21", "tim22", "tim23", |
| 311 | "tim24", | 354 | "tim24", |
| @@ -337,8 +380,13 @@ fn main() { | |||
| 337 | // ======== | 380 | // ======== |
| 338 | // Generate interrupt declarations | 381 | // Generate interrupt declarations |
| 339 | 382 | ||
| 383 | let mut exti2_tsc_shared_int_present: Option<stm32_metapac::metadata::Interrupt> = None; | ||
| 340 | let mut irqs = Vec::new(); | 384 | let mut irqs = Vec::new(); |
| 341 | for irq in METADATA.interrupts { | 385 | for irq in METADATA.interrupts { |
| 386 | // The PAC doesn't ensure this is listed as the IRQ of EXTI2, so we must do so | ||
| 387 | if irq.name == "EXTI2_TSC" { | ||
| 388 | exti2_tsc_shared_int_present = Some(irq.clone()) | ||
| 389 | } | ||
| 342 | irqs.push(format_ident!("{}", irq.name)); | 390 | irqs.push(format_ident!("{}", irq.name)); |
| 343 | } | 391 | } |
| 344 | 392 | ||
| @@ -350,103 +398,112 @@ fn main() { | |||
| 350 | ); | 398 | ); |
| 351 | }); | 399 | }); |
| 352 | 400 | ||
| 401 | g.extend(time_driver_irq_decl); | ||
| 402 | |||
| 353 | // ======== | 403 | // ======== |
| 354 | // Generate FLASH regions | 404 | // Generate FLASH regions |
| 355 | let mut flash_regions = TokenStream::new(); | 405 | cfgs.declare("flash"); |
| 356 | let flash_memory_regions: Vec<_> = memory | 406 | let mut has_flash = false; |
| 357 | .iter() | 407 | if !chip_name.starts_with("stm32n6") { |
| 358 | .filter(|x| x.kind == MemoryRegionKind::Flash && x.settings.is_some()) | 408 | cfgs.enable("flash"); |
| 359 | .collect(); | 409 | has_flash = true; |
| 360 | for region in flash_memory_regions.iter() { | 410 | |
| 361 | let region_name = format_ident!("{}", get_flash_region_name(region.name)); | 411 | let mut flash_regions = TokenStream::new(); |
| 362 | let bank_variant = format_ident!( | 412 | let flash_memory_regions: Vec<_> = memory |
| 363 | "{}", | 413 | .iter() |
| 364 | if region.name.starts_with("BANK_1") { | 414 | .filter(|x| x.kind == MemoryRegionKind::Flash && x.settings.is_some()) |
| 365 | "Bank1" | 415 | .collect(); |
| 366 | } else if region.name.starts_with("BANK_2") { | 416 | for region in flash_memory_regions.iter() { |
| 367 | "Bank2" | 417 | let region_name = format_ident!("{}", get_flash_region_name(region.name)); |
| 368 | } else if region.name == "OTP" { | 418 | let bank_variant = format_ident!( |
| 369 | "Otp" | 419 | "{}", |
| 370 | } else { | 420 | if region.name.starts_with("BANK_1") { |
| 371 | continue; | 421 | "Bank1" |
| 372 | } | 422 | } else if region.name.starts_with("BANK_2") { |
| 373 | ); | 423 | "Bank2" |
| 374 | let base = region.address; | 424 | } else if region.name == "OTP" { |
| 375 | let size = region.size; | 425 | "Otp" |
| 376 | let settings = region.settings.as_ref().unwrap(); | 426 | } else { |
| 377 | let erase_size = settings.erase_size; | 427 | continue; |
| 378 | let write_size = settings.write_size; | 428 | } |
| 379 | let erase_value = settings.erase_value; | 429 | ); |
| 380 | 430 | let base = region.address; | |
| 381 | flash_regions.extend(quote! { | 431 | let size = region.size; |
| 382 | pub const #region_name: crate::flash::FlashRegion = crate::flash::FlashRegion { | 432 | let settings = region.settings.as_ref().unwrap(); |
| 383 | bank: crate::flash::FlashBank::#bank_variant, | 433 | let erase_size = settings.erase_size; |
| 384 | base: #base, | 434 | let write_size = settings.write_size; |
| 385 | size: #size, | 435 | let erase_value = settings.erase_value; |
| 386 | erase_size: #erase_size, | 436 | |
| 387 | write_size: #write_size, | 437 | flash_regions.extend(quote! { |
| 388 | erase_value: #erase_value, | 438 | pub const #region_name: crate::flash::FlashRegion = crate::flash::FlashRegion { |
| 389 | _ensure_internal: (), | 439 | bank: crate::flash::FlashBank::#bank_variant, |
| 390 | }; | 440 | base: #base, |
| 391 | }); | 441 | size: #size, |
| 442 | erase_size: #erase_size, | ||
| 443 | write_size: #write_size, | ||
| 444 | erase_value: #erase_value, | ||
| 445 | _ensure_internal: (), | ||
| 446 | }; | ||
| 447 | }); | ||
| 392 | 448 | ||
| 393 | let region_type = format_ident!("{}", get_flash_region_type_name(region.name)); | 449 | let region_type = format_ident!("{}", get_flash_region_type_name(region.name)); |
| 394 | flash_regions.extend(quote! { | 450 | flash_regions.extend(quote! { |
| 395 | #[cfg(flash)] | 451 | #[cfg(flash)] |
| 396 | pub struct #region_type<'d, MODE = crate::flash::Async>(pub &'static crate::flash::FlashRegion, pub(crate) embassy_hal_internal::Peri<'d, crate::peripherals::FLASH>, pub(crate) core::marker::PhantomData<MODE>); | 452 | pub struct #region_type<'d, MODE = crate::flash::Async>(pub &'static crate::flash::FlashRegion, pub(crate) embassy_hal_internal::Peri<'d, crate::peripherals::FLASH>, pub(crate) core::marker::PhantomData<MODE>); |
| 397 | }); | 453 | }); |
| 398 | } | 454 | } |
| 399 | 455 | ||
| 400 | let (fields, (inits, region_names)): (Vec<TokenStream>, (Vec<TokenStream>, Vec<Ident>)) = flash_memory_regions | 456 | let (fields, (inits, region_names)): (Vec<TokenStream>, (Vec<TokenStream>, Vec<Ident>)) = flash_memory_regions |
| 401 | .iter() | 457 | .iter() |
| 402 | .map(|f| { | 458 | .map(|f| { |
| 403 | let region_name = get_flash_region_name(f.name); | 459 | let region_name = get_flash_region_name(f.name); |
| 404 | let field_name = format_ident!("{}", region_name.to_lowercase()); | 460 | let field_name = format_ident!("{}", region_name.to_lowercase()); |
| 405 | let field_type = format_ident!("{}", get_flash_region_type_name(f.name)); | 461 | let field_type = format_ident!("{}", get_flash_region_type_name(f.name)); |
| 406 | let field = quote! { | 462 | let field = quote! { |
| 407 | pub #field_name: #field_type<'d, MODE> | 463 | pub #field_name: #field_type<'d, MODE> |
| 408 | }; | 464 | }; |
| 409 | let region_name = format_ident!("{}", region_name); | 465 | let region_name = format_ident!("{}", region_name); |
| 410 | let init = quote! { | 466 | let init = quote! { |
| 411 | #field_name: #field_type(&#region_name, unsafe { p.clone_unchecked()}, core::marker::PhantomData) | 467 | #field_name: #field_type(&#region_name, unsafe { p.clone_unchecked()}, core::marker::PhantomData) |
| 412 | }; | 468 | }; |
| 413 | 469 | ||
| 414 | (field, (init, region_name)) | 470 | (field, (init, region_name)) |
| 415 | }) | 471 | }) |
| 416 | .unzip(); | 472 | .unzip(); |
| 417 | |||
| 418 | let regions_len = flash_memory_regions.len(); | ||
| 419 | flash_regions.extend(quote! { | ||
| 420 | #[cfg(flash)] | ||
| 421 | pub struct FlashLayout<'d, MODE = crate::flash::Async> { | ||
| 422 | #(#fields),*, | ||
| 423 | _mode: core::marker::PhantomData<MODE>, | ||
| 424 | } | ||
| 425 | 473 | ||
| 426 | #[cfg(flash)] | 474 | let regions_len = flash_memory_regions.len(); |
| 427 | impl<'d, MODE> FlashLayout<'d, MODE> { | 475 | flash_regions.extend(quote! { |
| 428 | pub(crate) fn new(p: embassy_hal_internal::Peri<'d, crate::peripherals::FLASH>) -> Self { | 476 | #[cfg(flash)] |
| 429 | Self { | 477 | pub struct FlashLayout<'d, MODE = crate::flash::Async> { |
| 430 | #(#inits),*, | 478 | #(#fields),*, |
| 431 | _mode: core::marker::PhantomData, | 479 | _mode: core::marker::PhantomData<MODE>, |
| 480 | } | ||
| 481 | |||
| 482 | #[cfg(flash)] | ||
| 483 | impl<'d, MODE> FlashLayout<'d, MODE> { | ||
| 484 | pub(crate) fn new(p: embassy_hal_internal::Peri<'d, crate::peripherals::FLASH>) -> Self { | ||
| 485 | Self { | ||
| 486 | #(#inits),*, | ||
| 487 | _mode: core::marker::PhantomData, | ||
| 488 | } | ||
| 432 | } | 489 | } |
| 433 | } | 490 | } |
| 434 | } | ||
| 435 | 491 | ||
| 436 | pub const FLASH_REGIONS: [&crate::flash::FlashRegion; #regions_len] = [ | 492 | pub const FLASH_REGIONS: [&crate::flash::FlashRegion; #regions_len] = [ |
| 437 | #(&#region_names),* | 493 | #(&#region_names),* |
| 438 | ]; | 494 | ]; |
| 439 | }); | 495 | }); |
| 440 | 496 | ||
| 441 | let max_erase_size = flash_memory_regions | 497 | let max_erase_size = flash_memory_regions |
| 442 | .iter() | 498 | .iter() |
| 443 | .map(|region| region.settings.as_ref().unwrap().erase_size) | 499 | .map(|region| region.settings.as_ref().unwrap().erase_size) |
| 444 | .max() | 500 | .max() |
| 445 | .unwrap(); | 501 | .unwrap(); |
| 446 | 502 | ||
| 447 | g.extend(quote! { pub const MAX_ERASE_SIZE: usize = #max_erase_size as usize; }); | 503 | g.extend(quote! { pub const MAX_ERASE_SIZE: usize = #max_erase_size as usize; }); |
| 448 | 504 | ||
| 449 | g.extend(quote! { pub mod flash_regions { #flash_regions } }); | 505 | g.extend(quote! { pub mod flash_regions { #flash_regions } }); |
| 506 | } | ||
| 450 | 507 | ||
| 451 | // ======== | 508 | // ======== |
| 452 | // Extract the rcc registers | 509 | // Extract the rcc registers |
| @@ -893,6 +950,60 @@ fn main() { | |||
| 893 | } | 950 | } |
| 894 | } | 951 | } |
| 895 | 952 | ||
| 953 | if kind == "gpio" { | ||
| 954 | for p in METADATA.peripherals { | ||
| 955 | // set all GPIOs to analog mode except for PA13 and PA14 which are SWDIO and SWDCLK | ||
| 956 | if p.registers.is_some() | ||
| 957 | && p.registers.as_ref().unwrap().kind == "gpio" | ||
| 958 | && p.registers.as_ref().unwrap().version != "v1" | ||
| 959 | { | ||
| 960 | let port = format_ident!("{}", p.name); | ||
| 961 | if p.name == "GPIOA" { | ||
| 962 | gg.extend(quote! { | ||
| 963 | // leave PA13 and PA14 as unchanged | ||
| 964 | crate::pac::#port.moder().modify(|w| { | ||
| 965 | w.set_moder(0, crate::pac::gpio::vals::Moder::ANALOG); | ||
| 966 | w.set_moder(1, crate::pac::gpio::vals::Moder::ANALOG); | ||
| 967 | w.set_moder(2, crate::pac::gpio::vals::Moder::ANALOG); | ||
| 968 | w.set_moder(3, crate::pac::gpio::vals::Moder::ANALOG); | ||
| 969 | w.set_moder(4, crate::pac::gpio::vals::Moder::ANALOG); | ||
| 970 | w.set_moder(5, crate::pac::gpio::vals::Moder::ANALOG); | ||
| 971 | w.set_moder(6, crate::pac::gpio::vals::Moder::ANALOG); | ||
| 972 | w.set_moder(7, crate::pac::gpio::vals::Moder::ANALOG); | ||
| 973 | w.set_moder(8, crate::pac::gpio::vals::Moder::ANALOG); | ||
| 974 | w.set_moder(9, crate::pac::gpio::vals::Moder::ANALOG); | ||
| 975 | w.set_moder(10, crate::pac::gpio::vals::Moder::ANALOG); | ||
| 976 | w.set_moder(11, crate::pac::gpio::vals::Moder::ANALOG); | ||
| 977 | w.set_moder(12, crate::pac::gpio::vals::Moder::ANALOG); | ||
| 978 | w.set_moder(15, crate::pac::gpio::vals::Moder::ANALOG); | ||
| 979 | }); | ||
| 980 | }); | ||
| 981 | } else { | ||
| 982 | gg.extend(quote! { | ||
| 983 | crate::pac::#port.moder().modify(|w| { | ||
| 984 | w.set_moder(0, crate::pac::gpio::vals::Moder::ANALOG); | ||
| 985 | w.set_moder(1, crate::pac::gpio::vals::Moder::ANALOG); | ||
| 986 | w.set_moder(2, crate::pac::gpio::vals::Moder::ANALOG); | ||
| 987 | w.set_moder(3, crate::pac::gpio::vals::Moder::ANALOG); | ||
| 988 | w.set_moder(4, crate::pac::gpio::vals::Moder::ANALOG); | ||
| 989 | w.set_moder(5, crate::pac::gpio::vals::Moder::ANALOG); | ||
| 990 | w.set_moder(6, crate::pac::gpio::vals::Moder::ANALOG); | ||
| 991 | w.set_moder(7, crate::pac::gpio::vals::Moder::ANALOG); | ||
| 992 | w.set_moder(8, crate::pac::gpio::vals::Moder::ANALOG); | ||
| 993 | w.set_moder(9, crate::pac::gpio::vals::Moder::ANALOG); | ||
| 994 | w.set_moder(10, crate::pac::gpio::vals::Moder::ANALOG); | ||
| 995 | w.set_moder(11, crate::pac::gpio::vals::Moder::ANALOG); | ||
| 996 | w.set_moder(12, crate::pac::gpio::vals::Moder::ANALOG); | ||
| 997 | w.set_moder(13, crate::pac::gpio::vals::Moder::ANALOG); | ||
| 998 | w.set_moder(14, crate::pac::gpio::vals::Moder::ANALOG); | ||
| 999 | w.set_moder(15, crate::pac::gpio::vals::Moder::ANALOG); | ||
| 1000 | }); | ||
| 1001 | }); | ||
| 1002 | } | ||
| 1003 | } | ||
| 1004 | } | ||
| 1005 | } | ||
| 1006 | |||
| 896 | let fname = format_ident!("init_{}", kind); | 1007 | let fname = format_ident!("init_{}", kind); |
| 897 | g.extend(quote! { | 1008 | g.extend(quote! { |
| 898 | pub unsafe fn #fname(){ | 1009 | pub unsafe fn #fname(){ |
| @@ -1329,14 +1440,32 @@ fn main() { | |||
| 1329 | (("tsc", "G8_IO2"), quote!(crate::tsc::G8IO2Pin)), | 1440 | (("tsc", "G8_IO2"), quote!(crate::tsc::G8IO2Pin)), |
| 1330 | (("tsc", "G8_IO3"), quote!(crate::tsc::G8IO3Pin)), | 1441 | (("tsc", "G8_IO3"), quote!(crate::tsc::G8IO3Pin)), |
| 1331 | (("tsc", "G8_IO4"), quote!(crate::tsc::G8IO4Pin)), | 1442 | (("tsc", "G8_IO4"), quote!(crate::tsc::G8IO4Pin)), |
| 1443 | (("lcd", "SEG"), quote!(crate::lcd::SegPin)), | ||
| 1444 | (("lcd", "COM"), quote!(crate::lcd::ComPin)), | ||
| 1445 | (("lcd", "VLCD"), quote!(crate::lcd::VlcdPin)), | ||
| 1332 | (("dac", "OUT1"), quote!(crate::dac::DacPin<Ch1>)), | 1446 | (("dac", "OUT1"), quote!(crate::dac::DacPin<Ch1>)), |
| 1333 | (("dac", "OUT2"), quote!(crate::dac::DacPin<Ch2>)), | 1447 | (("dac", "OUT2"), quote!(crate::dac::DacPin<Ch2>)), |
| 1334 | ].into(); | 1448 | ].into(); |
| 1335 | 1449 | ||
| 1336 | for p in METADATA.peripherals { | 1450 | for p in METADATA.peripherals { |
| 1337 | if let Some(regs) = &p.registers { | 1451 | if let Some(regs) = &p.registers { |
| 1452 | let mut adc_pairs: BTreeMap<u8, (Option<Ident>, Option<Ident>)> = BTreeMap::new(); | ||
| 1453 | let mut seen_lcd_seg_pins = HashSet::new(); | ||
| 1454 | |||
| 1338 | for pin in p.pins { | 1455 | for pin in p.pins { |
| 1339 | let key = (regs.kind, pin.signal); | 1456 | let mut key = (regs.kind, pin.signal); |
| 1457 | |||
| 1458 | // LCD is special. There are so many pins! | ||
| 1459 | if regs.kind == "lcd" { | ||
| 1460 | key.1 = pin.signal.trim_end_matches(char::is_numeric); | ||
| 1461 | |||
| 1462 | if key.1 == "SEG" && !seen_lcd_seg_pins.insert(pin.pin) { | ||
| 1463 | // LCD has SEG pins multiplexed in the peripheral | ||
| 1464 | // This means we can see them twice. We need to skip those so we're not impl'ing the trait twice | ||
| 1465 | continue; | ||
| 1466 | } | ||
| 1467 | } | ||
| 1468 | |||
| 1340 | if let Some(tr) = signals.get(&key) { | 1469 | if let Some(tr) = signals.get(&key) { |
| 1341 | let mut peri = format_ident!("{}", p.name); | 1470 | let mut peri = format_ident!("{}", p.name); |
| 1342 | 1471 | ||
| @@ -1379,6 +1508,11 @@ fn main() { | |||
| 1379 | } | 1508 | } |
| 1380 | } | 1509 | } |
| 1381 | 1510 | ||
| 1511 | // MDIO and MDC are special | ||
| 1512 | if pin.signal == "MDIO" || pin.signal == "MDC" { | ||
| 1513 | peri = format_ident!("{}", "ETH_SMA"); | ||
| 1514 | } | ||
| 1515 | |||
| 1382 | // XSPI NCS pin to CSSEL mapping | 1516 | // XSPI NCS pin to CSSEL mapping |
| 1383 | if pin.signal.ends_with("NCS1") { | 1517 | if pin.signal.ends_with("NCS1") { |
| 1384 | g.extend(quote! { | 1518 | g.extend(quote! { |
| @@ -1456,25 +1590,29 @@ fn main() { | |||
| 1456 | }; | 1590 | }; |
| 1457 | 1591 | ||
| 1458 | // H7 has differential voltage measurements | 1592 | // H7 has differential voltage measurements |
| 1459 | let ch: Option<u8> = if pin.signal.starts_with("INP") { | 1593 | let ch: Option<(u8, bool)> = if pin.signal.starts_with("INP") { |
| 1460 | Some(pin.signal.strip_prefix("INP").unwrap().parse().unwrap()) | 1594 | Some((pin.signal.strip_prefix("INP").unwrap().parse().unwrap(), false)) |
| 1461 | } else if pin.signal.starts_with("INN") { | 1595 | } else if pin.signal.starts_with("INN") { |
| 1462 | // TODO handle in the future when embassy supports differential measurements | 1596 | Some((pin.signal.strip_prefix("INN").unwrap().parse().unwrap(), true)) |
| 1463 | None | ||
| 1464 | } else if pin.signal.starts_with("IN") && pin.signal.ends_with('b') { | 1597 | } else if pin.signal.starts_with("IN") && pin.signal.ends_with('b') { |
| 1465 | // we number STM32L1 ADC bank 1 as 0..=31, bank 2 as 32..=63 | 1598 | // we number STM32L1 ADC bank 1 as 0..=31, bank 2 as 32..=63 |
| 1466 | let signal = pin.signal.strip_prefix("IN").unwrap().strip_suffix('b').unwrap(); | 1599 | let signal = pin.signal.strip_prefix("IN").unwrap().strip_suffix('b').unwrap(); |
| 1467 | Some(32u8 + signal.parse::<u8>().unwrap()) | 1600 | Some((32u8 + signal.parse::<u8>().unwrap(), false)) |
| 1468 | } else if pin.signal.starts_with("IN") { | 1601 | } else if pin.signal.starts_with("IN") { |
| 1469 | Some(pin.signal.strip_prefix("IN").unwrap().parse().unwrap()) | 1602 | Some((pin.signal.strip_prefix("IN").unwrap().parse().unwrap(), false)) |
| 1470 | } else { | 1603 | } else { |
| 1471 | None | 1604 | None |
| 1472 | }; | 1605 | }; |
| 1473 | if let Some(ch) = ch { | 1606 | if let Some((ch, false)) = ch { |
| 1607 | adc_pairs.entry(ch).or_insert((None, None)).0.replace(pin_name.clone()); | ||
| 1608 | |||
| 1474 | g.extend(quote! { | 1609 | g.extend(quote! { |
| 1475 | impl_adc_pin!( #peri, #pin_name, #ch); | 1610 | impl_adc_pin!( #peri, #pin_name, #ch); |
| 1476 | }) | 1611 | }) |
| 1477 | } | 1612 | } |
| 1613 | if let Some((ch, true)) = ch { | ||
| 1614 | adc_pairs.entry(ch).or_insert((None, None)).1.replace(pin_name.clone()); | ||
| 1615 | } | ||
| 1478 | } | 1616 | } |
| 1479 | 1617 | ||
| 1480 | if regs.kind == "opamp" { | 1618 | if regs.kind == "opamp" { |
| @@ -1513,6 +1651,23 @@ fn main() { | |||
| 1513 | }) | 1651 | }) |
| 1514 | } | 1652 | } |
| 1515 | } | 1653 | } |
| 1654 | |||
| 1655 | { | ||
| 1656 | let peri = format_ident!("{}", p.name); | ||
| 1657 | |||
| 1658 | for (ch, (pin, npin)) in adc_pairs { | ||
| 1659 | let (pin_name, npin_name) = match (pin, npin) { | ||
| 1660 | (Some(pin), Some(npin)) => (pin, npin), | ||
| 1661 | _ => { | ||
| 1662 | continue; | ||
| 1663 | } | ||
| 1664 | }; | ||
| 1665 | |||
| 1666 | g.extend(quote! { | ||
| 1667 | impl_adc_pair!( #peri, #pin_name, #npin_name, #ch); | ||
| 1668 | }) | ||
| 1669 | } | ||
| 1670 | } | ||
| 1516 | } | 1671 | } |
| 1517 | } | 1672 | } |
| 1518 | 1673 | ||
| @@ -1561,13 +1716,13 @@ fn main() { | |||
| 1561 | .into(); | 1716 | .into(); |
| 1562 | 1717 | ||
| 1563 | if chip_name.starts_with("stm32u5") { | 1718 | if chip_name.starts_with("stm32u5") { |
| 1564 | signals.insert(("adc", "ADC4"), quote!(crate::adc::RxDma4)); | 1719 | signals.insert(("adc", "ADC4"), quote!(crate::adc::RxDma)); |
| 1565 | } else { | 1720 | } else { |
| 1566 | signals.insert(("adc", "ADC4"), quote!(crate::adc::RxDma)); | 1721 | signals.insert(("adc", "ADC4"), quote!(crate::adc::RxDma)); |
| 1567 | } | 1722 | } |
| 1568 | 1723 | ||
| 1569 | if chip_name.starts_with("stm32wba") { | 1724 | if chip_name.starts_with("stm32wba") { |
| 1570 | signals.insert(("adc", "ADC4"), quote!(crate::adc::RxDma4)); | 1725 | signals.insert(("adc", "ADC4"), quote!(crate::adc::RxDma)); |
| 1571 | } | 1726 | } |
| 1572 | 1727 | ||
| 1573 | if chip_name.starts_with("stm32g4") { | 1728 | if chip_name.starts_with("stm32g4") { |
| @@ -1654,70 +1809,88 @@ fn main() { | |||
| 1654 | } | 1809 | } |
| 1655 | 1810 | ||
| 1656 | // ======== | 1811 | // ======== |
| 1657 | // Generate Div/Mul impls for RCC prescalers/dividers/multipliers. | 1812 | // Generate Div/Mul impls for RCC and ADC prescalers/dividers/multipliers. |
| 1658 | for e in rcc_registers.ir.enums { | 1813 | for (kind, psc_enums) in ["rcc", "adc", "adccommon"].iter().filter_map(|kind| { |
| 1659 | fn is_rcc_name(e: &str) -> bool { | 1814 | METADATA |
| 1660 | match e { | 1815 | .peripherals |
| 1661 | "Pllp" | "Pllq" | "Pllr" | "Plldivst" | "Pllm" | "Plln" | "Prediv1" | "Prediv2" | "Hpre5" => true, | 1816 | .iter() |
| 1662 | "Timpre" | "Pllrclkpre" => false, | 1817 | .filter_map(|p| p.registers.as_ref()) |
| 1663 | e if e.ends_with("pre") || e.ends_with("pres") || e.ends_with("div") || e.ends_with("mul") => true, | 1818 | .find(|r| r.kind == *kind) |
| 1664 | _ => false, | 1819 | .map(|r| (*kind, r.ir.enums)) |
| 1820 | }) { | ||
| 1821 | for e in psc_enums.iter() { | ||
| 1822 | fn is_adc_name(e: &str) -> bool { | ||
| 1823 | match e { | ||
| 1824 | "Presc" | "Adc4Presc" | "Adcpre" => true, | ||
| 1825 | _ => false, | ||
| 1826 | } | ||
| 1665 | } | 1827 | } |
| 1666 | } | ||
| 1667 | 1828 | ||
| 1668 | fn parse_num(n: &str) -> Result<Frac, ()> { | 1829 | fn is_rcc_name(e: &str) -> bool { |
| 1669 | for prefix in ["DIV", "MUL"] { | 1830 | match e { |
| 1670 | if let Some(n) = n.strip_prefix(prefix) { | 1831 | "Pllp" | "Pllq" | "Pllr" | "Plldivst" | "Pllm" | "Plln" | "Prediv1" | "Prediv2" | "Hpre5" => true, |
| 1671 | let exponent = n.find('_').map(|e| n.len() - 1 - e).unwrap_or(0) as u32; | 1832 | "Timpre" | "Pllrclkpre" => false, |
| 1672 | let mantissa = n.replace('_', "").parse().map_err(|_| ())?; | 1833 | e if e.ends_with("pre") || e.ends_with("pres") || e.ends_with("div") || e.ends_with("mul") => true, |
| 1673 | let f = Frac { | 1834 | _ => false, |
| 1674 | num: mantissa, | ||
| 1675 | denom: 10u32.pow(exponent), | ||
| 1676 | }; | ||
| 1677 | return Ok(f.simplify()); | ||
| 1678 | } | 1835 | } |
| 1679 | } | 1836 | } |
| 1680 | Err(()) | ||
| 1681 | } | ||
| 1682 | 1837 | ||
| 1683 | if is_rcc_name(e.name) { | 1838 | fn parse_num(n: &str) -> Result<Frac, ()> { |
| 1684 | let enum_name = format_ident!("{}", e.name); | 1839 | for prefix in ["DIV", "MUL"] { |
| 1685 | let mut muls = Vec::new(); | 1840 | if let Some(n) = n.strip_prefix(prefix) { |
| 1686 | let mut divs = Vec::new(); | 1841 | let exponent = n.find('_').map(|e| n.len() - 1 - e).unwrap_or(0) as u32; |
| 1687 | for v in e.variants { | 1842 | let mantissa = n.replace('_', "").parse().map_err(|_| ())?; |
| 1688 | let Ok(val) = parse_num(v.name) else { | 1843 | let f = Frac { |
| 1689 | panic!("could not parse mul/div. enum={} variant={}", e.name, v.name) | 1844 | num: mantissa, |
| 1690 | }; | 1845 | denom: 10u32.pow(exponent), |
| 1691 | let variant_name = format_ident!("{}", v.name); | 1846 | }; |
| 1692 | let variant = quote!(crate::pac::rcc::vals::#enum_name::#variant_name); | 1847 | return Ok(f.simplify()); |
| 1693 | let num = val.num; | 1848 | } |
| 1694 | let denom = val.denom; | 1849 | } |
| 1695 | muls.push(quote!(#variant => self * #num / #denom,)); | 1850 | Err(()) |
| 1696 | divs.push(quote!(#variant => self * #denom / #num,)); | ||
| 1697 | } | 1851 | } |
| 1698 | 1852 | ||
| 1699 | g.extend(quote! { | 1853 | if (kind == "rcc" && is_rcc_name(e.name)) || ((kind == "adccommon" || kind == "adc") && is_adc_name(e.name)) |
| 1700 | impl core::ops::Div<crate::pac::rcc::vals::#enum_name> for crate::time::Hertz { | 1854 | { |
| 1701 | type Output = crate::time::Hertz; | 1855 | let kind = format_ident!("{}", kind); |
| 1702 | fn div(self, rhs: crate::pac::rcc::vals::#enum_name) -> Self::Output { | 1856 | let enum_name = format_ident!("{}", e.name); |
| 1703 | match rhs { | 1857 | let mut muls = Vec::new(); |
| 1704 | #(#divs)* | 1858 | let mut divs = Vec::new(); |
| 1705 | #[allow(unreachable_patterns)] | 1859 | for v in e.variants { |
| 1706 | _ => unreachable!(), | 1860 | let Ok(val) = parse_num(v.name) else { |
| 1861 | panic!("could not parse mul/div. enum={} variant={}", e.name, v.name) | ||
| 1862 | }; | ||
| 1863 | let variant_name = format_ident!("{}", v.name); | ||
| 1864 | let variant = quote!(crate::pac::#kind::vals::#enum_name::#variant_name); | ||
| 1865 | let num = val.num; | ||
| 1866 | let denom = val.denom; | ||
| 1867 | muls.push(quote!(#variant => self * #num / #denom,)); | ||
| 1868 | divs.push(quote!(#variant => self * #denom / #num,)); | ||
| 1869 | } | ||
| 1870 | |||
| 1871 | g.extend(quote! { | ||
| 1872 | impl core::ops::Div<crate::pac::#kind::vals::#enum_name> for crate::time::Hertz { | ||
| 1873 | type Output = crate::time::Hertz; | ||
| 1874 | fn div(self, rhs: crate::pac::#kind::vals::#enum_name) -> Self::Output { | ||
| 1875 | match rhs { | ||
| 1876 | #(#divs)* | ||
| 1877 | #[allow(unreachable_patterns)] | ||
| 1878 | _ => unreachable!(), | ||
| 1879 | } | ||
| 1707 | } | 1880 | } |
| 1708 | } | 1881 | } |
| 1709 | } | 1882 | impl core::ops::Mul<crate::pac::#kind::vals::#enum_name> for crate::time::Hertz { |
| 1710 | impl core::ops::Mul<crate::pac::rcc::vals::#enum_name> for crate::time::Hertz { | 1883 | type Output = crate::time::Hertz; |
| 1711 | type Output = crate::time::Hertz; | 1884 | fn mul(self, rhs: crate::pac::#kind::vals::#enum_name) -> Self::Output { |
| 1712 | fn mul(self, rhs: crate::pac::rcc::vals::#enum_name) -> Self::Output { | 1885 | match rhs { |
| 1713 | match rhs { | 1886 | #(#muls)* |
| 1714 | #(#muls)* | 1887 | #[allow(unreachable_patterns)] |
| 1715 | #[allow(unreachable_patterns)] | 1888 | _ => unreachable!(), |
| 1716 | _ => unreachable!(), | 1889 | } |
| 1717 | } | 1890 | } |
| 1718 | } | 1891 | } |
| 1719 | } | 1892 | }); |
| 1720 | }); | 1893 | } |
| 1721 | } | 1894 | } |
| 1722 | } | 1895 | } |
| 1723 | 1896 | ||
| @@ -1727,7 +1900,19 @@ fn main() { | |||
| 1727 | for p in METADATA.peripherals { | 1900 | for p in METADATA.peripherals { |
| 1728 | let mut pt = TokenStream::new(); | 1901 | let mut pt = TokenStream::new(); |
| 1729 | 1902 | ||
| 1903 | let mut exti2_tsc_injected = false; | ||
| 1904 | if let Some(ref irq) = exti2_tsc_shared_int_present | ||
| 1905 | && p.name == "EXTI" | ||
| 1906 | { | ||
| 1907 | exti2_tsc_injected = true; | ||
| 1908 | let iname = format_ident!("{}", irq.name); | ||
| 1909 | let sname = format_ident!("{}", "EXTI2"); | ||
| 1910 | pt.extend(quote!(pub type #sname = crate::interrupt::typelevel::#iname;)); | ||
| 1911 | } | ||
| 1730 | for irq in p.interrupts { | 1912 | for irq in p.interrupts { |
| 1913 | if exti2_tsc_injected && irq.signal == "EXTI2" { | ||
| 1914 | continue; | ||
| 1915 | } | ||
| 1731 | let iname = format_ident!("{}", irq.interrupt); | 1916 | let iname = format_ident!("{}", irq.interrupt); |
| 1732 | let sname = format_ident!("{}", irq.signal); | 1917 | let sname = format_ident!("{}", irq.signal); |
| 1733 | pt.extend(quote!(pub type #sname = crate::interrupt::typelevel::#iname;)); | 1918 | pt.extend(quote!(pub type #sname = crate::interrupt::typelevel::#iname;)); |
| @@ -1760,7 +1945,7 @@ fn main() { | |||
| 1760 | flash_regions_table.push(row); | 1945 | flash_regions_table.push(row); |
| 1761 | } | 1946 | } |
| 1762 | 1947 | ||
| 1763 | let gpio_base = METADATA.peripherals.iter().find(|p| p.name == "GPIOA").unwrap().address as u32; | 1948 | let gpio_base = peripheral_map.get("GPIOA").unwrap().address as u32; |
| 1764 | let gpio_stride = 0x400; | 1949 | let gpio_stride = 0x400; |
| 1765 | 1950 | ||
| 1766 | for pin in METADATA.pins { | 1951 | for pin in METADATA.pins { |
| @@ -1844,7 +2029,12 @@ fn main() { | |||
| 1844 | if r.kind == "dma" || r.kind == "bdma" || r.kind == "gpdma" || r.kind == "lpdma" { | 2029 | if r.kind == "dma" || r.kind == "bdma" || r.kind == "gpdma" || r.kind == "lpdma" { |
| 1845 | for irq in p.interrupts { | 2030 | for irq in p.interrupts { |
| 1846 | let ch_name = format!("{}_{}", p.name, irq.signal); | 2031 | let ch_name = format!("{}_{}", p.name, irq.signal); |
| 1847 | let ch = METADATA.dma_channels.iter().find(|c| c.name == ch_name).unwrap(); | 2032 | let ch = METADATA.dma_channels.iter().find(|c| c.name == ch_name); |
| 2033 | |||
| 2034 | if ch.is_none() { | ||
| 2035 | continue; | ||
| 2036 | } | ||
| 2037 | let ch = ch.unwrap(); | ||
| 1848 | 2038 | ||
| 1849 | // Some H7 chips have BDMA1 hardcoded for DFSDM, ie no DMAMUX. It's unsupported, skip it. | 2039 | // Some H7 chips have BDMA1 hardcoded for DFSDM, ie no DMAMUX. It's unsupported, skip it. |
| 1850 | if has_dmamux && ch.dmamux.is_none() { | 2040 | if has_dmamux && ch.dmamux.is_none() { |
| @@ -1873,6 +2063,19 @@ fn main() { | |||
| 1873 | continue; | 2063 | continue; |
| 1874 | } | 2064 | } |
| 1875 | 2065 | ||
| 2066 | let dma_peri = peripheral_map.get(ch.dma).unwrap(); | ||
| 2067 | let stop_mode = dma_peri | ||
| 2068 | .rcc | ||
| 2069 | .as_ref() | ||
| 2070 | .map(|rcc| rcc.stop_mode.clone()) | ||
| 2071 | .unwrap_or_default(); | ||
| 2072 | |||
| 2073 | let stop_mode = match stop_mode { | ||
| 2074 | StopMode::Standby => quote! { Standby }, | ||
| 2075 | StopMode::Stop2 => quote! { Stop2 }, | ||
| 2076 | StopMode::Stop1 => quote! { Stop1 }, | ||
| 2077 | }; | ||
| 2078 | |||
| 1876 | let name = format_ident!("{}", ch.name); | 2079 | let name = format_ident!("{}", ch.name); |
| 1877 | let idx = ch_idx as u8; | 2080 | let idx = ch_idx as u8; |
| 1878 | #[cfg(feature = "_dual-core")] | 2081 | #[cfg(feature = "_dual-core")] |
| @@ -1885,12 +2088,10 @@ fn main() { | |||
| 1885 | quote!(crate::pac::Interrupt::#irq_name) | 2088 | quote!(crate::pac::Interrupt::#irq_name) |
| 1886 | }; | 2089 | }; |
| 1887 | 2090 | ||
| 1888 | g.extend(quote!(dma_channel_impl!(#name, #idx);)); | 2091 | g.extend(quote!(dma_channel_impl!(#name, #idx, #stop_mode);)); |
| 1889 | 2092 | ||
| 1890 | let dma = format_ident!("{}", ch.dma); | 2093 | let dma = format_ident!("{}", ch.dma); |
| 1891 | let ch_num = ch.channel as usize; | 2094 | let ch_num = ch.channel as usize; |
| 1892 | |||
| 1893 | let dma_peri = METADATA.peripherals.iter().find(|p| p.name == ch.dma).unwrap(); | ||
| 1894 | let bi = dma_peri.registers.as_ref().unwrap(); | 2095 | let bi = dma_peri.registers.as_ref().unwrap(); |
| 1895 | 2096 | ||
| 1896 | let dma_info = match bi.kind { | 2097 | let dma_info = match bi.kind { |
| @@ -1983,33 +2184,47 @@ fn main() { | |||
| 1983 | )); | 2184 | )); |
| 1984 | 2185 | ||
| 1985 | // ======== | 2186 | // ======== |
| 2187 | // Generate backup sram constants | ||
| 2188 | if let Some(m) = memory.iter().find(|m| m.name == "BKPSRAM") { | ||
| 2189 | let bkpsram_base = m.address as usize; | ||
| 2190 | let bkpsram_size = m.size as usize; | ||
| 2191 | |||
| 2192 | g.extend(quote!( | ||
| 2193 | pub const BKPSRAM_BASE: usize = #bkpsram_base; | ||
| 2194 | pub const BKPSRAM_SIZE: usize = #bkpsram_size; | ||
| 2195 | )); | ||
| 2196 | } | ||
| 2197 | |||
| 2198 | // ======== | ||
| 1986 | // Generate flash constants | 2199 | // Generate flash constants |
| 1987 | 2200 | ||
| 1988 | let flash_regions: Vec<&MemoryRegion> = memory | 2201 | if has_flash { |
| 1989 | .iter() | 2202 | let flash_regions: Vec<&MemoryRegion> = memory |
| 1990 | .filter(|x| x.kind == MemoryRegionKind::Flash && x.name.starts_with("BANK_")) | 2203 | .iter() |
| 1991 | .collect(); | 2204 | .filter(|x| x.kind == MemoryRegionKind::Flash && x.name.starts_with("BANK_")) |
| 1992 | let first_flash = flash_regions.first().unwrap(); | 2205 | .collect(); |
| 1993 | let total_flash_size = flash_regions | 2206 | let first_flash = flash_regions.first().unwrap(); |
| 1994 | .iter() | 2207 | let total_flash_size = flash_regions |
| 1995 | .map(|x| x.size) | 2208 | .iter() |
| 1996 | .reduce(|acc, item| acc + item) | 2209 | .map(|x| x.size) |
| 1997 | .unwrap(); | 2210 | .reduce(|acc, item| acc + item) |
| 1998 | let write_sizes: HashSet<_> = flash_regions | 2211 | .unwrap(); |
| 1999 | .iter() | 2212 | let write_sizes: HashSet<_> = flash_regions |
| 2000 | .map(|r| r.settings.as_ref().unwrap().write_size) | 2213 | .iter() |
| 2001 | .collect(); | 2214 | .map(|r| r.settings.as_ref().unwrap().write_size) |
| 2002 | assert_eq!(1, write_sizes.len()); | 2215 | .collect(); |
| 2216 | assert_eq!(1, write_sizes.len()); | ||
| 2003 | 2217 | ||
| 2004 | let flash_base = first_flash.address as usize; | 2218 | let flash_base = first_flash.address as usize; |
| 2005 | let total_flash_size = total_flash_size as usize; | 2219 | let total_flash_size = total_flash_size as usize; |
| 2006 | let write_size = (*write_sizes.iter().next().unwrap()) as usize; | 2220 | let write_size = (*write_sizes.iter().next().unwrap()) as usize; |
| 2007 | 2221 | ||
| 2008 | g.extend(quote!( | 2222 | g.extend(quote!( |
| 2009 | pub const FLASH_BASE: usize = #flash_base; | 2223 | pub const FLASH_BASE: usize = #flash_base; |
| 2010 | pub const FLASH_SIZE: usize = #total_flash_size; | 2224 | pub const FLASH_SIZE: usize = #total_flash_size; |
| 2011 | pub const WRITE_SIZE: usize = #write_size; | 2225 | pub const WRITE_SIZE: usize = #write_size; |
| 2012 | )); | 2226 | )); |
| 2227 | } | ||
| 2013 | 2228 | ||
| 2014 | // ======== | 2229 | // ======== |
| 2015 | // Generate EEPROM constants | 2230 | // Generate EEPROM constants |
| @@ -2309,6 +2524,10 @@ fn mem_filter(chip: &str, region: &str) -> bool { | |||
| 2309 | return false; | 2524 | return false; |
| 2310 | } | 2525 | } |
| 2311 | 2526 | ||
| 2527 | if region.starts_with("SDRAM_") || region.starts_with("FMC_") || region.starts_with("OCTOSPI_") { | ||
| 2528 | return false; | ||
| 2529 | } | ||
| 2530 | |||
| 2312 | true | 2531 | true |
| 2313 | } | 2532 | } |
| 2314 | 2533 | ||
