diff --git a/core_generator/src/gen.rs b/core_generator/src/gen.rs index e2e37a2..18d3904 100644 --- a/core_generator/src/gen.rs +++ b/core_generator/src/gen.rs @@ -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. if register.name == "GTCCR" { continue; } + writeln!(w, "#[allow(non_camel_case_types)]")?; writeln!(w, "pub struct {};", register.name)?; 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> { if let Some(port) = mcu.peripheral("PORT") { writeln!(w, "pub mod port {{")?; + writeln!(w, " #![allow(unused_imports)]")?; + writeln!(w)?; writeln!(w, " use super::*;")?; writeln!(w, " use crate::Pin;")?; 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)) .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)) + }; + let find_reg_suffix = |name: &'static str, suffix: &'static str| { + find_reg_suffix_optional(name, suffix) .expect(&format!("could not find '{}' register", name)) }; let timer_number = find_reg("TIMSK").name.chars().last().unwrap() .to_digit(10).unwrap(); - writeln!(w, "/// 8-bit timer.")?; - writeln!(w, "pub struct {};", TYPE_NAME)?; - writeln!(w)?; - writeln!(w, "impl modules::Timer8 for {} {{", TYPE_NAME)?; - writeln!(w, " type CompareA = {};", find_reg_suffix("OCR", "A").name)?; - writeln!(w, " type CompareB = {};", find_reg_suffix("OCR", "B").name)?; - writeln!(w, " type Counter = {};", find_reg("TCNT").name)?; - writeln!(w, " type ControlA = {};", find_reg_suffix("TCCR", "A").name)?; - writeln!(w, " type ControlB = {};", find_reg_suffix("TCCR", "B").name)?; - writeln!(w, " type InterruptMask = {};", find_reg("TIMSK").name)?; - writeln!(w, " type InterruptFlag = {};", find_reg("TIFR").name)?; - writeln!(w, " const CS0: RegisterBits = Self::ControlB::CS00;")?; - writeln!(w, " const CS1: RegisterBits = Self::ControlB::CS01;")?; - writeln!(w, " const CS2: RegisterBits = Self::ControlB::CS02;")?; - writeln!(w, " const WGM0: RegisterBits = Self::ControlA::WGM00;")?; - writeln!(w, " const WGM1: RegisterBits = Self::ControlA::WGM01;")?; - writeln!(w, " const WGM2: RegisterBits = Self::ControlB::WGM020;")?; - writeln!(w, " const OCIEA: RegisterBits = Self::InterruptMask::OCIE{}A;", timer_number)?; - writeln!(w, "}}")?; + // TODO: At the moment, we do not support 8 bit timers that don't have two compare + // registers. + let should_skip_timer = find_reg_suffix_optional("OCR", "B").is_none(); + + if !should_skip_timer { + writeln!(w, "/// 8-bit timer.")?; + writeln!(w, "pub struct {};", TYPE_NAME)?; + writeln!(w)?; + writeln!(w, "impl modules::Timer8 for {} {{", TYPE_NAME)?; + writeln!(w, " type CompareA = {};", find_reg_suffix("OCR", "A").name)?; + writeln!(w, " type CompareB = {};", find_reg_suffix("OCR", "B").name)?; + writeln!(w, " type Counter = {};", find_reg("TCNT").name)?; + writeln!(w, " type ControlA = {};", find_reg_suffix("TCCR", "A").name)?; + writeln!(w, " type ControlB = {};", find_reg_suffix("TCCR", "B").name)?; + writeln!(w, " type InterruptMask = {};", find_reg("TIMSK").name)?; + writeln!(w, " type InterruptFlag = {};", find_reg("TIFR").name)?; + writeln!(w, " const CS0: RegisterBits = Self::ControlB::CS00;")?; + writeln!(w, " const CS1: RegisterBits = Self::ControlB::CS01;")?; + writeln!(w, " const CS2: RegisterBits = Self::ControlB::CS02;")?; + writeln!(w, " const WGM0: RegisterBits = Self::ControlA::WGM00;")?; + writeln!(w, " const WGM1: RegisterBits = Self::ControlA::WGM01;")?; + writeln!(w, " const WGM2: RegisterBits = Self::ControlB::WGM020;")?; + writeln!(w, " const OCIEA: RegisterBits = Self::InterruptMask::OCIE{}A;", timer_number)?; + writeln!(w, "}}")?; + } } if let Some(tc) = mcu.module("TC16") { // Timer/Counter, 16-bit. diff --git a/core_generator/src/main.rs b/core_generator/src/main.rs index 6f043c0..7360949 100644 --- a/core_generator/src/main.rs +++ b/core_generator/src/main.rs @@ -4,7 +4,7 @@ mod gen; use avr_mcu::*; use std::fs::{self, File}; -use std::{env, io}; +use std::io; use std::io::prelude::*; use std::path::{Path, PathBuf}; @@ -12,7 +12,106 @@ use std::path::{Path, PathBuf}; /// archicectures that are not AVR. 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 { match std::env::args().skip(1).next() { @@ -46,7 +145,46 @@ fn main() { }; 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)); } @@ -55,7 +193,8 @@ fn generate_cores(mcus: &[Mcu]) -> Result<(), io::Error> { for mcu in mcus { 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> { @@ -64,18 +203,25 @@ fn generate_core_module(mcu: &Mcu) -> Result<(), io::Error> { 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 mut w = File::create(&path)?; + writeln!(w, "//! The primary module containing microcontroller-specific core definitions")?; writeln!(w)?; + for mcu in mcus { let module_name = core_module_name(mcu); writeln!(w, "/// The {}.", mcu.device.name)?; writeln!(w, "pub mod {};", module_name)?; - writeln!(w, "#[cfg(avr_mcu_{})]", module_name)?; - writeln!(w, "pub use self::{} as current;", module_name)?; + writeln!(w, "#[cfg(avr_mcu_{})] pub use self::{} as current;", module_name, module_name)?; + writeln!(w)?; } writeln!(w) }