摘要:本篇文章主要是围绕着MmwDemo_mboxReadTask任务线程函数讲解邮箱读取消息的过程,该任务用于处理从邮箱虚拟通道接收的毫米波 demo 消息。接下来将对该任务线程进行分片段进行讲解,并适当拓展。
1.任务线程函数原型:
描述:
用于处理邮箱虚拟通道接收的毫米波demo消息。
参数
两个Task 参数都没有使用,这里不拓展。
返回值
无返回值
2.参数声明部分
跳转进入到MmwDemo_mboxReadTask任务线程函数,按照老套路,在函数开头都会首先定义该线程所需结构体来存储相关的消息,回到该任务线程函数,仍是如此(如下代码片段),可以看到定义了两个参数。
1)参数 1 (message)
这是用于DSS/MSS通信交互的消息结构体,该结构定义了用于在MSS和DSS之间通信的消息结构。结构体原型如下;
从MmwDemo_message(参数1的结构体类型)结构体原型中可以看到它总共有三个元素,其中从上到下依次是type、subFrameNum、body,其中
type mmWave demo中用于MSS和DSS之间邮箱通信的消息类型。它是MmwDemo_message_type类型的枚举,保存mmWave demo中MSS和
DSS之间用于邮箱通信的所有消息类型。
subFrameNum 此消息适用的子帧号。 仅当使用高级帧配置时有效。 当高级帧配置不使用时,该字段应该设置为
MMWDEMO_SUBFRAME_NUM_FRAME_LEVEL_CONFIG。
body 毫米波演示中用于将配置从MSS传递到DSS的消息体。它的结构体原型如下;
从MmwDemo_message_body(参数1中元素body的结构体类型)结构体中可以看到,它总共有四个属性,其中从上到下依次是detObj、dataLogger、assertInfo、dss2mssISRinfoAdress,其中它们的作用如下
detObj DSS处理好的探测信息,即用于报告从数据路径到MSS的检测信息的消息 ,消息的格式满足TLV报文格式。
dataLogger 数据路径输出数据流大小的设置
assertInfo DSS断言消息,即用于报告DSS断言信息的消息 ,该结构定义了应转发到MSS的关于DSS异常的信息的消息体。
dss2mssISRinfoAddress DSS到MSS ISR信息存储的地址,通常在HSRAM中 ,通常HSRAM也叫做共享寄存器,用来存放DSS/MSS产生的消息,换句话说
DSS将处理好的消息存放到HSRAM,并告诉MSS,这时MSS就会去访问HSRAM并处理消息,同样MSS也如此;
补充:
TLV消息格式
携带检测信息的输出报文每帧通过UART发送出去。 每个报文由头MmwDemo_output_message_header_t和包含MmwDemo_output_message_type_e中枚举类型的各种数据信息的TLV条目数组成(即在下面的结构体原型中的tlv元素,它是一个数组,数组的长度是MmwDemo_output_message_type_e枚举类型)。 类型的数值可以在mmw_output.h中找到。 每个TLV项(看下图tlv结构体)由类型、长度和载荷信息(通常为地址信息)组成。 输出包的结构如下图所示。 由于数据包的长度取决于检测到的对象的数量,因此它可以在帧与帧之间变化。 包的结尾被填充,因此包的总长度总是32字节的倍数。
tlv结构体:
2)参数 2(retVal)
这个参数用于接收API的返回值,并通过这个返回值来判断API的执行状态。这里声明后直接赋值为0;
3.读取消息
在声明参数后,接下来就是在一个while循环里读取邮箱中的信息,进入while循环首先看到 Semaphore_pend代码,这是用来阻塞线程执行的,因为这个while循环是一个无限循环的函数且,可以将 Semaphore_pend当做函数的出口,它需要等待邮箱执行回调函数 MmwDemo_mboxCallback释放信号量才能接着执行,当DSS向邮箱写入消息时,促发这个回调函数,从而释放信号量,在信号量释放后,由于此时邮箱中已经有消息写入了,这时就需要将消息读取出来存储在前面声明的参数message中(这个过程是由 Mailbox_read API完成的),并将API的返回值传递给参数retVal,然后通过retVal的值(这个值是返回读取的字节数)来判断Mailbox_read API的执行状态,如果小于0则说明读取失败,等于0则表明消息为空,继续循坏这个while循坏,如果都不是,则成功将DSS存放在HSRAM寄存器中的数据读取出来存放在message参数中,接下来就是对这个消息进行读取。
MmwDemo_mboxCallback回调函数
在成功将消息读取到message参数后,接下来就是对message进行后续处理,从而通过串口(UART)将数据发送到上位机。在进行后续处理前,首先需要将邮箱的内容清除,以表明消息已处理完毕。 这将允许我们在处理接收到的消息时在邮箱中接收另一条消息。这个过程是由 Mailbox_readFlush API完成的。如下代码片段;
邮箱消息清除完成后,接下来就是通过switch 语句对message进行后续处理,通过判断message.type(消息类型)选择需要执行的代码块,当这个消息类型为MMWDEMO_DSS2MSS_DETOBJ_READY(DSS到MSS的消息,数据处理完成消息)时,表明message.body中存储的是数据路径处理完成的数据,开始执行对应的操作。值得注意的是,在这里,它将执行如下的代码片段完成message.body中消息的传输;
在上面的代码中,首先声明三个局部参数,依次为totalPacketLen、numPaddingBytes、itemIdx;
totalPacketLen 用于记录数据包的总长度
numPaddingBytes 用于记录数据报后需要填充的bite数
itemIdx 由于循坏的参数
局部参数声明完成后,接下来就是对消息通过UART串口发送到上位机,消息头和消息体依次发送;
发送消息头:
totalPacketLen = sizeof(MmwDemo_output_message_header);//表示先计算消息头的长度,后续每发送一个Tlv报文,这个数据包长度就增加一个tlv长度
发送消息体:
消息体需要通过一个for循坏来多次发送,主要是因为一个数据包中,包含多个TLV报文
将消息头和消息体都发送完成后,由于每个数据包总是32字节的倍数,所以需要检查这个数据包是否满足这个条件,如果不满足则需要在数据包后进行填充0,使其满足这个条件为止,如下代码片段所示;
到此就完整的将一个数据包发送到上位机,即参数(message)中的信息已经成功通过数据包发送给上位机,接下来就是MSS向邮箱存放消息告知DSS已经将你存放的消息处理完成了,值得注意的是,MSS在进行相关的邮箱写入操作时,需要将参数(message)初始化为了0。如下所示,在这里MSS通过外部函数MmwDemo_mboxWrite完成邮箱写入过程;
MmwDemo_mboxWrite函数:
到这里为止,当message.type=MMWDEMO_DSS2MSS_DETOBJ_READY类型的情况已经讲解完。当message.type=MMWDEMO_DSS2MSS_ASSERT_INFO(DSS到MSS的断言信息),代码块如下;
这表明,当参数(message)消息头等于这个时候,说明DSS发生了某些错误,需要中断程序,即调用断言函数,并且将错误信息显示在CLI命令行窗口,这是通过CLI_write API完成的。
在这个switch开关函数中除了上述描述的两种类型的消息头有定义外,其余的都无定义,在控制台显示错误信息,如下所示。
函数原型:
1)
描述
函数,从邮箱读取数据。邮箱一次只能从远程端点读取一条消息。 可以对邮箱中的同一消息执行多个Mailbox_read()调用。例如,应用程序可以读取消息的一部分来计算整个消息的长度,并发出后续的Mailbox_read()。邮箱驱动程序在内部跟踪为消息读取的字节数。 消息的第一个Mailbox_read()总是从字节0开始。 对于同一消息调用多个Mailbox_read()的情况,后续读取将从前一次读取停止的位置的下一个字节开始。 一旦应用程序完成读取消息,它必须发出Mailbox_readFlush()来释放邮箱缓冲区并通知远程端点。邮箱缓冲区的最大大小由MAILBOX_DATA_BUFFER_SIZE( (int32_t) 2044U)给出。 如果邮件的大小大于邮箱缓冲区,则应用程序代码负责对邮件进行分段处理。 所有与读取操作相关的中断都由驱动程序管理,不向应用程序公开。 返回已读取或错误的字节数。
参数
handle 邮箱控制句柄
buffer 指向空缓冲区的指针,接收到的数据应写入其中。
size 要写入缓冲区的字节数
返回值
返回已从邮箱中读取的字节数。 如果发生错误,则返回邮箱错误码之一。
2)
描述
应在应用程序完成读取消息后调用的函数。通知远程端点,在读取上一条消息之后,本地邮箱已准备好接收新消息。在本地端点发出Mailbox_readFlush()之前,远程端点不能向本地端点发送新消息。 一旦发出Mailbox_readFlush(),本地端点必须假定先前接收到的消息不再位于邮箱缓冲区中,并且后续的Mailbox_read()将不返回任何数据,直到新消息到达邮箱。
参数
handle 邮箱控制句柄
返回值
在失败时返回错误代码。
3)
描述
这个函数启动一个向UART控制器写入数据的操作,将数据写入UART。
参数
handle UART控制句柄
buffer 指向缓冲区的指针,其中包含要写入UART的数据
size 缓冲区中应该写入UART的字节数
返回值
返回已写入UART的字节数。 如果发生错误,则返回其中一个UART错误码。
4)
描述
将数据写入邮箱的函数。邮箱一次只能向远程端点发送一条消息。 数据复制到邮箱缓冲区后,驱动程序触发对远程端点的中断。 这意味着对Mailbox_write()的调用始终是一个完整的邮箱事务。 只有在前一条消息得到远程端点的确认之后,才能发送新消息。 确认过程由驱动程序内部处理。 所有与写操作相关的中断都由驱动程序管理,不向应用程序公开。 如果调用时使用的数据将超过邮箱缓冲区的最大大小,则写入操作将失败,并显示错误代码,并且不会向邮箱缓冲区写入任何内容。 返回写入的字节数或错误。
参数
handle UART控制句柄
buffer 指向包含要写入邮箱的数据的缓冲区的指针。
size 缓冲区中应该写入邮箱的字节数。
返回值
返回已写入邮箱的字节数。 如果发生错误,则返回邮箱错误码之一。
5)
描述
将消息记录到CLI控制台。
参数
format 格式字符串
返回值
无
结束语
读取邮箱的任务线程函数到这里就结束了,如有任何疑问,或小编有写错的地方,可以私信相互沟通学习。
参考资料
mmwave_automotive_toolbox\mmwave_automotive_toolbox_3_5_0\labs\lab0002_short_range_radar
mmwave_sdk_03_05_00_04\docs\mmwave_sdk_module_documentation.html