• TI的单芯片毫米波雷达传感器配置命令是如何传递到DSP和ARM核的?(串口程序代码走读)


    本文编辑:调皮哥的小助理

    TI毫米波雷达配置命令是如何传递到DSP和ARM核的?(程序代码走读)

    TI毫米波雷达,上位机通过串口接收数据,雷达配置命令也是上位机通过串口下发到雷达芯片里,如下图所示。那么这是如何做到的呢?

    在这里插入图片描述
    (雷达配置参数(射频前端+信号处理+数据处理算法))

    在这里插入图片描述
    (上传数据格式(部分))

    今天我以【呼吸心跳检测例程】为大家分享串口参数这个事儿。

    其中两个串口都要介绍,一个控制串口,一个是数据串口。

    〇、串口初始化位置

    先来看代码,本文代码只截取一些关键部位,详细内容请回归例程详细阅读。

    1.串口波特率设置和初始化

    gMmwMssMCB.cfg.loggingBaudRate   = 921600;
    gMmwMssMCB.cfg.commandBaudRate   = 115200;
    
    /* Initialize the UART */
    UART_init();
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2.串口参数设置(两个串口都配置)

    /* Setup the default UART Parameters */
    UART_Params_init(&uartParams);
    uartParams.clockFrequency  = gMmwMssMCB.cfg.sysClockFrequency;
    uartParams.baudRate        = gMmwMssMCB.cfg.commandBaudRate;
    uartParams.isPinMuxDone    = 1U;
    
    /* Setup the default UART Parameters */
    UART_Params_init(&uartParams);
    uartParams.writeDataMode = UART_DATA_BINARY;
    uartParams.readDataMode = UART_DATA_BINARY;
    uartParams.clockFrequency = gMmwMssMCB.cfg.sysClockFrequency;
    uartParams.baudRate       = gMmwMssMCB.cfg.loggingBaudRate;
    uartParams.isPinMuxDone   = 1U;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    3.打开串口

    /* Open the Logging UART Instance: */
    gMmwMssMCB.loggingUartHandle = UART_open(1, &uartParams);
    
    • 1
    • 2

    一、数据串口

    前面串口配置初始化完成之后,就是打开串口,然后就等待程序发送数据了。首先是数据串口,数据串口发送的数据比较多,数据协议今天不提,大家参照TI给提供的数据文档解析就完事儿了,很简单的。下面说一下数据串口在哪里发送数据的。

    1.MmwDemo_mboxReadTask(读邮箱任务)

    /* Create task to handle mailbox messges */
    Task_Params_init(&taskParams);
    taskParams.stackSize = 16*1024;
    Task_create(MmwDemo_mboxReadTask, &taskParams, NULL);
    
    • 1
    • 2
    • 3
    • 4

    进到这个任务中,可以看到这个语句:

    retVal = Mailbox_read(gMmwMssMCB.peerMailbox, (uint8_t*)&message,
    sizeof(MmwDemo_message));

    这个就是把DSS那边传过来的信息给读取出来,放到message中。然后下面根据message信息往上位机进行传送。下面这段代码比较重要:

                    totalPacketLen = sizeof(MmwDemo_output_message_header);
                    UART_writePolling (gMmwMssMCB.loggingUartHandle,
                                       (uint8_t*)&message.body.detObj.header,
                                       sizeof(MmwDemo_output_message_header));
    
                    /* Send TLVs */
                    for (itemIdx = 0;  itemIdx < message.body.detObj.header.numTLVs; itemIdx++)
                    {
                        UART_writePolling (gMmwMssMCB.loggingUartHandle,
                                           (uint8_t*)&message.body.detObj.tlv[itemIdx],
                                           sizeof(MmwDemo_output_message_tl));
                        UART_writePolling (gMmwMssMCB.loggingUartHandle,
                                           (uint8_t*)SOC_translateAddress(message.body.detObj.tlv[itemIdx].address,
                                                                          SOC_TranslateAddr_Dir_FROM_OTHER_CPU,NULL),
                                           message.body.detObj.tlv[itemIdx].length);
                        totalPacketLen += sizeof(MmwDemo_output_message_tl) + message.body.detObj.tlv[itemIdx].length;
                    }
    
                    /* Send padding to make total packet length multiple of MMWDEMO_OUTPUT_MSG_SEGMENT_LEN */
                    numPaddingBytes = MMWDEMO_OUTPUT_MSG_SEGMENT_LEN - (totalPacketLen & (MMWDEMO_OUTPUT_MSG_SEGMENT_LEN-1));
                    if (numPaddingBytes
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    MSS用函数UART_writePolling()即可把数据传送到上位机,那么具体这些数据内部是什么,下面继续分解。

    上面的程序用了四个UART_writePolling()函数:

    (1)帧头header

    (2)TLV

    (3)address

    (4)padding

    关于这些信息的具体含义,大家参照【呼吸心跳检测例程】PDF文档看就知道了,这里不做过多的阐述。其中这里最关键的信息是(3)address。这里传送的是一个地址,但是其实是传递这个地址下面的数据,具体地址下面是什么数据,接着解析。

    现在我们去寻找数据的来源,即前往DSP核去查看。

    依次往下寻找这些函数:

    2.static void MmwDemo_dssDataPathTask(UArg arg0, UArg arg1)

    if(event & MMWDEMO_FRAMESTART_EVT)
    {
    if(gMmwDssMCB.state == MmwDemo_DSS_STATE_STARTED)
    {
    if ((retVal = MmwDemo_dssDataPathProcessEvents(MMWDEMO_FRAMESTART_EVT)) < 0 )
    {
    System_printf (“Error: MMWDemoDSS Data Path process frame start event failed with Error[%d]\n”,
    retVal);
    }
    }
    }

    3.static int32_t MmwDemo_dssDataPathProcessEvents(UInt event)

                /* Sending detected objects to logging buffer */
                MmwDemo_dssDataPathOutputLogging (dataPathObj); 
                dataPathObj->frameProcDoneTimeStamp = Cycleprofiler_getTimeStamp();
    
    • 1
    • 2
    • 3

    4. void MmwDemo_dssDataPathOutputLogging(MmwDemo_DSS_DataPathObj * dataPathObj)
    /* Save output in logging buffer - HSRAM memory and a message is sent to MSS to notify
    logging buffer is ready /
    if (MmwDemo_dssSendProcessOutputToMSS(dataPathObj) < 0)
    {
    /
    Increment logging error */
    gMmwDssMCB.stats.detObjLoggingErr++;
    }

    5. int32_t MmwDemo_dssSendProcessOutputToMSS(uint8_t *ptrHsmBuffer,uint32_t outputBufSize, MmwDemo_DSS_DataPathObj *obj)

    这个函数下是关键信息,包含帧头、字节长度、类型、地址等等:

    在这里插入图片描述
    在这里插入图片描述

    下面疑惑的就是address映射的内容是什么了。

    (1)首先看赋值的指针:

    message.body.detObj.tlv[tlvIdx].address = (uint32_t) ptrCurrBuffer;;

    (2)内存复制

     memcpy(ptrCurrBuffer, (void *)&vitalSignsStats, itemPayloadLen);
    
    • 1

    (3)vitalSignsStats结构体

      VitalSignsDemo_OutputStats vitalSignsStats;
    
    • 1

    (4)进入VitalSignsDemo_OutputStats查看

    在这里插入图片描述

    这些就是数据协议里传输的数据,都在这里面了,经过前面的一顿操作,现在终于搞清楚了,不得不说TI搞得很牛,封装得很全!

    数据上传的部分说完了,现在讲数据下发,这个也不难!

    请做好准备,这是今天的关键部分!

    二、控制串口

    回到MSS工程,去找到 Task_create(MmwDemo_mssInitTask, &taskParams, NULL)任务,然后进去寻找 MmwDemo_CLIInit()函数。

     * At this point, MSS and DSS are both up and synced. Configuration is ready to be sent.
     * Start CLI to get configuration from user
     *****************************************************************************/
    MmwDemo_CLIInit();
    
    • 1
    • 2
    • 3
    • 4

    进入MmwDemo_CLIInit()函数,可以发现这个函数是雷达配置命令的格式说明,如。

    在这里插入图片描述

    所有的配置参数都被cliCfg所定义。

    最后这个函数是关键的地方:

    /* Open the CLI: */
    if (CLI_open (&cliCfg) < 0)
    {
        System_printf ("Error: Unable to open the CLI\n");
        return;
    }
    System_printf ("Debug: CLI is operational\n");
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    CLI_open (&cliCfg)函数,这是用于初始化和设置 CLI 的函数。具体的函数定义,需要在SDK中去寻找。
    在这里插入图片描述

    找到CLI_open (CLI_Cfg* ptrCLICfg)函数的具体定义如下:

    int32_t CLI_open (CLI_Cfg* ptrCLICfg)
    {
    Task_Params taskParams;
    uint32_t index;
    /* Sanity Check: Validate the arguments /
    if (ptrCLICfg == NULL)
    return -1;
    /
    Initialize the CLI MCB: /
    memset ((void
    )&gCLI, 0, sizeof(CLI_MCB));
    /* Copy over the configuration: */
    memcpy ((void *)&gCLI.cfg, (void )ptrCLICfg, sizeof(CLI_Cfg));
    /
    Cycle through and determine the number of supported CLI commands: /
    for (index = 0; index < CLI_MAX_CMD; index++)
    {
    /
    Do we have a valid entry? /
    if (gCLI.cfg.tableEntry[index].cmd == NULL)
    {
    /
    NO: This is the last entry /
    break;
    }
    else
    {
    /
    YES: Increment the number of CLI commands /
    gCLI.numCLICommands = gCLI.numCLICommands + 1;
    }
    }
    /
    Is the mmWave Extension enabled? /
    if (gCLI.cfg.enableMMWaveExtension == 1U)
    {
    /
    YES: Initialize the CLI Extension: /
    if (CLI_MMWaveExtensionInit (ptrCLICfg) < 0)
    return -1;
    }
    /
    Do we have a CLI Prompt specified? /
    if (gCLI.cfg.cliPrompt == NULL)
    gCLI.cfg.cliPrompt = “CLI:/>”;
    /
    The CLI provides a help command by default:
    * - Since we are adding this at the end of the table; a user of this module can also
    * override this to provide its own implementation. /
    gCLI.cfg.tableEntry[gCLI.numCLICommands].cmd = “help”;
    gCLI.cfg.tableEntry[gCLI.numCLICommands].helpString = NULL;
    gCLI.cfg.tableEntry[gCLI.numCLICommands].cmdHandlerFxn = CLI_help;
    /
    Increment the number of CLI commands: /
    gCLI.numCLICommands++;
    /
    Initialize the task parameters and launch the CLI Task: /
    Task_Params_init(&taskParams);
    taskParams.priority = gCLI.cfg.taskPriority;
    taskParams.stackSize = 4
    1024;
    gCLI.cliTaskHandle = Task_create(CLI_task, &taskParams, NULL);
    return 0;
    }

    在这个程序中有一个任务:

    gCLI.cliTaskHandle = Task_create(CLI_task, &taskParams, NULL);
    
    • 1

    点进去看任务,看到有一个串口读的程序段。

        /* Read the command message from the UART: */
        UART_read (gCLI.cfg.cliUartHandle, &cmdString[0], (sizeof(cmdString) - 1));
    
    • 1
    • 2

    其中有这么一段程序,这个就是我们之前下发命令时,上位机收到下位机的echo命令,用于确保命令下发正确(匹配):

    在这里插入图片描述
    在这里插入图片描述

    看到现在真不容易,但是下面的真的很关键,我都差点看晕过去。

    串口读到的数据存在cmdString[0]中,然后给了:

    ptrCLICommand = (char*)&cmdString[0];

    给了 ptrCLICommand, ptrCLICommand拆分又给了 tokenizedArgs[argIndex]。

       tokenizedArgs[argIndex] = strtok(ptrCLICommand, delimitter);
    
    • 1

    继续进入CLI_MMWaveExtensionHandler()函数

       cliStatus = CLI_MMWaveExtensionHandler (argIndex, tokenizedArgs);
    
    • 1

    在这里插入图片描述

    该函数中定义最关键的部分是:

    /* Get the pointer to the mmWave extension table */
    ptrCLICommandEntry = &gCLIMMWaveExtensionTable[0];
    
    • 1
    • 2

    &gCLIMMWaveExtensionTable[0]下就是串口数据赋值给雷达。

    在这里插入图片描述

    举个例子如,就是下面程序中进行赋值的:

    在这里插入图片描述
    在这里插入图片描述

    至此,我们知道了整个TI毫米波雷达串口数据上传、下发的所有过程,可谓历经千辛万苦,人都快吐了。

    还有很多地方解释的不详细,具体内容大家可以细细研究,如有写错还请告知。

    创作不宜,谢谢你的赞!

  • 相关阅读:
    如何正确计算导入Excel的行数(POI/NPOI)
    NVM Express® Zoned Namespace Command Set Specification翻译
    巨量广告投放时间段和计划类型如何配合使用?
    部队射击场实弹打靶有哪些注意事项?
    《C和指针》笔记22: 指针初始化和NULL指针
    深入理解java虚拟机-1.自动内存管理
    【MATLAB教程案例50】通过VisualSFM工具箱提取360度等间隔环绕拍摄得到的图像序列点云数据,并进行目标三维重建matlab仿真
    C/C++在嵌入式中地位不保,Rust将成为更好的“备胎”?
    Related to the third param of function “sort“ & Lambda of Cpp
    家长杂志家长杂志社家长编辑部2022年第30期目录
  • 原文地址:https://blog.csdn.net/qq_35844208/article/details/127719869