The test sketch writes a byte to 100 locations in SRAM, then reads back these 100 locations to check the byte value, which should be equal to the original byte written. The test sketch does this for bytes from 1 to 100. There's a total of 100*100 = 10000 write operations and 10000 read operations.
I thought I could figure out the time wasted from the Goofy Gopher code by
time wasted = T2 - 2*T1
T2 is the amount of time it takes to execute the sketch with both Anduino running. T1 is the amount of time it takes to execute the sketch with only one Anduino running, with no power to the second Arduino and pin 10 of that Arduino going to Vcc.
I'm using 2 Pro Mini running at 3.3 V and 8MHz.
My updated code
// Define SRAM Allocation:
// Name Offset SRAM Bytes
//-----------------------------------
#define Data1 0 // bytes 0 to 99
#define Data2 100 // bytes 100 to 199
// This is to define a very short delay:
#define NOP __asm__ __volatile__ ("nop\n\t")
/*
The sketch running on each arduino are almost identical.
Use #define Arduino1 to program Arduino 1
Comment out #define Arduino1 to program Arduino 2
*/
#define Arduino1 1
#include <SPI.h>
unsigned int Contentions_Avoided;
//--------------
void Start_SPI()
//--------------
{
volatile byte pin8;
/*
Use direct port manipulation so each Arduino can
grab the SPI lines as soon as possible.
DDRB - The Port B Data Direction Register - read/write
PORTB controls whether pins 8 to 13 are HIGH or LOW.
PINB reads the state of INPUT pins 8 to 13.
13 B5
12 B4
11 B3
10 B2
9 B1
8 B0
B6 and B7 are connected to the crystal! Don't touch.
*/
while(true)
{
pin8 = PINB & B00000001; // if(pin8 == 0) pin 8 is LOW else pin 8 is HIGH
while (pin8 == 0) pin8 = PINB & B00000001;
PORTB = PORTB & B11111011; // set pin 10 LOW
NOP; // short delay
pin8 = PINB & B00000001; // recheck pin 8
if (pin8 > 0) break; // if still HIGH then continue
PORTB = PORTB | B00000100; // else set pin 10 HIGH
Contentions_Avoided++;
}
DDRB = DDRB | B00101000; // set pins 11 and 13 as output
}
//-------------
void Stop_SPI()
//-------------
{
DDRB = DDRB & B11010111; // set pins 11 and 13 as input
PORTB = PORTB | B00000100; // set pin 10 HIGH
}
//---------------------------------
byte GetByte(int Offset, int Index)
//---------------------------------
{
unsigned int address;
byte data;
Start_SPI();
// Need a small delay between changing port directions
// and fisrt time use of the port.
address = Index + Offset; // Keep this line here.
SPI.transfer(3); // SRAM Read instruction
SPI.transfer((byte) (address >> 8));
SPI.transfer((byte) (address & 0xFF));
data = SPI.transfer(0);
Stop_SPI();
return data;
}
//---------------------------------------------
void PutByte(int Offset, int Index, byte value)
//---------------------------------------------
{
unsigned int address;
Start_SPI();
// Need a small delay between changing port directions
// and fisrt time use of the port.
address = Index + Offset; // Keep this line here.
SPI.transfer(2); // Write instruction
SPI.transfer((byte) (address >> 8));
SPI.transfer((byte) (address & 0xFF));
SPI.transfer(value);
Stop_SPI();
}
//----------
void setup()
//----------
{
byte Mode;
pinMode(8, INPUT);
pinMode(10, OUTPUT);
pinMode(11, OUTPUT);
pinMode(12, INPUT);
pinMode(13, OUTPUT);
//Set SPI chip select pins HIGH.
digitalWrite(10, HIGH);
// Begin SPI
SPI.beginTransaction(SPISettings(20000000, MSBFIRST, SPI_MODE0));
// In SPI_MODE0 (default the clock is normally low (CPOL = 0), and data
// is sampled on the transition from low to high (leading edge) (CPHA = 0)
delay(10);
DDRB = DDRB & B11010111; // set pins 11 and 13 as input
Serial.begin(115200); // start serial for output
// Read the SRAM Mode
Start_SPI();
SPI.transfer(5); // read mode instruction
Mode = SPI.transfer(0);
Stop_SPI();
//Default Mode = 64 or Sequential
#ifdef Arduino1
Serial.print(F("ARDUINO 1 "));
#else
Serial.print(F("ARDUINO 2 "));
#endif
Serial.print(F("SRAM Mode = "));
Serial.println(Mode);
}
//---------
void loop()
//---------
{
/*
Arduino 1 will write to data1 and read from data1
Arduino 2 will write to data2 and read from data2
*/
int i,j,k,l;
int data;
int ReadError, WriteError;
unsigned long ExecTime;
#ifdef Arduino1
data = Data1;
#else
data = Data2;
#endif
Contentions_Avoided = 0;
ReadError = 0;
WriteError = 0;
ExecTime = micros();
for (i = 1; i <= 100; i++)
{
for (j = 0; j < 100; j++) PutByte(data,j,i); // test write
for (j = 0; j < 100; j++) // test read
{
k = GetByte(data,j);
if (k != i)
{
l = GetByte(data,j);
if (k == l) WriteError++;
else ReadError++;
}
}
}
ExecTime = micros() - ExecTime;
Serial.print("ExecTime = ");
Serial.print(ExecTime);
Serial.print(" Contentions_Avoided = ");
Serial.print(Contentions_Avoided);
Serial.print(" ReadError = ");
Serial.print(ReadError);
Serial.print(" WriteError = ");
Serial.println(WriteError);
}
T2 is about 912.1 ms to 915.1 ms. Contentions_Avoided goes from about 30 to 100. ReadError and WriteError = 0.
T1 with Goofy Gopher code and data checking, execution time is about 604.8 ms.
time wasted = 915.1 ms - 2*604.8 ms = -294.5 ms
