前言
由于項目需要實現(xiàn)OTA功能學(xué)習(xí)了一下具體實現(xiàn)方法,以備后期查看,有問題的地方隨時指正修改
理論
1.什么是OTA
OTA是“over-the-air”的縮寫,是一種無線技術(shù),用于在不需要接觸設(shè)備的情況下向移動設(shè)備或物聯(lián)網(wǎng)設(shè)備提供更新、補(bǔ)丁或新版本的軟件。OTA更新通常通過無線網(wǎng)絡(luò)(如Wi-Fi或移動數(shù)據(jù))進(jìn)行,這使得設(shè)備可以在不需要任何物理連接的情況下獲得更新。這種技術(shù)在智能手機(jī)、智能家居設(shè)備和車載系統(tǒng)等設(shè)備中得到廣泛應(yīng)用。
2.什么是BootLoader
BOOTloader是一段特殊的程序,在計算機(jī)啟動時運行。它的主要作用是讀取和加載操作系統(tǒng)。
當(dāng)計算機(jī)啟動時,BOOTloader首先加載并啟動操作系統(tǒng)。它負(fù)責(zé)加載內(nèi)存中的系統(tǒng)映像,并初始化基本硬件設(shè)置。BOOTloader還可以提供一些選項,如選擇不同的操作系統(tǒng)版本或進(jìn)入系統(tǒng)恢復(fù)模式。
BOOTloader通常存儲在只讀存儲器(如ROM或flash存儲器)中,因此不容易遭到破壞或更改。它是系統(tǒng)啟動過程中非常重要的一部分,因為如果BOOTloader不能正常工作,則系統(tǒng)將無法啟動。
所以我們想實現(xiàn)BootLoader的話要對flash分區(qū),及對內(nèi)部偏移地址進(jìn)行指定,OTA主要是一種技術(shù)手段,我們主要是實現(xiàn)BootLoader。
正文
本次教程實現(xiàn)的功能是使用網(wǎng)線對STM32F407VGT6進(jìn)行OTA升級。
BootLoader
- 新建工程
根據(jù)自己的實際情況選擇芯片及型號后編譯下載初始代碼,檢查芯片及串口功能是否良好。2. 通過Cube配置功能
我這里使用的SPI3,CSS腳PE1。
點擊CubeMX Settings 配置時鐘,SPI引腳(片外Flash),串口3.配置RT-Thread
在項目資源管理器中點擊drivers->board.h文件配置 使能SPI、片內(nèi)Flash
#define BSP_USING_SPI3
#define BSP_USING_ON_CHIP_FLASH
點擊RT-Thread Settings 使能SPI、SFUD、FAL、QBOOT驅(qū)動程序
在FAL下要勾選FAL使用SFDU驅(qū)動程序,這個主要是管理片外Flash
在QBOOT組件下根據(jù)自己的需求進(jìn)行勾選相應(yīng)的功能
- 編寫SFUD驅(qū)動及FAL分區(qū)
新建w25q.c文件添加如下代碼,這個是使用SFUD驅(qū)動程序通過SPI對W25Q128抽象化管理。
#include <rtthread.h>
#include "drv_spi.h"
#include "spi_flash_sfud.h"
#define SPI_BUS_NAME "spi3"
#define W25Q_SPI_DEVICE_NAME "spi30"
//#define W25Q_FLASH_NAME "W25Q128"
static int rt_hw_spi_flash_init()
{
rt_err_t ree = RT_EOK;
ree = rt_hw_spi_device_attach(SPI_BUS_NAME, W25Q_SPI_DEVICE_NAME, GPIOE, GPIO_PIN_1);
//ree = rt_hw_spi_device_attach(SPI_BUS_NAME, W25Q_SPI_DEVICE_NAME, GPIOB, GPIO_PIN_6);
/* 使用 SFUD 探測 spi10 從設(shè)備,并將 spi10 連接的 flash 初始化為塊設(shè)備,名稱 W25Q128 */
if (RT_NULL == rt_sfud_flash_probe(FAL_USING_NOR_FLASH_DEV_NAME, W25Q_SPI_DEVICE_NAME))
{
return -RT_ERROR;
}
return ree;
}
INIT_COMPONENT_EXPORT(rt_hw_spi_flash_init);
新建fal_cfg.h文件,對flash引入及分配內(nèi)存,這要注意芯片的flash大小及偏移地址可能不同,我這個是對F404VGT6的,所以要看數(shù)據(jù)手冊進(jìn)行修改。
#ifndef _FAL_CFG_H_
#define _FAL_CFG_H_
#include <rtconfig.h>
#include <board.h>
#include <rtconfig.h>
#define FLASH_SIZE_GRANULARITY_16K (4 * 16 * 1024)
#define FLASH_SIZE_GRANULARITY_64K (64 * 1024)
#define FLASH_SIZE_GRANULARITY_128K (7 * 128 * 1024)
#define STM32_FLASH_START_ADRESS_16K STM32_FLASH_START_ADRESS
#define STM32_FLASH_START_ADRESS_64K (STM32_FLASH_START_ADRESS_16K + FLASH_SIZE_GRANULARITY_16K)
#define STM32_FLASH_START_ADRESS_128K (STM32_FLASH_START_ADRESS_64K + FLASH_SIZE_GRANULARITY_64K)
/* ===================== Flash device Configuration ========================= */
extern const struct fal_flash_dev stm32_onchip_flash_16k;
extern const struct fal_flash_dev stm32_onchip_flash_64k;
extern const struct fal_flash_dev stm32_onchip_flash_128k;
/* ===================== Flash device Configuration ========================= */
extern struct fal_flash_dev nor_flash0;
#define FAL_FLASH_DEV_TABLE \
{ \
&stm32_onchip_flash_16k, \
&stm32_onchip_flash_64k, \
&stm32_onchip_flash_128k, \
&nor_flash0, \
}
/* ====================== Partition Configuration ========================== */
#ifdef FAL_PART_HAS_TABLE_CFG
/* partition table */
//config_data分區(qū)必須是128k的整數(shù)倍,如果設(shè)置為1K,則在OTA升級后會擦除掉config_data分區(qū)的數(shù)據(jù)
//這種配置占用芯片flash太多,如果芯片flash存儲空間不夠可以考慮將config_data分區(qū)放在外部spi flash里
#define FAL_PART_TABLE \
{ \
{FAL_PART_MAGIC_WORD, "app", "onchip_flash_128k", 0, 768*1024, 0}, \
{FAL_PART_MAGIC_WORD, "config_data","onchip_flash_128k",768*1024, 128*1024, 0}, \
{FAL_PART_MAGIC_WORD, "download", FAL_USING_NOR_FLASH_DEV_NAME,0, 1024*1024, 0}, \
}
/*
#define FAL_PART_TABLE \
{ \
{FAL_PART_MAGIC_WORD, "config_data", "onchip_flash_128k", 0, 128*1024, 0}, \
{FAL_PART_MAGIC_WORD, "app","onchip_flash_128k",128*1024, 768*1024, 0}, \
{FAL_PART_MAGIC_WORD, "download", FAL_USING_NOR_FLASH_DEV_NAME,0, 1024*1024, 0}, \
}
*/
#endif /* FAL_PART_HAS_TABLE_CFG */
#endif /* _FAL_CFG_H_ */
修改main.c文件,添加FAL頭文件及初始化
#include <rtthread.h>
#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>
#include <fal.h>
int main(void)
{
int count = 1;
fal_init();
while (count++)
{
// LOG_D("Hello RT-Thread!");
rt_thread_mdelay(1000);
}
return RT_EOK;
}
5,下載驗證
編譯下載驗證,只要開到這幾條打印就代表BootLoader成功了
APP實現(xiàn)
- 創(chuàng)建工程
復(fù)制bootl工程改名為App2. 測試APP跳轉(zhuǎn)
在RT-Thread Studio 中刪除所有軟件包,修改main函數(shù),添加中斷向量表跳轉(zhuǎn)函數(shù)
#include <rtthread.h>
#include "fal.h"
#include <drivers/pin.h>
#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>
#define RT_APP_PART_ADDR 0x08020000
int main(void)
{
int count = 1;
fal_init();
// LOG_D("Hello RT-Thread!");
while (count++)
{
LOG_D("Hello RT-Thread!!!!!!");
rt_thread_mdelay(1000);
}
return RT_EOK;
}
static int ota_app_vtor_reconfig(void)
{
#define NVIC_VTOR_MASK 0xFFFFFF80
/* 根據(jù)應(yīng)用設(shè)置向量表 */
SCB->VTOR = RT_APP_PART_ADDR & NVIC_VTOR_MASK;
return 0;
}
INIT_BOARD_EXPORT(ota_app_vtor_reconfig);
然后在linkscripts下修改鏈接腳本起始地址,和下載地址這個地址是app的起始地址
下載測試后發(fā)現(xiàn)可以正常跳轉(zhuǎn)到app程序就OK了
- 配置驅(qū)動
接下來實現(xiàn)OTA功能
點擊CubeMX Settings,添加以太網(wǎng)外設(shè)(根據(jù)自己實際引腳配置)
點擊RT-Thread Settings添加ota_download、agile_console、agile_telnet、lwip組件
lwip組件下設(shè)置為靜態(tài)ipv4
設(shè)置如下:
ota_download
Lwipagile_telnet
agile_console
到這里就添加結(jié)束了,保存后在board.h文件下使能ETH并添加網(wǎng)卡型號
#define BSP_USING_ETH
#ifdef BSP_USING_ETH
#define PHY_USING_LAN8720A
/*#define PHY_USING_DM9161CEP*/
/*#define PHY_USING_DP83848C*/
#endif
編譯后會出現(xiàn)一個報錯,將這個報錯注釋掉3.修改main.c函數(shù)
這里添加app的偏移地址,讓中斷向量表跳轉(zhuǎn)及定義phy復(fù)位函數(shù)
#include <rtthread.h>
#include "fal.h"
#include <drivers/pin.h>
#include <board.h>
#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>
#define RT_APP_PART_ADDR 0x08020000
#define PHY_RESET_IO GET_PIN(A, 0)
void phy_reset(void)
{
rt_pin_mode(PHY_RESET_IO, PIN_MODE_OUTPUT);
rt_pin_write(PHY_RESET_IO, PIN_HIGH);
rt_thread_mdelay(50);
rt_pin_write(PHY_RESET_IO, PIN_LOW);
rt_thread_mdelay(50);
rt_pin_write(PHY_RESET_IO, PIN_HIGH);
}
int main(void)
{
int count = 1;
fal_init();
LOG_D("Hello RT-Thread!v1.0");
while (count++)
{
LOG_D("Hello RT-Thread!v1.0");
rt_thread_mdelay(1000);
}
return RT_EOK;
}
static int ota_app_vtor_reconfig(void)
{
#define NVIC_VTOR_MASK 0xFFFFFF80
/* 根據(jù)應(yīng)用設(shè)置向量表 */
SCB->VTOR = RT_APP_PART_ADDR & NVIC_VTOR_MASK;
return 0;
}
INIT_BOARD_EXPORT(ota_app_vtor_reconfig);
燒入打印如下
4. 驗證OTA功能
使用xshell和mywebServer
xshell配置如下IP地址是設(shè)備ip
點擊連接后會連接上同時打印信息,用法和串口一樣修改main.c函數(shù)主要是為了驗證 OTA不要下載進(jìn)去。
將編譯好的bin文件打包好,打包軟件和打包方式在下圖:
壓縮算法要與bootloader的壓縮方式一樣,固件分區(qū)名要與fal分區(qū)相同,我要下載到app里,如果填寫錯誤會導(dǎo)致QBoot搬運失敗。
打開mywebserver,設(shè)置如下
服務(wù)目錄是剛才打包好的的目錄,IP地址是本機(jī)IP地址,要注意設(shè)備與本機(jī)IP在同一網(wǎng)段,端口號默認(rèn)即可
在xshell中輸入http_ota http://192.168.1.112:80/rtthread.rbl
這樣mywebserver就偵聽到了請求,然后將文件傳輸?shù)街付ǚ謪^(qū)。
如下看效果。文章來源:http://www.zghlxwxcb.cn/news/detail-700402.html
文章來源地址http://www.zghlxwxcb.cn/news/detail-700402.html
到了這里,關(guān)于【RT-Thread】使用RT-Thread Studio 配置BootLoader及App實現(xiàn)OTA功能的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!