Newbee: How to pass pointers to function on atmel

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

After spending the last two days on reading on pointers, i've made several attempts to use them. Although the concept seems simple, i miss something here. Here's the simple code i'm trying:

...
uint8_t StrLength (char *a)
{
  return strlen(a);
}

main (void)
{
  char *a = "abcded";
  ioinit ();
  while(1)
  {
    blink(0);
    blink(1);
    blink(StrLength(a));
    blink(strlen(a));
   }
}

blink(n) lets a led blink n-times. I've tried several lengths of string a. In all cases strlen gives the right length, but StrLength gives:
String lenght: 1 2 3 4 5 6
Returns:____ 2 4 4 6 6 8

I apologize if this is really newbee, but i'm stuck and have no clue. Thanks in advance for giving one.

Leon

BTW: (atmega 48, STK500, avr-gcc 4.3.0, avrdude)

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

I can see absolutely nothing wrong with your program. StrLength() should give the same value as strlen().

Run your program in the Simulator to see where things go wrong.

I can only think that blink() has some dark secrets.

David.

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

I lifted your code to a desktop C compiler (MS Visual C++), removed the hardware stuff and made Blibk() just display the number of blinks. It behaves correctly.

Here are some speculations of mine:
- Maybe you didn't run the code that you where looking at. We've all done that, especially when being noobs, being tired and confused. Double check what code you are building, that you are using the correct hex file to program the AVR and that you are actually programming it.

-Maybe Blink contains an error, as also hinted at by David above. The error is deterministic. Notice the pattern in the data you've posted. (The argument against this is
that Blink performs correctly with strlen).

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

Pfew, I was afraid that I just missed something stupid, but apparently it is not so straightforward. Unfortunately, this will mean extra time to solve it...
The function blink so far worked flawlessly, so i had no suspicions here. But just for the record here's the code:

void blink (uint8_t n)
{
	uint8_t i;
	for (i=1;i<=n;++i)
	{	
	  PORTB &= ~_BV(PB3);
		_delay_ms(175);
		PORTB |=  _BV(PB3);
		_delay_ms(250);
	}
	_delay_ms(500);
}	

Especially for this post, i made a test directory and stripped the code until the version i sent. So i'm sure this is the code that is compiled and downloaded to the atmega48. Just for fun i tested up to 9 characters, and the pattern persists. I was hoping this could provide a clue.

I never had the need to do simulate things sofar (newbee), so i guess this means RTFM and STFW on this subject... :-(

Thanks for thinking along. I'll let you know the results on simulations (although this might take some time).

Leon

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

What happens with:

   for (i=0;i

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

Exactly the same thing. Same pattern.
Just for fun, i also compiled it onto another atmega48. Same results...

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

Other than the fact that strlen() probably returns an int16_t which your StrLenght() truncates to an int8_t I don't see the problem. Try having StrLenght() return an int16_t and change all the counters to int16_t's and see what happens.

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

Shame you haven't got access to a Dragon - you could forget the blinks and see exactly what's going on inside the mega48 using debugWire.

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

Show complete smallest program that displays the odd behaviour.

What happends if you run it in the simulator?

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

Below is the complete code. As suggested i've changed the uint8_t's to uint16_t's, but gave no change in behaviour.

#define F_CPU 1000000UL /* 8 MHz. Required for delay.h */

#include 
#include 
#include 

ioinit (void)                   
{
	DDRB	= _BV(PB3) ;
	PORTB	= _BV(PB3) ; 
}

void blink (uint16_t n)
{
	uint16_t i;
	for (i=0;i

Johan, by simulator you mean the one from AVR, or simulavr? I guess tomorrow I'll set thing up on my laptop, which has WinXP.

Thanks,
Leon

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

With the Simulator and avr-gcc 20081205 and -Os optimisation, everything is put as inline code, and virtually impossible to trace.

With -O0, it traces fine and you get the correct value of blinks.

In real life with an 8MHz Mega32, it blinks the correct number of times.

I can only suggest that you have some other problem such as a corrupted compiler.

David.

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

So it was a newbee problem after all:
David mentioned the -O0 optimization option, which i tried and resulted in 12 blinks for both functions for 3 or 4 chars. To me very strange but it led me on. Then i tried the -Os option and, tada, it works exactly the way it should!! :-D

I only once, when i was trying to understand the makefile, bothered to look into the optimization options. I remember I searched the web, got no conclusive answers and tried a few options. The -O seemed to work just fine and got stuck with it.
Now I just did some more googling, and discovered that the preferred option is indeed "-Os" or even "-Os -mcall-prologues". But in any case level 2 or higher.

So I apologize (bankers: look it's not so difficult ;-) ) for getting you on the wrong foot, and thanks again for the time you've put in to test the code. I really appreciate that!

Best,
Leon

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

A glimpse into the user manual at the documentation for _delay_ms() that you are using will confirm that they only work as expected when optimisation is on. Another advantage of using optimisation is that the floating point library will no longer be added into your code which, along with other optimisation savings, will have knocked 1-2K off the size of the program too.

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

Quote:
David mentioned the -O0 optimization option, which i tried and resulted in 12 blinks for both functions for 3 or 4 chars. To me very strange but it led me on. Then i tried the -Os option and, tada, it works exactly the way it should!! Very Happy

No. The program worked the same with -O0 or -Os.

If you get different behaviour then there is something seriously wrong with your set-up. Which compiler version are you using?

Since you are learning, it is wise to achieve Compilations that have no Warnings. If you do not understand the reasons for the Warnings, just ask.

David.

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

Quote:

If you get different behaviour then there is something seriously wrong with your set-up. Which compiler version are you using?

The timing will be different because of the way _delay_ms() works.

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

Ok, Cliff. By behaviour I mean the # of blinks. Yes the timing will vary depending on which avr-gcc version, optimisation and position of the stars in the sky.

A C compiler should provide the correct functionality even if it takes a long time to do it.

David.

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

Quote:

No. The program worked the same with -O0 or -Os.
If you get different behaviour then there is something seriously wrong with your set-up. Which compiler version are you using?

-O0 option
The code size is 3740 bytes.
I get the warning "#warning "Compiler optimizations disabled; functions from won't work as designed", which can be expected. However, the delay turns out to be the same, so I can still count the blinks. Both strlen and StrLength give the same count, as follows (used code here for formatting):

#chars:   1  2  3  4  5  6 
#blinks: 10 12 12 14 14 16. 

-O option
Code size: 258 bytes
I get no warnings and the results as discussed earlier: strlen gives the correct number, and StrLength gives:

#chars:  1 2 3 4 5 6 7  8  9
#blinks: 2 4 4 6 6 8 8 10 10.

Notice the similarity in patters. Should give an indication, no?

-Os option
Code size: 368 bytes
I get no warnings and correct behaviour.

Since you guys cannot reproduce the behaviour, i give a detailed description of the setup i use below. If i've let something crucial out, please let me know.

Leon

OS: Linux Ubuntu 8.10
CC: Avr-gcc 4.3.0
Loader: Avrdude 5.5
Board: STK500v2, using a Parallax USBto232 converter.
Makefile (perhaps there's another err here):

# AVR-GCC Makefile
PROJECT=Test
SOURCES=LCD.c 
CC=avr-gcc
OBJCOPY=avr-objcopy
MMCU=atmega48
 
CFLAGS=-mmcu=$(MMCU) -g -Os

$(PROJECT).hex: $(PROJECT).out
	$(OBJCOPY) -j .text -O ihex $(PROJECT).out $(PROJECT).hex

$(PROJECT).out: $(SOURCES) 
	$(CC) $(CFLAGS) -Wl,-Map,$(PROJECT).map -o $(PROJECT).out $(SOURCES)

program: $(PROJECT).hex
	avrdude -p m48 -c stk500v2 -u -P /dev/ttyUSB0 -U flash:w:$(PROJECT).hex

clean:
	rm -f $(PROJECT).o
	rm -f $(PROJECT).out
	rm -f $(PROJECT).map
	rm -f $(PROJECT).hex

"avr-objdump -S Test.out" gives (does: <__bad_interupt> give a lead?):

Test.out:     file format elf32-avr

Disassembly of section .text:

00000000 <__vectors>:
   0:	19 c0       	rjmp	.+50     	; 0x34 <__ctors_end>
   2:	33 c0       	rjmp	.+102    	; 0x6a <__bad_interrupt>
   4:	32 c0       	rjmp	.+100    	; 0x6a <__bad_interrupt>
   6:	31 c0       	rjmp	.+98     	; 0x6a <__bad_interrupt>
   8:	30 c0       	rjmp	.+96     	; 0x6a <__bad_interrupt>
   a:	2f c0       	rjmp	.+94     	; 0x6a <__bad_interrupt>
   c:	2e c0       	rjmp	.+92     	; 0x6a <__bad_interrupt>
   e:	2d c0       	rjmp	.+90     	; 0x6a <__bad_interrupt>
  10:	2c c0       	rjmp	.+88     	; 0x6a <__bad_interrupt>
  12:	2b c0       	rjmp	.+86     	; 0x6a <__bad_interrupt>
  14:	2a c0       	rjmp	.+84     	; 0x6a <__bad_interrupt>
  16:	29 c0       	rjmp	.+82     	; 0x6a <__bad_interrupt>
  18:	28 c0       	rjmp	.+80     	; 0x6a <__bad_interrupt>
  1a:	27 c0       	rjmp	.+78     	; 0x6a <__bad_interrupt>
  1c:	26 c0       	rjmp	.+76     	; 0x6a <__bad_interrupt>
  1e:	25 c0       	rjmp	.+74     	; 0x6a <__bad_interrupt>
  20:	24 c0       	rjmp	.+72     	; 0x6a <__bad_interrupt>
  22:	23 c0       	rjmp	.+70     	; 0x6a <__bad_interrupt>
  24:	22 c0       	rjmp	.+68     	; 0x6a <__bad_interrupt>
  26:	21 c0       	rjmp	.+66     	; 0x6a <__bad_interrupt>
  28:	20 c0       	rjmp	.+64     	; 0x6a <__bad_interrupt>
  2a:	1f c0       	rjmp	.+62     	; 0x6a <__bad_interrupt>
  2c:	1e c0       	rjmp	.+60     	; 0x6a <__bad_interrupt>
  2e:	1d c0       	rjmp	.+58     	; 0x6a <__bad_interrupt>
  30:	1c c0       	rjmp	.+56     	; 0x6a <__bad_interrupt>
  32:	1b c0       	rjmp	.+54     	; 0x6a <__bad_interrupt>

00000034 <__ctors_end>:
  34:	11 24       	eor	r1, r1
  36:	1f be       	out	0x3f, r1	; 63
  38:	cf ef       	ldi	r28, 0xFF	; 255
  3a:	d2 e0       	ldi	r29, 0x02	; 2
  3c:	de bf       	out	0x3e, r29	; 62
  3e:	cd bf       	out	0x3d, r28	; 61

00000040 <__do_copy_data>:
  40:	11 e0       	ldi	r17, 0x01	; 1
  42:	a0 e0       	ldi	r26, 0x00	; 0
  44:	b1 e0       	ldi	r27, 0x01	; 1
  46:	e0 e7       	ldi	r30, 0x70	; 112
  48:	f1 e0       	ldi	r31, 0x01	; 1
  4a:	02 c0       	rjmp	.+4      	; 0x50 <.do_copy_data_start>

0000004c <.do_copy_data_loop>:
  4c:	05 90       	lpm	r0, Z+
  4e:	0d 92       	st	X+, r0

00000050 <.do_copy_data_start>:
  50:	a0 30       	cpi	r26, 0x00	; 0
  52:	b1 07       	cpc	r27, r17
  54:	d9 f7       	brne	.-10     	; 0x4c <.do_copy_data_loop>

00000056 <__do_clear_bss>:
  56:	11 e0       	ldi	r17, 0x01	; 1
  58:	a0 e0       	ldi	r26, 0x00	; 0
  5a:	b1 e0       	ldi	r27, 0x01	; 1
  5c:	01 c0       	rjmp	.+2      	; 0x60 <.do_clear_bss_start>

0000005e <.do_clear_bss_loop>:
  5e:	1d 92       	st	X+, r1

00000060 <.do_clear_bss_start>:
  60:	a0 30       	cpi	r26, 0x00	; 0
  62:	b1 07       	cpc	r27, r17
  64:	e1 f7       	brne	.-8      	; 0x5e <.do_clear_bss_loop>
  66:	25 d0       	rcall	.+74     	; 0xb2 
68: 81 c0 rjmp .+258 ; 0x16c <_exit> 0000006a <__bad_interrupt>: 6a: ca cf rjmp .-108 ; 0x0 <__heap_end> 0000006c : #include #include ioinit (void) { DDRB = _BV(PB3) ; 6c: 88 e0 ldi r24, 0x08 ; 8 6e: 84 b9 out 0x04, r24 ; 4 PORTB = _BV(PB3) ; 70: 85 b9 out 0x05, r24 ; 5 } 72: 08 95 ret 00000074 : void blink (uint16_t n) { 74: ac 01 movw r20, r24 76: 20 e0 ldi r18, 0x00 ; 0 milliseconds can be achieved. */ void _delay_loop_2(uint16_t __count) { __asm__ volatile ( 78: e6 ee ldi r30, 0xE6 ; 230 7a: fa ea ldi r31, 0xAA ; 170 7c: 64 e2 ldi r22, 0x24 ; 36 7e: 74 ef ldi r23, 0xF4 ; 244 80: 09 c0 rjmp .+18 ; 0x94 uint8_t i; for (i=0;i _delay_ms(175); PORTB |= _BV(PB3); 8a: 2b 9a sbi 0x05, 3 ; 5 8c: cb 01 movw r24, r22 8e: 01 97 sbiw r24, 0x01 ; 1 90: f1 f7 brne .-4 ; 0x8e } void blink (uint16_t n) { uint8_t i; for (i=0;i 9e: 88 e8 ldi r24, 0x88 ; 136 a0: 93 e1 ldi r25, 0x13 ; 19 a2: 29 e1 ldi r18, 0x19 ; 25 a4: 30 e0 ldi r19, 0x00 ; 0 a6: f9 01 movw r30, r18 a8: 31 97 sbiw r30, 0x01 ; 1 aa: f1 f7 brne .-4 ; 0xa8 __ticks = (uint16_t) (__ms * 10.0); while(__ticks) { // wait 1/10 ms _delay_loop_2(((F_CPU) / 4e3) / 10); __ticks --; ac: 01 97 sbiw r24, 0x01 ; 1 __ticks = 1; else if (__tmp > 65535) { // __ticks = requested delay in 1/10 ms __ticks = (uint16_t) (__ms * 10.0); while(__ticks) ae: d9 f7 brne .-10 ; 0xa6 _delay_ms(175); PORTB |= _BV(PB3); _delay_ms(250); } _delay_ms(500); } b0: 08 95 ret 000000b2
: #include #include ioinit (void) { DDRB = _BV(PB3) ; b2: 88 e0 ldi r24, 0x08 ; 8 b4: 84 b9 out 0x04, r24 ; 4 PORTB = _BV(PB3) ; b6: 85 b9 out 0x05, r24 ; 5 b8: 28 e8 ldi r18, 0x88 ; 136 ba: 33 e1 ldi r19, 0x13 ; 19 bc: 66 ee ldi r22, 0xE6 ; 230 be: 7a ea ldi r23, 0xAA ; 170 c0: 44 e2 ldi r20, 0x24 ; 36 c2: 54 ef ldi r21, 0xF4 ; 244 c4: a9 e1 ldi r26, 0x19 ; 25 c6: b0 e0 ldi r27, 0x00 ; 0 c8: 05 c0 rjmp .+10 ; 0xd4 ca: cd 01 movw r24, r26 cc: 01 97 sbiw r24, 0x01 ; 1 ce: f1 f7 brne .-4 ; 0xcc { // wait 1/10 ms _delay_loop_2(((F_CPU) / 4e3) / 10); __ticks --; d0: 21 50 subi r18, 0x01 ; 1 d2: 30 40 sbci r19, 0x00 ; 0 __ticks = 1; else if (__tmp > 65535) { // __ticks = requested delay in 1/10 ms __ticks = (uint16_t) (__ms * 10.0); while(__ticks) d4: 21 15 cp r18, r1 d6: 31 05 cpc r19, r1 d8: c1 f7 brne .-16 ; 0xca void blink (uint16_t n) { uint8_t i; for (i=0;i _delay_ms(175); PORTB |= _BV(PB3); e2: 2b 9a sbi 0x05, 3 ; 5 e4: ca 01 movw r24, r20 e6: 01 97 sbiw r24, 0x01 ; 1 e8: f1 f7 brne .-4 ; 0xe6 ea: 88 e8 ldi r24, 0x88 ; 136 ec: 93 e1 ldi r25, 0x13 ; 19 ee: fd 01 movw r30, r26 f0: 31 97 sbiw r30, 0x01 ; 1 f2: f1 f7 brne .-4 ; 0xf0 { // wait 1/10 ms _delay_loop_2(((F_CPU) / 4e3) / 10); __ticks --; f4: 01 97 sbiw r24, 0x01 ; 1 __ticks = 1; else if (__tmp > 65535) { // __ticks = requested delay in 1/10 ms __ticks = (uint16_t) (__ms * 10.0); while(__ticks) f6: d9 f7 brne .-10 ; 0xee void blink (uint16_t n) { uint8_t i; for (i=0;i _delay_ms(175); PORTB |= _BV(PB3); 100: 2b 9a sbi 0x05, 3 ; 5 102: ca 01 movw r24, r20 104: 01 97 sbiw r24, 0x01 ; 1 106: f1 f7 brne .-4 ; 0x104 void blink (uint16_t n) { uint8_t i; for (i=0;i _delay_ms(175); PORTB |= _BV(PB3); 110: 2b 9a sbi 0x05, 3 ; 5 112: ca 01 movw r24, r20 114: 01 97 sbiw r24, 0x01 ; 1 116: f1 f7 brne .-4 ; 0x114 118: 88 e8 ldi r24, 0x88 ; 136 11a: 93 e1 ldi r25, 0x13 ; 19 11c: fd 01 movw r30, r26 11e: 31 97 sbiw r30, 0x01 ; 1 120: f1 f7 brne .-4 ; 0x11e { // wait 1/10 ms _delay_loop_2(((F_CPU) / 4e3) / 10); __ticks --; 122: 01 97 sbiw r24, 0x01 ; 1 __ticks = 1; else if (__tmp > 65535) { // __ticks = requested delay in 1/10 ms __ticks = (uint16_t) (__ms * 10.0); while(__ticks) 124: d9 f7 brne .-10 ; 0x11c void blink (uint16_t n) { uint8_t i; for (i=0;i _delay_ms(175); PORTB |= _BV(PB3); 12e: 2b 9a sbi 0x05, 3 ; 5 130: ca 01 movw r24, r20 132: 01 97 sbiw r24, 0x01 ; 1 134: f1 f7 brne .-4 ; 0x132 void blink (uint16_t n) { uint8_t i; for (i=0;i _delay_ms(175); PORTB |= _BV(PB3); 13e: 2b 9a sbi 0x05, 3 ; 5 140: ca 01 movw r24, r20 142: 01 97 sbiw r24, 0x01 ; 1 144: f1 f7 brne .-4 ; 0x142 146: 88 e8 ldi r24, 0x88 ; 136 148: 93 e1 ldi r25, 0x13 ; 19 14a: fd 01 movw r30, r26 14c: 31 97 sbiw r30, 0x01 ; 1 14e: f1 f7 brne .-4 ; 0x14c { // wait 1/10 ms _delay_loop_2(((F_CPU) / 4e3) / 10); __ticks --; 150: 01 97 sbiw r24, 0x01 ; 1 __ticks = 1; else if (__tmp > 65535) { // __ticks = requested delay in 1/10 ms __ticks = (uint16_t) (__ms * 10.0); while(__ticks) 152: d9 f7 brne .-10 ; 0x14a 154: 28 e8 ldi r18, 0x88 ; 136 156: 33 e1 ldi r19, 0x13 ; 19 158: b8 cf rjmp .-144 ; 0xca 0000015a : _delay_ms(500); } uint16_t StrLength (char *a) { return strlen(a); 15a: fc 01 movw r30, r24 15c: 01 90 ld r0, Z+ 15e: 00 20 and r0, r0 160: e9 f7 brne .-6 ; 0x15c 162: 31 97 sbiw r30, 0x01 ; 1 164: e8 1b sub r30, r24 166: f9 0b sbc r31, r25 } 168: cf 01 movw r24, r30 16a: 08 95 ret 0000016c <_exit>: 16c: f8 94 cli 0000016e <__stop_program>: 16e: ff cf rjmp .-2 ; 0x16e <__stop_program>

[/code]

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

Sorry my will to live does not go as far as reading avr-gcc disassembly output.

I am unsure as to avr-gcc v4.3.0
type "avr-gcc -v"
I do know that there was a duff release sometime in 2007/8.

I am still surprised that you could have wrong # of blinks with any Compiler.

My output:

avr-gcc -Os -gdwarf-2 -Wall -mmcu=atmega32 -DF_CPU=8000000L -I../ucntrlr -DKBV -c blinkcount.c
blinkcount.c:1:1: warning: "F_CPU" redefined
: warning: this is the location of the previous definition
blinkcount.c:8: warning: return type defaults to 'int'
blinkcount.c:32: warning: return type defaults to 'int'
blinkcount.c: In function 'ioinit':
blinkcount.c:11: warning: control reaches end of non-void function

Ignore the F_CPU whinges, but I would expect you to get the Warnings about the function signatures.

I should check your documentation for -O optimisation.

With most normal compilers -O will give a default optimisation, and -O0, -O1, -Os give specific settings.

Perhaps -O is a special duff setting on your avr-gcc.
I have tried it on my version and still get 4 blinks per StrLength()

David.

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

You say you're using avr-gcc version 4.3.0 on Ubuntu Linux. I assume you're using a native Linux build of avr-gcc, and not WinAVR under Wine.

Are you using the version of avr-gcc which is provided by Ubuntu's package management system, or did you build it yourself from the source code? If you built it from the source, what patches did you apply?

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

I'm using the avr-gcc which is provided by Ubuntu's package management system. Not good?

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

As for "avr-gcc -v", this gives:

Quote:
Using built-in specs.
Target: avr
Configured with: ../src/configure -v --enable-languages=c,c++ --prefix=/usr --infodir=/usr/share/info --mandir=/usr/share/man --libexecdir=/usr/lib --enable-shared --with-system-zlib --enable-long-long --enable-nls --without-included-gettext --disable-checking --disable-libssp --build=i486-linux-gnu --host=i486-linux-gnu --target=avr
Thread model: single
gcc version 4.3.0 (GCC)

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

Quote:

Not good?

Not Good.

Suggest you visit the GCC forum and look at the sticky thread at the top posted by Bingo600 which has scripts/procedure for building a GCC tolchain on Linux that includes most of the most recent patches (unlike the repo versions that are hugely out of date and should not be relied upon). I know for a fact that those scripts work very well on an Ubuntu 8 (.04 or .1) system.

Cliff

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

Ok, i've read the thread, sound great, BUT (NEWBEE) after an hour of clicking on everything than can be clicked on, googling and cursing, i cannot find where to download the scripts *blush*...
And now i'm to tired to care about the embarrassment of having to ask: "Can you give me the link?"
Thx!

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

Quote:

download the scripts

They should be in the very first post of the thread as attachments but I believe it's a feature of this board that if you are not logged in you cannot see attachments - maybe that's the problem?

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

Yep, i was reading the script not logged in... Got them now, thx!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
main (void)
{
   char *a = "abcd";
   
  ioinit ();
   
   while(1)
   {
      blink(0);
      blink(1);
      blink(StrLength(a));
      blink(strlen(a));
   }

While this is probably correct syntax, I might have coded it this way:

char a[] = "abcd";
blink(strlen(a)); // or blink(strlen(&a[0]));

The other way almost sounds like setting the contents of the pointer to the string turned into an address instead of creating the string and passing its address into the pointer.

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

Quote:

The other way almost sounds like setting the contents of the pointer to the string turned into an address instead of creating the string and passing its address into the pointer.

That's allowed. Often when debugging I'll do something like:

typedef enum {
 IDLE,
 INIT,
 WORKING,
 STOPPED
} STATES;

void do_something(STATES st) {
#ifdef DEBUG
 char * dbg_strs[] = { "IDLE", "INIT", "WORKING", "STOPPED" };
 printf("do_something with %s\n", dbg_strs[st]);
#endif
 // rest of fn
}

That creates both an array of pointers and also creates the anonymous strings to which each entry points.

Cliff

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

I know the next question is quite of topic, but since we've come sofar, i'll pose it here anyway and hope you'll indulge me one more time.

My old avr installation was in /usr/avr which i moved to another location. I've run the scripts from Bingo600 and changed PATH in /ect/environment, so far so good.
At this time "avr-gcc" -v still gave 4.3.0 (should be 4.2.2 with the scripts). Turned out there were avr executables in /usr/bin which i removed, assuming they were from the previous installation.
When i now type: "avr-gcc -v" i get: "bash: /usr/bin/avr-gcc: No such file or directory", however "echo $PATH" gives:
"/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/avr/bin:".
Indeed, avr-gcc is in the last dir of PATH.

Why does bash only search in /usr/bin?? Again i'm clueless. Searched the web, but all pages says to simply adjust the PATH variable and that's it. Where did i go wrong?

Leon

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

Well for one thing if you ever install something in Ubuntu from the repositories (that is a .deb file installed by apt-get or synaptic) then don't try to "hand uninstall it". Use synaptic or "apt-get remove ...". But if you have half-uninstalled it then run synaptic, find the entry under "Installed", look at properties then "installed files" and you can see which files it put in place and therefore which need to be removed.

As for PATH. The default path in Ubuntu is:

/usr/local/sbin;/usr/local/bin;/usr/sbin/usr/bin;/usr/games

and it will be searched in that order. You can, of course, add to this PATH with something like:

export PATH=$PATH:/path/to/files

but you are better off working within the default path structure and ensuring that the things you want to run are in one of those directories.

By the way to see what the PATH currently is:

echo $PATH

Cliff

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

Allright, we're back at the beginning:
1) Moved old AVR dir. back, and removed the whole with synaptic.
2) Removed /usr/local/avr and reran the scripts.
3) Check: "avr-gcc --version" gives 4.2.2 : made it sofar!
4) Blink test, all with "char *a = "abc";" gives the following results

Option     -O -O0 -Os -O2 -O3
#StrLength  4  12   4   4   3
#strlen     3  12   3   3   3 

Notice that with the previous avr-gcc installation -Os gave the correct number for both functions, but now -O3 does. But it gets even fishier.
5) As noticed by Cliff the suggestion from kscharf to initialise the string with "char a[] = "abc";" should not make any difference... Surprise!:

Option     -O -O0 -Os -O2 -O3
#StrLength  7  20   7   7  12 
#strlen     7  20   7   7  12 

That stinks!
6) And so were back at the beginning. Is it still a stupid error in the program or perhaps makefile? But you guys looked at that, and thought it OK. Is it the installation of avr-gcc? Well, i tried two versions, both giving very funny results. Is it the STK500? Well, so far it has worked flawlessly so i can't imagine. On the other hand, my previous compiler worked flawlessly so far as well. Is it the USBto232 converter? Is my linux installation corrupt?
I'm open to suggestions!
7) thx.

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

Do you not know someone with a Windows PC? I'd borrow that for half an hour, install WinaVR and AVR Studio, build/run the software there as a sanity check.

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

Ok, i've installed AVR studio and WINAVR on my laptop (running XP). Programming works: both -O0 and -Os optimization options give the right number of blinks for both function calls!

So we can conclude that XP rules over Linux... just kidding!
At least we can conclude that the chip, the STK500, the USBto232 converter and the program are functioning correctly. But what does it leave? I'll try another makefile, but that is my last option...

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

Quote:

But what does it leave? I'll try another makefile, but that is my last option...

I leaves the entire AVR tool chain on your GNU/Linux system. Compiler (avr-gcc), binutils (ld, objcopy...), programmer...

You might be able to compare the hex files (or maybe .lst files) from the two systems and tool chains.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

Finally, it all seems to work now!!!

I downloaded a makefile from Eric B. Weddington, Jörg Wunsch, et al, and it seems to do the trick. (As you may notice, i have difficulty believing all is OK now...).

I've tested for string length 3 and 5, and with optimization options -O0, -Os, O2, and all give the right amount of blinks for the two different funtion calls! Tsssh! (sound of beer can i'm opening to celebrate ... ;-) )

The only thing i noticed was that initialisation of the string with

 *a = [a,b,c,d,e]; 

resulted in a program of 52 bytes less than with initialisation

a[] = [a,b,c,d,e];

Anyone a concluding thought on this?

Anyway, one more time thank you all very much for taking the effort of writing suggestions. I felt supported in my struggle. Much appreciated!

Best,
Leon

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

Quote:

Anyone a concluding thought on this?

What are "a", "b", "c", "d", "e" - can you show more context of the two solutions? Also what is the type of the item on the left of '=' ?

Normally with pointers (with the exception of an anonymous string initialiser) you also have to arrange to allocated the space to which they point.

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

I apologise, i wasn't thinking and automatically converted to Matlab syntax.
I'll repose:
Initialisation of the string with

 char *a = "abcd"; 

leads to code 52 bytes less than

 char a[] = "abcd"; 

What's causing this?

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

Quote:

What's causing this?

You realise it's in YOUR power to find out?

I could make a small example program and build it each way then inspect the .lss to see how the generated code differs but it'd probably be more instructive for you to try this yourself.

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

You're probably right, i was just hoping for a quick answer on the mechanism behind array initialisation. Well i've looked at the .lss, and yes indeed there an additional piece of assembler code where the initialisation of the string takes place.

After a week of frustration, i'm not quite ready to take another side tour "getting to know assembler".So forget it, i'll find out in due time.
Thanks anyway.

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

Quote:

i'm not quite ready to take another side tour

It's a VERY useful one to take - it makes C programmers FAR more efficient if they can read and influence the quality of the Asm generated.

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

Point taken. It has shifted up on my todo list! Still much learning to do...

Leon