firmware: move i2c to libboard_misoc, enable IPv6 in bootloader, share network settings

This commit is contained in:
Sebastien Bourdeauducq 2019-10-21 12:58:52 +08:00
parent 1c5e749036
commit 8f76a3218e
12 changed files with 93 additions and 109 deletions

View File

@ -16,4 +16,4 @@ build_misoc = { path = "../libbuild_misoc" }
byteorder = { version = "1.0", default-features = false } byteorder = { version = "1.0", default-features = false }
crc = { version = "1.7", default-features = false } crc = { version = "1.7", default-features = false }
board_misoc = { path = "../libboard_misoc", features = ["uart_console", "smoltcp"] } board_misoc = { path = "../libboard_misoc", features = ["uart_console", "smoltcp"] }
smoltcp = { version = "0.5.0", default-features = false, features = ["proto-ipv4", "socket-tcp"] } smoltcp = { version = "0.5.0", default-features = false, features = ["proto-ipv4", "proto-ipv6", "socket-tcp"] }

View File

@ -12,7 +12,7 @@ use crc::crc32;
use byteorder::{ByteOrder, BigEndian}; use byteorder::{ByteOrder, BigEndian};
use board_misoc::{ident, cache, sdram, boot, mem as board_mem}; use board_misoc::{ident, cache, sdram, boot, mem as board_mem};
#[cfg(has_ethmac)] #[cfg(has_ethmac)]
use board_misoc::{clock, config, ethmac}; use board_misoc::{clock, config, ethmac, net_settings};
use board_misoc::uart_console::Console; use board_misoc::uart_console::Console;
fn check_integrity() -> bool { fn check_integrity() -> bool {
@ -155,18 +155,6 @@ fn network_boot() {
println!("Initializing network..."); println!("Initializing network...");
let eth_addr = match config::read_str("mac", |r| r.map(|s| s.parse())) {
Ok(Ok(addr)) => addr,
_ => EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x01])
};
let ip_addr = match config::read_str("ip", |r| r.map(|s| s.parse())) {
Ok(Ok(addr)) => addr,
_ => IpAddress::v4(192, 168, 1, 50)
};
println!("Using MAC address {} and IP address {}", eth_addr, ip_addr);
let mut net_device = unsafe { ethmac::EthernetDevice::new() }; let mut net_device = unsafe { ethmac::EthernetDevice::new() };
net_device.reset_phy_if_any(); net_device.reset_phy_if_any();
@ -174,12 +162,33 @@ fn network_boot() {
let neighbor_cache = let neighbor_cache =
smoltcp::iface::NeighborCache::new(&mut neighbor_map[..]); smoltcp::iface::NeighborCache::new(&mut neighbor_map[..]);
let mut ip_addrs = [IpCidr::new(ip_addr, 0)]; let mut ip_addrs = [IpCidr::new(ip_addr, 0)];
let mut interface = let net_addresses = net_settings::get_adresses();
smoltcp::iface::EthernetInterfaceBuilder::new(net_device) println!("network addresses: {}", net_addresses);
let mut interface = match net_addresses.ipv6_addr {
Some(addr) => {
let ip_addrs = [
IpCidr::new(net_addresses.ipv4_addr, 0),
IpCidr::new(net_addresses.ipv6_ll_addr, 0),
IpCidr::new(addr, 0)
];
smoltcp::iface::EthernetInterfaceBuilder::new(net_device)
.ethernet_addr(net_addresses.hardware_addr)
.ip_addrs(ip_addrs)
.neighbor_cache(neighbor_cache) .neighbor_cache(neighbor_cache)
.ethernet_addr(eth_addr) .finalize()
.ip_addrs(&mut ip_addrs[..]) }
.finalize(); None => {
let ip_addrs = [
IpCidr::new(net_addresses.ipv4_addr, 0),
IpCidr::new(net_addresses.ipv6_ll_addr, 0)
];
smoltcp::iface::EthernetInterfaceBuilder::new(net_device)
.ethernet_addr(net_addresses.hardware_addr)
.ip_addrs(ip_addrs)
.neighbor_cache(neighbor_cache)
.finalize()
}
};
let mut socket_set_storage = []; let mut socket_set_storage = [];
let mut sockets = let mut sockets =

View File

@ -17,7 +17,6 @@ extern crate proto_artiq;
pub mod pcr; pub mod pcr;
pub mod i2c;
pub mod spi; pub mod spi;
#[cfg(has_kernel_cpu)] #[cfg(has_kernel_cpu)]
@ -25,12 +24,8 @@ pub mod mailbox;
#[cfg(has_kernel_cpu)] #[cfg(has_kernel_cpu)]
pub mod rpc_queue; pub mod rpc_queue;
#[cfg(any(soc_platform = "kasli", has_si5324))]
mod pca9548;
#[cfg(has_si5324)] #[cfg(has_si5324)]
pub mod si5324; pub mod si5324;
#[cfg(soc_platform = "kasli")]
pub mod i2c_eeprom;
#[cfg(has_slave_fpga_cfg)] #[cfg(has_slave_fpga_cfg)]
pub mod slave_fpga; pub mod slave_fpga;

View File

@ -1,13 +0,0 @@
use i2c;
pub fn select(busno: u8, address: u8, channels: u8) -> Result<(), &'static str> {
i2c::start(busno).unwrap();
if !i2c::write(busno, address << 1)? {
return Err("PCA9548 failed to ack write address")
}
if !i2c::write(busno, channels)? {
return Err("PCA9548 failed to ack control word")
}
i2c::stop(busno).unwrap();
Ok(())
}

View File

@ -1,9 +1,7 @@
use core::result; use core::result;
use board_misoc::clock; use board_misoc::{clock, i2c};
#[cfg(not(si5324_soft_reset))] #[cfg(not(si5324_soft_reset))]
use board_misoc::csr; use board_misoc::csr;
use i2c;
use pca9548;
type Result<T> = result::Result<T, &'static str>; type Result<T> = result::Result<T, &'static str>;
@ -181,15 +179,15 @@ fn init() -> Result<()> {
#[cfg(soc_platform = "kasli")] #[cfg(soc_platform = "kasli")]
{ {
pca9548::select(BUSNO, 0x70, 0)?; i2c::pca9548_select(BUSNO, 0x70, 0)?;
pca9548::select(BUSNO, 0x71, 1 << 3)?; i2c::pca9548_select(BUSNO, 0x71, 1 << 3)?;
} }
#[cfg(soc_platform = "sayma_amc")] #[cfg(soc_platform = "sayma_amc")]
pca9548::select(BUSNO, 0x70, 1 << 4)?; i2c::pca9548_select(BUSNO, 0x70, 1 << 4)?;
#[cfg(soc_platform = "sayma_rtm")] #[cfg(soc_platform = "sayma_rtm")]
pca9548::select(BUSNO, 0x77, 1 << 5)?; i2c::pca9548_select(BUSNO, 0x77, 1 << 5)?;
#[cfg(soc_platform = "kc705")] #[cfg(soc_platform = "kc705")]
pca9548::select(BUSNO, 0x74, 1 << 7)?; i2c::pca9548_select(BUSNO, 0x74, 1 << 7)?;
if ident()? != 0x0182 { if ident()? != 0x0182 {
return Err("Si5324 does not have expected product number"); return Err("Si5324 does not have expected product number");

View File

@ -1,6 +1,6 @@
#[cfg(has_i2c)] #[cfg(has_i2c)]
mod imp { mod imp {
use board_misoc::{csr, clock}; use super::super::{csr, clock};
const INVALID_BUS: &'static str = "Invalid I2C bus"; const INVALID_BUS: &'static str = "Invalid I2C bus";
@ -46,7 +46,7 @@ mod imp {
} }
} }
pub fn init() { pub fn init() -> Result<(), &'static str> {
for busno in 0..csr::CONFIG_I2C_BUS_COUNT { for busno in 0..csr::CONFIG_I2C_BUS_COUNT {
let busno = busno as u8; let busno = busno as u8;
// Set SCL as output, and high level // Set SCL as output, and high level
@ -61,8 +61,6 @@ mod imp {
half_period(); half_period();
half_period(); half_period();
if !sda_i(busno) { if !sda_i(busno) {
warn!("SDA is stuck low on bus #{}, trying to unstuck", busno);
// Try toggling SCL a few times // Try toggling SCL a few times
for _bit in 0..8 { for _bit in 0..8 {
scl_o(busno, false); scl_o(busno, false);
@ -73,9 +71,10 @@ mod imp {
} }
if !sda_i(busno) { if !sda_i(busno) {
error!("SDA is stuck low on bus #{} and doesn't get unstuck", busno); return Err("SDA is stuck low and doesn't get unstuck");
} }
} }
Ok(())
} }
pub fn start(busno: u8) -> Result<(), &'static str> { pub fn start(busno: u8) -> Result<(), &'static str> {
@ -178,17 +177,30 @@ mod imp {
Ok(data) Ok(data)
} }
pub fn pca9548_select(busno: u8, address: u8, channels: u8) -> Result<(), &'static str> {
start(busno)?;
if !write(busno, address << 1)? {
return Err("PCA9548 failed to ack write address")
}
if !write(busno, channels)? {
return Err("PCA9548 failed to ack control word")
}
stop(busno)?;
Ok(())
}
} }
#[cfg(not(has_i2c))] #[cfg(not(has_i2c))]
mod imp { mod imp {
const NO_I2C: &'static str = "No I2C support on this platform"; const NO_I2C: &'static str = "No I2C support on this platform";
pub fn init() {} pub fn init() { Err(NO_I2C) }
pub fn start(_busno: u8) -> Result<(), &'static str> { Err(NO_I2C) } pub fn start(_busno: u8) -> Result<(), &'static str> { Err(NO_I2C) }
pub fn restart(_busno: u8) -> Result<(), &'static str> { Err(NO_I2C) } pub fn restart(_busno: u8) -> Result<(), &'static str> { Err(NO_I2C) }
pub fn stop(_busno: u8) -> Result<(), &'static str> { Err(NO_I2C) } pub fn stop(_busno: u8) -> Result<(), &'static str> { Err(NO_I2C) }
pub fn write(_busno: u8, _data: u8) -> Result<bool, &'static str> { Err(NO_I2C) } pub fn write(_busno: u8, _data: u8) -> Result<bool, &'static str> { Err(NO_I2C) }
pub fn read(_busno: u8, _ack: bool) -> Result<u8, &'static str> { Err(NO_I2C) } pub fn read(_busno: u8, _ack: bool) -> Result<u8, &'static str> { Err(NO_I2C) }
pub fn pca9548_select(busno: u8, address: u8, channels: u8) -> Result<(), &'static str> { Err(NO_I2C) }
} }
pub use self::imp::*; pub use self::imp::*;

View File

@ -1,5 +1,4 @@
use i2c; use i2c;
use pca9548;
#[cfg(soc_platform = "kasli")] #[cfg(soc_platform = "kasli")]
const I2C_SWITCH0: u8 = 0x70; const I2C_SWITCH0: u8 = 0x70;
@ -25,8 +24,8 @@ impl EEPROM {
fn select(&self) -> Result<(), &'static str> { fn select(&self) -> Result<(), &'static str> {
let mask: u16 = 1 << self.port; let mask: u16 = 1 << self.port;
pca9548::select(self.busno, I2C_SWITCH0, mask as u8)?; i2c::pca9548_select(self.busno, I2C_SWITCH0, mask as u8)?;
pca9548::select(self.busno, I2C_SWITCH1, (mask >> 8) as u8)?; i2c::pca9548_select(self.busno, I2C_SWITCH1, (mask >> 8) as u8)?;
Ok(()) Ok(())
} }

View File

@ -32,3 +32,8 @@ pub mod uart_console;
pub mod uart_logger; pub mod uart_logger;
#[cfg(all(has_ethmac, feature = "smoltcp"))] #[cfg(all(has_ethmac, feature = "smoltcp"))]
pub mod ethmac; pub mod ethmac;
pub mod i2c;
#[cfg(soc_platform = "kasli")]
pub mod i2c_eeprom;
#[cfg(all(has_ethmac, feature = "smoltcp"))]
pub mod net_settings;

View File

@ -1,8 +1,10 @@
use core::fmt;
use smoltcp::wire::{EthernetAddress, IpAddress}; use smoltcp::wire::{EthernetAddress, IpAddress};
use board_misoc::config; use config;
#[cfg(soc_platform = "kasli")] #[cfg(soc_platform = "kasli")]
use board_artiq::i2c_eeprom; use i2c_eeprom;
pub struct NetAddresses { pub struct NetAddresses {
@ -12,13 +14,22 @@ pub struct NetAddresses {
pub ipv6_addr: Option<IpAddress> pub ipv6_addr: Option<IpAddress>
} }
impl fmt::Display for NetAddresses {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "MAC:{} IPv4:{} IPv6-LL:{} IPv6:",
self.hardware_addr, self.ipv4_addr, self.ipv6_ll_addr)?;
match self.ipv6_addr {
Some(addr) => write!(f, "{}", addr)?,
None => write!(f, "no configured address")?
}
Ok(())
}
}
pub fn get_adresses() -> NetAddresses { pub fn get_adresses() -> NetAddresses {
let hardware_addr; let hardware_addr;
match config::read_str("mac", |r| r.map(|s| s.parse())) { match config::read_str("mac", |r| r.map(|s| s.parse())) {
Ok(Ok(addr)) => { Ok(Ok(addr)) => hardware_addr = addr,
hardware_addr = addr;
info!("using MAC address {}", hardware_addr);
}
_ => { _ => {
#[cfg(soc_platform = "kasli")] #[cfg(soc_platform = "kasli")]
{ {
@ -27,58 +38,34 @@ pub fn get_adresses() -> NetAddresses {
eeprom.read_eui48() eeprom.read_eui48()
.map(|addr_buf| { .map(|addr_buf| {
let hardware_addr = EthernetAddress(addr_buf); let hardware_addr = EthernetAddress(addr_buf);
info!("using MAC address {} from EEPROM", hardware_addr);
hardware_addr hardware_addr
}) })
.unwrap_or_else(|e| { .unwrap_or_else(|e| {
error!("failed to read MAC address from EEPROM: {}", e);
let hardware_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x21]); let hardware_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x21]);
warn!("using default MAC address {}; consider changing it", hardware_addr);
hardware_addr hardware_addr
}); });
} }
#[cfg(soc_platform = "sayma_amc")] #[cfg(soc_platform = "sayma_amc")]
{ { hardware_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x11]); }
hardware_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x11]);
warn!("using default MAC address {}; consider changing it", hardware_addr);
}
#[cfg(soc_platform = "metlino")] #[cfg(soc_platform = "metlino")]
{ { hardware_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x19]); }
hardware_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x19]);
warn!("using default MAC address {}; consider changing it", hardware_addr);
}
#[cfg(soc_platform = "kc705")] #[cfg(soc_platform = "kc705")]
{ { hardware_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x01]); }
hardware_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x01]);
warn!("using default MAC address {}; consider changing it", hardware_addr);
}
} }
} }
let ipv4_addr; let ipv4_addr;
match config::read_str("ip", |r| r.map(|s| s.parse())) { match config::read_str("ip", |r| r.map(|s| s.parse())) {
Ok(Ok(addr)) => { Ok(Ok(addr)) => ipv4_addr = addr,
ipv4_addr = addr;
info!("using IPv4 address {}", ipv4_addr);
}
_ => { _ => {
#[cfg(soc_platform = "kasli")] #[cfg(soc_platform = "kasli")]
{ { ipv4_addr = IpAddress::v4(192, 168, 1, 70); }
ipv4_addr = IpAddress::v4(192, 168, 1, 70);
}
#[cfg(soc_platform = "sayma_amc")] #[cfg(soc_platform = "sayma_amc")]
{ { ipv4_addr = IpAddress::v4(192, 168, 1, 60); }
ipv4_addr = IpAddress::v4(192, 168, 1, 60);
}
#[cfg(soc_platform = "metlino")] #[cfg(soc_platform = "metlino")]
{ { ipv4_addr = IpAddress::v4(192, 168, 1, 65); }
ipv4_addr = IpAddress::v4(192, 168, 1, 65);
}
#[cfg(soc_platform = "kc705")] #[cfg(soc_platform = "kc705")]
{ { ipv4_addr = IpAddress::v4(192, 168, 1, 50); }
ipv4_addr = IpAddress::v4(192, 168, 1, 50);
}
info!("using default IPv4 address {}", ipv4_addr);
} }
} }
@ -88,17 +75,10 @@ pub fn get_adresses() -> NetAddresses {
((hardware_addr.0[2] as u16) << 8) | 0x00ff, ((hardware_addr.0[2] as u16) << 8) | 0x00ff,
0xfe00 | (hardware_addr.0[3] as u16), 0xfe00 | (hardware_addr.0[3] as u16),
((hardware_addr.0[4] as u16) << 8) | (hardware_addr.0[5] as u16)); ((hardware_addr.0[4] as u16) << 8) | (hardware_addr.0[5] as u16));
info!("using IPv6 link-local address {}", ipv6_ll_addr);
let ipv6_addr = match config::read_str("ip6", |r| r.map(|s| s.parse())) { let ipv6_addr = match config::read_str("ip6", |r| r.map(|s| s.parse())) {
Ok(Ok(addr)) => { Ok(Ok(addr)) => Some(addr),
info!("using IPv6 configured address {}", addr); _ => None
Some(addr)
},
_ => {
info!("no IPv6 configured address");
None
}
}; };
NetAddresses { NetAddresses {

View File

@ -4,8 +4,8 @@ use sched::{Io, Mutex, Error as SchedError};
use session::{kern_acknowledge, kern_send, Error}; use session::{kern_acknowledge, kern_send, Error};
use rtio_mgt; use rtio_mgt;
use urc::Urc; use urc::Urc;
use board_misoc::i2c as local_i2c;
use board_artiq::drtio_routing; use board_artiq::drtio_routing;
use board_artiq::i2c as local_i2c;
use board_artiq::spi as local_spi; use board_artiq::spi as local_spi;
#[cfg(has_drtio)] #[cfg(has_drtio)]

View File

@ -30,7 +30,7 @@ use core::cell::RefCell;
use core::convert::TryFrom; use core::convert::TryFrom;
use smoltcp::wire::IpCidr; use smoltcp::wire::IpCidr;
use board_misoc::{csr, irq, ident, clock, boot, config}; use board_misoc::{csr, irq, ident, clock, boot, config, net_settings};
#[cfg(has_ethmac)] #[cfg(has_ethmac)]
use board_misoc::ethmac; use board_misoc::ethmac;
#[cfg(has_drtio)] #[cfg(has_drtio)]
@ -41,8 +41,6 @@ use proto_artiq::{mgmt_proto, moninj_proto, rpc_proto, session_proto, kernel_pro
#[cfg(has_rtio_analyzer)] #[cfg(has_rtio_analyzer)]
use proto_artiq::analyzer_proto; use proto_artiq::analyzer_proto;
mod net_settings;
mod rtio_clocking; mod rtio_clocking;
mod rtio_mgt; mod rtio_mgt;
@ -122,7 +120,7 @@ fn startup() {
setup_log_levels(); setup_log_levels();
#[cfg(has_i2c)] #[cfg(has_i2c)]
board_artiq::i2c::init(); board_misoc::i2c::init().expect("I2C initialization failed");
sayma_hw_init(); sayma_hw_init();
rtio_clocking::init(); rtio_clocking::init();
@ -152,6 +150,7 @@ fn startup() {
let neighbor_cache = let neighbor_cache =
smoltcp::iface::NeighborCache::new(alloc::btree_map::BTreeMap::new()); smoltcp::iface::NeighborCache::new(alloc::btree_map::BTreeMap::new());
let net_addresses = net_settings::get_adresses(); let net_addresses = net_settings::get_adresses();
info!("network addresses: {}", net_addresses);
let mut interface = match net_addresses.ipv6_addr { let mut interface = match net_addresses.ipv6_addr {
Some(addr) => { Some(addr) => {
let ip_addrs = [ let ip_addrs = [

View File

@ -8,8 +8,8 @@ extern crate board_misoc;
extern crate board_artiq; extern crate board_artiq;
use core::convert::TryFrom; use core::convert::TryFrom;
use board_misoc::{csr, irq, ident, clock, uart_logger}; use board_misoc::{csr, irq, ident, clock, uart_logger, i2c};
use board_artiq::{i2c, spi, si5324, drtioaux}; use board_artiq::{spi, si5324, drtioaux};
use board_artiq::drtio_routing; use board_artiq::drtio_routing;
#[cfg(has_hmc830_7043)] #[cfg(has_hmc830_7043)]
use board_artiq::hmc830_7043; use board_artiq::hmc830_7043;
@ -451,7 +451,7 @@ pub extern fn main() -> i32 {
#[cfg(has_slave_fpga_cfg)] #[cfg(has_slave_fpga_cfg)]
board_artiq::slave_fpga::load().expect("cannot load RTM FPGA gateware"); board_artiq::slave_fpga::load().expect("cannot load RTM FPGA gateware");
i2c::init(); i2c::init().expect("I2C initialization failed");
si5324::setup(&SI5324_SETTINGS, si5324::Input::Ckin1).expect("cannot initialize Si5324"); si5324::setup(&SI5324_SETTINGS, si5324::Input::Ckin1).expect("cannot initialize Si5324");
unsafe { unsafe {
csr::drtio_transceiver::stable_clkin_write(1); csr::drtio_transceiver::stable_clkin_write(1);