mirror of
https://github.com/saymrwulf/xous-core.git
synced 2026-11-08 04:56:43 +00:00
Merge pull request #511 from betrusted-io/cramium
add quantum timer feature to cramium target
This commit is contained in:
commit
f389b41ccf
4 changed files with 68 additions and 35 deletions
|
|
@ -947,6 +947,11 @@ impl PioSm {
|
|||
(self.pio.r(rp_pio::SFR_IRQ) & (1 << int_number)) != 0
|
||||
}
|
||||
|
||||
pub fn sm_interrupt_clear(&mut self, int_number: usize) {
|
||||
assert!(int_number < 8);
|
||||
self.pio.wo(rp_pio::SFR_IRQ, 1 << int_number)
|
||||
}
|
||||
|
||||
pub fn sm_drain_tx_fifo(&mut self) {
|
||||
let sm_offset = self.sm_to_stride_offset();
|
||||
let instr = {
|
||||
|
|
|
|||
|
|
@ -31,6 +31,6 @@ rkyv = { version = "0.4.3", default-features = false, features = [
|
|||
] }
|
||||
|
||||
[features]
|
||||
pio = []
|
||||
pio-memlcd = []
|
||||
# add this feature to enable pre-emption
|
||||
quantum-timer = ["utralib"]
|
||||
default = []
|
||||
|
|
|
|||
|
|
@ -1,12 +1,28 @@
|
|||
mod api;
|
||||
use api::*;
|
||||
#[cfg(feature = "pio")]
|
||||
mod pio;
|
||||
use cramium_hal::{
|
||||
iox,
|
||||
udma::{EventChannel, GlobalConfig, PeriphId},
|
||||
};
|
||||
#[cfg(feature = "quantum-timer")]
|
||||
use utralib::utra;
|
||||
#[cfg(feature = "quantum-timer")]
|
||||
use utralib::*;
|
||||
use xous::sender::Sender;
|
||||
use xous_pio::*;
|
||||
|
||||
#[cfg(feature = "quantum-timer")]
|
||||
fn timer_tick(_irq_no: usize, arg: *mut usize) {
|
||||
let sm_a = unsafe { &mut *(arg as *mut PioSm) };
|
||||
// this call forces preemption every timer tick
|
||||
// rsyscalls are "raw syscalls" -- used for syscalls that don't have a friendly wrapper around them
|
||||
// since ReturnToParent is only used here, we haven't wrapped it, so we use an rsyscall
|
||||
xous::rsyscall(xous::SysCall::ReturnToParent(xous::PID::new(1).unwrap(), 0))
|
||||
.expect("couldn't return to parent");
|
||||
|
||||
// acknowledge the timer
|
||||
sm_a.sm_interrupt_clear(1);
|
||||
}
|
||||
|
||||
fn try_alloc(ifram_allocs: &mut Vec<Option<Sender>>, size: usize, sender: Sender) -> Option<usize> {
|
||||
let mut size_pages = size / 4096;
|
||||
|
|
@ -97,6 +113,49 @@ fn main() {
|
|||
.expect("couldn't map UDMA global control");
|
||||
let mut udma_global = GlobalConfig::new(udma_global_csr.as_mut_ptr() as *mut u32);
|
||||
|
||||
#[cfg(feature = "quantum-timer")]
|
||||
{
|
||||
let mut pio_ss = xous_pio::PioSharedState::new();
|
||||
let mut sm_a = pio_ss.alloc_sm().unwrap();
|
||||
// claim the IRQ for the quanta timer
|
||||
xous::claim_interrupt(
|
||||
utralib::LITEX_IRQARRAY18_INTERRUPT,
|
||||
timer_tick,
|
||||
&mut sm_a as *mut PioSm as *mut usize,
|
||||
)
|
||||
.expect("couldn't claim IRQ");
|
||||
|
||||
pio_ss.clear_instruction_memory();
|
||||
pio_ss.pio.rmwf(utra::rp_pio::SFR_CTRL_EN, 0);
|
||||
#[rustfmt::skip]
|
||||
let timer_code = pio_proc::pio_asm!(
|
||||
"restart:",
|
||||
"set x, 6", // 4 cycles overhead gets us to 10 iterations per pulse
|
||||
"waitloop:",
|
||||
"jmp x-- waitloop",
|
||||
"irq set 0",
|
||||
"jmp restart",
|
||||
);
|
||||
let a_prog = LoadedProg::load(timer_code.program, &mut pio_ss).unwrap();
|
||||
sm_a.sm_set_enabled(false);
|
||||
a_prog.setup_default_config(&mut sm_a);
|
||||
sm_a.config_set_clkdiv(50_000.0f32); // set to 1ms per iteration
|
||||
sm_a.sm_init(a_prog.entry());
|
||||
sm_a.sm_irq0_source_enabled(PioIntSource::Sm, true);
|
||||
sm_a.sm_set_enabled(true);
|
||||
|
||||
// map and enable the interrupt for the PIO system timer
|
||||
let irq18_page = xous::syscall::map_memory(
|
||||
xous::MemoryAddress::new(utralib::generated::HW_IOX_BASE),
|
||||
None,
|
||||
4096,
|
||||
xous::MemoryFlags::R | xous::MemoryFlags::W,
|
||||
)
|
||||
.expect("couldn't claim irq18 csr");
|
||||
let mut irq18_csr = CSR::new(irq18_page.as_mut_ptr() as *mut u32);
|
||||
irq18_csr.wfo(utra::irqarray18::EV_ENABLE_PIOIRQ0_DUPE, 1);
|
||||
}
|
||||
|
||||
let mut msg_opt = None;
|
||||
log::debug!("Starting main loop");
|
||||
loop {
|
||||
|
|
|
|||
|
|
@ -1,31 +0,0 @@
|
|||
use cramium_hal::iox;
|
||||
use xous_pio::*;
|
||||
|
||||
/// This is the start of the memory LCD driver program, but aborted because we now
|
||||
/// realize the UDMA SPI block is much better suited for this task.
|
||||
fn pio_memlcd_program() {
|
||||
#[rustfmt::skip]
|
||||
let memlcd_line = pio_proc::pio_asm!(
|
||||
// The PIO engine is configured as a simple 16-bit, LSB-first shift register
|
||||
// to send data to the LCD at a rate of 2 MHz, requesting a new word via DMA
|
||||
// whenever the shift register is empty. It takes 2 PIO cycles to send one
|
||||
// bit, so the PIO engine should be configure to run at 4 MHz.
|
||||
//
|
||||
// In addition to the shift function, the PIO asserts the chip select signal
|
||||
// high for 12 cycles (3us @ 4MHz) before the first word starts shifting
|
||||
//
|
||||
// At the end of the DMA transfer, CS & clock should be dropped manually.
|
||||
".side_set 2 opt",
|
||||
|
||||
".define CS_SETUP_DELAY 12 ", // setup time for CS
|
||||
"setup_line:",
|
||||
" set y, CS_SETUP_DELAY side 0",
|
||||
"setup_cs:",
|
||||
" jmp y-- setup_cs side 1", // respect setup time
|
||||
".wrap_target",
|
||||
" out pins, 1 side 1", // assert data/clock low
|
||||
" nop side 3", // clock high
|
||||
".wrap",
|
||||
// after data transfer is done, clock and then CS should be dropped manually.
|
||||
);
|
||||
}
|
||||
Loading…
Reference in a new issue