I want to write a bit-banging driver for a Raspberry Pi 3. For testing I developed a simple Linux kernel mode driver which toggles a GPIO pin with approx. 1Mhz. Here is the code excerpt.
static ssize_t dev_write(struct file *filep, const char *buffer, size_t len, loff_t *offset)
...
volatile int k;
spin_lock_irqsave(&my_lock, flags);
// also disable FIQ
asm volatile ("mrs %0, cpsr": "=r" (mycpsr):);
asm volatile ("msr cpsr, %0": : "r" (mycpsr | 0x000000C0));
while(1)
{
iowrite32(32, (u8*)gpio+0x200000+0x1c);
for(k=0;k< 100;k++);
iowrite32(32, (u8*)gpio+0x200000+0x28);
for(k=0;k< 100;k++);
}
...
In order to get no interference by the Linux kernel, I disabled IRQ and FIQ before entering the toggling loop. I have also set CPU speed fix to 1.2Ghz. Then I monitor the GPIO pin with a scope. If I trigger the scope by pulse-width > 2, I can see gaps of different length, which sometimes last longer than 5 us (seems to depend on load for the other cores)
On a Rasperry Pi Zero no such effect occurs. The signal is total clean and stays at a stable frequency.
As I have disabled all interrupts, my Linux driver is running like a bare-metal OS. So I assume that the delays must be a pure hardware effect (e.g. cache misses ?).
Can anyone explain me how the hardware is causing such long delays?