共2条
1/1 1 跳转至页
LPC2210,flash 关于LPC2210的flash操作?奇怪,请周立功高手回答一下!
问
ARM2200开发板中,flash的地址线A0~A17分别连接到LPC2210的A1~A18,那么实际上从CPU发出读写地址时要把地址左移一位才行吧,例如:
flash地址 cpu发送的读写地址 (假设基址设在0x81000000)
0x0000 0x81000000
0x0001 0x81000002
0x0002 0x81000004
那么这样cpu的外部bank1(0x81000000)地址岂不不连续了?实际应该应该不是这样啊,我哪里理解错了呢?
但是ARM2200远程序写flash和擦除flash又确实显示地左移了一位啊,程序如下:
#define FLASH_ADDR 0x81000000
#define GetAddr(addr) (volatile uint16 *)(FLASH_ADDR|(addr<<1)) //这个宏负责左移
uint8 ChipErase(void)
{ volatile uint16 *ip;
uint16 temp1,temp2;
ip = GetAddr(0x5555);
ip[0] = 0xaaaa; // 第一个写周期,地址0x5555,数据0xAA
ip = GetAddr(0x2aaa);
ip[0] = 0x5555; // 第二个写周期,地址0x2aaa,数据0x55
ip = GetAddr(0x5555);
ip[0] = 0x8080; // 第三个写周期,地址0x5555,数据0x80
ip = GetAddr(0x5555);
ip[0] = 0xaaaa; // 第四个写周期,地址0x5555,数据0xAA
ip = GetAddr(0x2aaa);
ip[0] = 0x5555; // 第五个写周期,地址0x2aaa,数据0x55
ip = GetAddr(0x5555);
ip[0] = 0x1010; // 第六个写周期,地址0x5555,数据0x10
while (1) // 等待操作完成 (若擦除操作没有完成,每次读操作DQ6会跳变)
{ temp1 = *ip;
temp2 = *ip;
if (temp1 == temp2)
{ if (temp1 != 0xffff)
{ return(FALSE);
}
else
{ return(TRUE);
}
}
}
return(TRUE);
}
还有一个疑问就是关于扇区擦除:
如果地址确实需要左移一位,那么扇区擦除的地址也应该左移一位啊,flash扇区地址为A12~A17,那对应的cpu地址应该在A13~A18啊,可是我试过了,实际的擦除地址仍然对应cpu地址应该在A12~A17,这就奇怪了,为什么这时候又不用左移一位了呢? 答 1: re1.EasyARM2200开发板的外部Ram和Flash都是16位的。故访问外部Ram和Flash时候,地址线A0是没有用的。
2.擦写Flash时,如果要读取Flash的物理地址0x5555上的数据,那么ARM外部存储器总线上就得送出FLASH_ADDR|(0x5555<<1)的地址信号,这样flash扇区地址A0~A18上才会出现0x5555的地址信号。 答 2: 麻烦再详细一下,看我下面的理解到底错在哪了?请zlg高手帮忙!是这样的啊,我也是这样理解的啊。
一句话总结就是:
flash上的地址线A0~A17最终对应LPC2210的地址线A1~A18。
如果正常操作都要左移的话,我就能理解,但为什么下面情况没有左移:
1、写flash。
uint8 WordProgram(uint32 Addr, uint16 Data)
{ volatile uint16 *ip;
uint16 temp1,temp2;
ip = GetAddr(0x5555); // 转换地址0x5555
*ip = 0xaaaa; // 第一个写周期,地址0x5555,数据0xAA
ip = GetAddr(0x2aaa);
*ip = 0x5555; // 第二个写周期,地址0x2aaa,数据0x55
ip = GetAddr(0x5555);
*ip = 0xa0a0; // 第三个写周期,地址0x5555,数据0xA0
ip = (volatile uint16 *)(FLASH_ADDR_BASE|Addr);
*ip = Data; // 第四个写周期,地址Addr,数据Data
while (1) // 等待操作完成 (若编程操作没有完成,每次读操作DQ6会跳变)
{ temp1 = *ip;
temp2 = *ip;
if (temp1 == temp2)
{ if (temp1 != Data)
{ return(FALSE);
}
else
{ return(TRUE);
}
}
}
return(TRUE);
}
注意上面第四个写周期没有用GetAddr宏,这个宏会把flash的写地址左移一位。
但这一条没有左移:ip = (volatile uint16 *)(FLASH_ADDR_BASE|Addr);
但写入flash写入的数据是正确的,如果把这个地址左移了写入flash的数据反而是错误的。Addr就是flash的实际地址,是字对齐的。
2、起始读flash的操作也没有左移地址,如:
*(uint16 *0x80000002)实际读到的就是0x80000002的flash内容,而按照上面说的左移一位,读0x80000002处的flash,LPC2210上的地址应该是0x80000004啊。
3、扇区擦除时,扇区号出现在sst39sf160的地址线A12~A17,而实际从LPC2210输出的地址中,sst39sf160的扇区号也出现在A12~A17,按照前面说的应该左移一位出现在A13~A18才对啊。 答 3: re请大侠再漏一次面啊?
这个问题我实在是想不通,帮帮忙! 答 4: re你的程序在调用函数WordProgram(uint32 Addr, uint16 Data)对Flash操作的时候,Addr是已经是偶数地址了(所以A0实际上是没有用的),如果你再对Addr进行左移一位,那么就写到其他地址上去了。
答 5: re还是不能明白,烦请版主详细点。
尤其是扇区擦除时,扇区号应该出现在sst39sf160的地址线A12~A17,而按照实际电路图的接法,从LCP2210出来的flash扇区的地址线应该左移一位,即在LPC的地址线A13~A18才对。
可我实际写程序的时候发现flash扇区号的地址也要出现在LPC2210的A12~A18扇区擦除才正常。
到底是什么地方出了问题?
请版主详细讲讲。
flash地址 cpu发送的读写地址 (假设基址设在0x81000000)
0x0000 0x81000000
0x0001 0x81000002
0x0002 0x81000004
那么这样cpu的外部bank1(0x81000000)地址岂不不连续了?实际应该应该不是这样啊,我哪里理解错了呢?
但是ARM2200远程序写flash和擦除flash又确实显示地左移了一位啊,程序如下:
#define FLASH_ADDR 0x81000000
#define GetAddr(addr) (volatile uint16 *)(FLASH_ADDR|(addr<<1)) //这个宏负责左移
uint8 ChipErase(void)
{ volatile uint16 *ip;
uint16 temp1,temp2;
ip = GetAddr(0x5555);
ip[0] = 0xaaaa; // 第一个写周期,地址0x5555,数据0xAA
ip = GetAddr(0x2aaa);
ip[0] = 0x5555; // 第二个写周期,地址0x2aaa,数据0x55
ip = GetAddr(0x5555);
ip[0] = 0x8080; // 第三个写周期,地址0x5555,数据0x80
ip = GetAddr(0x5555);
ip[0] = 0xaaaa; // 第四个写周期,地址0x5555,数据0xAA
ip = GetAddr(0x2aaa);
ip[0] = 0x5555; // 第五个写周期,地址0x2aaa,数据0x55
ip = GetAddr(0x5555);
ip[0] = 0x1010; // 第六个写周期,地址0x5555,数据0x10
while (1) // 等待操作完成 (若擦除操作没有完成,每次读操作DQ6会跳变)
{ temp1 = *ip;
temp2 = *ip;
if (temp1 == temp2)
{ if (temp1 != 0xffff)
{ return(FALSE);
}
else
{ return(TRUE);
}
}
}
return(TRUE);
}
还有一个疑问就是关于扇区擦除:
如果地址确实需要左移一位,那么扇区擦除的地址也应该左移一位啊,flash扇区地址为A12~A17,那对应的cpu地址应该在A13~A18啊,可是我试过了,实际的擦除地址仍然对应cpu地址应该在A12~A17,这就奇怪了,为什么这时候又不用左移一位了呢? 答 1: re1.EasyARM2200开发板的外部Ram和Flash都是16位的。故访问外部Ram和Flash时候,地址线A0是没有用的。
2.擦写Flash时,如果要读取Flash的物理地址0x5555上的数据,那么ARM外部存储器总线上就得送出FLASH_ADDR|(0x5555<<1)的地址信号,这样flash扇区地址A0~A18上才会出现0x5555的地址信号。 答 2: 麻烦再详细一下,看我下面的理解到底错在哪了?请zlg高手帮忙!是这样的啊,我也是这样理解的啊。
一句话总结就是:
flash上的地址线A0~A17最终对应LPC2210的地址线A1~A18。
如果正常操作都要左移的话,我就能理解,但为什么下面情况没有左移:
1、写flash。
uint8 WordProgram(uint32 Addr, uint16 Data)
{ volatile uint16 *ip;
uint16 temp1,temp2;
ip = GetAddr(0x5555); // 转换地址0x5555
*ip = 0xaaaa; // 第一个写周期,地址0x5555,数据0xAA
ip = GetAddr(0x2aaa);
*ip = 0x5555; // 第二个写周期,地址0x2aaa,数据0x55
ip = GetAddr(0x5555);
*ip = 0xa0a0; // 第三个写周期,地址0x5555,数据0xA0
ip = (volatile uint16 *)(FLASH_ADDR_BASE|Addr);
*ip = Data; // 第四个写周期,地址Addr,数据Data
while (1) // 等待操作完成 (若编程操作没有完成,每次读操作DQ6会跳变)
{ temp1 = *ip;
temp2 = *ip;
if (temp1 == temp2)
{ if (temp1 != Data)
{ return(FALSE);
}
else
{ return(TRUE);
}
}
}
return(TRUE);
}
注意上面第四个写周期没有用GetAddr宏,这个宏会把flash的写地址左移一位。
但这一条没有左移:ip = (volatile uint16 *)(FLASH_ADDR_BASE|Addr);
但写入flash写入的数据是正确的,如果把这个地址左移了写入flash的数据反而是错误的。Addr就是flash的实际地址,是字对齐的。
2、起始读flash的操作也没有左移地址,如:
*(uint16 *0x80000002)实际读到的就是0x80000002的flash内容,而按照上面说的左移一位,读0x80000002处的flash,LPC2210上的地址应该是0x80000004啊。
3、扇区擦除时,扇区号出现在sst39sf160的地址线A12~A17,而实际从LPC2210输出的地址中,sst39sf160的扇区号也出现在A12~A17,按照前面说的应该左移一位出现在A13~A18才对啊。 答 3: re请大侠再漏一次面啊?
这个问题我实在是想不通,帮帮忙! 答 4: re你的程序在调用函数WordProgram(uint32 Addr, uint16 Data)对Flash操作的时候,Addr是已经是偶数地址了(所以A0实际上是没有用的),如果你再对Addr进行左移一位,那么就写到其他地址上去了。
答 5: re还是不能明白,烦请版主详细点。
尤其是扇区擦除时,扇区号应该出现在sst39sf160的地址线A12~A17,而按照实际电路图的接法,从LCP2210出来的flash扇区的地址线应该左移一位,即在LPC的地址线A13~A18才对。
可我实际写程序的时候发现flash扇区号的地址也要出现在LPC2210的A12~A18扇区擦除才正常。
到底是什么地方出了问题?
请版主详细讲讲。
共2条
1/1 1 跳转至页
回复
有奖活动 | |
---|---|
【有奖活动】分享技术经验,兑换京东卡 | |
话不多说,快进群! | |
请大声喊出:我要开发板! | |
【有奖活动】EEPW网站征稿正在进行时,欢迎踊跃投稿啦 | |
奖!发布技术笔记,技术评测贴换取您心仪的礼品 | |
打赏了!打赏了!打赏了! |