过去,我使用8位AVR和MSP430进行了大量工作,其中RAM和闪存都直接存储在芯片上。当你编译和下载你的程序时,它只是“正常工作”,你不必担心实际存储变量的位置和方式。
现在我正在启动一个项目,我希望能够为微控制器添加一些外部存储器(如果重要的话,可以使用TI Stellaris LM3S9D92),但我不完全确定如何使用代码来使用外部RAM。我可以看到你如何配置外部总线与其他外围设备非常相似,但令我困惑的是处理器如何跟踪何时与外部存储器通信以及何时与内部存储器通信。
据我所知,外部RAM映射到与内部SRAM相同的地址空间(内部从0x20000000开始,外部从0x60000000开始)。这是否意味着我写了这样的东西:
int* x= 0x20000000;
int* y= 0x60000000;
x和y分别指向内部和外部RAM的前4个字节(假设32位整数)吗?如果是这样,如果我做了这样的事情怎么办?
int x[999999999999]; //some super big array that uses all the internal ram
int y[999999999999]; //this would have to be in external ram or it wouldn't fit
我想我需要告诉某些事情关于每种类型内存的界限,或者我是否完全错了,硬件自己解决了什么?链接器脚本是否处理此问题?我知道他们与内存映射有关,但我不知道到底是什么。在阅读了有关如何设置ARM交叉编译器之后,我感觉像winavr(avr-gcc)之类的东西在幕后为我做了很多这样的事情,所以我不必处理它。
很抱歉有点乱,但如果有人能告诉我我是否在这条东西的正确轨道上,我真的很感激。
更新
对于任何未来的读者,我在谷歌搜索后再发现这几个小时http://www.bravegnu.org/gnu-eprog/index.html。结合答案,这对我帮助很大。
答案 0 :(得分:11)
一般来说,这正是它的工作原理。您必须正确设置硬件和/或硬件可能已经在固定地址处硬编码。
你可以问同样的问题,硬件如何知道当我写一个字节到地址0x21000010(我刚才那么说)那就是uart发送保持寄存器而那个写意味着我想发送一个字节uart?答案是因为它以逻辑方式硬编码。或者逻辑可能有一个偏移量,uart可能会移动它可能在某些其他控制寄存器内容加上0x10。将该控制寄存器(其本身具有一些硬编码地址)从0x21000000更改为0x90000000,然后写入0x90000010,另一个字节输出uart。
我必须查看那个特定的部分,但如果它确实支持外部存储器,那么从理论上讲,您只需知道处理器地址空间中的哪些地址映射到该外部存储器并且读取和写入将是导致外部存储器访问。
基于英特尔的计算机,PC,往往喜欢一个大的扁平地址空间,在你的Linux机箱上使用lspci命令(如果你有的话)或者其他命令(如果是windows或mac),你会发现你的视频卡已被给予一大块地址空间。如果你通过cpu /操作系统的保护并写入该空间的地址,它将通过pcie控制器直接进入处理器并进入视频卡,造成严重破坏或者只是改变颜色像素。您已经使用avr和msp430处理了这个问题。地址空间中的一些地址是闪存,有些是ram,cpu核心外部有一些逻辑,它们查看cpu核心地址总线并决定发送该访问的位置。到目前为止,闪存库和RAM存储库和逻辑都是自包含在芯片边界内的,这远远超出逻辑响应地址的范围,并且从中创建外部存储器周期,当它是完成或结果在读取时返回它完成内部存储器循环,然后继续下一步。
这是否有意义,还是我让它变得更糟?
答案 1 :(得分:0)
您可以使用保留字寄存器向编译器建议它将该变量放入内部存储器位置: 注册int iInside; 谨慎使用;编译器知道有多少字节的寄存器存储可用,并且当所有可用空间都消失时无关紧要。
仅将注册变量用于非常频繁使用的内容,例如计数器。