AVR 231 Bootloader GCC Port for AVRGCC 3.4 (Atmel Studio 6)

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

Hi Guys,

Has anybody thought about adapting the GCC Port of the AES Bootloader (AVR 231) to the changes in AVRGCC 3.4.0.65 which is implemented in Atmel Studio 6.0?

The filetypes with progmem attribute (put information only in flash and not in SRAM, e.g. prog_uchar) have been deprecated and so the Port won't compile. I tried to fix it, but didn't accomplish a lot since I don't have much experience in this field.

https://www.avrfreaks.net/index.php?module=Freaks%20Files&func=viewFile&id=3330&showinfo=1
(btw the "Published" Date on this site seems to show the date it was last downloaded, which is confusing)

I think this would be a very helpful thing to do, since the bootloader is IMHO very good.

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

Quote:

The filetypes with progmem attribute (put information only in flash and not in SRAM, e.g. prog_uchar) have been deprecated and so the Port won't compile. I tried to fix it, but didn't accomplish a lot since I don't have much experience in this field.

Eh? The only change in the 4.6.x within AS6 is that anything in PROGMEM now must be "const".

(moving this to GCC forum).

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

aaah yes, I tried it again, no compiling error.

Sry for bothering it is done simply by replacing said parts.

I have a different problem, but this code is not implemented in the AVR231 source files.

I have a function (not written by me) which measures the time of a signal on the serial port to calibrate the communication to any given baudrate.

uint16_t tmp = 0;

TCCR1B = 0x00;
TCNT1 = 0x00;
asm("wait_start_fall:"            "\n\t"
        "sbic   %[pin],%[pad]"      "\n\t"
        "rjmp   wait_start_fall"    "\n\t"
        : [pin] "M" (_SFR_IO_ADDR(PINE)), [pad] "M" (0));
TCCR1B = _BV(CS20);
asm("wait_start_rise:"            "\n\t"
        "sbis   %[pin],%[pad]"      "\n\t"
        "rjmp   wait_start_rise"    "\n\t"
        : [pin] "M" (_SFR_IO_ADDR(PINE)), [pad] "M" (0));
TCCR1B = 0x00;
tmp = TCNT1;

return (tmp>>4);

This calibration does not work (no compiler errors though) when compiled with AS6.0, but does work with AS5.1

It seems to be some problem with clock frequency which I tested by including a buzzer beep for 3000 ms (implemented with

setBuzzer();
_delay_ms(3000);
clearBuzzer(); 

-> AS 5.1 beeps 3 s, AS 6.0 beeps 6 s.

Other software has no problems of this kind.

I realize of course that this could be due some other code adaptations made by my predecessor, but any ideas anyone?

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

Maybe some additional information:
ATMega645
AVRDragon
Fuses (especially those which determine clock frequency are all the same in both studios)

but at least some PROGRESS:

While debugging I discovered that AS 5 writes a value in OSCCAL, AS 6 does not.

afaik, AS 5 does the right thing, it lets the Atmega645 load the factory calibration.

The question is now, why and how does AS 6 prevent this,
how can i prevent the prevention,
or can I manually load the factory calibration while runtime?

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

Quote:

While debugging I discovered that AS 5 writes a value in OSCCAL, AS 6 does not.

You are completely wrong about that - AVR-LibC's CRT never has and never will touch OSCCAL.
Quote:

or can I manually load the factory calibration while runtime?

If you've seen code that did this it is somewhere in your own source code. The AVR datasheets are clear about how to handle OSCCAL.

Note however that in all modern AVR that have only a single 8MHz oscillator (you can tell this by the presence of the CKDIV8 fuse and the CLKPR register) they automatically load the one and only OSCCAL factory calibration byte at power on anyway.

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

First: I want to thank you for your help, your inputs were helpful. Also just writing in this forum helped me a lot because I had to think about how to describe my problem to you, which brought me to new ideas.

Second: I found the factor, that solves this problem. Regardless I want to document the path how I found it.

Quote:
Note however that in all modern AVR that have only a single 8MHz oscillator (you can tell this by the presence of the CKDIV8 fuse and the CLKPR register) they automatically load the one and only OSCCAL factory calibration byte at power on anyway.

That is exactly my point.

To be completely sure that it happens I created both AS5 & AS6 Project files in the same folder with exactly! the same source files. When I change code with ether AS and save the file, it will of course be updated in the other.

I also put the OSSCAL value on a display on runtime, to eliminate debugging effects.

What happens:
If I compile the bootloader with AS5, the ATMega 645 does as described in the datasheet, it loads the initial OSCCAL Value and displays it (161).

If I compile EXACTLY the same code with AS6, the OSCCAL value is set to 0.

Compiler options are nearly the same, AS6 automatically adds

-MD -MP -MF "$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -MT"$(@:%.o=%.o)"

whatever this means.

Also AS6 adds

-Wl,--start-group  -Wl,--end-group

to the Linker Options.

So I assume AS6 does not somehow "prevent" the loading of the factory calibration but adds some code that rewrites OSCCAL.

For some more testing I manually added a instruction to write a value in OSCCAL, this works.

I looked in the Disassembly, there is the instruction which writes the given value to the according data space (0x0066, as specified also in the data sheet)

OSCCAL = 100;

 LDI R24,0x64		Load immediate 
 STS 0x0066,R24		Store direct to data space 

I could not find another point in the Disassembly were data was written in this data space. But searching is pretty limited.

Also I tried a different project apart from the bootloader in AS6, here the OSCCAL value is correct.
So seems to be a problem in bootloader code, and in code that is executed before entering the main routine.

Then I downloaded the original bootloader from your site again and created a completely new AS 6 Project with this files.

After adapting the files (prog_uchar -> unsigned char, defining F_CPU & BAUD),I added the Compiler and Linker Options step by step and debugged to see what happens with the OSCCAL.

I discovered that choosing the Linker option "Garbage collect unused sections (-Wl,--gc-sections)" not only saves about 20 byte of flash storage, but also somehow sets the OSCCAL value to 0 instead of factory settings.

Notice that this options was also chosen in AS5 but without this effect!! Also in the non-bootloader project is no problem with this.

As this works with the files from your site, you should be able to reproduce this.

Conclusion: Something did happen because of the new compiler/linker version. Perhaps its a bug.

Maybe, if somebody is interested in this stuff, can search for the underlying reason, I do not know how to go any deeper.

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

Quote:

So I assume AS6 does not somehow "prevent" the loading of the factory calibration but adds some code that rewrites OSCCAL.

No this is utter rubbish. The compiler adds no such code - there isn't even any such code in the library for it to add. You are mis-interptreting what's going on. If you really believe it is adding such code show the part of the .lss while where this occurs. I bet you a £1000 you cannot.

OSCCAL = 100;

 LDI R24,0x64      Load immediate
 STS 0x0066,R24      Store direct to data space 

but this is not code added by the compiler. *YOU* wrote it!

What I think is happening is that your reading/verification code to display what's there is not valid in some way and is mistakingly showing 0. It could be an optimisaztion issue or it could even be a bug but I can tell you for nothing that no code from the compiler is writing a value to OSCCAL unless you or code you #include is doing it.

In fact the ONLY "hidden" code in a C program is the C RunTime (CT) which consists of something like this:

00000054 <__ctors_end>:
  54:	11 24       	eor	r1, r1
  56:	1f be       	out	0x3f, r1	; 63
  58:	cf e5       	ldi	r28, 0x5F	; 95
  5a:	d4 e0       	ldi	r29, 0x04	; 4
  5c:	de bf       	out	0x3e, r29	; 62
  5e:	cd bf       	out	0x3d, r28	; 61

00000060 <__do_copy_data>:
  60:	10 e0       	ldi	r17, 0x00	; 0
  62:	a0 e6       	ldi	r26, 0x60	; 96
  64:	b0 e0       	ldi	r27, 0x00	; 0
  66:	e2 e1       	ldi	r30, 0x12	; 18
  68:	f1 e0       	ldi	r31, 0x01	; 1
  6a:	02 c0       	rjmp	.+4      	; 0x70 <__do_copy_data+0x10>
  6c:	05 90       	lpm	r0, Z+
  6e:	0d 92       	st	X+, r0
  70:	a0 36       	cpi	r26, 0x60	; 96
  72:	b1 07       	cpc	r27, r17
  74:	d9 f7       	brne	.-10     	; 0x6c <__do_copy_data+0xc>

00000076 <__do_clear_bss>:
  76:	10 e0       	ldi	r17, 0x00	; 0
  78:	a0 e6       	ldi	r26, 0x60	; 96
  7a:	b0 e0       	ldi	r27, 0x00	; 0
  7c:	01 c0       	rjmp	.+2      	; 0x80 <.do_clear_bss_start>

0000007e <.do_clear_bss_loop>:
  7e:	1d 92       	st	X+, r1

00000080 <.do_clear_bss_start>:
  80:	aa 37       	cpi	r26, 0x7A	; 122
  82:	b1 07       	cpc	r27, r17
  84:	e1 f7       	brne	.-8      	; 0x7e <.do_clear_bss_loop>
  86:	0e 94 75 00 	call	0xea	; 0xea 
8a: 0c 94 87 00 jmp 0x10e ; 0x10e <_exit>

that cleares R1, sets SREG (to 0), sets the stack (and at the same time the stack frame pointer held in Y) then it copies the .data initial values and wipes the .bss and finally CALLs your main(). Nothing more, nothing less. Certainly nothing to do with OSCCAL.

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

It might be that I misinterpret things, as I do not have any knowledge about the compiler.

But what I can say is, when the bootloader is compiled with the described linker option, OSCCAL is set to 0 on start, this is confirmed by showing it on the display, but more importantly while debugging, as Atmel Studio reads every bit of information and shows to the user in convenient style.

Something in the bootloader code in combination with this compiler version and this linker option, as a fact, sets OSCCAL to 0.

Feel free to try it yourself if you have some similar chip around.

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

Quote:

Feel free to try it yourself if you have some similar chip around.

I do not have a 645. Also how are you observing this - which debugger are you using? I have both JTAGICEmkII and Dragon I can try and a range of various AVRs (DIP package mainly for use in STK500). However I know that the C compiler does NOT generate code that writes OSCCAL. So if you see what appears to be a changed value it is an artefact of the way you are observing this could easily indicate a bug in the Atmel debugger parts of AS6. One thing it's not caused by though is the C compiler.

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

I debug with a Dragon, it's definitely not a debugger problem, as described much earlier:
The wrong OSCCAL value is directly noticeable when you e.g. turn an Outport on/off with a delay. The delay is different (approx. factor 2) when the code is compiled with the linker option. This also works without compiling.
On an STK500 you could easily display the OSCCAL value with the LEDs, something like PORTB = OSCCAL should work I guess.

I do not say it is a compiler problem, it has definitely something to do with the bootloader, as my "Main Software" doesn't have this problem.
But something in the bootloader is compiled differently in AS6 compared with AS5, when this option is chosen, which effects the OSCCAL.

I'm curious if you can reproduce this.

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

No I canot reproduce this. I suspect it could be a fault in the XML file for 645. Perhaps it has mapped the view of "OSCCAL" onto something else? Have you checked the d/sheet? Is the IO address 0x66?

One thing I can 100% assure you is that there is no "hidden code" inserted by the compiler that is writing that register. So if you see it changing it's most likely a problem with the observation.

Try this for example. Create a delay loop that delays exactly 10 seconds then lights an LED. Put this both before and after the place where you think OSCCAL is changed. Does the operational speed of the AVR actually change? Or does the stopwatch on your watch show 10 seconds in both cases?

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

I can't place it there, because it changes before entering main routine.

Although I can verify that the 10s timer works when compiled w/o said option, and with said option the same 10s delay takes about 20s.

could be that this is atmega645 specific.

In the .lss file I cant find anything, but also understand not much of it.

Would it help if I give you the 2 lss files, with and without this error?
Or do you want to drop it as I have a workaround now?

Last Edited: Tue. Nov 13, 2012 - 02:12 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

because it changes before entering main routine.

So step through the CRT.
Quote:

Would it help if I give you the 2 lss files, with and without this error?

Very much so.

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

Quote:
So step through the CRT.

Have to do some research to know how to do this, I'll try when I have more time on my hands.

I compiled now the said bootloader with and without garbage collect (-Wl,--gc-sections) which results in OSCCAL -> ok and OSCCAL -> zero.

To check it added I to the top of the main routine:

PORTD &= ~_BV(PD4);
DDRD |= _BV(PD4);
_delay_ms(1000);
PORTD |= _BV(PD4);
_delay_ms(5000);
PORTD &= ~_BV(PD4);

which results in a noticeable difference (~8s instead of 5) when OSCCAL is set zero.

Aside from that (and changes necessary e.g. prog_uchar -> unsigned char, custom key etc.) the files from this site are untouched.

Attachment(s): 

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

Oh right this looks like one of Atmel's toolchain known faults. It looks like it's incorrectly acting as if SRAM starts at 0x0060 rather than 0x0100.

  b2:	14 e0       	ldi	r17, 0x04	; 4
  b4:	a0 e6       	ldi	r26, 0x60	; 96
  b6:	b0 e0       	ldi	r27, 0x00	; 0
  b8:	01 c0       	rjmp	.+2      	; 0xbc <.do_clear_bss_start>

000000ba <.do_clear_bss_loop>:
  ba:	1d 92       	st	X+, r1

000000bc <.do_clear_bss_start>:
  bc:	a4 38       	cpi	r26, 0x84	; 132
  be:	b1 07       	cpc	r27, r17
  c0:	e1 f7       	brne	.-8      	; 0xba <.do_clear_bss_loop>

You appear to have 1060 bytes of .bss variables. So this code above is clearing 0x0060 to 0x0483 rather than 0x0100 to 0x0523 as it should.

Talk to Atmel, they screwed the pooch on this one.

BTW presumably the .map file shows RAM at 0x800060 rather than the expected 0x800100 ?

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

Can't find anything about RAM in the map file, just the bss wrongly positioned like in the lss

Attachment(s):