diff --git a/blink/Cargo.lock b/blink/Cargo.lock index 5929913..69bd93a 100644 --- a/blink/Cargo.lock +++ b/blink/Cargo.lock @@ -4,6 +4,7 @@ version = "0.1.0" dependencies = [ "arduino 0.1.0", "core 0.1.0", + "rustc_builtins 0.1.0", ] [[package]] @@ -17,3 +18,10 @@ dependencies = [ name = "core" version = "0.1.0" +[[package]] +name = "rustc_builtins" +version = "0.1.0" +dependencies = [ + "core 0.1.0", +] + diff --git a/blink/Cargo.toml b/blink/Cargo.toml index a51c25a..62ffa62 100644 --- a/blink/Cargo.toml +++ b/blink/Cargo.toml @@ -3,8 +3,21 @@ name = "blink" version = "0.1.0" authors = ["Jake Goulding "] +[profile.release] +lto = true + +# [dependencies] +# rlibc = "*" + [dependencies.core] -path = "../libcore" +path = "../rust-avr-libcore-mini" [dependencies.arduino] path = "../arduino" + +# [dependencies.compiler-rt] +# git = "https://github.com/japaric/compiler-rt.rs" + + +[dependencies.rustc_builtins] +path = "/Users/shep/Projects/rustc-builtins" diff --git a/blink/Makefile b/blink/Makefile index 6115053..6bafb45 100644 --- a/blink/Makefile +++ b/blink/Makefile @@ -1,5 +1,6 @@ COMPILED:=target/arduino/release/blink.elf HEX:=blink.hex +SERIAL_PORT:=/dev/cu.usbmodem1411 all: ${HEX} @@ -14,4 +15,8 @@ ${HEX}: ${COMPILED} # Download the HEX to the board .PHONY: program program: ${HEX} - avrdude -p atmega328p -c arduino -P /dev/cu.usbmodem1411 -U flash:w:$<:i + avrdude -p atmega328p -c arduino -P ${SERIAL_PORT} -U flash:w:$<:i + +.PHONY: connect-terminal +connect-terminal: + picocom ${SERIAL_PORT} diff --git a/blink/arduino.json b/blink/arduino.json index ee5bd27..87947eb 100644 --- a/blink/arduino.json +++ b/blink/arduino.json @@ -1,50 +1,58 @@ { "llvm-target": "avr-atmel-none", + "cpu": "atmega328p", + "target-endian": "little", "target-pointer-width": "16", "os": "none", "target-env": "gnu", "target-vendor": "unknown", "arch": "avr", - "data-layout": "e-p:16:8:8-i8:8:8-i16:8:8-i32:8:8-i64:8:8-f32:8:8-f64:8:8-n8", + "data-layout": "e-p:16:16:16-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-n8", "executables": true, "linker": "avr-gcc", - "pre-link-args": [ - "-mmcu=atmega328p", - "-nostartfiles", - "../interrupt_vector.S" - ], + "linker-flavor": "gcc", + "pre-link-args": { + "gcc": [ + "-mmcu=atmega328p", + "-nostartfiles", + "../interrupt_vector.S", + "../initialize_memory.S" + ] + }, "exe-suffix": ".elf", - "post-link-args": [ - "-Wl,--entry=main", - "-Wl,--entry=_ivr_irq0", - "-Wl,--entry=_ivr_irq1", - "-Wl,--entry=_ivr_pin_change_0", - "-Wl,--entry=_ivr_pin_change_1", - "-Wl,--entry=_ivr_pin_change_2", - "-Wl,--entry=_ivr_watchdog_timer", - "-Wl,--entry=_ivr_timer2_compare_a", - "-Wl,--entry=_ivr_timer2_compare_b", - "-Wl,--entry=_ivr_timer2_overflow", - "-Wl,--entry=_ivr_timer1_capture", - "-Wl,--entry=_ivr_timer1_compare_a", - "-Wl,--entry=_ivr_timer1_compare_b", - "-Wl,--entry=_ivr_timer1_overflow", - "-Wl,--entry=_ivr_timer0_compare_a", - "-Wl,--entry=_ivr_timer0_compare_b", - "-Wl,--entry=_ivr_timer0_overflow", - "-Wl,--entry=_ivr_spi_transfer_complete", - "-Wl,--entry=_ivr_usart_rx_complete", - "-Wl,--entry=_ivr_usart_udr_empty", - "-Wl,--entry=_ivr_usart_tx_complete", - "-Wl,--entry=_ivr_adc_conversion_complete", - "-Wl,--entry=_ivr_eeprom_ready", - "-Wl,--entry=_ivr_analog_comparator", - "-Wl,--entry=_ivr_two_wire_serial_interface", - "-Wl,--entry=_ivr_store_program_memory_ready" - ], + "post-link-args": { + "gcc": [ + "-Wl,--entry=main", + "-Wl,--entry=_ivr_irq0", + "-Wl,--entry=_ivr_irq1", + "-Wl,--entry=_ivr_pin_change_0", + "-Wl,--entry=_ivr_pin_change_1", + "-Wl,--entry=_ivr_pin_change_2", + "-Wl,--entry=_ivr_watchdog_timer", + "-Wl,--entry=_ivr_timer2_compare_a", + "-Wl,--entry=_ivr_timer2_compare_b", + "-Wl,--entry=_ivr_timer2_overflow", + "-Wl,--entry=_ivr_timer1_capture", + "-Wl,--entry=_ivr_timer1_compare_a", + "-Wl,--entry=_ivr_timer1_compare_b", + "-Wl,--entry=_ivr_timer1_overflow", + "-Wl,--entry=_ivr_timer0_compare_a", + "-Wl,--entry=_ivr_timer0_compare_b", + "-Wl,--entry=_ivr_timer0_overflow", + "-Wl,--entry=_ivr_spi_transfer_complete", + "-Wl,--entry=_ivr_usart_rx_complete", + "-Wl,--entry=_ivr_usart_udr_empty", + "-Wl,--entry=_ivr_usart_tx_complete", + "-Wl,--entry=_ivr_adc_conversion_complete", + "-Wl,--entry=_ivr_eeprom_ready", + "-Wl,--entry=_ivr_analog_comparator", + "-Wl,--entry=_ivr_two_wire_serial_interface", + "-Wl,--entry=_ivr_store_program_memory_ready" + ] + }, "no-compiler-rt": true } diff --git a/blink/src/main.rs b/blink/src/main.rs index e372dad..153f399 100644 --- a/blink/src/main.rs +++ b/blink/src/main.rs @@ -1,17 +1,22 @@ #![feature(lang_items)] #![feature(no_core)] #![feature(asm)] +#![feature(naked_functions)] +#![feature(abi_avr_interrupt)] #![no_core] #![no_main] +#[macro_use] extern crate core; extern crate arduino; +extern crate rustc_builtins; use core::prelude::v1::*; use core::ptr::{read_volatile, write_volatile}; // Let's pretend to have a standard library -pub use core::{option, iter}; +pub use core::{option, iter, fmt, ops}; +use core::fmt::Write; use arduino::*; use arduino::prelude::*; @@ -29,52 +34,214 @@ pub unsafe extern "avr-interrupt" fn _ivr_timer1_compare_a() { } const CPU_FREQUENCY_HZ: u64 = 16_000_000; -const DESIRED_HZ_TIM1: f64 = 1.0; -const TIM1_PRESCALER: u64 = 1024; -const INTERRUPT_EVERY_1_HZ_1024_PRESCALER: u16 = ((CPU_FREQUENCY_HZ as f64 / (DESIRED_HZ_TIM1 * TIM1_PRESCALER as f64)) as u64 - 1) as u16; +const CPU_RAM_BYTES: u16 = 2048; -const DESIRED_HZ_TIM0: f64 = 30.0; -const TIM0_PRESCALER: u64 = 1024; -const INTERRUPT_EVERY_30_HZ_1024_PRESCALER: u8 = ((CPU_FREQUENCY_HZ as f64 / (DESIRED_HZ_TIM0 * TIM0_PRESCALER as f64)) as u64 - 1) as u8; +const DESIRED_HZ_TIM1: f64 = 2.0; +const TIM1_PRESCALER: u64 = 1024; +const INTERRUPT_EVERY_1_HZ_1024_PRESCALER: u16 = + ((CPU_FREQUENCY_HZ as f64 / (DESIRED_HZ_TIM1 * TIM1_PRESCALER as f64)) as u64 - 1) as u16; + +// const DESIRED_HZ_TIM0: f64 = 30.0; +// const TIM0_PRESCALER: u64 = 1024; +// const INTERRUPT_EVERY_30_HZ_1024_PRESCALER: u8 = ((CPU_FREQUENCY_HZ as f64 / (DESIRED_HZ_TIM0 * TIM0_PRESCALER as f64)) as u64 - 1) as u8; const BAUD: u64 = 9600; const MYUBRR: u16 = (CPU_FREQUENCY_HZ / 16 / BAUD - 1) as u16; -#[no_mangle] -pub extern fn main() { +// const MEMORY_MAP_START: u16 = MEMORY_MAP_REGISTERS_START; +// const MEMORY_MAP_REGISTERS_START: u16 = 0x0000; // - 0x001F +// const MEMORY_MAP_IO_REGISTERS_START: u16 = 0x0020; // - 0x005F +// const MEMORY_MAP_EXTENDED_IO_REGISTERS_START: u16 = 0x0060; // - 0x00FF +// const MEMORY_MAP_SRAM_START: u16 = 0x0100; +// const MEMORY_MAP_SRAM_END: u16 = 0x0900; // EXCLUSIVE! DEPENDS ON PART! + // 0x02FF/0x04FF/0x4FF/0x08FF + + + +// extern { +// static __data_start: u16; +// static __data_end: u16; +// static __data_load_start: u16; +// static __data_load_end: u16; +// } + +extern { + #[naked] + fn __initialize_memory(); +} + +fn initialize_memory() { unsafe { - without_interrupts(|| { + __initialize_memory(); + } + + // let len = __data_load_end - __data_load_start; + // if len == 0 { return } + + // fn hi_lo(v: u16) -> (u8, u8) { + // (((v >> 8) & 0xFF) as u8, ((v >> 0) & 0xFF) as u8) + // } + + // let (len_hi, len_lo) = hi_lo(len); + // let (z_hi, z_lo) = hi_lo(__data_load_start); + // let (x_hi, x_lo) = hi_lo(__data_start); + +// unsafe { +// asm!(" +// sub r28, r30 +// sbc r29, r31 ; Y now contains the length of bytes +// entrypoint: +// lpm r0, Z+ ; Load from program memory, increment pointer +// st X+, r0 ; Store to RAM, increment pointer + +// subi r28, 1 ; Decrement the count +// sbci r29, 0 +// check: +// brne entrypoint ; Exit when all bytes copied" +// : // output operands +// : // input operands +// "{r31r30}"(__data_load_start) // Z +// "{r27r26}"(__data_start) // X +// "{r29r28}"(__data_load_end) // Y +// : // clobbers +// "cc r0" +// : // options +// ); + + // let src = __data_start as *mut u8; + // let dest = __data_load_start as *mut u8; + // let len = __data_load_end - __data_load_start; + + // let src = 00800100 as *mut u8; + // let dest = 00000126 as *mut u8; + // let len = 00000136 - 00000124; + + // let dest = __data_start as *mut u8; + // let src = __data_load_start as *mut u8; + // let end = __data_load_end as *mut u8; + + // 0x0118 + // 0x0128 + + +} + +#[no_mangle] +pub extern fn main() -> ! { + without_interrupts(|| { // TODO: we know interrupts are off, don't we? + // r1 is assumed to be always zero + unsafe { asm!("eor r1, r1"); } + + unsafe { + write_volatile(SP, CPU_RAM_BYTES); + } + + initialize_memory(); + + unsafe { // Configure all Port B pins as outputs write_volatile(DDRB, 0xFF); // Turn on all Port B pins write_volatile(PORTB, 0xFF); + } - timer0::Timer::new() - .waveform_generation_mode(timer0::WaveformGenerationMode::ClearOnTimerMatchOutputCompare) - .clock_source(timer0::ClockSource::Prescale1024) - .output_compare_1(Some(INTERRUPT_EVERY_30_HZ_1024_PRESCALER)) - .configure(); + timer1::Timer::new() + .waveform_generation_mode(timer1::WaveformGenerationMode::ClearOnTimerMatchOutputCompare) + .clock_source(timer1::ClockSource::Prescale1024) + .output_compare_1(Some(INTERRUPT_EVERY_1_HZ_1024_PRESCALER)) + .configure(); - timer1::Timer::new() - .waveform_generation_mode(timer1::WaveformGenerationMode::ClearOnTimerMatchOutputCompare) - .clock_source(timer1::ClockSource::Prescale1024) - .output_compare_1(Some(INTERRUPT_EVERY_1_HZ_1024_PRESCALER)) - .configure(); + serial::Serial::new(MYUBRR) + .character_size(serial::CharacterSize::EightBits) + .mode(serial::Mode::Asynchronous) + .parity(serial::Parity::Disabled) + .stop_bits(serial::StopBits::OneBit) + .configure(); + }); - serial::Serial::new(MYUBRR) - .character_size(serial::CharacterSize::EightBits) - .mode(serial::Mode::Asynchronous) - .parity(serial::Parity::Disabled) - .stop_bits(serial::StopBits::OneBit) - .configure(); - }); + serial::transmit(b'A'); - for &b in b"hello, world!" { + write_newline(); + for i in 0..4 { + let b = unsafe { *TO_HEX.get_unchecked(i) }; + serial::transmit(b); + } + write_newline(); + + write_u8_hex(0x00); + write_newline(); + write_u8_hex(0x05); + write_newline(); + write_u8_hex(0x50); + write_newline(); + write_u8_hex(0xFF); + write_newline(); + + write_slice_hex(&[0x00, 0x05, 0x50, 0xFF]); + write_newline(); + + write_raw("write_raw"); + + SuperSerial.write_str("write_str\r\n").unwrap(); + + // Formatting code disabled in libcore + writeln!(SuperSerial, "writeln!").unwrap(); + write_newline(); + + serial::transmit(b'Z'); + write_newline(); + + loop { + if let Some(b) = serial::try_receive() { serial::transmit(b); + serial::transmit(b'<'); } - - loop { - // forever! - } + // forever! + } +} + +pub static TO_HEX: &'static [u8; 16] = b"0123456789ABCDEF"; + +#[inline(never)] +pub fn write_slice_hex(v: &[u8]) { + for &b in v { + write_u8_hex(b); + } +} + +#[inline(never)] +pub fn write_u8_hex(v: u8) { + let top_idx = (v >> 4) & 0b1111; + let bot_idx = (v >> 0) & 0b1111; + + let top = unsafe { *TO_HEX.get_unchecked(top_idx as usize) }; + let bot = unsafe { *TO_HEX.get_unchecked(bot_idx as usize) }; + + serial::transmit(top); + serial::transmit(bot); +} + +#[inline(never)] +fn write_newline() { + serial::transmit(b'\r'); + serial::transmit(b'\n'); +} + +#[inline(never)] +fn write_raw(s: &str) { + for b in s.bytes() { + serial::transmit(b); + } + write_newline(); +} + +struct SuperSerial; + +impl fmt::Write for SuperSerial { + fn write_str(&mut self, s: &str) -> Result<(), fmt::Error> { + for b in s.bytes() { + serial::transmit(b); + } + Ok(()) } } diff --git a/initialize_memory.S b/initialize_memory.S new file mode 100644 index 0000000..ccd8bc8 --- /dev/null +++ b/initialize_memory.S @@ -0,0 +1,29 @@ +.section .text +.globl __initialize_memory +.type __initialize_memory, @function + +;;; Does not handle the region pointer! +__initialize_memory: + ldi r31, hi8(__data_load_start) + ldi r30, lo8(__data_load_start) ; Z + + ldi r29, hi8(__data_load_end) + ldi r28, lo8(__data_load_end) ; Y + + ldi r27, hi8(__data_start) + ldi r26, lo8(__data_start) ; X + + sub r28, r30 + sbc r29, r31 ; Y now contains the length of bytes + rjmp check + +entrypoint: + lpm r0, Z+ ; Load from program memory, increment pointer + st X+, r0 ; Store to RAM, increment pointer + + subi r28, 1 ; Decrement the count + sbci r29, 0 + +check: + brne entrypoint ; Exit when all bytes copied + ret diff --git a/libcore/Cargo.toml b/libcore/Cargo.toml index bc49df1..78d1a86 100644 --- a/libcore/Cargo.toml +++ b/libcore/Cargo.toml @@ -4,5 +4,5 @@ version = "0.1.0" authors = ["Jake Goulding "] [lib] -#path = "/Users/shep/Projects/avr-rust/src/libcore/lib.rs" -path = "/tmp/libcore/lib.rs" +path = "/Users/shep/Projects/avr-rust/src/libcore/lib.rs" +# path = "/tmp/libcore/lib.rs"