一、文件系统

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

1
2

mkfs -t elm W25Q256

#文件系统创建完成后需要重启设备

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/动态模块

1
2

scons --app=hello

编译lib/动态库

1
2

scons --lib=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);