How does the "delay" mechanism work in atmega328p

Go To Last Post
46 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

In a regular Linux x86 environment, we can use the "sleep(size_t x)" C function to delay execution X number of seconds.

Behind the scenes, libc calls "nanosecond" which makes a system call and gets the current time directly from BIOS. BIOS is programmed to 

return the time based on the frequency of the oscillator on the motherboard.

 

I know the "sleep" function doesn't exit with "avr-gcc".  Arduino uses the "delay" function to accomplish the same, here is the source code:

https://github.com/arduino/ArduinoCore-samd/blob/master/cores/arduino/delay.c

 

My question is, how does this work? 

 

Assume I need to wait "20 milliseconds" on atmega328p. How does its core know how long a millisecond is? Does it work like Linux x86 explained above?

This topic has a solution.
Last Edited: Tue. Jul 7, 2020 - 02:03 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

avruser1523 wrote:
How does its core know how long a millisecond is?

It uses a timer.

 

EDIT

 

which is  linked to the the equivalent of "the oscillator on the motherboard"

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Mon. Jul 6, 2020 - 09:31 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 2

Unless the program is dirt simple, if you end up hard delaying much time at all you should reconsider your overall program flow.

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

There are TWO mechanisms...

 

One, as implemented in Arduino-land, uses a hardware timer. It is not blocking because the MCU can continue to execute code while  the timer runs. The setup code has to know the MCU clock  frequency in order to determine how to initialize the timer.

 

The other, as implemented in avr-libc (and generally used in non-Arduino basic delay situations) sits in a function, "spinning" in a set of carefully crafted loops that run for a  specified number of microseconds or milliseconds. This is a "blocking" technique because the MCU really needs to spend all of its time in these software loops if the timing is going to be accurate. Thus, you don't want anything else happening, especially interrupts. The compiler has to build the desired pattern of loops when the program is compiled, so you cannot easily vary the delay time with a variable (though there are techniques around this limitation). To construct the pattern of loops, the compiler has to know the MCU clock frequency.

 

Hope this helps

Jim

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

My question is, how does this work? 

Exactly the same as it works in Linux, a hardware timer is used so that program flow is not halted.

 

I know you don't want to stress you brain in understanding hardware but if you are serious then you MUST get your hands dirty and understand something bout hardware.

 

ie READ the datasheet for the chip used in whatever Arduino board you are using.

John Samperi

Ampertronics Pty. Ltd.

https://www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Behind the scenes, libc calls "nanosecond" which makes a system call and gets the current time directly from BIOS.

I'm not convinced that your linux summary is very close to correct.  While there is a nanosecond counter "somewhere", a user-level "sleep" call will usually use a much lower-resolution "system tick" timer based on a periodic interrupt.  (sleep() has a resolution of seconds, the system tick for a desktop OS is usually about 10ms.)

 

On the Arduino, a timer controlled by the crystal is set up to interrupt the system every 1.024ms, and then millis() is incremented by an appropriate amount, and micros() is derived from the count of clock ticks plus the contents of timer registers.

delay(n) simply loops until 1000 us has gone by n times, to give you n milliseconds.  (it USED to be based on the millis() value, which had unfortunate effects when called near the "edges" of the milliseconds ticks.  delay(1) would delay somewhere between "very short" and about 3ms.)

 

On Arduino, your program sits there running waiting for the count to expire.  On a desktop OS, other processes will be permitted to run while the time passes.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ka7ehk wrote:
It is not blocking because the MCU can continue to execute code while  the timer runs

atmega328p is single threaded, so while sleeping, what other code could possibly run? interrupts i'm thinking would be the only ones?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Why would you think that it "sleeps" during delay wait? In one case, it is fully occupied, running delay loop after delay loop. In the other case, the timer runs, and it  can do anything else it wants (or you want it to). That "else" might include sleep, but I would guess that not many use it that way. This could very well be the difference between wait and delay.

 

Jim

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

Last Edited: Mon. Jul 6, 2020 - 11:39 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So use it like a callback? C doesn't have this natively if i'm not mistaking, you have to use threads on normal OS's, "sleep" would just block the thread. How is this done an AVR, is there a sample code?

I mean the whole point of "sleep" is to block execution.

Last Edited: Tue. Jul 7, 2020 - 12:11 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Be careful with your use of the term 'sleep'. In an OS context, 'sleep' means the task is not executing. In the AVR world, 'sleep' is a specific mode where the processor is suspended in order to save power.

 

You could run an RTOS like freeRTOS and get the functionality you expect but since the AVR is reasonably resource constrained (ie ram), a RTOS is not usually a good idea. Thus co-operative techniques are used.

 

For 'callbacks', there are timers and interrupts - load the timer with the required time value and configure it to interrupt when it expires.

 

With millis(), the idea is that you store a timestamp and then loop reading millis() until the required time has expired. As part of the loop you would perform other processing tasks. So, one thread of execution and dividing the large computing task into smaller chunks. Similar to the 'async' techniques that are popular at the moment.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

atmega328p is single threaded, so while sleeping, what other code could possibly run?

As you have been told a few times it's all in the datasheet, don't be lazy!!

 

9. Power Management and Sleep Modes
 

or are you just wasting everyone's time?

John Samperi

Ampertronics Pty. Ltd.

https://www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

On a 'full-fat' operating system, very many functions end up with a system call, which asks the kernel to do something for, or on behalf of, the requesting process. In the case of sleep(), etc it is saying 'don't bother giving me any CPU time for this number of seconds'. 

 

Most small microcontrollers don't run an operating system or task scheduler. There is one application (task, process) and one thread of execution, rather like the old days of MS-DOS.

 

Your OP linked to the Arduino SAMD core source, which is for Arm processors. That will confuse you if you're currently focusing on AVR. The link you want is: https://github.com/arduino/Ardui...

 

void delay(unsigned long ms)
{
	uint32_t start = micros();

	while (ms > 0) {
		yield();
		while ( ms > 0 && (micros() - start) >= 1000) {
			ms--;
			start += 1000;
		}
	}
}

Which in turn calls micros():

unsigned long micros() {
	unsigned long m;
	uint8_t oldSREG = SREG, t;
	
	cli();
	m = timer0_overflow_count;
#if defined(TCNT0)
	t = TCNT0;
#elif defined(TCNT0L)
	t = TCNT0L;
#else
	#error TIMER 0 not defined
#endif

#ifdef TIFR0
	if ((TIFR0 & _BV(TOV0)) && (t < 255))
		m++;
#else
	if ((TIFR & _BV(TOV0)) && (t < 255))
		m++;
#endif

	SREG = oldSREG;
	
	return ((m << 8) + t) * (64 / clockCyclesPerMicrosecond());
}

This, as you can see, uses a timer.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

js wrote:
or are you just wasting everyone's time?

Sir i think we are talking abut 2 different sleeps. I'm talking about the C sleep function, not the Sleep Mode in AVR.

 

 

obdevel wrote:
This, as you can see, uses a timer.

 

Thanks, so the "delay" function IS blocking, it's a while loop. So you guys are saying there is another way to do this similar to "setTimeout" in javascript which is not blocking and it uses a hardware timer? 

Last Edited: Tue. Jul 7, 2020 - 01:29 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You've been presented a number of ways. None of which are specific to the AVR.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Right, my source of confusions was how this is done in Arduino's core. It's done with a fully blocking infinite loop, not this method which you have presented:

 

For 'callbacks', there are timers and interrupts - load the timer with the required time value and configure it to interrupt when it expires.

I have not really seen this method much. Definitely never saw it done in regular operating systems with C, even thought x86 supports this. They all block the thread with a loop.

Last Edited: Tue. Jul 7, 2020 - 02:13 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

'Blocking' as a term doesn't make sense in this context. There is nothing else to give processor time to; no other tasks, applications or threads. We are not being 'selfish' by hogging the processor. There is no other work to be done, so it doesn't matter if the code consumes all the processor time in a tight busy-wait loop.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Errr....how does Linux, Windows and just about any known OS do it? There's a hardware timer in there.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kartman wrote:

Errr....how does Linux, Windows and just about any known OS do it? There's a hardware timer in there.

 

We are going in circles here, so let's clarify once and for all. Th OS's are using the counter and not an infinite loop then? 

the kernel scheduler removes the process from the runnable set until the time has expired <-- this is how you get the "blocking" effect?

 

The Arduino code is obviously just doing an infinite loop.

Last Edited: Tue. Jul 7, 2020 - 02:58 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I think we are wasting time here but maybe it's only me.

John Samperi

Ampertronics Pty. Ltd.

https://www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Maybe these ideas have given you new guidance on how to restate the question (this new understanding may allow a better-crafted question & removal of spurious factors).

 

 

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

avrcandies wrote:

Maybe these ideas have given you new guidance on how to restate the question (this new understanding may allow a better-crafted question & removal of spurious factors).

 

 

 

That's just crazy talk!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

so the "delay" function IS blocking, it's a while loop. So you guys are saying there is another way to do this similar to "setTimeout" in javascript which is not blocking and it uses a hardware timer? 

The arduino delay() function is blocking.  The timer that drives it using non-blocking code.  (this is true of sleep() on desktops as well, although "blocking" means something different.)

Arduino's delay() looks at the time kept by the non-blocking timer service (micros())  micros() does not block.

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

A couple of examples.

Let's say you have a simple application that just needs to do something approximately once a second.

One way is

while(1)

{

    do_stuff();

    delay(1000);

}

That delay function is just running round and round in a loop until it determines that the required amount of time has passed. The way it determines how much time has passed ultimately comes from a hardware timer that has been setup to tick away at a certain rate.

Whilst sat in this loop, clearly there is no other code in the main loop that can run. What can still run is any interrupt code.

This is OK for getting things up and running initially, and it might remain OK for a relatively simple application and if you don't need to care about power consumption.

 

Another way to do it is, particularly if you do care about power consumption, would be

 

while (1)

{

    do_stuff();

    /* put processor into a low power mode and arrange for it to wake itself up 1 second later */

}

Exactly how you "put processor into a low power mode and arrange for it to wake itself up 1 second later" is very much processor dependent.

Typically it will involve some kind of processor specific 'sleep' instruction along with maybe setting up a hardware timer interrupt to fire one second later, with that interrupt configured as a wake up source for the processor.

 

In practice, irrespective of exactly which timing method you use (the above are just 2 simple examples), it will amost certainly end up involving a hardware timer and timer interrupts in some maner.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

avruser1523 wrote:

I know the "sleep" function doesn't exit with "avr-gcc".  Arduino uses the "delay" function to accomplish the same, here is the source code:

https://github.com/arduino/ArduinoCore-samd/blob/master/cores/arduino/delay.c

 

My question is, how does this work? 

 

Assume I need to wait "20 milliseconds" on atmega328p. How does its core know how long a millisecond is? Does it work like Linux x86 explained above?

Your link is to the SAM D core.  If you are interested in atmega code then look at this rather: https://github.com/arduino/Ardui...

 

Everything used by delay is present above the code, except yield(), which is an empty stub.  Towards the top there are even some brief but helpful comments.  Hopefully the bits and pieces from the rest of this discussion falls in place when you can see the actual implementation.

 

Edit: Apologies obdevel, I just noticed I basically repeated what you mentioned in reply #12...

Last Edited: Tue. Jul 7, 2020 - 12:16 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

MrKendo wrote:

A couple of examples.

 

Thank you so much.

 

So to summarize; On a regular OS, "sleep" usually sets a timer, remove your process from the scheduler so other process can use the cpu, the cpu is not actually sleeping here. once time is up, it will be re-added to the scheduler.

 

On a MCU, it might set a timer then invoke a specific low-power state useful for battery operation (yield() in above code), the cpu literally sleeps (but the timer is running) until the timer is up at which point it resumes it's operation. It doesn't "run another code", there is no other code, all there is my code which is sleeping.

 

 

Last Edited: Tue. Jul 7, 2020 - 02:16 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

MrKendo wrote:

A couple of examples.

avruser1523 wrote:
On a MCU, it will ...

Note that they were just examples - not a definitive statement of what "sleep" will always do in every conceivable case.

 

  • timers may or may not be used
  • low-power modes may or may not be invoked
  • busy-wait loops may or may not be used
  • interrupts may or may not be involved
  • etc, etc, ...

 

What happens in any specific case will be down to the designer to decide...

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Tue. Jul 7, 2020 - 10:14 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

avruser1523 wrote:

So to summarize...

 

No to both of those.

 

It's entirely implementation dependent. Often provided as a library by the compiler vendor, its function will depend on the whim of the vendor. And what effect is has on the chip will depend on what facilities the chip has.

#1 Hardware Problem? https://www.avrfreaks.net/forum/...

#2 Hardware Problem? Read AVR042.

#3 All grounds are not created equal

#4 Have you proved your chip is running at xxMHz?

#5 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand."

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

avruser1523 wrote:
here is the source code:
avruser1523 wrote:
My question is, how does this work? 
What a curious thing to ask. You just linked to the source code. So if you read it you will know exactly how it works won't you??

 

Or were you really asking "where is yield()? and what does it do?"

Last Edited: Tue. Jul 7, 2020 - 02:36 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
Or were you really asking "where is yield()? and what does it do?"

No, I was reading the "27.8.2 Serial Programming Algorithm" section under the data sheet and it has this line:

 

2. Wait for at least 20ms and enable serial programming by sending the programming enable serial instruction to pin MOSI.

And then got curious on how you wait "20 ms" on this chip. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

avruser1523 wrote:

clawson wrote:
Or were you really asking "where is yield()? and what does it do?"

No, I was reading the "27.8.2 Serial Programming Algorithm" section under the data sheet and it has this line:

 

2. Wait for at least 20ms and enable serial programming by sending the programming enable serial instruction to pin MOSI.

And then got curious on how you wait "20 ms" on this chip. 

 

But that whole section has nothing to do with code running on the chip. It is how you program the chip from an external device. It is the external device which must wait 20ms.

#1 Hardware Problem? https://www.avrfreaks.net/forum/...

#2 Hardware Problem? Read AVR042.

#3 All grounds are not created equal

#4 Have you proved your chip is running at xxMHz?

#5 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand."

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Brian Fairchild wrote:
But that whole section has nothing to do with code running on the chip.

Yes aware of that, but brain went like "how would this be done anyways?....".

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

avruser1523 wrote:

On a MCU, it might set a timer...

 

If _it_ is defined as the uC then you should reconsider defining _it_ when designing software on bare metal. If you want sleeping to happen, you need to pull out the datasheet and figure out which sleep level you're targeting. You might be fine with the WDT ISR or you might want WDT always guarding and need an async timer using an external clock source. You might not care at all about the WDT at all and want to use its oscillator for the uC where it's supported. 

 

You're limitations aren't going to be about the APIs or OS's level of hardware abstraction. Also, this feels like an x/y question; the compiler doesn't decide if you program a function to return a value or if it will never evaluate true to a return condition; any program which you wouldn't want to return after a pre defined set of iterations doesn't "exit" at the bottom of main() like a game or a windowed program or the operating system; nongnu avr toolchain which includes avr-gcc and avr-libc does have sleep and delay functions/macros; and lastly, I'm quite ignorant so I try not to presuppose parts of an answer to something I'm asking because, regardless if I'm told part of something that I already know, 1) I tend to get the answer quicker than if I'm argumentative about what I think I know, 2) you'll likely never be regarded in a negative connotation for asking a question and listening but you will for being a know-it-all-of-wrong-things, and 3) it's the internet so everything I didn't agree with is wrong anyhow and nothing is to be remotely trusted without sources (including this post [1]AtM3llchip.datasheet [2]nongnu.tld/avr-libc [3]4chan/b)

Last Edited: Tue. Jul 7, 2020 - 04:10 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Are you trying to, as you say:

Assume I need to wait "20 milliseconds" on atmega328p.

 

or are you trying to sleep?

 

Waiting and sleeping can be entirely diffeent things.  You have to decide whether you want to simply do nothing & waste cycles for 20ms, go do something else during the 20ms (and poll a timer or set up an irq to resume), or shutdown the chip for 20ms.   Have you decided what you want to do?  Look at the datasheet section describing the timers & all of your options.

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Tue. Jul 7, 2020 - 04:13 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

avrcandies wrote:
Waiting and sleeping can be entirely diffeent things.

This is the word everyone took the wrong way in this post.

 

by sleep i meant "delay this process" from a regular OS point of view, the "sleep function in C" and NOT the sleep mode in MCU. 

You almost never put a CPU to sleep in a normal OS (the HLT instruction in x86). it just delays your process while running some other stuff.

 

I learned that an MCU however will most likely be put fully to sleep while the counter ticks. OR you could choose to run something else on it, but the Arduino "delay" is just putting it to sleep running round and round a loop until the time has elapsed.

Last Edited: Tue. Jul 7, 2020 - 05:20 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

avruser1523 wrote:
by sleep i meant "delay this process" from a regular OS point of view, the "sleep function in C" and NOT the sleep mode in MCU. 
This is because sleep() in a hosting OS like Linux is something quite, quite different to "SLEEP" in an AVR! For Linux it just means "this thread can sleep for time period N, the OS can schedule all the other tasks to continue to operate while this one waits for the period to expire and will then be awakened". SLEEP in an AVR means "stop fetching opcodes. All this proves you cannot view the operation of a micro in the same way you view the operation of a complex OS - micros simply don't have one. They are "bare metal".

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

avruser1523 wrote:
the "sleep function in C"

??? I don't see that in my K&R book, where would I find this "sleep function in C"?

 

Jim

 

 

FF = PI > S.E.T

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sleep() is inherited from Unix/C over 40 years ago, when it was originally a C library function**. Clearly it's an unhelpful context, implying an o/s, a scheduler and other processes to share the CPU with. But we're stuck with it, and the alternatives are similarly burdened by context-dependent implications, e.g. suspend, delay, pause, halt, etc. 

 

** Original man page: https://www.unix.com/man-page/v7...

 

NAME

       sleep - suspend execution for interval

SYNOPSIS

       sleep(seconds)
       unsigned seconds;

DESCRIPTION

       The  current process is suspended from execution for the number of seconds specified by the argument.  The actual suspension time may be up
       to 1 second less than that requested, because scheduled wakeups occur at fixed 1-second intervals, and an arbitrary amount  longer  because
       of other activity in the system.

       The  routine  is  implemented by setting an alarm clock signal and pausing until it occurs.  The previous state of this signal is saved and
       restored.  If the sleep time exceeds the time to the alarm signal, the process sleeps only until the signal would have  occurred,  and  the
       signal is sent 1 second later.

 

I believe it's now implemented as a system call into the kernel.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

avruser1523 wrote:
I learned that an MCU however will most likely be put fully to sleep while the counter ticks. OR you could choose to run something else on it, but the Arduino "delay" is just putting it to sleep

No, the Arduino delay is just running round and round a loop until the time has elapsed.

No sleeping going on. (That yield function call is just a stub function that does nothing).

In the Arduino delay, it works out when the time has elapsed based on a hardware timer.

It is also possible to have a busy loop that just wastes time by executing nop instructions, you can work out how many instructions are needed for a given delay for a given clock frequency, no hardware timer required.

 

You are right to not confuse 'sleep' with 'delay' when talking about bare metal MCU without an Operating System.

What we shuold be talking about here is just delays.

I made the point earlier about 'puting into a low power mode' just as an example that if you have a case where the processor is going to be wasting time running round a loop, one option can be to put it into a low power mode, that way you can save some power whilst you are 'wasting time'. Using a low power mode in this bare metal context is more what you would think of as sleeping.

How you do that, or whether you can do that, is totally dependent on the features provided by a given processor.

For the AVR, it was already stated back in post #11 where you can read about power saving modes in the 328p datasheet (Section 9 'Power Management and Sleep Modes').

 

(If you do have an Operating System, when the scheduler decides that it hasn't got any tasks that need running, the scheduler might put the procesor into a low power mode at that point).

 

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

MrKendo wrote:
No, the Arduino delay is just running round and round a loop until the time has elapsed.

Thanks, I have made the correction. So it just sets the timer and checks the timer in a loop, basically polls.

I guess it could have been more energy efficient by putting the chip to sleep and wait for an interrupt when counter was done.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

MrKendo wrote:
It is also possible to have a busy loop that just wastes time by executing nop instructions, you can work out how many instructions are needed for a given delay for a given clock frequency, no hardware timer required.

and this is what the AVR-Libc _delay_ms() does:

 

https://www.nongnu.org/avr-libc/user-manual/group__util__delay.html#gad22e7a36b80e2f917324dc43a425e9d3

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

avruser1523 wrote:

avrcandies wrote:
Waiting and sleeping can be entirely diffeent things.

This is the word everyone took the wrong way in this post.

avruser1523 wrote:

by sleep i meant "delay this process" from a regular OS point of view, the "sleep function in C" and NOT the sleep mode in MCU. 

You almost never put a CPU to sleep in a normal OS (the HLT instruction in x86). it just delays your process while running some other stuff.

which comes from unistd.h and windows.h iirc and are not part of the standard c library as in ANSI C standard.

 

avruser1523 wrote:

I learned that an MCU however will most likely be put fully to sleep while the counter ticks. OR you could choose to run something else on it, but the Arduino "delay" is just putting it to sleep, there is no callback.

again, this is all implementation defined characteristics. Sleeping is power management related and happens as a result of writing to uC registers, some of which must be done in a defined number of cycles so that it isn't accidentally put to sleep. avr-libc hides this behind macros that use inline asm.  The arduino delay() and the avr-libc _delay_ms() are busy-wait but they do it in different ways with a different degree of 'exactness' at the expense of code size. 

 

No one (I'm hoping/guessing) here is trying to make you feel less of yourself for not already knowing that the terms carry a different meaning outside of a domain which you're already familiar, rather that you do know when all is said and done. If you're pulled over at a traffic stop and the officer asks if you've been drinking and you're just leaving a milk chugging contest, you might answer that you've drank so much that you're stomach is rumbling and could vomit at any time. You won't get the opportunity to say it was milk after the officer decides that you're under arrest. Once those words and said and those cuffs are on, you've just admitted to driving under the influence and the officer may not (not legal advice) be required to administer a BAC test and can cite your confession.

 

I realize that this may be far fetched yet I'd bet someone similar has already happened to someone, somewhere in time.

 

 

Edit; apparently I took to long to type all these stuffs and this was already addressed mostly. however, avr-libc delay compiles to asm that that conditionally tests and increments a value I thought. I recently recall seeing this from a post where someone was throwing a fit about F_CPU value.

Last Edited: Tue. Jul 7, 2020 - 05:56 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

The important thing here is that there is NO inherent link between delay and sleep. You can have delay with or without sleep. That is what the term "implementation dependent" is all about. It all depends on how the code writer writes it.

 

Again, as I wrote in another message, you assume too much. If the spec sheet (for Arduino code, or for AVR-libc or for the MCU) says that it sleeps while delaying, then it does. If it does NOT say that, then do not assume that it does.

 

Timer-based delay can sleep while the timer runs to an overflow (or compare) interrupt. Delay that is 100% loop-based, as with avr-libc, cannot sleep. IF this is important to you, then it is your responsibility to read the code and determine for yourself, how it behaves. This comes with the territory. It is something that ALL of us have to do from time to time.

 

Jim

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ka7ehk wrote:
The important thing here is that there is NO inherent link between delay and sleep. You can have delay with or without sleep.

Indeed.

 

See #26.

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

there is NO inherent link between delay and sleep.

On a microcontroller that has "sleep" low-power modes.   sleep() in a linux program and delay() in an Arduino sketch are very similar, which is what the OP was trying to compare.

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

westfw wrote:
in an Arduino sketch are very similar

Arduino seems to be doing it with a busy wait, i'm not sure if Linux does it exactly the same, it seems like it just removes it from the scheduler and sets a timer and no loop is involved:

 

https://man7.org/linux/man-pages/man2/nanosleep.2.html

https://stackoverflow.com/questions/30969481/does-sleep-nanosleep-work-by-utilizing-a-busy-wait-scheme

https://github.com/torvalds/linux/blob/master/kernel/time/hrtimer.c#L1879

Last Edited: Wed. Jul 8, 2020 - 04:56 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

avruser1523 wrote:
i'm not sure if Linux does it exactly the same, i
No Linux is a multi-tasking operating system. A "sleep()" is simply a timed yield().