Merge pull request #511 from betrusted-io/cramium

add quantum timer feature to cramium target
This commit is contained in:
bunnie 2024-03-07 01:35:44 +08:00 committed by GitHub
commit f389b41ccf
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 68 additions and 35 deletions

View file

@ -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 = {

View file

@ -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 = []

View file

@ -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 {

View file

@ -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.
);
}