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(11) NUMBITS(1) [],
447 SM2 OFFSET(10) NUMBITS(1) [],
448 SM1 OFFSET(9) NUMBITS(1) [],
449 SM0 OFFSET(8) NUMBITS(1) [],
450 SM3_TXNFULL OFFSET(7) NUMBITS(1) [],
451 SM2_TXNFULL OFFSET(6) NUMBITS(1) [],
452 SM1_TXNFULL OFFSET(5) NUMBITS(1) [],
453 SM0_TXNFULL OFFSET(4) NUMBITS(1) [],
454 SM3_RXNEMPTY OFFSET(3) NUMBITS(1) [],
455 SM2_RXNEMPTY OFFSET(2) NUMBITS(1) [],
456 SM1_RXNEMPTY OFFSET(1) 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
563#[derive(Clone, Copy)]
564pub struct LoadedProgram {
565 used_memory: u32,
566 origin: usize,
567}
568
569#[derive(Clone, Copy, PartialEq, Eq, Debug)]
570pub enum ProgramError {
571 InsufficientSpace,
573 AddrInUse(usize),
575}
576
577#[derive(Clone, Copy, PartialEq, Debug)]
579pub enum SMNumber {
580 SM0 = 0,
581 SM1 = 1,
582 SM2 = 2,
583 SM3 = 3,
584}
585
586const SM_NUMBERS: [SMNumber; 4] = [SMNumber::SM0, SMNumber::SM1, SMNumber::SM2, SMNumber::SM3];
588
589#[derive(Clone, Copy, PartialEq)]
591pub enum PIONumber {
592 PIO0 = 0,
593 PIO1 = 1,
594}
595
596#[derive(PartialEq)]
598pub enum PioFifoJoin {
599 PioFifoJoinNone = 0,
600 PioFifoJoinTx = 1,
601 PioFifoJoinRx = 2,
602}
603
604#[derive(PartialEq)]
606pub enum InterruptSources {
607 Interrupt0 = 0,
608 Interrupt1 = 1,
609 Interrupt2 = 2,
610 Interrupt3 = 3,
611 Sm0TXNotFull = 4,
612 Sm1TXNotFull = 5,
613 Sm2TXNotFull = 6,
614 Sm3TXNotFull = 7,
615 Sm0RXNotEmpty = 8,
616 Sm1RXNotEmpty = 9,
617 Sm2RXNotEmpty = 10,
618 Sm3RXNotEmpty = 11,
619}
620
621pub trait PioTxClient {
622 fn on_buffer_space_available(&self);
623}
624
625pub trait PioRxClient {
626 fn on_data_received(&self, data: u32);
627}
628
629#[derive(Clone, Copy, Debug, Default)]
630enum StateMachineState {
631 #[default]
632 Ready,
633 Waiting,
634}
635
636pub struct StateMachine {
637 sm_number: SMNumber,
638 registers: StaticRef<PioRegisters>,
639 xor_registers: StaticRef<PioRegisters>,
640 set_registers: StaticRef<PioRegisters>,
641 tx_state: Cell<StateMachineState>,
642 tx_client: OptionalCell<&'static dyn PioTxClient>,
643 rx_state: Cell<StateMachineState>,
644 rx_client: OptionalCell<&'static dyn PioRxClient>,
645}
646
647impl StateMachine {
648 fn new(
649 sm_id: SMNumber,
650 registers: StaticRef<PioRegisters>,
651 xor_registers: StaticRef<PioRegisters>,
652 set_registers: StaticRef<PioRegisters>,
653 ) -> StateMachine {
654 StateMachine {
655 sm_number: sm_id,
656 registers,
657 xor_registers,
658 set_registers,
659 tx_state: Cell::new(StateMachineState::Ready),
660 tx_client: OptionalCell::empty(),
661 rx_state: Cell::new(StateMachineState::Ready),
662 rx_client: OptionalCell::empty(),
663 }
664 }
665
666 pub fn config(&self, config: &StateMachineConfiguration) {
668 self.set_in_pins(config.in_pins_base);
669 self.set_out_pins(config.out_pins_base, config.out_pins_count);
670 self.set_set_pins(config.set_pins_base, config.set_pins_count);
671 self.set_side_set_pins(
672 config.side_set_base,
673 config.side_set_bit_count,
674 config.side_set_opt_enable,
675 config.side_set_pindirs,
676 );
677 self.set_in_shift(
678 config.in_shift_direction_right,
679 config.in_autopush,
680 config.in_push_threshold,
681 );
682 self.set_out_shift(
683 config.out_shift_direction_right,
684 config.out_autopull,
685 config.out_pull_threshold,
686 );
687 self.set_jmp_pin(config.jmp_pin);
688 self.set_wrap(config.wrap_to, config.wrap);
689 self.set_mov_status(config.mov_status_sel, config.mov_status_n);
690 self.set_out_special(
691 config.out_special_sticky,
692 config.out_special_has_enable_pin,
693 config.out_special_enable_pin_index,
694 );
695 self.set_clkdiv_int_frac(config.div_int, config.div_frac);
696 }
697
698 pub fn set_tx_client(&self, client: &'static dyn PioTxClient) {
700 self.tx_client.set(client);
701 }
702
703 pub fn set_rx_client(&self, client: &'static dyn PioRxClient) {
705 self.rx_client.set(client);
706 }
707
708 pub fn set_in_pins(&self, in_base: u32) {
712 self.registers.sm[self.sm_number as usize]
713 .pinctrl
714 .modify(SMx_PINCTRL::IN_BASE.val(in_base));
715 }
716
717 pub fn set_set_pins(&self, set_base: u32, set_count: u32) {
722 self.registers.sm[self.sm_number as usize]
723 .pinctrl
724 .modify(SMx_PINCTRL::SET_BASE.val(set_base));
725 self.registers.sm[self.sm_number as usize]
726 .pinctrl
727 .modify(SMx_PINCTRL::SET_COUNT.val(set_count));
728 }
729
730 pub fn set_out_pins(&self, out_base: u32, out_count: u32) {
735 self.registers.sm[self.sm_number as usize]
736 .pinctrl
737 .modify(SMx_PINCTRL::OUT_BASE.val(out_base));
738 self.registers.sm[self.sm_number as usize]
739 .pinctrl
740 .modify(SMx_PINCTRL::OUT_COUNT.val(out_count));
741 }
742
743 pub fn set_in_shift(&self, shift_right: bool, autopush: bool, push_threshold: u32) {
749 self.registers.sm[self.sm_number as usize]
750 .shiftctrl
751 .modify(SMx_SHIFTCTRL::IN_SHIFTDIR.val(shift_right.into()));
752 self.registers.sm[self.sm_number as usize]
753 .shiftctrl
754 .modify(SMx_SHIFTCTRL::AUTOPUSH.val(autopush.into()));
755 self.registers.sm[self.sm_number as usize]
756 .shiftctrl
757 .modify(SMx_SHIFTCTRL::PUSH_THRESH.val(push_threshold));
758 }
759
760 pub fn set_out_shift(&self, shift_right: bool, autopull: bool, pull_threshold: u32) {
766 self.registers.sm[self.sm_number as usize]
767 .shiftctrl
768 .modify(SMx_SHIFTCTRL::OUT_SHIFTDIR.val(shift_right.into()));
769 self.registers.sm[self.sm_number as usize]
770 .shiftctrl
771 .modify(SMx_SHIFTCTRL::AUTOPULL.val(autopull.into()));
772 self.registers.sm[self.sm_number as usize]
773 .shiftctrl
774 .modify(SMx_SHIFTCTRL::PULL_THRESH.val(pull_threshold));
775 }
776
777 pub fn set_out_special(&self, sticky: bool, has_enable_pin: bool, enable_pin_index: u32) {
787 self.registers.sm[self.sm_number as usize]
788 .execctrl
789 .modify(SMx_EXECCTRL::OUT_STICKY.val(sticky as u32));
790 self.registers.sm[self.sm_number as usize]
791 .execctrl
792 .modify(SMx_EXECCTRL::INLINE_OUT_EN.val(has_enable_pin as u32));
793 self.registers.sm[self.sm_number as usize]
794 .execctrl
795 .modify(SMx_EXECCTRL::OUT_EN_SEL.val(enable_pin_index));
796 }
797
798 pub fn set_jmp_pin(&self, pin: u32) {
802 self.registers.sm[self.sm_number as usize]
803 .execctrl
804 .modify(SMx_EXECCTRL::JMP_PIN.val(pin));
805 }
806
807 pub fn set_clkdiv_int_frac(&self, div_int: u32, div_frac: u32) {
812 self.registers.sm[self.sm_number as usize]
813 .clkdiv
814 .modify(SMx_CLKDIV::INT.val(div_int));
815 self.registers.sm[self.sm_number as usize]
816 .clkdiv
817 .modify(SMx_CLKDIV::FRAC.val(div_frac));
818 }
819
820 pub fn set_fifo_join(&self, fifo_join: PioFifoJoin) {
824 if fifo_join == PioFifoJoin::PioFifoJoinRx {
825 self.registers.sm[self.sm_number as usize]
826 .shiftctrl
827 .modify(SMx_SHIFTCTRL::FJOIN_RX.val(fifo_join as u32));
828 } else if fifo_join == PioFifoJoin::PioFifoJoinTx {
829 self.registers.sm[self.sm_number as usize]
830 .shiftctrl
831 .modify(SMx_SHIFTCTRL::FJOIN_TX.val(fifo_join as u32));
832 }
833 }
834
835 pub fn set_side_set_pins(
846 &self,
847 sideset_base: u32,
848 bit_count: u32,
849 optional: bool,
850 pindirs: bool,
851 ) {
852 self.registers.sm[self.sm_number as usize]
853 .pinctrl
854 .modify(SMx_PINCTRL::SIDESET_BASE.val(sideset_base));
855 self.registers.sm[self.sm_number as usize]
856 .pinctrl
857 .modify(SMx_PINCTRL::SIDESET_COUNT.val(bit_count));
858 self.registers.sm[self.sm_number as usize]
859 .execctrl
860 .modify(SMx_EXECCTRL::SIDE_EN.val(optional as u32));
861 self.registers.sm[self.sm_number as usize]
862 .execctrl
863 .modify(SMx_EXECCTRL::SIDE_PINDIR.val(pindirs as u32));
864 }
865
866 pub fn set_pins_dirs(&self, mut pin: u32, mut count: u32, is_out: bool) {
875 let set_pindirs_0: u16 = 0b1110000010000000;
877 self.with_paused(|| {
878 let mut pindir_val: u8 = 0x00;
879 if is_out {
880 pindir_val = 0x1f;
881 }
882 while count > 5 {
883 self.registers.sm[self.sm_number as usize]
884 .pinctrl
885 .modify(SMx_PINCTRL::SET_COUNT.val(5));
886 self.registers.sm[self.sm_number as usize]
887 .pinctrl
888 .modify(SMx_PINCTRL::SET_BASE.val(pin));
889 self.exec((set_pindirs_0) | (pindir_val as u16));
890 count -= 5;
891 pin = (pin + 5) & 0x1f;
892 }
893 self.registers.sm[self.sm_number as usize]
894 .pinctrl
895 .modify(SMx_PINCTRL::SET_COUNT.val(count));
896 self.registers.sm[self.sm_number as usize]
897 .pinctrl
898 .modify(SMx_PINCTRL::SET_BASE.val(pin));
899 self.exec((set_pindirs_0) | (pindir_val as u16));
900 });
901 }
902
903 pub fn set_pins(&self, pins: &[&RPGpioPin<'_>], high: bool) {
909 self.with_paused(|| {
910 for pin in pins {
911 self.registers.sm[self.sm_number as usize]
912 .pinctrl
913 .modify(SMx_PINCTRL::SET_BASE.val(pin.pin() as u32));
914 self.registers.sm[self.sm_number as usize]
915 .pinctrl
916 .modify(SMx_PINCTRL::SET_COUNT.val(1));
917
918 self.exec(0b11100_000_000_00000 | high as u16);
919 }
920 });
921 }
922
923 pub fn set_wrap(&self, wrap_target: u32, wrap: u32) {
928 self.registers.sm[self.sm_number as usize]
929 .execctrl
930 .modify(SMx_EXECCTRL::WRAP_BOTTOM.val(wrap_target));
931 self.registers.sm[self.sm_number as usize]
932 .execctrl
933 .modify(SMx_EXECCTRL::WRAP_TOP.val(wrap));
934 }
935
936 pub fn init(&self) {
938 self.clear_fifos();
939 self.restart();
940 self.clkdiv_restart();
941 self.registers.sm[self.sm_number as usize]
942 .instr
943 .modify(SMx_INSTR::INSTR.val(0));
944 }
945
946 pub fn restart(&self) {
948 match self.sm_number {
949 SMNumber::SM0 => self.set_registers.ctrl.modify(CTRL::SM0_RESTART::SET),
950 SMNumber::SM1 => self.set_registers.ctrl.modify(CTRL::SM1_RESTART::SET),
951 SMNumber::SM2 => self.set_registers.ctrl.modify(CTRL::SM2_RESTART::SET),
952 SMNumber::SM3 => self.set_registers.ctrl.modify(CTRL::SM3_RESTART::SET),
953 }
954 }
955
956 pub fn clear_fifos(&self) {
958 self.xor_registers.sm[self.sm_number as usize]
959 .shiftctrl
960 .modify(SMx_SHIFTCTRL::FJOIN_RX::SET);
961 self.xor_registers.sm[self.sm_number as usize]
962 .shiftctrl
963 .modify(SMx_SHIFTCTRL::FJOIN_RX::SET);
964 }
965
966 pub fn clkdiv_restart(&self) {
968 match self.sm_number {
969 SMNumber::SM0 => self.set_registers.ctrl.modify(CTRL::CLKDIV0_RESTART::SET),
970 SMNumber::SM1 => self.set_registers.ctrl.modify(CTRL::CLKDIV1_RESTART::SET),
971 SMNumber::SM2 => self.set_registers.ctrl.modify(CTRL::CLKDIV2_RESTART::SET),
972 SMNumber::SM3 => self.set_registers.ctrl.modify(CTRL::CLKDIV3_RESTART::SET),
973 }
974 }
975
976 pub fn tx_full(&self) -> bool {
978 let field = match self.sm_number {
979 SMNumber::SM0 => FSTAT::TXFULL0,
980 SMNumber::SM1 => FSTAT::TXFULL1,
981 SMNumber::SM2 => FSTAT::TXFULL2,
982 SMNumber::SM3 => FSTAT::TXFULL3,
983 };
984 self.registers.fstat.read(field) != 0
985 }
986
987 pub fn rx_empty(&self) -> bool {
989 let field = match self.sm_number {
990 SMNumber::SM0 => FSTAT::RXEMPTY0,
991 SMNumber::SM1 => FSTAT::RXEMPTY1,
992 SMNumber::SM2 => FSTAT::RXEMPTY2,
993 SMNumber::SM3 => FSTAT::RXEMPTY3,
994 };
995 self.registers.fstat.read(field) != 0
996 }
997
998 pub fn tx_empty(&self) -> bool {
1000 let field = match self.sm_number {
1001 SMNumber::SM0 => FSTAT::TXEMPTY0,
1002 SMNumber::SM1 => FSTAT::TXEMPTY1,
1003 SMNumber::SM2 => FSTAT::TXEMPTY2,
1004 SMNumber::SM3 => FSTAT::TXEMPTY3,
1005 };
1006 self.registers.fstat.read(field) != 0
1007 }
1008
1009 pub fn exec(&self, instr: u16) {
1014 self.registers.sm[self.sm_number as usize]
1015 .instr
1016 .modify(SMx_INSTR::INSTR.val(instr as u32));
1017 }
1018
1019 pub fn exec_program(&self, program: LoadedProgram, wrap: bool) {
1025 if wrap {
1026 self.set_wrap(
1027 program.origin as u32,
1028 program.origin as u32 + program.used_memory.count_ones(),
1029 );
1030 }
1031 self.exec((program.origin as u16) & 0x1fu16)
1032 }
1033
1034 pub fn set_mov_status(&self, status_sel: PioMovStatusType, status_n: u32) {
1039 self.registers.sm[self.sm_number as usize]
1040 .execctrl
1041 .modify(SMx_EXECCTRL::STATUS_SEL.val(status_sel as u32));
1042 self.registers.sm[self.sm_number as usize]
1043 .execctrl
1044 .modify(SMx_EXECCTRL::STATUS_N.val(status_n));
1045 }
1046
1047 pub fn set_enabled(&self, enabled: bool) {
1051 match self.sm_number {
1052 SMNumber::SM0 => self.registers.ctrl.modify(match enabled {
1053 true => CTRL::SM0_ENABLE::SET,
1054 false => CTRL::SM0_ENABLE::CLEAR,
1055 }),
1056 SMNumber::SM1 => self.registers.ctrl.modify(match enabled {
1057 true => CTRL::SM1_ENABLE::SET,
1058 false => CTRL::SM1_ENABLE::CLEAR,
1059 }),
1060 SMNumber::SM2 => self.registers.ctrl.modify(match enabled {
1061 true => CTRL::SM2_ENABLE::SET,
1062 false => CTRL::SM2_ENABLE::CLEAR,
1063 }),
1064 SMNumber::SM3 => self.registers.ctrl.modify(match enabled {
1065 true => CTRL::SM3_ENABLE::SET,
1066 false => CTRL::SM3_ENABLE::CLEAR,
1067 }),
1068 }
1069 }
1070
1071 pub fn is_enabled(&self) -> bool {
1073 let field = match self.sm_number {
1074 SMNumber::SM0 => CTRL::SM0_ENABLE,
1075 SMNumber::SM1 => CTRL::SM1_ENABLE,
1076 SMNumber::SM2 => CTRL::SM2_ENABLE,
1077 SMNumber::SM3 => CTRL::SM3_ENABLE,
1078 };
1079 self.registers.ctrl.read(field) != 0
1080 }
1081
1082 fn with_paused(&self, f: impl FnOnce()) {
1085 let enabled = self.is_enabled();
1086 self.set_enabled(false);
1087
1088 let pio_sm = &self.registers.sm[self.sm_number as usize];
1089
1090 let pinctrl = pio_sm.pinctrl.get();
1091 let execctrl = pio_sm.execctrl.get();
1092 pio_sm.execctrl.modify(SMx_EXECCTRL::OUT_STICKY::CLEAR);
1094
1095 f();
1096
1097 pio_sm.pinctrl.set(pinctrl);
1098 pio_sm.execctrl.set(execctrl);
1099 self.set_enabled(enabled);
1100 }
1101
1102 pub fn push(&self, data: u32) -> Result<(), ErrorCode> {
1107 match self.tx_state.get() {
1108 StateMachineState::Ready => {
1109 if self.tx_full() {
1110 let field = match self.sm_number {
1112 SMNumber::SM0 => IRQ0_INTE::SM0_TXNFULL::SET,
1113 SMNumber::SM1 => IRQ0_INTE::SM1_TXNFULL::SET,
1114 SMNumber::SM2 => IRQ0_INTE::SM2_TXNFULL::SET,
1115 SMNumber::SM3 => IRQ0_INTE::SM3_TXNFULL::SET,
1116 };
1117 self.registers.irq0_inte.modify(field);
1118 self.tx_state.set(StateMachineState::Waiting);
1119 Err(ErrorCode::BUSY)
1120 } else {
1121 self.registers.txf[self.sm_number as usize].set(data);
1122 Ok(())
1123 }
1124 }
1125 StateMachineState::Waiting => Err(ErrorCode::BUSY),
1126 }
1127 }
1128
1129 pub fn push_blocking(&self, data: u32) -> Result<(), ErrorCode> {
1135 if self.tx_full() && !self.is_enabled() {
1136 return Err(ErrorCode::OFF);
1137 }
1138 while self.tx_full() {}
1139 self.registers.txf[self.sm_number as usize].set(data);
1140 Ok(())
1141 }
1142
1143 pub fn pull(&self) -> Result<u32, ErrorCode> {
1146 match self.rx_state.get() {
1147 StateMachineState::Ready => {
1148 if self.rx_empty() {
1149 let field = match self.sm_number {
1151 SMNumber::SM0 => IRQ0_INTE::SM0_RXNEMPTY::SET,
1152 SMNumber::SM1 => IRQ0_INTE::SM1_RXNEMPTY::SET,
1153 SMNumber::SM2 => IRQ0_INTE::SM2_RXNEMPTY::SET,
1154 SMNumber::SM3 => IRQ0_INTE::SM3_RXNEMPTY::SET,
1155 };
1156 self.registers.irq0_inte.modify(field);
1157 self.rx_state.set(StateMachineState::Waiting);
1158 Err(ErrorCode::BUSY)
1159 } else {
1160 Ok(self.registers.rxf[self.sm_number as usize].read(RXFx::RXF))
1161 }
1162 }
1163 StateMachineState::Waiting => Err(ErrorCode::BUSY),
1164 }
1165 }
1166
1167 pub fn pull_blocking(&self) -> Result<u32, ErrorCode> {
1171 if self.tx_full() && !self.is_enabled() {
1172 return Err(ErrorCode::OFF);
1173 }
1174 while self.rx_empty() {}
1175 Ok(self.registers.rxf[self.sm_number as usize].read(RXFx::RXF))
1176 }
1177
1178 fn handle_tx_interrupt(&self) {
1180 match self.tx_state.get() {
1181 StateMachineState::Waiting => {
1182 let field = match self.sm_number {
1184 SMNumber::SM0 => IRQ0_INTE::SM0_TXNFULL::CLEAR,
1185 SMNumber::SM1 => IRQ0_INTE::SM1_TXNFULL::CLEAR,
1186 SMNumber::SM2 => IRQ0_INTE::SM2_TXNFULL::CLEAR,
1187 SMNumber::SM3 => IRQ0_INTE::SM3_TXNFULL::CLEAR,
1188 };
1189 self.registers.irq0_inte.modify(field);
1190 self.tx_state.set(StateMachineState::Ready);
1191 self.tx_client.map(|client| {
1192 client.on_buffer_space_available();
1193 });
1194 }
1195 StateMachineState::Ready => {}
1196 }
1197 }
1198
1199 fn handle_rx_interrupt(&self) {
1201 match self.rx_state.get() {
1202 StateMachineState::Waiting => {
1203 let field = match self.sm_number {
1205 SMNumber::SM0 => IRQ0_INTE::SM0_RXNEMPTY::CLEAR,
1206 SMNumber::SM1 => IRQ0_INTE::SM1_RXNEMPTY::CLEAR,
1207 SMNumber::SM2 => IRQ0_INTE::SM2_RXNEMPTY::CLEAR,
1208 SMNumber::SM3 => IRQ0_INTE::SM3_RXNEMPTY::CLEAR,
1209 };
1210 self.registers.irq0_inte.modify(field);
1211 self.rx_state.set(StateMachineState::Ready);
1212 self.rx_client.map(|client| {
1213 client.on_data_received(
1214 self.registers.rxf[self.sm_number as usize].read(RXFx::RXF),
1215 );
1216 });
1217 }
1218 StateMachineState::Ready => {}
1219 }
1220 }
1221}
1222
1223pub struct Pio {
1224 registers: StaticRef<PioRegisters>,
1225 pio_number: PIONumber,
1226 sms: [StateMachine; NUMBER_STATE_MACHINES],
1227 instructions_used: Cell<u32>,
1228 _clear_registers: StaticRef<PioRegisters>,
1229}
1230
1231#[derive(Clone, Copy)]
1233pub enum PioMovStatusType {
1234 StatusTxLessthan = 0,
1235 StatusRxLessthan = 1,
1236}
1237
1238pub struct StateMachineConfiguration {
1242 pub out_pins_count: u32,
1243 pub out_pins_base: u32,
1244 pub set_pins_count: u32,
1245 pub set_pins_base: u32,
1246 pub in_pins_base: u32,
1247 pub side_set_base: u32,
1248 pub side_set_opt_enable: bool,
1249 pub side_set_bit_count: u32,
1250 pub side_set_pindirs: bool,
1251 pub wrap: u32,
1252 pub wrap_to: u32,
1253 pub in_shift_direction_right: bool,
1254 pub in_autopush: bool,
1255 pub in_push_threshold: u32,
1256 pub out_shift_direction_right: bool,
1257 pub out_autopull: bool,
1258 pub out_pull_threshold: u32,
1259 pub jmp_pin: u32,
1260 pub out_special_sticky: bool,
1261 pub out_special_has_enable_pin: bool,
1262 pub out_special_enable_pin_index: u32,
1263 pub mov_status_sel: PioMovStatusType,
1264 pub mov_status_n: u32,
1265 pub div_int: u32,
1266 pub div_frac: u32,
1267}
1268
1269impl Default for StateMachineConfiguration {
1270 fn default() -> Self {
1271 StateMachineConfiguration {
1272 out_pins_count: 32,
1273 out_pins_base: 0,
1274 set_pins_count: 0,
1275 set_pins_base: 0,
1276 in_pins_base: 0,
1277 side_set_base: 0,
1278 side_set_opt_enable: false,
1279 side_set_bit_count: 0,
1280 side_set_pindirs: false,
1281 wrap: 31,
1282 wrap_to: 0,
1283 in_shift_direction_right: true,
1284 in_autopush: false,
1285 in_push_threshold: 32,
1286 out_shift_direction_right: true,
1287 out_autopull: false,
1288 out_pull_threshold: 32,
1289 jmp_pin: 0,
1290 out_special_sticky: false,
1291 out_special_has_enable_pin: false,
1292 out_special_enable_pin_index: 0,
1293 mov_status_sel: PioMovStatusType::StatusTxLessthan,
1294 mov_status_n: 0,
1295 div_int: 0,
1296 div_frac: 0,
1297 }
1298 }
1299}
1300
1301impl Pio {
1302 pub fn gpio_init(&self, pin: &RPGpioPin) {
1304 if self.pio_number == PIONumber::PIO1 {
1305 pin.set_function(GpioFunction::PIO1)
1306 } else {
1307 pin.set_function(GpioFunction::PIO0)
1308 }
1309 }
1310
1311 pub fn new_pio0() -> Self {
1313 Self {
1314 registers: PIO0_BASE,
1315 _clear_registers: PIO0_CLEAR_BASE,
1316 pio_number: PIONumber::PIO0,
1317 sms: SM_NUMBERS.map(|x| StateMachine::new(x, PIO0_BASE, PIO0_XOR_BASE, PIO0_SET_BASE)),
1318 instructions_used: Cell::new(0),
1319 }
1320 }
1321
1322 pub fn new_pio1() -> Self {
1324 Self {
1325 registers: PIO1_BASE,
1326 _clear_registers: PIO1_CLEAR_BASE,
1327 pio_number: PIONumber::PIO1,
1328 sms: SM_NUMBERS.map(|x| StateMachine::new(x, PIO1_BASE, PIO1_XOR_BASE, PIO1_SET_BASE)),
1329 instructions_used: Cell::new(0),
1330 }
1331 }
1332
1333 pub fn sm(&self, sm_number: SMNumber) -> &StateMachine {
1335 &self.sms[sm_number as usize]
1336 }
1337
1338 pub fn set_irq_source(
1340 &self,
1341 irq_index: u32,
1342 interrupt_source: InterruptSources,
1343 enabled: bool,
1344 ) {
1345 if irq_index == 0 {
1346 match interrupt_source {
1347 InterruptSources::Interrupt0 => self
1348 .registers
1349 .irq0_inte
1350 .modify(IRQ0_INTE::SM0.val(enabled as u32)),
1351 InterruptSources::Interrupt1 => self
1352 .registers
1353 .irq0_inte
1354 .modify(IRQ0_INTE::SM1.val(enabled as u32)),
1355 InterruptSources::Interrupt2 => self
1356 .registers
1357 .irq0_inte
1358 .modify(IRQ0_INTE::SM2.val(enabled as u32)),
1359 InterruptSources::Interrupt3 => self
1360 .registers
1361 .irq0_inte
1362 .modify(IRQ0_INTE::SM3.val(enabled as u32)),
1363 InterruptSources::Sm0TXNotFull => self
1364 .registers
1365 .irq0_inte
1366 .modify(IRQ0_INTE::SM0_TXNFULL.val(enabled as u32)),
1367 InterruptSources::Sm1TXNotFull => self
1368 .registers
1369 .irq0_inte
1370 .modify(IRQ0_INTE::SM1_TXNFULL.val(enabled as u32)),
1371 InterruptSources::Sm2TXNotFull => self
1372 .registers
1373 .irq0_inte
1374 .modify(IRQ0_INTE::SM2_TXNFULL.val(enabled as u32)),
1375 InterruptSources::Sm3TXNotFull => self
1376 .registers
1377 .irq0_inte
1378 .modify(IRQ0_INTE::SM3_TXNFULL.val(enabled as u32)),
1379 InterruptSources::Sm0RXNotEmpty => self
1380 .registers
1381 .irq0_inte
1382 .modify(IRQ0_INTE::SM0_RXNEMPTY.val(enabled as u32)),
1383 InterruptSources::Sm1RXNotEmpty => self
1384 .registers
1385 .irq0_inte
1386 .modify(IRQ0_INTE::SM1_RXNEMPTY.val(enabled as u32)),
1387 InterruptSources::Sm2RXNotEmpty => self
1388 .registers
1389 .irq0_inte
1390 .modify(IRQ0_INTE::SM2_RXNEMPTY.val(enabled as u32)),
1391 InterruptSources::Sm3RXNotEmpty => self
1392 .registers
1393 .irq0_inte
1394 .modify(IRQ0_INTE::SM3_RXNEMPTY.val(enabled as u32)),
1395 }
1396 } else if irq_index == 1 {
1397 match interrupt_source {
1398 InterruptSources::Interrupt0 => self
1399 .registers
1400 .irq1_inte
1401 .modify(IRQ1_INTE::SM0.val(enabled as u32)),
1402 InterruptSources::Interrupt1 => self
1403 .registers
1404 .irq1_inte
1405 .modify(IRQ1_INTE::SM1.val(enabled as u32)),
1406 InterruptSources::Interrupt2 => self
1407 .registers
1408 .irq1_inte
1409 .modify(IRQ1_INTE::SM2.val(enabled as u32)),
1410 InterruptSources::Interrupt3 => self
1411 .registers
1412 .irq1_inte
1413 .modify(IRQ1_INTE::SM3.val(enabled as u32)),
1414 InterruptSources::Sm0TXNotFull => self
1415 .registers
1416 .irq1_inte
1417 .modify(IRQ1_INTE::SM0_TXNFULL.val(enabled as u32)),
1418 InterruptSources::Sm1TXNotFull => self
1419 .registers
1420 .irq1_inte
1421 .modify(IRQ1_INTE::SM1_TXNFULL.val(enabled as u32)),
1422 InterruptSources::Sm2TXNotFull => self
1423 .registers
1424 .irq1_inte
1425 .modify(IRQ1_INTE::SM2_TXNFULL.val(enabled as u32)),
1426 InterruptSources::Sm3TXNotFull => self
1427 .registers
1428 .irq1_inte
1429 .modify(IRQ1_INTE::SM3_TXNFULL.val(enabled as u32)),
1430 InterruptSources::Sm0RXNotEmpty => self
1431 .registers
1432 .irq1_inte
1433 .modify(IRQ1_INTE::SM0_RXNEMPTY.val(enabled as u32)),
1434 InterruptSources::Sm1RXNotEmpty => self
1435 .registers
1436 .irq1_inte
1437 .modify(IRQ1_INTE::SM1_RXNEMPTY.val(enabled as u32)),
1438 InterruptSources::Sm2RXNotEmpty => self
1439 .registers
1440 .irq1_inte
1441 .modify(IRQ1_INTE::SM2_RXNEMPTY.val(enabled as u32)),
1442 InterruptSources::Sm3RXNotEmpty => self
1443 .registers
1444 .irq1_inte
1445 .modify(IRQ1_INTE::SM3_RXNEMPTY.val(enabled as u32)),
1446 }
1447 } else {
1448 debug!("IRQ Index invalid - must be 0 or 1");
1449 }
1450 }
1451
1452 pub fn interrupt_get(&self, irq_num: u32) -> bool {
1454 let mut temp = 0;
1455 match irq_num {
1456 0 => temp = self.registers.irq.read(IRQ::IRQ0),
1457 1 => temp = self.registers.irq.read(IRQ::IRQ1),
1458 2 => temp = self.registers.irq.read(IRQ::IRQ2),
1459 3 => temp = self.registers.irq.read(IRQ::IRQ3),
1460 4 => temp = self.registers.irq.read(IRQ::IRQ4),
1461 5 => temp = self.registers.irq.read(IRQ::IRQ5),
1462 6 => temp = self.registers.irq.read(IRQ::IRQ6),
1463 7 => temp = self.registers.irq.read(IRQ::IRQ7),
1464 _ => debug!("IRQ Number invalid - must be from 0 to 7"),
1465 }
1466 temp != 0
1467 }
1468
1469 pub fn interrupt_clear(&self, irq_num: u32) {
1471 match irq_num {
1472 0 => self.registers.irq.modify(IRQ::IRQ0.val(1)),
1473 1 => self.registers.irq.modify(IRQ::IRQ1.val(1)),
1474 2 => self.registers.irq.modify(IRQ::IRQ2.val(1)),
1475 3 => self.registers.irq.modify(IRQ::IRQ3.val(1)),
1476 4 => self.registers.irq.modify(IRQ::IRQ4.val(1)),
1477 5 => self.registers.irq.modify(IRQ::IRQ5.val(1)),
1478 6 => self.registers.irq.modify(IRQ::IRQ6.val(1)),
1479 7 => self.registers.irq.modify(IRQ::IRQ7.val(1)),
1480 _ => debug!("IRQ Number invalid - must be from 0 to 7"),
1481 }
1482 }
1483
1484 pub fn handle_interrupt(&self) {
1486 let ints = &self.registers.irq0_ints;
1487 for (sm, irq) in self.sms.iter().zip([
1488 IRQ0_INTS::SM0_TXNFULL,
1489 IRQ0_INTS::SM1_TXNFULL,
1490 IRQ0_INTS::SM2_TXNFULL,
1491 IRQ0_INTS::SM3_TXNFULL,
1492 ]) {
1493 if ints.is_set(irq) {
1494 sm.handle_tx_interrupt();
1495 }
1496 }
1497 for (sm, irq) in self.sms.iter().zip([
1498 IRQ0_INTS::SM0_RXNEMPTY,
1499 IRQ0_INTS::SM1_RXNEMPTY,
1500 IRQ0_INTS::SM2_RXNEMPTY,
1501 IRQ0_INTS::SM3_RXNEMPTY,
1502 ]) {
1503 if ints.is_set(irq) {
1504 sm.handle_rx_interrupt();
1505 }
1506 }
1507 }
1508
1509 pub fn add_program(
1515 &self,
1516 origin: Option<usize>,
1517 program: &[u8],
1518 ) -> Result<LoadedProgram, ProgramError> {
1519 let mut program_u16: [u16; NUMBER_INSTR_MEMORY_LOCATIONS / 2] =
1520 [0; NUMBER_INSTR_MEMORY_LOCATIONS / 2];
1521 for (i, chunk) in program.chunks(2).enumerate() {
1522 program_u16[i] = ((chunk[0] as u16) << 8) | (chunk[1] as u16);
1523 }
1524
1525 self.add_program16(origin, &program_u16[0..program.len() / 2])
1526 }
1527
1528 pub fn add_program16(
1534 &self,
1535 origin: Option<usize>,
1536 program: &[u16],
1537 ) -> Result<LoadedProgram, ProgramError> {
1538 match origin {
1540 Some(origin) => {
1541 assert!(origin < NUMBER_INSTR_MEMORY_LOCATIONS);
1542 self.try_load_program_at(origin, program)
1543 .map_err(|_| ProgramError::AddrInUse(origin))
1544 }
1545 None => {
1546 for origin in 0..NUMBER_INSTR_MEMORY_LOCATIONS {
1547 if let res @ Ok(_) = self.try_load_program_at(origin, program) {
1548 return res;
1549 }
1550 }
1551 Err(ProgramError::InsufficientSpace)
1552 }
1553 }
1554 }
1555
1556 fn try_load_program_at(
1562 &self,
1563 origin: usize,
1564 program: &[u16],
1565 ) -> Result<LoadedProgram, ProgramError> {
1566 let program = RelocatedProgram::new(program.iter(), origin);
1568 let mut used_mask = 0;
1569 for (i, instr) in program.enumerate() {
1570 let addr = (i + origin) % 32;
1572 let mask = 1 << addr;
1573 if (self.instructions_used.get() | used_mask) & mask != 0 {
1574 return Err(ProgramError::AddrInUse(addr));
1575 }
1576 self.registers.instr_mem[addr]
1577 .instr_mem
1578 .modify(INSTR_MEMx::INSTR_MEM.val(instr as u32));
1579 used_mask |= mask;
1580 }
1581 self.instructions_used
1583 .set(self.instructions_used.get() | used_mask);
1584 Ok(LoadedProgram {
1585 used_memory: used_mask,
1586 origin,
1587 })
1588 }
1589
1590 pub fn clear_instr_registers(&self) {
1592 for i in 0..NUMBER_INSTR_MEMORY_LOCATIONS {
1593 self.registers.instr_mem[i]
1594 .instr_mem
1595 .modify(INSTR_MEMx::INSTR_MEM::CLEAR);
1596 }
1597
1598 self.instructions_used.set(0);
1600 }
1601
1602 pub fn init(&self) {
1604 let default_config: StateMachineConfiguration = StateMachineConfiguration::default();
1605 for state_machine in self.sms.iter() {
1606 state_machine.config(&default_config);
1607 }
1608 self.clear_instr_registers()
1609 }
1610}
1611
1612mod examples {
1613 use super::{
1614 debug, Pio, RPGpio, RPGpioPin, Readable, SMNumber, SMx_EXECCTRL, SMx_INSTR, SMx_PINCTRL,
1615 StateMachineConfiguration, DBG_PADOUT, FDEBUG,
1616 };
1617
1618 impl RPGpio {
1619 fn from_u32(value: u32) -> RPGpio {
1620 match value {
1621 0 => RPGpio::GPIO0,
1622 1 => RPGpio::GPIO1,
1623 2 => RPGpio::GPIO2,
1624 3 => RPGpio::GPIO3,
1625 4 => RPGpio::GPIO4,
1626 5 => RPGpio::GPIO5,
1627 6 => RPGpio::GPIO6,
1628 7 => RPGpio::GPIO7,
1629 8 => RPGpio::GPIO8,
1630 9 => RPGpio::GPIO9,
1631 10 => RPGpio::GPIO10,
1632 11 => RPGpio::GPIO11,
1633 12 => RPGpio::GPIO12,
1634 13 => RPGpio::GPIO13,
1635 14 => RPGpio::GPIO14,
1636 15 => RPGpio::GPIO15,
1637 16 => RPGpio::GPIO16,
1638 17 => RPGpio::GPIO17,
1639 18 => RPGpio::GPIO18,
1640 19 => RPGpio::GPIO19,
1641 20 => RPGpio::GPIO20,
1642 21 => RPGpio::GPIO21,
1643 22 => RPGpio::GPIO22,
1644 23 => RPGpio::GPIO23,
1645 24 => RPGpio::GPIO24,
1646 25 => RPGpio::GPIO25,
1647 26 => RPGpio::GPIO26,
1648 27 => RPGpio::GPIO27,
1649 28 => RPGpio::GPIO28,
1650 29 => RPGpio::GPIO29,
1651 _ => panic!(
1652 "Unknown value for GPIO pin: {} (should be from 0 to 29)",
1653 value
1654 ),
1655 }
1656 }
1657 }
1658
1659 impl Pio {
1660 pub fn blinking_hello_program_init(
1664 &self,
1665 sm_number: SMNumber,
1666 pin: u32,
1667 config: &StateMachineConfiguration,
1668 ) {
1669 let sm = &self.sms[sm_number as usize];
1670 sm.config(config);
1671 self.gpio_init(&RPGpioPin::new(RPGpio::from_u32(pin)));
1672 sm.set_enabled(false);
1673 sm.set_pins_dirs(pin, 1, true);
1674 sm.set_set_pins(pin, 1);
1675 sm.init();
1676 sm.set_enabled(true);
1677 }
1678
1679 pub fn blink_program_init(
1680 &self,
1681 sm_number: SMNumber,
1682 pin: u32,
1683 config: &StateMachineConfiguration,
1684 ) {
1685 let sm = &self.sms[sm_number as usize];
1686 sm.config(config);
1687 self.gpio_init(&RPGpioPin::new(RPGpio::from_u32(pin)));
1688 sm.set_enabled(false);
1689 sm.set_pins_dirs(pin, 1, true);
1690 sm.set_set_pins(pin, 1);
1691 sm.init();
1692 sm.set_enabled(true);
1693 }
1694
1695 pub fn sideset_program_init(
1696 &self,
1697 sm_number: SMNumber,
1698 pin: u32,
1699 config: &StateMachineConfiguration,
1700 ) {
1701 let sm = &self.sms[sm_number as usize];
1702 sm.config(config);
1703 self.gpio_init(&RPGpioPin::new(RPGpio::from_u32(pin)));
1704 self.gpio_init(&RPGpioPin::new(RPGpio::GPIO7));
1705 sm.set_enabled(false);
1706 sm.set_pins_dirs(pin, 1, true);
1707 sm.set_pins_dirs(7, 1, true);
1708 sm.set_set_pins(pin, 1);
1709 sm.set_side_set_pins(7, 1, false, true);
1710 sm.init();
1711 sm.set_enabled(true);
1712 }
1713
1714 pub fn hello_program_init(
1715 &self,
1716 sm_number: SMNumber,
1717 pin1: u32,
1718 pin2: u32,
1719 config: &StateMachineConfiguration,
1720 ) {
1721 let sm = &self.sms[sm_number as usize];
1722 let turn_on_gpio_6_7 = 0b11000000;
1724 sm.config(config);
1725 self.gpio_init(&RPGpioPin::new(RPGpio::from_u32(pin1)));
1726 self.gpio_init(&RPGpioPin::new(RPGpio::from_u32(pin2)));
1727 sm.set_enabled(false);
1728 sm.set_pins_dirs(pin1, 1, true);
1729 sm.set_pins_dirs(pin2, 1, true);
1730 sm.init();
1731 sm.set_enabled(true);
1732 sm.push_blocking(turn_on_gpio_6_7).ok();
1733 sm.push_blocking(0).ok();
1734 }
1735
1736 pub fn pwm_program_init(
1737 &self,
1738 sm_number: SMNumber,
1739 pin: u32,
1740 pwm_period: u32,
1741 config: &StateMachineConfiguration,
1742 ) {
1743 let sm = &self.sms[sm_number as usize];
1744 let pull_command = 0x8080_u16;
1746 let out_isr_32_command = 0x60c0_u16;
1748 sm.config(config);
1749 self.gpio_init(&RPGpioPin::new(RPGpio::from_u32(pin)));
1750 sm.set_enabled(false);
1751 sm.set_pins_dirs(pin, 1, true);
1752 sm.set_side_set_pins(pin, 1, false, true);
1753 sm.init();
1754 sm.push_blocking(pwm_period).ok();
1755 sm.exec(pull_command);
1756 sm.exec(out_isr_32_command);
1757 sm.set_enabled(true);
1758 }
1759
1760 pub fn spi_program_init(
1761 &self,
1762 sm_number: SMNumber,
1763 clock_pin: u32,
1764 in_pin: u32,
1765 out_pin: u32,
1766 config: &StateMachineConfiguration,
1767 ) {
1768 let sm = &self.sms[sm_number as usize];
1769 sm.config(config);
1770 self.gpio_init(&RPGpioPin::new(RPGpio::from_u32(clock_pin)));
1771 self.gpio_init(&RPGpioPin::new(RPGpio::from_u32(in_pin)));
1772 self.gpio_init(&RPGpioPin::new(RPGpio::from_u32(out_pin)));
1773 sm.set_enabled(false);
1774
1775 sm.set_out_pins(clock_pin, 1);
1778 sm.set_pins_dirs(clock_pin, 1, true);
1779 sm.set_side_set_pins(clock_pin, 1, false, false); sm.set_pins_dirs(out_pin, 1, true);
1782 sm.set_out_pins(out_pin, config.out_pins_count);
1783
1784 sm.init();
1785 sm.clear_fifos();
1786 sm.set_enabled(true);
1787 }
1788
1789 pub fn read_instr(&self, sm_number: SMNumber) -> u32 {
1792 self.registers.sm[sm_number as usize]
1793 .instr
1794 .read(SMx_INSTR::INSTR)
1795 }
1796
1797 pub fn read_sideset_reg(&self, sm_number: SMNumber) {
1798 debug!(
1799 "{}",
1800 self.registers.sm[sm_number as usize]
1801 .pinctrl
1802 .read(SMx_PINCTRL::SIDESET_COUNT)
1803 );
1804 debug!(
1805 "{}",
1806 self.registers.sm[sm_number as usize]
1807 .execctrl
1808 .read(SMx_EXECCTRL::SIDE_EN)
1809 );
1810 debug!(
1811 "{}",
1812 self.registers.sm[sm_number as usize]
1813 .execctrl
1814 .read(SMx_EXECCTRL::SIDE_PINDIR)
1815 );
1816 debug!(
1817 "{}",
1818 self.registers.sm[sm_number as usize]
1819 .pinctrl
1820 .read(SMx_PINCTRL::SIDESET_BASE)
1821 );
1822 }
1823
1824 pub fn read_dbg_padout(&self) -> u32 {
1825 self.registers.dbg_padout.read(DBG_PADOUT::DBG_PADOUT)
1826 }
1827
1828 pub fn read_fdebug(&self, tx: bool, stall: bool) -> u32 {
1829 if tx {
1830 if stall {
1831 self.registers.fdebug.read(FDEBUG::TXSTALL)
1832 } else {
1833 self.registers.fdebug.read(FDEBUG::TXOVER)
1834 }
1835 } else if stall {
1836 self.registers.fdebug.read(FDEBUG::RXSTALL)
1837 } else {
1838 self.registers.fdebug.read(FDEBUG::RXUNDER)
1839 }
1840 }
1841 }
1842}