Update stm32-data: rcc regs info comes from yamls now.

This commit is contained in:
Dario Nieuwenhuis 2021-11-29 02:10:06 +01:00
parent 3332c40705
commit b0fabfab5d
8 changed files with 75 additions and 148 deletions

View File

@ -103,7 +103,7 @@ crate::pac::peripherals!(
crate::pac::peripherals!( crate::pac::peripherals!(
(can, CAN) => { (can, CAN) => {
unsafe impl bxcan::FilterOwner for peripherals::$inst { unsafe impl bxcan::FilterOwner for peripherals::CAN {
const NUM_FILTER_BANKS: u8 = 14; const NUM_FILTER_BANKS: u8 = 14;
} }
}; };
@ -144,4 +144,10 @@ crate::pac::peripheral_pins!(
($inst:ident, can, CAN, $pin:ident, RX, $af:expr) => { ($inst:ident, can, CAN, $pin:ident, RX, $af:expr) => {
impl_pin!($inst, $pin, RxPin, $af); impl_pin!($inst, $pin, RxPin, $af);
}; };
($inst:ident, can, CAN, $pin:ident, TX) => {
impl_pin!($inst, $pin, TxPin, 0);
};
($inst:ident, can, CAN, $pin:ident, RX) => {
impl_pin!($inst, $pin, RxPin, 0);
};
); );

View File

@ -49,16 +49,11 @@ pac::dma_channels! {
/// safety: must be called only once /// safety: must be called only once
pub(crate) unsafe fn init() { pub(crate) unsafe fn init() {
pac::peripherals! { crate::pac::peripheral_rcc! {
(dmamux, $peri:ident) => { ($name:ident, dmamux, DMAMUX, $clock:ident, ($reg:ident, $field:ident, $set_field:ident), $rst:tt) => {
{ crate::pac::RCC.$reg().modify(|reg| {
pac::peripheral_rcc! { reg.$set_field(true);
($peri, $clock:ident, $en_reg:ident, $rst_reg:ident, $en_fn:ident, $rst_fn:ident) => { });
use crate::rcc::sealed::RccPeripheral;
crate::peripherals::$peri::enable()
};
}
}
}; };
} }
} }

View File

@ -601,14 +601,10 @@ crate::pac::pins!(
); );
pub(crate) unsafe fn init() { pub(crate) unsafe fn init() {
crate::pac::gpio_rcc! { crate::pac::peripheral_rcc! {
($en_reg:ident) => { ($name:ident, gpio, GPIO, $clock:ident, ($reg:ident, $field:ident, $set_field:ident), $rst:tt) => {
crate::pac::RCC.$en_reg().modify(|reg| { crate::pac::RCC.$reg().modify(|reg| {
crate::pac::gpio_rcc! { reg.$set_field(true);
($name:ident, $clock:ident, $en_reg, $rst_reg:ident, $en_fn:ident, $rst_fn:ident) => {
reg.$en_fn(true);
};
}
}); });
}; };
} }

View File

@ -120,35 +120,33 @@ pub(crate) mod sealed {
pub trait RccPeripheral: sealed::RccPeripheral + 'static {} pub trait RccPeripheral: sealed::RccPeripheral + 'static {}
crate::pac::peripheral_rcc!( crate::pac::peripheral_rcc!(
($inst:ident, $clk:ident, $enable:ident, $reset:ident, $perien:ident, $perirst:ident) => { ($inst:ident, gpio, GPIO, $clk:ident, $en:tt, $rst:tt) => {};
($inst:ident, $module:ident, $block:ident, $clk:ident, ($en_reg:ident, $en_field:ident, $en_set_field:ident), ($rst_reg:ident, $rst_field:ident, $rst_set_field:ident)) => {
impl sealed::RccPeripheral for peripherals::$inst { impl sealed::RccPeripheral for peripherals::$inst {
fn frequency() -> crate::time::Hertz { fn frequency() -> crate::time::Hertz {
critical_section::with(|_| { critical_section::with(|_| {
unsafe { unsafe { get_freqs().$clk }
let freqs = get_freqs();
freqs.$clk
}
}) })
} }
fn enable() { fn enable() {
critical_section::with(|_| { critical_section::with(|_| {
unsafe { unsafe {
crate::pac::RCC.$enable().modify(|w| w.$perien(true)); crate::pac::RCC.$en_reg().modify(|w| w.$en_set_field(true));
} }
}) })
} }
fn disable() { fn disable() {
critical_section::with(|_| { critical_section::with(|_| {
unsafe { unsafe {
crate::pac::RCC.$enable().modify(|w| w.$perien(false)); crate::pac::RCC.$en_reg().modify(|w| w.$en_set_field(false));
} }
}) })
} }
fn reset() { fn reset() {
critical_section::with(|_| { critical_section::with(|_| {
unsafe { unsafe {
crate::pac::RCC.$reset().modify(|w| w.$perirst(true)); crate::pac::RCC.$rst_reg().modify(|w| w.$rst_set_field(true));
crate::pac::RCC.$reset().modify(|w| w.$perirst(false)); crate::pac::RCC.$rst_reg().modify(|w| w.$rst_set_field(false));
} }
}) })
} }
@ -156,27 +154,24 @@ crate::pac::peripheral_rcc!(
impl RccPeripheral for peripherals::$inst {} impl RccPeripheral for peripherals::$inst {}
}; };
($inst:ident, $clk:ident, $enable:ident, $perien:ident) => { ($inst:ident, $module:ident, $block:ident, $clk:ident, ($en_reg:ident, $en_field:ident, $en_set_field:ident), _) => {
impl sealed::RccPeripheral for peripherals::$inst { impl sealed::RccPeripheral for peripherals::$inst {
fn frequency() -> crate::time::Hertz { fn frequency() -> crate::time::Hertz {
critical_section::with(|_| { critical_section::with(|_| {
unsafe { unsafe { get_freqs().$clk }
let freqs = get_freqs();
freqs.$clk
}
}) })
} }
fn enable() { fn enable() {
critical_section::with(|_| { critical_section::with(|_| {
unsafe { unsafe {
crate::pac::RCC.$enable().modify(|w| w.$perien(true)); crate::pac::RCC.$en_reg().modify(|w| w.$en_set_field(true));
} }
}) })
} }
fn disable() { fn disable() {
critical_section::with(|_| { critical_section::with(|_| {
unsafe { unsafe {
crate::pac::RCC.$enable().modify(|w| w.$perien(false)); crate::pac::RCC.$en_reg().modify(|w| w.$en_set_field(false));
} }
}) })
} }

@ -1 +1 @@
Subproject commit e60ce40e6f9d29e9a8b45ea7b9118e0d55b30928 Subproject commit ec3fb03dc0325e62ed55ac2dd949b412f3f864e6

View File

@ -42,11 +42,9 @@ pub struct Package {
pub struct Peripheral { pub struct Peripheral {
pub address: u64, pub address: u64,
#[serde(default)] #[serde(default)]
pub kind: Option<String>,
#[serde(default)]
pub block: Option<String>, pub block: Option<String>,
#[serde(default)] #[serde(default)]
pub clock: Option<String>, pub rcc: Option<PeripheralRcc>,
#[serde(default)] #[serde(default)]
pub pins: Vec<Pin>, pub pins: Vec<Pin>,
#[serde(default)] #[serde(default)]
@ -55,6 +53,26 @@ pub struct Peripheral {
pub interrupts: BTreeMap<String, String>, pub interrupts: BTreeMap<String, String>,
} }
#[derive(Debug, Eq, PartialEq, Clone, Deserialize)]
pub struct PeripheralRcc {
pub clock: String,
pub registers: PeripheralRccRegisters,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize)]
pub struct PeripheralRccRegisters {
#[serde(default)]
pub enable: Option<PeripheralRccRegister>,
#[serde(default)]
pub reset: Option<PeripheralRccRegister>,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize)]
pub struct PeripheralRccRegister {
pub register: String,
pub field: String,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize)] #[derive(Debug, Eq, PartialEq, Clone, Deserialize)]
pub struct Pin { pub struct Pin {
pub pin: String, pub pin: String,

View File

@ -1,5 +1,4 @@
use chiptool::generate::CommonModule; use chiptool::generate::CommonModule;
use chiptool::ir::IR;
use proc_macro2::TokenStream; use proc_macro2::TokenStream;
use regex::Regex; use regex::Regex;
use std::collections::{BTreeMap, HashMap, HashSet}; use std::collections::{BTreeMap, HashMap, HashSet};
@ -17,24 +16,6 @@ use chiptool::{generate, ir, transform};
mod data; mod data;
use data::*; use data::*;
fn find_reg<'c>(rcc: &'c ir::IR, reg_regex: &str, field_name: &str) -> Option<(&'c str, &'c str)> {
let reg_regex = Regex::new(reg_regex).unwrap();
for (name, fieldset) in &rcc.fieldsets {
// Workaround for some families that prefix register aliases with C1_, which does
// not help matching for clock name.
if !name.starts_with("C1") && !name.starts_with("C2") && reg_regex.is_match(name) {
for field in &fieldset.fields {
if field_name == field.name {
return Some((name.as_str(), field.name.as_str()));
}
}
}
}
None
}
fn make_peripheral_counts(out: &mut String, data: &BTreeMap<String, u8>) { fn make_peripheral_counts(out: &mut String, data: &BTreeMap<String, u8>) {
write!( write!(
out, out,
@ -130,21 +111,6 @@ pub fn gen_chip(
} }
}); });
// Load RCC register for chip
let (_, rcc) = core
.peripherals
.iter()
.find(|(name, _)| name == &"RCC")
.expect("RCC peripheral missing");
let rcc_block = rcc.block.as_ref().expect("RCC peripheral has no block");
let bi = BlockInfo::parse(&rcc_block);
let rcc_reg_path = options
.data_dir
.join("registers")
.join(&format!("{}_{}.yaml", bi.module, bi.version));
let rcc: IR = serde_yaml::from_reader(File::open(rcc_reg_path).unwrap()).unwrap();
let mut peripheral_versions: BTreeMap<String, String> = BTreeMap::new(); let mut peripheral_versions: BTreeMap<String, String> = BTreeMap::new();
let mut pin_table: Vec<Vec<String>> = Vec::new(); let mut pin_table: Vec<Vec<String>> = Vec::new();
let mut interrupt_table: Vec<Vec<String>> = Vec::new(); let mut interrupt_table: Vec<Vec<String>> = Vec::new();
@ -156,8 +122,6 @@ pub fn gen_chip(
let mut peripheral_counts: BTreeMap<String, u8> = BTreeMap::new(); let mut peripheral_counts: BTreeMap<String, u8> = BTreeMap::new();
let mut dma_channel_counts: BTreeMap<String, u8> = BTreeMap::new(); let mut dma_channel_counts: BTreeMap<String, u8> = BTreeMap::new();
let mut dbgmcu_table: Vec<Vec<String>> = Vec::new(); let mut dbgmcu_table: Vec<Vec<String>> = Vec::new();
let mut gpio_rcc_table: Vec<Vec<String>> = Vec::new();
let mut gpio_regs: HashSet<String> = HashSet::new();
let gpio_base = core.peripherals.get(&"GPIOA".to_string()).unwrap().address as u32; let gpio_base = core.peripherals.get(&"GPIOA".to_string()).unwrap().address as u32;
let gpio_stride = 0x400; let gpio_stride = 0x400;
@ -290,88 +254,38 @@ pub fn gen_chip(
_ => {} _ => {}
} }
// Workaround for clock registers being split on some chip families. Assume fields are if let Some(rcc) = &p.rcc {
// named after peripheral and look for first field matching and use that register. let mut clock = rcc.clock.to_ascii_lowercase();
let mut en = find_reg(&rcc, "^.+ENR\\d*$", &format!("{}EN", name)); if name.starts_with("TIM") {
let mut rst = find_reg(&rcc, "^.+RSTR\\d*$", &format!("{}RST", name)); clock = format!("{}_tim", clock)
if en.is_none() && name.ends_with("1") {
en = find_reg(
&rcc,
"^.+ENR\\d*$",
&format!("{}EN", &name[..name.len() - 1]),
);
rst = find_reg(
&rcc,
"^.+RSTR\\d*$",
&format!("{}RST", &name[..name.len() - 1]),
);
} }
match (en, rst) { let mut row = Vec::new();
(Some((enable_reg, enable_field)), reset_reg_field) => {
let clock = match &p.clock {
Some(clock) => clock.as_str(),
None => {
// No clock was specified, derive the clock name from the enable register name.
// N.B. STM32G0 has only one APB bus but split ENR registers
// (e.g. APBENR1).
Regex::new("([A-Z]+\\d*)ENR\\d*")
.unwrap()
.captures(enable_reg)
.unwrap()
.get(1)
.unwrap()
.as_str()
}
};
let clock = if name.starts_with("TIM") {
format!("{}_tim", clock.to_ascii_lowercase())
} else {
clock.to_ascii_lowercase()
};
let mut row = Vec::with_capacity(6);
row.push(name.clone()); row.push(name.clone());
row.push(bi.module.clone());
row.push(bi.block.clone());
row.push(clock); row.push(clock);
row.push(enable_reg.to_ascii_lowercase());
if let Some((reset_reg, reset_field)) = reset_reg_field { for reg in [&rcc.registers.enable, &rcc.registers.reset] {
row.push(reset_reg.to_ascii_lowercase()); if let Some(reg) = reg {
row.push(format!("set_{}", enable_field.to_ascii_lowercase())); row.push(format!(
row.push(format!("set_{}", reset_field.to_ascii_lowercase())); "({}, {}, set_{})",
reg.register.to_ascii_lowercase(),
reg.field.to_ascii_lowercase(),
reg.field.to_ascii_lowercase()
));
} else { } else {
row.push(format!("set_{}", enable_field.to_ascii_lowercase())); row.push("_".to_string())
}
} }
if !name.starts_with("GPIO") {
peripheral_rcc_table.push(row); peripheral_rcc_table.push(row);
} else {
gpio_rcc_table.push(row);
gpio_regs.insert(enable_reg.to_ascii_lowercase());
}
}
(None, Some(_)) => {
println!("Unable to find enable register for {}", name)
}
(None, None) => {
println!("Unable to find enable and reset register for {}", name)
}
} }
} }
dev.peripherals.push(ir_peri); dev.peripherals.push(ir_peri);
} }
for reg in gpio_regs {
gpio_rcc_table.push(vec![reg]);
}
// We should always find GPIO RCC regs. If not, it means something
// is broken and GPIO won't work because it's not enabled.
assert!(!gpio_rcc_table.is_empty());
for (id, channel_info) in &core.dma_channels { for (id, channel_info) in &core.dma_channels {
let mut row = Vec::new(); let mut row = Vec::new();
let dma_peri = core.peripherals.get(&channel_info.dma).unwrap(); let dma_peri = core.peripherals.get(&channel_info.dma).unwrap();
@ -502,7 +416,6 @@ pub fn gen_chip(
&peripheral_dma_channels_table, &peripheral_dma_channels_table,
); );
make_table(&mut data, "peripheral_rcc", &peripheral_rcc_table); make_table(&mut data, "peripheral_rcc", &peripheral_rcc_table);
make_table(&mut data, "gpio_rcc", &gpio_rcc_table);
make_table(&mut data, "dma_channels", &dma_channels_table); make_table(&mut data, "dma_channels", &dma_channels_table);
make_table(&mut data, "dbgmcu", &dbgmcu_table); make_table(&mut data, "dbgmcu", &dbgmcu_table);
make_peripheral_counts(&mut data, &peripheral_counts); make_peripheral_counts(&mut data, &peripheral_counts);
@ -547,6 +460,8 @@ pub fn gen(options: Options) {
let mut chip_core_names: Vec<String> = Vec::new(); let mut chip_core_names: Vec<String> = Vec::new();
for chip_name in &options.chips { for chip_name in &options.chips {
println!("Generating {}...", chip_name);
let chip = load_chip(&options, chip_name); let chip = load_chip(&options, chip_name);
for (core_index, core) in chip.cores.iter().enumerate() { for (core_index, core) in chip.cores.iter().enumerate() {
let chip_core_name = match chip.cores.len() { let chip_core_name = match chip.cores.len() {

View File

@ -8,7 +8,7 @@ fn main() {
let args: Vec<String> = args().collect(); let args: Vec<String> = args().collect();
let chips = match &args[..] { let mut chips = match &args[..] {
[_, chip] => { [_, chip] => {
vec![chip.clone()] vec![chip.clone()]
} }
@ -24,6 +24,8 @@ fn main() {
_ => panic!("usage: stm32-metapac-gen [chip?]"), _ => panic!("usage: stm32-metapac-gen [chip?]"),
}; };
chips.sort();
gen(Options { gen(Options {
out_dir, out_dir,
data_dir, data_dir,