Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
RT-Thread
自动初始化
模拟器_simulator
RT-Thread 模拟器simulator支持自动初始化机制
发布于 2021-03-13 19:55:25 浏览:1104
订阅该版
[tocm] [RT-Thread 入门学习笔记 - 目录](https://club.rt-thread.org/ask/article/3420.html) ## 前言 - RT-Thread的自动初始化机制,挺好用的,但是,bsp中模拟器simulator,不支持。 - 研究了一下自动初始化机制,发现,可以让pc的模拟器,也可以实现自动初始化 ## 研究过程 - 运行bsp的模拟器,使用vs2019。 - 发现:INIT_BOARD_EXPORT INIT_COMPONENT_EXPORT,没有效果 - 分析代码发现默认不支持PC端的模拟器: ``` /* initialization export */ #ifdef RT_USING_COMPONENTS_INIT typedef int (*init_fn_t)(void); #ifdef _MSC_VER /* we do not support MS VC++ compiler */ #define INIT_EXPORT(fn, level) #else ``` - 经过一番的搜索、验证分析,发现,自动初始化机制如下: 1. 需要使用section(段、节),让编译器把函数指针,放在里面 2. __attribute__((section(x))) 在VS2019上不支持(_MSC_VER) 3. 找到基于VS2019 _MSC_VER的section操作,即可实现自动初始化 4. MSH_CMD_EXPORT,支持模拟器的section的操作,用于导出MSH CMD函数 ## 基于VS2019的section的操作: ``` #pragma section(".rti_fn.$0") #define INIT_EXPORT_LEVEL0(fn) \ __declspec(allocate(".rti_fn.$0")) const init_fn_t __rt_init_##fn = fn ``` - 为啥不直接使用:(".rti_fn." level),因为编译报错 ## 修改代码 ### rtdef.h 修改 ``` /* initialization export */ #ifdef RT_USING_COMPONENTS_INIT typedef int (*init_fn_t)(void); #ifdef _MSC_VER /* we do not support MS VC++ compiler */ #pragma section(".rti_fn.$0") #pragma section(".rti_fn.$1") #pragma section(".rti_fn.$2") #pragma section(".rti_fn.$3") #pragma section(".rti_fn.$4") #pragma section(".rti_fn.$5") #pragma section(".rti_fn.$6") #pragma section(".rti_fn.$0.end") #pragma section(".rti_fn.$1.end") #pragma section(".rti_fn.$6.end") #define INIT_EXPORT_LEVEL0(fn) \ __declspec(allocate(".rti_fn.$0")) const init_fn_t __rt_init_##fn = fn #define INIT_EXPORT_LEVEL0_END(fn) \ __declspec(allocate(".rti_fn.$0.end")) const init_fn_t __rt_init_##fn = fn #define INIT_EXPORT_LEVEL1_END(fn) \ __declspec(allocate(".rti_fn.$1.end")) const init_fn_t __rt_init_##fn = fn #define INIT_EXPORT_LEVEL6_END(fn) \ __declspec(allocate(".rti_fn.$6.end")) const init_fn_t __rt_init_##fn = fn #define INIT_EXPORT_LEVEL1(fn) \ __declspec(allocate(".rti_fn.$1")) const init_fn_t __rt_init_##fn = fn #define INIT_EXPORT_LEVEL2(fn) \ __declspec(allocate(".rti_fn.$2")) const init_fn_t __rt_init_##fn = fn #define INIT_EXPORT_LEVEL3(fn) \ __declspec(allocate(".rti_fn.$3")) const init_fn_t __rt_init_##fn = fn #define INIT_EXPORT_LEVEL4(fn) \ __declspec(allocate(".rti_fn.$4")) const init_fn_t __rt_init_##fn = fn #define INIT_EXPORT_LEVEL5(fn) \ __declspec(allocate(".rti_fn.$5")) const init_fn_t __rt_init_##fn = fn #define INIT_EXPORT_LEVEL6(fn) \ __declspec(allocate(".rti_fn.$6")) const init_fn_t __rt_init_##fn = fn #else #if RT_DEBUG_INIT struct rt_init_desc { const char* fn_name; const init_fn_t fn; }; #define INIT_EXPORT(fn, level) \ const char __rti_##fn##_name[] = #fn; \ RT_USED const struct rt_init_desc __rt_init_desc_##fn RT_SECTION(".rti_fn." level) = \ { __rti_##fn##_name, fn}; #else #define INIT_EXPORT(fn, level) \ RT_USED const init_fn_t __rt_init_##fn RT_SECTION(".rti_fn." level) = fn #endif #endif #else #define INIT_EXPORT(fn, level) #endif /* board init routines will be called in board_init() function */ #ifdef _MSC_VER #define INIT_BOARD_EXPORT(fn) INIT_EXPORT_LEVEL1(fn) #else #define INIT_BOARD_EXPORT(fn) INIT_EXPORT(fn, "1") #endif /* pre/device/component/env/app init routines will be called in init_thread */ /* components pre-initialization (pure software initilization) */ #ifdef _MSC_VER #define INIT_PREV_EXPORT(fn) INIT_EXPORT_LEVEL2(fn) #else #define INIT_PREV_EXPORT(fn) INIT_EXPORT(fn, "2") #endif /* device initialization */ #ifdef _MSC_VER #define INIT_DEVICE_EXPORT(fn) INIT_EXPORT_LEVEL3(fn) #else #define INIT_DEVICE_EXPORT(fn) INIT_EXPORT(fn, "3") #endif /* components initialization (dfs, lwip, ...) */ #ifdef _MSC_VER #define INIT_COMPONENT_EXPORT(fn) INIT_EXPORT_LEVEL4(fn) #else #define INIT_COMPONENT_EXPORT(fn) INIT_EXPORT(fn, "4") #endif /* environment initialization (mount disk, ...) */ #ifdef _MSC_VER #define INIT_ENV_EXPORT(fn) INIT_EXPORT_LEVEL5(fn) #else #define INIT_ENV_EXPORT(fn) INIT_EXPORT(fn, "5") #endif /* appliation initialization (rtgui application etc ...) */ #ifdef _MSC_VER #define INIT_APP_EXPORT(fn) INIT_EXPORT_LEVEL6(fn) #else #define INIT_APP_EXPORT(fn) INIT_EXPORT(fn, "6") #endif ``` ### components.c 修改: ``` static int rti_start(void) { return 0; } #ifdef _MSC_VER INIT_EXPORT_LEVEL0(rti_start); #else INIT_EXPORT(rti_start, "0"); #endif static int rti_board_start(void) { return 0; } #ifdef _MSC_VER INIT_EXPORT_LEVEL0_END(rti_board_start); #else INIT_EXPORT(rti_board_start, "0.end"); #endif static int rti_board_end(void) { return 0; } #ifdef _MSC_VER INIT_EXPORT_LEVEL1_END(rti_board_end); #else INIT_EXPORT(rti_board_end, "1.end"); #endif static int rti_end(void) { return 0; } #ifdef _MSC_VER INIT_EXPORT_LEVEL6_END(rti_end); #else INIT_EXPORT(rti_end, "6.end"); #endif /** * RT-Thread Components Initialization for board */ void rt_components_board_init(void) { #if RT_DEBUG_INIT int result; const struct rt_init_desc *desc; for (desc = &__rt_init_desc_rti_board_start; desc < &__rt_init_desc_rti_board_end; desc ++) { rt_kprintf("initialize %s", desc->fn_name); result = desc->fn(); rt_kprintf(":%d done\n", result); } #else volatile const init_fn_t *fn_ptr; for (fn_ptr = &__rt_init_rti_board_start; fn_ptr < &__rt_init_rti_board_end; fn_ptr++) { if (*fn_ptr != RT_NULL) (*fn_ptr)(); } #endif } /** * RT-Thread Components Initialization */ void rt_components_init(void) { #if RT_DEBUG_INIT int result; const struct rt_init_desc *desc; rt_kprintf("do components initialization.\n"); for (desc = &__rt_init_desc_rti_board_end; desc < &__rt_init_desc_rti_end; desc ++) { rt_kprintf("initialize %s", desc->fn_name); result = desc->fn(); rt_kprintf(":%d done\n", result); } #else volatile const init_fn_t *fn_ptr; for (fn_ptr = &__rt_init_rti_board_end; fn_ptr < &__rt_init_rti_end; fn_ptr ++) { if (*fn_ptr != RT_NULL) (*fn_ptr)(); } #endif } #endif /* RT_USING_COMPONENTS_INIT */ ``` ### 使能:RT_USING_COMPONENTS_INIT 可以配置Kconfig实现定义 ### 在 simulator的:application.c中,增加: ``` void rt_init_thread_entry(void *parameter) { rt_kprintf("Hello RT-Thread!\n"); rt_components_board_init(); rt_components_init(); platform_init(); mnt_init(); ``` ## 增加自动初始化测试例程: ``` #include
int func_a1(void) { rt_kprintf("%s: init ok!\n", __func__); return 0; } int func_a2(void) { rt_kprintf("%s: init ok!\n", __func__); return 0; } int func_a3(void) { rt_kprintf("%s: init ok!\n", __func__); return 0; } int func_a4(void) { rt_kprintf("%s: init ok!\n", __func__); return 0; } int func_a5(void) { rt_kprintf("%s: init ok!\n", __func__); return 0; } int func_a6(void) { rt_kprintf("%s: init ok!\n", __func__); return 0; } int func_a7(void) { rt_kprintf("%s: init ok!\n", __func__); return 0; } int func_a8(void) { rt_kprintf("%s: init ok!\n", __func__); return 0; } INIT_BOARD_EXPORT(func_a1); INIT_PREV_EXPORT(func_a2); INIT_DEVICE_EXPORT(func_a3); INIT_COMPONENT_EXPORT(func_a4); INIT_ENV_EXPORT(func_a5); INIT_APP_EXPORT(func_a6); INIT_DEVICE_EXPORT(func_a7); INIT_ENV_EXPORT(func_a8); ``` ## 功能验证 - 编译通过(最新的RT-Thread 代码:报timegm 未定义,先注释掉) - 运行: ``` \ | / - RT - Thread Operating System / | \ 4.0.3 build Mar 13 2021 2006 - 2021 Copyright by rt-thread team Hello RT-Thread! func_a1: init ok! func_a2: init ok! func_a3: init ok! func_a7: init ok! func_a4: init ok! func_a5: init ok! func_a8: init ok! func_a6: init ok! finsh shell already init. dfs already init. File System on root initialized! [E/DFS] There is no space to mount this file system (elm). File System on sd initialization failed! msh /> ``` - 发现自动初始化的函数,执行了。有些手动执行的函数,可以注释掉了。 ## 总结 - 需要了解VS(Visual Studio)环境下,section的操作。 - 可以借助PC端的工具:OD、Die等工具,分析PE文件,了解生成的执行文件section内容 - 使用OD反编译生成的exe文件,查找函数地址、section ![2021-02-12_204437.png](https://oss-club.rt-thread.org/uploads/20210313/21d139a357050d1547afa4de3c10cf5a.png) - 使用Die,查看exe文件的section ![2021-03-13_195445.png](https://oss-club.rt-thread.org/uploads/20210313/46b0e6ca32648a2df02e607a6fdbf11b.png) ![2021-03-13_195504.png](https://oss-club.rt-thread.org/uploads/20210313/df17e924e91b0234399c0c304b48b00b.png)
0
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
张世争
学以致用
文章
131
回答
805
被采纳
174
关注TA
发私信
相关文章
1
RT-THREAD在STM32H747平台上移植lwip
2
正点原子miniSTM32开发板读写sdcard
3
反馈rtt串口驱动对低功耗串口lpuart1不兼容的问题
4
Keil MDK 移植 RT-Thread Nano
5
RT1061/1052 带 RTT + LWIP和LPSPI,有什么坑要注意吗?
6
RT thread HID 如何收发数据
7
求一份基于RTT系统封装好的STM32F1系列的FLASH操作程序
8
RT-Thread修改项目名称之后不能下载
9
rt-studio编译c++
10
有木有移植rt-thread(nano)到riscv 32位MCU上
推荐文章
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组件
热门标签
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
WIZnet_W5500
UART
ota在线升级
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
Debug
编译报错
SFUD
msh
rt_mq_消息队列_msg_queue
keil_MDK
ulog
MicroPython
C++_cpp
本月问答贡献
出出啊
1517
个答案
342
次被采纳
小小李sunny
1443
个答案
289
次被采纳
张世争
805
个答案
174
次被采纳
crystal266
547
个答案
161
次被采纳
whj467467222
1222
个答案
148
次被采纳
本月文章贡献
出出啊
1
篇文章
4
次点赞
小小李sunny
1
篇文章
1
次点赞
张世争
1
篇文章
1
次点赞
crystal266
2
篇文章
2
次点赞
whj467467222
2
篇文章
1
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部