pub enum ConfigurationChange {
SelfProgramming,
ProtectedRegister
}
pub trait Cpu {
unsafe fn write_protected(&mut self, change: ConfigurationChange,
register: &mut u8, value: u8 );
fn read_sp(&self) -> u16;
unsafe fn write_sp(&mut self, sp: u16);
fn read_sreg(&self) -> u8;
unsafe fn write_sreg(&mut self, sp: u8);
fn interrupts_enabled(&self) -> bool;
}
pub trait ClockControl {
unsafe fn clk_per_prescaler(&mut self, scaler: u8);
}
#[cfg(target_arch="avr")]
pub mod base {
use crate::{v_read,v_write};
use crate::hal::generic::cpu::{ConfigurationChange, Cpu, ClockControl};
#[repr(C)]
pub struct AvrCpuControlBlock {
reserved_0: [u8; 4],
pub(crate) ccp: u8,
reserved_1: [u8; 8],
pub(crate) sp: u16,
pub(crate) sreg: u8
}
#[allow(dead_code)]
pub struct AvrClockControl {
pub(crate) mclkctrla: u8,
pub(crate) mclkctrlb: u8,
pub(crate) mclklock: u8,
pub(crate) mclkstatus: u8,
reserved_0: [u8; 12],
pub(crate) osc20mctrla: u8,
pub(crate) osc20mcaliba: u8,
pub(crate) osc20mcalibb: u8,
reserved_1: [u8; 5],
pub(crate) osc32kctrla: u8,
reserved_2: [u8; 3],
pub(crate) xosc32kctrla: u8
}
extern "C" {
fn ccp_io_write(ioaddr: *mut u8, value: u8);
fn ccp_spm_write(ioaddr: *mut u8, value: u8);
}
impl Cpu for AvrCpuControlBlock {
unsafe fn write_protected(&mut self, change: ConfigurationChange, register: &mut u8, value: u8) {
match change {
ConfigurationChange::SelfProgramming =>
ccp_spm_write(register as *mut u8, value),
ConfigurationChange::ProtectedRegister =>
ccp_io_write(register as *mut u8, value),
}
}
#[inline(always)]
fn read_sp(&self) -> u16 {
unsafe {
v_read!(u16, self.sp)
}
}
#[inline(always)]
unsafe fn write_sp(&mut self, sp: u16) {
v_write!(u16, self.sp, sp)
}
#[inline(always)]
fn read_sreg(&self) -> u8 {
unsafe {
v_read!(u8, self.sreg)
}
}
#[inline(always)]
unsafe fn write_sreg(&mut self, sreg:u8) {
v_write!(u8, self.sreg, sreg);
}
#[inline(always)]
fn interrupts_enabled(&self) -> bool {
unsafe {
(v_read!(u8, self.sreg) & 0b10000000) > 0
}
}
}
impl ClockControl for AvrClockControl {
unsafe fn clk_per_prescaler(&mut self, scaler: u8) {
if scaler == 0 {
ccp_io_write(&mut self.mclkctrlb as *mut u8, 0x00);
} else {
let pdiv_val = match scaler {
2 => 0x00,
4 => 0x01,
8 => 0x02,
16 => 0x03,
32 => 0x04,
64 => 0x05,
6 => 0x08,
10 => 0x09,
12 => 0x0A,
24 => 0x0B,
48 => 0x0C,
_ => panic!()
};
ccp_io_write(&mut self.mclkctrlb as *mut u8, (pdiv_val << 1) | 0x01);
}
}
}
#[doc(hidden)]
#[macro_export]
macro_rules! atmel_cpu_tpl {
($cpuref:expr,$clkref:expr) => {
use crate::hal::generic::cpu::base::{AvrCpuControlBlock,AvrClockControl};
pub type CpuImpl = AvrCpuControlBlock;
#[inline(always)]
pub fn instance() -> &'static mut AvrCpuControlBlock {
unsafe {
core::mem::transmute($cpuref)
}
}
#[inline(always)]
pub fn clock() -> &'static mut AvrClockControl {
unsafe {
core::mem::transmute($clkref)
}
}
}
}
}
#[cfg(not(target_arch="avr"))]
pub mod dummy {
use crate::hal::generic::cpu::{ConfigurationChange, Cpu, ClockControl};
pub struct DummyCpuControlBlock {
pub(crate) sreg: u8
}
pub struct DummyClockControl {}
impl Cpu for DummyCpuControlBlock {
unsafe fn write_protected(&mut self, _change: ConfigurationChange, register: &mut u8, value: u8) {
println!("*** CPU: Protected register write: @{} <- {}", register, value);
}
fn read_sp(&self) -> u16 {
unimplemented!()
}
unsafe fn write_sp(&mut self, _sp: u16) {
unimplemented!()
}
fn read_sreg(&self) -> u8 {
println!("*** CPU: Read SREG: {}", self.sreg);
self.sreg
}
unsafe fn write_sreg(&mut self, sreg: u8) {
println!("*** CPU: Write SREG: {}", sreg);
self.sreg = sreg;
}
fn interrupts_enabled(&self) -> bool {
true
}
}
impl ClockControl for DummyClockControl {
unsafe fn clk_per_prescaler(&mut self, scaler: u8) {
println!("*** CPU: Set clock prescaler to: {}", scaler);
}
}
#[doc(hidden)]
#[macro_export]
macro_rules! atmel_cpu_tpl {
($cpuref:expr,$clkref:expr) => {
use crate::hal::generic::cpu::dummy::{DummyCpuControlBlock,DummyClockControl};
pub type CpuImpl = DummyCpuControlBlock;
static mut DUMMY_CPU: DummyCpuControlBlock = DummyCpuControlBlock {
sreg: 0
};
static mut DUMMY_CLOCK: DummyClockControl = DummyClockControl {};
#[inline(always)]
pub fn instance() -> &'static mut DummyCpuControlBlock {
unsafe {
&mut DUMMY_CPU
}
}
#[inline(always)]
pub fn clock() -> &'static mut DummyClockControl {
unsafe {
&mut DUMMY_CLOCK
}
}
}
}
}