2022-11-08 13:44:31 +08:00
|
|
|
|
#include "rtthread.h"
|
|
|
|
|
#include "ipc/completion.h"
|
|
|
|
|
#include "ymodem.h"
|
2024-07-24 16:22:31 +08:00
|
|
|
|
#include <stdint.h>
|
|
|
|
|
#include <stddef.h>
|
2022-11-08 13:44:31 +08:00
|
|
|
|
|
|
|
|
|
#include "fal.h"
|
2022-12-26 14:47:07 +08:00
|
|
|
|
#define IAP_FLASH_APP_SEC "app"
|
|
|
|
|
#define IAP_FLASH_BOOT_SEC "boot"
|
2022-11-08 13:44:31 +08:00
|
|
|
|
|
2024-07-24 16:22:31 +08:00
|
|
|
|
#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;
|
|
|
|
|
}
|
2022-11-08 13:44:31 +08:00
|
|
|
|
|
|
|
|
|
#define IS_AF(c) ((c >= 'A') && (c <= 'F'))
|
|
|
|
|
#define IS_af(c) ((c >= 'a') && (c <= 'f'))
|
|
|
|
|
#define IS_09(c) ((c >= '0') && (c <= '9'))
|
|
|
|
|
#define ISVALIDHEX(c) IS_AF(c) || IS_af(c) || IS_09(c)
|
|
|
|
|
#define ISVALIDDEC(c) IS_09(c)
|
|
|
|
|
#define CONVERTDEC(c) (c - '0')
|
|
|
|
|
|
|
|
|
|
#define CONVERTHEX_alpha(c) (IS_AF(c) ? (c - 'A'+10) : (c - 'a'+10))
|
|
|
|
|
#define CONVERTHEX(c) (IS_09(c) ? (c - '0') : CONVERTHEX_alpha(c))
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Convert a string to an integer
|
|
|
|
|
* @param inputstr: The string to be converted
|
|
|
|
|
* @param intnum: The intger value
|
|
|
|
|
* @retval 1: Correct
|
|
|
|
|
* 0: Error
|
|
|
|
|
*/
|
|
|
|
|
rt_inline rt_uint32_t Str2Int(uint8_t *inputstr, int32_t *intnum)
|
|
|
|
|
{
|
|
|
|
|
rt_uint32_t i = 0, res = 0;
|
|
|
|
|
rt_uint32_t val = 0;
|
|
|
|
|
|
|
|
|
|
if (inputstr[0] == '0' && (inputstr[1] == 'x' || inputstr[1] == 'X'))
|
|
|
|
|
{
|
|
|
|
|
if (inputstr[2] == '\0')
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
for (i = 2; i < 11; i++)
|
|
|
|
|
{
|
|
|
|
|
if (inputstr[i] == '\0')
|
|
|
|
|
{
|
|
|
|
|
*intnum = val;
|
|
|
|
|
/* return 1; */
|
|
|
|
|
res = 1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (ISVALIDHEX(inputstr[i]))
|
|
|
|
|
{
|
|
|
|
|
val = (val << 4) + CONVERTHEX(inputstr[i]);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* return 0, Invalid input */
|
|
|
|
|
res = 0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/* over 8 digit hex --invalid */
|
|
|
|
|
if (i >= 11)
|
|
|
|
|
{
|
|
|
|
|
res = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else /* max 10-digit decimal input */
|
|
|
|
|
{
|
|
|
|
|
for (i = 0;i < 11;i++)
|
|
|
|
|
{
|
|
|
|
|
if (inputstr[i] == '\0')
|
|
|
|
|
{
|
|
|
|
|
*intnum = val;
|
|
|
|
|
/* return 1 */
|
|
|
|
|
res = 1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
else if ((inputstr[i] == 'k' || inputstr[i] == 'K') && (i > 0))
|
|
|
|
|
{
|
|
|
|
|
val = val << 10;
|
|
|
|
|
*intnum = val;
|
|
|
|
|
res = 1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
else if ((inputstr[i] == 'm' || inputstr[i] == 'M') && (i > 0))
|
|
|
|
|
{
|
|
|
|
|
val = val << 20;
|
|
|
|
|
*intnum = val;
|
|
|
|
|
res = 1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
else if (ISVALIDDEC(inputstr[i]))
|
|
|
|
|
{
|
|
|
|
|
val = val * 10 + CONVERTDEC(inputstr[i]);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* return 0, Invalid input */
|
|
|
|
|
res = 0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/* Over 10 digit decimal --invalid */
|
|
|
|
|
if (i >= 11)
|
|
|
|
|
{
|
|
|
|
|
res = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-24 16:22:31 +08:00
|
|
|
|
static const char *port_list[] = {
|
|
|
|
|
"uart1",
|
|
|
|
|
"uart2",
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#define PORTS_NUM (sizeof(port_list)/sizeof(port_list[0]))
|
|
|
|
|
|
2024-07-26 09:03:23 +08:00
|
|
|
|
void rt_hw_shell_relink(const char *name, rt_uint32_t baud);
|
2023-01-03 13:16:29 +08:00
|
|
|
|
|
2024-07-24 16:22:31 +08:00
|
|
|
|
static rt_device_t _read_ports(rt_device_t ports[], rt_uint8_t want)
|
2023-01-03 13:16:29 +08:00
|
|
|
|
{
|
2024-07-24 16:22:31 +08:00
|
|
|
|
rt_uint8_t tmp;
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < PORTS_NUM; i++)
|
2023-01-03 13:16:29 +08:00
|
|
|
|
{
|
2024-07-24 16:22:31 +08:00
|
|
|
|
if (ports[i] == RT_NULL)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (rt_device_read(ports[i], 0, &tmp, 1) != 1)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (tmp == want)
|
|
|
|
|
return ports[i];
|
2023-01-03 13:16:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
2024-07-24 16:22:31 +08:00
|
|
|
|
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++)
|
2023-01-03 13:16:29 +08:00
|
|
|
|
{
|
2024-07-24 16:22:31 +08:00
|
|
|
|
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);
|
2023-01-03 13:16:29 +08:00
|
|
|
|
}
|
2024-07-24 16:22:31 +08:00
|
|
|
|
}
|
2023-01-03 13:16:29 +08:00
|
|
|
|
|
2024-07-24 16:22:31 +08:00
|
|
|
|
static void _close_other_ports(rt_device_t ports[], rt_device_t console_dev)
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; i < PORTS_NUM; i++)
|
2023-01-03 13:16:29 +08:00
|
|
|
|
{
|
2024-07-24 16:22:31 +08:00
|
|
|
|
if (ports[i] == RT_NULL)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (ports[i] == console_dev)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
rt_device_close(ports[i]);
|
|
|
|
|
ports[i] = RT_NULL;
|
2023-01-03 13:16:29 +08:00
|
|
|
|
}
|
2024-07-24 16:22:31 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void _print_ports(rt_device_t ports[], const char *fmt, ...)
|
|
|
|
|
{
|
|
|
|
|
va_list args;
|
|
|
|
|
char line_buf[128] = { 0 };
|
|
|
|
|
rt_size_t real;
|
2023-01-03 13:16:29 +08:00
|
|
|
|
|
2024-07-24 16:22:31 +08:00
|
|
|
|
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++)
|
2023-01-03 13:16:29 +08:00
|
|
|
|
{
|
2024-07-24 16:22:31 +08:00
|
|
|
|
if (ports[i] == RT_NULL)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
rt_device_write(ports[i], 0, line_buf, real);
|
2023-01-03 13:16:29 +08:00
|
|
|
|
}
|
2024-07-24 16:22:31 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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'};
|
2023-01-03 13:16:29 +08:00
|
|
|
|
|
2024-07-24 16:22:31 +08:00
|
|
|
|
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);
|
2023-01-03 13:16:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
2024-07-24 16:22:31 +08:00
|
|
|
|
#define RT_BUF_SIZE (1024)
|
|
|
|
|
|
2022-11-08 13:44:31 +08:00
|
|
|
|
struct custom_ctx {
|
|
|
|
|
struct rym_ctx parent;
|
|
|
|
|
int32_t file_size;
|
|
|
|
|
int32_t w_index;
|
2023-01-03 13:16:29 +08:00
|
|
|
|
int32_t recevied_head;
|
2022-11-08 13:44:31 +08:00
|
|
|
|
const struct fal_partition *flash;
|
|
|
|
|
rt_uint8_t ck_buffer[RT_BUF_SIZE];
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static enum rym_code _rym_recv_begin(
|
|
|
|
|
struct rym_ctx *ctx,
|
|
|
|
|
rt_uint8_t *buf,
|
|
|
|
|
rt_size_t len)
|
|
|
|
|
{
|
|
|
|
|
struct custom_ctx *cctx = (struct custom_ctx *) ctx;
|
|
|
|
|
RT_ASSERT(cctx);
|
|
|
|
|
|
|
|
|
|
rt_uint8_t tmp_size[16] = {0};
|
|
|
|
|
while (*buf != 0)
|
|
|
|
|
{
|
|
|
|
|
buf ++;
|
|
|
|
|
}
|
|
|
|
|
buf ++;
|
|
|
|
|
|
|
|
|
|
rt_bool_t end = RT_FALSE;
|
|
|
|
|
for (rt_uint8_t i = 0; i < 16; i++)
|
|
|
|
|
{
|
|
|
|
|
if (*buf == 0)
|
|
|
|
|
{
|
|
|
|
|
tmp_size[i] = 0;
|
|
|
|
|
end = RT_TRUE;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tmp_size[i] = *buf++;
|
|
|
|
|
}
|
|
|
|
|
if (!end)
|
|
|
|
|
{
|
|
|
|
|
return RYM_CODE_CAN;
|
|
|
|
|
}
|
|
|
|
|
if (!Str2Int(tmp_size, &cctx->file_size))
|
|
|
|
|
{
|
|
|
|
|
return RYM_CODE_CAN;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (cctx->file_size >= cctx->flash->len)
|
|
|
|
|
{
|
|
|
|
|
return RYM_CODE_CAN;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cctx->w_index = 0;
|
2023-01-03 13:16:29 +08:00
|
|
|
|
cctx->recevied_head = 0;
|
2022-11-08 13:44:31 +08:00
|
|
|
|
|
|
|
|
|
return RYM_CODE_ACK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static enum rym_code _rym_recv_data(
|
|
|
|
|
struct rym_ctx *ctx,
|
|
|
|
|
rt_uint8_t *buf,
|
|
|
|
|
rt_size_t len)
|
|
|
|
|
{
|
|
|
|
|
struct custom_ctx *cctx = (struct custom_ctx *) ctx;
|
|
|
|
|
RT_ASSERT(cctx);
|
|
|
|
|
RT_ASSERT(len <= RT_BUF_SIZE);
|
|
|
|
|
|
2023-01-03 13:16:29 +08:00
|
|
|
|
if (cctx->recevied_head == 0)
|
|
|
|
|
{
|
|
|
|
|
if (fal_partition_erase(cctx->flash, 0, cctx->file_size) < 0)
|
|
|
|
|
{
|
|
|
|
|
return RYM_CODE_CAN;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cctx->recevied_head = 1;
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-24 09:35:53 +08:00
|
|
|
|
if (cctx->w_index >= cctx->file_size)
|
2022-11-08 13:44:31 +08:00
|
|
|
|
{
|
|
|
|
|
return RYM_CODE_ACK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (cctx->w_index + len > cctx->file_size)
|
|
|
|
|
{
|
|
|
|
|
len = cctx->file_size - cctx->w_index;
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-24 16:22:31 +08:00
|
|
|
|
if (fal_partition_write(cctx->flash, cctx->w_index, buf, len) <= 0)
|
2022-11-08 13:44:31 +08:00
|
|
|
|
{
|
|
|
|
|
return RYM_CODE_CAN;
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-24 16:22:31 +08:00
|
|
|
|
if (fal_partition_read(cctx->flash, cctx->w_index, cctx->ck_buffer, len) <= 0)
|
2022-11-08 13:44:31 +08:00
|
|
|
|
{
|
|
|
|
|
return RYM_CODE_CAN;
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-24 16:22:31 +08:00
|
|
|
|
for (int i = 0; i < len; i++)
|
2022-11-08 13:44:31 +08:00
|
|
|
|
{
|
2024-07-24 16:22:31 +08:00
|
|
|
|
if (cctx->ck_buffer[i] != buf[i])
|
2022-11-08 13:44:31 +08:00
|
|
|
|
return RYM_CODE_CAN;
|
|
|
|
|
}
|
2024-07-24 16:22:31 +08:00
|
|
|
|
cctx->w_index += len;
|
2022-11-08 13:44:31 +08:00
|
|
|
|
|
|
|
|
|
return RYM_CODE_ACK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static enum rym_code _rym_recv_end(
|
|
|
|
|
struct rym_ctx *ctx,
|
|
|
|
|
rt_uint8_t *buf,
|
|
|
|
|
rt_size_t len)
|
|
|
|
|
{
|
|
|
|
|
return RYM_CODE_ACK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
enum iap_v5_cmd
|
|
|
|
|
{
|
|
|
|
|
IAP_V5_CMD_ONE_REPLY = 1,
|
|
|
|
|
IAP_V5_CMD_C_REPLY,
|
|
|
|
|
IAP_V5_CMD_UPDATE_SUCCEED,
|
|
|
|
|
IAP_V5_CMD_UPDATE_FAILED,
|
|
|
|
|
IAP_V5_CMD_BIN_OVERSIZE,
|
|
|
|
|
IAP_V5_CMD_CHECK_FAILED,
|
|
|
|
|
IAP_V5_CMD_USER_CANCEL,
|
|
|
|
|
IAP_V5_CMD_RECEIVE_FAILED,
|
|
|
|
|
IAP_V5_CMD_POWER_ON_AGAIN,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief 响应协议
|
|
|
|
|
*
|
|
|
|
|
* 0xB5,0x5B,{cmd},0xBB, 0x00
|
|
|
|
|
*/
|
|
|
|
|
#define IAP_V5_CMD_SIZE (5)
|
|
|
|
|
|
|
|
|
|
static const rt_uint8_t *_pack_cmd(enum iap_v5_cmd cmd)
|
|
|
|
|
{
|
|
|
|
|
static rt_uint8_t _cmd_line[IAP_V5_CMD_SIZE]
|
|
|
|
|
= { 0xB5, 0x5B, 0x00, 0xBB, 0x00 };
|
|
|
|
|
|
|
|
|
|
_cmd_line[2] = cmd;
|
|
|
|
|
return _cmd_line;
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-17 17:29:41 +08:00
|
|
|
|
#define _response_cmd(cmd) \
|
2022-11-08 13:44:31 +08:00
|
|
|
|
rt_device_write(console_dev, 0, _pack_cmd(cmd), IAP_V5_CMD_SIZE)
|
|
|
|
|
|
2024-07-24 16:22:31 +08:00
|
|
|
|
static rt_device_t iap_v5_req_char(rt_device_t ports[],
|
2023-04-17 17:29:41 +08:00
|
|
|
|
struct rt_completion *_wait,
|
|
|
|
|
rt_uint8_t want,
|
|
|
|
|
rt_tick_t wait)
|
2022-12-24 09:35:53 +08:00
|
|
|
|
{
|
2023-04-17 17:29:41 +08:00
|
|
|
|
rt_tick_t start = rt_tick_get();
|
2024-07-24 16:22:31 +08:00
|
|
|
|
rt_device_t get = RT_NULL;
|
2023-04-17 17:29:41 +08:00
|
|
|
|
|
|
|
|
|
while (rt_tick_get() - start < wait)
|
2022-11-08 13:44:31 +08:00
|
|
|
|
{
|
2024-07-24 16:22:31 +08:00
|
|
|
|
get = _read_ports(ports, want);
|
|
|
|
|
if (get != RT_NULL)
|
2022-11-08 13:44:31 +08:00
|
|
|
|
{
|
2024-07-24 16:22:31 +08:00
|
|
|
|
break;
|
2022-11-08 13:44:31 +08:00
|
|
|
|
}
|
|
|
|
|
|
2023-04-17 17:29:41 +08:00
|
|
|
|
if (rt_completion_wait(_wait, wait - (rt_tick_get() - start))
|
|
|
|
|
!= RT_EOK)
|
2022-12-26 14:47:07 +08:00
|
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
2022-12-24 09:35:53 +08:00
|
|
|
|
}
|
2023-04-17 17:29:41 +08:00
|
|
|
|
|
2024-07-24 16:22:31 +08:00
|
|
|
|
return get;
|
2022-12-24 09:35:53 +08:00
|
|
|
|
}
|
2022-11-08 13:44:31 +08:00
|
|
|
|
|
2023-04-17 17:29:41 +08:00
|
|
|
|
static void jump_to_app(void);
|
|
|
|
|
extern const uint32_t IapAppAddr;
|
|
|
|
|
|
2022-12-26 14:47:07 +08:00
|
|
|
|
static int _iap_entry(rt_bool_t is_boot);
|
|
|
|
|
|
2022-11-08 13:44:31 +08:00
|
|
|
|
int iap_main_entry(void)
|
|
|
|
|
{
|
2022-12-26 14:47:07 +08:00
|
|
|
|
return _iap_entry(RT_TRUE);
|
|
|
|
|
}
|
2024-07-24 16:22:31 +08:00
|
|
|
|
// INIT_APP_EXPORT(iap_main_entry);
|
2022-12-26 14:47:07 +08:00
|
|
|
|
|
2023-01-03 13:16:29 +08:00
|
|
|
|
#include "shell.h"
|
|
|
|
|
|
2024-07-24 16:22:31 +08:00
|
|
|
|
static void _jump_to_app_entry(void *p)
|
2022-12-26 14:47:07 +08:00
|
|
|
|
{
|
2024-07-24 16:22:31 +08:00
|
|
|
|
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)
|
2022-11-08 13:44:31 +08:00
|
|
|
|
{
|
2024-07-24 16:22:31 +08:00
|
|
|
|
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;
|
|
|
|
|
}
|
2022-11-08 13:44:31 +08:00
|
|
|
|
}
|
|
|
|
|
|
2024-07-24 16:22:31 +08:00
|
|
|
|
return cnt_c > 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int _iap_entry(rt_bool_t is_boot)
|
|
|
|
|
{
|
|
|
|
|
if (IapAppAddr && is_boot)
|
2023-01-03 13:16:29 +08:00
|
|
|
|
{
|
2024-07-24 16:22:31 +08:00
|
|
|
|
return 0;
|
2023-01-03 13:16:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
2024-07-24 16:22:31 +08:00
|
|
|
|
rt_device_t _ports[PORTS_NUM] = {0};
|
2022-11-08 13:44:31 +08:00
|
|
|
|
rt_err_t err = RT_EOK;
|
|
|
|
|
struct custom_ctx *ctx = RT_NULL;
|
|
|
|
|
|
2024-07-24 16:22:31 +08:00
|
|
|
|
rt_device_t console_dev = rt_console_get_device();
|
2023-04-17 17:29:41 +08:00
|
|
|
|
RT_ASSERT(console_dev);
|
2022-11-08 13:44:31 +08:00
|
|
|
|
|
|
|
|
|
rt_completion_init(&_wait);
|
|
|
|
|
|
2024-07-24 16:22:31 +08:00
|
|
|
|
// 使用特殊设备暂时替代 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)
|
2022-11-08 13:44:31 +08:00
|
|
|
|
{
|
2024-07-24 16:22:31 +08:00
|
|
|
|
_close_other_ports(_ports, console_dev);
|
2023-04-17 17:29:41 +08:00
|
|
|
|
goto _exit;
|
2022-12-24 09:35:53 +08:00
|
|
|
|
}
|
2024-07-24 16:22:31 +08:00
|
|
|
|
if (get_port != console_dev)
|
|
|
|
|
{
|
|
|
|
|
console_dev = get_port;
|
|
|
|
|
}
|
2022-12-24 09:35:53 +08:00
|
|
|
|
|
2024-07-24 16:22:31 +08:00
|
|
|
|
_close_other_ports(_ports, console_dev);
|
2022-11-08 13:44:31 +08:00
|
|
|
|
|
2024-07-24 16:22:31 +08:00
|
|
|
|
_response_cmd(IAP_V5_CMD_ONE_REPLY);
|
|
|
|
|
|
|
|
|
|
if (!_handle_connect(console_dev, 1000))
|
|
|
|
|
{
|
|
|
|
|
err = RT_ERROR;
|
|
|
|
|
iap_dbg("_handle_connect failed\n");
|
|
|
|
|
goto _exit;
|
|
|
|
|
}
|
2022-11-08 13:44:31 +08:00
|
|
|
|
|
|
|
|
|
ctx = rt_calloc(1, sizeof(*ctx));
|
|
|
|
|
if (!ctx)
|
|
|
|
|
{
|
|
|
|
|
err = RT_ENOMEM;
|
2024-07-24 16:22:31 +08:00
|
|
|
|
iap_dbg("rt_malloc failed\n");
|
2022-11-08 13:44:31 +08:00
|
|
|
|
goto _exit;
|
|
|
|
|
}
|
2023-12-08 08:42:05 +08:00
|
|
|
|
ctx->parent.v5_iap_adapt = RT_TRUE;
|
2022-11-08 13:44:31 +08:00
|
|
|
|
|
2022-12-26 14:47:07 +08:00
|
|
|
|
ctx->flash = fal_partition_find(IapAppAddr? IAP_FLASH_BOOT_SEC: IAP_FLASH_APP_SEC);
|
2022-11-08 13:44:31 +08:00
|
|
|
|
if (ctx->flash == RT_NULL)
|
|
|
|
|
{
|
|
|
|
|
err = RT_ENOSYS;
|
2024-07-24 16:22:31 +08:00
|
|
|
|
iap_dbg("fal_partition_find %s failed: %d\n", IapAppAddr? IAP_FLASH_BOOT_SEC: IAP_FLASH_APP_SEC, rt_get_errno());
|
2022-11-08 13:44:31 +08:00
|
|
|
|
rt_free(ctx);
|
|
|
|
|
goto _exit;
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-17 17:29:41 +08:00
|
|
|
|
err = rym_recv_on_device(&ctx->parent, console_dev, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
|
2022-11-08 13:44:31 +08:00
|
|
|
|
_rym_recv_begin, _rym_recv_data, _rym_recv_end, 1000);
|
|
|
|
|
rt_free(ctx);
|
|
|
|
|
|
|
|
|
|
rt_thread_mdelay(200);
|
|
|
|
|
|
|
|
|
|
if (err == RT_EOK)
|
|
|
|
|
{
|
2023-04-17 17:29:41 +08:00
|
|
|
|
_response_cmd(IAP_V5_CMD_UPDATE_SUCCEED);
|
2024-07-24 16:22:31 +08:00
|
|
|
|
_on_iap_end(console_dev);
|
2022-11-08 13:44:31 +08:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_exit:
|
2022-12-26 14:47:07 +08:00
|
|
|
|
if (err == RT_EOK && is_boot)
|
2022-11-08 13:44:31 +08:00
|
|
|
|
{
|
2024-07-24 16:22:31 +08:00
|
|
|
|
rt_thread_startup(rt_thread_create("iap_boot", _jump_to_app_entry, RT_NULL, 2048, 10, 10));
|
|
|
|
|
_on_iap_end(console_dev);
|
2022-11-08 13:44:31 +08:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-17 17:29:41 +08:00
|
|
|
|
_response_cmd(IAP_V5_CMD_UPDATE_FAILED);
|
|
|
|
|
_response_cmd(IAP_V5_CMD_POWER_ON_AGAIN);
|
2022-11-08 13:44:31 +08:00
|
|
|
|
|
2024-07-24 16:22:31 +08:00
|
|
|
|
_on_iap_end(console_dev);
|
2022-11-08 13:44:31 +08:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#include <stdint.h>
|
|
|
|
|
|
|
|
|
|
#define FLASH_RUN_BASEADDR 0x08020000
|
|
|
|
|
|
|
|
|
|
//定义函数指针,用于跳转到APP
|
|
|
|
|
typedef void (*pFunction)(void);
|
|
|
|
|
static pFunction JumpToApplication;
|
|
|
|
|
static uint32_t JumpAddress;
|
|
|
|
|
|
2024-07-24 16:22:31 +08:00
|
|
|
|
void jump_to_app(void)
|
2022-11-08 13:44:31 +08:00
|
|
|
|
{
|
2024-07-24 16:22:31 +08:00
|
|
|
|
SysTick->CTRL = 0; //关键代码
|
2022-11-08 13:44:31 +08:00
|
|
|
|
|
2024-07-24 16:22:31 +08:00
|
|
|
|
HAL_DeInit();
|
|
|
|
|
HAL_NVIC_DisableIRQ(SysTick_IRQn);
|
|
|
|
|
HAL_NVIC_ClearPendingIRQ(SysTick_IRQn);
|
2022-11-08 13:44:31 +08:00
|
|
|
|
|
|
|
|
|
/* Jump to user application */
|
|
|
|
|
__disable_irq();
|
|
|
|
|
|
|
|
|
|
JumpAddress = *(__IO uint32_t*) (FLASH_RUN_BASEADDR + 4);
|
|
|
|
|
|
|
|
|
|
JumpToApplication = (pFunction) JumpAddress;
|
|
|
|
|
/* Initialize user application's Stack Pointer */
|
|
|
|
|
__set_MSP(*(__IO uint32_t*) FLASH_RUN_BASEADDR);
|
|
|
|
|
|
2024-07-24 16:22:31 +08:00
|
|
|
|
__set_CONTROL(0);
|
|
|
|
|
|
|
|
|
|
__enable_irq();
|
|
|
|
|
|
2022-11-08 13:44:31 +08:00
|
|
|
|
JumpToApplication();
|
|
|
|
|
}
|
|
|
|
|
MSH_CMD_EXPORT(jump_to_app, jump_to_app);
|
2022-12-26 14:47:07 +08:00
|
|
|
|
|
|
|
|
|
static void _cmd_iap(void)
|
|
|
|
|
{
|
|
|
|
|
_iap_entry(RT_FALSE);
|
|
|
|
|
}
|
|
|
|
|
MSH_CMD_EXPORT_ALIAS(_cmd_iap, iap, iap bootloader / app start);
|
2024-07-24 16:22:31 +08:00
|
|
|
|
|
|
|
|
|
#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
|