Hey everyone, I have noticed on the Arduino Giga the M4 core micros() function returns a time that is too short by about 50%. For example if I want to toggle a pin every 500 microseconds (I can do this is in a few clock cycles in assembly and is proven to work, but can also use digitalwrite for illustrative purposes, what is happening is the time with respect to a professional logic analyzer is slow, always by the same scaling (multiplicative) amount, 500 microseconds is 750, 1000 microseconds is 1500, etc. The M7 is fine but the M4 is totally wrong. All my code does is wait the specified time then toggles the pin. Any ideas why the M4 timing is incorrect? Thanks!
For the record the arduino giga reports the correct time +-1 microsecond from its perpective, but 2 different logic analyzers and a random sanity check on an Arduino uno WIFI rev2 say otherwise...
UPDATE: The people at Arduino have totally cooked this board, the clock source on the Giga M4 is horrific as determined by me tapping off it with my logic analyzer. Using the following code (small example for demonstration of simplicity, M4 code is slightly different) it is counting 1 second for every 1.558876 real seconds. I have two boards, both exhibit this exact behavior. 5 more on the way. I think we have a serious issue here.
#include "mbed.h"
void setup() {
Serial.begin(115200);
}
void loop() {
uint32_t time_us = us_ticker_read();
// Print the time since boot in microseconds
Serial.println(time_us);
}
Again M7 is fine, but M4 is in a broken state with regards to timing, and this timing issue has been cooking many other Arduino libraries like I2C (Wire), Serial, etc. In reference to my other posts on the Giga many things are starting to make sense. If the M4 cant keep time correctly then things wont work as specified. More updates to come! If you guys have anything to add I would love to hear it!
I think the issue will lie in the clock speed written somewhere in files, or indeed the config of m4 timers. I can try to look into the timer multiplexer registers, but i don’t think such a ratio could be achieved that way, so it’s probably just bad code on arduino ide side.
Another common isssue is some examples stating 400mhz as clock speed even though it’s actually 480 unlike on portenta.
FINAL UPDATE: Just when you think it couldn't get any worse on the Arduino side. The M4 is reporting its "SystemCoreClock" at 375,000,000 Hz when it should be 240,000,000 HZ. Again our golden boy the M7 reports the correct clock of 480,000,000. This is the code to fix it on the M4, replace "SystemCoreClock" with 240Mhz. Very disappointed in the Arduino team today.
This matches my obsevation of 500us being stretched to 779.438us or about a ratio of 1.5625
FYI this incorrect reported clock speed has bricked almost everything from Serial to I2C on the M4 core. not a good day to have a Giga. Lets get a message to the devs to get this fixed highest priority.
My guess is the issue will be different high speed crystal. The giga r1 has a 16mhz one while portenta h7 which lot of code was ported from has 25mhz, and 25/16 is very close to the ratio you got.
375 * 16 / 25 also gives 240, so it’s probably just unfinished porting over from portenta, where the library looks at timers and assumes 25mhz clock speed as high speed oscillator, while in reality that’s not the case, and it’s 16mhz
Thank you for your insight! That likely is the reason! I’m extremely surprised the Arduino team didn’t have testing in place to make sure that works, it’s pretty fundamental to the operation of almost all IO features on the board!
The bad library is the hardware timing library buried in Arduino.h and associated files related to the millis() and micros() functions. Fix it by building your own timing library as I outlined above.
For code you can do something like this on the M4:
At least 10 of them are on the Arduino GitHub for this issue, they dont seem to care about the Giga currently as they are dealing with the botched release of the Uno R4 and its poor port of the Arduino Due Libraries. The first thing I do in the Arduino setup function is spin up another MBED OS process to run my own code then immediately kill the Arduino process by setting it to "osPriorityIdle" then killing it, behind the scenes the Arduino compiler for the Giga is total trash currently.
it appears like the millis() method appears to work on the M4, but micros has major problems.
ILI9341 screen fills on M4 Screen fill 547389:842 547347:842 547417:842 547463:842 547499:841 547680
The number:number values are delta micros : delta millis
Running same code on M7 Screen fill 367267:368 367248:367 367352:367 367296:368 367235:367 367465
Which has the millis and micros appear to be consistent.
(Plus over twice as fast to fill the screen),
This was also confirmed by checking some digital outputs that bracketed the outputs and viewed on logic analyzer.
And here I wondered if the UNO R4 boards were getting any attention.
Hi everyone. This issue was correctly described by @bexin in this post back in April. Currently all boards with an M4 processor shares the same variant as they also have the same crystal (25 MHz), but as the GIGA R1 WiFi has a 16 MHz crystal, the timing is off.
Apologies for the inconvenience and for the late response in this case, it is currently being investigated by our FW team. You can read more about it in this issue.
wouldn't've you guys known about this while you're designing the board? No one thought to see if basic timing was working on the board before shipping your flagship consumer product?
"All" is incorrect here. For instance, the new Uno R4 has an M4 processor, but since it's from a different vendor the whole clock system is entirely different.
I'll also spend some time and go into deeper details on WHY this bug exist (and no, it's not the fact that we are sloppy and stupid).
We originally had only one board with the STM32H747, the Portenta H7, so it made complete sense to have two variants, one for the M7 and one for the M4 core. Now we have 3 more boards (Nicla vision, Opta and Giga) with the same MCU, so supporting all the combinations is basically meaningless, since the M4 is not an independent core and must rely on the M7 for booting and clock configuration.
All is good until some code lurking around does uses the HSE_VALUE macro, which of course is the same for all the boards except Giga.
The first time it got reported it slipped under the radar, but now it got fixed and will be available in the next release of the core