Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
RT-Thread一般讨论
自动初始化
[新功能] 组件初始化
发布于 2013-06-22 07:50:15 浏览:33622
订阅该版
老的代码: ```c static void rt_init_thread_entry(void *parameter) { #ifdef RT_USING_PM efm32gg_pm_hw_init(); rt_hw_serial_pm_init(); #endif /* RT_USING_PM */ rt_hw_userled_init(); #ifdef RT_USING_MTD_NAND rt_hw_mtd_nand_init(); #endif /* RT_USING_MTD_NAND */ #ifdef RT_USING_LOGTRACE /* initialize log trace component */ log_trace_init(); log_trace_set_device(RT_CONSOLE_DEVICE_NAME); #ifdef LOG_TRACE_NAND /* set exception handler */ rt_hw_exception_install(exception_handle); #endif log_trace(LOG_TRACE_INFO"log trace initialized! "); #endif /* RT_USING_LOGTRACE */ /* File System Initialization */ #ifdef RT_USING_DFS { /* initialize the device file system */ dfs_init(); #ifdef RT_USING_DFS_ELMFAT /* initialize the elm chan FatFs file system*/ elm_init(); #endif /* RT_USING_DFS_ELMFAT */ #ifdef RT_USING_NFTL nftl_attach("nand0"); if (dfs_mount("nand0", "/", "elm", 0, 0) == 0) { rt_kprintf("Mount FatFs file system to root, Done! "); } else { rt_kprintf("Mount FatFs file system failed. "); } #endif #ifdef RT_USING_RAMFS dfs_ramfs_init(); { struct dfs_ramfs* ramfs; ramfs = dfs_ramfs_create((rt_uint8_t*)EFM32_RAMFS_BEGIN, EFM32_RAMFS_SIZE); if (ramfs != RT_NULL) { if (dfs_mount(RT_NULL, "/ramfs", "ram", 0, ramfs) == 0) { rt_kprintf("Mount RAMDisk done! "); } else { rt_kprintf("Mount RAMDisk failed. "); } } } #endif } #endif /* RT_USING_DFS */ /* Initialize I2C bus */ #ifdef RT_USING_I2C rt_i2c_core_init(); rt_hw_iicbus_init(); #endif /* RT_USING_I2C */ /* Initialize RTC */ #ifdef RT_USING_RTC #ifdef RT_USING_ALARM rt_alarm_system_init(); #endif #ifdef SH3H_USING_RX8025 rt_hw_rx8025_init(EFM32GG_IICBUS1_NAME); #endif #ifdef EFM32GG_USING_CHIP_RTC rt_hw_rtc_init(); #endif #ifdef SH3H_USING_RX8564 rt_hw_rx8564_init(EFM32GG_IICBUS0_NAME); #endif #endif /* RT_USING_RTC */ /* Initialize Watchdog */ #ifdef RT_USING_WDT #ifdef EFM32GG_USING_CHIP_WDT rt_hw_wdt_init(); #endif #ifdef SH3H_USING_X4043_WDT rt_hw_x4043_init(EFM32GG_IICBUS1_NAME); #endif #ifdef SH3H_USING_STM6822_WDT rt_hw_stm6822_init(); #endif wdtmgr_init(SH3H_STM6822_WDT_NAME); #endif /* RT_USING_WDT */ #ifdef RT_USING_LWIP /* initialize lwip system */ eth_system_device_init(); lwip_system_init(); rt_kprintf("TCP/IP initialized! "); #ifdef RT_LWIP_PPP /* initialize ppp protocol */ pppInit(); modem_system_init(); modem_mg323_init(); modem_mc323_init(); modem_gl868_init(); #endif /* RT_LWIP_PPP */ #endif /* RT_USING_LWIP */ #ifdef RT_USING_USB_DEVICE rt_hw_usbd_init(); rt_usb_device_init("usbd"); #if defined(RT_USING_LWIP) && defined(RT_USB_DEVICE_RNDIS) { extern void dhcpd_start(void); extern void ssdp_start(void); extern void telnet_srv(void); dhcpd_start(); ssdp_start(); telnet_srv(); } #ifdef RT_USING_WEBNET { extern void httpd_init(void); httpd_init(); } #endif /* RT_USING_WEBNET */ #endif // RT_USING_LWIP && RT_USB_DEVICE_RNDIS #endif /* RT_USING_USB_DEVICE */ #ifdef RT_USING_PM { rt_pm_release(PM_RUNNING_MODE); rt_pm_release(PM_SLEEP_MODE); rt_pm_request(PM_TIMER_MODE); rt_hw_plug_init(); } #endif /* RT_USING_PM */ /* init finsh */ #ifdef RT_USING_FINSH finsh_system_init(); finsh_set_device(RT_CONSOLE_DEVICE_NAME); #endif /* RT_USING_FINSH */ } ``` 其中的宏条件、宏定义够多够乱!为了实现不同组件的独立性,不得不加无数的宏条件,“貌似”没什么好办法,但其实这些初始化是很规律性的,或者最简单的一点:编译进代码中的,需要初始化,不编译的自然不需要初始化。
查看更多
39
个回答
默认排序
按发布时间排序
bernard
2013-06-22
这家伙很懒,什么也没写!
原来有一个components.c,期望它可以进行各个组件的初始化,期望它能够做到: ```c #include
static void rt_init_thread_entry(void *parameter) { rt_components_init(); } ``` 然后用户的代码自然也就清晰了,再乱也只是乱在rt_components_init()的实现里: ```c /** * RT-Thread Components Initialization */ void rt_components_init(void) { #ifdef RT_USING_MODULE rt_system_module_init(); #endif #ifdef RT_USING_FINSH /* initialize finsh */ finsh_system_init(); finsh_set_device(RT_CONSOLE_DEVICE_NAME); #endif #ifdef RT_USING_LWIP /* initialize lwip stack */ /* register ethernetif device */ eth_system_device_init(); /* initialize lwip system */ lwip_system_init(); #endif #ifdef RT_USING_DFS /* initialize the device file system */ dfs_init(); #ifdef RT_USING_DFS_ELMFAT /* initialize the elm chan FatFS file system*/ elm_init(); #endif #if defined(RT_USING_DFS_NFS) && defined(RT_USING_LWIP) /* initialize NFSv3 client file system */ nfs_init(); #endif #ifdef RT_USING_DFS_YAFFS2 dfs_yaffs2_init(); #endif #ifdef RT_USING_DFS_UFFS dfs_uffs_init(); #endif #ifdef RT_USING_DFS_JFFS2 dfs_jffs2_init(); #endif #ifdef RT_USING_DFS_ROMFS dfs_romfs_init(); #endif #ifdef RT_USING_DFS_DEVFS devfs_init(); #endif #endif /* end of RT_USING_DFS */ #ifdef RT_USING_NEWLIB libc_system_init(RT_CONSOLE_DEVICE_NAME); #else /* the pthread system initialization will be initiallized in libc */ #ifdef RT_USING_PTHREADS pthread_system_init(); #endif #endif #ifdef RT_USING_RTGUI rtgui_system_server_init(); #endif #ifdef RT_USING_USB_HOST rt_usb_host_init(); #endif return; } ``` 一样的宏条件,一样的糟糕的代码。特别是,一个巨大的问题: components.c属于rt-thread里的代码,如果每个用户都需要自己再去修改里面的代码, 那么和把初始化代码放在application.c中没有本质的区别。
bernard
2013-06-22
这家伙很懒,什么也没写!
components.c的缺陷在于,依然不能摆脱宏条件的实现方式,另一个,用户不能够很方便的加入到初始化的序列中。 不过finsh shell中灵活地把一个函数输出到命令行中,为我们提供一丝灵感。既然能够让用户的程序输出到命令行中,那么也自然能够让用户初始化函数输出到 组件初始化 序列中。 finsh shell的实现方式是把函数入口放到了一个独立的section中,然后再通过编译+链接过程中,获取这个section首地址、尾地址的形式,从而实现系统中所有输出符号的序列。同时为了能够在shell中按照函数名称来查找,在这个独立的section中实际填写的是: ```c /* system call table */ struct finsh_syscall { const char* name; /* the name of system call */ #if defined(FINSH_USING_DESCRIPTION) && defined(FINSH_USING_SYMTAB) const char* desc; /* description of system call */ #endif syscall_func func; /* the function address of system call */ }; ``` 这样一个结构体。记得论坛上好像有人提及到FINSH_USING_DESCRIPTION和FINSH_USING_SYMTAB的意义来着,其实就是决定shell中列出的命令函数列表,是否有帮助、描述信息。 name给出了函数的名称(所以也能够使用FINSH_FUNCTION_EXPORT_ALIAS宏把一个函数名更改成一个别名),shell中就是使用这个名称来查找对应的func函数指针。section FSymTab存放的则是这一个个struct finsh_syscall结构体。 好像有些扯远了,回过头来说组件初始化。 类似的这样的方式,Linux也提供了一些借鉴,把一个函数的地址(注意是函数地址,而不是函数本身)输出到一个独立的section中,同时按照一定顺序进行排列,例如: ``` .rti_fn.0 .rti_fn.1 .rti_fn.2 ... .rti_fn.7 ``` 这样几个section(这样几个不同的section也给出了排列的顺序)。同时把.rti_fn.0和.rti_fn.7保留给系统使用,分别定义出两个桩放置在这两个点上。也可以按照RT-Thread的形式定义简化的宏: ```c typedef int (*init_fn_t)(void); #define INIT_EXPORT(fn, level) const init_fn_t __rt_init_##fn SECTION(".rti_fn."level) = fn #define INIT_BOARD_EXPORT(fn) INIT_EXPORT(fn, "1") #define INIT_CPU_EXPORT(fn) INIT_EXPORT(fn, "2") #define INIT_DEVICE_EXPORT(fn) INIT_EXPORT(fn, "3") #define INIT_COMPONENT_EXPORT(fn) INIT_EXPORT(fn, "4") #define INIT_FS_EXPORT(fn) INIT_EXPORT(fn, "5") #define INIT_APP_EXPORT(fn) INIT_EXPORT(fn, "6") ``` INIT_EXPORT宏用于输出一个函数到初始化序列中,相应的可以定义一些更简化的宏。 这样两个桩可以定义成: ```c static int rti_start(void) { return 0; } INIT_EXPORT(rti_start, "0"); static int rti_end(void) { return 0; } INIT_EXPORT(rti_end,"7"); ``` 根据这两个桩的位置,简化的rt_components_init()函数就可以变成: ```c void rt_components_init(void) { const init_fn_t* fn_ptr; for (fn_ptr = &__rt_init_rti_start; fn_ptr < &__rt_init_rti_end; ) { (*fn_ptr)(); fn_ptr ++; } } ``` 世界清静了!
aozima
2013-06-22
调网络不抓包,调I2C等时序不上逻辑分析仪,就像电工不用万用表!多用整理的好的文字,比截图更省流量,还能在整理过程中思考。
这个要顶。
xiao苦
2013-06-22
这家伙很懒,什么也没写!
这个方式确实很不错呢, 不过如果关掉finsh,这个还能这么用吗???
bernard
2013-06-22
这家伙很懒,什么也没写!
这个功能和finsh无关,独立的,只需要把组件管理打开,这个就打开了。今天晚上完成代码,然后推到github上去
geniusgogo
认证专家
2013-06-23
这家伙很懒,什么也没写!
>``` >.rti_fn.0 > .rti_fn.1 >.rti_fn.2 >... >.rti_fn.7 ``` 如何保证这8个section是按顺序排列的? [s:179]
shaolin
2013-06-23
这家伙很懒,什么也没写!
>如何保证这8个section是按顺序排列的? [s:179] 这个就靠编译器了。
bernard
2013-06-23
这家伙很懒,什么也没写!
这个顺序,GNU GCC、Keil MDK是没有问题的。其它还有待验证,我的机器装不了IAR啊
geniusgogo
认证专家
2013-06-23
这家伙很懒,什么也没写!
>``` >finsh_system_init(); >finsh_set_device(RT_CONSOLE_DEVICE_NAME); ``` 像这种有初始化顺序的组合步骤,在符号导出之后不好控制他们被调用的次序吧? [s:194]
aozima
2013-06-23
调网络不抓包,调I2C等时序不上逻辑分析仪,就像电工不用万用表!多用整理的好的文字,比截图更省流量,还能在整理过程中思考。
测试了一下,MDK还要需要像finsh一样 “--keep __rt_init*” GCC和IAR中还不行,链接时被扔掉了。
撰写答案
登录
注册新账号
关注者
0
被浏览
33.6k
关于作者
bernard
这家伙很懒,什么也没写!
提问
414
回答
5939
被采纳
76
关注TA
发私信
相关问题
1
有关动态模块加载的一篇论文
2
最近的调程序总结
3
晕掉了,这么久都不见layer2的踪影啊
4
继续K9ii的历程
5
[GUI相关] FreeType 2
6
[GUI相关]嵌入式系统中文输入法的设计
7
20081101 RT-Thread开发者聚会总结
8
嵌入式系统基础
9
linux2.4.19在at91rm9200 上的寄存器设置
10
[转]基于嵌入式Linux的通用触摸屏校准程序
推荐文章
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
使用百度AI助手辅助编写一个rt-thread下的ONVIF设备发现功能的功能代码
2
RT-Thread 发布 EtherKit开源以太网硬件!
3
rt-thread使用cherryusb实现虚拟串口
4
《C++20 图形界面程序:速度与渲染效率的双重优化秘籍》
5
《原子操作:程序世界里的“最小魔法单位”解析》
热门标签
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
ota在线升级
UART
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
Debug
编译报错
msh
SFUD
keil_MDK
rt_mq_消息队列_msg_queue
at_device
ulog
C++_cpp
本月问答贡献
踩姑娘的小蘑菇
7
个答案
3
次被采纳
张世争
8
个答案
2
次被采纳
rv666
5
个答案
2
次被采纳
用户名由3_15位
11
个答案
1
次被采纳
KunYi
6
个答案
1
次被采纳
本月文章贡献
程序员阿伟
6
篇文章
2
次点赞
hhart
3
篇文章
4
次点赞
大龄码农
1
篇文章
2
次点赞
ThinkCode
1
篇文章
1
次点赞
Betrayer
1
篇文章
1
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部