Tools millis()/micro Timer settings, Tools attachInterrupt Mode settings, and TCB use result in broken millis()/delay()

Open
#1,293 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
25/100
Issue type
Bug
Clarity
Mostly clear
Activity status
Active
Tech stack
arduino, c
Domain
embedded-iot

Research direction

Start with wiring_micros_ISR.h in the megaTinyCore megaavr cores folder, which sets up the millis() interrupt for the default, TCB0 and RTC timer sources. Reproduce on an ATtiny3224 with the minimal blink sketch, changing TCB1.CCMPL/CCMPH and the attachInterrupt mode. Done means delay() and millis() stay accurate under each combination, and the root cause is identified.

Written by the indexing model from the issue text.

Description

*Edit2: Target is ATtiny2 ATtiny3224. PA3 used instead of LED_BUILTIN as that pin is open in my circuit.

TCB1 is the default timer for millis().

Minimum Blink example:


void setup() {
  
  pinMode(PIN_PA3, OUTPUT); //Using PA3 instead of LED_BUILTIN(PA7)

  TCB1.CCMPL = 0x00; //modify frequency of flash here
  TCB1.CCMPH = 0x01;
}
// the loop function runs over and over again forever
void loop() {
  digitalWrite(PIN_PA3, HIGH);  // change state of the LED by setting the pin to the HIGH voltage level
  delay(1000);                      // wait for a second
  digitalWrite(PIN_PA3, LOW);   // change state of the LED by setting the pin to the LOW voltage level
  delay(1000);                      // wait for a second
}

attachInterrupt Mode default and millis() source to TCB0. This works:

Image

attachInterrupt Mode PortA and millis() source to TCB0, This doesn't:

Image

attachInterrupt Mode PortA and millis() source to RTC, This does:

Image

attachInterrupt Mode default and millis() source to RTC, This doesn't:

Image

When it works, it flashes at the expected rate. When it doesn't, it flashes at various rates determined by the setting in TCB1.CCMPL/H.

// 2.45 Hz
  TCB1.CCMPL = 0x01;
  TCB1.CCMPH = 0x00;

// 0.613 Hz
  TCB1.CCMPL = 0x00;
  TCB1.CCMPH = 0x20;

//10.4 Hz
  TCB1.CCMPL = 0xFF;
  TCB1.CCMPH = 0x7F;

//5.68 Hz
  TCB1.CCMPL = 0xFF;
  TCB1.CCMPH = 0xFF;

//20.0 Hz
  TCB1.CCMPL = 0x00;
  TCB1.CCMPH = 0x01;

I'm not sure what's going on. If I dig further into it, I'm going to begin by looking at how the millis() interrupt is setup when the sources are default/TCB0/RTC. I'd start with wiring_micros_ISR.h

I'm able to work around for my needs without finding the actual source of the behavior. In my case I'm using the RTC as the millis() source, With interrupts set to PORTA, I'm able to use both TCB0 and TCB1 without millis() being broken.

I can probably figure out the root cause, but haven't been able to find it after some digging. If anyone else needs it, I might give it another try. Likely that someone else can quickly figure it out, I don't know much about interrupts and am only starting to learn.

*Edit: corrected after accidental early post.

Dominant language
C
Stars
690
Forks
162
PR merge metrics
No merged PRs in 30d

Getting set up

This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from SpenceKonde/megaTinyCore

All issues in SpenceKonde/megaTinyCore

Similar issues

More C issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.