织梦CMS - 轻松建站从此开始!

罗索

ADS、Linux、u-boot让我加深了对volatile的认识

jackyhwei 发布于 2010-11-14 12:27 点击:次 
最近在升级u-boot,从1.1.4升级到1.3.3,原因是想用Linux的MTD层和nand驱动,方便管理坏块。可是一个问题困扰了一整天,NAND初始化总是不正确,经过排查,定位到读ID不正确。
TAG:

最近在升级u-boot,从1.1.4升级到1.3.3,原因是想用Linux的MTD层和nand驱动,方便管理坏块。

可是一个问题困扰了一整天,NAND初始化总是不正确,经过排查,定位到读ID不正确。

4020这颗芯片读ID应该很简单的,只要发送0x80000090命令,再读取EMI的NAND_ID寄存器就行了,可我怎么用了一整天都读不正确呢?于是写了一段最简单的代码来验证:

首先是ADS的代码:
    IntInit();
    InitEmi();
   InitGpio();
    
*(unsigned long*)EMI_NAND_COM = 0X00000090;
*(unsigned long*)EMI_NAND_COM |= 0X80000000;

   tempnand = (*(volatile unsigned long*)EMI_NAND_ID)>>8;

发现读取是正确的。

然后是Linux下的代码:

*(unsigned long*)INTC_IMR_V = 0XFFFFFFFF;

*(unsigned long*)INTC_IMR_V = 0X00000000;

*(unsigned long*)EMI_NAND_CONF1_V = 0x06302857;

   *(unsigned long*)EMI_NAND_CONF2_V = 0x00514353;

 

   *(unsigned long*)GPIO_PORTG_SEL_V |= 0x0080;

   *(unsigned long*)GPIO_PORTG_DATA_V |= 0x0080;

*(unsigned long*)GPIO_PORTG_DIR_V &= ~0x0080;

 

*(unsigned long*)EMI_NAND_COM_V = 0X00000090;

*(unsigned long*)EMI_NAND_COM_V |= 0X80000000;

unsigned int tempnand = (*(volatile unsigned long*)EMI_NAND_ID_V)>>8;

printk("read id! id is 0x%x,0x%x\n\n",tempnand,EMI_NAND_ID_V );

启动时发现,tempnand的值为0;

最后是u-boot的代码:

*(unsigned long*)INTC_IMR_V = 0XFFFFFFFF;

*(unsigned long*)INTC_IMR_V = 0X00000000;

*(unsigned long*)EMI_NAND_CONF1_V = 0x06302857;

   *(unsigned long*)EMI_NAND_CONF2_V = 0x00514353;

 

   *(unsigned long*)GPIO_PORTG_SEL_V |= 0x0080;

   *(unsigned long*)GPIO_PORTG_DATA_V |= 0x0080;

*(unsigned long*)GPIO_PORTG_DIR_V &= ~0x0080;

 

*(unsigned long*)EMI_NAND_COM_V = 0X00000090;

*(unsigned long*)EMI_NAND_COM_V |= 0X80000000;

unsigned int tempnand = (EMI_NAND_ID)>>8;
printk("read id! id is 0x%x\n\n", tempnand);

打印的值更诡异,竟然是0x800000。

 

奇怪吧,容我解释逐条解释原因:

1)Linux的代码,在加上volatile后,顺利的读出了ID,难道这就是传说中的因为没加volatile,同一个寄存器赋值两次,被优化掉了!!!???

2)怀疑u-boot代码也是volatile原因,在添加后,依然不成功?

3)仔细看u-boot的寄存器定义:

#define EMI_NAND_ID      (REGW(EMI_BASE+0X130))

比Linux多了个REGW,这个REGW是什么东西???

翻到上面,赫然看到:

#define REGW(addr) (*(volatile unsigned int *)(addr))

晕,人家都加好了,再加一遍,数据能对就怪了!

附修改后的代码:

Linux:

*(volatile unsigned long*)INTC_IMR_V = 0XFFFFFFFF;

*(volatile unsigned long*)INTC_IMR_V = 0X00000000;

*(volatile unsigned long*)EMI_NAND_CONF1_V = 0x06302857;

   *(volatile unsigned long*)EMI_NAND_CONF2_V = 0x00514353;

   *(volatile unsigned long*)GPIO_PORTG_SEL_V |= 0x0080;

   *(volatile unsigned long*)GPIO_PORTG_DATA_V |= 0x0080;

*(volatile unsigned long*)GPIO_PORTG_DIR_V &= ~0x0080;

 

*(volatile unsigned long*)EMI_NAND_COM_V = 0X00000090;

*(volatile unsigned long*)EMI_NAND_COM_V |= 0X80000000;

unsigned int tempnand = (*(volatile unsigned long*)EMI_NAND_ID_V)>>8;

printk("read id! id is 0x%x,0x%x\n\n",tempnand,EMI_NAND_ID_V );

 

u-boot:

INTC_IMR = 0XFFFFFFFF;

INTC_IMR = 0X00000000;

EMI_NAND_CONF1 = 0x06302857;

   EMI_NAND_CONF2 = 0x00514353;

   GPIO_PORTG_SEL |= 0x0080;

   GPIO_PORTG_DATA |= 0x0080;

GPIO_PORTG_DIR &= ~0x0080;

EMI_NAND_COM = 0X00000090;
EMI_NAND_COM |= 0X80000000;


unsigned int tempnand = (EMI_NAND_ID)>>8;
printk("read id! id is 0x%x\n\n", tempnand);

(aokikyon)
本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。转载请注明:文章转载自:罗索实验室 [http://www.rosoo.net/a/201011/10463.html]
本文出处:百度博客 作者:aokikyon
顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
将本文分享到微信
织梦二维码生成器
推荐内容