📄 flash.c
字号:
#include <conio.h>
#include <math.h>
#include <environment.h>
#include "flash.h"
#ifndef FLASH_INTEL_STRATA
#error "Flash type not supported!"
#endif
#if ((FLASH_BANK_SIZE * FLASH_NOF_BANKS) != FLASH_SIZE)
#error "Illegal bank- flash- size combination!"
#endif
//some globals for managment purposes
T_FLASH_SPEC g_tFlash;
#ifdef _USE_VDK_
#include <VDK.h>
#include <services/services.h>
char Flash_LockAccess (VDK_ThreadID *ThreadId) {
if (g_tFlash.bLocked) {
*ThreadId = g_tFlash.tThreadId;
return -1;
} else {
g_tFlash.tThreadId = VDK_GetThreadID();
g_tFlash.bLocked = true;
return 0;
}
}
char Flash_UnlockAccess (void) {
g_tFlash.bLocked = false;
return 0;
}
#endif
static void Flash_BankSelectReset (void) {
unsigned char i = 0;
for (i=0; i<g_tFlash.cNofBankSelect; i++) {
gpio_clear (g_tFlash.nBankSelect[i]);
}
g_tFlash.cCurrentBank = 0;
}
void Flash_BankSelectSetup (void) {
unsigned char i = 0;
for (i=0; i<g_tFlash.cNofBankSelect; i++) {
gpio_becomeOutput (g_tFlash.nBankSelect[i]);
gpio_clear (g_tFlash.nBankSelect[i]);
}
g_tFlash.cCurrentBank = 0;
}
// has to be called, prior to use the flash
void Flash_Setup (void) {
g_tFlash.cNofBanks = FLASH_NOF_BANKS;
g_tFlash.nBankSize = FLASH_BANK_SIZE;
g_tFlash.cNofBankSelect = (unsigned char)(log ( (double)g_tFlash.cNofBanks) / log (2.0));
g_tFlash.nBankSelect[0] = FLASH_BANK_SELECT0;
g_tFlash.nBankSelect[1] = FLASH_BANK_SELECT1;
g_tFlash.nBankSelect[2] = FLASH_BANK_SELECT2;
g_tFlash.nBankSelect[3] = FLASH_BANK_SELECT3;
#ifdef _USE_VDK_
g_tFlash.bLocked = false;
#endif
Flash_BankSelectSetup ();
}
void Flash_SelectBank (unsigned char pa_cBank) {
if (g_tFlash.cCurrentBank != pa_cBank) {
// bank must be changed
if (pa_cBank < g_tFlash.cNofBanks) {
// valid bank selected
register unsigned char i;
register unsigned char cBankMask = 0x01;
for (i=0; i<g_tFlash.cNofBankSelect; i++) {
if (pa_cBank & cBankMask) {
gpio_set (g_tFlash.nBankSelect[i]);
} else {
gpio_clear (g_tFlash.nBankSelect[i]);
}
cBankMask <<= 1;
}
g_tFlash.cCurrentBank = pa_cBank;
// wait for stabilizing gpio pins
Sleep (5);
}
}
}
inline unsigned char Flash_GetBank (unsigned long nOffset) {
return (nOffset / g_tFlash.nBankSize);
}
inline unsigned long Flash_GetAddress (unsigned char cBank, unsigned long nOffset) {
return (nOffset - cBank * g_tFlash.nBankSize);
}
//deletes one sector
unsigned short Flash_EraseSector(unsigned long startAddress, unsigned long sectorAddress) {
if (g_tFlash.cNofBanks > 1) {
// we have more than one bank, so check witch bank to select
// and correct the offset
unsigned char cBank = Flash_GetBank (sectorAddress);
Flash_SelectBank (cBank);
sectorAddress = Flash_GetAddress (cBank, sectorAddress);
}
volatile unsigned short *memIndex = (unsigned short *)(startAddress + sectorAddress);
*memIndex = 0x0050;
asm("ssync;");
*memIndex = 0x0020;
asm("ssync;");
*memIndex = 0x00d0;
asm("ssync;");
unsigned short status;
unsigned long nTimeout = 0;
do {
status = *memIndex;
asm("ssync;");
nTimeout ++;
}
while (((status & 0x0080) == 0x00) && (nTimeout < FLASH_ERASE_TIMEOUT));
if (nTimeout >= FLASH_ERASE_TIMEOUT) {
status = 0xff00;
}
nTimeout = FLASH_ERASE_TIMEOUT;
do {
*memIndex = 0xff; //back to "read array mode"
asm("ssync;");
nTimeout--;
}
while ((*memIndex != 0xffff) && nTimeout);
if (!nTimeout) {
status = 0xff00;
}
return (status);
}
//deletes the entire flash
unsigned short Flash_EraseChip(void) {
volatile unsigned long sectorAddress;
unsigned short status;
sectorAddress = 0;
Flash_Reset ();
do {
status = Flash_EraseSector(FLASH_START_ADDRESS, sectorAddress);
#if FLASH_DEBUG_LEVEL > 1
printf(" Status of block %xh: %xh\n", sectorAddress, status);
#endif
sectorAddress += FLASH_SECTOR_SIZE;
}
while ((sectorAddress <= FLASH_LAST_SECTOR) && (status != 0xff00));
return (status);
}
// Programmingsequence for intel flash devices.
// Offset: Wordaddress, relativ to startAddress
// Return values:
// 0x0080: everything ok.
// 0xff00: programming sequence timeout error.
// 0xee00: value not programmed correctly.
unsigned short Flash_ProgramWord(unsigned long startAddress, unsigned long wordAddress, unsigned short data) {
if (g_tFlash.cNofBanks > 1) {
// we have more than one bank, so check witch bank to select
// and correct the offset
unsigned char cBank = Flash_GetBank (wordAddress);
Flash_SelectBank (cBank);
wordAddress = Flash_GetAddress (cBank, wordAddress);
}
volatile unsigned short *memIndex;
unsigned long nTimeout;
unsigned short status;
memIndex = (unsigned short *)(startAddress + wordAddress);
*memIndex = 0x0050; //reset statusregister
asm("ssync;");
*memIndex = 0x0040;
asm("ssync;");
*memIndex = data;
asm("ssync;");
nTimeout=0;
do {
status = *memIndex;
nTimeout++;
asm("ssync;");
}
while (((status & 0x0080) == 0x00) && (nTimeout < FLASH_PROGRAM_TIMEOUT));
if (nTimeout >= FLASH_PROGRAM_TIMEOUT) {
status = 0xff00;
}
*memIndex = 0xffff; //back to "read array mode".
asm("ssync;");
if (status != 0xff00) {
if (*memIndex != data) {
status = 0xee00;
}
}
return status;
}
void Flash_ReadIdentifier (unsigned short *cDevCode, unsigned short *cManuCode) {
volatile unsigned short *nFlashAddr;
Flash_BankSelectReset ();
nFlashAddr = (unsigned short *)FLASH_START_ADDRESS;
*nFlashAddr = 0x0090; //read identifier command.
asm("ssync;");
*cManuCode = *nFlashAddr;
asm("ssync;");
nFlashAddr++;
*cDevCode = *nFlashAddr;
asm("ssync;");
*nFlashAddr = 0x00ff; //return to read array mode.
asm("ssync;");
}
unsigned short Flash_UnlockBlock (unsigned long pa_nSectorAddr) {
if (g_tFlash.cNofBanks > 1) {
// we have more than one bank, so check witch bank to select
// and correct the offset
unsigned char cBank = Flash_GetBank (pa_nSectorAddr);
Flash_SelectBank (cBank);
pa_nSectorAddr = Flash_GetAddress (cBank, pa_nSectorAddr);
}
volatile unsigned short *nFlashAddr;
unsigned short nStatus = 0;
nFlashAddr = (unsigned short *)(FLASH_START_ADDRESS + pa_nSectorAddr);
*nFlashAddr = 0x00ff;
asm("ssync;");
*nFlashAddr = 0x0050; //reset statusregister
asm("ssync;");
*nFlashAddr = 0x0060;
asm("ssync;");
*nFlashAddr = 0x00d0;
asm("ssync;");
unsigned long nTimeout = FLASH_UNLOCK_TIMEOUT;
do {
nStatus = *nFlashAddr;
nTimeout --;
} while (((nStatus & 0x0080) != 0x0080) && nTimeout);
*nFlashAddr = 0x00ff; //return to read array mode.
if (!nTimeout) {
nStatus = 0xff00;
}
return (nStatus);
}
unsigned short Flash_LockBlock (unsigned long pa_nSectorAddr) {
if (g_tFlash.cNofBanks > 1) {
// we have more than one bank, so check witch bank to select
// and correct the offset
unsigned char cBank = Flash_GetBank (pa_nSectorAddr);
Flash_SelectBank (cBank);
pa_nSectorAddr = Flash_GetAddress (cBank, pa_nSectorAddr);
}
volatile unsigned short *nFlashAddr;
unsigned short nStatus = 0x0080;
unsigned long nTimeout = 0;
nFlashAddr = (unsigned short *)(FLASH_START_ADDRESS + pa_nSectorAddr);
nTimeout=0;
asm("ssync;");
*nFlashAddr = 0x0060;
asm("ssync;");
*nFlashAddr = 0x0001;
asm("ssync;");
*nFlashAddr = 0x00ff; //return to read array mode.
asm("ssync;");
return (nStatus);
}
unsigned short Flash_LockAll (void) {
volatile unsigned long sectorAddress = 0;
unsigned short status = 0;
Flash_Reset ();
do {
status = Flash_LockBlock (sectorAddress);
sectorAddress += FLASH_SECTOR_SIZE;
}
while ((sectorAddress <= FLASH_LAST_SECTOR) && (status != 0xff00));
return status;
}
unsigned short Flash_UnlockAll (void) {
volatile unsigned long sectorAddress = 0;
unsigned short status = 0;
Flash_Reset ();
do {
status = Flash_UnlockBlock (sectorAddress);
sectorAddress += FLASH_SECTOR_SIZE;
}
while ((sectorAddress <= FLASH_LAST_SECTOR) && (status != 0xff00));
return status;
}
unsigned short Flash_Reset (void) {
// reset the bank selectors
Flash_BankSelectReset ();
// return to read array mode
*(unsigned short *)FLASH_START_ADDRESS = 0xffff;
asm("ssync;");
return 0;
}
unsigned short Flash_ReadWord (unsigned long pa_nOffset) {
if (g_tFlash.cNofBanks > 1) {
// we have more than one bank, so check witch bank to select
// and correct the offset
unsigned char cBank = Flash_GetBank (pa_nOffset);
Flash_SelectBank (cBank);
pa_nOffset = Flash_GetAddress (cBank, pa_nOffset);
}
volatile unsigned short *nFlashAddr;
unsigned short nValue;
nFlashAddr = (unsigned short *)(FLASH_START_ADDRESS + pa_nOffset);
// put the value at the location passed in
nValue = (*nFlashAddr);
asm ("ssync;");
return (nValue);
}
int Flash_GetSectorNumber( unsigned long ulOffset) {
if (g_tFlash.cNofBanks > 1) {
// we have more than one bank, so check witch bank to select
// and correct the offset
unsigned char cBank = Flash_GetBank (ulOffset);
Flash_SelectBank (cBank);
ulOffset = Flash_GetAddress (cBank, ulOffset);
}
return ((int)(ulOffset / FLASH_SECTOR_SIZE)); //calculates the sectornumber.
}
bool Flash_CheckIfEmpty (unsigned long pa_nStartAddress) {
unsigned long nWordIndex;
// calculate relative offset to FLASH_START_ADDRESS
pa_nStartAddress -= FLASH_START_ADDRESS;
for (nWordIndex=pa_nStartAddress; nWordIndex<FLASH_SIZE; nWordIndex+=2) {
if (Flash_ReadWord(nWordIndex) != 0xffff) {
return false;
}
}
return true;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -