MSS代码解读-MmwDemo_mboxReadTask线程(八)

摘要:本篇文章主要是围绕着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

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
#精准延迟包: from ctypes import windll import cv2 ##检测模式 import numpy as np #为睡眠做准备 TimeBeginPeriod = windll.winmm.timeBeginPeriod HPSleep = windll.kernel32.Sleep TimeEndPeriod = windll.winmm.timeEndPeriod #精准延迟 def Precise_delay(num): # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ TimeBeginPeriod(1) HPSleep(int(num)) # 减少报错 TimeEndPeriod(1) #截图模式 def Screenshot_Mode(ps_mode , pos_x,pos_y,mcx,mcy): if ps_mode == 0: from mss import mss Screenshot_value = mss() #目标检测范围 window_size_mss = (pos_x- mcx , pos_y - mcy , pos_x + mcx , pos_y + mcy) # monitor = 960-320,540-320,960+320,540+320 window_size = { "left":pos_x- mcx, "top":pos_y - mcy, "width":pos_x + mcx, "height":pos_y + mcy, } #目标检测中心点 core_x = int((window_size_mss[2]-window_size_mss[0])/2) core_y = int((window_size_mss[3]-window_size_mss[1])/2) elif ps_mode == 1: print("使用DXGI截图") from d3dshot import create # pip install d3dshot -i https://pypi.tuna.tsinghua.edu.cn/simple Screenshot_value = create("numpy",frame_buffer_size = 100) #目标检测范围 window_size = (pos_x- mcx , pos_y - mcy , pos_x + mcx , pos_y + mcy) #目标检测中心点 core_x = int((window_size[2]-window_size[0])/2) core_y = int((window_size[3]-window_size[1])/2) return window_size,core_x,core_y,Screenshot_value #检测模式 def Detection_mode(test_mode,Screenshot_value,window_size): if test_mode == 0: img = Screenshot_value.grab(window_size) img = np.array(img) img = cv2.cvtColor(img, cv2.COLOR_BGRA2BGR)#原版 elif test_mode == 1: img = Screenshot_value.screenshot(region=window_size) #使用opencv删除一个通道 img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR) return img window_size,core_x,core_y,Screenshot_value = Screenshot_Mode(0, 960, 540, 150, 150) print(window_size,core_x,core_y,Screenshot_value) img = Detection_mode(0, Screenshot_value, window_size) print(img) 这个代码实现了什么功能
07-16

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值