951 lines
26 KiB
C
951 lines
26 KiB
C
/****************************************************************************
|
||
|
||
Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
|
||
|
||
This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
|
||
be copied by any method or incorporated into another program without
|
||
the express written consent of Aerospace C.Power. This Information or any portion
|
||
thereof remains the property of Aerospace C.Power. The Information contained herein
|
||
is believed to be accurate and Aerospace C.Power assumes no responsibility or
|
||
liability for its use in any way and conveys no license or title under
|
||
any patent or copyright and makes no representation or warranty that this
|
||
Information is free from patent or copyright infringement.
|
||
|
||
****************************************************************************/
|
||
//common
|
||
#include "os_types.h"
|
||
#include "iot_errno_api.h"
|
||
#include "iot_ringbuf_api.h"
|
||
#include "iot_gpio_api.h"
|
||
#include "os_mem_api.h"
|
||
#include "iot_board_api.h"
|
||
#include "iot_io_api.h"
|
||
#include "os_utils_api.h"
|
||
#include "os_timer_api.h"
|
||
#include "iot_img_hdr.h"
|
||
#include "iot_ntoh_api.h"
|
||
#include "iot_oem.h"
|
||
#include "iot_board.h"
|
||
|
||
#include "vc_task.h"
|
||
#include "vc_upgrade.h"
|
||
#include "vc_upgrade_driver.h"
|
||
|
||
/* define ring buffer size, unit is byte */
|
||
#define VC_UPGRADE_RING_BUF_SIZE (256 + 32)
|
||
|
||
/* define stm32 upgrade file min size, unit is byte */
|
||
#define VC_UPGRADE_STM32_FILE_SIZE_MIN 10
|
||
|
||
/* define the waiting time for serial port reception, unit is ms */
|
||
#define VC_UPGARDE_CMD_WAIT_TIME 500
|
||
|
||
/* define monitor timer period, unit is ms */
|
||
#define VC_UPGRADE_TIMER_PERIOD 100
|
||
|
||
/* define stm32 upgrade fw header buffer size. */
|
||
#define VC_UPGRADE_FW_HEAD_BUFFER_SIZE 256
|
||
|
||
/* define send data is the fw data. */
|
||
#define VC_UPGRADE_FW_DATA 0
|
||
|
||
/* define send data is the fw data header. */
|
||
#define VC_UPGRADE_FW_DATA_HEADER 1
|
||
|
||
#define VC_UPGRADE_FW_DEV_TYPE 0xdc03
|
||
|
||
#define VC_UPGRADE_FW_GUARD 0xa4e49a17
|
||
|
||
typedef struct _vc_upgrade_t {
|
||
/* init flag, 1 mean succeed */
|
||
uint8_t init_flag;
|
||
/* stm32 boot0 gpio */
|
||
uint8_t gpio_boot0;
|
||
/* stm32 reset gpio */
|
||
uint8_t gpio_reset;
|
||
/* ring buf, save uart data */
|
||
ringbuf_t ring_buf;
|
||
/* stm32 handle */
|
||
stm32_t *stm32;
|
||
/* upgrade file addr */
|
||
uint8_t *file_addr;
|
||
/* upgrade file size */
|
||
uint32_t file_size;
|
||
/* upgrade status */
|
||
vc_upgrd_state_e status;
|
||
/* percentage of data sent */
|
||
uint32_t percentage;
|
||
/* write buffer */
|
||
uint8_t *buffer_w;
|
||
/* read buffer */
|
||
uint8_t *buffer_r;
|
||
/* write data lenght */
|
||
uint32_t len_transf;
|
||
/* current addr of the stm32 to write */
|
||
uint32_t addr_curr;
|
||
/* header addr of the stm32 to write */
|
||
uint32_t addr_headr;
|
||
/* data offset of upd file */
|
||
uint32_t offset_curr;
|
||
/* header offset of upd file */
|
||
uint32_t offset_header;
|
||
/* send the completion flag, 1 -> completion */
|
||
uint8_t flag_transf_over;
|
||
} vc_upgrade_t;
|
||
|
||
#if INCLUDE_VIRTUAL_CHANNEL
|
||
|
||
vc_upgrade_t *g_upgrade = NULL;
|
||
|
||
static const uint8_t stm32_bin[] = {
|
||
#include "stm32_bin.txt"
|
||
};
|
||
|
||
static stm32_err_t vc_upgrade_buffer_compare(uint8_t *buf_w,
|
||
uint8_t *buf_r, uint32_t len)
|
||
{
|
||
if (buf_w == NULL || buf_r == NULL || len == 0) {
|
||
return STM32_ERR_UNKNOWN;
|
||
}
|
||
|
||
for(uint32_t i = 0; i < len; i++) {
|
||
if (buf_w[i] != buf_r[i]) {
|
||
stm32_dbg_printf("Failed to verify at address 0x%08x, "
|
||
"expected 0x%02x and found 0x%02x\n", g_upgrade->addr_curr + i,
|
||
buf_w[i], buf_r[i]);
|
||
return STM32_ERR_UNKNOWN;
|
||
}
|
||
}
|
||
return STM32_ERR_OK;
|
||
}
|
||
|
||
static stm32_err_t vc_upgrade_stm32_file_transfer_once(uint8_t type)
|
||
{
|
||
uint32_t max_wlen = STM32_MAX_TX_PAYLOAD_LENGTH;
|
||
uint32_t *addr_temp = NULL, *offset = NULL;
|
||
uint32_t len = 0;
|
||
uint32_t addr_end = 0x0;
|
||
uint32_t file_size;
|
||
uint8_t *buffer = NULL;
|
||
stm32_t *stm32 = NULL;
|
||
stm32_err_t err = STM32_ERR_UNKNOWN;
|
||
uint32_t left = 0;
|
||
uint32_t reason = 0;
|
||
(void)reason;
|
||
|
||
(void)left; //eliminate compile errors
|
||
if (!g_upgrade || !g_upgrade->init_flag || !g_upgrade->stm32->is_connect) {
|
||
reason = 1;
|
||
goto out;
|
||
}
|
||
stm32 = g_upgrade->stm32;
|
||
addr_end = g_upgrade->stm32->dev->fl_end;
|
||
file_size = g_upgrade->file_size;
|
||
buffer = g_upgrade->buffer_w;
|
||
|
||
if (VC_UPGRADE_FW_DATA_HEADER == type) {
|
||
addr_temp = &g_upgrade->addr_headr;
|
||
offset = &g_upgrade->offset_header;
|
||
} else {
|
||
addr_temp = &g_upgrade->addr_curr;
|
||
offset = &g_upgrade->offset_curr;
|
||
}
|
||
|
||
if (*addr_temp >= addr_end || *offset >= file_size) {
|
||
*addr_temp = 0;
|
||
*offset = 0;
|
||
g_upgrade->flag_transf_over = 1;
|
||
reason = 2;
|
||
goto out;
|
||
}
|
||
|
||
left = addr_end - *addr_temp;
|
||
len = max_wlen > left ? left : max_wlen;
|
||
len = len > file_size - *offset ? file_size - *offset : len;
|
||
if (VC_UPGRADE_FW_DATA_HEADER == type) {
|
||
len = HEADER_TOLTAL_SIZE;
|
||
}
|
||
stm32_dbg_printf("addr:0x%08x, offset:%d, len:%d\n",*addr_temp, *offset, len);
|
||
os_mem_cpy(buffer, &g_upgrade->file_addr[*offset], len);
|
||
err = stm32_send_write_data(stm32, buffer, len);
|
||
if (err != STM32_ERR_OK) {
|
||
g_upgrade->status = VC_UPGRD_STATE_ERR;
|
||
reason = 3;
|
||
goto out;
|
||
}
|
||
g_upgrade->len_transf = len;
|
||
|
||
if (VC_UPGRADE_FW_DATA == type) {
|
||
*addr_temp += len;
|
||
*offset += len;
|
||
|
||
g_upgrade->percentage = 100 * (*offset) / file_size;
|
||
/* prevent additional write cmd from being executed once after burning */
|
||
if (g_upgrade->percentage == 100) {
|
||
g_upgrade->flag_transf_over = 1;
|
||
}
|
||
}
|
||
out:
|
||
stm32_dbg_printf("result:%d, reason:%d \n", err, reason);
|
||
return err;
|
||
}
|
||
|
||
static uint32_t vc_upgrade_status_handle(uint8_t state)
|
||
{
|
||
uint32_t result = ERR_OK;
|
||
int32_t reason = 0;
|
||
uint32_t spage = 0;
|
||
uint32_t pages = 0;
|
||
(void)reason; //eliminate compile errors
|
||
if (state >= UPGRADE_STATE_MAX) {
|
||
reason = -1;
|
||
result = ERR_FAIL;
|
||
goto out;
|
||
}
|
||
reason = state;
|
||
switch (state) {
|
||
case UPGRADE_SEND_INIT:
|
||
result = stm32_send_get_version_cmd(g_upgrade->stm32);
|
||
g_upgrade->stm32->state = UPGRADE_SEND_GET_VERSION;
|
||
break;
|
||
case UPGRADE_SEND_GET_VERSION:
|
||
result = stm32_send_get_cmd(g_upgrade->stm32);
|
||
g_upgrade->stm32->state = UPGRADE_SEND_GET;
|
||
break;
|
||
case UPGRADE_SEND_GET:
|
||
result = stm32_send_get_id_cmd(g_upgrade->stm32);
|
||
g_upgrade->stm32->state = UPGRADE_SEND_GET_ID;
|
||
break;
|
||
case UPGRADE_SEND_GET_ID:
|
||
result = stm32_send_erase_cmd(g_upgrade->stm32);
|
||
g_upgrade->stm32->state = UPGRADE_SEND_ERASE;
|
||
g_upgrade->status = VC_UPGRD_STATE_CLEAR_STORAGE_HEADER;
|
||
break;
|
||
case UPGRADE_SEND_ERASE_DATA:
|
||
result = stm32_send_erase_cmd(g_upgrade->stm32);
|
||
g_upgrade->stm32->state = UPGRADE_SEND_ERASE;
|
||
g_upgrade->status = VC_UPGRD_STATE_CLEAR_STORAGE;
|
||
break;
|
||
case UPGRADE_SEND_ERASE:
|
||
if (VC_UPGRD_STATE_CLEAR_STORAGE_HEADER == g_upgrade->status) {
|
||
spage = (g_upgrade->stm32->dev->fl_end - g_upgrade->stm32->dev->fl_start)
|
||
/ g_upgrade->stm32->dev->fl_ps[0] - 1;
|
||
pages = 1;
|
||
result = stm32_send_erase_page_info(g_upgrade->stm32, spage, pages);
|
||
g_upgrade->stm32->state = UPGRADE_SEND_ERASE_DATA;
|
||
} else {
|
||
//now, we'll just erase from the first page
|
||
spage = 0;
|
||
pages = flash_addr_to_page_ceil(g_upgrade->stm32,
|
||
g_upgrade->stm32->dev->fl_start + g_upgrade->file_size) - spage;
|
||
result = stm32_send_erase_page_info(g_upgrade->stm32, spage, pages);
|
||
g_upgrade->stm32->state = UPGRADE_SEND_ERASE_PAGE_INFO;
|
||
}
|
||
break;
|
||
case UPGRADE_SEND_ERASE_PAGE_INFO:
|
||
result = stm32_send_write_cmd(g_upgrade->stm32);
|
||
g_upgrade->stm32->state = UPGRADE_SEND_WRITE;
|
||
g_upgrade->status = VC_UPGRD_STATE_WRITE_HEADER;
|
||
break;
|
||
case UPGRADE_SEND_WRITE:
|
||
if (VC_UPGRD_STATE_WRITE_HEADER == g_upgrade->status) {
|
||
result = stm32_send_write_addr(g_upgrade->stm32, g_upgrade->addr_headr);
|
||
} else {
|
||
result = stm32_send_write_addr(g_upgrade->stm32, g_upgrade->addr_curr);
|
||
}
|
||
g_upgrade->stm32->state = UPGRADE_SEND_WRITE_ADDR;
|
||
break;
|
||
case UPGRADE_SEND_WRITE_ADDR:
|
||
if (VC_UPGRD_STATE_WRITE_HEADER == g_upgrade->status) {
|
||
result = vc_upgrade_stm32_file_transfer_once(VC_UPGRADE_FW_DATA_HEADER);
|
||
} else {
|
||
result = vc_upgrade_stm32_file_transfer_once(VC_UPGRADE_FW_DATA);
|
||
}
|
||
g_upgrade->stm32->state = UPGRADE_SEND_WRITE_DATA;
|
||
break;
|
||
case UPGRADE_SEND_WRITE_DATA:
|
||
result = stm32_send_read_cmd(g_upgrade->stm32);
|
||
g_upgrade->stm32->state = UPGRADE_SEND_READ;
|
||
break;
|
||
case UPGRADE_SEND_READ:
|
||
if (VC_UPGRD_STATE_WRITE_HEADER == g_upgrade->status) {
|
||
result = stm32_send_read_addr(g_upgrade->stm32, g_upgrade->addr_headr);
|
||
} else {
|
||
result = stm32_send_read_addr(g_upgrade->stm32,
|
||
g_upgrade->addr_curr - g_upgrade->len_transf);
|
||
}
|
||
g_upgrade->stm32->state = UPGRADE_SEND_READ_ADDR;
|
||
break;
|
||
case UPGRADE_SEND_READ_ADDR:
|
||
result = stm32_send_read_length(g_upgrade->stm32, g_upgrade->len_transf);
|
||
g_upgrade->stm32->state = UPGRADE_SEND_READ_LENGTH;
|
||
break;
|
||
case UPGRADE_SEND_READ_LENGTH:
|
||
result = stm32_send_read_rdata(g_upgrade->stm32,
|
||
g_upgrade->buffer_r, g_upgrade->len_transf);
|
||
result |= vc_upgrade_buffer_compare(g_upgrade->buffer_w,
|
||
g_upgrade->buffer_r, g_upgrade->len_transf);
|
||
if (g_upgrade->flag_transf_over != 1) {
|
||
result = stm32_send_write_cmd(g_upgrade->stm32);
|
||
g_upgrade->stm32->state = UPGRADE_SEND_WRITE;
|
||
if (result == ERR_OK) {
|
||
g_upgrade->status = VC_UPGRD_STATE_WRITE_DATA;
|
||
}
|
||
} else {
|
||
g_upgrade->status = VC_UPGRD_STATE_ENDUP;
|
||
}
|
||
break;
|
||
default:
|
||
result = STM32_ERR_UNKNOWN;
|
||
break;
|
||
}
|
||
out:
|
||
stm32_dbg_printf("result:%d, reason:%d \n", result, reason);
|
||
return result;
|
||
}
|
||
|
||
static uint32_t vc_upgrade_status_refresh(uint8_t state, uint32_t len)
|
||
{
|
||
uint32_t needed_len = 0;
|
||
uint32_t result = ERR_OK;
|
||
int32_t reason = 0;
|
||
(void)reason; //eliminate compile errors
|
||
|
||
if (state >= UPGRADE_STATE_MAX) {
|
||
reason = -1;
|
||
result = ERR_FAIL;
|
||
goto out;
|
||
}
|
||
|
||
if (g_upgrade->status == VC_UPGRD_STATE_ERR) {
|
||
reason = -2;
|
||
result = ERR_FAIL;
|
||
goto out;
|
||
}
|
||
|
||
reason = state;
|
||
switch (state) {
|
||
case UPGRADE_SEND_INIT:
|
||
needed_len = 1;
|
||
if (len < needed_len) {
|
||
break;
|
||
}
|
||
result = stm32_send_init_handle(g_upgrade->stm32);
|
||
break;
|
||
case UPGRADE_SEND_GET_VERSION:
|
||
needed_len = 5;
|
||
if (len < needed_len) {
|
||
break;
|
||
}
|
||
result = stm32_send_get_version_handle(g_upgrade->stm32);
|
||
break;
|
||
case UPGRADE_SEND_GET:
|
||
needed_len = 15;
|
||
if (len < needed_len) {
|
||
break;
|
||
}
|
||
result = stm32_send_get_handle(g_upgrade->stm32);
|
||
break;
|
||
case UPGRADE_SEND_GET_ID:
|
||
needed_len = 5;
|
||
if (len < needed_len) {
|
||
break;
|
||
}
|
||
result = stm32_send_get_id_handle(g_upgrade->stm32);
|
||
g_upgrade->addr_curr = g_upgrade->stm32->dev->fl_start;
|
||
g_upgrade->addr_headr = g_upgrade->stm32->dev->fl_end -
|
||
VC_UPGRADE_FW_HEAD_BUFFER_SIZE;
|
||
break;
|
||
case UPGRADE_SEND_ERASE:
|
||
needed_len = 1;
|
||
if (len < needed_len) {
|
||
break;
|
||
}
|
||
result = stm32_get_ack(g_upgrade->stm32);
|
||
break;
|
||
case UPGRADE_SEND_ERASE_DATA:
|
||
needed_len = 1;
|
||
if (len < needed_len) {
|
||
break;
|
||
}
|
||
result = stm32_get_ack(g_upgrade->stm32);
|
||
break;
|
||
case UPGRADE_SEND_ERASE_PAGE_INFO:
|
||
needed_len = 1;
|
||
if (len < needed_len) {
|
||
break;
|
||
}
|
||
result = stm32_get_ack(g_upgrade->stm32);
|
||
break;
|
||
case UPGRADE_SEND_WRITE:
|
||
needed_len = 1;
|
||
if (len < needed_len) {
|
||
break;
|
||
}
|
||
result = stm32_get_ack(g_upgrade->stm32);
|
||
break;
|
||
case UPGRADE_SEND_WRITE_ADDR:
|
||
needed_len = 1;
|
||
if (len < needed_len) {
|
||
break;
|
||
}
|
||
result = stm32_get_ack(g_upgrade->stm32);
|
||
break;
|
||
case UPGRADE_SEND_WRITE_DATA:
|
||
needed_len = 1;
|
||
if (len < needed_len) {
|
||
break;
|
||
}
|
||
result = stm32_get_ack(g_upgrade->stm32);
|
||
break;
|
||
case UPGRADE_SEND_READ:
|
||
needed_len = 1;
|
||
if (len < needed_len) {
|
||
break;
|
||
}
|
||
result = stm32_get_ack(g_upgrade->stm32);
|
||
break;
|
||
case UPGRADE_SEND_READ_ADDR:
|
||
needed_len = 1;
|
||
if (len < needed_len) {
|
||
break;
|
||
}
|
||
result = stm32_get_ack(g_upgrade->stm32);
|
||
break;
|
||
case UPGRADE_SEND_READ_LENGTH:
|
||
needed_len = 1 + g_upgrade->len_transf;
|
||
if (len < needed_len) {
|
||
break;
|
||
}
|
||
result = stm32_get_ack(g_upgrade->stm32);
|
||
break;
|
||
default:
|
||
result = STM32_ERR_UNKNOWN;
|
||
break;
|
||
}
|
||
|
||
if (len < needed_len) {
|
||
goto out;
|
||
}
|
||
|
||
if (result != STM32_ERR_OK) {
|
||
g_upgrade->status = VC_UPGRD_STATE_ERR;
|
||
stm32_dbg_printf("result:%d, reason:%d \n", result, reason);
|
||
goto out;
|
||
}
|
||
|
||
//Go to the next step
|
||
result = vc_upgrade_status_handle(state);
|
||
if (result != STM32_ERR_OK) {
|
||
g_upgrade->status = VC_UPGRD_STATE_ERR;
|
||
goto out;
|
||
}
|
||
out:
|
||
return result;
|
||
}
|
||
|
||
uint32_t vc_upgrd_receive_func(uint8_t *p_buf, uint32_t len)
|
||
{
|
||
IOT_ASSERT(p_buf);
|
||
if (len == 0 || g_upgrade == NULL) {
|
||
return ERR_FAIL;
|
||
}
|
||
|
||
#if 0
|
||
iot_printf("uart rec len:%d, data:");
|
||
for (uint32_t i = 0; i < len; i++) {
|
||
iot_printf("%02X ", p_buf[i]);
|
||
}
|
||
iot_printf("\n");
|
||
#endif
|
||
|
||
uint32_t free_size = iot_ringbuf_size(&g_upgrade->ring_buf)
|
||
- iot_ringbuf_elements(&g_upgrade->ring_buf);
|
||
if (free_size < len) {
|
||
return ERR_FAIL;
|
||
}
|
||
|
||
(void)iot_ringbuf_puts(&g_upgrade->ring_buf, p_buf, len);
|
||
|
||
(void)vc_upgrade_status_refresh(g_upgrade->stm32->state,
|
||
iot_ringbuf_elements(&g_upgrade->ring_buf));
|
||
|
||
return ERR_OK;
|
||
}
|
||
|
||
uint32_t vc_upgrade_pull_data_from_ringbuf(uint8_t *buf, uint32_t len)
|
||
{
|
||
uint32_t result = ERR_OK;
|
||
uint32_t len_readed = 0;
|
||
uint32_t temp = 0;
|
||
|
||
IOT_ASSERT(buf);
|
||
if (!g_upgrade || len == 0) {
|
||
result = ERR_FAIL;
|
||
goto out;
|
||
}
|
||
|
||
while(len_readed < len) {
|
||
temp = iot_ringbuf_gets(&g_upgrade->ring_buf, buf, len - len_readed);
|
||
len_readed += temp;
|
||
}
|
||
out:
|
||
return result;
|
||
}
|
||
|
||
void vc_upgrade_state_moniter(uint32_t counter)
|
||
{
|
||
static uint8_t state_old = UPGRADE_STATE_MAX;
|
||
static uint32_t run_time = 0; //ms
|
||
|
||
if (state_old != g_upgrade->stm32->state) {
|
||
state_old = g_upgrade->stm32->state;
|
||
run_time = 0;
|
||
return;
|
||
}
|
||
|
||
/* gets the command execution time,
|
||
the maximum change is the interval between calls to this function */
|
||
run_time += counter;
|
||
|
||
if (state_old == UPGRADE_SEND_WRITE_DATA
|
||
|| state_old == UPGRADE_SEND_READ_LENGTH) {
|
||
if (run_time > VC_UPGARDE_CMD_WAIT_TIME * 10) {
|
||
g_upgrade->status = VC_UPGRD_STATE_ERR;
|
||
}
|
||
} else {
|
||
if (run_time > VC_UPGARDE_CMD_WAIT_TIME) {
|
||
g_upgrade->status = VC_UPGRD_STATE_ERR;
|
||
}
|
||
}
|
||
|
||
stm32_dbg_printf("state:%d, percentage:%d\n",
|
||
g_upgrade->status, g_upgrade->percentage);
|
||
return;
|
||
}
|
||
|
||
uint32_t vc_upgrade_module_init(void)
|
||
{
|
||
uint8_t reason = 0;
|
||
uint8_t *ptr_ring = NULL;
|
||
uint32_t result = ERR_FAIL;
|
||
uint8_t rst_reason = 0;
|
||
|
||
g_upgrade = (vc_upgrade_t *)os_mem_malloc(IOT_DRIVER_MID, sizeof(vc_upgrade_t));
|
||
if (g_upgrade == NULL) {
|
||
reason = 1;
|
||
goto out;
|
||
}
|
||
os_mem_set(g_upgrade, 0x0, sizeof(vc_upgrade_t));
|
||
g_upgrade->status = VC_UPGRD_STATE_IDLE;
|
||
|
||
//gpio init
|
||
g_upgrade->gpio_boot0 = iot_board_get_gpio(GPIO_VC_EXT_CHIP_BOOT);
|
||
g_upgrade->gpio_reset = iot_board_get_gpio(GPIO_VC_EXT_CHIP_RST);
|
||
if (g_upgrade->gpio_boot0 == GPIO_NO_VALID
|
||
|| g_upgrade->gpio_reset == GPIO_NO_VALID) {
|
||
reason = 2;
|
||
goto free_upgrade;
|
||
}
|
||
if (iot_gpio_open_as_output(g_upgrade->gpio_boot0) != ERR_OK) {
|
||
reason = 3;
|
||
goto free_upgrade;
|
||
}
|
||
if (iot_gpio_open_as_output(g_upgrade->gpio_reset) != ERR_OK) {
|
||
(void)iot_gpio_close(g_upgrade->gpio_boot0);
|
||
reason = 4;
|
||
goto free_upgrade;
|
||
}
|
||
stm32_dbg_printf("GPIO_VC_EXT_CHIP_BOOT:%d, GPIO_VC_EXT_CHIP_RST:%d \n",
|
||
g_upgrade->gpio_boot0, g_upgrade->gpio_reset);
|
||
iot_gpio_set_pull_mode(g_upgrade->gpio_boot0, GPIO_PULL_DOWN);
|
||
iot_gpio_set_pull_mode(g_upgrade->gpio_reset, GPIO_PULL_UP);
|
||
|
||
//ring buffer init
|
||
ptr_ring = (uint8_t *)os_mem_malloc(IOT_DRIVER_MID, VC_UPGRADE_RING_BUF_SIZE);
|
||
if (ptr_ring == NULL) {
|
||
reason = 5;
|
||
goto close_gpio;
|
||
}
|
||
os_mem_set(ptr_ring, 0x0, VC_UPGRADE_RING_BUF_SIZE);
|
||
iot_ringbuf_init(&g_upgrade->ring_buf, ptr_ring, VC_UPGRADE_RING_BUF_SIZE);
|
||
|
||
//stm32 handle init
|
||
g_upgrade->stm32 = (stm32_t*)os_mem_malloc(IOT_DRIVER_MID, sizeof(stm32_t));
|
||
if (g_upgrade->stm32 == NULL) {
|
||
reason = 6;
|
||
goto free_ringbuf;
|
||
}
|
||
g_upgrade->stm32->cmd = (stm32_cmd_t *)os_mem_malloc(IOT_DRIVER_MID,
|
||
sizeof(stm32_cmd_t));
|
||
if (g_upgrade->stm32->cmd == NULL) {
|
||
reason = 7;
|
||
goto free_stm32;
|
||
}
|
||
//0xff -> STM32_CMD_ERR
|
||
os_mem_set(g_upgrade->stm32->cmd, 0xff, sizeof(stm32_cmd_t));
|
||
g_upgrade->stm32->port = os_mem_malloc(IOT_DRIVER_MID, sizeof(port_interface_t));
|
||
if (g_upgrade->stm32->port == NULL) {
|
||
reason = 8;
|
||
goto free_stm32;
|
||
}
|
||
|
||
g_upgrade->file_addr = (uint8_t *)stm32_bin;
|
||
g_upgrade->file_size = sizeof(stm32_bin) / sizeof(stm32_bin[0]);
|
||
stm32_dbg_printf("upgrade file size:%d \n", g_upgrade->file_size);
|
||
if (g_upgrade->file_size < VC_UPGRADE_STM32_FILE_SIZE_MIN) {
|
||
reason = 9;
|
||
goto free_stm32;
|
||
}
|
||
|
||
if (vc_module_upgrade_register_receive(vc_upgrd_receive_func) != ERR_OK) {
|
||
reason = 10;
|
||
goto free_stm32;
|
||
}
|
||
|
||
/**
|
||
* USB V2的板子kl1控制GD32的boot&reset初始状态不符合GD32的正常启动
|
||
* 需要在fw层控制GD32的power up;
|
||
* USB V3的板子kl1控制pin修改后默认状态可以直接power up GD32
|
||
* 因此不需要这里再次power up
|
||
* 如kl芯片crash软复位了,这里reset一下,把两边状态重新对上。
|
||
*/
|
||
if (iot_board_get_boot_reason(&rst_reason) != SYSTEM_RESET_PWR
|
||
|| (iot_oem_get_board_id() == BOARD_HTZDCCO01
|
||
&& iot_board_hw_version_hex() == HW_VERSION_CCO_USB_V2)) {
|
||
vc_upgrd_ext_chip_reset(VC_UPGRD_RESET_TO_POWERUP);
|
||
}
|
||
//init secceed
|
||
g_upgrade->init_flag = 1;
|
||
g_upgrade->stm32->port->read = vc_upgrade_pull_data_from_ringbuf;
|
||
result = ERR_OK;
|
||
goto out;
|
||
|
||
free_stm32:
|
||
if (g_upgrade->stm32) {
|
||
if (g_upgrade->stm32->port) {
|
||
os_mem_free(g_upgrade->stm32->port);
|
||
}
|
||
if (g_upgrade->stm32->cmd) {
|
||
os_mem_free(g_upgrade->stm32->cmd);
|
||
}
|
||
os_mem_free(g_upgrade->stm32);
|
||
}
|
||
g_upgrade->stm32 = NULL;
|
||
free_ringbuf:
|
||
os_mem_free(ptr_ring);
|
||
close_gpio:
|
||
(void)iot_gpio_close(g_upgrade->gpio_boot0);
|
||
(void)iot_gpio_close(g_upgrade->gpio_reset);
|
||
free_upgrade:
|
||
os_mem_free(g_upgrade);
|
||
g_upgrade = NULL;
|
||
out:
|
||
iot_printf("%s result:%d, reason:%d\n", __FUNCTION__, result, reason);
|
||
return result;
|
||
}
|
||
|
||
void vc_upgrade_modele_deinit(void)
|
||
{
|
||
if (g_upgrade) {
|
||
if (g_upgrade->stm32) {
|
||
if (g_upgrade->stm32->cmd) {
|
||
os_mem_free(g_upgrade->stm32->cmd);
|
||
}
|
||
if (g_upgrade->stm32->port) {
|
||
os_mem_free(g_upgrade->stm32->port);
|
||
}
|
||
os_mem_free(g_upgrade->stm32);
|
||
}
|
||
if (g_upgrade->ring_buf.data) {
|
||
os_mem_free(g_upgrade->ring_buf.data);
|
||
}
|
||
os_mem_free(g_upgrade);
|
||
g_upgrade = NULL;
|
||
}
|
||
}
|
||
|
||
//stm32 model: boot0=1, boot1=x -> rom
|
||
// boot0=0, boot1=x -> flash
|
||
static uint32_t vc_upgrade_stm32_boot_model_select(uint8_t model)
|
||
{
|
||
uint32_t result = ERR_FAIL;
|
||
|
||
if (!g_upgrade) {
|
||
goto out;
|
||
}
|
||
|
||
if (model == VC_UPGRD_RESET_TO_DOWNLOAD) {
|
||
if (iot_gpio_value_set(g_upgrade->gpio_boot0, 1) != ERR_OK) {
|
||
goto out;
|
||
}
|
||
} else if (model == VC_UPGRD_RESET_TO_POWERUP) {
|
||
if (iot_gpio_value_set(g_upgrade->gpio_boot0, 0) != ERR_OK) {
|
||
goto out;
|
||
}
|
||
if (g_upgrade->stm32->is_connect) {
|
||
g_upgrade->stm32->is_connect = 0;
|
||
}
|
||
}
|
||
|
||
result = ERR_OK;
|
||
out:
|
||
return result;
|
||
}
|
||
|
||
static uint32_t vc_upgrade_stm32_reset(void)
|
||
{
|
||
uint32_t result = ERR_FAIL;
|
||
|
||
if (!g_upgrade) {
|
||
goto out;
|
||
}
|
||
|
||
if (iot_gpio_value_set(g_upgrade->gpio_reset, 0) != ERR_OK) {
|
||
goto out;
|
||
}
|
||
/* keep low level, reset stm32 */
|
||
os_delay(3);
|
||
if (iot_gpio_value_set(g_upgrade->gpio_reset, 1) != ERR_OK) {
|
||
goto out;
|
||
}
|
||
|
||
result = ERR_OK;
|
||
out:
|
||
return result;
|
||
}
|
||
|
||
uint32_t vc_upgrd_ext_chip_reset(uint8_t flag)
|
||
{
|
||
uint32_t result = ERR_OK;
|
||
uint8_t reason = 0;
|
||
|
||
if (flag >= VC_UPGRD_RESET_MAX) {
|
||
result = ERR_INVAL;
|
||
reason = 1;
|
||
goto out;
|
||
}
|
||
|
||
if (!g_upgrade) {
|
||
reason = 2;
|
||
goto out;
|
||
}
|
||
|
||
if (vc_upgrade_stm32_boot_model_select(flag) != ERR_OK) {
|
||
reason = 3;
|
||
result = ERR_FAIL;
|
||
goto out;
|
||
}
|
||
|
||
if (vc_upgrade_stm32_reset() != ERR_OK) {
|
||
reason = 4;
|
||
result = ERR_FAIL;
|
||
goto out;
|
||
}
|
||
|
||
out:
|
||
iot_printf("%s result:%d, reason:%d\n", __FUNCTION__, result, reason);
|
||
return result;
|
||
}
|
||
|
||
uint32_t vc_upgrd_set_start(vc_upgrd_send_func p_func)
|
||
{
|
||
uint32_t result = ERR_FAIL;
|
||
uint8_t reason = 0;
|
||
(void)reason; //eliminate compile errors
|
||
|
||
if (!g_upgrade) {
|
||
reason = 1;
|
||
goto out;
|
||
}
|
||
|
||
if (!p_func) {
|
||
result = ERR_INVAL;
|
||
reason = 2;
|
||
goto out;
|
||
}
|
||
|
||
if (g_upgrade->stm32->port->write != p_func) {
|
||
g_upgrade->stm32->port->write = p_func;
|
||
}
|
||
|
||
if (g_upgrade->buffer_r == NULL) {
|
||
g_upgrade->buffer_r = (uint8_t *)os_mem_malloc(IOT_STM32_MODULE_ID,
|
||
STM32_MAX_RX_PAYLOAD_LENGTH);
|
||
if (g_upgrade->buffer_r == NULL) {
|
||
reason = 3;
|
||
goto out;
|
||
}
|
||
}
|
||
|
||
if (g_upgrade->buffer_w == NULL) {
|
||
g_upgrade->buffer_w = (uint8_t *)os_mem_malloc(IOT_STM32_MODULE_ID,
|
||
STM32_MAX_TX_PAYLOAD_LENGTH);
|
||
if (g_upgrade->buffer_w == NULL) {
|
||
reason = 4;
|
||
goto mem_err;
|
||
}
|
||
}
|
||
|
||
g_upgrade->stm32->state = UPGRADE_SEND_INIT;
|
||
|
||
g_upgrade->flag_transf_over = 0;
|
||
/* start offset of the upd file for stm32 */
|
||
g_upgrade->offset_curr = sizeof(imgHdr);
|
||
g_upgrade->offset_header = 0;
|
||
g_upgrade->len_transf = 0;
|
||
g_upgrade->percentage = 0;
|
||
g_upgrade->status = VC_UPGRD_STATE_IDLE;
|
||
|
||
if (stm32_send_init_cmd(g_upgrade->stm32) != STM32_ERR_OK) {
|
||
reason = 5;
|
||
g_upgrade->status = VC_UPGRD_STATE_ENDUP;
|
||
goto out;
|
||
}
|
||
|
||
return ERR_OK;
|
||
|
||
mem_err:
|
||
os_mem_free(g_upgrade->buffer_r);
|
||
g_upgrade->buffer_r = NULL;
|
||
out:
|
||
iot_printf("%s result:%d reason:%d\n", __FUNCTION__, result, reason);
|
||
return result;
|
||
}
|
||
|
||
uint32_t vc_upgrd_set_stop(void)
|
||
{
|
||
uint32_t result = ERR_FAIL;
|
||
|
||
if (!g_upgrade) {
|
||
goto out;
|
||
}
|
||
|
||
result = vc_upgrade_stm32_boot_model_select(VC_UPGRD_RESET_TO_POWERUP);
|
||
if (result != ERR_OK) {
|
||
goto out;
|
||
}
|
||
|
||
if (vc_upgrade_stm32_reset() != ERR_OK) {
|
||
goto out;
|
||
}
|
||
|
||
if (g_upgrade->buffer_r != NULL) {
|
||
os_mem_free(g_upgrade->buffer_r);
|
||
g_upgrade->buffer_r = NULL;
|
||
}
|
||
|
||
if (g_upgrade->buffer_w != NULL) {
|
||
os_mem_free(g_upgrade->buffer_w);
|
||
g_upgrade->buffer_w = NULL;
|
||
}
|
||
|
||
g_upgrade->status = VC_UPGRD_STATE_ENDUP;
|
||
result = ERR_OK;
|
||
out:
|
||
stm32_dbg_printf("result:%d \n", result);
|
||
return result;
|
||
}
|
||
|
||
vc_upgrd_state_e vc_upgrd_get_state(void)
|
||
{
|
||
if (!g_upgrade) {
|
||
return VC_UPGRD_STATE_ERR;
|
||
}
|
||
|
||
return g_upgrade->status;
|
||
}
|
||
|
||
uint32_t vc_upgrd_get_percentage(void)
|
||
{
|
||
if (!g_upgrade) {
|
||
return 0;
|
||
}
|
||
|
||
return g_upgrade->percentage;
|
||
}
|
||
|
||
uint32_t vc_upgrd_get_firmware_info(vc_fw_ver_t *p_fw)
|
||
{
|
||
imgHdr hdr = {0};
|
||
|
||
if ((NULL == p_fw) || (!g_upgrade)) {
|
||
return ERR_FAIL;
|
||
}
|
||
|
||
img_header_construct(&hdr, (char*)g_upgrade->file_addr);
|
||
|
||
if ((VC_UPGRADE_FW_DEV_TYPE == iot_imghdr_get_devType(&hdr)) &&
|
||
(VC_UPGRADE_FW_GUARD == iot_imghdr_get_guard(&hdr))) {
|
||
p_fw->crc32 = iot_imghdr_get_imgCRC(&hdr);
|
||
p_fw->version = iot_imghdr_get_imgVer(&hdr);
|
||
p_fw->length = iot_imghdr_get_imgSize(&hdr);
|
||
} else {
|
||
iot_printf("[VC] get local fw info failed!!!\n");
|
||
}
|
||
|
||
return ERR_OK;
|
||
}
|
||
|
||
#else
|
||
|
||
uint32_t vc_upgrade_module_init(void)
|
||
{
|
||
return ERR_OK;
|
||
}
|
||
|
||
void vc_upgrade_modele_deinit(void)
|
||
{
|
||
return;
|
||
}
|
||
|
||
uint32_t vc_upgrd_ext_chip_reset(uint8_t flag)
|
||
{
|
||
(void)flag;
|
||
return ERR_OK;
|
||
}
|
||
|
||
uint32_t vc_upgrd_set_start(vc_upgrd_send_func p_func)
|
||
{
|
||
(void)p_func;
|
||
return ERR_OK;
|
||
}
|
||
|
||
uint32_t vc_upgrd_set_stop(void)
|
||
{
|
||
return ERR_OK;
|
||
}
|
||
|
||
vc_upgrd_state_e vc_upgrd_get_state(void)
|
||
{
|
||
return VC_UPGRD_STATE_IDLE;
|
||
}
|
||
|
||
uint32_t vc_upgrd_get_percentage(void)
|
||
{
|
||
return ERR_OK;
|
||
}
|
||
|
||
uint32_t vc_upgrd_receive_func(uint8_t *p_buf, uint32_t len)
|
||
{
|
||
(void)p_buf;
|
||
(void)len;
|
||
return ERR_OK;
|
||
}
|
||
|
||
uint32_t vc_upgrd_get_firmware_info(vc_fw_ver_t *p_fw)
|
||
{
|
||
if (NULL == p_fw) {
|
||
return ERR_FAIL;
|
||
}
|
||
|
||
p_fw->crc32 = 0;
|
||
p_fw->length = 0;
|
||
p_fw->version = 0;
|
||
|
||
return ERR_OK;
|
||
}
|
||
|
||
#endif
|
||
|