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

📄 drv_flash.c

📁 基于Freescale的MX21处理器的bootloader程序
💻 C
📖 第 1 页 / 共 2 页
字号:
// ***************************************************************************
//
//  Filename:       flash.c
//
//  Created:        Louis Lai (6/20/2003)
//
//  Modified:       $Author: $ $Date: $
//
// ***************************************************************************


// ***************************************************************************
//  pragmas
// ***************************************************************************


// ***************************************************************************
//  includes
// ***************************************************************************
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "drv_defs.h"#include "flash.h"

#if 1
void FlashSearchSector(u32 sAddress, u32 *Sec_start, u32 *Sec_size)
{
	u32 SA;
	u32 base, nSize;

	base = FLASH_BASE;
	
	for (SA = 0; SA <= 133; SA++)
	{
		if ((SA >= 0 && SA <= 3) || (SA >= 130 && SA <= 133))
		{	
			nSize = 0x4000*4;
		}
		else
		{
			nSize = 0x10000*4;
		}
		if ((sAddress >= base)&&(sAddress < (base+nSize))){
			*Sec_start = base;
			*Sec_size = nSize/4;
			break;
		}
		base += nSize;
	}
}
#else
void FlashSearchSector(u32 sAddress, u32 *Sec_start, u32 *Sec_size)
{
	u32 SA;
	u32 base, nSize;

	base = FLASH_BASE;
	
	for (SA = 1; SA <= 270; SA++)
	{
		if ((SA >= 1 && SA <= 8) || (SA >= 263 && SA <= 270))
		{	
			nSize = 0x1000*4;
		}
		else
		{
			nSize = 0x8000*4;
		}
		if ((sAddress >= base)&&(sAddress < (base+nSize))){
			*Sec_start = base;
			*Sec_size = nSize/4;
			break;
		}
		base += nSize;
	}
}
#endif

int FlashEraseSector(u32 sAddress)
{
	volatile u32*       pBase;
	volatile u32*       pWalk;
	int                 bFailTotal;
	int                 bDone;
	int                 bFail;
	u32                 nPoll;
	u32                 nDone;
	
	// This sector overlaps the address range. Erase it
	// ************************************************
	pWalk = (volatile u32*) sAddress;
	pBase = (u32*)FLASH_BASE;
	// Execute "normal" sector erase algorithm
	// ***************************************
	*(pBase + 0x555) = 0x00aa00aa;
	*(pBase + 0x2aa) = 0x00550055;
	*(pBase + 0x555) = 0x00800080;
	*(pBase + 0x555) = 0x00aa00aa;
	*(pBase + 0x2aa) = 0x00550055;
	*(pWalk)         = 0x00300030;

	// Data polling algorithm for erase operation
	// ******************************************
	bDone = FALSE;
	bFail = FALSE;

	while ((!bDone) && (!bFail))
	{
		nPoll = *(pWalk);
		if (((~nPoll) & FLASH_DQ7_2X16) == 0)
		{  
			bDone = TRUE;
		}
		else if ((nPoll & FLASH_DQ5_2X16) == FLASH_DQ5_2X16)
		{
			nPoll = *(pWalk);
			if (((~nPoll) & FLASH_DQ7_2X16) == 0)
			{
				bDone = TRUE;
			}
			else
			{
				bFail      = TRUE;
				bFailTotal = TRUE;
			}
		}
    }

	return (bDone?0:1);
}
        
// ***************************************************************************
//
//  Function:       FlashWrite
//
//                  This function programs data into flash memory. It is 
//                  assumed that the memory has been erased before calling
//                  this function.
//
//
//  Parameters:     U32             sAddress        start address for write
//                  U32*     	    pData           data to write
//                  U32             nData        	number of words to write
//                  
//  Return Value:   U32             number of bytes written or zero on error
//
// ***************************************************************************

/*U32 FlashWrite(U32 sAddress, 
               void* pData, 
               U32 nData)*/

void FlashWrite(u32 sAddress, u32* pData, u32 nData)
{
	volatile u32*       pBase;				// base address of the selected memory bank		
	volatile u32*       pWalk;				// flash programming pointer
	u32*                pWalkSrc;			// ram source pointer
	int                 bFailTotal;
	int                 bDone;
	int                 bFail;
	u32                 nWalk;
	u32                 nPoll;
	u32                 nDone;
	u32 				nAddress;  
	u32   			 	i=0;

	u32 Flash_Write			= 0x27272727;
 
	// Check the Flash Starting Address
	pBase = (volatile u32*)FLASH_BASE;

	// Reset flash devices before starting programming sequence
	// ********************************************************
	*(pBase + 0x000) = 0x00f000f0;

	// execute unlock bypass sequence 
	// ******************************************
	*(pBase + 0x555) = 0x00aa00aa;
	*(pBase + 0x2aa) = 0x00550055;
	*(pBase + 0x555) = 0x00200020;

	 
	// start the flash programming algorithm
	// **********************************************
		nWalk      = sAddress;
	pWalk      = (u32*) sAddress;
	pWalkSrc   = (u32*) pData;


	// nAddress = (((nData - 1) / sizeof(*pBase)) + 1) * sizeof(*pBase) + sAddress;
	nAddress = sAddress + sizeof(*pData)*(nData - 1);
 		
	while (nWalk <= nAddress){
		i++;
		if( (i&0xFFFF) == 0 ){
			printf("P");
			//CheckFlashComplete(Flash_Write);
		}
		// Execute unlock bypass program algorithm
		// ***************************************
		*(pBase + 0x555) = 0x00a000a0;
		*(pWalk)         = *(pWalkSrc);

		// Data polling algorithm for program operation
		// ********************************************
		bDone = FALSE;
		bFail = FALSE;
		bFailTotal = FALSE;
    		
		while ((!bDone) && (!bFail))
		{	
			nPoll = *(pWalk);
			if (((nPoll ^ *(pWalkSrc)) & FLASH_DQ7_2X16) == 0){
				bDone = TRUE;
			}
			else if ((nPoll & FLASH_DQ5_2X16) == FLASH_DQ5_2X16){
				nPoll = *(pWalk);
				if (((nPoll ^ *(pWalkSrc)) & FLASH_DQ7_2X16) == 0){
					bDone = TRUE;
				}
				else{
					bFail      = TRUE;
					bFailTotal = TRUE;
				}
			}
		}
		if (bDone == TRUE){
			nDone += sizeof(*pWalk);
		}

		nWalk += sizeof(*pWalk);
		pWalk++;
		pWalkSrc++;
	}
    	
	// Cancel unlock bypass mode
	// ************************************************
	*(pBase + 0x000) = 0x00900090;
		*(pBase + 0x000) = 0x00000000;

	// Reset flash devices
	// *******************
	*(pBase + 0x000) = 0x00f000f0;

}

u32	FlashVerify(u32 fAddress, u32 rAddress, u32 nWords)
{
	u32		i;
	u32		Errors = 0;
	u32*	fWalk;
	u32*	rWalk;
	u32		nAddress;
	
	u32 Flash_Verify		= 0x37373737;

	fWalk = (u32*)fAddress;
	rWalk = (u32*)rAddress;
	nAddress = fAddress + (nWords - 1) * sizeof(*fWalk);

//	printf("Flash Verifing at [0x%08X - 0x%08X]...\n", fAddress, nAddress);

	for (i = 0; i < nWords;i++)
	{ 
		if (*fWalk != *rWalk)
		{
			Errors++;	
		}
		fWalk++;
		rWalk++;
	}
	return Errors;
}

// ***************************************************************************
//
//  Function:       FlashChipErase
//
//                  This function erases all flash memory sectors 
//
//
//  Parameters:     U32             sAddress        start address for erase
//
//  Return Value:   BOOL           	chip erase success?
//                                  
//
// ***************************************************************************
int FlashChipErase(u32 sAddress)
{
	volatile u32*       pBase;
	int               	bDone;
	int                bFail;
	u32                 nPoll;
	u32					i = 0;

	// Check the Flash Starting Address
	pBase = (volatile u32*)FLASH_BASE;
			
	// Reset flash devices before chip erase
	// ***************************************
	*(pBase + 0x000) = 0x00f000f0;

	// Execute "normal" chip erase algorithm
	// ***************************************
	*(pBase + 0x555) = 0x00aa00aa;
	*(pBase + 0x2aa) = 0x00550055;
	*(pBase + 0x555) = 0x00800080;
	*(pBase + 0x555) = 0x00aa00aa;
	*(pBase + 0x2aa) = 0x00550055;
	*(pBase + 0x555) = 0x00100010;

	printf("Chip Erasing...\n");

	// Data polling algorithm for erase operation
	// ******************************************
	bDone = FALSE;
	bFail = FALSE;

	while ((!bDone) && (!bFail)){
		i++;
		if ((i & 0xFFFF) == 0){
			printf(".");
		}
		nPoll = *(pBase);
		if (((~nPoll) & FLASH_DQ7_2X16) == 0){
			bDone = TRUE;
		}
		else if ((nPoll & FLASH_DQ5_2X16) == FLASH_DQ5_2X16){
			nPoll = *(pBase);
			if (((~nPoll) & FLASH_DQ7_2X16) == 0){
			    bDone = TRUE;
			}
			else{
		    	bFail      = TRUE;
			}
		}
	}
	// Reset flash evices
	// *******************
	*(pBase + 0x000) = 0x00f000f0;

	printf("\nChip Erase Complete\n");
	return bFail;
}


// ***************************************************************************
//
//  Function:       FlashSectorErase
//
//                  This function erases all flash memory sectors overlapping
//                  the address range specified in the parameters.
//
//
//  Parameters:     U32             sAddress        start address for erase
//                  U32             nAddress        end address for erase
//
//  Return Value:   U32             number of bytes erased (rounded up to
//                                  next sector limit), or zero on error
//
// ***************************************************************************
u32 FlashSectorErase(u32 sAddress, u32 nAddress)
{
	volatile u32*       pBase;
	volatile u32*       pWalk;
	int                bFailTotal;
	int                bDone;
	int                bFail;
	u32                 nWalk;
	u32                 nSize;
	u32                 nPoll;
	u32                 nDone;
	u32                 nSec;
	u32					SA;
	u32					i = 0;

	u32 Flash_Erase			= 0x17171717;

	// Check the Flash Starting Address
	pBase = (volatile u32*)FLASH_BASE;


	// Reset flash devices before starting erase sequences
	// ***************************************************
	*(pBase + 0x000) = 0x00f000f0;

	nSec = (u32)pBase;
	nDone = 0;
	nWalk = sAddress;
	printf("Sector Erase at [0x%08X - 0x%08X]...\n",sAddress, nAddress);
		
	for (SA = 1; SA <= 270; SA++)
	{
		if ((SA >= 1 && SA <= 8) || (SA >= 263 && SA <= 270))
		{	
			nSize = 0x1000*4;
		}
		else
		{
			nSize = 0x8000*4;
		}
		
		if ((nSec <= nWalk) && (nSec + nSize > nWalk) && (nSec <= nAddress))
		{
			
			// This sector overlaps the address range. Erase it
			// ************************************************
			pWalk = (volatile u32*) nWalk;

			// Execute "normal" sector erase algorithm
			// ***************************************
			*(pBase + 0x555) = 0x00aa00aa;
			*(pBase + 0x2aa) = 0x00550055;
			*(pBase + 0x555) = 0x00800080;
			*(pBase + 0x555) = 0x00aa00aa;
			*(pBase + 0x2aa) = 0x00550055;
			*(pWalk)         = 0x00300030;


			// Data polling algorithm for erase operation
			// ******************************************
			bDone = FALSE;
			bFail = FALSE;

			while ((!bDone) && (!bFail))
			{
				nPoll = *(pWalk);
				if (((~nPoll) & FLASH_DQ7_2X16) == 0)
				{  
					bDone = TRUE;
				}
				else if ((nPoll & FLASH_DQ5_2X16) == FLASH_DQ5_2X16)
				{
					nPoll = *(pWalk);
					if (((~nPoll) & FLASH_DQ7_2X16) == 0)
					{
						bDone = TRUE;
					}
					else
					{
						bFail      = TRUE;
						bFailTotal = TRUE;
					}
				}
				if ( (i &= 0xFFFF) ==0)
				{
					printf(".");
					//CheckFlashComplete(Flash_Erase);
				}
				i++;
	        }
	        nDone += nSize;
	        nWalk += nSize;
	    }
	    nSec += nSize;
	}

	// Reset flash devices
	// *******************
	*(pBase + 0x000) = 0x00f000f0;

	return bFailTotal ? 0 : nDone;
}



int FlashProgram(u32 sAddress, u32* pData, u32 nData)
{
	static char sector[0x10000*4];
	u32 Sec_start, Sec_size, AvailableBytes;
	u32 offset;
	int repeat;
	char *src;
	int error;

	error = 0;
	repeat = nData * 4;

	while(repeat > 0){
		FlashSearchSector(sAddress, &Sec_start, &Sec_size);
		offset = sAddress - Sec_start;
		AvailableBytes = Sec_size*4 - offset;

		if (offset == 0){
			if (repeat >= AvailableBytes){
//				src = (char *)pData;
				src = &sector[0];
				memcpy(src, (char *)pData, Sec_size*4);
			}
			else{
				src = &sector[0];
				memcpy(src, (char *)Sec_start, Sec_size*4);
				memcpy(src, (char *)pData, repeat);
			}
		}
		else{
			if (repeat >= AvailableBytes){
				src = &sector[0];
				memcpy(src, (char *)Sec_start, Sec_size*4);
				memcpy((src+offset), pData, AvailableBytes);
			}
			else{
				src = &sector[0];
				memcpy(src, (char *)Sec_start, Sec_size*4);
				memcpy((src+offset), pData, repeat);
			}
		}
		
		FlashEraseSector(Sec_start);
		FlashWrite(Sec_start, (u32 *)src, Sec_size);
		error += FlashVerify(Sec_start, (u32)src, Sec_size);
		
		repeat -= AvailableBytes;
		sAddress += AvailableBytes;
		pData += (AvailableBytes/4);

	}
	return error;
}



// ***************************************************************************
//
//  Function:       FlashRead
//

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -