RTCZero getEpoch() causes missing characters at serial comms

Hi All,

When I call RTCZero getEpoch() at the moment an external device is sending a serial message over the rs232 port, one or more charecters are lost. I assume that for some reason interrupts are blocked by RTCZero inplementation.

I encountered this problem at the SodaqONE and some time back on the Autonomo too (not 100% sure however, it’s a while ago).

Is this a known issue and is there a workaround?

Axel

There was a known issue with this which was fixed a while ago. However, the library maintainers didn’t push the fixed version out immediately.

Please check that you have v1.5.0.

Gabriel,

I installed v1.5.0. Same result.

Is there a way I can verify the code of the library to be sure I have the right version?

Github version is 5 months old.

Axel

The commit bd4d27f pulled the fix I submitted in March. However, this wasn’t released properly until the end of July.

The correct code should look like this now:

The issue was that if you tried to read the CLOCK register while it was in the middle of a synchronisation, it would stall the bus and block all interrupts until the synchronisation was complete. The fix calls a synchronisation request, and waits for it to complete, before reading the CLOCK register. Additionally, the CLOCK register is read in a single operation now instead of piecewise.

What does your interrupt routine look like (ISR). While, the SAMD platform does support nested interrupts, an interrupt routine will block any other interrupts of equal or lower priority.

The SERCOMs in UART mode use an interrupt when new data is received. That interrupt copies the data into the appropriate buffer. If the interrupt is blocked for long enough, a new character will have arrived, meaning the old character is lost.

Hi Gabriel,

The code you provided is the version I am using.

I am using the standard SodaqONE Serial instance that is connected to the TX and RX pins of the ONE. Not sure which driver/interrupt routines are behind.

However, it is clear that I still miss characters due to the interrupt being blocked too long.

I assume that the hardware defines the interrupt order/priority?

Axel

Can you show me what your ISR code looks like?

Also at where in your code are you calling the getEpoch() method?

I did not write any interrupt code myself. I am using the standard Serial class: Uart Serial from variant.h.

I call rtc.getEpoch() in my main loop.

Oh, sorry I thought you were using the RTC interrupt as well.

The SERCOM NVIC priority is set on line 687 of cores/arduino/SERCOM.cpp. I’m fairly certain that the set value resolves to 0, which is the highest priority level (Samd21 supports 4 priority levels).

Perhaps we can test a few things.

First, could you try commenting out line 371 of RTCZero.cpp.
You will receive an incorrect epoch value, but I’m curious if it is the read operation that is at fault.

You could also try, separately, commenting out the synchronisation request on line 369 of RTCZero.cpp.

Hi Gabriel,

The problem is in the line: clockTime.reg = RTC->MODE2.CLOCK.reg;

In case I comment out this line: the serial bytes that I receive are fine.

Do I comment out line 369: no difference.

The file Sercom.cpp is not on my PC, so I could not verify that.

Axel

Hmm, this is odd. Can you confirm that you are calling the begin() method (once during intialisation) before trying to read the epoch value?

Can you try the following:

Try commenting out lines 439, 440 and 443.

Then can you try changing line 76 to this:

RTC->MODE2.READREQ.reg |= RTC_READREQ_RCONT;

If you want, I can run some of these tests, however, I will need an example which replicates this issue.

Hi Gabriel,

Yes, I use rtc.begin().

I followed your instructions and the result is still not good. In fact: it seems worse.

Axel

Could you email me a simplifed version of your sketch so that I could try a find the underlying bug.

Hi Gabriel,

Please find below. Make sure that you use a different source that sends that data. Using the Serial.PrintLn() will not cause problems as it is synchronous, so all bytes are sent before the rtc.getEpoch(); is called.

Axel

#include <RTCZero.h>
#define CONSOLE_SERIAL SerialUSB
#define ENABLE_READER	1

RTCZero rtc;
static int cnt = 0;
// the setup function runs once when you press reset or power the board
void setup() 
{
	while ((!SerialUSB) && (millis() < 10000)) {
		// Wait 10 seconds for the debugSerial
	}

	delay(1000);

	pinMode(ENABLE_READER, OUTPUT);
	digitalWrite(ENABLE_READER, HIGH);

	Serial.begin(19200);

	rtc.begin();

	CONSOLE_SERIAL.println(String("Starting"));
}

// the loop function runs over and over again until power down or reset
void loop() 
{
	rtc.getEpoch();

	if (Serial.available())
	{
		String test = Serial.readStringUntil(0x0d);
		CONSOLE_SERIAL.println(test);
	}
  
}

I’m sorry but I haven’t been able to replicate the issue.

I am using a second board which is sending 72 character (+CRLF) lines, as fast as possible.

void setup() 
{
  Serial1.begin(19200);
}

void loop() 
{
  Serial1.println("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ");
}

I am not seeing any dropped characters.

If you are willing to send your whole sketch to me, I can try testing it to see if there is some other issue.
You can email me at: gabriel at sodaq dot com

Just to give a follow up on this.

The issue was eventually tracked down and is related to using the VisualMicro plugin for VisualStudio.
Building the and programming the board via the Arduino IDE resolved the issue.

The exact cause of the issue, while using VisualMicro, is not yet known.