Forum: Mikrocontroller und Digitale Elektronik SPM-Instruction beim Atmega328p


von Glenn (Gast)


Lesenswert?

Hallo,
ich bin gerade dabei, den Atmega328p näher kennenzulernen, indem ich 
einen Arduino Uno über einen ISP-Programmer (Diamex) und AVR-Studio 4 in 
Assembler programmiere. Es sind meine ersten Gehversuche in Assembler.
Da ich perspektivisch einen kleinen programmierbaren 
Kommando-Interpreter (Forth-ähnlich) schreiben möchte, möchte ich auch 
die Technik beherrschen, User-Input remanent ins Flash zu schreiben - 1 
KB EEPROM ist mir einfach zu wenig. Und je mehr Programmspeicher ein 
Atmega hat, desto mehr macht eine solche Möglichkeit auch Sinn.
Ich habe also eine kleine Testroutine geschrieben, die den Temporary 
Buffer mit ansteigenden Werten füllt, diesen in die entsprechende, vom 
Z-Pointer indizierte Page schreibt und diese Page dann ausliest - für 
den Simulator etwas abgespeckt, die Subroutines getbyte und sendbyte 
sind hier funktionslos.
Der Simulatorlauf funktioniert, egal wo im 'Flash' spm-execute steht.
Auf dem Controller selbst sieht es anders aus: steht spm-execute in der 
Bootloader-Section scheint der Controller dort festzuhängen, denn das 
Auslesen der Page funktioniert dann nicht.
Schreibe ich spm-execute einfach irgendwo in die Application-Section 
hinein, wird die Seite zwar ausgelesen, aber erkennbar ist der Temporary 
Buffer dort vorher nicht hineingeschrieben worden - was ja zu erwarten 
war.
Mich interessiert also, warum der Controller in der Bootloader-Section 
festhängt. Darf man vom Applikationsbereich nicht einfach eine 
Subroutine aufrufen, die in der Bootloader-Section steht?
Für Erklärungen oder Vorschläge wäre ich dankbar.
Viele Grüße
Glenn

1
;------------------------------------ Testprogram for SPM Storage Checking ------------------------------------------------
2
3
.include "M328pDEF.INC"
4
.org 0000
5
6
.def  char = r17
7
.def  char1 = r18
8
.def  wordcounter = r22
9
10
ldi   r16, low(RAMEND)
11
out   SPL, r16
12
ldi   r16, high(RAMEND)
13
out   SPH, r16
14
15
ldi   r16, 0b00011000  ;getbyte Enable (RXEN) + sendbyte Enable (TXEN) = (11)
16
sts   UCSR0B,r16            
17
ldi   r16, 0b00000110  ;USART Mode Select Asynchronuos (URMSEL01:0) = (00), 8-bit Character Size (UCSZ1:0) = (11)  
18
sts   UCSR0C,r16    ;No Parity, No Stop-Bit (000)
19
ldi   r16, 0x33      ;Baud Rate Register = 0x33, 19200 at 16 MHz 
20
sts   UBRR0L,r16
21
22
;----------------------------------------------------------------------------------------------------------------------
23
24
ldi    wordcounter,64  ; 64 words
25
ldi   char,0
26
27
ldi   ZL,low(25600)
28
ldi   ZH,high(25600)
29
30
word_to_buffer:
31
mov    r0,char
32
inc   char
33
mov    r1,char
34
inc   char
35
ldi    r16,0b00000001
36
call  spm_execute
37
adiw  Z,2
38
dec    wordcounter
39
brne  word_to_buffer
40
41
ldi   ZL,low(25600)
42
ldi   ZH,high(25600)  
43
ldi    r16, 0b00000011  ; page erase
44
call  spm_execute      
45
ldi    r16, 0b00000101  ; page write
46
call  spm_execute    
47
ldi    r16, 0b00010001  ; section re-enable
48
call  spm_execute
49
50
ldi   ZL,low(25600)
51
ldi   ZH,high(25600)
52
ldi    wordcounter,128  ; 128 bytes
53
word_send:
54
lpm   char1,Z
55
;call  sendbyte
56
adiw  Z,1
57
dec   wordcounter
58
brne  word_send
59
60
halt: rjmp halt
61
62
;------------------------------------------------ subroutines ---------------------------------------------------------
63
64
getbyte: 
65
lds   r16,UCSR0A
66
sbrs  r16,RXC0
67
rjmp  getbyte
68
lds   char,UDR0
69
ret
70
71
sendbyte: 
72
lds   r16,UCSR0A
73
sbrs  r16,UDRE0
74
rjmp  sendbyte
75
sts   UDR0,char
76
ret
77
78
.org 0x3C00
79
spm_execute:    
80
out SPMCSR,r16
81
spm
82
complete:  
83
in   r16,SPMCSR
84
sbrc r16,SELFPRGEN
85
rjmp complete
86
ret

von bitflipser (Gast)


Lesenswert?

Das 328/P Datenblatt liefert in
"30. BTLDR - Boot Loader Support – Read-While-Write Self-Programming"
ein paar Hinweise:
SPM wird aus dem Anwendungsspeicher, glaube ich, ignoriert und während 
einer Lösch- oder Schreibaktion im RWW-Speicherbereich (i.d.R. der 
Anwendungsspeicher) darf darauf nicht zugegriffen werden.
Kurz:
Dieser Teil sollte komplett im NRWW-/Bootloaderbereich laufen (zusammen 
mit spm_execute):
1
ldi   ZL,low(25600)
2
ldi   ZH,high(25600)  
3
ldi    r16, 0b00000011  ; page erase
4
call  spm_execute      
5
ldi    r16, 0b00000101  ; page write
6
call  spm_execute    
7
ldi    r16, 0b00010001  ; section re-enable
8
call  spm_execute

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.