Hi,
I'm trying to do digital I/O by accessing the registers in my UNO R4 Minima as described in this post and her sample file on github:
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.
/* Arduino UNO R4 test code for fast ADC and digital pin operation
* Susan Parker - 10th June 2023.
*
* This code is "AS IS" without warranty or liability.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
// RA4M1 User’s Manual: Hardware
// This doc has all the register discriptions I use:
// https://www.renesas.com/us/en/document/mah/renesas-ra4m1-group-users-manual-hardware
This file has been truncated. show original
I can get it to write on on Pin 2 (verified on 'scope) and have connected the output to Pin 7 but just getting zeros on the serial monitor and PuTTy
My code is:
void loop()
{
*PFS_P105PFS_BY = 0x04; // D2 low
char_val = *PFS_P107PFS_BY; //d7
Serial.println(char_val, HEX);
delayMicroseconds(10000);
*PFS_P105PFS_BY = 0x05; // d2 high
delayMicroseconds(10000);
}
I just included the loop as all the rest is as per the github file. For printing the output I tried BIn, HEX and no formatting.
Thanks
KurtE
October 26, 2024, 4:52pm
2
It has been awhile since I played with my UNO R4 boards, but you might take a look
at my quick and dirty digitalWriteFast, digitalToggleFast, digitalReadFast functions:
UNOR4-stuff/libraries/UNOR4_digitalWriteFast/UNOR4_digitalWriteFast.h at main · KurtE/UNOR4-stuff
They worked a lot faster than the normal digital functions...
@heyheywhatcanido you need to read twice in loop():
// Code to demonstrate direct reading of a port-pin
#define PORTBASE 0x40040000 /* Port Base */
#define PFS_P105PFS_BY ((volatile unsigned char *)(PORTBASE + 0x0843 + ( 5 * 4))) // D2
#define PFS_P107PFS_BY ((volatile unsigned char *)(PORTBASE + 0x0843 + ( 7 * 4))) // D7
#define SERIAL_BAUD 115200 // Serial COM port speed
void setup()
{
Serial.begin(SERIAL_BAUD); // connect to the serial port
}
void loop()
{
*PFS_P105PFS_BY = 0x04; // D2 low
char char_val = *PFS_P107PFS_BY; //d7
Serial.println(char_val, HEX);
delay(500);
*PFS_P105PFS_BY = 0x05; // d2 high
char_val = *PFS_P107PFS_BY; //d7
Serial.println(char_val, HEX);
delay(500);
}
Many thanks, I'll have a look at that!
That's great, it appears to be working with a 50 microsecond delay, what do you think the min I could use is?
And thank you for the code!
Hi @heyheywhatcanido
From https://github.com/TriodeGirl/Arduino_Direct_Register_Operations
*PFS_P107PFS_BY = 0x05; // Each Port Output bit clear to set takes c. 82nS
*PFS_P107PFS_BY = 0x04; // Each Port Output bit set to clear takes c. 85nS
*PFS_P107PFS_BY = 0x05; // Set HIGH
char_val = *PFS_P107PFS_BY; // Port State Input read - takes about 165nS
*PFS_P107PFS_BY = 0x04; // Read plus Set LOW = c. 250nS
Fantastic, many thanks Susan.
I misread your first answer, just copied your code. I see now my mistake of just doing the read once per loop, no wonder it never changed
DaveX
April 17, 2025, 6:09pm
8
Cool, it's got all the timings:
*PFS_P107PFS_BY = 0x05; // digitalWrite(monitorPin, HIGH); // Digital Pin D7
adc_val_16 = *ADC140_ADDR09; // adcValue = analogRead(analogPin); // Internal 16bit register read = c. 123nS
*ADC140_ADCSR |= (0x01 << 15); // Next ADC conversion = write to register c. 300nS
*PFS_P107PFS_BY = 0x04; // digitalWrite(monitorPin, LOW);
// Set High, read ADC register, set Low = c. 207nS
// Set High, read ADC register, trigger Conversion, set Low = c. 500nS
*PFS_P107PFS_BY = 0x05; // Each Port Output bit clear to set takes c. 82nS
*PFS_P107PFS_BY = 0x04; // Each Port Output bit set to clear takes c. 85nS
*PFS_P107PFS_BY = 0x05; // Set HIGH
char_val = *PFS_P107PFS_BY; // Port State Input read - takes about 165nS
*PFS_P107PFS_BY = 0x04; // Read plus Set LOW = c. 250nS
But how do the fast port operations compare to the standard speeds on the Uno R4?
I see some 1000X on-off toggling timings in code in this post :
...to give Uno R4 write timings as :
digitalWrite(): 1515us/(1000*2)= 757ns
fasterDigitalWrite: 1515us/(1000*2)= 590ns
digitalWriteFast: 179us/(1000*2)= 90ns
POSR/PORR: 179us/(1000*2)= 90ns
I don't have an R4, but I am curious about the Arduino basic digitalRead() speed versus the direct port access Port State Input Read speed of ~165ns.
Could someone try this on an R4?
void setup(){
Serial.begin(115200);
uint32_t start_time = micros();
for (int i = 0; i < 1000; i++) {
digitalRead(13);
}
uint32_t delta_time = micros() - start_time;
Serial.print("digitalRead: ");
Serial.println(delta_time, DEC);
}
void loop(){}
Hi @DaveX - just to mention that my timings were derived using an oscilloscope and looking at the actual individual pin changing states.
So there may be some small nS differences between my measured values and the code timed ones