kirito 2020-11-29 V1.0
0簡介
開發闆: stm32f407vgt6
IDE: keil + cubemx6.0
功能: 實作stm32HAL 序列槽IAP, 協定采用非阻塞式ymodem協定, 能夠使用超級終端或者securRT 發送bin檔案, 同時能接受檔案
1 流程
序列槽中斷發送過來的資料存儲到緩沖區, 每次從緩沖區中拿出資料丢到資料解析器, 解析出每幀.
// 可以切換接受和發送模式
#define USE_RX_MODE
#define KAPP_ADDR (uint32_t)0x08004000
// 序列槽接受回調
void g_com_rx_callBack(unsigned char* data,uint32_t size)
{
#ifdef USE_RX_MODE
ymodem_rx_handle(data,size);
#else
ymodem_tx_handle(data,size);
#endif
}
// 序列槽錯誤回調
void g_ymodem_rx_error_handle(int error_code)
{
printf("--error code :%d--\r\n",error_code);
}
// 接受head回調
char g_ymodem_rx_head_handle(char *file_name,uint16_t file_name_len, uint32_t file_len)
{
printf("file:%s %d\r\n",file_name,file_len);
FLASH_If_Erase( KAPP_ADDR);
return 0;
}
uint32_t app_addr = KAPP_ADDR;
// 接受資料回調
void g_ymodem_rx_data_handle(char *data, uint16_t len,uint32_t download_byte,uint8_t percent)
{
printf("data len:%d %d %d\r\n",len,download_byte ,percent);
if (FLASH_If_Write(app_addr,(uint32_t*) data,len/4) == FLASHIF_OK)
{
app_addr += len;
printf("data write ok\r\n");
}else{
printf("data write error\r\n");
}
}
// 接受完成回調
void g_ymodem_rx_finish_handle(int state)
{
if(state ==0){
printf("--file end--\r\n");
iap_load_app(KAPP_ADDR);
}else{
printf("--file end error1 :%d--\r\n",state);
}
}
// 發送資料處理
void g_ymodem_tx_data_handle(uint8_t **file_read_addr, uint32_t file_read_size, uint32_t file_has_read_size, uint32_t file_remain_size,uint8_t percent)
{
printf("read size:%d has_read:%d remain:%d per:%d\r\n",file_read_size,file_has_read_size, file_remain_size,percent);
// 指針指向的位址 重新指向
*file_read_addr = &file[file_has_read_size];
}
int main()
{
// 注冊序列槽緩沖區回調
dev_comctrl_init();
dev_comctrl_regist_rx_callback(g_com_rx_callBack);
// 注冊ymodem回調
Ymodem_TypeDef ymodem;
ymodem.ymodem_write_byte = drv_com1_write;
ymodem.ymodem_rx_error_handle = g_ymodem_rx_error_handle;
ymodem.ymodem_rx_head_handle = g_ymodem_rx_head_handle;
ymodem.ymodem_rx_data_handle = g_ymodem_rx_data_handle;
ymodem.ymodem_rx_finish_handle = g_ymodem_rx_finish_handle;
ymodem.ymodem_tx_data_handle = g_ymodem_tx_data_handle;
ymodem_init(&ymodem);
// 循環
while (1)
{ // 序列槽緩沖區處理
dev_comctrl_handle();
// ymodem定時處理
ymodem_rx_time_handle();
return 0;
}
2 發送模式使用:
1 流程
把宏定義注釋打開,就是往單片機寫資料
#define USE_RX_MODE
軟體: securRT或者超級終端都可以
1 重新開機32, 會一直發C
2 選擇transfer -> send ymodem , 選擇要發送的檔案 選中固件之後, 直接點選發送
3 接受模式使用
1 流程
把宏定義去掉
// #define USE_RX_MODE
打開接受模式
注意的是:
// 發送資料處理
void g_ymodem_tx_data_handle(uint8_t **file_read_addr, uint32_t file_read_size, uint32_t file_has_read_size, uint32_t file_remain_size,uint8_t percent)
{
printf("read size:%d has_read:%d remain:%d per:%d\r\n",file_read_size,file_has_read_size, file_remain_size,percent);
// 指針指向的位址 重新指向
*file_read_addr = &file[file_has_read_size];
}
file_read_addr是指針的指針, 用于重定向指針指向, 是以每次發送資料後都要重新指定, 避免發送重複 ,這種使用的最好場景就是大檔案的發送, 可以開1K的緩沖區, 然後每次發送之後重新指定指針指向
如果下載下傳失敗,或者擦除失敗
注意除了main.c 有定義使用者啟動位址, flash_if.h .c中也定義了APP位址和要擦除的扇區
如果往stm32寫資料失敗, 注意flash_if.c裡面的扇區擦除, 如果目前代碼太大,超過了之前設定的代碼, 那麼就造成失敗
是以一定要預留好bootloader的flash空間
代碼位址:
git: https://github.com/kirito6/stm32_HAL_YMODEM_IAP
csdn: