GPIO r/w on Due (84MHz) slower than on a M0 (48MHz)

hello,
why is GPIO r/w on Due (84MHz) slower than on a M0 (48MHz)?
I actually expected it to be almost up to 2x as fast as on an M0...

My test code

//--------------------------------------------
int32_t test_GPIO(){  // 6,000,000 r/w toggle GPIO plus counter
   volatile static bool w=false, r;
   uint32_t y;
   for (y=0; y<2000000; y++) {      
         digitalWrite(11, w);
         w=!w;
         r=digitalRead(13);
         digitalWrite(12, w&!r);      
   }
   return 1; // debug
}

shows the runtimes:

Arduino Due: 11787 ms
M0 (ItsyBitsy): 9734 ms

How can the Due GPIO r/w performance be (easily) enhanced?

Arduino functions such as digitalRead / digitalWrite are not designed to be fast, even on a DUE. You want to read carefully the PIO section of Sam3x datasheet to leverage the DUE GPIOs.

Providing you write an adapted code for a DUE, the result is much better (691 ms):

const uint32_t Read_Pos = 27;
const uint32_t Read_Mask = 1 << Read_Pos;
const uint32_t Pin11_Pos = 7;             
const uint32_t Pin12_Pos = 8;           

void setup() {
  Serial.begin(250000);
  
  pinMode(11, OUTPUT); //PD7
  pinMode(12, OUTPUT); //PD8
  // Enable writting on Pin 11 and Pin 12
  PIOD->PIO_OWER = (1 << Pin11_Pos) | (1 << Pin12_Pos);

  pinMode(13, INPUT);  // PB27

  uint32_t Timestamp = micros();
  YourGPIOTest();
  Timestamp = micros() - Timestamp;
  printf(" The 2000000 loop takes : %d us\n", Timestamp);
}

void loop() {

}

void YourGPIOTest(void) {

  static boolean Read, Write = false;

  for (int32_t Index = 2000000; Index > 0; Index--) {
    PIOD->PIO_ODSR = Write << Pin11_Pos;
    Write = !Write;
    Read = (boolean)((PIOB->PIO_PDSR & Read_Mask) >> Read_Pos);
    PIOD->PIO_ODSR = (Write & !Read) << Pin12_Pos; 
  }
}

yes, thank you, I already assumed that low-level bit read/write would be much faster on an ARM Cortex.
Also on a Mega2560, register bit r/w is 9x as fast as digitalRead/Write.

Nonetheless, back to my TO question:
why is digitalRead/digitalWrite so slow on Due, compared to a (by cpu clock) much slower M0/Zero?

My guess is that the guys at Arduino didn't try to leverage the Cortex M3 power for these super basic functions, so they ended up by adding abstraction layers to abstraction layers from the AVR boards.

do you think that this issue would be fixed when reported on github?

I don't think so....

General though: with this board (ARM Cortex M3 uc), there is a learning curve, get started with simple codes you can find on the DUE subforum and try (hard) to understand how that works under the hood. Don't expect to find libraries for all your projects, and even if you could, debugging requires a good deal of datasheet readings. Keep simple arduino functions for the parts of your projects that do not require substancial speed.

yes, I already noticed that many Arduino libs are not maintained for the Due.
Nevertheless, I admittedly expected the basic functions to work much faster than they actually do on the Due.

also fp arithmetics are just half as quick as they are supposed to work
https://forum.arduino.cc/index.php?topic=559309.msg3813919#msg3813919

  • and moreover, even much slower then on a M0, surprisingly...!

Your test shows a score ~3X faster for the DUE than the Mega with the basic functions you used.

The uc clock speed is not the only parameter to take into account to do the math for speed evaluation. As there is no Floating Point Unit on this M3, calculations with floats (double floats are not concerned with FPU anyway) are not supposed to be super fast unless you swap to fixed point arithmetics.

There are several ways to speed up calculations (or at least not slow down your code) like:

  • doing calculations while you process other DMA tasks with the board,
  • using as much as possible integer arithmetics (e.g. multiply all values by 10000 at the beginning and divide by 10000 at the end),
  • using as much as possible the few multiply and accumulate assembler instructions provided by the uc (1 to 3 clock cycle each if I can remember),
  • suspend interruptions during calculations,
  • using fixed point arithmetics according to the precision required,
  • ...

Every project is a trade off. Finally, what sort of speed do you really need ?

ard_newbie,
your post is misleading -

exactly because of clock speeds
M0/Zero 48 MHz
M3/Due 84 MHz

the GPIO r/w tests are not supposed to work slower for the even faster Due!
Either which counters or arithmetic calculations are performed additionally!

Also posted at:

If you're going to do that then please be considerate enough to add links to the other places you cross posted. This will let us avoid wasting time due to duplicate effort and also help others who have the same questions and find your post to discover all the relevant information. When you post links please always use the chain links icon on the toolbar to make them clickable.

FYI, you posted that issue to the wrong place. The correct one is the Arduino SAM Boards repo:

In fact, it's already been posted there:

that issue was originally posted in the arduino/Arduino repository when Arduino SAM Boards was part of that repo so you probably should have found it even there with a bit of searching.

dsyleixa:
do you think that this issue would be fixed when reported on github?

I wouldn't hold your breath. No Arduino employee has done any work on the SAM hardware package for 1.5 years. The only development since then has come from the community. If you want this dealt with you'll probably need to take some initiative. Luckily you have a very good lead because westfw provided a patch that is supposed to double the speed. So spend some time investigating that and then if it turns out to be good, submit a pull request.

will this westfw patch be fixed/integrated in the next official Due board core? (currently 1.6.11)?

You posted this same thing three different places. That's very disrespectful. That sort of behavior will certainly not help in your goal. I already explained what needs to happen. If you want it faster then make it faster. That's how open source works. But if you piss off the Arduino team along the way with a bunch of spam then any work you do will be for nothing because they'll just start ignoring you.

I pointed out to this issue because it was extremely surprising to me what I found out.
I supposed it to be very helpful to others to notice that.
It is definitively not disrespectful.
OTOH, to close those issues, mark the topics as resolved, which actually is not true, and lock conversation to collaborators: that attitude really IS disrespectful IMO.

And now you did it again. I've now had to lock two different threads because of you spamming. Before this, I think I've only locked two in the entire last year. Maybe you don't realize that 941 people get an email every time you comment on the repository. So now 4723 emails have been sent out for absolutely no reason. STOP!!!

it is disrespectful by you to lead this discussion about github here in this forum.
I was posting over there, because you referred to the related topics which also are not resolved yet, and asked for an answer, which was not given there so far.

You know how on an AVR, you can activate pullups on a pin by writing HIGH while the pin is in input mode? That's the way the AVR hardware works, and it got documented for Arduino back before "pinMode(pin, INPUT_PULLUP)" was implemented.

The SAM and SAMD hardware doesn't work that way, but the behavior of digitalWrite() has been preserved for the sake of backward-compatibility. The digitalWrite() code for the arms contains an explicit check to see if the pin is in input mode (a function call to libsam code), and if so it activates the pullup...

IIRC, the SAM3X "ports" are on a relatively slow "peripheral bus" that runs at half the speed of the CPU...
(The SAMD "ports" are on a different type of bus. They're also accessible by a "single cycle bus", but the Arduino code doesn't currently use that.)

hi,
thanks again for your input! That again explaines very lucidly where those issues may come from, to my great surprise.
So I must therefore also resign with this issue, but good to know where it comes from...

again, thanks a lot!

So I must therefore also resign with this issue

You can always write a faster version...
See also https://forums.adafruit.com/viewtopic.php?f=57&t=133497

thank you for your link! I will have a close look on that!

It looks like a new release of Arduino SAM Boards might be required to fix some screwiness of the Arduino Web Editor:

On the other hand, the way they run the Arduino Web Editor, they might not even use release versions. I know they decided to chuck the unfinished and known-buggy arduino-preprocessor in there, even though it hasn't even been considered stable enough for the hourly build of the Arduino IDE.

So if anyone wants to try to get some changes made that have a chance of being in a release this decade, it might be a good time to submit those PRs.