Porting code from IAR to avr-gcc - general tips

Go To Last Post
34 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

HI guys,
I had to write down some general tips about porting code from IAR to avr-gcc/WinAVR. After a quick search, I could not find something similar through this forum, so here goes. If there is anything else around, please point me to it!

Attached as .txt

Cheers;
Eivind :-)

Attachment(s): 

*** Eivind, webmaster ***

Last Edited: Sat. Jul 1, 2017 - 03:05 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Look at the avr-gcc butterfly port and threads about it.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Regarding porting code from IAR to GCC; a few tips:

1)
Most register/memory locations have aliases in the IAR .h file,
that must be edited in the corresponding .h files for avr-gcc since they (less) often have unidentical entries.
Example: #define UL PB5
The avr-gcc .h file may not have an entry called "PB5", rather one called "PORTB5".
Hence, you must edit such entries to resolve all addresses correctly.

2) Interrupts services are handled using #pragma directives in IAR.
Example:
#pragma vector=TIMER0_OVF_vect
__interrupt void MotorPWMBottom(){
// blabla

}
Interrupt Service Routines used to be implemented using SIGNAL or INTERRUPT keywords in avr-gcc.
Now, the common thing to do is to use the ISR syntax: ISR(vector){ ... }
Example: ISR(PCINT1_vect){ //blablabla }

All vectors are defined in the avr-gcc header file

3) Intrinsic functions.
Examples: __enable_interrupts(), __disable_interrupts(), and __watchdog_reset();
are intrinsic functions that have counterparts with other names in avr-gcc.
All these are actual AVR instructions, so they can be called using C-syntax like:
asm("SEI"); etc....
These are usually defined as macros for avr-gcc, but they're not co-located in a separate file
for _all_ intrinsic functions, rather in the particular .h file pertaining to their function.

Example: SEI() and CLI() are defined in
etc.

4) Locking registers.
The IAR compiler lock general registers, from r15 and down, by using compiler options and this keyword syntax:
__regvar __no_init volatile unsigned int filteredTimeSinceCommutation @14;

This line locks r14 for use only when explicitly referenced in your code thorugh the var
name "filteredTimeSinceCommutation". This means that the compiler cannot dispose of it at its own will.

I dont know how this is done in avr-gcc, but if you do - please let me know!

Cheers;
eivind

Hi Eivind,

Here are some additions and corrections:

1. Symbols such as "PB5" are always available in avr-libc. The file includes which contains all of these shortened generic defined symbols. So you don't have to go edit. Just #include .

2. avr-libc now provides the same interrupt vector names as IAR, to help facilitate migration. One can put in a header file a macro with conditional compilation that can support either GCC or IAR ISRs:

#if defined(__ICCAVR__) // IAR C Compiler
#define PRAGMA(x) _Pragma( #x )
#define ISR(vec) PRAGMA( vector=vec ) __interrupt void handler_##vec(void)
#endif
#if defined(__GNUC__) // GNU Compiler
#include
#endif

Note that the above was taken (and edited) from a real project that compiles for both IAR and GCC, and was written and tested by Joerg Wunsch. The macros are defined for the IAR compiler, so you write your ISRs in the syntax used for GCC and those macros then convert it to the format that IAR needs.

Also note, the interrupt vectors are NOT defined in but they are defined in each individual processor IO header file, which will get included when you #include

3. Please note that the avr-libc macros are NOT uppercase. They are sei() and cli(), not SEI() and CLI(). C language is case sensitive.

4. There is a way to lock registers to a variable in the AVR GCC toolchain. See the avr-libc manual, FAQ #3:
http://www.nongnu.org/avr-libc/u...
CAVEAT! Doing this is not recommended as it removes this register from the purview of the compiler, which may make code generation worse. Use at your own risk.

5. IAR has non-standard keywords to define data to be put in Flash. GCC uses "attributes" with their own, non-standard syntax. The reason why both syntaxes are non-standard is because the C language was not designed for Harvard architecture devices, such as the AVR. So for example, one would have to create macros to define a common way to do this. Like so:
#if defined(__ICCAVR__) // IAR C Compiler
#define FLASH_DECLARE(x) __flash x
#endif
#if defined(__GNUC__) // GNU Compiler
#define FLASH_DECLARE(x) x __attribute__((__progmem__))
#endif

Again, this is taken from the same project, and was written by Joerg Wunsch.

I'm sure there are similar issues with declaring a variable to reside in EEPROM.

Eivind, if you need more items, feel free to give myself or Joerg Wunsch a call.

Thanks
Eric Weddington

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Eivind,

Most topics have been already mentioned in your text and corrected by Eric and others in the previous posts. But I think two rather important topics are missing (or I have not seen it):
(a) the access to "flash-constants" is (very) different.
(b) sometimes new devices are not supported by the open-source tools when they become available but support usualy gets added soon to gcc and/or avr-libc.

Some time ago I have done the porting of the the AVR Butterfly example-application written for the IAR-compiler to the GNU-toolchain. I have kept most of the original IAR-code in the source in comments.
http://www.siwawi.arubi.uni-kl.d...

During the porting of the BF-application the adaption of the flash-constant handling has been the most time-consuming part (the access not the declaration). Everything else has been basicly a "search and replace". Feel free to contact me by e-mail (address at buttom of the mentioned URL).

Martin Thomas

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Not sure how IAR handle printf() but it's often the case that folks porting to GCC don't understand why printf() output to UART stops working and the need for fdevopen() and to provide their own getchar() and putchar() style routines.

Cliff

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

> Not sure how IAR handle printf()...

I tried to research that, it's not very obvious from the
documentation. Maybe I've missed something, but it appears
you are supposed to pick up the template implementations for
__open(), __close(), __read(), and __write() from the library
source code that ships with IAR, and fill in your own stuff
there.

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Humm,
thought I uploaded this already but must have scr**ed up somehow. Here goes next revision. Feel free. Still no ambitions to be exhaustive and publishable ;-)

Thanks;
Eivind

Attachment(s): 

*** Eivind, webmaster ***

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

(Adding a watch to this thread)
I will put my overview on the wiki.

Eivind

*** Eivind, webmaster ***

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm migrating some IAR code to GCC, what about this IAR intrinsic functions? __save_interrupt(), __restore_interrupt(), __delay_cycles().
Do you know something?
Thanks!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

GCC has no direct equivalent of __save_interrupt() and __restore_interrupt() but you do have direct access to SREG using the symbol 'SREG'. So to protect a region use:

uint8_t sreg_state=SREG;
cli();
//access protected variable
SREG = sreg_state;

For __delay_cycles() look at util/delay.h and util/delay_basic.h

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks!
I have another problem.
When I try to add a file in my new AVR Studio Project, a message appears: "This file probably contained illegal characters". This file works perfectly with the IAR compiler. Where is the problem?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I don't know Argentinian - is it possible your comments contain some "unusual" language symbol? Maybe that's what it's objecting too. I'd write a little C or BASIC program on the PC that opens an example file and reads it byte by byte and priints out the symbol and hex code of anything above character 127. This may help you locate those things that Studio thinks might be "illegal"

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks! The problem was the file name: "sas .c". There was a space (0x20) before the .c extension. Sorry and thank you for your time!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I started to use _delay_us(). When I measure with an oscilloscope the time is smaller. For example _delay_us(1) is 0.6usec. I´m using a 14.7456MHz XTAL and in my Makefile says: F_CPU=14745600UL

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

GCC has no direct equivalent of __save_interrupt() and __restore_interrupt() but you do have direct access to SREG using the symbol 'SREG'. So to protect a region use:

Don't forget about my atomic header addition to the library in . That way you can protect areas with:

ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
{
 // Code here
}

And the compiler will take care of saving and restoring the SREG when the block is exited.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Noelia wrote:
I started to use _delay_us(). When I measure with an oscilloscope the time is smaller. For example _delay_us(1) is 0.6usec. I´m using a 14.7456MHz XTAL and in my Makefile says: F_CPU=14745600UL

i don't know if this function is accurate for small delays or not... try to make _delay_us(100); for example and see the deviations

Regards,
-- A.EL-Saeed

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm reading dallas ibuttons so I need small delays when I use the overdrive mode. Now I'm using one library that I've downloaded from here, called delay_x and I have the same problem...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

did you try the timers ?! i guess it may be more precise !!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

No! You can't use the interrupts when you are reading an ibutton because of the noise.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

then try to loop with _delay_loop_1 or _delay_loop_2 for the no. of cycles you need. or you may make a simple delay loop with "nop" instruction and get its counter from the datasheet or by trial and error

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes, this is the best way (though laborious when you need different delays) but I thought that delay_us() and delay_x() would be perfect for me! Now I know that is impossible to do small delays (usec) with a library and nobody say this in this forum. Now I am using the gcc compiler but whit iar I had the same problem!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

abcminiuser wrote:

Don't forget about my atomic header addition to the library in . That way you can protect areas with:

ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
{
 // Code here
}

And the compiler will take care of saving and restoring the SREG when the block is exited.

- Dean :twisted:

Hi,

I tried to use this new feature, and it seems to be working good. As I was looking inside this macro, I wonder what happen if I call this code:

ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
{
 // Some code here....
 return;
}

Calling return inside the block, crashes program because of disabling global interuppts. Mayby it's good idea to write some warning about this situation in avr-libc docs? My solution for this is to define special ATOMIC_RETURN() macro which will looks like this:

#define ATOMIC_RETURN(_value) \
{\
 //restore SREG or sei() calling
 return _value;\
}\

What do you think about this?

Best ragards,
Lukas

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Lukas,

Can you please pose a snippet showing that the code causes problems? I just did a small test and it works as expected - SREG is restored before the function returns. The magic is in the GCC "cleanup" attribute on the variable, which should force the SREG restore no matter how the function exits (or, more actually, how the variable goes out of scope.)

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

You are right, I was wrong:(, in fact it works just like you say. I didn't notice this section with __atribute__(_cleanup__), it's amazing how it works! I'm trying to implement this feature on ARM7 uC and that's from my question come from. I'm using KEIL software with armcc compiler, there is something like __atribute__ section but I can't find anything similar to __cleanup__. Have you got any idea?

Lukas

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

who can introduce some IAR learning website for me!
thanks

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

An interesting question on the Forum entitled "AVR GCC".

How about this one?
http://www.iar.com/website1/1.0....

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,
I'm migrating some IAR code to GCC, how i would change this code?:

}
#pragma vector = USART_UDRE_vect // transmit interrupt
__interrupt void UCSRB_TX()
{
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Look up the vector name for your AVR on this page:

http://www.nongnu.org/avr-libc/u...

Then:

ISR(NAME_vect) {
...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

And if you always use the ISR() macro, you can swap between Compilers painlessly:

#if defined (__IAR_SYSTEMS_ICC__) 
...
#define PRAGMA(x)	_Pragma( #x ) 
#define ISR(num) PRAGMA(vector = num) __interrupt void isr_##num(void)

There are occasional spelling changes between vectors but it keeps your code tidy.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Have somebody converted code iar to atme 7 ? l thibk convert myself is very difficile .thank in advace

vandi

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I just send all the files through a SED script.

 

Yes,  you have to do some hand-editing.

 

Are you trying to convert a regular Atmel App Note?

Or some private IAR code?

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Did you actually read this thread?

 

But more than that have you seen this page in the user manual?...

 

http://www.nongnu.org/avr-libc/u...

 

That has been written as guidance for how to migrate IAR code to avr-gcc which is the C compiler in AS7.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

There are several descriptions and guides.   Study them.

 

For anything more than a trivial 20-line program,   it is worth using automated editing.   You reduce the risk of typos.

 

Of course,  it is still wise to check what the machine has actually done.   e.g. diff the result with the original.

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

can you send again because i have lost the script 

thank you in advance

vandi

Topic locked