#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操作。