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/18 3:53:13 阅读更多 →
计算机组成原理(16):定点数与无符号数的加减运算

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

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

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

最新新闻

AIGC视频生成实战指南:从扩散模型到生产管线全解析

AIGC视频生成实战指南:从扩散模型到生产管线全解析

从第一次看到文生图模型把一段文字变成精致画面,我就隐约觉得视频会是下一个突破口。等到真正上手跑通几段AI生成视频,再回头看这个赛道,我的判断变成了一句话:AIGC视频不是AIGC的一个分支,而是AIGC领域真正意义上的未…

2026/10/19 13:17:58 阅读更多 →
STM32F407工业级Modbus RTU通信栈:支持字节序可配CRC与三相电表稳定接入

STM32F407工业级Modbus RTU通信栈:支持字节序可配CRC与三相电表稳定接入

简介:本资源是一套基于STM32F407ZGT6微控制器实现Modbus RTU通信协议的完整嵌入式开发工程,面向嵌入式初学者、工业自动化开发者及高校电类专业实践者,解决智能电表数据可靠读取与传输中的协议解析、硬件接口配置及CRC-16校验等核心问题。压缩…

2026/10/19 13:17:58 阅读更多 →
数据结构查找算法复习:从顺序查找到哈希表的演进主线与ASL

数据结构查找算法复习:从顺序查找到哈希表的演进主线与ASL

临近期末,复习数据结构第九章“查找”的同学,很多都会掉进同一个坑:把顺序查找、二分查找、二叉排序树、AVL、B树、哈希表当成一堆相互独立的算法,挨个背定义、背复杂度、背公式。背完合上书,拿到一道综合题还是不知道…

2026/10/19 13:17:58 阅读更多 →
单机持久化方案设计:从WAL、fsync到崩溃恢复的可靠性与实践

单机持久化方案设计:从WAL、fsync到崩溃恢复的可靠性与实践

做后端这些年,我一直信奉一句话:单机可靠性是技术架构的地基,而持久化设计是这块地基的钢筋。很多团队一上来就聊分布式、上容器、搞微服务,结果单机层面连“进程突然被 kill 后数据还在不在”这种问题都没摸清楚,上层…

2026/10/19 13:17:58 阅读更多 →
open-code-review:面向工程实践的开源代码审查脚手架

open-code-review:面向工程实践的开源代码审查脚手架

1. 这不是又一个“AI代码审查”玩具:open-code-review 的真实定位与设计哲学你可能已经点开过十几个标着“AI Code Review”的开源项目——它们大多长这样:拖拽一个文件,点击“分析”,然后弹出几条泛泛而谈的建议:“变…

2026/10/19 13:17:58 阅读更多 →
多模态落地与长上下文成本:小模型微调及推理加速实践周报

多模态落地与长上下文成本:小模型微调及推理加速实践周报

这周(3.9~3.15)的深度学习圈子,和前几周相比少了点"又出大新闻"的爆炸感,多了一些闷头干活的务实气氛。我把这周刷过的论文、跑完的实验、踩进去又爬出来的坑归拢了一下,发现几条主线非常清晰:多…

2026/10/19 13:16:51 阅读更多 →

日新闻

频率跟踪型PWM电源设计:臭氧发生器谐振点漂移与软开关实现

频率跟踪型PWM电源设计:臭氧发生器谐振点漂移与软开关实现

简介:本资源为电源技术方向的学术研究文档,聚焦介质阻挡放电型臭氧发生器电源的频率跟踪型PWM控制策略,面向电力电子、高压电源及臭氧应用领域的科研人员与工程技术人员。针对负载呈容性、等效电容随外加电压升高而增大、谐振频率随之漂移的难…

2026/10/19 0:00:47 阅读更多 →
Vibe Coding 遇上 TaoToken:把开发者思维圣殿的灵感流接入统一 Key 通道

Vibe Coding 遇上 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/19 0:00:47 阅读更多 →
HundredCV-Chat话题建模实战教程:利用4,871个内置话题标签构建主题分析系统

HundredCV-Chat话题建模实战教程:利用4,871个内置话题标签构建主题分析系统

【免费下载链接】HundredCV-Chat 项目地址: https://ai.gitcode.com/hf_mirrors/Jax-dan/HundredCV-Chat 点击查看 免费下载 HundredCV-Chat 是一个由 100 位青年简历数据开发而来的中文多轮对话数据集,共包含 24,750 组日常闲聊对话和 4,871 个话题标签…

2026/10/19 0:00:47 阅读更多 →

周新闻

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

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

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

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

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

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

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

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

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

2026/10/19 1:30:52 阅读更多 →

月新闻

我发现了一个新思路:用 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/19 2:54:50 阅读更多 →
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/19 9:10:22 阅读更多 →
黑夜航拍船只数据集训练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/18 12:16:16 阅读更多 →