Are you saying you toss the SPI hardware and bit bang the I/O port at the bit level?
... AND still run all the other functions in the rPi?
Are you saying you toss the SPI hardware and bit bang the I/O port at the bit level?
... AND still run all the other functions in the rPi?
No. I use the Linux kernel drivers which have slowly been improving in recent years. However what you can do is drive the SPI hardware directly
- not bit-bang, but fill up the FIFO yourself, poke the command into the start register, poll the Tx complete flag and so on. Currently, the Linux kernel drivers achieve about 12K transfers/sec on small transfers - obviously with the size of the transfer increasing the overall transfer speed increases as latency then isn't a major factor.
I have a new SPI driver to go into wiringPi to do this as an alternative to the kernel driver, but it's not complete yet. The main issue then is that it will consume 100% cpu during the transfer - which might be OK for small 2-4 byte data exchanges between e.g. an ADC but somewhat sub-optimal when sending 250K bytes to a display.
One thing you can not accurately do in user-land is percise timing. This is due to the nature of the multi-user, multi-tasking operating system, however it's do-able if you write a kernel module. (So using an SPI device to accurately sample at 1K samples/sec is not going to work well - it will work, but jitter will be high)
My little record playback example works as it exchanges the same number of bytes to read as to write over the SPI bus and it runs at the max. speed I can push the SPI bus at - which in that example, ~2 years ago was just over 8K samples/sec. All I did was read & stire in a tight loop until I'd read in a few KB of samples, then play it back in a similarly tight loop. No timing in the loop.
Yes. I observed my software PWM driver using about 1% cpu per pin. There are hardware tricks to use all pins via a hybrid driver too which abuses a DMA channel and so uses virtually no CPU (but it steals a little bit of memory bandwidth) - all do-able from userland, but my code doesn't do that yet.
Gordon
I think the real shortcoming of the code I've seen so far is that it doesn't make full use of the hardware. I have not read all the details (partly because the docs are not 100% clear on the details) but it looks to me like the DMA should be able to handle all the data movements and if it can be coupled to a timer the timing should be a lot more deterministic (important for ADC/DAC use).
Essentially, it is better to just not use the software since the CPU is shared across every task running. But hardware is dedicated.
For the LED multiplexer DMA would be both optimal and straightforward. I'm just not sure how to tie it to a timer. If you have to trigger each DMA transfer with software I'm not sure that would be useful since it would need to run at kHz rates.
In your code how did you set the timing of your multiplexing?
I'm not convinced. The SPI FIFO is 16 bytes deep. Most SPI transactions are going to be less than 16 bytes - e.g. to red a 12-bit ADC needs an SPI exchange of just 3 bytes.
The longer transactions take an interrupt every 16 bytes - and that's fine - I did a driver for an LCD display that used SPI and the overhead of sending a framebuffer to the display (about 240K bytes) was minimal.
So I fear you're chasing the wrong thing.
When I last looked at the kernel driver, it suggested there may be an issue with the hardware, so rather than kick off the transaction it kicked off a zero length transaction then released - and waited for the next interrupt to come in from the hardware to do the proper transaction - hence adding to the latenct. Fix that and it will fly.
Avoid premature optimisations...
Why not look at it?
cd git clone git://git.drogon.net/wiringPi
You'll find softPwm.c in there. There's no real magic.
Also look for the file 7segments.c - referenced in this article:
Gordon
I don't think you understand some of the issues involved in using ADC/DACs. Look up simultaneous sampling. Multiple interrupts won't hack it.
I'm not sure what you mean. Even if you get the SPI driver running with less latency, the timing is horrible because of all the issues of doing this under a non-real time system. To control the multiplexing of the display being discussed also requires control of the timing, although no where near as good as ADC/DAC data. Still, the brightness of each LED is directly proportional to the time it is on. Give control of that to the software and I expect it will not look as good as the OP wants. Heck he is talking about using constant current sources. No point if the timing is not controlled.
Why not just tell me? What controls the timing of the multiplexing?
I couldn't remember whether it did or not.
Good point, though I'll probably stick with I2C, since PICAXEs can act as I2C slaves and, if I go that way, I'd want the RPi to talk to more than one of them: they are quite a neat way of implementing the slave part of the non-clock control task I've mentioned.
Sounds good. Thanks for that.
C for me every time, except on PICAXEs or STAMPs.
Good point. Thanks.
I wrote some general purpose routines in VFX Forth for ARM Linux in user space and achieved toggle frequencies (low-high-low) in excess of 10 MHz. Using code for specific pins should give output in the range of 15-20 MHz. Using I2C or SPI at around 1MHz should be very doable.
Other data available supports these caims. Somewhere there's a comparison of many methods of bit-banging.
Stephen
Have something to add? Share your thoughts — no account required.
Ask the community — no account required