|
Fórum » PIC - Miértek, hogyanok haladóknak
Igen, pont azt akartam még hozzátenni, hogy előtte adtam meg a címet:
S ha jól rémlik, 64 byte-os határra kell essen a törlés miatt.
Az nem az EEPROM címe, hanem egy szekvencia, ami az íráshoz kell! A hozzászólás módosítva: Jún 19, 2020
Oké, köszi, szerintem így már menni fog. Ha elakadok majd írok. Köszi a segítséget.
Üdv!
Kissé megkésve bár, de nekem is van egy ötletem a problémád megoldására:
Definíciók:
.equ LED1,0
.equ LED1_P,PORTB
.macro BS bit
bset &bit&_P,#\bit
.endm
.macro BC bit
bclr &bit&_P,#\bit
.endm
Felhasználás:
A hozzászólás módosítva: Jún 19, 2020
Címzésben tudsz esetleg még segíteni?
Azt látom, hogy 21bit címet vár, de nem egészen értem az összetételét.
Azt írja, hogy 3 részből tevődik össze a TBLPTR regiszter, TBLPTRU, TBLPTRH és TBLPTRL.
TBLPTRL-ben lehet kiválasztani az írást, olvasást vagy törlést ez 7-0 bitek közt van, 0-ás az olvasás, 3-as az írás és 6-os a törlés. Aztán jön a cím 2 byte hosszan. Jól értelmezem?
Hol látom, hogy mettől meddig címezhetem meg a program memóriát? Gondolom a memória szervezésnél kell kitökölnom. A programozó lineárisan írja be a programot? Tehát feltételezve, hogy az a 3Kbyte adat az elejétől pontosan a maga 3Kbyte címet fedi csak le és utána nem kell számítanom másra? Ennyi hirtelen ami eszembe jutott. Köszi előre is.
A Cim változó nálam 16 bites! 16 bit cím mindenre elég!(ismerős szöveg )
Szerintem valamit ott összekeversz, a művelet típusát nem a TBLPTR regiszterekben állítod be, abban a műveletre vonatkozó címet adod meg. Magát a műveletet pedig más regiszterekben állítod be. Lásd a kódrészlet, amit adtam...
Azt, hogy mettől, meddig írod az rajtad áll, nyilván az adott eszköz memóriája szabja meg a határt! A határoknál a törlésé a legnagyobb méret. Tehát erre kell kerekíteni minden utána(előtte) lévő címhatárt.... De az egész folyamatos, a legelejétől a legvégéig...
Nem a TBLPTR -ben kell kiválasztani műveletet, hanem a műveleteknek van egy "fix mérete".
Az EECON1 -ben kell kiválasztani a műveletet.
EECON1bits.EEPGD=1; // 1 -> Program memória , 0 -> adat memória
EECON1bits.CFGS=0; // 1 -> Configurációs terület , 0 -> Program terület
EECON1bits.FREE=1; // Törlés
EECON1bits.WREN=1; // Írás engedélyezése
EECON1bits.RD=1; // Olvasási művelet indítása
EECON1bits.WR=1; // Írási művelet indítása
Idézet: „Hol látom, hogy mettől meddig címezhetem meg a program memóriát?”
Röviden: Az adatlapban... Memory orgenaization.
18F2x25 - 18F4x26:
A "TABLE POINTER OPERATIONS WITH TBLRD AND TBLWT INSTRUCTIONS" mutatja az egyes műveletek "fix méreteit".
TABLE WRITE --- Ebben a típusban egyszerre csak 32 utasítás / 64 byte írható
TABLE ERASE --- Ebben a típusban egyszerre csak 32 utasítás / 64 byte törölhető
A fenti két művenetnél a TBLPTR 5..0 bitjei nem vesznek részt a címzésben.
TABLE READ --- Egyesével olvashatók a byte-ok, a címzésben mind a 21 bit részt vesz.
// PIC18F452 program memóriájának törlése 64byte / block
void PICFlashBlockErase(unsigned int Addr)
{
TBLPTR=Addr;
//----------------- Blokk törlés ----------------------------------
EECON1bits.EEPGD=1; // Flash Program vagy adat EEPROM memória vélasztó bit
// 1 = Hozzáférés a flash program memóriához
// 0 = Hozzáférés az EEPROM memóriához
EECON1bits.CFGS=0; // Flash Program / adat EEPROM vagy konfiguráció választó bit
// 1 = Hozzáférés a konfigurációs nyilvántartásokhoz
// 0 = Hozzáférés a Flash program vagy adat EEPROM memóriához
EECON1bits.WREN=1; // Flash Program / adat EEPROM írást engedélyező bit
// 1 = Engedélyezi a Flash program / adat EEPROM írását
// 0 = Gátolja a Flash program / adat EEPROM írását
EECON1bits.FREE=1; // flash törlésének engedélyezése
// 1 = Törlés engedélyezése
// 0 = Csak olvasás
INTCONbits.GIE=0; // Megszakítás letiltva
EECON2=0x55; // EEPROM nem fizikai adat regiszter, írás és törlési szekvencia
EECON2=0xAA;
EECON1bits.WR=1; // Írást vezérlő bit
// 1 = kezdeményez adat EEPROM törlés / írás ciklust vagy a program memória törlési ciklust vagy írási ciklus
// 0 = Write ciklus az EEPROM teljes
Nop(); // 1 órajel szünet
INTCONbits.GIE=1; // Megszakítás engedélyezve
EECON1bits.WREN=0; // Flash Program / adat EEPROM írást engedélyező bit
// 1 = Engedélyezi a Flash program / adat EEPROM írását
// 0 = Gátolja a Flash program / adat EEPROM írását
}
// PIC18F452 program memória írása 64byte / block és 8 byte / írás
void PICFlashBlockWrite(unsigned int Addr, unsigned char *Data)
{
unsigned char i = 0, K = 0;
TBLPTR=Addr;
EECON1bits.WREN=0; // Flash Program / adat EEPROM írást engedélyező bit
// 1 = Engedélyezi a Flash program / adat EEPROM írását
// 0 = Gátolja a Flash program / adat EEPROM írását
for(K=0;K<64;K=K+8)
{
for(i=0;i<8;i++)
{
TABLAT = Data[K+i];
_asm TBLWTPOSTINC _endasm;
}
_asm TBLRDPOSTDEC _endasm;
EECON1bits.EEPGD=1; // Flash Program vagy adat EEPROM memória vélasztó bit
// 1 = Hozzáférés a flash program memóriához
// 0 = Hozzáférés az EEPROM memóriához
EECON1bits.CFGS=0; // Flash Program / adat EEPROM vagy konfiguráció választó bit
// 1 = Hozzáférés a konfigurációs nyilvántartásokhoz
// 0 = Hozzáférés a Flash program vagy adat EEPROM memóriához
EECON1bits.WREN=1; // Flash Program / adat EEPROM írást engedélyező bit
// 1 = Engedélyezi a Flash program / adat EEPROM írását
// 0 = Gátolja a Flash program / adat EEPROM írását
INTCONbits.GIE=0; // Megszakítás letiltva
EECON2=0x55; // EEPROM nem fizikai adat regiszter, írás és törlési szekvencia
EECON2=0xAA;
EECON1bits.WR=1; // Írást vezérlő bit
// 1 = kezdeményez adat EEPROM törlés / írás ciklust vagy a program memória törlési ciklust vagy írási ciklus
// 0 = Write ciklus az EEPROM teljes
Nop(); // 1 órajel szünet
EECON1bits.WREN=0; // Flash Program / adat EEPROM írást engedélyező bit
// 1 = Engedélyezi a Flash program / adat EEPROM írását
// 0 = Gátolja a Flash program / adat EEPROM írását
INTCONbits.GIE=1; // Megszakítás engedélyezése
_asm TBLRDPOSTINC _endasm;
}
}
Eddig jutottam.
Csatoltam egy képet a memória szervezésről, ez kell nekem, hogy lássam hogy hova címezhetek adatokat? Még azt nem értem, hogy itt 0-tól 7FFF-ig lehet címezni, de az 32Kbyte, és az adatlap csak 16-ot ír, amit használni lehet.
Milyen címtől írhatok a program memóriára biztonságosan? Le kell egyáltalán foglalni a területet vagy a direkt írás miatt felesleges? Köszi előre is a kiokítást.
Gondod, bajod rögtön elszáll, ha figyelembe veszed, hogy a Program memória byte szervezésű, de egy utasítás 2 (4) byte.
A 0x0000 - 0x7FFF byte címeken elérhető. azaz 32kbyte, de csak 16k utasítás.
Idézet: „The PIC18F252 and PIC18F452 each have 32 Kbytes of FLASH memory, while the PIC18F242 and PIC18F442 have 16 Kbytes of FLASH. This means that PIC18FX52 devices can store up to 16K of single word instructions, and PIC18FX42 devices can store up to 8K of single word instructions.”
Nah igen, ez világos, de most akkor sem áll össze a kép. A kód amúgy jó amit beágyaztam?
Debugolom, de fingom nincs egyelőre mit kellene látnom, vagy is sejtem, de egyelőre nem működik.
Annyi biztos hiányzik, hogy meg kell várni, amíg a művelet befejeződik, azaz a WR bit 0-ra áll.
Be raktam a kódba.
// PIC18F452 program memóriájának törlése 64byte / block
void PICFlashBlockErase(unsigned int Addr)
{
TBLPTR=Addr;
//----------------- Blokk törlés ----------------------------------
EECON1bits.EEPGD=1; // Flash Program vagy adat EEPROM memória vélasztó bit
// 1 = Hozzáférés a flash program memóriához
// 0 = Hozzáférés az EEPROM memóriához
EECON1bits.CFGS=0; // Flash Program / adat EEPROM vagy konfiguráció választó bit
// 1 = Hozzáférés a konfigurációs nyilvántartásokhoz
// 0 = Hozzáférés a Flash program vagy adat EEPROM memóriához
EECON1bits.WREN=1; // Flash Program / adat EEPROM írást engedélyező bit
// 1 = Engedélyezi a Flash program / adat EEPROM írását
// 0 = Gátolja a Flash program / adat EEPROM írását
EECON1bits.FREE=1; // flash törlésének engedélyezése
// 1 = Törlés engedélyezése
// 0 = Csak olvasás
INTCONbits.GIE=0; // Megszakítás letiltva
EECON2=0x55; // EEPROM nem fizikai adat regiszter, írás és törlési szekvencia
EECON2=0xAA;
EECON1bits.WR=1; // Írást vezérlő bit
// 1 = kezdeményez adat EEPROM törlés / írás ciklust vagy a program memória törlési ciklust vagy írási ciklus
// 0 = Write ciklus az EEPROM teljes
while (EECON1bits.WR == 1); // Várakozunk az írás befejezéséig
Nop(); // 1 órajel szünet
INTCONbits.GIE=1; // Megszakítás engedélyezve
EECON1bits.WREN=0; // Flash Program / adat EEPROM írást engedélyező bit
// 1 = Engedélyezi a Flash program / adat EEPROM írását
// 0 = Gátolja a Flash program / adat EEPROM írását
}
// PIC18F452 program memória írása 64byte / block és 8 byte / írás
void PICFlashBlockWrite(unsigned int Addr, unsigned char *Data)
{
unsigned char i = 0, K = 0;
TBLPTR=Addr;
EECON1bits.WREN=0; // Flash Program / adat EEPROM írást engedélyező bit
// 1 = Engedélyezi a Flash program / adat EEPROM írását
// 0 = Gátolja a Flash program / adat EEPROM írását
for(K=0;K<64;K=K+8)
{
for(i=0;i<8;i++)
{
TABLAT = Data[K+i];
_asm TBLWTPOSTINC _endasm;
}
_asm TBLRDPOSTDEC _endasm;
EECON1bits.EEPGD=1; // Flash Program vagy adat EEPROM memória vélasztó bit
// 1 = Hozzáférés a flash program memóriához
// 0 = Hozzáférés az EEPROM memóriához
EECON1bits.CFGS=0; // Flash Program / adat EEPROM vagy konfiguráció választó bit
// 1 = Hozzáférés a konfigurációs nyilvántartásokhoz
// 0 = Hozzáférés a Flash program vagy adat EEPROM memóriához
EECON1bits.WREN=1; // Flash Program / adat EEPROM írást engedélyező bit
// 1 = Engedélyezi a Flash program / adat EEPROM írását
// 0 = Gátolja a Flash program / adat EEPROM írását
INTCONbits.GIE=0; // Megszakítás letiltva
EECON2=0x55; // EEPROM nem fizikai adat regiszter, írás és törlési szekvencia
EECON2=0xAA;
EECON1bits.WR=1; // Írást vezérlő bit
// 1 = kezdeményez adat EEPROM törlés / írás ciklust vagy a program memória törlési ciklust vagy írási ciklus
// 0 = Write ciklus az EEPROM teljes
while (EECON1bits.WR == 1); // Várakozunk az írás befejezéséig
Nop(); // 1 órajel szünet
EECON1bits.WREN=0; // Flash Program / adat EEPROM írást engedélyező bit
// 1 = Engedélyezi a Flash program / adat EEPROM írását
// 0 = Gátolja a Flash program / adat EEPROM írását
INTCONbits.GIE=1; // Megszakítás engedélyezése
_asm TBLRDPOSTINC _endasm;
}
}
A hozzászólás módosítva: Jún 19, 2020
Közben még kutakodtam a témában és egy ilyesmi kódot is találtam, persze nem pont ebben a formában, már picit átírtam a teszteléshez, meg hogy kompatibilis legyen, de sajnos nem működik.
Definíció: #define PRGM_BUFFER_SIZE 8
#define TABLE_WRITE_SIZE 64
#define LOAD_TBL_PTR(x) { TBLPTRU = ((((x)>>8)>>8)&0xff);\
TBLPTRH = (((x) >> 8) & 0xff);\
TBLPTRL = ((x) & 0xff);\
}
Funkciók: /******************************************************
* Function : write_block
* Input : uint16_t position in destination flash
* Global : uint8_t buffer[64] - Location of source data
* Output : None
* Description : Writes the contents of the 64 byte
* data buffer to program flash space. Only 64 bytes
* can be written at once. The process of writing
* to flash is: Erase->Write.
******************************************************/
static void write_block(unsigned int addr, unsigned char *buffer)
{
int r, c;
// Erase flash block first. Erases a 64 byte block at a time.
LOAD_TBL_PTR(addr);
EECON1bits.EEPGD = 1; // Point to flash program memory
EECON1bits.CFGS = 0; // Access flash memory
EECON1bits.WREN = 1; // Enable write to memory
EECON1bits.FREE = 1; // Enable Erase operation
EECON2 = 0x55;
EECON2 = 0xAA;
EECON1bits.WR = 1; // Clear the flash
while(EECON1bits.WR);
Nop(); // Stall
// Write buffer to internal buffer. This process writes 8 bytes at a time
// so we need to loop 8 times (8*8 = 64).)
for (r = 0; r < 8; r++)
{
LOAD_TBL_PTR((addr + (r * 8)));
for (c = 0; c < PRGM_BUFFER_SIZE; c++)
{
TABLAT = buffer[(r * 8) + c];
_asm TBLWTPOSTINC _endasm; // Push byte and then inc to next internal buffer cell
}
// Write the block to flash
_asm TBLRDPOSTDEC _endasm; // Point back to original row
// Write internal buffer to flash
EECON1bits.EEPGD = 1; // Point to flash program memory
EECON1bits.CFGS = 0; // Access flash program memory
EECON1bits.WREN = 1; // Enable write to memory
INTCONbits.GIE = 0; // Disable interrupts
EECON2 = 0x55;
EECON2 = 0xAA;
EECON1bits.WR = 1; // Start programming flash
while(EECON1bits.WR);
INTCONbits.GIE = 1; // Re-enable interrupts
EECON1bits.WREN = 0; // Disable write to memory
}
}
/******************************************************
* Function : compare_block
* Input : uint16_t position in destination flash
* Global : uint8_t buffer[64] - Location of previous written data
* Output : bool true=successful, false=did not match
* Description : Reads a 64 byte block of flash memory and
* compares it to the data found in the global buffer.
******************************************************/
static unsigned char compare_block(unsigned int addr, unsigned char *buffer)
{
unsigned char retVal = 1; // succeeds
unsigned char i = 0;
INTCONbits.GIE = 0; // Disable interrupts
LOAD_TBL_PTR(addr);
for (i = 0; i < TABLE_WRITE_SIZE && retVal == 1; i++)
{
_asm TBLWTPOSTINC _endasm;
if (buffer[i] != TABLAT)
retVal = 0;
}
INTCONbits.GIE = 1; // Enable interrupts
return retVal;
}
Main()-ba pedig így: write_block(0x2000, Data);
Upload = 1;
Upload = compare_block(0x2000, Data);
A compre_block() elvileg ellenőrzi, hogy helyes adat van e a címen.. Sajna 0xFF-eket olvas vissza, így feltételezem, hogy nem ír a kiválasztott címre.
Mi lehet a gond?
Az a kódrészlet, amit küldtem 100%-ban működő, mert működő projectből másoltam ki! Ha nem megy, akkor valami más oka van neki....
Én ilyenkor a programozóval (PICKIT / ICD) szoktam visszaolvasni a PIC memóriáját, hogy lássam mit csinált az író rutin.
Egyelőre nem működik. Most azt fogom csinálni, hogy egy teljesen új projektet nyitok és nulláról indított projektben tesztelem mert ha tényleg így működni kell, akkor tényleg nálam lesz valami gond. Bár egyelőre nem értem mi lehet.
Program memóriát vizsgálgatom MPLAB-ban, de ott nincs semmi változás.
Uraim, agyaltam és nem lehet az a baj, hogy debugban nézegetem a program memóriát és a debug nem tudja nyomon követni azt? Mert hogy új projektben, amelyben semmi sallang nincs, sem működik egyik kód sem. Nem írja a program memóriát. header állományt is átnéztem nincs bekapcsolva védelem.
Köszi srácok a segítséget. Utóbbi volt a baj, debug módban nem tudtam nyomon követni a programmemória változását. superuser-nek jár a mancs.. A hozzászólás módosítva: Jún 20, 2020
A régi jó MpLab 8.92 szimulátora rendesen mutatja a memória változását.
Sajnos nekem nem, 8.91-est használok, lehet frissítenem kellene?
Vagy ezzel is látnom kellene? Azt hiszem valahol meg is van a 8.92-is.
Tévedtem nincs meg. A hozzászólás módosítva: Jún 20, 2020
Látnod kelllene. Debugger / MpLab Sim. Újrafordítás. Indítás előtt a törlésre kijelült területre a View / Program Memory segítségével valamit beírni. Ezután lépésneként is lehet menni...
Ez is működik:
...
for(i=0;i<8;i++)
{
*(rom far char *)((Addr) + K + i) = Data[K + i];
}
...
A hozzászólás módosítva: Jún 20, 2020
Üdv!
Próbálkozott már valaki dinamikus memóriakezeléssel (malloc / calloc függvénnyel) PIC -el? (MPLAB és xc16)
Sehogy nem akar működni a dolog. (Később rakok fel kódot is)
Ez az írás mutatóval történő megadása. Van ilyen olvasásra is gondolom? Ott a mutatót hogy kell megadni? Tehát ha egy adott címről akarok közvetlen olvasni, ezzel a módszerrel is megtehetem? Tudsz mutatni arra is egy példát? Köszi.
rom far char *pAdr;
unsigned chr data;
...
data = *(pAdr);
Véleményed szerint melyik hajtódik hamarabb végre?
Az általad mutatott mutatós megoldás vagy az amelyet feljebb beillesztettem?
Ez a kód mit csinál? A háttérben a program memóriába ír adatokat?
Vegyük számba. mit csinál a 4. sor:
- (far rom char *) 24 aza 21 bites cím kezelését írja elő. A sorhoz fordított kód feltölti a TBLPTRU, TBLPTRH, TBLPTR regisztereket a címmel. A fordító nem használhatja ki, hogy esetleg egymás utáni címeket olhasunk.
- ki kell olvasni az adatot. tblrd* utasítással a TABLAT regiszterbe.
- át kell adni az étéket a data változónak: movff TABLAT, data.
Ha máskép csinálod meg, kihasználhatod az egyszerűsítési lehetőségeket:
- TBLPTRU feltöltése egyszer,
- TBLPTRH feltöltése egyszer, módosítása ha szükséges,
- TBLPTR módosítható azzal a művelettel, amivel kiolvassuk az adatot tblrd*+
Ez a sor csak a program memória buffer latch -eit tölti fel. A sor egy előző hozzászólás környezetében működik és a program memóriát tölti fel (adattal vagy utasításokkal). Arra kell vigyázni, hogy ne "maga alatt" töröljön, módosítson.
Azért kérdeztem, mert pl az xc8 fordítónak van egy érdekes egyszerűsítése, hogy képes az EEPROM-ot kezelni a háttérben, anélkül, hogy neked bármit kellene vele tenni, tehát a megfelelő módon létrehozott változó, kódban történő hivatkozása(írás, olvasás) az EEPROM memória írását, olvasását váltja ki a háttérben.
Azt gondoltam, ez is valami hasonló dolog lesz....
Csak régi emlékekből, flash-t és eeprom-ot is az EECON-on keresztül fogsz írni, egy bit determinálja a regiszterekben, hogy flash vagy eeprom írás fog következni.
A címet EEADR vagy hasonló regiszterrel fogod megadni.
Az általad írt két sor unlock sequence.
Köszi, sikeresen átrágtuk magunkat a témán, és most már működik is.. Debugban volt gondom, hogy nem láttam a program memória írt részét, de programozóval kiolvasva már látom, de sajnos nem segített az egyik kérdéses gondomon, amiért a program memóriához fordultam, max több helyem lett, amivel gazdálkodhatok, de ..., ez már nem ide tartozik.
|
|