Can I use the value of MILLIS_INC from wiring.c in my sketch?

I'm writing a new interrupt for millis that doesn't include the "catch-up" increment that causes millis to be double incremented from time to time. I appear to be able to use two variables defined in wiring.c in my sketch by defining them at the top as:

extern volatile unsigned long timer0_millis;
extern volatile unsigned long timer0_overflow_count;

But there's a value called MILLIS_INC used in wiring.c to adjust for various system clock speeds, and it is never actually defined as a C variable, but rather #defined back through a series of other #defines back to F_CPU. Is there a way to use MILLIS_INC in my sketch? Or even a way to use the value of F_CPU? I would just like to make my code automatically adjust for 8MHz vs 16 MHz.

What happened when you tried to use MILLIS_INC and F_CPU in your sketch?

giova014:
What happened when you tried to use MILLIS_INC and F_CPU in your sketch?

MILLIS_INC gave me a not defined in this scope error. I hadn't actually tried using F_CPU, assuming I would get the same error. But I just tried it, and it compiled ok. So I should be able to calculate the MILLIS_INC value in the same way that wiring.c does.

But after going through it in detail, it appears that the MILLIS_INC value for an 8MHz 328P would be 2. In other words, the I/O prescaler is left at 64 (there is no 32 option), so the interrupt occurs only every ~2ms. Does that sound right, or am I missing something?

Using F_CPU is not something rare, but I can't think of a pratical use for MILLIS_INC.
What are you trying to achieve?

ShermanP:
I'm writing a new interrupt for millis that doesn't include the "catch-up" increment that causes millis to be double incremented from time to time.

WHY ?

If you need more precision than millis() provides just use micros()

...R

ShermanP:
MILLIS_INC gave me a not defined in this scope error. I hadn't actually tried using F_CPU, assuming I would get the same error. But I just tried it, and it compiled ok. So I should be able to calculate the MILLIS_INC value in the same way that wiring.c does.

But after going through it in detail, it appears that the MILLIS_INC value for an 8MHz 328P would be 2. In other words, the I/O prescaler is left at 64 (there is no 32 option), so the interrupt occurs only every ~2ms. Does that sound right, or am I missing something?

You cannot use a #define macro from one .c file in a different file. The only option is to copy and paste it. They're defined that way because their values are never needed outside of the file implementing the timer interrupt.

More importantly, this is probably a classic X-Y problem. Why do you think you need to rewrite the millis() interrupt? What is your goal?

F_CPU is different, because it's the base cock speed of the microcontroller. There are many features of a microcontroller where you need to know the clock speed in order to use them properly, so any good microcontroller project will have some way of creating a global #define that holds the clock speed (though it might have a different name, F_CPU is just the convention for AVRs). Arduino does this when you select the board, and passes it to you source files as part of the command line when you compile them. Check the example output like when I compile a blank project, and you'll see -DF_CPU=16000000L. -D allows you to create a #define in the command line, so whatever IDE you're using can use this to #define the same value in all code files. You can use F_CPU in any place in any Arduino project.

"C:\Users\XXX\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\5.4.0-atmel3.6.1-arduino2/bin/avr-gcc" -c -g -Os -Wall -Wextra -std=gnu11 -ffunction-sections -fdata-sections -MMD -flto -fno-fat-lto-objects -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10805 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR   "-IC:\Users\XXX\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.23\cores\arduino" "-IC:\Users\XXX\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.23\variants\standard" "C:\Users\XXX\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.23\cores\arduino\WInterrupts.c" -o "C:\Users\XXX\AppData\Local\Temp\arduino_build_44731\core\WInterrupts.c.o"

ShermanP:
I'm writing a new interrupt for millis that doesn't include the "catch-up" increment that causes millis to be double incremented from time to time.

Have you decide what your changes are going to do to the Timer0 PWM outputs?

Thanks for the responses. This all came about as a response to this thread:

https://forum.arduino.cc/index.php?topic=600484.0

I thought it might be useful to have a millis alternative that really incremented at 1ms intervals, with no catch-up extra increment. Since this would be at the cost of at least one of the PWM functions for the pins that use timer0 for that (5 and 6, I believe), it wouldn't be for general use, but rather for those occasions when the periodic millis correction was causing problems, or at least to see if that really was the problem.

I had already done the part about disabling the existing interrupt, and enabling a new one that triggered at the compare value of 249, producing an interrupt every 250 timer0 clocks, which is exactly 1ms. But I ended up putting all my loop() code into the ISR, leaving only the sleep functions in loop(), so I didn't need to rewrite the millis ISR. But for this I wanted to completed that process.

In wiring.c, MILLIS_INC is the amount by which the millis count is incremented on each interrupt, subject to further increment if it's time for a catch-up. It is the number of milliseconds between interrupts, and is calculated via all the #defines as the integer portion of:

(64 * 256) / (F_CPU / 1000).

In my version it will be:

(64 * 250) / (F_CPU / 1000).

64 is the I/O clock prescaler, and 256 is the timer0 overflow count.

In both cases, the value is 1 for a 16 MHz clock, but in my version there is no remainder requiring a catch-up.

What's odd to me about this is that it appears to mean that for an 8 MHz Pro Mini, for example, MILLIS_INC is 2. The interrupt takes place every two milliseconds, and millis is incremented by 2 each time, or by 3 for a catch-up. That would mean that the millis() count only increases by 2 or 3, never by just 1. I just didn't know that was the case.

Anyway, my test code is posted in the other thread, except that I don't have a working Arduino to test it on. So all I know at this point is that it compiles ok.