⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 flash.c

📁 black-fin DSP处理器串行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 + -