RTT简介及其简单应用

一、 裸机系统和多任务系统
裸机系统通常分为轮询系统和前后台系统。
轮询系统不难理解就是按照顺序从上往下反复来执行,伪代码如下:

int main()
{
		Init();
		while(1)
		{
			/*事件1*/
			event1();
			/*事件2*/
			event2();
			/*事件3*/
			event3();
		}
}

前后台系统就是在轮询系统的基础上多个一个中断,伪代码为:

int main(void)
{
	Init();
	while(1)
	{
		/*事件1*/
		event1();
		/*事件2*/
		event2();
		/事件3*/
		event3();
	}
}

void interrupt(void)
{
	dosoemthing();
}

多任务系统则是一个个单独的任务之间相互协调,且这些任务都是无限循环且不返回的,伪代码为:

int main(void)
{
	Init();
	RTOS_Init();
	RTOS_Start();
}

void thread1_entry(void *arg)
{
	while(1)
	{
		event1();
	}
}

void thread2_entry(void *arg)
{
	while(1)
	{
		event2();
	}
}

二、RTT操作系统
RTT就是一个多任务抢占式操作系统,和裸机系统相比,RTT的优势在于当工程庞大时,我们可以将其分解成一个个小任务,这些任务都有优先级,操作系统的调度机制来决定任务的运行顺序,不用担心每个模块之间的相互干扰,同时,抢占的机制可以迅速的来处理紧急任务。

三,RTT相关函数

rt_thread_t rt_thread_create(const char *name,
                             void (*entry)(void *parameter),
                             void       *parameter,
                             rt_uint32_t stack_size,
                             rt_uint8_t  priority,
                             rt_uint32_t tick)

函数功能:创建一个线程
参数讲解:
const char *name:线程名称
void (*entry)(void *parameter):线程入口
void *parameter:线程参数
rt_uint32_t stack_size:线程栈大小
rt_uint8_t priority:线程优先级
rt_uint32_t tick:时间片
函数返回值:该线程的句柄

rt_err_t rt_thread_startup(rt_thread_t thread)

函数功能:启动线程
参数讲解:
rt_thread_t thread:线程的句柄

信号量机制:
信号量是一种实现线程间通信的机制,实现线程之间同步或临界资源的互斥访问, 常用于协助一组相互竞争的线程来访问临界资源。在多线程系统中,各线程之间需要同步或互斥实现临界资源的保护。

rt_sem_t rt_sem_create(const char *name, rt_uint32_t value, rt_uint8_t flag);

函数功能:创建一个信号量
参数讲解:
const char *name:信号量的名字
rt_uint32_t value:持有信号量的个数
rt_uint8_t flag:RT_IPC_FLAG_FIFO(按先后顺序), RT_IPC_FLAG_PRIO(按优先级)。
函数返回值:信号量句柄

rt_err_t rt_sem_release(rt_sem_t sem)

函数功能:释放一个信号量

rt_err_t rt_sem_take(rt_sem_t sem, rt_int32_t time)

函数功能:获取一个信号量
说明:如果欲获取的信号量为0,则调用该函数的线程会被挂起,挂起的时间由第二个参数设置

四、小demo
生产者、消费者模型:生产者不停的生产数据,但是当队列满了,就停止生产,消费者不停消费数据,当队列空了停止消费。
在这里插入图片描述

#include "board.h"
#include "rtthread.h"

rt_thread_t producer_thread = RT_NULL;
rt_thread_t consumer_thread = RT_NULL;

rt_sem_t notfull_sem = RT_NULL;
rt_sem_t notempty_sem = RT_NULL;


#define BUF_SIZE		5
typedef struct
{
	uint32_t buf[BUF_SIZE];
	uint32_t write_p;
	uint32_t read_p;
}data;

data data_t;

void producer_thread_entry(void *arg);
void consumer_thread_entry(void *arg);

int main(void)
{	
	notfull_sem = rt_sem_create("notfull_sem", 0, RT_IPC_FLAG_FIFO);
	notempty_sem = rt_sem_create("notempty_sem", 0, RT_IPC_FLAG_FIFO);
	
	producer_thread = rt_thread_create("producer_thread",
									    producer_thread_entry,
										RT_NULL,
										512,
										0,
										20);
		
	consumer_thread = rt_thread_create("consumer_thread",
									    consumer_thread_entry,
										RT_NULL,
										512,
										1,
										20);
	rt_thread_startup(producer_thread);
	rt_thread_startup(consumer_thread);
	
}

void producer_thread_entry(void *arg)
{
	static uint32_t cnt=0;
	while(1)
	{		
		if(data_t.write_p - data_t.read_p < BUF_SIZE - 1)
		{				
			
			data_t.buf[data_t.write_p % BUF_SIZE] = cnt++;
			rt_kprintf("生产一个数据: %d\n",data_t.buf[data_t.write_p % BUF_SIZE]);
			data_t.write_p++;
			rt_sem_release(notempty_sem);
			rt_thread_delay(200);
		}
		else
		{
			rt_kprintf("生产缓冲区已满\n");
			rt_sem_take(notfull_sem,RT_WAITING_FOREVER);
			rt_thread_delay(200);
		}		
	}
}

void consumer_thread_entry(void *arg)
{
	while(1)
	{
		
		if(data_t.read_p != data_t.write_p)
		{			
			rt_kprintf("消费一个数据: %d\n",data_t.buf[data_t.read_p% BUF_SIZE]);
			data_t.read_p++;			
			rt_sem_release(notfull_sem);
			rt_thread_delay(400);
		}
		else
		{
			rt_sem_take(notempty_sem,RT_WAITING_FOREVER);
			rt_kprintf("消费缓冲区已空\n");
		}
	}
}

在这里插入图片描述可以看到生产者的生产速度大于消费者,出现了缓冲区已满的现象,生产者则停止生产,等待消费者消费一个数据后继续生产

  • 6
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值