如何提高Am335x GPMC 对 Nand pagenand读写速度的速度

This is tested with a custom AM3359 (rev 2.0) board.
NAND chip: MT29F16G08ABABAWP
This code allows me to boot from ROM code.
The ROM code forces BCH16 on NAND chips with a 4k page size.
BCH16 is not enabled by default.
arch/arm/include/asm/arch-am33xx/cpu.h
arch/arm/include/asm/arch-am33xx/omap_gpmc.h |
43 ++++++++
drivers/mtd/nand/omap_gpmc.c
| 150 +++++++++++++++++----------
include/linux/mtd/mtd-abi.h
4 files changed, 148 insertions(+), 55 deletions(-)
diff --git a/arch/arm/include/asm/arch-am33xx/cpu.h b/arch/arm/include/asm/arch-am33xx/cpu.h
index 16e8a80..0a1f1ff 100644
--- a/arch/arm/include/asm/arch-am33xx/cpu.h
+++ b/arch/arm/include/asm/arch-am33xx/cpu.h
@@ -78,6 +78,10 @@ struct bch_res_0_3 {
u32 bch_result_x[4];
+struct bch_res_4_6 {
+ u32 bch_result_x[3];
struct gpmc {
u8 res1[0x10];
/* 0x10 */
@@ -107,7 +111,9 @@ struct gpmc {
u8 res7[12];
/* 0x224 */
u32 testmomde_ /* 0x230 */
u8 res8[12];
/* 0x234 */
- struct bch_res_0_3 bch_result_0_3[2]; /* 0x240 */
+ struct bch_res_0_3 bch_result_0_3; /* 0x240 */
+ u32 dummy[44];
/* not used */
+ struct bch_res_4_6 bch_result_4_6; /* 300 */
/* Used for board specific gpmc initialization */
diff --git a/arch/arm/include/asm/arch-am33xx/omap_gpmc.h b/arch/arm/include/asm/arch-am33xx/omap_gpmc.h
index 572f9d0..534fa6e 100644
--- a/arch/arm/include/asm/arch-am33xx/omap_gpmc.h
+++ b/arch/arm/include/asm/arch-am33xx/omap_gpmc.h
@@ -117,4 +117,47 @@
{.offset = 106,\
.length = 8 } } \
+#define GPMC_NAND_4K_HW_BCH8_ECC_LAYOUT {\
+ .eccbytes = 112,\
+ .eccpos = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,\
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,\
28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,\
40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,\
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,\
64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75,\
76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87,\
88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,\
100, 101, 102, 103, 104, 105, 106, 107, 108, 109,\
110, 111, 112, 113},\
+ .oobfree = {\
{.offset = 114,\
.length = 110 } } \
+#define GPMC_NAND_4K_HW_BCH16_ECC_LAYOUT {\
+ .eccbytes = 208,\
+ .eccpos = { 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,\
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,\
28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,\
40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,\
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,\
64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75,\
76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87,\
88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,\
100, 101, 102, 103, 104, 105, 106, 107, 108, 109,\
110, 111, 112, 113, 114, 115, 116, 117, 118, 119,\
120, 121, 122, 123, 124, 125, 126, 127, 128, 129,\
130, 131, 132, 133, 134, 135, 136, 137, 138, 139,\
140, 141, 142, 143, 144, 145, 146, 147, 148, 149,\
150, 151, 152, 153, 154, 155, 156, 157, 158, 159,\
160, 161, 162, 163, 164, 165, 166, 167, 168, 169,\
170, 171, 172, 173, 174, 175, 176, 177, 178, 179,\
180, 181, 182, 183, 184, 185, 186, 187, 188, 189,\
190, 191, 192, 193, 194, 195, 196, 197, 198, 199,\
200, 201, 202, 203, 204, 205, 206, 207, 208, 209},\
+ .oobfree = {\
{.offset = 210,\
.length = 14 } } \
#endif /* __ASM_ARCH_OMAP_GPMC_H */
diff --git a/drivers/mtd/nand/omap_gpmc.c b/drivers/mtd/nand/omap_gpmc.c
index cee394e..3c42a54 100644
--- a/drivers/mtd/nand/omap_gpmc.c
+++ b/drivers/mtd/nand/omap_gpmc.c
@@ -76,8 +76,8 @@ int omap_spl_dev_ready(struct mtd_info *mtd)
* omap_hwecc_init - Initialize the Hardware ECC for NAND flash in
GPMC controller
MTD device structure
GPMC controller
MTD device structure
static void __maybe_unused omap_hwecc_init(struct nand_chip *chip)
@@ -170,19 +170,19 @@ static int __maybe_unused omap_correct_data(struct mtd_info *mtd, uint8_t *dat,
omap_calculate_ecc - Generate non-inverted ECC bytes.
+ * omap_calculate_ecc - Generate non-inverted ECC bytes.
Using noninverted ECC can be considered ugly since writing a blank
page ie. padding will clear the ECC bytes. This is no problem as
long nobody is trying to write data on the seemingly unused page.
Reading an erased page will produce an ECC mismatch between
generated and read ECC bytes that has to be dealt with separately.
E.g. if page is 0xFF (fresh erased), and if HW ECC engine within GPMC
is used, the result of read will be 0x0 while the ECC offsets of the
spare area will be 0xFF which will result in an ECC mismatch.
@mtd: MTD structure
@dat: unused
@ecc_code: ecc_code buffer
+ * Using noninverted ECC can be considered ugly since writing a blank
+ * page ie. padding will clear the ECC bytes. This is no problem as
+ * long nobody is trying to write data on the seemingly unused page.
+ * Reading an erased page will produce an ECC mismatch between
+ * generated and read ECC bytes that has to be dealt with separately.
+ * E.g. if page is 0xFF (fresh erased), and if HW ECC engine within GPMC
+ * is used, the result of read will be 0x0 while the ECC offsets of the
+ * spare area will be 0xFF which will result in an ECC mismatch.
+ * @mtd: MTD structure
+ * @dat: unused
+ * @ecc_code: ecc_code buffer
static int __maybe_unused omap_calculate_ecc(struct mtd_info *mtd,
const uint8_t *dat, uint8_t *ecc_code)
@@ -207,8 +207,8 @@ static int __maybe_unused omap_calculate_ecc(struct mtd_info *mtd,
* omap_enable_ecc - This function enables the hardware ecc functionality
MTD device structure
- * @mode:
Read/Write mode
MTD device structure
+ * @mode:
Read/Write mode
static void __maybe_unused omap_enable_hwecc(struct mtd_info *mtd, int32_t mode)
@@ -258,7 +258,7 @@ struct nand_bch_priv {
#define ECC_BCH8_NIBBLES 26
#define ECC_BCH16_NIBBLES 52
-static struct nand_ecclayout hw_bch8_nand_oob = GPMC_NAND_HW_BCH8_ECC_LAYOUT;
+static struct nand_ecclayout nand_ecclayout = GPMC_NAND_HW_BCH8_ECC_LAYOUT;
static struct nand_bch_priv bch_priv = {
.mode = NAND_ECC_HW_BCH,
@@ -280,21 +280,21 @@ static void omap_read_bch8_result(struct mtd_info *mtd, uint8_t big_endian,
int8_t i = 0,
if (big_endian) {
ptr = &gpmc_cfg-&bch_result_0_3[0].bch_result_x[3];
ptr = &gpmc_cfg-&bch_result_0_3.bch_result_x[3];
ecc_code[i++] = readl(ptr) & 0xFF;
for (j = 0; j & 3; j++) {
ecc_code[i++] = (readl(ptr) && 24) & 0xFF;
ecc_code[i++] = (readl(ptr) && 16) & 0xFF;
ecc_code[i++] = (readl(ptr) &&
8) & 0xFF;
ecc_code[i++] = (readl(ptr) && 8) & 0xFF;
ecc_code[i++] = readl(ptr) & 0xFF;
ptr = &gpmc_cfg-&bch_result_0_3[0].bch_result_x[0];
ptr = &gpmc_cfg-&bch_result_0_3.bch_result_x[0];
for (j = 0; j & 3; j++) {
ecc_code[i++] = readl(ptr) & 0xFF;
ecc_code[i++] = (readl(ptr) &&
8) & 0xFF;
ecc_code[i++] = (readl(ptr) && 8) & 0xFF;
ecc_code[i++] = (readl(ptr) && 16) & 0xFF;
ecc_code[i++] = (readl(ptr) && 24) & 0xFF;
@@ -304,6 +304,53 @@ static void omap_read_bch8_result(struct mtd_info *mtd, uint8_t big_endian,
+static void omap_read_bch16_result(struct mtd_info *mtd, uint8_t big_endian,
uint8_t *ecc_code)
+ uint32_t *
+ int8_t i = 0,
+ if(big_endian) {
ptr = &gpmc_cfg-&bch_result_4_6.bch_result_x[2];
for (j = 0; j & 7; j++) {
if(j == 3) {
ptr = &gpmc_cfg-&bch_result_0_3.bch_result_x[3];
data = readl(ptr);
if(i & 0) {
ecc_code[i++] = (data && 24) & 0xFF;
ecc_code[i++] = (data && 16) & 0xFF;
ecc_code[i++] = (data && 8) & 0xFF;
ecc_code[i++] = data & 0xFF;
ecc_code[i++] = 0;
ecc_code[i++] = 0;
ptr = &gpmc_cfg-&bch_result_0_3.bch_result_x[0];
for (j = 0; j & 7; j++) {
if(j == 4) {
ptr = &gpmc_cfg-&bch_result_4_6.bch_result_x[0];
data = readl(ptr);
ecc_code[i++] = data & 0xFF;
ecc_code[i++] = (data && 8) & 0xFF;
ecc_code[i++] = (data && 16) & 0xFF;
ecc_code[i++] = (data && 24) & 0xFF;
* omap_ecc_disable - Disable H/W ECC calculation
@@ -330,7 +377,7 @@ static void omap_rotate_ecc_bch(struct mtd_info *mtd, uint8_t *calc_ecc,
struct nand_chip *chip = mtd-&
struct nand_bch_priv *bch = chip-&
uint8_t n_bytes = 0;
- int8_t i,
switch (bch-&type) {
case ECC_BCH4:
@@ -338,7 +385,12 @@ static void omap_rotate_ecc_bch(struct mtd_info *mtd, uint8_t *calc_ecc,
case ECC_BCH16:
n_bytes = 28;
n_bytes = 26;
/* Last 2 register of ELM need to be zero */
syndrome[26] = 0;
syndrome[27] = 0;
case ECC_BCH8:
@@ -347,16 +399,17 @@ static void omap_rotate_ecc_bch(struct mtd_info *mtd, uint8_t *calc_ecc,
- for (i = 0, j = (n_bytes-1); i & n_ i++, j--)
syndrome[i] =
calc_ecc[j];
+ for (i = 0; i & n_ i++) {
syndrome[i] = calc_ecc[(n_bytes-1)-i];
omap_calculate_ecc_bch - Read BCH ECC result
+ * omap_calculate_ecc_bch - Read BCH ECC result
@mtd: MTD structure
@dat: unused
@ecc_code: ecc_code buffer
+ * @mtd: MTD structure
+ * @dat: unused
+ * @ecc_code: ecc_code buffer
static int omap_calculate_ecc_bch(struct mtd_info *mtd, const uint8_t *dat,
uint8_t *ecc_code)
@@ -368,7 +421,9 @@ static int omap_calculate_ecc_bch(struct mtd_info *mtd, const uint8_t *dat,
if (bch-&type == ECC_BCH8)
omap_read_bch8_result(mtd, big_endian, ecc_code);
- else /* BCH4 and BCH16 currently not supported */
+ else if(bch-&type == ECC_BCH16)
omap_read_bch16_result(mtd, big_endian, ecc_code);
+ else /* BCH4 currently not supported */
@@ -434,7 +489,7 @@ static int omap_correct_data_bch(struct mtd_info *mtd, uint8_t *dat,
struct nand_bch_priv *bch = chip-&
uint8_t syndrome[28];
uint32_t error_count = 0;
- uint32_t error_loc[8];
+ uint32_t error_loc[16];
uint32_t i, ecc_
ecc_flag = 0;
@@ -470,7 +525,7 @@ static int omap_correct_data_bch(struct mtd_info *mtd, uint8_t *dat,
* omap_hwecc_init_bch - Initialize the BCH Hardware ECC for NAND flash in
GPMC controller
MTD device structure
MTD device structure
* @mode: Read/Write mode
static void omap_hwecc_init_bch(struct nand_chip *chip, int32_t mode)
@@ -525,8 +580,8 @@ static void omap_hwecc_init_bch(struct nand_chip *chip, int32_t mode)
* omap_enable_ecc_bch- This function enables the bch h/w ecc functionality
MTD device structure
- * @mode:
Read/Write mode
MTD device structure
+ * @mode:
Read/Write mode
static void omap_enable_ecc_bch(struct mtd_info *mtd, int32_t mode)
@@ -611,12 +666,13 @@ static int omap_read_page_bch(struct mtd_info *mtd, struct nand_chip *chip,
void omap_nand_switch_ecc(int32_t hardware)
+#ifndef CONFIG_AM33XX
struct nand_chip *
struct mtd_info *
if (nand_curr_device & 0 ||
nand_curr_device &= CONFIG_SYS_MAX_NAND_DEVICE ||
!nand_info[nand_curr_device].name) {
nand_curr_device &= CONFIG_SYS_MAX_NAND_DEVICE ||
!nand_info[nand_curr_device].name) {
printf(&Error: Can't switch ecc, no devices available\n&);
@@ -646,19 +702,6 @@ void omap_nand_switch_ecc(int32_t hardware)
nand-&ecc.calculate = omap_calculate_
omap_hwecc_init(nand);
printf(&HW ECC selected\n&);
-#ifdef CONFIG_AM33XX
- } else if (hardware == 2) {
nand-&ecc.mode = NAND_ECC_HW;
nand-&ecc.layout = &hw_bch8_nand_
nand-&ecc.size = 512;
nand-&ecc.bytes = 14;
nand-&ecc.read_page = omap_read_page_
nand-&ecc.hwctl = omap_enable_ecc_
nand-&ecc.correct = omap_correct_data_
nand-&ecc.calculate = omap_calculate_ecc_
omap_hwecc_init_bch(nand, NAND_ECC_READ);
printf(&HW BCH8 selected\n&);
nand-&ecc.mode = NAND_ECC_SOFT;
/* Use mtd default settings */
@@ -671,6 +714,7 @@ void omap_nand_switch_ecc(int32_t hardware)
nand_scan_tail(mtd);
nand-&options &= ~NAND_OWN_BUFFERS;
#endif /* CONFIG_SPL_BUILD */
@@ -684,10 +728,10 @@ void omap_nand_switch_ecc(int32_t hardware)
* - ecc.hwctl: function to enable (reset) hardware ecc generator
* - ecc.mode: mode of ecc, see defines
* - chip_delay: chip dependent delay for transfering data from array to
read regs (tR)
read regs (tR)
* - options: various chip options. They can partly be set to inform
nand_scan about special functionality. See the defines for further
explanation
nand_scan about special functionality. See the defines for further
explanation
int board_nand_init(struct nand_chip *nand)
@@ -742,7 +786,7 @@ int board_nand_init(struct nand_chip *nand)
/* Default ECC mode */
#ifdef CONFIG_AM33XX
nand-&ecc.mode = NAND_ECC_HW;
- nand-&ecc.layout = &hw_bch8_nand_
+ nand-&ecc.layout = &nand_
nand-&ecc.size = CONFIG_SYS_NAND_ECCSIZE;
nand-&ecc.bytes = CONFIG_SYS_NAND_ECCBYTES;
nand-&ecc.hwctl = omap_enable_ecc_
diff --git a/include/linux/mtd/mtd-abi.h b/include/linux/mtd/mtd-abi.h
index 8bdd231..0644
--- a/include/linux/mtd/mtd-abi.h
+++ b/include/linux/mtd/mtd-abi.h
@@ -125,7 +125,7 @@ struct nand_oobfree {
struct nand_ecclayout {
- uint32_t eccpos[128];
+ uint32_t eccpos[208];
struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES];
Previous message:
Next message:
Messages sorted by:需要确认注册邮箱后才能开通博客,
>>>为AM335x移植Linux内核主线代码(7)使用SD卡中的U-Boot操作NAND Flash
2年会员勋章目前已领取。领取条件:&凡是注册时间两年以上的活跃用户即可领取该勋章。
3年会员勋章目前未领取。领取条件:&凡是注册时间三年以上的活跃用户即可领取该勋章。
不是猫咪不是机器人的博客&&Linux/Hardware Blog
博主:&&&&
Robot Engineer
文章(207)&&&&
访问(204789)&&&&
评论(253)&&&&
投票(183)&&&&
订阅本博&&
博文列表查看方式:
需要确认注册邮箱后才能下载,
使用OK335xD核心板上的NAND Flash,无论是速度还是稳定性,都比SD卡好,所以接下来的任务是使用SD中的U-Boot操作NAND Flash,把需要的镜像烧录进去之后,就可以从NAND Flash启动了!
第一步:按照《U-Boot for AM335x》的步骤准备好:
OK335x开发板
按照TI公司官方文档的要求,格式化的SD卡(create-sdcard.sh)
准备一份编译通过的可用的U-Boot源代码(uart/mmc0/eth/gpio/i2c功能)
uImage和文件系统镜像
第二步:修改U-Boot源代码中mux部分:
static struct module_pin_mux nand_pin_mux[] = {
&&&&&&& {OFFSET(gpmc_ad0),&&&&& MODE(0) | PULLUP_EN | RXACTIVE},
&&&&&&& {OFFSET(gpmc_ad1),&&&&& MODE(0) | PULLUP_EN | RXACTIVE},
&&&&&&& {OFFSET(gpmc_ad2),&&&&& MODE(0) | PULLUP_EN | RXACTIVE},
&&&&&&& {OFFSET(gpmc_ad3),&&&&& MODE(0) | PULLUP_EN | RXACTIVE},
&&&&&&& {OFFSET(gpmc_ad4),&&&&& MODE(0) | PULLUP_EN | RXACTIVE},
&&&&&&& {OFFSET(gpmc_ad5),&&&&& MODE(0) | PULLUP_EN | RXACTIVE},
&&&&&&& {OFFSET(gpmc_ad6),&&&&& MODE(0) | PULLUP_EN | RXACTIVE},
&&&&&&& {OFFSET(gpmc_ad7),&&&&& MODE(0) | PULLUP_EN | RXACTIVE},
&&&&&&& {OFFSET(gpmc_wait0),&&& MODE(0) | PULLUP_EN | RXACTIVE},
&&&&&&& {OFFSET(gpmc_wpn),&&&&& MODE(0) | PULLUP_EN | RXACTIVE},
&&&&&&& {OFFSET(gpmc_csn0),&&&& MODE(0) | PULLUP_EN},
&&&&&&& {OFFSET(gpmc_oen_ren),& MODE(0) | PULLUP_EN},
&&&&&&& {OFFSET(gpmc_wen),&&&&& MODE(0) | PULLUP_EN},
&&&&&&& {OFFSET(gpmc_be0n_cle), MODE(0) | PULLUP_EN},
&&&&&&& {-1},
别忘了执行下面这句:
configure_module_pin_mux(nand_pin_mux);
第三步:在U-Boot源代码中board_init函数中添加:
gpmc_init();
第四步:在include/configs/maria_am335x.h中添加:
#define CONFIG_CMD_NAND
#define CONFIG_SYS_MAX_NAND_DEVICE&&&&& 1
#define CONFIG_SYS_NAND_BASE&&&&&&&&&&& 0x800000
#define CONFIG_NAND_OMAP_GPMC
#define CONFIG_NAND_OMAP_ELM
#define CONFIG_SYS_NAND_5_ADDR_CYCLE
#define CONFIG_SYS_NAND_PAGE_COUNT&&&&& (CONFIG_SYS_NAND_BLOCK_SIZE / \
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& CONFIG_SYS_NAND_PAGE_SIZE)
#define CONFIG_SYS_NAND_PAGE_SIZE&&&&&& 2048
#define CONFIG_SYS_NAND_OOBSIZE&&&&&&&& 64
#define CONFIG_SYS_NAND_BLOCK_SIZE&&&&& (128*1024)
#define CONFIG_SYS_NAND_BAD_BLOCK_POS&& NAND_LARGE_BADBLOCK_POS
#define CONFIG_SYS_NAND_ECCPOS&&&&&&&&& { 2, 3, 4, 5, 6, 7, 8, 9, \
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& 10, 11, 12, 13, 14, 15, 16, 17, \
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& 18, 19, 20, 21, 22, 23, 24, 25, \
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& 26, 27, 28, 29, 30, 31, 32, 33, \
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& 34, 35, 36, 37, 38, 39, 40, 41, \
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& 42, 43, 44, 45, 46, 47, 48, 49, \
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& 50, 51, 52, 53, 54, 55, 56, 57, }
#define CONFIG_SYS_NAND_ECCSIZE&&&&&&&& 512
#define CONFIG_SYS_NAND_ECCBYTES&&&&&&& 14
#define CONFIG_SYS_NAND_ONFI_DETECTION
#define CONFIG_NAND_OMAP_ECCSCHEME&&&&& OMAP_ECC_BCH8_CODE_HW
#define CONFIG_SYS_NAND_U_BOOT_START&&& CONFIG_SYS_TEXT_BASE
#define CONFIG_SYS_NAND_U_BOOT_OFFS&&&& 0x80000
为什么不直接只用CONFIG_NAND,这些宏不就跟着定义了吗?
因为CONFIG_NAND的含义是从NAND启动,而这里只是要对NAND Flash进行读取和烧写操作,booting设备还是SD卡。
第五步:修改arch/arm/cpu/armv7/am33xx/mem.c中的&gpmc_init&函数:
void gpmc_init(void)
&&&&&&& gpmc_cfg = (struct gpmc *)GPMC_BASE;
&&&&&&& const u32& gpmc_regs[GPMC_MAX_REG] = {& M_NAND_GPMC_CONFIG1,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& M_NAND_GPMC_CONFIG2,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& M_NAND_GPMC_CONFIG3,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& M_NAND_GPMC_CONFIG4,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& M_NAND_GPMC_CONFIG5,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& M_NAND_GPMC_CONFIG6,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& 0
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& };
&&&&&&& u32 size = GPMC_SIZE_256M;
&&&&&&& u32 base = CONFIG_SYS_NAND_BASE;
&&&&&&& writel(0x, &gpmc_cfg-&sysconfig);
&&&&&&& writel(0x, &gpmc_cfg-&irqstatus);
&&&&&&& writel(0x, &gpmc_cfg-&irqenable);
&&&&&&& writel(0x, &gpmc_cfg-&config);
&&&&&&& writel(0, &gpmc_cfg-&cs[0].config7);
&&&&&&& sdelay(1000);
&&&&&&& enable_gpmc_cs_config(gpmc_regs, &gpmc_cfg-&cs[0], base, size);
这是因为gpmc_init依赖于CONFIG_NAND,要不然基本不干活,因此去掉它的宏判断。
第六步:编译它:
make ARCH=arm CROSS_COMPILE=/opt/arm-arago-linux-gcc/usr/bin/arm-linux-gnueabihf- -j8 O=../build maria_am335x_config
make ARCH=arm CROSS_COMPILE=/opt/arm-arago-linux-gcc/usr/bin/arm-linux-gnueabihf- -j8 O=../build all
第七步:将生成的MLO和u-boot.img放置到SD卡中:
cp ../build/MLO ../build/u-boot.img /run/media/maria/boot/
第八步:开发板插入SD卡,设置为从SD卡启动,上电。
在命令提示符下输入:
U-Boot# set ipaddr 192.168.1.117
U-Boot# set serverip 192.168.1.116
U-Boot# tftp 0x MLO
U-Boot# nand erase 0x0 0x20000
U-Boot# nand write.i 0xx0 0x20000
U-Boot# tftp 0x u-boot.img
U-Boot# nand erase 0x00
U-Boot# nand write.i 0xx00
这些命令的含义是,从tftp服务器上获取MLO和u-boot.img,存放在SDRAM的0x处,并分别烧写在NAND Flash的0x0和0x80000地址。拔除SD卡,重新上电,就能看到U-Boot从NAND Flash启动的串口打印信息了!
NOTICE: 存放在tftp上的MLO和u-boot.img不能是Forlinx光盘里面的镜像,也不是上面所述的这个,而是需要使用全新的源代码重新编译。因为Forlinx和这里的MLO和u-boot.img都是从SD卡启动的,全新编译出来的应该是从NAND Flash启动。参照boards.cfg文件!
现在,这张SD卡就相当于一个下载器了,可以使用它实现读取和烧写存储器的功能,包括串口、SD卡和NAND Flash操作,这也说明,U-Boot的重要性,硬件开发绝对绕不开它!
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮
1.扫描左侧二维码
2.点击右上角的分享按钮
3.选择分享给朋友
&&&&&&有[ 1 ]名读者喜欢此文
阅读(1654)&&
最近到访博主
评论是对思考最好的总结…
你还可以输入1000字
对的,这里的SRAM应该是SDRAM,多谢啦~
--- 现有 2 个主题,共 1 页 ---
转发到我的博客
评论&&的“为AM335x移植Linux内核主线代码(7)使用SD卡中的U-Boot操作NAND Flash”
使用OK335xD核心板上的NANDFlash,无论是速度还是稳定性,都比SD卡好,所以接下来的任务是使用SD中的U-Boot操作NANDFlash,把需要的镜像烧录进去之后,就可以从NANDFlash启动了!第一步:按照《U-BootforAM335x》的步骤准备好:OK335x开发板按照TI公司...
你还可以输入30000字
同时评论给&不是猫咪不是机器人
Robot Engineer
不是猫咪不是机器人&&13:32 06-06
liumingd&&09:48 06-06
jwdxu2009&&18:32 06-05
zcz2004&&16:00 06-03
jthykj&&09:46 06-03
成员3221名创建者:
-- Use of this website is subject to its terms of use.
京ICP备号-4 |
京公网安备37 |
新版社区已上线,旧版论坛、博客将停用
1、为防数据丢失,旧版论坛、博客不再接受发帖;
2、老用户只需重设密码,即可直接登录新平台;
3、新版博客将于8月底完美归来,敬请期待;
4、全新论坛、问答,体验升级、手机阅读更方便。AM335x通过GPMC快速读取FPGA数据的问题——读写速率完全不行 - Sitara(TM) Cortex-A8 和 ARM9 微处理器 - 德州仪器在线技术支持社区
AM335x通过GPMC快速读取FPGA数据的问题——读写速率完全不行
发表于2年前
<input type="hidden" id="hGroupID" value="34"
& & 通过AM335x的GPMC来访问FPGA,FPGA作为norflash设备,使用了CS2,同步模式,连续不断的读取数据,未使用bust模式。&/p>
&p>& & 通过示波器测试相关信号,发现每两次读取16bit数据时间间隔为300ns,即两次CS2片选下降沿为300ns(每次都是)。每次读取的时间大概是70ns左右(片选,读使能等信号的低电平持续时间),总是有很长一段时间的高电平持续时间,造成无法达到本来预想的读取速度。&/p>
&p>& & 根据手册,设置了相关的寄存器,没有效果。如果将两次读取的间隔时间设长,会发现两次读取的时间会延长(超过300ns),但是无法降低到300ns以下。&/p>
&p>& & 不知道还有什么地方可以设置两次读之间的时间。还是所AM335x性能就这样(以前是有ARM9,读写速率都比这个快!!!!!!!!),如果这样就完全失去了使用这款芯片的意义。&/p>
&p>& & 盼回复&/p>&div style=&clear:&>&/div>" />
AM335x通过GPMC快速读取FPGA数据的问题——读写速率完全不行
此问题尚无答案
All Replies
& & 通过AM335x的GPMC来访问FPGA,FPGA作为norflash设备,使用了CS2,同步模式,连续不断的读取数据,未使用bust模式。
& & 通过示波器测试相关信号,发现每两次读取16bit数据时间间隔为300ns,即两次CS2片选下降沿为300ns(每次都是)。每次读取的时间大概是70ns左右(片选,读使能等信号的低电平持续时间),总是有很长一段时间的高电平持续时间,造成无法达到本来预想的读取速度。
& & 根据手册,设置了相关的寄存器,没有效果。如果将两次读取的间隔时间设长,会发现两次读取的时间会延长(超过300ns),但是无法降低到300ns以下。
& & 不知道还有什么地方可以设置两次读之间的时间。还是所AM335x性能就这样(以前是有ARM9,读写速率都比这个快!!!!!!!!),如果这样就完全失去了使用这款芯片的意义。
& & 盼回复
You have posted to a forum that requires a moderator to approve posts before they are publicly available.
榜眼8966分
把你的配置信息之类的贴上来讨论啊
You have posted to a forum that requires a moderator to approve posts before they are publicly available.
配置参数:
#define STNOR_GPMC_CONFIG1 0x#define STNOR_GPMC_CONFIG2 0x#define STNOR_GPMC_CONFIG3 0x#define STNOR_GPMC_CONFIG4 0x#define STNOR_GPMC_CONFIG5 0x#define STNOR_GPMC_CONFIG6 0x
将两个成功片选间隔设置为了1个时钟周期,大概为10ns,实际测量,片选低电平大概70ns左右,和设置的基本一致。高电平200多ns!!如果将连个成功片选间隔增加的话,高电平持续也会跟着增加。貌似200多ns就是最小值了。。。。。
还有两次读取之间没有进行其他操作,使用的是ioread16_rep函数连续读取大量数据。
这不会是GPMC的读取速度的限制吧。。。
You have posted to a forum that requires a moderator to approve posts before they are publicly available.
榜眼8966分
我的配置是这样的
#define STNOR_GPMC_CONFIG1&&0x#define STNOR_GPMC_CONFIG2&&0x#define STNOR_GPMC_CONFIG3&0x0#define STNOR_GPMC_CONFIG4&&0x#define STNOR_GPMC_CONFIG5&0x#define STNOR_GPMC_CONFIG6&0x0
写100kB时间大约70ms,读100kB大概3ms
You have posted to a forum that requires a moderator to approve posts before they are publicly available.
我看了看您配置的参数,使用的是异步模式。
我们这边的配置参数是和FPGA配合的,修改后就不能正常读取fpga的状态和数据了。
我修改了一下程序,不去管fpga的状态,直接读取数据,通过示波器查看波形。使用了您除了GPMC_CONFIG1的配置以外的其他配置,片选情况还是没有改变。片选的低电平变短了点,但是高电平还是那么多。
难道内核或者其他什么地方对这个高电平还能有什么设置????
You have posted to a forum that requires a moderator to approve posts before they are publicly available.
探花10891分
使用GPMC与FPGA通信,可以多留一个GPIO连到FPGA。
使用GPIO触发EDMA中断,读取FPGA内FIFO中的数据。
如果答案回答了您的问题,请确认答案,谢谢!:)
You have posted to a forum that requires a moderator to approve posts before they are publicly available.
没懂您的意思。
多连一个GPIO就能提高读取的速度?
连上以后读取操作怎么进行?
是FPGA发出中断,ARM响应去读取FPGA的数据??
现在我们实现的是ARM不断读取FPGA的寄存器来判断什么时候开始读取数据,开始读取数据时,是一次性读取很多字节数据。比如说一次性读取100个字节的数据,由于使用的16bit读取,肯定会重复读取50次,这50次中每两次间隔就是300ns。这50次读取是调用一次ioread16_rep函数来实现的。
You have posted to a forum that requires a moderator to approve posts before they are publicly available.
探花10891分
我的意思是通过GPIO触发EDMA,通过EDMA的方式去FPGA内的FIFO中读取数据。这不是中断。。。
具体查看TRM EDMA的章节。
如果答案回答了您的问题,请确认答案,谢谢!:)
You have posted to a forum that requires a moderator to approve posts before they are publicly available.
哦。回头我看一看。
这种方式读写速度会比不用快很多么?
为什么使用GPMC直接读取会这么慢呢?以前使用ARM9的时候速度都快很多啊,不过不是用的GPMC。
这种限制是什么情况下造成的?
You have posted to a forum that requires a moderator to approve posts before they are publicly available.
榜眼8966分
我这个也是和fpga通信的,完全没啥问题啊
你们fpga程序是不是没配合好啊
You have posted to a forum that requires a moderator to approve posts before they are publicly available.
榜眼8966分
你确定自己的配置是对的吗? 我用你的配置和fpga通信,写时序是这个样子,感觉不对啊
You have posted to a forum that requires a moderator to approve posts before they are publicly available.
应该是没有问题的,必须和fpga相配合。
所以用你的配置从我这边的fpga读不到数据的。我只是用示波器看了看片选,时钟等信号的波形。
使用我的配置,读写fpga都没有问题,就是读的速度太慢,找不到原因。
PS:你这个截图使用什么工具看时序的,我们还是用示波器看的,落后啊:)
You have posted to a forum that requires a moderator to approve posts before they are publicly available.
榜眼8966分
你的读写fpga是对的吗?你看我的图,地址线没有变化哦
我这个是从fpga测抓出来的信号,使用的配置是和你的一样的
使用edma貌似速度能够上去,不过目前还没研究过&
You have posted to a forum that requires a moderator to approve posts before they are publicly available.
你地址抓的是那个管脚的信号?
我们用的是地址数据复用。读写都没有问题的
你使用的抓图工具是什么啊?
You have posted to a forum that requires a moderator to approve posts before they are publicly available.
榜眼8966分
那怪不得没地址信息,我没注意到你是地址和数据线复用的,等我测试一下看看;
抓图工具用的是 quantus里面的SignalTap
You have posted to a forum that requires a moderator to approve posts before they are publicly available.

我要回帖

更多关于 am335x nandflash 的文章

 

随机推荐