Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
RTT死机
编译链接
自动初始化
[BUG]RT-Stdio工程,自动初始化机制,BUG
发布于 2023-01-02 15:02:51 浏览:844
订阅该版
RTT中,某些组件的初始化函数,使用指定的宏进行修饰后,能够在启动的时候,进行隐式调用执行,我们姑且称之为自动初始化机制。 这种系统性的代码,按理说,我作为一个使用者是不用去研究的。 然而在使用过程中,出现了这样的情况: ==>在RT-Studio设置界面中,勾选(点亮)任何组件(DFS,elm,lua,mpy等),编译烧写后,都会死机!!! 我使用仿真器对单板代码一行一行地仿真执行,发现问题果然在自动初始化机制上面。 代码执行到rt_components_init()这个函数,便死机了。 我一行一行去跟踪,确认了,是在读函数后,跳转时死机的,也就是这一句: ```c result = desc->fn(); ``` rtdef.h头文件里面,我们发现几个这样的宏 ```c /* board init routines will be called in board_init() function */ #define INIT_BOARD_EXPORT(fn) INIT_EXPORT(fn, "1") /* pre/device/component/env/app init routines will be called in init_thread */ /* components pre-initialization (pure software initialization) */ #define INIT_PREV_EXPORT(fn) INIT_EXPORT(fn, "2") /* device initialization */ #define INIT_DEVICE_EXPORT(fn) INIT_EXPORT(fn, "3") /* components initialization (dfs, lwip, ...) */ #define INIT_COMPONENT_EXPORT(fn) INIT_EXPORT(fn, "4") /* environment initialization (mount disk, ...) */ #define INIT_ENV_EXPORT(fn) INIT_EXPORT(fn, "5") /* application initialization (rtgui application etc ...) */ #define INIT_APP_EXPORT(fn) INIT_EXPORT(fn, "6") ``` 这应该是分先后,分初始化等级,一共6个等级。 而在components.c中,却只实现了2个等级,我修改代码,将除了"board"以外的5个等级都编写一遍。也许以后用得上。 ```c static int rti_start(void) { return 0; } INIT_EXPORT(rti_start, "0"); static int rti_board_start(void) { return 0; } INIT_EXPORT(rti_board_start, "0.end"); static int rti_board_end(void) { return 0; } INIT_EXPORT(rti_board_end, "1.end"); /*-----------------------------------*/ static int rti_prev_start(void) { return 0; } INIT_EXPORT(rti_prev_start, "2"); static int rti_prev_end(void) { return 0; } INIT_EXPORT(rti_prev_end, "2.end"); /*-----------------------------------*/ static int rti_device_start(void) { return 0; } INIT_EXPORT(rti_device_start, "3"); static int rti_device_end(void) { return 0; } INIT_EXPORT(rti_device_end, "3.end"); /*-----------------------------------*/ static int rti_component_start(void) { return 0; } INIT_EXPORT(rti_component_start, "4"); static int rti_component_end(void) { return 0; } INIT_EXPORT(rti_component_end, "4.end"); /*-----------------------------------*/ static int rti_env_start(void) { return 0; } INIT_EXPORT(rti_env_start, "5"); static int rti_env_end(void) { return 0; } INIT_EXPORT(rti_env_end, "5.end"); /*-----------------------------------*/ static int rti_app_start(void) { return 0; } INIT_EXPORT(rti_app_start, "6"); static int rti_end(void) { return 0; } INIT_EXPORT(rti_end, "6.end"); static void rt_auto_init_prev(void) { #if RT_DEBUG_INIT int result; const struct rt_init_desc *desc; rt_kprintf("rt_auto_init_prev\r\n"); for (desc = &__rt_init_desc_rti_prev_start; desc < &__rt_init_desc_rti_prev_end; desc ++) { //rti_prev_start rt_kprintf("initialize %s", desc->fn_name); result = desc->fn(); rt_kprintf(":%d done\n", result); } #else #warring "please write code !" #endif /* RT_DEBUG_INIT */ } void rt_auto_init_device(void) { #if RT_DEBUG_INIT int result; const struct rt_init_desc *desc; rt_kprintf("rt_auto_init_device\r\n"); for (desc = &__rt_init_desc_rti_device_start; desc < &__rt_init_desc_rti_device_end; desc ++) { rt_kprintf("initialize %s", desc->fn_name); result = desc->fn(); rt_kprintf(":%d done\n", result); } #else #warring "please write code !" #endif /* RT_DEBUG_INIT */ } static void rt_auto_init_component(void) { #if RT_DEBUG_INIT int result; const struct rt_init_desc *desc; rt_kprintf("rt_auto_init_component\r\n"); for (desc = &__rt_init_desc_rti_component_start; desc < &__rt_init_desc_rti_component_end; desc ++) { rt_kprintf("initialize %s", desc->fn_name); result = desc->fn(); rt_kprintf(":%d done\n", result); } #else #warring "please write code !" #endif /* RT_DEBUG_INIT */ } static void rt_auto_init_env(void) { #if RT_DEBUG_INIT int result; const struct rt_init_desc *desc; rt_kprintf("rt_auto_init_env\r\n"); for (desc = &__rt_init_desc_rti_env_start; desc < &__rt_init_desc_rti_env_end; desc ++) { rt_kprintf("initialize %s", desc->fn_name); result = desc->fn(); rt_kprintf(":%d done\n", result); } #else #warring "please write code !" #endif /* RT_DEBUG_INIT */ } static void rt_auto_init_app(void) { #if RT_DEBUG_INIT int result; const struct rt_init_desc *desc; rt_kprintf("rt_auto_init_env\r\n"); for (desc = &__rt_init_desc_rti_app_start; desc < &__rt_init_desc_rti_end; desc ++) { rt_kprintf("initialize %s", desc->fn_name); result = desc->fn(); rt_kprintf(":%d done\n", result); } #else #warring "please write code !" #endif /* RT_DEBUG_INIT */ } ``` 然后修改原函数 ```c void rt_components_init(void) { rt_auto_init_prev(); rt_auto_init_device(); rt_auto_init_component(); rt_auto_init_env(); rt_auto_init_app(); } ``` 这个时候,按理说,开机后可以清晰看到各等级初始化的过程了。 在RT-Studio中,使能虚拟文件系统,使能elm。 ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20230102/61be9e0011a2464a8ea105e9ac0e29d2.png) 编译,烧写,启动后在初始化rti_component阶段死机,日志如下: ```c \ | / - RT - Thread Operating System / | \ 4.1.1 build Jan 2 2023 14:42:51 2006 - 2022 Copyright by RT-Thread team rt_auto_init_prev initialize rti_prev_start:0 done initialize rt_hw_spi_flash_with_sfud_initrt_hw_spi_flash_with_sfud_init -> 55 [I/SFUD] Find a Winbond flash chip. Size is 4194304 bytes. [I/SFUD] wind25qx flash device is initialize success. [I/SFUD] Probe SPI flash wind25qx by SPI device spi00 success. SPI_FLASH_CHIP:wind25qx SPI_FLASH_DEVICE_NAME:spi00 rt_hw_spi_flash_with_sfud_init -> 65 :0 done rt_auto_init_device initialize rti_device_start:0 done rt_auto_init_component initialize rti_component_start:0 done initialize : 0x000f0000 r00: 0x0000000c r01: 0x000000b5 r02: 0x0000000c r03: 0x00020b3c r04: 0xdeadbeef r05: 0xdeadbeef r06: 0xdeadbeef r07: 0x20002c50 r08: 0xdeadbeef r09: 0xdeadbeef r10: 0xdeadbeef r11: 0xdeadbeef r12: 0xffffffff lr: 0x00001325 pc: 0x00020b3c hard fault on thread: main thread pri status sp stack size max used left tick error -------- --- ------- ---------- ---------- ------ ---------- --- tidle0 31 ready 0x00000044 0x00000100 26% 0x00000020 OK main 10 running 0x00000044 0x00000800 25% 0x00000009 OK usage fault: SCB_CFSR_UFSR:0x02 INVSTATE ``` 对map文件进行分析,被修饰为自动初始化的函数,已经成功映射装填在对应的"x.start","x.end"之中: ```c *(SORT(.rti_fn*)) .rti_fn.0 0x00021c94 0x8 ./rt-thread/src/components.o 0x00021c94 __rt_init_desc_rti_start .rti_fn.0.end 0x00021c9c 0x8 ./rt-thread/src/components.o 0x00021c9c __rt_init_desc_rti_board_start .rti_fn.1 0x00021ca4 0x8 ./drivers/drv_gpio.o 0x00021ca4 __rt_init_desc_rt_hw_pin_init .rti_fn.1 0x00021cac 0x8 ./drivers/drv_spi.o 0x00021cac __rt_init_desc_rt_hw_spi_init .rti_fn.1 0x00021cb4 0x8 ./drivers/drv_uart.o 0x00021cb4 __rt_init_desc_rt_hw_uart_init .rti_fn.1.end 0x00021cbc 0x8 ./rt-thread/src/components.o 0x00021cbc __rt_init_desc_rti_board_end .rti_fn.2 0x00021cc4 0x8 ./rt-thread/src/components.o 0x00021cc4 __rt_init_desc_rti_prev_start .rti_fn.2 0x00021ccc 0x8 ./drivers/drv_spi_flash.o 0x00021ccc __rt_init_desc_rt_hw_spi_flash_with_sfud_init .rti_fn.2.end 0x00021cd4 0x8 ./rt-thread/src/components.o 0x00021cd4 __rt_init_desc_rti_prev_end .rti_fn.3 0x00021cdc 0x8 ./rt-thread/src/components.o 0x00021cdc __rt_init_desc_rti_device_start .rti_fn.3.end 0x00021ce4 0x8 ./rt-thread/src/components.o 0x00021ce4 __rt_init_desc_rti_device_end .rti_fn.4 0x00021cec 0x8 ./rt-thread/src/components.o 0x00021cec __rt_init_desc_rti_component_start .rti_fn.4 0x00021cf4 0x4 ./rt-thread/components/dfs/src/dfs.o 0x00021cf4 __rt_init_dfs_init .rti_fn.4 0x00021cf8 0x8 ./rt-thread/components/dfs/filesystems/elmfat/dfs_elm.o 0x00021cf8 __rt_init_desc_elm_init .rti_fn.4.end 0x00021d00 0x8 ./rt-thread/src/components.o 0x00021d00 __rt_init_desc_rti_component_end .rti_fn.5 0x00021d08 0x8 ./rt-thread/src/components.o 0x00021d08 __rt_init_desc_rti_env_start .rti_fn.5.end 0x00021d10 0x8 ./rt-thread/src/components.o 0x00021d10 __rt_init_desc_rti_env_end .rti_fn.6 0x00021d18 0x8 ./rt-thread/src/components.o 0x00021d18 __rt_init_desc_rti_app_start .rti_fn.6 0x00021d20 0x8 ./rt-thread/components/finsh/shell.o 0x00021d20 __rt_init_desc_finsh_system_init .rti_fn.6.end 0x00021d28 0x8 ./rt-thread/src/components.o 0x00021d28 __rt_init_desc_rti_end 0x00021d30 __rt_init_end = . 0x00021d30 . = ALIGN (0x4) 0x00021d30 . = ALIGN (0x4) 0x00021d30 _etext = . 0x00021d30 __exidx_start = . ``` 解决办法, ①找到dfs.c,注释掉dfs_init函数自动初始化修饰的代码。 ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20230102/29a091f03a97f00c787fc4f4ed00119d.png) ②找到dfs_elm.c,注释掉elm_init函数自动初始化修饰的代码。 ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20230102/8b396d6baebc19ec32228afe69f558bf.png) ③在components.c中,显式调用这两个函数。死机的情况解除。 ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20230102/2d11d97326ae620e9b7817eca8dae817.png) 最后,系统正常启动,dfs,elm功能皆正常。 ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20230102/b0cac0143bd7c48ed4e022356fadce94.png) 本帖子编写于2023年1月2日, 桌面运行环境:win10 X64 RT-Studio 版本: 2.2.6 芯片平台:华芯微特SWM320 内存大小:128KB 存储大小:512KB
查看更多
出出啊
2023-01-03
恃人不如自恃,人之为己者不如己之自为也
目测你的map文件里的函数地址不多啊。 看你的调试信息,你应该开启了 `RT_DEBUG_INIT` 所以,`struct rt_init_desc` 应该包含两个元素。map 里面的地址多数是占用了 8 个字节,唯独 `__rt_init_dfs_init` 这个函数地址只占用了 4 个字节。貌似是在 dfs.c 文件里 `RT_DEBUG_INIT` 宏失效了。 可以有两个办法测试一下我上面的猜想。 一、预编译错误,确定宏定义有效 ``` #if RT_DEBUG_INIT #error "RT_DEBUG_INIT" #endif ``` 二、多添加一个无用函数在 dfs_init 之前 ``` int dfs_none(void) { return 0; } INIT_PREV_EXPORT(dfs_init); int dfs_init(void) { ...... ```
2
个回答
默认排序
按发布时间排序
张世争
2023-01-03
学以致用
- 自动初始化机制,不能保证相同等级的初始化次序,所以有初始化次序依赖的,建议手动初始化或调整初始化次序,或者关闭自动初始化机制 - 当前应该是与audo 驱动产生了初始化次序的依赖
撰写答案
登录
注册新账号
关注者
2
被浏览
844
关于作者
LinjieGuo
这家伙很懒,什么也没写!
提问
4
回答
3
被采纳
0
关注TA
发私信
相关问题
1
RT-Thread Studio在编译 Nano项目时报错?
2
文件夹没纳入编译,只能强制解锁
3
在程序添加完fal_init()接口之后,编译就报错了
4
怎样设置RT_studio编译时将代码从指定地址存放
5
rt-smart SCONS 怎么把kernel文件夹编译进去的
6
链接时找不到 exit 和 sbrk 等符号
7
使用ENV scons -j8编译和keil编译同一份工程目标bin文件差异很大
8
RT-Thread有没有像keil这样的编译前自定义执行的操作
9
rtthread studio编译问题
10
链接脚本中使用 ENTRY 的功能?
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
最新文章
1
RT-Thread项目助手v0.2.0 - 支持Env Windows
2
RttreadV5.10上,GD32F450Z RTC时间显示问题
3
rt-smart启动流程分析
4
EtherKit快速上手PROFINET
5
RTThread USB转串口无法接收数据
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
UART
WIZnet_W5500
ota在线升级
PWM
cubemx
flash
freemodbus
BSP
packages_软件包
潘多拉开发板_Pandora
定时器
ADC
flashDB
GD32
socket
编译报错
中断
Debug
rt_mq_消息队列_msg_queue
SFUD
msh
keil_MDK
ulog
MicroPython
C++_cpp
本月问答贡献
出出啊
1517
个答案
342
次被采纳
小小李sunny
1444
个答案
290
次被采纳
张世争
813
个答案
177
次被采纳
crystal266
547
个答案
161
次被采纳
whj467467222
1222
个答案
149
次被采纳
本月文章贡献
出出啊
1
篇文章
2
次点赞
小小李sunny
1
篇文章
1
次点赞
张世争
1
篇文章
3
次点赞
crystal266
2
篇文章
2
次点赞
whj467467222
2
篇文章
2
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部