The rp2040 is an amazing chip and the two PIO units are powerful! However, as I try to learn the exact timing, it's hard to get it right. For example, I see this helpful image in this repo:
But, it's hard to follow exactly the exact timing, because we have D+ and D- and then the inverses of them (since their pins are inverted), etc. It's also hard for me to see exactly when the bits flip exactly how that impacts the PIO instructions. I've read through the data sheet, but it doesn't totally help answer my questions such as exactly when do instructions meet certain conditions and move to the next instruction or perform a jump.
Is there anyone here that understands at least the rx_pio code enough (and has some spare time) to be able to describe in more detail the actual PIO instructions below?
A few questions I have are:
1) Who fires the IRQ_RX_EOP interrupt?
2) When exactly does a command like jmp pin start move to the next instruction? If the pin is high for 3.05 cycles, does the jmp program move to the next instruction at the 4th cycle? Or, since the condition is still true at the start of the 3rd cycle and first fails when checking at the start of the 4th cycle, do we have to wait for that cycle to complete and then run the next instruction at the 5th cycle? I have the same question for wait instructions.
3) Maybe it would be easier to take one of the cases, such as only FS (Full speed) mode of USB and summarize the code from that context. Also, because we have FS and LS here and D+ and D- and they are also inverted, it is just sort of melting my brain trying to map it all out.
If someone could describe in detail what the 17 instruction edge detection program and the 15 instruction NRZI decoder are doing, it would be extremely helpful.
I think there might be many others that would also benefit from reading through a clear description.
Sorry to ask for something that seems like I should "do on my own", I've spent about 10 days looking at these 32 instructions and my (apparently) small brain is still having a problem understanding them.
If someone has the time to write up a quick summary, it would be greatly appreciated. Thanks!
.define public IRQ_RX_BS_ERR 1 ; bit stuffinc error
.define public IRQ_RX_EOP 2 ; eop detect flag
.define public IRQ_RX_START 3 ; packet start flag
.define public IRQ_DECODER 4 ; NRZI decoder trigger
.define db0 0
.define db1 1
; --[ edge detector ]---------------------------------------------------------
; USB signal edge and eop detector (17 instructions)
; FS(12M) LS(1.5M)
; Run at 96MHz 12MHz
; jmp_pin D- D+
; in_pin D+ D-
;
; both D+ and D- pins should be input invert overridden
.program usb_edge_detector
.side_set 1
eop:
irq wait IRQ_RX_EOP side db0 ; TODO: who triggers this irq?
start:
jmp pin start side db1 ; wait for a falling edge
irq IRQ_RX_START [1] side db0 ; see pio_usb_device.c?
.wrap_target
pin_still_low:
irq IRQ_DECODER [1] side db0 ; trigger NRZI decoder
; resync on rising edge
pin_low:
jmp pin pin_went_high side db1
pin_went_low:
jmp pin pin_went_high side db1
jmp pin pin_went_high side db1
jmp pin pin_went_high side db1
jmp pin pin_went_high side db1
jmp pin pin_went_high side db1
.wrap
pin_still_high:
mov x isr [2] side db1
jmp x-- eop side db1 ; jump to eop if jmp_pin and in_pin are high because both inputs are inverted
; jump here on rising edge
pin_went_high:
mov isr null side db1
in pins 1 side db0 ; capture pin to check for eop
irq IRQ_DECODER side db0 ; trigger NRZI decoder
jmp pin pin_still_high side db0
jmp pin_went_low side db1 ; jump to pin_went_low (not pin_low) to adjust interval of decoder trigger
.wrap
; --[ NRZI decoder ]----------------------------------------------------------
; USB NRZI data decoder (15 instructions)
; FS(12M) LS(1.5M)
; Run at as fast as possible
; jmp_pin D+ D-
;
; both D+ and D- pins should be input invert overridden
;
; NOTE: you must fill OSR by 1 and set 0 to x before runnning this program
.program usb_nrzi_decoder
.side_set 1 opt
start:
; set x 0 side db0
.wrap_target
set_y:
set y 6
irq_wait:
wait 1 irq IRQ_DECODER ; wait for edge detector
jmp pin pin_high
pin_low:
jmp !y flip side db0 ; ignore stuffed bit (no error)
jmp !x K1 side db0
K2:
; x == 1
in null 1
jmp flip
K1:
; x == 0
in osr 1
jmp y-- irq_wait
pin_high:
jmp !y flip side db1 ; ignore stuffed bit (no error)
jmp !x J1 side db1
J2:
; x == 1
in x 1
jmp y-- irq_wait
J1:
; x == 0
in null 1
flip:
mov x ~x
.wrap
The
rp2040
is an amazing chip and the two PIO units are powerful! However, as I try to learn the exact timing, it's hard to get it right. For example, I see this helpful image in this repo:But, it's hard to follow exactly the exact timing, because we have D+ and D- and then the inverses of them (since their pins are inverted), etc. It's also hard for me to see exactly when the bits flip exactly how that impacts the PIO instructions. I've read through the data sheet, but it doesn't totally help answer my questions such as exactly when do instructions meet certain conditions and move to the next instruction or perform a jump.
Is there anyone here that understands at least the
rx_pio
code enough (and has some spare time) to be able to describe in more detail the actual PIO instructions below?A few questions I have are:
1) Who fires the
IRQ_RX_EOP
interrupt? 2) When exactly does a command likejmp pin start
move to the next instruction? If the pin is high for 3.05 cycles, does thejmp
program move to the next instruction at the 4th cycle? Or, since the condition is still true at the start of the 3rd cycle and first fails when checking at the start of the 4th cycle, do we have to wait for that cycle to complete and then run the next instruction at the 5th cycle? I have the same question forwait
instructions. 3) Maybe it would be easier to take one of the cases, such as only FS (Full speed) mode of USB and summarize the code from that context. Also, because we have FS and LS here and D+ and D- and they are also inverted, it is just sort of melting my brain trying to map it all out.If someone could describe in detail what the 17 instruction edge detection program and the 15 instruction NRZI decoder are doing, it would be extremely helpful.
I think there might be many others that would also benefit from reading through a clear description.
Sorry to ask for something that seems like I should "do on my own", I've spent about 10 days looking at these 32 instructions and my (apparently) small brain is still having a problem understanding them.
If someone has the time to write up a quick summary, it would be greatly appreciated. Thanks!