Where did my string literal go?

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

Summary: When building on linux contents of initialized variables are mangled, same code works perfect with avrstudio on windows.

Having a natural distrust to everything windows, i thought i'd set up a build environment on linux for my first endeavours in coding for MCU's.
It works pretty well, except when i use an initialized variable like
uint8_t = 2;
or
char *s = "string";
then i'll either get garbage or my atmega328p will keep resetting.

Here's the kicker: When i compile the same code with avrstudio/winavr everything works great. Naturally this really bugs me.

Example:

#include 
#include "pins.h"
#include "hd44780.h"

static void setup_pins()
{
	DDRD = 0xFF;
}

// Not interesting
static void setup_display()
{
	hd44780_init();
	hd44780_cmd(	HD44780_SETUP | 
			HD44780_4BIT | 
			HD44780_2LINES | 
			HD44780_5X8DOTS
			);
	hd44780_cmd(	HD44780_DISPLAY |
			HD44780_POWER_ON |
			HD44780_CURSOR_ON |
			HD44780_BLINK_ON
			);

	hd44780_clear();
	hd44780_home();
}

int main()
{

	setup_pins();
	setup_display();

// This works every time
	hd44780_putc('c');

// This only seems to work with avrstudio
	char *s = "abc";
	while(*s != '\0'){
		hd44780_putc(*s);
		s++;
	}

	while(1);
}

I don't think the hd44780.* files will be interesting.

Compiled with any of the 4 recent toolchains for linux i've tried, this will output something like

Quote:
c@

Compiled with avrstudio, it produces the expected

Quote:
cabc

In either case i compile it with:

avr-gcc -pipe -mmcu=atmega328p -Wall -Os -I/usr/avr/include -DF_CPU=20000000UL  -MM testcase.c > testcase.dep
avr-gcc -pipe -mmcu=atmega328p -Wall -Os -I/usr/avr/include -DF_CPU=20000000UL  -o testcase.o -c testcase.c
avr-gcc -pipe -mmcu=atmega328p -Wall -Os -I/usr/avr/include -DF_CPU=20000000UL  -MM hd44780.c > hd44780.dep
avr-gcc -pipe -mmcu=atmega328p -Wall -Os -I/usr/avr/include -DF_CPU=20000000UL  -o hd44780.o -c hd44780.c
avr-gcc  -o testcase.elf testcase.o hd44780.o 
avr-objcopy -j .text -j .data -O ihex testcase.elf testcase.hex 

No errors or warnings are produced.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
avr-gcc  -o testcase.elf testcase.o hd44780.o 

The code is not linked for the correct device. Put a "-mmcu=atmega328p" also in that command line.

If the problem remains I would suspect your linux avr-gcc tool chain. Where did it come from? Any prebuild distribution package?

Stefan Ernst

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

sternst wrote:

avr-gcc  -o testcase.elf testcase.o hd44780.o 

The code is not linked for the correct device. Put a "-mmcu=atmega328p" also in that command line.

Amazing! I've been at it for 4 days, and it took you less than 7 minutes to figure out :shock:

Thanks a bunch. It actually works now :!:

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

I can see no reason for linux or Windoze to generate different code.

OTOH, you must have exactly the same build of Compiler and libraries.

And your makefile needs to be identical.

So you can do a 'make file.S' on both systems, and diff the outputs.

I would expect your libc.a's and crts.o's to be exact binary replicas for the same build versions.

David.