Improve the core generator so that it doesn't generate broken modules
Now that the core generator is set to generate modules for all microcontrollers, we need to blacklist the ones it cannot yet handle.
This commit is contained in:
parent
ccad9c169b
commit
d6ab7fafd2
|
@ -9,6 +9,7 @@ pub fn write_registers(mcu: &Mcu, w: &mut dyn Write) -> Result<(), io::Error> {
|
||||||
// HACK: Skip, atmeg328p pack defines two of these.
|
// HACK: Skip, atmeg328p pack defines two of these.
|
||||||
if register.name == "GTCCR" { continue; }
|
if register.name == "GTCCR" { continue; }
|
||||||
|
|
||||||
|
writeln!(w, "#[allow(non_camel_case_types)]")?;
|
||||||
writeln!(w, "pub struct {};", register.name)?;
|
writeln!(w, "pub struct {};", register.name)?;
|
||||||
writeln!(w)?;
|
writeln!(w)?;
|
||||||
|
|
||||||
|
@ -47,6 +48,8 @@ pub fn write_registers(mcu: &Mcu, w: &mut dyn Write) -> Result<(), io::Error> {
|
||||||
pub fn write_pins(mcu: &Mcu, w: &mut dyn Write) -> Result<(), io::Error> {
|
pub fn write_pins(mcu: &Mcu, w: &mut dyn Write) -> Result<(), io::Error> {
|
||||||
if let Some(port) = mcu.peripheral("PORT") {
|
if let Some(port) = mcu.peripheral("PORT") {
|
||||||
writeln!(w, "pub mod port {{")?;
|
writeln!(w, "pub mod port {{")?;
|
||||||
|
writeln!(w, " #![allow(unused_imports)]")?;
|
||||||
|
writeln!(w)?;
|
||||||
writeln!(w, " use super::*;")?;
|
writeln!(w, " use super::*;")?;
|
||||||
writeln!(w, " use crate::Pin;")?;
|
writeln!(w, " use crate::Pin;")?;
|
||||||
writeln!(w)?;
|
writeln!(w)?;
|
||||||
|
@ -164,32 +167,41 @@ pub fn write_timers(mcu: &Mcu, w: &mut dyn Write) -> Result<(), io::Error> {
|
||||||
tc.registers().find(|r| r.name.starts_with(name))
|
tc.registers().find(|r| r.name.starts_with(name))
|
||||||
.expect(&format!("could not find '{}' register", name))
|
.expect(&format!("could not find '{}' register", name))
|
||||||
};
|
};
|
||||||
let find_reg_suffix = |name: &'static str, suffix: &'static str| {
|
let find_reg_suffix_optional = |name: &'static str, suffix: &'static str| {
|
||||||
tc.registers().find(|r| r.name.starts_with(name) && r.name.ends_with(suffix))
|
tc.registers().find(|r| r.name.starts_with(name) && r.name.ends_with(suffix))
|
||||||
|
};
|
||||||
|
let find_reg_suffix = |name: &'static str, suffix: &'static str| {
|
||||||
|
find_reg_suffix_optional(name, suffix)
|
||||||
.expect(&format!("could not find '{}' register", name))
|
.expect(&format!("could not find '{}' register", name))
|
||||||
};
|
};
|
||||||
let timer_number = find_reg("TIMSK").name.chars().last().unwrap()
|
let timer_number = find_reg("TIMSK").name.chars().last().unwrap()
|
||||||
.to_digit(10).unwrap();
|
.to_digit(10).unwrap();
|
||||||
|
|
||||||
writeln!(w, "/// 8-bit timer.")?;
|
// TODO: At the moment, we do not support 8 bit timers that don't have two compare
|
||||||
writeln!(w, "pub struct {};", TYPE_NAME)?;
|
// registers.
|
||||||
writeln!(w)?;
|
let should_skip_timer = find_reg_suffix_optional("OCR", "B").is_none();
|
||||||
writeln!(w, "impl modules::Timer8 for {} {{", TYPE_NAME)?;
|
|
||||||
writeln!(w, " type CompareA = {};", find_reg_suffix("OCR", "A").name)?;
|
if !should_skip_timer {
|
||||||
writeln!(w, " type CompareB = {};", find_reg_suffix("OCR", "B").name)?;
|
writeln!(w, "/// 8-bit timer.")?;
|
||||||
writeln!(w, " type Counter = {};", find_reg("TCNT").name)?;
|
writeln!(w, "pub struct {};", TYPE_NAME)?;
|
||||||
writeln!(w, " type ControlA = {};", find_reg_suffix("TCCR", "A").name)?;
|
writeln!(w)?;
|
||||||
writeln!(w, " type ControlB = {};", find_reg_suffix("TCCR", "B").name)?;
|
writeln!(w, "impl modules::Timer8 for {} {{", TYPE_NAME)?;
|
||||||
writeln!(w, " type InterruptMask = {};", find_reg("TIMSK").name)?;
|
writeln!(w, " type CompareA = {};", find_reg_suffix("OCR", "A").name)?;
|
||||||
writeln!(w, " type InterruptFlag = {};", find_reg("TIFR").name)?;
|
writeln!(w, " type CompareB = {};", find_reg_suffix("OCR", "B").name)?;
|
||||||
writeln!(w, " const CS0: RegisterBits<Self::ControlB> = Self::ControlB::CS00;")?;
|
writeln!(w, " type Counter = {};", find_reg("TCNT").name)?;
|
||||||
writeln!(w, " const CS1: RegisterBits<Self::ControlB> = Self::ControlB::CS01;")?;
|
writeln!(w, " type ControlA = {};", find_reg_suffix("TCCR", "A").name)?;
|
||||||
writeln!(w, " const CS2: RegisterBits<Self::ControlB> = Self::ControlB::CS02;")?;
|
writeln!(w, " type ControlB = {};", find_reg_suffix("TCCR", "B").name)?;
|
||||||
writeln!(w, " const WGM0: RegisterBits<Self::ControlA> = Self::ControlA::WGM00;")?;
|
writeln!(w, " type InterruptMask = {};", find_reg("TIMSK").name)?;
|
||||||
writeln!(w, " const WGM1: RegisterBits<Self::ControlA> = Self::ControlA::WGM01;")?;
|
writeln!(w, " type InterruptFlag = {};", find_reg("TIFR").name)?;
|
||||||
writeln!(w, " const WGM2: RegisterBits<Self::ControlB> = Self::ControlB::WGM020;")?;
|
writeln!(w, " const CS0: RegisterBits<Self::ControlB> = Self::ControlB::CS00;")?;
|
||||||
writeln!(w, " const OCIEA: RegisterBits<Self::InterruptMask> = Self::InterruptMask::OCIE{}A;", timer_number)?;
|
writeln!(w, " const CS1: RegisterBits<Self::ControlB> = Self::ControlB::CS01;")?;
|
||||||
writeln!(w, "}}")?;
|
writeln!(w, " const CS2: RegisterBits<Self::ControlB> = Self::ControlB::CS02;")?;
|
||||||
|
writeln!(w, " const WGM0: RegisterBits<Self::ControlA> = Self::ControlA::WGM00;")?;
|
||||||
|
writeln!(w, " const WGM1: RegisterBits<Self::ControlA> = Self::ControlA::WGM01;")?;
|
||||||
|
writeln!(w, " const WGM2: RegisterBits<Self::ControlB> = Self::ControlB::WGM020;")?;
|
||||||
|
writeln!(w, " const OCIEA: RegisterBits<Self::InterruptMask> = Self::InterruptMask::OCIE{}A;", timer_number)?;
|
||||||
|
writeln!(w, "}}")?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(tc) = mcu.module("TC16") { // Timer/Counter, 16-bit.
|
if let Some(tc) = mcu.module("TC16") { // Timer/Counter, 16-bit.
|
||||||
|
|
|
@ -4,7 +4,7 @@ mod gen;
|
||||||
|
|
||||||
use avr_mcu::*;
|
use avr_mcu::*;
|
||||||
use std::fs::{self, File};
|
use std::fs::{self, File};
|
||||||
use std::{env, io};
|
use std::io;
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
|
@ -12,7 +12,106 @@ use std::path::{Path, PathBuf};
|
||||||
/// archicectures that are not AVR.
|
/// archicectures that are not AVR.
|
||||||
const DEFAULT_MCU_FOR_NON_AVR_DOCS: &'static str = "atmega328";
|
const DEFAULT_MCU_FOR_NON_AVR_DOCS: &'static str = "atmega328";
|
||||||
|
|
||||||
const DEFAULT_FREQUENCY_HZ_FOR_NON_AVR_DOCS: u64 = 16_000_000;
|
// Disable core generation for various devices as it does not work for them yet.
|
||||||
|
const DISABLE_FOR_DEVICES: &'static [&'static str] = &[
|
||||||
|
"ATmega256RFR2",
|
||||||
|
"AT90PWM81",
|
||||||
|
"at90can128",
|
||||||
|
"at90can32",
|
||||||
|
"at90can64",
|
||||||
|
"at90pwm216",
|
||||||
|
"at90pwm316",
|
||||||
|
"at90usb1286",
|
||||||
|
"at90usb1287",
|
||||||
|
"at90usb162",
|
||||||
|
"at90usb646",
|
||||||
|
"at90usb647",
|
||||||
|
"at90usb82",
|
||||||
|
"atmega1280",
|
||||||
|
"atmega1281",
|
||||||
|
"atmega1284",
|
||||||
|
"atmega1284p",
|
||||||
|
"atmega164a",
|
||||||
|
"atmega164p",
|
||||||
|
"atmega164pa",
|
||||||
|
"atmega165a",
|
||||||
|
"atmega165p",
|
||||||
|
"atmega165pa",
|
||||||
|
"atmega168pb",
|
||||||
|
"atmega169a",
|
||||||
|
"atmega169p",
|
||||||
|
"atmega169pa",
|
||||||
|
"atmega16m1",
|
||||||
|
"atmega2560",
|
||||||
|
"atmega2561",
|
||||||
|
"atmega324a",
|
||||||
|
"atmega324p",
|
||||||
|
"atmega324pa",
|
||||||
|
"atmega324pb",
|
||||||
|
"atmega325",
|
||||||
|
"atmega3250",
|
||||||
|
"atmega3250a",
|
||||||
|
"atmega3250p",
|
||||||
|
"atmega3250pa",
|
||||||
|
"atmega325a",
|
||||||
|
"atmega325p",
|
||||||
|
"atmega325pa",
|
||||||
|
"atmega328pb",
|
||||||
|
"atmega329",
|
||||||
|
"atmega3290",
|
||||||
|
"atmega3290a",
|
||||||
|
"atmega3290p",
|
||||||
|
"atmega3290pa",
|
||||||
|
"atmega329a",
|
||||||
|
"atmega329p",
|
||||||
|
"atmega329pa",
|
||||||
|
"atmega32c1",
|
||||||
|
"atmega32m1",
|
||||||
|
"atmega48pb",
|
||||||
|
"atmega640",
|
||||||
|
"atmega644",
|
||||||
|
"atmega644a",
|
||||||
|
"atmega644p",
|
||||||
|
"atmega644pa",
|
||||||
|
"atmega645",
|
||||||
|
"atmega6450",
|
||||||
|
"atmega6450a",
|
||||||
|
"atmega6450p",
|
||||||
|
"atmega645a",
|
||||||
|
"atmega645p",
|
||||||
|
"atmega649",
|
||||||
|
"atmega6490",
|
||||||
|
"atmega6490a",
|
||||||
|
"atmega6490p",
|
||||||
|
"atmega649a",
|
||||||
|
"atmega649p",
|
||||||
|
"atmega64c1",
|
||||||
|
"atmega64m1",
|
||||||
|
"atmega88pb",
|
||||||
|
"attiny10",
|
||||||
|
"attiny102",
|
||||||
|
"attiny104",
|
||||||
|
"attiny13",
|
||||||
|
"attiny13a",
|
||||||
|
"attiny167",
|
||||||
|
"attiny24",
|
||||||
|
"attiny24a",
|
||||||
|
"attiny4",
|
||||||
|
"attiny43u",
|
||||||
|
"attiny44",
|
||||||
|
"attiny44a",
|
||||||
|
"attiny5",
|
||||||
|
"attiny80",
|
||||||
|
"attiny828",
|
||||||
|
"attiny84",
|
||||||
|
"attiny840",
|
||||||
|
"attiny84a",
|
||||||
|
"attiny87",
|
||||||
|
"attiny9",
|
||||||
|
"at90pwm1",
|
||||||
|
"at90pwm2b",
|
||||||
|
"at90pwm3b",
|
||||||
|
];
|
||||||
|
|
||||||
fn base_output_path() -> PathBuf {
|
fn base_output_path() -> PathBuf {
|
||||||
match std::env::args().skip(1).next() {
|
match std::env::args().skip(1).next() {
|
||||||
|
@ -46,7 +145,46 @@ fn main() {
|
||||||
};
|
};
|
||||||
let current_mcu_name = current_mcu.device.name.clone();
|
let current_mcu_name = current_mcu.device.name.clone();
|
||||||
|
|
||||||
generate_cores(&[current_mcu]).unwrap();
|
let microcontrollers = avr_mcu::microcontrollers();
|
||||||
|
let (count_total, mut cores_successful, mut cores_failed) = (microcontrollers.len(), Vec::new(), Vec::new());
|
||||||
|
|
||||||
|
for (i, mcu) in microcontrollers.iter().enumerate() {
|
||||||
|
if DISABLE_FOR_DEVICES.iter().any(|d| mcu.device.name == *d || core_module_name(mcu) == *d) {
|
||||||
|
println!("skipping generation of core for '{}'", mcu.device.name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let result = std::panic::catch_unwind(|| {
|
||||||
|
println!("generating core for '{}' ({} of {})", mcu.device.name, i + 1, count_total);
|
||||||
|
generate_cores(&[mcu.clone()]).unwrap();
|
||||||
|
});
|
||||||
|
|
||||||
|
match result {
|
||||||
|
Ok(..) => {
|
||||||
|
println!("successfully generated core for '{}'", mcu.device.name);
|
||||||
|
cores_successful.push(mcu);
|
||||||
|
},
|
||||||
|
Err(e) => {
|
||||||
|
delete_core_module(mcu).unwrap(); // Don't leave around broken core files.
|
||||||
|
|
||||||
|
let error_message = if let Some(e) = e.downcast_ref::<&dyn std::error::Error>() {
|
||||||
|
format!("{}", e)
|
||||||
|
} else {
|
||||||
|
String::new()
|
||||||
|
};
|
||||||
|
|
||||||
|
eprintln!("failed to generate core for '{}', skipping: {}\n", mcu.device.name, error_message);
|
||||||
|
cores_failed.push(mcu);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println!("generating 'src/cores/mod.rs' for the {} successfully generated cores", cores_successful.len());
|
||||||
|
generate_cores_mod_rs(&cores_successful[..]).expect("failed to generates src/cores/mod.rs");
|
||||||
|
|
||||||
|
println!("statistics:");
|
||||||
|
println!(" total successful: {}", cores_successful.len());
|
||||||
|
println!(" total failed: {}", cores_failed.len());
|
||||||
|
|
||||||
|
|
||||||
println!("cargo:rustc-cfg=avr_mcu_{}", normalize_device_name(¤t_mcu_name));
|
println!("cargo:rustc-cfg=avr_mcu_{}", normalize_device_name(¤t_mcu_name));
|
||||||
}
|
}
|
||||||
|
@ -55,7 +193,8 @@ fn generate_cores(mcus: &[Mcu]) -> Result<(), io::Error> {
|
||||||
for mcu in mcus {
|
for mcu in mcus {
|
||||||
generate_core_module(mcu).expect("failed to generate mcu core");
|
generate_core_module(mcu).expect("failed to generate mcu core");
|
||||||
}
|
}
|
||||||
generate_cores_mod_rs(mcus)
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_core_module(mcu: &Mcu) -> Result<(), io::Error> {
|
fn generate_core_module(mcu: &Mcu) -> Result<(), io::Error> {
|
||||||
|
@ -64,18 +203,25 @@ fn generate_core_module(mcu: &Mcu) -> Result<(), io::Error> {
|
||||||
write_core_module(mcu, &mut file)
|
write_core_module(mcu, &mut file)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_cores_mod_rs(mcus: &[Mcu]) -> Result<(), io::Error> {
|
fn delete_core_module(mcu: &Mcu) -> Result<(), io::Error> {
|
||||||
|
let path = cores_path().join(format!("{}.rs", core_module_name(mcu)));
|
||||||
|
std::fs::remove_file(&path)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generate_cores_mod_rs(mcus: &[&Mcu]) -> Result<(), io::Error> {
|
||||||
let path = cores_path().join("mod.rs");
|
let path = cores_path().join("mod.rs");
|
||||||
let mut w = File::create(&path)?;
|
let mut w = File::create(&path)?;
|
||||||
|
|
||||||
|
writeln!(w, "//! The primary module containing microcontroller-specific core definitions")?;
|
||||||
writeln!(w)?;
|
writeln!(w)?;
|
||||||
|
|
||||||
for mcu in mcus {
|
for mcu in mcus {
|
||||||
let module_name = core_module_name(mcu);
|
let module_name = core_module_name(mcu);
|
||||||
writeln!(w, "/// The {}.", mcu.device.name)?;
|
writeln!(w, "/// The {}.", mcu.device.name)?;
|
||||||
writeln!(w, "pub mod {};", module_name)?;
|
writeln!(w, "pub mod {};", module_name)?;
|
||||||
|
|
||||||
writeln!(w, "#[cfg(avr_mcu_{})]", module_name)?;
|
writeln!(w, "#[cfg(avr_mcu_{})] pub use self::{} as current;", module_name, module_name)?;
|
||||||
writeln!(w, "pub use self::{} as current;", module_name)?;
|
writeln!(w)?;
|
||||||
}
|
}
|
||||||
writeln!(w)
|
writeln!(w)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue