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
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#![no_std]
#![feature(alloc)]
#![feature(lang_items)]
#![feature(const_fn)]
#![feature(tool_lints)]
#![feature(crate_visibility_modifier)]
#![allow(dead_code)]

extern crate alloc;
extern crate alloc_cortex_m;
extern crate cortex_m;
#[macro_use(entry, exception)]
extern crate cortex_m_rt as rt;
use alloc::alloc::Layout;
use rt::ExceptionFrame;
#[macro_use(interrupt)]
extern crate nrf51;
extern crate nb;
pub extern crate nrf51_hal as hal;
extern crate panic_semihosting;

use hal::prelude::*;

use alloc_cortex_m::CortexMHeap;

pub mod display;
pub mod gpio;
mod rtc;
pub mod serial;
pub mod temp;

#[global_allocator]
static ALLOCATOR: CortexMHeap = CortexMHeap::empty();

#[macro_export]
macro_rules! start {
    ($path:ident) => {
        #[export_name = "begin"]
        pub extern "C" fn __impl_begin() -> ! {
            let f: fn() -> ! = $path;

            f()
        }
    };
}

exception!(HardFault, hard_fault);

fn hard_fault(ef: &ExceptionFrame) -> ! {
    panic!("HardFault at {:#?}", ef);
}

exception!(*, default_handler);

fn default_handler(irqn: i16) {
    panic!("Unhandled exception (IRQn = {})", irqn);
}

entry!(__start);

fn __start() -> ! {
    extern "C" {
        fn begin() -> !;
    }

    let start = rt::heap_start() as usize;
    let size = 1024; // in bytes
    unsafe {
        ALLOCATOR.init(start, size);
    }

    if let Some(p) = nrf51::Peripherals::take() {
        p.CLOCK.tasks_lfclkstart.write(|w| unsafe { w.bits(1) });
        while p.CLOCK.events_lfclkstarted.read().bits() == 0 {}
        p.CLOCK.events_lfclkstarted.write(|w| unsafe { w.bits(0) });

        rtc::init_scheduler(p.RTC1);

        let gpio = p.GPIO.split();

        let row1 = gpio.pin13.into_push_pull_output();
        let row2 = gpio.pin14.into_push_pull_output();
        let row3 = gpio.pin15.into_push_pull_output();

        let column1 = gpio.pin4.into_push_pull_output();
        let column2 = gpio.pin5.into_push_pull_output();
        let column3 = gpio.pin6.into_push_pull_output();
        let column4 = gpio.pin7.into_push_pull_output();
        let column5 = gpio.pin8.into_push_pull_output();
        let column6 = gpio.pin9.into_push_pull_output();
        let column7 = gpio.pin10.into_push_pull_output();
        let column8 = gpio.pin11.into_push_pull_output();
        let column9 = gpio.pin12.into_push_pull_output();

        display::init_display(
            row1, row2, row3, column1, column2, column3, column4, column5, column6, column7,
            column8, column9,
        );

        let txpin = gpio.pin24.into_push_pull_output();
        let rxpin = gpio.pin25.into_floating_input();

        serial::init_serial(p.UART0, txpin, rxpin);

        let a_pin = gpio.pin17.into_floating_input();
        let b_pin = gpio.pin26.into_floating_input();

        gpio::init_buttons(a_pin, b_pin, p.GPIOTE);

        if let Some(mut p) = cortex_m::peripheral::Peripherals::take() {
            p.NVIC.enable(nrf51::Interrupt::RTC1);
            p.NVIC.enable(nrf51::Interrupt::GPIOTE);
            p.NVIC.clear_pending(nrf51::Interrupt::RTC1);
            p.NVIC.clear_pending(nrf51::Interrupt::GPIOTE);
        }

        unsafe {
            begin();
        }
    }

    #[allow(clippy::empty_loop)]
    loop {}
}

#[lang = "oom"]
#[no_mangle]
pub fn rust_oom(_: Layout) -> ! {
    panic!("Out of heap memory!")
}

interrupt! {
    RTC1,
    rtc::handler
}

interrupt! {
    GPIOTE,
    gpio::gpiote_handler
}