Switch Case Statements do not operate when using GCC Arm compiler and optimization - gcc

I am using the 2011 Q3 ARM GCC compiler with an ARM M0 platform. On my current application, if I do not use optimizations (compiling with -O0), my code is too large and doesn't fit. If I use any optimization (-O1, -O2, -O3, -Os), the SWITCH CASE statements do not work. I have validated the code inside this block is not getting executed as simple GPIO toggling operations are not coming through.
I read somewhere that any optimization from -O1 and above will have issues with goto code. However, I can't find the solution to this problem anywhere.
I also tried using the latest GCC ARM compiler, but my tools are not compatible with this release.
Any help on this matter is appreciated!

Try splitting your source code like so: the code that you don't want to optimize (eg. accesses to the memory mapped regions like GPIO) and the rest of it.
After you compile each source file with a different optimization level, you will get a working version with the "fragile" code.
Then, when you will debug the code, you will work with an object (.o) file and compile the rest.

Related

when does the compiler compile the code into machine code?

As far as I know, the compiler compiles the code by converting it to a language that a computer can understand which is the machine language and this is done before running the code.
So, does the compiler compile my code each time I write a character in the file?
And if so, does it check the whole code? Or just the line that updated.
An important part to this question is the type of programming language(PL) we are talking about. Generally speaking, I would categorize PL into 3 groups:
Traditional PLs. Ex: C, C++, Rust
The compiler compiles the code into machine language when you hit the "build" button or the "run" button.
It doesn't compile every time you change the code, but a code linter does continuously observe your code and check it for errors.
Another note, when you change part of the code and compile it, the compiler doesn't recompile everything. It usually only recompile the current assembly file (or module or whatever you call them).
It is also important to note that a lot of modern IDEs, compile when you save the files.
There is also the hot reload feature. It is a smart compiler feature that can swap certain parts of the code while it is running.
Interpreted PLs Ex: python, JS and PHP
Those languages never get compiled; Rather, they get interpreted or translated into native code on the fly and in-memory when you run them.
Those languages usually employee a cache to accelerate the subsequent code execution.
Intermediary Code PL. Ex: Kotlin, java, C#
Have 2 stages of compilation:
Build time compilation.
Just in time (run-time) compilation.
Build time compilation converts the code into intermediary language (IL) machine code, which is special to the run-time.
This code only understood by the run time like Java runtime or dot net runtime
The second compilation happens when the programs get installed or ran for the first time. This is called just in time compilation (JIT)
The run-time convert the code into native code specific to the run-time OS.

Compile single static library for Cortex M3, M4, M23 and M33

I'm currently working on a rather generic communication stack. It gets bytes in on one end, parses the packet and calls a callback.
I want to have this stack in a static library (i.e. libcommstack.a).
The library is aimed towards embedded ARM Cortex-M devices. At the moment we have specified that at least a Cortex-M3 should be used (but it should also work for an M4 or M33).
Right now I'm integrating it into another application to verify that linking it is possible. In the future the idea is that we will ship this .a file to customers so they can build their application around it, without having direct access to our sources (to encapsulate our IP).
We are using GCC ARM v7.2.1 to compile both the library and the application that is linked to it.
The application I'm trying to integrate it with is compiled for a Cortex M33 with -mfloat-abi=hard -mfpu-fpv6-sp-d16.
The code for the library does not use any floating points and is compiled using -march=archv7-m (both have the -mthumb flag).
Linking seemed to all go well, until I actually called a function from the lib. At that point the linker starts to complain:
application.elf uses VFP register arguments, libcommstack.a(somefile.c.obj) does not
failed to merge target specific data of file libcommstack.a(somefile.c.obj)
Since I'm not using floating points in the library and I don't know (upfront) if the target application does or does not have an FPU (or even uses floats), I'm not sure how to approach this.
I figured there would be two approaches:
Compile a single version of the lib, using an instruction set that all of the microcontrollers understand. I was hoping that this would be the case with ARMv7 (although I'm not yet 100% confident that the M23/M33 also support this).
Compile a lot of different libs for the different flavors based on the different architectures, FPU, etc.
As you can imagine, I would prefer to keep it simple and go for option 1, but I'm not sure how to "convince" the linker to link these two (or perhaps how to convince the compiler NOT to care about floating points for the lib).
Does anyone know if option 1 is feasible and how it can be achieved?
If it is not feasible, what would be the variables to keep in mind to determine the different build flavors?
Does anyone know if option 1 is feasible
Well, feasible, probably.
how it can be achieved?
Get all the processors you want to support and determine the instructions sets available on all these processors. Then compile for that instruction set.
But, please don't, that is a workaround.
If it is not feasible, what would be the variables to keep in mind to determine the different build flavors?
Gcc has something like "multilib profiles". See arm-none-eabi-gcc --print-multi-lib output. If you have newlib installed, you can go to /usr/arm-none-eabi/lib/thumb/ and see the directories there - newlib is compiled for each profile and installs separate library for it and different library is picked up depending on configuration. Compile for each of those profiles, and package your library by putting libraries in proper /usr/arm-none-eabi/lib/proper/directory/here and compiler will pick them up by itself (see gcc -v output for library search paths). For an example search newlib sources where it happens, can't find it. (Here's my example). With cmake as a backend as a example you could compile and install as follows:
arm-none-eabi-gcc --print-multi-lib |
while IFS=';' read -r dir opts; do
cmake -B builddir CMAKE_C_FLAGS="$opts" CMAKE_INSTALL_LIBDIR="$dir"
cmake --build builddir
cmake --install builddir --prefix "/usr/arm-none-eabi/"
done

How to Build & Decode using OpenMAX Development Layer (DL) By ARM

I have tried study long time some easy way to build and utilize ARM Optimized OpenMax DL Library without success which is available here https://silver.arm.com/browse/OX002 but need login to download.
No easy to use api could be found to decode or easy compile instruction of high level library(FFMpeg) which could utilize OpenMAX DL.
I got some hope to get ans on stackoverflow because of some similer discussion here Bench marking ARM NEON OpenMAx Numbers
What I want to achieve is to build OpenMax DL with Gnu Compiler and could decode some samples on Cortex A8 to see and use performance difference.
Any suggestion or pointer on how to do that will be highly appreciated.
Thanks & Regards
PV
I am the one who posted the question. The libraries can be compiled or can be simply be used by including the source code of the file you want to use. There are three versions of the Openmax library,
One version is in c https://silver.arm.com/browse/OX000 (can be compiled with any compiler) .
The second version is NEON specific code https://silver.arm.com/browse/OX002 . This can be directly compiled using ARM's compiler like armcc, if you want to compile using some other compiler like GCC you need to make changes in the assembly macros,code remains the same . The changes are simple changes in macros and compiler directives...
The third version is for arm11.
Please specify any specific problem so that I can help.

Mixing memory-aligned and unaligned code

I recently compiled GotoBLAS2 (MacOSX 10.6) and linked it to my code, leading to all kind of wrong results. I ran everything through valgrind noticing some illegal reads from the GotoBLAS. When looking at it more carefully I found that the GotoBLAS is compiled with the -m128bit-long-double alignment option. As soon as I did compile my code with this flag as well (although I don't use any long doubles at all) everything works, giving correct results without any valgrind obscurities.
Now my question ist:
Do I have to compile all other library dependencies using the same alignment flag?

Migrating from Winarm to Yagarto

This question must apply to so few people...
I am busy mrigrating my ARM C project from Winarm GCC 4.1.2 to Yagarto GCC 4.3.3.
I did not expect any differences and both compile my project happily using the same makefile and .ld files.
However while the Winarm version runs the Yagarto version doesn't. The processor is an Atmel AT91SAM7S.
Any ideas on where to look would be most welcome. i am thinking that my assumption that a makefile is a makefile is incorrect or that the .ld file for Winarm is not applicable to Yagarto.
Since they are both GCC toolchains and presumably use the same linker they must surely be compatable.
TIA
Ends.
I agree that the gcc's and the other binaries (ld) should be the same or close enough for you not to notice the differences. but the startup code whether it is your or theirs, and the C library can make a big difference. Enough to make the difference between success and failure when trying to use the same source and linker script. Now if this is 100% your code, no libraries or any other files being used from WinARM or Yagarto then this doesnt make much sense. 3.x.x to 4.x.x yes I had to re-spin my linker scripts, but 4.1.x to 4.3.x I dont remember having problems there.
It could also be a subtle difference in compiler behavior: code generation does change from gcc release to gcc release, and if your code contains pieces which are implementation-dependent for their semantics, it might well bite you in this way. Memory layouts of data might change, for example, and code that accidentally relied on it would break.
Seen that happen a lot of times.
Try it with different optimization options in the compile and see if that makes a difference.
Both WinARM and YAGARTO are based on gcc and should treat ld files equally. Also both are using gnu make utility - make files will be processed the same way. You can compare the two toolchains here and here.
If you are running your project with an OCD, then there is a difference between the implementation of the OpenOCD debugger. Also the commands sent to the debugger to configure it could be different.
If you are producing an hex file, then this could be different as the two toolchains are not using the same version of newlib library.
In order to be on the safe side, make sure that in both cases the correct binutils are first in the path.
If I were you I'd check the compilation/linker flags - specifically the defaults. It is very common for different toolchains to have different default ABIs or FP conventions. It might even be compiling using an instruction set extension that isn't supported by your CPU.

Resources