Compare commits
8 Commits
master
...
flash-mini
Author | SHA1 | Date | |
---|---|---|---|
2f754de64b | |||
b5b3cf69f7 | |||
3b657ffef0 | |||
9bfc15cbb9 | |||
c8d03a43c6 | |||
e2ba91b79b | |||
acb5207d0e | |||
2b20d6b6c8 |
@ -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 {}
|
||||||
}
|
}
|
||||||
|
@ -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 {}
|
||||||
|
@ -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,
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 };
|
||||||
|
@ -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
10
link.x
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user