一、文件系统
RT-Thread 文件系统结构图
最顶层是一套面向嵌入式系统,专门优化过的设备虚拟文件系统 POSIX 文件接口
中间层是各种文件系统的实现
比如 ELM FatFS、RomFS、devfs、RamFS、Yaffs2、Uffs2、JFFS2 、NFS 等
最底层是各类存储设备驱动
初始化存储设备并向上层提供存储设备的驱动接口。存储设备的类型可能是 SPI Flash,SD卡 等
1.文件系统的移植
1)开启/配置 DFS 框架
进入
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
menuconfig : RT-Thread Components → Device virtual file system
[x] Using device virtual file system : 使用设备虚拟文件系统,即 RT-Thread 文件系统。
[x] Using working directory : 打开这个选项,在 finsh/msh 中就可以使用基于当前工作目录的相对路径。
[ ] The maximal number of mounted file system : 最大挂载文件系统的数量。
[ ] The maximal number of file system type : 最大支持文件系统类型的数量。
[ ] The maximal number of opened files : 打开文件的最大数量。
[x] Enable elm-chan fatfs : 使用 elm-chan FatFs,用于挂载在spi flash等存储设备上。
elm-chan's FatFs, Generic FAT Filesystem Module : elm-chan 文件系统的配置项。
[x] Using devfs for device objects : 开启 devfs 文件系统。
[ ] Enable BSD socket operated by file system API : 使 BSD socket 可以使用文件系统的 API 来管理,比如读写操作和 select/poll 的 POSIX API 调用。
[x] Enable ReadOnly file system on flash : 在 Flash 上使用只读文件系统RomFS。
[ ] Enable RAM file system : 使用 RAM 文件系统。
[ ] Enable UFFS file system: Ultra-low-cost Flash File System :使用 UFFS。
[ ] Enable JFFS2 file system : 使用 JFFS2 文件系统。
[ ] Using NFS v3 client file system :使用 NFS 文件系统。
|
配置和指定文件系统
2)存储设备驱动初始化
根据所使用的储存设备,如 SPI Flash,SD卡,初始化其驱动
如:RT-Thread Components → Device Drivers 界面中选中 Using SPI Bus/Device device drivers 以及 Using Serial Flash Universal Driver 选项,
检查储存设备驱动
编译程序并下载到开发板上
list_device #查看是否识别到有spi 驱动
sf probe xxx #检测spi设备接口下是否有 spi flash
sf bench yes #对存储设备进行测试
3)创建存储设备
由于只有块设备类型的设备才能和文件系统对接,所以需要根据 SPI Device 找到 SPI Flash 设备,并创建与其对应的 Block Device。
在drv_spi_flash.c文件中添加如下函数,注册块设备
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
static int rt_hw_spi_flash_with_sfud_init(void)
{
//使用spi50 设备接口注册W25Q256块设备
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设备
image
2.文件系统使用
1)文件系统的初始化
初始化 DFS 框架
初始化文件系统必须的数据表,以及互斥锁
由dfs_init函数完成
初始化具体文件系统
将所选择的elm FatFS 等文件系统的操作函数注册到 DFS 框架中
由elm_init等函数完成
初始化存储设备
2)在存储设备创建文件系统
存储设备上需要先创建相应的文件系统,才能挂载文件系统
当重启开发板直接挂载文件系统,就会看到 spi flash mount to /spi failed!
的提示,因为此时在 SPI Flash 中还没有创建相应类型的文件系统。
在存储设备上创建相应的文件系统
使用mkfs命令:mkfs [-t type] device
#文件系统创建完成后需要重启设备
3)挂载文件系统
文件系统的挂载指的是将文件系统和具体的存储设备关联起来,并挂载到某个挂载点,这个挂载点即为这个文件系统的根目录。
在rt_application_init函数初始化的线程中调用api函数挂载文件系统(如application.c的rt_init_thread_entry函数)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
|
//挂载romfs到根目录/
if (dfs_mount(RT_NULL, "/", "rom", 0, &(romfs_root)) == 0)
{
rt_kprintf("ROM file system initializated!\n");
}
//将elm FatFS文件系统与W25Q256设备关联,并挂载到/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文件系统与sd0设备关联,并挂载到/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 命令
文件系统的操作命令在 RT-Thread online packages → miscellaneous packages → samples: kernel and components sample -> filesystem sample options中选择.
默认命令有ls、cd、cp、rm、mv、ifconfig、echo、cat、pwd、mkdir等
文件系统提供的 Sample 还有 openfile、readwrite、stat、rename、opendir、readdir 、 tell_seek_dir等命令
添加新的sample会在工程中添加新的文件夹
二、FinSH shell
finsh运行于开发板,它可以使用串口/以太网/USB等与PC机进行通信,提供一套供用户在命令行的操作接口。
finsh是一个C语言风格的Shell,在finsh shell中使用命令(即C语言中的函数),必须携带()符号,finsh命令的输出为此函数的返回值。
finsh支持两种模式:
C语言解释器模式,为行文方便称之为c-style;
#列举支持的命令
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
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
|
测试命令格式
1
2
3
4
|
finsh >hello()
finsh >version()
|
传统命令行模式,此模式又称为msh(module shell)。
列举支持的命令
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
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.
|
测试命令格式
1
2
3
4
|
msh >help
msh >version
|
所以的finsh命令或msh命令都是在cmd.c文件中导出的
finsh命令通过宏定义FINSH_FUNCTION_EXPORT导出
msh命令通过宏定义MSH_CMD_EXPORT导出
三、动态模块
1.简介
dlmodule 则是 RT-Thread 下,在内核空间对外提供的动态模块加载机制的软件组件。
dlmodule 组件更多的是一个 ELF 格式加载器,把单独编译的一个 elf 文件的代码段,数据段加载到内存中,并对其中的符号进行解析,绑定到内核导出的 API 地址上。
动态模块被系统加载到内存的
动态模块 elf 文件需要放置于 RT-Thread 下的文件系统上
RT-Thread 的动态模块支持两种格式:
.mo 动态模块;它可以被加载,并且系统中会自动创建一个主线程执行这个动态模块中的 main 函数;同时这个 main(int argc, char**argv) 函数也可以接受命令行上的参数。
.so 动态库;它可以被加载,并驻留在内存中,并提供一些函数集由其他程序(内核里的代码或动态模块)来使用。
2.编译固件
进入bsp库,执行:menuconfig ,选择
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
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中添加动态模块编译时需要的配置参数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
#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中添加对应的信息
1
2
3
4
5
6
7
8
9
10
|
/* section information for modules */
. = ALIGN(4);
__rtmsymtab_start = .;
KEEP(*(RTMSymTab))
__rtmsymtab_end = .;
|
执行编译
1
2
3
4
5
6
7
8
|
scons #使用动态模块只能使用gcc编译
#生成编译动态模块时需要包括的内核头文件搜索路径及全局宏定义
scons --target=ua -s
|
3.编译动态模块
在 github 上有一份独立仓库: rtthread-apps ,这份仓库中放置了一些和动态模块。
目录名 说明
cxx 演示了如何在动态模块中使用 C++ 进行编程
hello 最简单的 hello world 示例
lib 动态库的示例
md5 为一个文件产生 md5 码
tools 动态模块编译时需要使用到的 Python/SConscript 脚本
ymodem 通过串口以 YModem 协议下载一个文件到文件系统上
执行编译
指向到 RT-Thread 代码的根目录
1
2
|
set RTT_ROOT=E:\@Git_Depository\rt-thread
|
指向到 BSP 的工程目录
1
2
|
set BSP_ROOT=E:\@Git_Depository\rt-thread\bsp\stm32f429-apollo #注意工程路径
|
#编译hello/动态模块
编译lib/动态库
编译成功会生成xxx.mo文件,将文件放置到rt-thread的文件系统上,就可以执行。
4.动态模块开发
在msh命令中输入list_symbol命令。可以看到内核符号表(kernel symbol table)所映射的函数,这些函数就是模块模块开发当前能使用的函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
|
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
|
上述函数主要来自于rt-thread/src/xx.c
文件、rt-thread/components/使用的组件xxx/src/xx.c
文件
1)导出函数到内核符号表
通过宏定义RTM_EXPORT(symbol) ,可以将函数导出到符号表。
1
2
|
RTM_EXPORT(rt_timer_control);
|
2)动态模块操作片级资源
操作gpio
rt-thread\components\drivers\misc\pin.c默认没有把rt_pin_mode、rt_pin_write、rt_pin_read等函数添加到符号表,需要人为添加
STM32F429-apollo是基于STM32F4xx_PIN_NUMBERS == 176的芯片,参考rt-thread\bsp\stm32f429-apollo\drivers\drv_gpio.c的pins[]数组,PB.0和PB.1分别对应index 56和57。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
#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;
}
|
5.对动态模块的操作
1)动态模块的结构体
rt_dlmodule结构体
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
|
struct rt_dlmodule
{
struct rt_object parent;
rt_list_t object_list; /* objects inside this module */
rt_uint8_t stat; /* status of module */ //动态模块的状态
/* 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)动态模块API
动态模块API函数在rt-thread\components\libc\libdl\dlmodule.c文件中定义。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
#include "dlmodule.h"
//加载动态模块
struct rt_dlmodule *dlmodule_load(const char* pgname);
//执行动态模块
struct rt_dlmodule *dlmodule_exec(const char* pgname, const char* cmd, int cmd_size);
//退出动态模块
void dlmodule_exit(int ret_code);
//查找动态模块
struct rt_dlmodule *dlmodule_find(const char *name);
//返回动态模块:返回调用上下文环境下动态模块的指针
struct rt_dlmodule *dlmodule_self(void);
//查找符号
rt_uint32_t dlmodule_symbol_find(const char *sym_str);
|
在keil工程中是不会添加dlmodule.c的,但是在gcc工程中已经包含其路径。
停止动态模块
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
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);
|