文章目录
前言
本篇文章主要是基于Automated Parking这个案例中的mss工程进行解读,这个案例是对MSS和BSS之间进行的连接。
基础知识
文章中会用到的专业术语
- BSS:指的是mmWave Front End(雷达前端)
- MSS:指的是Master Sub-system(Cortex R4F)
- DSS:指的是DSP Sub-system(C674x core)
毫米波雷达的初始化流程(在MSS中)
在MSS中初始化流程是说明要讲MSS和BSS之间建立连接
上述图片摘自于mmwave_sdk中的MMWAVE SDK User Guide,上述三张图片说明了毫米波雷达的启动流程,后面的代码解析就是基于上面的3张图片进行阐述。
本案例中要用的其他知识
UART
首先要明确串口的作用是什么?串口的作用就是在两个设备之间进行通信。在这个案例中用到了两个串口,一个串口的作用是通过上位机将信息发送到AWR1843,另一个串口就是将雷达采集到的数据通过DSS处理以后在发送到PC。
MailBox
邮箱,在我们的日常生活中,也就是来进行通信的工具,在这里也不例外,邮箱的作用就是在MSS和DSS之间建立连接。
Semaphore
关于信号量这个东西,想必学过操作系统课程的同学都知道,信号量的作用就是防止资源竞争,就是协调各个线程,保证他们能够正确、合理的是使用公共资源。
代码解读
基础知识已经介绍完了以后,就可以进行代码的解读了
main函数
所有的程序都是从main函数开始执行的,那么首先看一下main函数中的内容。
int32_t main (void)
{
Task_Params taskParams;
int32_t errCode;
SOC_Cfg socCfg;
/* Initialize the ESM: Dont clear errors as TI RTOS does it */
ESM_init(0U);
/* Initialize the global variables */
memset ((void*)&gMrrMSSMCB, 0, sizeof(Mrr_MSS_MCB));
/* Initialize the SOC configuration: */
memset ((void *)&socCfg, 0, sizeof(SOC_Cfg));
/* Populate the SOC configuration: */
socCfg.clockCfg = SOC_SysClock_INIT;
/* Initialize the SOC Module: This is done as soon as the application is started
* to ensure that the MPU is correctly configured. */
gMrrMSSMCB.socHandle = SOC_init (&socCfg, &errCode);
if (gMrrMSSMCB.socHandle == NULL)
{
System_printf ("Error: SOC Module Initialization failed [Error code %d]\n", errCode);
return -1;
}
/* Check if the SOC is a secure device */
if (SOC_isSecureDevice(gMrrMSSMCB.socHandle, &errCode))
{
/* Disable firewall for JTAG and LOGGER (UART) which is needed by the demo */
SOC_controlSecureFirewall(gMrrMSSMCB.socHandle,
(uint32_t)(SOC_SECURE_FIREWALL_JTAG | SOC_SECURE_FIREWALL_LOGGER),
SOC_SECURE_FIREWALL_DISABLE,
&errCode);
}
/* Initialize the Task Parameters. */
Task_Params_init(&taskParams);
taskParams.priority = 3;
Task_create(MRR_MSS_initTask, &taskParams, NULL);
/* Start BIOS */
BIOS_start();
return 0;
}
在这个main函数中可以看到首先定义了三个参数第一个是任务的参数,第二个是错误信息的代号,第三个片上操作系统的配置,接下的ESM_init(0U)函数不太重要,接下来两个memset函数分别用于将全局变量gMrrMSSMCB和片上系统的配置socCfg进行初始化,接下就是片上系统初始化,设置的时钟为SOC_SysClock_INIT。接下来就是检查设备是否是一个安全的设备,这个应该与你电脑的防火墙开没开有关系(个人猜想),接下来就是任务参数的初始化,这里优先级设置为3,然后就是执行Task_create函数,这个函数的第一个参数是一个函数指针,要对MRR_MSS_initTask这个函数进行回调(这个函数包括了所有的内容,很重要),待会再看这个函数,接下来就是BIOS_start()了,启动你的设备
MRR_MSS_initTask
static void MRR_MSS_initTask (UArg arg0, UArg arg1)
{
int32_t errCode;
MMWave_InitCfg initCfg;
UART_Params uartParams;
Task_Params taskParams;
SOC_SysIntListenerCfg listenerCfg;
Semaphore_Params semParams;
Mailbox_Config mboxCfg;
/* Debug Message: */
System_printf("Debug: Launched the Initialization Task\n");
/*****************************************************************************
* Initialize the mmWave SDK components:
*****************************************************************************/
/* Pinmux setting */
/* Setup the PINMUX to bring out the UART-1 */
Pinmux_Set_OverrideCtrl(SOC_XWR18XX_PINN5_PADBE, PINMUX_OUTEN_RETAIN_HW_CTRL, PINMUX_INPEN_RETAIN_HW_CTRL);
Pinmux_Set_FuncSel(SOC_XWR18XX_PINN5_PADBE, SOC_XWR18XX_PINN5_PADBE_MSS_UARTA_TX);
Pinmux_Set_OverrideCtrl(SOC_XWR18XX_PINN4_PADBD, PINMUX_OUTEN_RETAIN_HW_CTRL, PINMUX_INPEN_RETAIN_HW_CTRL);
Pinmux_Set_FuncSel(SOC_XWR18XX_PINN4_PADBD, SOC_XWR18XX_PINN4_PADBD_MSS_UARTA_RX);
/* Setup the PINMUX to bring out the UART-3 */
Pinmux_Set_OverrideCtrl(SOC_XWR18XX_PINF14_PADAJ, PINMUX_OUTEN_RETAIN_HW_CTRL, PINMUX_INPEN_RETAIN_HW_CTRL);
Pinmux_Set_FuncSel(SOC_XWR18XX_PINF14_PADAJ, SOC_XWR18XX_PINF14_PADAJ_MSS_UARTB_TX);
/* Setup the PINMUX to bring out the DSS UART */
Pinmux_Set_OverrideCtrl(SOC_XWR18XX_PINP8_PADBM, PINMUX_OUTEN_RETAIN_HW_CTRL, PINMUX_INPEN_RETAIN_HW_CTRL);
Pinmux_Set_FuncSel(SOC_XWR18XX_PINP8_PADBM, SOC_XWR18XX_PINP8_PADBM_DSS_UART_TX);
/* Initialize the UART */
UART_init();
/* Initialize the GPIO */
GPIO_init();
/* Initialize the Mailbox */
Mailbox_init(MAILBOX_TYPE_MSS);
/* Open UART Driver: */
UART_Params_init(&uartParams);
uartParams.clockFrequency = MSS_SYS_VCLK;
uartParams.baudRate = 115200;
uartParams.isPinMuxDone = 1;
/* Open the Command UART Instance */
gMrrMSSMCB.commandUartHandle = UART_open(0, &uartParams);
if (gMrrMSSMCB.commandUartHandle == NULL)
{
System_printf("Error: Unable to open the Command UART Instance\n");
return;
}
/* Setup the default UART Parameters */
UART_Params_init(&uartParams);
uartParams.writeDataMode = UART_DATA_BINARY;
uartParams.readDataMode = UART_DATA_BINARY;
uartParams.clockFrequency = MSS_SYS_VCLK;
uartParams.baudRate = 115200*8;
uartParams.isPinMuxDone = 1U;
/* Open the Logging UART Instance: */
gMrrMSSMCB.loggingUartHandle = UART_open(1, &uartParams);
if (gMrrMSSMCB.loggingUartHandle == NULL)
{
System_printf("Error: MMWDemoMSS Unable to open the Logging UART Instance\n");
return;
}
/*****************************************************************************
* Creating communication channel between MSS & DSS
*****************************************************************************/
/* Create a binary semaphore which is used to handle mailbox interrupt. */
Semaphore_Params_init(&semParams);
semParams.mode = Semaphore_Mode_BINARY;
gMrrMSSMCB.mboxSemHandle = Semaphore_create(0, &semParams, NULL);
/* Setup the default mailbox configuration */
Mailbox_Config_init(&mboxCfg);
/* Setup the configuration: */
mboxCfg.chType = MAILBOX_CHTYPE_MULTI;
mboxCfg.chId = MAILBOX_CH_ID_0;
mboxCfg.writeMode = MAILBOX_MODE_BLOCKING;
mboxCfg.readMode = MAILBOX_MODE_CALLBACK;
mboxCfg.readCallback = &MmwDemo_mboxCallback;
/* Initialization of Mailbox Virtual Channel */
gMrrMSSMCB.peerMailbox = Mailbox_open(MAILBOX_TYPE_DSS, &mboxCfg, &errCode);
if (gMrrMSSMCB.peerMailbox == NULL)
{
/* Error: Unable to open the mailbox */
System_printf("Error: Unable to open the Mailbox to the DSS [Error code %d]\n", errCode);
return;
}
/* Create task to handle mailbox messges */
Task_Params_init(&taskParams);
taskParams.stackSize = 16*1024;
Task_create(MmwDemo_mboxReadTask, &taskParams, NULL);
/* Register Chirp Available Listener */
memset ((void*)&listenerCfg, 0, sizeof(SOC_SysIntListenerCfg));
listenerCfg.systemInterrupt = SOC_XWR18XX_MSS_CHIRP_AVAIL_IRQ;
listenerCfg.listenerFxn = MRR_MSS_chirpIntCallback;
listenerCfg.arg = 0;
gMrrMSSMCB.chirpIntHandle = SOC_registerSysIntListener (gMrrMSSMCB.socHandle, &listenerCfg, &errCode);
if (gMrrMSSMCB.chirpIntHandle == NULL)
{
System_printf ("Error: Unable to register the Chirp Available Listener [Error code %d]\n", errCode);
return;
}
/* Register Frame Start Listener */
memset ((void*)&listenerCfg, 0, sizeof(SOC_SysIntListenerCfg));
listenerCfg.systemInterrupt = SOC_XWR18XX_MSS_FRAME_START_INT;
listenerCfg.listenerFxn = MRR_MSS_frameStartIntCallback;
listenerCfg.arg = 0;
gMrrMSSMCB.frameStartIntHandle = SOC_registerSysIntListener (gMrrMSSMCB.socHandle, &listenerCfg, &errCode);
if (gMrrMSSMCB.frameStartIntHandle == NULL)
{
System_printf("Error: Unable to register the Frame start Listener [Error code %d]\n", errCode);
return ;
}
/*****************************************************************************
* Initialize the mmWave module:
*****************************************************************************/
memset ((void *)&initCfg, 0, sizeof(MMWave_InitCfg));
/* Populate the initialization configuration:
* The MMWAve is configured in minimal isolation mode. */
initCfg.domain = MMWave_Domain_MSS;
initCfg.socHandle = gMrrMSSMCB.socHandle;
initCfg.eventFxn = &MRR_MSS_eventFxn;
initCfg.cfgMode = MMWave_ConfigurationMode_MINIMAL;
initCfg.executionMode = MMWave_ExecutionMode_ISOLATION;
initCfg.linkCRCCfg.useCRCDriver = 1U;
initCfg.linkCRCCfg.crcChannel = CRC_Channel_CH1;
initCfg.cooperativeModeCfg.cfgFxn = &MRR_MSS_cfgFxn;
initCfg.cooperativeModeCfg.startFxn = &MRR_MSS_startFxn;
initCfg.cooperativeModeCfg.stopFxn = &MRR_MSS_stopFxn;
initCfg.cooperativeModeCfg.openFxn = &MRR_MSS_openFxn;
initCfg.cooperativeModeCfg.closeFxn = &MRR_MSS_closeFxn;
/* Initialize and setup the mmWave Control module */
gMrrMSSMCB.ctrlHandle = MMWave_init (&initCfg, &errCode);
if (gMrrMSSMCB.ctrlHandle == NULL)
{
/* Error: Unable to initialize the mmWave control module */
System_printf ("Error: mmWave Control Initialization failed [Error code %d]\n", errCode);
return;
}
System_printf ("Debug: Initialized the mmWave module\n");
/*****************************************************************************
* Synchronize the mmWave module:
*****************************************************************************/
while (1)
{
int32_t syncStatus;
/* Get the synchronization status: */
syncStatus = MMWave_sync (gMrrMSSMCB.ctrlHandle, &errCode);
if (syncStatus < 0)
{
/* Error: Unable to synchronize the mmWave control module */
System_printf ("Error: mmWave Control Synchronization failed [Error code %d]\n", errCode);
return;
}
if (syncStatus == 1)
{
/* Synchronization acheived: */
break;
}
/* Sleep and poll again: */
Task_sleep(1);
}
System_printf ("Debug: Synchronized the mmWave module\n");
#ifdef SUBFRAME_CONF_MRR_USRR
gMrrMSSMCB.numChirpsPerSubframe[0] = SUBFRAME_MRR_NUM_CHIRPS_TOTAL;
gMrrMSSMCB.numChirpsPerSubframe[1] = SUBFRAME_USRR_NUM_CHIRPS_TOTAL;
#else
#ifdef SUBFRAME_CONF_MRR
gMrrMSSMCB.numChirpsPerSubframe[0] = SUBFRAME_MRR_NUM_CHIRPS_TOTAL;
#endif
#ifdef SUBFRAME_CONF_USRR
gMrrMSSMCB.numChirpsPerSubframe[0] = SUBFRAME_USRR_NUM_CHIRPS_TOTAL;
#endif
#endif
#ifdef USE_LVDS_INTERFACE_FOR_OBJECT_DATA_TX
/* Configure the LVDS streaming interface.*/
{
int32_t streamConfiguration = MRR_MSS_configureStreaming() ;
if (streamConfiguration != 0)
{
System_printf ("Error: Unable to activate the Streaming Session [Error code %d]\n", streamConfiguration);
DebugP_assert (0);
}
}
#endif
/*****************************************************************************
* 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 = 6;
taskParams.stackSize = 3*1024;
Task_create(MRR_MSS_mmWaveCtrlTask, &taskParams, NULL);
/*****************************************************************************
* Setup the CLI
*****************************************************************************/
MRR_MSS_CLIInit ();
}
首先这个函数定义为static类型,这个指的是该函数的作用域仅局限于本文件。参考连接。知道这个知识点以后,就可以看函数内部的任务了首先定义了几个变量,这些变量的作用基本上就是参数值的设定,没有太多的关系的,接下来就是驱动初始化,首先是UART,再这里使用了两个,这两个UART的波特率分别为115200和921600,接下来就是邮箱初始化,初始化的函数是int32_t Mailbox_init ( Mailbox_Type localEndpoint ) 因为这里的程序时在MSS中,实参就是MAILBOX_TYPE_MSS,接下来就是邮箱的打开,邮箱打开的函数为Mbox_Handle Mailbox_open ( Mailbox_Type remoteEndpoint,const Mailbox_Config * cfg,int32_t * errCode ) ,因此第一个实参就是MAILBOX_TYPE_DSS,后面的两个参数分别是邮箱配置和错误代码。还有就是信号量的创建,接下来就是回调MmwDemo_mboxReadTask,这个任务的空间的大小为16KB,这个函数的任务就是从DSS中读取数据,将数据发送到PC机上,然后就是chirp函数MRR_MSS_chirpIntCallback和frame函数MRR_MSS_frameStartIntCallback的注册,这两个函数是在ADCBuf中注册的函数,当chirp和frame可用的时候,才会被调用。在所有的驱动初始化完毕以后,就可以要启动mmwave设备了,所用到的API如下图所示:
在这个函数中只能看到MMWave_init和MMWave_sync,MMWave_execute这个函数会在MRR_MSS_mmWaveCtrlTask函数中的while 1中一直调用,MMWave_execute这个函数的作用就是执行mmWave的控制模块。最后就是MRR_MSS_CLIInit()这个函数了,这个函数中定义的就是上位机通过发送命令信息后要执行的任务。
OK,MRR_MSS_initTask这个函数就在此介绍完了。下一个要介绍的就是MRR_MSS_CLIInit ()函数
MRR_MSS_CLIInit
void MRR_MSS_CLIInit (void)
{
CLI_Cfg cliCfg;
/* Initialize the CLI configuration: */
memset ((void *)&cliCfg, 0, sizeof(CLI_Cfg));
/* Populate the CLI configuration: */
cliCfg.cliPrompt = "PaTIDesign:/>";
cliCfg.cliUartHandle = gMrrMSSMCB.commandUartHandle;
cliCfg.taskPriority = 3;
cliCfg.mmWaveHandle = gMrrMSSMCB.ctrlHandle;
cliCfg.enableMMWaveExtension = 0U;
cliCfg.usePolledMode = true;
cliCfg.tableEntry[0].cmd = "basicCfg";
cliCfg.tableEntry[0].helpString = "Basic Cfg [Hardcoded Parameters]";
cliCfg.tableEntry[0].cmdHandlerFxn = MRR_MSS_CLIBasicCfg;
cliCfg.tableEntry[1].cmd = "advFrameCfg";
cliCfg.tableEntry[1].helpString = "Advanced Frame Cfg [Hardcoded Parameters]";
cliCfg.tableEntry[1].cmdHandlerFxn = MRR_MSS_CLIAdvancedFrameCfg;
cliCfg.tableEntry[2].cmd = "sensorStart";
cliCfg.tableEntry[2].helpString = "Start the sensor; ensure that the configuration is completed";
cliCfg.tableEntry[2].cmdHandlerFxn = MRR_MSS_CLISensorStart;
cliCfg.tableEntry[3].cmd = "sensorStop";
cliCfg.tableEntry[3].helpString = "Stop the sensor";
cliCfg.tableEntry[3].cmdHandlerFxn = MRR_MSS_CLISensorStop;
/* 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");
/* The link is not configured. */
gMrrMSSMCB.cfgStatus = false;
gMrrMSSMCB.runningStatus = false;
gMrrMSSMCB.isMMWaveOpen = false;
return;
}
这个函数相比于上面的那一个函数就简单多了,意思是实现的功能性更简单了,这个函数定义了四个要从上位机接收到到的命令,分别时:basicCfg、advFrameCfg、sensorStart、sensorStop他们四个对应要执行的函数分别为MRR_MSS_CLIBasicCfg、MRR_MSS_CLIAdvancedFrameCfg、MRR_MSS_CLISensorStart、MRR_MSS_CLISensorStop。
下面介绍着重介绍这两个函数:MRR_MSS_CLIAdvancedFrameCfg、MRR_MSS_CLISensorStart
MRR_MSS_CLIAdvancedFrameCfg
static int32_t MRR_MSS_CLIAdvancedFrameCfg (int32_t argc, char* argv[])
{
MMWave_OpenCfg openCfg;
int32_t errCode;
rlProfileCfg_t profileCfg;
rlChirpCfg_t chirpCfg;
rlAdvFrameCfg_t advFrameCfg;
int32_t retVal;
int32_t indx;
rlRfLdoBypassCfg_t rfLdoBypassCfg[1] = {0};
if (gMrrMSSMCB.cfgStatus == true)
{
/* Radar has already been configured. */
return 0;
}
/* Setup the calibration frequency: */
openCfg.freqLimitLow = 760U;
openCfg.freqLimitHigh = 810U;
openCfg.defaultAsyncEventHandler = MMWave_DefaultAsyncEventHandler_MSS;
/* Initialize the minimal configuration: */
Cfg_ChannelCfgInitParams (&openCfg.chCfg);
Cfg_LowPowerModeInitParams(&openCfg.lowPowerMode);
Cfg_ADCOutCfgInitParams (&openCfg.adcOutCfg);
/* Open the mmWave module: */
if (MMWave_open (gMrrMSSMCB.ctrlHandle, &openCfg, NULL, &errCode) < 0)
{
System_printf ("Error: MMWDemoMSS mmWave open configuration failed [Error code %d]\n", errCode);
return -1;
}
System_printf ("Set LDO Bypass\n");
rfLdoBypassCfg->ldoBypassEnable = 0x03;
retVal = rlRfSetLdoBypassConfig(RL_DEVICE_MAP_INTERNAL_BSS, (rlRfLdoBypassCfg_t*)rfLdoBypassCfg);
if (retVal != RL_RET_CODE_OK)
{
System_printf ("Error: LDO Bypass config failed [Error %d]\n", retVal);
return -1;
}
/********************************************************************************
* MMWave Link and BSS is operational now. In minimal mode we have access to all
* the mmWave Link API to perform the configuration
*
* Profile configurations:
********************************************************************************/
for (indx = 0; indx < NUM_PROFILES; indx++)
{
Cfg_ProfileCfgInitParams (indx, &profileCfg);
retVal = rlSetProfileConfig (RL_DEVICE_MAP_INTERNAL_BSS, 1U, &profileCfg);
if (retVal != RL_RET_CODE_OK)
{
System_printf ("Error: Unable to configure the profile %d [Error %d]\n", indx, retVal);
return -1;
}
}
/********************************************************************************
* Chirp configurations:
********************************************************************************/
for (indx = 0; indx < NUM_CHIRP_PROG; indx++)
{
Cfg_ChirpCfgInitParams (indx, &chirpCfg);
retVal = rlSetChirpConfig(RL_DEVICE_MAP_INTERNAL_BSS, 1U, &chirpCfg);
if (retVal != RL_RET_CODE_OK)
{
System_printf ("Error: Unable to configure chirp %d [Error %d]\n", indx, retVal);
return -1;
}
}
/* Advanced Frame configuration. */
Cfg_AdvFrameCfgInitParams (&advFrameCfg);
retVal = rlSetAdvFrameConfig(RL_DEVICE_MAP_INTERNAL_BSS, &advFrameCfg);
if (retVal != RL_RET_CODE_OK)
{
System_printf ("Error: Advanced Frame configuration failed [Error %d]\n", retVal);
return -1;
}
/* The link has been configured. */
gMrrMSSMCB.cfgStatus = true;
System_printf ("Debug: MMWave has been configured for MRR.\n");
return 0;
}
函数Cfg_ChannelCfgInitParams(&openCfg.chCfg);分别是对天线的数目进行参数的设置,这里是4发3收,实现是通过左移操作和位或操作来实现,函数Cfg_LowPowerModeInitParams(&openCfg.lowPowerMode);是设置为低功耗模式,函数
Cfg_ADCOutCfgInitParams (&openCfg.adcOutCfg)是对adc数据参数进行的设置,设置为16位的complex数据格式,接下来就是MMWave_open()函数将设备打开,接下来就是profiles、chirp、frame的配置
MRR_MSS_CLISensorStart
static int32_t MRR_MSS_CLISensorStart (int32_t argc, char* argv[])
{
MMWave_CalibrationCfg calibrationCfg;
int32_t errCode;
if (gMrrMSSMCB.runningStatus == true)
{
/* Already running. */
return 0;
}
/* The sensor can only be started; if the link has been configured */
if (gMrrMSSMCB.cfgStatus == true)
{
/* Initialize the calibration configuration: */
memset ((void *)&calibrationCfg, 0, sizeof(MMWave_CalibrationCfg));
/* Populate the calibration configuration: */
calibrationCfg.dfeDataOutputMode =
MMWave_DFEDataOutputMode_ADVANCED_FRAME;
calibrationCfg.u.chirpCalibrationCfg.enableCalibration = true;
calibrationCfg.u.chirpCalibrationCfg.enablePeriodicity = true;
calibrationCfg.u.chirpCalibrationCfg.periodicTimeInFrames = 10U;
System_printf ("Debug: Sensor will start momentarily. \n");
/* Start the mmWave: */
if (MMWave_start (gMrrMSSMCB.ctrlHandle, &calibrationCfg, &errCode) < 0)
{
/* Error: Unable to start the mmWave control module */
System_printf ("Error: mmWave start failed [Error code %d]\n", errCode);
return -1;
}
gMrrMSSMCB.runningStatus = true;
return 0;
}
else
{
/* Invalid CLI use case; doing a sensor start without executing the basic or advanced configuration
* command. Inform the user and return an error code. */
System_printf ("Error: Please ensure that the XXXCfg CLI command is invoked before starting the sensor\n");
return -1;
}
}
这个函数的任务就是调用MMWave_start()让mmwave设备开始执行
OK,本篇文章对mss的代码解读就此结束,通过这篇文章,可以对mss的流程有一个清楚的认识