Next-generation FPGA SoC toolkit
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

310 lines
13 KiB

#![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);
}
}