Pages: [1] 2   Go Down
Author Topic: How to view the raw C / AVR code generated by IDE before compliation?  (Read 1324 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Jr. Member
**
Karma: 0
Posts: 57
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

So I write my arduino code in the IDE, and with one click of a button, the compiled binary is whizzing down my USB cable to Arduinos flash. Simple!
However, sometimes I want to see the straight C code that sits behind my Arduino code in the libraries.  The IDE must dump a .c file in some temporary location before it becomes hex and goes to my board.....how can I see this C file?
Logged

Yorkshire England
Offline Offline
Sr. Member
****
Karma: 2
Posts: 267
Arduino good init
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Cant you just look at the libraries your using. In their folder is a .h file and a .cpp file you can open them in a text editor or notepad2 is good. Sometimes you will need to to reconfigure them.
Logged

Offline Offline
Jr. Member
**
Karma: 0
Posts: 57
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

yes, that is one way of doing it, if you have a LOT of spare time.....also seems such a waste since the IDE generates a .c file anyway. There must be a way of getting a dump of this .c file.
Logged

Offline Offline
Edison Member
*
Karma: 33
Posts: 1468
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I don't think it does create a .c file. I think it goes straight to intermediate code and then assembly language.
Logged

UK
Offline Offline
Shannon Member
****
Karma: 223
Posts: 12630
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

yes, that is one way of doing it, if you have a LOT of spare time

I don't understand why you think that the time taken is "a lot". The source code for the libraries you use is readily available under the Arduino directory (for the standard libraries) and under your sketches directory (for libraries that you have added).

If you want to see what your sketch looks like after the IDE has converted it from .ino to .cpp then you can turn on verbose output in the IDE options and then look for the message telling you where the IDE has placed your temporary files. I can't imagine many situations where that would be necessary, though.
Logged

I only provide help via the forum - please do not contact me for private consultancy.

SF Bay Area (USA)
Offline Offline
Tesla Member
***
Karma: 135
Posts: 6782
Strongly opinionated, but not official!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

For your sketch, the pre-processed C++ code will be in $TMP/sketchname.ino.cpp or $TMP/sketchname.cpp (depending on exactly which version of the IDE you are using, apparently.)
$TMP is some temporary directory with a weird name that Java picks for you; the easiest way to find it is to turn on the "verbose" compilation option in the preferences menu, do a "verify", and copy/paste.

Libraries are compile directly from their source code, which can be found in the distribution directory.

You're likely to be disappointed.  There is actually very little pre-processing that goes on, and your sketch will look very much like the original.  See also: http://arduino.cc/en/Hacking/BuildProcess
Logged

North Queensland, Australia
Offline Offline
Edison Member
*
Karma: 74
Posts: 2210
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

What you will need to do, is compile your app using the IDE with a change to the preferences ( command line options, for ide 1.0.1 and above ), Or call GCC directly. There is a flag the compiler can use to output the code as a single huge file with all pre-processing expanded.

This can be useful, but remember all includes are expanded too so the file is generally enormous, however the sketch should be the last thing in the file.

I cannot remember the command line flag, but a quick google search using keywords like 'GCC compiler option' should prove useful.
Logged


Offline Offline
Jr. Member
**
Karma: 0
Posts: 57
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

peterH, the time taken is relative to the size of my arduino sketch and how many different library functions are used. In this case it would take me a couple of hours to trawl through the librarys and build a pure C file, not too long but even so I'd like to know how to do this in the future.
Yeah I tried the verbose output, since I tried it on my windows machine the temp files are in some folder that isn't there,  (C:\Users\enyquist\AppData)  . I'll try it with a linux distro.
pyro_65, arduino's 'preferences.txt' file is in this same elusive AppData folder, god I hate windows. Again I'll try this on my linux box, really shouldn't be that hard.....

Logged

North Queensland, Australia
Offline Offline
Edison Member
*
Karma: 74
Posts: 2210
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I tried it with the IDE and it works, need \arduino\hardware\arduino\avr\platform.txt

modify
compiler.cpp.flags=-c -g -Os -w -fno-exceptions -ffunction-sections -fdata-sections -MMD

to

compiler.cpp.flags=-c -g -Os -w -fno-exceptions -ffunction-sections -fdata-sections -MMD -E

then compile, when the linker spews up, open the temporary compilation folder and open the .o files. That is your code expanded.
Logged


UK
Offline Offline
Shannon Member
****
Karma: 223
Posts: 12630
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

In this case it would take me a couple of hours to trawl through the librarys and build a pure C file

Why on Earth would you want to do that? The libraries consist of plain old C++ files and you have the source right there in front of you.

Your sketch goes through some subtle mangling to generate the final C++ file that is given to the compiler, but from a developers point of view this is basically just adding in some declarations and includes for you and doesn't change the main body of the code; it's pretty rare that you would need to see the generated C++ since it is almost identical to the .ino code you see in the IDE.
Logged

I only provide help via the forum - please do not contact me for private consultancy.

Offline Offline
Jr. Member
**
Karma: 0
Posts: 57
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

no practical reason, I'm simply interested in AVRs and I'd like to see which AVR registers are being modified. This will just make that a bit easier. I KNOW that these can be found in the .cpp and .h files but this means I won't have to sift through the whole thing, I can see only the registers that are actually being written in the compiled program
Logged

SF Bay Area (USA)
Offline Offline
Tesla Member
***
Karma: 135
Posts: 6782
Strongly opinionated, but not official!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I'd like to see which AVR registers are being modified
Looking at the preprocessed output (from -E) will actually obscure this, compared to looking at the core/library.  The C compiler doesn't deal with named AVR-registers at the low level; they all become rather obscure looking operations on pointers.  For example, here is digitalWrite():
Code:
void digitalWrite(uint8_t pin, uint8_t val)
{
 uint8_t timer = ( (__extension__({ uint16_t __addr16 = (uint16_t)((uint16_t)(digital_pin_to_timer_PGM + (pin))); uint8_t __result; __asm__ ( "lpm %0, Z" "\n\t" : "=r" (__result) : "z" (__addr16) ); __result; })) );
 uint8_t bit = ( (__extension__({ uint16_t __addr16 = (uint16_t)((uint16_t)(digital_pin_to_bit_mask_PGM + (pin))); uint8_t __result; __asm__ ( "lpm %0, Z" "\n\t" : "=r" (__result) : "z" (__addr16) ); __result; })) );
 uint8_t port = ( (__extension__({ uint16_t __addr16 = (uint16_t)((uint16_t)(digital_pin_to_port_PGM + (pin))); uint8_t __result; __asm__ ( "lpm %0, Z" "\n\t" : "=r" (__result) : "z" (__addr16) ); __result; })) );
 volatile uint8_t *out;

 if (port == 0) return;
 if (timer != 0) turnOffPWM(timer);
 out = ( (volatile uint8_t *)( (__extension__({ uint16_t __addr16 = (uint16_t)((uint16_t)(port_to_output_PGM + (port))); uint16_t __result; __asm__ ( "lpm %A0, Z+" "\n\t" "lpm %B0, Z" "\n\t" : "=r" (__result), "=z" (__addr16) : "1" (__addr16) ); __result; }))) );

 uint8_t oldSREG = (*(volatile uint8_t *)((0x3F) + 0x20));
 __asm__ __volatile__ ("cli" ::);

 if (val == 0x0) {
  *out &= ~bit;
 } else {
  *out |= bit;
 }

 (*(volatile uint8_t *)((0x3F) + 0x20)) = oldSREG;
}

Are you sure you don't want to look at the assembly language produced?  That's much more "concentrated", more stripped of extraneous garbage, and closer to actual AVR architecture stuff...
Logged

North Queensland, Australia
Offline Offline
Edison Member
*
Karma: 74
Posts: 2210
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

no practical reason, I'm simply interested in AVRs and I'd like to see which AVR registers are being modified. This will just make that a bit easier. I KNOW that these can be found in the .cpp and .h files but this means I won't have to sift through the whole thing, I can see only the registers that are actually being written in the compiled program

That's quite a bit different to viewing pre-processed code, sure the register macros are expanded to volatile pointer casts, but not quite what happens in the 'compiled program'

On windows to view the asm listing, type 'shell:sendto' into explorer, hit enter then copy the file I attached below in there.
You can then go into the IDE temp compile folder and right click on your sketch *.elf file then SendTo->AVR_ASM.bat

You will have to open the file in notepad and edit the path to the arduino directory.

But it will generate a text file containing the asm for your sketch.

* AVR-ASM.bat (0.07 KB - downloaded 14 times.)
« Last Edit: January 31, 2013, 11:32:17 am by pYro_65 » Logged


SF Bay Area (USA)
Offline Offline
Tesla Member
***
Karma: 135
Posts: 6782
Strongly opinionated, but not official!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

For example, consider a statement in your sketch like:
Code:
PORTB = 0x12;
In the pre-processed C code (from -E), you would see:
Code:
  (*(volatile uint8_t *)((0x05) + 0x20)) = 0x12;
Which I claim is not very useful.  The assembler output would contain:
Quote
100:   82 e1           ldi     r24, 0x12       ; 18
 102:   85 b9           out     0x05, r24       ; 5

The original source code is best.

Unfortunately, there is no way to get "partially pre-processed" code that might tell you something like:
Code:
digitalWriteFast(13,1);
turns into
Code:
PORTD |= 0x40;
Fortunately, the Arduino code doesn't have many of the sort of complex macros that would make that sort of thing more useful.  digitalWrite() is a true function, and its source code is pretty understandable.


Logged

Offline Offline
Jr. Member
**
Karma: 0
Posts: 57
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

pyro_65, thanks for that batch file, I ran it on my .elf  but I have a silly question...

where is the .asm file dumped?  I can't find it anywhere...
Logged

Pages: [1] 2   Go Up
Jump to: