IAR help

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

I got the IAR Embedded Workbench for Atmel AVR demo. It confused me a lot. I wrote some code and it compiles it, it doesn't show how much flash it uses, i cant figure out a way to set the chip frequency, the debugger shows disassembler and nothing nice like the avr studio, finally i see no way to actually program my atmega16.

Can someone please explain the basics of how to use the IAR Embedded Workbench for Atmel AVR.

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

Re. flash usage, you need tolook in the .map file it generates - can't remmeber if this is generated by default or you need to enable it in the linker options ( I think you need to enable 'module summary' in the list file options).
I normally use AVR studio for programming - just program the file IAR puts in the .exe folder using Tools->program.
Not sure what you mean by setting the chip frequency - fuse options are set in AVR Studio's programmer window. If you need to enter it for simultion, I'm sure there will be a clock frequency setting, probably somewhare like project options->simulator.
AFAIK IAR doesn't have inbuilt programmer support, although it does suppport JTAG-ICEMK2 ( and this works more reliably than in AVR Studio last time I used it)

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

Look,

1. In order to see the compiled program size you have first to do this:
Project/Options/Linker/List: Sellect "Generate Linker Listing", "Segment map", "Module map".
Then rebuild your project, go to the project files (windows explorer) get in the debug dir, then List dir and finally open the .map file. In the end of this you will find the flash size of your applycation.

2. If you feel better using the AVRStudio do this:
Project/Options/Linker/Output/Other: Output format" ubrof 8 (forced). Rebuild your project, Open the AVRStudio, open the .d90 file from Project files/Debug/Exe. Then the AVR Studio will ask you to save the debuging project, save it in the Project files and then enjoy. Each time you rebuild your project from IAR, the AVR Studio will automatically ask you to reload the new program - Yes.

I hope that helps.

Michael.

Michael.

User of:
IAR Embedded Workbench C/C++ Compiler
Altium Designer

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

Thank you i got the basics now. Still can't decide if its better to switch to IAR or stick with CodevisionAVR.

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

Vlad_J wrote:
Still can't decide if its better to switch to IAR or stick with CodevisionAVR.
I own both. It comes down to whether the extra features of IAR is worth the extra cost compared with CVAVR. For me, it was a simple decision because IAR's compact code size allowed use of a smaller (and cheaper) AVR which more than paid for the additional cost of IAR. Also, it's integrated debugger worked at the time when AVR Studio's would crash (AVR Studio has since been fixed). But, what was important for me will not be important for everyone, so it is an idiosyncratic decision that you have to make.

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

Is there a way printf works with USART in IAR? I got putchar to work by adding a function in write.c

int MyLowLevelPutchar(int x)
{
  //put data in USART data register
  UDR = x;
  //wait untill the byte is sent
  while (!(UCSRA&(1<<6)));
  
  //clear the txc flag
  UCSRA |= (1<<6);
  return x;
  
}
putchar('a');

send a to hyperterminal

printf("a");  or
printf("%c",'a');

does nothing

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

Vlad_J wrote:
Is there a way printf works with USART in IAR?
Yes, but I don't recall the particulars. The method does vary if your using CLIB or DLIB. Read the C/C++ compiler manual for the details.

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

Well it says that printf needs __write fuction. So i take the write.c with __write template from src/lib/dlib folder. It says create you own MyLowLevelPutchar that the __write function will use. If I debug, putchar('a'); enters the __write function and it works. printf("abc"); enters __write but sends ' ' and then '(' over and over.

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

printf and all the stdio (stdout, stdin) use these functions:

size_t __write(int Handle, const unsigned char * buf, size_t bufcount);
size_t __read(int Handle, unsigned char * buffer, size_t bufcount)

where Handle is normally 0 (meaning, e.g., UART 0) for stdout and the other two params are a buffer pointer and a byte count. Both return the number of bytes transferred.

Examples of these are, I think, in the examples, at least they are for the ARM version of IAR's system. These are polling, not interrupt driven. I'll bet you can find interrupt driven UART IO examples too.

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

I understand that and I am using __write from examples with my own MyLowLevelPutchar function. When I debug

printf("%s","asdf");

never sends anything to __write but resets everything and starts from main() again.

printf("asdf");

goes into __write but const unsigned char * buffer points to '(' or another weird character.

putchar('a');

Also uses the __write function but points to the correct character 'a'

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

I have only just downloaded Kickstart, but as far as I can see:

1. initialise your UART
2. add your own UART putchar() function
3. add your own UART getchar() function

then all the functions should work.
(with CodeVision you only need to initalise the UART, the default library putchar() works with the UART )

int putchar(int c)
{
     while ((UCSRA & (1<<UDRE)) == 0) ;
     return (UDR = c);
}

void main()
{
     UBRRL = 51;		//F_CPU/9600/16 -1;
     UCSRA = 0;
     UCSRB = (1<<TXEN)|(1<<RXEN);
     UCSRC = (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0);
     printf("hello world\r\n");
     while (1);
}

David.

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

in your program, call __write(0, "hello", 5) and prove that it works, irrespective of printf et al.

in your example, you have putchar() but you don't show __write().

putchar() is part of the C library; you shouldn't have your own if you intend to use the C library printf et al.

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

if using IAR's clib the fundamental functions are:

int putchar(int ch)
{
/*
        put your own putchar-function here
*/
  return ch;
}

and

char _low_level_get(void)
{
  char ch=0;
/*
        put your own getchar-function here
*/
  return ch;
}

by default the functions are empty, so you need to provide your own versions that direct the character output/input to/from whatever device you want (UART, LCD, etc.).

If using dlib there are a number of functions you can customize, depending on at what level you want to override. __write() and __writechar() are the suggested choices. However, the default version of __write() calls __writechar(), and the default version of __writechar() calls __putchar(). [__readchar() calls __getchar()] So you should be able to do a basic implementation by simply providing your own version of __putchar() and __getchar() (format is the same as putchar() and _low_level_get() for clib)

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

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

I have no experience with IAR, but I have just commented out my UART putchar() and getchar() functions and linked with the default library versions.

When you trace the ASM in C-SPY, you see that putchar() is just a single RET instruction. So I am not surprised that nothing happens.

Incidentally, stdio routines function just fine with my putchar() and getchar() functions. requires functions and not macros.

Perhaps an IAR user can elaborate.

David.

Edit. Thankyou glitch. That seems a very reasonable explanation. I can see no sense in using block i/o with a polled UART.

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

Ok with clib making my own putchar function worked. With normal dlib nothing seems to work. printf calls __write but sends a pointer to weird square character. If i make my own putchar it just restarts at main. If i try full dlib i get some error

Error[e12]: Unable to open file 'C:\....LIB\DLIB\dlAVR-3s-ec_mul-sf-f.r90' 

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

for dlib it is not putchar... but rather __putchar the reason it probably restarts is that the default __putchar is designed to output to the debugger.

If overriding __putchar does not work, then do it with __writechar. __writechar is the lowest level output routine. (I tend to use my own routines, so I have never tried this)

Note, you can override __writechar without overriding __write, but the reverse is not true. if you override __write, you need to override __writechar as well, since not all routines will call __write. I don't believe any routines call __putchar directly, instead they call __writechar, which in turn calls __putchar.

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

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

If I try to override __writechar without __write i get the error

Error[e46]: Undefined external "__write" referred in ?putchar ( C:\...\LIB\DLIB\ 

If I override __write I get random results. printf sends a pointer to random character, sometimes it sends pointer to first character then second then crashes, sometimes it just crashes.

my __write comes from the template provided by IAR it says create you own MyLowLevelPutchar

int MyLowLevelPutchar(int x)
{
   UDR = x;
   
   while(!(UCSRA & (1<<TXC)));
   
   //clear flag
   UCSRA |= (1<<6);

   return x;
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Isn't the reason you pay $3000 for the compiler because IAR will send a harem of Polynesian virgins to cater for your every want and whim at the drop of a hat? What do they say about all this?

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

All I can say is you must be doing something wrong in the way you are overriding the function. Based on the example code I have, __write() calls __writechar(). [putchar() does call __write(), via fputc()]

I cam find no mention of "MyLowLevelPutChar" in any of the documentation, or code, I have.

Here are the comments from __write & __write char template files. (I've also included the relevant calls to other functions)

/*******************
 *
 * Copyright 1998-1999 IAR Systems.  All rights reserved.
 *
 * $Revision: 1.1 $
 *
 * This is the default implementation of __write, the low level output
 * function used by the standard library.  This implementation uses
 * __writechar to perform the actual output.  Replace one of __write
 * and __writechar with a system-specific implementation.
 *
 ********************/

int (__write)(int Handle, const unsigned char *Buf, size_t BufSize)
{
.
.
.
    if (__writechar(Handle, *Buf++) < 0)
.
.
.
}
/*******************
 *
 * Copyright 1999 IAR Systems.  All rights reserved.
 *
 * $Revision: 1.1 $
 *
 * This is the default implementation of the __writechar function used
 * by the standard library.  This implementation sends characters
 * written to the file descriptors associated with stdout and stderr
 * to the debugger.  Replace one of __write and __writechar with a
 * system-specific implementation.
 *
 ********************/
int (__writechar)(int Handle, unsigned char c)
{
.
.
.
    return __putchar(c);
.
.
.
}

So unless this has been changed in later versions I do not see any reference to another low level routine.

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

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

Quote:
Isn't the reason you pay $3000 for the compiler because IAR will send a harem of Polynesian virgins to cater for your every want and whim at the drop of a hat?

Yes but do you get evaluation virgins ?

I am a little surprised at the lack of "tutorial". I would assume that a user wants to compile blinky or hello world to a serial terminal or even an LCD. When this does not work, she only then thinks about a simulator.

Certain other compilers will at least get you over this hurdle.

David.

Last Edited: Wed. Aug 13, 2008 - 10:43 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Isn't the reason you pay $3000 for the compiler because IAR will send a harem of Polynesian virgins to cater for your every want and whim at the drop of a hat?

Yes, and my experience with support from IAR (Germany) was always positive (ok, no polynesian virgins :( ).
Although a bit arrogant sometimes ('why don't you read the manual first, it's all in there...') response was always within hours.

Jörg.

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

I am struggling.

I can use a regular uart_init() and implement a putchar() that uses the UART. This works fine in a real AVR. But will not display via C-SPY.

I can use the default CLIBS putchar(), get no AVR output, but can use C-SPY.

I tried implementing: int MyLowLevelPutchar(int c); that uses the UART. ( and enabled the stubs in the __write() function. I can use C-SPY but get nothing on the real UART.

David.

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

@david with CLIB creating your own putchar gets the printf and USART working. With DLIB the manual says make you own __write, template provided.

@glitch the template for __write I found in write.c .....\avr\src\lib\dlib seems different from yours.

/*******************
 *
 * Copyright 1998-2003 IAR Systems.  All rights reserved.
 *
 * $Revision: 3162 $
 *
 * This is a template implementation of the "__write" function used by
 * the standard library.  Replace it with a system-specific
 * implementation.
 *
 * The "__write" function should output "size" number of bytes from
 * "buffer" in some application-specific way.  It should return the
 * number of characters written, or _LLIO_ERROR on failure.
 *
 * If "buffer" is zero then __write should perform flushing of
 * internal buffers, if any.  In this case "handle" can be -1 to
 * indicate that all handles should be flushed.
 *
 * The template implementation below assumes that the application
 * provides the function "MyLowLevelPutchar".  It should return the
 * character written, or -1 on failure.
 *
 ********************/

int MyLowLevelPutchar(int x);

/*
 * If the __write implementation uses internal buffering, uncomment
 * the following line to ensure that we are called with "buffer" as 0
 * (i.e. flush) when the application terminates.
 */

size_t __write(int handle, const unsigned char * buffer, size_t size)
{
.
.

    if (MyLowLevelPutchar(*buffer++) < 0)
.
.
}

also there seems to be no default __write if I dont include write.c I get the error

Error[e46]: Undefined external "__write" referred in ?putchar ( C:\...\LIB\DLIB\dlAVR-3t-ec_mul-sf-n.r90 
 

Maybe I'm doing something wrong in the settings ?

C/C++ compiler: Embedded C++
Linker: format: ubrof 8 forced

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

AHA i got it. There are settings for CSTACK and RSTACK i put large numbers instead of small numbers and everything works.

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

Glad to hear that you got it working!

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

glitch wrote:
All I can say is you must be doing something wrong in the way you are overriding the function. Based on the example code I have, __write() calls __writechar(). [putchar() does call __write(), via fputc()]

I cam find no mention of "MyLowLevelPutChar" in any of the documentation, or code, I have.

Here are the comments from __write & __write char template files. (I've also included the relevant calls to other functions)

/*******************
 *
 * Copyright 1998-1999 IAR Systems.  All rights reserved.
 *
 * $Revision: 1.1 $
 *
 * This is the default implementation of __write, the low level output
 * function used by the standard library.  This implementation uses
 * __writechar to perform the actual output.  Replace one of __write
 * and __writechar with a system-specific implementation.
 *
 ********************/

int (__write)(int Handle, const unsigned char *Buf, size_t BufSize)
{
.
.
.
    if (__writechar(Handle, *Buf++) < 0)
.
.
.
}
/*******************
 *
 * Copyright 1999 IAR Systems.  All rights reserved.
 *
 * $Revision: 1.1 $
 *
 * This is the default implementation of the __writechar function used
 * by the standard library.  This implementation sends characters
 * written to the file descriptors associated with stdout and stderr
 * to the debugger.  Replace one of __write and __writechar with a
 * system-specific implementation.
 *
 ********************/
int (__writechar)(int Handle, unsigned char c)
{
.
.
.
    return __putchar(c);
.
.
.
}

So unless this has been changed in later versions I do not see any reference to another low level routine.

My approach was to just write my own __write() and not use either their __write() nor the other lower level one.

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

Steve, the OP said he got things working by fixing his stack sizes.