You could do something like that with PIO, but it would be tricky to make it actually any better than you can get with SPI (and I've usually more important things wanting the PIO resource while the SPIs are spare - your usage may differ).Was looking at this a little more and I'm wondering about saving some GPIO pins and using a 74HC595 Shift register. I would need to research more but I though if I had a uint8_t that mapped to the output of the shift register I could just use a PIO to keep the outputs updated?
Is this something that would work the PIO would only be used to display what was in the uint8_t the flashing would be done with a timer or something.
So using SPI you can set the clock really quite fast (about 10MHz with 74HC running on 3V3, 130MHz if you went for 74LVC instead which is usually no more expensive). So even with the HC you can clock out a whole byte in less than 1us, and the SPI unit has a FIFO. So in practice you can just sling new values into the SPI FIFO without having to wait - at 10MHz, you should probably still call spi_writeN_blocking() but with confidence that it will never block in normal use; at clk_sys/2 it would be almost impossible to overflow the FIFO with real code.
To be able to toggle individual bits, software will need to maintain the current state in a variable; any change updates the variable and throws the updated value into the SPI FIFO. Maintaining that variable atomically is tedious if accessed from interrupts or both cores; I've used one of the small number of atomically updatable spare registers in the the watchdog unit to provide the atomic-update shadow register where I've needed that access (but you could just use interrupt-disable/spinlocks or whatever your environment needs).
How could the PIO improve this? It could give you fractionally improved latency in obscure cases - discarding extra values rather than shifting them out if you ever manage to get more than 2 items in the FIFO - and could maybe give you a guarantee that the FIFO never overflows even under extreme conditions (though the PIO instruction cost to ensure that is probably not worth paying). You'd like to make it so you could read-back the current state rather than having the separate tracking variable, but that's difficult to do. More useful (but different) might be to have the PIO program accept 'commands' rather than just values to be shifted out - "set bit n", "clear bit n", though that's again quite expensive in PIO instructions - maybe worth it if the things attached to the shift register are unrelated outputs that want to be set/cleared by different bits of code.
SPI can only handle two cascaded shift registers for 16 output bits (without the overhead of software having to toggle the nCS line - which ruins the 'fire and forget' nature of it). PIO could go to 32 bits (4 cascaded '595s) on the same basis.
Finally, '594 are often better than '595 (though more expensive) - the 594 has a pin to clear the outputs which can be used for a power-on reset to make sure the outputs power-up in a safe state, while the 595 just has an output tristate (and a clear for the shift register, which is useless in this application as it doesn't affect the outputs until you toggle the load).
Statistics: Posted by arg001 — Fri Jan 19, 2024 10:50 am