405 iap 工程结构调试

Signed-off-by: a1012112796 <1012112796@qq.com>
This commit is contained in:
2024-07-24 16:22:31 +08:00
parent b1d8ce2643
commit c1bcad0c50
8 changed files with 378 additions and 195 deletions

402
iap/iap.c
View File

@@ -1,13 +1,46 @@
#include "rtthread.h"
#include "ipc/completion.h"
#include "ymodem.h"
#include <stdint.h>
#include <stddef.h>
#include "fal.h"
#define IAP_FLASH_APP_SEC "app"
#define IAP_FLASH_BOOT_SEC "boot"
static rt_device_t console_dev;
struct rt_completion _wait;
#define IFLASH_PAGE_SIZE (128 * 1024)
// #define IAP_DBG
#include "rthw.h"
#ifdef IAP_DBG
char iap_dbg_log[4096] = "";
int iap_dbg_index = 0;
#endif
void iap_dbg(const char *fmt, ...)
{
#ifdef IAP_DBG
va_list args;
rt_base_t level = rt_hw_interrupt_disable();
va_start(args, fmt);
iap_dbg_index += rt_vsnprintf(&iap_dbg_log[iap_dbg_index], sizeof(iap_dbg_log) - iap_dbg_index, fmt, args);
va_end(args);
rt_hw_interrupt_enable(level);
#endif
}
static struct rt_completion _wait;
rt_err_t port_rx_ind(rt_device_t dev, rt_size_t size)
{
rt_completion_done(&_wait);
return RT_EOK;
}
#define IS_AF(c) ((c >= 'A') && (c <= 'F'))
#define IS_af(c) ((c >= 'a') && (c <= 'f'))
@@ -109,64 +142,122 @@ rt_inline rt_uint32_t Str2Int(uint8_t *inputstr, int32_t *intnum)
return res;
}
rt_err_t port_rx_ind(rt_device_t dev, rt_size_t size)
static const char *port_list[] = {
"uart1",
"uart2",
};
#define PORTS_NUM (sizeof(port_list)/sizeof(port_list[0]))
void rt_hw_shell_relink(const char *name, rt_uint32_t baud)
{
rt_completion_done(&_wait);
return RT_EOK;
struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
config.baud_rate = baud;
rt_device_t dev = rt_device_find(name);
RT_ASSERT(dev);
rt_device_control(dev, RT_DEVICE_CTRL_CONFIG, &config);
rt_console_set_device(name);
rt_thread_t tid = rt_thread_find(FINSH_THREAD_NAME);
if (tid)
{
rt_thread_resume(tid);
rt_schedule();
}
}
static rt_device_t _read_ports(rt_device_t ports[], rt_uint8_t want)
{
rt_uint8_t tmp;
for (int i = 0; i < PORTS_NUM; i++)
{
if (ports[i] == RT_NULL)
continue;
if (rt_device_read(ports[i], 0, &tmp, 1) != 1)
continue;
if (tmp == want)
return ports[i];
}
return RT_NULL;
}
static void _init_all_ports(rt_device_t ports[])
{
struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
config.baud_rate = BAUD_RATE_460800;
for (int i = 0; i < PORTS_NUM; i++)
{
ports[i] = rt_device_find(port_list[i]);
if (ports[i] == RT_NULL)
continue;
rt_enter_critical();
ports[i]->rx_indicate = port_rx_ind;
rt_exit_critical();
rt_device_control(ports[i], RT_DEVICE_CTRL_CONFIG, &config);
rt_device_open(ports[i], RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX);
}
}
static void _close_other_ports(rt_device_t ports[], rt_device_t console_dev)
{
for (int i = 0; i < PORTS_NUM; i++)
{
if (ports[i] == RT_NULL)
continue;
if (ports[i] == console_dev)
continue;
rt_device_close(ports[i]);
ports[i] = RT_NULL;
}
}
static void _print_ports(rt_device_t ports[], const char *fmt, ...)
{
va_list args;
char line_buf[128] = { 0 };
rt_size_t real;
va_start(args, fmt);
real = rt_vsnprintf(line_buf, sizeof(line_buf), fmt, args);
va_end(args);
for (int i = 0; i < PORTS_NUM; i++)
{
if (ports[i] == RT_NULL)
continue;
rt_device_write(ports[i], 0, line_buf, real);
}
}
static const char version_header[] = {0xB5,0x5B,0xff,'\0'};
static const char Firmware_Version[] = "\r\nXY_F405_IAP_460800_FV2.0_R20240724";
static const char version_end[] = {0xBB,'\0'};
static void iap_show_version_string(rt_device_t ports[])
{
char iap_version[100]= {'\0'};
strcat(iap_version,version_header);
strcat(iap_version,Firmware_Version);
strcat(iap_version,version_end);
iap_version[2] = strlen(iap_version);
_print_ports(ports, "%s\n", iap_version);
}
#define RT_BUF_SIZE (1024)
/*
* 固件格式:
*
* 作用 & 说明
* - 记录固件对应硬件 & 版本信息
* - 简便起见,不包含校验信息
* - 允许 iap 升级不含 header 的普通固件
*
* index len desc
* 0 4 'XYFC'
* 4 4 固件信息长度
* 8 N 固件信息 ('类型'-'版本')
* 8+N M 固件数据
*/
static const char FIXED_HEAD[] = {'X', 'Y', 'F', 'C'};
extern const char IAP_BIN_PREFIX[];
static int _check_head(const rt_uint8_t *buf, rt_size_t len)
{
if (len < 8)
{
return 0;
}
for (int i = 0; i < sizeof(FIXED_HEAD); i++)
{
if (FIXED_HEAD[i] != buf[i])
{
return 0;
}
}
rt_uint32_t real = *((const rt_uint32_t *)&buf[4]);
rt_uint32_t want = rt_strlen(IAP_BIN_PREFIX);
if (real <= want || len - 8 < real)
{
return -3;
}
for(int i = 0; i < want; i++)
{
if (IAP_BIN_PREFIX[i] != buf[8 + i])
{
return -4;
}
}
return real + 8;
}
struct custom_ctx {
struct rym_ctx parent;
int32_t file_size;
@@ -181,8 +272,6 @@ static enum rym_code _rym_recv_begin(
rt_uint8_t *buf,
rt_size_t len)
{
// return RYM_ERR_ACK;
// return RYM_CODE_CAN;
struct custom_ctx *cctx = (struct custom_ctx *) ctx;
RT_ASSERT(cctx);
@@ -234,15 +323,8 @@ static enum rym_code _rym_recv_data(
RT_ASSERT(cctx);
RT_ASSERT(len <= RT_BUF_SIZE);
int offset = 0;
if (cctx->recevied_head == 0)
{
offset = _check_head(buf, len);
if (offset < 0)
{
return RYM_ERR_FILE;
}
if (fal_partition_erase(cctx->flash, 0, cctx->file_size) < 0)
{
return RYM_CODE_CAN;
@@ -261,22 +343,22 @@ static enum rym_code _rym_recv_data(
len = cctx->file_size - cctx->w_index;
}
if (fal_partition_write(cctx->flash, cctx->w_index, &buf[offset], len - offset) <= 0)
if (fal_partition_write(cctx->flash, cctx->w_index, buf, len) <= 0)
{
return RYM_CODE_CAN;
}
if (fal_partition_read(cctx->flash, cctx->w_index, cctx->ck_buffer, len - offset) <= 0)
if (fal_partition_read(cctx->flash, cctx->w_index, cctx->ck_buffer, len) <= 0)
{
return RYM_CODE_CAN;
}
for (int i = 0; i < len - offset; i++)
for (int i = 0; i < len; i++)
{
if (cctx->ck_buffer[i] != buf[i + offset])
if (cctx->ck_buffer[i] != buf[i])
return RYM_CODE_CAN;
}
cctx->w_index += len - offset;
cctx->w_index += len;
return RYM_CODE_ACK;
}
@@ -321,26 +403,20 @@ static const rt_uint8_t *_pack_cmd(enum iap_v5_cmd cmd)
#define _response_cmd(cmd) \
rt_device_write(console_dev, 0, _pack_cmd(cmd), IAP_V5_CMD_SIZE)
static rt_bool_t iap_v5_req_char(rt_device_t console_dev,
static rt_device_t iap_v5_req_char(rt_device_t ports[],
struct rt_completion *_wait,
rt_uint8_t want,
rt_tick_t wait)
{
rt_uint8_t ch;
rt_tick_t start = rt_tick_get();
rt_bool_t rt = RT_FALSE;
rt_device_t get = RT_NULL;
while (rt_tick_get() - start < wait)
{
if (rt_device_read(console_dev, 0, &ch, 1) == 1)
get = _read_ports(ports, want);
if (get != RT_NULL)
{
if (ch == want)
{
rt = RT_TRUE;
break;
}
continue;
break;
}
if (rt_completion_wait(_wait, wait - (rt_tick_get() - start))
@@ -350,7 +426,7 @@ static rt_bool_t iap_v5_req_char(rt_device_t console_dev,
}
}
return rt;
return get;
}
static void jump_to_app(void);
@@ -362,9 +438,57 @@ int iap_main_entry(void)
{
return _iap_entry(RT_TRUE);
}
// INIT_APP_EXPORT(iap_main_entry);
#include "shell.h"
static void _jump_to_app_entry(void *p)
{
rt_thread_delay(500);
rt_kprintf("jump to app ...\n");
jump_to_app();
}
void _on_iap_end(rt_device_t console_dev)
{
rt_device_close(console_dev);
rt_hw_shell_relink(console_dev->parent.name, BAUD_RATE_460800);
}
static rt_bool_t _handle_connect(rt_device_t console_dev, rt_tick_t timeout)
{
rt_int32_t cnt_c = 0;
rt_uint8_t tmp;
rt_tick_t start = rt_tick_get();
while (rt_tick_get() - start < timeout)
{
if (rt_device_read(console_dev, 0, &tmp, 1) != 1)
{
if (rt_completion_wait(&_wait, timeout - (rt_tick_get() - start)) != RT_EOK)
break;
continue;
}
if (tmp == '1')
{
_response_cmd(IAP_V5_CMD_ONE_REPLY);
continue;
}
if (tmp == 'c')
{
cnt_c ++;
_response_cmd(IAP_V5_CMD_C_REPLY);
break;
}
}
return cnt_c > 0;
}
static int _iap_entry(rt_bool_t is_boot)
{
if (IapAppAddr && is_boot)
@@ -372,42 +496,50 @@ static int _iap_entry(rt_bool_t is_boot)
return 0;
}
if ((!IapAppAddr) && is_boot)
{
finsh_set_prompt("msh (IAP)");
}
rt_err_t (*odev_rx_ind)(rt_device_t dev, rt_size_t size);
rt_device_t _ports[PORTS_NUM] = {0};
rt_err_t err = RT_EOK;
struct custom_ctx *ctx = RT_NULL;
console_dev = rt_console_get_device();
rt_device_t console_dev = rt_console_get_device();
RT_ASSERT(console_dev);
rt_completion_init(&_wait);
odev_rx_ind = console_dev->rx_indicate;
rt_device_set_rx_indicate(console_dev, port_rx_ind);
if (!iap_v5_req_char(console_dev, &_wait, '1', is_boot? 1000: 100000))
// 使用特殊设备暂时替代 console 口, 避免逻辑出错
rt_hw_shell_relink("block_r", BAUD_RATE_460800);
rt_thread_delay(200);
_init_all_ports(_ports);
iap_show_version_string(_ports);
rt_device_t get_port = iap_v5_req_char(_ports, &_wait, '1', is_boot? 1000: 100000);
if (get_port == RT_NULL)
{
_close_other_ports(_ports, console_dev);
goto _exit;
}
if (get_port != console_dev)
{
console_dev = get_port;
}
_close_other_ports(_ports, console_dev);
_response_cmd(IAP_V5_CMD_ONE_REPLY);
rt_thread_mdelay(200);
// if (!iap_v5_req_char(console_dev, &_wait, 'c', 1000))
// {
// err = RT_ENOSYS;
// goto _exit;
// }
_response_cmd(IAP_V5_CMD_C_REPLY);
if (!_handle_connect(console_dev, 1000))
{
err = RT_ERROR;
iap_dbg("_handle_connect failed\n");
goto _exit;
}
ctx = rt_calloc(1, sizeof(*ctx));
if (!ctx)
{
err = RT_ENOMEM;
rt_kprintf("rt_malloc failed\n");
iap_dbg("rt_malloc failed\n");
goto _exit;
}
ctx->parent.v5_iap_adapt = RT_TRUE;
@@ -416,7 +548,7 @@ static int _iap_entry(rt_bool_t is_boot)
if (ctx->flash == RT_NULL)
{
err = RT_ENOSYS;
rt_kprintf("fal_partition_find %s failed: %d\n", IapAppAddr? IAP_FLASH_BOOT_SEC: IAP_FLASH_APP_SEC, rt_get_errno());
iap_dbg("fal_partition_find %s failed: %d\n", IapAppAddr? IAP_FLASH_BOOT_SEC: IAP_FLASH_APP_SEC, rt_get_errno());
rt_free(ctx);
goto _exit;
}
@@ -430,25 +562,25 @@ static int _iap_entry(rt_bool_t is_boot)
if (err == RT_EOK)
{
_response_cmd(IAP_V5_CMD_UPDATE_SUCCEED);
_on_iap_end(console_dev);
return 0;
}
_exit:
if (err == RT_EOK && is_boot)
{
rt_kprintf("jump to app ...\n");
jump_to_app();
rt_thread_startup(rt_thread_create("iap_boot", _jump_to_app_entry, RT_NULL, 2048, 10, 10));
_on_iap_end(console_dev);
return 0;
}
_response_cmd(IAP_V5_CMD_UPDATE_FAILED);
_response_cmd(IAP_V5_CMD_POWER_ON_AGAIN);
rt_device_set_rx_indicate(console_dev, odev_rx_ind);
_on_iap_end(console_dev);
return 0;
}
#include <stm32f4xx.h>
#include <stdint.h>
#define FLASH_RUN_BASEADDR 0x08020000
@@ -458,13 +590,13 @@ typedef void (*pFunction)(void);
static pFunction JumpToApplication;
static uint32_t JumpAddress;
static void jump_to_app(void)
void jump_to_app(void)
{
SysTick->CTRL = 0; //关键代码
SysTick->CTRL = 0; //关键代码
HAL_DeInit(); //可选
HAL_NVIC_DisableIRQ(SysTick_IRQn); //可选
HAL_NVIC_ClearPendingIRQ(SysTick_IRQn); //可选
HAL_DeInit();
HAL_NVIC_DisableIRQ(SysTick_IRQn);
HAL_NVIC_ClearPendingIRQ(SysTick_IRQn);
/* Jump to user application */
__disable_irq();
@@ -475,6 +607,10 @@ static void jump_to_app(void)
/* Initialize user application's Stack Pointer */
__set_MSP(*(__IO uint32_t*) FLASH_RUN_BASEADDR);
__set_CONTROL(0);
__enable_irq();
JumpToApplication();
}
MSH_CMD_EXPORT(jump_to_app, jump_to_app);
@@ -484,3 +620,49 @@ static void _cmd_iap(void)
_iap_entry(RT_FALSE);
}
MSH_CMD_EXPORT_ALIAS(_cmd_iap, iap, iap bootloader / app start);
static void shell_relink(int argc, char **argv)
{
if (argc < 2)
{
rt_kprintf("%s prt_name\n", argv[0]);
return;
}
rt_hw_shell_relink(argv[1], BAUD_RATE_460800);
}
MSH_CMD_EXPORT(shell_relink, relink msh to other port);
#ifdef IAP_DBG
void iap_log()
{
int index = 0;
for (int i = 0; i < iap_dbg_index; i++)
{
if (iap_dbg_log[i] == '\n' || iap_dbg_log[i] == '\0')
{
iap_dbg_log[i] = '\0';
rt_kprintf("log: %s\n", &iap_dbg_log[index]);
index = i+1;
}
}
}
MSH_CMD_EXPORT(iap_log, iap log);
#endif
static struct rt_device blocked_reader_ = {0};
static rt_size_t _blocked_reader_read (rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
{
return 0;
}
int init_block_reader()
{
blocked_reader_.read = _blocked_reader_read;
rt_device_register(&blocked_reader_, "block_r", RT_DEVICE_FLAG_RDWR);
return 0;
}
INIT_BOARD_EXPORT(init_block_reader);