TA的每日心情 | 无聊 2017-3-12 00:04 |
---|
签到天数: 62 天 连续签到: 1 天 [LV.6]常住居民II
|
鉴于F7那么强大的功能,如果没有一个充足的内存空间,再多的外设也会受到执行空间的限制,当然一般的程序,这个还真是不需要考虑,但是你要是想跑个大点的系统或者想要做个炫酷的GUI,或者实现炫酷的功能,肯能内部的SRAM就不够用了,我们先看一下内部SRAM的分配,整个的SRAM 共分为4个部分,但是用户可用的只有3个部分,ITCM RAM为指令存储区,只能被CPU访问,字节大小为4kb,系统SRAM总计有320KB,SRAM1的起始地址为0x2001000总共字节大小为240KB可以直接被所有的AHB总线存取,SRAM2的起始地址为0x2004C000总字节大小为16KB可以直接被所有的AHB总线存取. DTCM-RAM起始地址为0x20000000总字节大小为64KB可以直接被所有的AHB总线存取但是通过一种特殊的AHB从总线。其实用大白话来说DTCM-RAM和ITCM-RAM的存储速度更快,就是内部的高速缓冲区,可以直接开启的。这么算来供我们实际使用的RAM为256KB字节,256说大不大,说小不小,曾经做了一个项目用的是M4的核内部也是256KB的内存,后来实现一个功能的时候就是由于SRAM的空间不够伤透了脑筋,要是能使用SDRAM那可是如虎添翼啊。今天的帖子要做的事情就是让我们的程序在SDRAM上运行。在这里想说明一下,其实SDRAM和SRAM的区别呢没有特别大的地方,在小狂的认知中,SRAM的速度比SDRAM的速度要快,但是由于技术的限制,SRAM做不大,大的SRAM的价格也是相当昂贵,总的来说性价比不高,就是你会发现一个芯片内部的SRAM总不会超过1M的,SDRAM虽然说速度慢点,但是性价比还是比较高的。当然有好多前辈们在F4上实现了,小狂这里也是参考修改,加上自己的理解,如果有不对的地方,还请指正,谢谢。
在这里我们先分析一下F7对SDRAM的支持。内部存在两个SDRAM的控制器,每一个有13位行地址,11位列地址,4个块,每一个控制器最大支持256MB。也就是说两块最大支持512MB(在这里偷偷笑一下,如果是这样的话,哈哈,那岂不是玩啥都不是问题了,哈哈,我都有想把LINUX内核移植到F7的冲动了,哈哈)
DISCOVERY板子上有一片SDRAM,内部存储空间128Mb,也就是16MB的内存,一般的应用也是足够了,对于单片机来说,这个存储空间完全够用,妈妈再也不怕我存储空间不够了,哈哈。
介绍也基本完事了,下面就要实现功能了,其实,实现功能很简单,在这里不得不说一下STM32的启动流程了,在初学者的世界里,大部分人都认为main函数是一个程序的开始,其实并不是这样,每一个STM32都会有一个启动文件,在这个文件里会初始化单片机的堆栈空间,定义中断变量,初始化系统时钟,最后才会进入到main函数中去执行相应的程序,这个事编译器给我们做好的事情,从单片机步入嵌入式的行列就会更加明白这个的流程,因为大部分的嵌入式是没有集成的IDE的所有的都要自己写,自己完成。要实现我们想要的功能也不难,也就几个步骤,因为我们使用的是集成的IDE keil,所有的内存分配都是在编译的时候完成的。
- 1、在keil5中重新定义RAM的分配
- 2、修改启动文件,在执行Main函数之前初始化SDRAM。
- 3、重新把栈指针指向SDRAM,然后转到main函数。
先说第一步,修改编译器的内存分配,看图
因为我们得SDRAM挂在了Bank1上,其实地址为0xC0000000,所以我们的RAM中的起始地址也是0xC0000000,大小为16MB,换算成二进制位0x1000000,这样软件就分配好了内存空间,其次是修改启动代码,这一部分基本上都是用汇编写的,但是也都是基本的语言,看不懂可以百度搜索一下,基本上就没有啥问题,我们就是主要添加几个部分
1和3基本上不用你来写,是自己生成的,主要是1、定义栈空间3、定义堆空间,2的目的是在SRAM中开辟一个空间用于初始化时钟和SDRAM程序
1是初始化物理存储地址,其实是第一次调用函数的地址,我们第一次调用的函数是systeminit函数,这个位置必须是实际的物理地址,第二个按照正常的顺序来写,在手册中有顺序,千万不能写错。否则就找不到入口了,执行完向量表后,会执行RESET_HANDLER
首先调用SystemInit程序,里边有RCC初始化程序和SDRAM初始化程序,具体可参考Stm32F746的FSC例程
图中红线框内的就是sdram的初始化程序,具体代码就不贴了,有兴趣的可以找Stm32F746的FSC的历程,找不到的可以在下方留言,要是真有需要我会贴上来,然后声明函数
在编译器里定义宏变量
执行了这个函数之后,重新给定栈指针,让其指向SDRAM的内存空间
然后执行__main函数,__main函数中会初始化堆栈空间,然后跳转到真正的main函数中
基本上到这里,我们得程序就搭建完成了,然后让我们来测试一下,在main()函数中定义一个数组然后读取定义数组的地址,以及主函数入口的地址,我们就知道我们得程序到底执行在什么当中了。
由打印结果来看,我们得程序已经正确在SDRAM中执行了,可以一起愉快的玩耍了,哈哈。
到此,这一篇帖子的内容也算完成了,其实小狂在做这个的时候只用了半个小时不到,但是写帖子确实是废了不少时间,至少是做的4倍吧,小狂在这里谢谢各位看官的支持,下一篇帖子也会往更深层的走,撒花,撒花,哈哈。 |
|