#define S3C2440_NFCONF_TWRPH1(x) ((x)<<4)
#define S3C2440_ADDR_NALE 0x08
#define S3C2440_ADDR_NCLE 0x0C
Then modify the s3c2440_hwcontrol function and board_nand_init function, and keep other functions unchanged.
The board_nand_init function is mainly used to initialize NandFlash. The modifications to it are the registers NFCONF and NFCONT. The following is the modified board_nand_init function, where the red marked parts are the modified parts:
int board_nand_init(struct nand_chip *nand)
{
u_int32_t cfg;
u_int8_t tacls, twrph0, twrph1;
struct s3c24x0_clock_power *clk_power = s3c24x0_get_base_clock_power();
struct s3c2440_nand *nand_reg = s3c2440_get_base_nand();
debugX(1,"board_nand_init()n");
writel(readl(&clk_power->clkcon) |(1 << 4), &clk_power->clkcon);
#ifdefined(CONFIG_S3C24XX_CUSTOM_NAND_TIMING)
tacls = CONFIG_S3C24XX_TACLS;
twrph0 = CONFIG_S3C24XX_TWRPH0;
twrph1 = CONFIG_S3C24XX_TWRPH1;
#else
tacls = 2;
twrph0 = 3;
twrph1 = 1;
#endif
cfg = S3C2440_NFCONF_TACLS(tacls - 1);
cfg |= S3C2440_NFCONF_TWRPH0(twrph0 - 1);
cfg |= S3C2440_NFCONF_TWRPH1(twrph1 - 1);
writel(cfg,&nand_reg->nfconf);
cfg = S3C2440_NFCONT_SECCL;
cfg |= S3C2440_NFCONT_MECCL;
cfg |= S3C2440_NFCONT_MODE;
writel(cfg,&nand_reg->nfcont);
nand->IO_ADDR_R = (void*)&nand_reg->nfdata;
nand->IO_ADDR_W = (void*)&nand_reg->nfdata;
nand->select_chip = NULL;
#ifdefCONFIG_NAND_SPL
nand->read_buf = nand_read_buf;
#endif
nand->cmd_ctrl = s3c2440_hwcontrol;
nand->dev_ready = s3c2440_dev_ready;
#ifdefCONFIG_S3C2440_NAND_HWECC
nand->ecc.hwctl = s3c2440_nand_enable_hwecc;
nand->ecc.calculate = s3c2440_nand_calculate_ecc;
nand->ecc.correct = s3c2440_nand_correct_data;
nand->ecc.mode = NAND_ECC_HW;
nand->ecc.size =CONFIG_SYS_NAND_ECCSIZE;
nand->ecc.bytes =CONFIG_SYS_NAND_ECCBYTES;
#else
nand->ecc.mode = NAND_ECC_SOFT;
#endif
#ifdef CONFIG_S3C2440_NAND_BBT
nand->options = NAND_USE_FLASH_BBT;
#else
nand->options = 0;
#endif
debugX(1, "end ofnand_initn");
return 0;
}
Finally, modify the s3c2440_hwcontrol function, which is used to write commands and write addresses to NandFlash:
static void s3c2440_hwcontrol(structmtd_info *mtd, int cmd, unsigned int ctrl)
{
struct nand_chip *chip =mtd->priv;
struct s3c2440_nand *nand = s3c2440_get_base_nand();
debugX(1,"hwcontrol(): 0xx 0xxn", cmd, ctrl);
if (ctrl &NAND_CTRL_CHANGE) {
ulong IO_ADDR_W = (ulong)nand;
if (!(ctrl &NAND_CLE))
IO_ADDR_W|= S3C2440_ADDR_NCLE;
if (!(ctrl &NAND_ALE))
IO_ADDR_W|= S3C2440_ADDR_NALE;
if(cmd == NAND_CMD_NONE)
IO_ADDR_W = &nand->nfdata;
chip->IO_ADDR_W= (void *)IO_ADDR_W;
if (ctrl &NAND_NCE)
writel(readl(&nand->nfconf)& ~S3C2440_NFCONT_nCE,
&nand->nfconf);
else
writel(readl(&nand->nfconf)| S3C2440_NFCONT_nCE,
&nand->nfconf);
}
if (cmd != NAND_CMD_NONE)
writeb(cmd, chip->IO_ADDR_W);
}
In this function, in addition to modifying the register value and setting the IO port for writing commands and addresses, we also added the if (cmd == NAND_CMD_NONE) judgment statement. Without this judgment statement, data cannot be written into NandFlash. Although the system will not prompt any errors and display "OK", the data is not actually written. Therefore, this statement must be added. This is because after writing the command and address, the address of the IO port must be reset to the register NFDATA.
It should be noted that since the system does not define CONFIG_S3C2410_NAND_HWECC, we will not modify the s3c2440_nand_enable_hwecc function, s3c2440_nand_calculate_ecc function and s3c2440_nand_correct_data function for the time being.
We burn the compiled u-boot.bin file into norflash and use the relevant commands of NandFlash to verify:
U-Boot2011.06 (Aug 10 2011 - 23:16:25)
DRAM: 64 MiB
Flash: 2MiB
NAND: 256 MiB
***Warning - bad CRC, using default environment
In: serial
Out: serial
Err: serial
Net: CS8900-0
gq2440# nand info
Device 0: nand0, sector size 128 KiB
gq2440# nand device 0
gq2440# nand erase 0x100000 0x300000
NANDerase: device 0 offset 0x100000, size 0x300000
Erasingat 0x3e0000 -- 100% complete.
OK
gq2440# nand write 0 0x100000 0x300000
NANDwrite: device 0 offset 0x100000, size 0x300000
3145728 bytes written: OK
gq2440# nand read 0x30004000 0x100000 0x300000
NANDread: device 0 offset 0x100000, size 0x300000
3145728 bytes read: OK
gq2440#md.b 0
00000000:13 00 00 ea 14 f0 9f e5 14 f0 9fe5 14 f0 9f e5 ............
00000010:14 f0 9f e5 14 f0 9fe5 14 f0 9f e5 14 f0 9fe5 ............
00000020:e0 01 00 00 40 02 00 00 a0 0200 00 00 03 00 00 ....@........
00000030:60 03 00 00 c0 03 00 00 20 04 0000 ef be ad de `....... .......
gq2440#md.b 0x30004000
30004000:13 00 00 ea 14 f0 9f e5 14 f0 9fe5 14 f0 9f e5 ............
30004010:14 f0 9f e5 14 f0 9fe5 14 f0 9f e5 14 f0 9fe5 ............
30004020:e0 01 00 00 40 02 00 00 a0 0200 00 00 03 00 00 ....@.......
30004030:60 03 00 00 c0 03 00 00 20 04 0000 ef be ad de `....... .......
After power-on, NAND shows 256MiB, indicating that the system can correctly identify NandFlash. Then we write the data in SDRAM to NandFlash, and then read the data in NandFlash. By comparing it with the original SDRAM data, we can see that the contents of the two data segments are consistent, so we can conclude that the transplanted u-boot can correctly read and write NandFlash.
In addition, if you want to know more about the NandFlash on the development board, you can change MTDDEBUG in line 2676 of drivers/mtd/nand/nand_base.c to printf, and then remove MTD_DEBUG_LEVEL0 in the line. After power-on, the following content will be displayed:
U-Boot2011.06 (Aug 10 2011 - 23:55:48)
DRAM: 64 MiB
Flash: 2MiB
NAND: NAND device: ManufacturerID: 0xec, Chip ID: 0xda (Samsung NAND 256MiB 3,3V 8-bit)
256 MiB
***Warning - bad CRC, using default environment
In: serial
Out: serial
Err: serial
Net: CS8900-0
4 Solve raise: Signal # 8 caught
In fact, it is very simple to remove this bug. Just replace the four global variables in the time.c file (in the arch/arm/arm920t/s3c24x0 directory) with the four related members of the gd data structure. Specifically:
timer_load_val is replaced by gd->timer_rate_hz;
timer_clk is replaced by gd->tbl;
timestamp is replaced by gd->timer_reset_value;
lastdec is replaced by gd->lastinc.
Below we list the specific places where the time.c file needs to be modified:
Remove the declarations of the timer_load_val and timer_clk variables in lines 38 and 39 and add the following code:
38:DECLARE_GLOBAL_DATA_PTR;
Remove the declarations of the variables timestamp and lastdec in lines 49 and 50;
Remove the statements from lines 60 to 68 (the judgment content of if (timer_load_val == 0)) and change them to:
60: gd->timer_rate_hz = get_PCLK() /(2*16*100);
61: gd->tbl = get_PCLK() / (2 * 16);
The remaining content that needs to be modified is the specific variable replacement, where the line number before each statement is the line number of the source file:
70: gd->lastinc = gd->timer_rate_hz;
71: writel(gd->timer_rate_hz,&timers->tcntb4);
78: gd->timer_reset_value = 0;
99: gd->timer_reset_value = t;
108:tmo *= (gd->timer_rate_hz * 100);
118: gd->lastinc = READ_TIMER();
119: gd->timer_reset_value = 0;
126: return tmr / (gd->tbl / CONFIG_SYS_HZ);
137: tmo *= (gd->timer_rate_hz * 100);
140: tmo = usec * (gd->timer_rate_hz * 100);
160: if (gd->lastinc >= now) {
162: gd->timer_reset_value += gd->lastinc -now;
165: gd->timer_reset_value += gd->lastinc + gd->timer_rate_hz- now;
167: gd->lastinc = now;
169: return gd->timer_reset_value;
181: tbclk = gd->timer_rate_hz * 100;
With the above modifications, there will no longer be raise: Signal # 8 caught after we power on.
5 Hardware ECC
We have completed the reading and writing of NandFlash by u-boot very well, but this reading and writing is software ECC, that is, ECC is implemented by software programming. We know that the NandFlash controller of S3C2440 supports hardware ECC, so here we will explain how to implement hardware ECC.
Each page of NandFlash is divided into main area and spare area. NandFlash controller of S3C2440 supports hardware ECC of these two areas, but in order to be compatible with u-boot-2011.06, we only implement hardware ECC of main area.
In order to implement hardware ECC, you first need to define the macro CONFIG_S3C2440_NAND_HWECC in the include/configs/gq2440.h file. In this way, the three functions required for hardware ECC are defined in the drivers/mtd/nand/s3c2440_nand.c file: s3c2440_nand_enable_hwecc function, s3c2440_nand_calculate_ecc function and s3c2440_nand_correct_data function. In addition, in the board_nand_init function, these three functions are assigned to the three members of the corresponding structure respectively. In this way, these three functions will be called when reading and writing NandFlash, thereby implementing hardware ECC. The s3c2440_nand_enable_hwecc function is responsible for enabling hardware ECC, the s3c2440_nand_calculate_ecc function is responsible for calculating ECC (of course, this calculation is done by hardware), and the s3c2440_nand_correct_data function is responsible for checking ECC (similarly, this check is also automatically done by hardware).
In order to understand how u-boot performs hardware ECC, let's briefly analyze the related functions. NandFlash performs read and write operations in pages as the smallest unit. The read operation that supports hardware ECC is ultimately completed by the nand_read_page_hwecc function (in the drivers/mtd/nand directory), and the write operation that supports hardware ECC is ultimately completed by the nand_write_page_hwecc function (in the drivers/mtd/nand directory). The process of the nand_read_page_hwecc function is to first read the main area data, and at the same time get the hardware ECC by calling the s3c2440_nand_calculate_ecc function; then read the spare area data; then extract the main area ECC stored in the spare area; finally, call the s3c2440_nand_correct_data function to verify the main area data just read. The process of nand_write_page_hwecc function is relatively simple. It first writes the main area data and gets the hardware ECC by calling s3c2440_nand_calculate_ecc function; then it writes the hardware ECC into the spare area.
Previous article:ALSA sound card 10_Data transmission from scratch_Study notes
Next article:Camera driver learning
Recommended ReadingLatest update time:2024-11-15 02:08
- Learn ARM development(16)
- Learn ARM development(17)
- Learn ARM development(18)
- Embedded system debugging simulation tool
- A small question that has been bothering me recently has finally been solved~~
- Learn ARM development (1)
- Learn ARM development (2)
- Learn ARM development (4)
- Learn ARM development (6)
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
- CGD and Qorvo to jointly revolutionize motor control solutions
- CGD and Qorvo to jointly revolutionize motor control solutions
- Keysight Technologies FieldFox handheld analyzer with VDI spread spectrum module to achieve millimeter wave analysis function
- Infineon's PASCO2V15 XENSIV PAS CO2 5V Sensor Now Available at Mouser for Accurate CO2 Level Measurement
- Advanced gameplay, Harting takes your PCB board connection to a new level!
- Advanced gameplay, Harting takes your PCB board connection to a new level!
- A new chapter in Great Wall Motors R&D: solid-state battery technology leads the future
- Naxin Micro provides full-scenario GaN driver IC solutions
- Interpreting Huawei’s new solid-state battery patent, will it challenge CATL in 2030?
- Are pure electric/plug-in hybrid vehicles going crazy? A Chinese company has launched the world's first -40℃ dischargeable hybrid battery that is not afraid of cold
- How to switch the unit of Proteus simulation software from inches to mm? Pressing m does not work, and Baidu can't find it
- TI C64X+ General Library Function User Manual
- Examples of capacitor applications in power supply design (recommended for collection)
- How can I hide certain items when printing in AD, such as the frequency mark of the crystal oscillator?
- gw1n FPGA reads ADS8598H actual DC measurement
- Shouldn't the charging curve of a capacitor be inversely proportional to its discharging curve?
- IP core issues in ISE
- Attenuator Specifications
- AD15 Help, help, help
- N methods of converting 5V to 3.3V