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
629pub trait PioSmClient {
631 fn on_irq(&self);
632}
633
634#[derive(Clone, Copy, Debug, Default)]
635enum StateMachineState {
636 #[default]
637 Ready,
638 Waiting,
639}
640
641pub struct StateMachine {
642 sm_number: SMNumber,
643 registers: StaticRef<PioRegisters>,
644 xor_registers: StaticRef<PioRegisters>,
645 set_registers: StaticRef<PioRegisters>,
646 tx_state: Cell<StateMachineState>,
647 tx_client: OptionalCell<&'static dyn PioTxClient>,
648 rx_state: Cell<StateMachineState>,
649 rx_client: OptionalCell<&'static dyn PioRxClient>,
650 sm_client: OptionalCell<&'static dyn PioSmClient>,
651}
652
653impl StateMachine {
654 fn new(
655 sm_id: SMNumber,
656 registers: StaticRef<PioRegisters>,
657 xor_registers: StaticRef<PioRegisters>,
658 set_registers: StaticRef<PioRegisters>,
659 ) -> StateMachine {
660 StateMachine {
661 sm_number: sm_id,
662 registers,
663 xor_registers,
664 set_registers,
665 tx_state: Cell::new(StateMachineState::Ready),
666 tx_client: OptionalCell::empty(),
667 rx_state: Cell::new(StateMachineState::Ready),
668 sm_client: OptionalCell::empty(),
669 rx_client: OptionalCell::empty(),
670 }
671 }
672
673 pub fn config(&self, config: &StateMachineConfiguration) {
675 self.set_in_pins(config.in_pins_base);
676 self.set_out_pins(config.out_pins_base, config.out_pins_count);
677 self.set_set_pins(config.set_pins_base, config.set_pins_count);
678 self.set_side_set_pins(
679 config.side_set_base,
680 config.side_set_bit_count,
681 config.side_set_opt_enable,
682 config.side_set_pindirs,
683 );
684 self.set_in_shift(
685 config.in_shift_direction_right,
686 config.in_autopush,
687 config.in_push_threshold,
688 );
689 self.set_out_shift(
690 config.out_shift_direction_right,
691 config.out_autopull,
692 config.out_pull_threshold,
693 );
694 self.set_jmp_pin(config.jmp_pin);
695 self.set_wrap(config.wrap_to, config.wrap);
696 self.set_mov_status(config.mov_status_sel, config.mov_status_n);
697 self.set_out_special(
698 config.out_special_sticky,
699 config.out_special_has_enable_pin,
700 config.out_special_enable_pin_index,
701 );
702 self.set_clkdiv_int_frac(config.div_int, config.div_frac);
703 }
704
705 pub fn set_tx_client(&self, client: &'static dyn PioTxClient) {
707 self.tx_client.set(client);
708 }
709
710 pub fn set_rx_client(&self, client: &'static dyn PioRxClient) {
712 self.rx_client.set(client);
713 }
714
715 pub fn set_sm_client(&self, client: &'static dyn PioSmClient) {
717 self.sm_client.set(client);
718 }
719
720 pub fn set_in_pins(&self, in_base: u32) {
724 self.registers.sm[self.sm_number as usize]
725 .pinctrl
726 .modify(SMx_PINCTRL::IN_BASE.val(in_base));
727 }
728
729 pub fn set_set_pins(&self, set_base: u32, set_count: u32) {
734 self.registers.sm[self.sm_number as usize]
735 .pinctrl
736 .modify(SMx_PINCTRL::SET_BASE.val(set_base));
737 self.registers.sm[self.sm_number as usize]
738 .pinctrl
739 .modify(SMx_PINCTRL::SET_COUNT.val(set_count));
740 }
741
742 pub fn set_out_pins(&self, out_base: u32, out_count: u32) {
747 self.registers.sm[self.sm_number as usize]
748 .pinctrl
749 .modify(SMx_PINCTRL::OUT_BASE.val(out_base));
750 self.registers.sm[self.sm_number as usize]
751 .pinctrl
752 .modify(SMx_PINCTRL::OUT_COUNT.val(out_count));
753 }
754
755 pub fn set_in_shift(&self, shift_right: bool, autopush: bool, push_threshold: u32) {
761 self.registers.sm[self.sm_number as usize]
762 .shiftctrl
763 .modify(SMx_SHIFTCTRL::IN_SHIFTDIR.val(shift_right.into()));
764 self.registers.sm[self.sm_number as usize]
765 .shiftctrl
766 .modify(SMx_SHIFTCTRL::AUTOPUSH.val(autopush.into()));
767 self.registers.sm[self.sm_number as usize]
768 .shiftctrl
769 .modify(SMx_SHIFTCTRL::PUSH_THRESH.val(push_threshold));
770 }
771
772 pub fn set_out_shift(&self, shift_right: bool, autopull: bool, pull_threshold: u32) {
778 self.registers.sm[self.sm_number as usize]
779 .shiftctrl
780 .modify(SMx_SHIFTCTRL::OUT_SHIFTDIR.val(shift_right.into()));
781 self.registers.sm[self.sm_number as usize]
782 .shiftctrl
783 .modify(SMx_SHIFTCTRL::AUTOPULL.val(autopull.into()));
784 self.registers.sm[self.sm_number as usize]
785 .shiftctrl
786 .modify(SMx_SHIFTCTRL::PULL_THRESH.val(pull_threshold));
787 }
788
789 pub fn set_out_special(&self, sticky: bool, has_enable_pin: bool, enable_pin_index: u32) {
799 self.registers.sm[self.sm_number as usize]
800 .execctrl
801 .modify(SMx_EXECCTRL::OUT_STICKY.val(sticky as u32));
802 self.registers.sm[self.sm_number as usize]
803 .execctrl
804 .modify(SMx_EXECCTRL::INLINE_OUT_EN.val(has_enable_pin as u32));
805 self.registers.sm[self.sm_number as usize]
806 .execctrl
807 .modify(SMx_EXECCTRL::OUT_EN_SEL.val(enable_pin_index));
808 }
809
810 pub fn set_jmp_pin(&self, pin: u32) {
814 self.registers.sm[self.sm_number as usize]
815 .execctrl
816 .modify(SMx_EXECCTRL::JMP_PIN.val(pin));
817 }
818
819 pub fn set_clkdiv_int_frac(&self, div_int: u32, div_frac: u32) {
824 self.registers.sm[self.sm_number as usize]
825 .clkdiv
826 .modify(SMx_CLKDIV::INT.val(div_int));
827 self.registers.sm[self.sm_number as usize]
828 .clkdiv
829 .modify(SMx_CLKDIV::FRAC.val(div_frac));
830 }
831
832 pub fn set_fifo_join(&self, fifo_join: PioFifoJoin) {
836 if fifo_join == PioFifoJoin::PioFifoJoinRx {
837 self.registers.sm[self.sm_number as usize]
838 .shiftctrl
839 .modify(SMx_SHIFTCTRL::FJOIN_RX.val(fifo_join as u32));
840 } else if fifo_join == PioFifoJoin::PioFifoJoinTx {
841 self.registers.sm[self.sm_number as usize]
842 .shiftctrl
843 .modify(SMx_SHIFTCTRL::FJOIN_TX.val(fifo_join as u32));
844 }
845 }
846
847 pub fn set_side_set_pins(
858 &self,
859 sideset_base: u32,
860 bit_count: u32,
861 optional: bool,
862 pindirs: bool,
863 ) {
864 self.registers.sm[self.sm_number as usize]
865 .pinctrl
866 .modify(SMx_PINCTRL::SIDESET_BASE.val(sideset_base));
867 self.registers.sm[self.sm_number as usize]
868 .pinctrl
869 .modify(SMx_PINCTRL::SIDESET_COUNT.val(bit_count));
870 self.registers.sm[self.sm_number as usize]
871 .execctrl
872 .modify(SMx_EXECCTRL::SIDE_EN.val(optional as u32));
873 self.registers.sm[self.sm_number as usize]
874 .execctrl
875 .modify(SMx_EXECCTRL::SIDE_PINDIR.val(pindirs as u32));
876 }
877
878 pub fn set_pins_dirs(&self, mut pin: u32, mut count: u32, is_out: bool) {
887 let set_pindirs_0: u16 = 0b1110000010000000;
889 self.with_paused(|| {
890 let mut pindir_val: u8 = 0x00;
891 if is_out {
892 pindir_val = 0x1f;
893 }
894 while count > 5 {
895 self.registers.sm[self.sm_number as usize]
896 .pinctrl
897 .modify(SMx_PINCTRL::SET_COUNT.val(5));
898 self.registers.sm[self.sm_number as usize]
899 .pinctrl
900 .modify(SMx_PINCTRL::SET_BASE.val(pin));
901 self.exec((set_pindirs_0) | (pindir_val as u16));
902 count -= 5;
903 pin = (pin + 5) & 0x1f;
904 }
905 self.registers.sm[self.sm_number as usize]
906 .pinctrl
907 .modify(SMx_PINCTRL::SET_COUNT.val(count));
908 self.registers.sm[self.sm_number as usize]
909 .pinctrl
910 .modify(SMx_PINCTRL::SET_BASE.val(pin));
911 self.exec((set_pindirs_0) | (pindir_val as u16));
912 });
913 }
914
915 pub fn set_pins(&self, pins: &[&RPGpioPin<'_>], high: bool) {
921 self.with_paused(|| {
922 for pin in pins {
923 self.registers.sm[self.sm_number as usize]
924 .pinctrl
925 .modify(SMx_PINCTRL::SET_BASE.val(pin.pin() as u32));
926 self.registers.sm[self.sm_number as usize]
927 .pinctrl
928 .modify(SMx_PINCTRL::SET_COUNT.val(1));
929
930 self.exec(0b11100_000_000_00000 | high as u16);
931 }
932 });
933 }
934
935 pub fn set_wrap(&self, wrap_target: u32, wrap: u32) {
940 self.registers.sm[self.sm_number as usize]
941 .execctrl
942 .modify(SMx_EXECCTRL::WRAP_BOTTOM.val(wrap_target));
943 self.registers.sm[self.sm_number as usize]
944 .execctrl
945 .modify(SMx_EXECCTRL::WRAP_TOP.val(wrap));
946 }
947
948 pub fn init(&self) {
950 self.clear_fifos();
951 self.restart();
952 self.clkdiv_restart();
953 self.registers.sm[self.sm_number as usize]
954 .instr
955 .modify(SMx_INSTR::INSTR.val(0));
956 }
957
958 pub fn rx_fifo_addr(&self, pio: PIONumber) -> u32 {
960 let base_addr = match pio {
961 PIONumber::PIO0 => PIO_0_BASE_ADDRESS,
962 PIONumber::PIO1 => PIO_1_BASE_ADDRESS,
963 };
964 (base_addr as u32) + 0x20 + 4 * (self.sm_number as u32)
965 }
966
967 pub fn tx_fifo_addr(&self, pio: PIONumber) -> u32 {
969 let base_addr = match pio {
970 PIONumber::PIO0 => PIO_0_BASE_ADDRESS,
971 PIONumber::PIO1 => PIO_1_BASE_ADDRESS,
972 };
973 (base_addr as u32) + 0x10 + 4 * (self.sm_number as u32)
974 }
975
976 pub fn restart(&self) {
978 match self.sm_number {
979 SMNumber::SM0 => self.set_registers.ctrl.modify(CTRL::SM0_RESTART::SET),
980 SMNumber::SM1 => self.set_registers.ctrl.modify(CTRL::SM1_RESTART::SET),
981 SMNumber::SM2 => self.set_registers.ctrl.modify(CTRL::SM2_RESTART::SET),
982 SMNumber::SM3 => self.set_registers.ctrl.modify(CTRL::SM3_RESTART::SET),
983 }
984 }
985
986 pub fn clear_fifos(&self) {
988 self.xor_registers.sm[self.sm_number as usize]
989 .shiftctrl
990 .modify(SMx_SHIFTCTRL::FJOIN_RX::SET);
991 self.xor_registers.sm[self.sm_number as usize]
992 .shiftctrl
993 .modify(SMx_SHIFTCTRL::FJOIN_RX::SET);
994 }
995
996 pub fn clkdiv_restart(&self) {
998 match self.sm_number {
999 SMNumber::SM0 => self.set_registers.ctrl.modify(CTRL::CLKDIV0_RESTART::SET),
1000 SMNumber::SM1 => self.set_registers.ctrl.modify(CTRL::CLKDIV1_RESTART::SET),
1001 SMNumber::SM2 => self.set_registers.ctrl.modify(CTRL::CLKDIV2_RESTART::SET),
1002 SMNumber::SM3 => self.set_registers.ctrl.modify(CTRL::CLKDIV3_RESTART::SET),
1003 }
1004 }
1005
1006 pub fn tx_full(&self) -> bool {
1008 let field = match self.sm_number {
1009 SMNumber::SM0 => FSTAT::TXFULL0,
1010 SMNumber::SM1 => FSTAT::TXFULL1,
1011 SMNumber::SM2 => FSTAT::TXFULL2,
1012 SMNumber::SM3 => FSTAT::TXFULL3,
1013 };
1014 self.registers.fstat.read(field) != 0
1015 }
1016
1017 pub fn rx_empty(&self) -> bool {
1019 let field = match self.sm_number {
1020 SMNumber::SM0 => FSTAT::RXEMPTY0,
1021 SMNumber::SM1 => FSTAT::RXEMPTY1,
1022 SMNumber::SM2 => FSTAT::RXEMPTY2,
1023 SMNumber::SM3 => FSTAT::RXEMPTY3,
1024 };
1025 self.registers.fstat.read(field) != 0
1026 }
1027
1028 pub fn tx_empty(&self) -> bool {
1030 let field = match self.sm_number {
1031 SMNumber::SM0 => FSTAT::TXEMPTY0,
1032 SMNumber::SM1 => FSTAT::TXEMPTY1,
1033 SMNumber::SM2 => FSTAT::TXEMPTY2,
1034 SMNumber::SM3 => FSTAT::TXEMPTY3,
1035 };
1036 self.registers.fstat.read(field) != 0
1037 }
1038
1039 pub fn exec(&self, instr: u16) {
1044 self.registers.sm[self.sm_number as usize]
1045 .instr
1046 .modify(SMx_INSTR::INSTR.val(instr as u32));
1047 }
1048
1049 pub fn exec_program(&self, program: LoadedProgram, wrap: bool) {
1055 if wrap {
1056 self.set_wrap(
1057 program.origin as u32,
1058 program.origin as u32 + program.used_memory.count_ones(),
1059 );
1060 }
1061 self.exec((program.origin as u16) & 0x1fu16)
1062 }
1063
1064 pub fn set_mov_status(&self, status_sel: PioMovStatusType, status_n: u32) {
1069 self.registers.sm[self.sm_number as usize]
1070 .execctrl
1071 .modify(SMx_EXECCTRL::STATUS_SEL.val(status_sel as u32));
1072 self.registers.sm[self.sm_number as usize]
1073 .execctrl
1074 .modify(SMx_EXECCTRL::STATUS_N.val(status_n));
1075 }
1076
1077 pub fn set_enabled(&self, enabled: bool) {
1081 match self.sm_number {
1082 SMNumber::SM0 => self.registers.ctrl.modify(match enabled {
1083 true => CTRL::SM0_ENABLE::SET,
1084 false => CTRL::SM0_ENABLE::CLEAR,
1085 }),
1086 SMNumber::SM1 => self.registers.ctrl.modify(match enabled {
1087 true => CTRL::SM1_ENABLE::SET,
1088 false => CTRL::SM1_ENABLE::CLEAR,
1089 }),
1090 SMNumber::SM2 => self.registers.ctrl.modify(match enabled {
1091 true => CTRL::SM2_ENABLE::SET,
1092 false => CTRL::SM2_ENABLE::CLEAR,
1093 }),
1094 SMNumber::SM3 => self.registers.ctrl.modify(match enabled {
1095 true => CTRL::SM3_ENABLE::SET,
1096 false => CTRL::SM3_ENABLE::CLEAR,
1097 }),
1098 }
1099 }
1100
1101 pub fn is_enabled(&self) -> bool {
1103 let field = match self.sm_number {
1104 SMNumber::SM0 => CTRL::SM0_ENABLE,
1105 SMNumber::SM1 => CTRL::SM1_ENABLE,
1106 SMNumber::SM2 => CTRL::SM2_ENABLE,
1107 SMNumber::SM3 => CTRL::SM3_ENABLE,
1108 };
1109 self.registers.ctrl.read(field) != 0
1110 }
1111
1112 fn with_paused(&self, f: impl FnOnce()) {
1115 let enabled = self.is_enabled();
1116 self.set_enabled(false);
1117
1118 let pio_sm = &self.registers.sm[self.sm_number as usize];
1119
1120 let pinctrl = pio_sm.pinctrl.get();
1121 let execctrl = pio_sm.execctrl.get();
1122 pio_sm.execctrl.modify(SMx_EXECCTRL::OUT_STICKY::CLEAR);
1124
1125 f();
1126
1127 pio_sm.pinctrl.set(pinctrl);
1128 pio_sm.execctrl.set(execctrl);
1129 self.set_enabled(enabled);
1130 }
1131
1132 pub fn push(&self, data: u32) -> Result<(), ErrorCode> {
1137 match self.tx_state.get() {
1138 StateMachineState::Ready => {
1139 if self.tx_full() {
1140 let field = match self.sm_number {
1142 SMNumber::SM0 => IRQ0_INTE::SM0_TXNFULL::SET,
1143 SMNumber::SM1 => IRQ0_INTE::SM1_TXNFULL::SET,
1144 SMNumber::SM2 => IRQ0_INTE::SM2_TXNFULL::SET,
1145 SMNumber::SM3 => IRQ0_INTE::SM3_TXNFULL::SET,
1146 };
1147 self.registers.irq0_inte.modify(field);
1148 self.tx_state.set(StateMachineState::Waiting);
1149 Err(ErrorCode::BUSY)
1150 } else {
1151 self.registers.txf[self.sm_number as usize].set(data);
1152 Ok(())
1153 }
1154 }
1155 StateMachineState::Waiting => Err(ErrorCode::BUSY),
1156 }
1157 }
1158
1159 pub fn push_blocking(&self, data: u32) -> Result<(), ErrorCode> {
1165 if self.tx_full() && !self.is_enabled() {
1166 return Err(ErrorCode::OFF);
1167 }
1168 while self.tx_full() {}
1169 self.registers.txf[self.sm_number as usize].set(data);
1170 Ok(())
1171 }
1172
1173 pub fn pull(&self) -> Result<u32, ErrorCode> {
1176 match self.rx_state.get() {
1177 StateMachineState::Ready => {
1178 if self.rx_empty() {
1179 let field = match self.sm_number {
1181 SMNumber::SM0 => IRQ0_INTE::SM0_RXNEMPTY::SET,
1182 SMNumber::SM1 => IRQ0_INTE::SM1_RXNEMPTY::SET,
1183 SMNumber::SM2 => IRQ0_INTE::SM2_RXNEMPTY::SET,
1184 SMNumber::SM3 => IRQ0_INTE::SM3_RXNEMPTY::SET,
1185 };
1186 self.registers.irq0_inte.modify(field);
1187 self.rx_state.set(StateMachineState::Waiting);
1188 Err(ErrorCode::BUSY)
1189 } else {
1190 Ok(self.registers.rxf[self.sm_number as usize].read(RXFx::RXF))
1191 }
1192 }
1193 StateMachineState::Waiting => Err(ErrorCode::BUSY),
1194 }
1195 }
1196
1197 pub fn pull_blocking(&self) -> Result<u32, ErrorCode> {
1201 if self.tx_full() && !self.is_enabled() {
1202 return Err(ErrorCode::OFF);
1203 }
1204 while self.rx_empty() {}
1205 Ok(self.registers.rxf[self.sm_number as usize].read(RXFx::RXF))
1206 }
1207
1208 fn handle_tx_interrupt(&self) {
1210 match self.tx_state.get() {
1211 StateMachineState::Waiting => {
1212 let field = match self.sm_number {
1214 SMNumber::SM0 => IRQ0_INTE::SM0_TXNFULL::CLEAR,
1215 SMNumber::SM1 => IRQ0_INTE::SM1_TXNFULL::CLEAR,
1216 SMNumber::SM2 => IRQ0_INTE::SM2_TXNFULL::CLEAR,
1217 SMNumber::SM3 => IRQ0_INTE::SM3_TXNFULL::CLEAR,
1218 };
1219 self.registers.irq0_inte.modify(field);
1220 self.tx_state.set(StateMachineState::Ready);
1221 self.tx_client.map(|client| {
1222 client.on_buffer_space_available();
1223 });
1224 }
1225 StateMachineState::Ready => {}
1226 }
1227 }
1228
1229 fn handle_rx_interrupt(&self) {
1231 match self.rx_state.get() {
1232 StateMachineState::Waiting => {
1233 let field = match self.sm_number {
1235 SMNumber::SM0 => IRQ0_INTE::SM0_RXNEMPTY::CLEAR,
1236 SMNumber::SM1 => IRQ0_INTE::SM1_RXNEMPTY::CLEAR,
1237 SMNumber::SM2 => IRQ0_INTE::SM2_RXNEMPTY::CLEAR,
1238 SMNumber::SM3 => IRQ0_INTE::SM3_RXNEMPTY::CLEAR,
1239 };
1240 self.registers.irq0_inte.modify(field);
1241 self.rx_state.set(StateMachineState::Ready);
1242 self.rx_client.map(|client| {
1243 client.on_data_received(
1244 self.registers.rxf[self.sm_number as usize].read(RXFx::RXF),
1245 );
1246 });
1247 }
1248 StateMachineState::Ready => {}
1249 }
1250 }
1251
1252 fn handle_sm_interrupt(&self) {
1254 let _ = self.sm_client.map(|client| {
1255 client.on_irq();
1256 });
1257 }
1258}
1259
1260pub struct Pio {
1261 registers: StaticRef<PioRegisters>,
1262 pio_number: PIONumber,
1263 sms: [StateMachine; NUMBER_STATE_MACHINES],
1264 instructions_used: Cell<u32>,
1265 _clear_registers: StaticRef<PioRegisters>,
1266}
1267
1268#[derive(Clone, Copy)]
1270pub enum PioMovStatusType {
1271 StatusTxLessthan = 0,
1272 StatusRxLessthan = 1,
1273}
1274
1275pub struct StateMachineConfiguration {
1279 pub out_pins_count: u32,
1280 pub out_pins_base: u32,
1281 pub set_pins_count: u32,
1282 pub set_pins_base: u32,
1283 pub in_pins_base: u32,
1284 pub side_set_base: u32,
1285 pub side_set_opt_enable: bool,
1286 pub side_set_bit_count: u32,
1287 pub side_set_pindirs: bool,
1288 pub wrap: u32,
1289 pub wrap_to: u32,
1290 pub in_shift_direction_right: bool,
1291 pub in_autopush: bool,
1292 pub in_push_threshold: u32,
1293 pub out_shift_direction_right: bool,
1294 pub out_autopull: bool,
1295 pub out_pull_threshold: u32,
1296 pub jmp_pin: u32,
1297 pub out_special_sticky: bool,
1298 pub out_special_has_enable_pin: bool,
1299 pub out_special_enable_pin_index: u32,
1300 pub mov_status_sel: PioMovStatusType,
1301 pub mov_status_n: u32,
1302 pub div_int: u32,
1303 pub div_frac: u32,
1304}
1305
1306impl Default for StateMachineConfiguration {
1307 fn default() -> Self {
1308 StateMachineConfiguration {
1309 out_pins_count: 32,
1310 out_pins_base: 0,
1311 set_pins_count: 0,
1312 set_pins_base: 0,
1313 in_pins_base: 0,
1314 side_set_base: 0,
1315 side_set_opt_enable: false,
1316 side_set_bit_count: 0,
1317 side_set_pindirs: false,
1318 wrap: 31,
1319 wrap_to: 0,
1320 in_shift_direction_right: true,
1321 in_autopush: false,
1322 in_push_threshold: 32,
1323 out_shift_direction_right: true,
1324 out_autopull: false,
1325 out_pull_threshold: 32,
1326 jmp_pin: 0,
1327 out_special_sticky: false,
1328 out_special_has_enable_pin: false,
1329 out_special_enable_pin_index: 0,
1330 mov_status_sel: PioMovStatusType::StatusTxLessthan,
1331 mov_status_n: 0,
1332 div_int: 0,
1333 div_frac: 0,
1334 }
1335 }
1336}
1337
1338impl Pio {
1339 pub fn gpio_init(&self, pin: &RPGpioPin) {
1341 if self.pio_number == PIONumber::PIO1 {
1342 pin.set_function(GpioFunction::PIO1)
1343 } else {
1344 pin.set_function(GpioFunction::PIO0)
1345 }
1346 }
1347
1348 pub fn new_pio0() -> Self {
1350 Self {
1351 registers: PIO0_BASE,
1352 _clear_registers: PIO0_CLEAR_BASE,
1353 pio_number: PIONumber::PIO0,
1354 sms: SM_NUMBERS.map(|x| StateMachine::new(x, PIO0_BASE, PIO0_XOR_BASE, PIO0_SET_BASE)),
1355 instructions_used: Cell::new(0),
1356 }
1357 }
1358
1359 pub fn new_pio1() -> Self {
1361 Self {
1362 registers: PIO1_BASE,
1363 _clear_registers: PIO1_CLEAR_BASE,
1364 pio_number: PIONumber::PIO1,
1365 sms: SM_NUMBERS.map(|x| StateMachine::new(x, PIO1_BASE, PIO1_XOR_BASE, PIO1_SET_BASE)),
1366 instructions_used: Cell::new(0),
1367 }
1368 }
1369
1370 pub fn number(&self) -> PIONumber {
1372 self.pio_number
1373 }
1374
1375 pub fn sm(&self, sm_number: SMNumber) -> &StateMachine {
1377 &self.sms[sm_number as usize]
1378 }
1379
1380 pub fn set_irq_source(
1382 &self,
1383 irq_index: u32,
1384 interrupt_source: InterruptSources,
1385 enabled: bool,
1386 ) {
1387 if irq_index == 0 {
1388 match interrupt_source {
1389 InterruptSources::Interrupt0 => self
1390 .registers
1391 .irq0_inte
1392 .modify(IRQ0_INTE::SM0.val(enabled as u32)),
1393 InterruptSources::Interrupt1 => self
1394 .registers
1395 .irq0_inte
1396 .modify(IRQ0_INTE::SM1.val(enabled as u32)),
1397 InterruptSources::Interrupt2 => self
1398 .registers
1399 .irq0_inte
1400 .modify(IRQ0_INTE::SM2.val(enabled as u32)),
1401 InterruptSources::Interrupt3 => self
1402 .registers
1403 .irq0_inte
1404 .modify(IRQ0_INTE::SM3.val(enabled as u32)),
1405 InterruptSources::Sm0TXNotFull => self
1406 .registers
1407 .irq0_inte
1408 .modify(IRQ0_INTE::SM0_TXNFULL.val(enabled as u32)),
1409 InterruptSources::Sm1TXNotFull => self
1410 .registers
1411 .irq0_inte
1412 .modify(IRQ0_INTE::SM1_TXNFULL.val(enabled as u32)),
1413 InterruptSources::Sm2TXNotFull => self
1414 .registers
1415 .irq0_inte
1416 .modify(IRQ0_INTE::SM2_TXNFULL.val(enabled as u32)),
1417 InterruptSources::Sm3TXNotFull => self
1418 .registers
1419 .irq0_inte
1420 .modify(IRQ0_INTE::SM3_TXNFULL.val(enabled as u32)),
1421 InterruptSources::Sm0RXNotEmpty => self
1422 .registers
1423 .irq0_inte
1424 .modify(IRQ0_INTE::SM0_RXNEMPTY.val(enabled as u32)),
1425 InterruptSources::Sm1RXNotEmpty => self
1426 .registers
1427 .irq0_inte
1428 .modify(IRQ0_INTE::SM1_RXNEMPTY.val(enabled as u32)),
1429 InterruptSources::Sm2RXNotEmpty => self
1430 .registers
1431 .irq0_inte
1432 .modify(IRQ0_INTE::SM2_RXNEMPTY.val(enabled as u32)),
1433 InterruptSources::Sm3RXNotEmpty => self
1434 .registers
1435 .irq0_inte
1436 .modify(IRQ0_INTE::SM3_RXNEMPTY.val(enabled as u32)),
1437 }
1438 } else if irq_index == 1 {
1439 match interrupt_source {
1440 InterruptSources::Interrupt0 => self
1441 .registers
1442 .irq1_inte
1443 .modify(IRQ1_INTE::SM0.val(enabled as u32)),
1444 InterruptSources::Interrupt1 => self
1445 .registers
1446 .irq1_inte
1447 .modify(IRQ1_INTE::SM1.val(enabled as u32)),
1448 InterruptSources::Interrupt2 => self
1449 .registers
1450 .irq1_inte
1451 .modify(IRQ1_INTE::SM2.val(enabled as u32)),
1452 InterruptSources::Interrupt3 => self
1453 .registers
1454 .irq1_inte
1455 .modify(IRQ1_INTE::SM3.val(enabled as u32)),
1456 InterruptSources::Sm0TXNotFull => self
1457 .registers
1458 .irq1_inte
1459 .modify(IRQ1_INTE::SM0_TXNFULL.val(enabled as u32)),
1460 InterruptSources::Sm1TXNotFull => self
1461 .registers
1462 .irq1_inte
1463 .modify(IRQ1_INTE::SM1_TXNFULL.val(enabled as u32)),
1464 InterruptSources::Sm2TXNotFull => self
1465 .registers
1466 .irq1_inte
1467 .modify(IRQ1_INTE::SM2_TXNFULL.val(enabled as u32)),
1468 InterruptSources::Sm3TXNotFull => self
1469 .registers
1470 .irq1_inte
1471 .modify(IRQ1_INTE::SM3_TXNFULL.val(enabled as u32)),
1472 InterruptSources::Sm0RXNotEmpty => self
1473 .registers
1474 .irq1_inte
1475 .modify(IRQ1_INTE::SM0_RXNEMPTY.val(enabled as u32)),
1476 InterruptSources::Sm1RXNotEmpty => self
1477 .registers
1478 .irq1_inte
1479 .modify(IRQ1_INTE::SM1_RXNEMPTY.val(enabled as u32)),
1480 InterruptSources::Sm2RXNotEmpty => self
1481 .registers
1482 .irq1_inte
1483 .modify(IRQ1_INTE::SM2_RXNEMPTY.val(enabled as u32)),
1484 InterruptSources::Sm3RXNotEmpty => self
1485 .registers
1486 .irq1_inte
1487 .modify(IRQ1_INTE::SM3_RXNEMPTY.val(enabled as u32)),
1488 }
1489 } else {
1490 debug!("IRQ Index invalid - must be 0 or 1");
1491 }
1492 }
1493
1494 pub fn interrupt_get(&self, irq_num: u32) -> bool {
1496 let mut temp = 0;
1497 match irq_num {
1498 0 => temp = self.registers.irq.read(IRQ::IRQ0),
1499 1 => temp = self.registers.irq.read(IRQ::IRQ1),
1500 2 => temp = self.registers.irq.read(IRQ::IRQ2),
1501 3 => temp = self.registers.irq.read(IRQ::IRQ3),
1502 4 => temp = self.registers.irq.read(IRQ::IRQ4),
1503 5 => temp = self.registers.irq.read(IRQ::IRQ5),
1504 6 => temp = self.registers.irq.read(IRQ::IRQ6),
1505 7 => temp = self.registers.irq.read(IRQ::IRQ7),
1506 _ => debug!("IRQ Number invalid - must be from 0 to 7"),
1507 }
1508 temp != 0
1509 }
1510
1511 pub fn interrupt_clear(&self, irq_num: u32) {
1513 match irq_num {
1514 0 => self.registers.irq.modify(IRQ::IRQ0.val(1)),
1515 1 => self.registers.irq.modify(IRQ::IRQ1.val(1)),
1516 2 => self.registers.irq.modify(IRQ::IRQ2.val(1)),
1517 3 => self.registers.irq.modify(IRQ::IRQ3.val(1)),
1518 4 => self.registers.irq.modify(IRQ::IRQ4.val(1)),
1519 5 => self.registers.irq.modify(IRQ::IRQ5.val(1)),
1520 6 => self.registers.irq.modify(IRQ::IRQ6.val(1)),
1521 7 => self.registers.irq.modify(IRQ::IRQ7.val(1)),
1522 _ => debug!("IRQ Number invalid - must be from 0 to 7"),
1523 }
1524 }
1525
1526 pub fn handle_interrupt(&self) {
1528 let ints = &self.registers.irq0_ints;
1529
1530 for (sm, irq) in self.sms.iter().zip([
1531 IRQ0_INTS::SM0_TXNFULL,
1532 IRQ0_INTS::SM1_TXNFULL,
1533 IRQ0_INTS::SM2_TXNFULL,
1534 IRQ0_INTS::SM3_TXNFULL,
1535 ]) {
1536 if ints.is_set(irq) {
1537 sm.handle_tx_interrupt();
1538 }
1539 }
1540 for (sm, irq) in self.sms.iter().zip([
1541 IRQ0_INTS::SM0_RXNEMPTY,
1542 IRQ0_INTS::SM1_RXNEMPTY,
1543 IRQ0_INTS::SM2_RXNEMPTY,
1544 IRQ0_INTS::SM3_RXNEMPTY,
1545 ]) {
1546 if ints.is_set(irq) {
1547 sm.handle_rx_interrupt();
1548 }
1549 }
1550 for (sm, irq) in self.sms.iter().zip([
1551 IRQ0_INTS::SM0,
1552 IRQ0_INTS::SM1,
1553 IRQ0_INTS::SM2,
1554 IRQ0_INTS::SM3,
1555 ]) {
1556 if ints.is_set(irq) {
1557 sm.handle_sm_interrupt();
1558 }
1559 }
1560 }
1561
1562 pub fn set_input_sync_bypass(&self, pin: &RPGpioPin, enabled: bool) {
1563 let pin = pin.pin();
1564 let reg_val = self.registers.input_sync_bypass.get();
1565 if enabled {
1566 self.registers.input_sync_bypass.set(reg_val | (1 << pin));
1567 } else {
1568 self.registers
1569 .input_sync_bypass
1570 .set(reg_val & (!(1 << pin)));
1571 }
1572 }
1573
1574 pub fn add_program(
1580 &self,
1581 origin: Option<usize>,
1582 program: &[u8],
1583 ) -> Result<LoadedProgram, ProgramError> {
1584 let mut program_u16: [u16; NUMBER_INSTR_MEMORY_LOCATIONS / 2] =
1585 [0; NUMBER_INSTR_MEMORY_LOCATIONS / 2];
1586 for (i, chunk) in program.chunks(2).enumerate() {
1587 program_u16[i] = ((chunk[0] as u16) << 8) | (chunk[1] as u16);
1588 }
1589
1590 self.add_program16(origin, &program_u16[0..program.len() / 2])
1591 }
1592
1593 pub fn add_program16(
1599 &self,
1600 origin: Option<usize>,
1601 program: &[u16],
1602 ) -> Result<LoadedProgram, ProgramError> {
1603 match origin {
1605 Some(origin) => {
1606 assert!(origin < NUMBER_INSTR_MEMORY_LOCATIONS);
1607 self.try_load_program_at(origin, program)
1608 .map_err(|_| ProgramError::AddrInUse(origin))
1609 }
1610 None => {
1611 for origin in 0..NUMBER_INSTR_MEMORY_LOCATIONS {
1612 if let res @ Ok(_) = self.try_load_program_at(origin, program) {
1613 return res;
1614 }
1615 }
1616 Err(ProgramError::InsufficientSpace)
1617 }
1618 }
1619 }
1620
1621 fn try_load_program_at(
1627 &self,
1628 origin: usize,
1629 program: &[u16],
1630 ) -> Result<LoadedProgram, ProgramError> {
1631 let program = RelocatedProgram::new(program.iter(), origin);
1633 let mut used_mask = 0;
1634 for (i, instr) in program.enumerate() {
1635 let addr = (i + origin) % 32;
1637 let mask = 1 << addr;
1638 if (self.instructions_used.get() | used_mask) & mask != 0 {
1639 return Err(ProgramError::AddrInUse(addr));
1640 }
1641 self.registers.instr_mem[addr]
1642 .instr_mem
1643 .modify(INSTR_MEMx::INSTR_MEM.val(instr as u32));
1644 used_mask |= mask;
1645 }
1646 self.instructions_used
1648 .set(self.instructions_used.get() | used_mask);
1649 Ok(LoadedProgram {
1650 used_memory: used_mask,
1651 origin,
1652 })
1653 }
1654
1655 pub fn clear_instr_registers(&self) {
1657 for i in 0..NUMBER_INSTR_MEMORY_LOCATIONS {
1658 self.registers.instr_mem[i]
1659 .instr_mem
1660 .modify(INSTR_MEMx::INSTR_MEM::CLEAR);
1661 }
1662
1663 self.instructions_used.set(0);
1665 }
1666
1667 pub fn init(&self) {
1669 let default_config: StateMachineConfiguration = StateMachineConfiguration::default();
1670 for state_machine in self.sms.iter() {
1671 state_machine.config(&default_config);
1672 }
1673 self.clear_instr_registers()
1674 }
1675}
1676
1677mod examples {
1678 use kernel::hil::gpio::Configure;
1679
1680 use super::{
1681 debug, Pio, RPGpio, RPGpioPin, Readable, SMNumber, SMx_EXECCTRL, SMx_INSTR, SMx_PINCTRL,
1682 StateMachineConfiguration, DBG_PADOUT, FDEBUG,
1683 };
1684
1685 impl RPGpio {
1686 fn from_u32(value: u32) -> RPGpio {
1687 match value {
1688 0 => RPGpio::GPIO0,
1689 1 => RPGpio::GPIO1,
1690 2 => RPGpio::GPIO2,
1691 3 => RPGpio::GPIO3,
1692 4 => RPGpio::GPIO4,
1693 5 => RPGpio::GPIO5,
1694 6 => RPGpio::GPIO6,
1695 7 => RPGpio::GPIO7,
1696 8 => RPGpio::GPIO8,
1697 9 => RPGpio::GPIO9,
1698 10 => RPGpio::GPIO10,
1699 11 => RPGpio::GPIO11,
1700 12 => RPGpio::GPIO12,
1701 13 => RPGpio::GPIO13,
1702 14 => RPGpio::GPIO14,
1703 15 => RPGpio::GPIO15,
1704 16 => RPGpio::GPIO16,
1705 17 => RPGpio::GPIO17,
1706 18 => RPGpio::GPIO18,
1707 19 => RPGpio::GPIO19,
1708 20 => RPGpio::GPIO20,
1709 21 => RPGpio::GPIO21,
1710 22 => RPGpio::GPIO22,
1711 23 => RPGpio::GPIO23,
1712 24 => RPGpio::GPIO24,
1713 25 => RPGpio::GPIO25,
1714 26 => RPGpio::GPIO26,
1715 27 => RPGpio::GPIO27,
1716 28 => RPGpio::GPIO28,
1717 29 => RPGpio::GPIO29,
1718 _ => panic!(
1719 "Unknown value for GPIO pin: {} (should be from 0 to 29)",
1720 value
1721 ),
1722 }
1723 }
1724 }
1725
1726 impl Pio {
1727 pub fn blinking_hello_program_init(
1731 &self,
1732 sm_number: SMNumber,
1733 pin: u32,
1734 config: &StateMachineConfiguration,
1735 ) {
1736 let sm = &self.sms[sm_number as usize];
1737 sm.config(config);
1738 self.gpio_init(&RPGpioPin::new(RPGpio::from_u32(pin)));
1739 sm.set_enabled(false);
1740 sm.set_pins_dirs(pin, 1, true);
1741 sm.set_set_pins(pin, 1);
1742 sm.init();
1743 sm.set_enabled(true);
1744 }
1745
1746 pub fn blink_program_init(
1747 &self,
1748 sm_number: SMNumber,
1749 pin: u32,
1750 config: &StateMachineConfiguration,
1751 ) {
1752 let sm = &self.sms[sm_number as usize];
1753 sm.config(config);
1754 self.gpio_init(&RPGpioPin::new(RPGpio::from_u32(pin)));
1755 sm.set_enabled(false);
1756 sm.set_pins_dirs(pin, 1, true);
1757 sm.set_set_pins(pin, 1);
1758 sm.init();
1759 sm.set_enabled(true);
1760 }
1761
1762 pub fn sideset_program_init(
1763 &self,
1764 sm_number: SMNumber,
1765 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(pin)));
1771 self.gpio_init(&RPGpioPin::new(RPGpio::GPIO7));
1772 sm.set_enabled(false);
1773 sm.set_pins_dirs(pin, 1, true);
1774 sm.set_pins_dirs(7, 1, true);
1775 sm.set_set_pins(pin, 1);
1776 sm.set_side_set_pins(7, 1, false, true);
1777 sm.init();
1778 sm.set_enabled(true);
1779 }
1780
1781 pub fn hello_program_init(
1782 &self,
1783 sm_number: SMNumber,
1784 pin1: u32,
1785 pin2: u32,
1786 config: &StateMachineConfiguration,
1787 ) {
1788 let sm = &self.sms[sm_number as usize];
1789 let turn_on_gpio_6_7 = 0b11000000;
1791 sm.config(config);
1792 self.gpio_init(&RPGpioPin::new(RPGpio::from_u32(pin1)));
1793 self.gpio_init(&RPGpioPin::new(RPGpio::from_u32(pin2)));
1794 sm.set_enabled(false);
1795 sm.set_pins_dirs(pin1, 1, true);
1796 sm.set_pins_dirs(pin2, 1, true);
1797 sm.init();
1798 sm.set_enabled(true);
1799 let _ = sm.push_blocking(turn_on_gpio_6_7);
1800 let _ = sm.push_blocking(0);
1801 }
1802
1803 pub fn pwm_program_init(
1804 &self,
1805 sm_number: SMNumber,
1806 pin: u32,
1807 pwm_period: u32,
1808 config: &StateMachineConfiguration,
1809 ) {
1810 let sm = &self.sms[sm_number as usize];
1811 let pull_command = 0x8080_u16;
1813 let out_isr_32_command = 0x60c0_u16;
1815 sm.config(config);
1816 self.gpio_init(&RPGpioPin::new(RPGpio::from_u32(pin)));
1817 sm.set_enabled(false);
1818 sm.set_pins_dirs(pin, 1, true);
1819 sm.set_side_set_pins(pin, 1, false, true);
1820 sm.init();
1821 let _ = sm.push_blocking(pwm_period);
1822 sm.exec(pull_command);
1823 sm.exec(out_isr_32_command);
1824 sm.set_enabled(true);
1825 }
1826
1827 pub fn spi_program_init(
1828 &self,
1829 sm_number: SMNumber,
1830 clock_pin: u32,
1831 in_pin: u32,
1832 out_pin: u32,
1833 config: &StateMachineConfiguration,
1834 ) {
1835 let sm = &self.sms[sm_number as usize];
1836 sm.config(config);
1837 self.gpio_init(&RPGpioPin::new(RPGpio::from_u32(clock_pin)));
1838 self.gpio_init(&RPGpioPin::new(RPGpio::from_u32(in_pin)));
1839 self.gpio_init(&RPGpioPin::new(RPGpio::from_u32(out_pin)));
1840 sm.set_enabled(false);
1841
1842 sm.set_out_pins(clock_pin, 1);
1845 sm.set_pins_dirs(clock_pin, 1, true);
1846 sm.set_side_set_pins(clock_pin, 1, false, false); sm.set_pins_dirs(out_pin, 1, true);
1849 sm.set_out_pins(out_pin, config.out_pins_count);
1850
1851 sm.init();
1852 sm.clear_fifos();
1853 sm.set_enabled(true);
1854 }
1855
1856 pub fn cyw43_spi_program_init(
1857 &self,
1858 sm_number: SMNumber,
1859 clock_pin: u32,
1860 dio_pin: u32,
1861 config: &StateMachineConfiguration,
1862 ) {
1863 let sm = &self.sms[sm_number as usize];
1864 sm.set_enabled(false);
1865 sm.config(config);
1866 let clock_pin_handle = RPGpioPin::new(RPGpio::from_u32(clock_pin));
1867 let dio_pin_handle = RPGpioPin::new(RPGpio::from_u32(dio_pin));
1868 self.gpio_init(&clock_pin_handle);
1869 self.gpio_init(&dio_pin_handle);
1870
1871 dio_pin_handle.set_floating_state(kernel::hil::gpio::FloatingState::PullNone);
1872 dio_pin_handle.set_schmitt(true);
1873 self.set_input_sync_bypass(&dio_pin_handle, true);
1874 dio_pin_handle.set_drive_strength(crate::gpio::DriveStrength::Drive12ma);
1875 dio_pin_handle.set_slew_rate(crate::gpio::SlewRate::Fast);
1876 dio_pin_handle.activate_pads();
1877
1878 clock_pin_handle.set_drive_strength(crate::gpio::DriveStrength::Drive12ma);
1879 clock_pin_handle.set_slew_rate(crate::gpio::SlewRate::Fast);
1880 clock_pin_handle.set_floating_state(kernel::hil::gpio::FloatingState::PullNone);
1881 clock_pin_handle.set_schmitt(true);
1882 clock_pin_handle.set_slew_rate(crate::gpio::SlewRate::Slow);
1883 clock_pin_handle.activate_pads();
1884
1885 sm.set_pins_dirs(dio_pin, 1, true);
1886 sm.set_pins_dirs(clock_pin, 1, true);
1887
1888 sm.set_pins(&[&clock_pin_handle, &dio_pin_handle], false);
1889
1890 sm.init();
1891 sm.clear_fifos();
1892 sm.set_enabled(true);
1893 }
1894
1895 pub fn read_instr(&self, sm_number: SMNumber) -> u32 {
1898 self.registers.sm[sm_number as usize]
1899 .instr
1900 .read(SMx_INSTR::INSTR)
1901 }
1902
1903 pub fn read_sideset_reg(&self, sm_number: SMNumber) {
1904 debug!(
1905 "{}",
1906 self.registers.sm[sm_number as usize]
1907 .pinctrl
1908 .read(SMx_PINCTRL::SIDESET_COUNT)
1909 );
1910 debug!(
1911 "{}",
1912 self.registers.sm[sm_number as usize]
1913 .execctrl
1914 .read(SMx_EXECCTRL::SIDE_EN)
1915 );
1916 debug!(
1917 "{}",
1918 self.registers.sm[sm_number as usize]
1919 .execctrl
1920 .read(SMx_EXECCTRL::SIDE_PINDIR)
1921 );
1922 debug!(
1923 "{}",
1924 self.registers.sm[sm_number as usize]
1925 .pinctrl
1926 .read(SMx_PINCTRL::SIDESET_BASE)
1927 );
1928 }
1929
1930 pub fn read_dbg_padout(&self) -> u32 {
1931 self.registers.dbg_padout.read(DBG_PADOUT::DBG_PADOUT)
1932 }
1933
1934 pub fn read_fdebug(&self, tx: bool, stall: bool) -> u32 {
1935 if tx {
1936 if stall {
1937 self.registers.fdebug.read(FDEBUG::TXSTALL)
1938 } else {
1939 self.registers.fdebug.read(FDEBUG::TXOVER)
1940 }
1941 } else if stall {
1942 self.registers.fdebug.read(FDEBUG::RXSTALL)
1943 } else {
1944 self.registers.fdebug.read(FDEBUG::RXUNDER)
1945 }
1946 }
1947 }
1948}