一筷黔、文件系統(tǒng)
- RT-Thread 文件系統(tǒng)結(jié)構(gòu)圖
- 最頂層是一套面向嵌入式系統(tǒng)面殖,專門優(yōu)化過(guò)的設(shè)備虛擬文件系統(tǒng) POSIX 文件接口
- 中間層是各種文件系統(tǒng)的實(shí)現(xiàn)
- 比如 ELM FatFS、RomFS、devfs刷晋、RamFS记焊、Yaffs2袱讹、Uffs2面睛、JFFS2 、NFS 等
- 最底層是各類存儲(chǔ)設(shè)備驅(qū)動(dòng)
- 初始化存儲(chǔ)設(shè)備并向上層提供存儲(chǔ)設(shè)備的驅(qū)動(dòng)接口冲甘。存儲(chǔ)設(shè)備的類型可能是 SPI Flash绩卤,SD卡 等
1.文件系統(tǒng)的移植
1)開(kāi)啟/配置 DFS 框架
-
進(jìn)入menuconfig : RT-Thread Components → Device virtual file system
- [x] Using device virtual file system : 使用設(shè)備虛擬文件系統(tǒng),即 RT-Thread 文件系統(tǒng)江醇。
- [x] Using working directory : 打開(kāi)這個(gè)選項(xiàng)濒憋,在 finsh/msh 中就可以使用基于當(dāng)前工作目錄的相對(duì)路徑。
- [ ] The maximal number of mounted file system : 最大掛載文件系統(tǒng)的數(shù)量嫁审。
- [ ] The maximal number of file system type : 最大支持文件系統(tǒng)類型的數(shù)量。
- [ ] The maximal number of opened files : 打開(kāi)文件的最大數(shù)量赖晶。
- [x] Enable elm-chan fatfs : 使用 elm-chan FatFs律适,用于掛載在spi flash等存儲(chǔ)設(shè)備上。
- elm-chan's FatFs, Generic FAT Filesystem Module : elm-chan 文件系統(tǒng)的配置項(xiàng)遏插。
- [x] Using devfs for device objects : 開(kāi)啟 devfs 文件系統(tǒng)捂贿。
- [ ] Enable BSD socket operated by file system API : 使 BSD socket 可以使用文件系統(tǒng)的 API 來(lái)管理,比如讀寫操作和 select/poll 的 POSIX API 調(diào)用胳嘲。
- [x] Enable ReadOnly file system on flash : 在 Flash 上使用只讀文件系統(tǒng)RomFS厂僧。
- [ ] Enable RAM file system : 使用 RAM 文件系統(tǒng)。
- [ ] Enable UFFS file system: Ultra-low-cost Flash File System :使用 UFFS了牛。
- [ ] Enable JFFS2 file system : 使用 JFFS2 文件系統(tǒng)颜屠。
- [ ] Using NFS v3 client file system :使用 NFS 文件系統(tǒng)。
配置和指定文件系統(tǒng)
2)存儲(chǔ)設(shè)備驅(qū)動(dòng)初始化
根據(jù)所使用的儲(chǔ)存設(shè)備鹰祸,如 SPI Flash甫窟,SD卡,初始化其驅(qū)動(dòng)
如:RT-Thread Components → Device Drivers 界面中選中 Using SPI Bus/Device device drivers 以及 Using Serial Flash Universal Driver 選項(xiàng)蛙婴,
-
檢查儲(chǔ)存設(shè)備驅(qū)動(dòng)
編譯程序并下載到開(kāi)發(fā)板上
list_device #查看是否識(shí)別到有spi 驅(qū)動(dòng) sf probe xxx #檢測(cè)spi設(shè)備接口下是否有 spi flash sf bench yes #對(duì)存儲(chǔ)設(shè)備進(jìn)行測(cè)試
3)創(chuàng)建存儲(chǔ)設(shè)備
由于只有塊設(shè)備類型的設(shè)備才能和文件系統(tǒng)對(duì)接粗井,所以需要根據(jù) SPI Device 找到 SPI Flash 設(shè)備,并創(chuàng)建與其對(duì)應(yīng)的 Block Device街图。
-
在drv_spi_flash.c文件中添加如下函數(shù)浇衬,注冊(cè)塊設(shè)備
static int rt_hw_spi_flash_with_sfud_init(void) { //使用spi50 設(shè)備接口注冊(cè)W25Q256塊設(shè)備 if (RT_NULL == rt_sfud_flash_probe("W25Q256", "spi50")) { return RT_ERROR; }; return RT_EOK; } INIT_COMPONENT_EXPORT(rt_hw_spi_flash_with_sfud_init);
-
重新編譯下載程序,使用list_device命令可以找到W25Q256設(shè)備
2.文件系統(tǒng)使用
1)文件系統(tǒng)的初始化
- 初始化 DFS 框架
- 初始化文件系統(tǒng)必須的數(shù)據(jù)表餐济,以及互斥鎖
- 由dfs_init函數(shù)完成
- 初始化具體文件系統(tǒng)
- 將所選擇的
elm FatFS
等文件系統(tǒng)的操作函數(shù)注冊(cè)到 DFS 框架中 - 由elm_init等函數(shù)完成
- 將所選擇的
- 初始化存儲(chǔ)設(shè)備
2)在存儲(chǔ)設(shè)備創(chuàng)建文件系統(tǒng)
存儲(chǔ)設(shè)備上需要先創(chuàng)建相應(yīng)的文件系統(tǒng)耘擂,才能掛載文件系統(tǒng)
當(dāng)重啟開(kāi)發(fā)板直接掛載文件系統(tǒng),就會(huì)看到 spi flash mount to /spi failed! 的提示絮姆,因?yàn)榇藭r(shí)在 SPI Flash 中還沒(méi)有創(chuàng)建相應(yīng)類型的文件系統(tǒng)梳星。
-
在存儲(chǔ)設(shè)備上創(chuàng)建相應(yīng)的文件系統(tǒng)
-
使用mkfs命令:mkfs [-t type] device
mkfs -t elm W25Q256 #文件系統(tǒng)創(chuàng)建完成后需要重啟設(shè)備
-
3)掛載文件系統(tǒng)
文件系統(tǒng)的掛載指的是將文件系統(tǒng)和具體的存儲(chǔ)設(shè)備關(guān)聯(lián)起來(lái)赞赖,并掛載到某個(gè)掛載點(diǎn),這個(gè)掛載點(diǎn)即為這個(gè)文件系統(tǒng)的根目錄冤灾。
-
在rt_application_init函數(shù)初始化的線程中調(diào)用api函數(shù)掛載文件系統(tǒng)(如application.c的rt_init_thread_entry函數(shù))
//掛載romfs到根目錄/ if (dfs_mount(RT_NULL, "/", "rom", 0, &(romfs_root)) == 0) { rt_kprintf("ROM file system initializated!\n"); } //將elm FatFS文件系統(tǒng)與W25Q256設(shè)備關(guān)聯(lián)前域,并掛載到/spi目錄下 /* mount sd card fat partition 0 as root directory */ if (dfs_mount("W25Q256", "/spi", "elm", 0, 0) == 0) { rt_kprintf("spi flash mount to /spi !\n"); } else { rt_kprintf("spi flash mount to /spi failed!\n"); } //將elm FatFS文件系統(tǒng)與sd0設(shè)備關(guān)聯(lián),并掛載到/sdcard目錄下 /* mount sd card fat partition 0 as root directory */ if (dfs_mount("sd0", "/sdcard", "elm", 0, 0) == 0) { rt_kprintf("sd card mount to /sdcard!\n"); } else { rt_kprintf("sd card mount to /sdcard failed!\n"); }
3.文件與目錄操作 shell 命令
- 文件系統(tǒng)的操作命令在 RT-Thread online packages → miscellaneous packages → samples: kernel and components sample -> filesystem sample options中選擇.
- 默認(rèn)命令有l(wèi)s韵吨、cd匿垄、cp、rm归粉、mv椿疗、ifconfig、echo糠悼、cat届榄、pwd、mkdir等
- 文件系統(tǒng)提供的 Sample 還有 openfile倔喂、readwrite铝条、stat、rename席噩、opendir班缰、readdir 、 tell_seek_dir等命令
- 添加新的sample會(huì)在工程中添加新的文件夾
二悼枢、FinSH shell
finsh運(yùn)行于開(kāi)發(fā)板埠忘,它可以使用串口/以太網(wǎng)/USB等與PC機(jī)進(jìn)行通信,提供一套供用戶在命令行的操作接口馒索。
finsh是一個(gè)C語(yǔ)言風(fēng)格的Shell莹妒,在finsh shell中使用命令(即C語(yǔ)言中的函數(shù)),必須攜帶()符號(hào)绰上,finsh命令的輸出為此函數(shù)的返回值动羽。
-
finsh支持兩種模式:
-
C語(yǔ)言解釋器模式,為行文方便稱之為c-style渔期;
#列舉支持的命令 finsh >list() --Function List: pinMode -- set hardware pin mode pinWrite -- write value to hardware pin pinRead -- read status from hardware pin hello -- say hello world version -- show RT-Thread version information list_thread -- list thread list_sem -- list semaphore in system list_event -- list event in system list_mutex -- list mutex in system list_mailbox -- list mail box in system list_msgqueue -- list message queue in system list_memheap -- list memory heap in system list_mempool -- list memory pool in system list_timer -- list timer in system list_device -- list device in system list -- list all symbol in system msh -- use module shell --Variable List: dummy -- dummy variable for finsh
#測(cè)試命令格式 finsh >hello() finsh >version()
-
傳統(tǒng)命令行模式运吓,此模式又稱為msh(module shell)。
#列舉支持的命令 msh >help RT-Thread shell commands: reboot - Reboot System version - show RT-Thread version information list_thread - list thread list_sem - list semaphore in system list_event - list event in system list_mutex - list mutex in system list_mailbox - list mail box in system list_msgqueue - list message queue in system list_memheap - list memory heap in system list_mempool - list memory pool in system list_timer - list timer in system list_device - list device in system exit - return to RT-Thread shell mode. help - RT-Thread shell help. ps - List threads in the system. time - Execute command with time. free - Show the memory usage in the system.
#測(cè)試命令格式 msh >help msh >version
-
-
所以的finsh命令或msh命令都是在cmd.c文件中導(dǎo)出的
- finsh命令通過(guò)宏定義FINSH_FUNCTION_EXPORT導(dǎo)出
- msh命令通過(guò)宏定義MSH_CMD_EXPORT導(dǎo)出
三疯趟、動(dòng)態(tài)模塊
1.簡(jiǎn)介
-
dlmodule
則是 RT-Thread 下拘哨,在內(nèi)核空間對(duì)外提供的動(dòng)態(tài)模塊加載機(jī)制的軟件組件。-
dlmodule
組件更多的是一個(gè) ELF 格式加載器信峻,把單獨(dú)編譯的一個(gè) elf 文件的代碼段倦青,數(shù)據(jù)段加載到內(nèi)存
中,并對(duì)其中的符號(hào)進(jìn)行解析盹舞,綁定到內(nèi)核導(dǎo)出的 API 地址上产镐。- 動(dòng)態(tài)模塊被系統(tǒng)加載到內(nèi)存的
-
[圖片上傳失敗...(image-dd0ae4-1563508716000)]
動(dòng)態(tài)模塊 elf 文件需要放置于 RT-Thread 下的文件系統(tǒng)上
-
RT-Thread 的動(dòng)態(tài)模塊支持兩種格式:
-
.mo
動(dòng)態(tài)模塊隘庄;它可以被加載,并且系統(tǒng)中會(huì)自動(dòng)創(chuàng)建一個(gè)主線程執(zhí)行這個(gè)動(dòng)態(tài)模塊中的main
函數(shù)癣亚;同時(shí)這個(gè)main(int argc, char**argv)
函數(shù)也可以接受命令行上的參數(shù)丑掺。 -
.so
動(dòng)態(tài)庫(kù);它可以被加載述雾,并駐留在內(nèi)存中街州,并提供一些函數(shù)集由其他程序(內(nèi)核里的代碼或動(dòng)態(tài)模塊)來(lái)使用。
-
2.編譯固件
-
進(jìn)入bsp庫(kù)玻孟,執(zhí)行:menuconfig 唆缴,選擇
RT-Thread Components ---> POSIX layer and C standard library ---> [*] Enable dynamic module with dlopen/dlsym/dlclose feature RT-Thread Components ---> Device virtual file system ---> [*] Using device virtual file system
-
在編譯文件rtconfig.py中添加動(dòng)態(tài)模塊編譯時(shí)需要的配置參數(shù)
#CXXFLAGS = CFLAGS + ' -Woverloaded-virtual -fno-exceptions -fno-rtti' M_CFLAGS = CFLAGS + '-mlong-calls -fPIC' M_CXXFLAGS = CXXFLAGS + '-mlong-calls -fPIC' M_LFLAGS = DEVICE + CXXFLAGS + '-Wl,--gc-sections,-z,max-page-size=0x4' +\ '-shared -fPIC -nostartfiles -nostdlib -static-libgcc' M_POST_ACTION = STRIP + '-R .hash $TARGET\n' + SIZE + '$TARGET \n' M_BIN_PATH = r'E:\qemu-dev310\fatdisk\root'
-
在鏈接腳本xxx.ld中添加對(duì)應(yīng)的信息
/* section information for modules */ . = ALIGN(4); __rtmsymtab_start = .; KEEP(*(RTMSymTab)) __rtmsymtab_end = .;
-
執(zhí)行編譯
scons #使用動(dòng)態(tài)模塊只能使用gcc編譯 #生成編譯動(dòng)態(tài)模塊時(shí)需要包括的內(nèi)核頭文件搜索路徑及全局宏定義 scons --target=ua -s
3.編譯動(dòng)態(tài)模塊
在 github 上有一份獨(dú)立倉(cāng)庫(kù): rtthread-apps ,這份倉(cāng)庫(kù)中放置了一些和動(dòng)態(tài)模塊黍翎。
目錄名 | 說(shuō)明 |
---|---|
cxx | 演示了如何在動(dòng)態(tài)模塊中使用 C++ 進(jìn)行編程 |
hello | 最簡(jiǎn)單的 hello world 示例 |
lib | 動(dòng)態(tài)庫(kù)的示例 |
md5 | 為一個(gè)文件產(chǎn)生 md5 碼 |
tools | 動(dòng)態(tài)模塊編譯時(shí)需要使用到的 Python/SConscript 腳本 |
ymodem | 通過(guò)串口以 YModem 協(xié)議下載一個(gè)文件到文件系統(tǒng)上 |
- 執(zhí)行編譯
#指向到 RT-Thread 代碼的根目錄
set RTT_ROOT=E:\@Git_Depository\rt-thread
#指向到 BSP 的工程目錄
set BSP_ROOT=E:\@Git_Depository\rt-thread\bsp\stm32f429-apollo #注意工程路徑
#編譯hello/動(dòng)態(tài)模塊
scons --app=hello
#編譯lib/動(dòng)態(tài)庫(kù)
scons --lib=lib
? 編譯成功會(huì)生成xxx.mo文件面徽,將文件放置到rt-thread的文件系統(tǒng)上,就可以執(zhí)行匣掸。
4.動(dòng)態(tài)模塊開(kāi)發(fā)
在msh命令中輸入list_symbol命令趟紊。可以看到內(nèi)核符號(hào)表(kernel symbol table)所映射的函數(shù)旺聚,這些函數(shù)就是模塊模塊開(kāi)發(fā)當(dāng)前能使用的函數(shù)
msh /spi>list_module
module ref address
-------- -------- ------------
msh /spi>list_sy
list_symbols
msh /spi>list_symbols\
list_symbols\: command not found.
msh /spi>list_symbols
rt_tick_get => 0x0800c4e1
rt_tick_from_millisecond => 0x0800c53d
rt_device_register => 0x0800c6b1
rt_device_unregister => 0x0800c715
rt_device_find => 0x0800c781
rt_device_create => 0x0800c811
rt_device_destroy => 0x0800c85d
rt_device_open => 0x0800c941
rt_device_close => 0x0800ca5d
rt_device_read => 0x0800caf9
rt_device_write => 0x0800cb81
rt_device_control => 0x0800cc09
rt_device_set_rx_indicate => 0x0800cc71
rt_device_set_tx_complete => 0x0800ccc5
rt_sem_init => 0x0800d06d
rt_sem_detach => 0x0800d0d5
rt_sem_create => 0x0800d149
rt_sem_delete => 0x0800d1d9
rt_sem_take => 0x0800d285
rt_sem_trytake => 0x0800d3e5
rt_sem_release => 0x0800d401
rt_sem_control => 0x0800d4a1
rt_mutex_init => 0x0800d525
rt_mutex_detach => 0x0800d58d
rt_mutex_create => 0x0800d609
rt_mutex_delete => 0x0800d695
rt_mutex_take => 0x0800d741
rt_mutex_release => 0x0800d91d
rt_mutex_control => 0x0800dabd
rt_event_init => 0x0800db0d
rt_event_detach => 0x0800db61
rt_event_create => 0x0800dbdd
rt_event_delete => 0x0800dc51
rt_event_send => 0x0800dcfd
rt_event_recv => 0x0800de45
rt_event_control => 0x0800e041
rt_mb_init => 0x0800e0c1
rt_mb_detach => 0x0800e139
rt_mb_create => 0x0800e1bd
rt_mb_delete => 0x0800e279
rt_mb_send_wait => 0x0800e339
rt_mb_send => 0x0800e541
rt_mb_recv => 0x0800e561
rt_mb_control => 0x0800e795
rt_mq_init => 0x0800e829
rt_mq_detach => 0x0800e8e9
rt_mq_create => 0x0800e965
rt_mq_delete => 0x0800ea65
rt_mq_send => 0x0800eb1d
rt_mq_urgent => 0x0800ec71
rt_mq_recv => 0x0800edb5
rt_mq_control => 0x0800f001
rt_interrupt_enter => 0x0800f0b5
rt_interrupt_leave => 0x0800f0f5
rt_interrupt_get_nest => 0x0800f135
rt_hw_interrupt_disable => 0x080001ad
rt_hw_interrupt_enable => 0x080001b5
rt_get_errno => 0x0800f14d
rt_set_errno => 0x0800f185
_rt_errno => 0x0800f1c5
rt_memset => 0x0800f1f9
rt_memcpy => 0x0800f2b1
rt_memmove => 0x0800f385
rt_memcmp => 0x0800f409
rt_strstr => 0x0800f461
rt_strcasecmp => 0x0800f4c1
rt_strncpy => 0x0800f525
rt_strncmp => 0x0800f589
rt_strcmp => 0x0800f5d5
rt_strnlen => 0x0800f619
rt_strlen => 0x0800f659
rt_strdup => 0x0800f689
rt_show_version => 0x0800f6c5
rt_vsnprintf => 0x0800f98d
rt_snprintf => 0x0800fed5
rt_vsprintf => 0x0800ff05
rt_sprintf => 0x0800ff29
rt_console_get_device => 0x0800ff55
rt_console_set_device => 0x0800ff6d
rt_hw_console_output => 0x0800ffb9
rt_kprintf => 0x0800ffcd
rt_malloc_align => 0x0801004d
rt_free_align => 0x080100bd
rt_assert_handler => 0x0801014d
rt_malloc => 0x080103c5
rt_realloc => 0x08010659
rt_calloc => 0x080107f1
rt_free => 0x0801082d
rt_memheap_init => 0x080109f9
rt_memheap_detach => 0x08010b3d
rt_memheap_alloc => 0x08010bb1
rt_memheap_realloc => 0x08010da9
rt_memheap_free => 0x080110b9
rt_mp_init => 0x080112ed
rt_mp_detach => 0x080113bd
rt_mp_create => 0x08011469
rt_mp_delete => 0x08011575
rt_mp_alloc => 0x08011661
rt_mp_free => 0x080117bd
rt_object_get_information => 0x080118c1
rt_enter_critical => 0x08012099
rt_exit_critical => 0x080120c5
rt_critical_level => 0x08012119
rt_thread_init => 0x08012365
rt_thread_self => 0x080123d1
rt_thread_startup => 0x080123e9
rt_thread_detach => 0x08012489
rt_thread_create => 0x0801254d
rt_thread_delete => 0x080125b1
rt_thread_yield => 0x08012659
rt_thread_delay => 0x0801275d
rt_thread_mdelay => 0x08012775
rt_thread_control => 0x08012795
rt_thread_suspend => 0x08012869
rt_thread_resume => 0x08012911
rt_thread_timeout => 0x080129a9
rt_thread_find => 0x08012a2d
rt_timer_init => 0x08012c11
rt_timer_detach => 0x08012c59
rt_timer_create => 0x08012cd5
rt_timer_delete => 0x08012d15
rt_timer_start => 0x08012d95
rt_timer_stop => 0x08012f91
rt_timer_control => 0x08013025
dfs_subdir => 0x08013b11
dfs_normalize_path => 0x08013b61
open => 0x0801517d
close => 0x080151e9
read => 0x0801523d
write => 0x08015299
lseek => 0x080152f5
rename => 0x080153a9
unlink => 0x080153d9
stat => 0x08015405
fstat => 0x08015435
fsync => 0x080154ad
fcntl => 0x080154e9
ioctl => 0x08015555
statfs => 0x08015589
mkdir => 0x080155b9
rmdir => 0x08015631
opendir => 0x0801565d
readdir => 0x080156f5
telldir => 0x080157b1
seekdir => 0x080157fd
rewinddir => 0x08015851
closedir => 0x080158a5
chdir => 0x08015905
getcwd => 0x080159b1
system => 0x0801dce5
strcpy => 0x08046d3d
strncpy => 0x08046ec1
strlen => 0x080007c1
strcat => 0x08046c2d
strstr => 0x08047205
strchr => 0x08046c6d
strcmp => 0x080004e9
strtol => 0x08047581
strtoul => 0x08047739
strncmp => 0x08046e21
memcpy => 0x08000391
memcmp => 0x08045dc1
memmove => 0x08045e25
memset => 0x08045eed
memchr => 0x080002f1
putchar => 0x08046565
puts => 0x08046635
printf => 0x0804653d
sprintf => 0x08046b55
snprintf => 0x08046ab9
fwrite => 0x08045a51
localtime => 0x08045a71
time => 0x08023a15
longjmp => 0x080004d1
setjmp => 0x080004c5
exit => 0x0802398d
abort => 0x080239e1
rand => 0x08046645
__assert_func => 0x08045149
dlclose => 0x08023a89
dlerror => 0x08024951
dlmodule_find => 0x08025315
dlopen => 0x080253f5
dlsym => 0x080254bd
lwip_accept => 0x0802960d
lwip_bind => 0x080298a5
lwip_shutdown => 0x0802abb1
lwip_getpeername => 0x0802adc9
lwip_getsockname => 0x0802aded
lwip_getsockopt => 0x0802ae11
lwip_setsockopt => 0x0802b369
lwip_close => 0x080299a1
lwip_connect => 0x08029a55
lwip_listen => 0x08029b71
lwip_recv => 0x08029fe9
lwip_read => 0x08029fbd
lwip_recvfrom => 0x08029c3d
lwip_send => 0x0802a015
lwip_sendto => 0x0802a0e1
lwip_socket => 0x0802a251
lwip_write => 0x0802a309
lwip_select => 0x0802a5c9
lwip_ioctl => 0x0802b791
lwip_fcntl => 0x0802b911
lwip_htons => 0x0802bd4d
lwip_htonl => 0x0802bd69
lwip_gethostbyname => 0x08028e39
lwip_gethostbyname_r => 0x08028ed1
lwip_freeaddrinfo => 0x08028fd1
lwip_getaddrinfo => 0x08028ffd
dhcp_start => 0x08036c49
dhcp_renew => 0x080371d9
dhcp_stop => 0x08037629
netifapi_netif_set_addr => 0x08029329
netif_set_link_callback => 0x0802d879
netif_set_status_callback => 0x0802d791
netif_find => 0x0802d4a9
netif_set_addr => 0x0802d451
netif_set_ipaddr => 0x0802d519
netif_set_gw => 0x0802d5bd
netif_set_netmask => 0x0802d5f5
gethostbyname => 0x0803cf21
gethostbyname_r => 0x0803cf39
freeaddrinfo => 0x0803cf65
getaddrinfo => 0x0803cf7d
accept => 0x0803d315
bind => 0x0803d3c9
shutdown => 0x0803d3f1
getpeername => 0x0803d475
getsockname => 0x0803d49d
getsockopt => 0x0803d4c5
setsockopt => 0x0803d4f5
connect => 0x0803d525
listen => 0x0803d54d
recv => 0x0803d571
recvfrom => 0x0803d5a5
send => 0x0803d5d9
sendto => 0x0803d60d
socket => 0x0803d641
closesocket => 0x0803d6d9
ioctlsocket => 0x0803d759
rt_completion_init => 0x08042df9
rt_completion_wait => 0x08042e3d
rt_completion_done => 0x08042f39
rt_data_queue_init => 0x08043025
rt_data_queue_push => 0x080430a9
rt_data_queue_pop => 0x08043239
rt_data_queue_peak => 0x0804341d
rt_data_queue_reset => 0x080434b9
rt_rbb_init => 0x08043691
rt_rbb_create => 0x08043731
rt_rbb_destroy => 0x080437ad
rt_rbb_blk_alloc => 0x08043859
rt_rbb_blk_put => 0x08043a59
rt_rbb_blk_get => 0x08043a9d
rt_rbb_blk_size => 0x08043b25
rt_rbb_blk_buf => 0x08043b59
rt_rbb_blk_free => 0x08043b89
rt_rbb_blk_queue_get => 0x08043c09
rt_rbb_blk_queue_len => 0x08043d21
rt_rbb_blk_queue_buf => 0x08043d85
rt_rbb_blk_queue_free => 0x08043db5
rt_rbb_next_blk_queue_len => 0x08043e25
rt_rbb_get_buf_size => 0x08043edd
rt_ringbuffer_init => 0x08043f5d
rt_ringbuffer_put => 0x08044001
rt_ringbuffer_put_force => 0x0804416d
rt_ringbuffer_get => 0x0804433d
rt_ringbuffer_putchar => 0x08044499
rt_ringbuffer_putchar_force => 0x08044551
rt_ringbuffer_getchar => 0x0804464d
rt_ringbuffer_data_len => 0x08044701
rt_ringbuffer_reset => 0x08044785
rt_ringbuffer_create => 0x080447d9
rt_ringbuffer_destroy => 0x0804484d
上述函數(shù)主要來(lái)自于rt-thread/src/xx.c文件织阳、rt-thread/components/使用的組件xxx/src/xx.c文件
1)導(dǎo)出函數(shù)到內(nèi)核符號(hào)表
通過(guò)宏定義RTM_EXPORT(symbol) 眶蕉,可以將函數(shù)導(dǎo)出到符號(hào)表砰粹。
RTM_EXPORT(rt_timer_control);
2)動(dòng)態(tài)模塊操作片級(jí)資源
-
操作gpio
- rt-thread\components\drivers\misc\pin.c默認(rèn)沒(méi)有把rt_pin_mode、rt_pin_write造挽、rt_pin_read等函數(shù)添加到符號(hào)表碱璃,需要人為添加
- STM32F429-apollo是基于STM32F4xx_PIN_NUMBERS == 176的芯片,參考rt-thread\bsp\stm32f429-apollo\drivers\drv_gpio.c的pins[]數(shù)組饭入,PB.0和PB.1分別對(duì)應(yīng)index 56和57嵌器。
#include <stdio.h> #include <board.h> #include <rtthread.h> #include <rtdevice.h> #include <rthw.h> int main(int argc, char *argv[]) { rt_pin_mode(56, PIN_MODE_OUTPUT); printf("Hello, world1\n"); while (1) { rt_pin_write(56, PIN_HIGH); rt_thread_mdelay(2000); rt_pin_write(56, PIN_LOW); rt_thread_mdelay(2000); } return 0; }
- rt-thread\components\drivers\misc\pin.c默認(rèn)沒(méi)有把rt_pin_mode、rt_pin_write造挽、rt_pin_read等函數(shù)添加到符號(hào)表碱璃,需要人為添加
5.對(duì)動(dòng)態(tài)模塊的操作
1)動(dòng)態(tài)模塊的結(jié)構(gòu)體
rt_dlmodule結(jié)構(gòu)體
struct rt_dlmodule
{
struct rt_object parent;
rt_list_t object_list; /* objects inside this module */
rt_uint8_t stat; /* status of module */ //動(dòng)態(tài)模塊的狀態(tài)
/* main thread of this module */
rt_uint16_t priority;
rt_uint32_t stack_size;
struct rt_thread *main_thread;
/* the return code */
int ret_code;
/* VMA base address for the first LOAD segment */
rt_uint32_t vstart_addr;
/* module entry, RT_NULL for dynamic library */
rt_dlmodule_entry_func_t entry_addr;
char *cmd_line; /* command line */
rt_addr_t mem_space; /* memory space */
rt_uint32_t mem_size; /* sizeof memory space */
/* init and clean function */
rt_dlmodule_init_func_t init_func;
rt_dlmodule_cleanup_func_t cleanup_func;
rt_uint16_t nref; /* reference count */
rt_uint16_t nsym; /* number of symbols in the module */
struct rt_module_symtab *symtab; /* module symbol table */
};
2)動(dòng)態(tài)模塊API
動(dòng)態(tài)模塊API函數(shù)在rt-thread\components\libc\libdl\dlmodule.c文件中定義。
#include "dlmodule.h"
//加載動(dòng)態(tài)模塊
struct rt_dlmodule *dlmodule_load(const char* pgname);
//執(zhí)行動(dòng)態(tài)模塊
struct rt_dlmodule *dlmodule_exec(const char* pgname, const char* cmd, int cmd_size);
//退出動(dòng)態(tài)模塊
void dlmodule_exit(int ret_code);
//查找動(dòng)態(tài)模塊
struct rt_dlmodule *dlmodule_find(const char *name);
//返回動(dòng)態(tài)模塊:返回調(diào)用上下文環(huán)境下動(dòng)態(tài)模塊的指針
struct rt_dlmodule *dlmodule_self(void);
//查找符號(hào)
rt_uint32_t dlmodule_symbol_find(const char *sym_str);
- 在keil工程中是不會(huì)添加dlmodule.c的谐丢,但是在gcc工程中已經(jīng)包含其路徑爽航。
停止動(dòng)態(tài)模塊
rt_err_t dlmodule(uint8_t argc, char **argv)
{
rt_err_t res = 0;
struct rt_dlmodule *module;
if (argc != 2) {
rt_kprintf("uasge:dlmodule name\n");
return 0;
}
module = dlmodule_find(argv[1]);
if ( module != RT_NULL) {
//close dlmodule
module->stat = RT_DLMODULE_STAT_CLOSING;
rt_timer_stop(&(module->main_thread->thread_timer));
res = rt_thread_delete(module->main_thread);
} else {
rt_kprintf("dlmodule find fail\n");
}
return res;
}
MSH_CMD_EXPORT(dlmodule, find dlmodule symbol);