使用qboot软件包制作bootloader
-
为了使bootloader尽量小,对内核及其组件进行了如下配置
线程间通信只用选择这两个:
为了方便调试,下面这项配置成这样:
组件中除了这两项其他都不选:
这个msh shell其实占用rom挺多的。我们用console打印调试信息,但是可以不用shell, shell只是一些命令集
网络组件全部不用,这些子菜单点进去,确认都没有选上!
-
配置qboot
开发板上红色灯是E7,低电平点亮,所以这里
running status led pin
设置为71,led on level
设置为0。
必须要开启片内flash
-
下载软件包并编译
运行pkgs --update
后,会自动下载qboot及其依赖包
下载完成后,在board/ports/fal
目录下,添加如下源文件(把其他文件删掉,只保留SConscript)
fal_cfg.h:
#ifndef _FAL_CFG_H_
#define _FAL_CFG_H_
#include <rtconfig.h>
#include <board.h>
#include <stdlib.h>
#define RT_APP_PART_ADDR (0x08000000 + 64 * 1024) // app partition begin address
#define NOR_FLASH_DEV_NAME FAL_USING_NOR_FLASH_DEV_NAME//"norflash0"
/* ===================== Flash device Configuration ========================= */
extern const struct fal_flash_dev stm32_onchip_flash;
//extern struct fal_flash_dev nor_flash0;
/* flash device table */
#define FAL_FLASH_DEV_TABLE \
{ \
&stm32_onchip_flash, \
/*&nor_flash0,*/ \
}
/* ====================== Partition Configuration ========================== */
#ifdef FAL_PART_HAS_TABLE_CFG
/* partition table */
#define FAL_PART_TABLE \
{ \
/*{FAL_PART_MAGIC_WORD, "bl", "onchip_flash", 0, 32*1024, 0},*/ \
{FAL_PART_MAGIC_WORD, "app", "onchip_flash", 64*1024, 128*1024, 0}, \
{FAL_PART_MAGIC_WORD, "factory", "onchip_flash", 192*1024, 128*1024, 0}, \
{FAL_PART_MAGIC_WORD, "download", "onchip_flash", 320*1024, 128*1024, 0}, \
/*{FAL_PART_MAGIC_WORD, "param", "onchip_flash", 252*1024, 4*1024, 0},*/ \
/*{FAL_PART_MAGIC_WORD, "filesys", NOR_FLASH_DEV_NAME, 0, 8*1024*1024, 0},*/ \
}
#endif /* FAL_PART_HAS_TABLE_CFG */
#endif /* _FAL_CFG_H_ */
注意RT_APP_PART_ADDR
这个宏,这是app跳转地址。这里分了64k给bootloader
drv_fal_init.c:
#include <rtthread.h>
#ifdef PKG_USING_FAL
#include <fal.h>
extern int fal_init(void);
INIT_COMPONENT_EXPORT(fal_init);
#endif
修改main.c
int main(void)
{
/* set LED0 pin mode to output */
return RT_EOK;
}
把编译优化级别设置为Os
,修改rtconfig.py文件:
运行scons编译,我这编译完了之后,有36kb。
- 运行效果
因为app区 download区 和factory区都没有固件,所以一直重启(等待时间是默认的5秒):
制作带ota升级功能的app
- 使能ymodem和fal
- board/ports/fal目录中的所有源文件内容保持和bootloader中的一样。
- app的地址偏移是64k,必须保证以下两点才能跳转成功
- 修改链接脚本
- 重新设置中断向量表地址
main.c中添加如下代码段:
/* 将中断向量表起始地址重新设置为 app 分区的起始地址 */
static int ota_app_vtor_reconfig(void)
{
#define NVIC_VTOR_MASK 0x3FFFFF80
#define RT_APP_PART_ADDR 0x08010000
/* 根据应用设置向量表 */
SCB->VTOR = RT_APP_PART_ADDR & NVIC_VTOR_MASK;
return 0;
}
INIT_BOARD_EXPORT(ota_app_vtor_reconfig);
- 为了使用ymodem传输固件,还需要在applications目录添加如下源文件
ymodem_update.c:
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-01-30 armink the first version
* 2018-08-27 Murphy update log
*/
#include <rtthread.h>
#include <stdio.h>
#include <stdbool.h>
#include <finsh.h>
#include <fal.h>
// #include <spi_flash_sfud.h>
#include <ymodem.h>
#define DBG_ENABLE
#define DBG_SECTION_NAME "ymodem"
#ifdef YMODEM_DEBUG
#define DBG_LEVEL DBG_LOG
#else
#define DBG_LEVEL DBG_INFO
#endif
#define DBG_COLOR
#include <rtdbg.h>
static size_t update_file_total_size, update_file_cur_size;
static const struct fal_partition * dl_part = RT_NULL;
static enum rym_code ymodem_on_begin(struct rym_ctx *ctx, rt_uint8_t *buf, rt_size_t len)
{
char *file_name, *file_size;
/* calculate and store file size */
file_name = (char *)&buf[0];
file_size = (char *)&buf[rt_strlen(file_name) + 1];
update_file_total_size = atol(file_size);
update_file_cur_size = 0;
/* Get download partition information and erase download partition data */
if ((dl_part = fal_partition_find("download")) == RT_NULL)
{
LOG_E("Firmware download failed! Partition (%s) find error!", "download");
return RYM_CODE_CAN;
}
if (update_file_total_size > dl_part->len)
{
LOG_E("Firmware is too large! File size (%d), '%s' partition size (%d)", update_file_total_size, "download", dl_part->len);
return RYM_CODE_CAN;
}
LOG_I("Start erase. Size (%d)", update_file_total_size);
/* erase DL section */
if (fal_partition_erase(dl_part, 0, update_file_total_size) < 0)
{
LOG_E("Firmware download failed! Partition (%s) erase error!", dl_part->name);
return RYM_CODE_CAN;
}
return RYM_CODE_ACK;
}
static enum rym_code ymodem_on_data(struct rym_ctx *ctx, rt_uint8_t *buf, rt_size_t len)
{
/* write data of application to DL partition */
if (fal_partition_write(dl_part, update_file_cur_size, buf, len) < 0)
{
LOG_E("Firmware download failed! Partition (%s) write data error!", dl_part->name);
return RYM_CODE_CAN;
}
update_file_cur_size += len;
return RYM_CODE_ACK;
}
void update(uint8_t argc, char **argv)
{
struct rym_ctx rctx;
rt_kprintf("Waring: Ymodem has started! This operator will not recovery.\n");
rt_kprintf("Please select the ota firmware file and use Ymodem to send.\n");
if (!rym_recv_on_device(&rctx, rt_console_get_device(), RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
ymodem_on_begin, ymodem_on_data, NULL, RT_TICK_PER_SECOND))
{
rt_kprintf("Download firmware to flash success.\n");
rt_kprintf("System now will restart...\r\n");
/* wait some time for terminal response finish */
rt_thread_delay(rt_tick_from_millisecond(200));
/* Reset the device, Start new firmware */
extern void rt_hw_cpu_reset(void);
rt_hw_cpu_reset();
/* wait some time for terminal response finish */
rt_thread_delay(rt_tick_from_millisecond(200));
}
else
{
/* wait some time for terminal response finish */
rt_thread_delay(RT_TICK_PER_SECOND);
rt_kprintf("Update firmware fail.\n");
}
return;
}
MSH_CMD_EXPORT_ALIAS(update, ymodem_start, Update user application firmware);
- main函数中打印标记当前版本:
int main(void)
{
/* set LED0 pin mode to output */
LOG_I("app version is v1.0\n");
rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT);
while (1)
{
rt_pin_write(LED0_PIN, PIN_HIGH);
rt_thread_mdelay(500);
rt_pin_write(LED0_PIN, PIN_LOW);
rt_thread_mdelay(500);
}
return RT_EOK;
}
编译下载到 0x08010000
后运行效果:
试试升级功能
- 修改一下main.c
int main(void)
{
/* set LED0 pin mode to output */
LOG_I("app version is v2.0\n");
rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT);
while (1)
{
rt_pin_write(LED0_PIN, PIN_HIGH);
rt_thread_mdelay(500);
rt_pin_write(LED0_PIN, PIN_LOW);
rt_thread_mdelay(500);
}
return RT_EOK;
}
- 编译完了之后 ,用固件打包器打包
- 传输新固件
- 输入
ymodem_start
- 选择.rbl文件
注意终端工具用的是xshell
传完了之后自动重启:
- 输入