I2C-Bootlader AN1302
Mittwoch, 23. Mai 2012
 
 

PIC Mikrocontroller Forum  |  PIC Mikrocontroller  |  Programmiersprache C  |  I2C-Bootlader AN1302 « vorheriges nächstes »
Seiten: [1] Nach unten Drucken
Autor Thema: I2C-Bootlader AN1302  (Gelesen 3153 mal)
 
BL1
Jr. Member
**
Offline Offline

Beiträge: 82


Profil anzeigen
« am: Juli 20, 2011, 15:09:12 »

Hallo,


es hat sich nicht zufällig schon mal jemand mit obiger Application Note beschäftigt?

Ich habe jetzt tagelang an dem Ding geschwitzt und bin der Meinung, das kann so gar nicht funktionieren. Da gibt es eine Sequenz in einer H-Datei, da werden Variablen deklariert:
Code:
// externs
extern unsigned char nrbytes;
extern unsigned char flash_buffer[];
extern unsigned char pksa_index;
extern unsigned char pksa_wd_address;
extern unsigned char pksa_status;
extern unsigned char pksa_cmd;

Da ist da das Array flash_buffer. Da werden in der I2C-Übertragung Daten rein geschrieben. Die Variablen danach beschreiben Zustände, die während des Übertragens der in flash_buffer zu schreibenden Daten gebraucht werden. Mal davon abgesehen, dass diese Deklaration eines Arrays ohne Anzahl der Speicherplätze mir schon komisch vorkommt. Ich habe die ganze AN in CC5x rübergenommen, da mußte ich das dann sowieso anders schreiben, nämlich:
Code:
// externs
unsigned char nrbytes;
unsigned char *flash_buffer;
unsigned char pksa_index;
unsigned char pksa_wd_address;
unsigned char pksa_status;
unsigned char pksa_cmd;

Das hat nun zur Folge das auf Speicherplatz x die Variable flash_buffer steht, auf x+1 pksa_index, auf x+2 pksa_wd_address usw. An der Stelle kracht es nun, wenn man Daten in flash_buffer
  • schreiben will, dann überschreibt man damit die Zustandsvariablen, die gerade gebraucht werden. Und schon schießt das Ganze ins Nirwana.

Nun ist die AN doch sicher für den diesen HCPIC-pro-9.80-Compiler gemacht. Kann man denn da ein Array ohne Längenangabe definieren, ohne solche Abstürze zu provozieren? Wenn nicht, kann doch diese Application Note nie wirklich gelaufen sein.



BL
Gespeichert
Stampede
Globaler Moderator
Hero Member
*****
Offline Offline

Beiträge: 969



Profil anzeigen WWW
« Antworten #1 am: Juli 20, 2011, 20:24:44 »

Hallo,

das Array wird ja eben nicht an dieser Stelle definiert. Das extern bedeutet, dass dies an einer anderen Stelle (andere Code- oder Headerdatei) geschehen ist. Daher braucht die Länge auch nicht angegeben werden.
Mit dem C Complier für PIC16 kenne ich mich aber sonst gar nicht aus.

Gruß
Stefan
Gespeichert

Bernd
Globaler Moderator
Hero Member
*****
Offline Offline

Beiträge: 3815



Profil anzeigen
« Antworten #2 am: Juli 20, 2011, 21:34:07 »

Die extern Deklaration des Arrays ist ohne Größenangabe korrekt. Die erste Dimension eines Arrays in ANSI-C muß in einer Deklaration nicht angegeben werden (bei mehrdimensionalen Array dann z.B. extern char array [][2][3]).

flash_buffer ist in der AN1302 in bootlader.c definiert als

Code:
unsigned char flash_buffer[16];

Zitat
Code:
unsigned char *flash_buffer;

definiert einen Zeiger auf den Typ unsigned char und ist keinesfalls ein Array vom Typ unsigned char. Siehe dazu auch: http://www.lysator.liu.se/c/c-faq/c-2.html

Viele Grüße

Bernd
Gespeichert

BL1
Jr. Member
**
Offline Offline

Beiträge: 82


Profil anzeigen
« Antworten #3 am: Juli 23, 2011, 16:34:49 »

Gut, Asche auf mein Haupt, die bootlader.c hab ich übersehen, weil in mein Projekt nicht eingebunden.

Ich hab's umgefriemt und es geht jetzt.

Da aber vor dem Problem nachdem Problem ist, hier gleich noch so'n Ding:

Ich bringe meine Daten via I2C in den Buffer und schribe dann diesen Buffer in den Flash. Da ich gelesen habe, dass man vor dem Überschreiben der Flash-Speicherzellen dieselben erts löschen sollte(?), habe ich die Erase-Sequenz einfach zwischenkopiert.
Code:
void flash_memory_write (uns16 address, unsigned char *data )
{
unsigned char wdi,x;

EEADRL = address.low8; // load address
EEADRH = address.high8; // load address
for (wdi=0;wdi<14;wdi+=2)
{
CFGS = 0; // access FLASH program, not config
WREN = 1; // allow program/erase
EEPGD = 1; // access program space FLASH memory
FREE = 1; // perform an erase on next WR command, cleared by hardware
EECON2 = 0x55; // required sequence
EECON2 = 0xAA; // required sequence
WR = 1; // set WR to begin erase cycle
WREN = 0; // disallow program/erase
#asm
NOP
NOP
#endasm
Carry = 0;
EEADRL++;
if (Carry)
EEADRH++;
}

EECON1 = 0;

EEADRL = address.low8; // load address
EEADRH = address.high8; // load address

for (wdi=0;wdi<14;wdi+=2)
{
x = wdi;

EEDATH = (&data+x) - 0x29;
x = wdi+1;
EEDATL = (&data+x) - 0x29;

EEPGD = 1; // access program space FLASH memory
CFGS = 0; // access FLASH program, not config
WREN = 1; // allow program/erase
LWLO = 1; // only load latches
EECON2 = 0x55;
EECON2 = 0xAA;


WR = 1; // set WR to begin write
#asm
NOP
NOP
#endasm
Carry = 0;
EEADRL++;
if (Carry)
EEADRH++;
}

EEDATH = data[14] - 0x29;
EEDATL = data[15] - 0x29;
EEPGD = 1; // access program space FLASH memory
CFGS = 0; // access FLASH program, not config
WREN = 1; // allow program/erase

LWLO = 0; // this time start write
EECON2 = 0x55;
EECON2 = 0xAA;
WR = 1; // set WR to begin write
#asm
NOP
NOP
#endasm


WREN = 0; // disallow program/erase

}
Was ich nun nicht versteh, ist dass ich die Daten bevor sie in den Flash kommen, immer erst mit 0x29 subtrahieren muß. Mit anderen Worten, addiert das Ding diese 0x29 immer fröhlich drauf. Zumindest ist das mit Testdaten(0x01 02 03 04 .. 0F) so. Richtigen Code zu brennen, hab ich mir noch nicht getraut.



BL
Gespeichert
BL1
Jr. Member
**
Offline Offline

Beiträge: 82


Profil anzeigen
« Antworten #4 am: Juli 23, 2011, 18:05:29 »

Da ist noch so' Ding.

Ich habe zum Test eine kleine Funktion auf die Adresse 0x400 im Flash geschrieben. Diese Geschichte kompiliert und siehe da, das steht im ProgrammMemory auf auf 0x400. Wenn ich jetzt im MPLAB exportiere und angebem er soll Programmspeicher exportieren und zwar von 0x0400 bis 0x0410, kommt da an:
Code:
:020000040000FA
:100800002000DD0A0319DE0A01305D02FF305E3B85
:10081000031C0C2C0D170D2C0D130800FF3FFF3F80
:02082000FF3F98
:00000001FF

Da steht ja nun in der ersten Zeile die richtige Adresse 0400. Ab Zeile 2 steht aber Adresse 0x0800. Das eht doch dann in die Hose.
Wie kriege ich denn nun die richtigen Bytes auf die richtige Adresse?



BL
Gespeichert
BL1
Jr. Member
**
Offline Offline

Beiträge: 82


Profil anzeigen
« Antworten #5 am: Juli 24, 2011, 10:19:26 »

Exportiere ich das
Code:
1024   3FF     3FFF                          MOVWI [-1]FSR1                         
  1025   400     0020 BlinkLED                 MOVLB 0                               
  1026   401     0ADD                          INCF counter, F                       
  1027   402     1903                          BTFSC STATUS, 0x2                     
  1028   403     0ADE                          INCF counter_e1, F                     
  1029   404     3001                          MOVLW 0x1                             
  1030   405     025D                          SUBWF counter, W                       
  1031   406     30FF                          MOVLW 0xff                             
  1032   407     3B5E                          SUBWFB counter_e1, W                   
  1033   408     1C03                          BTFSS STATUS, 0                       
  1034   409     2C0C                          GOTO m033                             
  1035   40A     170D                          BSF PORTB, 0x6                         
  1036   40B     2C0D                          GOTO m034                             
  1037   40C     130D m033                     BCF PORTB, 0x6                         
  1038   40D     0008 m034                     RETURN                                 
unter der Angabe dass ich eigentlich die Adressen 0x200 bis 0x230 exportieren will,
kommt das im hex-File an:
Code:
:020000040000FA
:1004000020000D150800FF3F08002000FF01FF013C
:10041000A0307F020F307F3B0318132A0000FF0A31
:100420000319FF0A082A04308D06062ACF309500EA
:10043000031A212A64007608F50029082000CD005F
:10044000222A281264006A30210099006F3084004B
:100450002130850000301B00851A2B2A85001B00E7
:02046000041A7C
:00000001FF
Nun müßte doch in Zeile 2 nach dem Doppelpunkt stehen: 16 Byte Daten; Adresse 0x0400; 0x00=Datarecord und dann 16Byte Programmcode(die CRC lassen wir erstmal weg).
Code:
20
00
0D
15
08
00
FF
3F
08
00
20
00
FF
01
FF
01
Das hat doch aber mit dem Ausschnitt oben aus dem Programmspeicher herzlich wenig zu tun.

Wie macht Ihr denn das?


BL


* scsh1.jpg (161.83 KB, 1680x1050 - angeschaut 54 Mal.)
Gespeichert
Bernd
Globaler Moderator
Hero Member
*****
Offline Offline

Beiträge: 3815



Profil anzeigen
« Antworten #6 am: Juli 24, 2011, 14:28:54 »

Zitat
Was ich nun nicht versteh, ist dass ich die Daten bevor sie in den Flash kommen, immer erst mit 0x29 subtrahieren muß. Mit anderen Worten, addiert das Ding diese 0x29 immer fröhlich drauf. Zumindest ist das mit Testdaten(0x01 02 03 04 .. 0F) so. Richtigen Code zu brennen, hab ich mir noch nicht getraut.

Code:
EEDATH = (&data+x) - 0x29;

Damit wird EEDATH die Adresse des Zeigers data zugewiesen und nicht der Wert der Speicherstelle, auf den er zeigt. Höchstwahrscheinlich hat der Zeiger data die Adresse 0x30 im RAM, was für den ungünstig gewählten Testfall zufällig ein „richtiges“ Ergebnis liefert. Erzeugt der Compiler dafür keine Warnung der Art „assignment makes integer from pointer without a cast“?

Korrekter Code wäre:

Code:
EEDATH = *(data+x);

Zitat
Das hat doch aber mit dem Ausschnitt oben aus dem Programmspeicher herzlich wenig zu tun.

Die „Adressverdopplung“ im Hex-File ist normal und richtig. In der Ansicht „Program Memory“ verwendet MPLAB die Adresse eine Programm-Words (14 Bit). Im Hex-File gibt es nur Byte-Adressen, d.h. ein Programm-Word an der Adresse 0x0 wird im Hex-File an den Byte-Adressen 0x0 und 0x1 gespeichert, ein Programm-Word an der Adresse 0x1 wird in den Byte-Adressen 0x2 und 0x3 gespeichert usw.

Wenn nun in MPLAB der Bereich von 0x200 bis 0x230 als Hex-File exportiert wird, erhält man den Inhalt der Word-Adressen 0x200 bis 0x230 im Hex-File an den Byte-Adressen 0x400 bis 0x460.

Die Daten des generierten HEX-Files mußt du somit mit dem „Program Memory“ an den Adressen 0x200 bis 0x230 vergleichen.


Viele Grüße

Bernd 
Gespeichert

BL1
Jr. Member
**
Offline Offline

Beiträge: 82


Profil anzeigen
« Antworten #7 am: Juli 24, 2011, 16:29:29 »

Damit wird EEDATH die Adresse des Zeigers data zugewiesen und nicht der Wert der Speicherstelle, auf den er zeigt. Höchstwahrscheinlich hat der Zeiger data die Adresse 0x30 im RAM, was für den ungünstig gewählten Testfall zufällig ein „richtiges“ Ergebnis liefert. Erzeugt der Compiler dafür keine Warnung der Art „assignment makes integer from pointer without a cast“?

Korrekter Code wäre:

Code:
EEDATH = *(data+x);

Naja, da hätte ich auch selber drauf müßt komm. Herzlichen Dank! Wobei der Compiler an der Stelle nicht meckert. Ich nehm ihn aber trotzdem weiter. Wobei mir die Gene '*' und '&' nicht zu verwechseln wohl nicht mehr wachsen.

Die „Adressverdopplung“ im Hex-File ist normal und richtig. In der Ansicht „Program Memory“ verwendet MPLAB die Adresse eine Programm-Words (14 Bit). Im Hex-File gibt es nur Byte-Adressen, d.h. ein Programm-Word an der Adresse 0x0 wird im Hex-File an den Byte-Adressen 0x0 und 0x1 gespeichert, ein Programm-Word an der Adresse 0x1 wird in den Byte-Adressen 0x2 und 0x3 gespeichert usw.

Wenn nun in MPLAB der Bereich von 0x200 bis 0x230 als Hex-File exportiert wird, erhält man den Inhalt der Word-Adressen 0x200 bis 0x230 im Hex-File an den Byte-Adressen 0x400 bis 0x460.

Die Daten des generierten HEX-Files mußt du somit mit dem „Program Memory“ an den Adressen 0x200 bis 0x230 vergleichen.
Das wußte ich so wiederum noch nicht. Das heißt doch aber, man muß die Adress-Werte aus dem hex-File erst halbieren, bevor man sie in den Flash schreibt.


BL
Gespeichert
Seiten: [1] Nach oben Drucken 
« vorheriges nächstes »
Gehe zu:  

Powered by MySQL Powered by PHP Made for Mozilla (Firefox) Made for Internet Explorer
Seite erstellt in 0.049 Sekunden mit 18 Zugriffen.
 
Top! Top!