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 oder uint16_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 Lesefunktion unsigned short[]/c], aber verwendest einen [c]unsigned int für die Referenzierung? Warum multiplizierst du adr 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 du write_eeprom einen unsigned char* übergibst, wenn ein unsigned 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 ich printf 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;
    }
    

Anmelden zum Antworten