Author Topic: [SAMC] pointer code only works within a function  (Read 12616 times)

0 Members and 2 Guests are viewing this topic.

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 18916
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
[SAMC] pointer code only works within a function
« on: January 24, 2020, 09:03:40 pm »
I am just testing out my first very basic libraries for the SAMC. So lets toggle a pin. I started with just setting and resetting the pin and noticed that my little program required 20.5 clock cycles so i assume depending on which way the if/else goes 20 or 21 cycles. So I though right lets try toggle to see how much faster it is. Not that much at 18 cycles. So I thought maybe I should take my code from the function and just put that in to so if it runs quicker. But then it stopped working. If I call my function it works, but if I just use the functions code nothing.

So the function code:
Code: [Select]
void pin_tgl(uint8_t port, uint8_t pin ){
( * ( uint32_t * )( PORT_BASE + PORT_PIN_TOGGLE + port * PORT_OFFSET ) ) = 0x1 << pin ;
}

So

pin_tgl( 1, 8 );   

gets me a 111kHz square wave.

( * ( uint32_t * )( PORT_BASE + PORT_PIN_TOGGLE + 1 * PORT_OFFSET ) ) = 0x1 << 8;

gets me nothing
even

( *  (uint32_t * )( 0x4100009C)  ) = 0x00000100 ;

got nothing.

So what is going on? why will the code only work when it is wrapped in a function?
 

Offline ataradov

  • Super Contributor
  • ***
  • Posts: 12498
  • Country: us
    • Personal site
Re: [SAMC] pointer code only works within a function
« Reply #1 on: January 24, 2020, 09:12:02 pm »
Try "( *  (volatile uint32_t * )( 0x4100009C)  ) = 0x00000100 ;". It might be a compiler optimization.

Also, looking at the disassembly is a great debugging tool in cases like this.

I usually add a bunch of nop instructions to be able to locate the piece of code easily.

Code: [Select]
asm("nop");
asm("nop");
asm("nop");
asm("nop");
( *  (uint32_t * )( 0x4100009C)  ) = 0x00000100 ;
asm("nop");
asm("nop");
asm("nop");
asm("nop");

Then run "arm-none-eabi-objdump -d file.elf > disasm.txt".

And then look for those nops and see what happened to the code in between.
« Last Edit: January 24, 2020, 09:14:26 pm by ataradov »
Alex
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 18916
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [SAMC] pointer code only works within a function
« Reply #2 on: January 24, 2020, 09:16:11 pm »
Yes that works, but volatile is for a variable that can be changed by another part of a program like an interrupt. what is the relevance here?

Now running 400kHz so 5 clock cycles, the function call and return is taking 13 cycles
« Last Edit: January 24, 2020, 09:18:36 pm by Simon »
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 18916
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [SAMC] pointer code only works within a function
« Reply #3 on: January 24, 2020, 09:16:52 pm »
should I put volatile on any pointer to a register?
 

Offline ataradov

  • Super Contributor
  • ***
  • Posts: 12498
  • Country: us
    • Personal site
Re: [SAMC] pointer code only works within a function
« Reply #4 on: January 24, 2020, 09:20:56 pm »
Yes, you should. Otherwise compiler assumes that it is a normal memory location. And if  you write into a variable, but never read back, the write is not necessary and can be optimized.
Alex
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 18916
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [SAMC] pointer code only works within a function
« Reply #5 on: January 24, 2020, 09:23:17 pm »
right. Thanks
 

Offline andersm

  • Super Contributor
  • ***
  • Posts: 1198
  • Country: fi
Re: [SAMC] pointer code only works within a function
« Reply #6 on: January 24, 2020, 09:39:45 pm »
but volatile is for a variable that can be changed by another part of a program like an interrupt.
No. The volatile qualifier was added to the language as a tool for accessing hardware registers. The formal definition is something like "any expression referring to [a volatile-qualified object] shall be evaluated strictly according to the rules of the abstract machine". In practice it is a method of telling the compiler that touching some things has side-effects which it can't deduce from the code, and thus isn't allowed to eg. perform some types of optimizations. While volatile is often used with variables shared between interrupts and user mode code, it is in fact not the right tool for that, since it doesn't protect you against race conditions. Instead, you should use atomic types, provided your compiler supports them.
 
The following users thanked this post: nigelwright7557

Offline mikerj

  • Super Contributor
  • ***
  • Posts: 3671
  • Country: gb
Re: [SAMC] pointer code only works within a function
« Reply #7 on: January 24, 2020, 10:44:05 pm »
While volatile is often used with variables shared between interrupts and user mode code, it is in fact not the right tool for that, since it doesn't protect you against race conditions. Instead, you should use atomic types, provided your compiler supports them.

Volatile should be used in addition to atomic access methods in this case.
 

Online Siwastaja

  • Super Contributor
  • ***
  • Posts: 11386
  • Country: fi
Re: [SAMC] pointer code only works within a function
« Reply #8 on: January 25, 2020, 01:34:36 pm »
Also add the same volatile to the function version. It's now working by pure luck. It's also slow for the same reason: it's not defined inline.

Define it as "static inline", and it becomes as quick as your direct code copypasta version - and likely also stops working.
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 18916
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [SAMC] pointer code only works within a function
« Reply #9 on: January 25, 2020, 01:37:42 pm »

Define it as "static inline", and it becomes as quick as your direct code copypasta version - and likely also stops working.

You mean it would stop working if i did not put volatile into the static function. So if I use static it will basically just pun the function content in and not treat it as a function call and return?
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 18916
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [SAMC] pointer code only works within a function
« Reply #10 on: January 25, 2020, 01:56:45 pm »
static inline void pin_tgl(uint8_t port, uint8_t pin ){
   ( * ( volatile uint32_t * )( PORT_BASE + PORT_PIN_TOGGLE + port * PORT_OFFSET ) ) = 0x1 << pin ;
}

produces the error: static declaration of 'pin_tgl' follows non-static declaration   
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 18916
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [SAMC] pointer code only works within a function
« Reply #11 on: January 25, 2020, 01:57:28 pm »
do i have to take out the "void"?
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 18916
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [SAMC] pointer code only works within a function
« Reply #12 on: January 25, 2020, 02:01:29 pm »
it can't be static because it takes arguments surely?
 

Online Siwastaja

  • Super Contributor
  • ***
  • Posts: 11386
  • Country: fi
Re: [SAMC] pointer code only works within a function
« Reply #13 on: January 25, 2020, 02:16:26 pm »
it can't be static because it takes arguments surely?

Absolutely nothing to do with arguments. You know, you can look these things up on Google instead of guessing.

Static function defines whether you want to expose the function to other modules - i.e., other, separately compiled C files. It's a qualifier, like inline, so you use the return type as well:

static inline void function(int argument)
{

}


If you are making a library, for example, you want to have the interface functions without static qualifier. The "internals", i.e. functions that your module calls (for code readability / reuse within that module) can and should be all static.

Without static, compiler needs to expose the function for linker, and is forced to assume anyone can call the function from anywhere, so it can't optimize much. With static, only that file uses the function, so compiler can do whatever it wants.

A beginner often does small projects in one file. In this case, all functions should be made static. Yes, beginners also forget to do that, resulting in larger and slower code.
« Last Edit: January 25, 2020, 02:19:01 pm by Siwastaja »
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 18916
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [SAMC] pointer code only works within a function
« Reply #14 on: January 25, 2020, 02:18:50 pm »
i was not the one wanting to make it static. Apparently it was going to make it faster.
 

Offline AG6QR

  • Frequent Contributor
  • **
  • Posts: 868
  • Country: us
    • AG6QR Blog
Re: [SAMC] pointer code only works within a function
« Reply #15 on: January 25, 2020, 04:12:47 pm »
static inline void pin_tgl(uint8_t port, uint8_t pin ){
   ( * ( volatile uint32_t * )( PORT_BASE + PORT_PIN_TOGGLE + port * PORT_OFFSET ) ) = 0x1 << pin ;
}

produces the error: static declaration of 'pin_tgl' follows non-static declaration

That suggests the problem is that you have a non-static declaration of the function before your static declaration.  Did you make a function prototype anywhere?  In a header file?

If so, make sure the declaration matches the definition.

 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 18916
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [SAMC] pointer code only works within a function
« Reply #16 on: January 25, 2020, 04:15:04 pm »
Yes, did that but then as explained it means the function can only be used in that file which is not main.c so it failed to work as the definition of the function was missing.
 

Offline donotdespisethesnake

  • Super Contributor
  • ***
  • Posts: 1093
  • Country: gb
  • Embedded stuff
Re: [SAMC] pointer code only works within a function
« Reply #17 on: January 25, 2020, 04:40:26 pm »
If you make a function inline, and want to use it in a different file, put the whole function definition into the header file, and remove it from the .c file.
Bob
"All you said is just a bunch of opinions."
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 18916
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [SAMC] pointer code only works within a function
« Reply #18 on: January 25, 2020, 04:45:30 pm »
ooh yea baby, function call with nearly 4x the speed.
 

Offline ataradov

  • Super Contributor
  • ***
  • Posts: 12498
  • Country: us
    • Personal site
Re: [SAMC] pointer code only works within a function
« Reply #19 on: January 25, 2020, 05:03:59 pm »
And I once again will strongly advice to looks at the disassmbly. It has multiple benefits:
1. You will become more familiar with the ARM assembly.
2. You will be more familiar with the compiler behaviour in general.
3. You will actually know if compiler does what you expect it to do.
Alex
 
The following users thanked this post: mikerj

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 18916
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [SAMC] pointer code only works within a function
« Reply #20 on: January 25, 2020, 05:07:09 pm »
how do I get the assembly from AS7? I am not overly interested as i have enough on my plate but was curious and in time yes i should look at it.
 

Offline ataradov

  • Super Contributor
  • ***
  • Posts: 12498
  • Country: us
    • Personal site
Re: [SAMC] pointer code only works within a function
« Reply #21 on: January 25, 2020, 05:11:02 pm »
There is a disassembly view, but it is bad. I would not look for anything other tan actual step-by-step debugging.

To get a real disassembly use  "arm-none-eabi-objdump -d file.elf > disasm.txt". You can add this into your post-build events in the AS project settings and it will automatically generate the text file every time you build the project.
Alex
 
The following users thanked this post: hsn93

Offline Nerull

  • Frequent Contributor
  • **
  • Posts: 694
Re: [SAMC] pointer code only works within a function
« Reply #22 on: January 25, 2020, 05:34:44 pm »
inline often does nothing on modern compilers. The compiler can and will decide for itself if a function should be inlined, and it will inline functions you didn't ask it to and ignore your requests to inline functions it doesn't think are a good idea. It may even eliminate functions entirely.

For example, here's this simple code compiled on clang 8 with -O2:
Code: [Select]
static int square(int num) {
    return num * num;
}

int main() {
    return square(5);
}

And here's the intel-format generated ASM:
Code: [Select]
        mov     eax, 25
        ret

That's it.

It does a similar thing without 'static', but it keeps the code for the square function around, just never calls it. Link time optimization would likely remove that as well. Sticking -flto on the command line confirms that 'static' makes no difference in this case.
« Last Edit: January 25, 2020, 05:42:52 pm by Nerull »
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 18916
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [SAMC] pointer code only works within a function
« Reply #23 on: January 25, 2020, 05:38:52 pm »
yes because the function did not take any runtime input. My functions do although they are predetermined and maybe if i used a lot of them it would stop inlining and call it to save space. i am not overly bothered but if inlining the function makes it more likely to to be treated as such and speed up the program great. If it can't then so be it.
 

Offline andersm

  • Super Contributor
  • ***
  • Posts: 1198
  • Country: fi
Re: [SAMC] pointer code only works within a function
« Reply #24 on: January 25, 2020, 06:53:12 pm »
yes because the function did not take any runtime input.
Having constant arguments allows the compiler to evaluate the function call at compile time, but it's not a limit for inlining. Rather, the compiler will use some heuristic to determine if it should inline the function call or not. GCC for example will almost always inline a function if the overhead of calling it is larger than the function body itself.


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf

 

- - -
-->