8
\$\begingroup\$

On a microcontroller (more specifically, on an Arduino Uno board using the ATmega 328P microcontroller) I would normally use an infinite loop to check for inputs etc (in Arduino land, this is normally the loop() function). If I leave this function blank however, it doesn't cause any problems.

On a desktop / laptop with an Intel i7 CPU etc if I ran a similar infinite loop (with nothing to do, or very little to do) it would pin the CPU at ~100% and generally spin up the fans etc ( a delay could be added to prevent this for example).

Why is this seemingly ok on a microcontroller but not usually wanted on a microprocessor? Am I right in thinking that the ATmega is in fact running at 100%, and that because it is so low powered it doesn't cause any obvious heat problems?

\$\endgroup\$
  • 1
    \$\begingroup\$ What if I told you the "idle" task on a processor was just a loop using up all the unused processor time that wasn't otherwise scheduled? \$\endgroup\$ – Ron Beyer Jan 5 at 15:31
  • 1
    \$\begingroup\$ @RonBeyer you mean things like the Linux idle task that executes the HLT (halt) instruction instead of actually looping? \$\endgroup\$ – Marcus Müller Jan 5 at 18:14
12
\$\begingroup\$

Why is this seemingly ok on a microcontroller but not usually wanted on a microprocessor?

It is also unwanted on a microcontroller for the same reason: it wastes power.

Am I right in thinking that the ATmega is in fact running at 100%

Correct.

and that because it is so low powered it doesn't cause any obvious heat problems?

Correct. However, if you run your microcontroller on batteries, then you have to think real hard about not wasting power. On a tiny cpu like AtMega328P it will not cause heat problems, but it will definitely shorten battery life.

All cpu's, whether they're desktop powerhouses or tiny microcontrollers, use the same methods:

1- Reduce clock speed or voltage.

2- Shut down unneeded hardware.

3- Go to sleep and wake up on an event (this is a special case of shutting down unneeded hardware, in this case the cpu is shut down).

In the AtMega328P you can implement this too. You can use a slower clock if you don't need all the awesome power of the 8-bit core, you can shut down unneeded peripherals... and the most important is the sleep mode.

You should read the manual for details, as there are several sleep modes which differ in wake-up latencies, what peripherals remain online and able to wake the cpu, whether RAM data is conserved or lost, etc. But basically the idea is: when in sleep mode, the cpu is stopped so it uses much less power. When an interrupt occurs, this wakes up the CPU and it processes the interrupt.

Of course you have to use the proper sleep mode and configure it properly so the peripheral that needs to wake up the cpu (for example, a timer or a GPIO interrupt) is not shut down. If everything is shut down, you'll have to use NMI or even Reset to wake it up, in the latter case by rebooting it.

If all your application does is wait on interrupts, like:

  • Pin Change Interrupt (PCI) to detect a button press or an incoming signal

  • Timer

  • Data received by UART or USB

  • etc

Then you don't need to spin the main loop. After configuring everything at boot, you'd start the main loop with a "go to sleep" instruction. The next instruction will execute after the cpu wakes up, processes all pending interrupts, and returns to the main loop. Then the main loop can, if required, do something about the received events, if they were not entirely handled by the interrupt code... and then go back to sleep.

Even if you're not using batteries, having low standby current can a mains powered the switching power supply to skip cycles and waste a lot less power too.

| improve this answer | |
\$\endgroup\$
8
\$\begingroup\$

On a microcontroller (more specifically, on an Arduino Uno board using the ATmega 328P microcontroller) I would normally use an infinite loop to check for inputs etc (in Arduino land, this is normally the loop() function). If I leave this function blank however, it doesn't cause any problems.

Classical programming pattern, having a main loop…

On a desktop / laptop with an Intel i7 CPU etc if I ran a similar infinite loop (with nothing to do, or very little to do) it would pin the CPU at ~100% and generally spin up the fans etc ( a delay could be added to prevent this for example).

… we might be writing different main loops.

This same main loop would be bad practice on a microcontroller too, because that also runs the CPU of that at full load – which burns power. Don't do that, especially if you're on battery.

Modern CPU cores have synchronization mechanisms. That allows people to implement something like "let this loop's execution sleep until 1 ms has passed, or until this condition has changed".

That's basically at the core of any multi-task operating system – and basically all OSes that deserve that name are by now. On microcontrollers, you'll often find so-called RTOSes (real-time operating systems), which make guarantees on how sure you can be that the execution of something has started after so and so many nanoseconds, because that's typical for the use case of microcontrollers, whereas on desktops and server CPUs you'll usually find fully-fledged simultaneous multiprocessing OSes that make fewer guarantees on timing, but offer a much larger set of functionalities and hardware and software environment abstraction.

I don't know the Arduino execution environment well enough to actually make qualified statements about it, I'm researching this as I write: Arduino seems not designed for this – it really expects you to just spin busily. Since it has no "yield" functionality, the "housekeeping" that it does between calls to your loop can't get called when you use the built-in delay function. Ugh! Bad design.

What you'd do in a power and/or latency-aware design, you'd use an RTOS for your microcontroller – FreeRTOS is pretty popular, for the ARM Cortex-M series, mbed has a lot of traction, I personally like ChibiOS (but I don't think that's a good choice when switching over from Arduino sketches), the Linux Foundation is pushing Zephyr (which I'm conflicted about); really, there's a wealth of choices, and the manufacturer of your microcontroller usually supports one or multiple through their IDEs.

Why is this seemingly ok on a microcontroller but not usually wanted on a microprocessor?

It's not really OK, it's an unusual design pattern, in fact, for microcontrollers, which typically do things in regular intervals or react to external stimuli. It's not usual that you want to "use as much CPU as you can" on a microcontroller continuously.

There's exceptions to that pattern, and they exist both in the MCU as well in the server/desktop processor world; when you know you practically always have e.g. network data to process in a switch appliance, or when you know that your game could always already precompute a bit of world that you might or might not need in a few moments, then you'll find these spin loops. In some hardware drivers, you'll find "spin locks", meaning that the CPU continuously queries a value until it has changed (e.g. the hardware is done setting up and can be used now), but it's generally an emergency solution only, and you'll have to explain why you're doing that when trying to get such code into Linux, for example.

Am I right in thinking that the ATmega is in fact running at 100%, and that because it is so low powered it doesn't cause any obvious heat problems?

Yes. The ATMega isn't, by modern standards, low powered, but it's low-power enough for the heat not to become a problem.

| improve this answer | |
\$\endgroup\$
  • 1
    \$\begingroup\$ .... dude. Freaking out about a downvote before I even had time to leave a comment explaining why. To go beyond the explanation I already gave, this is inferior to the other answer because it doesn’t take the context of the question into consideration. \$\endgroup\$ – RubberDuck Jan 5 at 14:00
  • 3
    \$\begingroup\$ Look at my reputation count: I couldn't care less about how many additional imaginary internet points I get; what's valuable to me is honest feedback. If I take anything out of EE.SE, it's that I learn a lot AND the social interaction :) \$\endgroup\$ – Marcus Müller Jan 5 at 14:03
  • 2
    \$\begingroup\$ "It's not really OK," nonsense, most of the time it's fine. It's not like the chip has anything else to do. The power you save with a fancy RTOS will never make up for the power expended implementing it, especially if you use a modern PC to do it! \$\endgroup\$ – Bruce Abbott Jan 5 at 19:36
  • 3
    \$\begingroup\$ Sure, but how much power did your PC use while you were programming it? More than 2 alkalines I bet. Probably more than 100 alkalines - enough to run that MCU for years! :) Since the OP asked specifically about Arduino Uno, there's little point talking about ultra-low power software (minimum current draw on that board is 15mA) and for the vast majority of things they get used for it doesn't matter. \$\endgroup\$ – Bruce Abbott Jan 5 at 20:22
  • 1
    \$\begingroup\$ How much power did the Arduino compiler use? Rounded to the nearest 1% of the monthly semi-random variation in my utility bills, zero. Whereas those AA's have been powering some BLE Arduino up in a tree for well over a month. Significant effort to climb that tree and replace them. \$\endgroup\$ – hotpaw2 Jan 5 at 20:48
3
\$\begingroup\$

Am I right in thinking that the ATmega is in fact running at 100%, and that because it is so low powered it doesn't cause any obvious heat problems?

Yes, it normally runs at 100% all the time, but is so low powered that it doesn't heat up significantly.

On a desktop / laptop with an Intel i7 CPU etc if I ran a similar infinite loop (with nothing to do, or very little to do) it would pin the CPU at ~100% and generally spin up the fans etc

The faster a CPU is clocked the more power it draws, because each time a logic level changes it must charge the capacitances of the transistors in the gates. Modern CPUs are designed to run as fast as possible - actually faster than possible. Even after making the transistors as small as possible, using the lowest possible voltage, and applying a huge heatsink, they still can't run fast enough to satisfy the PC user's 'need for speed'. So they rely on the fact that the OS and application programs spend most their time waiting for stuff to happen (user input, peripheral hardware etc.).

If you tried to run all the cores in an i7 continuously at maximum frequency it would melt down. To prevent this unused cores are powered off, and when maximum speed is not required (ie. most of the time) the active core(s) run at a lower frequency. When idle the OS doesn't just run a busy loop continuously executing instructions, but puts the CPU into a slowed down or halted state while it waits for interrupts etc. Various parts of the CPU can also be powered down when not in use.

The ATmega can also be put into lower power modes and individual peripherals turned off when not needed. If the system clock is changed to a lower frequency such as 32.678 kHz and all unnecessary peripherals are turned off, it can run (slowly) on just a few μA - not to reduce temperature, but to last longer on a small battery.

It is also possible to 'overclock' many Atmega chips. I have run an ATmega1284p (rated for 20MHz max at 5V) at 30MHz and it worked fine, but got quite warm.

| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

Depends on whether your ATmega system is running off of AC wall power or small batteries.

Running off of AC (via a wall wart power supply) the power consumed by 100% CPU utilizing spin loop is below the noise floor of the variation in your utility bill. Heat dissipation most likely too small to require a heat sink or fan, unless in a super insulated environment. Might be measurable with an IR thermometer.

Running off of small batteries, an Arduino spin loop will make a significant difference in how often you have to replace or recharge those batteries. Perhaps hours versus months. A serious problem if access to your embedded system is difficult. One common solution is to use some sort of timed lower-power sleep mode inside the infinite loop, or a sleep mode plus a wake-up interrupt from some external source.

| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

On a contemporary microprocessor you will most likely write a graphical user interface that does your job. The GUI has its own event loop(s) where things like mouse clicks, redraws etc. are processed. Most of your functionality will be located inside of an event handler that is delegated to by the main event loop.

Thus, if inside such an event handler you start an infinite loop, you are going to break the usual event processing, because it relies on you returning to the event loop after a pretty short period of time for the user interface to remain responsive. At least your own application will become unresponsive if you have an infinite loop (mouse clicks do nothing, graphics will not be updated anymore).

Multitasking as such (and thus the other processes) will normally not suffer from that, because other processes will be switched to by the OS-kernel nonetheless.

So it is not "evil" to have an infinite loop on a microprocessor, but it is against user experience standards, at least for graphical applications. For a console application however, you might well have an infinite loop without harm, say for example if you want to calculate pi up to 1 million digits (and finally put the result to the console) or anything similar, because the user is normally (worst-case) prepared for console applications that take almost forever to produce their results.

| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.