norflash的读,写,擦除操作,不能进入CFI模式,不然会有问题。
先说读吧,
先写出工具代码吧。因为地址是word是16位的,所以用unsigned int。
#include "my_printf.h"
#include "string_utils.h"
#define BASE 0
/*读命令*/
unsigned int read_nor(unsigned int base , unsigned int offset )
{
volatile unsigned short *p =( volatile unsigned short *)(base + (offset << 1)); //offset<< 1是因为,这个offset是基于norflash的角度看的,nor_addr0对于cpu_addr1;
return *p;
}
unsigned int do_read_nor(unsigned int offset )
{
return read_nor(BASE,offset);
}
void write_nor(unsigned int base , unsigned int offset , unsigned int data)
{
volatile unsigned short *p =( volatile unsigned short *)(base + (offset << 1));
*p = data;
}
void do_write_nor(unsigned int offset , unsigned int data)
{
write_nor(BASE,offset,data);
}
/*****************************************************************读操作**********************************************************/
void read_norflash()
{
int i,j;
unsigned char string[16],c;
unsigned int addr;
volatile unsigned char *p ;
printf("please input addr to read");
addr = get_uint();
p = (volatile unsigned char *)addr;
for(i = 0 ;i < 4;i++ )
{
for(j = 0 ;j < 16 ;j++ )
{
c = *p++;;
string[j] = c;
printf("%02x ",c);
}
puts(" ;");
for(j = 0 ;j < 16 ;j++ )
{
/*判断是否是可见字符*/
if(string[j] < 0x20||string[j] > 0x7e)
{
putchar('.');
}
else
putchar(string[j]);
}
puts("\n\r"); //每16个数据换行
}
}
/**************************************************************写操作**********************************************************************/
void write_norflash()
{
unsigned int addr,data;
int i,j;
unsigned char string[100];
printf("please input addr\n\r");
addr = get_uint();
printf("please input data\n\r");
gets(string);
i=0,j=1;
while(string[i]&&string[j])
{
data = string[i] + (string[j] << 8);
do_write_nor(0x555,0xaa);//开启写模式
do_write_nor(0x2aa,0x55);
do_write_nor(0x555,0xa0);
do_write_nor(addr>>1,data);
wait_nor(addr);
addr+=2;
i+=2,j+=2;
}
data = string[i];
do_write_nor(0x555,0xaa);//开启写模式
do_write_nor(0x2aa,0x55);
do_write_nor(0x555,0xa0);
do_write_nor(addr>>1,data); ///////这里因为我们原本就是基于nor的角度,所以写nor原本就好了,>>与<<抵消;
printf("writing!.....\n\r");
/*还要写等待一下下*/
wait_nor(addr);
}
/***************************************************擦除操作**********************************************************/
void erase_norflash()
{
unsigned int addr ;
printf("input the addr to erase \n\r");
addr = get_uint();
do_write_nor(0x555,0xaa);//解锁
do_write_nor(0x2aa,0x55);
do_write_nor(0x555,0x80);
do_write_nor(0x555,0xaa);
do_write_nor(0x2aa,0x55);
do_write_nor(addr>>1,0x30); //擦除
/*等待*/
wait_nor(addr);
printf("erase!.....\n\r");
}
/*****************************************************等待地址是否操作完成***************************************************/
void wait_nor(unsigned int addr)
{
unsigned int val , p;
val = do_read_nor(addr >>1);
p = do_read_nor(addr >>1);
while((val&(1 <<6))!=(p&(1 <<6))) /////////////////////
{
p = val;
val = do_read_nor(addr >>1);
}
}
/***********************************************************菜单***************************************************************/
void nor_test()
{
char c;
while(1)
{
printf("input the [r] is read nor \n\r");
printf("input the [w] is write nor \n\r");
printf("input the [c] is check nor \n\r");
printf("input the [e] is erase nor \n\r");
printf("input the [q] is quit nor \n\r");
c = getchar();
printf("%c\n\r",c);
switch(c)
{
case 'r':
case 'R':
read_norflash();
break;
case 'w':
case 'W':
write_norflash();
break;
case 'E':
case 'e':
erase_norflash();
break;
case 'c':
case 'C':
nor_check();
break;
case 'Q':
case 'q':
default :break;
}
}
}
最重要的一点就是Makefile,如果你这样写了的话,只能读,还是对nor写不了和擦除不了,因为他的指令烧写错误了,我们没有写错,是编译器对字节没有处理好,导致最终的指令不对,所以也就解锁不了。
all: start.o led.o uart.o init.o main.o exception.o interrupt.o timer.o norflash_test.o my_printf.o string_utils.o lib1funcs.o
#arm-linux-ld -Ttext 0 -Tdata 0x30000000 start.o led.o uart.o init.o main.o -o sdram.elf
arm-linux-ld -T sdram.lds $^ -o sdram.elf
arm-linux-objcopy -O binary -S sdram.elf sdram.bin
arm-linux-objdump -D sdram.elf > sdram.dis
clean:
rm *.bin *.o *.elf *.dis
%.o : %.c
arm-linux-gcc -march=armv4 -c -o $@ $< #这里要加个 -march=armv4
%.o : %.S
arm-linux-gcc -march=armv4 -c -o $@ $< #这里要加个 -march=armv4
看我们这个写工具函数。
使用了strb 一个字节一个字节的写,我们是16位的,我们想要的是一次性先16位,用str或ldr.
当我们加上-march=armv4之后。
看他通过ldr,所以这样就可以一下传16位。这样就指令不会出错。