007_mini2440裸机norflash

#include "my_printf.h"
#include "string_utils.h"
#include "norflash.h"
#include "uart_init.h"


#define NOR_FLASH_BASE  0  				//norflash接到nGCS0因此其基地址为0x0000_0000

void norflash_test(void)
{
	char c;
	while(1)
	{
		printf("[s] Scan norflash\n\r") ;	//打印菜单供我们选择测试内容
		printf("[e] Erase norflash\n\r");
		printf("[w] Write norflash\n\r");
		printf("[r] Read norflash\n\r");
		printf("[q] quit\n\r");
		printf("Enter selection: ");

		c = my_getchar();					//通过串口发送数据给ARM选择测试项目
		printf("%c\n\r",c);				    //通过串口把接收数据发送给电脑显示
	
		/*********************************
		测试内容
		1、识别norflash
		2、擦除norflash某个扇区
		3、指定地址写数据
		4、指定地址读数据
		*********************************/
		switch(c)
		{
			case 's':
			case 'S':	
				scan_norflash();
				break;
		
			case 'e':
			case 'E':	
				erase_norflash();
				break;
		
			case 'w':
			case 'W':	
				write_norflash();
				break;
		
			case 'r':
			case 'R':	
				read_norflash();
				break;
		
			case 'q':
			case 'Q':	
				break;
		
			defalut:	
				break;
		}
		
	}
}

void norflash_write_word(unsigned int base, unsigned int offset, unsigned int data)
{
	volatile unsigned short int *p = (volatile unsigned short int *)(base + (offset << 1));
	*p = data;
}

unsigned short int norflash_read_word(unsigned int base, unsigned int offset)
{
	volatile unsigned short int *p = (volatile unsigned short int *)(base + (offset << 1));
	return *p;
}


void wait_ready(unsigned int addr)
{
	unsigned int val;
	unsigned int pre;

	pre = norflash_read_word(NOR_FLASH_BASE,addr>>1);
	val = norflash_read_word(NOR_FLASH_BASE,addr>>1);
	while ((val & (1<<6)) != (pre & (1<<6)))
	{
		pre = val;
		val = norflash_read_word(NOR_FLASH_BASE,addr>>1);		
	}
}


void scan_norflash(void)
{
	unsigned short int vecdor_id = 0,device_id = 0;
	char str[4];		        //读除CFI模式的标志数据
	unsigned int size;          //获取norflash的尺寸大小
	unsigned int regions;       //获取region个数
	unsigned int regions_base;  //获取region基地址
	int i,j,count;
	unsigned int blocks;        //获取block个数
	unsigned int block_size;    //获取block容量
	unsigned int block_addr;    //获取block地址
	/*
	1、获得norflash厂家ID、设备ID
	2、获取norflash容量的大小
	3、获取每个block的起始地址
	*/

	/*
	1、读厂家ID和设备ID
	由于CPU的地址总线从A1开始接的flash地址线的A0因此需要左移一位
	AAH(数据) ----> 555H(flash地址) ----> (555H<<1)(CPU给出的地址信息)
	55H(数据) ----> 2AAH(flash地址) ----> (2AAH<<1)(CPU给出的地址信息)
	90H(数据) ----> 555H(flash地址) ----> (555H<<1)(CPU给出的地址信息)
	A1=0, A0 = 0 for manufacturer code,A1=0, A0 = 1 for device code.
	DDI = Data of Device identifier : C2H for manufacture code, 22DA/DA(Top), and 225B/5B(Bottom) for device code.
	*/
	norflash_write_word(NOR_FLASH_BASE,0x555,0xAA);
	norflash_write_word(NOR_FLASH_BASE,0x2AA,0x55);
	norflash_write_word(NOR_FLASH_BASE,0x555,0x90);

	vecdor_id = norflash_read_word(NOR_FLASH_BASE,0);
	device_id = norflash_read_word(NOR_FLASH_BASE,1);
	printf("vecdor_id = 0x%x,device_id = 0x%x\n\r",vecdor_id,device_id);
	
	/*
	1、获取norflash存储容量的大小
	2、获取regions的数量(一个norflash含有一个或者多个region一个region含有一个或者多个block)
	3、Erase block region information(前2字节+1: 表示该region有多少个block,后2字节*256:表示block的大小)
	4、打印各个扇区的起始地址
	*/
	norflash_write_word(NOR_FLASH_BASE, 0x0,0xF0);				//复位norflash
	norflash_write_word(NOR_FLASH_BASE,0x55,0x98);		        //进入CFI模式
	
	str[0] = (char)norflash_read_word(NOR_FLASH_BASE,0x10);     //读出CFI标识QRY
	str[1] = (char)norflash_read_word(NOR_FLASH_BASE,0x11);
	str[2] = (char)norflash_read_word(NOR_FLASH_BASE,0x12);
	str[3] = '\0';
	printf("str = %s\n\r",str);

	size = 1 << (norflash_read_word(NOR_FLASH_BASE,0x27)); 	    //获取norflash的空间大小
	regions = norflash_read_word(NOR_FLASH_BASE,0x2C);		    //获取region的数量
	printf("size = %dM,regions = %d\n\r",size/(1024*1024),regions);

	printf("Block/Sector start Address:\n\r");					//打印各个扇区的起始地址
	regions_base = 0x2D;										//regions基地址
	block_addr = 0;
	for (i = 0; i < regions; i++)
	{
		blocks = 1 + norflash_read_word(NOR_FLASH_BASE,regions_base) + (norflash_read_word(NOR_FLASH_BASE,regions_base + 1)<<8);
		block_size = 256 * (norflash_read_word(NOR_FLASH_BASE,regions_base + 2) + (norflash_read_word(NOR_FLASH_BASE,regions_base + 3)<<8));
		regions_base += 4;
		for (j = 0; j < blocks; j++)
		{
			printHex(block_addr);
			my_putchar(' ');
			count++;
			block_addr += block_size;
			if (count % 5 == 0)
				printf("\n\r");
		}
	}
	printf("\n\r");
	norflash_write_word(NOR_FLASH_BASE, 0x0,0xF0);				//复位norflash
}

void erase_norflash(void)
{
	unsigned int addr;

	printf("Enter the address of sector to write: "); //从串口获取擦除数据地址
	addr = get_uint();

	printf("erasing ...\n\r");
	norflash_write_word(NOR_FLASH_BASE,0x555, 0xAA); //解锁
	norflash_write_word(NOR_FLASH_BASE,0x2AA, 0x55); 
	norflash_write_word(NOR_FLASH_BASE,0x555, 0x80);	 
	
	norflash_write_word(NOR_FLASH_BASE,0x555, 0xAA);   //解锁
	norflash_write_word(NOR_FLASH_BASE,0x2AA, 0x55); 
	norflash_write_word(NOR_FLASH_BASE,addr>>1, 0x30);	 	           //发出扇区地址 
	wait_ready(addr);
}

void write_norflash(void)
{
	unsigned int addr;
	unsigned char str[100];
	int i, j;
	unsigned int val;
	
	
	printf("Enter the address of sector to write: ");  //获得地址 
	addr = get_uint();
	printf("Enter the string to write: ");
	gets(str);

	printf("writing ...\n\r");

	i = 0;
	j = 1;
	while(str[i] && str[j])
	{
		val = str[i] + (str[j]<<8);
		
		norflash_write_word(NOR_FLASH_BASE,0x555, 0xaa);	//解锁 
		norflash_write_word(NOR_FLASH_BASE,0x2aa, 0x55); 
		norflash_write_word(NOR_FLASH_BASE,0x555, 0xa0);	
		norflash_write_word(NOR_FLASH_BASE,addr>>1, val);
		
		wait_ready(addr);	   //等待烧写完成 : 读数据, Q6无变化时表示结束 

		i += 2;
		j += 2;
		addr += 2;
	}
	val = str[i];
	norflash_write_word(NOR_FLASH_BASE,0x555, 0xaa);	 //解锁 
	norflash_write_word(NOR_FLASH_BASE,0x2aa, 0x55); 
	norflash_write_word(NOR_FLASH_BASE,0x555, 0xa0);	 
	norflash_write_word(NOR_FLASH_BASE,addr>>1, val);
	wait_ready(addr);      //等待烧写完成 : 读数据, Q6无变化时表示结束
}

void read_norflash(void)
{
	unsigned int addr;
	printf("Enter the address to read:");
	volatile unsigned char *p;
	int i, j;
	unsigned char c;
	unsigned char str[16];
	
	addr = get_uint();		//从串口里面获得地址

	p = (volatile unsigned char *)addr;
	
	/*
	1、长度固定读取的数据长度为64个字符 
	*/	
	for(i=0;i<4;i++)			 
	{
		for(j=0;j<16;j++)	//每行打印16个数据 
		{
			c = *p++;
			str[j] = c;
			printf("%02x ",c);		//先打印数值 
		}
		printf("   ; ");
		for (j=0;j<16;j++)    //后打印字符
		{
			if (str[j]<0x20 || str[j]>0x7e)  
				my_putchar('.');
			else
				my_putchar(str[j]);
		}
		printf("\n\r");
	}
}

编写程序时遇到的问题:
1、编译程序时必须加上-march=armv4,否则volatile unsigned short *p = xxx;会被拆分成2个strb操作。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Da Liu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值