Why is sched_yield() necessary to bitbang GPIO output on Rasperry Pi

44 Views Asked by At

I'm trying to implement a synchronous protocol to talk from my Pi (Model 3B V1.2) to a separate processor (6502/6522). I started by using pigpio. I observed that I have to insert calls to usleep(0) or sched_yield(). Otherwise the communication does not work correctly. So my solution works but it is much slower than expected.

To test if the problem is related to pigpio I switched to bcm2835 (https://www.airspayce.com/mikem/bcm2835/). The result is exactly the same: The calls to the functions is still necessary and the throughput is identical (bad).

So can anybody explain the cause behind this? And is there any way to get away with these calls?

The code to read a byte looks like this. GPIO_READ etc. are macros which direct to the function of pigpio or bcm2835. YIELD is a macro which uses usleep(0) or sched_yield(). I also tried a memory barrier via __sync_synchronize(). But this did not have any effect.

static void wait_data_ready_rx()
{
  while( GPIO_READ(PIN_DATAREADY_RX) != 0 ) {
    ;
  }
  YIELD;
}

static void data_taken_rx()
{
  GPIO_WRITE(PIN_DATATAKEN_RX, 0);
  YIELD;
  GPIO_WRITE(PIN_DATATAKEN_RX, 1);
}

static unsigned char read_byte()
{
  int bit;
  int bitno = 0;
  unsigned char byte = 0;

  for(bitno=0; bitno<8; ++bitno) {
    wait_data_ready_rx();
    bit = GPIO_READ(PIN_DATA_RX_0);
    byte = byte << 1 | bit;
    data_taken_rx();
  }
  return byte;
}

Update: Thank you for your hints. It really is a timing issue: A delay is necessary between the two GPIO_WRITE. It's a coincidence that sched_yield() is just the right time for this. This simply brought me on the wrong track.

In the meantime I think I understand the logic behind it. And I'm able to optimize the communication between the two computers.

0

There are 0 best solutions below