STM32F103VE+Air720H+AT_Client升级过程分享

发布于 2020-04-14 19:54:52
    本帖最后由 yc985055 于 2020-4-14 19:58 编辑


这些天一直在测试STM32F103VE通过Air720H的HTTP功能升级固件。
其中参考了官方文档
https://www.rt-thread.org/docume ... -rtboot/#bootloader
和以下链接
https://www.rt-thread.org/qa/for ... ypeid%26typeid%3D64
1.下面是擦除download分区和写数据函数。
/***************************************************************************************************
* @fn hw_upgrade_start(void)
*
* @brief erase flash
*
* @param
*
* @return none
****************************************************************************************************/;
static void hw_upgrade_start(void)
{
http_size_bytes = 0;
http_size_conts = 0;
http_size_conts_max = 0;
u16UdpCrc = 0;

rt_kprintf("hw_upgrade_start() !!!\r\n");
if ((dl_part = fal_partition_find(recv_partition)) == RT_NULL)
{
rt_kprintf("Firmware download failed! Partition (%s) find error!", recv_partition);
return;
}
/* erase DL section */
if (fal_partition_erase(dl_part, 0, 196 * 1024) < 0)
{
rt_kprintf("Firmware download failed! Partition (%s) erase error!", dl_part->name);
return ;
}

//stm32_flash_erase ((rt_uint32_t)INT_FLASH_DOWNLOAD_ADDR, 196 * 1024);
}

/***************************************************************************************************
* @fn void hw_upgrade_data_save(rt_uint8_t *pDataBuf, rt_uint16_t dataLen)
*
* @brief save upgrade data to flash
*
* @param
*
* @return none
****************************************************************************************************/
static void hw_upgrade_data_save(rt_uint8_t *pDataBuf, rt_uint16_t dataLen)
{
rt_uint16_t tempU16 = 0;
tempU16 = dataLen;


//if (tempU16 == stm32_flash_write((rt_uint32_t)INT_FLASH_DOWNLOAD_ADDR + (rt_uint32_t)(http_size_conts * HTTP_SIZE_PER_PKT), pDataBuf, dataLen))
if (fal_partition_write(dl_part, (rt_uint32_t)(http_size_conts * HTTP_SIZE_PER_PKT), pDataBuf, dataLen) > 0)
{
http_size_conts++;

//计算校验,最后两字节是校验值,不参与运算
rt_kprintf("http_size_conts is-%d!!! UdpCrc is 0x%04x !!!0x%02x 0x%02x\r\n", http_size_conts, u16UdpCrc, pDataBuf[tempU16 - 2], pDataBuf[tempU16 - 1]);
if (tempU16 < HTTP_SIZE_PER_PKT)
{
tempU16 -= 2;
}
for (rt_uint16_t i = 0; i < tempU16; i++)
{
u16UdpCrc = hw_udp_pkt_run_poly(u16UdpCrc, pDataBuf
    );
    }
    }
    else
    {
    rt_kprintf("fal_partition_write() error\r\n");
    }
    }

    注:其实用stm32_flash_erase(...) stm32_flash_write(...)来执行是一样的,我开始升级不成功,以为是它们的原因。所以调用了ymodem_ota中的两个函数。

    2.http读取数据函数。
    http线程函数

    case HTTP_READ_DATA:

    {
    if ((http_size_bytes - http_size_conts * HTTP_SIZE_PER_PKT) >= HTTP_SIZE_PER_PKT)
    {
    u16Temp = HTTP_SIZE_PER_PKT;
    }
    else
    {
    u16Temp = http_size_bytes - http_size_conts * HTTP_SIZE_PER_PKT;
    }

    rt_kprintf("http_size_bytes %d http_size_conts:%d http_size_conts_max:%d\r\n", http_size_bytes, http_size_conts, http_size_conts_max);

    at_delete_resp(resp);
    resp = at_create_resp(HTTP_SIZE_PER_PKT + 56, 0, rt_tick_from_millisecond(500));
    if(resp == NULL)
    {
    rt_kprintf(" create HTTP resp no memory");
    }
    sprintf((char *)HTTP_CMD_READ,(char const *)"%s%d%s%d",(char const *)"AT+HTTPREAD=", (rt_uint32_t)(http_size_conts * HTTP_SIZE_PER_PKT), ",", u16Temp);

    if (at_exec_cmd(resp, HTTP_CMD_READ) == RT_EOK)
    {
    http_read_func(resp);
    }
    else
    {
    rt_kprintf("at_exec_cmd return error\r\n");
    }
    }

    /***************************************************************************************************
    * @fn void http_read_func(at_response_t httpReadResp)
    *
    * @brief 读取http下载的数据
    *
    * @param none
    *
    * @return none
    ****************************************************************************************************/
    static void http_read_func(at_response_t httpReadResp)
    {
    rt_bool_t bIsHaveData = RT_FALSE;
    rt_uint16_t u16Temp ,i;
    const char *line_buffer = RT_NULL;
    char *httpReadBuf = RT_NULL;

    if (httpReadResp == RT_NULL || httpReadResp->line_counts < 4)
    {
    return;
    }
    httpReadBuf = rt_malloc(HTTP_SIZE_PER_PKT);
    if (httpReadBuf == RT_NULL)
    {
    rt_kprintf("http_read_func out of memory!!\r\n");
    }

    if ((http_size_bytes - http_size_conts * HTTP_SIZE_PER_PKT) >= HTTP_SIZE_PER_PKT)
    {
    u16Temp = HTTP_SIZE_PER_PKT;
    }
    else
    {
    u16Temp = http_size_bytes - http_size_conts * HTTP_SIZE_PER_PKT;
    }

    rt_kprintf("The max lines is %d size is %d\r\n", httpReadResp->line_counts, httpReadResp->buf_len);

    for (rt_size_t line_num = 1; line_num <= httpReadResp->line_counts; line_num++)
    {
    if((line_buffer = at_resp_get_line(httpReadResp, line_num)) != RT_NULL)
    {
    //找到数据区的前一行
    if(strstr(line_buffer, "+HTTPREAD:"))
    {
    //找到数据区的首行
    if((line_buffer = at_resp_get_line(httpReadResp, line_num + 1)) != RT_NULL)
    {
    bIsHaveData = RT_TRUE;
    break;
    }

    }
    //rt_kprintf("line %d %02x %02x %02x %02x\r\n", line_num, line_buffer[0],line_buffer[1],line_buffer[2],line_buffer[3]);
    }
    }


    if (httpReadResp->line_counts > 4)
    {
    for (i = 0; i < u16Temp; i++)
    {
    if (line_buffer
      == 0x0D && line_buffer[i + 1] == 0x00)
      {
      httpReadBuf[i++] = 0x0D;
      httpReadBuf
        = 0x0A;

        }
        else
        {
        httpReadBuf
          = line_buffer
            ;
            }
            }
            }

            if (bIsHaveData)
            {
            if (httpReadResp->line_counts > 4 )
            {
            hw_upgrade_data_save((rt_uint8_t *)httpReadBuf, u16Temp);
            }
            else
            {
            hw_upgrade_data_save((rt_uint8_t *)line_buffer, u16Temp);
            }
            }

            //判断是否下载完成
            if (http_size_conts >= http_size_conts_max)
            {
            //系统重启
            air_cur_status = HTTP_TERM;
            rt_kprintf("System now will restart...u16UdpCrc value is 0x%04x\r\n", u16UdpCrc);

            hw_upgrade_crc_check();
            /* wait some time */
            rt_thread_delay(500);
            rt_hw_cpu_reset();
            rt_thread_delay(500);
            }
            else
            {
            air_cur_status = HTTP_READ_DATA;
            }

            rt_free(httpReadBuf);
            }

            注:这里遇到不少问题。
            A. 不能用urc函数获取{"+HTTPREAD", "\r\n", urc_http_read_func}. 因为没有结束符。
            B. 想用at_client_recv代替at_exec_cmd和at_create_resp函数来读数据。老返回失败
            C. 后面在AT_Client中找了,没有合适函数还是用at_exec_cmd和at_create_resp. 这里我通过每条数据包校验打印才发现。at_create_resp以行为单位读取数据,会把文件中的0x0D 0x0A转换成0x0D 0x00。 现在我是做了判断,把数据反转回来。暂时可以这样做,升级没有问题。
            D.没用采用ota_http升级中的函数,或许会更容易,我是为了减少源码大小。

            E期间,我还自己写了C#代码来计算校验值,看是哪个包出错啦。



            在此要感谢以下两位的帮助:面码1314 发表于 2020-4-12 18:07 小小李sunny 发表于 2020-4-12 22:07

查看更多

关注者
0
被浏览
217
0 个回答
jerry4cool
jerry4cool 2020-06-19
感谢分享。。。。
暂无答案,快来添加答案吧

撰写答案

请登录后再发布答案,点击登录

发布
问题

分享
好友