rtt-studio——OTA远程升级(HTTP)
一.软件准备1.rtthread-studio2.mobaxterm可选3.STM32 ST-LINK Utility4.cubemx二.制作Bootloader1.打开rtt官方的网站登录进去iot_admin2.注册并进入新建一个产品随意书写就行按照步骤1,2,3根据自己手头板子型号来制作bootloaderstm32f407默认是128k给bootloader所以app区应该是从0x8020000开始根据自己程序所占的空间大小来分配对应的data大小128的整数倍download区是最好跟app区配置一样的选的是片上外设就没有配置spi flash3.bootloader生成之后会生成.zip文件解压缩里面有.bin文件打开STM32 ST-LINK Utility这个软件先设置配置如下前提是先连接stlink与单片机然后点击连接连接成功会出现如图所示选择刚刚生成的bootloader的.bin文件然后点击start下载三.硬件驱动配置1.在cubemx中开启网口即可时钟这些配置一下网上教程很多。2.打开rtthread-studio进行相关的配置配置自己相关的局域网地址即可。3.编译驱动时会报错需要把如图这个文件中的section 2这部分替换为下面的根据板子上的网口芯片正点原子开发板是lan8720/* LAN8720A_PHY_ADDRESS Address*/ #define LAN8720A_PHY_ADDRESS 1U /* PHY Reset delay these values are based on a 1 ms Systick interrupt*/ #define PHY_RESET_DELAY ((uint32_t)0x000000FFU) /* PHY Configuration delay */ #define PHY_CONFIG_DELAY ((uint32_t)0x00000FFFU) #define PHY_READ_TO ((uint32_t)0x0000FFFFU) #define PHY_WRITE_TO ((uint32_t)0x0000FFFFU) /* Section 3: Common PHY Registers */ #define PHY_BCR ((uint16_t)0x00U) /*! Transceiver Basic Control Register */ #define PHY_BSR ((uint16_t)0x01U) /*! Transceiver Basic Status Register */ #define PHY_RESET ((uint16_t)0x8000U) /*! PHY Reset */ #define PHY_LOOPBACK ((uint16_t)0x4000U) /*! Select loop-back mode */ #define PHY_FULLDUPLEX_100M ((uint16_t)0x2100U) /*! Set the full-duplex mode at 100 Mb/s */ #define PHY_HALFDUPLEX_100M ((uint16_t)0x2000U) /*! Set the half-duplex mode at 100 Mb/s */ #define PHY_FULLDUPLEX_10M ((uint16_t)0x0100U) /*! Set the full-duplex mode at 10 Mb/s */ #define PHY_HALFDUPLEX_10M ((uint16_t)0x0000U) /*! Set the half-duplex mode at 10 Mb/s */ #define PHY_AUTONEGOTIATION ((uint16_t)0x1000U) /*! Enable auto-negotiation function */ #define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200U) /*! Restart auto-negotiation function */ #define PHY_POWERDOWN ((uint16_t)0x0800U) /*! Select the power down mode */ #define PHY_ISOLATE ((uint16_t)0x0400U) /*! Isolate PHY from MII */ #define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020U) /*! Auto-Negotiation process completed */ #define PHY_LINKED_STATUS ((uint16_t)0x0004U) /*! Valid link established */ #define PHY_JABBER_DETECTION ((uint16_t)0x0002U) /*! Jabber condition detected */ /* Section 4: Extended PHY Registers */ #define PHY_SR ((uint16_t)0x1FU) /*! PHY status register Offset */ #define PHY_SPEED_STATUS ((uint16_t)0x0004U) /*! PHY Speed mask */ #define PHY_DUPLEX_STATUS ((uint16_t)0x0010U) /*! PHY Duplex mask */ #define PHY_ISFR ((uint16_t)0x001DU) /*! PHY Interrupt Source Flag register Offset */ #define PHY_ISFR_INT4 ((uint16_t)0x000BU) /*! PHY Link down inturrupt */再把main中的与eth相关的注释掉再编译5.修改board.c中的文件修改board.h中的文件6.添加软件包5.1rtthread应该是在ota-download里内置了fal这个所以不需要下载先安装下面的ota需要额外添加一个文件文件内容如下/* * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2018-12-5 SummerGift first version */ #ifndef _FAL_CFG_H_ #define _FAL_CFG_H_ #include rtthread.h #include board.h #ifdef BSP_USING_SPI_FLASH_LITTLEFS extern struct fal_flash_dev w25q128; #else extern const struct fal_flash_dev stm32_onchip_flash; #endif /* flash device table */ #ifdef BSP_USING_SPI_FLASH_LITTLEFS #define FAL_FLASH_DEV_TABLE \ { \ w25q128, \ } #else #define FAL_FLASH_DEV_TABLE \ { \ stm32_onchip_flash, \ } #endif /* Partition Configuration */ #ifdef FAL_PART_HAS_TABLE_CFG /* partition table */ #ifdef BSP_USING_SPI_FLASH_LITTLEFS #define FAL_PART_TABLE \ { \ {FAL_PART_MAGIC_WROD, spiflash0, W25Q128, 0 , 16 * 1024 * 1024, 0}, \ } #else #define FAL_PART_TABLE \ { \ {FAL_PART_MAGIC_WROD, bootloader, onchip, 0x00000, 128 * 1024, 0}, \ {FAL_PART_MAGIC_WROD, app, onchip, 0x20000, 384 * 1024, 0}, \ {FAL_PART_MAGIC_WROD, download, onchip, 0x80000, 384 * 1024, 0}, \ } #endif #endif /* FAL_PART_HAS_TABLE_CFG */ #endif /* _FAL_CFG_H_ */在board.h中再添加对于drivers文件夹下的drv_flash_f4.c替换成下面的代码/* * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2018-12-5 SummerGift first version */ #include board.h #ifdef BSP_USING_ON_CHIP_FLASH #include drv_config.h #include drv_flash.h #if defined(RT_USING_FAL) || defined(PKG_USING_FAL) #include fal.h #endif //#define DRV_DEBUG #define LOG_TAG drv.flash #include drv_log.h /* Base address of the Flash sectors Bank 1 */ #define ADDR_FLASH_SECTOR_0 ((uint32_t)0x08000000) /* Base of Sector 0, 16 Kbytes */ #define ADDR_FLASH_SECTOR_1 ((uint32_t)0x08004000) /* Base of Sector 1, 16 Kbytes */ #define ADDR_FLASH_SECTOR_2 ((uint32_t)0x08008000) /* Base of Sector 2, 16 Kbytes */ #define ADDR_FLASH_SECTOR_3 ((uint32_t)0x0800C000) /* Base of Sector 3, 16 Kbytes */ #define ADDR_FLASH_SECTOR_4 ((uint32_t)0x08010000) /* Base of Sector 4, 64 Kbytes */ #define ADDR_FLASH_SECTOR_5 ((uint32_t)0x08020000) /* Base of Sector 5, 128 Kbytes */ #define ADDR_FLASH_SECTOR_6 ((uint32_t)0x08040000) /* Base of Sector 6, 128 Kbytes */ #define ADDR_FLASH_SECTOR_7 ((uint32_t)0x08060000) /* Base of Sector 7, 128 Kbytes */ #define ADDR_FLASH_SECTOR_8 ((uint32_t)0x08080000) /* Base of Sector 8, 128 Kbytes */ #define ADDR_FLASH_SECTOR_9 ((uint32_t)0x080A0000) /* Base of Sector 9, 128 Kbytes */ #define ADDR_FLASH_SECTOR_10 ((uint32_t)0x080C0000) /* Base of Sector 10, 128 Kbytes */ #define ADDR_FLASH_SECTOR_11 ((uint32_t)0x080E0000) /* Base of Sector 11, 128 Kbytes */ /* Base address of the Flash sectors Bank 2 */ #define ADDR_FLASH_SECTOR_12 ((uint32_t)0x08100000) /* Base of Sector 0, 16 Kbytes */ #define ADDR_FLASH_SECTOR_13 ((uint32_t)0x08104000) /* Base of Sector 1, 16 Kbytes */ #define ADDR_FLASH_SECTOR_14 ((uint32_t)0x08108000) /* Base of Sector 2, 16 Kbytes */ #define ADDR_FLASH_SECTOR_15 ((uint32_t)0x0810C000) /* Base of Sector 3, 16 Kbytes */ #define ADDR_FLASH_SECTOR_16 ((uint32_t)0x08110000) /* Base of Sector 4, 64 Kbytes */ #define ADDR_FLASH_SECTOR_17 ((uint32_t)0x08120000) /* Base of Sector 5, 128 Kbytes */ #define ADDR_FLASH_SECTOR_18 ((uint32_t)0x08140000) /* Base of Sector 6, 128 Kbytes */ #define ADDR_FLASH_SECTOR_19 ((uint32_t)0x08160000) /* Base of Sector 7, 128 Kbytes */ #define ADDR_FLASH_SECTOR_20 ((uint32_t)0x08180000) /* Base of Sector 8, 128 Kbytes */ #define ADDR_FLASH_SECTOR_21 ((uint32_t)0x081A0000) /* Base of Sector 9, 128 Kbytes */ #define ADDR_FLASH_SECTOR_22 ((uint32_t)0x081C0000) /* Base of Sector 10, 128 Kbytes */ #define ADDR_FLASH_SECTOR_23 ((uint32_t)0x081E0000) /* Base of Sector 11, 128 Kbytes */ /** * brief Gets the sector of a given address * param None * retval The sector of a given address */ static rt_uint32_t GetSector(rt_uint32_t Address) { rt_uint32_t sector 0; if((Address ADDR_FLASH_SECTOR_1) (Address ADDR_FLASH_SECTOR_0)) { sector FLASH_SECTOR_0; } else if((Address ADDR_FLASH_SECTOR_2) (Address ADDR_FLASH_SECTOR_1)) { sector FLASH_SECTOR_1; } else if((Address ADDR_FLASH_SECTOR_3) (Address ADDR_FLASH_SECTOR_2)) { sector FLASH_SECTOR_2; } else if((Address ADDR_FLASH_SECTOR_4) (Address ADDR_FLASH_SECTOR_3)) { sector FLASH_SECTOR_3; } else if((Address ADDR_FLASH_SECTOR_5) (Address ADDR_FLASH_SECTOR_4)) { sector FLASH_SECTOR_4; } else if((Address ADDR_FLASH_SECTOR_6) (Address ADDR_FLASH_SECTOR_5)) { sector FLASH_SECTOR_5; } else if((Address ADDR_FLASH_SECTOR_7) (Address ADDR_FLASH_SECTOR_6)) { sector FLASH_SECTOR_6; } else if((Address ADDR_FLASH_SECTOR_8) (Address ADDR_FLASH_SECTOR_7)) { sector FLASH_SECTOR_7; } #if defined(FLASH_SECTOR_8) else if((Address ADDR_FLASH_SECTOR_9) (Address ADDR_FLASH_SECTOR_8)) { sector FLASH_SECTOR_8; } #endif #if defined(FLASH_SECTOR_9) else if((Address ADDR_FLASH_SECTOR_10) (Address ADDR_FLASH_SECTOR_9)) { sector FLASH_SECTOR_9; } #endif #if defined(FLASH_SECTOR_10) else if((Address ADDR_FLASH_SECTOR_11) (Address ADDR_FLASH_SECTOR_10)) { sector FLASH_SECTOR_10; } #endif #if defined(FLASH_SECTOR_11) else if((Address ADDR_FLASH_SECTOR_12) (Address ADDR_FLASH_SECTOR_11)) { sector FLASH_SECTOR_11; } #endif #if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx)|| defined(STM32F439xx) || defined(STM32F469xx) || defined(STM32F479xx) else if((Address ADDR_FLASH_SECTOR_13) (Address ADDR_FLASH_SECTOR_12)) { sector FLASH_SECTOR_12; } else if((Address ADDR_FLASH_SECTOR_14) (Address ADDR_FLASH_SECTOR_13)) { sector FLASH_SECTOR_13; } else if((Address ADDR_FLASH_SECTOR_15) (Address ADDR_FLASH_SECTOR_14)) { sector FLASH_SECTOR_14; } else if((Address ADDR_FLASH_SECTOR_16) (Address ADDR_FLASH_SECTOR_15)) { sector FLASH_SECTOR_15; } else if((Address ADDR_FLASH_SECTOR_17) (Address ADDR_FLASH_SECTOR_16)) { sector FLASH_SECTOR_16; } else if((Address ADDR_FLASH_SECTOR_18) (Address ADDR_FLASH_SECTOR_17)) { sector FLASH_SECTOR_17; } else if((Address ADDR_FLASH_SECTOR_19) (Address ADDR_FLASH_SECTOR_18)) { sector FLASH_SECTOR_18; } else if((Address ADDR_FLASH_SECTOR_20) (Address ADDR_FLASH_SECTOR_19)) { sector FLASH_SECTOR_19; } else if((Address ADDR_FLASH_SECTOR_21) (Address ADDR_FLASH_SECTOR_20)) { sector FLASH_SECTOR_20; } else if((Address ADDR_FLASH_SECTOR_22) (Address ADDR_FLASH_SECTOR_21)) { sector FLASH_SECTOR_21; } else if((Address ADDR_FLASH_SECTOR_23) (Address ADDR_FLASH_SECTOR_22)) { sector FLASH_SECTOR_22; } else /* (Address FLASH_END_ADDR) (Address ADDR_FLASH_SECTOR_23) */ { sector FLASH_SECTOR_23; } #endif return sector; } /** * Read data from flash. * note This operations units is word. * * param addr flash address * param buf buffer to store read data * param size read bytes size * * return result */ int stm32_flash_read(rt_uint32_t addr, rt_uint8_t *buf, size_t size) { size_t i; if ((addr size) STM32_FLASH_END_ADDRESS) { LOG_E(read outrange flash size! addr is (0x%p), (void*)(addr size)); return -1; } for (i 0; i size; i, buf, addr) { *buf *(rt_uint8_t *) addr; } return size; } /** * Write data to flash. * note This operations units is word. * note This operation must after erase. see flash_erase. * * param addr flash address * param buf the write data buffer * param size write bytes size * * return result */ int stm32_flash_write(rt_uint32_t addr, const rt_uint8_t *buf, size_t size) { rt_err_t result RT_EOK; rt_uint32_t end_addr addr size; rt_uint32_t written_size 0; rt_uint32_t write_size 0; if ((end_addr) STM32_FLASH_END_ADDRESS) { LOG_E(write outrange flash size! addr is (0x%p), (void*)(addr size)); return -RT_EINVAL; } if (size 1) { return -RT_EINVAL; } HAL_FLASH_Unlock(); __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR); while (written_size size) { if (((addr written_size) % 4 0) (size - written_size 4)) { if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, addr written_size, *((rt_uint32_t *)(buf written_size))) HAL_OK) { if (*(rt_uint32_t *)(addr written_size) ! *(rt_uint32_t *)(buf written_size)) { result -RT_ERROR; break; } } else { result -RT_ERROR; break; } write_size 4; } else if (((addr written_size) % 2 0) (size - written_size 2)) { if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, addr written_size, *((rt_uint16_t *)(buf written_size))) HAL_OK) { if (*(rt_uint16_t *)(addr written_size) ! *(rt_uint16_t *)(buf written_size)) { result -RT_ERROR; break; } } else { result -RT_ERROR; break; } write_size 2; } else { if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, addr written_size, *((rt_uint8_t *)(buf written_size))) HAL_OK) { if (*(rt_uint8_t *)(addr written_size) ! *(rt_uint8_t *)(buf written_size)) { result -RT_ERROR; break; } } else { result -RT_ERROR; break; } write_size 1; } written_size write_size; } HAL_FLASH_Lock(); if (result ! RT_EOK) { return result; } return size; } /** * Erase data on flash. * note This operation is irreversible. * note This operations units is different which on many chips. * * param addr flash address * param size erase bytes size * * return result */ int stm32_flash_erase(rt_uint32_t addr, size_t size) { rt_err_t result RT_EOK; rt_uint32_t FirstSector 0, NbOfSectors 0; rt_uint32_t SECTORError 0; if ((addr size) STM32_FLASH_END_ADDRESS) { LOG_E(ERROR: erase outrange flash size! addr is (0x%p)\n, (void*)(addr size)); return -RT_EINVAL; } if (size 1) { return -RT_EINVAL; } /*Variable used for Erase procedure*/ FLASH_EraseInitTypeDef EraseInitStruct; /* Unlock the Flash to enable the flash control register access */ HAL_FLASH_Unlock(); __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR); /* Get the 1st sector to erase */ FirstSector GetSector(addr); /* Get the number of sector to erase from 1st sector*/ NbOfSectors GetSector(addr size - 1) - FirstSector 1; /* Fill EraseInit structure*/ EraseInitStruct.TypeErase FLASH_TYPEERASE_SECTORS; EraseInitStruct.VoltageRange FLASH_VOLTAGE_RANGE_3; EraseInitStruct.Sector FirstSector; EraseInitStruct.NbSectors NbOfSectors; if (HAL_FLASHEx_Erase(EraseInitStruct, (uint32_t *)SECTORError) ! HAL_OK) { result -RT_ERROR; goto __exit; } __exit: HAL_FLASH_Lock(); if (result ! RT_EOK) { return result; } LOG_D(erase done: addr (0x%p), size %d, (void*)addr, size); return size; } #if defined(RT_USING_FAL) || defined(PKG_USING_FAL) static int fal_flash_read(long offset, rt_uint8_t *buf, size_t size); static int fal_flash_write(long offset, const rt_uint8_t *buf, size_t size); static int fal_flash_erase(long offset, size_t size); const struct fal_flash_dev stm32_onchip_flash { onchip, STM32_FLASH_START_ADRESS, STM32_FLASH_SIZE, (128 * 1024), {NULL, fal_flash_read, fal_flash_write, fal_flash_erase} }; static int fal_flash_read(long offset, rt_uint8_t *buf, size_t size) { return stm32_flash_read(stm32_onchip_flash.addr offset, buf, size); } static int fal_flash_write(long offset, const rt_uint8_t *buf, size_t size) { return stm32_flash_write(stm32_onchip_flash.addr offset, buf, size); } static int fal_flash_erase(long offset, size_t size) { return stm32_flash_erase(stm32_onchip_flash.addr offset, size); } #endif #endif /* BSP_USING_ON_CHIP_FLASH */修改终端向量表的便宜地址修改linkscripts中的link文件大小是你的app的data区的大小7.添加ota软件包进入修改配置选项自己电脑的ip地址修改/packages/src中的http_ota.c文件/* * Copyright (c) 2006-2018, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2018-03-22 Murphy the first version */ #include stdio.h #include stdint.h #include stdlib.h #include rtthread.h #include finsh.h #include webclient.h #include fal.h #define DBG_ENABLE #define DBG_SECTION_NAME http_ota #ifdef OTA_DOWNLOADER_DEBUG #define DBG_LEVEL DBG_LOG #else #define DBG_LEVEL DBG_INFO #endif #define DBG_COLOR #include rtdbg.h #ifdef PKG_USING_HTTP_OTA #define HTTP_OTA_BUFF_LEN (2 * 1024) #define GET_HEADER_BUFSZ 1024 #define GET_RESP_BUFSZ 512 #define HTTP_OTA_DL_DELAY (10 * RT_TICK_PER_SECOND) #define HTTP_OTA_URL PKG_HTTP_OTA_URL /* the address offset of download partition */ #ifndef RT_USING_FAL #error Please enable and confirgure FAL part. #endif /* RT_USING_FAL */ const struct fal_partition * dl_part RT_NULL; static int begin_offset 0; static int file_size 0; static void print_progress(size_t cur_size, size_t total_size) { static unsigned char progress_sign[100 1]; uint8_t i, per cur_size * 100 / total_size; if (per 100) { per 100; } for (i 0; i 100; i) { if (i per) { progress_sign[i] ; } else if (per i) { progress_sign[i] ; } else { progress_sign[i] ; } } progress_sign[sizeof(progress_sign) - 1] \0; LOG_I(Download: [%s] %03d%%\033[1A, progress_sign, per); } /* handle function, you can store data and so on */ static int http_ota_fw_download(const char* uri) { int ret RT_EOK; int status; int read_len; uint8_t *buffer RT_NULL; struct webclient_session* session RT_NULL; /* create webclient session and set header response size */ session webclient_session_create(GET_HEADER_BUFSZ); if (!session) { LOG_E(open uri failed.); ret -RT_ERROR; goto __exit; } /* * Use one normal GET and stream its body to flash. This also works with * HTTP servers (such as Python http.server) which do not support Range. */ status webclient_get(session, uri); if (status ! 200) { LOG_E(HTTP GET failed, status: %d, status); ret -RT_ERROR; goto __exit; } file_size webclient_content_length_get(session); if (file_size 0) { LOG_E(Request file size is 0!); ret -RT_ERROR; goto __exit; } else if (file_size 0) { LOG_E(webclient GET request type is chunked.); ret -RT_ERROR; goto __exit; } LOG_I(OTA file size is (%d), file_size); LOG_I(\033[1A); /* 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); ret -RT_ERROR; goto __exit; } if (file_size dl_part-len) { LOG_E(Firmware is too large! File size (%d), partition size (%d), file_size, dl_part-len); ret -RT_ERROR; goto __exit; } LOG_I(Start erase flash (%s) partition!, dl_part-name); if (fal_partition_erase(dl_part, 0, file_size) 0) { LOG_E(Firmware download failed! Partition (%s) erase error!, dl_part-name); ret -RT_ERROR; goto __exit; } LOG_I(Erase flash (%s) partition success!, dl_part-name); buffer rt_malloc(HTTP_OTA_BUFF_LEN); if (buffer RT_NULL) { LOG_E(No memory for OTA buffer (%d bytes)., HTTP_OTA_BUFF_LEN); ret -RT_ENOMEM; goto __exit; } while (begin_offset file_size) { int remaining file_size - begin_offset; int request_len remaining HTTP_OTA_BUFF_LEN ? HTTP_OTA_BUFF_LEN : remaining; read_len webclient_read(session, buffer, request_len); if (read_len 0) { LOG_E(Read firmware failed at offset %d, error %d., begin_offset, read_len); ret -RT_ERROR; goto __exit; } if (fal_partition_write(dl_part, begin_offset, buffer, read_len) ! read_len) { LOG_E(Firmware download failed! Partition (%s) write data error!, dl_part-name); ret -RT_ERROR; goto __exit; } begin_offset read_len; print_progress(begin_offset, file_size); } ret RT_EOK; if (ret RT_EOK) { if (session ! RT_NULL) { webclient_close(session); session RT_NULL; } LOG_I(\033[0B); LOG_I(Download firmware to flash success.); LOG_I(System now will restart...); rt_hw_interrupt_disable(); NVIC_SystemReset(); } else { LOG_E(Download firmware failed.); } __exit: if (buffer ! RT_NULL) rt_free(buffer); if (session ! RT_NULL) webclient_close(session); begin_offset 0; return ret; } void http_ota(uint8_t argc, char **argv) { if (argc 2) { rt_kprintf(using uri: HTTP_OTA_URL \n); http_ota_fw_download(HTTP_OTA_URL); } else { http_ota_fw_download(argv[1]); } } /** * msh /http_ota [url] */ MSH_CMD_EXPORT(http_ota, Use HTTP to download the firmware); #endif /* PKG_USING_HTTP_OTA */在main中书写#include fal.h int fal_partitions; /* OTA depends on the FAL flash device and partition table. */ fal_partitions fal_init(); if (fal_partitions 0) { rt_kprintf([MAIN] Error: FAL initialization failed (%d)\n, fal_partitions); return -1; } rt_kprintf([MAIN] FAL initialized, %d partitions found\n, fal_partitions);四.打包app编译自己的工程编译完成后会生成.bin文件找到打包应用选择debug下的.bin文件打包完成之后会生成一个.rbl文件五.远程烧录测试在.rbl文件夹中打开cmd运行命令python -m http.server 8080进入单片机的串口中使用命令计算机的ip地址这样就会远程ota升级成功

相关新闻

mcopy命令

mcopy命令

mcopy是 mtools​ 套件里的命令,用于在 Linux/Unix 下不挂载软盘/磁盘镜像的情况下,直接读写 FAT12/FAT16/FAT32​ 文件系统(常见于软盘、U 盘镜像、DOS 分区等)。基本语法mcopy [选项] 源文件 目标文件常见用法示例从当前系统复制…

2026/10/17 19:02:27 阅读更多 →
别再手动写@Test了,ChatGPT已通过ISO/IEC/IEEE 29119测试标准验证——你的团队还在用2005年的方式做TDD?

别再手动写@Test了,ChatGPT已通过ISO/IEC/IEEE 29119测试标准验证——你的团队还在用2005年的方式做TDD?

更多请点击: https://codechina.net 第一章:ChatGPT写单元测试的范式革命 传统单元测试编写长期受限于开发者认知边界、时间成本与领域知识断层——测试用例常流于“能跑通”,而非“覆盖边界”“揭示契约”。ChatGPT 的介入并非简单替代人工…

2026/10/16 13:20:27 阅读更多 →
计算机组成原理(16):定点数与无符号数的加减运算

计算机组成原理(16):定点数与无符号数的加减运算

写在前面 学习《计算机组成原理》的时候,我一直觉得一个问题特别有意思:为什么我们小时候都会做的加减法,计算机却要花这么大的篇幅去研究? 我们拿起纸和笔,算出 15-24-9 几乎不用思考;可是计算机却要研究原…

2026/10/18 3:52:43 阅读更多 →

最新新闻

水性醛酮树脂CT系列:提升漆膜光泽与硬度的功能助树脂

水性醛酮树脂CT系列:提升漆膜光泽与硬度的功能助树脂

做水性涂料这几年,我听得最多的反馈就三个:光泽差一点,硬度软一点,色浆放两天就返粗。这三个问题单拎出来都不算大,但放到工业漆、木器漆和油墨上,就是客户整批次退货的理由,严重一点直接丢订单…

2026/10/18 3:52:22 阅读更多 →
XERJ Autoindex + MCP 在 Windows 上的端到端实战:从安装、建索引到 Agent 检索的一站式闭环

XERJ Autoindex + MCP 在 Windows 上的端到端实战:从安装、建索引到 Agent 检索的一站式闭环

人工智能搜索引擎本地部署后端MCP 服务 【免费下载链接】xerj XERJ is the new way for AI to search data. Its autoindex capability activates agents to know your data without the token waste of grep and sed. One command indexes code, docs, logs and PDFs for sear…

2026/10/18 3:52:22 阅读更多 →
JavaScript原生四则运算计算器:从字符串拼接陷阱到精度控制

JavaScript原生四则运算计算器:从字符串拼接陷阱到精度控制

1. 这不是计算器Demo,而是前端交互逻辑的“最小可行验证”你有没有遇到过这样的场景:在表单里填两个数字,点个按钮,结果却卡在页面上不动?或者更糟——输入1和2,显示出来的却是"12"?这…

2026/10/18 3:52:22 阅读更多 →
JS高德地图设备图标实战:实时位置渲染与Marker管理优化

JS高德地图设备图标实战:实时位置渲染与Marker管理优化

1. 从一张“会说话的地图”说起:设备图标到底在解决什么问题做过物联网监控大屏、车辆调度后台或者共享设备管理平台的人,大概率都绕不开一个需求:把一堆设备的实时位置,用一张地图直观地铺出来。而“基于JS高德地图设置设备图标”…

2026/10/18 3:52:22 阅读更多 →
Unity协程底层原理与生命周期深度解析

Unity协程底层原理与生命周期深度解析

1. 协程不是“多线程”,但比多线程更难讲清楚刚接触 Unity 的开发者,十有八九会在协程(Coroutine)上栽第一个跟头。我见过太多人把StartCoroutine当成“开个后台线程”来用——结果发现 UI 还是卡、计时器不准、对象销毁后协程还在…

2026/10/18 3:52:22 阅读更多 →
从零跑通开源大模型:选型、环境、加载与推理全指南

从零跑通开源大模型:选型、环境、加载与推理全指南

很多人第一次看到“初始大模型”这个说法,第一反应是:是不是得先啃下一堆数学公式和论文?我在刚开始接触时也是这么想的,后来才发现,初始大模型这件事拆开来看,无非是两条线:一条是认知线&#…

2026/10/18 3:51:21 阅读更多 →

日新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 0:55:02 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 14:23:36 阅读更多 →