TI AWR1642 评估板 77G行人检测雷达代码分析(3-1)-任务(MSS工程)
之前,讲了四个主要的任务,只是大概讲了每个任务是做什么的,但是还没有仔细分析每一个任务具体是怎么做的。
下面一起来看看吧。
首先,要明白一个概念,就是什么是任务?
我们现在的评估板是基于SYS_BIOS操作系统,在SYS_BIOS中,任务是被任务模块管理的线程,任务的优先级高于空闲循环低于硬件和软件中断的线程。
任务模块根据任务的优先级和当前执行状态动态调度和抢占任务,这确保处理器总是运行优先级最高的准备就绪的任务。
(1)Task_create(MmwDemo_mboxReadTask, &taskParams, NULL),这个任务是用来处理邮箱的信息的。
/* Create task to handle mailbox messages */
Task_Params_init(&taskParams);
taskParams.stackSize = 4*1024;
taskParams.priority = 4;
Task_create(MmwDemo_mboxReadTask, &taskParams, NULL);
按F3进一步看到如下,代码量太多,截取前面部分:
outputMessage这个结构体变量是用来输出信息的,即使用串口向上位机输出。
第一个部分是帧头信息,如:
outputMessage.magicWord[0] = 0x0102;
outputMessage.magicWord[1] = 0x0304;
outputMessage.magicWord[2] = 0x0506;
outputMessage.magicWord[3] = 0x0708;
outputMessage.platform = 0xA1642;
outputMessage.version = MMWAVE_SDK_VERSION_BUILD | //DEBUG_VERSION
(MMWAVE_SDK_VERSION_BUGFIX << 8) |
(MMWAVE_SDK_VERSION_MINOR << 16) |
(MMWAVE_SDK_VERSION_MAJOR << 24);
outputMessage.subFrameNumber = 0;
关于上位机与下位机的数据格式,大家可以参考文档pplcount_user_guide.pdf。这是帧头的信息,其他的部分可以依次对照,如下:
对应文档:
接着是,从对等邮箱中读取消息,从单个线程中调用。
retVal = Mailbox_read(gMmwMssMCB.peerMailbox, (uint8_t*)&message, sizeof(MmwDemo_message));
这个函数中, (uint8_t*)&message是指向空缓冲区的指针,应将接收到的数据写入其中,就是接收到的信息全部存在message中。
后面的程序会直接调用message这个结构体变量中的元素,例如message.type,即不同的message.type执行不同的模块。
这个函数的作用是将结构体从原地址搬移到目的地址,然后赋值给结构体inputFromDSP,结构体中的每一个元素都对应原地址结构体的每一个元素:
srcAddress = (inputFromDSP *)SOC_translateAddress(message.body.detObj.detObjOutAddress, SOC_TranslateAddr_Dir_FROM_OTHER_CPU,NULL);
后面会将srcAddress 结构体的元素赋值给outputMessage的元素。
接着是,点云数据上传部分,其中有获取点数numPoints、最大点数限制125、然后给点云数据加上帧头等信息。。
numPoints = srcAddress->outputToTracker.object_count;
if(numPoints > gMmwMssMCB.cfg.trackingCfg.config.maxNumPoints) {
numPoints = gMmwMssMCB.cfg.trackingCfg.config.maxNumPoints;
}
if (numPoints > 125) {
outPoints = 125;
} else {
outPoints = numPoints;
}
if(numPoints) {
gMmwMssMCB.pointCloud->header.length = sizeof(MmwDemo_output_message_tl) + outPoints*sizeof(MmwDemo_output_message_point);
for(nPoint = 0; nPoint < numPoints; nPoint++) {
gMmwMssMCB.pointCloud->point[nPoint].range = srcAddress->outputToTracker.range[nPoint];
gMmwMssMCB.pointCloud->point[nPoint].azimuth = srcAddress->outputToTracker.angle[nPoint] + gMmwMssMCB.cfg.applicationCfg.sensorAzimuthTilt;
gMmwMssMCB.pointCloud->point[nPoint].doppler = srcAddress->outputToTracker.doppler[nPoint];
gMmwMssMCB.pointCloud->point[nPoint].snr = srcAddress->outputToTracker.snr[nPoint];
}
}
else
gMmwMssMCB.pointCloud->header.length = 0;
gMmwMssMCB.mssDataPathObj.cycleLog.copyResultsTimeCurrInusec = ((float)(Cycleprofiler_getTimeStamp() - timeStart))/(float)R4F_CLOCK_MHZ;
if ((gMmwMssMCB.mssDataPathObj.cycleLog.copyResultsTimeCurrInusec > 0) && (gMmwMssMCB.mssDataPathObj.cycleLog.copyResultsTimeCurrInusec > gMmwMssMCB.mssDataPathObj.cycleLog.copyResultsTimeMaxInusec))
gMmwMssMCB.mssDataPathObj.cycleLog.copyResultsTimeMaxInusec = gMmwMssMCB.mssDataPathObj.cycleLog.copyResultsTimeCurrInusec;
点云信息主要包含四个部分:距离、速度、角度、信噪比,如下代码可见,我们要知道上位机和下位机之间的数据是如何组建的,这里就说的很清楚了。
for(nPoint = 0; nPoint < numPoints; nPoint++) {
gMmwMssMCB.pointCloud->point[nPoint].range = srcAddress->outputToTracker.range[nPoint];
gMmwMssMCB.pointCloud->point[nPoint].azimuth = srcAddress->outputToTracker.angle[nPoint] + gMmwMssMCB.cfg.applicationCfg.sensorAzimuthTilt;
gMmwMssMCB.pointCloud->point[nPoint].doppler = srcAddress->outputToTracker.doppler[nPoint];
gMmwMssMCB.pointCloud->point[nPoint].snr = srcAddress->outputToTracker.snr[nPoint];
}
接着是将message中的全部内容清零,然后利用MmwDemo_mboxWrite(&message)写到MSS的中,这里可能是为了向MSS发送消息以记录输出数据:
/* Send a message to MSS to log the output data */
memset((void *)&message, 0, sizeof(MmwDemo_message));
message.type = MMWDEMO_MSS2DSS_DETOBJ_SHIPPED;
if (MmwDemo_mboxWrite(&message) != 0)
{
System_printf ("Error: Mailbox send message id=%d failed \n", message.type);
}
接着是组建的雷达对行人检测跟踪的数据的帧头信息:
/* Post a job for group tracker */
sendDescr = gMmwMssMCB.targetDescrHandle->currentDescr;
gMmwMssMCB.targetDescrHandle->currentDescr = !sendDescr;
if(gMmwMssMCB.mssDataPathObj.groupTrackerEnabled)
Semaphore_post(gMmwMssMCB.appSemHandle);
outputMessage.timeStamp = Cycleprofiler_getTimeStamp();
outputMessage.totalPacketLen = sizeof(MmwDemo_output_message_header);
outputMessage.numTLVs = 0;
outputMessage.checksum = 0;
if(gMmwMssMCB.pointCloud->header.length && gMmwMssMCB.pcEnable) {
/* Add pointCloud TLV length */
outputMessage.totalPacketLen += gMmwMssMCB.pointCloud->header.length;
outputMessage.numTLVs += 1;
}
if(gMmwMssMCB.targetDescrHandle->tList[sendDescr]->header.length) {
/* Add targetList TLV length */
outputMessage.totalPacketLen += gMmwMssMCB.targetDescrHandle->tList[sendDescr]->header.length;
outputMessage.numTLVs += 1;
}
if(gMmwMssMCB.targetDescrHandle->tIndex[sendDescr]->header.length) {
/* Add targetIndex TLV length */
outputMessage.totalPacketLen += gMmwMssMCB.targetDescrHandle->tIndex[sendDescr]->header.length;
outputMessage.numTLVs += 1;
}
接着是校验,校验信息也是要上传到上位机的:
/* Calculate header checksum */
headerPtr = (uint16_t *)&outputMessage;
for(n=0, sum = 0; n < sizeof(MmwDemo_output_message_header)/sizeof(uint16_t); n++)
sum += *headerPtr++;
outputMessage.checksum = ~((sum >> 16) + (sum & 0xFFFF));
//GPIO_toggle(SOC_XWR16XX_PINP5_PADBG);
/* Always send a packet header */
调用UART_write函数执行发送,主要有几个部分:
第一个是outputMessage,是包头
第二个是gMmwMssMCB.pointCloud,是点云数据
第三个是 gMmwMssMCB.targetDescrHandle->tList[sendDescr],列表数据,包含坐标信息。
第四个是gMmwMssMCB.targetDescrHandle->tIndex[sendDescr],目标指数,包含跟踪ID号。
UART_write (gMmwMssMCB.loggingUartHandle, (uint8_t *)&outputMessage, sizeof(MmwDemo_output_message_header));
if(gMmwMssMCB.pointCloud->header.length && gMmwMssMCB.pcEnable) {
/* If any points detected, send Point Cloud TLV */
UART_write (gMmwMssMCB.loggingUartHandle, (uint8_t *)gMmwMssMCB.pointCloud, gMmwMssMCB.pointCloud->header.length);
}
if(gMmwMssMCB.targetDescrHandle->tList[sendDescr]->header.length) {
/* If any targets tracked, send send target List TLV */
UART_write (gMmwMssMCB.loggingUartHandle, (uint8_t *)gMmwMssMCB.targetDescrHandle->tList[sendDescr], gMmwMssMCB.targetDescrHandle->tList[sendDescr]->header.length);
}
if(gMmwMssMCB.targetDescrHandle->tIndex[sendDescr]->header.length) {
/* If exists, send target Index TLV */
UART_write (gMmwMssMCB.loggingUartHandle, (uint8_t *)gMmwMssMCB.targetDescrHandle->tIndex[sendDescr], gMmwMssMCB.targetDescrHandle->tIndex[sendDescr]->header.length);
}
//GPIO_toggle(SOC_XWR16XX_PINP5_PADBG);
这些地方都可以修改,自己重新制作上位机,把数据格式弄明白之后,就可以解析出来。
好了,由于时间关系,今天就到这里吧,下次继续分享,有写的不好的地方,希望大家直接说出来,很多地方其实我也看的不是很明白。感谢大家,一起学习。