Hallo zusammen, benötige mal die Hilfe eines ARM7 bzw. C-Experten: Ich arbeite mit dem Keil Evakuation-Board mit dem 2368 von NXP und der Keil MDK Versiuon 4.03. In meiner Software habe ich die Wahl, aus Kompatibilitätsgründen Daten über den I2C-Bus in ein externes RAM oder in den FLASH des Controllers zu schreiben. Das Schreiben und Lesen ins RAM funktioniert einwandfrei, der CRC wird richtig berechnet. Das Speichern und Auslesen ins und aus dem FLASH funktioniert ebenfalls einwandfrei, nur bei der Berechnung des CRC nach dem Auslesen erhalte ich ein falsches Ergebnis und weiß nicht, weshalb. Die Daten werden richtig geschrieben und auch wieder ausgelesen (jedenfalls lt. Debugger). Wenn ich den CRC 5 mal berechnen lasse, erhalte ich 3 unterschiedliche Ergebnisse. Ich benutze haargenau die gleiche Routine und die gleichen Buffer. Im Flash werden keine Daten versehentlich überschrieben oder gelöscht. Auch stehen sie im Memory-Bereich an der richtigen Adresse. (Sie werden ja richtig ausgelesen.) Wo ist der sch... Fehler? Hat jemand eine Idee? Bin für jeden Hinweis oder Tip dankbar! Freundlicher Gruß Roland Hier mein Code (Auszüge): #define START_ADRESS_DATA 0x00010000 // Startadresse Flashdaten #define numFlash 512 // Blockgröße, Anzahl Bytes zum Schreiben int i; unsigned char rec_buf[numFlash]; unsigned char send_buf[numFlash]; long crc, crc_read; for (i=0;i<236;i++) // den Sendebuffer vorbesetzen { send_buf[i]=(unsigned char) i; } send_buf[236]=0x00; crc=crc32i(&send_buf[1],236); // CRC bis Byte 235 berechnen, Routine ist i.O. send_buf[237]=(char)((crc >> 24)& 0xFF); // CRC anhängen send_buf[238]=(char)((crc >> 16)& 0xFF); // statt char > unsigned char einstellen bringt nichts send_buf[239]=(char)((crc >> 8)& 0xFF); send_buf[240]=(char)(crc & 0xFF); // hier die Daten über den I2C-Bus ins RAM schreiben, funktioniert einwandfrei send_to_ram(send_buf); // Daten ins RAM schreiben read_from_ram (rec_buf); // Daten aus RAM in rec_buf schreiben crc=crc32i(&rec_buf[1],236); // CRC vom 1. Wert (nicht vom 0ten!) über 235 Bytes // berechnen crc_read= rec_buf[237]; crc_read=(crc_read<<8) | rec_buf[238]; crc_read=(crc_read<<8) | rec_buf[239]; crc_read=(crc_read<<8) | rec_buf[240]; // Beim Vergleich stimmen die CRCs überein, alles i.o. if(crc!=crc_read) // CRCs stimmen nicht überein { // Fehlerroutine } // Jetzt die Routine zum Schreiben ins Flash void write_flash(unsigned long FLASH_adr,unsigned char *buf) { prepare_sector(GetSecNum (FLASH_adr),GetSecNum (FLASH_adr+numFlash)); if(result[0]!=CMD_SUCCESS) while(1); command[0] = 51; command[1] = FLASH_adr; command[2] = (unsigned long)buf; command[3] = numFlash; command[4] = cclock; dis_interrupt(); // Interrupts disablen iap_entry(command,result); en_interrupt(); } void write_parm_to_flash() // { erase_sector(GetSecNum (START_ADRESS_DATA),GetSecNum (START_ADRESS_DATA+numFlash)); write_flash(START_ADRESS_DATA, send_buf); } // und die Daten wieder einlesen for(i=0; i<241; i++) // aus Flash auslesen { rec_buf[i]=*((unsigned char*)START_ADRESS_DATA+i); // ab Adresse } // Die eingelesenen Werte im rec_buf stimmen mit denen im Sendepuffer überein // Und jetzt kommts! crc=crc32i(&rec[1],236); // Hier wird der CRC falsch berechnet!!!!!!!!!! // Wenn ich den CRC 5 mal berechnen lasse, erhalte ich 3 unterschiedliche Werte crc_read= rec_buf[237]; // Werte im Buffer sind in Ordnung!!! crc_read=(crc_read<<8) | rec_buf[238]; crc_read=(crc_read<<8) | rec_buf[239]; crc_read=(crc_read<<8) | rec_buf[240]; if(crc!=crc_read) // hier stimmen dire CRCs nicht überein { // Fehlerroutine } // Die Werte in crc_read sind die gleichen, wie die ins Flash geschriebenen // wurden. Die sind mit den Werten in der Routine zum Schreiben ins RAM // absolut identisch. Der CRC wird am Anfang also richtig berechnet. // Hier die Routine zum Brechnen des CRC; ich habe bereits eine andere //Routine verwendet, das Ergebnis ist das gleiche. unsigned long crc32i(unsigned char *txt,int l) // Berechnung der Checksumme { int i,j; int hbit,bit; unsigned long crc32=0xffffffff; for (i=0;i<l;i++) { for (j=0x01;j<=0x80;j=j<<1) { bit =(txt[i] & j) ? 1 :0; hbit=(crc32 & 0x01) ? 1 : 0; if (hbit != bit) crc32=(crc32>>1) ^ CRC32POLY; else crc32=crc32>>1; } } return (crc32^0xffffffff); }
Hmm, schwierig. Ich würde mir zwei Kanarienvögelchen beschaffen, die den Bereich abgrenzen, über den die CRC berechnet wird. Vielleicht liest du über den eigentlichen 236 Byte großen Bereich hinaus und der Unterschied ist dadurch zu erklären, dass in der verbotenen Zone einmal Nullen stehen (unsigned char rec_buf[numFlash]; unsigned char send_buf[numFlash]; sind initialisiert?) oder eine eingetragene CRC. hbit, bit und j würde ich unsigned char definieren und nicht int. Wie ist das technisch mit dem Lesen aus dem externen Flash? Die Daten sind zum Zeitpunkt der CRC Berechnung garantiert alle gelesen, da hängen nicht noch Daten in der Leitung, die beim schnellen Ablauf den Anschluss verpassen aber beim langsamen Debuggen Zeit hatten einzutrudeln?
Stefan B. schrieb: > hbit, bit und j würde ich unsigned char definieren und nicht int. Du hast zu viel mit 8-Bittern programmiert. Bei grösseren Maschinchen ist das ineffizient.
Effizient wird das erst wenn der CRC byteweise berechnet wird, mit einer Tabelle.
Wenn du das über 235 Bytes berechnen willst, warum schreibst du dann 236?
Juergen schrieb: > Effizient wird das erst wenn der CRC byteweise berechnet wird, mit einer > Tabelle. Erst einmal wird es so schneller. Ob effizienter hängt davon ab, worauf es dem Programmierer dabei ankommt. Platz oder Zeit. Ausserdem gibt es neben der algorithmischen Effizienz auch eine des Compilers. Registervariablen sind als Maschinenworte effizienter umgesetzt, kleinere Datentypen können zu zusätzlichem Code führen, ohne Nutzen.
Ich hatte mich an unsigned char *txt orientiert und die Effizienz erstmal aussen vor gelassen.
Hallo Stefan, danke für Deine Antwort. Ein Lesen über die Buffergrenzen hinaus findet nicht statt. Habe ich kontrolliert. Der I2C-Buffer als auch der Flashbuffer sind beide gleich als 'unsigned char flash_buf[512] oder 'unsigned char i2c_buf[256] definiert. Und bei I2C funktionierts ja. Aber Dein Tip mit dem Timing-Problem klingt interessant. Werde da mal ein Delay einbauen: Gruß Roland
Hallo Juergen weil die CRC-Routine <236 berechnet. >>>>>>>>>>>>>>>>>>>>> unsigned long crc32i(unsigned char *txt,int l) // Berechnung der Checksumme { for (i=0;i<l;i++) { >>>>>>>>>>>>>>>>>> hier steht '<l' also <236, sind in C 235. Gruß Roland
>> // Und jetzt kommts! >> crc=crc32i(&rec[1],236); // Hier wird der CRC falsch Hmmm, muesste da nicht rec_buf stehen? VG, Hans
> for (i=0;i<l;i++) > hier steht '<l' also <236, sind in C 235. Da du bei 0 anfängst, sind es 236.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.