Norflash and nandflash are non-volatile flash memories implemented using different technologies. Their respective characteristics will not be introduced here, but only the operation of norflash by s3c2440 will be explained. The norflash we use is EN29LV160AB. In fact, there is little difference in the reading and writing operations of various types of norflash.
The operations of norflash are mainly read, write, erase and identify. The data width of EN29LV160AB can be 8-bit byte or 16-bit word, which is realized by a pin configuration of EN29LV160AB. Here we select the word.
The read operation of norflash is relatively simple. The system will automatically enter the read mode after power-on, and no additional commands are required to implement the read operation. The following function implements the read operation:
U16 read_en29lv160ab(U32 addr)
{
return *((volatile U16 *)(addr));
}
Norflash can not only implement hardware reset, but also software reset. The operation of software reset is to write the reset command 0xF0 to any address. The following function implements software reset:
void reset_en29lv160ab(void)
{
*((volatile U16 *)0x0) = 0xf0;
}
The erase and write operations of norflash are slightly more complicated. They require 4 or 6 cycles to complete. Each cycle requires writing the corresponding command into a command register in norflash. The write operation process is that the first cycle is to write the command 0xAA into the command register with address 0x555, the second cycle is to write the command 0x55 into the command register with address 0x2AA, the third cycle is to write the command 0xA0 into the command register with address 0x555, and the fourth cycle is to actually write the data to be written into the address of norflash. The following function implements the write operation, in which the two input parameters of the function are the data and address to be written. For convenience, we define the command register in advance:
#define flash_base 0x00000000
#define CMD_ADDR0 *((volatile U16 *)(0x555<<1+flash_base))
#define CMD_ADDR1 *((volatile U16 *)(0x2aa<<1+flash_base))
U8 en29lv160ab_program(U32 addr, U16 dat)
{
CMD_ADDR0 = 0xaa;
CMD_ADDR1 = 0x55;
CMD_ADDR0 = 0xa0;
*((volatile U16 *)(addr)) = dat;
return check_toggle();
}
Since we connected norflash to bank 0 of s3c2440, the base address of norflash is 0x00000000 relative to s3c2440. The reason why we shifted the address in norflash to the left (i.e. multiplied by 2) is because we connected ADDR1 of s3c2440 to A0 of norflash. In this function, we also called the check_toggle function, which is used to determine whether the operation is correct. Its prototype is:
U8 check_toggle()
{
volatile U16 newtoggle,oldtoggle;
oldtoggle = *((volatile U16 *)0x0);
while(1)
{
newtoggle = *((volatile U16 *)0x0);
if((oldtoggle & 0x40)==(newtoggle & 0x40))
break;
if(newtoggle & 0x20) //DQ5
{
oldtoggle = *((volatile U16 *)0x0);
newtoggle = *((volatile U16 *)0x0);
if((oldtoggle & 0x40)==(newtoggle & 0x40))
break;
else
return 0; //error
}
oldtoggle = newtoggle;
}
return 1; //Correct
}
Its principle is to read the data on the data bus twice in succession to determine whether the 6th bit value (DQ6) on the data bus is flipped. If it is not flipped, it is correct. Otherwise, the 5th bit (DQ5) must be judged to determine whether the flip is caused by timeout.
The write operation can only change "1" to "0", and only the erase operation can change "0" to "1". Therefore, you must erase before writing. Erasing is divided into block erase and whole chip erase. The process of block erase is that the first cycle is to write the command 0xAA to the command register with address 0x555, the second cycle is to write the command 0x55 to the command register with address 0x2AA, the third cycle is to write the command 0x80 to the command register with address 0x555, the fourth cycle is to write the command 0xAA to the command register with address 0x555, the fifth cycle is to write the command 0x55 to the command register with address 0x2AA, and the sixth cycle is to write the command 0x30 to the first address of the block to be erased. The following function is block erase, where the input parameter is the first address of the block to be erased:
U8 en29lv160ab_sector_erase(U32 section_addr)
{
CMD_ADDR0 = 0xaa;
CMD_ADDR1 = 0x55;
CMD_ADDR0 = 0x80;
CMD_ADDR0 = 0xaa;
CMD_ADDR1 = 0x55;
*((volatile U16 *)(section_addr)) = 0x30;
return check_toggle();
}
Another common operation for norflash is to read the chip ID. The process of reading the manufacturer ID is that the first cycle is to write the command 0xAA to the command register at address 0x555, the second cycle is to write the command 0x55 to the command register at address 0x2AA, the third cycle is to write the command 0x90 to the command register at address 0x555, and the fourth cycle is to read the content at address 0x100, that is, the manufacturer ID (0x1C). The first three cycles of the process of reading the device ID are the same as reading the manufacturer ID. The fourth cycle is to read the content at address 0x01, that is, the device ID (0x2249). The following function is to read the chip ID:
U32 get_en29lv160ab_id(void)
{
U32 temp=0;
CMD_ADDR0 = 0xaa;
CMD_ADDR1 = 0x55;
CMD_ADDR0 = 0x90;
temp = (*(volatile unsigned short *)(flash_base+ (0x100<<1)))<<16;
temp |= *(volatile unsigned short *)(flash_base + (1<<1));
return temp;
}
The following program implements the operations of erasing, writing, and reading an area, and determines whether the written data is the same as the read data:
…… ……
U16 buffer[1024];
char cmd;
…… ……
void test_en29lv160ab(void)
{
U32 temp;
U8 sta;
int i;
for(i=0;i<1024;i++)
buffer[i]=2*i+1;
//Read ID
temp = get_en29lv160ab_id();
while(!(rUTRSTAT0 & 0x2)) ;
rUTXH0=(U8)((temp&0xff000000)>>24);
while(!(rUTRSTAT0 & 0x2)) ;
rUTXH0=(U8)((temp&0x00ff0000)>>16);
while(!(rUTRSTAT0 & 0x2)) ;
rUTXH0=(U8)((temp&0x0000ff00)>>8);
while(!(rUTRSTAT0 & 0x2)) ;
rUTXH0=(U8)((temp&0x000000ff));
reset_en29lv160ab(); //Must reset here
delay(100);
// Erase block 33
sta=en29lv160ab_sector_erase(0xf0000);
if(sta == 0)
{
while(!(rUTRSTAT0 & 0x2)) ;
rUTXH0=0xaf; //Erase error
}
else
{
for(i=0;i<1024;i++)
{
sta = en29lv160ab_program(0xf0000+(i<<1),buffer[i]); //write
if(sta == 0) //Write error
{
while(!(rUTRSTAT0 & 0x2));
rUTXH0=0xbf;
break;
}
delay(200);
}
if(sta == 1)
{
for(i=0;i<1024;i++)
{
if(read_en29lv160ab(0xf0000+(i<<1))!=buffer[i]) //Read error
{
while(!(rUTRSTAT0 & 0x2)) ;
rUTXH0=0xcf;
sta = 3;
break;
}
}
if(sta !=3) //All operations are correct
{
while(!(rUTRSTAT0 & 0x2)) ;
rUTXH0=0x66;
}
}
}
while(!(rUTRSTAT0 & 0x2)) ;
rUTXH0=0x88; //End
}
//Simple test CFI
void test_en29lv160ab_CFI(void)
{
U16 temp;
*((volatile U16 *)(0x55<<1+flash_base))=0x98; //CFI command
temp = (*(volatile unsigned short *)(flash_base+ (0x10<<1)));
//while(!(rUTRSTAT0 & 0x2)) ;
//rUTXH0=(U8)((temp&0xff00)>>8);
while(!(rUTRSTAT0 & 0x2)) ;
rUTXH0=(U8)(temp&0x00ff);
temp = (*(volatile unsigned short *)(flash_base+ (0x11<<1)));
//while(!(rUTRSTAT0 & 0x2)) ;
//rUTXH0=(U8)((temp&0xff00)>>8);
while(!(rUTRSTAT0 & 0x2)) ;
rUTXH0=(U8)(temp&0x00ff);
temp = (*(volatile unsigned short *)(flash_base+ (0x12<<1)));
//while(!(rUTRSTAT0 & 0x2)) ;
//rUTXH0=(U8)((temp&0xff00)>>8);
while(!(rUTRSTAT0 & 0x2)) ;
rUTXH0=(U8)(temp&0x00ff);
temp = (*(volatile unsigned short *)(flash_base+ (0x13<<1)));
//while(!(rUTRSTAT0 & 0x2)) ;
//rUTXH0=(U8)((temp&0xff00)>>8);
while(!(rUTRSTAT0 & 0x2)) ;
rUTXH0=(U8)(temp&0x00ff);
temp = (*(volatile unsigned short *)(flash_base+ (0x14<<1)));
//while(!(rUTRSTAT0 & 0x2)) ;
//rUTXH0=(U8)((temp&0xff00)>>8);
while(!(rUTRSTAT0 & 0x2)) ;
rUTXH0=(U8)(temp&0x00ff);
temp = (*(volatile unsigned short *)(flash_base+ (0x15<<1)));
//while(!(rUTRSTAT0 & 0x2)) ;
//rUTXH0=(U8)((temp&0xff00)>>8);
while(!(rUTRSTAT0 & 0x2)) ;
rUTXH0=(U8)(temp&0x00ff);
temp = (*(volatile unsigned short *)(flash_base+ (0x16<<1)));
//while(!(rUTRSTAT0 & 0x2)) ;
//rUTXH0=(U8)((temp&0xff00)>>8);
Previous article:Simple configuration of linux-arm development environment
Next article:TX2440 bare metal program-touch screen
Recommended ReadingLatest update time:2024-11-15 16:53
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- LED chemical incompatibility test to see which chemicals LEDs can be used with
- Application of ARM9 hardware coprocessor on WinCE embedded motherboard
- What are the key points for selecting rotor flowmeter?
- LM317 high power charger circuit
- A brief analysis of Embest's application and development of embedded medical devices
- Single-phase RC protection circuit
- stm32 PVD programmable voltage monitor
- Introduction and measurement of edge trigger and level trigger of 51 single chip microcomputer
- Improved design of Linux system software shell protection technology
- What to do if the ABB robot protection device stops
- Huawei's Strategic Department Director Gai Gang: The cumulative installed base of open source Euler operating system exceeds 10 million sets
- Download from the Internet--ARM Getting Started Notes
- Learn ARM development(22)
- Learn ARM development(21)
- Learn ARM development(20)
- Learn ARM development(19)
- Learn ARM development(14)
- Learn ARM development(15)
- Analysis of the application of several common contact parts in high-voltage connectors of new energy vehicles
- Wiring harness durability test and contact voltage drop test method
- Southchip SC8905 evaluation board free evaluation, supports charging and discharging bidirectional operation
- RFID electronic tag application and technology tutorial
- Analysis of the design steps of RS-485 bus interface circuit
-
[NXP Rapid IoT Review] +
NXP Rapid IoT Online IDE Air Quality Test - How to get the most out of your low noise amplifier solution?
- Android4.4.2 source code compilation-iMX6Q/D core board-non-device tree source code
- 【GD32E503 Review】 Unboxing and Powering on the Machine
- JHIHAI APM32E103VET6 Review: External Interrupt (EINT)
- PYPL Programming Language Popularity Index, September 2022
- I don't quite understand this thermal imager resolution comparison chart