当前位置:   article > 正文

keil从非0x08000000地址调试STM32单片机程序方法_stm32启动地址设置及从非0x800000 开始调试程序

stm32启动地址设置及从非0x800000 开始调试程序

  在使用stm32单片机的串口IAP升级功能时,需要调试bootloader程序和app程序,一般bootloader的程序都是从0x08000000地址开始运行的,使用keil软件可以直接进行仿真,但是如果调试app程序的话,由于它不是从0x08000000地址开始的,使用keil仿真的时候,仿真不了。为了可以直接使用keil仿真APP程序,在网上找了好多方法,不过好多方法都讲的比较凌乱,看起来也不方便。下面就将自己总结的2种方法分享出来。

  所用到的程序源码下载连接如下: https://download.csdn.net/download/qq_20222919/87872428

方法一:通过先下载bootloader的程序仿真APP程序。

bootloader程序

  先看一下bootloader的程序

#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "stmflash.h"
#include "iap.h"
int main ( void )
{
    u8 bit_new = 0;					//接收到程序标志
    u8 bit_10s = 0;
    u16 oldcount = 0;				//老的串口接收数据值
    u16 applenth = 0;				//接收到的app代码长度
    u8 t = 0, clearflag = 0;

    SystemInit();
    NVIC_PriorityGroupConfig ( NVIC_PriorityGroup_2 ); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
    uart_init ( 115200 );	//串口初始化为115200
    delay_init();	   	 	//延时初始化

	printf ( "bootloader is running!\r\n" );
    while ( 1 )
    {
        if ( USART_RX_CNT )
        {
            if ( oldcount == USART_RX_CNT ) //新周期内,没有收到任何数据,认为本次数据接收完成.
            {
                applenth = USART_RX_CNT;
                oldcount = 0;
                USART_RX_CNT = 0;
                printf ( "用户程序接收完成!\r\n" );
                printf ( "代码长度:%dBytes\r\n", applenth );
            }
            else oldcount = USART_RX_CNT;
        }

        if ( applenth != 0 )
        {
            if ( ( ( * ( vu32* ) ( 0X20001000 + 4 ) ) & 0xFF000000 ) == 0x08000000 ) //判断是否为0X08XXXXXX.
            {
                iap_write_appbin ( FLASH_APP1_ADDR, USART_RX_BUF, applenth ); //更新FLASH代码
                printf ( "固件更新完成!\r\n" );
                bit_new = 1;
            }
            applenth = 0;
        }

        if ( ( bit_10s == 30 ) || ( bit_new == 1 ) )
        {
            bit_10s = 0;
            bit_new = 0;
            //执行FLASH中的代码

            if ( ( ( * ( vu32* ) ( FLASH_APP1_ADDR + 4 ) ) & 0xFF000000 ) == 0x08000000 ) //判断是否为0X08XXXXXX.
            {
                printf ( "开始执行FLASH用户代码!!\r\n\r\n" );
                iap_load_app ( FLASH_APP1_ADDR ); //执行FLASH APP代码
            }

            //执行SRAM中的代码
//            if(((*(vu32 *)(0X20001000 + 4)) & 0xFF000000) == 0x20000000) //判断是否为0X20XXXXXX.
//            {
//                printf("开始执行SRAM用户代码!!\r\n");
//                iap_load_app(0X20001000);//SRAM地址
//            }
        }
        t++;
        delay_ms ( 10 );
        if ( t == 20 )
        {
            bit_10s++;
            if ( clearflag )
            {
                clearflag--;
                if ( clearflag == 0 )
                    printf ( "清除显示!\r\n" ); //清除显示
            }
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78

  在bootloader中一直等待串口发送升级文件,当串口接收完升级文件之后,才会跳转到flash中执行APP代码。bootloader代码地址设置如下:
在这里插入图片描述
在这里插入图片描述
  当使用keil调试bootloader代码时,是可以正常调试的。
在这里插入图片描述

APP程序

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"

int main ( void )
{
    SCB->VTOR = FLASH_BASE | 0x5000;
    SystemInit();
    uart_init ( 115200 );	//串口初始化为115200
    delay_init();
    LED_Init();
    delay_ms( 500 );
    printf ( "\r\n\r\napp is running!\r\n" );

    while ( 1 )
    {
        delay_ms ( 500 );
        LED = !LED;
        printf ( "led flashing !\r\n" );
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

  进入APP程序之后,首先设置地址的偏移量。然后在APP程序中让LED灯闪烁,然后打印信息。APP的地址设置如下:
在这里插入图片描述
在这里插入图片描述
  此时如果直接用keil单步调试APP程序,会发现程序不能进入到main函数中。
在这里插入图片描述

  程序虽然一直在运行,但是却不能跳转到main函数中来,这是因为程序上电后直接运行bootloader程序,而在bootloader程序中会一直等待串口数据,所以不会跳转到APP程序中来。如果想要程序跳转到APP中来,那么就需要用串口助手发送APP程序。
请添加图片描述

  当使用串口助手发送完升级文件之后,在bootloader程序中会直接跳转到APP程序所在的地址,这样才能单步调试APP程序。但是这样调试程序的太麻烦了,能不能不通过bootloader‘直接调试APP程序呢,当然是可以的。

方法二:通过配置文件直接仿真APP程序

  使用这种方法单片机中可以不烧写bootloader程序。首先看APP软件在keil中的配置,地址配置不变。
在这里插入图片描述
  在debug选项中,在初始化文件的位置处添加了一个配置文件。
在这里插入图片描述
  这个boot.bin文件和工程文件放在同一个目录下。
在这里插入图片描述
  新建一个记事本文件,将名称改为 boot.bin ,记得将记事本的后缀名改为ini,然后使用记事本打开boot.ini文件,再里面输入下面的内容。

FUNC void Setup (void) 
{ 
SP = _RDWORD(0x8005000);          // 堆栈指针 
PC = _RDWORD(0x8005004);          // PC 
_WDWORD(0xE000ED08, 0x8005000);   // 中断向量偏移地址 
} 
load %L incremental
Setup();
g, main                             //跳转到main  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

  注意代码中的这三个地址值,这个值和APP程序的起始地址有关,根据自己的程序去修改这三个值。
在这里插入图片描述
  其他设置保持不变
在这里插入图片描述
  下面就可以通过keil软件直接单步调试APP程序了。
在这里插入图片描述

  单机仿真按钮进入仿真界面之后,会发现此时程序直接就跳转到了main函数之中,不需要借助bootloader程序跳转了。这样通过一个配置文件,直接通过配置文件就可以让keil软件直接跳转到main函数中了。
在这里插入图片描述

  使用这种方法调试APP程序时,可以不用烧写bootloader程序。但是单片机独立运行时,还是需要烧写bootloader程序的。这个配置文件只对keil仿真器起作用,只有在使用keil仿真时才会起作用。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/blog/article/detail/56623
推荐阅读
相关标签
  

闽ICP备14008679号