天天看點

stm32 HAL ymodem IAP0簡介1 流程2 發送模式使用:3 接受模式使用如果下載下傳失敗,或者擦除失敗

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:

繼續閱讀