-
Notifications
You must be signed in to change notification settings - Fork 4.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
SPI speed ~2x slower than it should be on RPi 4 #3381
Comments
The SPI clock is a divided down version of the core clock. If you want to force the full speed of SPI you need to about core clock from clocking down.
or
Or from the arm:
|
Is 50 kHz the best it can do when slowed down? In all cases when running the test, the system was otherwise idle - if requesting 200kHz, the system managed to run SPI at 80kHz, this seems like a bug - it should be able to get something closer to 100kHz when being asked for 100kHz... |
The core clock changes outside of the spi driver's knowledge. Typically core_freq=500 core_freq_min=200. |
The SPI interfaces (and I2C and UART1) share the same clock as the VPU cores; if the VPU clock frequency changes, so does the SPI clock. The Linux SPI driver is unaware of these clock changes, so to avoid a bus speed which is too high the clock divisor is calculated for the turbo speed, but when running at the normal speed the divisor is too high with the result that the bus clock is too slow. Locking the VPU/core clock to a fixed value allows the divisor to be correctly calculated without affecting the ARM clock speeds. |
What are default frequencies for RPi 3B+ and RPi 4? Does |
Pi4 uses 200MHz for and and all older Pi's 250MHz. gpu_freq=250 will have stable frequency on Pi0-3.
You'll have marginally higher temperatures due to the higher clock when idle, and no change when arm is busy. |
I see, I assumed the communication or some other drivers would be handling clock changes not to impact the communication too much. Is there something that can be added to a device tree overlay EEPROM to ensure a minimum clock speed, so we can make sure that the SPI communication is within minimum and maximum allowable range? |
FYI: there are two functions that might be of interest here. You can register a notifier for clock and/or cpu frequenctychange |
@marckleinebudde I suspect those are for monitoring CPU-side clock changes, whereas the issue here is GPU-side clock changes (since the SPI, I2C and UART1 peripherals are running off the VPU clock rather than the CPU clock, as @pelwell describes above). |
@lurch I'm not familiar with the raspi clock tree, but if the GPU-side clock is not mapped to the linux clock framework, this doesn't work. |
The raspberrypi-clk driver sends all requests to the VPU/GPU, so it's well aware of what is changing. |
I am also seeing about half the SPI sampling rate on my Pi 4 when compared against my Pi 3B+. I have tried to implement the suggestions made by @popcornmix on my Pi 4 running Raspberry Pi OS (kernel 5.4.83-v7l+), and they don't seem to have any impact on the sampling rate. The Pi docs suggest setting the Any other ideas? |
Raspberry Pi OS is now using a 5.10 kernel... http://downloads.raspberrypi.org/raspios_armhf/release_notes.txt |
I upgraded to |
FYI, I continued to do some more testing on my Pi 4B. Both kernel version 5.4.x and 5.10.x exhibited the same issue with SPI data rates. I went back to using kernel version 4.19 and the issue is gone. For the record, using For future readers, assuming this issue goes unresolved...UPDATE: (June, 2022) This may no longer be a suitable workaround if you have a newer Pi with a newer bootloader. I've had trouble getting the newer bootloaders to boot 4.x kernels, but I can't find any documentation about bootloader/kernel support.The command (on a Raspberry Pi running Raspberry Pi OS) to install a specific kernel is:
... where <hash> is the commit hash from the following GitHub repository that correlates to the specific kernel version you want to install: So, to install v4.19.118, the command is: Simply press |
I have been experimenting with SPI driving NeopIxels from RPI mostly using pi zero and didn’t really see this issue. But when I tried on a pi 4 I had the same issue with the pulses being too slow. same cause the cpu clock was slowing ( much wider range on pi4 over piZero). in practice I also found that it helped to check the speed at the end, and if it changed then I just did a retry. in my case I drive 20+ NeopIxels with no observable issues. note I also found that a pull down resistor on the SPI pin from the pi helped with stray cases. |
Has this been addressed in the recent 5.15.44 kernel? |
Hi, |
@janvanhulzen, thanks for sharing the pics with everyone. (Additional context about your setup, and specific kernel version would be helpful) I just ran a test on the latest Raspberry Pi OS Lite build (Sept 6 '22), kernel Without modifying the clock settings, the SPI clock is all over the place. I would check the CPU frequency immediately before running an spidev test at 1MHz and I can clearly see correlation between CPU clock speed and SPI clock speed.
(where The results of the SPI clock speed, as measured by my scope on the SCLK pin, at various CPU clocks are as follows:
You can see that the final result where the CPU clock is at its peak is the only result remotely near the requested 1 MHz SPI clock. So, I tested with The C driver for the SPI interface demonstrates, at least, that kernel In my application that uses the Python |
I notice that on Pi 5 the SPI speed seems to be constant, regardless of CPU scaling and current CPU frequency, while Pi 4 and earlier models keep changing the speeds. Is it possible for a kernel module to know that it is running on a Pi 5? (Or have a device tree overlay dedicated for Pi 5 and the rest of the Pis which would pass a param to the kernel module? (in particular, I'd like to pass the SPI baud rate to use for different models)) |
FWIW, I'm observing what I presume is the same issue on an RPi4 running Debian 1:6.1.63-1+rpt1 (2023-11-24). From a python script, using the spidev package, I can start the SPI SCK at 50 MHz, but about six seconds later, it drops down to 20MHz. Needless to say, I didn't expect this behavior. Here's the CPU info in case it is useful to anyone:
|
@rdpoor the solutions are any one of the following:
Boost the minimum core frequency. Add to config.txt
Force turbo. Add to config.txt
|
The SPI transfer speed used on RPi4 is 2 times slower (50kHz) than requested for example here: https://github.com/raspberrypi/linux/blob/rpi-4.19.y/sound/soc/bcm/pisound.c#L329 (100kHz)
On RPi4, requesting 100000 Hz produces 50kHz communcation speed. Changing the requested speed to 200000 Hz, on RPi4 it first starts at 80kHz, then at some point it switches to 100kHz, so that means RPi4 is capable of using exactly 100kHz.
On RPi3B+, requesting 100000 yields 62.5kHz speed. Requesting 200000 gives 125kHz. I assume RPi3B+ does not have in-between speeds like RPi4.
The question (and bug) is - why does RPi4 pick 50kHz when requested 100kHz instead, even though it can be seen being capable of 80kHz and 100kHz speeds.
To reproduce
Without any hat connected, you may run spidev_test to test drive /dev/spidev.0.0. Either an oscilloscope or logic analyzer can be connected to SCK line to measure the frequency, or it can very roughly be inferred based on the reported data rate and the duration of execution. Here are test results of sending 80000 bytes in 16 byte transfers using 100kHz and 200kHz requested speeds on RPi4 and 3B+, they contain SPI logic analyzer timed output, as well as the spidev_test invocation, results and additional notes at the very bottom.
spi_test_results.zip
100kHz RPi4
100kHz RPi3B+
200kHz RPi4
200kHz RPi3B+
As can be seen from the results of same command being executed on RPi3B+ and RPi4, the tests finish significantly faster on RPi3B+.
Expected behaviour
100kHz gets picked when requesting 100kHz speed, or at least something closer like 80kHz.
System
RPi 3B+ and RPi 4 using latest Raspbian Lite running:
Linux raspberrypi 4.19.88-v7+ #1284 SMP Wed Dec 11 13:46:41 GMT 2019 armv7l GNU/Linux
The text was updated successfully, but these errors were encountered: