311 lines
13 KiB
Rust
311 lines
13 KiB
Rust
#![no_std]
|
|
#![no_main]
|
|
|
|
extern crate riscv_rt;
|
|
extern crate panic_halt;
|
|
|
|
use riscv_rt::entry;
|
|
|
|
mod uart;
|
|
mod gpio;
|
|
mod timer;
|
|
mod spiflash;
|
|
mod eth;
|
|
|
|
#[entry]
|
|
fn main() -> ! {
|
|
uart::uart_enable_rx();
|
|
println!("");
|
|
println!(" * * HeavyX Testing Firmware * *");
|
|
println!("");
|
|
|
|
loop {
|
|
println!("--------------------------------------------------");
|
|
println!("");
|
|
println!(" [Main Menu]");
|
|
println!("");
|
|
println!(" Type a number to select function:");
|
|
println!(" [1] UART Typewriter");
|
|
println!(" [2] SPI Flash Reader");
|
|
println!(" [3] Ethernet Packet Viewer");
|
|
println!(" [4] LED Blinker");
|
|
print!(">> ");
|
|
loop {
|
|
if uart::uart_get_rxready() == 1 {
|
|
let c = uart::uart_read_byte() as u8;
|
|
if c == b'1' { print!("{}\n", c as char); uart_test(); break; }
|
|
if c == b'2' { print!("{}\n", c as char); spi_test(); break; }
|
|
if c == b'3' { print!("{}\n", c as char); eth_test(); break; }
|
|
if c == b'4' { print!("{}\n", c as char); blink_test(); break; }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fn uart_test() {
|
|
println!("--------------------------------------------------");
|
|
println!("");
|
|
println!(" [UART Typewriter]");
|
|
println!("");
|
|
println!(" Type to start writing.");
|
|
println!(" Backspacing is disabled.");
|
|
println!(" Press [Ctrl]+[D] to exit.");
|
|
println!("..................................................");
|
|
loop {
|
|
if uart::uart_get_rxready() == 1 {
|
|
let c = uart::uart_read_byte() as u8;
|
|
if c == b'\r' { print!("\n") }
|
|
else if c == 0x04 { print!("\n"); break; }
|
|
else if c > 0x1f && c != 0x7f { print!("{}", c as char) }
|
|
}
|
|
}
|
|
}
|
|
|
|
fn spi_test() {
|
|
println!("--------------------------------------------------");
|
|
println!("");
|
|
println!(" [SPI Flash Reader]");
|
|
println!("");
|
|
println!(" Press - / + to change start address.");
|
|
println!(" Press [ / ] to adjust read size.");
|
|
println!(" Press , / . to adjust SPI divisor.");
|
|
println!(" Press [Enter] to read.");
|
|
println!(" Press [Ctrl]+[D] to exit.");
|
|
let mut spi_read_addr = 0x000000 as u32;
|
|
let mut spi_read_size = 512 as u32;
|
|
loop {
|
|
let mut spi_div = spiflash::flash_get_div() as u32;
|
|
println!(">> [ 0x{:06x} - 0x{:06x} ({} bytes) @ divisor = {} ]",
|
|
spi_read_addr, spi_read_addr + spi_read_size - 1, spi_read_size, spi_div);
|
|
let mut spi_exit = 0 as u8;
|
|
loop {
|
|
if uart::uart_get_rxready() == 1 {
|
|
let c = uart::uart_read_byte() as u8;
|
|
// Change address
|
|
if c == b'-' || c == b'+' {
|
|
if c == b'-' && spi_read_addr > 0 {
|
|
if spi_read_addr < spi_read_size { spi_read_addr = 0 }
|
|
else { spi_read_addr -= spi_read_size }
|
|
}
|
|
if c == b'+' && spi_read_addr < 0xffffff {
|
|
if spi_read_addr >= 0x1000000 - spi_read_size { spi_read_addr = 0x1000000 - spi_read_size}
|
|
else { spi_read_addr += spi_read_size }
|
|
}
|
|
break;
|
|
}
|
|
// Change read size
|
|
if c == b'[' || c == b']' {
|
|
if c == b'[' && spi_read_size > 16 {
|
|
spi_read_size >>= 1
|
|
}
|
|
if c == b']' && spi_read_addr + (spi_read_size << 1) <= 0x1000000 {
|
|
spi_read_size <<= 1
|
|
}
|
|
break;
|
|
}
|
|
// Change divisor
|
|
if c == b',' || c == b'.' {
|
|
if c == b',' && spi_div > 1 { spiflash::flash_set_div(spi_div-1) }
|
|
if c == b'.' && spi_div < 0xffff { spiflash::flash_set_div(spi_div+1) }
|
|
break;
|
|
}
|
|
// Read
|
|
if c == b'\r' {
|
|
for x in (spi_read_addr..(spi_read_addr+spi_read_size)).step_by(16) {
|
|
println!(" 0x{:06x} : {:08x} {:08x} {:08x} {:08x}", x,
|
|
spiflash::flash_read_word(x), spiflash::flash_read_word(x+4),
|
|
spiflash::flash_read_word(x+8), spiflash::flash_read_word(x+12));
|
|
}
|
|
break;
|
|
}
|
|
else if c == 0x04 { spi_exit = 1; break; }
|
|
}
|
|
}
|
|
if spi_exit == 1 { break; }
|
|
}
|
|
}
|
|
|
|
fn eth_test() {
|
|
println!("--------------------------------------------------");
|
|
println!("");
|
|
println!(" [Ethernet Packet Viewer]");
|
|
println!("");
|
|
println!(" Automatically receiving incoming packets ...");
|
|
println!(" Press [Ctrl]+[D] to exit.");
|
|
println!("");
|
|
let mut eth_rx_count = 0 as u32;
|
|
let mut eth_rx_start = 1 as u32;
|
|
loop {
|
|
let mut j = 0;
|
|
let mut byte_count = 0;
|
|
let mut eth_exit = 0 as u8;
|
|
loop {
|
|
if eth::eth_get_rxready() == 1 {
|
|
// Read a byte from the packet
|
|
let rxdat = eth::eth_read_rxdat();
|
|
// If reading returns no data, accept UART interrupt
|
|
if eth::eth_get_nodat_from_dat(rxdat) == 1 && eth_rx_start == 1 {
|
|
timer::timer_set(5000000, 0);
|
|
timer::timer_enable();
|
|
while timer::timer_get() != 0 {
|
|
if uart::uart_get_rxready() == 1 {
|
|
let c = uart::uart_read_byte() as u8;
|
|
if c == 0x04 { eth_exit = 1; timer::timer_disable(); break; }
|
|
}
|
|
}
|
|
timer::timer_disable();
|
|
}
|
|
// Otherwise, return byte
|
|
else {
|
|
eth_rx_start = 0;
|
|
if byte_count == 0 {
|
|
println!(">> New eth packet # {}:", eth_rx_count);
|
|
}
|
|
if j == 0 { print!(" ") }
|
|
if j == 8 { print!(" ") }
|
|
print!("{:02x} ", eth::eth_get_byte_from_dat(rxdat));
|
|
byte_count += 1;
|
|
if eth::eth_get_eop_from_dat(rxdat) == 1 {
|
|
print!("\n");
|
|
j = 0;
|
|
eth_rx_start = 1;
|
|
eth_rx_count += 1;
|
|
break;
|
|
}
|
|
if j == 15 { print!("\n"); j = 0; }
|
|
else { j += 1; }
|
|
}
|
|
}
|
|
else {
|
|
println!("\n>> Buffer is full, clearing current buffer...");
|
|
eth::eth_enable_rx_clear();
|
|
while eth::eth_get_rxready() == 0 {
|
|
if uart::uart_get_rxready() == 1 {
|
|
let c = uart::uart_read_byte() as u8;
|
|
if c == 0x04 { eth_exit = 1; timer::timer_disable(); break; }
|
|
}
|
|
}
|
|
eth::eth_disable_rx_clear();
|
|
println!(">> Buffer cleared. Abandoned eth packet # {}:", eth_rx_count);
|
|
j = 0;
|
|
byte_count = 0;
|
|
eth_rx_count += 1;
|
|
}
|
|
if eth_exit == 1 { break; }
|
|
}
|
|
if eth_exit == 1 { break; }
|
|
}
|
|
}
|
|
|
|
fn blink_test() {
|
|
println!("--------------------------------------------------");
|
|
println!("");
|
|
println!(" [LED Blinker]");
|
|
println!("");
|
|
println!(" Each LED will blink once first (primary),");
|
|
println!(" and then twice (secondary).");
|
|
println!(" Press - / + to adjust primary blink time.");
|
|
println!(" Press , / . to adjust secondary blink time.");
|
|
println!(" Press [Ctrl]+[D] to stop and exit.");
|
|
println!("");
|
|
for i in 0..8 {
|
|
gpio::gpio_led_off(i);
|
|
}
|
|
let mut timer_load_primary = 50000000 as u32;
|
|
let mut timer_load_secondary = 12500000 as u32;
|
|
println!(">> [ Primary @ {} clocks ]", timer_load_primary);
|
|
println!(" [ Secondary @ {} clocks ]", timer_load_secondary);
|
|
let mut blink_exit = 0 as u8;
|
|
loop {
|
|
for i in 0..8 {
|
|
println!(">> Blinking LED #{}", i+1);
|
|
timer::timer_set(timer_load_primary, 0);
|
|
timer::timer_enable();
|
|
gpio::gpio_led_toggle(i);
|
|
while timer::timer_get() != 0 {
|
|
if uart::uart_get_rxready() == 1 {
|
|
let c = uart::uart_read_byte() as u8;
|
|
if c == b'-' || c == b'+' {
|
|
if c == b'-' && timer_load_primary > 5000000 { timer_load_primary >>= 1 }
|
|
if c == b'+' && timer_load_primary < 0xffffffff { timer_load_primary <<= 1 }
|
|
}
|
|
if c == b',' || c == b'.' {
|
|
if c == b',' && timer_load_secondary > 5000000 { timer_load_secondary >>= 1 }
|
|
if c == b'.' && timer_load_secondary < 0xffffffff { timer_load_secondary <<= 1 }
|
|
}
|
|
else if c == 0x04 { blink_exit = 1; timer::timer_disable(); break; }
|
|
println!(">> [ Primary @ {} clocks ]", timer_load_primary);
|
|
println!(" [ Secondary @ {} clocks ]", timer_load_secondary);
|
|
}
|
|
}
|
|
timer::timer_disable(); // Reset to LOAD
|
|
timer::timer_enable();
|
|
gpio::gpio_led_toggle(i);
|
|
while timer::timer_get() != 0 {
|
|
if uart::uart_get_rxready() == 1 {
|
|
let c = uart::uart_read_byte() as u8;
|
|
if c == b'-' || c == b'+' {
|
|
if c == b'-' && timer_load_primary > 5000000 { timer_load_primary >>= 1 }
|
|
if c == b'+' && timer_load_primary < 0xffffffff { timer_load_primary <<= 1 }
|
|
}
|
|
if c == b',' || c == b'.' {
|
|
if c == b',' && timer_load_secondary > 5000000 { timer_load_secondary >>= 1 }
|
|
if c == b'.' && timer_load_secondary < 0xffffffff { timer_load_secondary <<= 1 }
|
|
}
|
|
else if c == 0x04 { blink_exit = 1; timer::timer_disable(); break; }
|
|
println!(">> [ Primary @ {} clocks ]", timer_load_primary);
|
|
println!(" [ Secondary @ {} clocks ]", timer_load_secondary);
|
|
}
|
|
}
|
|
timer::timer_disable(); // Reset to LOAD
|
|
for __ in 0..2 {
|
|
timer::timer_set(timer_load_secondary, 0);
|
|
timer::timer_enable();
|
|
gpio::gpio_led_toggle(i);
|
|
while timer::timer_get() != 0 {
|
|
if uart::uart_get_rxready() == 1 {
|
|
let c = uart::uart_read_byte() as u8;
|
|
if c == b'-' || c == b'+' {
|
|
if c == b'-' && timer_load_primary > 5000000 { timer_load_primary >>= 1 }
|
|
if c == b'+' && timer_load_primary < 0xffffffff { timer_load_primary <<= 1 }
|
|
}
|
|
if c == b',' || c == b'.' {
|
|
if c == b',' && timer_load_secondary > 5000000 { timer_load_secondary >>= 1 }
|
|
if c == b'.' && timer_load_secondary < 0xffffffff { timer_load_secondary <<= 1 }
|
|
}
|
|
else if c == 0x04 { blink_exit = 1; timer::timer_disable(); break; }
|
|
println!(">> [ Primary @ {} clocks ]", timer_load_primary);
|
|
println!(" [ Secondary @ {} clocks ]", timer_load_secondary);
|
|
}
|
|
}
|
|
timer::timer_disable(); // Reset to LOAD
|
|
timer::timer_enable();
|
|
gpio::gpio_led_toggle(i);
|
|
while timer::timer_get() != 0 {
|
|
if uart::uart_get_rxready() == 1 {
|
|
let c = uart::uart_read_byte() as u8;
|
|
if c == b'-' || c == b'+' {
|
|
if c == b'-' && timer_load_primary > 5000000 { timer_load_primary >>= 1 }
|
|
if c == b'+' && timer_load_primary < 0xffffffff { timer_load_primary <<= 1 }
|
|
}
|
|
if c == b',' || c == b'.' {
|
|
if c == b',' && timer_load_secondary > 5000000 { timer_load_secondary >>= 1 }
|
|
if c == b'.' && timer_load_secondary < 0xffffffff { timer_load_secondary <<= 1 }
|
|
}
|
|
else if c == 0x04 { blink_exit = 1; timer::timer_disable(); break; }
|
|
println!(">> [ Primary @ {} clocks ]", timer_load_primary);
|
|
println!(" [ Secondary @ {} clocks ]", timer_load_secondary);
|
|
}
|
|
}
|
|
timer::timer_disable(); // Reset to LOAD
|
|
}
|
|
gpio::gpio_led_off(i); // Turn off the current LED
|
|
if blink_exit == 1 { break; }
|
|
}
|
|
if blink_exit == 1 { break; }
|
|
}
|
|
for i in 0..8 {
|
|
gpio::gpio_led_off(i);
|
|
}
|
|
}
|