koyodza (29.05.2013 13:25, просмотров: 141) ответил Лeoнид Ивaнoвич на Как жить без EEPROM?
AN2594 http://www.st.com/web/en/resource/technical/document/application_note/CD00165693.pdf
у меня реализовано немного не так, без таблицы в ОЗУ использованных ячеек:
__private void* EE_FindTopOfPage(DWORD pageAddr)
{
DWORD addr = (pageAddr & dwPageMask) | dwAddrMask;
DWORD* p = (DWORD*)addr;
while (dwAddrMask & (DWORD)p)
{
if (*p == MAX_DWORD)
return p;
p--;
}
return NULL;
}
///////////////////////////////////////////////////////////////////////////////
__private void* EE_Find(DWORD startAddr, WORD vAddr)
{
UN32* p = (UN32*)startAddr;
do
{
p++;
if (!(dwAddrMask & (DWORD)p))
return NULL;
}
while (p->wh != vAddr);
return p;
}
///////////////////////////////////////////////////////////////////////////////
__private void EE_CopyPage(void)
{
static BYTE nEnter = 0;
nEnter++;
if (nEnter > 1)
return;
DWORD pageDst = (DWORD)pFreePage & dwPageMask;
DWORD pageSrc = (DWORD)pTop & dwPageMask;
UN32* pSrcBegin = (UN32*)pageSrc;
UN32* pSrc = pTop;
UN32 sign32 = *pSrcBegin;
pTop = (UN32*)((pageDst & dwPageMask) | dwAddrMask);
if (!FlashIsFree((void*)pageDst, 1024))
FlashErasePage((void*)pageDst);
if (!FlashIsFree((void*)(pageDst + 1024), 1024))
FlashErasePage((void*)(pageDst + 1024));
while (TRUE)
{
pSrc++;
if (!(dwAddrMask & (DWORD)pSrc))
break;
UN32 tmp = *pSrc;
if (!EE_Find((DWORD)pTop, tmp.wh))
EE_Write(tmp.wh, tmp.wl);
}
sign32.dw = LOBYTE(sign32.dw + 1);
FlashWrite32((void*)pageDst, sign32);
pPage = (UN32*)(pageDst & dwPageMask);
pFreePage = pSrcBegin;
nEnter--;
}
///////////////////////////////////////////////////////////////////////////////
__public int EE_Write(WORD vAddr, WORD vData)
{
if (!((DWORD)pTop & dwAddrMask))
EE_CopyPage();
FlashWrite32(pTop, (UN32){.wh = vAddr, .wl = vData});
pTop--;
return TRUE;
}
///////////////////////////////////////////////////////////////////////////////
__public int EE_Read(WORD vAddr, WORD* pData)
{
DWORD startAddr = (DWORD)pTop;
UN32* p = EE_Find(startAddr, vAddr);
if (p)
{
*pData = p->wl;
return TRUE;
}
return FALSE;
}
///////////////////////////////////////////////////////////////////////////////
__public void EEPROMInit(void)
{
DWORD pageSize = 0x800;
dwAddrMask = pageSize - 4;
dwPageMask = ~(pageSize - 1);
DWORD flashSize = DEVSIGN->flashSize * 1024;
UN32* pX[2] =
{
(UN32*)(FLASH_BASE + flashSize - pageSize),
(UN32*)(FLASH_BASE + flashSize - (2 * pageSize)),
};
__int8 d = pX[0]->b[0] - pX[1]->b[0];
pPage = pX[0], pFreePage = pX[1];
if (d < 0)
pPage = pX[1], pFreePage = pX[0];
else if (d == 0)
{
FlashErasePage(pPage);
FlashErasePage(pFreePage);
FlashWrite32(pPage, (UN32){.wh = MAX_WORD, .wl = 0});
}
DWORD addr = (DWORD)pPage + dwAddrMask;
UN32* p = EE_FindTopOfPage(addr);
if (!p)
p = pPage;
pTop = p;
}