Forum: Mikrocontroller und Digitale Elektronik ASM: Rücksprung aus Funktion fehlerhaft (Mega32)


von Thomas B. (nichtessbar)


Lesenswert?

Hallo,

ich denke dass ich einfach irgendwas übersehe, aber ich suche jetzt 
schon ein paar Stunden und finde den Fehler nicht darum möcht ich gern 
jemand Außenstehenden um Hilfe fragen.

Folgendes Problem:
Unten geposteter Code soll irgendwann mal ein Bootloader werden, 
momentan versuche ich einfach eine Echoschleife für die USART zu machen 
(als Test).

Wenn ich jetzt die Funktion init_uart aufrufe mittels rcall wird diese 
ausgeführt und dann springt der PC irgendwohin im Speicher bis der 
Prozessor dann wieder resettet und von vorn anfängt. Verhalten konnte 
mit AVR Sim und alternativ JTAGICE direkt am Prozessor beobachtet 
werden. Schreibe ich die richtige Rücksprungadresse manuell beim 
Debuggen in den Speicher, auf den der Stackpointer zeigt, läuft das 
Programm tadellos (auch Interruptabarbeitung etc. funktioniert).

Stackpointer hat beim Programmstart den Wert 0x0000 und wenn dann zwei 
weggezählt (wg. 2 Byte PC am Stack ablegen, siehe AVR-ISM rcall) werden 
kommt natürlich ein Überlauf (dann zeigt er auf 0x0ffe) - das ist das 
einzige was mir derzeit komisch erscheint?
1
/*
2
 * assBootloader.asm
3
 *
4
 *  Created: 28.01.2012 19:52:00
5
 *   Author: tbergmueller
6
 */ 
7
8
 .include "m32def.inc"
9
10
  .def    mp=R16    
11
  .equ    INT_TAB_LENGTH=100                    ; Länge der Interrupttabelle (für Tests mal lang genug...)
12
  .equ    APP_STARTADDR=0                      ; Start der Applikation, 0 wegen Debugmöglichkeit, später dann 0x03f00
13
  .equ    BOOTLOADER_STARTADDR=APP_STARTADDR+INT_TAB_LENGTH    ; start der Eigentlichen Bootloadersoftware
14
   
15
16
 .cseg
17
18
 .org APP_STARTADDR
19
      rjmp  main      ; reset handler
20
 .org URXCaddr+APP_STARTADDR
21
      rjmp  recByte      ; RXC Handler
22
23
24
25
;.org BOOTLOADER_STARTADDR
26
27
main:    ;call  Move_interrupts  
28
      rcall  init_uart
29
30
      ; Testweise 8 LED an Port einschalten
31
      ldi    mp, 0xff
32
      out    DDRA, mp
33
      ldi    mp, 0
34
      out    PORTA, mp
35
36
loop:    rjmp  loop          ; endlosschleife
37
      jmp    0            ; start normal (später für Bootloader)
38
39
40
41
; ################### FUNCTIONS
42
init_uart:  ldi    mp, 0x98        ; load registers
43
      out    UCSRB, mp        ; RXIE enabled, RXEN, TXEN      test
44
      ldi    mp, 103          ; load ubrrl
45
      out    UBRRL, mp
46
      sei  
47
      ret
48
49
; Interrupthandler RXC
50
recByte:  in    mp, UDR
51
      call  USART_Transmit
52
53
      reti
54
55
; Senden via USART
56
USART_Transmit:
57
      sbis  UCSRA,UDRE
58
      rjmp  USART_Transmit
59
60
      out    UDR,mp
61
      ret
62
63
; Interrupts in den Bootloaderbereich verschieben
64
Move_interrupts:      
65
      ; Enable change of interrupt vectors
66
      ldi    mp, (1<<IVCE)
67
      out    GICR, mp
68
      ; Move interrupts to boot Flash section
69
      ldi    mp, (1<<IVSEL)
70
      out    GICR, mp
71
      ret


Vielen Dank schonmal für die Hilfe und ich mir ist der vermutlich extrem 
dumme Fehler jetzt schon peinlich...

Thomas

von MWS (Gast)


Lesenswert?

Du hast schon mal davon gehört, dass man den SP initialisieren muss ?

von spess53 (Gast)


Lesenswert?

Hi

Beim ATMega32 musst du den Stackpointer initialisieren:
1
  
2
  ldi r16,high(RAMEND)
3
  out SPH,r16
4
  ldi r16,Low(RAMEND)
5
  out SPL,r16

MfG spess

von Thomas B. (nichtessbar)


Lesenswert?

Wusst ich's doch dass es ein peinlicher Fehler ist...

Dankeschön für die rasche Hilfe! Muss zugeben, hab Assembler das letzte 
Mal glaub ich vor 5 Jahren benutzt und das am 8051, da war wurde 
StackPtr per default initialisiert, soweit hab ich nicht gedacht.

von spess53 (Gast)


Lesenswert?

Hi

>...und das am 8051, da war wurde
>StackPtr per default initialisiert, soweit hab ich nicht gedacht.

Ist bei neueren AVR auch so. Der ATMega32 ist halt schon ein 
Dinosaurier.

MfG Spess

von Thomas B. (nichtessbar)


Lesenswert?

War der einzige den ich in DIL-Bauform zuhause hatte und am Steckbrett 
is doch am Einfachsten JTAG anzuschließen für ein paar schnelle Tests ;)

Aber auf alle Fälle gut zu wissen dass es Controller gibt die das nicht 
selbst machen.

von oldmax (Gast)


Lesenswert?

Hi
Auch wenn es vielleicht jetzt noch nicht zum tragen kommt, aber ich würd 
die ISR so nicht stehen lassen...
1
; Interrupthandler RXC
2
recByte:  in    mp, UDR
3
      call  USART_Transmit
4
5
      reti
In einer ISR macht es Sinn, grad bei Assembler, verwendete Register zu 
sichern. Das Status- als auch das mp-Register kann wichtige Inhalte 
haben, die dann u.U. beim Eintreten eines Interrupts futsch sind.
Gruß oldmax

von Ben _. (burning_silicon)


Lesenswert?

Das Statusregister MUSS bei Interruptroutinen gesichert werden. 
Ansonsten gibts schwere Probleme wenn ein Interrupt zwischen einem 
Compare und der nachfolgenden Branch-If-Irgendwas-Anweisung auftritt. 
Schade daß die Dinger kein PUSHF/POPF können wie die x86...

von Thomas B. (nichtessbar)


Lesenswert?

Ich seh schon, das wird ein langer Kampf bis das alles stabil läuft und 
getestet ist, es fehlt einfach die Routine ;)

Danke für die Hinweise!

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.