• STM32的程序下载


    1、STM32下载方法

      单片机的烧录方式主要可以分为三种,分别为ICP(In Circuit Programing)在电路编程 、ISP(In System Programing)在系统编程 以及IAP(In applicating Programing)在应用编程

      1.1、ICP(In Circuit Programing)在电路编程

        ICP是指“在电路编程”,PC上运行的编程工具通过JATAG/SWD协议接口下载器更新晶片内部APROM、LDROM、数据闪存(DataFlash)和目标用户配置字(Config)芯片。

        支持JATAG/SWD协议接口的下载器有JLINK、ULINK、CMSIS-DAP、 STLINK等,这些下载器基本都带有仿真功能。与之配套的烧录软件为J-Flash、NuMicro_ICP_Programming_Tool、st-link utility等。程序编译器烧写一般都采用仿真器,既可以烧写也可以仿真。

    在这里插入图片描述

        (1)JTAG协议接口下载

        JTAG(Joint Test Action Group,联合测试工作组)是一种国际标准测试协议(IEEE 1149.1兼容),主要用于芯片内部测试。

        现在多数的高级器件都支持JTAG协议,如DSP、FPGA器件等。标准的JTAG接口是4线:TMS、TCK、TDI、TDO,分别为模式选择、时钟、数据输入和数据输出线。

        需要接线:VCC、GND、TRST---PB4、TDI---PA15、TMS/SWDIO---PA13、TCLK/SWCLK---PA14、TDO/SWO---PB3、RESET---NRST。

        (2)SWD协议接口下载

        用标准的 JTAG 调试,需要占用 5 个 IO 口,有些时候,可能造成 IO 口不够用,而用 SWD则只需要 2 个 IO 口,大大节约了 IO 数量,但他们达到的效果是一样的,所以我们强烈建议仿真器使用 SWD 模式!

        SWD 只需要 2 根线(SWCLK 和 SWDIO)就可以下载并调试代码了,这同我们使用串口下载代码差不多,而且速度非常快,能调试。所以建议大家在设计产品的时候,可以留出 SWD 来下载调试代码,而摒弃 JTAG。 STM32 的 SWD 接口与 JTAG 是共用的,只要接上 JTAG,你就可以使用 SWD 模式了(其实并不需要 JTAG 这么多线),当然,你的调试器必须支持 SWD 模式, JLINK V7/V8、ULINK2 和 ST LINK 等都支持 SWD 调试。

        特别提醒, JTAG 有几个信号线用来接其他外设了,但是 SWD 是完全没有接任何其他外设的,所以在使用的时候, 推荐大家一律使用 SWD 模式!!!

        需要接线:VCC、GND、TMS/SWDIO---PA13、TCK/SWCLK---PA14

        (3)JTAG/SWD对比

          1)SWD模式比JTAG在高速模式下面更加可靠,在大数据量的情况下JTAG下载程序会失败,但是SWD发生的几率会小很多,基本使用JTAG的模式下可以直接使用SWD模式的,前提是仿真器支持

          2)在GPIO口刚好缺一个的时候,可使用SWD仿真,这种模式支持更少的引脚,使用SW模式PA15,PB3,PB4,都自由了就可以做普通IO口了,只用了stm32的PA13和PA14两个口

          3)在PCB设计体积有限的时候推荐使用SWD模式

      1.2、ISP(In System Programing)在系统编程

      (1)、 ISP 简介

        ISP,即In-System Programming,在系统编程。目标芯片使用USB/UART/SPI/I²C/RS-485/CAN周边接口的LDROM引导代码去更新晶片内部APROM、数据闪存(DataFlash)和用户配置字(Config)。

        ISP(In-System Programming)在系统编程,指电路板上的空白器件可以编程写入最终用户代码,而不需要从电路板上取下器件,已经编程的器件也可以用ISP方式擦除或再编程。ISP技术是未来发展方向。

        ISP 的实现相对要简单一些,一般通用做法是内部的存储器可以由上位机的软件通过串口来进行改写。对于单片机来讲可以通过SPI或其它的串行接口接收上位机传来的数据并写入存储器中。

        ISP是使用STM32系统存储器中所带的引导程序通过USB/UART等接口进行烧录的,ISP 下载程序的时候需要用到(bootloader)自举程序,自举程序存储在 STM32 器件的内部自举ROM 存储器(系统存储器)中。

        其主要任务是通过一种可用的串行外设( USART、 CAN、USB、 I2C 等)将应用程序下载到内部 Flash 中。每种串行接口都定义了相应的通信协议,其中包含兼容的命令集和序列。

        与仿真器相比, ISP 只能下载程序,不能在线调试且下载速度慢。 而利用调试工具比如JLINK、ULINK、STLINK 等就可以实时跟踪程序, 从而找到程序中的bug。

      (2)、 ISP 普通下载流程

        现在我们针对 USART1 的 ISP 进行分析,通常的 ISP 的步骤如下:

        1)、电脑通过 USB 线连接 STM32 的USART、 CAN、USB、 I2C 等,并打开电脑端的上位机;

        2)、设置跳线保持 BOOT0 为高电平, BOOT1 为低电平(系统存储器);

        3)、复位单片机使其进入 bootloader 模式,通过上位机下载程序;

        4)、下载完毕,设置跳线保持 BOOT0 为低电平, BOOT1 为低电平(内部FLASH);

        5)、复位单片机即可启动用户代码,正常运行。

      以上步骤有个不好的地方就是下载程序需要跳线及复位操作,很繁琐。通过对 ISP 的原理认识,一键 ISP 就诞生了,它需要做的事情就是用上位机去控制 BOOT0 脚和单片机的复位脚,原理图如下:

      (3)、开始下载

      打开 mcuisp 软件,配置如下:

        1)、搜索串口,设置波特率 115200(尽量不要设置的太高)

        2)、选择要下载的 HEX 文件

        3)、校验、编程后执行

        4)、DTR 低电平复位, RTS 高电平进入 bootloader

        5)、开始编程。如果出现一直连接的情况,按一下开发板的复位键

       

      (4) ISP 一键下载

      USB 转串口估计大家都很熟悉,一般都是用到 RXD 和 TXD 这两个口,一键 ISP 电路中我们需要用 USB 转串口的芯片的 DTR 口和 RTS 口来控制单片机的 BOOT0 和 NRST,原理如下:

      1)、通过上位机控制 U6(CH340G)的 RTS 脚为低电平, Q1 导通, BOOT0 的电平上拉为高电平。

      2)、通过上位机控制 U6(CH340G)的 DTR 脚为高电平,由于 RTS 为低电平, Q2 导通,U8 的 2 脚为低电平, U18 为一个模拟开关,使能端由 4 脚控制,默认高电平, U18的 1 脚和 2 脚导通,所以 NRST 为低电平系统复位。

      3)、单片机进入 ISP 模式,此时可以将 DTR 脚设置为低电平, RTS 设置为高电平。 Q1和 Q2 为截至状态, BOOT0 和 NRST 还原默认电平。

      4)、上位机将程序下载到单片机,下载完毕之后,程序自动运行。

      5)、至此,很多人还会认为 U18、 Q1、 Q2 是多余的,用 U6 的 RTS 和 DTR 直接控制也可以。正常情况下,这样理解没有问题,但是我们忽略了一点,就是单片机上电瞬间如果 USB 转串口连接了电脑, DTR 和 RTS 的电平是变化的,如果不处理好,单片机会一直进入 ISP 模式,或者系统会复位多次,这种情况是不允许的。

      6)、于是,就有了我们全新的一键 ISP 电路。我们主要是分析上电瞬间的逻辑关系,单片机上电时我们通过示波器观察波形得知 DTR 和 RTS 的电平是变化的,但是也有一个规律就是:只要 RTS 为低电平的时候, DTR 的电平也是低,因此一般情况 Q2不会导通,但由于这两个 IO 口的电平存在“竞争冒险”,会出现 RTS 的下降沿的时候刚好遇到 DTR 的上升沿,这个时候 Q2 导通,导致系统复位,而 BOOT0 此时有可能也为高电平,就会进入 ISP 模式。这个是不受我们控制的,我们不想系统出现这样的情况。因此加入了模拟开关来切断这种干扰。

      7)、加入模拟开关 U18,通过控制 U18 的 4 脚的开关来达到隔离干扰电平的目的。下面我们分析一下延时开关电路,上电瞬间,电容 C65 通过电阻 R18 来充电,由于电阻 100k 很大,电容的充电电流很小,等电容充电达到 U18 的 4 脚的有效电平 2V时,大概耗时 1S,在这个 1S 时间内 U18 的模拟开关是断开的,因此 RTS 和 DTR的干扰电平不会影响到系统复位。系统正常运行。

      1.3、IAP(In applicating Programing)在应用编程

      IAP(In Application Programming)即在应用编程,就是通过软件实现在线电擦除和编程的方法。 IAP 是用户自己的程序在运行过程中对User Flash 的部分区域进行烧写,目的是为了在产品发布后可以方便地通过预留的通信口对产品中的固件程序进行更新升级。

      通常实现 IAP 功能时,即用户程序运行中作自身的更新操作,需要在设计固件程序时编写两个项目代码,第一个项目程序不执行正常的功能操作,而只是通过某种通信方式(如 USB、 USART)接收程序或数据,执行对第二部分代码的更新;第二个项目代码才是真正的功能代码。这两部分项目代码都同时烧录在 User Flash 中,当芯片上电后,首先是第一个项目代码开始运行,它作如下操作:

        1)检查是否需要对第二部分代码进行更新
        2)如果不需要更新则转到 4)
        3)执行更新操作
        4)跳转到第二部分代码执行

      第一部分代码必须通过其它手段,如 JTAG 或 ISP 烧入;第二部分代码可以使用第一部分代码 IAP 功能烧入,也可以和第一部分代码一起烧入,以后需要程序更新时再通过第一部分 IAP代码更新。

      我们将第一个项目代码称之为 Bootloader 程序,第二个项目代码称之为 APP 程序,他们存放在 STM32 FLASH 的不同地址范围,一般从最低地址区开始存放 Bootloader,紧跟其后的就是 APP 程序(注意,如果 FLASH 容量足够,是可以设计很多 APP 程序的,本章我们只讨论一个 APP 程序的情况)。这样我们就是要实现 2 个程序: Bootloader 和 APP。

      IAP技术是从结构上将Flash存储器映射为两个存储体,当运行一个存储体上的用户程序时,可对另一个存储体重新编程,之后将程序从一个存储体转向另一个。

      IAP就是通过软件实现在线电擦除和编程的方法,没有使用任何工具,仅仅是通过软件的方法来更新Flash中的数据。

      讲述一个案例,那就是通过4G模块来远程更新程序。将Flash分成两块区域,第一块为Boodload程序,第二块区域存放的是应用程序APP。4G模块和目标板通讯,通讯中包含是否更新的位,如果主板接收到需要更新的位,就往Flash中写入一个标志位,比如'P',之后程序跳到第一段程序Boodload程序中执行,首先判断Flash中的是否有更新程序的标志位'P',如果有则通过规定的协议进行更新应用程序中的程序,更新完毕后清除Flash中的更新标志位,跳转到应用程序中去执行。如果没有更新程序标志位‘P’,跳到应用程序执行。

      我们先来看看 STM32 正常的程序运行流程,如下图所示:

      STM32 的内部闪存(FLASH)地址起始于 0x08000000,一般情况下,程序文件就从此地址开始写入。此外 STM32 是基于 Cortex-M3 内核的微控制器,其内部通过一张“中断向量表”来响应中断,程序启动后,将首先从“中断向量表”取出复位中断向量执行复位中断程序完成启动,而这张“中断向量表”的起始地址是 0x08000004,当中断来临, STM32 的内部硬件机制亦会自动将 PC 指针定位到“中断向量表”处,并根据中断源取出对应的中断向量执行中断服务程序。

      在上图 中, STM32 在复位后,先从 0X08000004 地址取出复位中断向量的地址,并跳转到复位中断服务程序,如图标号①所示;在复位中断服务程序执行完之后,会跳转到我们的main 函数,如图标号②所示;而我们的 main 函数一般都是一个死循环,在 main 函数执行过程中,如果收到中断请求(发生重中断),此时 STM32 强制将 PC 指针指回中断向量表处,如图标号③所示;然后,根据中断源进入相应的中断服务程序,如图标号④所示;在执行完中断服务程序以后,程序再次返回 main 函数执行,如图标号⑤所示。当加入 IAP 程序之后,程序运行流程如下图所示:

      在上图所示流程中, STM32 复位后, 还是从 0X08000004 地址取出复位中断向量的地址,并跳转到复位中断服务程序,在运行完复位中断服务程序之后跳转到 IAP 的 main 函数,如图标号①所示,此部分同图 52.1.1 一样;在执行完 IAP 以后(即将新的 APP 代码写入 STM32的 FLASH,灰底部分。新程序的复位中断向量起始地址为 0X08000004+N+M),跳转至新写入程序的复位向量表,取出新程序的复位中断向量的地址,并跳转执行新程序的复位中断服务程序,随后跳转至新程序的 main 函数,如图标号②和③所示,同样 main 函数为一个死循环,并且注意到此时 STM32 的 FLASH,在不同位置上,共有两个中断向量表。

      在 main 函数执行过程中,如果 CPU 得到一个中断请求, PC 指针仍强制跳转到地址0X08000004 中断向量表处,而不是新程序的中断向量表,如图标号④所示;程序再根据我们设置的中断向量表偏移量,跳转到对应中断源新的中断服务程序中,如图标号⑤所示;在执行完中断服务程序后,程序返回 main 函数继续运行,如图标号⑥所示。

      通过以上两个过程的分析,我们知道 IAP 程序必须满足两个要求:

        1) 新程序必须在 IAP 程序之后的某个偏移量为 x 的地址开始;
        2) 必须将新程序的中断向量表相应的移动,移动的偏移量为 x;

      1.3.1、APP 程序起始地址设置方法

      默认的条件下,图中 IROM1 的起始地址(Start)一般为 0X08000000,大小(Size)为 0X80000,即从 0X08000000 开始的 512K FLASH的地址空间为我们的程序存储(因为我们的 STM32F103ZET6 的 FLASH大小是 512K)。而图中,我们设置起始地址(Start)为 0X08010000,即偏移量为 0X10000(64K 字节),因而,留给 APP 用的 FLASH 空间(Size)只有 0X80000-0X10000=0X70000(448K 字节)大小了。设置好 Start 和 Szie,就完成 APP 程序的起始地址设置。

      这里的 64K 字节,需要大家根据 Bootloader 程序大小进行选择,比如我们的 Bootloader程序为 22K 左右,理论上我们只需要确保 APP 起始地址在 Bootloader 之后,并且偏移量为 0X200的倍数即可(相关知识,请参考: http://www.openedv.com/posts/list/392.htm)。这里我们选择 64K(0X10000)字节,留了一些余量,方便 Bootloader 以后的升级修改。

      这是针对 FLASH APP 的起始地址设置,如果是 SRAM APP,那么起始地址设置如图 52.1.4所示:

     

      这里我们将 IROM1 的起始地址(Start)定义为: 0X20001000,大小为 0XC000(48K 字节),即从地址 0X20000000 偏移 0X1000 开始,存放 APP 代码。因为整个 STM32F103ZET6 的 SRAM大 小 为 64K 字 节 , 所 以 IRAM1 ( SRAM ) 的 起 始 地 址 变 为 0X2000D000( 0x20001000+0xC000=0X2000D000 ) , 大 小 只 有 0X3000 ( 12K 字 节 )。 这 样 , 整 个STM32F103ZET6 的 SRAM 分配情况为:最开始的 4K 给 Bootloader 程序使用,随后的 48K 存放 APP 程序,最后 12K,用作 APP 程序的内存。这个分配关系大家可以根据自己的实际情况修改,不一定和我们这里的设置一模一样,不过也需要注意,保证偏移量为 0X200 的倍数(我们这里为 0X1000)。

      1.3.2、中断向量表的偏移量设置方法

      之前我们讲解过,在系统启动的时候,会首先调用 systemInit 函数初始化时钟系统,同时systemInit 还完成了中断向量表的设置,我们可以打开 systemInit 函数,看看函数体的结尾处有这样几行代码:

    #ifdef VECT_TAB_SRAM
        SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET;  /* Vector Table Relocation in Internal SRAM. */
    #else
        SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET;  /* Vector Table Relocation in Internal FLASH. */
    #endif

      从 代 码 可 以 理 解 , VTOR 寄 存 器 存 放 的 是 中 断 向 量 表 的 起 始 地 址 。 默 认 的 情 况VECT_TAB_SRAM 是没有定义,所以执行 SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET;

      对于 FLASH APP,我们设置为 FLASH_BASE+偏移量 0x10000,所以我们可以在 FLASH APP 的main 函数最开头处添加如下代码实现中断向量表的起始地址的重设:

    SCB->VTOR = FLASH_BASE | 0x10000;

      以上是 FLASH APP 的情况,当使用 SRAM APP 的时候, 我们设置起始地址为:SRAM_bASE+0x1000,同样的方法,我们在 SRAM APP 的 main 函数最开始处,添加下面代码:

    SCB->VTOR = SRAM_BASE | 0x1000;

      这样,我们就完成了中断向量表偏移量的设置。

      通过以上两个步骤的设置,我们就可以生成 APP 程序了,只要 APP 程序的 FLASH 和 SRAM大小不超过我们的设置即可。不过 MDK 默认生成的文件是.hex 文件,并不方便我们用作 IAP更新,我们希望生成的文件是.bin 文件,这样可以方便进行 IAP 升级(至于为什么,请大家自行百度 HEX 和 BIN 文件的区别!)。这里我们通过 MDK 自带的格式转换工具 fromelf.exe,来实现.axf 文件到.bin 文件的转换。该工具在 MDK 的安装目录ARMBIN40 文件夹里面。

      fromelf.exe 转换工具的语法格式为: fromelf [options] input_file。其中 options 有很多选项可以设置,详细使用请参考光盘《mdk 如何生成 bin 文件.doc》 .

      本章,我们通过在 MDK 点击 Options for Target→User 选项卡,在 After Build/Rebuild 栏,勾选 Run #1,并写入: D: oolsmdk5.14ARMARMCCinfromelf.exe --bin -o ..OBJRTC.bin..OBJRTC.axf。如图 52.1.6 所示:

     

      通过这一步设置,我们就可以在 MDK 编译成功之后,调用 fromelf.exe(注意,我的 MDK 是安装在 D: oolsmdk5.14 文件夹下, 如果你是安装在其他目录,请根据你自己的目录修改fromelf.exe 的路径),根据当前工程的 RTC.axf(如果是其他的名字,请记住修改,这个文件存放在 OBJ 目录下面,格式为 xxx.axf),生成一个 RTC.bin 的文件。并存放在 axf 文件相同的目录下,即工程的 OBJ 文件夹里面。在得到.bin 文件之后,我们只需要将这个 bin 文件传送给单片机,即可执行 IAP 升级。

      最后再来看 APP 程序的生成步骤:

        1) 设置 APP 程序的起始地址和存储空间大小

          对于在 FLASH 里面运行的 APP 程序, 我们可以按照图 52.1.3 的设置。对于 SRAM 里面运行的 APP 程序,我们可以参考图 52.1.4 的设置。
        2) 设置中断向量表偏移量

          这一步按照上面讲解,重新设置 SCB->VTOR 的值即可。

        3) 设置编译后运行 fromelf.exe,生成.bin 文件.

          通过在 User 选项卡,设置编译后调用 fromelf.exe,根据.axf 文件生成.bin 文件,用于IAP 更新。

      以上 3 个步骤,我们就可以得到一个.bin 的 APP 程序,通过 Bootlader 程序即可实现更新。

      1.4、总结

        ICP:使用JTAG/SWD接口进行烧录,如J-Link烧录器和J-Flash软件配合使用。

        ISP:使用引导程序(Bootload)加上外围UART/USB等接口进行烧录。

        IAP:软件自身实现在线电擦除和编程的方法,不使用任何工具。程序通常分成两块,分别为引导程序和应用程序。

  • 相关阅读:
    Dockerfile深度剖析
    centos 7安装jdk8
    Centos 7 修改YUM镜像源地址为阿里云镜像地址
    Fabric智能合约(余额转移样本)
    Fabric智能合约(base)
    Fabric背书策略文件编写说明
    多catch块折叠
    Frp内网穿透服务部署
    Linux常用命令合集(初级)--Centos版
    English trip EM3-LP-5A Shopping Teacher: GABRIELE
  • 原文地址:https://www.cnblogs.com/The-explosion/p/13724872.html
Copyright © 2020-2023  润新知