C String on Attiny202

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

Today I was testing the UART example from Microchip https://github.com/MicrochipTech... and it didn't work. After some debug I realize that the micro-controller ignore what is inside " ". So if I create a c string as a global variable it works:

 

char test[6] = "Hello";

int main(void)
{

  ...

  USART0_sendString(test);

  ...

}

However if I declare the variable as local variable it doesn't work:

 


int main(void)
{

  char test[6] = "Hello";
  ...

  USART0_sendString(test);

  ...

}

It fills test with '\0' and strlen return 0.

void USART0_sendString(char *str)
{   
  for(size_t i = 0; i < strlen(str); i++)
  {
    USART0_sendChar(str[i]);
  }
}

I'm using AVR GCC 5.4.0.

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

metRo_ wrote:
I'm using AVR GCC 5.4.0.
But building in what environment? This looks like it might be an objcopy issue.

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

clawson wrote:

metRo_ wrote:
I'm using AVR GCC 5.4.0.
But building in what environment? This looks like it might be an objcopy issue.

 

ze@ze-XPS-13-9380:~/development/fw$ avr-gcc -v
Using built-in specs.
Reading specs from /usr/lib/gcc/avr/5.4.0/device-specs/specs-avr2
COLLECT_GCC=avr-gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/avr/5.4.0/lto-wrapper
Target: avr
Configured with: ../gcc/configure -v --enable-languages=c,c++ --prefix=/usr/lib --infodir=/usr/share/info --mandir=/usr/share/man --bindir=/usr/bin --libexecdir=/usr/lib --libdir=/usr/lib --enable-shared --with-system-zlib --enable-long-long --enable-nls --without-included-gettext --disable-libssp --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=avr CFLAGS='-g -O2 -fdebug-prefix-map=/build/gcc-avr-q39GPj/gcc-avr-5.4.0+Atmel3.6.1=. -fstack-protector-strong -Wformat ' CPPFLAGS='-Wdate-time -D_FORTIFY_SOURCE=2' CXXFLAGS='-g -O2 -fdebug-prefix-map=/build/gcc-avr-q39GPj/gcc-avr-5.4.0+Atmel3.6.1=. -fstack-protector-strong -Wformat ' FCFLAGS='-g -O2 -fdebug-prefix-map=/build/gcc-avr-q39GPj/gcc-avr-5.4.0+Atmel3.6.1=. -fstack-protector-strong' FFLAGS='-g -O2 -fdebug-prefix-map=/build/gcc-avr-q39GPj/gcc-avr-5.4.0+Atmel3.6.1=. -fstack-protector-strong' GCJFLAGS='-g -O2 -fdebug-prefix-map=/build/gcc-avr-q39GPj/gcc-avr-5.4.0+Atmel3.6.1=. -fstack-protector-strong' LDFLAGS='-Wl,-Bsymbolic-functions -Wl,-z,relro' OBJCFLAGS='-g -O2 -fdebug-prefix-map=/build/gcc-avr-q39GPj/gcc-avr-5.4.0+Atmel3.6.1=. -fstack-protector-strong -Wformat ' OBJCXXFLAGS='-g -O2 -fdebug-prefix-map=/build/gcc-avr-q39GPj/gcc-avr-5.4.0+Atmel3.6.1=. -fstack-protector-strong -Wformat '
Thread model: single
gcc version 5.4.0 (GCC) 

 

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

You have various ways of hunting this down.

 

An lss file will tell you what asm code is being produced, and you should be seeing the array being filled with data from flash (and then can also see what flash address is being used, which is a memory mapped address in this case, or it should be).

The map file will tell you where that string resides, although if a local it may or may not show up (should be in .rodata section, and at a memory mapped address).

The hex file can confirm the flash data (will be 0 based instead of mapped flash address which in this case is 0x8000 based).

 

My guess is your linker script is somehow wrong, and is not using __RODATA_PM_OFFSET__. That would mean your global char string would work as it is using the c startup to populate that var via lpm (your var is not const so is copied to ram in startup code). When you use the local constant strings, they are expected to be in memory mapped flash, except if the .rodata section in the linker script is not using a virtual memory address (using __RODATA_PM_OFFSET__) then the addresses used will be 0 based and reading 0 based addresses means you are most likely reading from some io area instead.

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

clawson wrote:

But building in what environment?

I meant "are you using an IDE or a command line makefile? In either case what does the makefile actually invoke?"

 

Apart from the avr-objcopy that doesn't "-j .data" (a common error in "roll your own") another common fault is "avr-gcc -c" that does give the -mmcu but then the final avr-gcc link invocation that omits it.

 

But as Curt suggests this might be a linker script thing. As a lot of these chips are so new and still in a state of flux Atmel-Microchip are making regular updates to device packs for these newer devices so you might be using packs that are out of date with things like .x errors etc.