There may be some conflict between RTC and the serial

Hello everyone, when I tried to run the example in https://docs.arduino.cc/tutorials/uno-r4-wifi/rtc#Periodic-Interrupt, I found some errors in it.

In order to make the code run correctly, I made modifications to the code. The modified code is as follows:

// Include the RTC library
#include "RTC.h"

const int led = LED_BUILTIN;

void setup() {
  pinMode(led, OUTPUT);

  Serial.begin(9600);

  // Initialize the RTC
  RTC.begin();

  // RTC.setTime() must be called for RTC.setPeriodicCallback to work, but it doesn't matter
  // what date and time it's set to
  RTCTime mytime(30, Month::JUNE, 2023, 13, 37, 00, DayOfWeek::WEDNESDAY, SaveLight::SAVING_TIME_ACTIVE);
  RTC.setTime(mytime);

  if (!RTC.setPeriodicCallback(periodicCallback, Period::ONCE_EVERY_2_SEC)) {
    Serial.println("ERROR: periodic callback not set");
  }
}

void loop() {
}

// This is the callback function to be passed to RTC.setPeriodicCallback()
void periodicCallback()
{
  static bool ledState = false;
  if (ledState == true) {
    digitalWrite(LED_BUILTIN, HIGH);
  }
  else {
    digitalWrite(LED_BUILTIN, LOW);
  }
  ledState = !ledState;

  Serial.println("PERIODIC INTERRUPT");
}

Unfortunately, when I uploaded the code to my Arduino R4 WiFi, its performance did not meet expectations.The LED did not blink at a two-second interval and it was unable to print the complete message on the serial monitor.
However, when I uploaded this code to Uno R4 Minima, everything worked fine.
(Additional information: The firmware version of Arduino R4 WiFi is 0.3.0, and the library version displayed in the board manager is 1.0.4.)

Does anyone know why this is? Or has anyone done the same test on the R4 wifi board? Thank you very much for any help.

Another strange thing is that when I comment out the line of code Serial.println("PERIODIC INTERRUPT"); in the periodicCallback() function, the LED can blink once every two seconds as expected.

Hmm. Yeah, that original example looks like it might have been copied from something else and not updated for the R4 (both variants of which, for example, have the builtin LED on pin 13, not pin 22). Edit: and for that matter, where's the Serial.begin() call in the original??

And myself, I would not generally attempt to print from inside a callback function. In this instance, I'd sooner set a volatile flag in the callback and poll it from the main loop, resetting the flag and printing the message when I saw that the callback had set the flag. Something like this:

// Include the RTC library
#include "RTC.h"

const int led = LED_BUILTIN;

void setup() {
  pinMode(led, OUTPUT);

  Serial.begin(9600);

  // Initialize the RTC
  RTC.begin();

  // RTC.setTime() must be called for RTC.setPeriodicCallback to work, but it doesn't matter
  // what date and time it's set to
  RTCTime mytime(30, Month::JUNE, 2023, 13, 37, 00, DayOfWeek::WEDNESDAY, SaveLight::SAVING_TIME_ACTIVE);
  RTC.setTime(mytime);

  if (!RTC.setPeriodicCallback(periodicCallback, Period::ONCE_EVERY_2_SEC)) {
    Serial.println("ERROR: periodic callback not set");
  }
}

volatile bool blink = false;               // <------

void loop() {
  if (blink) {                             // <------
    blink = false;                         // <------
    Serial.println("PERIODIC INTERRUPT");  // <------
  }
}

// This is the callback function to be passed to RTC.setPeriodicCallback()
void periodicCallback()
{
  static bool ledState = false;
  if (ledState == true) {
    digitalWrite(LED_BUILTIN, HIGH);
  }
  else {
    digitalWrite(LED_BUILTIN, LOW);
  }
  ledState = !ledState;
  blink = true;                            // <------
  //  Serial.println("PERIODIC INTERRUPT");// <------
}

2 Likes

Thank you for your reply and suggestions.

May I ask if you can test the code I mentioned on R4 wifi? I have already tested it on R4 minima, and the code runs as expected. However, on my R4 WIFI, periodicCallback() does not seem to work correctly as long as it includes Serial.println("PERIODIC INTERRUPT");. Your test results will help me determine whether it is an issue with the code library or my hardware. Thank you very much!

Your modified code worked (or failed, if you like) the same way on my R4 Wifi. And that doesn't surprise me. Nor does it really surprise me that it seemed to work just fine on a Minima. The USB comm on R4 Wifi is a different setup than the Minima. From what I recall reading, the RA4M1 on the Minima talks directly to the USB itself, whereas on the Wifi, the RA4M1 talks to the ESP32 which then talks to the USB. You'd likely have to delve pretty deeply into the USB Serial code for both boards to figure out what the difference was. Me, I'd just stay away from printing from a callback (that I'd bet is more likely than not to be running in an interrupt context) and save the aggravation.

2 Likes

@wulu

It is not advised to do long operations inside interrupts.
IRQs only have a limited amount of time to execute, and if such time is consumed, the callback will exit without completing its execution.

The way to use IRQs is to generally set a flag that will be checked against inside your loop.
As little code as possible, that's the rule.

volatile bool irqFlag = false;
ledState = false;

#include "RTC.h"

const int led = LED_BUILTIN;

void setup() {
  pinMode(led, OUTPUT);

  Serial.begin(9600);

  // Initialize the RTC
  RTC.begin();

  // RTC.setTime() must be called for RTC.setPeriodicCallback to work, but it doesn't matter
  // what date and time it's set to
  RTCTime mytime(30, Month::JUNE, 2023, 13, 37, 00, DayOfWeek::WEDNESDAY, SaveLight::SAVING_TIME_ACTIVE);
  RTC.setTime(mytime);

  if (!RTC.setPeriodicCallback(periodicCallback, Period::ONCE_EVERY_2_SEC)) {
    Serial.println("ERROR: periodic callback not set");
  }
}

void loop(){
  if(irqFlag){
    Serial.println("Timed CallBack");
    ledState = !ledState;
    digitalWrite(LED_BUILTIN, ledState);
    irqFlag = false;
  }
}

void periodicCallback()
{
  irqFlag = true;
}
1 Like

Thank you for the reply @ubidefeo , and thank you @van_der_decken for giving me suggestions.

I wrote the code in this way because I am not very familiar with RTC knowledge and I am trying to learn. So, I referred to the tutorial on this webpage. https://docs.arduino.cc/tutorials/uno-r4-wifi/rtc
Thank you very much for your correction.

Maybe I should make a suggestion at GitHub - arduino/docs-content: Arduino documentation (docs.arduino.cc). This tutorial's example code contains errors and is somewhat misleading.

no worries, we're all here to get help or help :slight_smile:

I'll submit your feedback to our documentation team.
thank you for making me notice :slight_smile:

u.

2 Likes

@ubidefeo @wulu - It should be noted that the issue you ran into here is not really a problem with what you did in your sketch, but is due to issues with the currently released Hardware Serial (UART) implementation. Note: On the WIFI board, the USB serial goes through a UART to talk to the ESP32, which then sends the data to your PC.

There are lots of problems with the current UART code, this one I mentioned in an issue:
[Serial.print() - from Interrupt callbacks hangs the processor. · Issue #38 ·

arduino/ArduinoCore-renesas (github.com)](Serial.print() - from Interrupt callbacks hangs the processor. · Issue #38 · arduino/ArduinoCore-renesas · GitHub)

That I later closed as part of other issues and frustration back then.

The primary issue here is that the UART write code does not use the Software TX fifo buffer that is built into the UART object, instead what the current code, calls the lower level with one byte to output, and then waits for an callback from the lower level in response to an interrupt. The interrupt handler for the UART is at the default interrupt level, like your RTC interrupt, so the NVIC(Nested Vector Interrupt Controller) will not interrupt your current interrupt handling and so you wait forever.

I have a Pull Request to try to address these issues, that I opened about a month and a half ago, that needs reviewing. There were a lot of interconnected issues, and the changes were significant, so probably needs additional testing, and is still waiting for Code reviews and the like. So far it is still just waiting.

Serial: Tx use FIFO plus fixes by KurtE · Pull Request #90 · arduino/ArduinoCore-renesas (github.com)

Short term easy work around to make work:
Edit the file IRQManager.cpp, on my Windows 11 machine for IDE 2, this is at:
C:\Users\kurte\AppData\Local\Arduino15\packages\arduino\hardware\renesas_uno\1.0.4\cores\arduino\IRQManager.cpp

On your machine probably different location, unless your user name is kurte :wink:

Look for the line which on my machine is at line 14:
#define UART_SCI_PRIORITY 12

And change it to a lower number like 10 or 8 or 6 or 4which gives it a higher priority, depending on which other interrupts you wish to be able to interrupt.... I would try 8 unless you are doing this for interrupts in SPI code.

Alternative If the fix I mentioned or similar implementation is not going to be integrated anytime soon, then update the function:

size_t UART::write(uint8_t c) {

to not rely on interrupts, instead simply wait for the Transfer Data Register Empty(TDRE) on those UARTS without FIFO or for FIFO not full for those that do, and then put the new byte out into the appropriate transfer register.

Which again won't hang the processor!

Sorry just frustrated.

2 Likes

hey @KurtE

sorry, I missed the PR in the plethora of threads I have to follow.
Let me bring it to the FW team's attention right away :slight_smile:

hope they review it and give you feedback if necessary

thank you
u.

Thank you for your reply!

Yes, in this post, it seems that everyone has focused on discussing whether my code is reasonable. However, I still believe that the performance of the code does not meet expectations and should be a bug rather than a feature. Therefore, I have raised separate issues in the documentation repository and the core repository.

For ArduinoCore-renesas:[UNO R4 WIFI] - periodicCallback() does not seem to work correctly as long as it includes Serial.println(). · Issue #138 · arduino/ArduinoCore-renesas · GitHub

For documentation:The example code in the Arduino UNO R4 WiFi Real-Time Clock document is incorrect and misleading · Issue #1351 · arduino/docs-content · GitHub

I'm not well-versed in the inner workings of Arduino's underlying code, but I hope your pull request receives the attention it deserves.