4

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?

1 Answers1

1

The Raspberry Pi 3 has multiple cores that all share the same bus and peripherals.

So when some other core uses the bus or locks things down for exclusive access your code will be blocked for short times and that's probably what you see.

To verify try disabling the other cores before you start big banging.