Compare commits

...

8 Commits

9 changed files with 173 additions and 203 deletions

View File

@ -1,32 +1,16 @@
#![no_std] #![no_std]
#![no_main] #![no_main]
use core::mem::transmute;
use libcortex_a9::mutex::Mutex;
use libboard_zynq::{print, println, self as zynq, clocks::Clocks, clocks::source::{ClockSource, ArmPll, IoPll}}; use libboard_zynq::{print, println, self as zynq, clocks::Clocks, clocks::source::{ClockSource, ArmPll, IoPll}};
use libsupport_zynq::{ use libsupport_zynq as _;
ram, alloc::{vec, vec::Vec},
boot,
smoltcp::wire::{EthernetAddress, IpAddress, IpCidr},
smoltcp::iface::{NeighborCache, EthernetInterfaceBuilder},
smoltcp::time::Instant,
smoltcp::socket::SocketSet,
smoltcp::socket::{TcpSocket, TcpSocketBuffer},
};
const HWADDR: [u8; 6] = [0, 0x23, 0xde, 0xea, 0xbe, 0xef];
static mut STACK_CORE1: [u32; 512] = [0; 512];
#[no_mangle] #[no_mangle]
pub fn main_core0() { pub fn main_core0() {
// zynq::clocks::CpuClocks::enable_io(1_250_000_000);
println!("\nzc706 main"); println!("\nzc706 main");
{ let clocks = zynq::clocks::Clocks::get();
use libregister::RegisterR; println!("CPU Clocks: {}/{}/{}/{}", clocks.cpu_6x4x(), clocks.cpu_3x2x(), clocks.cpu_2x(), clocks.cpu_1x());
println!("Boot mode: {:?}", zynq::slcr::RegisterBlock::new().boot_mode.read().boot_mode_pins());
}
// Clock setup
#[cfg(feature = "target_zc706")] #[cfg(feature = "target_zc706")]
const CPU_FREQ: u32 = 800_000_000; const CPU_FREQ: u32 = 800_000_000;
#[cfg(feature = "target_cora_z7_10")] #[cfg(feature = "target_cora_z7_10")]
@ -41,6 +25,7 @@ pub fn main_core0() {
let clocks = zynq::clocks::Clocks::get(); let clocks = zynq::clocks::Clocks::get();
println!("CPU Clocks: {}/{}/{}/{}", clocks.cpu_6x4x(), clocks.cpu_3x2x(), clocks.cpu_2x(), clocks.cpu_1x()); println!("CPU Clocks: {}/{}/{}/{}", clocks.cpu_6x4x(), clocks.cpu_3x2x(), clocks.cpu_2x(), clocks.cpu_1x());
// Flash: Linear Addressing Mode
let mut flash = zynq::flash::Flash::new(200_000_000).linear_addressing_mode(); let mut flash = zynq::flash::Flash::new(200_000_000).linear_addressing_mode();
let flash_ram: &[u8] = unsafe { core::slice::from_raw_parts(flash.ptr(), flash.size()) }; let flash_ram: &[u8] = unsafe { core::slice::from_raw_parts(flash.ptr(), flash.size()) };
for i in 0..=1 { for i in 0..=1 {
@ -52,17 +37,20 @@ pub fn main_core0() {
} }
let mut flash = flash.stop(); let mut flash = flash.stop();
let mut ddr = zynq::ddr::DdrRam::new(); // Flash: Manual I/O Mode
#[cfg(not(feature = "target_zc706"))]
ddr.memtest();
ram::init_alloc(&mut ddr);
for i in 0..=1 { for i in 0..=1 {
let mut flash_io = flash.manual_mode(i); let mut flash_io = flash.manual_mode(i);
// println!("rdcr={:02X}", flash_io.rdcr());
print!("Flash {} ID:", i); print!("Flash {} ID:", i);
for b in flash_io.rdid() { for (i, b) in flash_io.rdid().enumerate() {
print!(" {:02X}", b); print!(" {:02X}", b);
if i % 0x10 == 0xf {
println!("");
} else if i % 8 == 7 {
print!(" ");
} else if i % 4 == 3 {
print!(" ");
}
} }
println!(""); println!("");
print!("Flash {} I/O:", i); print!("Flash {} I/O:", i);
@ -85,138 +73,32 @@ pub fn main_core0() {
flash_io.dump("ASP Read", 0x2B); flash_io.dump("ASP Read", 0x2B);
flash_io.dump("Password Read", 0xE7); flash_io.dump("Password Read", 0xE7);
for o in 0..8 {
const SIZE: u32 = 0x100;
flash_io.write_enabled(|flash_io| { flash_io.write_enabled(|flash_io| {
flash_io.erase(0); println!("Erase page {}", o);
flash_io.erase(o * SIZE);
}); });
flash_io.write_enabled(|flash_io| { flash_io.write_enabled(|flash_io| {
flash_io.program(0, [0x23054223; (0x100 >> 2)].iter().cloned()); println!("Program page {}", o);
flash_io.program(o * SIZE, [0x55FD02AA; (SIZE >> 2) as usize].iter().cloned());
}); });
}
print!("Flash {} I/O:", i);
for o in 0..8 {
const CHUNK: u32 = 32;
for b in flash_io.read(CHUNK * o, CHUNK as usize) {
print!(" {:02X}", b);
}
}
println!("");
flash = flash_io.stop(); flash = flash_io.stop();
} }
let core1_stack = unsafe { &mut STACK_CORE1[..] };
println!("{} bytes stack for core1", core1_stack.len());
let core1 = boot::Core1::start(core1_stack);
for _ in 0..0x1000000 {
let mut l = SHARED.lock();
*l += 1;
}
while !*DONE.lock() {
let x = { *SHARED.lock() };
println!("shared: {:08X}", x);
}
let x = { *SHARED.lock() };
println!("done shared: {:08X}", x);
core1.reset();
libcortex_a9::asm::dsb();
print!("Core1 stack [{:08X}..{:08X}]:", &core1.stack[0] as *const _ as u32, &core1.stack[core1.stack.len() - 1] as *const _ as u32);
for w in core1.stack {
print!(" {:08X}", w);
}
println!(".");
let eth = zynq::eth::Eth::default(HWADDR.clone());
println!("Eth on");
const RX_LEN: usize = 8;
let mut rx_descs = (0..RX_LEN)
.map(|_| zynq::eth::rx::DescEntry::zeroed())
.collect::<Vec<_>>();
let mut rx_buffers = vec![[0u8; zynq::eth::MTU]; RX_LEN];
// Number of transmission buffers (minimum is two because with
// one, duplicate packet transmission occurs)
const TX_LEN: usize = 8;
let mut tx_descs = (0..TX_LEN)
.map(|_| zynq::eth::tx::DescEntry::zeroed())
.collect::<Vec<_>>();
let mut tx_buffers = vec![[0u8; zynq::eth::MTU]; TX_LEN];
let eth = eth.start_rx(&mut rx_descs, &mut rx_buffers);
//let mut eth = eth.start_tx(&mut tx_descs, &mut tx_buffers);
let mut eth = eth.start_tx(
// HACK
unsafe { transmute(tx_descs.as_mut_slice()) },
unsafe { transmute(tx_buffers.as_mut_slice()) },
);
let ethernet_addr = EthernetAddress(HWADDR);
// IP stack
let local_addr = IpAddress::v4(192, 168, 1, 51);
let mut ip_addrs = [IpCidr::new(local_addr, 24)];
let mut neighbor_storage = vec![None; 256];
let neighbor_cache = NeighborCache::new(&mut neighbor_storage[..]);
let mut iface = EthernetInterfaceBuilder::new(&mut eth)
.ethernet_addr(ethernet_addr)
.ip_addrs(&mut ip_addrs[..])
.neighbor_cache(neighbor_cache)
.finalize();
let mut sockets_storage = [
None, None, None, None,
None, None, None, None
];
let mut sockets = SocketSet::new(&mut sockets_storage[..]);
// taken from example code for smoltcp
let mut tcp_server_rx_data = vec![0; 512 * 1024];
let mut tcp_server_tx_data = vec![0; 512 * 1024];
let tcp_rx_buffer = TcpSocketBuffer::new(&mut tcp_server_rx_data[..]);
let tcp_tx_buffer = TcpSocketBuffer::new(&mut tcp_server_tx_data[..]);
let tcp_socket = TcpSocket::new(tcp_rx_buffer, tcp_tx_buffer);
let tcp_handle = sockets.add(tcp_socket);
/// `chargen`
const TCP_PORT: u16 = 19;
let mut time = 0u32;
loop {
time += 1;
let timestamp = Instant::from_millis(time);
match iface.poll(&mut sockets, timestamp) {
Ok(_) => {},
Err(e) => {
println!("poll error: {}", e);
}
}
// (mostly) taken from smoltcp example: TCP echo server
let mut socket = sockets.get::<TcpSocket>(tcp_handle);
if !socket.is_open() {
socket.listen(TCP_PORT).unwrap()
}
if socket.may_recv() && socket.can_send() {
socket.recv(|buf| {
let len = buf.len().min(4096);
let buffer = buf[..len].iter().cloned().collect::<Vec<_>>();
(len, buffer)
})
.and_then(|buffer| socket.send_slice(&buffer[..]))
.map(|_| {})
.unwrap_or_else(|e| println!("tcp: {:?}", e));
}
}
// #[allow(unreachable_code)]
// drop(tx_descs);
// #[allow(unreachable_code)]
// drop(tx_buffers);
} }
static SHARED: Mutex<u32> = Mutex::new(0);
static DONE: Mutex<bool> = Mutex::new(false);
#[no_mangle] #[no_mangle]
pub fn main_core1() { pub fn main_core1() {
println!("Hello from core1!");
for _ in 0..0x1000000 {
let mut l = SHARED.lock();
*l += 1;
}
println!("core1 done!");
*DONE.lock() = true;
loop {} loop {}
} }

View File

@ -172,9 +172,14 @@ impl DdrRam {
#[cfg(feature = "target_cora_z7_10")] #[cfg(feature = "target_cora_z7_10")]
let width = regs::DataBusWidth::Width16bit; let width = regs::DataBusWidth::Width16bit;
self.regs.ddrc_ctrl.modify(|_, w| w self.regs.ddrc_ctrl.modify(|_, w| w
.soft_rstb(true) .soft_rstb(false)
.powerdown_en(false) .powerdown_en(false)
.data_bus_width(width) .data_bus_width(width)
.burst8_refresh(1)
.rdwr_idle_gap(1)
.dis_rd_bypass(false)
.dis_act_bypass(false)
.dis_auto_refresh(false)
); );
while self.status() == regs::ControllerStatus::Init {} while self.status() == regs::ControllerStatus::Init {}

View File

@ -1,6 +1,6 @@
use volatile_register::{RO, RW}; use volatile_register::{RO, RW};
use libregister::{register, register_bit, register_bits_typed}; use libregister::{register, register_bit, register_bits, register_bits_typed};
#[allow(unused)] #[allow(unused)]
#[repr(u8)] #[repr(u8)]
@ -169,7 +169,11 @@ register_bit!(ddrc_ctrl,
soft_rstb, 0); soft_rstb, 0);
register_bit!(ddrc_ctrl, powerdown_en, 1); register_bit!(ddrc_ctrl, powerdown_en, 1);
register_bits_typed!(ddrc_ctrl, data_bus_width, u8, DataBusWidth, 2, 3); register_bits_typed!(ddrc_ctrl, data_bus_width, u8, DataBusWidth, 2, 3);
// (ddrc_ctrl) ... register_bits!(ddrc_ctrl, burst8_refresh, u8, 4, 6);
register_bits!(ddrc_ctrl, rdwr_idle_gap, u8, 7, 13);
register_bit!(ddrc_ctrl, dis_rd_bypass, 14);
register_bit!(ddrc_ctrl, dis_act_bypass, 15);
register_bit!(ddrc_ctrl, dis_auto_refresh, 16);
// Controller operation mode status // Controller operation mode status
register!(mode_sts_reg, register!(mode_sts_reg,

View File

@ -10,16 +10,21 @@ mod regs;
mod bytes; mod bytes;
pub use bytes::{BytesTransferExt, BytesTransfer}; pub use bytes::{BytesTransferExt, BytesTransfer};
mod spi_flash_register; mod spi_flash_register;
use spi_flash_register::*; pub use spi_flash_register::*;
mod transfer; mod transfer;
use transfer::Transfer; use transfer::Transfer;
const FLASH_BAUD_RATE: u32 = 50_000_000; #[cfg(feature = "target_zc706")]
const FLASH_BAUD_RATE: u32 = 10_000_000;
#[cfg(feature = "target_cora_z7_10")]
const FLASH_BAUD_RATE: u32 = 10_000_000;
/// 16 MB /// 16 MB
pub const SINGLE_CAPACITY: u32 = 0x1000000; pub const SINGLE_CAPACITY: u32 = 0x1000000;
pub const SECTOR_SIZE: u32 = 0x10000; pub const SECTOR_SIZE: u32 = 0x10000;
pub const PAGE_SIZE: u32 = 0x100; pub const PAGE_SIZE: u32 = 0x100;
/// Write Register
const INST_WRR: u8 = 0x01;
/// Instruction: Read Identification /// Instruction: Read Identification
const INST_RDID: u8 = 0x9F; const INST_RDID: u8 = 0x9F;
const INST_READ: u8 = 0x03; const INST_READ: u8 = 0x03;
@ -31,8 +36,10 @@ const INST_WREN: u8 = 0x06;
const INST_PP: u8 = 0x02; const INST_PP: u8 = 0x02;
/// Instruction: Erase 4K Block /// Instruction: Erase 4K Block
const INST_BE_4K: u8 = 0x20; const INST_BE_4K: u8 = 0x20;
/// Instruction: Clear Status Register
const INST_CLSR: u8 = 0x30;
#[derive(Clone)] #[derive(Clone, Debug)]
pub enum SpiWord { pub enum SpiWord {
W8(u8), W8(u8),
W16(u16), W16(u16),
@ -105,9 +112,11 @@ impl<MODE> Flash<MODE> {
); );
} }
fn wait_tx_fifo_flush(&mut self) { fn wait_tx_fifo_flush(&mut self) -> u32 {
self.regs.config.modify(|_, w| w.man_start_com(true)); self.regs.config.modify(|_, w| w.man_start_com(true));
while !self.regs.intr_status.read().tx_fifo_not_full() {} let mut waited = 0;
while !self.regs.intr_status.read().tx_fifo_not_full() { waited += 1; }
waited
} }
} }
@ -220,6 +229,7 @@ impl Flash<()> {
// Option: Add Feedback Output Clock // Option: Add Feedback Output Clock
// 7. Configure MIO pin 8 for feedback clock. // 7. Configure MIO pin 8 for feedback clock.
// #[cfg(not(feature = "target_zc706"))]
slcr.mio_pin_08.write( slcr.mio_pin_08.write(
slcr::MioPin08::zeroed() slcr::MioPin08::zeroed()
.l0_sel(true) .l0_sel(true)
@ -258,9 +268,12 @@ impl Flash<()> {
while baud_rate_div < 7 && 2u32.pow(1 + baud_rate_div) < divider { while baud_rate_div < 7 && 2u32.pow(1 + baud_rate_div) < divider {
baud_rate_div += 1; baud_rate_div += 1;
} }
println!("delay: {:08X}", self.regs.delay.read());
self.regs.config.write(regs::Config::zeroed() self.regs.config.write(regs::Config::zeroed()
.baud_rate_div(baud_rate_div as u8) .baud_rate_div(baud_rate_div as u8)
.clk_ph(true)
.clk_pol(true)
.mode_sel(true) .mode_sel(true)
.leg_flsh(true) .leg_flsh(true)
.holdb_dr(true) .holdb_dr(true)
@ -292,6 +305,7 @@ impl Flash<()> {
.mode_en(true) .mode_en(true)
// 2 devices // 2 devices
.two_mem(true) .two_mem(true)
.sep_bus(true)
.u_page(false) .u_page(false)
// Linear Addressing Mode // Linear Addressing Mode
.lq_mode(true) .lq_mode(true)
@ -324,6 +338,11 @@ impl Flash<()> {
.lq_mode(false) .lq_mode(false)
); );
self.regs.enable.write(
regs::Enable::zeroed()
.spi_en(true)
);
self.transition() self.transition()
} }
} }
@ -349,14 +368,28 @@ impl Flash<LinearAddressing> {
impl Flash<Manual> { impl Flash<Manual> {
pub fn stop(self) -> Flash<()> { pub fn stop(self) -> Flash<()> {
self.regs.enable.modify(|_, w| w.spi_en(false));
self.transition() self.transition()
} }
pub fn read_reg<R: SpiFlashRegister>(&mut self) -> R { pub fn read_reg<R: SpiFlashRegister>(&mut self) -> R {
let args = Some(R::inst_code()); let args = Some(R::inst_code());
let transfer = self.transfer(args.into_iter(), 2) let transfer = self.transfer(args.into_iter(), 3)
.bytes_transfer(); .bytes_transfer();
R::new(transfer.skip(1).next().unwrap()) let b = transfer.skip(1).next().unwrap();
R::new(b)
}
pub fn write_regs(&mut self, sr1: SR1, cr: CR) {
self.write_enabled(|flash| {
let args = [
INST_WRR,
sr1.inner,
cr.inner,
];
flash.transfer(args.iter().cloned(), 3);
});
} }
pub fn read_reg_until<R, F, A>(&mut self, f: F) -> A pub fn read_reg_until<R, F, A>(&mut self, f: F) -> A
@ -368,10 +401,10 @@ impl Flash<Manual> {
while result.is_none() { while result.is_none() {
let args = Some(R::inst_code()); let args = Some(R::inst_code());
for b in self.transfer(args.into_iter(), 32) for b in self.transfer(args.into_iter(), 32)
.bytes_transfer().skip(1) { .bytes_transfer().skip(5) {
result = f(R::new(b)); result = f(R::new(b));
if result.is_none() { if result.is_some() {
break; break;
} }
} }
@ -381,19 +414,22 @@ impl Flash<Manual> {
/// Status Register-1 remains `0x00` immediately after invoking a command. /// Status Register-1 remains `0x00` immediately after invoking a command.
fn wait_while_sr1_zeroed(&mut self) -> SR1 { fn wait_while_sr1_zeroed(&mut self) -> SR1 {
self.read_reg_until::<SR1, _, SR1>(|sr1| println!("wait while sr1 0");
let sr1 = self.read_reg_until::<SR1, _, SR1>(|sr1|
if sr1.is_zeroed() { if sr1.is_zeroed() {
None None
} else { } else {
Some(sr1) Some(sr1)
} }
) );
println!("sr1 non-zero: {:02X}", sr1.inner);
sr1
} }
/// Read Identification /// Read Identification
pub fn rdid(&mut self) -> core::iter::Skip<BytesTransfer<Transfer<core::option::IntoIter<u32>, u32>>> { pub fn rdid(&mut self) -> core::iter::Skip<BytesTransfer<Transfer<core::option::IntoIter<u32>, u32>>> {
let args = Some((INST_RDID as u32) << 24); let args = Some((INST_RDID as u32) << 24);
self.transfer(args.into_iter(), 0x44) self.transfer(args.into_iter(), 0x56)
.bytes_transfer().skip(1) .bytes_transfer().skip(1)
} }
@ -422,21 +458,23 @@ impl Flash<Manual> {
print!("."); print!(".");
} }
println!(""); println!("");
} else {
println!("erased? sr1={:02X}", sr1.inner);
} }
println!("erased? sr1={:02X}", sr1.inner);
} }
pub fn program<I: Iterator<Item=u32>>(&mut self, offset: u32, data: I) { pub fn program<I: Iterator<Item=u32>>(&mut self, offset: u32, data: I) {
{ {
let len = 4 + 4 * data.size_hint().0; let len = 4 + 4 * data.size_hint().0;
// let args = Some(SpiWord::W8(INST_PP)).into_iter()
// .chain(Some(SpiWord::W24(offset as u32)).into_iter())
let args = Some(SpiWord::W32(((INST_PP as u32) << 24) | (offset as u32))).into_iter() let args = Some(SpiWord::W32(((INST_PP as u32) << 24) | (offset as u32))).into_iter()
.chain(data.map(SpiWord::W32)); .chain(data.map(SpiWord::W32));
self.transfer(args, len); self.transfer(args, len);
} }
// let sr1 = self.wait_while_sr1_zeroed(); let sr1 = self.wait_while_sr1_zeroed();
let sr1 = self.read_reg::<SR1>(); // let sr1 = self.read_reg::<SR1>();
if sr1.e_err() { if sr1.e_err() {
println!("E_ERR"); println!("E_ERR");
@ -454,10 +492,13 @@ impl Flash<Manual> {
} }
pub fn write_enabled<F: Fn(&mut Self) -> R, R>(&mut self, f: F) -> R { pub fn write_enabled<F: Fn(&mut Self) -> R, R>(&mut self, f: F) -> R {
let args = Some(INST_CLSR);
self.transfer(args.into_iter(), 1);
// Write Enable // Write Enable
let args = Some(INST_WREN); let args = Some(INST_WREN);
self.transfer(args.into_iter(), 1); self.transfer(args.into_iter(), 1);
self.regs.gpio.modify(|_, w| w.wp_n(true)); self.regs.gpio.modify(|_, w| w.wp_n(true));
println!("WPn hi");
let sr1 = self.wait_while_sr1_zeroed(); let sr1 = self.wait_while_sr1_zeroed();
if !sr1.wel() { if !sr1.wel() {
panic!("Cannot write-enable flash"); panic!("Cannot write-enable flash");
@ -468,6 +509,7 @@ impl Flash<Manual> {
// Write Disable // Write Disable
let args = Some(INST_WRDI); let args = Some(INST_WRDI);
self.transfer(args.into_iter(), 1); self.transfer(args.into_iter(), 1);
println!("WPn lo");
self.regs.gpio.modify(|_, w| w.wp_n(false)); self.regs.gpio.modify(|_, w| w.wp_n(false));
result result

View File

@ -35,6 +35,18 @@ macro_rules! u8_register {
} }
u8_register!(CR, "Configuration Register", 0x35); u8_register!(CR, "Configuration Register", 0x35);
impl CR {
/// quad I/O mode
pub fn quad(&self) -> bool {
self.inner.get_bit(1)
}
/// set quad I/O mode
pub fn set_quad(&mut self, value: bool) {
self.inner.set_bit(1, value);
}
}
u8_register!(SR1, "Status Register-1", 0x05); u8_register!(SR1, "Status Register-1", 0x05);
impl SR1 { impl SR1 {
/// Write In Progress /// Write In Progress

View File

@ -1,5 +1,4 @@
use libregister::{RegisterR, RegisterW, RegisterRW}; use libregister::{RegisterR, RegisterRW};
use super::regs;
use super::{SpiWord, Flash, Manual}; use super::{SpiWord, Flash, Manual};
pub struct Transfer<'a, Args: Iterator<Item = W>, W: Into<SpiWord>> { pub struct Transfer<'a, Args: Iterator<Item = W>, W: Into<SpiWord>> {
@ -13,10 +12,6 @@ pub struct Transfer<'a, Args: Iterator<Item = W>, W: Into<SpiWord>> {
impl<'a, Args: Iterator<Item = W>, W: Into<SpiWord>> Transfer<'a, Args, W> { impl<'a, Args: Iterator<Item = W>, W: Into<SpiWord>> Transfer<'a, Args, W> {
pub fn new(flash: &'a mut Flash<Manual>, args: Args, len: usize) -> Self { pub fn new(flash: &'a mut Flash<Manual>, args: Args, len: usize) -> Self {
flash.regs.config.modify(|_, w| w.pcs(false)); flash.regs.config.modify(|_, w| w.pcs(false));
flash.regs.enable.write(
regs::Enable::zeroed()
.spi_en(true)
);
let mut xfer = Transfer { let mut xfer = Transfer {
flash, flash,
@ -35,13 +30,15 @@ impl<'a, Args: Iterator<Item = W>, W: Into<SpiWord>> Transfer<'a, Args, W> {
let arg = self.args.next() let arg = self.args.next()
.map(|n| n.into()) .map(|n| n.into())
.unwrap_or(SpiWord::W32(0)); .unwrap_or(SpiWord::W32(0));
match arg {
// println!("w {:?}", arg);
let write_len = match arg {
SpiWord::W32(w) => { SpiWord::W32(w) => {
// println!("txd0 {:08X}", w); // println!("txd0 {:08X}", w);
unsafe { unsafe {
self.flash.regs.txd0.write(w); self.flash.regs.txd0.write(w);
} }
self.sent += 4; 4
} }
// Only txd0 can be used without flushing // Only txd0 can be used without flushing
_ => { _ => {
@ -50,32 +47,38 @@ impl<'a, Args: Iterator<Item = W>, W: Into<SpiWord>> Transfer<'a, Args, W> {
self.flash.wait_tx_fifo_flush(); self.flash.wait_tx_fifo_flush();
} }
match arg { let write_len = match arg {
SpiWord::W8(w) => { SpiWord::W8(w) => {
// println!("txd1 {:02X}", w); // println!("txd1 {:02X}", w);
unsafe { unsafe {
self.flash.regs.txd1.write(u32::from(w) << 24); self.flash.regs.txd1.write(u32::from(w) << 24);
} }
self.sent += 1; 1
} }
SpiWord::W16(w) => { SpiWord::W16(w) => {
unsafe { unsafe {
self.flash.regs.txd2.write(u32::from(w) << 16); self.flash.regs.txd2.write(u32::from(w) << 16);
} }
self.sent += 2; 2
} }
SpiWord::W24(w) => { SpiWord::W24(w) => {
unsafe { unsafe {
self.flash.regs.txd3.write(w << 8); self.flash.regs.txd3.write(w << 8);
} }
self.sent += 3; 3
} }
SpiWord::W32(_) => unreachable!(), SpiWord::W32(_) => unreachable!(),
} };
self.flash.wait_tx_fifo_flush(); self.flash.wait_tx_fifo_flush();
write_len
} }
} };
self.sent += write_len;
// if self.sent % 258 == 0 {
// self.flash.wait_tx_fifo_flush();
// }
} }
} }
@ -85,6 +88,7 @@ impl<'a, Args: Iterator<Item = W>, W: Into<SpiWord>> Transfer<'a, Args, W> {
fn read(&mut self) -> u32 { fn read(&mut self) -> u32 {
let rx = self.flash.regs.rx_data.read(); let rx = self.flash.regs.rx_data.read();
// println!("r 0x{:02X}", rx);
self.received += 4; self.received += 4;
rx rx
} }
@ -97,15 +101,21 @@ impl<'a, Args: Iterator<Item = W>, W: Into<SpiWord>> Drop for Transfer<'a, Args,
self.read(); self.read();
} }
// Stop // // Stop
self.flash.regs.enable.write( // self.flash.regs.enable.write(
regs::Enable::zeroed() // regs::Enable::zeroed()
.spi_en(false) // .spi_en(false)
); // );
self.flash.regs.config.modify(|_, w| w self.flash.regs.config.modify(|_, w| w
.pcs(true) .pcs(true)
.man_start_com(false) .man_start_com(false)
); );
// Leave PCS high for a few cycles
for _ in 0..0x100 {
libcortex_a9::asm::nop();
}
} }
} }
@ -119,7 +129,10 @@ impl<'a, Args: Iterator<Item = W>, W: Into<SpiWord>> Iterator for Transfer<'a, A
self.fill_tx_fifo(); self.fill_tx_fifo();
// print!("read:");
while !self.can_read() {} while !self.can_read() {}
Some(self.read()) let b = self.read();
// println!(" {:08X}", b);
Some(b)
} }
} }

View File

@ -8,7 +8,7 @@ macro_rules! def_reg_r {
impl RegisterR for $name { impl RegisterR for $name {
type R = $type; type R = $type;
#[inline(always)] #[inline]
fn read(&self) -> Self::R { fn read(&self) -> Self::R {
let mut value: u32; let mut value: u32;
unsafe { asm!($asm_instr : "=r" (value) ::: "volatile") } unsafe { asm!($asm_instr : "=r" (value) ::: "volatile") }
@ -23,12 +23,13 @@ macro_rules! def_reg_w {
impl RegisterW for $name { impl RegisterW for $name {
type W = $type; type W = $type;
#[inline(always)] #[inline]
fn write(&mut self, value: Self::W) { fn write(&mut self, value: Self::W) {
let value: u32 = value.into(); let value: u32 = value.into();
unsafe { asm!($asm_instr :: "r" (value) :: "volatile") } unsafe { asm!($asm_instr :: "r" (value) :: "volatile") }
} }
#[inline]
fn zeroed() -> Self::W { fn zeroed() -> Self::W {
0u32.into() 0u32.into()
} }
@ -43,6 +44,7 @@ macro_rules! wrap_reg {
pub inner: u32, pub inner: u32,
} }
impl From<u32> for Read { impl From<u32> for Read {
#[inline]
fn from(value: u32) -> Self { fn from(value: u32) -> Self {
Read { inner: value } Read { inner: value }
} }
@ -52,11 +54,13 @@ macro_rules! wrap_reg {
pub inner: u32, pub inner: u32,
} }
impl From<u32> for Write { impl From<u32> for Write {
#[inline]
fn from(value: u32) -> Self { fn from(value: u32) -> Self {
Write { inner: value } Write { inner: value }
} }
} }
impl Into<u32> for Write { impl Into<u32> for Write {
#[inline]
fn into(self) -> u32 { fn into(self) -> u32 {
self.inner self.inner
} }
@ -133,6 +137,7 @@ register_bit!(actlr, l1_prefetch_enable, 2);
register_bit!(actlr, fw, 0); register_bit!(actlr, fw, 0);
impl RegisterRW for ACTLR { impl RegisterRW for ACTLR {
#[inline]
fn modify<F: FnOnce(Self::R, Self::W) -> Self::W>(&mut self, f: F) { fn modify<F: FnOnce(Self::R, Self::W) -> Self::W>(&mut self, f: F) {
let r = self.read(); let r = self.read();
let w = actlr::Write { inner: r.inner }; let w = actlr::Write { inner: r.inner };

View File

@ -55,6 +55,7 @@ macro_rules! register_r {
impl libregister::RegisterR for $struct_name { impl libregister::RegisterR for $struct_name {
type R = $mod_name::Read; type R = $mod_name::Read;
#[inline]
fn read(&self) -> Self::R { fn read(&self) -> Self::R {
let inner = self.inner.read(); let inner = self.inner.read();
$mod_name::Read { inner } $mod_name::Read { inner }
@ -69,10 +70,12 @@ macro_rules! register_w {
impl libregister::RegisterW for $struct_name { impl libregister::RegisterW for $struct_name {
type W = $mod_name::Write; type W = $mod_name::Write;
#[inline]
fn zeroed() -> $mod_name::Write { fn zeroed() -> $mod_name::Write {
$mod_name::Write { inner: 0 } $mod_name::Write { inner: 0 }
} }
#[inline]
fn write(&mut self, w: Self::W) { fn write(&mut self, w: Self::W) {
unsafe { unsafe {
self.inner.write(w.inner); self.inner.write(w.inner);
@ -86,6 +89,7 @@ macro_rules! register_w {
macro_rules! register_rw { macro_rules! register_rw {
($mod_name: ident, $struct_name: ident) => ( ($mod_name: ident, $struct_name: ident) => (
impl libregister::RegisterRW for $struct_name { impl libregister::RegisterRW for $struct_name {
#[inline]
fn modify<F: FnOnce(Self::R, Self::W) -> Self::W>(&mut self, f: F) { fn modify<F: FnOnce(Self::R, Self::W) -> Self::W>(&mut self, f: F) {
unsafe { unsafe {
self.inner.modify(|inner| { self.inner.modify(|inner| {
@ -105,6 +109,7 @@ macro_rules! register_vcell {
impl libregister::RegisterR for $struct_name { impl libregister::RegisterR for $struct_name {
type R = $mod_name::Read; type R = $mod_name::Read;
#[inline]
fn read(&self) -> Self::R { fn read(&self) -> Self::R {
let inner = self.inner.get(); let inner = self.inner.get();
$mod_name::Read { inner } $mod_name::Read { inner }
@ -113,15 +118,18 @@ macro_rules! register_vcell {
impl libregister::RegisterW for $struct_name { impl libregister::RegisterW for $struct_name {
type W = $mod_name::Write; type W = $mod_name::Write;
#[inline]
fn zeroed() -> $mod_name::Write { fn zeroed() -> $mod_name::Write {
$mod_name::Write { inner: 0 } $mod_name::Write { inner: 0 }
} }
#[inline]
fn write(&mut self, w: Self::W) { fn write(&mut self, w: Self::W) {
self.inner.set(w.inner); self.inner.set(w.inner);
} }
} }
impl libregister::RegisterRW for $struct_name { impl libregister::RegisterRW for $struct_name {
#[inline]
fn modify<F: FnOnce(Self::R, Self::W) -> Self::W>(&mut self, f: F) { fn modify<F: FnOnce(Self::R, Self::W) -> Self::W>(&mut self, f: F) {
let r = self.read(); let r = self.read();
let w = $mod_name::Write { inner: r.inner }; let w = $mod_name::Write { inner: r.inner };
@ -169,6 +177,7 @@ macro_rules! register_bit {
$(#[$outer])* $(#[$outer])*
impl $mod_name::Read { impl $mod_name::Read {
#[allow(unused)] #[allow(unused)]
#[inline]
pub fn $name(&self) -> bool { pub fn $name(&self) -> bool {
use bit_field::BitField; use bit_field::BitField;
@ -179,6 +188,7 @@ macro_rules! register_bit {
$(#[$outer])* $(#[$outer])*
impl $mod_name::Write { impl $mod_name::Write {
#[allow(unused)] #[allow(unused)]
#[inline]
pub fn $name(mut self, value: bool) -> Self { pub fn $name(mut self, value: bool) -> Self {
use bit_field::BitField; use bit_field::BitField;
@ -195,6 +205,7 @@ macro_rules! register_bits {
($mod_name: ident, $(#[$outer:meta])* $name: ident, $type: ty, $bit_begin: expr, $bit_end: expr) => ( ($mod_name: ident, $(#[$outer:meta])* $name: ident, $type: ty, $bit_begin: expr, $bit_end: expr) => (
impl $mod_name::Read { impl $mod_name::Read {
#[allow(unused)] #[allow(unused)]
#[inline]
$(#[$outer])* $(#[$outer])*
pub fn $name(&self) -> $type { pub fn $name(&self) -> $type {
use bit_field::BitField; use bit_field::BitField;
@ -207,6 +218,7 @@ macro_rules! register_bits {
$(#[$outer])* $(#[$outer])*
impl $mod_name::Write { impl $mod_name::Write {
#[allow(unused)] #[allow(unused)]
#[inline]
pub fn $name(mut self, value: $type) -> Self { pub fn $name(mut self, value: $type) -> Self {
use bit_field::BitField; use bit_field::BitField;
@ -226,6 +238,7 @@ macro_rules! register_bits_typed {
($mod_name: ident, $(#[$outer:meta])* $name: ident, $bit_type: ty, $type: ty, $bit_begin: expr, $bit_end: expr) => ( ($mod_name: ident, $(#[$outer:meta])* $name: ident, $bit_type: ty, $type: ty, $bit_begin: expr, $bit_end: expr) => (
impl $mod_name::Read { impl $mod_name::Read {
#[allow(unused)] #[allow(unused)]
#[inline]
$(#[$outer])* $(#[$outer])*
pub fn $name(&self) -> $type { pub fn $name(&self) -> $type {
use bit_field::BitField; use bit_field::BitField;
@ -237,6 +250,7 @@ macro_rules! register_bits_typed {
impl $mod_name::Write { impl $mod_name::Write {
#[allow(unused)] #[allow(unused)]
#[inline]
$(#[$outer])* $(#[$outer])*
pub fn $name(mut self, value: $type) -> Self { pub fn $name(mut self, value: $type) -> Self {
use bit_field::BitField; use bit_field::BitField;
@ -254,6 +268,7 @@ macro_rules! register_at {
($name: ident, $addr: expr, $ctor: ident) => ( ($name: ident, $addr: expr, $ctor: ident) => (
impl $name { impl $name {
#[allow(unused)] #[allow(unused)]
#[inline]
pub fn $ctor() -> &'static mut Self { pub fn $ctor() -> &'static mut Self {
let addr = $addr as *mut Self; let addr = $addr as *mut Self;
unsafe { &mut *addr } unsafe { &mut *addr }

10
link.x
View File

@ -21,17 +21,9 @@ MEMORY
SECTIONS SECTIONS
{ {
.exceptions ORIGIN(OCM) : .text :
{ {
KEEP(*(.text.exceptions)); KEEP(*(.text.exceptions));
} > OCM
.__fill (NOLOAD) : {
. = ORIGIN(OCM) + 0x8000;
} > OCM
.text (ORIGIN(OCM) + 0x8000) :
{
*(.text.boot); *(.text.boot);
*(.text .text.*); *(.text .text.*);
} > OCM } > OCM