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