• GD32(7)程序烧录及运行


    简介

           微控制器在硬件中作为核心,通过执行保存在内部存储器中的程序,运行各种外设,并通过引脚,控制其它电路,而将程序保存在微控制器内部存储器的过程,被称为烧录

           烧录的方式可分为以下三种:

    • ICP(In-Circuit Programmer,在电路编程)
    • ISP(In-System Programming,在系统编程)
    • IAP(In-Application Programming,在应用编程)

           在介绍不同烧录方式的区别前,先介绍一下微控制器的启动方式。

    启动方式

           微控制器的启动方式有引脚Boot0和Boot1的电平决定,一般通过拨码开关或引脚+跳线帽的方式控制,根据组合有以下三种启动方式,其中‘x‘表示高电平或低电平(即高低电平皆可)。
    在这里插入图片描述

    Boot0=0,Boot1=x

           当Boot0=0, Boot1=x时,上电复位后微控制器从内部Flash的主存储区开始运行程序,该地址一般是0x0800 0000。

           设置该启动模式前,程序应该被保存在内部Flash主存储区的最前面。

    Boot0=1,Boot1=0

           当Boot0=1, Boot1=0时,上电复位后微控制器自动运行引导装载程序,即内部Flash信息块中的Bootloader区,通过运行该程序将代码引导装载至内部Flash中,完成程序烧录。

    Bootloader区的地址可能随着微控制器的不同而改变,主要是由于内部Flash的主存储区大小变化。

    Boot0=1,Boot1=1

           当Boot0=1, Boot1=1时,上电复位后微控制器从内部SRAM开始运行程序,该地址一般是0x2000 0000。

           同理,设置该启动模式前,程序应该被保存在内部SRAM的最前面,并且由于SRAM掉电后不会保留数据,因此不能进行复位等操作,一般该启动模式用于调试程序。

    烧录方式

    ICP

           ICP(In-Circuit Programmer)指在电路中编程,需要ST-Link、J-Link等烧录器进行烧录(此时使用JTAG、SWD等接口),使用该烧录方式时,通过烧录器连接计算机和微控制器后通过keil5进行程序烧录(听说除了keil5还有其它软件,但都需要烧录器),此时烧录文件为编译后产生的bin文件。

           通过ICP进行烧录时,启动方式设置为第1种,即Boot0=0,Boot1=x,以在烧录完成并复位后直接从内部Flash开始运行。

    虽然这时候在硬件设置启动方式为Boot0=0,Boot1=x,但烧录器会在下载时调整为Boot0=1,Boot1=0以进行程序烧录,但这不影响后续复位后的程序运行。

    ISP

            ISP(In-System Programming)指在系统编程,不需要烧录器,但同样需要将计算机和微控制器连接,用于作为程序的数据进行传输,可以使用USB、USB转串口模块(常用)等方式进行烧录,在烧录时计算机需要打开ISP烧录软件,并选择对应的模式,一般不同微控制器使用的ISP软件不同,下图分别是ST和GD使用的ISP软件。

           红框中为烧录时选择模式,DTR(Data Terminal Ready)表示数据终端准备好,RTS(Request To Send)表示请求发送 。可以看到都是通过串口进行烧录的(当然还有其它的ISP软件)。

           通过ISP烧录时,启动方式设置为第2种,即Boot0=1,Boot1=0,运行引导装载程序以将传输的数据作为程序存储在内部Flash最前面,烧录完成后需要修改启动方式为第1种。

           通过ISP方式烧录到程序文件通常是hex文件。

    当然,使用此种模式一般将Boot0接到按键上,然后不按下接高电平,按下后接低电平,此时通过ISP烧录前按住按键即可。

    在这里插入图片描述

    IAP

            IAP(In-Application Programming)指在应用编程,不需要通过烧录器、USB等设备与计算机连接,但需要从SD卡等存储设备获取新程序(bin文件)进行自我更新(当然,通过USB、UART等接口获取的程序也可行)。

           IAP烧录方式的烧录逻辑是:在内部Flash的最前面烧录第1个程序(称为Bootloader程序),其次在相对0800 0000具有偏移的位置存储第2个程序(称为APP程序)。在Bootloader程序中,完成APP程序的更新,以及跳转至APP程序执行。

    APP程序则和上述两种烧录方式烧录的程序相同,为正式运行的程序。

    IAP的作用

           IAP一般可以用于产品的程序更新,避免更新时需要对其进行收回、拆解等步骤,并且方便用于自行操作。

    IAP与ICP、ISP的运行差别

           ICP和ISP都是将1个程序存储到内部Flash中并运行,程序在内部Flash中的存储空间分布如下图所示,最前面是栈顶地址,其次是各个中断向量,然后是各个中断向量对应的中断程序入口,最后是main函数入口。

           程序运行时,栈指针指向复位中断向量,其次通过该向量跳转至复位中断程序中运行,复位中断程序一般在startupxx.s文件中定义,用于初始化系统并跳转至main函数运行,最后进入main函数执行循环。当中断请求出现时,栈指针指向对应中断向量,并通过该向量跳转至对应的中断程序中运行,运行结束后再回到原位置,继续运行循环中的内容。

    在这里插入图片描述

           IAP是从Bootloader程序中跳转至APP程序中运行,因此在内部Flash中的空间分布略有不同,如下图所示,在执行Bootloader程序的main函数时,进行APP函数的跳转过程,最后执行APP程序中的main函数。当中断请求出现时,栈指针指向Bootloader程序中断向量表中对应中断向量,并通过该向量及程序偏移值跳转至对应的中断程序中运行,运行结束后再回到原位置,继续运行循环中的内容。

    在这里插入图片描述

    IAP的Bootloader程序实现

           Bootloader程序主要完成APP程序的更新以及跳转,其中APP程序的更新即从接口或存储设备中获取后存放在内部Flash对应区域中接口(相对首地址有偏移量)。

           APP程序的跳转可参考以下代码,其中& 0x2FFE0000并与0x20000000判断是否相等,表示该地址在0x20000000 ~ 0x2001 0000之间(理论上可修改,在内部SRAM中即可)。

    void GotoApp(u32 appAddr)
    {
      //App复位中断服务函数
      void (*appResetHandler)(void); 
    
      //延时变量
      u32 delay;
    
      //检查栈顶地址是否合法.
      if(0x20000000 == ((*(u32*)appAddr) & 0x2FFE0000)) 
      {
        //获取App复位中断服务函数地址,用户代码区第2个字为程序开始地址(复位地址)
        appResetHandler = (void (*)(void))(*(u32*)(appAddr + 4));
    
        //设置App主栈指针,用户代码区的第一个字用于存放栈顶地址
        SetMSP(*(u32*)(appAddr));
    
        //跳转到App
      	__set_FAULTMASK(1);//关闭所有中断
    	NVIC_SystemReset();//系统复位
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

           其中SetMSP为汇编程序编写的函数,如下所示,其中r0为addr的地址,具体可参考ARM架构基本寄存器一文及该专栏。

    __asm static void SetMSP(u32 addr)
    {
      MSR MSP, r0
      BX r14
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    IAP的APP程序实现

           APP程序为用户程序,实际上任意程序都可以,但需要进行相应的配置,配置步骤如下:

    1. 设置起始地址和存储空间
             在keil中设置起始地址和存储空间的大小,如下图所示,在Options for Target 'Target1’对话框中,打开Target标签页,勾选IROM1选项,并将起始地址设置为0x8010000,大小为0x70000(即448KB,可修改,用于存放APP程序),此时APP程序代码存放地址即为Flash起始地址加上相对偏移量X(这里将偏移量X设置为10000),即0x08010000。

    在这里插入图片描述
    2. 设置中断向量表偏移量

           在APP程序的main函数执行硬件初始化前,加入以下代码,设置相对偏移量X为0x10000。

    nvic_vector_table_set(FLASH_BASE,0x10000);
    
    • 1
    1. 设置bin文件生成
             通过上面两个步骤即可生成APP程序,但keil默认生成hex文件,因此需要设置生成bin文件:如下图所示,在Options for Target 'Target1’对话框中,打开Target标签页User标签页,勾选Run#1选项,并在对应的User command栏中添加格式转换工具fromelf.exe路径、bin文件存放路径和用户程序路径,3个路径之间通过空格隔开。

    fromelf.exe路径在leil安装路径中找,bin文件存放路径任意,用户程序路径指APP程序的axf文件路径。
    注意:路径可以是相对路径或绝对路径,并且需要空格隔开。

    在这里插入图片描述

           设置结束后点击编译,即可在上面填写的bin文件路径中找到对应的bin文件。

  • 相关阅读:
    react 修改less文件后保存,内存溢出,项目崩溃问题解决
    17、简单记录一下两个流媒体工具和推流测试
    【DIY飞控板PX4移植】BARO模块BMP388气压计的PCB硬件设计和PX4驱动配置
    postman使用pre-request script
    网工内推 | 信息安全主管,CISP认证优先,最高25K,加绩效提成
    用c语言将文件中十六进制数据与二进制数据相互转换
    大四如何稳稳当当的毕业--计算机毕设如何做?
    第三章:最新版零基础学习 PYTHON 教程(第五节 - Python 运算符—Python 逻辑运算符及示例)
    调用链监控工具之CAT上
    DocumentType类型
  • 原文地址:https://blog.csdn.net/weixin_47447179/article/details/126601723