Arduino millis() is based on a timer that trips an overflow interrupt at very close to 1 KHz, or 1 millisecond. To achieve the same thing, I suggest you setup a timer on the ARM platform and update a volatile unsigned long variable with a counter. That will be the equivalent of millis().

Here is what millis() is doing behind the scenes:

SIGNAL(TIMER0_OVF_vect)
{
    // copy these to local variables so they can be stored in registers
    // (volatile variables must be read from memory on every access)
    unsigned long m = timer0_millis;
    unsigned char f = timer0_fract;

    m += MILLIS_INC;
    f += FRACT_INC;
    if (f >= FRACT_MAX) {
        f -= FRACT_MAX;
        m += 1;
    }

    timer0_fract = f;
    timer0_millis = m;
    timer0_overflow_count++;
}

unsigned long millis()
{
    unsigned long m;
    uint8_t oldSREG = SREG;

    // disable interrupts while we read timer0_millis or we might get an
    // inconsistent value (e.g. in the middle of a write to timer0_millis)
    cli();
    m = timer0_millis;
    SREG = oldSREG;

    return m;
}

Coming from the embedded world, arguably the first thing you should do when starting a project on a new platform is establish clocks and get a timer interrupt going at a prescribed rate. That is the "Hello World" of embedded systems. ;) If you choose to do this at 1 KHz, you're most of the way there.

Answer from TomServo on Stack Overflow
🌐
GitHub
github.com › ZakKemble › millis › blob › master › arduino › millis › millis.cpp
millis/arduino/millis/millis.cpp at master · ZakKemble/millis
* Web: http://blog.zakkemble.net/millisecond-tracking-library-for-avr/ */ · // Here we're using C code in a .cpp file so Arduino compiles with the correct settings (mainly C99) · #include <avr/io.h> #include <avr/interrupt.h> #include <avr/power.h> #include <util/atomic.h> #include "millis.h" ·
Author   ZakKemble
🌐
GitHub
github.com › sourceperl › millis › blob › master › millis.c
millis/millis.c at master · sourceperl/millis
millis.c - sample Arduino millis() on an ATTiny85 (use timer0 overflow · interrupt do to it) · · Code in public domain · **********************************/ · #define F_CPU 8000000UL · #include <avr/io.h> #include <inttypes.h> #include <avr/interrupt.h> ·
Author   sourceperl
Discussions

c - Equivalent to Arduino millis() - Stack Overflow
I am currently working on the integration of a "shunt" type sensor on an electronic board. My choice was on a Linear (LTC2947), unfortunately it only has an Arduino driver. I have to translate ever... More on stackoverflow.com
🌐 stackoverflow.com
How to Code Millis
I am relatives new to arduino and dont understand how to Code millis More on forum.arduino.cc
🌐 forum.arduino.cc
12
0
July 2, 2024
Using millis() for timing. A beginners guide
Part 1 It is not usually long before new Arduino users discover that although the delay() function is easy to use it has side effects, the main one of which is that its stops all activity on the Arduino until the delay is finished (not quite true, I know, but that is usually how the problem ... More on forum.arduino.cc
🌐 forum.arduino.cc
3
42
October 2, 2017
Help with code - using millis() instead of a delay
I have to say that the code is really weirdly formatted and very tough to read. But working with millis in general: Millis returns a number of milliseconds since the board has started. At the end of setup, store millis() value in a variable and then in your main loop, you continuously compare if: millis() - last_millis > delay_you_want If it is, it means that the time you needed has passed and you should perform the action you want. After doing the deed, you store millis() in last_millis, which effectively "resets" the timer and you keep checking the difference in the main loop, until the time has come to do the deed again. Since you need to change the delay, I guess you could compare the millis difference against a global variable and every time you do a deed, you update the delay variable depending on if you need to wait for a dash/dot/between characters etc. More on reddit.com
🌐 r/arduino
14
1
October 11, 2024
🌐
Programming Electronics Academy
programmingelectronics.com › home › arduino sketch with millis() instead of delay()
millis() instead of delay() with Arduino [Guide + Code]
November 13, 2023 - Trying to use millis() instead of delay() with Arduino? This lesson will give you the explanations and code you need to master millis()!
🌐
Arduino
arduino.cc › reference › en › language › functions › time › millis
millis() | Arduino Documentation
October 31, 2023 - This function returns the number of milliseconds passed since the program started. Data type: ... This example code prints on the serial port the number of milliseconds passed since the Arduino board started running the code itself.
🌐
FC2
garretlab.web.fc2.com › top › arduino › internal structure of arduino software › avr › wiring.c › millis()
millis() - garretlab - FC2
July 31, 2025 - The millis() is defined in hardware/arduino/avr/cores/arduino/wiring.c as below. Only the souce code for Arduino UNO is quoted. The original source code supports many tips using #if’s.
🌐
GitHub
github.com › Koepel › Fun_with_millis
GitHub - Koepel/Fun_with_millis: Small Arduino examples using the millis() function. · GitHub
millis_short_press_long_press_extra.ino This sketch does exactly the same as "millis_short_press_long_press.ino" but a finite state machine is used. The compiled code uses less memory, but the source code is harder to understand.
Starred by 15 users
Forked by 2 users
Languages   C++
Top answer
1 of 3
2

Arduino millis() is based on a timer that trips an overflow interrupt at very close to 1 KHz, or 1 millisecond. To achieve the same thing, I suggest you setup a timer on the ARM platform and update a volatile unsigned long variable with a counter. That will be the equivalent of millis().

Here is what millis() is doing behind the scenes:

SIGNAL(TIMER0_OVF_vect)
{
    // copy these to local variables so they can be stored in registers
    // (volatile variables must be read from memory on every access)
    unsigned long m = timer0_millis;
    unsigned char f = timer0_fract;

    m += MILLIS_INC;
    f += FRACT_INC;
    if (f >= FRACT_MAX) {
        f -= FRACT_MAX;
        m += 1;
    }

    timer0_fract = f;
    timer0_millis = m;
    timer0_overflow_count++;
}

unsigned long millis()
{
    unsigned long m;
    uint8_t oldSREG = SREG;

    // disable interrupts while we read timer0_millis or we might get an
    // inconsistent value (e.g. in the middle of a write to timer0_millis)
    cli();
    m = timer0_millis;
    SREG = oldSREG;

    return m;
}

Coming from the embedded world, arguably the first thing you should do when starting a project on a new platform is establish clocks and get a timer interrupt going at a prescribed rate. That is the "Hello World" of embedded systems. ;) If you choose to do this at 1 KHz, you're most of the way there.

2 of 3
2
#include <time.h>
unsigned int millis () {
  struct timespec t ;
  clock_gettime ( CLOCK_MONOTONIC_RAW , & t ) ; // change CLOCK_MONOTONIC_RAW to CLOCK_MONOTONIC on non linux computers
  return t.tv_sec * 1000 + ( t.tv_nsec + 500000 ) / 1000000 ;
}

or

#include <sys/time.h>
unsigned int millis () {
  struct timeval t ;
  gettimeofday ( & t , NULL ) ;
  return t.tv_sec * 1000 + ( t.tv_usec + 500 ) / 1000 ;
}

The gettimeofday() version probably does not work on non linux computers.

The clock_gettime() version probably does not work with old C compilers.

The arduino millis() returns unsigned long, 32 bit unsigned integer. Most computers are 32 bit or 64 bit, so there is no need to use long except on 16 bit computers like arduino, so these versions return unsigned int. If you want to measure a time period longer than 50 days in milliseconds, or if you want the number of milliseconds since the beginning of unix in 1970, you need a long long (64 bit) integer.

If a computer clock has the incorrect time, the operating system or system administrator or program which synchonizes the computer clock with internet clocks may change the computer clock to the correct time. This will affect these functions, especially the gettimeofday() version. Usually there is a big change in the computer clock when the computer boots, connects to the network, and synchonizes the computer clock with the network time server. But most programs are not running this early in the boot process, and thus are not affected. Usually other changes to the computer clock are very small, and the effect on other programs is very small. So usually changes to the computer clock are not a problem.

The clock_gettime() requires a clock id.

CLOCK_MONOTONIC is not affected by discontinuous jumps in the system time, but is affected by incremental adjustments, and does not count time computer is suspended.

CLOCK_MONOTONIC_RAW is linux only, not affected by discontinuous jumps in the system time, not affected by incremental adjustments, does not count time computer is suspended.

CLOCK_BOOTTIME is linux only, not affected by discontinuous jumps in the system time, but is affected by incremental adjustments, does count time computer is suspended. It counts the time since the computer booted.

CLOCK_REALTIME is affected by discontinuous jumps in the system time, and by incremental adjustments. It does count the time the computer is suspended. It counts standard unix time (time since the beginning of unix in 1970).

I think CLOCK_MONOTONIC_RAW is the best choice for linux, and CLOCK_MONOTONIC is the best choice for non linux. Usually millisecond time is used to measure short periods of time, like how long it takes for part of a computer program to run. In a short period of time, there will probably be no changes to the computer clock, and the computer will probably not be suspended, so any clock id will work, so the choice of clock id is not important.

Precise time measurements are unreliable on multitasking computers because the time measurement might be interrupted. Errors are usually small. Sometimes this is a problem, and sometimes it isn't. If you need more precise time measurements, you need dedicated hardware which cannot be interrupted. Some computers have such hardware built in. For example, if a program uses software pwm, changes to the output will be delayed if the computer is interrupted at the time the computer needs to change the output. But if the program uses hardware pwm, the hardware pwm controller cannot be interrupted, and will change the output at the correct time.

Tested on a raspberry pi.

Find elsewhere
🌐
Best Microcontroller Projects
best-microcontroller-projects.com › home › arduino hardware › arduino millis
Secrets of Arduino millis: How it works and how to use it.
Note: The above discussion is talking ... main code and operate e.g. timers or I2C interfaces etc. still work. Note: millis() does not always increment by one due to the way the timing is calculated within the interrupt routine. The link takes you to a detailed simulation of millis() in this page. No it is not! Well, it does quite a good job. ... The clock source - This is true of all crystal oscillator based systems but some Arduino boards use ...
🌐
CircuitDigest
circuitdigest.com › microcontroller-projects › arduino-multitasking-using-millis-in-arduino
Arduino Millis Tutorial - How to use millis() in Arduino Code for Multitasking
April 14, 2022 - This finishes the Arduino millis​() Tutorial. Note that in order to get habitual with millis(), just practice to implement this logic in some other applications. You can also expand it to use motors, servo motors, sensor and other peripherals. In case of any doubt then please write to our forum or comment below. Complete code and Video for demonstrating the use of millis function in Arduino is provided below.
🌐
ElectronicsHub
electronicshub.org › home › arduino
Arduino - ElectronicsHub
August 16, 2018 - Raspberry Pi and Arduino are two very popular boards among electronics DIY builders, hobbyists and even professionals.
🌐
GitHub
github.com › arduino › reference-es › blob › master › Language › Functions › Time › millis.adoc
reference-es/Language/Functions/Time/millis.adoc at master · arduino/reference-es
Returns the number of milliseconds since the Arduino board began running the current program. This number will overflow (go back to zero), after approximately 50 days. ... The code reads the milllisecond since the Arduino board began.
Author   arduino
🌐
Arduino Getting Started
arduinogetstarted.com › reference › arduino-millis
millis() | Arduino Getting Started
3 days ago - const unsigned long TIME_INTERVAL = 1000; unsigned long previousMillis; void setup() { Serial.begin(9600); previousMillis = millis(); } void loop() { if (millis() - previousMillis >= TIME_INTERVAL) { previousMillis = millis(); Serial.printl...
🌐
Programming Electronics Academy
programmingelectronics.com › home › millis() arduino function: 5+ things to consider
millis() Arduino function: 5+ things to consider - Programming Electronics Academy
April 6, 2023 - Have you heard of the Arduino millis() function? Did you know that it gives you access to the Arduino internal timer counter hardware which can be used for the timing of different events? We will discuss this and more in the video tutorial below.  Topics in this lesson What is a hardware ...
🌐
AranaCorp
aranacorp.com › blog › tutorials › using the millis() function of the arduino ide
Using the millis() function of the Arduino IDE • AranaCorp
April 23, 2023 - The millis() function takes no parameters and returns a value representing the number of milliseconds that have elapsed since the Arduino was powered up. The value is unsigned long (4-bytes or 32-bits).
🌐
GitHub
github.com › CIRCUITSTATE › CSE_MillisTimer
GitHub - CIRCUITSTATE/CSE_MillisTimer: Arduino library to simplify the use of millis() timer.
CSE_MillisTimer is a simple timer library from CIRCUITSTATE Electronics for the Arduino platform. It uses the millis() function to create a timer instance that you can use for controlled timing of events in your code.
Author   CIRCUITSTATE
🌐
Arduino Forum
forum.arduino.cc › projects › programming
How to Code Millis - Programming - Arduino Forum
July 2, 2024 - I am relatives new to arduino and dont understand how to Code millis
🌐
Seeed Studio
seeedstudio.com › home › multitasking with arduino – millis(), rtos & more!
Multitasking with Arduino - Millis(), RTOS & More! - Latest News from Seeed Studio
September 29, 2021 - Take your microcontroller programming to the next level by achieving multitasking with Arduino. This article covers millis(), RTOS, and more!
🌐
GitHub
github.com › sourceperl › millis
GitHub - sourceperl/millis: Implementation of millis() (like in Arduino IDE) on AVR microcontrollers ATTiny85 · GitHub
Implementation of millis() (like in Arduino IDE) on AVR microcontrollers ATTiny85 - sourceperl/millis
Author   sourceperl
🌐
Arduino Forum
forum.arduino.cc › projects › tutorials
Using millis() for timing. A beginners guide - Tutorials - Arduino Forum
October 2, 2017 - Part 1 It is not usually long before new Arduino users discover that although the delay() function is easy to use it has side effects, the main one of which is that its stops all activity on the Arduino until the delay is finished (not quite true, I know, but that is usually how the problem ...