2
0
mirror of https://github.com/m-labs/artiq.git synced 2024-12-28 20:53:35 +08:00

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 }
crc = { version = "1.7", default-features = false }
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 board_misoc::{ident, cache, sdram, boot, mem as board_mem};
#[cfg(has_ethmac)]
use board_misoc::{clock, config, ethmac};
use board_misoc::{clock, config, ethmac, net_settings};
use board_misoc::uart_console::Console;
fn check_integrity() -> bool {
@ -155,18 +155,6 @@ fn network_boot() {
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() };
net_device.reset_phy_if_any();
@ -174,12 +162,33 @@ fn network_boot() {
let neighbor_cache =
smoltcp::iface::NeighborCache::new(&mut neighbor_map[..]);
let mut ip_addrs = [IpCidr::new(ip_addr, 0)];
let mut interface =
smoltcp::iface::EthernetInterfaceBuilder::new(net_device)
let net_addresses = net_settings::get_adresses();
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)
.ethernet_addr(eth_addr)
.ip_addrs(&mut ip_addrs[..])
.finalize();
.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 sockets =

View File

@ -17,7 +17,6 @@ extern crate proto_artiq;
pub mod pcr;
pub mod i2c;
pub mod spi;
#[cfg(has_kernel_cpu)]
@ -25,12 +24,8 @@ pub mod mailbox;
#[cfg(has_kernel_cpu)]
pub mod rpc_queue;
#[cfg(any(soc_platform = "kasli", has_si5324))]
mod pca9548;
#[cfg(has_si5324)]
pub mod si5324;
#[cfg(soc_platform = "kasli")]
pub mod i2c_eeprom;
#[cfg(has_slave_fpga_cfg)]
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 board_misoc::clock;
use board_misoc::{clock, i2c};
#[cfg(not(si5324_soft_reset))]
use board_misoc::csr;
use i2c;
use pca9548;
type Result<T> = result::Result<T, &'static str>;
@ -181,15 +179,15 @@ fn init() -> Result<()> {
#[cfg(soc_platform = "kasli")]
{
pca9548::select(BUSNO, 0x70, 0)?;
pca9548::select(BUSNO, 0x71, 1 << 3)?;
i2c::pca9548_select(BUSNO, 0x70, 0)?;
i2c::pca9548_select(BUSNO, 0x71, 1 << 3)?;
}
#[cfg(soc_platform = "sayma_amc")]
pca9548::select(BUSNO, 0x70, 1 << 4)?;
i2c::pca9548_select(BUSNO, 0x70, 1 << 4)?;
#[cfg(soc_platform = "sayma_rtm")]
pca9548::select(BUSNO, 0x77, 1 << 5)?;
i2c::pca9548_select(BUSNO, 0x77, 1 << 5)?;
#[cfg(soc_platform = "kc705")]
pca9548::select(BUSNO, 0x74, 1 << 7)?;
i2c::pca9548_select(BUSNO, 0x74, 1 << 7)?;
if ident()? != 0x0182 {
return Err("Si5324 does not have expected product number");

View File

@ -1,6 +1,6 @@
#[cfg(has_i2c)]
mod imp {
use board_misoc::{csr, clock};
use super::super::{csr, clock};
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 {
let busno = busno as u8;
// Set SCL as output, and high level
@ -61,8 +61,6 @@ mod imp {
half_period();
half_period();
if !sda_i(busno) {
warn!("SDA is stuck low on bus #{}, trying to unstuck", busno);
// Try toggling SCL a few times
for _bit in 0..8 {
scl_o(busno, false);
@ -73,9 +71,10 @@ mod imp {
}
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> {
@ -178,17 +177,30 @@ mod imp {
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))]
mod imp {
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 restart(_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 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::*;

View File

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

View File

@ -32,3 +32,8 @@ pub mod uart_console;
pub mod uart_logger;
#[cfg(all(has_ethmac, feature = "smoltcp"))]
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 board_misoc::config;
use config;
#[cfg(soc_platform = "kasli")]
use board_artiq::i2c_eeprom;
use i2c_eeprom;
pub struct NetAddresses {
@ -12,13 +14,22 @@ pub struct NetAddresses {
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 {
let hardware_addr;
match config::read_str("mac", |r| r.map(|s| s.parse())) {
Ok(Ok(addr)) => {
hardware_addr = addr;
info!("using MAC address {}", hardware_addr);
}
Ok(Ok(addr)) => hardware_addr = addr,
_ => {
#[cfg(soc_platform = "kasli")]
{
@ -27,58 +38,34 @@ pub fn get_adresses() -> NetAddresses {
eeprom.read_eui48()
.map(|addr_buf| {
let hardware_addr = EthernetAddress(addr_buf);
info!("using MAC address {} from EEPROM", hardware_addr);
hardware_addr
})
.unwrap_or_else(|e| {
error!("failed to read MAC address from EEPROM: {}", e);
let hardware_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x21]);
warn!("using default MAC address {}; consider changing it", hardware_addr);
hardware_addr
});
}
#[cfg(soc_platform = "sayma_amc")]
{
hardware_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x11]);
warn!("using default MAC address {}; consider changing it", hardware_addr);
}
{ hardware_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x11]); }
#[cfg(soc_platform = "metlino")]
{
hardware_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x19]);
warn!("using default MAC address {}; consider changing it", hardware_addr);
}
{ hardware_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x19]); }
#[cfg(soc_platform = "kc705")]
{
hardware_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x01]);
warn!("using default MAC address {}; consider changing it", hardware_addr);
}
{ hardware_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x01]); }
}
}
let ipv4_addr;
match config::read_str("ip", |r| r.map(|s| s.parse())) {
Ok(Ok(addr)) => {
ipv4_addr = addr;
info!("using IPv4 address {}", ipv4_addr);
}
Ok(Ok(addr)) => ipv4_addr = addr,
_ => {
#[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")]
{
ipv4_addr = IpAddress::v4(192, 168, 1, 60);
}
{ ipv4_addr = IpAddress::v4(192, 168, 1, 60); }
#[cfg(soc_platform = "metlino")]
{
ipv4_addr = IpAddress::v4(192, 168, 1, 65);
}
{ ipv4_addr = IpAddress::v4(192, 168, 1, 65); }
#[cfg(soc_platform = "kc705")]
{
ipv4_addr = IpAddress::v4(192, 168, 1, 50);
}
info!("using default IPv4 address {}", ipv4_addr);
{ ipv4_addr = IpAddress::v4(192, 168, 1, 50); }
}
}
@ -88,17 +75,10 @@ pub fn get_adresses() -> NetAddresses {
((hardware_addr.0[2] as u16) << 8) | 0x00ff,
0xfe00 | (hardware_addr.0[3] 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())) {
Ok(Ok(addr)) => {
info!("using IPv6 configured address {}", addr);
Some(addr)
},
_ => {
info!("no IPv6 configured address");
None
}
Ok(Ok(addr)) => Some(addr),
_ => None
};
NetAddresses {

View File

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

View File

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

View File

@ -8,8 +8,8 @@ extern crate board_misoc;
extern crate board_artiq;
use core::convert::TryFrom;
use board_misoc::{csr, irq, ident, clock, uart_logger};
use board_artiq::{i2c, spi, si5324, drtioaux};
use board_misoc::{csr, irq, ident, clock, uart_logger, i2c};
use board_artiq::{spi, si5324, drtioaux};
use board_artiq::drtio_routing;
#[cfg(has_hmc830_7043)]
use board_artiq::hmc830_7043;
@ -451,7 +451,7 @@ pub extern fn main() -> i32 {
#[cfg(has_slave_fpga_cfg)]
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");
unsafe {
csr::drtio_transceiver::stable_clkin_write(1);