PlatformIO Community

Grand Central M4 (SAMD51) - PIO Unified Debugger, timers, delays

Sorry for the cross post. I originally posted my message in the “Development Platforms” section of this board. Probably this is is the correct location. If a moderator wants to delete one of the posts, please go ahead (there is no response in the other location).

https://community.platformio.org/t/grand-central-m4-samd51-timers-delays-and-debugging/14946

Cross-posted at the Adafruit forums: https://forums.adafruit.com/viewtopic.php?f=63&t=167384

Hi folks,

I’m sorry if this is a newbie question.

I’ve just purchased an Adafruit Grand Central M4, and Segger J-Link Mini Edu . Using VS Code with PlatformIO as my IDE, I compiled the classic Arduino “blink” program and downloaded it to the GC over the J-Link connection (using SWD). In the loop() function, this blink program turns on the built-in LED, inserts a delay (I tried various numbers, the classic example used 1000 ms), turns off the LED, inserts another delay.

If I run the program by itself (not in the debugger), everything works just fine. I ran this way by simply pressing the reset button on the GC. If I run the program within the debugger, I can step through and see the code executing, but the delay() seems to return immediately. The LED appears to be on continuously (but it is probably blinking very very fast).

I created a similar blink program, but using the millis() function to check the time in the loop() function, rather than using the delay() function. Again, this program runs fine outside of the debugger, but within the debugger millis() always returns 0. I set a breakpoint after the call and checked the return value.

Is there some known interaction between the debugging system and the timer on the GC? And is there a setting or workaround to allow debugging with delays and timers? If this question is answered elsewhere in the forums, a link or a search string to find that answer would be great.

The GCM4 includes a bootloader, which might be setting up some registers when it runs. Is it possible that these settings conflict with the debugger running under PlatformIO?

arduino-blink is the only example provided in the atmel-sam category which supports the Arduino framework. Apparently the GCM4 board only supports this framework. I am hoping that I can get this example running in PlatformIO as a starting point for future projects. So I was surprised when I ran into an issue which was not in the documentation.

Thanks in advance for your help.

Could be a code optimization issue, though extremely weird that the optimized -Os code would work while the debug-code (-Og) not…

I don’t have such a board but I can stll look at the outputted assembly for the millis() function in normal and debug to spot some weirdness.

If the code is fine, aka “reads a global variable in all cases”, then there might by an issue in the peripheral registers for the timer feeding the millis() tick – e.g. not running at all or running weirdly in debug mode. But that again can further be checked by breaking inside the ISRs responsible for this (if they are reached at all).

The compiled code looks good in both Release and Debug mode.

Basically a src\main.cpp

#include <Arduino.h>

void setup() {
  //Serial.begin(115200);
  pinMode(LED_BUILTIN, OUTPUT);
}

void loop() {
  unsigned long now = millis();
  if(now % 1000 == 0) {
     digitalWrite(LED_BUILTIN, digitalRead(LED_BUILTIN) ^ 1);
  }
}

and a platformio.ini of

[env:adafruit_grandcentral_m4]
platform = atmelsam
board = adafruit_grandcentral_m4
framework = arduino

[env:adafruit_grandcentral_m4_debug]
platform = atmelsam
board = adafruit_grandcentral_m4
framework = arduino
build_type = debug

when compiling and reverse-engineering the firmware again we see that millis() in both configuration does:

uint32_t millis()
{
  return ulTickCount;
}

void SysTick_DefaultHandler()
{
  ++ulTickCount;
  tickReset();
}

In other words, the interrupt service routine SysTick_DefaultHandler() should be executed every millisecond, increasing the ulTickCount variable by one. This value should be returned by the millis() function. The microcode looks fine, which may imply a problem with the peripheral setup.

Can you please:

  • use the above project code and configuration
  • place a breakpoint at the first line in setup()
  • start a debug session and let it hit the breakpoint in setup()
  • follow the mills() defintion in code to get to the C:\Users\<user>\.platformio\packages\framework-arduino-samd-adafruit\cores\arduino\delay.c file
  • place a breakpoint in the SysTick_DefaultHandler() function
  • continue execution
  • –> Does it hit the SysTick_DefaultHandler() breakpoint? Is the global variable _ulTickCount thus changed (variable window on the left)? Is this value correctly returned by millis()?

Hello maxgerhardt,

Thank you for your kind and detailed reply.

I created a project with your provided platformio.ini file and main.cpp

I added the following lines to the [env:adafruit_grandcentral_m4_debug] configuration that you had provided:
debug_tool = jlink
upload_protocol = jlink

I set a breakpoint at the code line containing the call to millis (1st line of the loop fn).

I stepped into millis(), and then found the SysTick_DefaultHandler handler, and set a breakpoint there. Then clicked “continue”. The breakpoint was never hit.

Any suggestions?

Take care and stay safe.

Hm it seems like if the SysTick handler is never invoked then this explains the behavior, as then the millisecond variable is never incremented and stays 0.

One or more things could have happened:

  • Somehow, the debugger disables the systick when debugging the chip…
  • The SYSTICK control registers (SYST_CSR, SYST_RVR, …) are misconfigured in debug-mode compiled code
  • The interrupt for the SysTick was disabled in the NVIC (nested vector interrupt control)
  • The clock generation setup which feeds the SysTick hardware its base clock is setup wrong

I’ll see if I can write some code which prints out some diagnostic output on what’s going on here.

1 Like

That would be excellent. Please let me know if you want or need help in deploying the tests.

Hello Max,

Have you had a moment to think about how to make these tests?

Thanks in advance.

My goodness have I been busy… I’ll look into it after studying some datasheets of the clock tree of this thing.

Hello Max,

Sorry to pester you again… I’m still not able to use the PIO debugger with the Grand Central M4.