Electronic – Differences in using c user-defined functions on PC and on ARM

armatmel-studiodelaydiodesmicrocontroller

I am new to programming in c and to ARM also, so forgive me silly question. I would like to find answer on the net rather than to bother you, but there is not many materials in the web.
I am using Arduino Due board with Atmel SAM3X8E, ARM Cortex M3 and Atmel Studio 6 instead of Arduino IDE.

I wanted to create simple program based on sleep function to blink diode. Sure, there is no point in using sleep function instead of timers. I was just about to check if that work and get familiar with interrupts. But it doesn't work…

Because as I found out here there is no delay functions for ARM, so I created my one.
When I put the for loop into main function (In the places I show in comments) everything is okay, diodes blinks alternately. When I use mySleep() they both blink continuously. I've generated similiar program in CodeBlocks on PC with stdio.h and printf instead of asf.h and PIO registers. That works as I wanted. Here is code below:

#include <asf.h>

void mySleep(void);

int main (void)
    {
    PIOB->PIO_PER = PIO_PB26;
    PIOB->PIO_OER = PIO_PB26;
    PIOB->PIO_PUDR = PIO_PB26;
    PIOA->PIO_PER = PIO_PA14;
    PIOA->PIO_OER = PIO_PA14;
    PIOA->PIO_PUDR = PIO_PA14;

    while(1)
    {
        PIOB->PIO_SODR = PIO_PB26;
        PIOA->PIO_CODR = PIO_PA14;
        mySleep();
        //for(unsigned long long i=0;i<1000000;i++);    
        PIOB->PIO_CODR = PIO_PB26;
        PIOA->PIO_SODR = PIO_PA14;
        mySleep();
        //for(unsigned long long i=0;i<1000000;i++);
    }
}

void mySleep(void)
{
    for(unsigned long long i=0;i<1000000;i++);
}

Program is bulit with no error.
Here is my question. What is the difference between programming on PC and ARM? What should I do to get user-defined funtion work? Is there any additional library needed?

Thanks in advance.

Best Answer

The difference isn't in the platfrom.

The difference is that CodeBlocks probably compiles to no optimisation at Debug setting, whereas many, if not most, embedded compilers - as configured out of the box - optimise away function calls that have no macroscopic effect.

If you go to debug mode you will see you can't put any breakpoints inside mySleep(). This is because the compiler decided to not include it in the limited code space of your processor, since inside it nothing happens.

That said, Atmel has Delay(), Delay_ms() and Delay_us() that use an ASM VOLATILE nop loop to get very close to guaranteed delays if the CPU speed is set correctly.

You can also include inline ASM code (google it if you want) as VOLATILE inside your loop, having it execute a single NOP instruction (NOP = No Operation = Do nothing). For ARM GCC, an online cookbook quotes:

asm volatile("mov r0, r0");

Volatile means "do not touch!" or otherwise "Do not optimise it away for me!".

I'm too lazy to check, but I believe ARM also has the NOP instruction.


You can also probably change the settings for optimisation, but that means your code will become huge very quickly if you're just starting out.