digitalWriteFast with UNO R4

ARM "registers" (IO registers) are memory locations, and there is no "write immediate value to a memory location" instruction:

  *PFS_P107PFS_BY = 0x05;         // = digitalWrite(7, HIGH);
    4100:       4b02            ldr     r3, [pc, #8]    ; load address of PFS_P107PFS_BY
    4102:       2205            movs    r2, #5
    4104:       701a            strb    r2, [r3, #0]
  *PFS_P107PFS_BY = 0x04;         // = digitalWrite(7, LOW);
    4106:       2204            movs    r2, #4
    4108:       701a            strb    r2, [r3, #0]

( see also post #12 in this thread.)

As I said, referring to the ARM documentation.
ARM Access Memory Mapped Peripherals
My interest is running as fast as possible, thankfully I am NOT interested in portability since I am optimizing code specifically for this device - not writing inscrutable libraries in cpp.

For comparison, same deal but with an R3 ATmega UNO...

Could you post the full sketch used to make those scope shots?
I want to look at the object code, and also make modifications to see how the other alternative methods for setting pin states compare. (I've ordered some boards; hopefully they'll get here soon!)

@westfw Files here:
Arduino R4 and R3 files

2 Likes

Thank you!!

Your file for R4 is exactly what I was looking for to add markers for logic analyzers and scopes.

1 Like

Ah...
Usually the output port pins are represented by a register, let's call it OutPins, and you can set pins with an instructions like:

  port->OutPins = 0x101;   // set bit 0 and 8 of the port to 1, others to 0.
  port->OutPins |= 0x100;  // set bit 8, leaving the other bits alone.

The first of these is inconvenient unless your particular function is using all of the pins in a port, and the second has "issues" as soon as you start think about concurrency. Therefore, MOST modern chips also support OutPinsSet and OutPinsClear registers that only modify the bits that are set to one in the value you write:

  port->OutPinsSet = 0x101;  // set pin 0 and 8 only.
  port->OutPinsClear = 0x100;  //  clear bit 8 only.

This maps somewhat nicely onto the Arduino digitalWrite() function.

The Renesas R4 chip have yet another way to modify bits. They have a "Pin Function Select" (PFS) register for each bit in a port that lets you set the bit value as well as other parameters of the pin (direction, pullup state, etc. This is more common; setting the pin state at the same time is unusual.) This lets you do:

  port->PFS[8] = PIN_IS_OUTPUT + 1;   // set pin 8 to one
  port->PFS[8] = PIN_IS_OUTPUT + 0;   // set pin 8 low.

(which is what Susan's code is doing.) This also maps nicely to digitalWrite(). It's probably SLIGHTLY faster than using the OutPinsSet method, because the constant you're writing is always only one byte long.

2 Likes

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.