Avrdude 64KB Problem: Fehler bei mehr als 64KB

Dies ist ein Problem in "avrdude" (Version 5.10 und 5.11). Offenbar ist es ein Bug in avrdude selbst oder ein Fehler im MK3-Programmer (oder beides).

In diesem Paket ist eine provisorische Umgehung dieses Problems enthalten: rolfslcdtreiber.tar.gz
(die aufgeteilten Blöcke der hex-Datei werden noch mit falschen Adressen modifiziert um avrdude zu überlisten)

Versucht man eine hex-Datei von mehr als 64KB zu speichern erhält man einen Fehler. Wenn man jetzt die grosse hex-Datei auf mehrere jeweils maximal 64KB grosse Teile aufteilt und diese einzeln brennt (wobei man nur bei der 1. den Flash zuvor löscht), dann scheint es korrekt zu funktionieren. Aber das stimmt nicht! Denn beim zurücklesen passiert der selbe Fehler nochmals. Offenbar wird der zweite und vierte 64KB Block innerhalb des Flash-Speichers jeweils vertauscht geschrieben. Und beim zurücklesen wird ebenfalls der zweite und vierte Block vertauscht.

Man muss also innerhalb des Microkontroller-Programms überprüfen ob die Daten an der richtigen Stelle gespeichert wurden.
Hier ein entsprechendes einfaches Assemblerprogramm:

;; flashcheck.asm
;; checking flash memory
;; Hardware: mk3 board with myAVRstamp256 (Atmega2560)
;;           connected LEDs at PORTL and PORTB

.include "m2560def.inc"

main:   ldi r16, low(RAMEND)
        ldi r17, high(RAMEND)
        out SPL, r16
        out SPH, r17
        ldi r16, 0xFF
        sts DDRL, r16           ;whole PORTL as output
        out DDRB, r16           ;whole PORTB as output
mainloop:
;        ldi r16, 1
        ldi r16, 0x06           ;Number "1" for 7 segment display on MK3 board
        out PORTB, r16          ;Number 1 at PORTB
        call subroutine1
        sts PORTL, r16          ;Result of subroutine1 at PORTL
        rcall wait              ;wait about 1 sec
;        ldi r16, 2
        ldi r16, 0x5B           ;Number "2" for 7 segment display on MK3 board
        out PORTB, r16          ;Number 2 at PORTB
        call subroutine2
        sts PORTL, r16          ;Result of subroutine2 at PORTL
        rcall wait              ;wait about 1 sec
;        ldi r16, 3
        ldi r16, 0x4F           ;Number "3" for 7 segment display on MK3 board
        out PORTB, r16          ;Number 3 at PORTB
        call subroutine3
        sts PORTL, r16          ;Result of subroutine3 at PORTL
        rcall wait              ;wait about 1 sec
;        ldi r16, 4
        ldi r16, 0x66           ;Number "4" for 7 segment display on MK3 board
        out PORTB, r16          ;Number 4 at PORTB
        call subroutine4
        sts PORTL, r16          ;Result of subroutine4 at PORTL
        rcall wait
        rcall wait
        rcall wait              ;wait about 3 sec
        rjmp mainloop

wait:                 ; waiting subroutine
        push r24              ; save registers on stack
        push r25
        push r16
        ldi r16, 150          ; counter for outer loop
w1:     ldi r24, low(-32000)  ; r25:r24 as 16 bit counter for inner loop
        ldi r25, high(-32000)
w2:     adiw r24, 1           ; r25:r24 incrementing
        brne w2               ; branch if not zero
        dec r16
        brne w1               ; outer loop
        pop r16               ; restore registers from stack
        pop r25
        pop r24
        ret

subroutine1:                    ;first subroutine at low flash address
        ldi r16, 0x11
        ret

.org 0x8000
subroutine2:                    ;2. subroutine above 64KB
        ldi r16, 0x22
        ret
        
.org 0x10000
subroutine3:                    ;3. subroutine above 128KB
        ldi r16, 0x33
        ret

.org 0x18000
subroutine4:                    ;4. subroutine above 192KB
        ldi r16, 0x44
        ret
Wenn man die ".org" Befehle weglässt, dann funktioniert es korrekt. Es werden der Reihe nach die Zahlen 1 bis 4 auf dem 7-Segment-Display angezeigt und gleichzeitig der entsprechende Rückgabewert von der jeweiligen Subroutine auf den PORTL-LEDs angezeigt.
Mit den ".org" Befehlen sind subroutine2 und subroutine4 vertauscht.

Provisorische Umgehung des Problems

C Programm um hex-Dateien zu wandeln: hex.tar.gz
Obiges Beispiel mit entsprechendem makefile: asmbeispiele.tar.gz
Mit "make install" wird ganz normal gebrannt.
Mit "make install2" wird mittels "hexsplit -a" die hex-Datei aufgespalten und einzeln gebrannt.

Last update: 29.Sep.2012 / Rolf                                                                                 Validator