make TRNG testing variants easier to configure

This commit is contained in:
bunnie 2021-04-20 03:21:53 +08:00
parent 9f9575fdd8
commit ec2a87e306
7 changed files with 232 additions and 342 deletions

13
Cargo.lock generated
View file

@ -1457,19 +1457,6 @@ dependencies = [
"xous-names",
]
[[package]]
name = "trng-tester"
version = "0.1.0"
dependencies = [
"heapless",
"log",
"log-server",
"ticktimer-server",
"typenum",
"utralib",
"xous",
]
[[package]]
name = "typenum"
version = "1.12.0"

View file

@ -20,7 +20,6 @@ default-members = [
"services/shellchat",
"services/llio",
"services/rtc",
"services/trng-tester",
"services/cb-test-srv",
"services/cb-test-c1",
"services/cb-test-c2",
@ -55,7 +54,6 @@ members = [
"services/content-plugin-api",
"services/llio",
"services/rtc",
"services/trng-tester",
"services/cb-test-srv",
"services/cb-test-c1",
"services/cb-test-c2",

View file

@ -1,24 +0,0 @@
[package]
name = "trng-tester"
version = "0.1.0"
authors = ["bunnie <bunnie@kosagi.com>"]
edition = "2018"
description = "TRNG tester"
[dependencies]
xous = { path = "../../xous-rs" }
heapless = "0.5"
log-server = { path = "../log-server" }
ticktimer-server = { path = "../ticktimer-server" }
log = "0.4"
typenum = "1.12"
[target.'cfg(not(any(windows,unix)))'.dependencies]
utralib = { path = "../../utralib"}
[target.'cfg(any(windows,unix))'.dependencies]
[features]
debugprint = []
default = [] # "debugprint"
#default = ["debugprint"]

View file

@ -1,265 +0,0 @@
#![cfg_attr(target_os = "none", no_std)]
#![cfg_attr(target_os = "none", no_main)]
use log::info;
pub enum WhichMessible {
One,
Two,
}
pub const TRNG_BUFF_LEN: usize = 512*1024;
#[cfg(target_os = "none")]
mod implementation {
use utralib::generated::*;
use xous::MemoryRange;
use crate::WhichMessible;
pub struct Trng {
server_csr: utralib::CSR<u32>,
messible_csr: utralib::CSR<u32>,
messible2_csr: utralib::CSR<u32>,
buffer_a: MemoryRange,
buffer_b: MemoryRange,
}
fn handle_irq(_irq_no: usize, arg: *mut usize) {
let trng = unsafe { &mut *(arg as *mut Trng) };
// just clear the pending request, as this is used as a "wait" until request function
trng.server_csr.wo(utra::trng_server::EV_PENDING, trng.server_csr.r(utra::trng_server::EV_PENDING));
}
impl Trng {
pub fn new() -> Trng {
let server_csr = xous::syscall::map_memory(
xous::MemoryAddress::new(utra::trng_server::HW_TRNG_SERVER_BASE),
None,
4096,
xous::MemoryFlags::R | xous::MemoryFlags::W,
)
.expect("couldn't map TRNG Server CSR range");
let buff_a = xous::syscall::map_memory(
xous::MemoryAddress::new(0x4020_0000), // fix this at a known physical address
None,
crate::TRNG_BUFF_LEN,
xous::MemoryFlags::R | xous::MemoryFlags::W,
)
.expect("couldn't map TRNG comms buffer A");
let buff_b = xous::syscall::map_memory(
xous::MemoryAddress::new(0x4030_0000), // fix this at a known physical address
None,
crate::TRNG_BUFF_LEN,
xous::MemoryFlags::R | xous::MemoryFlags::W,
)
.expect("couldn't map TRNG comms buffer B");
let messible = xous::syscall::map_memory(
xous::MemoryAddress::new(utra::messible::HW_MESSIBLE_BASE),
None,
4096,
xous::MemoryFlags::R | xous::MemoryFlags::W,
)
.expect("couldn't map messible");
let messible2 = xous::syscall::map_memory(
xous::MemoryAddress::new(utra::messible2::HW_MESSIBLE2_BASE),
None,
4096,
xous::MemoryFlags::R | xous::MemoryFlags::W,
)
.expect("couldn't map messible");
let mut trng = Trng {
server_csr: CSR::new(server_csr.as_mut_ptr() as *mut u32),
buffer_a: buff_a,
buffer_b: buff_b,
messible_csr: CSR::new(messible.as_mut_ptr() as *mut u32),
messible2_csr: CSR::new(messible2.as_mut_ptr() as *mut u32),
};
xous::claim_interrupt(
utra::trng_server::TRNG_SERVER_IRQ,
handle_irq,
(&mut trng) as *mut Trng as *mut usize,
)
.expect("couldn't claim irq");
trng
}
pub fn init(&mut self) {
///// configure power settings and which generator to use
self.server_csr.wo(utra::trng_server::CONTROL,
self.server_csr.ms(utra::trng_server::CONTROL_ENABLE, 1)
| self.server_csr.ms(utra::trng_server::CONTROL_POWERSAVE, 0)
// | self.server_csr.ms(utra::trng_server::CONTROL_AV_DIS, 1) // disable the AV generator to characterize the RO
// | self.server_csr.ms(utra::trng_server::CONTROL_RO_DIS, 1) // disable the RO to characterize only the AV
);
///// configure avalanche
// delay in microseconds for avalanche poweron after powersave
// self.server_csr.rmwf(utra::trng_server::AV_CONFIG_POWERDELAY, 50_000);
self.server_csr.wo(utra::trng_server::AV_CONFIG,
self.server_csr.ms(utra::trng_server::AV_CONFIG_POWERDELAY, 50_000)
| self.server_csr.ms(utra::trng_server::AV_CONFIG_SAMPLES, 32)
);
///// configure ring oscillator
self.server_csr.wo(utra::trng_server::RO_CONFIG,
self.server_csr.ms(utra::trng_server::RO_CONFIG_DELAY, 4)
| self.server_csr.ms(utra::trng_server::RO_CONFIG_DWELL, 100)
| self.server_csr.ms(utra::trng_server::RO_CONFIG_GANG, 1)
| self.server_csr.ms(utra::trng_server::RO_CONFIG_FUZZ, 1)
| self.server_csr.ms(utra::trng_server::RO_CONFIG_OVERSAMPLING, 3)
)
/* historical note -- for modular noise variants -- do not remove
self.xadc_csr.rmwf(utra::trng::MODNOISE_CTL_PERIOD, 495); // to set just the period
self.xadc_csr.wo(utra::trng::MODNOISE_CTL, // to set also the deadtime
self.xadc_csr.ms(utra::trng::MODNOISE_CTL_ENA, 1)
| self.xadc_csr.ms(utra::trng::MODNOISE_CTL_PERIOD, 64)
| self.xadc_csr.ms(utra::trng::MODNOISE_CTL_DEADTIME, 5)
);*/
}
pub fn messible_send(&mut self, which: WhichMessible, value: u8) {
match which {
WhichMessible::One => self.messible_csr.wfo(utra::messible::IN_IN, value as u32),
WhichMessible::Two => self.messible2_csr.wfo(utra::messible2::IN_IN, value as u32),
}
}
#[allow(dead_code)]
pub fn messible_get(&mut self, which: WhichMessible) -> u8 {
match which {
WhichMessible::One => self.messible_csr.rf(utra::messible::OUT_OUT) as u8,
WhichMessible::Two => self.messible2_csr.rf(utra::messible2::OUT_OUT) as u8,
}
}
pub fn messible_wait_get(&mut self, which: WhichMessible) -> u8 {
match which {
WhichMessible::One => {
while self.messible_csr.rf(utra::messible::STATUS_HAVE) == 0 {
xous::yield_slice();
}
self.messible_csr.rf(utra::messible::OUT_OUT) as u8
},
WhichMessible::Two => {
while self.messible2_csr.rf(utra::messible2::STATUS_HAVE) == 0 {
xous::yield_slice();
}
self.messible2_csr.rf(utra::messible2::OUT_OUT) as u8
},
}
}
pub fn get_buff_a(&self) -> *mut u32 {
self.buffer_a.as_mut_ptr() as *mut u32
}
pub fn get_buff_b(&self) -> *mut u32 {
self.buffer_b.as_mut_ptr() as *mut u32
}
pub fn get_data_eager(&self) -> u32 {
while self.server_csr.rf(utra::trng_server::STATUS_AVAIL) == 0 {
xous::yield_slice();
}
self.server_csr.rf(utra::trng_server::DATA_DATA)
}
pub fn wait_full(&self) {
while self.server_csr.rf(utra::trng_server::STATUS_FULL) == 0 {
xous::yield_slice();
}
}
}
}
// a stub to try to avoid breaking hosted mode for as long as possible.
#[cfg(not(target_os = "none"))]
mod implementation {
pub struct Trng {
}
impl Trng {
pub fn new() -> Trng {
Trng {
}
}
pub fn messible_send(&mut self, which: WhichMessible, value: u32) {
}
pub fn init(&mut self) {
}
}
}
fn wdt_thread() {
let ticktimer = ticktimer_server::Ticktimer::new().expect("Couldn't connect to Ticktimer");
loop {
ticktimer.sleep_ms(100).unwrap();
}
}
#[xous::xous_main]
fn xmain() -> ! {
use crate::implementation::Trng;
log_server::init_wait().unwrap();
log::set_max_level(log::LevelFilter::Info);
info!("my PID is {}", xous::process::id());
let ticktimer = ticktimer_server::Ticktimer::new().expect("Couldn't connect to Ticktimer");
xous::create_thread_0(wdt_thread).expect("couldn't create waking thread");
// Create a new com object
let mut trng = Trng::new();
trng.init();
// just create buffers out of pointers. Definitely. Unsafe.
let buff_a = trng.get_buff_a() as *mut u32;
let buff_b = trng.get_buff_b() as *mut u32;
for i in 0..TRNG_BUFF_LEN / 4 {
// buff_a[i] = trng.get_data_eager();
unsafe { buff_a.add(i).write_volatile(trng.get_data_eager()) };
}
for i in 0..TRNG_BUFF_LEN / 4 {
// buff_b[i] = trng.get_data_eager();
unsafe { buff_b.add(i).write_volatile(trng.get_data_eager()) };
}
info!("TRNG: starting service");
let mut phase = 1;
trng.messible_send(WhichMessible::One, phase); // indicate buffer A is ready to go
loop {
if false {
// to test the powerdown feature
trng.wait_full();
ticktimer.sleep_ms(5000).expect("couldn't sleep");
}
// to test the full loop
trng.messible_wait_get(WhichMessible::Two);
phase += 1;
if phase % 2 == 1 {
info!("TRNG: filling A");
for i in 0..TRNG_BUFF_LEN / 4 {
//buff_a[i] = trng.get_data_eager();
unsafe { buff_a.add(i).write_volatile(trng.get_data_eager()) };
}
trng.messible_send(WhichMessible::One, phase);
} else {
info!("TRNG: filling B");
for i in 0..TRNG_BUFF_LEN / 4 {
//buff_b[i] = trng.get_data_eager();
unsafe { buff_b.add(i).write_volatile(trng.get_data_eager()) };
}
trng.messible_send(WhichMessible::One, phase);
}
}
}

View file

@ -21,4 +21,6 @@ utralib = { path = "../../utralib"}
[features]
debugprint = []
avalanchetest = []
ringosctest = []
default = [] # "debugprint"

View file

@ -34,12 +34,38 @@ mod implementation {
};
///// configure power settings and which generator to use
trng.csr.wo(utra::trng_server::CONTROL,
trng.csr.ms(utra::trng_server::CONTROL_ENABLE, 1)
| trng.csr.ms(utra::trng_server::CONTROL_POWERSAVE, 1)
// | self.server_csr.ms(utra::trng_server::CONTROL_AV_DIS, 1) // disable the AV generator to characterize the RO
// | self.server_csr.ms(utra::trng_server::CONTROL_RO_DIS, 1) // disable the RO to characterize only the AV
);
if !(cfg!(feature = "avalanchetest") || cfg!(feature = "ringosctest")) {
trng.csr.wo(utra::trng_server::CONTROL,
trng.csr.ms(utra::trng_server::CONTROL_ENABLE, 1)
| trng.csr.ms(utra::trng_server::CONTROL_POWERSAVE, 1)
// | self.server_csr.ms(utra::trng_server::CONTROL_AV_DIS, 1) // disable the AV generator to characterize the RO
// | self.server_csr.ms(utra::trng_server::CONTROL_RO_DIS, 1) // disable the RO to characterize only the AV
);
log::trace!("TRNG configured for normal operation (av+ro): 0x{:08x}", trng.csr.r(utra::trng_server::CONTROL));
} else if cfg!(feature = "avalanchetest") && ! cfg!(feature = "ringosctest") {
// avalanche test only
trng.csr.wo(utra::trng_server::CONTROL,
trng.csr.ms(utra::trng_server::CONTROL_ENABLE, 1)
| trng.csr.ms(utra::trng_server::CONTROL_POWERSAVE, 1) // question: do we want power save on or off for testing?? let's leave it on for now, it will make the test run slower but maybe more accurate to our usual use case
| trng.csr.ms(utra::trng_server::CONTROL_RO_DIS, 1) // disable the RO to characterize only the AV
);
log::info!("TRNG configured for avalanche testing: 0x{:08x}", trng.csr.r(utra::trng_server::CONTROL));
} else if ! cfg!(feature = "avalanchetest") && cfg!(feature = "ringosctest") {
// ring osc test only
trng.csr.wo(utra::trng_server::CONTROL,
trng.csr.ms(utra::trng_server::CONTROL_ENABLE, 1)
| trng.csr.ms(utra::trng_server::CONTROL_POWERSAVE, 1)
| trng.csr.ms(utra::trng_server::CONTROL_AV_DIS, 1) // disable the AV generator to characterize the RO
);
log::info!("TRNG configured for ring oscillator testing: 0x{:08x}", trng.csr.r(utra::trng_server::CONTROL));
} else {
// both on
trng.csr.wo(utra::trng_server::CONTROL,
trng.csr.ms(utra::trng_server::CONTROL_ENABLE, 1)
| trng.csr.ms(utra::trng_server::CONTROL_POWERSAVE, 1)
);
log::info!("TRNG configured for both avalanche and ring oscillator testing: 0x{:08x}", trng.csr.r(utra::trng_server::CONTROL));
}
/*** TRNG tuning parameters: these were configured and tested in a long run against Dieharder
There is a rate of TRNG generation vs. quality trade-off. The tuning below is toward quality of
@ -65,6 +91,11 @@ mod implementation {
trng
}
// for the test procedure
#[cfg(any(feature = "avalanchetest", feature="ringosctest"))]
pub fn get_trng_csr(&self) -> *mut u32 {
self.csr.base
}
pub fn get_data_eager(&self) -> u32 {
while self.csr.rf(utra::trng_server::STATUS_AVAIL) == 0 {
@ -145,6 +176,166 @@ mod implementation {
}
}
#[cfg(any(feature = "avalanchetest", feature="ringosctest"))]
pub const TRNG_BUFF_LEN: usize = 512*1024;
#[cfg(any(feature = "avalanchetest", feature="ringosctest"))]
pub enum WhichMessible {
One,
Two,
}
#[cfg(any(feature = "avalanchetest", feature="ringosctest"))]
struct Tester {
server_csr: utralib::CSR<u32>,
messible_csr: utralib::CSR<u32>,
messible2_csr: utralib::CSR<u32>,
buffer_a: xous::MemoryRange,
buffer_b: xous::MemoryRange,
ticktimer: ticktimer_server::Ticktimer,
}
#[cfg(any(feature = "avalanchetest", feature="ringosctest"))]
impl Tester {
pub fn new(server_csr: *mut u32) -> Tester {
use utralib::generated::*;
let buff_a = xous::syscall::map_memory(
xous::MemoryAddress::new(0x4020_0000), // fix this at a known physical address
None,
crate::TRNG_BUFF_LEN,
xous::MemoryFlags::R | xous::MemoryFlags::W,
)
.expect("couldn't map TRNG comms buffer A");
let buff_b = xous::syscall::map_memory(
xous::MemoryAddress::new(0x4030_0000), // fix this at a known physical address
None,
crate::TRNG_BUFF_LEN,
xous::MemoryFlags::R | xous::MemoryFlags::W,
)
.expect("couldn't map TRNG comms buffer B");
let messible = xous::syscall::map_memory(
xous::MemoryAddress::new(utra::messible::HW_MESSIBLE_BASE),
None,
4096,
xous::MemoryFlags::R | xous::MemoryFlags::W,
)
.expect("couldn't map messible");
let messible2 = xous::syscall::map_memory(
xous::MemoryAddress::new(utra::messible2::HW_MESSIBLE2_BASE),
None,
4096,
xous::MemoryFlags::R | xous::MemoryFlags::W,
)
.expect("couldn't map messible");
Tester {
server_csr: CSR::new(server_csr),
buffer_a: buff_a,
buffer_b: buff_b,
messible_csr: CSR::new(messible.as_mut_ptr() as *mut u32),
messible2_csr: CSR::new(messible2.as_mut_ptr() as *mut u32),
ticktimer: ticktimer_server::Ticktimer::new().unwrap(),
}
}
pub fn messible_send(&mut self, which: WhichMessible, value: u8) {
use utralib::generated::*;
match which {
WhichMessible::One => self.messible_csr.wfo(utra::messible::IN_IN, value as u32),
WhichMessible::Two => self.messible2_csr.wfo(utra::messible2::IN_IN, value as u32),
}
}
#[allow(dead_code)]
pub fn messible_get(&mut self, which: WhichMessible) -> u8 {
use utralib::generated::*;
match which {
WhichMessible::One => self.messible_csr.rf(utra::messible::OUT_OUT) as u8,
WhichMessible::Two => self.messible2_csr.rf(utra::messible2::OUT_OUT) as u8,
}
}
pub fn messible_wait_get(&mut self, which: WhichMessible) -> u8 {
use utralib::generated::*;
match which {
WhichMessible::One => {
while self.messible_csr.rf(utra::messible::STATUS_HAVE) == 0 {
//xous::yield_slice();
self.ticktimer.sleep_ms(50).unwrap();
}
self.messible_csr.rf(utra::messible::OUT_OUT) as u8
},
WhichMessible::Two => {
while self.messible2_csr.rf(utra::messible2::STATUS_HAVE) == 0 {
//xous::yield_slice();
self.ticktimer.sleep_ms(50).unwrap();
}
self.messible2_csr.rf(utra::messible2::OUT_OUT) as u8
},
}
}
pub fn get_buff_a(&self) -> *mut u32 {
self.buffer_a.as_mut_ptr() as *mut u32
}
pub fn get_buff_b(&self) -> *mut u32 {
self.buffer_b.as_mut_ptr() as *mut u32
}
pub fn get_data_eager(&self) -> u32 {
use utralib::generated::*;
while self.server_csr.rf(utra::trng_server::STATUS_AVAIL) == 0 {
xous::yield_slice();
}
self.server_csr.rf(utra::trng_server::DATA_DATA)
}
#[allow(dead_code)]
pub fn wait_full(&self) {
use utralib::generated::*;
while self.server_csr.rf(utra::trng_server::STATUS_FULL) == 0 {
xous::yield_slice();
}
}
}
#[cfg(any(feature = "avalanchetest", feature="ringosctest"))]
fn tester_thread(csr: usize) {
let mut trng = Tester::new(csr as *mut u32);
// just create buffers out of pointers. Definitely. Unsafe.
let buff_a = trng.get_buff_a() as *mut u32;
let buff_b = trng.get_buff_b() as *mut u32;
for i in 0..TRNG_BUFF_LEN / 4 {
// buff_a[i] = trng.get_data_eager();
unsafe { buff_a.add(i).write_volatile(trng.get_data_eager()) };
}
for i in 0..TRNG_BUFF_LEN / 4 {
// buff_b[i] = trng.get_data_eager();
unsafe { buff_b.add(i).write_volatile(trng.get_data_eager()) };
}
log::info!("TRNG_TESTER: starting service");
let mut phase = 1;
trng.messible_send(WhichMessible::One, phase); // indicate buffer A is ready to go
loop {
trng.messible_wait_get(WhichMessible::Two);
phase += 1;
if phase % 2 == 1 {
log::info!("TRNG_TESTER: filling A");
for i in 0..TRNG_BUFF_LEN / 4 {
//buff_a[i] = trng.get_data_eager();
unsafe { buff_a.add(i).write_volatile(trng.get_data_eager()) };
}
trng.messible_send(WhichMessible::One, phase);
} else {
log::info!("TRNG_TESTER: filling B");
for i in 0..TRNG_BUFF_LEN / 4 {
//buff_b[i] = trng.get_data_eager();
unsafe { buff_b.add(i).write_volatile(trng.get_data_eager()) };
}
trng.messible_send(WhichMessible::One, phase);
}
}
}
#[xous::xous_main]
fn xmain() -> ! {
use crate::implementation::Trng;
@ -163,6 +354,10 @@ fn xmain() -> ! {
#[cfg(not(target_os = "none"))]
let mut trng = Trng::new();
if cfg!(feature = "avalanchetest") || cfg!(feature = "ringosctest") {
xous::create_thread_1(tester_thread, trng.get_trng_csr() as usize).expect("couldn't create test thread");
}
// pump the TRNG hardware to clear the first number out, sometimes it is 0 due to clock-sync issues on the fifo
trng.get_trng(2);
log::trace!("ready to accept requests");

View file

@ -90,22 +90,6 @@ fn try_main() -> Result<(), DynError> {
"cb-test-c1",
"cb-test-c2",
];
let trng_pkgs = [
//"gam",
//"shellchat",
//"ime-frontend",
//"ime-plugin-shell",
"graphics-server",
"ticktimer-server",
"log-server",
"com",
"xous-names",
"keyboard",
"llio",
"rtc",
"trng-tester",
];
let task = env::args().nth(1);
match task.as_deref() {
Some("renode-image") => renode_image(false, &hw_pkgs)?,
@ -115,12 +99,17 @@ fn try_main() -> Result<(), DynError> {
)?,
Some("renode-image-debug") => renode_image(true, &hw_pkgs)?,
Some("run") => run(false, &hw_pkgs)?,
Some("hw-image") => build_hw_image(false, env::args().nth(2), &hw_pkgs)?,
Some("benchmark") => build_hw_image(false, env::args().nth(2), &benchmark_pkgs)?,
Some("fcc-agent") => build_hw_image(false, env::args().nth(2), &fcc_pkgs)?,
Some("minimal") => build_hw_image(false, env::args().nth(2), &minimal_pkgs)?,
Some("cbtest") => build_hw_image(false, env::args().nth(2), &cbtest_pkgs)?,
Some("trng-test") => build_hw_image(false, env::args().nth(2), &trng_pkgs)?,
Some("hw-image") => build_hw_image(false, env::args().nth(2), &hw_pkgs, None)?,
Some("benchmark") => build_hw_image(false, env::args().nth(2), &benchmark_pkgs, None)?,
Some("fcc-agent") => build_hw_image(false, env::args().nth(2), &fcc_pkgs, None)?,
Some("minimal") => build_hw_image(false, env::args().nth(2), &minimal_pkgs, None)?,
Some("cbtest") => build_hw_image(false, env::args().nth(2), &cbtest_pkgs, None)?,
Some("trng-test") => build_hw_image(false, env::args().nth(2), &hw_pkgs,
Some(&["--features", "ringosctest", "--features", "avalanchetest"]))?,
Some("ro-test") => build_hw_image(false, env::args().nth(2), &hw_pkgs,
Some(&["--features", "ringosctest"]))?,
Some("av-test") => build_hw_image(false, env::args().nth(2), &hw_pkgs,
Some(&["--features", "avalanchetest"]))?,
Some("debug") => run(true, &hw_pkgs)?,
_ => print_help(),
}
@ -140,12 +129,14 @@ benchmark [soc.svd] builds a benchmarking image for real hardware
fcc-agent [soc.svd] builds a version suitable for FCC testing
minimal [soc.svd] builds a minimal image for API testing
cbtest builds an image for callback testing
trng-test [soc.svd] builds an image for TRNG testing
trng-test [soc.svd] builds an image for TRNG testing (both avalanche and ring oscillator on)
ro-test [soc.svd] builds an image for ring oscillator only TRNG testing
av-test [soc.svd] builds an image for avalanche generater only TRNG testing
"
)
}
fn build_hw_image(debug: bool, svd: Option<String>, packages: &[&str]) -> Result<(), DynError> {
fn build_hw_image(debug: bool, svd: Option<String>, packages: &[&str], extra_args: Option<&[&str]>) -> Result<(), DynError> {
let svd_file = match svd {
Some(s) => s,
None => return Err("svd file not specified".into()),
@ -163,13 +154,13 @@ fn build_hw_image(debug: bool, svd: Option<String>, packages: &[&str]) -> Result
let kernel = build_kernel(debug)?;
let mut init = vec![];
let base_path = build(packages, debug, Some(TARGET), None)?;
let base_path = build(packages, debug, Some(TARGET), None, extra_args)?;
for pkg in packages {
let mut pkg_path = base_path.clone();
pkg_path.push(pkg);
init.push(pkg_path);
}
let mut loader = build(&["loader"], debug, Some(TARGET), Some("loader".into()))?;
let mut loader = build(&["loader"], debug, Some(TARGET), Some("loader".into()), None)?;
loader.push(PathBuf::from("loader"));
let output_bundle = create_image(&kernel, &init, debug, MemorySpec::SvdFile(svd_file))?;
@ -192,8 +183,7 @@ fn build_hw_image(debug: bool, svd: Option<String>, packages: &[&str]) -> Result
"--",
loader.as_os_str().to_str().unwrap(),
loader_bin.as_os_str().to_str().unwrap(),
])
.status()?;
]).status()?;
if !status.success() {
return Err("cargo build failed".into());
}
@ -221,13 +211,13 @@ fn renode_image(debug: bool, packages: &[&str]) -> Result<(), DynError> {
std::env::set_var("XOUS_SVD_FILE", path.canonicalize().unwrap());
let kernel = build_kernel(debug)?;
let mut init = vec![];
let base_path = build(packages, debug, Some(TARGET), None)?;
let base_path = build(packages, debug, Some(TARGET), None, None)?;
for pkg in packages {
let mut pkg_path = base_path.clone();
pkg_path.push(pkg);
init.push(pkg_path);
}
build(&["loader"], debug, Some(TARGET), Some("loader".into()))?;
build(&["loader"], debug, Some(TARGET), Some("loader".into()), None)?;
create_image(
&kernel,
@ -242,7 +232,7 @@ fn renode_image(debug: bool, packages: &[&str]) -> Result<(), DynError> {
fn run(debug: bool, init: &[&str]) -> Result<(), DynError> {
let stream = if debug { "debug" } else { "release" };
build(&init, debug, None, None)?;
build(&init, debug, None, None, None)?;
// Build and run the kernel
let mut args = vec!["run"];
@ -283,7 +273,7 @@ fn run(debug: bool, init: &[&str]) -> Result<(), DynError> {
}
fn build_kernel(debug: bool) -> Result<PathBuf, DynError> {
let mut path = build(&["kernel"], debug, Some(TARGET), Some("kernel".into()))?;
let mut path = build(&["kernel"], debug, Some(TARGET), Some("kernel".into()), None)?;
path.push("kernel");
Ok(path)
}
@ -293,6 +283,7 @@ fn build(
debug: bool,
target: Option<&str>,
directory: Option<PathBuf>,
extra_args: Option<&[&str]>,
) -> Result<PathBuf, DynError> {
let stream = if debug { "debug" } else { "release" };
let mut args = vec!["build"];
@ -314,6 +305,12 @@ fn build(
args.push("--release");
}
if let Some(extra) = extra_args {
for &a in extra {
args.push(a);
}
}
let mut dir = project_root();
if let Some(subdir) = &directory {
dir.push(subdir);