)
一.软件准备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升级成功