基于“ModBus写文件”实现STM32串口IAP升级固件(下)

STM32下位机这边分为两个程序,一个是BootLoader,一个是正常启动的APP

流程

正常启动流程

Created with Raphaël 2.1.2 开始 读取内部Flash OTA_STATUS==0? 跳转APP 等待固件升级 yes no

固件升级流程

上位机流程详情见上一篇博客

Created with Raphaël 2.1.2 接收串口数据(ModBus写寄存器) OTA_STATUS=1(修改内部Flash) 跳转回BootLoader

总的来说,下位机运行在APP是常态,通过ModBus指令,让其跳转回BootLoader。
在BootLoader中进行接收固件,覆盖APP程序,以达到固件升级的目的。

BootLoader程序

以SMT32F103ZET6为例,有512k flash,总共有0x80000个地址。
切割成两块。BootLoader占据64k,APP占据448k。

程序块 start size end
BootLoader 0x8000000 0x10000 0x8010000
App 0x8010000 0x70000 0x8080000

ROM配置

这里写图片描述

main.c

#include "main.h"

uint8_t rx_buffer[USART_MAX_LEN];
uint8_t tx_buffer[USART_MAX_LEN];
uint16_t rx_buffer_len=0;

uint16_t otaStatus=0;               //OTA״̬
uint16_t softwareVersion=0;     //¹Ì¼þ°æ±¾
_W2Byte softwareLength;         //¹Ì¼þ´óС
uint16_t _recordNumber;         //¼Ç¼ºÅ


int main(void)
{ 
    HAL_Init();                             //³õʼ»¯ HAL¿â     
    Stm32_Clock_Init(RCC_PLL_MUL9);     //³õʼ»¯ ʱÖÓ,72M 
    IWDG_Init(IWDG_PRESCALER_64,2000);  //³õʼ»¯ ÄÚ²¿¿´ÃŹ· ·ÖƵÊýΪ64,ÖØÔØֵΪ1000,Òç³öʱ¼äΪ4s    
    SP706SE_Init();                                         //³õʼ»¯ Íⲿ¿´ÃŹ·
    BUZZ_Init();
    MX_USART1_UART_Init();                          //³õʼ»¯ ´®¿Ú1
    USP_USART_RINGBUFFER_Init();            //³õʼ»¯ ´®¿Ú»·Ðλº³åÇø

    Boot2App();  

    while(1)
    {
        HAL_Delay(10);
        IWDG_Feed();        //ι¹· ÄÚ²¿¿´ÃŹ·
        SP706SE_WDOG;       //ι¹· Íⲿ¿´ÃŹ· 

        USART_Receive_Data(&huart1,rx_buffer,&rx_buffer_len);
        if(rx_buffer_len>0)
        {
            ModbusTask();
        } 
    } 
}

void Boot2App(void)
{
    STMFLASH_Read(FLASH_OTA_STATUS_ADDR,&otaStatus,1);//¶ÁÈ¡µ±Ç°OTA״̬  
    if(otaStatus==0)
    {  
        DBG_DEBUG("Boot2App");
        if(((*(vu32*)(FLASH_APP_ADDR+4))&0xFF000000)==0x08000000)//ÅжÏÊÇ·ñΪ0X08XXXXXX.     
            iap_load_app(FLASH_APP_ADDR);//Ö´ÐÐFLASH APP´úÂë
        else  
            DBG_ERROR("·ÇFLASHÓ¦ÓóÌÐò,ÎÞ·¨Ö´ÐÐ!\r\n");   
    }
    DBG_DEBUG("%d,BootLoader...",otaStatus);
}

void ModbusTask(void)
{
    uint16_t crc;
    uint8_t cmd;

    if(rx_buffer[0] == 0x09)                            
    {
        crc = CRC16(rx_buffer, rx_buffer_len -2);
        if(crc == ((rx_buffer[rx_buffer_len-1]<<8)|rx_buffer[rx_buffer_len-2]))//УÑéCRC
        {
            cmd = rx_buffer[1];
            switch(cmd)
            {
                case 0x03:
                    Modbus_Function_3();     
                break;
                case 0x10:
                    Modbus_Function_10();
                break;
                case 0x15:
                    Modbus_Function_15();
                break;
            }
        } 
    } 
}

//¶Á¶à¸ö¼Ä´æÆ÷
void Modbus_Function_3(void)   
{
    u16 reg_addr;
    u16 reg_count; 
    u16 crc16;  
    u16 index=3;
    reg_addr = (rx_buffer[2]<<8) + rx_buffer[3];
    reg_count = (rx_buffer[4]<<8) + rx_buffer[5]; 

    if(reg_addr == 0xFF00 && reg_count==0x01)                               
    { //¶ÁÈ¡µ±Ç°OTA״̬  
        index=3;
        STMFLASH_Read(FLASH_OTA_STATUS_ADDR,&otaStatus,1);
        tx_buffer[index++] = otaStatus>>8;
        tx_buffer[index++] = otaStatus;
        DBG_DEBUG("otaStatus=%d",otaStatus);
    }
    if(reg_addr == 0xFF02 && reg_count==0x01)
    { //¶ÁÈ¡¹Ì¼þ°æ±¾
        index=3;
        STMFLASH_Read(FLASH_SOFTWARE_VERSION_ADDR,&softwareVersion,1);
        tx_buffer[index++] = softwareVersion>>8;
        tx_buffer[index++] = softwareVersion;
        DBG_DEBUG("softwareVersion=%d",softwareVersion);
    }
    if(reg_addr == 0xFF04 && reg_count==0x02)
    { //¶ÁÈ¡¹Ì¼þ´óС
        index=3;
        STMFLASH_Read(FLASH_SOFTWARE_LENGTH_ADDR,softwareLength.w,2);
        tx_buffer[index++] = softwareLength.b[0];
        tx_buffer[index++] = softwareLength.b[1];
        tx_buffer[index++] = softwareLength.b[2];
        tx_buffer[index++] = softwareLength.b[3];
        DBG_DEBUG("softwareLength=%d",softwareLength.w2);
    }

    tx_buffer[0] = rx_buffer[0];//modbusµØÖ·
    tx_buffer[1] = 0x03;
    tx_buffer[2] =  index-3; //×Ö½ÚÊý

    crc16 = CRC16(tx_buffer, index);
    tx_buffer[index++] = crc16;
    tx_buffer[index++] = crc16>>8;
    HAL_UART_Transmit(&huart1, tx_buffer, index, 3000); 
}

//дÈë¶à¼Ä´æÆ÷
void Modbus_Function_10(void)           
{
    u16 reg_addr, reg_count;
    u16 crc16, i;  

    reg_addr = (rx_buffer[2]<<8) + rx_buffer[3];
    reg_count = (rx_buffer[4]<<8) + rx_buffer[5];  

    if(reg_addr == 0xFF00 && reg_count==0x0001)  
    {   //дOTA״̬   
        otaStatus = (rx_buffer[7]<<8) + rx_buffer[8];
        STMFLASH_Write(FLASH_OTA_STATUS_ADDR,&otaStatus,1);
        DBG_DEBUG("дOTA STATUS : %d",otaStatus);
        Boot2App();
    }  
    if(reg_addr == 0xFF02 && reg_count==0x0001)  
    {   //д¹Ì¼þ°æ±¾
        softwareVersion = (rx_buffer[7]<<8) + rx_buffer[8];
        STMFLASH_Write(FLASH_SOFTWARE_VERSION_ADDR,&softwareVersion,1);
        DBG_DEBUG("дSoftware Version : %d",softwareVersion); 
    }  
    if(reg_addr == 0xFF04 && reg_count==0x0002)  
    {   //д¹Ì¼þ´óС 
        softwareLength.b[0] = rx_buffer[7];
        softwareLength.b[1] = rx_buffer[8];
        softwareLength.b[2] = rx_buffer[9];
        softwareLength.b[3] = rx_buffer[10];
        STMFLASH_Write(FLASH_SOFTWARE_LENGTH_ADDR,softwareLength.w,2);
        DBG_DEBUG("дSoftware Length : %d",softwareLength.w2); 
    }  

    for(i = 0; i < 6; i++)
        tx_buffer[i] = rx_buffer[i];

    crc16 = CRC16(tx_buffer, 6);
    tx_buffer[6] = crc16;
    tx_buffer[7] = crc16>>8; 

    HAL_UART_Transmit(&huart1, tx_buffer, 8, 3000); 
} 

//дÈëÎļþ
void Modbus_Function_15(void)           
{
    u8 refType;                 //²Î¿¼ÀàÐÍ
    u16 fileNumber;         //ÎļþºÅ
    u16 recordNumber;       //¼Ç¼ºÅ 
    u16 recordLength;       //¼Ç¼³¤¶È
    u16 i; 

    refType = (rx_buffer[3]);
    fileNumber = (rx_buffer[4]<<8) + rx_buffer[5];
    recordNumber = (rx_buffer[6]<<8) + rx_buffer[7]; 
    recordLength = (rx_buffer[8]<<8) + rx_buffer[9]; 

    if(refType!=0x06)
    {
        DBG_ERROR("дÎļþ ²Î¿¼ÀàÐÍ ERROR");
        return;
    }
    if(recordLength!=0xf0)
    {
        DBG_ERROR("дÎļþ ¼Ç¼ºÅ³¤¶È ERROR");       
        return;
    }
    if(softwareLength.w==0)
    {
        DBG_ERROR("дÎļþ ¹Ì¼þ´óСΪ¿Õ");       
        return;
    }

    if(recordNumber==0)
        _recordNumber=0;
    else
    {
        if(recordNumber-_recordNumber==1 || recordNumber==_recordNumber)
        {   //дÈëÏÂÒ»¸öÎļþ¼Ç¼
            _recordNumber=recordNumber; 
        }
        else
        {
            DBG_ERROR("дÎļþ ¼Ç¼ºÅ Error");
            return;
        }
    }  

    iap_write_appbin(FLASH_APP_ADDR+_recordNumber*0xf0,rx_buffer+10,recordLength);//¸üÐÂFLASH´úÂë   

    for(i = 0; i < rx_buffer_len; i++)
        tx_buffer[i] = rx_buffer[i];


    HAL_UART_Transmit(&huart1, tx_buffer, rx_buffer_len, 3000); 

    if( (_recordNumber == (softwareLength.w2/0xf0-1) && (softwareLength.w2%0xf0==0)) ||
            (_recordNumber == (softwareLength.w2/0xf0) && (softwareLength.w2%0xf0!=0)) )
    {   //¼Ç¼ºÅ==¹Ì¼þ´óС£¬¹Ì¼þ½ÓÊÕÍê³É£¬¿ªÊ¼Éý¼¶
        otaStatus = 0; 
        softwareVersion=fileNumber; 

        STMFLASH_Write(FLASH_OTA_STATUS_ADDR,&otaStatus,1);
        STMFLASH_Write(FLASH_SOFTWARE_VERSION_ADDR,&softwareVersion,1); 
        Boot2App();
    }
} 

/* 
 * º¯ÊýÃû£ºCRC16
 * ÃèÊö  : ¼ÆËãCRC16
 * ÊäÈë  £ºaData---Êý¾Ý£¬ aSize---Êý¾Ý³¤¶È
 * Êä³ö  : УÑéÖµ
 */
uint16_t CRC16(uint8_t *ptr,uint16_t len)
{
     unsigned char i;
     unsigned short crc = 0xFFFF;
     if(len==0)
     {
         len = 1;
     }
     while(len--) 
     {
         crc ^= *ptr;
         for(i=0; i<8; i++)
         {
             if(crc&1)
             {
                 crc >>= 1;
                 crc ^= 0xA001;
             }
             else
             {
                    crc >>= 1;
             }
         }
         ptr++;
     }
     return(crc);
} 

APP程序

ROM配置

这里写图片描述

生成bin文件

这里写图片描述

D:\Keil_v5\ARM\ARMCC\bin\fromelf.exe   --bin -o  ..\OBJ\RTU_V1_0.bin ..\OBJ\RTU_V1_0.axf

main.c

#include "main.h"

uint8_t rx_buffer[USART_MAX_LEN];
uint8_t tx_buffer[USART_MAX_LEN];
uint16_t rx_buffer_len=0; 


int main(void)
{ 
    SCB->VTOR = ((uint32_t)0x08010000);

    HAL_Init();                             //³õʼ»¯ HAL¿â     
    Stm32_Clock_Init(RCC_PLL_MUL9);     //³õʼ»¯ ʱÖÓ,72M 
  IWDG_Init(IWDG_PRESCALER_64,2000);  //³õʼ»¯ ÄÚ²¿¿´ÃŹ· ·ÖƵÊýΪ64,ÖØÔØֵΪ1000,Òç³öʱ¼äΪ4s  
    SP706SE_Init();                                         //³õʼ»¯ Íⲿ¿´ÃŹ·
    BUZZ_Init();
  MX_USART1_UART_Init();                            //³õʼ»¯ ´®¿Ú1
  USP_USART_RINGBUFFER_Init();          //³õʼ»¯ ´®¿Ú»·Ðλº³åÇø 

    while(1)
    {
        HAL_Delay(10);
        IWDG_Feed();        //ι¹· ÄÚ²¿¿´ÃŹ·
        SP706SE_WDOG;       //ι¹· Íⲿ¿´ÃŹ·

        DBG_WARN("APP..."); 

        USART_Receive_Data(&huart1,rx_buffer,&rx_buffer_len);
        if(rx_buffer_len>0)
        {
            ModbusTask();
        } 
    } 
}

void APP2Boot(void)
{
    uint16_t otaStatus=0; 
    STMFLASH_Read(FLASH_OTA_STATUS_ADDR,&otaStatus,1);//¶ÁÈ¡µ±Ç°OTA״̬  
    if(otaStatus==1)
    {  
        DBG_DEBUG("APP2Boot");
        iap_load_app(FLASH_BOOT_ADDR);//Ìøת»ØBOOT³ÌÐò 
    }
}

void ModbusTask(void)
{
    uint16_t crc;
    uint8_t cmd;

    if(rx_buffer[0] == 0x09)                            
    {
        crc = CRC16(rx_buffer, rx_buffer_len -2);
        if(crc == ((rx_buffer[rx_buffer_len-1]<<8)|rx_buffer[rx_buffer_len-2]))//УÑéCRC
        {
            cmd = rx_buffer[1];
            switch(cmd)
            {
                case 0x03:
                    Modbus_Function_3();     
                break;
                case 0x10:
                    Modbus_Function_10();
                break; 
            }
        } 
    } 
}

//¶Á¶à¸ö¼Ä´æÆ÷
void Modbus_Function_3(void)   
{
    u16 reg_addr;
    u16 reg_count; 
    u16 crc16;  
    u16 index=3;
    reg_addr = (rx_buffer[2]<<8) + rx_buffer[3];
    reg_count = (rx_buffer[4]<<8) + rx_buffer[5]; 
    if(reg_addr == 0xFF00 && reg_count == 0x0001)                               
    { //¶ÁÈ¡µ±Ç°OTA״̬ 
        uint16_t otaStatus=0; 
        index=3;
        STMFLASH_Read(FLASH_OTA_STATUS_ADDR,&otaStatus,1);
        tx_buffer[index++] = otaStatus>>8;
        tx_buffer[index++] = otaStatus;
    }
    if(reg_addr == 0xFF02 && reg_count == 0x0001)
    { //¶ÁÈ¡¹Ì¼þ°æ±¾
        uint16_t softwareVersion=0;
        index=3;
        STMFLASH_Read(FLASH_SOFTWARE_VERSION_ADDR,&softwareVersion,1);
        tx_buffer[index++] = softwareVersion>>8;
        tx_buffer[index++] = softwareVersion;
    }
    if(reg_addr == 0xFF04 && reg_count == 0x0002)
    { //¶ÁÈ¡¹Ì¼þ´óС
        _W2Byte softwareLength;
        index=3;
        STMFLASH_Read(FLASH_SOFTWARE_LENGTH_ADDR,softwareLength.w,2);
        tx_buffer[index++] = softwareLength.b[0];
        tx_buffer[index++] = softwareLength.b[1];
        tx_buffer[index++] = softwareLength.b[2];
        tx_buffer[index++] = softwareLength.b[3];
    }

    tx_buffer[0] = rx_buffer[0];//modbusµØÖ·
    tx_buffer[1] = 0x03;
    tx_buffer[2] =  index-3; //×Ö½ÚÊý

    crc16 = CRC16(tx_buffer, index);
    tx_buffer[index++] = crc16;
    tx_buffer[index++] = crc16>>8;
    HAL_UART_Transmit(&huart1, tx_buffer, index, 3000); 
}

//дÈë¶à¼Ä´æÆ÷
void Modbus_Function_10(void)           
{
    u16 reg_addr, reg_count;
    u16 crc16, i;  

    reg_addr = (rx_buffer[2]<<8) + rx_buffer[3];
    reg_count = (rx_buffer[4]<<8) + rx_buffer[5];  

    if(reg_addr == 0xFF00 && reg_count == 0x0001)  
    {   //дOTA״̬   
        uint16_t otaStatus=0; 
        otaStatus = (rx_buffer[7]<<8) + rx_buffer[8];
        STMFLASH_Write(FLASH_OTA_STATUS_ADDR,&otaStatus,1);
        DBG_DEBUG("дOTA STATUS : %d",otaStatus);
        APP2Boot();
    }   

    for(i = 0; i < 6; i++)
        tx_buffer[i] = rx_buffer[i];

    crc16 = CRC16(tx_buffer, 6);
    tx_buffer[6] = crc16;
    tx_buffer[7] = crc16>>8; 

    HAL_UART_Transmit(&huart1, tx_buffer, 8, 3000); 
}  

/* 
 * º¯ÊýÃû£ºCRC16
 * ÃèÊö  : ¼ÆËãCRC16
 * ÊäÈë  £ºaData---Êý¾Ý£¬ aSize---Êý¾Ý³¤¶È
 * Êä³ö  : УÑéÖµ
 */
uint16_t CRC16(uint8_t *ptr,uint16_t len)
{
     unsigned char i;
     unsigned short crc = 0xFFFF;
     if(len==0)
     {
         len = 1;
     }
     while(len--) 
     {
         crc ^= *ptr;
         for(i=0; i<8; i++)
         {
             if(crc&1)
             {
                 crc >>= 1;
                 crc ^= 0xA001;
             }
             else
             {
                    crc >>= 1;
             }
         }
         ptr++;
     }
     return(crc);
} 

这里写图片描述

猜你喜欢

转载自blog.csdn.net/kangweijian/article/details/80374551