1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
/* cpu.rs
 *
 * Developed by Tim Walls <tim.walls@snowgoons.com>
 * Copyright (c) All Rights Reserved, Tim Walls
 */
//! ATmega4809-specific CPU control block implementation

// Imports ===================================================================
use avr_oxide::{atmel_cpu_tpl};
use avr_oxide::concurrency::interrupt;
use avr_oxide::hal::generic::cpu::{ContextSaveRestore, ProcessorContext};
use avr_oxide::util::datatypes::{BitField, BitFieldAccess, BitIndex, VolatileBitField};

// Declarations ==============================================================
pub mod cpuregs {
  use avr_oxide::hal::generic::datatypes::IOSpaceU8;

  pub const MAX_BIT_ADDRESSABLE: u8 = 0x1F;

  pub const IOADR_SPL:  u8 = 0x3D;
  pub const IOADR_SPH:  u8 = 0x3E;
  pub const IOADR_SREG: u8 = 0x3F;
  pub const RAMTOP: u16 = 0x3FFF;

  pub const IOADR_CURRENT_CONTEXT_LO:  u8  = 0x1D;
  pub const IOADR_CURRENT_CONTEXT_HI:  u8  = 0x1E;
  pub const IOADR_CONTEXT_FLAGS:       u8  = 0x1C;

  pub(crate) static mut IOREG_SREG           : IOSpaceU8<IOADR_SREG> = IOSpaceU8::get();
  pub(crate) static mut IOREG_CONTEXT_FLAGS  : IOSpaceU8<IOADR_CONTEXT_FLAGS> = IOSpaceU8::get();
  pub(crate) static mut IOREG_CURRENT_CONTEXT_LO : IOSpaceU8<IOADR_CURRENT_CONTEXT_LO> = IOSpaceU8::get();
  pub(crate) static mut IOREG_CURRENT_CONTEXT_HI : IOSpaceU8<IOADR_CURRENT_CONTEXT_HI> = IOSpaceU8::get();
}

#[repr(C)]
pub struct PortmuxControl {
  pub(crate) evsysroutea: u8,
  pub(crate) cclroutea: u8,
  pub(crate) usartroutea: u8,
  pub(crate) twispiroutea: VolatileBitField,
  pub(crate) tcaroutea: u8,
  pub(crate) tcbroutea: u8
}

// Code ======================================================================

atmel_cpu_tpl!(avr_oxide::hal::generic::cpu::base::AvrCpuControlBlock,
  super::ADDR_CPU,super::ADDR_CLKCTRL,super::ADDR_SLPCTRL);

/**
 * Obtain a reference to the CPU controller instance
 */
#[macro_export]
macro_rules! cpu {
  () => {
    avr_oxide::hal::atmega4809::cpu::instance()
  }
}

/**
 * Obtain a references to the Sleep controller instance
 */
#[macro_export]
macro_rules! sleepctrl {
  ($isotoken:expr) => {
    avr_oxide::hal::atmega4809::cpu::sleepctrl_isolated($isotoken)
  };
  () => {
    avr_oxide::hal::atmega4809::cpu::sleepctrl()
  };
}

impl ContextSaveRestore for avr_oxide::hal::generic::cpu::base::AvrCpuControlBlock {
  unsafe fn get_processor_context(&self, _isotoken: interrupt::token::Isolated) -> &mut ProcessorContext {
    let context_addr =
      (((cpuregs::IOREG_CURRENT_CONTEXT_HI.read_byte() as usize) << 8) |
        (cpuregs::IOREG_CURRENT_CONTEXT_LO.read_byte() as usize)) as *mut ProcessorContext;

    &mut *context_addr
  }

  fn was_thread_restored(&self) -> bool {
    unsafe {
     cpuregs::IOREG_CONTEXT_FLAGS.is_set_c::<0>()
    }
  }
}