Discussion:
uP port mapping
(too old to reply)
Theo
2024-09-12 16:43:04 UTC
Permalink
Suppose we have a c program running on some little uP, and it has some
integer variable value, 8 or 12 bits or something, and wants to drive
a parallel DAC off-chip.
The msb...lsb bits of the variable obviously have to get to the right
pins of the DAC.
So, in general, how does one pick the physical i/o port pins on the
uP, to get the order right? The PCB layout is easiest if we just wire
the DAC to the handiest port pins.
A lot of MPUs have 'ports', ie you don't have individual GPIOs, but P0.0 to
P0.7, P1.0-P1.7, etc. You can write to a whole 8 bit port in a single
operation. That way you know to wire up P0.0 to the LSB of your DAC and
P0.7 to the MSB, or maybe use P1.0-1.3 for the upper 4 bits.

Slightly surprisingly I don't see that on the RP2040 datasheet, it looks
like you can only set single bits at a time. It seems you have to use the
PIOs to get parallel transfers. Maybe you can also do something with DMA?

There's a 'PIO and DMA (a logic analyser)" in 3.2.3 of the C/C++ SDK doc:
https://datasheets.raspberrypi.com/pico/raspberry-pi-pico-c-sdk.pdf

which says:

"Pin Groups (Mapping)
We mentioned earlier that there are four pin groups to configure, to connect a state machine’s internal
data buses to the GPIOs it manipulates. A state machine accesses all pins within a group at once, and
pin groups can overlap. So far we have seen the out, side-set and in pin groups. The fourth is set.
The out group is the pins affected by shifting out data from the OSR, using out pins or out pindirs, up to
32 bits at a time. The set group is used with set pins and set pindirs instructions, up to 5 bits at a time,
with data that is encoded directly in the instruction. It’s useful for toggling control signals. The side-set
group is similar to the set group, but runs simultaneously with another instruction. Note: mov pin uses
the in or out group, depending on direction."

and 3.2.5 in the RP2040 datasheet says:

"3.2.5. Pin Mapping
PIO controls the output level and direction of up to 32 GPIOs, and can observe their input levels. On every system clock
cycle, each state machine may do none, one, or both of the following:
• Change the level or direction of some GPIOs via an OUT or SET instruction, or read some GPIOs via an IN instruction
• Change the level or direction of some GPIOs via a side-set operation
Each of these operations is on one of four contiguous ranges of GPIOs, with the base and count of each range
configured via each state machine’s PINCTRL register. There is a range for each of OUT, SET, IN and side-set operations.
Each range can cover any of the GPIOs accessible to a given PIO block (on RP2040 this is the 30 user GPIOs), and the
ranges can overlap.
For each individual GPIO output (level and direction separately), PIO considers all 8 writes that may have occurred on
that cycle, and applies the write from the highest-numbered state machine. If the same state machine performs a SET
/OUT and a side-set on the same GPIO simultaneously, the side-set is used. If no state machine writes to this GPIO
output, its value does not change from the previous cycle.
Generally each state machine’s outputs are mapped to a distinct group of GPIOs, implementing some peripheral
interface."

so I suppose you want all of your pins consecutively in the same pin group.

It looks like this example does parallel output:
https://github.com/raspberrypi/pico-examples/blob/master/gpio/hello_7segment/hello_7segment.c
via gpio_set_mask() (set to high all the bits in the mask) and gpio_clr_mask()
but I wouldn't say for sure that it's atomic.

Theo
The Natural Philosopher
2024-09-12 17:24:41 UTC
Permalink
Post by Theo
Suppose we have a c program running on some little uP, and it has some
integer variable value, 8 or 12 bits or something, and wants to drive
a parallel DAC off-chip.
The msb...lsb bits of the variable obviously have to get to the right
pins of the DAC.
So, in general, how does one pick the physical i/o port pins on the
uP, to get the order right? The PCB layout is easiest if we just wire
the DAC to the handiest port pins.
A lot of MPUs have 'ports', ie you don't have individual GPIOs, but P0.0 to
P0.7, P1.0-P1.7, etc. You can write to a whole 8 bit port in a single
operation. That way you know to wire up P0.0 to the LSB of your DAC and
P0.7 to the MSB, or maybe use P1.0-1.3 for the upper 4 bits.
Slightly surprisingly I don't see that on the RP2040 datasheet, it looks
like you can only set single bits at a time. It seems you have to use the
PIOs to get parallel transfers. Maybe you can also do something with DMA?
https://datasheets.raspberrypi.com/pico/raspberry-pi-pico-c-sdk.pdf
"Pin Groups (Mapping)
We mentioned earlier that there are four pin groups to configure, to connect a state machine’s internal
data buses to the GPIOs it manipulates. A state machine accesses all pins within a group at once, and
pin groups can overlap. So far we have seen the out, side-set and in pin groups. The fourth is set.
The out group is the pins affected by shifting out data from the OSR, using out pins or out pindirs, up to
32 bits at a time. The set group is used with set pins and set pindirs instructions, up to 5 bits at a time,
with data that is encoded directly in the instruction. It’s useful for toggling control signals. The side-set
group is similar to the set group, but runs simultaneously with another instruction. Note: mov pin uses
the in or out group, depending on direction."
"3.2.5. Pin Mapping
PIO controls the output level and direction of up to 32 GPIOs, and can observe their input levels. On every system clock
• Change the level or direction of some GPIOs via an OUT or SET instruction, or read some GPIOs via an IN instruction
• Change the level or direction of some GPIOs via a side-set operation
Each of these operations is on one of four contiguous ranges of GPIOs, with the base and count of each range
configured via each state machine’s PINCTRL register. There is a range for each of OUT, SET, IN and side-set operations.
Each range can cover any of the GPIOs accessible to a given PIO block (on RP2040 this is the 30 user GPIOs), and the
ranges can overlap.
For each individual GPIO output (level and direction separately), PIO considers all 8 writes that may have occurred on
that cycle, and applies the write from the highest-numbered state machine. If the same state machine performs a SET
/OUT and a side-set on the same GPIO simultaneously, the side-set is used. If no state machine writes to this GPIO
output, its value does not change from the previous cycle.
Generally each state machine’s outputs are mapped to a distinct group of GPIOs, implementing some peripheral
interface."
so I suppose you want all of your pins consecutively in the same pin group.
https://github.com/raspberrypi/pico-examples/blob/master/gpio/hello_7segment/hello_7segment.c
via gpio_set_mask() (set to high all the bits in the mask) and gpio_clr_mask()
but I wouldn't say for sure that it's atomic.
Theo
I read something that indicates that groups of pins have their own tiny
processor! You dont talk to the pins, you talk to the processor instead.
--
Climate Change: Socialism wearing a lab coat.
john larkin
2024-09-12 19:35:15 UTC
Permalink
On Thu, 12 Sep 2024 18:24:41 +0100, The Natural Philosopher
Post by The Natural Philosopher
Post by Theo
Suppose we have a c program running on some little uP, and it has some
integer variable value, 8 or 12 bits or something, and wants to drive
a parallel DAC off-chip.
The msb...lsb bits of the variable obviously have to get to the right
pins of the DAC.
So, in general, how does one pick the physical i/o port pins on the
uP, to get the order right? The PCB layout is easiest if we just wire
the DAC to the handiest port pins.
A lot of MPUs have 'ports', ie you don't have individual GPIOs, but P0.0 to
P0.7, P1.0-P1.7, etc. You can write to a whole 8 bit port in a single
operation. That way you know to wire up P0.0 to the LSB of your DAC and
P0.7 to the MSB, or maybe use P1.0-1.3 for the upper 4 bits.
Slightly surprisingly I don't see that on the RP2040 datasheet, it looks
like you can only set single bits at a time. It seems you have to use the
PIOs to get parallel transfers. Maybe you can also do something with DMA?
https://datasheets.raspberrypi.com/pico/raspberry-pi-pico-c-sdk.pdf
"Pin Groups (Mapping)
We mentioned earlier that there are four pin groups to configure, to connect a state machine’s internal
data buses to the GPIOs it manipulates. A state machine accesses all pins within a group at once, and
pin groups can overlap. So far we have seen the out, side-set and in pin groups. The fourth is set.
The out group is the pins affected by shifting out data from the OSR, using out pins or out pindirs, up to
32 bits at a time. The set group is used with set pins and set pindirs instructions, up to 5 bits at a time,
with data that is encoded directly in the instruction. It’s useful for toggling control signals. The side-set
group is similar to the set group, but runs simultaneously with another instruction. Note: mov pin uses
the in or out group, depending on direction."
"3.2.5. Pin Mapping
PIO controls the output level and direction of up to 32 GPIOs, and can observe their input levels. On every system clock
• Change the level or direction of some GPIOs via an OUT or SET instruction, or read some GPIOs via an IN instruction
• Change the level or direction of some GPIOs via a side-set operation
Each of these operations is on one of four contiguous ranges of GPIOs, with the base and count of each range
configured via each state machine’s PINCTRL register. There is a range for each of OUT, SET, IN and side-set operations.
Each range can cover any of the GPIOs accessible to a given PIO block (on RP2040 this is the 30 user GPIOs), and the
ranges can overlap.
For each individual GPIO output (level and direction separately), PIO considers all 8 writes that may have occurred on
that cycle, and applies the write from the highest-numbered state machine. If the same state machine performs a SET
/OUT and a side-set on the same GPIO simultaneously, the side-set is used. If no state machine writes to this GPIO
output, its value does not change from the previous cycle.
Generally each state machine’s outputs are mapped to a distinct group of GPIOs, implementing some peripheral
interface."
so I suppose you want all of your pins consecutively in the same pin group.
https://github.com/raspberrypi/pico-examples/blob/master/gpio/hello_7segment/hello_7segment.c
via gpio_set_mask() (set to high all the bits in the mask) and gpio_clr_mask()
but I wouldn't say for sure that it's atomic.
Theo
I read something that indicates that groups of pins have their own tiny
processor! You dont talk to the pins, you talk to the processor instead.
RP2040 has I think 2 PIO blocks and each has a couple of hardware
programmable state machines, and those can be set up to drive pins.
I'm mostly concerned now with a PCB schematic design, picking the
appropriate and easy-to-route pins from the CPU to things.

My general question, for various processors, is how to associate bits
in integer variables with physical pins on the chip.
Theo
2024-09-12 21:28:42 UTC
Permalink
Post by john larkin
RP2040 has I think 2 PIO blocks and each has a couple of hardware
programmable state machines, and those can be set up to drive pins.
I'm mostly concerned now with a PCB schematic design, picking the
appropriate and easy-to-route pins from the CPU to things.
My general question, for various processors, is how to associate bits
in integer variables with physical pins on the chip.
This is the function of a 'pinmux'. Different chips have different
capabilities of the pinmux, but it's rare to be able to connect any GPIO to
any pin - that's more FPGA territory. Typically the pinmux is just about
selecting one of multiple fixed functions for a given pin
(SPI1_MISO/I2C3_SDA/UART2_TX/...)

So either you route your DAC to consecutive pins (D0 to GPIOn, D1 to n+1,
..., ideally where n is a multiple of 8), or you're prepared to do the
necessary bit shuffling in software (which can be slow and non-atomic). I'd
suggest sticking to consecutive ordering if you can.

(although I have no experience of the RP2xxx GPIO/PIO shenanigans)

Theo
The Natural Philosopher
2024-09-13 08:36:31 UTC
Permalink
Post by Theo
Post by john larkin
RP2040 has I think 2 PIO blocks and each has a couple of hardware
programmable state machines, and those can be set up to drive pins.
I'm mostly concerned now with a PCB schematic design, picking the
appropriate and easy-to-route pins from the CPU to things.
My general question, for various processors, is how to associate bits
in integer variables with physical pins on the chip.
This is the function of a 'pinmux'. Different chips have different
capabilities of the pinmux, but it's rare to be able to connect any GPIO to
any pin - that's more FPGA territory. Typically the pinmux is just about
selecting one of multiple fixed functions for a given pin
(SPI1_MISO/I2C3_SDA/UART2_TX/...)
That is my understanding, too. What the pins do is programmable, but
not tire mappings to specific registers inside the processor
Post by Theo
So either you route your DAC to consecutive pins (D0 to GPIOn, D1 to n+1,
..., ideally where n is a multiple of 8), or you're prepared to do the
necessary bit shuffling in software (which can be slow and non-atomic). I'd
suggest sticking to consecutive ordering if you can.
Yes.
Post by Theo
(although I have no experience of the RP2xxx GPIO/PIO shenanigans)
I have - a very very little - but I have spent some time reading the
docs to see at least if the Pi PICO is suitable for various speculative
projects or not.

There is a massive amount of shit it *can* do that probably only one
person in a hundred would ever use.

It just so happens that driving parallel connected external logic is
something I have an interest in, so I read that bit... :-)
Post by Theo
Theo
--
Civilization exists by geological consent, subject to change without notice.
– Will Durant
The Natural Philosopher
2024-09-13 08:30:22 UTC
Permalink
Post by john larkin
RP2040 has I think 2 PIO blocks and each has a couple of hardware
programmable state machines, and those can be set up to drive pins.
I'm mostly concerned now with a PCB schematic design, picking the
appropriate and easy-to-route pins from the CPU to things.
It would be unusual for the pins in numerical order not to be part of
the same PIO block
So you might as well design the PCB that way.
Post by john larkin
My general question, for various processors, is how to associate bits
in integer variables with physical pins on the chip.
Well that is a software issue.
I thought that on the Pi PICO there was software to do a bulk set of pins

Yes.

https://www.raspberrypi.com/documentation/pico-sdk/hardware.html#functions70
There is a set pins by mask - mask is up to 32 bits - and clear pins by
mask.

So presumably if you invert the mask (XOR with FFFF) and clear with that
and set with the original mask and add a strobe pulse as well to latch
the data, its three calls in C....or have I misunderstood..not sure if
you can set AND clear simultaneously.

Now irrespective of whether the hardware supports more, that's as good
as you are going to get with the C SDK, and presumably only assembler is
faster. And presumably the actual gpio functions are written in
assembler anyway. So that (c gpio) will be as good as it gets.

What that leads to in respect of your original question is to treat the
gpio numbers as if they represented the bits in order.

https://forums.raspberrypi.com/viewtopic.php?t=326719

That conversation implies that they are.

So gpio 0-12 should e.g. go to the DAC lsb->msb set of bots.

These are all arranged in order down one side of the board, so it should
be easy

Good luck!
--
No Apple devices were knowingly used in the preparation of this post.
The Natural Philosopher
2024-09-12 15:29:13 UTC
Permalink
Suppose we have a c program running on some little uP, and it has some
integer variable value, 8 or 12 bits or something, and wants to drive
a parallel DAC off-chip.
The msb...lsb bits of the variable obviously have to get to the right
pins of the DAC.
So, in general, how does one pick the physical i/o port pins on the
uP, to get the order right? The PCB layout is easiest if we just wire
the DAC to the handiest port pins.
TBH once you go to at least 2 layer and dont worry about super small
size, that isn't very hard. You can use traces with via's as jumpers.
Once the board is done there is no added cost


Helped by the fact that the PIO pins on the boards go in order IIRC.
One could test and bit-bang each bit and port individually, and then
strobe the DAC, but that's inelegant.
Wastes CPU too.
In the RP2040 chip, one can apparently write to a register in a
PIO/state machine block, where each bit of the register can be
assigned to drive a physical port pin. I think there are some
constraints on the selected pins.
I think so, though I have not found the need to use it.
Obviously for deeply parallel operations that works. But modern
practice is to implement some sort of high speed serial bus.
In general that is fast enough for a DAC anyway
--
For in reason, all government without the consent of the governed is the
very definition of slavery.

Jonathan Swift
Loading...