RT Thread Studio 配置OTA实现远程程序下载(亲测成功,巨详细)

RT Thread Studio 配置OTA(亲测成功,巨详细)

用rt thread新建工程,我用的stm32f103vet6,stlink

在这里插入图片描述
首先配置外部时钟hse,可以直接复制以下代码到drv_clk.c中的void system_clock_config(int target_freq_Mhz),也可以自己在cubemx生成。
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

/** Initializes the RCC Oscillators according to the specified parameters

  • in the RCC_OscInitTypeDef structure.
    /
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
    RCC_OscInitStruct.HSEState = RCC_HSE_ON;
    RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
    RCC_OscInitStruct.HSIState = RCC_HSI_ON;
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
    RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
    RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
    if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
    {
    Error_Handler();
    }
    /
    * Initializes the CPU, AHB and APB buses clocks
    */
    RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
    |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
    RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
    RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
    RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}

配置spi,这个按board.h中的步骤来就行

在这里插入图片描述
这里我用的野火的f103指南者,w25q64是a5,a6,a7,不同的板子要在cubemx自己修改

void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi)
{

  GPIO_InitTypeDef GPIO_InitStruct;
  if(hspi->Instance==SPI1)
  {
  /* USER CODE BEGIN SPI1_MspInit 0 */

  /* USER CODE END SPI1_MspInit 0 */
    /* Peripheral clock enable */
    __HAL_RCC_SPI1_CLK_ENABLE();

    /**SPI3 GPIO Configuration
    PA5     ------> SPI1_SCK
    PA6     ------> SPI1_MISO
    PA7     ------> SPI1_MOSI
    */
    GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_7;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_6;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /* USER CODE BEGIN SPI1_MspInit 1 */

  /* USER CODE END SPI1_MspInit 1 */
  }

}

然后配置rtc,按这个步骤来就行

在这里插入图片描述

标题在applications下创建flash.c,这里叫什么无所谓,把以下代码复制进去

#include "spi_flash_sfud.h"
#include <rtthread.h>
#include <board.h>
#include <rtdevice.h>


rt_uint8_t wData[4096] = {"SPI bus write data to W25X flash."};
rt_uint8_t rData[4096];
extern rt_err_t rt_hw_spi_device_attach(const char *bus_name,
                                        const char *device_name,
                                        GPIO_TypeDef* cs_gpiox,
                                        uint16_t cs_gpio_pin);
int spi1_device_init(void)
{
    __HAL_RCC_GPIOB_CLK_ENABLE();
    //设备挂载到SPI总线,抽象为 spi10 设备
    rt_hw_spi_device_attach("spi1", "spi10", GPIOC, GPIO_PIN_0);

        if (rt_sfud_flash_probe("W25Q64", "spi10")) {
        rt_kprintf("rt sfud flash probe success\n");
    } else {
        rt_kprintf("rt sfud flash probe fail\n");
    };

    return RT_EOK;
}
INIT_DEVICE_EXPORT(spi1_device_init);//自动初始化

rt_hw_spi_device_attach(“spi1”, “spi10”, GPIOC, GPIO_PIN_0);这行就是spi中的cs,如果用的引脚不同记得修改,和硬件上对应。编译,下载。
在这里插入图片描述

添加fal软件包,这个地方,把名字改成和自己对应的,我的是W25Q64

在这里插入图片描述
把这个文件复制到这里。
在这里插入图片描述
在这里插入图片描述
回到rt thread studio刷新一下,把下面代码复制进去。

#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 */
#define FAL_PART_TABLE                                                               \
{                                                                                    \
                                                                                            \
    {FAL_PART_MAGIC_WORD,       "app",     "onchip_flash_128k",   0,  256*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_ */

然后编译会报错

在这里插入图片描述

是因为这几个16k,64k,128k没定义,复制一下程序到这个.c文件里

在这里插入图片描述

在这里插入图片描述

const struct fal_flash_dev stm32f2_onchip_flash =
{
    .name       = "stm32_onchip",
    .addr       = 0x08000000,
    .len        = 1024*1024,
    .blk_size   = 128*1024,
    .ops        = {init, read, write, erase},
    .write_gran = 8
};
const struct fal_flash_dev stm32_onchip_flash_128k =
{
    .name       = "onchip_flash_128k",
    .addr       = 0x08020000,
    .len        = 1024*1024,
    .blk_size   = 1024*1024,
    .ops        = {init, read, write, erase},
    .write_gran = 8
};
const struct fal_flash_dev stm32_onchip_flash_16k =
{
    .name       = "onchip_flash_16k",
    .addr       = 0x08000000,
    .len        = 1024*1024,
    .blk_size   = 256*1024,
    .ops        = {init, read, write, erase},
    .write_gran = 8
};
const struct fal_flash_dev stm32_onchip_flash_64k =
{
    .name       = "onchip_flash_64k",
    .addr       = 0x08010000,
    .len        = 1024*1024,
    .blk_size   = 1024*1024,
    .ops        = {init, read, write, erase},
    .write_gran = 8
};

这里打开main.c把下面的代码复制进去

/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2021-09-26     RT-Thread    first version
 */

#include <rtthread.h>

#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>
#include <board.h>
#include <rtdevice.h>
#include "fal.h"
#define RT_APP_PART_ADDR 0x08020000

#define VER "V3.6.0"


int main(void)
{
    int count = 1;
        fal_init();
        LOG_D("Hello RT-Thread!");
        rt_kprintf("version:%s\r\n",VER);

        while (count++)
        {
            rt_thread_mdelay(1000);
        }

        return RT_EOK;
}

编译,下载

在这里插入图片描述

恭喜你。快成功了。打开link.lds,修改为0x802

在这里插入图片描述

安装ota

在这里插入图片描述

把ymodem也打开

在这里插入图片描述

接下来配置bootloader。进入http://iot.rt-thread.com

在这里插入图片描述
这个地方随便创建就好,其他的按自己板子的情况选就好
在这里插入图片描述
在这里插入图片描述
点击生成bootloader

打开STM32 ST-LINK Utility,用j-link也行,这方面的教程很多,我这里用STM32 ST-LINK Utility,选择刚刚在邮箱下载的bin文件。

在这里插入图片描述

重新下程序,出现报错,把libc打开

在这里插入图片描述
在这里插入图片描述

可能会出现stlink下不进程序的问题,重新用STM32 ST-LINK Utility升级一下stlink固件就好了,或者按着单片机复位键下程序。这里是为啥我也不知道。

在这里插入图片描述
在这里插入图片描述

用打包工具打包,在这个路径下

在这里插入图片描述

选择该工程的固件

在这里插入图片描述
在这里插入图片描述

在命令行输入ymodem_ota

在这里插入图片描述

然后得用一下xshell了,右键传输,选择刚刚debug文件下的rbl,文件

在这里插入图片描述
在这里插入图片描述
点击打开就开始了,这里实现远程下载的话可以用4g模块,其实esp8266应该也可以
在这里插入图片描述
在这里插入图片描述

开始了!成功了。。。。。。。。。。。。。。。。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
RT-Thread是一款开源的嵌入式实时操作系统,提供了OTA升级功能的实现方法。下面是通用OTA代码实现的步骤: 1. 配置网络连接:OTA升级需要连接服务器进行升级,因此需要先配置网络连接。RT-Thread提供了多种网络协议的支持,开发者可以根据自己的需求选择适合的网络协议。 2. 下载OTA升级包:OTA升级包通常是在服务器上存储的,需要通过网络下载RT-Thread提供了HTTP、FTP等多种下载方式的支持,开发者可以根据实际情况选择下载方式。 3. 验证OTA升级包:下载完成后需要对OTA升级包进行验证,确保其完整性和正确性。可以使用CRC校验或者数字签名等方式进行验证。 4. 升级系统:验证通过后,可以开始执行OTA升级。RT-Thread提供了OTA升级接口,开发者只需要调用相应的接口即可完成升级。 下面是一个简单的OTA代码实现示例: ```c #include <rtthread.h> #include <dfs_posix.h> #include <netdb.h> #include <sys/socket.h> #include <arpa/inet.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #define OTA_SERVER_ADDR "192.168.1.100" #define OTA_SERVER_PORT 80 static int ota_download(const char *url, const char *filename) { int sockfd = -1; struct sockaddr_in servaddr; struct hostent *server; char buf[1024]; int len; /* 解析OTA服务器地址 */ server = gethostbyname(OTA_SERVER_ADDR); if (server == NULL) { rt_kprintf("Error: no such host\n"); return -1; } /* 创建socket连接OTA服务器 */ sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) { rt_kprintf("Error: cannot create socket\n"); return -1; } memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; memcpy(&servaddr.sin_addr.s_addr, server->h_addr, server->h_length); servaddr.sin_port = htons(OTA_SERVER_PORT); if (connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) { rt_kprintf("Error: cannot connect to OTA server\n"); return -1; } /* 发送HTTP请求 */ sprintf(buf, "GET %s HTTP/1.1\r\n", url); strcat(buf, "Host: "); strcat(buf, OTA_SERVER_ADDR); strcat(buf, "\r\n\r\n"); if (write(sockfd, buf, strlen(buf)) < 0) { rt_kprintf("Error: cannot send HTTP request\n"); return -1; } /* 下载OTA升级包 */ int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC); if (fd < 0) { rt_kprintf("Error: cannot create file %s\n", filename); return -1; } while ((len = read(sockfd, buf, sizeof(buf))) > 0) { if (write(fd, buf, len) < 0) { rt_kprintf("Error: cannot write to file %s\n", filename); close(fd); return -1; } } close(fd); close(sockfd); return 0; } static int ota_verify(const char *filename) { /* TODO: 实现OTA升级包验证 */ return 0; } static int ota_upgrade(const char *filename) { /* TODO: 实现OTA升级 */ return 0; } int ota_update(const char *url) { char *filename = strrchr(url, '/'); if (filename == NULL) { rt_kprintf("Error: invalid OTA URL\n"); return -1; } filename++; if (ota_download(url, filename) < 0) { return -1; } if (ota_verify(filename) < 0) { return -1; } if (ota_upgrade(filename) < 0) { return -1; } return 0; } ``` 以上示例代码中,`ota_download`函数用于下载OTA升级包,`ota_verify`函数用于验证OTA升级包,`ota_upgrade`函数用于执行OTA升级。`ota_update`函数是一个包装函数,调用以上三个函数完成整个OTA升级过程。 开发者可以根据自己的需求修改示例代码,实现符合自己产品的OTA升级功能。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值