cancel
Showing results for 
Search instead for 
Did you mean: 

Does main() require an infinite loop?

The BOOM
Associate III

This page says:

"With a custom main() on Arduino, do not return from main(). As there is no operating system running on a standard Arduino, there is no where to return to. If you do return, abort() is called, then exit(). On the AVR-8 MCU ( Uno, Mega ) this results in global interrupts being disabled and execution enters an infinite loop. To overcome the eventual return, you can utilize an infinite loop of your own, which is not unlike what the Arduino core does itself."

Does this same rule apply to the STM32 MCUs?"

thx

21 REPLIES 21

>>Ok, but is the loop required for interrupts and other features to work, as it is on Arduino?

The while() loop is to stop it exiting main() and disappearing down a wormhole... or falls of the edge of the known world.

Follow where it goes. You want a functioning system with code execution, not end up in a fault handler because it ran out of things to execute.

The use of a __WFI() basically stops the CPU until the next interrupt comes along. It services the interrupt, and runs back into the __WFI()

Use while(1) loop(); if it makes you more at home.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

@Community member​ "disappearing down a wormhole... or falls of the edge of the known world"

can you define that in STM32 terms?

Are you saying interrupts will fail without the while loop?

How is while(1) loop(); any different? It is still just an infinite loop.

"if it makes you more at home."

I'd like to eliminate the while loop, if possible, and still receive interrupts.

@KnarfB​ i think i misunderstood your reply, above. You weren't saying to remove the while() loop, just saying to put the HAL_PWR_ statements inside of it, correct?

The BOOM
Associate III

Some have said the while loop "doesn't hurt". Which is different than saying it's "required" for interrupts to work.

To clarify, my main purpose here isn't to save power. It's to stop code running while awaiting interrupts. i'll be running the ADC at high frequency. i don't want to wake up every time the ADC fires an interrupt.

Is sleep-mode the only way to stop execution between interrupts?

In Keil then GNU/GCC startup.s

; Reset handler
Reset_Handler   PROC
                EXPORT  Reset_Handler                    [WEAK]
                IMPORT  SystemInit
                IMPORT  __main
 
                LDR     R0, =SystemInit
                BLX     R0
                LDR     R0, =__main
                BX      R0
; Edge of the Flat-Earth..
;  probably some literals here before the tortoises and elephants.
                ENDP
 
HardFault_Handler\
                PROC
                EXPORT  HardFault_Handler                [WEAK]
 
                ; Determine correct stack
 
                TST     lr, #4
                ITE     EQ
                MRSEQ   R0, MSP         ; Read MSP (Main)
                MRSNE   R0, PSP         ; Read PSP (Process)
 
                MOV     R1, R4
                MOV     R2, R5
                MOV     R3, R6
 
                EXTERN  hard_fault_handler_c
                B       hard_fault_handler_c
                ENDP
 
; Dummy Exception Handlers (infinite loops which can be modified)
 
NMI_Handler     PROC
                EXPORT  NMI_Handler                      [WEAK]
                B       .
                ENDP
..
...
LoopFillZerobss:
  ldr  r3, = _ebss
  cmp  r2, r3
  bcc  FillZerobss
 
/* Call static constructors */
    bl __libc_init_array
/* Call the application's entry point.*/
  bl  main
  bx  lr /* who knows where this wormhole comes out the other side */
.size  Reset_Handler, .-Reset_Handler

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

>>Are you saying interrupts will fail without the while loop?

No, I'm asking what magical CPU state they are coming out of?

>>How is while(1) loop(); any different? It is still just an infinite loop.

It isn't, but it is what your Arduino model is doing behind the curtain, right?

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

now i just need to understand the code you gave. Was hoping for a plain-english explanation. "LoopFillZerobss" doesn't get me closer to understanding whether the while loop is required for interrupts to work.

KnarfB
Principal III

Let me put it in other words: the processor doesn't know about main, loops etc.. It will execute the next machine instruction in (basically ) every new clock cycle. Unless it sleeps and is not woken up. Its a programmer's responsibility that the processor always finds a valid next instruction. An unconditional while loop at the end of main is a simple way of ensuring that.

Interrupts interrupt the normal flow of instructions. If the processor sleeps, an interrupt wakes it up. At the end of an interrupt handler, the processor returns to the interrupted instruction stream (which must be valid!) or returns to sleep (if sleep-on-exit is on).

For more information, I really recommend Joseph Yiu "The Definitive Guide to the ARM_Cortex-M..."

While reading, pick an IDE and start implementing what you read.

hth

KnarfB

Piranha
Chief II

Just to add to the confusion.. One can exit the "endless loop" with break or goto, if necessary. And exiting from main() can be used in bootloader or some other scenarios. With appropriate startup code, obviously.

Piranha, will interrupts still work?
thx

Interrupts will work whiile enabled and the CPU has not hit some trap.