zoukankan      html  css  js  c++  java
  • Rt1052从外部启动 keil测试

    当 RT105x 板载的 Boot 模式跳线帽短接到NC, 系统会通过片上的 FlexSPI 接口执行外部串行SPI Nor Flash 的启动, 其启动地址为 Table1-2 所示的 0x6000_0000(如果是从并行的 NorFlash 启动则启动地址为 0x8000_0000) , 关于其他 Boot pin 对启动模式的配置影响,见
    RT105x 的 RM 手册 8.6 章节,这里就不细说了。 

     

    如图 1 所示为完整的 SPI Nor Flash 启动流程图, 当 RT105x 的片上 ROM 在检测到启动模式为 FlexSPI 接口后, 会根据 Boot Pin 的配置信息配置该模式下需要使用的 FlexSPI 接口管脚的复用模式并将 FlexSPI 的时钟配置成默认的低速 30MHz, 然后会以 0x6000_0000 为首地址读取前 512 个字节作为外部 Flash 的配置信息( 即 Flash Configuration Parameters, 包括几线制的 SPI Flash, SPI 的时钟频率, LUT 查找表, DDR/SDR 模式以及片选 CS 管脚的 Hold/Setup Time 等信息,见 RM8.6.3 章节) 并以此来配置 FlexSPI 模块以满足外部 Flash 的特性, 待配置
    完毕后, RT105x CPU 以后即会以 AHB 总线读取数据和指令的方式(虽然从外部来看仍然是FlexSPI 接口, 但是由于 LUT 查找表读取数据的指令已经配置好, CPU 只是通过 AHB 总线发送读取指令即可触发 LUT 以操作外部 Flash, 也就是说在内部对 CPU 来讲已经屏蔽掉了 FlexSPI 的
    底层) 来读取接下来的跟用户 Image 相关的几个关键信息, 即 IVT(Image Vector Table),Boot Data 和 DCD( Device configuration data)如图 2, 其中 IVT 需要放在外部 Flash 的固定偏移地址( 如图 3,对 Nor Flash 来说其需要存储在基地址 + 4KB 的偏移地址, 比如0x60000000+4*1024) 供 ROM 读取以便让系统知道用户 Image 的第一条可执行指令放在了哪里以

    l 及 BootData 和 DCD 的存放地址, BootData 则保存了完整 Image 的首地址和整个 image 所占的 空间大小, 而 DCD 则包含了一些配置命令以便在跳到用户程序入口之前供 ROM 调用配置内部外设以更好的匹配外部 IC,一般如果系统外挂了 SDRAM 的情况则需要配置好 DCD( 因为有时需要
    主程序在跑起来之前,外部 SDRAM 就得处在 ready 状态, 以供 CPU 把 data 或者 code copy 到SDRAM 里时不会出错)。 

     综上所述,我们实际上就可以得出结论来,如果要让系统能正常 Boot 起来,则烧写到外部串行 SPI Flash 里面的完整 image 必须要包括五个重要元素,即 Flash ConfigurationParameters, IVT, Boot Data, DCD 和用户 image, 而其中 Flash Configuration Parameters和 IVT 是存放在固定的地址的,而后三者则由 IVT 的内容来决定, 无论是直接编译生成或者通过辅助工具手动添加,只要我们最后形成的 image 里面包含了这几个元素, CPU 就会认可这个
    image 并执行(先不谈安全加密的事) 。 所以我们只要搞清楚这个基本原理了, 无论是什么方法, 最后都是殊途同归, 下面就可以放心大胆地去解决 RT105x 的 FlesSPI 启动问题了 

     工程配置里,右键工程 Options->C/C++,添加 QSPI_BOOT 和
    XIP_EXTERNAL_FLASH 这两个宏如下图 1 

     

     添加两个文件,fsl_flexspi_nor_boot.cfsl_flexspi_nor_flash.c.scf 链接文件 使用KEIL安装目录下的xip工程的scf文件即:MIMXRT1052xxxxx_flexspi_nor_sdram。而且 keil 下也已经添加了 Keep 变量以防止 xip 这几个元素信息因为程序里没有调用而自动被编译器优化掉(注意:下图显示窗口有限,实际上要 keep 的信息段.boot_hdr.ivt, .boot_hdr.boot_data, .boot_hdr.dcd_data和.boot_hdr.conf,格式参考下图)

    至此我们编译整个工程,最后打开生成的.map 文件如下图可以看到我们想要的几个 QSPI启动必须的元素信息头都已经正确的分配到 image 文件里了;   

     

    看下startup_MIMXRT1052.S文件其中有复位启动流程:

    Reset_Handler   PROC

                    EXPORT  Reset_Handler             [WEAK]

                    IMPORT  SystemInit  

     ...

       LDR     R2, [R1]

                    MSR     MSP, R2

                    LDR     R0, =SystemInit

                    BLX     R0

                    CPSIE   i               ; Unmask interrupts

                    LDR     R0, =__main

                    BX      R0

                    ENDP

    打开system_MIMXRT1052.c系统配置文件,也就是SystemInit函数所在的文件里面添加如下图所示SDRAM初始化相关的函数并在SystemInit的最后调用就可以在使用SDRAM之前将其初始化(具体修改后的源文件见随文档附带的压缩包),而且初始化函数均是以C语言形式读写配置SDRAM相关寄存器,这样的话即使SDRAM更换了也可以随时修改初始化寄存器配置以适配不同的SDRAM了,俗话说未知是最可怕的,而一旦都是开放的话就

    没那么难了。至于SDRAM这块的初始化是怎么找到的呢,实际上就是将SDRAM的预处理文件(当前目录下的evkmimxrt1050_sdram_init.mac)里面的命令用C语言实现了而已。

    void SystemInit (void) {

    #if 1 //SEMCW9825_SDRAM

        SDRAM_Init();

    #endif

    }

    上面使用了预编译命令判断HYBERFLASH_SDRAM宏来决定是否初始化SDRAM,所以在当前工程配置下需要添加HYBERFLASH_SDRAM宏声明以使在当前工程配置下SDRAM初始化生效

    接下来要解决keil下download、Erase和debug需要的QSPI Flash烧写算法问题,本文档附带的压缩包文件里路径FirmwareKeil_Algorithm下MIMXRT_QSPIFLASH.FLM文件为我已经优化修改好的可以支持ISSI,GD和Winbond烧写的Flash算法,将其copy到keil安装路径下C:Keil_v5ARMFlash即可,然后右键工程options->Debug-> CMSIS-DAP debugger,进入settings->Flash Download,点击Add找到如下图所示的MIMXRT_QSPIFLASH(4KB Sec),另外建议给Flash算法预留的RAM空间大一些否则可能会导致算法运行失败,因为这个flash算法比较占空间,我这里修改成了0x4000大小是没有问题的;

    设置完毕之后,我们再次重新编译整个工程,然后点击F8或者keil菜单栏Flash->Download即可完成对外部QSPI的擦除和写入,待烧写完毕之后我们点击debug即可正常调试(建议:如果程序做了修改,在编译之后进入debug之前先Download一次,再点debug),重新断电之后程序也可以。

    注意:蓝色字是重点!!

    注意1:在APP初始化里面不需要对semc再次初始化,因为在sysInit里面已经初始化完成了,不然会造成死机。

    / CLOCK_SetMux(kCLOCK_SemcMux,0); //PERIPH_CLK作为SEMC时钟源,PERIPH_CLK=600M

        //CLOCK_SetDiv(kCLOCK_SemcDiv,3); //设置SEMC时钟由PERIPH_CLK四分频得到,即SEMC Clock=600/4=150Mhz

    注意2:在Ini文件里面,不需要再次对semi外部SDRAM初始化。

    原来增加的代码可以删除。支持 QSPI 启动的完整 image 文件通过以上几步我们已经解决了 !

    文章参考了网友的文章,若有侵权请联系我删除,谢谢。

  • 相关阅读:
    git track
    npm 升级到最新版本
    三行代码实现垂直居中和cube
    布局之定位
    MongoDB的安装问题
    正则表达式
    javascript表单验证
    Oracle中创建表,行级触发器,序列
    查找某个字符在字符串中出现的次数
    oracle表中有一列id她是自动增长的,插入一条数据时怎么取得id的值
  • 原文地址:https://www.cnblogs.com/zhihui-3669/p/12973535.html
Copyright © 2011-2022 走看看