2026-01-27 7:19 PM - last edited on 2026-01-28 4:01 AM by Andrew Neil
2026-01-28 4:00 AM
Hello @fujiangmu ,
Please use </> button to share your code instead of pasting screenshots of it.
Thank you for your understanding.
2026-01-29 12:05 AM
//主程序入口点
int main(void)
{
unsigned int count_old;
unsigned int count;
unsigned int count_old_key;
unsigned short flash_data;
unsigned int quotient;//串口收集到数据个数/2K的商部分
unsigned int remainder;//串口收集到数据个数/2K的余数部分
unsigned int iap_sp_addr;//烧录程序栈顶起始地址
VOID_FUN_TYPE_DEF* iap_jump_fun;
count_old = 0;
count_old_key = 0;
flash_data = 0x0123;
quotient = 0;
remainder = 0;
iap_sp_addr = 0x20000800;
g_uart_1_buff_number = 0;//全局变量要在main()函数里初始化才行
clock_init(9);
uart_init(72,115200);
key_5_init();
led_0_init();
while(1)
{
if(g_uart_1_buff_number)
{
if(g_uart_1_buff_number == count_old)
{
delay_big();
if(g_uart_1_buff_number == count_old)
{
if((count_old == 5) &&
((*((unsigned char*)(g_uart_1_buff))) == 0xAA)
)
{
//若是发0xAA+32位地址则打印从该地址起的20字节数据
g_uart_1_rxd_addr = (*(g_uart_1_buff+4)) + \
((*(g_uart_1_buff+3))<<8) + \
((*(g_uart_1_buff+2))<<16) + \
((*(g_uart_1_buff+1))<<24);
for(count=0;count<20;count++)
{
UART1->DR = *((unsigned char*)(g_uart_1_rxd_addr+count));
delay_little();
}
}
else if((count_old == 9) &&
((*((unsigned char*)(g_uart_1_buff))) == 0xCC)
)
{
//若是发0xCC+32位地址+32位数据,则将32位数据写入32位地址
g_uart_1_txd_addr = (*(g_uart_1_buff+4)) + \
((*(g_uart_1_buff+3))<<8) + \
((*(g_uart_1_buff+2))<<16) + \
((*(g_uart_1_buff+1))<<24);
g_uart_1_txd = (*(g_uart_1_buff+8)) + \
((*(g_uart_1_buff+7))<<8) + \
((*(g_uart_1_buff+6))<<16) + \
((*(g_uart_1_buff+5))<<24);
*((unsigned int*)g_uart_1_txd_addr) = g_uart_1_txd;
}
else if((count_old == 1) &&
((*((unsigned char*)(g_uart_1_buff))) == 0xDD)
)
{
//若是发0xDD,则将片内FLASH各寄存器值读出
//FLASH读取必须以32字节为单位
for(count=0;count<9;count++)
{
UART1->DR = (*((unsigned int*)0x40022000+count))>>24;
delay_little();
UART1->DR = (*((unsigned int*)0x40022000+count))>>16;
delay_little();
UART1->DR = (*((unsigned int*)0x40022000+count))>>8;
delay_little();
UART1->DR = (*((unsigned int*)0x40022000+count));
delay_little();
}
}
else if((count_old == 1) &&
((*((unsigned char*)(g_uart_1_buff))) == 0xD0)
)
{
//若是发0xD0,则将片内FLASH解锁
FLASH->KEYR = 0x45670123;
FLASH->KEYR = 0xCDEF89AB;
}
else if((count_old == 1) &&
((*((unsigned char*)(g_uart_1_buff))) == 0xD1)
)
{
//若是发0xD1,则将片内FLASH上锁
FLASH->CR |= 1<<7;
}
else if((count_old == 1) &&
((*((unsigned char*)(g_uart_1_buff))) == 0xD2)
)
{
//若是发0xD2,则将片内FLASH地址为0x0807F800所在页擦除
//选择页擦除
FLASH->CR &= 0xFFFFFFE0;
FLASH->CR |= 1<<1;
//将要擦除页的首地址写入闪存地址寄存器
FLASH->AR = 0x0807F800;
//选择页擦除功能,并开始操作
//开始页擦除
FLASH->CR |= 1<<6;
}
else if((count_old == 1) &&
((*((unsigned char*)(g_uart_1_buff))) == 0xD3)
)
{
//若是发0xD3,则将片内FLASH地址为0x0807F800处写入数据
//选择编程操作
FLASH->CR &= 0xFFFFFFE0;
FLASH->CR |= 1;
//写入1个半字数据
*((unsigned short*)0x0807F800) = 0x0123;
}
else if((count_old == 1) &&
((*((unsigned char*)(g_uart_1_buff))) == 0xD4)
)
{
//若是发0xD4,则将(*(unsigned short*)(g_uart_1_buff+30))
//写入片内FLASH地址为0x0807F800处
//测试用改变数据类型代替与或+位移拼贴数据的方法是否可行,可行
//选择编程操作
FLASH->CR &= 0xFFFFFFE0;
FLASH->CR |= 1;
//写入1个半字数据
*((unsigned short*)0x0807F800) = (*(unsigned short*)(g_uart_1_buff+30));
}
else if((count_old == 1) &&
((*((unsigned char*)(g_uart_1_buff))) == 0xD5)
)
{
//若是发0xD5,则将片内FLASH地址为0x08009000所在页及后1页擦除
flash_erase_page(0x08009000);
flash_erase_page(0x08009800);
}
else if((count_old == 1) &&
((*((unsigned char*)(g_uart_1_buff))) == 0xEE)
)
{
//若是发0xEE,则将跳转到烧录程序起始地址0x08009000+4处
//堆栈寄存器放入烧录程序起始地址0x08009000
__asm volatile
(
"MSR MSP,%0\n"
:
:"r"(iap_sp_addr)
:
);
//iap_addr = iap_addr+4;
iap_jump_fun = (VOID_FUN_TYPE_DEF*)0x08009005;
(*iap_jump_fun)();
//led_0();//可以
//iap_jump_fun = led_0;//可以
//iap_jump_fun = (VOID_FUN_TYPE_DEF*)0x080007f5;//最低位必须为1,可以
//(*iap_jump_fun)();
}
else
{
//否则就打印出0xAA+接收数据个数+0xFF+数据内容
UART1->DR = 0xAA;
delay_little();
UART1->DR = count_old>>24;
delay_little();
UART1->DR = count_old>>16;
delay_little();
UART1->DR = count_old>>8;
delay_little();
UART1->DR = count_old;
delay_little();
UART1->DR = 0xFF;
delay_little();
for(count=0;count<count_old;count++)
{
UART1->DR = *((unsigned char*)(g_uart_1_buff+count));
delay_little();
}
}
UART1->DR = 0xFF;//接收完成
g_uart_1_buff_number = 0;
}
else
{
count_old = g_uart_1_buff_number;//未接收完成
}
}
else
{
count_old = g_uart_1_buff_number;//未接收完成
}
}
if(g_key_5_exti_2)
{
if(g_key_5_exti_2 == count_old_key)
{
delay_big();
if(g_key_5_exti_2 == count_old_key)
{
UART1->DR = 0xBB;//有按键,且停止按键
delay_little();
UART1->DR = count_old>>8;//打印
delay_little();
UART1->DR = count_old;//打印
delay_little();
//擦除Flash
//flash_erase_page(0x08009000);
quotient = count_old/(2*1024);
remainder = count_old%(2*1024);
UART1->DR = quotient;//打印
delay_little();
UART1->DR = remainder;//打印
delay_little();
for(count=0;count<quotient;count++)
{
flash_erase_page(0x08009000+count*0x800);
}
UART1->DR = count;//打印
delay_little();
flash_erase_page(0x08009000+count*0x800);
//flash_erase_page(0x08009000);
//flash_erase_page(0x08009800);
//延时一会
delay_big();
//写入Flash
//flash_write_page(0x08009000,(unsigned short*)(g_uart_1_buff),0x20);
for(count=0;count<quotient;count++)
{
flash_write_page(0x08009000+count*0x800,(unsigned short*)(g_uart_1_buff+count*0x800),0x3FF);
}
UART1->DR = count;//打印
delay_little();
if(0 == ((remainder/2)%2))
{
flash_write_page(0x08009000+count*0x800,(unsigned short*)(g_uart_1_buff+count*0x800),(remainder/2));
}
else
{
flash_write_page(0x08009000+count*0x800,(unsigned short*)(g_uart_1_buff+count*0x800),(remainder/2)+1);
}
//flash_write_page(0x08009000,(unsigned short*)(g_uart_1_buff),0x3FF);
//flash_write_page(0x08009800,(unsigned short*)(g_uart_1_buff+0x800),0x304);
UART1->DR = 0xFF;//烧录完成
g_key_5_exti_2 = 0;
}
else
{
count_old_key = g_key_5_exti_2;//未停止按键
}
}
else
{
count_old_key = g_key_5_exti_2;//未停止按键
}
}
}
return 0;
}
2026-01-29 12:07 AM
Like this?
I use the code now,but have different result.
Can you tell me why?
2026-01-29 12:19 AM
I try to restore result that shows the irrelevant information on serial port,but there are different results on the serial port.
2026-01-29 12:31 AM
I tried to restore the code that shows the irrelevant information on serial port,bur there are different results.
First time,I burned FLASH APP onto the chip,it isn't normal.Then I read the FLASH,it was erased.
Sencond time,I burned FLASH APP onto the chip,it is normal.
2026-01-31 8:03 PM
It can work!
You are right.It must change the GPIO configure to disable the intterupt.
But why can't I use the command of "CPSID I" to disable the intterupt for the initialization.
2026-01-31 11:15 PM
Can you believe ?!
Now I can jump the FLASH APP,but don't need to disable the EXTI interrupt through changing the GPIO config.
2026-02-01 7:40 AM - edited 2026-02-01 7:41 AM
I think you will need to present a clearer picture if you want useful feedback.Show the entire program, show what is happening vs what you expect to happen. Attaching complete project or files may be more helpful than showing code snippets.
The UART peripheral works the same regardless of where it is called. Debugging your program, setting breakpoints and examine the logic will be most useful. There is not enough information here to know what is going on.
2026-02-01 5:05 PM
Sorry,I think that the informations written in the screenshot are helpful for understanding.
Must it change the GPIO configure to disable the intterupt before jumping to the FLASH APP?
2026-02-02 6:47 AM
You don't need to change GPIO configuration not to get UART output.
The only way to get UART output is by sending data to the UART. Stop doing that and you won't get spurious data.
Interrupts should generally be disabled during the jump because the location of variables in RAM are different and the vector table changes.