Struct Array in bestimmten Speicherbereich ablegen
-
also die Daten im EEProm sind defintiv richtig:
Uart_SendString(debugUart,"\nErgebnis EEprom read:\n"); for(z=0; z<108; z++) { read_eeprom(z); Uart_SendBin2Asci(debugUart,z, DEC, '0',3); Uart_SendString(debugUart,","); } Uart_SendString(debugUart,"\n");
Ergibt:
Ergebnis EEprom read: 000,001,002,003,004,005,006,007,008,009,010,011,012,013,014,015,016,017,018,019,020,021,022,023,024,025,026,027,028,029,030,031,032,033,034,035,036,037,038,039,040,041,042,043,044,045,046,047,048,049,050,051,052,053,054,055,056,057,058,059,060,061,062,063,064,065,066,067,068,069,070,071,072,073,074,075,076,077,078,079,080,081,082,083,084,085,086,087,088,089,090,091,092,093,094,095,096,097,098,099,100,101,102,103,104,105,106,107,
Also funktioniert der Write-Befehl korrekt.
Ich habe mir auch mal die Mühe gemacht:
for(z=0; z<10; z++) { Uart_SendString(debugUart,"Channel="); Uart_SendBin2Asci(debugUart,PPG[z].Channel , DEC, '0',5); Uart_SendString(debugUart,", Status="); Uart_SendBin2Asci(debugUart,PPG[z].Status , DEC, '0',5); Uart_SendString(debugUart,", Strom="); Uart_SendBin2Asci(debugUart,PPG[z].Strom , DEC, '0',5); Uart_SendString(debugUart,", Period="); Uart_SendBin2Asci(debugUart,PPG[z].Period , DEC, '0',5); Uart_SendString(debugUart,", Duty100="); Uart_SendBin2Asci(debugUart,PPG[z].Duty100 , DEC, '0',5); Uart_SendString(debugUart,", Duty50="); Uart_SendBin2Asci(debugUart,PPG[z].Duty50 , DEC, '0',5); Uart_SendString(debugUart,", Duty1="); Uart_SendBin2Asci(debugUart,PPG[z].Duty1 , DEC, '0',5); Uart_SendString(debugUart,"\n"); }
einmal mit und einmal ohne Schleife also 9 * hintereinander den ganzen Block geschrieben und für 'z' echte Zahlen in jeden Block geschrieben. Das Ergebnis ist das gleiche:
Ergebnis EEprom read: z=00000 Channel=00000, Status=00001, Strom=00770, Period=01284, Duty100=01798, Duty50=02312, Duty1=02826 z=00001 Channel=00012, Status=00013, Strom=03854, Period=04368, Duty100=04882, Duty50=05396, Duty1=05910 z=00002 Channel=00012, Status=00013, Strom=03854, Period=04368, Duty100=04882, Duty50=05396, Duty1=05910 z=00003 Channel=00024, Status=00025, Strom=06938, Period=07452, Duty100=07966, Duty50=08480, Duty1=08994 z=00004 Channel=00024, Status=00025, Strom=06938, Period=07452, Duty100=07966, Duty50=08480, Duty1=08994 z=00005 Channel=00036, Status=00037, Strom=10022, Period=10536, Duty100=11050, Duty50=11564, Duty1=12078 z=00006 Channel=00036, Status=00037, Strom=10022, Period=10536, Duty100=11050, Duty50=11564, Duty1=12078 z=00007 Channel=00048, Status=00049, Strom=13106, Period=13620, Duty100=14134, Duty50=14648, Duty1=15162 z=00008 Channel=00048, Status=00049, Strom=13106, Period=13620, Duty100=14134, Duty50=14648, Duty1=15162
Also müsste der Fehler doch irgendwo hier liegen:
typedef struct PPG_Setup_Data { // Länge 12 Byte char Channel; char Status; short Strom; short Period; short Duty100; short Duty50; short Duty1; } Setup_PPG; __far Setup_PPG *PPG = (__far Setup_PPG*)0xDF4000;
-
Du gibst
z
aus, aber:dachschaden schrieb:
Hast du mal die gegenwärtige Adresse, auf die &PPG[z] zeigt, ausgegeben? Nur um sicherzugehen, dass er auch wirklich in 12-Byte-Schritten durchläuft.
Mich beschleicht das Gefühl, dass du bei jedem zweiten Schritten vorwärts einen Schritt zurück machst.
-
Kann das was damit zu tun haben das __far nicht allein stehen darf sondern nur mit (__far unsigned int*) im EEProm Code gibt es nur __far mit unsigned int* nie alleine?
unsigned short read_eeprom(unsigned short adr) { return (*(__far unsigned int*) (0xDF4000 + adr * 2)); }
-
Code:
Uart_SendString(debugUart,"\nErgebnis EEprom read:\n"); for(z=0; z<9; z++) { Uart_SendString(debugUart,"z="); Uart_SendBin2Asci(debugUart,z , DEC, '0',5); Uart_SendString(debugUart,", ADR:0x"); Uart_SendBin2Asci(debugUart,&PPG[z] , HEX, '0',6); Uart_SendString(debugUart," Channel="); Uart_SendBin2Asci(debugUart,PPG[z].Channel , DEC, '0',5); Uart_SendString(debugUart,", Status="); Uart_SendBin2Asci(debugUart,PPG[z].Status , DEC, '0',5); Uart_SendString(debugUart,", Strom="); Uart_SendBin2Asci(debugUart,PPG[z].Strom , DEC, '0',5); Uart_SendString(debugUart,", Period="); Uart_SendBin2Asci(debugUart,PPG[z].Period , DEC, '0',5); Uart_SendString(debugUart,", Duty100="); Uart_SendBin2Asci(debugUart,PPG[z].Duty100 , DEC, '0',5); Uart_SendString(debugUart,", Duty50="); Uart_SendBin2Asci(debugUart,PPG[z].Duty50 , DEC, '0',5); Uart_SendString(debugUart,", Duty1="); Uart_SendBin2Asci(debugUart,PPG[z].Duty1 , DEC, '0',5); Uart_SendString(debugUart,"\n"); }
Ausgabe:
Ergebnis EEprom read: z=00000, ADR:0xDF4000 Channel=00000, Status=00001, Strom=00770, Period=01284, Duty100=01798, Duty50=02312, Duty1=02826 z=00001, ADR:0xDF400C Channel=00012, Status=00013, Strom=03854, Period=04368, Duty100=04882, Duty50=05396, Duty1=05910 z=00002, ADR:0xDF4018 Channel=00012, Status=00013, Strom=03854, Period=04368, Duty100=04882, Duty50=05396, Duty1=05910 z=00003, ADR:0xDF4024 Channel=00024, Status=00025, Strom=06938, Period=07452, Duty100=07966, Duty50=08480, Duty1=08994 z=00004, ADR:0xDF4030 Channel=00024, Status=00025, Strom=06938, Period=07452, Duty100=07966, Duty50=08480, Duty1=08994 z=00005, ADR:0xDF403C Channel=00036, Status=00037, Strom=10022, Period=10536, Duty100=11050, Duty50=11564, Duty1=12078 z=00006, ADR:0xDF4048 Channel=00036, Status=00037, Strom=10022, Period=10536, Duty100=11050, Duty50=11564, Duty1=12078 z=00007, ADR:0xDF4054 Channel=00048, Status=00049, Strom=13106, Period=13620, Duty100=14134, Duty50=14648, Duty1=15162 z=00008, ADR:0xDF4060 Channel=00048, Status=00049, Strom=13106, Period=13620, Duty100=14134, Duty50=14648, Duty1=15162
Adresspointer sind also auch richtig
-
Wieso verwendest du nicht direkt Typen wie
uint8_t
oderuint16_t
? Warum packst du die Werte im Typen nicht in ein Array?#include <stdint.h> typedef struct { uint8_t fields_1[2]; /*Channel, Status*/ uint16_t fields_2[5]; /*Strom, Period, Duty100, Duty50, Duty1*/ }Setup_PPG;
Warum hast du nicht direkt auch ein paar Debug-Strings?
const char*const debug_strings_fields_1[] = { "Channel=", ", Status=" }; const char*const debug_strings_fields_2[] = { ", Strom=", ", Period=", ", Duty100=", ", Duty50=", ", Duty1=" };
Warum hast du kein Makro, mit dem du die Elemente in einem Array erhältst?
#define ARRAY_SIZE(array) ((sizeof(array) / sizeof((array)[0])))
Warum packst du die Ausgabe des Objekts nicht direkt in eine Funktion?
void print_eeprom(__far Setup_PPG*tmp_PPG) { uint16_t i; for(i = 0;i < ARRAY_SIZE(tmp_PPG->fields_1);i++) printf("%s%u",debug_strings_fields_1[i],tmp_PPG->fields_1[i]); for(i = 0;i < ARRAY_SIZE(tmp_PPG->fields_2);i++) printf("%s%u",debug_strings_fields_2[i],tmp_PPG->fields_2[i]); puts(""); }
Was ist die Größe eines
unsigned int
auf deiner Plattform? Warum ist dein Rückgabetyp für deine Lesefunktionunsigned short[]/c], aber verwendest einen [c]unsigned int
für die Referenzierung? Warum multiplizierst duadr
mit 2, anstatt ordentlich zu indizieren?uint16_t read_eeprom(uint16_t index) { __far uint16_t*tmp = (__far uint16_t*)PPG; return tmp[index]; }
Wieso postest du den Code zu
write_eeprom
nicht? Warum erhältst du keine Fehlermeldung beim Kompilieren, dass duwrite_eeprom
einenunsigned char*
übergibst, wenn einunsigned short*
erwartet wird?Auf keine diese Fragen möchte ich ein "Weiß ich nicht" sehen.
Deine Lese-Funktion liest 2-Byte-Werte - deine Ausgabe:
000,001,002,003,004,005,006 ...
Bedeutet also, dass dein EEPROM folgendes Muster hat:
0x00,0x00,0x01,0x00,0x02,0x00,0x03,0x00
Aber deine Ausgabe:
z=00000, ADR:0xDF4000 Channel=00000, Status=00001, Strom=00770, Period=01284, Duty100=01798, Duty50=02312, Duty1=02826
Zeigt eher, dass dein EEPROM so aussieht:
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07
Sprich, die Funktion, die die Daten schreibt, macht dies Byte-weise, nicht 2-Byte-Weise. Das passt nicht aber zu der Ausgabe deines EEPROM.
Ich habe mal den ganzen Scheiß versucht, nachzubauen:
#include <sys/mman.h> #include <stdint.h> #include <stdio.h> #include <string.h> typedef struct { uint8_t fields_1[2]; /*Channel, Status*/ uint16_t fields_2[5]; /*Strom, Period, Duty100, Duty50, Duty1*/ }Setup_PPG; Setup_PPG*PPG; #define STATIC_ADDR (0xDF0000) #define STATIC_LEN (0x4000) const char*const debug_strings_fields_1[] = { "Channel=", ", Status=" }; const char*const debug_strings_fields_2[] = { ", Strom=", ", Period=", ", Duty100=", ", Duty50=", ", Duty1=" }; #define ARRAY_SIZE(array) ((sizeof(array) / sizeof((array)[0]))) void eeprom_write(uint16_t index,uint16_t len,const uint8_t*data) { uint16_t*tmp = (uint16_t*)PPG; uint16_t i; for(i = 0;i < len;i++) tmp[index + i] = data[i]; } uint16_t eeprom_read(uint16_t index) { uint16_t*tmp = (uint16_t*)PPG; return tmp[index]; } const uint8_t Test[9][12] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,100,101,102,103,104,105,106,107 }; void eeprom_print(Setup_PPG*tmp_PPG) { uint16_t i; for(i = 0;i < ARRAY_SIZE(tmp_PPG->fields_1);i++) { printf("%s%05u",debug_strings_fields_1[i],tmp_PPG->fields_1[i]); } for(i = 0;i < ARRAY_SIZE(tmp_PPG->fields_2);i++) { printf("%s%05u",debug_strings_fields_2[i],tmp_PPG->fields_2[i]); } puts(""); } int main(void) { uint16_t i,j; PPG = mmap((void*)STATIC_ADDR,STATIC_LEN,PROT_READ | PROT_WRITE,MAP_PRIVATE | MAP_ANONYMOUS,-1,0); if(MAP_FAILED == PPG) { printf("Konnte Mapping nicht anlegen"); return 1; } for(i = 0;i < ARRAY_SIZE(Test);i++) eeprom_write(i * sizeof(Test[i]),sizeof(Test[i]),Test[i]); for(i = 0;i < ARRAY_SIZE(Test);i++) eeprom_print(&PPG[i]); for(i = 0;i < 108;i++) { if(!(i % sizeof(Test[i]))) puts(""); printf("%03d|",eeprom_read(i)); } puts(""); munmap(PPG,STATIC_LEN); return 0; }
Die einzigen Unterschiede sind, dass ich keine
__far
-Zeiger nutzen muss (wegen linearem Adressraum) und ichprintf
verwenden kann. Und ich kann dein Problem nicht nachvollziehen:Channel=00000, Status=00000, Strom=00001, Period=00002, Duty100=00003, Duty50=00004, Duty1=00005 Channel=00006, Status=00000, Strom=00007, Period=00008, Duty100=00009, Duty50=00010, Duty1=00011 Channel=00012, Status=00000, Strom=00013, Period=00014, Duty100=00015, Duty50=00016, Duty1=00017 Channel=00018, Status=00000, Strom=00019, Period=00020, Duty100=00021, Duty50=00022, Duty1=00023 Channel=00024, Status=00000, Strom=00025, Period=00026, Duty100=00027, Duty50=00028, Duty1=00029 Channel=00030, Status=00000, Strom=00031, Period=00032, Duty100=00033, Duty50=00034, Duty1=00035 Channel=00036, Status=00000, Strom=00037, Period=00038, Duty100=00039, Duty50=00040, Duty1=00041 Channel=00042, Status=00000, Strom=00043, Period=00044, Duty100=00045, Duty50=00046, Duty1=00047 Channel=00048, Status=00000, Strom=00049, Period=00050, Duty100=00051, Duty50=00052, Duty1=00053 000|001|002|003|004|005|006|007|008|009|010|011| 012|013|014|015|016|017|018|019|020|021|022|023| 024|025|026|027|028|029|030|031|032|033|034|035| 036|037|038|039|040|041|042|043|044|045|046|047| 048|049|050|051|052|053|054|055|056|057|058|059| 060|061|062|063|064|065|066|067|068|069|070|071| 072|073|074|075|076|077|078|079|080|081|082|083| 084|085|086|087|088|089|090|091|092|093|094|095| 096|097|098|099|100|101|102|103|104|105|106|107|
Wie sieht deine
write_eeprom
-Routine aus?
-
Also das ist eine 16 Bit MCU und die Bibliothek <stdint.h> hat er leider nicht und somit auch kein uint8_t etc.
Das Teil hat nur sehr wenig Flash/RAM deshalb muss alles recht "einfach" gehalten werden...
Deine Lese-Funktion liest 2-Byte-Werte - deine Ausgabe:
Code:
000,001,002,003,004,005,006 ...Das ist nur ein Trick, er liest ab Adresse0 2 Byte aber ins char passt ja nur eins davon. Dann liest er ab Adresse1 2 Bytes also quasi mittendrin und so weiter...
Hier die write_eeprom: Das mit den zwei Sektoren hat nichts mit dem Problem zu tun und kann ignoriert werden!
unsigned char write_eeprom(unsigned short adr, unsigned short len, unsigned short *data) { volatile unsigned short i, j, wdata; unsigned char error; volatile unsigned long fadr1, fadr2, fvalid; // check which sector is valid if (*(__far unsigned int*)(Sektor2 + 0x1FFE) == 0x0000) { // read from Sektor1 and write to Sektor2 Uart_SendString(2,"\nSektor 1 read, Sektor 2 write\n"); fadr1 = Sektor1; fadr2 = Sektor2; fvalid = Sektor1 + 0x1FFE; } else { // read from Sektor2 and write to Sektor1 Uart_SendString(2,"\nSektor 2 read, Sektor 1 write\n"); fadr1 = Sektor2; fadr2 = Sektor1; fvalid = Sektor2 + 0x1FFE; } for (i = 0; i < len ; i++) { wdata = (*(__far unsigned int*) (fadr1+(adr+i)*2) | data[i]); // Da nur Nullen o. löschen geschrieben werden können beide Werte mit OR verkn. und wenn der Wert nicht größer als die Flashdaten sind ist es möglich if (wdata > (*(__far unsigned int*) (fadr1+(adr+i)*2))) { // Daten können nicht ohne EEprom zu löschen geschrieben werden! if (*(__far unsigned int*)(fadr2 + 0x1FFE) != 0xFFFF) { // Erase SECTOR to be written error = Main_Flash_sector_erase(fadr2); // erase Sector } else { Uart_SendString(2,"\nSektor nicht geloescht!"); } // Write valid flag of old SECTOR: 1st step error = Main_Flash_write(fvalid, 0x00FF); j = 0; i = 0; for (i = 0; i < EEPROM_size; i+=2) { // count word-wise if ((i >= ((adr*2)+len*2)) || (i < adr * 2)) { wdata = (*(__far unsigned int*) (fadr1 + i)); // copy data } else { wdata = data[j]; // new data j++; } error = Main_Flash_write(fadr2 + i, wdata); } // Overwrite valid flag of old SECTOR: 2nd step error = Main_Flash_write(fvalid, 0x0000); return error; } else if (*(__far unsigned int*) (fadr1+(adr+i)*2) != data[i]) { // Daten können OHNE EEprom löschen geschrieben werden error = Main_Flash_write(fadr1 + (adr+i)*2, data[i]); } } return error; }