This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

main endless loop Timer Problem

i am running this code on my nrf.

const nrf_drv_timer_t TIMER_LED = NRF_DRV_TIMER_INSTANCE(0);


uint8_t flag;

/**
 * @brief Handler for timer events.
 */
void timer_led_event_handler(nrf_timer_event_t event_type, void* p_context)
{
    //static uint32_t i;
    //uint32_t led_to_invert = (1 << leds_list[(i++) % LEDS_NUMBER]);
    
    switch(event_type)
    {
        case NRF_TIMER_EVENT_COMPARE0:
            //LEDS_INVERT(led_to_invert);
				nrf_gpio_pin_clear(LED_1);
				flag = 1;
				
            break;
        
        default:
            //Do nothing.
		
            break;
    }    
}


/**
 * @brief Function for main application entry.
 */
int main(void)
{
	flag=0;

    uint32_t time_ms = 3000; //Time(in miliseconds) between consecutive compare events.
    uint32_t time_ticks;
    //uint32_t err_code = NRF_SUCCESS;
    
    //Configure all leds on board.
    LEDS_CONFIGURE(LEDS_MASK);
    LEDS_OFF(LEDS_MASK);
    
    //Configure TIMER_LED for generating simple light effect 
    nrf_drv_timer_init(&TIMER_LED, NULL, timer_led_event_handler);
    
    time_ticks = nrf_drv_timer_ms_to_ticks(&TIMER_LED, time_ms);
    
    nrf_drv_timer_extended_compare(
         &TIMER_LED, NRF_TIMER_CC_CHANNEL0, time_ticks, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, true);
    
    nrf_drv_timer_enable(&TIMER_LED);
	while(1)
	{}
}

Why there is a need of while loop at the end without it my timer never starts

Parents
  • The normal start of any function (including main) starts ( with { ) with a PUSH operation. Where a bunch of register contents are pushed to the stack (to an address pointed by Stack Pointer, Register R13), then the address of next instruction to be executed is copied into link register and the start address of the function to be exxecuted is copied into PC(program counter) register, also called branch.

    Similarly when the function ends (with } ), the compiler adds a POP instruction that would restore the PUSHED register values back to the register. This all the main registers will have the same value just as before the function was started.

    But main is not a normal function. If you go to arm_startup_nrf51.s (assuming you are running Keil) you see the that main is started by Reset_Handler

    Reset_Handler   PROC
                    ...........
                    ...........
                    LDR     R0, =SystemInit
                    BLX     R0
                    LDR     R0, =__main
                    BX      R0
                    ENDP
    

    Here there was no push operation done. This means that the Reset_handler never expects the main to return (end). If the last closing bracket " } " in main is reached, then it will automatically mean a POP operation to the compiler. At this point the stack pointer is not pointing to any PUSHED registers because the Reset_Handler did not perform a PUSH (because it expects main not to return). Thus all the registers get corrupted with garbage POP operation and also the PC starts to execute garbage instructions probably corrupting the memory and probably hard_faulting. That is why your timer interrupts were not called.

    So the end of main should have an endless loop for the main never to return.

Reply
  • The normal start of any function (including main) starts ( with { ) with a PUSH operation. Where a bunch of register contents are pushed to the stack (to an address pointed by Stack Pointer, Register R13), then the address of next instruction to be executed is copied into link register and the start address of the function to be exxecuted is copied into PC(program counter) register, also called branch.

    Similarly when the function ends (with } ), the compiler adds a POP instruction that would restore the PUSHED register values back to the register. This all the main registers will have the same value just as before the function was started.

    But main is not a normal function. If you go to arm_startup_nrf51.s (assuming you are running Keil) you see the that main is started by Reset_Handler

    Reset_Handler   PROC
                    ...........
                    ...........
                    LDR     R0, =SystemInit
                    BLX     R0
                    LDR     R0, =__main
                    BX      R0
                    ENDP
    

    Here there was no push operation done. This means that the Reset_handler never expects the main to return (end). If the last closing bracket " } " in main is reached, then it will automatically mean a POP operation to the compiler. At this point the stack pointer is not pointing to any PUSHED registers because the Reset_Handler did not perform a PUSH (because it expects main not to return). Thus all the registers get corrupted with garbage POP operation and also the PC starts to execute garbage instructions probably corrupting the memory and probably hard_faulting. That is why your timer interrupts were not called.

    So the end of main should have an endless loop for the main never to return.

Children
No Data
Related