书接上文,在上一篇(https://blog.csdn.net/qq_27379251/article/details/89416075)中将程序运行在了外部SRAM中,网上看到一篇文章https://www.cnblogs.com/killer-xc/p/6594422.html,将外部的SRAM作为内存来使用,自己试着配置了一下,使用的还是上一篇中的工程,但是程序运行到main函数中的 LCD_Init(); 有的时候程序出错运行到了 HardFault_Handler() 经跟踪程序汇编,发现有的时候会导致在SRAM中的堆栈被破坏掉,想到 LCD 和 外部SRAM都使用的是FSMC总线,在配置LCD的时候,总线上有数据,这时候外部SRAM也在运行中,FSMC总线上同时挂着LCD 和 SRAM 而SRAM由于作为了内存使用,这时候也不能暂时被停掉所以SRAM中的数据有可能被破坏掉,注释掉有关LCD的代码,运行就没问题了,但是又遇到新问题,定义了一个200KB的大数组(在SRAM上)给这个数组写数据,然后读出来看是否一致,定义了一个for循环:
for(cnti=0; cnti<sizeof(testbuf);cnti++ )
{
testbuf[cnti] = 0x11;
}
但是 cnti 是一个全局变量,它在SRAM中,调试发现有的时候cnti有的时候就跑飞了,出现了一个脏数,但是把它定在内部RAM中就没有问题,百思不得其解,后来想是不是硬件的问题,因此将 cnti 定义在内部SRAM中,循环改为:
for(cnti=0; cnti<sizeof(testbuf);cnti++ )
{
testbuf[cnti] = 0x11;
testbuf[cnti] = 0x11;
testbuf[cnti] = 0x11;
testbuf[cnti] = 0x11;
}
发现连续得给外部SRAM中赋值就有问题,现在只能暂且认为硬件配置的时序不太合适,在***高速下会有问题,还需再好好研究一下时序图***。同样这也给自己一个提示,之前工作时,一位老工程师讲他们使用芯片RAM时,假如片内有好几块RAM,首选什么样子的RAM作为bootloader的堆栈,其次的选择是什么,现在感觉很有意义。搞底层就要既懂硬件又懂软件。
(仔细看了一下SRAM的datasheet,然后分析了FSMC的初始化部分,想到即使硬件设计的不太好,在高速下有问题,但是可以通过修改软件的配置,使软件慢下来,使时序慢一些,这样或许可以好一些,然后修改了FSMC初始化部分地址建立时间
readWriteTiming.FSMC_AddressSetupTime = 0x01; // 0x00;
从 0x00改为了0x01使地址建立时间多一些,然后继续跑测试代码就没有问题了。
虽然程序跑通了,但是这样外挂SRAM必然导致了芯片执行指令变慢(访问外部SRAM会比访问外部SRAM慢),在实际项目中肯定是尽量优化代码,以使内部RAM够用。这篇文章和上一篇文章虽然在实际工程中或许没有应用场景,但是说明了一个嵌入式开发中的一个加载域与执行域的基本问题,也还是有借鉴意义的。
)。
说一下,参考的那个工程吧,
参考工程在启动文件中修改了 __initial_sp EQU 0x20000000+Stack_Size 这是给__initial_sp 符一个值,它指向了内部SRAM,芯片启动的时候外部SRAM还没有被初始化,这时候只有内部RAM能用,就先用内部RAM了,但是经过__main之后发现堆栈指针SP已经指向了外部SRAM(在它之前还是内部RAM呢)。
在工程的配置中必须在RAM1处打勾
这样才能将大数组定义在外部的SRAM中,打勾的意思或许是默认使用外部RAM吧。