The RP2350B processor contains a PIO engine that can be used to implement realtime communication protocol exchanges. This Go based project is one to help work with PIO sequences.
The package only supports assembling and disassembling known PIO instructions. The tests are extracted from known assembly output.
To explore:
$ git clone https://github.com/tinkerator/pious.git
$ cd pious
$ go test -v
=== RUN TestDisassemble
--- PASS: TestDisassemble (0.00s)
=== RUN TestAssemble
--- PASS: TestAssemble (0.20s)
PASS
ok zappem.net/pub/io/pious 0.204s
An example assembling and then disassembling a .pio
program:
$ go run examples/piocli.go --src pio/clock.pio
read: .program clock
read: set pindirs, 1
read: .wrap_target
read: set pins, 0 [1]
read: set pins, 1 [1]
read: .wrap
That output matches the pio/clock.pio
input.
The PIO Instruction set has 10 instruction types. One of these (nop
)
is a conventional alias for a pointless mov
instruction. Full
details are provided in the RP2350
Datasheet,
but we provide a quick summary here:
-
jmp
is the control flow jump instruction, it sets the next execution address. If it includes a condition then the condition must evaluate to true for the jump to be performed, otherwise PIO program execution continues at the next instruction. -
wait
causes execution of the PIO program to stall until some condition becomes true. The first argument, 1 or 0, indicates what polarity of value is being waited for. If omitted 1 is assumed. You can wait forgpio
,pin
,irq
orjmppin
(pin offset from some base index). -
in
shifts a counted number of bits into theisr
register. (Bit shift direction is a configuration setting for the executing state machine, and only refers to the end ofisr
that the bits are removed from.). The source of the bits is provided with the instruction and is one of:pins
,x
,y
,null
(zeros),isr
,osr
. If automatic push is enabled, thenisr
is pushed intorxfifo
when it is sufficiently empty. Operations stall in such cases when therxfifo
becomes full. -
out
shifts a counted number of bits out of theosr
register. (Bit shift direction is a configuration setting for the executing state machine, and only refers to the end ofosr
that the bits are inserted into.) The destination for the shift is one of:pins
,x
,y
,null
(discard),pindirs
,pc
,isr
,exec
. The shift wholly sets the destination register with unshifted bits being set to zero. In this way, we are setting the register with a subset of theosr
bits. If automatic pull is enabled, thenosr
is refilled fromrxfifo
when it is sufficiently empty, or stalls until something has been inserted into therxfifo
. -
push
can be used to more explicitly push (as opposed to automatic push) whole 32-bitisr
values into therxfifo
. -
pull
can be used to more explicitly pull (as opposed to automatic pull) whole 32-bitosr
values from therxfifo
. -
mov
is used to move between registers or a register:pins
,x
,y
,isr
,osr
, and an indexed element in therxfifo
. Some values can also be used as sources:null
,status
, and an indexed element of therxfifo
. Some values can also be used as destinations:pindirs
,exec
(force execution of a datum as an instruction),pc
(indirect jump). -
irq
generate an interrupt with the indicated index. -
set
sets a register value from an immediate 5-bit value. Larger values need to be provided throughout
ormov
operations.
Things I'm thinking about exploring:
-
Figure out how to generate
tinygo
compatible output. -
Support side-set feature: immediate side-effect setting of a pin (or up to 5 pins) when performing some other instruction. It is encoded in a way that limits the amount instructions can delay, and that limitation is a setting of the PIO state machine.
-
PIO simulator for debugging.
This is a personal project aiming at exploring the capabilities of the pico2-ice board. As such, no support can be expected. That being said, if you find a bug, or want to request a feature, use the github pious bug tracker.
See the LICENSE file: the same BSD 3-clause license as that used by golang itself.