技术标签: RT-Thread
邮箱用于线程间通信,特点是开销比较低,效率较高
邮箱中的每一封邮件只能容纳固定的 4 字节内容(针对 32 位处理系统,指针为 4 个字节大小,一封邮件恰好能够容纳一个指针
rt_thread_app.c:
#include "rtthread.h"
#include "rt_thread_app.h"
#include "bsp_usart.h"
static rt_thread_t usart1_thread = RT_NULL;
rt_mailbox_t usart1_mail = RT_NULL;
static void usart_receive_thread_entry(void* parameter);
int rt_thread_app_init(void)
{
/* 创建一个邮箱 */
usart1_mail = rt_mb_create("usart1_mail", /* 邮箱名字 */
10, /* 邮箱大小 */
RT_IPC_FLAG_FIFO);/* 信号量模式 FIFO(0x00)*/
if (usart1_mail != RT_NULL)
rt_kprintf("邮箱创建成功!\n\n");
usart1_thread = /* 线程控制块指针 */
rt_thread_create( "receive", /* 线程名字 */
usart_receive_thread_entry, /* 线程入口函数 */
RT_NULL, /* 线程入口函数参数 */
512, /* 线程栈大小 */
3, /* 线程的优先级 */
20); /* 线程时间片 */
/* 启动线程,开启调度 */
if (usart1_thread != RT_NULL)
rt_thread_startup(usart1_thread);
else
return -1;
}
//串口消息处理线程
static void usart_receive_thread_entry(void* parameter)
{
rt_err_t uwRet = RT_EOK;
stUsartMsgBuffer *usart1Msg;
/* 任务都是一个无限循环,不能返回 */
while(1)
{
/* 等待接邮箱消息 */
uwRet = rt_mb_recv(usart1_mail, /* 串口消息的邮箱对象句柄 */
(rt_uint32_t*)&usart1Msg, /* 接收串口的邮箱消息 */
RT_WAITING_FOREVER); /* 指定超时事件,一直等 */
if(RT_EOK == uwRet) /* 如果接收完成并且正确 */
{
rt_kprintf ( "邮箱的内容是:%s\r\n", usart1Msg->rxBuf);
}
else
rt_kprintf ( "邮箱接收错误!错误码是0x%x\n", uwRet);
UsartBuffer_Reset(usart1Msg);
}
}
bsp_usart.c:
#define USART1_RX_BUFFER_SIZE 256
#define EN_USART1_RX 1
static u8 usart1RxBuffer[USART1_RX_BUFFER_SIZE];
stUsartMsgBuffer usart1MsgBuffer;
void UsartBuffer_Init(stUsartMsgBuffer *usartBuf, USART_TypeDef *USARTx, u8 *rxbuf, u32 rxbufSize)
{
usartBuf->rxIndex = 0;
usartBuf->status = 0;
usartBuf->rxBuf = rxbuf;
usartBuf->txBufSize = 0;
usartBuf->USARTx = USARTx;
memset(usartBuf->rxBuf, 0, rxbufSize);
}
void UsartBuffer_Reset(stUsartMsgBuffer *usartBuf)
{
usartBuf->rxIndex = 0;
memset(usartBuf->rxBuf, 0, usartBuf->rxBufSize);
}
void Usart_Send(stUsartMsgBuffer *usartBuf, u8 *txbuf, u32 txbufSize)
{
u16 i, ucErrTime;
for (i = 0; i < txbufSize; i++)
{
ucErrTime = 0;
while (USART_GetFlagStatus(usartBuf->USARTx, USART_FLAG_TC) == RESET)
{
if (ucErrTime++ > 2000) //这个值更具CPU的频率不同而有所改变
{
printf("USART_Write error: Write timeout\r\n");
return;
}
}
USART_SendData(usartBuf->USARTx, (uint8_t)txbuf[i]);
}
}
void UsartIRQHandler(stUsartMsgBuffer *usartBuf)
{
u8 retval;
if (!usartBuf)
return;
if (USART_GetITStatus(usartBuf->USARTx, USART_IT_RXNE) == SET) //接收中断(接收到的数据必须是0x0d 0x0a结尾)
{
retval = USART_ReceiveData(usartBuf->USARTx);
if (usartBuf->rxIndex > usartBuf->rxBufSize - 1) //长度超出,位找下面的头做准备
{
usartBuf->rxBuf[0] = usartBuf->rxBuf[usartBuf->rxIndex - 1]; //把最后一个搬到第一个
usartBuf->rxIndex = 1; //指向第二个
}
usartBuf->rxBuf[usartBuf->rxIndex++] = retval; //(USART1->DR); //读取接收到的数据
}
if (USART_GetITStatus(usartBuf->USARTx, USART_IT_IDLE) == SET) //idle interrupt
{
extern rt_mailbox_t usart1_mail;
USART_ReceiveData(usartBuf->USARTx); //clear idle interrupt
usartBuf->status = 1;
rt_mb_send(usart1_mail, (rt_uint32_t)usartBuf);
// USART_ITConfig(usartBuf->USARTx, USART_IT_RXNE, DISABLE);
}
}
void USART1_IRQHandler(void) //串口1中断服务程序
{
UsartIRQHandler(&usart1MsgBuffer);
}
消息队列是另一种常用的线程间通讯方式,是邮箱的扩展。可以应用在多种场合:线程间的消息交换、使用串口接收不定长数据等;
消息队列是一种异步的通信方式
消息队列是直接的数据内容复制,所以不需要动态分配内存作为缓存,只需用了局部变量作为缓存保存消息,这样也就免去动态内存分配的烦恼。
#include "rtthread.h"
#include "rt_thread_app.h"
#include "bsp_usart.h"
static rt_thread_t usart1_thread = RT_NULL;
rt_mq_t usart1_mq = RT_NULL;
static void usart_receive_thread_entry(void* parameter);
int rt_thread_app_init(void)
{
/* 创建一个消息队列 */
usart1_mq = rt_mq_create("usart1_mq",/* 消息队列名字 */
40, /* 消息的最大长度 */
20, /* 消息队列的最大容量 */
RT_IPC_FLAG_FIFO);/* 队列模式 FIFO(0x00)*/
if (usart1_mq != RT_NULL)
rt_kprintf("消息队列创建成功!\n\n");
usart1_thread = /* 线程控制块指针 */
rt_thread_create( "receive", /* 线程名字 */
usart_receive_thread_entry, /* 线程入口函数 */
RT_NULL, /* 线程入口函数参数 */
512, /* 线程栈大小 */
3, /* 线程的优先级 */
20); /* 线程时间片 */
/* 启动线程,开启调度 */
if (usart1_thread != RT_NULL)
rt_thread_startup(usart1_thread);
else
return -1;
}
static void usart_receive_thread_entry(void* parameter)
{
rt_err_t uwRet = RT_EOK;
stUsartMsgBuffer usart1Msg;
/* 任务都是一个无限循环,不能返回 */
while(1)
{
/* 等待接邮箱消息 */
uwRet = rt_mq_recv(usart1_mq, /* 读取(接收)队列的ID(句柄) */
&usart1Msg, /* 读取(接收)的数据保存位置 */
sizeof(usart1Msg), /* 读取(接收)的数据的长度 */
RT_WAITING_FOREVER); /* 等待时间:一直等 */
if(RT_EOK == uwRet) /* 如果接收完成并且正确 */
{
rt_kprintf ( "消息队列的内容是: %s\n\n", usart1Msg.rxBuf);
}
else
rt_kprintf ( "消息队列接收错误!错误码是0x%x\n", uwRet);
}
}
void UsartIRQHandler(stUsartMsgBuffer *usartBuf)
{
u8 retval;
if (!usartBuf)
return;
if (USART_GetITStatus(usartBuf->USARTx, USART_IT_RXNE) == SET) //接收中断
{
retval = USART_ReceiveData(usartBuf->USARTx);
if (usartBuf->rxIndex > usartBuf->rxBufSize - 1)
{
usartBuf->rxBuf[0] = usartBuf->rxBuf[usartBuf->rxIndex - 1];
usartBuf->rxIndex = 1;
}
usartBuf->rxBuf[usartBuf->rxIndex++] = retval;
}
if (USART_GetITStatus(usartBuf->USARTx, USART_IT_IDLE) == SET) //idle interrupt
{
extern rt_mq_t usart1_mq;
USART_ReceiveData(usartBuf->USARTx); //clear idle interrupt
// usartBuf->status = 1;
rt_mq_send( usart1_mq, /* 写入(发送)队列的ID(句柄) */
usartBuf, /* 写入(发送)的数据 */
sizeof(stUsartMsgBuffer)); /* 数据的长度 */
UsartBuffer_Reset(usartBuf);
// USART_ITConfig(usartBuf->USARTx, USART_IT_RXNE, DISABLE);
}
}
void USART1_IRQHandler(void) //串口1中断服务程序
{
UsartIRQHandler(&usart1MsgBuffer);
}
两种方式都是在中断中接收数据,在线程中处理处理数据,处理数据是比较耗时的工作。这样的操作是将中断的处理分为上半部
和底半部
。在Linux中对于中断的处理也是这类似这样处理的。
上半部
——耗时短的工作放在中断中处理
底半部
——耗时长的工作通过IPC
通知线程处理
CASIO计算器中计算这个算式,与下面的方法基本相同;(1+0.5%)^12=1.0616778118644995687897076174316.......方法与步骤如下:步骤1、用计算器数字键输入并计算0.5÷100+1=1.005,如下图:步骤2、按下图红框这个键,如下图:步骤3、用计算器输入12,如下图:步骤4、按“=”这个键,如下图红框这个键,就计算出结果了:(1+0.5%)的12次方等...
【jetson-nano】 2.1、安装监控软件jtop1、背景2、安装jtop3、jtop使用1、背景jtop是一款开源软件,可以查看Jetson Nano的运行状态。jtop的github官网:https://github.com/rbonghi/jetson_stats2、安装jtopsudo -H pip3 install -U jetson-stats查看版本[email protected]:~$ jtop -vjtop 3.1.13、jtop使用在终端直接输入jtop之
一、前言二、QAC构建三、QAC常见报警3.1 Msg(2:4700) metric value out of threshold range: STCYC=22:STLIN=307:STMCC = 48;函数内执行的代码行数少于5,比如一个函数中只有if-else if...或者switch-case3.2 Msg(2:4304) An expression of 'essentially Boolean type'is being cast to unsigne...
一、前言二、QAC构建三、QAC常见报警3.1 Msg(2:4700) metric value out of threshold range: STCYC=22:STLIN=307:STMCC = 48;函数内执行的代码行数少于5,比如一个函数中只有if-else if...或者switch-case3.2 Msg(2:4304) An expression of 'essentially Boolean type'is being cast to unsigne...
一、前言二、QAC构建三、QAC常见报警3.1 Msg(2:4700) metric value out of threshold range: STCYC=22:STLIN=307:STMCC = 48;函数内执行的代码行数少于5,比如一个函数中只有if-else if...或者switch-case3.2 Msg(2:4304) An expression of 'essentially Boolean type'is being cast to unsigne...
英伟达JETSON NANO利用网线与笔记本电脑连接前言环境及准备:开始咯前言在开发板下vncserver服务的时候做个笔记,博主刚刚拿到jetson nano开发板,准备用usb转ttl连接笔记本电脑的时候发现杜邦线不够,然后根据网上的教程用网线直接连接开发板和笔记本,但是!博主发现自己挂在了第二步,用arp -a根本扫不出开发板的ip地址,在查找了一番资料以后博主觉得可能是网线的原因,网络...
C语言中的__FILE__用以指示本行语句所在源文件的文件名,举例如下(test.c):#include &lt;stdio.h&gt;int main(){printf("%s\n",__FILE__);}在gcc编译生成a.out,执行后输出结果为:test.c在windows的vc6.0下...
现在部门的后台数据绑定框架是AngularJS,特整理一些常用方法,和大家分享 第一 迭代输出之ng-repeat标签 ng-repeat让table ul ol等标签和js里的数组完美结合 12345 <ul><li ng...
在无法进入win的情况下,给win创建启动项
大概率是版本问题,SpringCloud对应SpringBoot的版本是否对应,又或者SpringBoot与其他的jar不兼容。
最近在写一个守护进程的服务,遇到了一点儿问题,现在记录下来,也希望能帮到有需要的人。开发环境:win7,VS2015问题: 1、通过process启动App,不显示界面 2、有的电脑安装服务Service后,App启动正常,有的电脑仍然不显示界面原因: 问题1:与windows session有关,请参考文章“链接1”,里面写的很详细且易懂。 问
一、前言二、QAC构建三、QAC常见报警3.1 Msg(2:4700) metric value out of threshold range: STCYC=22:STLIN=307:STMCC = 48;函数内执行的代码行数少于5,比如一个函数中只有if-else if...或者switch-case3.2 Msg(2:4304) An expression of 'essentially Boolean type'is being cast to unsigne...