1use core::cell::Cell;
15
16use kernel::utilities::cells::OptionalCell;
17use kernel::utilities::registers::interfaces::{ReadWriteable, Readable, Writeable};
18use kernel::utilities::registers::{register_bitfields, register_structs, ReadOnly, ReadWrite};
19use kernel::utilities::StaticRef;
20use kernel::{debug, ErrorCode};
21
22use crate::gpio::{GpioFunction, RPGpio, RPGpioPin};
23
24const NUMBER_STATE_MACHINES: usize = 4;
25const NUMBER_INSTR_MEMORY_LOCATIONS: usize = 32;
26
27#[repr(C)]
28struct InstrMem {
29 instr_mem: ReadWrite<u32, INSTR_MEMx::Register>,
31}
32
33#[repr(C)]
34struct StateMachineReg {
35 clkdiv: ReadWrite<u32, SMx_CLKDIV::Register>,
38 execctrl: ReadWrite<u32, SMx_EXECCTRL::Register>,
40 shiftctrl: ReadWrite<u32, SMx_SHIFTCTRL::Register>,
43 addr: ReadOnly<u32, SMx_ADDR::Register>,
45 instr: ReadWrite<u32, SMx_INSTR::Register>,
49 pinctrl: ReadWrite<u32, SMx_PINCTRL::Register>,
51}
52
53register_structs! {
54PioRegisters {
55 (0x000 => ctrl: ReadWrite<u32, CTRL::Register>),
57 (0x004 => fstat: ReadOnly<u32, FSTAT::Register>),
59 (0x008 => fdebug: ReadWrite<u32, FDEBUG::Register>),
61 (0x00C => flevel: ReadOnly<u32, FLEVEL::Register>),
63 (0x010 => txf: [ReadWrite<u32, TXFx::Register>; 4]),
68 (0x020 => rxf: [ReadOnly<u32, RXFx::Register>; 4]),
74 (0x030 => irq: ReadWrite<u32, IRQ::Register>),
84 (0x034 => irq_force: ReadWrite<u32, IRQ_FORCE::Register>),
90 (0x038 => input_sync_bypass: ReadWrite<u32, INPUT_SYNC_BYPASS::Register>),
99 (0x03C => dbg_padout: ReadOnly<u32, DBG_PADOUT::Register>),
102 (0x040 => dbg_padoe: ReadOnly<u32, DBG_PADOE::Register>),
106 (0x044 => dbg_cfginfo: ReadOnly<u32, DBG_CFGINFO::Register>),
109 (0x048 => instr_mem: [InstrMem; NUMBER_INSTR_MEMORY_LOCATIONS]),
111 (0x0c8 => sm: [StateMachineReg; NUMBER_STATE_MACHINES]),
113 (0x128 => intr: ReadWrite<u32, INTR::Register>),
115 (0x12C => irq0_inte: ReadWrite<u32, IRQ0_INTE::Register>),
117 (0x130 => irq0_intf: ReadWrite<u32, IRQ0_INTF::Register>),
119 (0x134 => irq0_ints: ReadWrite<u32, IRQ0_INTS::Register>),
121 (0x138 => irq1_inte: ReadWrite<u32, IRQ1_INTE::Register>),
123 (0x13C => irq1_intf: ReadWrite<u32, IRQ1_INTF::Register>),
125 (0x140 => irq1_ints: ReadWrite<u32, IRQ1_INTS::Register>),
127 (0x144 => @END),
128 }
129}
130
131register_bitfields![u32,
132CTRL [
133 CLKDIV3_RESTART OFFSET(11) NUMBITS(1) [],
145 CLKDIV2_RESTART OFFSET(10) NUMBITS(1) [],
146 CLKDIV1_RESTART OFFSET(9) NUMBITS(1) [],
147 CLKDIV0_RESTART OFFSET(8) NUMBITS(1) [],
148 SM3_RESTART OFFSET(7) NUMBITS(1) [],
157 SM2_RESTART OFFSET(6) NUMBITS(1) [],
158 SM1_RESTART OFFSET(5) NUMBITS(1) [],
159 SM0_RESTART OFFSET(4) NUMBITS(1) [],
160 SM3_ENABLE OFFSET(3) NUMBITS(1) [],
167 SM2_ENABLE OFFSET(2) NUMBITS(1) [],
168 SM1_ENABLE OFFSET(1) NUMBITS(1) [],
169 SM0_ENABLE OFFSET(0) NUMBITS(1) [],
170],
171FSTAT [
172 TXEMPTY3 OFFSET(27) NUMBITS(1) [],
174 TXEMPTY2 OFFSET(26) NUMBITS(1) [],
175 TXEMPTY1 OFFSET(25) NUMBITS(1) [],
176 TXEMPTY0 OFFSET(24) NUMBITS(1) [],
177 TXFULL3 OFFSET(19) NUMBITS(1) [],
179 TXFULL2 OFFSET(18) NUMBITS(1) [],
180 TXFULL1 OFFSET(17) NUMBITS(1) [],
181 TXFULL0 OFFSET(16) NUMBITS(1) [],
182 RXEMPTY3 OFFSET(11) NUMBITS(1) [],
184 RXEMPTY2 OFFSET(10) NUMBITS(1) [],
185 RXEMPTY1 OFFSET(9) NUMBITS(1) [],
186 RXEMPTY0 OFFSET(8) NUMBITS(1) [],
187 RXFULL3 OFFSET(3) NUMBITS(1) [],
189 RXFULL2 OFFSET(2) NUMBITS(1) [],
190 RXFULL1 OFFSET(1) NUMBITS(1) [],
191 RXFULL0 OFFSET(0) NUMBITS(1) []
192],
193FDEBUG [
194 TXSTALL OFFSET(24) NUMBITS(4) [],
198 TXOVER OFFSET(16) NUMBITS(4) [],
205 RXUNDER OFFSET(8) NUMBITS(4) [],
212 RXSTALL OFFSET(0) NUMBITS(4) []
218],
219FLEVEL [
220 RX3 OFFSET(28) NUMBITS(4) [],
221 TX3 OFFSET(24) NUMBITS(4) [],
222 RX2 OFFSET(20) NUMBITS(4) [],
223 TX2 OFFSET(16) NUMBITS(4) [],
224 RX1 OFFSET(12) NUMBITS(4) [],
225 TX1 OFFSET(8) NUMBITS(4) [],
226 RX0 OFFSET(4) NUMBITS(4) [],
227 TX0 OFFSET(0) NUMBITS(4) []
228],
229TXFx [
230 TXF OFFSET(0) NUMBITS(32) []
231],
232RXFx [
233 RXF OFFSET(0) NUMBITS(32) []
234],
235IRQ [
236 IRQ7 OFFSET(7) NUMBITS(1) [],
237 IRQ6 OFFSET(6) NUMBITS(1) [],
238 IRQ5 OFFSET(5) NUMBITS(1) [],
239 IRQ4 OFFSET(4) NUMBITS(1) [],
240 IRQ3 OFFSET(3) NUMBITS(1) [],
241 IRQ2 OFFSET(2) NUMBITS(1) [],
242 IRQ1 OFFSET(1) NUMBITS(1) [],
243 IRQ0 OFFSET(0) NUMBITS(1) []
244],
245IRQ_FORCE [
246 IRQ_FORCE OFFSET(0) NUMBITS(8) []
247],
248INPUT_SYNC_BYPASS [
249 INPUT_SYNC_BYPASS OFFSET(0) NUMBITS(32) []
250],
251DBG_PADOUT [
252 DBG_PADOUT OFFSET(0) NUMBITS(32) []
253],
254DBG_PADOE [
255 DBG_PADOE OFFSET(0) NUMBITS(32) []
256],
257DBG_CFGINFO [
258 IMEM_SIZE OFFSET(16) NUMBITS(6) [],
261 SM_COUNT OFFSET(8) NUMBITS(4) [],
264 FIFO_DEPTH OFFSET(0) NUMBITS(6) []
267],
268INSTR_MEMx [
269 INSTR_MEM OFFSET(0) NUMBITS(16) []
271],
272SMx_CLKDIV [
273 INT OFFSET(16) NUMBITS(16) [],
277 FRAC OFFSET(8) NUMBITS(8) []
279],
280SMx_EXECCTRL [
281 EXEC_STALLED OFFSET(31) NUMBITS(1) [],
285 SIDE_EN OFFSET(30) NUMBITS(1) [],
292 SIDE_PINDIR OFFSET(29) NUMBITS(1) [],
295 JMP_PIN OFFSET(24) NUMBITS(5) [],
298 OUT_EN_SEL OFFSET(19) NUMBITS(5) [],
300 INLINE_OUT_EN OFFSET(18) NUMBITS(1) [],
308 OUT_STICKY OFFSET(17) NUMBITS(1) [],
310 WRAP_TOP OFFSET(12) NUMBITS(5) [],
315 WRAP_BOTTOM OFFSET(7) NUMBITS(5) [],
318 STATUS_SEL OFFSET(4) NUMBITS(1) [],
319 STATUS_N OFFSET(0) NUMBITS(4) []
321],
322SMx_SHIFTCTRL [
323 FJOIN_RX OFFSET(31) NUMBITS(1) [],
329 FJOIN_TX OFFSET(30) NUMBITS(1) [],
335 PULL_THRESH OFFSET(25) NUMBITS(5) [],
339 PUSH_THRESH OFFSET(20) NUMBITS(5) [],
343 OUT_SHIFTDIR OFFSET(19) NUMBITS(1) [
344 ShiftRight = 1,
345 ShiftLeft = 0
346 ],
347 IN_SHIFTDIR OFFSET(18) NUMBITS(1) [
348 ShiftRight = 1,
349 ShiftLeft = 0
350 ],
351 AUTOPULL OFFSET(17) NUMBITS(1) [],
356 AUTOPUSH OFFSET(16) NUMBITS(1) []
360],
361SMx_ADDR [
362 ADDR OFFSET(0) NUMBITS(5) []
363],
364SMx_INSTR [
365 INSTR OFFSET(0) NUMBITS(16) []
366],
367SMx_PINCTRL [
368 SIDESET_COUNT OFFSET(29) NUMBITS(3) [],
373 SET_COUNT OFFSET(26) NUMBITS(3) [],
376 OUT_COUNT OFFSET(20) NUMBITS(6) [],
380 IN_BASE OFFSET(15) NUMBITS(5) [],
385 SIDESET_BASE OFFSET(10) NUMBITS(5) [],
393 SET_BASE OFFSET(5) NUMBITS(5) [],
397 OUT_BASE OFFSET(0) NUMBITS(5) []
402],
403INTR [
404 SM3 OFFSET(11) NUMBITS(1) [],
405 SM2 OFFSET(10) NUMBITS(1) [],
406 SM1 OFFSET(9) NUMBITS(1) [],
407 SM0 OFFSET(8) NUMBITS(1) [],
408 SM3_TXNFULL OFFSET(7) NUMBITS(1) [],
409 SM2_TXNFULL OFFSET(6) NUMBITS(1) [],
410 SM1_TXNFULL OFFSET(5) NUMBITS(1) [],
411 SM0_TXNFULL OFFSET(4) NUMBITS(1) [],
412 SM3_RXNEMPTY OFFSET(3) NUMBITS(1) [],
413 SM2_RXNEMPTY OFFSET(2) NUMBITS(1) [],
414 SM1_RXNEMPTY OFFSET(1) NUMBITS(1) [],
415 SM0_RXNEMPTY OFFSET(0) NUMBITS(1) []
416],
417IRQ0_INTE [
418 SM3 OFFSET(11) NUMBITS(1) [],
419 SM2 OFFSET(10) NUMBITS(1) [],
420 SM1 OFFSET(9) NUMBITS(1) [],
421 SM0 OFFSET(8) NUMBITS(1) [],
422 SM3_TXNFULL OFFSET(7) NUMBITS(1) [],
423 SM2_TXNFULL OFFSET(6) NUMBITS(1) [],
424 SM1_TXNFULL OFFSET(5) NUMBITS(1) [],
425 SM0_TXNFULL OFFSET(4) NUMBITS(1) [],
426 SM3_RXNEMPTY OFFSET(3) NUMBITS(1) [],
427 SM2_RXNEMPTY OFFSET(2) NUMBITS(1) [],
428 SM1_RXNEMPTY OFFSET(1) NUMBITS(1) [],
429 SM0_RXNEMPTY OFFSET(0) NUMBITS(1) []
430],
431IRQ0_INTF [
432 SM3 OFFSET(11) NUMBITS(1) [],
433 SM2 OFFSET(10) NUMBITS(1) [],
434 SM1 OFFSET(9) NUMBITS(1) [],
435 SM0 OFFSET(8) NUMBITS(1) [],
436 SM3_TXNFULL OFFSET(7) NUMBITS(1) [],
437 SM2_TXNFULL OFFSET(6) NUMBITS(1) [],
438 SM1_TXNFULL OFFSET(5) NUMBITS(1) [],
439 SM0_TXNFULL OFFSET(4) NUMBITS(1) [],
440 SM3_RXNEMPTY OFFSET(3) NUMBITS(1) [],
441 SM2_RXNEMPTY OFFSET(2) NUMBITS(1) [],
442 SM1_RXNEMPTY OFFSET(1) NUMBITS(1) [],
443 SM0_RXNEMPTY OFFSET(0) NUMBITS(1) []
444],
445IRQ0_INTS [
446 SM3 OFFSET(0) NUMBITS(1) [],
447 SM2 OFFSET(0) NUMBITS(1) [],
448 SM1 OFFSET(0) NUMBITS(1) [],
449 SM0 OFFSET(0) NUMBITS(1) [],
450 SM3_TXNFULL OFFSET(0) NUMBITS(1) [],
451 SM2_TXNFULL OFFSET(0) NUMBITS(1) [],
452 SM1_TXNFULL OFFSET(0) NUMBITS(1) [],
453 SM0_TXNFULL OFFSET(0) NUMBITS(1) [],
454 SM3_RXNEMPTY OFFSET(0) NUMBITS(1) [],
455 SM2_RXNEMPTY OFFSET(0) NUMBITS(1) [],
456 SM1_RXNEMPTY OFFSET(0) NUMBITS(1) [],
457 SM0_RXNEMPTY OFFSET(0) NUMBITS(1) []
458],
459IRQ1_INTE [
460 SM3 OFFSET(11) NUMBITS(1) [],
461 SM2 OFFSET(10) NUMBITS(1) [],
462 SM1 OFFSET(9) NUMBITS(1) [],
463 SM0 OFFSET(8) NUMBITS(1) [],
464 SM3_TXNFULL OFFSET(7) NUMBITS(1) [],
465 SM2_TXNFULL OFFSET(6) NUMBITS(1) [],
466 SM1_TXNFULL OFFSET(5) NUMBITS(1) [],
467 SM0_TXNFULL OFFSET(4) NUMBITS(1) [],
468 SM3_RXNEMPTY OFFSET(3) NUMBITS(1) [],
469 SM2_RXNEMPTY OFFSET(2) NUMBITS(1) [],
470 SM1_RXNEMPTY OFFSET(1) NUMBITS(1) [],
471 SM0_RXNEMPTY OFFSET(0) NUMBITS(1) []
472],
473IRQ1_INTF [
474 SM3 OFFSET(11) NUMBITS(1) [],
475 SM2 OFFSET(10) NUMBITS(1) [],
476 SM1 OFFSET(9) NUMBITS(1) [],
477 SM0 OFFSET(8) NUMBITS(1) [],
478 SM3_TXNFULL OFFSET(7) NUMBITS(1) [],
479 SM2_TXNFULL OFFSET(6) NUMBITS(1) [],
480 SM1_TXNFULL OFFSET(5) NUMBITS(1) [],
481 SM0_TXNFULL OFFSET(4) NUMBITS(1) [],
482 SM3_RXNEMPTY OFFSET(3) NUMBITS(1) [],
483 SM2_RXNEMPTY OFFSET(2) NUMBITS(1) [],
484 SM1_RXNEMPTY OFFSET(1) NUMBITS(1) [],
485 SM0_RXNEMPTY OFFSET(0) NUMBITS(1) []
486],
487IRQ1_INTS [
488 SM3 OFFSET(11) NUMBITS(1) [],
489 SM2 OFFSET(10) NUMBITS(1) [],
490 SM1 OFFSET(9) NUMBITS(1) [],
491 SM0 OFFSET(8) NUMBITS(1) [],
492 SM3_TXNFULL OFFSET(7) NUMBITS(1) [],
493 SM2_TXNFULL OFFSET(6) NUMBITS(1) [],
494 SM1_TXNFULL OFFSET(5) NUMBITS(1) [],
495 SM0_TXNFULL OFFSET(4) NUMBITS(1) [],
496 SM3_RXNEMPTY OFFSET(3) NUMBITS(1) [],
497 SM2_RXNEMPTY OFFSET(2) NUMBITS(1) [],
498 SM1_RXNEMPTY OFFSET(1) NUMBITS(1) [],
499 SM0_RXNEMPTY OFFSET(0) NUMBITS(1) []
500]
501];
502
503const PIO_0_BASE_ADDRESS: usize = 0x50200000;
504const PIO_1_BASE_ADDRESS: usize = 0x50300000;
505const PIO0_BASE: StaticRef<PioRegisters> =
506 unsafe { StaticRef::new(PIO_0_BASE_ADDRESS as *const PioRegisters) };
507const PIO0_XOR_BASE: StaticRef<PioRegisters> =
508 unsafe { StaticRef::new((PIO_0_BASE_ADDRESS + 0x1000) as *const PioRegisters) };
509const PIO0_SET_BASE: StaticRef<PioRegisters> =
510 unsafe { StaticRef::new((PIO_0_BASE_ADDRESS + 0x2000) as *const PioRegisters) };
511const PIO0_CLEAR_BASE: StaticRef<PioRegisters> =
512 unsafe { StaticRef::new((PIO_0_BASE_ADDRESS + 0x3000) as *const PioRegisters) };
513const PIO1_BASE: StaticRef<PioRegisters> =
514 unsafe { StaticRef::new(PIO_1_BASE_ADDRESS as *const PioRegisters) };
515const PIO1_XOR_BASE: StaticRef<PioRegisters> =
516 unsafe { StaticRef::new((PIO_1_BASE_ADDRESS + 0x1000) as *const PioRegisters) };
517const PIO1_SET_BASE: StaticRef<PioRegisters> =
518 unsafe { StaticRef::new((PIO_1_BASE_ADDRESS + 0x2000) as *const PioRegisters) };
519const PIO1_CLEAR_BASE: StaticRef<PioRegisters> =
520 unsafe { StaticRef::new((PIO_1_BASE_ADDRESS + 0x3000) as *const PioRegisters) };
521
522pub struct RelocatedProgram<'a, I>
527where
528 I: Iterator<Item = &'a u16>,
529{
530 iter: I,
531 origin: usize,
532}
533
534impl<'a, I> RelocatedProgram<'a, I>
535where
536 I: Iterator<Item = &'a u16>,
537{
538 fn new(iter: I, origin: usize) -> Self {
539 Self { iter, origin }
540 }
541}
542
543impl<'a, I> Iterator for RelocatedProgram<'a, I>
544where
545 I: Iterator<Item = &'a u16>,
546{
547 type Item = u16;
548
549 fn next(&mut self) -> Option<Self::Item> {
550 self.iter.next().map(|&instr| {
551 if instr & 0b1110_0000_0000_0000 == 0 {
552 let address = instr & 0b1_1111;
554 let address = address.wrapping_add(self.origin as u16) % 32;
555 instr & (!0b11111) | address
556 } else {
557 instr
558 }
559 })
560 }
561}
562
563pub struct LoadedProgram {
564 used_memory: u32,
565 origin: usize,
566}
567
568#[derive(Clone, Copy, PartialEq, Eq, Debug)]
569pub enum ProgramError {
570 InsufficientSpace,
572 AddrInUse(usize),
574}
575
576#[derive(Clone, Copy, PartialEq, Debug)]
578pub enum SMNumber {
579 SM0 = 0,
580 SM1 = 1,
581 SM2 = 2,
582 SM3 = 3,
583}
584
585const SM_NUMBERS: [SMNumber; 4] = [SMNumber::SM0, SMNumber::SM1, SMNumber::SM2, SMNumber::SM3];
587
588#[derive(PartialEq)]
590pub enum PIONumber {
591 PIO0 = 0,
592 PIO1 = 1,
593}
594
595#[derive(PartialEq)]
597pub enum PioFifoJoin {
598 PioFifoJoinNone = 0,
599 PioFifoJoinTx = 1,
600 PioFifoJoinRx = 2,
601}
602
603#[derive(PartialEq)]
605pub enum InterruptSources {
606 Interrupt0 = 0,
607 Interrupt1 = 1,
608 Interrupt2 = 2,
609 Interrupt3 = 3,
610 Sm0TXNotFull = 4,
611 Sm1TXNotFull = 5,
612 Sm2TXNotFull = 6,
613 Sm3TXNotFull = 7,
614 Sm0RXNotEmpty = 8,
615 Sm1RXNotEmpty = 9,
616 Sm2RXNotEmpty = 10,
617 Sm3RXNotEmpty = 11,
618}
619
620pub trait PioTxClient {
621 fn on_buffer_space_available(&self);
622}
623
624pub trait PioRxClient {
625 fn on_data_received(&self, data: u32);
626}
627
628#[derive(Clone, Copy, Debug, Default)]
629enum StateMachineState {
630 #[default]
631 Ready,
632 Waiting,
633}
634
635pub struct StateMachine {
636 sm_number: SMNumber,
637 registers: StaticRef<PioRegisters>,
638 xor_registers: StaticRef<PioRegisters>,
639 set_registers: StaticRef<PioRegisters>,
640 tx_state: Cell<StateMachineState>,
641 tx_client: OptionalCell<&'static dyn PioTxClient>,
642 rx_state: Cell<StateMachineState>,
643 rx_client: OptionalCell<&'static dyn PioRxClient>,
644}
645
646impl StateMachine {
647 fn new(
648 sm_id: SMNumber,
649 registers: StaticRef<PioRegisters>,
650 xor_registers: StaticRef<PioRegisters>,
651 set_registers: StaticRef<PioRegisters>,
652 ) -> StateMachine {
653 StateMachine {
654 sm_number: sm_id,
655 registers,
656 xor_registers,
657 set_registers,
658 tx_state: Cell::new(StateMachineState::Ready),
659 tx_client: OptionalCell::empty(),
660 rx_state: Cell::new(StateMachineState::Ready),
661 rx_client: OptionalCell::empty(),
662 }
663 }
664
665 pub fn config(&self, config: &StateMachineConfiguration) {
667 self.set_in_pins(config.in_pins_base);
668 self.set_out_pins(config.out_pins_base, config.out_pins_count);
669 self.set_set_pins(config.set_pins_base, config.set_pins_count);
670 self.set_side_set_pins(
671 config.side_set_base,
672 config.side_set_bit_count,
673 config.side_set_opt_enable,
674 config.side_set_pindirs,
675 );
676 self.set_in_shift(
677 config.in_shift_direction_right,
678 config.in_autopush,
679 config.in_push_threshold,
680 );
681 self.set_out_shift(
682 config.out_shift_direction_right,
683 config.out_autopull,
684 config.out_pull_threshold,
685 );
686 self.set_jmp_pin(config.jmp_pin);
687 self.set_wrap(config.wrap_to, config.wrap);
688 self.set_mov_status(config.mov_status_sel, config.mov_status_n);
689 self.set_out_special(
690 config.out_special_sticky,
691 config.out_special_has_enable_pin,
692 config.out_special_enable_pin_index,
693 );
694 self.set_clkdiv_int_frac(config.div_int, config.div_frac);
695 }
696
697 pub fn set_tx_client(&self, client: &'static dyn PioTxClient) {
699 self.tx_client.set(client);
700 }
701
702 pub fn set_rx_client(&self, client: &'static dyn PioRxClient) {
704 self.rx_client.set(client);
705 }
706
707 pub fn set_in_pins(&self, in_base: u32) {
711 self.registers.sm[self.sm_number as usize]
712 .pinctrl
713 .modify(SMx_PINCTRL::IN_BASE.val(in_base));
714 }
715
716 pub fn set_set_pins(&self, set_base: u32, set_count: u32) {
721 self.registers.sm[self.sm_number as usize]
722 .pinctrl
723 .modify(SMx_PINCTRL::SET_BASE.val(set_base));
724 self.registers.sm[self.sm_number as usize]
725 .pinctrl
726 .modify(SMx_PINCTRL::SET_COUNT.val(set_count));
727 }
728
729 pub fn set_out_pins(&self, out_base: u32, out_count: u32) {
734 self.registers.sm[self.sm_number as usize]
735 .pinctrl
736 .modify(SMx_PINCTRL::OUT_BASE.val(out_base));
737 self.registers.sm[self.sm_number as usize]
738 .pinctrl
739 .modify(SMx_PINCTRL::OUT_COUNT.val(out_count));
740 }
741
742 pub fn set_in_shift(&self, shift_right: bool, autopush: bool, push_threshold: u32) {
748 self.registers.sm[self.sm_number as usize]
749 .shiftctrl
750 .modify(SMx_SHIFTCTRL::IN_SHIFTDIR.val(shift_right.into()));
751 self.registers.sm[self.sm_number as usize]
752 .shiftctrl
753 .modify(SMx_SHIFTCTRL::AUTOPUSH.val(autopush.into()));
754 self.registers.sm[self.sm_number as usize]
755 .shiftctrl
756 .modify(SMx_SHIFTCTRL::PUSH_THRESH.val(push_threshold));
757 }
758
759 pub fn set_out_shift(&self, shift_right: bool, autopull: bool, pull_threshold: u32) {
765 self.registers.sm[self.sm_number as usize]
766 .shiftctrl
767 .modify(SMx_SHIFTCTRL::OUT_SHIFTDIR.val(shift_right.into()));
768 self.registers.sm[self.sm_number as usize]
769 .shiftctrl
770 .modify(SMx_SHIFTCTRL::AUTOPULL.val(autopull.into()));
771 self.registers.sm[self.sm_number as usize]
772 .shiftctrl
773 .modify(SMx_SHIFTCTRL::PULL_THRESH.val(pull_threshold));
774 }
775
776 pub fn set_out_special(&self, sticky: bool, has_enable_pin: bool, enable_pin_index: u32) {
786 self.registers.sm[self.sm_number as usize]
787 .execctrl
788 .modify(SMx_EXECCTRL::OUT_STICKY.val(sticky as u32));
789 self.registers.sm[self.sm_number as usize]
790 .execctrl
791 .modify(SMx_EXECCTRL::INLINE_OUT_EN.val(has_enable_pin as u32));
792 self.registers.sm[self.sm_number as usize]
793 .execctrl
794 .modify(SMx_EXECCTRL::OUT_EN_SEL.val(enable_pin_index));
795 }
796
797 pub fn set_jmp_pin(&self, pin: u32) {
801 self.registers.sm[self.sm_number as usize]
802 .execctrl
803 .modify(SMx_EXECCTRL::JMP_PIN.val(pin));
804 }
805
806 pub fn set_clkdiv_int_frac(&self, div_int: u32, div_frac: u32) {
811 self.registers.sm[self.sm_number as usize]
812 .clkdiv
813 .modify(SMx_CLKDIV::INT.val(div_int));
814 self.registers.sm[self.sm_number as usize]
815 .clkdiv
816 .modify(SMx_CLKDIV::FRAC.val(div_frac));
817 }
818
819 pub fn set_fifo_join(&self, fifo_join: PioFifoJoin) {
823 if fifo_join == PioFifoJoin::PioFifoJoinRx {
824 self.registers.sm[self.sm_number as usize]
825 .shiftctrl
826 .modify(SMx_SHIFTCTRL::FJOIN_RX.val(fifo_join as u32));
827 } else if fifo_join == PioFifoJoin::PioFifoJoinTx {
828 self.registers.sm[self.sm_number as usize]
829 .shiftctrl
830 .modify(SMx_SHIFTCTRL::FJOIN_TX.val(fifo_join as u32));
831 }
832 }
833
834 pub fn set_side_set_pins(
845 &self,
846 sideset_base: u32,
847 bit_count: u32,
848 optional: bool,
849 pindirs: bool,
850 ) {
851 self.registers.sm[self.sm_number as usize]
852 .pinctrl
853 .modify(SMx_PINCTRL::SIDESET_BASE.val(sideset_base));
854 self.registers.sm[self.sm_number as usize]
855 .pinctrl
856 .modify(SMx_PINCTRL::SIDESET_COUNT.val(bit_count));
857 self.registers.sm[self.sm_number as usize]
858 .execctrl
859 .modify(SMx_EXECCTRL::SIDE_EN.val(optional as u32));
860 self.registers.sm[self.sm_number as usize]
861 .execctrl
862 .modify(SMx_EXECCTRL::SIDE_PINDIR.val(pindirs as u32));
863 }
864
865 pub fn set_pins_dirs(&self, mut pin: u32, mut count: u32, is_out: bool) {
874 let set_pindirs_0: u16 = 0b1110000010000000;
876 self.with_paused(|| {
877 let mut pindir_val: u8 = 0x00;
878 if is_out {
879 pindir_val = 0x1f;
880 }
881 while count > 5 {
882 self.registers.sm[self.sm_number as usize]
883 .pinctrl
884 .modify(SMx_PINCTRL::SET_COUNT.val(5));
885 self.registers.sm[self.sm_number as usize]
886 .pinctrl
887 .modify(SMx_PINCTRL::SET_BASE.val(pin));
888 self.exec((set_pindirs_0) | (pindir_val as u16));
889 count -= 5;
890 pin = (pin + 5) & 0x1f;
891 }
892 self.registers.sm[self.sm_number as usize]
893 .pinctrl
894 .modify(SMx_PINCTRL::SET_COUNT.val(count));
895 self.registers.sm[self.sm_number as usize]
896 .pinctrl
897 .modify(SMx_PINCTRL::SET_BASE.val(pin));
898 self.exec((set_pindirs_0) | (pindir_val as u16));
899 });
900 }
901
902 pub fn set_pins(&self, pins: &[&RPGpioPin<'_>], high: bool) {
908 self.with_paused(|| {
909 for pin in pins {
910 self.registers.sm[self.sm_number as usize]
911 .pinctrl
912 .modify(SMx_PINCTRL::SET_BASE.val(pin.pin() as u32));
913 self.registers.sm[self.sm_number as usize]
914 .pinctrl
915 .modify(SMx_PINCTRL::SET_COUNT.val(1));
916
917 self.exec(0b11100_000_000_00000 | high as u16);
918 }
919 });
920 }
921
922 pub fn set_wrap(&self, wrap_target: u32, wrap: u32) {
927 self.registers.sm[self.sm_number as usize]
928 .execctrl
929 .modify(SMx_EXECCTRL::WRAP_BOTTOM.val(wrap_target));
930 self.registers.sm[self.sm_number as usize]
931 .execctrl
932 .modify(SMx_EXECCTRL::WRAP_TOP.val(wrap));
933 }
934
935 pub fn init(&self) {
937 self.clear_fifos();
938 self.restart();
939 self.clkdiv_restart();
940 self.registers.sm[self.sm_number as usize]
941 .instr
942 .modify(SMx_INSTR::INSTR.val(0));
943 }
944
945 pub fn restart(&self) {
947 match self.sm_number {
948 SMNumber::SM0 => self.set_registers.ctrl.modify(CTRL::SM0_RESTART::SET),
949 SMNumber::SM1 => self.set_registers.ctrl.modify(CTRL::SM1_RESTART::SET),
950 SMNumber::SM2 => self.set_registers.ctrl.modify(CTRL::SM2_RESTART::SET),
951 SMNumber::SM3 => self.set_registers.ctrl.modify(CTRL::SM3_RESTART::SET),
952 }
953 }
954
955 pub fn clear_fifos(&self) {
957 self.xor_registers.sm[self.sm_number as usize]
958 .shiftctrl
959 .modify(SMx_SHIFTCTRL::FJOIN_RX::SET);
960 self.xor_registers.sm[self.sm_number as usize]
961 .shiftctrl
962 .modify(SMx_SHIFTCTRL::FJOIN_RX::SET);
963 }
964
965 pub fn clkdiv_restart(&self) {
967 match self.sm_number {
968 SMNumber::SM0 => self.set_registers.ctrl.modify(CTRL::CLKDIV0_RESTART::SET),
969 SMNumber::SM1 => self.set_registers.ctrl.modify(CTRL::CLKDIV1_RESTART::SET),
970 SMNumber::SM2 => self.set_registers.ctrl.modify(CTRL::CLKDIV2_RESTART::SET),
971 SMNumber::SM3 => self.set_registers.ctrl.modify(CTRL::CLKDIV3_RESTART::SET),
972 }
973 }
974
975 pub fn tx_full(&self) -> bool {
977 let field = match self.sm_number {
978 SMNumber::SM0 => FSTAT::TXFULL0,
979 SMNumber::SM1 => FSTAT::TXFULL1,
980 SMNumber::SM2 => FSTAT::TXFULL2,
981 SMNumber::SM3 => FSTAT::TXFULL3,
982 };
983 self.registers.fstat.read(field) != 0
984 }
985
986 pub fn rx_empty(&self) -> bool {
988 let field = match self.sm_number {
989 SMNumber::SM0 => FSTAT::RXEMPTY0,
990 SMNumber::SM1 => FSTAT::RXEMPTY1,
991 SMNumber::SM2 => FSTAT::RXEMPTY2,
992 SMNumber::SM3 => FSTAT::RXEMPTY3,
993 };
994 self.registers.fstat.read(field) != 0
995 }
996
997 pub fn exec(&self, instr: u16) {
1002 self.registers.sm[self.sm_number as usize]
1003 .instr
1004 .modify(SMx_INSTR::INSTR.val(instr as u32));
1005 }
1006
1007 pub fn exec_program(&self, program: LoadedProgram, wrap: bool) {
1013 if wrap {
1014 self.set_wrap(
1015 program.origin as u32,
1016 program.origin as u32 + program.used_memory.count_ones(),
1017 );
1018 }
1019 self.exec((program.origin as u16) & 0x1fu16)
1020 }
1021
1022 pub fn set_mov_status(&self, status_sel: PioMovStatusType, status_n: u32) {
1027 self.registers.sm[self.sm_number as usize]
1028 .execctrl
1029 .modify(SMx_EXECCTRL::STATUS_SEL.val(status_sel as u32));
1030 self.registers.sm[self.sm_number as usize]
1031 .execctrl
1032 .modify(SMx_EXECCTRL::STATUS_N.val(status_n));
1033 }
1034
1035 pub fn set_enabled(&self, enabled: bool) {
1039 match self.sm_number {
1040 SMNumber::SM0 => self.registers.ctrl.modify(match enabled {
1041 true => CTRL::SM0_ENABLE::SET,
1042 false => CTRL::SM0_ENABLE::CLEAR,
1043 }),
1044 SMNumber::SM1 => self.registers.ctrl.modify(match enabled {
1045 true => CTRL::SM1_ENABLE::SET,
1046 false => CTRL::SM1_ENABLE::CLEAR,
1047 }),
1048 SMNumber::SM2 => self.registers.ctrl.modify(match enabled {
1049 true => CTRL::SM2_ENABLE::SET,
1050 false => CTRL::SM2_ENABLE::CLEAR,
1051 }),
1052 SMNumber::SM3 => self.registers.ctrl.modify(match enabled {
1053 true => CTRL::SM3_ENABLE::SET,
1054 false => CTRL::SM3_ENABLE::CLEAR,
1055 }),
1056 }
1057 }
1058
1059 pub fn is_enabled(&self) -> bool {
1061 let field = match self.sm_number {
1062 SMNumber::SM0 => CTRL::SM0_ENABLE,
1063 SMNumber::SM1 => CTRL::SM1_ENABLE,
1064 SMNumber::SM2 => CTRL::SM2_ENABLE,
1065 SMNumber::SM3 => CTRL::SM3_ENABLE,
1066 };
1067 self.registers.ctrl.read(field) != 0
1068 }
1069
1070 fn with_paused(&self, f: impl FnOnce()) {
1073 let enabled = self.is_enabled();
1074 self.set_enabled(false);
1075
1076 let pio_sm = &self.registers.sm[self.sm_number as usize];
1077
1078 let pinctrl = pio_sm.pinctrl.get();
1079 let execctrl = pio_sm.execctrl.get();
1080 pio_sm.execctrl.modify(SMx_EXECCTRL::OUT_STICKY::CLEAR);
1082
1083 f();
1084
1085 pio_sm.pinctrl.set(pinctrl);
1086 pio_sm.execctrl.set(execctrl);
1087 self.set_enabled(enabled);
1088 }
1089
1090 pub fn push(&self, data: u32) -> Result<(), ErrorCode> {
1095 match self.tx_state.get() {
1096 StateMachineState::Ready => {
1097 if self.tx_full() {
1098 let field = match self.sm_number {
1100 SMNumber::SM0 => IRQ0_INTE::SM0_TXNFULL::SET,
1101 SMNumber::SM1 => IRQ0_INTE::SM1_TXNFULL::SET,
1102 SMNumber::SM2 => IRQ0_INTE::SM2_TXNFULL::SET,
1103 SMNumber::SM3 => IRQ0_INTE::SM3_TXNFULL::SET,
1104 };
1105 self.registers.irq0_inte.modify(field);
1106 self.tx_state.set(StateMachineState::Waiting);
1107 Err(ErrorCode::BUSY)
1108 } else {
1109 self.registers.txf[self.sm_number as usize].set(data);
1110 Ok(())
1111 }
1112 }
1113 StateMachineState::Waiting => Err(ErrorCode::BUSY),
1114 }
1115 }
1116
1117 pub fn push_blocking(&self, data: u32) -> Result<(), ErrorCode> {
1123 if self.tx_full() && !self.is_enabled() {
1124 return Err(ErrorCode::OFF);
1125 }
1126 while self.tx_full() {}
1127 self.registers.txf[self.sm_number as usize].set(data);
1128 Ok(())
1129 }
1130
1131 pub fn pull(&self) -> Result<u32, ErrorCode> {
1134 match self.rx_state.get() {
1135 StateMachineState::Ready => {
1136 if self.rx_empty() {
1137 let field = match self.sm_number {
1139 SMNumber::SM0 => IRQ0_INTE::SM0_RXNEMPTY::SET,
1140 SMNumber::SM1 => IRQ0_INTE::SM1_RXNEMPTY::SET,
1141 SMNumber::SM2 => IRQ0_INTE::SM2_RXNEMPTY::SET,
1142 SMNumber::SM3 => IRQ0_INTE::SM3_RXNEMPTY::SET,
1143 };
1144 self.registers.irq0_inte.modify(field);
1145 self.rx_state.set(StateMachineState::Waiting);
1146 Err(ErrorCode::BUSY)
1147 } else {
1148 Ok(self.registers.rxf[self.sm_number as usize].read(RXFx::RXF))
1149 }
1150 }
1151 StateMachineState::Waiting => Err(ErrorCode::BUSY),
1152 }
1153 }
1154
1155 pub fn pull_blocking(&self) -> Result<u32, ErrorCode> {
1159 if self.tx_full() && !self.is_enabled() {
1160 return Err(ErrorCode::OFF);
1161 }
1162 while self.rx_empty() {}
1163 Ok(self.registers.rxf[self.sm_number as usize].read(RXFx::RXF))
1164 }
1165
1166 fn handle_tx_interrupt(&self) {
1168 match self.tx_state.get() {
1169 StateMachineState::Waiting => {
1170 let field = match self.sm_number {
1172 SMNumber::SM0 => IRQ0_INTE::SM0_TXNFULL::CLEAR,
1173 SMNumber::SM1 => IRQ0_INTE::SM1_TXNFULL::CLEAR,
1174 SMNumber::SM2 => IRQ0_INTE::SM2_TXNFULL::CLEAR,
1175 SMNumber::SM3 => IRQ0_INTE::SM3_TXNFULL::CLEAR,
1176 };
1177 self.registers.irq0_inte.modify(field);
1178 self.tx_state.set(StateMachineState::Ready);
1179 self.tx_client.map(|client| {
1180 client.on_buffer_space_available();
1181 });
1182 }
1183 StateMachineState::Ready => {}
1184 }
1185 }
1186
1187 fn handle_rx_interrupt(&self) {
1189 match self.rx_state.get() {
1190 StateMachineState::Waiting => {
1191 let field = match self.sm_number {
1193 SMNumber::SM0 => IRQ0_INTE::SM0_RXNEMPTY::CLEAR,
1194 SMNumber::SM1 => IRQ0_INTE::SM1_RXNEMPTY::CLEAR,
1195 SMNumber::SM2 => IRQ0_INTE::SM2_RXNEMPTY::CLEAR,
1196 SMNumber::SM3 => IRQ0_INTE::SM3_RXNEMPTY::CLEAR,
1197 };
1198 self.registers.irq0_inte.modify(field);
1199 self.rx_state.set(StateMachineState::Ready);
1200 self.rx_client.map(|client| {
1201 client.on_data_received(
1202 self.registers.rxf[self.sm_number as usize].read(RXFx::RXF),
1203 );
1204 });
1205 }
1206 StateMachineState::Ready => {}
1207 }
1208 }
1209}
1210
1211pub struct Pio {
1212 registers: StaticRef<PioRegisters>,
1213 pio_number: PIONumber,
1214 sms: [StateMachine; NUMBER_STATE_MACHINES],
1215 instructions_used: Cell<u32>,
1216 _clear_registers: StaticRef<PioRegisters>,
1217}
1218
1219#[derive(Clone, Copy)]
1221pub enum PioMovStatusType {
1222 StatusTxLessthan = 0,
1223 StatusRxLessthan = 1,
1224}
1225
1226pub struct StateMachineConfiguration {
1230 pub out_pins_count: u32,
1231 pub out_pins_base: u32,
1232 pub set_pins_count: u32,
1233 pub set_pins_base: u32,
1234 pub in_pins_base: u32,
1235 pub side_set_base: u32,
1236 pub side_set_opt_enable: bool,
1237 pub side_set_bit_count: u32,
1238 pub side_set_pindirs: bool,
1239 pub wrap: u32,
1240 pub wrap_to: u32,
1241 pub in_shift_direction_right: bool,
1242 pub in_autopush: bool,
1243 pub in_push_threshold: u32,
1244 pub out_shift_direction_right: bool,
1245 pub out_autopull: bool,
1246 pub out_pull_threshold: u32,
1247 pub jmp_pin: u32,
1248 pub out_special_sticky: bool,
1249 pub out_special_has_enable_pin: bool,
1250 pub out_special_enable_pin_index: u32,
1251 pub mov_status_sel: PioMovStatusType,
1252 pub mov_status_n: u32,
1253 pub div_int: u32,
1254 pub div_frac: u32,
1255}
1256
1257impl Default for StateMachineConfiguration {
1258 fn default() -> Self {
1259 StateMachineConfiguration {
1260 out_pins_count: 32,
1261 out_pins_base: 0,
1262 set_pins_count: 0,
1263 set_pins_base: 0,
1264 in_pins_base: 0,
1265 side_set_base: 0,
1266 side_set_opt_enable: false,
1267 side_set_bit_count: 0,
1268 side_set_pindirs: false,
1269 wrap: 31,
1270 wrap_to: 0,
1271 in_shift_direction_right: true,
1272 in_autopush: false,
1273 in_push_threshold: 32,
1274 out_shift_direction_right: true,
1275 out_autopull: false,
1276 out_pull_threshold: 32,
1277 jmp_pin: 0,
1278 out_special_sticky: false,
1279 out_special_has_enable_pin: false,
1280 out_special_enable_pin_index: 0,
1281 mov_status_sel: PioMovStatusType::StatusTxLessthan,
1282 mov_status_n: 0,
1283 div_int: 0,
1284 div_frac: 0,
1285 }
1286 }
1287}
1288
1289impl Pio {
1290 pub fn gpio_init(&self, pin: &RPGpioPin) {
1292 if self.pio_number == PIONumber::PIO1 {
1293 pin.set_function(GpioFunction::PIO1)
1294 } else {
1295 pin.set_function(GpioFunction::PIO0)
1296 }
1297 }
1298
1299 pub fn new_pio0() -> Self {
1301 Self {
1302 registers: PIO0_BASE,
1303 _clear_registers: PIO0_CLEAR_BASE,
1304 pio_number: PIONumber::PIO0,
1305 sms: SM_NUMBERS.map(|x| StateMachine::new(x, PIO0_BASE, PIO0_XOR_BASE, PIO0_SET_BASE)),
1306 instructions_used: Cell::new(0),
1307 }
1308 }
1309
1310 pub fn new_pio1() -> Self {
1312 Self {
1313 registers: PIO1_BASE,
1314 _clear_registers: PIO1_CLEAR_BASE,
1315 pio_number: PIONumber::PIO1,
1316 sms: SM_NUMBERS.map(|x| StateMachine::new(x, PIO1_BASE, PIO1_XOR_BASE, PIO1_SET_BASE)),
1317 instructions_used: Cell::new(0),
1318 }
1319 }
1320
1321 pub fn sm(&self, sm_number: SMNumber) -> &StateMachine {
1323 &self.sms[sm_number as usize]
1324 }
1325
1326 pub fn set_irq_source(
1328 &self,
1329 irq_index: u32,
1330 interrupt_source: InterruptSources,
1331 enabled: bool,
1332 ) {
1333 if irq_index == 0 {
1334 match interrupt_source {
1335 InterruptSources::Interrupt0 => self
1336 .registers
1337 .irq0_inte
1338 .modify(IRQ0_INTE::SM0.val(enabled as u32)),
1339 InterruptSources::Interrupt1 => self
1340 .registers
1341 .irq0_inte
1342 .modify(IRQ0_INTE::SM1.val(enabled as u32)),
1343 InterruptSources::Interrupt2 => self
1344 .registers
1345 .irq0_inte
1346 .modify(IRQ0_INTE::SM2.val(enabled as u32)),
1347 InterruptSources::Interrupt3 => self
1348 .registers
1349 .irq0_inte
1350 .modify(IRQ0_INTE::SM3.val(enabled as u32)),
1351 InterruptSources::Sm0TXNotFull => self
1352 .registers
1353 .irq0_inte
1354 .modify(IRQ0_INTE::SM0_TXNFULL.val(enabled as u32)),
1355 InterruptSources::Sm1TXNotFull => self
1356 .registers
1357 .irq0_inte
1358 .modify(IRQ0_INTE::SM1_TXNFULL.val(enabled as u32)),
1359 InterruptSources::Sm2TXNotFull => self
1360 .registers
1361 .irq0_inte
1362 .modify(IRQ0_INTE::SM2_TXNFULL.val(enabled as u32)),
1363 InterruptSources::Sm3TXNotFull => self
1364 .registers
1365 .irq0_inte
1366 .modify(IRQ0_INTE::SM3_TXNFULL.val(enabled as u32)),
1367 InterruptSources::Sm0RXNotEmpty => self
1368 .registers
1369 .irq0_inte
1370 .modify(IRQ0_INTE::SM0_RXNEMPTY.val(enabled as u32)),
1371 InterruptSources::Sm1RXNotEmpty => self
1372 .registers
1373 .irq0_inte
1374 .modify(IRQ0_INTE::SM1_RXNEMPTY.val(enabled as u32)),
1375 InterruptSources::Sm2RXNotEmpty => self
1376 .registers
1377 .irq0_inte
1378 .modify(IRQ0_INTE::SM2_RXNEMPTY.val(enabled as u32)),
1379 InterruptSources::Sm3RXNotEmpty => self
1380 .registers
1381 .irq0_inte
1382 .modify(IRQ0_INTE::SM3_RXNEMPTY.val(enabled as u32)),
1383 }
1384 } else if irq_index == 1 {
1385 match interrupt_source {
1386 InterruptSources::Interrupt0 => self
1387 .registers
1388 .irq1_inte
1389 .modify(IRQ1_INTE::SM0.val(enabled as u32)),
1390 InterruptSources::Interrupt1 => self
1391 .registers
1392 .irq1_inte
1393 .modify(IRQ1_INTE::SM1.val(enabled as u32)),
1394 InterruptSources::Interrupt2 => self
1395 .registers
1396 .irq1_inte
1397 .modify(IRQ1_INTE::SM2.val(enabled as u32)),
1398 InterruptSources::Interrupt3 => self
1399 .registers
1400 .irq1_inte
1401 .modify(IRQ1_INTE::SM3.val(enabled as u32)),
1402 InterruptSources::Sm0TXNotFull => self
1403 .registers
1404 .irq1_inte
1405 .modify(IRQ1_INTE::SM0_TXNFULL.val(enabled as u32)),
1406 InterruptSources::Sm1TXNotFull => self
1407 .registers
1408 .irq1_inte
1409 .modify(IRQ1_INTE::SM1_TXNFULL.val(enabled as u32)),
1410 InterruptSources::Sm2TXNotFull => self
1411 .registers
1412 .irq1_inte
1413 .modify(IRQ1_INTE::SM2_TXNFULL.val(enabled as u32)),
1414 InterruptSources::Sm3TXNotFull => self
1415 .registers
1416 .irq1_inte
1417 .modify(IRQ1_INTE::SM3_TXNFULL.val(enabled as u32)),
1418 InterruptSources::Sm0RXNotEmpty => self
1419 .registers
1420 .irq1_inte
1421 .modify(IRQ1_INTE::SM0_RXNEMPTY.val(enabled as u32)),
1422 InterruptSources::Sm1RXNotEmpty => self
1423 .registers
1424 .irq1_inte
1425 .modify(IRQ1_INTE::SM1_RXNEMPTY.val(enabled as u32)),
1426 InterruptSources::Sm2RXNotEmpty => self
1427 .registers
1428 .irq1_inte
1429 .modify(IRQ1_INTE::SM2_RXNEMPTY.val(enabled as u32)),
1430 InterruptSources::Sm3RXNotEmpty => self
1431 .registers
1432 .irq1_inte
1433 .modify(IRQ1_INTE::SM3_RXNEMPTY.val(enabled as u32)),
1434 }
1435 } else {
1436 debug!("IRQ Index invalid - must be 0 or 1");
1437 }
1438 }
1439
1440 pub fn interrupt_get(&self, irq_num: u32) -> bool {
1442 let mut temp = 0;
1443 match irq_num {
1444 0 => temp = self.registers.irq.read(IRQ::IRQ0),
1445 1 => temp = self.registers.irq.read(IRQ::IRQ1),
1446 2 => temp = self.registers.irq.read(IRQ::IRQ2),
1447 3 => temp = self.registers.irq.read(IRQ::IRQ3),
1448 4 => temp = self.registers.irq.read(IRQ::IRQ4),
1449 5 => temp = self.registers.irq.read(IRQ::IRQ5),
1450 6 => temp = self.registers.irq.read(IRQ::IRQ6),
1451 7 => temp = self.registers.irq.read(IRQ::IRQ7),
1452 _ => debug!("IRQ Number invalid - must be from 0 to 7"),
1453 }
1454 temp != 0
1455 }
1456
1457 pub fn interrupt_clear(&self, irq_num: u32) {
1459 match irq_num {
1460 0 => self.registers.irq.modify(IRQ::IRQ0.val(1)),
1461 1 => self.registers.irq.modify(IRQ::IRQ1.val(1)),
1462 2 => self.registers.irq.modify(IRQ::IRQ2.val(1)),
1463 3 => self.registers.irq.modify(IRQ::IRQ3.val(1)),
1464 4 => self.registers.irq.modify(IRQ::IRQ4.val(1)),
1465 5 => self.registers.irq.modify(IRQ::IRQ5.val(1)),
1466 6 => self.registers.irq.modify(IRQ::IRQ6.val(1)),
1467 7 => self.registers.irq.modify(IRQ::IRQ7.val(1)),
1468 _ => debug!("IRQ Number invalid - must be from 0 to 7"),
1469 }
1470 }
1471
1472 pub fn handle_interrupt(&self) {
1474 let ints = &self.registers.irq0_ints;
1475 for (sm, irq) in self.sms.iter().zip([
1476 IRQ0_INTS::SM0_TXNFULL,
1477 IRQ0_INTS::SM1_TXNFULL,
1478 IRQ0_INTS::SM2_TXNFULL,
1479 IRQ0_INTS::SM3_TXNFULL,
1480 ]) {
1481 if ints.is_set(irq) {
1482 sm.handle_tx_interrupt();
1483 }
1484 }
1485 for (sm, irq) in self.sms.iter().zip([
1486 IRQ0_INTS::SM0_RXNEMPTY,
1487 IRQ0_INTS::SM1_RXNEMPTY,
1488 IRQ0_INTS::SM2_RXNEMPTY,
1489 IRQ0_INTS::SM3_RXNEMPTY,
1490 ]) {
1491 if ints.is_set(irq) {
1492 sm.handle_rx_interrupt();
1493 }
1494 }
1495 }
1496
1497 pub fn add_program(
1503 &self,
1504 origin: Option<usize>,
1505 program: &[u8],
1506 ) -> Result<LoadedProgram, ProgramError> {
1507 let mut program_u16: [u16; NUMBER_INSTR_MEMORY_LOCATIONS / 2] =
1508 [0; NUMBER_INSTR_MEMORY_LOCATIONS / 2];
1509 for (i, chunk) in program.chunks(2).enumerate() {
1510 program_u16[i] = ((chunk[0] as u16) << 8) | (chunk[1] as u16);
1511 }
1512
1513 self.add_program16(origin, &program_u16[0..program.len() / 2])
1514 }
1515
1516 pub fn add_program16(
1522 &self,
1523 origin: Option<usize>,
1524 program: &[u16],
1525 ) -> Result<LoadedProgram, ProgramError> {
1526 match origin {
1528 Some(origin) => {
1529 assert!(origin < NUMBER_INSTR_MEMORY_LOCATIONS);
1530 self.try_load_program_at(origin, program)
1531 .map_err(|_| ProgramError::AddrInUse(origin))
1532 }
1533 None => {
1534 for origin in 0..NUMBER_INSTR_MEMORY_LOCATIONS {
1535 if let res @ Ok(_) = self.try_load_program_at(origin, program) {
1536 return res;
1537 }
1538 }
1539 Err(ProgramError::InsufficientSpace)
1540 }
1541 }
1542 }
1543
1544 fn try_load_program_at(
1550 &self,
1551 origin: usize,
1552 program: &[u16],
1553 ) -> Result<LoadedProgram, ProgramError> {
1554 let program = RelocatedProgram::new(program.iter(), origin);
1556 let mut used_mask = 0;
1557 for (i, instr) in program.enumerate() {
1558 let addr = (i + origin) % 32;
1560 let mask = 1 << addr;
1561 if (self.instructions_used.get() | used_mask) & mask != 0 {
1562 return Err(ProgramError::AddrInUse(addr));
1563 }
1564 self.registers.instr_mem[addr]
1565 .instr_mem
1566 .modify(INSTR_MEMx::INSTR_MEM.val(instr as u32));
1567 used_mask |= mask;
1568 }
1569 self.instructions_used
1571 .set(self.instructions_used.get() | used_mask);
1572 Ok(LoadedProgram {
1573 used_memory: used_mask,
1574 origin,
1575 })
1576 }
1577
1578 pub fn clear_instr_registers(&self) {
1580 for i in 0..NUMBER_INSTR_MEMORY_LOCATIONS {
1581 self.registers.instr_mem[i]
1582 .instr_mem
1583 .modify(INSTR_MEMx::INSTR_MEM::CLEAR);
1584 }
1585 }
1586
1587 pub fn init(&self) {
1589 let default_config: StateMachineConfiguration = StateMachineConfiguration::default();
1590 for state_machine in self.sms.iter() {
1591 state_machine.config(&default_config);
1592 }
1593 self.clear_instr_registers()
1594 }
1595}
1596
1597mod examples {
1598 use super::{
1599 debug, Pio, RPGpio, RPGpioPin, Readable, SMNumber, SMx_EXECCTRL, SMx_INSTR, SMx_PINCTRL,
1600 StateMachineConfiguration, DBG_PADOUT, FDEBUG,
1601 };
1602
1603 impl RPGpio {
1604 fn from_u32(value: u32) -> RPGpio {
1605 match value {
1606 0 => RPGpio::GPIO0,
1607 1 => RPGpio::GPIO1,
1608 2 => RPGpio::GPIO2,
1609 3 => RPGpio::GPIO3,
1610 4 => RPGpio::GPIO4,
1611 5 => RPGpio::GPIO5,
1612 6 => RPGpio::GPIO6,
1613 7 => RPGpio::GPIO7,
1614 8 => RPGpio::GPIO8,
1615 9 => RPGpio::GPIO9,
1616 10 => RPGpio::GPIO10,
1617 11 => RPGpio::GPIO11,
1618 12 => RPGpio::GPIO12,
1619 13 => RPGpio::GPIO13,
1620 14 => RPGpio::GPIO14,
1621 15 => RPGpio::GPIO15,
1622 16 => RPGpio::GPIO16,
1623 17 => RPGpio::GPIO17,
1624 18 => RPGpio::GPIO18,
1625 19 => RPGpio::GPIO19,
1626 20 => RPGpio::GPIO20,
1627 21 => RPGpio::GPIO21,
1628 22 => RPGpio::GPIO22,
1629 23 => RPGpio::GPIO23,
1630 24 => RPGpio::GPIO24,
1631 25 => RPGpio::GPIO25,
1632 26 => RPGpio::GPIO26,
1633 27 => RPGpio::GPIO27,
1634 28 => RPGpio::GPIO28,
1635 29 => RPGpio::GPIO29,
1636 _ => panic!(
1637 "Unknown value for GPIO pin: {} (should be from 0 to 29)",
1638 value
1639 ),
1640 }
1641 }
1642 }
1643
1644 impl Pio {
1645 pub fn blinking_hello_program_init(
1649 &self,
1650 sm_number: SMNumber,
1651 pin: u32,
1652 config: &StateMachineConfiguration,
1653 ) {
1654 let sm = &self.sms[sm_number as usize];
1655 sm.config(config);
1656 self.gpio_init(&RPGpioPin::new(RPGpio::from_u32(pin)));
1657 sm.set_enabled(false);
1658 sm.set_pins_dirs(pin, 1, true);
1659 sm.set_set_pins(pin, 1);
1660 sm.init();
1661 sm.set_enabled(true);
1662 }
1663
1664 pub fn blink_program_init(
1665 &self,
1666 sm_number: SMNumber,
1667 pin: u32,
1668 config: &StateMachineConfiguration,
1669 ) {
1670 let sm = &self.sms[sm_number as usize];
1671 sm.config(config);
1672 self.gpio_init(&RPGpioPin::new(RPGpio::from_u32(pin)));
1673 sm.set_enabled(false);
1674 sm.set_pins_dirs(pin, 1, true);
1675 sm.set_set_pins(pin, 1);
1676 sm.init();
1677 sm.set_enabled(true);
1678 }
1679
1680 pub fn sideset_program_init(
1681 &self,
1682 sm_number: SMNumber,
1683 pin: u32,
1684 config: &StateMachineConfiguration,
1685 ) {
1686 let sm = &self.sms[sm_number as usize];
1687 sm.config(config);
1688 self.gpio_init(&RPGpioPin::new(RPGpio::from_u32(pin)));
1689 self.gpio_init(&RPGpioPin::new(RPGpio::GPIO7));
1690 sm.set_enabled(false);
1691 sm.set_pins_dirs(pin, 1, true);
1692 sm.set_pins_dirs(7, 1, true);
1693 sm.set_set_pins(pin, 1);
1694 sm.set_side_set_pins(7, 1, false, true);
1695 sm.init();
1696 sm.set_enabled(true);
1697 }
1698
1699 pub fn hello_program_init(
1700 &self,
1701 sm_number: SMNumber,
1702 pin1: u32,
1703 pin2: u32,
1704 config: &StateMachineConfiguration,
1705 ) {
1706 let sm = &self.sms[sm_number as usize];
1707 let turn_on_gpio_6_7 = 0b11000000;
1709 sm.config(config);
1710 self.gpio_init(&RPGpioPin::new(RPGpio::from_u32(pin1)));
1711 self.gpio_init(&RPGpioPin::new(RPGpio::from_u32(pin2)));
1712 sm.set_enabled(false);
1713 sm.set_pins_dirs(pin1, 1, true);
1714 sm.set_pins_dirs(pin2, 1, true);
1715 sm.init();
1716 sm.set_enabled(true);
1717 sm.push_blocking(turn_on_gpio_6_7).ok();
1718 sm.push_blocking(0).ok();
1719 }
1720
1721 pub fn pwm_program_init(
1722 &self,
1723 sm_number: SMNumber,
1724 pin: u32,
1725 pwm_period: u32,
1726 config: &StateMachineConfiguration,
1727 ) {
1728 let sm = &self.sms[sm_number as usize];
1729 let pull_command = 0x8080_u16;
1731 let out_isr_32_command = 0x60c0_u16;
1733 sm.config(config);
1734 self.gpio_init(&RPGpioPin::new(RPGpio::from_u32(pin)));
1735 sm.set_enabled(false);
1736 sm.set_pins_dirs(pin, 1, true);
1737 sm.set_side_set_pins(pin, 1, false, true);
1738 sm.init();
1739 sm.push_blocking(pwm_period).ok();
1740 sm.exec(pull_command);
1741 sm.exec(out_isr_32_command);
1742 sm.set_enabled(true);
1743 }
1744
1745 pub fn read_instr(&self, sm_number: SMNumber) -> u32 {
1748 self.registers.sm[sm_number as usize]
1749 .instr
1750 .read(SMx_INSTR::INSTR)
1751 }
1752
1753 pub fn read_sideset_reg(&self, sm_number: SMNumber) {
1754 debug!(
1755 "{}",
1756 self.registers.sm[sm_number as usize]
1757 .pinctrl
1758 .read(SMx_PINCTRL::SIDESET_COUNT)
1759 );
1760 debug!(
1761 "{}",
1762 self.registers.sm[sm_number as usize]
1763 .execctrl
1764 .read(SMx_EXECCTRL::SIDE_EN)
1765 );
1766 debug!(
1767 "{}",
1768 self.registers.sm[sm_number as usize]
1769 .execctrl
1770 .read(SMx_EXECCTRL::SIDE_PINDIR)
1771 );
1772 debug!(
1773 "{}",
1774 self.registers.sm[sm_number as usize]
1775 .pinctrl
1776 .read(SMx_PINCTRL::SIDESET_BASE)
1777 );
1778 }
1779
1780 pub fn read_dbg_padout(&self) -> u32 {
1781 self.registers.dbg_padout.read(DBG_PADOUT::DBG_PADOUT)
1782 }
1783
1784 pub fn read_fdebug(&self, tx: bool, stall: bool) -> u32 {
1785 if tx {
1786 if stall {
1787 self.registers.fdebug.read(FDEBUG::TXSTALL)
1788 } else {
1789 self.registers.fdebug.read(FDEBUG::TXOVER)
1790 }
1791 } else if stall {
1792 self.registers.fdebug.read(FDEBUG::RXSTALL)
1793 } else {
1794 self.registers.fdebug.read(FDEBUG::RXUNDER)
1795 }
1796 }
1797 }
1798}