使用RT-Thread的一个很有用的组件-finsh

合集下载

Finsh的基本使用

Finsh的基本使用

event set
suspend thread
-------- ---------- --------------
通过 list_event() 则可以查看当前系统中使用的 event,event 字段 表示事件的名称,set 字段表示事件的值,suspend thread 字段表示等在 这个事件上的线程数目。
dummy
-- dummy variable for Finsh
0, 0x00000000
Finsh>>
按照上面命令的描述,先 list_thread() 下,查看当前系统中运行的 所有线程
\|/
- RT - Thread Operating System
/ | \ 1.1.0 build Aug 17 2012
具体请参见《Realtouch 开发板使用手册》
实验原理及程序结构
对于用户来讲,Finsh 组件有三个主要功能 获取系统运行时信息,如各种 RT-Thread 内核对象的动态信息。 能够对任意寄存器和内存地址进行读写操作 能够直接在 shell 中调用系统函数,访问系统变量
实验设计
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
--Variable List:
2006 - 2012 Copyright by rt-thread team
thread1 working...

在 RT-Thread Nano 上添加控制台与 FinSH

在 RT-Thread Nano 上添加控制台与 FinSH

本片文档分为两部分:第一部分是实现UART 控制台,该部分只需要实现两个数即可完成UART 控制台打印功能。

第二部分是实现移植FinSH 组件,实现在控制台输入命令调试系统,该部分实现基于第一部分,只需要添加FinSH 组件源码并再对接一个系统函数即可实现。

下面将对这两部分进行说明。

在 Nano 上添加 UART 控制台在RT-Thread Nano 上添加UART 控制台打印功能后,就可以在代码中使用RT-Thread 提供的打印函数rt_kprintf() 进行信息打印,从而获取自定义的打印信息,方便定位代码bug 或者获取系统当前运行状态等。

实现控制台打印(需要确认rtconfig.h 中已使及对接一个系统输出字符的函数,本小节将详细说明。

实现串口初始化使用串口对接控制台的打印,首先需要初始化串口,如引脚、波特率等。

uart_init() 需要在 board.c 中2static int uart_init(void);示例代码:如下是基于 HAL 库的STM32F103 串口驱动,完成添加控制台的示例代码,仅做参考。

1static UART_HandleTypeDef UartHandle;2static int uart_init(void)3{4 /* 初始化串口参数,如波特率、停止位等等 */5 UartHandle.Instance = USART1;6 UartHandle.Init.BaudRate = 115200;7 UartHandle.Init.HwFlowCtl = UART_HWCONTROL_NONE;8 UartHandle.Init.Mode = UART_MODE_TX_RX;9 UartHandle.Init.OverSampling = UART_OVERSAMPLING_16;10 UartHandle.Init.WordLength = UART_WORDLENGTH_8B;11 UartHandle.Init.StopBits = UART_STOPBITS_1;12 UartHandle.Init.Parity = UART_PARITY_NONE;1314 /* 初始化串口引脚等 */15 if (HAL_UART_Init(&UartHandle) != HAL_OK)16 {17 while(1);18 }1920 return 0;21}22INIT_BOARD_EXPORT(uart_init);1/* board.c */2void rt_hw_board_init(void)3{4 ....5 uart_init(); // 在 rt_hw_board_init 函数中调用串口初始化函数6 ....7}实现 rt_hw_console_output实现 finsh 组件输出一个字符,即在该函数中实现 uart 输出字符:1/* 实现 2:输出一个字符,系统函数,函数名不可更改*/2void rt_hw_console_output(const char *str);示例代码:如下是基于STM32F103 HAL 串口驱动对接的rt_hw_console_output() 函数,实现控制台字符输出,示例仅做参考。

RTT4-RTThread使用Shell finsh及TC测试框架

RTT4-RTThread使用Shell finsh及TC测试框架

使用RT-Thread 1.0.2 (或者打开任何一个RTThread工程)部分引自Prife的《RT_Thread的测试框架使用及分析》,仔细阅读后作了修订。

/prife/article/details/74870381.Finsh组件配置在例程源代码中,系统配置已经完毕,首先是修改了rtconfig.h 文件,将使用Finsh组件的宏打开其次将Finsh 组件的源文件加入到工程中编译2.连接串口下载程序后,连接好串口1,打开SecureCRT.exe,设置波特率115200,后连接。

开发板上电后,显示:输入list()后回车,list()命令的作用就是将系统中支持的所有shell命令都打印出来,也可以按TAB键。

有点类似与其他系统中的help命令。

有了这些命令和描述信息,我们就可以深入内核,查看它们的信息。

当前系统中运行的线程信息。

敲入list_thread(),回车。

当前系统实际运行时所有线程信息。

当前系统中运行着10个线程。

线程的名称,优先级,运行状态,堆栈地址,堆栈大小,最大使用堆栈,剩余运行tick 时间,错误信息都一览无遗,呵呵,是不是很方便。

其实,Finsh 的更强大功能还等着你挖掘呢.4.一个最简单的测试用例(不使用TestCase 框架)在application.c中的最后添加如下代码int testfunc(void){rt_kprintf("hello, rt-thread!\n");return 0;}#include <finsh.h>FINSH_FUNCTION_EXPORT(testfunc, just a test function);重新编译工程,启动串口工具输入命令list() 或者按Tab键多出一行。

接下来,在finsh上输入t 然后按下Tab键,finsh会自动地为我们补全testfunc,然后我们手动输入()后回车,可以看到如下运行效果:finsh />testfunc()hello, rt-thread!0, 0x00000000finsh />注:finsh跟linux下的shell很像,都具有tab键自动补全的功能,但是又有些不同,finsh的命令是C语言风格的,命令即函数调用语句。

rtthread多线程写法

rtthread多线程写法

rtthread多线程写法一、引言RT-Thread是一种广泛使用的实时操作系统,它支持多线程编程,使得开发者能够充分利用多核处理器的能力,提高系统的性能和稳定性。

本文将介绍RT-Thread多线程的编写方法,包括线程的创建、同步、通信等关键技术。

二、线程创建RT-Thread支持多种线程创建方式,包括手动创建、自动创建和共享内存创建。

手动创建适用于简单的应用场景,自动创建适用于复杂的应用场景,而共享内存创建适用于需要跨进程或跨线程通信的情况。

在创建线程时,需要指定线程的优先级、堆栈大小等参数,并为其分配必要的资源。

三、线程同步多线程编程中,线程同步是至关重要的一环。

RT-Thread提供了多种同步机制,包括互斥锁、信号量、条件变量等。

互斥锁用于保护共享资源的访问,避免出现竞态条件;信号量用于控制线程的执行流程,实现线程间的通信;条件变量用于实现线程间的异步通信,提高系统的响应速度。

在使用这些同步机制时,需要注意避免死锁、饥饿等问题。

四、线程通信线程通信是多线程编程中的另一个重要问题。

RT-Thread提供了消息队列、事件通知等机制来实现线程间的通信。

消息队列用于在多个线程之间传递数据,事件通知用于在特定条件下触发某个线程的行为。

在实现线程通信时,需要考虑到通信的效率、可靠性和安全性,避免出现数据丢失、重复接收等问题。

五、代码示例下面是一个简单的RT-Thread多线程示例代码:```c++#include <rtthread.h>// 定义互斥锁rt_mutex_t mutex;// 定义信号量,初始值为1,表示只有一个线程可以执行以下代码块rt_sem_t sem;void thread_func(void* arg){// 锁定互斥锁rt_mutex_lock(&mutex);// 释放信号量,表示有线程进入了等待队列rt_sem_release(&sem);// 执行需要同步的代码块rt_sem_take(&sem, RT_WAITING_FOREVER);// 解锁互斥锁rt_mutex_unlock(&mutex);}int main(){// 创建线程1,参数为线程函数和传递的参数rt_thread_t tid1 = rt_thread_create("tid1", thread_func, NULL, 2048, 5, 3);if (tid1 == RT_NULL) {rt_kprintf("Failed to create thread1\n");return -1;}// 创建线程2,参数为线程函数和传递的参数rt_thread_t tid2 = rt_thread_create("tid2", thread_func, NULL, 2048, 5, 3);if (tid2 == RT_NULL) {rt_kprintf("Failed to create thread2\n");return -1;}// 启动线程1和线程2rt_thread_startup(tid1);rt_thread_startup(tid2);// 等待所有线程退出完成rt_thread_join(tid1);rt_thread_join(tid2);// 销毁线程资源并释放内存空间rt_thread_delete(tid1);rt_thread_delete(tid2);return 0;}```这个示例代码创建了两个线程,并使用互斥锁和信号量实现了简单的同步和通信。

rtthread龙芯移植技术文档

rtthread龙芯移植技术文档
2.1 C语言的对象化模型
面向对象的特征主要包括:
封装,隐藏内部实现
继承,复用现有代码
多态,改写对象行为
采象的特征。
2.1.1封装
封装是一种信息隐蔽技术,它体现于类的说明,是对象的重要特性。封装使数据和加工该数据的方法(函数)封装为一个整体,以实现独立性很强的模块,使得用户只能见到对象的外特性(对象能接受哪些消息,具有那些处理能力),而对象的内特性(保存内部状态的私有数据和实现加工能力的算法)对用户是隐蔽的。封装的目的在于把对象的设计者和对象者的使用分开,使用者不必知晓行为实现的细节,只须用设计者提供的消息来访问该对象。
structparent_class *parent_ptr;/*父类指针*/
obj_ptr = &obj;
/*取父指针*/
parent_ptr = (structparent_class*) &obj;
/*可通过转换过类型的父类指针访问相应的属性*/
parent_ptr->a= 1;
parent_ptr->b= 5;
1.3轻型IP协议栈
LwIP是瑞士计算机科学院(Swedish Institute of Computer Science)的Adam Dunkels等开发的一套用于嵌入式系统的开放源代码TCP/IP协议栈,它在包含完整的TCP协议实现基础上实现了小型的资源占用,因此它十分适合于使用到嵌入式设备中,RT-Thread采用LwIP做为默认的TCP/IP协议栈,同时根据小型设备的特点对其进行再优化,体积相对进一步减小,RAM占用缩小到5kB附近(依据上层应用使用情况会有浮动)。
1.1.2任务同步机制
系统支持信号量、互斥锁作为线程间同步机制。互斥锁采用优先级继存方式以解决优先级翻转问题。信号量的释放动作可安全用于中断服务例程中。同步机制支持线程按优先级等待或按先进先出方式获取信号量或互斥锁。

干货扒一扒RT-Thread内核对象管理器设计思路

干货扒一扒RT-Thread内核对象管理器设计思路

干货扒一扒RT-Thread内核对象管理器设计思路RT-Tread内核架构RT-Thread,全称是 Real Time-Thread,顾名思义,它是一个嵌入式实时多线程操作系统,基本属性之一是支持多任务,允许多个任务同时运行并不意味着处理器在同一时刻真地执行了多个任务。

其内核架构如下图所示:RT-Thread 内核及底层结构对于各部分的功能,这里不做展开描述。

RT-Tread内核吸引我的方面:•代码优雅、可读性非常高•体积小巧、代码类Linux风格,可裁剪•社区活跃,国人自主开发,用户越来越多•优秀的设计,对于面向对象设计思想可以说是非常优秀的实践•主要定位于物联网应用,各种组件丰富,融合的也很好•........所以如果是RTOS应用或者开发从业者,面对这么优秀且比较容易深入学习的内核,如果不去好好读读,实在有点可惜。

要去体会RT-Thread对象设计思想,从其对内核对象object的管理入手,不失为一个非常好的切入点。

什么是RT-Thread内核对象管理?RT-Thread 采用内核对象管理系统来访问/ 管理所有内核对象,内核对象包含了内核中绝大部分设施,这些内核对象既可以是静态分配的静态对象,也可以是从系统内存堆中分配的动态对象。

通过这种内核对象的设计方式,RT-Thread 做到了不依赖于具体的内存分配方式,系统的灵活性得到极大的提高。

RT-Thread 内核对象包括:线程,信号量,互斥量,事件,邮箱,消息队列和定时器,内存池,设备驱动等。

对象容器中包含了每类内核对象的信息,包括对象类型,大小等。

对象容器给每类内核对象分配了一个链表,所有的内核对象都被链接到该链表上,如图RT-Thread 的内核对象容器及链表如下图所示:RT-Thread 的内核对象容器及链表参考自:/document/site/programming-manual/basic/basic/#_7这个集中管理的内核对象容器在内存的开销方面代价很小,但却具有高度的灵活性,从设计的角度看其代码也非常利于扩展,增加新的内核对象类别,以及对于相应的内核对象功能的裁剪适配。

十余年历史的国产RTOS,从RT

十余年历史的国产RTOS,从RT

十余年历史的国产RTOS,从RT现在是一个快节奏的时代,技术领域也是如此。

近些年,IoT备受资本青睐,各种新技术新方案层出不穷,质量也参差不齐,这边唱罢那边登台,以至于有些技术还未被人熟知,就被淹没在长河中了。

客观的说,RTOS领域玩家众多,仅笔者短短的从业时间,国产RTOS就听闻了五、六款之多。

 RT-Thread作为一个有十余年历史的国产RTOS,经历了长时间的考验和用户的青睐,目前发展趋势蒸蒸日上,也即将发布RT-Thread 3.0,其中必然有值得我们思考和学习的地方,我们也可以从中汲取到不少宝贵的经验。

 软件工程管理 软件工程管理对于软件研发是十分重要的,甚至可以说是开发过程的基石。

公司中有高水平的嵌入式软件程序员,也有刚入职的实习生,水平难免参差不齐,当共同协作开发一个项目时,如何彼此协调也是一个难题。

 时至今日,很多公司仍然在使用落后的代码管理方式。

有些甚至使用把代码压缩成一个个的压缩包来做版本管理。

同事之间的协作依靠互相发送文件,每次接收到同事的新文件首先要花半天时间解决编译error,甚至还要在本地对同事的代码进行修改,这样,软件基本处在半失控的状态,某次改动产生问题,就要从浩瀚的压缩包海洋里挑选一个,进行版本回退。

在开发一个大项目的时候,这种情况下甚至会出现人数越多,开发难度和周期越大的情况。

 而RT-Thread,提供了一个教科书级的范例。

RT-Thread由13000多个文件构成,支持各类设备和芯片近70款,从代码量和组织方式上来说,是一个相当庞大的软件工程。

在近十年的时间里,至少有将近100个开发者参与到了RT-Thread的开发中,使得RT-Thread稳步迭代,而这也是有一定的维护难。

RT-Thread学习之对FLASH进行分区管理

RT-Thread学习之对FLASH进行分区管理

FLASH分区管理是怎么一回事呢?我们可以以个人电脑来做类比,我们的电脑通常都分有很多个盘符:这些都是我们硬盘的分区,我这里装了两块硬盘,512GB的机械硬盘+128GB的固态硬盘,共分C~H六个分区,我这里的C盘和H盘是固态硬盘,其它盘符是机械硬盘:分区是为了方便我们对我们的资料进行管理,各个分区互不影响,比如格式化某个分区只会删除这个分区的内容而不会影响其它分区及整个硬盘等。

同样的,在我们的STM32上也是可以进行分区管理的,这篇笔记我们来使用RT-Thread的FAL软件包来对我STM32片内FLASH及片外FLASH的分区管理。

FAL软件包介绍FAL (Flash Abstraction Layer) Flash 抽象层,是 RT-Thread 的一个软件包,是对 Flash 及基于 Flash的分区进行管理、操作的抽象层,对上层统一了 Flash 及分区操作的 API ,并具有以下特性:• 支持静态可配置的分区表,并可关联多个 Flash 设备;• 分区表支持自动装载。

避免在多固件项目,分区表被多次定义的问题;• 代码精简,对操作系统无依赖,可运行于裸机平台,比如对资源有一定要求的 bootloader;• 统一的操作接口。

保证了文件系统、 OTA、 NVM 等对 Flash 有一定依赖的组件,底层 Flash 驱动的可重用性;• 自带基于 Finsh/MSH 的测试命令,可以通过 Shell 按字节寻址的方式操作(读写擦) Flash 或分区,方便开发者进行调试、测试;FAL软件包使用本笔记主要对潘多拉开发板的FAL例程进行一次梳理,所以部分表述来自于教程文档。

我们这个实验建立如下分区表:1、移植接口文件说明FAL软件包的目录如下,其中samples文件夹下为移植接口文件:其中fal_cfg.h 为fal 配置文件(Flash 设备配置和分区表配置):fal 是 Flash 抽象层,要操作 Flash 设备必然要将 Flash 的读、写、擦接口对接到 fal 抽象层中。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
#include <finsh.h> void fun_a(int input) {
rt_kprintf("input : %d \r\n",input); rt_kprintf("fun_a done.\r\n"); } FINSH_FUNCTION_EXPORT(fun_a, fun_a desc);
#endif
//初始化 FINSH 线程 //设置 FINSH 使用的输入输出设备为 "uart1"
在以前,FINSH 需要自己实现输入和输出,现改进为使用 RT-Thread 的设备管理框架来实现 输入输出,这样可以很方便地使用"uart2"来操作 Finsh,甚至是网络,类似于 telnet. 极大地增强了灵活性,
finsh>> fun_a(9) finsh>> fun_b(10) finsh>> int fun_val = 20 finsh>> fun_a(fun_val) finsh>> fun_b(++fun_val) finsh>> fun_a(fun_val *2)
Finsh 使用秘籍: 1.finsh>>状态下按 TAB 有惊喜. 2.输入 fun 再按 TAB 依然有惊喜.(可以输入 list 再按 TAB 测试下) 3.执行一个函数退出后再按上,下键可浏览历史.
//定义使用 RT-Thread 的设备管理
#define RT_USING_UART1
//使用 UART1 在 /src/usart.c 中有用到.
2. 取消原来的简单串口输出程序 把原来 board.c 中的 rt_hw_console_init(); 函数取消掉,换成 usart 中的 rt_hw_usart_init(); RT-Thread 中的 rt_kprinf() 也可以使用设备来输出,只需要
/* enter interrupt */ rt_interrupt_enter(); rt_hw_serial_isr(&uart1_device);
/* leave interrupt */ rt_interrupt_leave(); }
第四步: 写一个简单应用来使用 Finsh
因为原来 app.c 中有两个线程,都有使用 rt_kprintf 来打印信息,因 console 和 finsh 现都使用 "uart1",这两个线程打印的信息可能会影响观察,我们sart.c 把每个串口注册成设备.因 STM32 有多个串口,所以,根据需要来使用.
1.rtconfig.h 打开使用 RT-Thread 的设备管理
/* SECTION: Device System */
/* Using Device System */
#define RT_USING_DEVICE
使用 finsh
本例程和目标 CPU 配置无关,已把芯片内部 SRAM 容量配置为 20KB,C8T6~ZET6 通用. 除使用 USART1 外不使用其它外设.
Finsh 是一个很有用的调试-交互组件,使用 Finsh 可以查看所有线程,信号量,设备等信息. 是调试系统的得力肋手,下面介绍下如何使用 finsh.
后记:
因为需要导出一些符号给 finsh shell 使用,也就是那些函数名,变量名. 而这些函数名和变量名统一的放在两个 section 中,这样 finsh shell 能够自动的到这两个段中寻找. 而因为上面的 fun_a() fun_b() 并没有在别处被引用,因此在链接时可能被链接程序自动移除掉. 所以需要添加如下图链接选项让链接器保留这些段.
"--keep __fsym_* --keep __vsym_*" 详 细 请 看 FINSH_FUNCTION_EXPORT 的 实 现
3.添加 USART1 中断服务程序,在前面我们仅实现输出,通过查询方式,没有使用中断。
#include <rtthread.h> void USART1_IRQHandler(void) {
extern struct rt_device uart1_device; extern void rt_hw_serial_isr(struct rt_device *device);
所以,在下面,我们还需要实现这个 "uart1"设备.
第三步: 实现统一的设备管理
在 base_kernel 例程中,为了使例程变成简单,我们实现了一个最简单的通过查询方式的串口 输出程序.缺点很明显:没有灵活性,性能也只能做来做演示.
RT-Thread 提供了一个完整的设备管理方案,可以把不同类型的外设都按统一的接口进行 操作,通过设备名称就可以找到设备,然后就可以直接访问了.
void fun_b(int input) {
rt_kprintf("input : %d \r\n",input); rt_kprintf("fun_b done.\r\n"); } FINSH_FUNCTION_EXPORT(fun_b, fun_b desc); //同上
这样,当我们在 finsh 中执行 fun_a() 时,就会运行 fun_a 这个函数(注意加回车).
然后需要在初始化 RT-Thread 时把 Finsh 也一并初始化.
/* init application */ rt_application_init();
#ifdef RT_USING_FINSH /* init finsh */ finsh_system_init(); finsh_set_device("uart1");
第一步: 添加 Finsh 源文件
本例程基于 base_kernel 例程修改 既然要使用 Finsh,首先是添加 Finsh 的全部源文件.见:rt-thread/finsh.
然后更新头文件搜索路径:
第二步: 配置使用 Finsh 并初始化 Finsh.
作为 RT-Thread 的一个组件,要使用 Finsh,需要在 rtconfig.h 中开启使用 Finsh.
rt_console_set_device("uart1"); 就可以让 rt_kprinf() 通过"uart1"来输出,原来的 rt_hw_console_output() 也可以取消掉. 因为设置 rt_kprinf() 通过设备来输出后,就不会再通过 rt_hw_console_output() 来输出数 据了.
因为 STM32 的各型号外设兼容性极高,所以 RT-Thread 为 STM32 的 USART 提供了一个通用 框架.
rt-thread/stm32/serial.c rt-thread/stm32/serial.h 之所以写一个框架是因为 STM32 有多达 5 个串口.这样是为了提高程序的重用性.
/* SECTION: finsh, a C-Express shell */
#define RT_USING_FINSH
//定义使用 FINSH
/* Using symbol table */
#define FINSH_USING_SYMTAB
#define FINSH_USING_DESCRIPTION
相关文档
最新文档