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

📄 flash.c

📁 在ARM ADS开发环境下,做的一个通过串口下载接收bootloader的程序,包含对flash的操作.
💻 C
字号:
/////////////////////////////////////////////////////////////////////////////////
// Copyright(c) 2001-2002 Hybus Co,.ltd. All rights reserved.
//
// Module name:
//      flash.c
//
// Description:
//
//
// Author:
//      bedguy
//
// Created:
//      2002.10
//
///////////////////////////////////////////////////////////////////////////////

#include "flash.h"
//#include "stdio.h"



#ifdef XHYPER255A
#define IT(x) 	(*((volatile unsigned short *)(x)))
#else
#define IT(x) 	(*((volatile unsigned int *)(x)))
#endif

typedef enum {
	ACT_PGM,
	ACT_ERASE,
	ACT_LOCK,
	ACT_UNLOCK,
	ACT_WRITE_BUF
} FLASH_ACTION;
	

bool			EraseFlashBlocks(FUNIT *addr, ulong len);
static bool		EraseOneFlashBlock(FUNIT *addr);
static bool		FlashLock(FUNIT *addr);
static bool		FlashUnlock(void);
bool			FullStatusCheck(volatile FUNIT *addr, FLASH_ACTION which);

bool DoWriteToFlashBlocks(CMD_TBL *cptr, int argc, char **argv){
	long	dest=0, src=0, len, wsize;
	
	switch (argc){
		case 2 :
			if (!StrCmp(argv[1], "kernel")){
				dest = (long)KERNEL_SRAM_BASE;
				src  = (long)KERNEL_DRAM_BASE;
				len  = (long)KERNEL_MAX_SIZE;
				printf("Saving kernel to flash...\n");
			}
			else if (!StrCmp(argv[1], "root")){
				dest = (long)ROOT_SRAM_BASE;
				src  = (long)ROOT_DRAM_BASE;
				len  = (long)ROOT_MAX_SIZE;
				printf("Saving root to flash...\n");
			}
			else if (!StrCmp(argv[1], "loader")){
				dest = (long)LOADER_SRAM_BASE;
				src  = (long)LOADER_DRAM_BASE;
				len  = (long)LOADER_MAX_SIZE;
				printf("Saving bootloader to flash...\n");
			}

			else {
				printf(cptr->usage);
				return false;	
			}
			break;
		// "flash [dest] [src] [len]".
		case 4 :
			if (!HexToInt(argv[1], &dest, 32) || !HexToInt(argv[2], &src, 32) ||
					!HexToInt(argv[3], &len, 32)){
				printf(cptr->usage);
				return false;
			}
			if (dest % FLASH_BLOCK_SIZE){
				printf("dest is not Flash Block Base.\n");
				return false;
			}
			break;
		default :
			printf(cptr->usage);
			return false;
			break;
	}

	// erase flash blocks.
	printf("Erase flash blocks from 0x%08lx to 0x%08lx.\n", dest, (long)dest+len-1);
	if (!EraseFlashBlocks((FUNIT *)dest, len)) return false;
	printf("\tDone.\n");

	// write to flash.
	printf("Write to flash...\n");

	wsize = FLASH_BLOCK_SIZE;

    do{
            printf("\tWriting at 0x%08lx...", (ulong)dest);
            if (!WriteToFlashBuffer((FUNIT *)dest, (FUNIT *)src)) break;

            dest += FLASH_BLOCK_SIZE;
            src += FLASH_BLOCK_SIZE;
			ClearLine();
    } while((len -= FLASH_BLOCK_SIZE) >0);

	printf("\tWriting at 0x%08lx\r\n", (ulong)dest);
	printf("\tDone\n");

	IT(dest) = FlashCMD(READ_ARRAY);	
	return true;
}	// DoWriteToFlashBlocks.



bool WriteToFlashBuffer(void *dest, void *src){
#ifdef XHYPER255A
	int             i;
        volatile FUNIT *s1=dest, *s2=src, result, *end=s1+(FLASH_BLOCK_SIZE/FBOUND);
        ushort writeBuf = 32;

        while (s1<end){ 
                *s1 = FlashCMD(WRITE_BUF);                      

                do {
                        *s1 = FlashCMD(STATUS_READ);
                        result = *s1; 
                 } while  ((~result & STATUS_BUSY));                     

                *s1 = (writeBuf)/2 - 1;

                for (i=0; i<(writeBuf)/FBOUND; i++)
			*s1++ = *s2++;

		IT((s1)) = FlashCMD(WRITE_BUF_COMFIRM);

		do {
			result = IT(s1);
		} while((result & STATUS_BUSY ) != STATUS_BUSY);
		IT(s1) = FlashCMD(READ_ARRAY);
        }
#else
	ulong		i=0;
	volatile uchar *s1=(uchar *)dest; 
	uchar *s2=(uchar *)src;
	
	ushort  writeBuf = 32;
		
	while(i < FLASH_BLOCK_SIZE)
	{
		int cnt = writeBuf / sizeof(ushort);
		int result;
			
		do {
			IT(s1) = WRITE_BUF;
			result = IT(s1);
		} while((result & STATUS_BUSY ) != STATUS_BUSY);

		IT(s1) = FlashCMD((writeBuf / sizeof(ushort) -1) | \
				((writeBuf / sizeof(ushort) -1 ) << (sizeof(ulong) * 4)));

		while(cnt--)
		{
				IT((s1+i)) = IT(s2);
				i += sizeof(ulong);
				s2 += sizeof(ulong);
		}
		IT((s1)) = FlashCMD(WRITE_BUF_COMFIRM);

		do {
			result = IT(s1);
		} while((result & STATUS_BUSY ) != STATUS_BUSY);

		IT(s1) = FlashCMD(READ_ARRAY);
	}
#endif
	return true;
}



bool EraseFlashBlocks(FUNIT *addr, ulong len){
	FUNIT	*ptr, *end=addr+len/FBOUND;

	// erase block loop.
	for (ptr=addr; ptr<end; ptr+=FLASH_BLOCK_SIZE/FBOUND){
		ClearLine();
		printf("\tErase Block at : 0x%08lx.", (long)ptr);
		// erase block.
		if (!EraseOneFlashBlock(ptr)){
			return false;
		}
	}
	printf("\n");
	return true;
}






bool DoEraseFlashBlocks(CMD_TBL *cptr, int argc, char **argv){
	ulong	addr=0, len, end;
	
	switch (argc){
        case 2 :
            if (!StrCmp(argv[1], "kernel")){
                addr = (long)KERNEL_SRAM_BASE;
                len  = (long)KERNEL_MAX_SIZE;
            }
            else if (!StrCmp(argv[1], "root")){
                addr = (long)ROOT_SRAM_BASE;
                len  = (long)ROOT_MAX_SIZE;
            }
            else if (!StrCmp(argv[1], "loader")){
                addr = (long)LOADER_SRAM_BASE;
                len  = (long)LOADER_MAX_SIZE;
            } 
            else {
                printf(cptr->usage);
                return false;
            }
			if ((long)addr%FLASH_BLOCK_SIZE){
				printf("addr is not flash block base.\n");
				return false;
			}

		    // erase flash blocks.
		    printf("Erase flash blocks from 0x%08lx to 0x%08lx.\n", addr, (long)addr+len-1);
		    if (!EraseFlashBlocks((FUNIT *)addr, len)) return false;

		    printf("\tDone.\n");	
        
		    break;

			// "erase [addr] [len]".
	case 3 :
		// error.
		if (!HexToInt(argv[2], &len, 32)){
			printf(cptr->usage);
			return false;
		}
		if ((long)addr%FLASH_BLOCK_SIZE){
			printf("addr is not flash block base.\n");
			return false;
		}

		// erase flash blocks.
		end = addr + len;
		for (; addr<end; addr+=FLASH_BLOCK_SIZE){
			if (!EraseOneFlashBlock((FUNIT *)addr)) return false;
		}
		break;
	// error.
	default :
		printf(cptr->usage);
		return false;
		break;
	}
	return true;
}	// DoEraseOneFlashBlock.







static bool EraseOneFlashBlock(FUNIT *addr){
	volatile FUNIT	*s=addr;

	// error.
	if ((long)addr%FLASH_BLOCK_SIZE) return false;
	
	// do command.
	*s = FlashCMD(ERASE_SETUP);
	*s = FlashCMD(ERASE_CONFIRM);

	if (!FullStatusCheck(s, ACT_ERASE)) return false;
	return true;
}	// EraseOne.







bool DoFlashLock(CMD_TBL *cptr, int argc, char **argv){
	long	i, addr, len, cnt;
	// error.
	if (argc < 2){
		printf(cptr->usage);
		return false;
	}

	switch (argc){
		// "lock [addr]".
		case 2 :
			if (!StrCmp(argv[1], "loader")){
				addr = (long)LOADER_SRAM_BASE;
				len  = (long)LOADER_SRAM_MAX_SIZE;
			}
			else if (!StrCmp(argv[1], "kernel")){
				addr = (long)KERNEL_SRAM_BASE;
				len  = (long)KERNEL_MAX_SIZE;
			}
			else if (!StrCmp(argv[1], "root")){
				addr = (long)ROOT_SRAM_BASE;
				len  = (long)ROOT_MAX_SIZE;
			}
			else {
				if (!HexToInt(argv[1], &addr, 32)){
					printf(cptr->usage);
					return false;
				}
				len = (long)FLASH_BLOCK_SIZE;
			}
			break;
		// "lock [addr] [len]".
		default :
			printf(cptr->usage);
			return false;
			break;
	}
	// lock of flash blocks.
	cnt = len/FLASH_BLOCK_SIZE + ((len&(FLASH_BLOCK_SIZE-1)) ? 1 : 0);
	for (i=0; i<cnt; i++, addr+=FLASH_BLOCK_SIZE){
		if (!FlashLock((FUNIT *)addr)) return false;
	}
	return true;
}	// DoFlashLock.


bool DoFlashUnlock(CMD_TBL *cptr, int argc, char **argv){
	// error.
	if (argc != 1){
		printf(cptr->usage);
		return false;
	}

	// Unlock of whole flash blocks.
	if (!FlashUnlock()) return false;
	return true;
}	// DoFlashUnlock.


bool FlashLock(FUNIT *addr){
	volatile FUNIT	*s=addr;

	// error.
	if ((long)addr % FLASH_BLOCK_SIZE){
		printf("addr is not flash block base.\n");
		return false;
	}
	
	// do command.
	*s = FlashCMD(FLASH_SETUP);
	*s = FlashCMD(BLOCK_LOCK_BIT_SET);
	
	if (!FullStatusCheck(s, ACT_LOCK)) return false;
	return true;
}	// FlashLock.


bool FlashUnlock(void){
	volatile FUNIT	*s=(FUNIT *)FLASH_BASE;

	// do command.
	*s = FlashCMD(FLASH_SETUP);
	*s = FlashCMD(BLOCK_LOCK_BIT_CLEAR);
	
	if (!FullStatusCheck(s, ACT_UNLOCK)) return false;
	return true;
}	// FlashUnlock.



// error啊 乐栏搁 false, 酒聪搁 true return.
bool FullStatusCheck(volatile FUNIT *addr, FLASH_ACTION which){
	FUNIT	result;
	
	// delay before command is done.
	do {
		*addr = FlashCMD(STATUS_READ);
		result = *addr;
	} while  ((~result & STATUS_BUSY));
	*addr = FlashCMD(READ_ARRAY);

	return true;
	// if no error, return true.
	if ((result & STATUS_ERR_FILTER) == 0) return true;

	// if error, print out error message.
	if (result & STATUS_LOCK_DETECT){
		printf("Block Lock-bit detected.\n\n");
	} else if (result & STATUS_VOLT_RANG_ERR){
		printf("Voltage Range Error.\n\n");
	} else if ((result & STATUS_CMD_SEQ_ERR) == STATUS_CMD_SEQ_ERR){
		printf("Command Sequence Error.\n\n");
  	} else if ((result & STATUS_PGM_ERR) && ACT_PGM){
  	printf("\nWrite error at address 0x%08lx\n\n", (long)addr);
	} else if ((result & STATUS_LOCK_ERR) && ACT_LOCK){
		printf("Set Lock-Bit Error.\n\n");
	} else if ((result & STATUS_ERASE_ERR) && ACT_ERASE){
		printf("Fail to erase. retry again.\n\n");
	} else if ((result & STATUS_UNLOCK_ERR) && ACT_UNLOCK){
		printf("Clear Lock-Bit Error.\n\n");
	}
	else {
		printf("Unknown Error.\n\n");
	}

	*addr = FlashCMD(STATUS_CLEAR);
	*addr = FlashCMD(READ_ARRAY);
	return true;
}











/////WriteProToFlash(FLASH_BLOCK_SIZE*2);
  
bool WriteProToFlash(int file_len)

{


  //  FILE    *fp;
	
	long	dest=0, src=0,len,i;
	
	
	FUNIT	*s,c;

	//long    buffer=0x1212; 
	
	  
	
	  ////????
	
   // char * string = "12345678901234567890";
	
	//char * string1 = "\n\nThis is my first embody program!\nPlease send file.....\n\n";
	////
	//char  cc='a';
	
  //  int num;
    
 
    len=file_len;	///0x80000
    
  
    
	dest = (long)LOADER_SRAM_BASE;////#define LOADER_SRAM_BASE		(0x00000000)
	
	
	
	src  = (long)KERNEL_DRAM_BASE;////#define KERNEL_DRAM_BASE		(0xA0008000)
	
	
///	EraseFlashBlocks((FUNIT *)dest, len);	
		
	//s=(FUNIT *)src;
	
	
	//s=(FUNIT *)dest;
	
	
	
	//*(s)=*string;
	 







	 
	/* 
	for(i=0;i<4;i++)
	
	{ 
	
	
	
	
	WriteToFlashBuffer((FUNIT *)dest, (FUNIT *)src);
	 
	// string++;
	 
	 
	 //s++;
	 
	 
	// s=(FUNIT *)src;
	
	dest++;
	
	src++;
	
	
	
	
	// *(s)=*string;
	 
	
	
	 
	}
	
	
*/
	

	
	
	


	
	
	
	
	
	
	
	//num=file_len/FLASH_BLOCK_SIZE;
	
	
	
	
	//len=(num+1)*FLASH_BLOCK_SIZE;
	
	
	
	



	
	
/*	
	s=(FUNIT *)src;
	*(s)=buffer;
	
	
	                //#define KERNEL_DRAM_BASE	(0xA0008000)
	             
	             
	src  = (long)(KERNEL_DRAM_BASE+FLASH_BLOCK_SIZE);///#define FLASH_BLOCK_SIZE	         SRAM_BLOCK_SIZE
	                                                  ///#define SRAM_BLOCK_SIZE			(0x00040000)
	
	
*/







	 
	 
	 
	 
	 
	 /*
	for(i=0;i<100;i++)
	 {
	  *(s+i)=cc;
	  }
	  
	s=(FUNIT *)src;
	for(i=0;i<len;i++)
	 {
	  c=*(s+i);
	 // printf(" %FUNIT ",c);
	 // SerialOutputByte(c);
	 }
	
	 */ 
	 




	 
/*	 
	 src  = (long)KERNEL_DRAM_BASE;	///#define KERNEL_DRAM_BASE		(0xA0008000)	
	 s=(FUNIT *)src;///define  FUNIT long
	 
*/


	 
	 
	 
	 
	printf("\nErase flash blocks from 0x%08lx to 0x%08lx.\n", dest, (long)dest+len-1);
	
	
	if (!EraseFlashBlocks((FUNIT *)dest, len)) return false;////如果函数EraseFlashBlocks返回0,则return false
	printf("\tDone.\n");





	// write to flash.
	printf("\nWrite to flash...\n");     ///否则输出"正在写到flash"
	
	

	do{
            
            
            printf("\tWriting at 0x%08lx...", (ulong)dest);
            
            
            
            if (!WriteToFlashBuffer((FUNIT *)dest, (FUNIT *)src)) break;

             ///是一个block 一个block的写!不是一个字节一个字节的写
            
            printf("\tWriting at 0x%08lx\r\n", (ulong)dest);
            
            
            
            dest += FLASH_BLOCK_SIZE;
            
            
            
            src += FLASH_BLOCK_SIZE;
            
            
            
            
			ClearLine();
			
			
    } while((len -= FLASH_BLOCK_SIZE) >0);
    
    
    
    

	//printf("\tWriting at 0x%08lx\r\n", (ulong)dest);
	printf("\tDone\n");






















/////#define IT(x) 	(  *(  (volatile unsigned int *)(x)  )  )


/*

	IT(dest) = FlashCMD(READ_ARRAY);    /////#define FlashCMD(A)		((FUNIT)(A))
	

		
	dest = (long)LOADER_SRAM_BASE;
	s=(FUNIT *)dest;

	
	num=file_len/FLASH_BLOCK_SIZE;
	
	len=(num+1)*FLASH_BLOCK_SIZE;
	
*/	
	













	
	
	
	
	
	
	
	
	while(1);
	
	
	
	
	
	
	
/*	
	
	printf("\nread flash content...\n");
	// ReadCharsFromFlash(s,file_len);
	return true;
	
*/	
	
	
	
	
}






















bool    ReadCharsFromFlash(void *pro_dest, ulong pro_len){

    ulong     i;
    FUNIT	*dest,c;	
	
	dest=(FUNIT	*)pro_dest;
	
	
	 
   IT(dest) = FlashCMD(READ_ARRAY);
  
   for(i=0;i<=pro_len;i++)
    {
     c=*(dest+i);
     printf("%c",c);
    } 
   printf("\nread done!");
    return true;
}

void save_file(char c,uint len)
{
 long	src=0;
 FUNIT	*s;
 src  = (long)KERNEL_DRAM_BASE;
 s=(FUNIT *)src;
  *(s+len)=c;
}

⌨️ 快捷键说明

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