Parallel bus sync without interrupts

I am writing code to create a parallel bus between two boards nucleo and arduino. However their is some sync issue which i do not know how to solve i have a feel that because the nucleo is so much faster than the arduino that many messages get sent before the appropriate flag can be set.

the idea is that flag1 (f1) will go high when a message is ready set by the nucleo and wants the arduino to read it. then when the arduino has finished reading it will set flag2 high (f2) so that the nucleo knows that it can change its pins. I am trying to avoid interrupts in this code as i want both of the MCUs to be at certain point in their code when they transfer the data.

mbed code

#include "mbed.h"

DigitalOut b1(D1);
DigitalOut b2(D2);
DigitalOut b3(D3);
DigitalOut b4(D4);
DigitalOut b5(D5);
DigitalOut b6(D6);
DigitalOut b7(D7);
DigitalOut b8(D8);
DigitalOut f1(D9);
DigitalIn f2(D13);
    
void send_msg(uint8_t msg){
    if(msg&1) b1 = 1;
    if((msg>>1)&1) b2 = 1;
    if((msg>>2)&1) b3 = 1;
    if((msg>>3)&1) b4 = 1;
    if((msg>>4)&1) b5 = 1;
    if((msg>>5)&1) b6 = 1;
    if((msg>>6)&1) b7 = 1;
    if((msg>>7)&1) b8 = 1;
    f1=1;
    while(f2.read()<0.5){
        printf("%f\r\n",f2.read());
    }

    ***
    wait_us(20);
    ***

    f1=0;b1=0;b2=0;b3=0;b4=0;b5=0;b6=0;b7=0;b8=0;
}
 
int main(){
    while(1){
        for(int i = 0; i<256; i++){
            send_msg(i);
        }
        while(1){}
    }
}

Arduino code

#include <SPI.h>

// using two incompatible SPI devices, A and B. Incompatible means that they need different SPI_MODE
const int b1 = 36;
const int b2 = 50;
const int b3 = 48;
const int b4 = 46;
const int b5 = 44;
const int b6 = 42;
const int b7 = 40;
const int b8 = 38;
const int f1 = 34;
const int f2 = 30;


void setup() {
  
  pinMode(b1, INPUT);
  pinMode(b2, INPUT);
  pinMode(b3, INPUT);
  pinMode(b4, INPUT);
  pinMode(b5, INPUT);
  pinMode(b6, INPUT);
  pinMode(b7, INPUT);
  pinMode(b8, INPUT);
  pinMode(f1, INPUT);
  pinMode(f2, OUTPUT);
  SPI.begin();
  Serial.begin(9600);
  Serial.println("boot");
}

uint8_t sample[256];
int i = 0;

void loop(){
  while(1){
    if(digitalRead(f1)==HIGH){
      //Serial.println("if(digitalRead(f1)==HIGH)");
      sample[i] = read_byte();
      Serial.println(sample[i]);
    }
  }
}

uint8_t read_byte(){
  uint8_t Byte = 0;
  if(digitalRead(b8)==HIGH){
   Byte+=1;}
  for(int i = 40;i < 51;i=i+2){
    if(digitalRead(i)==HIGH){
     Byte=(Byte<<1)+1;}
    else{
      Byte=(Byte<<1);}
  }
  if(digitalRead(36)==HIGH){
   Byte=(Byte<<1)+1;}
  else{
    Byte=(Byte<<1);}
    
  //Serial.println("digitalWrite(f2,HIGH)");
  digitalWrite(f2,HIGH);
  //Serial.println("while(digitalRead(f1)==HIGH)");
  while(digitalRead(f1)==HIGH){}
  digitalWrite(f2,LOW);
  //Serial.println("(digitalRead(f1)==LOW)");
  return Byte;
}

image

Edit i found a solution to use a 20 microsecond delay however this feels crude and possibly unreliable? I will put in the delay wrapped in ** if it helps andbody else wanting to do somthing simular i couldnt find anything elsewhere about similar techniques.

Is there a particular reason you’re using a parallel interface?

It uses (wastes?) many more I/O pins and if you have to insert 20ms delay then there’s no speed advantage over, say, a serial connection…

In any case a few things come to mind:

Your test of f2 looks like comparing an analogue value(?). A ‘digital in’ variable can be compared to 1 or 0 for hi & lo respectively.

You should only need 1 signalling line which can function as arduino free/ready (=1 or HI), busy (=0 or LO). This could be controlled by the Arduino. So the pseudocode of each side could look like:

Nucleo:

DigitalIn f2(D13);
// config other pin definitions as you like

main() {
    while(1) {
      if(f2 ==1) {
         write_parallel_pins();
    }
}

Arduino:

setup() {
   pinMode(int f2, OUTPUT);
   f2 = 0;
   // other stuff
}

main() {
   while(1) {
      f2 = 0;
      read_parallel_pins();
      f2 = 1;
   }
}

The nucleo side should be able to be easily done in an interrupt (f2 falling edge) so it can do other things if necessary.

Not sure if I understood your problem, but hope it helps anyway.