forked from M-Labs/artiq
firmware: implement hotswap through artiq_coreboot tool.
This commit is contained in:
parent
12e22823a2
commit
b0cdef3211
@ -34,6 +34,8 @@ class _H2DMsgType(Enum):
|
|||||||
FLASH_ERASE_REQUEST = 11
|
FLASH_ERASE_REQUEST = 11
|
||||||
FLASH_REMOVE_REQUEST = 12
|
FLASH_REMOVE_REQUEST = 12
|
||||||
|
|
||||||
|
HOTSWAP = 14
|
||||||
|
|
||||||
|
|
||||||
class _D2HMsgType(Enum):
|
class _D2HMsgType(Enum):
|
||||||
LOG_REPLY = 1
|
LOG_REPLY = 1
|
||||||
@ -326,6 +328,10 @@ class CommKernel:
|
|||||||
|
|
||||||
self._read_empty(_D2HMsgType.FLASH_OK_REPLY)
|
self._read_empty(_D2HMsgType.FLASH_OK_REPLY)
|
||||||
|
|
||||||
|
def hotswap(self, image):
|
||||||
|
self._write_header(_H2DMsgType.HOTSWAP)
|
||||||
|
self._write_bytes(image)
|
||||||
|
|
||||||
def load(self, kernel_library):
|
def load(self, kernel_library):
|
||||||
self._write_header(_H2DMsgType.LOAD_KERNEL)
|
self._write_header(_H2DMsgType.LOAD_KERNEL)
|
||||||
self._write_bytes(kernel_library)
|
self._write_bytes(kernel_library)
|
||||||
|
31
artiq/firmware/libboard/hotswap.rs
Normal file
31
artiq/firmware/libboard/hotswap.rs
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
use irq;
|
||||||
|
|
||||||
|
pub unsafe fn run(new_code: &[u8]) -> ! {
|
||||||
|
irq::set_ie(false);
|
||||||
|
#[cfg(target_arch="or1k")]
|
||||||
|
asm!(r#"
|
||||||
|
# This loop overwrites itself, but it's structured in such a way
|
||||||
|
# that before that happens, it loads itself into I$$ fully.
|
||||||
|
l.movhi r4, hi(_ftext)
|
||||||
|
l.ori r4, r4, lo(_ftext)
|
||||||
|
l.or r7, r4, r0
|
||||||
|
0: l.sfnei r5, 0
|
||||||
|
l.bf 1f
|
||||||
|
l.nop
|
||||||
|
l.jr r7
|
||||||
|
l.nop
|
||||||
|
1: l.lwz r6, 0(r3)
|
||||||
|
l.sw 0(r4), r6
|
||||||
|
l.addi r3, r3, 4
|
||||||
|
l.addi r4, r4, 4
|
||||||
|
l.addi r5, r5, -4
|
||||||
|
l.bf 0b
|
||||||
|
l.nop
|
||||||
|
"#
|
||||||
|
:
|
||||||
|
: "{r3}"(new_code.as_ptr() as usize),
|
||||||
|
"{r5}"(new_code.len())
|
||||||
|
:
|
||||||
|
: "volatile");
|
||||||
|
loop {}
|
||||||
|
}
|
@ -35,6 +35,8 @@ mod ad9154_reg;
|
|||||||
#[cfg(has_ad9154)]
|
#[cfg(has_ad9154)]
|
||||||
pub mod ad9154;
|
pub mod ad9154;
|
||||||
|
|
||||||
|
pub mod hotswap;
|
||||||
|
|
||||||
#[cfg(feature = "uart_console")]
|
#[cfg(feature = "uart_console")]
|
||||||
pub use uart_console::Console;
|
pub use uart_console::Console;
|
||||||
|
|
||||||
|
@ -46,6 +46,8 @@ pub enum Request {
|
|||||||
FlashWrite { key: String, value: Vec<u8> },
|
FlashWrite { key: String, value: Vec<u8> },
|
||||||
FlashRemove { key: String },
|
FlashRemove { key: String },
|
||||||
FlashErase,
|
FlashErase,
|
||||||
|
|
||||||
|
Hotswap(Vec<u8>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Request {
|
impl Request {
|
||||||
@ -97,6 +99,7 @@ impl Request {
|
|||||||
12 => Request::FlashRemove {
|
12 => Request::FlashRemove {
|
||||||
key: reader.read_string()?
|
key: reader.read_string()?
|
||||||
},
|
},
|
||||||
|
14 => Request::Hotswap(reader.read_bytes()?),
|
||||||
_ => return Err(io::Error::new(io::ErrorKind::InvalidData, "unknown request type"))
|
_ => return Err(io::Error::new(io::ErrorKind::InvalidData, "unknown request type"))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -268,6 +268,10 @@ fn process_host_message(io: &Io,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// artiq_coreboot
|
||||||
|
host::Request::Hotswap(binary) =>
|
||||||
|
unsafe { board::hotswap::run(&binary) },
|
||||||
|
|
||||||
// artiq_run/artiq_master
|
// artiq_run/artiq_master
|
||||||
host::Request::SwitchClock(clk) => {
|
host::Request::SwitchClock(clk) => {
|
||||||
if session.running() {
|
if session.running() {
|
||||||
|
36
artiq/frontend/artiq_coreboot.py
Normal file
36
artiq/frontend/artiq_coreboot.py
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import struct
|
||||||
|
|
||||||
|
from artiq.tools import verbosity_args, init_logger
|
||||||
|
from artiq.master.databases import DeviceDB
|
||||||
|
from artiq.master.worker_db import DeviceManager
|
||||||
|
|
||||||
|
|
||||||
|
def get_argparser():
|
||||||
|
parser = argparse.ArgumentParser(description="ARTIQ core device hotswap tool")
|
||||||
|
|
||||||
|
verbosity_args(parser)
|
||||||
|
parser.add_argument("--device-db", default="device_db.pyon",
|
||||||
|
help="device database file (default: '%(default)s')")
|
||||||
|
|
||||||
|
parser.add_argument("image", metavar="IMAGE", type=argparse.FileType('rb'),
|
||||||
|
help="runtime image to be executed")
|
||||||
|
|
||||||
|
return parser
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
args = get_argparser().parse_args()
|
||||||
|
init_logger(args)
|
||||||
|
device_mgr = DeviceManager(DeviceDB(args.device_db))
|
||||||
|
try:
|
||||||
|
comm = device_mgr.get("comm")
|
||||||
|
comm.check_system_info()
|
||||||
|
comm.hotswap(args.image.read())
|
||||||
|
finally:
|
||||||
|
device_mgr.close_devices()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
1
setup.py
1
setup.py
@ -24,6 +24,7 @@ console_scripts = [
|
|||||||
"artiq_coreanalyzer=artiq.frontend.artiq_coreanalyzer:main",
|
"artiq_coreanalyzer=artiq.frontend.artiq_coreanalyzer:main",
|
||||||
"artiq_coreconfig=artiq.frontend.artiq_coreconfig:main",
|
"artiq_coreconfig=artiq.frontend.artiq_coreconfig:main",
|
||||||
"artiq_corelog=artiq.frontend.artiq_corelog:main",
|
"artiq_corelog=artiq.frontend.artiq_corelog:main",
|
||||||
|
"artiq_coreboot=artiq.frontend.artiq_coreboot:main",
|
||||||
"artiq_ctlmgr=artiq.frontend.artiq_ctlmgr:main",
|
"artiq_ctlmgr=artiq.frontend.artiq_ctlmgr:main",
|
||||||
"artiq_devtool=artiq.frontend.artiq_devtool:main",
|
"artiq_devtool=artiq.frontend.artiq_devtool:main",
|
||||||
"artiq_influxdb=artiq.frontend.artiq_influxdb:main",
|
"artiq_influxdb=artiq.frontend.artiq_influxdb:main",
|
||||||
|
Loading…
Reference in New Issue
Block a user