【TI毫米波雷达】IWR6843AOP的CCS工程模板创建(MSS)(cannot find file “libsleep_xwr68xx.aer4f“解决方案)

【TI毫米波雷达】IWR6843AOP的CCS工程模板创建(MSS)(cannot find file "libsleep_xwr68xx.aer4f"解决方案)

主要参考:
基于mmWave SDK创建一个IWR6843工程模板(MSS侧)

本文大体上与之类似 但用的SDK是3.5版本
若遇到报错:

cannot find file "libsleep_xwr68xx.aer4f"

则按我的配置流程和我先前的文章来

MSS工程模板:

TI毫米波雷达IWR6843AOP的CCS工程模板(MSS)

根据官方工程改的模板:

工程创建

新建工程

在CCS里面新建工程 选择芯片 调试用设备和typical工程类型在这里插入图片描述
Next之后要求选择Target和Platform,在页面下方处如下填写:

Target: ti.targets.arm.elf.R4Ft
Platform: ti.platforms.cortexR:IWR68XX:false:200

Build-profile任意选择
建立好工程以后 在工程属性的general中也可以进行更改 只不过改到release版本以后需要重新配置各个设置
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
另外 在products中 点击add 添加mmwave sdk和sysconfig 如图

修改文件

这样工程就创建好了。在左侧的Project Explorer中,可以看到。接下来,我们需要对工程的属性进行调整,并覆盖一些工程自带的文件来满足开发需求。
在这里插入图片描述
其中 main.h main_callback.h和main_callback.h是我自己添加的
代码如下:

main.c:

#include "main.h"

//MCPI_LOGBUF_INIT(9216);
MMWave_Global MMWave_Global_Params={0};

void Init_UART(void)
{
    UART_Params uart0_params;
    /* 串口引脚初始化 */
    /* 共有两个串口,分别为UART-1和UART-3,序号为0和2 */
    /* Setup the PINMUX to bring out the MSS UART-1 */
    Pinmux_Set_FuncSel(SOC_XWR68XX_PINN5_PADBE, SOC_XWR68XX_PINN5_PADBE_MSS_UARTA_TX);
    Pinmux_Set_OverrideCtrl(SOC_XWR68XX_PINN5_PADBE, PINMUX_OUTEN_RETAIN_HW_CTRL, PINMUX_INPEN_RETAIN_HW_CTRL);
    Pinmux_Set_FuncSel(SOC_XWR68XX_PINN4_PADBD, SOC_XWR68XX_PINN4_PADBD_MSS_UARTA_RX);
    Pinmux_Set_OverrideCtrl(SOC_XWR68XX_PINN4_PADBD, PINMUX_OUTEN_RETAIN_HW_CTRL, PINMUX_INPEN_RETAIN_HW_CTRL);

    // 这一块用不上
    /* Setup the PINMUX to bring out the MSS UART-3 */
//    Pinmux_Set_OverrideCtrl(SOC_XWR68XX_PINF14_PADAJ, PINMUX_OUTEN_RETAIN_HW_CTRL, PINMUX_INPEN_RETAIN_HW_CTRL);
//    Pinmux_Set_FuncSel(SOC_XWR68XX_PINF14_PADAJ, SOC_XWR68XX_PINF14_PADAJ_MSS_UARTB_TX);

    UART_Params_init(&uart0_params);

    uart0_params.baudRate = 115200*8;                   //波特率115200*8
    uart0_params.clockFrequency = MSS_SYS_VCLK;      //系统时钟频率200MHz
    uart0_params.dataLength = UART_LEN_8;             //8bit字长
    uart0_params.isPinMuxDone = 1;                    //已经完成引脚复用初始化
    uart0_params.parityType = UART_PAR_NONE;          //无校验位
    uart0_params.readDataMode = UART_DATA_BINARY;     //按位方式读取数据
    uart0_params.readEcho = UART_ECHO_OFF;            //关闭回显
    uart0_params.readReturnMode = UART_RETURN_FULL;   //完整读取
    uart0_params.stopBits = UART_STOP_ONE;            //1停止位
    uart0_params.writeDataMode = UART_DATA_BINARY;    //按位方式写入(发送)数据

    MMWave_Global_Params.handle.uart0_handle = UART_open(0, &uart0_params);             //打开串口

    if(MMWave_Global_Params.handle.uart0_handle == NULL)
    {
        System_printf("[INFO] UART0 open fail\n!");
        return;
    }
    else
    {
        System_printf("[INFO] UART0 open success\n!");
        /*
        while(1)
        {
            //不断读取收到的数据,并通过串口发送出去
            //该函数会使进程进入挂起等待状态,不会使其他任务无法执行
            //可以发现打印任务也可以执行
            UART_read(MMWave_Global_Params.handle.uart0_handle, &MMWave_Global_Params.uart0_rx, 1);
            UART_write(MMWave_Global_Params.handle.uart0_handle, &MMWave_Global_Params.uart0_rx, 1);
        }
        */
    }
}

/**
 *  @b Description
 *  @n
 *      The task is used to provide an execution context for the MMWave
 *      control task
 *
 *  @retval
 *      Not Applicable.
 */
void Ctrl_MMWave(UArg arg0, UArg arg1)
{
    int32_t errCode;

    while (1)
    {
        /* Execute the MMWave control module: */
        if (MMWave_execute (MMWave_Global_Params.handle.MMWave_handle, &errCode) < 0)
        {
            //System_printf ("Error: MMWave control execution failed [Error code %d]\n", errCode);
        }
    }
}

void Init_MMWave(void)
{
    int32_t         errCode;
    MMWave_InitCfg      initCfg;
    MMWave_OpenCfg      openCfg;
    MMWave_CtrlCfg      ctrlCfg;
    MMWave_CalibrationCfg       calibrationCfg;
    Task_Params     taskParams; //任务参数

    memset ((void*)&initCfg, 0 , sizeof(MMWave_InitCfg));
    memset ((void*)&initCfg, 0 , sizeof(MMWave_OpenCfg));
    memset ((void *)&calibrationCfg, 0, sizeof(MMWave_CalibrationCfg));
    memset ((void*)&ctrlCfg, 0 , sizeof(MMWave_CtrlCfg));

    initCfg.domain                  = MMWave_Domain_MSS;
    initCfg.socHandle               = MMWave_Global_Params.handle.socHandle;
    initCfg.eventFxn                = MMWave_eventFxnCallback;  //事件回调
    initCfg.linkCRCCfg.useCRCDriver = 0U;           //1开启CRC 0关闭CRC
    initCfg.linkCRCCfg.crcChannel   = CRC_Channel_CH1;      //CRC通道1
    initCfg.cfgMode                 = MMWave_ConfigurationMode_MINIMAL;  //最小模式 也可以设置成全部模式
    initCfg.executionMode           = MMWave_ExecutionMode_ISOLATION;  //MSS和DSS不通讯 如果需要 则换个模式
    //以下全是回调
    initCfg.cooperativeModeCfg.cfgFxn   = MMWave_cfgFxnCallback;
    initCfg.cooperativeModeCfg.closeFxn = MMWave_closeFxnCallback;
    initCfg.cooperativeModeCfg.openFxn  = MMWave_openFxnCallback;
    initCfg.cooperativeModeCfg.startFxn = MMWave_startFxnCallback;
    initCfg.cooperativeModeCfg.stopFxn  = MMWave_stopFxnCallback;

    /* Initialize and setup the MMWave Control module */
    MMWave_Global_Params.handle.MMWave_handle = MMWave_init (&initCfg, &errCode);
    if (MMWave_Global_Params.handle.MMWave_handle == NULL)
    {
        /* Error: Unable to initialize the MMWave control module */
        System_printf ("[INFO] Error: MMWave Control Initialization failed [Error code %d]\n", errCode);
        return;
    }
    System_printf ("[INFO] Debug: MMWave Control Initialization was successful\n");

    /* Synchronization: This will synchronize the execution of the control module
     * between the domains. This is a prerequiste and always needs to be invoked. */
    //同步
    if (MMWave_sync (MMWave_Global_Params.handle.MMWave_handle, &errCode) < 0)
    {
        /* Error: Unable to synchronize the MMWave control module */
        System_printf ("[INFO] Error: MMWave Control Synchronization failed [Error code %d]\n", errCode);
        return;
    }
    System_printf ("[INFO] Debug: MMWave Control Synchronization was successful\n");

    /*****************************************************************************
    * Launch the MMWave control execution task
    * - This should have a higher priroity than any other task which uses the
    *   MMWave control API
    *****************************************************************************/
   //这里是开了一个线程循环调用
   Task_Params_init(&taskParams);
   taskParams.priority  = 5;
   taskParams.stackSize = 3*1024;
   MMWave_Global_Params.task.MMWaveCtrl = Task_create(Ctrl_MMWave, &taskParams, NULL);

    openCfg.freqLimitLow  = 600U;   //低频限制
    openCfg.freqLimitHigh = 640U;   //高频限制

    openCfg.chCfg.rxChannelEn = 0x000F;  //开启四个RX
    openCfg.chCfg.txChannelEn = 0x0007;  //开启四个TX
    openCfg.chCfg.cascading   = 0x0000;  //不开启级联
    openCfg.chCfg.cascadingPinoutCfg = 0;  //直接给0

    openCfg.lowPowerMode.lpAdcMode = 0x0000; //Regular ADC mode

    openCfg.adcOutCfg.fmt.b2AdcBits = 2; //16bit
    openCfg.adcOutCfg.fmt.b8FullScaleReducFctr = 0; //16bit只能为0
    openCfg.adcOutCfg.fmt.b2AdcOutFmt = 2;  //Complex with Image band

    openCfg.defaultAsyncEventHandler    = MMWave_DefaultAsyncEventHandler_MSS;

    openCfg.disableFrameStartAsyncEvent = false;
    openCfg.disableFrameStopAsyncEvent  = false;

    openCfg.useCustomCalibration        = false;  // 无自定义校准 false表示默认启用所有校准
    openCfg.customCalibrationEnableMask = 0x0;

    openCfg.calibMonTimeUnit            = 1;   //一帧一次校准

    /*
    MMWave_CalibrationData      calibrationData;
    memset ((void*)&calibrationCfg, 0 , sizeof(MMWave_CalibrationCfg));

    calibrationData.ptrCalibData->calibChunk
    calibrationData.ptrPhaseShiftCalibData->PhShiftcalibChunk
    */

    /* Open the mmWave module: */
    if (MMWave_open (MMWave_Global_Params.handle.MMWave_handle, &openCfg, NULL, &errCode) < 0)
    {
        /* Error: decode and Report the error */
        //MMWave_decodeError (errCode, &errorLevel, &mmWaveErrorCode, &subsysErrorCode);
        //System_printf ("Error: mmWave Open failed [Error code: %d Subsystem: %d]\n",mmWaveErrorCode, subsysErrorCode);
    }

    ctrlCfg.dfeDataOutputMode = MMWave_DFEDataOutputMode_FRAME;

    ctrlCfg.u.frameCfg.profileHandle[0]=NULL;
    ctrlCfg.u.frameCfg.profileHandle[1]=NULL;
    ctrlCfg.u.frameCfg.profileHandle[2]=NULL;
    ctrlCfg.u.frameCfg.profileHandle[3]=NULL;

    ctrlCfg.u.frameCfg.frameCfg.chirpStartIdx = 0;
    ctrlCfg.u.frameCfg.frameCfg.chirpEndIdx = 2;
    ctrlCfg.u.frameCfg.frameCfg.numLoops = 96;
    ctrlCfg.u.frameCfg.frameCfg.numFrames = 0;
    ctrlCfg.u.frameCfg.frameCfg.numAdcSamples = 96;
    ctrlCfg.u.frameCfg.frameCfg.framePeriodicity = 11000;  //55ms
    ctrlCfg.u.frameCfg.frameCfg.triggerSelect = 0x0001; //软件API触发

    ctrlCfg.u.frameCfg.frameCfg.numDummyChirpsAtEnd = 0;
    ctrlCfg.u.frameCfg.frameCfg.frameTriggerDelay = 0;

    /*
    //frame模式不用配
    ctrlCfg.u.continuousModeCfg.cfg.startFreqConst
    ctrlCfg.u.continuousModeCfg.cfg.txOutPowerBackoffCode
    ctrlCfg.u.continuousModeCfg.cfg.txPhaseShifter
    ctrlCfg.u.continuousModeCfg.cfg.digOutSampleRate
    ctrlCfg.u.continuousModeCfg.cfg.hpfCornerFreq1
    ctrlCfg.u.continuousModeCfg.cfg.hpfCornerFreq2
    ctrlCfg.u.continuousModeCfg.cfg.rxGain
    ctrlCfg.u.continuousModeCfg.cfg.vcoSelect
    ctrlCfg.u.continuousModeCfg.dataTransSize
    */
    //ctrlCfg.u.advancedFrameCfg.profileHandle = //NULL;  //frame模式不用配

    /* Configure the mmWave module: */
    if (MMWave_config (MMWave_Global_Params.handle.MMWave_handle, &ctrlCfg, &errCode) < 0)
    {
        /* Error: Report the error */
        //MMWave_decodeError (errCode, &errorLevel, &mmWaveErrorCode, &subsysErrorCode);
        //System_printf ("Error: mmWave Config failed [Error code: %d Subsystem: %d]\n",mmWaveErrorCode, subsysErrorCode);
    }

    calibrationCfg.dfeDataOutputMode = ctrlCfg.dfeDataOutputMode;

    calibrationCfg.u.chirpCalibrationCfg.enableCalibration = true;
    calibrationCfg.u.chirpCalibrationCfg.enablePeriodicity = true;
    calibrationCfg.u.chirpCalibrationCfg.periodicTimeInFrames = 10;  //每10帧一次校准

    //calibrationCfg.u.contCalibrationCfg.enableOneShotCalibration  //frame模式不用配

    /* Start the mmWave module: The configuration has been applied successfully. */
    if (MMWave_start(MMWave_Global_Params.handle.MMWave_handle, &calibrationCfg, &errCode) < 0)
    {
        /* Error/Warning: Unable to start the mmWave module */
        //MMWave_decodeError (errCode, &errorLevel, &mmWaveErrorCode, &subsysErrorCode);
        //System_printf ("Error: mmWave Start failed [mmWave Error: %d Subsys: %d]\n", mmWaveErrorCode, subsysErrorCode);
        /* datapath has already been moved to start state; so either we initiate a cleanup of start sequence or
           assert here and re-start from the beginning. For now, choosing the latter path */
    }

}

void MMWave_InitTask (UArg arg0, UArg arg1)
{
    //MCPI_Initialize();
    GPIO_init();                //GPIO初始化
    UART_init();                //串口初始化

    Init_UART();
    Init_MMWave();
}

int main (void)
{
    int32_t         errCode;    //存放SOC初始化错误代码
    SOC_Cfg         socCfg;     //SOC配置结构体
    Task_Params     taskParams; //任务参数

    ESM_init(0U);               //与安全等有关,可略过

    /* Initialize the SOC configuration: */
    /* 初始化SOC配置结构体 */
    memset ((void *)&socCfg, 0, sizeof(SOC_Cfg));

    /* 配置SOC配置结构体 */
    /* Populate the SOC configuration: */
    socCfg.clockCfg = SOC_SysClock_INIT;
    socCfg.mpuCfg = SOC_MPUCfg_CONFIG;

    /* require to UNHALT the DSS if this core is available in selected device */
    socCfg.dssCfg = SOC_DSSCfg_UNHALT;

    /* Initialize the SOC Module: This is done as soon as the application is started
     * to ensure that the MPU is correctly configured. */

    /* SOC初始化,必须在系统运行后尽快调用该初始化函数 */
    MMWave_Global_Params.handle.socHandle = SOC_init (&socCfg, &errCode);

    if (MMWave_Global_Params.handle.socHandle == NULL)
    {
        System_printf ("[INFO] Error: SOC Module Initialization failed [Error code %d]\n", errCode);
        return -1;
    }

    /* Initialize the Task Parameters. */
    /* 创建一个任务用于测试 */
    Task_Params_init(&taskParams);
    taskParams.priority = 3;      //优先级3
    MMWave_Global_Params.task.init = Task_create(MMWave_InitTask, &taskParams, NULL);
    /* Start BIOS */
    BIOS_start();
    return 0;
}

这里priority 越大 优先级越高 越先响应

main.h:

/*
 * main.h
 *
 *  Created on: 2023年7月31日
 *      Author: ZHOU
 */

#ifndef MAIN_H_
#define MAIN_H_

#include <stdint.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
#include <math.h>

/* BIOS/XDC Include Files. */
/* SYS/BIOS所使用的头文件 */
#include <xdc/std.h>
#include <xdc/cfg/global.h>
#include <xdc/runtime/IHeap.h>
#include <xdc/runtime/System.h>
#include <xdc/runtime/Error.h>
#include <xdc/runtime/Memory.h>
#include <ti/sysbios/BIOS.h>
#include <ti/sysbios/knl/Task.h>
#include <ti/sysbios/knl/Event.h>
#include <ti/sysbios/knl/Semaphore.h>
#include <ti/sysbios/knl/Clock.h>
#include <ti/sysbios/heaps/HeapBuf.h>
#include <ti/sysbios/heaps/HeapMem.h>
#include <ti/sysbios/knl/Event.h>
#include <ti/sysbios/family/arm/v7a/Pmu.h>
#include <ti/sysbios/family/arm/v7r/vim/Hwi.h>
#include <ti/sysbios/utils/Load.h>
#include <ti/drivers/osal/MemoryP.h>

/* MMWave SDK Include Files: */
/* SDK头文件 */
#include <ti/common/sys_common.h>
#include <ti/common/MMWave_sdk_version.h>
#include <ti/drivers/soc/soc.h>
#include <ti/drivers/esm/esm.h>
#include <ti/drivers/crc/crc.h>
#include <ti/drivers/gpio/gpio.h>
#include <ti/drivers/mailbox/mailbox.h>
#include <ti/drivers/pinmux/pinmux.h>
#include <ti/drivers/adcbuf/ADCBuf.h>
#include <ti/control/MMWave/MMWave.h>
#include <ti/control/dpm/dpm.h>
#include <ti/drivers/osal/DebugP.h>
#include <ti/drivers/uart/UART.h>
#include <ti/utils/cli/cli.h>
#include <ti/utils/mathutils/mathutils.h>
#include <ti/utils/testlogger/logger.h>

#include "main_callback.h"

typedef struct
{
    SOC_Handle      socHandle;
    UART_Handle     uart0_handle;
    MMWave_Handle   MMWave_handle;
    ADCBuf_Handle   adcbuf_handle;
}
MMWave_Global_Handle;

typedef struct
{
    Task_Handle init;
    Task_Handle MMWaveCtrl;
}
MMWave_Global_Task;

typedef struct
{
    MMWave_Global_Handle handle;
    MMWave_Global_Task task;
    uint8_t uart0_rx;
    uint8_t uart0_rxbuf[1024];
    uint8_t uart0_tx;
    uint8_t uart0_txbuf[1024];
}MMWave_Global;

extern MMWave_Global MMWave_Global_Params;

#endif /* MAIN_H_ */

main_callback.c:

/*
 * main_callback.c
 *
 *  Created on: 2023年8月3日
 *      Author: ZHOU
 */


#include "main_callback.h"

int32_t MMWave_eventFxnCallback(uint16_t msgId, uint16_t sbId, uint16_t sbLen, uint8_t *payload)
{
    return 0;
}

void MMWave_cfgFxnCallback(MMWave_CtrlCfg* ptrCtrlCfg)
{

}

void MMWave_openFxnCallback(MMWave_OpenCfg* ptrOpenCfg)
{

}

void MMWave_closeFxnCallback(void)
{

}

void MMWave_startFxnCallback(MMWave_CalibrationCfg* ptrCalibrationCfg)
{

}

void MMWave_stopFxnCallback(void)
{

}



main_callback.h:

/*
 * main_callback.h
 *
 *  Created on: 2023年8月3日
 *      Author: ZHOU
 */

#ifndef MAIN_CALLBACK_H_
#define MAIN_CALLBACK_H_

#include "main.h"

int32_t MMWave_eventFxnCallback(uint16_t msgId, uint16_t sbId, uint16_t sbLen, uint8_t *payload);
void MMWave_cfgFxnCallback(MMWave_CtrlCfg* ptrCtrlCfg);
void MMWave_openFxnCallback(MMWave_OpenCfg* ptrOpenCfg);
void MMWave_closeFxnCallback(void);
void MMWave_startFxnCallback(MMWave_CalibrationCfg* ptrCalibrationCfg);
void MMWave_stopFxnCallback(void);

#endif /* MAIN_CALLBACK_H_ */

关于如何新建文件 可以查看CCS相关操作

这段代码是我基于官方demo例程进行的编写和修改。
其中 MCPI 是用于系统调试log输出的 但是也可以不加 不然可能会因为没有指定MCPI模块运行的地方而报错 所以我直接注释了

移植配置文件

  1. 从 <SDK安装路径>/packages/ti/platform/xwr68xx 下,拷贝r4f_linker.cmd到工程中

  2. 打开**<SDK安装路径>/packages/ti/drivers**下的任意一个驱动文件夹,这里以gpio驱动为例,则打开<SDK安装路径>/packages/ti/drivers/gpio/test/xwr68xx,从中拷贝mss.cfg到工程中,此时工程如下
    在这里插入图片描述

修改工程属性

  1. Resource->Linked Resources,右侧点击New添加条目MMWAVE_SDK_DIR(名称可自定),路径定位到mmWave SDK安装路径,如下在这里插入图片描述
  2. 在XDC构建SYS/BIOS的过程中,需要让其将枚举的类型设置为int型,否则可能会导致诸如串口无法开启、控制台无法打印输出等问题,具体原理暂时不明。

Build->XDCtools->Advanced Options中,页面下方的Additional complier options,填入"--enum_type=int",如下
在这里插入图片描述
一定要注意–是两个英文的横杠(减号)
3. Build->Arm Complier->Processor Options,右侧的Designate code state,从32修改为16,否则会产生一些奇奇怪怪的问题。在这里插入图片描述
4. Build->Arm Complier->Include Options,右侧上方的搜索路径列表,点击带有绿色加号的图标添加,添加目录 ${MMWAVE_SDK_DIR}/packages

  1. mmWave SDK提供的库在设计的时候考虑了整个系列雷达芯片的兼容性,因此库内有多套代码,通过宏定义来区分需要使用哪一段代码进行编译。为此,我们需要向编译器的预定义符号里添加一些用来表示当前目标芯片的宏。

Build->Arm Complier->Prodefined Symbols,右侧上方添加以下符号(直接复制下面的内容,然后点击框内原先已有的宏,按Ctrl+V即可一次性直接粘贴进去)

SOC_XWR68XX
SUBSYS_MSS
DOWNLOAD_FROM_CCS
MMWAVE_L3RAM_NUM_BANK=6
MMWAVE_SHMEM_TCMA_NUM_BANK=0
MMWAVE_SHMEM_TCMB_NUM_BANK=0
MMWAVE_SHMEM_BANK_SIZE=0x20000
DebugP_ASSERT_ENABLED
_LITTLE_ENDIAN
OBJDET_NO_RANGE
AOP

其中 如果需要指定L3代码和MSS用的大小 则配置:

MMWAVE_L3_CODEMEM_SIZE=0x100
MMWAVE_MSSUSED_L3RAM_SIZE=0x90000

在这里插入图片描述
6. 此处需要更改Runtime Model Options内的选项,同样也是将enum类型设置为int,与在XDCtools中的设置保持一致。

Build->Arm Complier->Advanced Options,右侧Designate enum type更改为int类型
在这里插入图片描述
7. 大部分驱动的函数都封装成库提供给用户了,所以需要将库文件添加到连接器的搜索路径中,否则会出现未解析符号的问题。

Build->Arm Linker->File Search Path,上方添加如下内容(一样可以直接复制过去)

libosal_xwr68xx.aer4f
libesm_xwr68xx.aer4f
libtestlogger_xwr68xx.aer4f
libgpio_xwr68xx.aer4f
libsoc_xwr68xx.aer4f
libpinmux_xwr68xx.aer4f
libcrc_xwr68xx.aer4f
libuart_xwr68xx.aer4f
libmailbox_xwr68xx.aer4f
libmmwavelink_xwr68xx.aer4f
libmmwave_xwr68xx.aer4f
libadcbuf_xwr68xx.aer4f
libdma_xwr68xx.aer4f
libedma_xwr68xx.aer4f
libcli_xwr68xx.aer4f
libhwa_xwr68xx.aer4f
libdpm_xwr68xx.aer4f
libmathutils.aer4f
libcbuff_xwr68xx.aer4f
libhsiheader_xwr68xx.aer4f
librangeproc_hwa_xwr68xx.aer4f
libdpedma_hwa_xwr68xx.aer4f
libqspi_xwr68xx.aer4f
libqspiflash_xwr68xx.aer4f
rtsv7R4_T_le_v3D16_eabi.lib

其中 libsleep_xwr68xx.aer4f是3.6才有的 3.5没有
下方添加如下内容,其中MMWAVE_SDK_DIR和前面设定Linked Resources时添加的变量名保持一致即可。

${MMWAVE_SDK_DIR}/packages/ti/control/mmwave/lib
${MMWAVE_SDK_DIR}/packages/ti/control/mmwavelink/lib
${MMWAVE_SDK_DIR}/packages/ti/control/dpm/lib
${MMWAVE_SDK_DIR}/packages/ti/drivers/adcbuf/lib
${MMWAVE_SDK_DIR}/packages/ti/drivers/crc/lib
${MMWAVE_SDK_DIR}/packages/ti/drivers/dma/lib
${MMWAVE_SDK_DIR}/packages/ti/drivers/edma/lib
${MMWAVE_SDK_DIR}/packages/ti/drivers/esm/lib
${MMWAVE_SDK_DIR}/packages/ti/drivers/gpio/lib
${MMWAVE_SDK_DIR}/packages/ti/drivers/hwa/lib
${MMWAVE_SDK_DIR}/packages/ti/drivers/mailbox/lib
${MMWAVE_SDK_DIR}/packages/ti/drivers/osal/lib
${MMWAVE_SDK_DIR}/packages/ti/drivers/pinmux/lib
${MMWAVE_SDK_DIR}/packages/ti/drivers/soc/lib
${MMWAVE_SDK_DIR}/packages/ti/drivers/uart/lib
${MMWAVE_SDK_DIR}/packages/ti/utils/cli/lib
${MMWAVE_SDK_DIR}/packages/ti/utils/mathutils/lib
${MMWAVE_SDK_DIR}/packages/ti/datapath/dpu/rangeproc/lib
${MMWAVE_SDK_DIR}/packages/ti/datapath/dpedma/lib
${MMWAVE_SDK_DIR}/packages/ti/drivers/cbuff/lib
${MMWAVE_SDK_DIR}/packages/ti/utils/hsiheader/lib
${MMWAVE_SDK_DIR}/packages/ti/drivers/qspi/lib
${MMWAVE_SDK_DIR}/packages/ti/drivers/qspiflash/lib
${MMWAVE_SDK_DIR}/packages/ti/utils/libsleep/lib
${MMWAVE_SDK_DIR}/packages/ti/utils/testlogger/lib

若是3.6版本的sdk可以加上:

libsleep_xwr68xx.aer4f

${MMWAVE_SDK_DIR}/packages/ti/utils/libsleep/lib

在这里插入图片描述
8. 同样地,在此处也需要填入一些预定义的符号,比如r4f_linker.cmd文件中用到的几个宏的大小。

Build->Arm Linker->Advanced Options->Command File PreProcess,上方添加

MMWAVE_L3RAM_NUM_BANK=6
MMWAVE_SHMEM_TCMA_NUM_BANK=0
MMWAVE_SHMEM_TCMB_NUM_BANK=0
MMWAVE_SHMEM_BANK_SIZE=0x20000

其中 如果需要指定L3代码和MSS用的大小 则配置:

MMWAVE_L3_CODEMEM_SIZE=0x100
MMWAVE_MSSUSED_L3RAM_SIZE=0x90000

在这里插入图片描述
9. 修改大端格式
因为芯片烧录是大端 所以要在general里面修改为大端格式:
小端格式也可以 官方工程大多就是小端格式 但是不要用be32或者be8格式 否则会警告只能用大端格式在这里插入图片描述

  1. 点击右下角Apply and Close,再对工程重新编译,可以看到所有错误都消失了。但仍然有一个警告,提示缺少systemHeap段定义。因此打开r4f_linker.cmd文件,手动在SECTIONS内添加:
systemHeap : {} > DATA_RAM

在这里插入图片描述
之后再编译就不会出现问题了。

编译生成bin文件

这一块不太懂的 可以看我TI-CCS笔记中关于bin文件编译的文章:

blog.csdn.net/weixin_53403301/article/details/132319924

如果要编译成最终可以烧录的bin文件 则参考文章:
【TI毫米波雷达】MSS和DSS的工程编译及bin文件生成配置(共同生成一个bin文件,以IWR6843AOP为例)
必须将DSS和MSS以及BSS链接起来才行 形成最终的一个bin文件
另外 仅MSS的工程也需要链接BSS 但不用链接DSS
在这里插入图片描述
在工程属性 build-steps下有个post-build 这里就需要写入脚本(中间每个参数以空格隔开 不能换行)
在这里插入图片描述
以TI的毫米波雷达的MSS部分为例(一般为ARM Cortex-R4F架构)
如IWR6843AOP:
其编译器采用ti-cgt-arm_20.2.7.LTS
且编译时 采用的是 armofd armhex 两个可执行文件

注意 第二个参数和第三个参数根据工程实际情况来更改

"${CCS_INSTALL_ROOT}/utils/tiobj2bin/tiobj2bin" "${PROJECT_LOC}/Debug/IWR6843AOP_Demo.out" "${PROJECT_LOC}/Debug/IWR6843AOP_Demo.bin" "${CG_TOOL_ROOT}/bin/armofd" "${CG_TOOL_ROOT}/bin/armhex" "${CCS_INSTALL_ROOT}/utils/tiobj2bin/mkhex4bin"

其中 我的工程名为:IWR6843AOP_Demo
生成的out、bin文件名也为:IWR6843AOP_Demo

首先 需要调用"${CCS_INSTALL_ROOT}/utils/tiobj2bin/tiobj2bin" 脚本
传入的参数文件就是生成的out文件"${PROJECT_LOC}/Debug/IWR6843AOP_Demo.out"
另外指定生成bin文件的目录"${PROJECT_LOC}/Debug/IWR6843AOP_Demo.bin"
以及两个编译器的链接和mkhex4bin脚本"${CG_TOOL_ROOT}/bin/armofd" "${CG_TOOL_ROOT}/bin/armhex" "${CCS_INSTALL_ROOT}/utils/tiobj2bin/mkhex4bin"
最后编译之后 就能在Debug目录下找到bin文件

当然 还有个前提就是工程建立和环境配置完成 且能够生成.out文件

同样在pre-build中可以填入一些参数 用于预编译(如编译前修改或删除一些文件)
如:

rm -f "${PROJECT_ROOT}/Debug/IWR6843AOP_Demo.bin"

附录:结构框架

雷达基本原理叙述

雷达工作原理是上电-发送chirps-帧结束-处理-上电循环
一个Frame,首先是信号发送,比如96个chirp就顺次发出去,然后接收回来,混频滤波,ADC采样,这些都是射频模块的东西。射频完成之后,FFT,CFAR,DOA这些就是信号处理的东西。然后输出给那个结构体,就是当前帧获得的点云了。
在这里插入图片描述
在射频发送阶段 一个frame发送若干个chirp 也就是上图左上角
第一个绿色点为frame start 第二个绿色点为frame end
其中发送若干chirps(小三角形)
chirps的个数称为numLoops(代码中 rlFrameCfg_t结构体)
在mmwave studio上位机中 则称为 no of chirp loops

frame end 到 周期结束的时间为计算时间 称为inter frame period
在这里插入图片描述
frame start到循环结束的时间称为framePeriodicity(代码中 rlFrameCfg_t结构体)
在mmwave studio上位机中 则称为 Periodicity

如下图frame配置部分
在这里插入图片描述
在inter frame Periodicity时间内(比如这里整个周期是55ms)
就是用于计算和处理的时间 一定比55ms要小
如果chirps很多的话 那么计算时间就会减小

如果是处理点云数据 则只需要每一帧计算一次点云即可
计算出当前帧的xyz坐标和速度 以及保存时间戳

雷达天线排列位置

在工业雷达包:

C:\ti\mmwave_industrial_toolbox_4_12_0\antennas\ant_rad_patterns

路径下 有各个EVM开发板的天线排列说明
同样的 EVM手册中也有
如IWR6843AOPEVM:
在这里插入图片描述
在这里插入图片描述
其天线的间距等等位于数据手册:
在这里插入图片描述

芯片框架

IWR6843AOP可以分成三个主要部分及多个外设
BSS:雷达前端部分
MSS:cortex-rf4内核 主要用于控制
DSS: DSP C674内核 主要用于信号处理
外设:UART GPIO DPM HWA等

在这里插入图片描述
其中 大部分外设可以被MSS或DSS调用
另外 雷达前端BSS部分在SDK里由MMWave API调用

代码框架上 可以分成两个代码 MSS和DSS 两个代码同时运行 通过某些外设进行同步 协同运作

但也可以只跑一个内核 在仅MSS模式下 依旧可以调用某些用于信号处理的外设 demo代码就是如此

如下图为demo代码流程
在这里插入图片描述

Demo工程功能

IWR6843AOP的开箱工程是根据IWR6843AOPEVM开发板来的
该工程可以将IWR6843AOP的两个串口利用起来 实现的功能主要是两个方面:
通过115200波特率的串口配置参数 建立握手协议
通过115200*8的串口输出雷达数据
此工程需要匹配TI官方的上位机:mmWave_Demo_Visualizer_3.6.0来使用
该上位机可以在连接串口后自动化操作 并且对雷达数据可视化
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
关于雷达参数配置 则在SDK的mmw\profiles目录下
言简意赅 可以直接更改该目录下的文件参数来达到配置雷达参数的目的
在这里插入图片描述

但这种方法不利于直接更改 每次用上位机运行后的参数是固定的(上位机运行需要SDK环境) 所以也可以在代码中写死 本文探讨的就是这个方向

CCS工程导入

首先 在工业雷达包目录下找到该工程设置

C:\ti\mmwave_industrial_toolbox_4_12_0\labs\Out_Of_Box_Demo\src\xwr6843AOP

使用CCS的import project功能导入工程后 即可完成环境搭建
在这里插入图片描述
这里用到的SDK最新版为3.6版本

工程叙述

以下来自官方文档 可以直接跳过

Software Tasks

The demo consists of the following (SYSBIOS) tasks:

MmwDemo_initTask. This task is created/launched by main and is a one-time active task whose main functionality is to initialize drivers (<driver>_init), MMWave module (MMWave_init), DPM module (DPM_init), open UART and data path related drivers (EDMA, HWA), and create/launch the following tasks (the CLI_task is launched indirectly by calling CLI_open).
CLI_task. This command line interface task provides a simplified 'shell' interface which allows the configuration of the BSS via the mmWave interface (MMWave_config). It parses input CLI configuration commands like chirp profile and GUI configuration. When sensor start CLI command is parsed, all actions related to starting sensor and starting the processing the data path are taken. When sensor stop CLI command is parsed, all actions related to stopping the sensor and stopping the processing of the data path are taken
MmwDemo_mmWaveCtrlTask. This task is used to provide an execution context for the mmWave control, it calls in an endless loop the MMWave_execute API.
MmwDemo_DPC_ObjectDetection_dpmTask. This task is used to provide an execution context for DPM (Data Path Manager) execution, it calls in an endless loop the DPM_execute API. In this context, all of the registered object detection DPC (Data Path Chain) APIs like configuration, control and execute will take place. In this task. When the DPC's execute API produces the detected objects and other results, they are transmitted out of the UART port for display using the visualizer.

Data Path

在这里插入图片描述
Top Level Data Path Processing Chain
在这里插入图片描述
Top Level Data Path Timing

The data path processing consists of taking ADC samples as input and producing detected objects (point-cloud and other information) to be shipped out of UART port to the PC. The algorithm processing is realized using the DPM registered Object Detection DPC. The details of the processing in DPC can be seen from the following doxygen documentation:
ti/datapath/dpc/objectdetection/objdethwa/docs/doxygen/html/index.html

Output information sent to host

Output packets with the detection information are sent out every frame through the UART. Each packet consists of the header MmwDemo_output_message_header_t and the number of TLV items containing various data information with types enumerated in MmwDemo_output_message_type_e. The numerical values of the types can be found in mmw_output.h. Each TLV item consists of type, length (MmwDemo_output_message_tl_t) and payload information. The structure of the output packet is illustrated in the following figure. Since the length of the packet depends on the number of detected objects it can vary from frame to frame. The end of the packet is padded so that the total packet length is always multiple of 32 Bytes.

在这里插入图片描述
Output packet structure sent to UART
The following subsections describe the structure of each TLV.

List of detected objects
Type: (MMWDEMO_OUTPUT_MSG_DETECTED_POINTS)

Length: (Number of detected objects) x (size of DPIF_PointCloudCartesian_t)

Value: Array of detected objects. The information of each detected object is as per the structure DPIF_PointCloudCartesian_t. When the number of detected objects is zero, this TLV item is not sent. The maximum number of objects that can be detected in a sub-frame/frame is DPC_OBJDET_MAX_NUM_OBJECTS.

The orientation of x,y and z axes relative to the sensor is as per the following figure. (Note: The antenna arrangement in the figure is shown for standard EVM (see gAntDef_default) as an example but the figure is applicable for any antenna arrangement.)

在这里插入图片描述
Coordinate Geometry
The whole detected objects TLV structure is illustrated in figure below.
在这里插入图片描述
Detected objects TLV

Range profile
Type: (MMWDEMO_OUTPUT_MSG_RANGE_PROFILE)

Length: (Range FFT size) x (size of uint16_t)

Value: Array of profile points at 0th Doppler (stationary objects). The points represent the sum of log2 magnitudes of received antennas expressed in Q9 format.

Noise floor profile
Type: (MMWDEMO_OUTPUT_MSG_NOISE_PROFILE)

Length: (Range FFT size) x (size of uint16_t)

Value: This is the same format as range profile but the profile is at the maximum Doppler bin (maximum speed objects). In general for stationary scene, there would be no objects or clutter at maximum speed so the range profile at such speed represents the receiver noise floor.
Azimuth static heatmap
Type: (MMWDEMO_OUTPUT_MSG_AZIMUT_STATIC_HEAT_MAP)

Length: (Range FFT size) x (Number of "azimuth" virtual antennas) (size of cmplx16ImRe_t_)

Value: Array DPU_AoAProcHWA_HW_Resources::azimuthStaticHeatMap. The antenna data are complex symbols, with imaginary first and real second in the following order:
Imag(ant 0, range 0), Real(ant 0, range 0),...,Imag(ant N-1, range 0),Real(ant N-1, range 0)
         ...
         Imag(ant 0, range R-1), Real(ant 0, range R-1),...,Imag(ant N-1, range R-1),Real(ant N-1, range R-1)

Note that the number of virtual antennas is equal to the number of “azimuth” virtual antennas. The antenna symbols are arranged in the order as they occur at the input to azimuth FFT. Based on this data the static azimuth heat map could be constructed by the GUI running on the host.

Azimuth/Elevation static heatmap
Type: (MMWDEMO_OUTPUT_MSG_AZIMUT_ELEVATION_STATIC_HEAT_MAP)

Length: (Range FFT size) x (Number of all virtual antennas) (size of cmplx16ImRe_t_)

Value: Array DPU_AoAProcHWA_HW_Resources::azimuthStaticHeatMap. The antenna data are complex symbols, with imaginary first and real second in the following order:
 Imag(ant 0, range 0), Real(ant 0, range 0),...,Imag(ant N-1, range 0),Real(ant N-1, range 0)
         ...
         Imag(ant 0, range R-1), Real(ant 0, range R-1),...,Imag(ant N-1, range R-1),Real(ant N-1, range R-1)

Note that the number of virtual antennas is equal to the total number of active virtual antennas. The antenna symbols are arranged in the order as they occur in the radar cube matrix. This TLV is sent by AOP version of MMW demo, that uses AOA2D DPU. Based on this data the static azimuth or elevation heat map could be constructed by the GUI running on the host.

Range/Doppler heatmap
Type: (MMWDEMO_OUTPUT_MSG_RANGE_DOPPLER_HEAT_MAP)

Length: (Range FFT size) x (Doppler FFT size) (size of uint16_t)

Value: Detection matrix DPIF_DetMatrix::data. The order is :
 X(range bin 0, Doppler bin 0),...,X(range bin 0, Doppler bin D-1),
        ...
        X(range bin R-1, Doppler bin 0),...,X(range bin R-1, Doppler bin D-1)
Stats information
Type: (MMWDEMO_OUTPUT_MSG_STATS )

Length: (size of MmwDemo_output_message_stats_t)

Value: Timing information as per MmwDemo_output_message_stats_t. See timing diagram below related to the stats.

在这里插入图片描述
Processing timing

Note:

The MmwDemo_output_message_stats_t::interChirpProcessingMargin is not computed (it is always set to 0). This is because there is no CPU involvement in the 1D processing (only HWA and EDMA are involved), and it is not possible to know how much margin is there in chirp processing without CPU being notified at every chirp when processing begins (chirp event) and when the HWA-EDMA computation ends. The CPU is intentionally kept free during 1D processing because a real application may use this time for doing some post-processing algorithm execution.
While the MmwDemo_output_message_stats_t::interFrameProcessingTime reported will be of the current sub-frame/frame, the MmwDemo_output_message_stats_t::interFrameProcessingMargin and MmwDemo_output_message_stats_t::transmitOutputTime will be of the previous sub-frame (of the same MmwDemo_output_message_header_t::subFrameNumber as that of the current sub-frame) or of the previous frame.
The MmwDemo_output_message_stats_t::interFrameProcessingMargin excludes the UART transmission time (available as MmwDemo_output_message_stats_t::transmitOutputTime). This is done intentionally to inform the user of a genuine inter-frame processing margin without being influenced by a slow transport like UART, this transport time can be significantly longer for example when streaming out debug information like heat maps. Also, in a real product deployment, higher speed interfaces (e.g LVDS) are likely to be used instead of UART. User can calculate the margin that includes transport overhead (say to determine the max frame rate that a particular demo configuration will allow) using the stats because they also contain the UART transmission time.

The CLI command “guMonitor” specifies which TLV element will be sent out within the output packet. The arguments of the CLI command are stored in the structure MmwDemo_GuiMonSel_t.

Side information of detected objects
Type: (MMWDEMO_OUTPUT_MSG_DETECTED_POINTS_SIDE_INFO)

Length: (Number of detected objects) x (size of DPIF_PointCloudSideInfo_t)

Value: Array of detected objects side information. The side information of each detected object is as per the structure DPIF_PointCloudSideInfo_t). When the number of detected objects is zero, this TLV item is not sent.
Temperature Stats
Type: (MMWDEMO_OUTPUT_MSG_TEMPERATURE_STATS)

Length: (size of MmwDemo_temperatureStats_t)

Value: Structure of detailed temperature report as obtained from Radar front end. MmwDemo_temperatureStats_t::tempReportValid is set to return value of rlRfGetTemperatureReport. If MmwDemo_temperatureStats_t::tempReportValid is 0, values in MmwDemo_temperatureStats_t::temperatureReport are valid else they should be ignored. This TLV is sent along with Stats TLV described in Stats information
Range Bias and Rx Channel Gain/Phase Measurement and Compensation

Because of imperfections in antenna layouts on the board, RF delays in SOC, etc, there is need to calibrate the sensor to compensate for bias in the range estimation and receive channel gain and phase imperfections. The following figure illustrates the calibration procedure.

在这里插入图片描述
Calibration procedure ladder diagram

The calibration procedure includes the following steps:

Set a strong target like corner reflector at the distance of X meter (X less than 50 cm is not recommended) at boresight.
Set the following command in the configuration profile in .../profiles/profile_calibration.cfg, to reflect the position X as follows: where D (in meters) is the distance of window around X where the peak will be searched. The purpose of the search window is to allow the test environment from not being overly constrained say because it may not be possible to clear it of all reflectors that may be stronger than the one used for calibration. The window size is recommended to be at least the distance equivalent of a few range bins. One range bin for the calibration profile (profile_calibration.cfg) is about 5 cm. The first argument "1" is to enable the measurement. The stated configuration profile (.cfg) must be used otherwise the calibration may not work as expected (this profile ensures all transmit and receive antennas are engaged among other things needed for calibration).
   measureRangeBiasAndRxChanPhase 1 X D
Start the sensor with the configuration file.
In the configuration file, the measurement is enabled because of which the DPC will be configured to perform the measurement and generate the measurement result (DPU_AoAProc_compRxChannelBiasCfg_t) in its result structure (DPC_ObjectDetection_ExecuteResult_t::compRxChanBiasMeasurement), the measurement results are written out on the CLI port (MmwDemo_measurementResultOutput) in the format below: For details of how DPC performs the measurement, see the DPC documentation.
   compRangeBiasAndRxChanPhase <rangeBias> <Re(0,0)> <Im(0,0)> <Re(0,1)> <Im(0,1)> ... <Re(0,R-1)> <Im(0,R-1)> <Re(1,0)> <Im(1,0)> ... <Re(T-1,R-1)> <Im(T-1,R-1)>
The command printed out on the CLI now can be copied and pasted in any configuration file for correction purposes. This configuration will be passed to the DPC for the purpose of applying compensation during angle computation, the details of this can be seen in the DPC documentation. If compensation is not desired, the following command should be given (depending on the EVM and antenna arrangement) Above sets the range bias to 0 and the phase coefficients to unity so that there is no correction. Note the two commands must always be given in any configuration file, typically the measure commmand will be disabled when the correction command is the desired one.
   For ISK EVM:
   compRangeBiasAndRxChanPhase 0.0   1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 
   For AOP EVM
   compRangeBiasAndRxChanPhase 0.0   1 0 -1 0 1 0 -1 0 1 0 -1 0 1 0 -1 0 1 0 -1 0 1 0 -1 0 
Streaming data over LVDS
The LVDS streaming feature enables the streaming of HW data (a combination of ADC/CP/CQ data) and/or user specific SW data through LVDS interface. The streaming is done mostly by the CBUFF and EDMA peripherals with minimal CPU intervention. The streaming is configured through the MmwDemo_LvdsStreamCfg_t CLI command which allows control of HSI header, enable/disable of HW and SW data and data format choice for the HW data. The choices for data formats for HW data are:

MMW_DEMO_LVDS_STREAM_CFG_DATAFMT_DISABLED
MMW_DEMO_LVDS_STREAM_CFG_DATAFMT_ADC
MMW_DEMO_LVDS_STREAM_CFG_DATAFMT_CP_ADC_CQ
In order to see the high-level data format details corresponding to the above data format configurations, refer to the corresponding slides in ti\drivers\cbuff\docs\CBUFF_Transfers.pptx

When HW data LVDS streaming is enabled, the ADC/CP/CQ data is streamed per chirp on every chirp event. When SW data streaming is enabled, it is streamed during inter-frame period after the list of detected objects for that frame is computed. The SW data streamed every frame/sub-frame is composed of the following in time:

HSI header (HSIHeader_t): refer to HSI module for details.
User data header: MmwDemo_LVDSUserDataHeader
User data payloads:
Point-cloud information as a list : DPIF_PointCloudCartesian_t x number of detected objects
Point-cloud side information as a list : DPIF_PointCloudSideInfo_t x number of detected objects

The format of the SW data streamed is shown in the following figure:
在这里插入图片描述
LVDS SW Data format

Note:

Only single-chirp formats are allowed, multi-chirp is not supported.
When number of objects detected in frame/sub-frame is 0, there is no transmission beyond the user data header.
For HW data, the inter-chirp duration should be sufficient to stream out the desired amount of data. For example, if the HW data-format is ADC and HSI header is enabled, then the total amount of data generated per chirp is:
(numAdcSamples * numRxChannels * 4 (size of complex sample) + 52 [sizeof(HSIDataCardHeader_t) + sizeof(HSISDKHeader_t)] ) rounded up to multiples of 256 [=sizeof(HSIHeader_t)] bytes.
The chirp time Tc in us = idle time + ramp end time in the profile configuration. For n-lane LVDS with each lane at a maximum of B Mbps,
maximum number of bytes that can be send per chirp = Tc * n * B / 8 which should be greater than the total amount of data generated per chirp i.e
Tc * n * B / 8 >= round-up(numAdcSamples * numRxChannels * 4 + 52, 256).
E.g if n = 2, B = 600 Mbps, idle time = 7 us, ramp end time = 44 us, numAdcSamples = 512, numRxChannels = 4, then 7650 >= 8448 is violated so this configuration will not work. If the idle-time is doubled in the above example, then we have 8700 > 8448, so this configuration will work.
For SW data, the number of bytes to transmit each sub-frame/frame is:
52 [sizeof(HSIDataCardHeader_t) + sizeof(HSISDKHeader_t)] + sizeof(MmwDemo_LVDSUserDataHeader_t) [=8] +
number of detected objects (Nd) * { sizeof(DPIF_PointCloudCartesian_t) [=16] + sizeof(DPIF_PointCloudSideInfo_t) [=4] } rounded up to multiples of 256 [=sizeof(HSIHeader_t)] bytes.
or X = round-up(60 + Nd * 20, 256). So the time to transmit this data will be
X * 8 / (n*B) us. The maximum number of objects (Ndmax) that can be detected is defined in the DPC (DPC_OBJDET_MAX_NUM_OBJECTS). So if Ndmax = 500, then time to transmit SW data is 68 us. Because we parallelize this transmission with the much slower UART transmission, and because UART transmission is also sending at least the same amount of information as the LVDS, the LVDS transmission time will not add any burdens on the processing budget beyond the overhead of reconfiguring and activating the CBUFF session (this overhead is likely bigger than the time to transmit).
The total amount of data to be transmitted in a HW or SW packet must be greater than the minimum required by CBUFF, which is 64 bytes or 32 CBUFF Units (this is the definition CBUFF_MIN_TRANSFER_SIZE_CBUFF_UNITS in the CBUFF driver implementation). If this threshold condition is violated, the CBUFF driver will return an error during configuration and the demo will generate a fatal exception as a result. When HSI header is enabled, the total transfer size is ensured to be at least 256 bytes, which satisfies the minimum. If HSI header is disabled, for the HW session, this means that numAdcSamples * numRxChannels * 4 >= 64. Although mmwavelink allows minimum number of ADC samples to be 2, the demo is supported for numAdcSamples >= 64. So HSI header is not required to be enabled for HW only case. But if SW session is enabled, without the HSI header, the bytes in each packet will be 8 + Nd * 20. So for frames/sub-frames where Nd < 3, the demo will generate exception. Therefore HSI header must be enabled if SW is enabled, this is checked in the CLI command validation.
Implementation Notes
The LVDS implementation is mostly present in mmw_lvds_stream.h and mmw_lvds_stream.c with calls in mss_main.c. Additionally HSI clock initialization is done at first time sensor start using MmwDemo_mssSetHsiClk.
EDMA channel resources for CBUFF/LVDS are in the global resource file (mmw_res.h, see Hardware Resource Allocation) along with other EDMA resource allocation. The user data header and two user payloads are configured as three user buffers in the CBUFF driver. Hence SW allocation for EDMA provides for three sets of EDMA resources as seen in the SW part (swSessionEDMAChannelTable[.]) of MmwDemo_LVDSStream_EDMAInit. The maximum number of HW EDMA resources are needed for the data-format MMW_DEMO_LVDS_STREAM_CFG_DATAFMT_CP_ADC_CQ, which as seen in the corresponding slide in ti\drivers\cbuff\docs\CBUFF_Transfers.pptx is 12 channels (+ shadows) including the 1st special CBUFF EDMA event channel which CBUFF IP generates to the EDMA, hence the HW part (hwwSessionEDMAChannelTable[.]) of MmwDemo_LVDSStream_EDMAInit has 11 table entries.
Although the CBUFF driver is configured for two sessions (hw and sw), at any time only one can be active. So depending on the LVDS CLI configuration and whether advanced frame or not, there is logic to activate/deactivate HW and SW sessions as necessary.
The CBUFF session (HW/SW) configure-create and delete depends on whether or not re-configuration is required after the first time configuration.
For HW session, re-configuration is done during sub-frame switching to re-configure for the next sub-frame but when there is no advanced frame (number of sub-frames = 1), the HW configuration does not need to change so HW session does not need to be re-created.
For SW session, even though the user buffer start addresses and sizes of headers remains same, the number of detected objects which determines the sizes of some user buffers changes from one sub-frame/frame to another sub-frame/frame. Therefore SW session needs to be recreated every sub-frame/frame.
User may modify the application software to transmit different information than point-cloud in the SW data e.g radar cube data (output of range DPU). However the CBUFF also has a maximum link list entry size limit of 0x3FFF CBUFF units or 32766 bytes. This means it is the limit for each user buffer entry [there are maximum of 3 entries -1st used for user data header, 2nd for point-cloud and 3rd for point-cloud side information]. During session creation, if this limit is exceeded, the CBUFF will return an error (and demo will in turn generate an exception). A single physical buffer of say size 50000 bytes may be split across two user buffers by providing one user buffer with (address, size) = (start address, 25000) and 2nd user buffer with (address, size) = (start address + 25000, 25000), beyond this two (or three if user data header is also replaced) limit, the user will need to create and activate (and wait for completion) the SW session multiple times to accomplish the transmission.

The following figure shows a timing diagram for the LVDS streaming (the figure is not to scale as actual durations will vary based on configuration).
在这里插入图片描述

How to bypass CLI
Re-implement the file mmw_cli.c as follows:

MmwDemo_CLIInit should just create a task with input taskPriority. Lets say the task is called "MmwDemo_sensorConfig_task".
All other functions are not needed
Implement the MmwDemo_sensorConfig_task as follows:
Fill gMmwMCB.cfg.openCfg
Fill gMmwMCB.cfg.ctrlCfg
Add profiles and chirps using MMWave_addProfile and MMWave_addChirp functions
Call MmwDemo_CfgUpdate for every offset in Offsets for storing CLI configuration (MMWDEMO_xxx_OFFSET in mmw.h)
Fill gMmwMCB.dataPathObj.objDetCommonCfg.preStartCommonCfg
Call MmwDemo_openSensor
Call MmwDemo_startSensor (One can use helper function MmwDemo_isAllCfgInPendingState to know if all dynamic config was provided)
Hardware Resource Allocation
The Object Detection DPC needs to configure the DPUs hardware resources (HWA, EDMA). Even though the hardware resources currently are only required to be allocated for this one and only DPC in the system, the resource partitioning is shown to be in the ownership of the demo. This is to illustrate the general case of resource allocation across more than one DPCs and/or demo's own processing that is post-DPC processing. This partitioning can be seen in the mmw_res.h file. This file is passed as a compiler command line define
"--define=APP_RESOURCE_FILE="<ti/demo/xwr64xx/mmw/mmw_res.h>" 

in mmw.mak when building the DPC sources as part of building the demo application and is referred in object detection DPC sources where needed as

#include APP_RESOURCE_FILE 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

网易独家音乐人Mike Zhou

光电帝国,光联万物!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值