Keil は 0x08000000 以外のアドレスから STM32 MCU プログラム メソッドをデバッグします

  stm32 シングルチップマイコンのシリアルポート IAP アップグレード機能を使用する場合、ブートローダプログラムとアプリプログラムのデバッグが必要です 通常、ブートローダプログラムはアドレス 0x08000000 から実行されます。シミュレーションは可能ですが、アプリプログラムがデバッグされている場合、アドレス 0x08000000 から開始されていないため、keil シミュレーションを使用するとシミュレーションできません。keilシミュレーションAPPプログラムを直接使用するために、インターネット上で多くの方法を見つけましたが、多くの方法は面倒で不便です。以下にまとめた 2 つの方法を共有します。

  使用したプログラム ソース コードのダウンロード リンクは次のとおりです: https://download.csdn.net/download/qq_20222919/87872428

方法 1: 最初にブートローダー プログラムをダウンロードして、APP プログラムをシミュレートします。

ブートローダープログラム

  まずはブートローダープログラムを見てみましょう

#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" ); //清除显示
            }
        }
    }
}

  ブートローダーでは、シリアル ポートがアップグレード ファイルを送信するのを待機しており、シリアル ポートがアップグレード ファイルを受信すると、フラッシュにジャンプして APP コードを実行します。ブートローダーコードのアドレスは以下のように設定されています。
ここに画像の説明を挿入
ここに画像の説明を挿入
  keil を使用してブートローダーコードをデバッグする場合、正常にデバッグできます。
ここに画像の説明を挿入

アプリプログラム

#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" );
    }
}

  APP プログラムに入ったら、まずアドレスのオフセットを設定します。次に、APP プログラムで LED ライトを点滅させ、情報を印刷します。APP アドレスは次のように設定されます。
ここに画像の説明を挿入
ここに画像の説明を挿入
  keil を直接使用して APP プログラムを段階的にデバッグすると、プログラムが main 関数に入ることができないことがわかります。
ここに画像の説明を挿入

  プログラムは実行されていますが、メイン関数にジャンプできません。これは、プログラムが電源投入直後にブートローダ プログラムを実行し、ブートローダ プログラムが常にシリアル ポートのデータを待機するためです。 APPプログラム。プログラムを APP にジャンプさせたい場合は、シリアル ポート アシスタントを使用して APP プログラムを送信する必要があります。
画像の説明を追加してください

  シリアル ポート アシスタントを使用してアップグレード ファイルを送信すると、ブートローダー プログラムは APP プログラムが存在するアドレスに直接ジャンプするため、APP プログラムを段階的にデバッグできます。しかし、この方法でプログラムをデバッグするのはあまりにも面倒です。ブートローダーを使用せずに、APP プログラムを直接デバッグできませんか。もちろん、それは可能です。

方法 2: 構成ファイルを使用して APP プログラムを直接シミュレートする

  この方法を使用すると、マイクロコントローラーにブートローダー プログラムを書き込む必要がありません。まず、keil の APP ソフトウェアの構成を確認します。アドレス構成は変更されていません。
ここに画像の説明を挿入
  デバッグ オプションでは、初期化ファイルの場所に設定ファイルが追加されました。
ここに画像の説明を挿入
  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  

  コード内のこれら 3 つのアドレス値に注意してください。この値は APP プログラムの開始アドレスに関連しています。これらの 3 つの値を独自のプログラムに合わせて変更してください。
ここに画像の説明を挿入
  他の設定を変更しないでください
ここに画像の説明を挿入
  。そうすれば、keil ソフトウェアを使用して 1 ステップで APP プログラムを直接デバッグできます。
ここに画像の説明を挿入

  スタンドアロン シミュレーション ボタンがシミュレーション インターフェイスに入ると、この時点でプログラムが main 関数に直接ジャンプし、ジャンプするためにブートローダー プログラムを使用する必要がないことがわかります。このようにして、keil ソフトウェアは構成ファイルを通じて直接 main 機能にジャンプできます。
ここに画像の説明を挿入

  この方法を使用して APP プログラムをデバッグする場合、ブートローダー プログラムを書き込む必要はありません。ただし、MCU が独立して実行される場合でも、ブートローダー プログラムを書き込む必要があります。この設定ファイルは keil エミュレータ上でのみ動作し、keil エミュレーションを使用する場合にのみ動作します。

おすすめ

転載: blog.csdn.net/qq_20222919/article/details/131076871