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 エミュレーションを使用する場合にのみ動作します。