Arduino Uno and new R4, atomic.h

I'm trying to use the code below. After hours of trying to get this to work on a new Uno R4 I decided to give an older Uno board a try. With an older Uno board it works. With the R4 I get

Compilation error: util/atomic.h: No such file or directory


#include <util/atomic.h> // For the ATOMIC_BLOCK macro


#define ENCA 2 // YELLOW
#define ENCB 3 // WHITE
#define PWM 5
#define IN2 6
#define IN1 7

volatile int posi = 0; // specify posi as volatile: https://www.arduino.cc/reference/en/language/variables/variable-scope-qualifiers/volatile/

void setup() {
  Serial.begin(9600);
  pinMode(ENCA,INPUT);
  pinMode(ENCB,INPUT);
  attachInterrupt(digitalPinToInterrupt(ENCA),readEncoder,RISING);
  
  pinMode(PWM,OUTPUT);
  pinMode(IN1,OUTPUT);
  pinMode(IN2,OUTPUT);
}

void loop() {
  
  // Read the position in an atomic block to avoid a potential
  // misread if the interrupt coincides with this code running
  // see: https://www.arduino.cc/reference/en/language/variables/variable-scope-qualifiers/volatile/
  int pos = 0; 
  ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
    pos = posi;
  }

  setMotor(1, 25, PWM, IN1, IN2);
  delay(200);
  Serial.println(pos);
  setMotor(-1, 25, PWM, IN1, IN2);
  delay(200);
  Serial.println(pos);
  setMotor(0, 25, PWM, IN1, IN2);
  delay(20);
  Serial.println(pos);
}

void setMotor(int dir, int pwmVal, int pwm, int in1, int in2){
  analogWrite(pwm,pwmVal);
  if(dir == 1){
    digitalWrite(in1,HIGH);
    digitalWrite(in2,LOW);
  }
  else if(dir == -1){
    digitalWrite(in1,LOW);
    digitalWrite(in2,HIGH);
  }
  else{
    digitalWrite(in1,LOW);
    digitalWrite(in2,LOW);
  }
}

void readEncoder(){
  int b = digitalRead(ENCB);
  if(b > 0){
    posi++;
  }
  else{
    posi--;
  }
}

Hello

Uno R4 uses an ARM processor

Try :

Thank you!

No it doesn't.
Uno R4 uses a Renesas processor it is a totally different thing.

1 Like

From the first sentence on the product landing page:

The flexible Renesas Advanced (RA) 32-bit microcontrollers (MCUs) are industry-leading 32-bit MCUs with the Arm® Cortex®-M33, -M23 and -M4 processor cores and PSA certification.

It sounds to me like they're calling them Arm over at Renesas.

Renesas has a bunch of different processors. The RA4 used in the Uno R4 has an ARM Cortex-M4 CPU. With some weirdness added on top of it.

1 Like

From a marking department that talks about this being a "Quantum leap" in computing power do you have any faith that it knows what it is talking about?

Maybe I should have said that it uses a R7FA4M1AB3CFL/ R7FA4M1AB3CNE processor then. That is the cut down 48 pin package that has many features that are inaccessible due to the lack of pins.

But what ever it is, it is not just an Arm processor.

Maybe @westfw has it right with

It is that weirdness that stops normal Arm code from working. As you can see from reading other posts.

1 Like

it is not just an Arm processor.

No of course not. Nothing is JUST an "Arm processor", because that would be pretty useless. It's all about the peripherals. And the Renesas peripherals are different than the SAMD peripherals, and different than the ST peripherals. That doesn't mean much.

How are you defining "normal ARM code"? The biggest weirdness I see at the hardware level is that they have inserted their own Interrupt Controller that sits on top of the CM4 "NVIC", and maps the 174 sources to 32 ARM interrupts. (I don't know why. CM4 allows for many NVIC interrupts. Perhaps they want to maintain compatibility with CM0 chips as well? Or some other legacy chips?)

And then there's the software. I (sadly) do not expect a new chip with new peripherals to work with all of the libraries that were working on some subset of previous boards. With the "chaotic" state of Arduino libraries (some of which were written a long time ago by people who have long since gafiated from the Arduino world), it shouldn't be surprising.
There ARE oddities in the core implementation - the decision to work on top of the Renesas SDK ensures that (although the weirdest thing I've found is that the core uses one of the chip-specific timers instead of the ARM SysTick for the millisecond tick, and that seems excessively NIH-ish.)

1 Like

Tried that. Won't compile.

#include <RadioHead.h>
#include <RHutil/atomic.h>

//#include <util/atomic.h> // For the ATOMIC_BLOCK macro

#define ENCA 2 // YELLOW
#define ENCB 3 // WHITE
#define IN2 5
#define IN1 6

volatile int posi = 0; // specify posi as volatile: https://www.arduino.cc/reference/en/language/variables/variable-scope-qualifiers/volatile/
long prevT = 0;
float eprev = 0;
float eintegral = 0;


void setup() {
  Serial.begin(9600);
  pinMode(ENCA,INPUT_PULLUP);
  pinMode(ENCB,INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(ENCA),readEncoder,RISING);
  
  pinMode(IN1,OUTPUT);
  pinMode(IN2,OUTPUT);
}

void loop() {
  // set target position
  int target = 300;
  //int target = 250*sin(prevT/1e6);

  // PID constants
  float kp = 4.0;
  float kd = 0.0;
  float ki = 0.0;

  // time difference
  long currT = micros();
  float deltaT = ((float) (currT - prevT))/( 1.0e6 );
  prevT = currT;

  // Read the position in an atomic block to avoid a potential
  // misread if the interrupt coincides with this code running
  // see: https://www.arduino.cc/reference/en/language/variables/variable-scope-qualifiers/volatile/
  int pos = 0; 
  ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
    pos = posi;
  }
  
  // error
  int e = pos - target;

  // derivative
  float dedt = (e-eprev)/(deltaT);

  // integral
  eintegral = eintegral + e*deltaT;

  // control signal
  float u = kp*e + kd*dedt + ki*eintegral;

  // motor power
  float pwr = fabs(u);
  if( pwr > 255 ){
    pwr = 255;
  }

  // motor direction
  int dir = 1;
  if(u<0){
    dir = -1;
  }

  // signal the motor
  
  if(abs(e) > 1){
    setMotor(dir,pwr,IN1,IN2);
     Serial.print(target);
    Serial.print(" ");
    Serial.print(pos);
    Serial.print(" ");
    Serial.print(pwr);
    Serial.print(" ");
    Serial.println();
  }
  else{
    digitalWrite(IN1,LOW);
    digitalWrite(IN2,LOW);
  }

  // store previous error
  eprev = e;
}

void setMotor(int dir, int pwmVal, int in1, int in2){//variable pwm shouldn't be needed any longer
  //analogWrite(pwm,pwmVal);
  if(pwmVal < 6){
    pwmVal = 6;
  }
  
  if(dir == 1){
    analogWrite(in1,pwmVal);
    digitalWrite(in2,LOW);
  }
  else if(dir == -1){
    digitalWrite(in1,LOW);
    analogWrite(in2,pwmVal);
  }
  else{
    digitalWrite(in1,LOW);
    digitalWrite(in2,LOW);
  }  
}

void readEncoder(){
  int b = digitalRead(ENCB);
  if(b > 0){
    posi++;
  }
  else{
    posi--;
  }
}

c:\Users\travi\Documents\Arduino\libraries\RadioHead\RHHardwareSPI.cpp: In member function 'virtual void RHHardwareSPI::begin()':
c:\Users\travi\Documents\Arduino\libraries\RadioHead\RHHardwareSPI.cpp:137:57: error: invalid conversion from 'uint8_t {aka unsigned char}' to 'BitOrder' [-fpermissive]
_settings = SPISettings(frequency, bitOrder, dataMode);
^
In file included from C:\Users\travi\AppData\Local\Arduino15\packages\arduino\hardware\renesas_uno\1.0.4\libraries\SPI/SPI.h:22:0,
from c:\Users\travi\Documents\Arduino\libraries\RadioHead/RadioHead.h:1517,
from c:\Users\travi\Documents\Arduino\libraries\RadioHead/RHGenericSPI.h:10,
from c:\Users\travi\Documents\Arduino\libraries\RadioHead/RHHardwareSPI.h:10,
from c:\Users\travi\Documents\Arduino\libraries\RadioHead\RHHardwareSPI.cpp:7:
C:\Users\travi\AppData\Local\Arduino15\packages\arduino\hardware\renesas_uno\1.0.4\cores\arduino/api/HardwareSPI.h:47:3: note: initializing argument 2 of 'arduino::SPISettings::SPISettings(uint32_t, BitOrder, int)'
SPISettings(uint32_t clock, BitOrder bitOrder, int dataMode) {
^~~~~~~~~~~
c:\Users\travi\Documents\Arduino\libraries\RadioHead\RH_ASK.cpp: In member function 'void RH_ASK::timerSetup()':
c:\Users\travi\Documents\Arduino\libraries\RadioHead\RH_ASK.cpp:463:5: error: 'TCCR1A' was not declared in this scope
TCCR1A = 0; // Output Compare pins disconnected
^~~~~~
c:\Users\travi\Documents\Arduino\libraries\RadioHead\RH_ASK.cpp:464:5: error: 'TCCR1B' was not declared in this scope
TCCR1B = _BV(WGM12); // Turn on CTC mode
^~~~~~
c:\Users\travi\Documents\Arduino\libraries\RadioHead\RH_ASK.cpp:464:18: error: 'WGM12' was not declared in this scope
TCCR1B = _BV(WGM12); // Turn on CTC mode
^~~~~
c:\Users\travi\Documents\Arduino\libraries\RadioHead\RH_ASK.cpp:464:14: error: '_BV' was not declared in this scope
TCCR1B = _BV(WGM12); // Turn on CTC mode
^~~
c:\Users\travi\Documents\Arduino\libraries\RadioHead\RH_ASK.cpp:464:14: note: suggested alternative: '_B'
TCCR1B = _BV(WGM12); // Turn on CTC mode
^~~
_B
c:\Users\travi\Documents\Arduino\libraries\RadioHead\RH_ASK.cpp:471:5: error: 'OCR1A' was not declared in this scope
OCR1A = nticks;
^~~~~
c:\Users\travi\Documents\Arduino\libraries\RadioHead\RH_ASK.cpp:478:5: error: 'TIMSK' was not declared in this scope
TIMSK |= _BV(OCIE1A);
^~~~~
c:\Users\travi\Documents\Arduino\libraries\RadioHead\RH_ASK.cpp:478:18: error: 'OCIE1A' was not declared in this scope
TIMSK |= _BV(OCIE1A);
^~~~~~
c:\Users\travi\Documents\Arduino\libraries\RadioHead\RH_ASK.cpp: At global scope:
c:\Users\travi\Documents\Arduino\libraries\RadioHead\RH_ASK.cpp:798:4: error: expected constructor, destructor, or type conversion before '(' token
ISR(RH_ASK_TIMER_VECTOR)
^

exit status 1

Compilation error: exit status 1

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