Ich verwende den PIC24fj256ga702-Controller in meinem Projekt. Ich wollte einige Byte-Daten in einem nichtflüchtigen Speicher speichern, falls es zu einem Stromausfall kommt.
Also habe ich einige Funktionen nach http://microchipdeveloper.com/16bit:flash-write geschrieben
#define pagelength 1024 //page 42, one erase block 1024 instruction words
#define rowlength 128 //one write block = 128 instruction words.
/*
* program memory upper boundary (instruction words) 0x02AFFE,
* +2, i.e. 0x02B000, start of address
* page length 1024 instruction words(erase block)
* write block 128 instruction block; 255 bytes.
*/
#define address 0x2B002 // might have less than 255 blocks for writing data
uint8_t Rambuffer[pagelength * 2];
uint8_t Rowbuffer[rowlength * 2]; //one row of data, that can be written once. 255 bytes.
void readFlashPage(void)
{
int offset, i;
TBLPAG = __builtin_tblpage (address); //returns the page number of the memory address received as a parameter. For table instructions the returned value is placed in TBLPAG
offset = __builtin_tbloffset (address); //returns the offset from the base address for a memory location whose address is passed as a parameter. The return value of this function is passed as a parameter to table read and table write instructions
offset = offset & 0xF800; //set to the base of page
for(i = 0; i<(pagelength * 2); i++){
Rambuffer[i++] = __builtin_tblrdl(offset); //returns the lower 16 bits of the memory address specified by TBLPAG and the offset parameter(calls TBLRDL instruction)
Rambuffer[i] = __builtin_tblrdh(offset); //returns the upper 8-bits of the memory adddress specified by TBLPAG and the offset parameter(calls TBLRDL instruction)
offset = offset + 2;
}
}
void eraseFlashPage(void){
int offset;
NVMADRU = __builtin_tblpage(address);
offset = __builtin_tbloffset(address);
NVMADR = (offset & 0xF800); // for page size of 1024 PM words
//set WREN and page Erase in NVMCON
NVMCON = 0x4003;
__builtin_disi(6); //disable interrupts for next six instructions
__builtin_write_NVM(); //intiate write process
}
void rowFlashWrite(void){
int offset, i;
TBLPAG = 0xFA; // base address of write latches 0xFA0000h till 0xFA00FEh
//load row of data into write latches
offset = 0;
for (i = 0; i < rowlength * 2 ; i++){
__builtin_tblwtl(offset, Rowbuffer[i++]);
__builtin_tblwth(offset, Rowbuffer[i]);
offset+=2;
}
//set the destination address into the NVM address registers
NVMADRU = __builtin_tblpage(address);
offset = __builtin_tbloffset(address);
NVMADR = (offset & 0xF800); // for page size of 1024 PM words
//set WREN and enable row write in NVMCON
NVMCON = 0x4002;
__builtin_disi(6); // disable interrupts for 6 instruction cycles
__builtin_write_NVM(); // initate write process
}
void rowFlashRead(void){
int offset, i;
TBLPAG = __builtin_tblpage (address); //returns the page number of the memory address received as a parameter. For table instructions the returned value is placed in TBLPAG
offset = __builtin_tbloffset (address); //returns the offset from the base address for a memory location whose address is passed as a parameter. The return value of this function is passed as a parameter to table read and table write instructions
for(i = 0; i<(rowlength * 2); i++){
Rowbuffer[i++] = __builtin_tblrdl(offset); //returns the lower 16 bits of the memory address specified by TBLPAG and the offset parameter(calls TBLRDL instruction)
Rowbuffer[i] = __builtin_tblrdh(offset); //returns the upper 8-bits of the memory adddress specified by TBLPAG and the offset parameter(calls TBLRDL instruction)
offset = offset + 2;
}
}
aber ich erhalte diesen Fehler, wenn ich versuche, es zu erstellen
make -f nbproject/Makefile-default.mk SUBPROJECTS= .build-conf
make[1]: Entering directory 'C:/Users/HP/MPLABXProjects/Rollman/emulate.X'
make -f nbproject/Makefile-default.mk dist/default/production/emulate.X.production.hex
make[2]: Entering directory 'C:/Users/HP/MPLABXProjects/Rollman/emulate.X'
"C:\Program Files (x86)\Microchip\xc16\v1.35\bin\xc16-gcc.exe" main.c -o build/default/production/main.o -c -mcpu=24FJ256GA702 -MMD -MF "build/default/production/main.o.d" -mno-eds-warn -g -omf=elf -DXPRJ_default=default -legacy-libc -O0 -msmart-io=1 -Wall -msfr-warn=off
nbproject/Makefile-default.mk:155: recipe for target 'build/default/production/main.o' failed
make[2]: Leaving directory 'C:/Users/HP/MPLABXProjects/Rollman/emulate.X'
nbproject/Makefile-default.mk:90: recipe for target '.build-conf' failed
make[1]: Leaving directory 'C:/Users/HP/MPLABXProjects/Rollman/emulate.X'
nbproject/Makefile-impl.mk:39: recipe for target '.build-impl' failed
main.c: In function 'readFlashPage':
main.c:83:32: error: Argument to __builtin_tblpage() is not the address
of an object in a code, psv, or eedata section;
the object must not be qualified with any form of index
main.c:84:34: error: Argument to __builtin_tbloffset() is not the address
of an object in a code, psv, or eedata section;
the object must not be qualified with any form of index
main.c: In function 'eraseFlashPage':
main.c:95:32: error: Argument to __builtin_tblpage() is not the address
of an object in a code, psv, or eedata section;
the object must not be qualified with any form of index
main.c:96:33: error: Argument to __builtin_tbloffset() is not the address
of an object in a code, psv, or eedata section;
the object must not be qualified with any form of index
main.c: In function 'rowFlashWrite':
main.c:120:32: error: Argument to __builtin_tblpage() is not the address
of an object in a code, psv, or eedata section;
the object must not be qualified with any form of index
main.c:121:33: error: Argument to __builtin_tbloffset() is not the address
of an object in a code, psv, or eedata section;
the object must not be qualified with any form of index
main.c: In function 'rowFlashRead':
main.c:134:32: error: Argument to __builtin_tblpage() is not the address
of an object in a code, psv, or eedata section;
the object must not be qualified with any form of index
main.c:135:34: error: Argument to __builtin_tbloffset() is not the address
of an object in a code, psv, or eedata section;
the object must not be qualified with any form of index
make[2]: *** [build/default/production/main.o] Error 255
make[1]: *** [.build-conf] Error 2
make: *** [.build-impl] Error 2
BUILD FAILED (exit value 2, total time: 573ms)
Wird es dadurch behoben?
uint16_t address __attribute__ ((space(prog))) = 0x2B002;
und Übergabe von &Adresse an __builtin_tblpage ?
aber das space-Attribut wird verwendet, um den Compiler anzuweisen, eine Variable in bestimmten Speicherbereichen zuzuweisen, also kann das nicht korrekt sein?
Ich brauche hier wirklich etwas Hilfe.
Danke
PS auch, kannst du bitte den Code sehen und mir sagen, was ich falsch mache
Sie versuchen, Speicher zu verwenden, der nicht vorhanden ist.
Es gibt nur Flash unter der Adresse 0x2AFFE und Sie versuchen, auf 0x2B002 zuzugreifen.
Siehe Datenblatt Seite 42.
An Adressen zwischen 0x2AFFE und 0x800000 ist auf Ihrem Gerät kein Speicher implementiert - deshalb gibt das Datenblatt für diesen Bereich "Unimplemented Read '0'" an.
Wenn Sie Flash verwenden möchten, um EEPROM zu emulieren, müssen Sie Flash im Bereich „User Flash Program Memory“ zwischen 0x00000 und 0x2AFFE verwenden.
const unsigned int attribute ((space(prog), address (0x6000))) table[10];
ist ein durchaus akzeptabler Weg, dies zu tun.
Sie lassen den Compiler diesen Speicherblock Ihrem Array zuweisen, damit dort kein Code abgelegt wird, sodass Sie ihn sicher verwenden können.
Sie müssen jedoch sicher sein, dass die Adresse und Größe, die Sie für Ihr Array angeben, mit genau einem oder mehreren der "Löschblöcke" im Flash Ihres PIC übereinstimmt.
Das Datenblatt sagt Ihnen, dass der 0x2B000-Bereich in 172 Blöcke aufgeteilt ist, also 0x400 pro Block. Ihre Array-Startadresse und -Größe müssen ein Vielfaches dieses Werts sein, daher sollten Sie für Ihren Fall die Größe Ihres Arrays ändern.
Wenn Ihr Array einen oder mehrere Blöcke nicht genau ausfüllt, kann der Compiler den Rest eines Blocks für Code verwenden. Da der PIC jedoch einen ganzen Block löscht, wenn dies für Ihre EEPROM-Emulation erforderlich ist, würde dies dazu führen in einigen Code wird auch gelöscht.
Es scheint, dass die Variable, die Sie an __builtin_tblpage-Makros übergeben, ein Byte (Bit) ist, während Sie ein kurzes (16 Bit) übergeben müssen.
Ich verwende diese Funktion für Microchip, um den PIC24EP-Mikrochip zu schreiben / zu lesen, sie sollten für Sie ziemlich ähnlich sein.
/*********************************************************************
* Function: unsigned int NVMErasePage(void* address)
*
* Description: Block Erases Program Memory
* PreCondition: None
*
* Inputs: address: Destination page address to Erase.
*
* Output: '0' if operation completed successfully.
*
* Example: NVMemErasePage(UINT32 0xBD000000)
********************************************************************/
UINT NVMemBlockErase(void)
{
NVMCON = 0x400D; //Bulk erase on next WR
INTCON2bits.GIE = 0; //Disable interrupts for next few instructions for unlock sequence
__builtin_write_NVM();
while(NVMCONbits.WR == 1){}
INTCON2bits.GIE = 1; // Re-enable the interrupts (if required).
// Return WRERR state.
return NVMCONbits.WRERR;
}
/*********************************************************************
* Function: unsigned int NVMErasePage(void* address)
*
* Description: A page erase will erase a single page of program flash,
* which equates to 1k instructions (3KBytes). The page to
* be erased is selected using NVMADDR. The lower bytes of
* the address given by NVMADDR are ignored in page selection.
*
* PreCondition: None
*
* Inputs: address: Destination page address to Erase.
*
* Output: '0' if operation completed successfully.
*
* Example: NVMemErasePage(UINT32 0xBD000000)
********************************************************************/
UINT NVMemErasePage(UINT32 address)
{
DWORD_VAL eraseAddress;
eraseAddress.Val = address;
TBLPAG = eraseAddress.byte.UB;
NVMADRU = eraseAddress.word.HW;
NVMADR = eraseAddress.word.LW;
__builtin_tblwtl(eraseAddress.word.LW, 0xFFFF);
NVMCON = 0x4003; //Erase page on next WR
INTCON2bits.GIE = 0; //Disable interrupts for next few instructions for unlock sequence
__builtin_write_NVM();
while(NVMCONbits.WR == 1){}
INTCON2bits.GIE = 1; // Re-enable the interrupts (if required).
// Return WRERR state.
return NVMCONbits.WRERR;
}
/*********************************************************************
* Function: unsigned int NVMWriteWord(UINT32 address, UINT32 data)
*
* Description: The word at the location pointed to by NVMADDR is programmed.
*
* PreCondition: None
*
* Inputs: address: Destination address to write.
* data: Word to write.
*
* Output: '0' if operation completed successfully.
*
* Example: NVMWriteWord(0xBD000000, 0x12345678)
********************************************************************/
UINT NVMemWriteWord(UINT32 address, UINT32 data)
{
DWORD_VAL writeAddress;
DWORD_VAL writeData;
writeAddress.Val = address;
writeData.Val = data;
NVMCON = 0x4001; //Perform WORD write next time WR gets set = 1.
NVMADRU = writeAddress.word.HW;
NVMADR = writeAddress.word.LW;
// Set the table address of "Latch". The data is programmed into the FLASH from a temporary latch.
TBLPAG = 0xFA;
//The smallest block of data that can be programmed in
//a single operation is 2 instruction words (6 Bytes + 2 Phantom Bytes).
// Mask the high or low instruction words depending on the address and write either high or low instruction word.
if(address % 4)
{
__builtin_tblwtl(0, 0xFFFF); //Mask the low word of 1-st instruction into the latch.
__builtin_tblwth(1, 0x00FF); //Mask the high word of 1-st instruction into the latch. (8 bits of data + 8 bits of "phantom data" (phantom byte is always 0))
__builtin_tblwtl(2, writeData.word.LW); //Write the low word of 2-nd instruction into the latch
__builtin_tblwth(3, writeData.word.HW); //Write the high word of 2-nd instruction into the latch
}
else
{
__builtin_tblwtl(0, writeData.word.LW); //Write the low word of 1-st instruction into the latch
__builtin_tblwth(1, writeData.word.HW); //Write the high word of 1-st instruction into the latch
__builtin_tblwtl(2, 0xFFFF); //Mask the low word of 2-nd instruction into the latch.
__builtin_tblwth(3, 0x00FF); //Mask the high word of 2-nd instruction into the latch. (8 bits of data + 8 bits of "phantom data" (phantom byte is always 0))
}
INTCON2bits.GIE = 0; //Disable interrupts for next few instructions for unlock sequence
__builtin_write_NVM();
while(NVMCONbits.WR == 1){}
INTCON2bits.GIE = 1; // Re-enable the interrupts (if required).
// Return WRERR state.
return NVMCONbits.WRERR;
}
Und ich benutze sie wie:
typedef short Word16;
typedef unsigned short UWord16;
typedef long Word32;
typedef unsigned long UWord32;
typedef union tuReg32
{
UWord32 Val32;
struct
{
UWord16 LW;
UWord16 HW;
} Word;
char Val[4];
} uReg32;
void WritePM(char *Data, uReg32 SourceAddr, unsigned int Size)
{
unsigned int j, i = 0;
uReg32 data1;
char ptrData[6];
while (i < Size)
{
for (j=0; j <6;j++)
ptrData[j] = Data[j+i];
data1.Val[0] = ptrData[0];
data1.Val[1] = ptrData[1];
data1.Val[2] = ptrData[2];
NVMemWriteWord((UINT32) SourceAddr.Val32, (UINT32) data1.Val32);
SourceAddr.Val32 += 2;
i += 3;
ClrWdt();
}
}
Und
#define CONFIG_ADDR 0x7FF000
void WriteConf(char * ptr, unsigned int size)
{
uReg32 Addr;
Addr.Val32 = CONFIG_ADDR;
_IPL = 7;
Erase(Addr.Word.HW, Addr.Word.LW,PM_ROW_ERASE);
_IPL = 0;
WritePM( ptr, Addr, size);
}
void ReadConf(char * ptr, unsigned int size)
{
uReg32 Addr;
Addr.Val32 = CONFIG_ADDR;
_IPL = 7;
ReadPM(ptr, Addr, size);
_IPL = 0;
}
Sie können einfach eine Struktur Ihrer Daten erstellen und einen Zeiger auf diese Funktionen senden.
Notiz:
brhans
aamir
brhans
aamir
aamir
brhans