Whether it is the nand_write_page_hwecc function or the nand_write_page_hwecc function, there is a for loop body like this inside:
for(i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
…… ……
}
The three main variables are defined as:
eccsize= chip->ecc.size;
eccbytes = chip->ecc.bytes;
eccsteps = chip->ecc.steps;
Let's introduce the role of this loop: The number of bytes of hardware ECC that can be completed by the NandFlash controller of different CPUs at one time is different. For example, some CPUs can only complete 512 bytes of hardware ECC at a time, but if the NandFlash on the development board has 2048 bytes per page, what should we do? At this time, a loop body is used to get the hardware ECC of a page by looping multiple times. For example, in the above case, it is necessary to loop 4 times (2048÷512=4) to get the hardware ECC of the complete data in this page. In addition, the number of ECC bytes generated by different CPUs for each hardware ECC is also different, some are 3 bytes, and some are 4 bytes.
Then, the meanings of the three variables above are:
ecc.size: The number of bytes checked by hardware ECC each time
ecc.bytes: The number of bytes generated by each hardware ECC
ecc.steps: The number of times each page needs to perform hardware ECC
For S3C2440, hardware ECC can check 2048 bytes at a time and generate 4 bytes of ECC, so ecc.size should be 2048 and ecc.bytes should be 4. ecc.steps is obtained through calculation, that is, the size of each page of NandFlash can be known after the system is powered on, and this value divided by ecc.size is equal to ecc.steps. Therefore, for these three parameters, you only need to define the first two parameters in advance. These two parameters are defined and assigned in the board_nand_init function in the drivers/mtd/nand/s3c2440_nand.c file, namely:
nand->ecc.size = 2048;
nand->ecc.bytes = 4;
u-boot-2011.06 does not fully define the registers of the NandFlash controller of S3C2440, and there are errors, so we also need to modify it. Delete the content from line 167 to line 178 in the arch/arm/include/asm/arch-s3c24x0/s3c24x0.h file and add the following content:
struct s3c2440_nand {
u32 nfconf;
u32 nfcont;
u32 nfcmd;
u32 nfaddr;
u32 nfdata;
u32 nfmeccd0;
u32 nfmeccd1;
u32 nfseccd;
u32 nfstat;
u32 nfestat0;
u32 nfestat1;
u32 nfmecc0;
u32 nfmecc1;
u32 nfsecc;
u32 nfsblk;
u32 nfeblk;
};
Finally, we modify the s3c2440_nand_enable_hwecc function, s3c2440_nand_calculate_ecc function, and s3c2440_nand_correct_data function.
void s3c2440_nand_enable_hwecc(structmtd_info *mtd, int mode)
{
struct s3c2440_nand *nand = s3c2440_get_base_nand();
debugX(1,"s3c2440_nand_enable_hwecc(%p,%d)n", mtd, mode);
writel(readl(&nand->nfcont)| S3C2440_NFCONT_INITECC& ~S3C2440_NFCONT_MECCL,&nand->nfcont);
}
The task of this function is to initialize ECC (i.e. reset ECC) and unlock the main area ECC.
static int s3c2440_nand_calculate_ecc(struct mtd_info *mtd, constu_char *dat,
u_char *ecc_code)
{
struct s3c2440_nand *nand = s3c2440_get_base_nand();
u32 mecc0;
writel(readl(&nand->nfcont)| S3C2440_NFCONT_MECCL,&nand->nfcont);
mecc0 = readl(&nand->nfmecc0);
ecc_code[0] = mecc0 & 0xff;
ecc_code[1] = (mecc0 >> 8) &0xff;
ecc_code[2] = (mecc0 >> 16) &0xff;
ecc_code[3] =(mecc0 >> 24) & 0xff;
debugX(1,"s3c2440_nand_calculate_hwecc(%p,):0xx 0xx 0xx 0xxn",
mtd, ecc_code[0], ecc_code[1], ecc_code[2], ecc_code[3]);
return 0;
}
The function first locks the main area ECC, then reads the register NFMECC0, which stores the main area ECC generated by the hardware, and finally stores four 1-byte ECCs into the ecc_code array.
static int s3c2440_nand_correct_data(struct mtd_info *mtd, u_char*dat,
u_char *read_ecc, u_char *calc_ecc)
{
struct s3c2440_nand *nand = s3c2440_get_base_nand();
u32 meccdata0, meccdata1, estat0, err_byte_addr;
int ret = -1;
u8 repaired;
meccdata0= (read_ecc[1] << 16) | read_ecc[0];
meccdata1= (read_ecc[3] << 16) | read_ecc[2];
writel(meccdata0,&nand->nfmeccd0);
writel(meccdata1,&nand->nfmeccd1);
estat0= readl(&nand->nfestat0);
switch(estat0 & 0x3) {
case 0:
ret = 0;
break;
case 1:
err_byte_addr= (estat0 >> 7) & 0x7ff;
repaired= dat[err_byte_addr] ^ (1 << ((estat0 >> 4) & 0x7));
printf("S3C NAND: 1 bit error detected at byte%ld. "
"Correcting from 0xx to0xx...OKn",
err_byte_addr, dat[err_byte_addr],repaired);
dat[err_byte_addr]= repaired;
ret = 1;
break;
case 2:
case 3:
printf("S3C NAND: ECC uncorrectable errordetected. "
"Not correctable.n");
ret = -1;
break;
}
return ret;
}
The function first stores the ECC in the read_ecc array into registers NFMECCD0 and NFMECCD1, so that the system will automatically verify the data and put the status into register NFESTAT0, and then read the last 4 bits of the register. When it is 0, it means the verification is correct; when it is 1, it means a 1-bit error has occurred (this type of error can be corrected), and we correct it; when it is 2 and 3, it means other types of errors have occurred, which cannot be corrected.
By modifying the above content, we have implemented the hardware ECC of NandFlash.
ECC is sufficient to ensure the correctness of the read data and can correct errors in some cases, but it cannot guarantee the correctness of the written data. In order to ensure the correctness of the written data, u-boot can also define the macro CONFIG_MTD_NAND_VERIFY_WRITE in the include/configs/gq2440.h file to read the written data again and then compare it with the written data to determine the correctness of the written data. This process is called and implemented in the nand_write_page function of the drivers/mtd/nand/nand_base.c file.
6 DM9000 migration
I implemented the DM9000 part in UBOOT. Of course, I just used some ideas. I am quite unfamiliar with network cards.
First, remove the original definition of the CS8900 network card in include/configs/fl2440.h, and then define various macros related to the DM9000 network card:
-
/*#define CONFIG_CS8900*/ /* we have a CS8900 on-board */
-
/*#define CONFIG_CS8900_BASE 0x19000300 */
-
/*#define CONFIG_CS8900_BUS16*/ /* the Linux driver does accesses as shorts */
-
#define CONFIG_DRIVER_DM9000 1
-
#define CONFIG_DM9000_BASE 0x20000300
-
#define DM9000_IO CONFIG_DM9000_BASE
-
#define DM9000_DATA (CONFIG_DM9000_BASE+4) /* the cmd pin is addr2*/
-
#define CONFIG_ETHADDR a8:00:3E:26:0A:5B
-
#define CONFIG_NETMASK 255.255.255.0
-
#define CONFIG_IPADDR 192.168.1.11
-
#define CONFIG_SERVERIP 192.168.1.234
-
#define CONFIG_NET_MULTI
-
-
/*
-
#define CONFIG_NETMASK 255.255.255.0
-
#define CONFIG_IPADDR 10.0.0.110
-
#define CONFIG_SERVERIP 10.0.0.1
-
*/
DM9000 hardware connection schematic diagram on FL2440:
It can be seen from the figure that DM9000 is connected to NGCS4. Looking at the address space, we can know that the base address of NGCS4 is 0x20000000, so the base address of the network card is 0x20000300. They said that the 300 at the end is how the internal registers of DM9000 are defined. In reality, my network card works well at this base address, so it should be correct.
CMD is connected to ADDR2. According to the DM9000 manual, when CMD is 1, data information is sent. Therefore, the data address of DM9000 is 0x20000304. This is easy to understand.
Modify the board_eth_init function in fl2440.c:
-
#ifdef CONFIG_CMD_NET
-
int board_eth_init(bd_t *bis)
-
{
-
return dm9000_initialize(bis);
-
}
-
#endif
Modify drivers/net/dm9000x.c and comment out the following paragraph. I don't know the reason, so I don't care.
-
i = 0;
-
while (!(dm9000_phy_read(1) & 0x20)) { /* autonegation complete bit */
-
udelay(1000);
-
i++;
-
if (i == 10000) {
-
printf("could not establish linkn");
-
return 0;
-
}
-
}
-
-
/* see what we've got */
-
lnk = dm9000_phy_read(17) >> 12;
-
printf("operating at ");
-
switch (lnk) {
-
case 1:
-
printf("10M half duplex ");
-
break;
-
case 2:
-
printf("10M full duplex");
-
break;
-
case 4:
-
printf("100M half duplex");
-
break;
-
case 8:
-
printf("100M full duplex");
-
break;
-
default:
-
printf("unknown: %d ", lnk);
-
break;
-
}
-
printf("moden");
Comment out the contents of this function, otherwise the network card will be automatically disconnected:
-
static void dm9000_halt(struct eth_device *netdev)
-
{
-
#if 0
-
DM9000_DBG("%sn", __func__);
-
-
/* RESET device */
-
dm9000_phy_write(0, 0x8000); /* PHY RESET */
-
DM9000_iow(DM9000_GPR, 0x01); /* Power-Down PHY */
-
DM9000_iow(DM9000_IMR, 0x80); /* Disable all interrupt */
-
DM9000_iow(DM9000_RCR, 0x00); /* Disable RX */
-
#endif
-
}
After compiling, the network card is up.
7 Modify the machine code
u-boot-2011.06boardsamsunggq2440gq2440.c
/* arch number of SMDK2410-Board */
gd->bd->bi_arch_number = 1999;
/* adress of boot parameters */
gd->bd->bi_boot_params = 0x30000100;
Finish!
Previous article:ALSA sound card 10_Data transmission from scratch_Study notes
Next article:Camera driver learning
Recommended ReadingLatest update time:2024-11-15 01:42
- 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
- Waveform changes of different ANT frequencies
- Regulator tube usage help
- Electric vehicle charger schematic, file name is chip name
- SD card creative stickers
- How do you entertain yourself while staying at home?
- The difference and relationship between embedded Linux and embedded development of 51/430/STM32
- 【DM642】Porting of H.264 source code on DM642
- [2022 Digi-Key Innovation Design Competition] Material Unboxing
- Prize-giving live broadcast: Book a session on "Meeting the test challenges in 5G signal generation" and win Keysight gifts
- Simple stopwatch based on MSP430f149 microcontroller