171
社区成员
发帖
与我相关
我的任务
分享我的最大距离25.6米,距离分辨率:0.4m,最大速度:12.8m,速度分辨率:0.4m/s,起始频率60GHZ,一帧数据为:64*64*4*8/1024=128KB,如果所示,一个datacube的payload为3KB,应该要传输43次,在i等于36时,我们可以看到一帧总长为128KB,偏移量为105,意味着后面还有7个datacube,但是在i等于37的时候,直接收到了传输完成的命令,意味着more为0,且status:00,我检测到more为0且notify io为0我就输出00,因此这里是怎么回事。明明一帧数据还没有输出完,就显示没有数据了且设备也没有处于就绪态了。

如果是我的代码读取时延太高了,那我应该怎么优化呢?主要是get_one_chirp函数怎么优化,我感觉我写得和手册的差不多吧,或者我有什么错误吗
这是我测试IO为高电平到一帧接收完的时间,大概耗时65ms:

相关读取代码如下,其中spi_transmit()为数据传输的函数,get_one_chirp函数为获取一帧数据,主函数就是唤醒雷达,读取数据。是我的读取数据的代码不够高效,导致时延太大了吗?
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdbool.h>
#include <sys/ioctl.h>
#include <linux/spi/spidev.h>
#include <gpiod.h>
#include <time.h>
uint8_t calc_check8(uint8_t *h){
uint8_t sum=h[0]+h[2]+h[3]+h[4]+h[5];
return ~sum;
}
uint32_t calc_check32(uint8_t *cmd,uint32_t len){
uint32_t wd=len/4;
uint32_t sum=0;
for(int i=0;i<wd;i++){
sum+=((cmd[i*4]<<24)|(cmd[i*4+1]<<16)|(cmd[i*4+2]<<8)|cmd[i*4+3]);
}
return ~sum;
}
int spi_transmit(int spi,struct spi_ioc_transfer *spi_trans,uint8_t *tx,uint8_t *rx,int len,uint8_t mode){
int status=-1;
if(mode==0){
spi_trans->tx_buf=(unsigned long)tx;
spi_trans->rx_buf=(unsigned long)rx;
spi_trans->len=len;
status=ioctl(spi,SPI_IOC_MESSAGE(1),spi_trans);
}else if(mode==1){
spi_trans->tx_buf=(unsigned long)tx;
spi_trans->rx_buf=0;
spi_trans->len=len;
status=ioctl(spi,SPI_IOC_MESSAGE(1),spi_trans);
}else if(mode==2){
spi_trans->tx_buf=0;
spi_trans->rx_buf=(unsigned long)rx;
spi_trans->len=len;
status=ioctl(spi,SPI_IOC_MESSAGE(1),spi_trans);
}
return status;
}
int get_one_chirp(int spi,struct spi_ioc_transfer *spi_trans,uint8_t *miso,struct gpiod_line *line){
uint8_t poll_cmd[14]={0xA5,0x35,0x15,0x0C,0x04,0x00,0x02,0x00,0x2D,0x00,0xE8,0xF3,0xCE,0xFF};
int len=14,status=0,value=0,n=0;
status=spi_transmit(spi,spi_trans,poll_cmd,NULL,len,1);
usleep(2000);
bool more=false;
uint8_t header[6];
uint32_t checksum=0;
for(int i=0;i<poll_cmd[8];i++){
value=0;
while(value!=1){value=gpiod_line_get_value(line);}
status=spi_transmit(spi,spi_trans,NULL,header,6,2);
if(header[0]==0xA5){
n+=1;
}else{
continue;
}
len=((header[5]&0x0F)<<8)|header[4]+4;
more=((header[2]&0x20)==0x20)?true:false;
usleep(200);
status=spi_transmit(spi,spi_trans,NULL,miso,len,2);
/* printf("i:%d,header:",i);
for(int i=0;i<6;i++){printf("%02X ",header[i]);}
printf("\n");
for(int i=0;i<256;i++){printf("%02X ",miso[i]);}
printf("\n");*/
value=gpiod_line_get_value(line);
if(more==1&&value==0){return 0;}
if(more!=1){
usleep(50);
value=gpiod_line_get_value(line);
if(value==1){
poll_cmd[8]=45-i-1;
checksum=calc_check32(&poll_cmd[2],8);
poll_cmd[10]=checksum>>24;
poll_cmd[11]=(checksum>>16)&0xFF;
poll_cmd[12]=(checksum>>8)&0xFF;
poll_cmd[13]=(checksum&0xFF);
status=spi_transmit(spi,spi_trans,poll_cmd,NULL,14,1);
usleep(2000);
}else{
return n;
}
}
}
return n;
}
int main(){
struct gpiod_chip *chip;
struct gpiod_line *line;
int value=0;
chip=gpiod_chip_open_by_name("gpiochip2");
if(!chip){printf("open gpio failed\n");return -1;}
line=gpiod_chip_get_line(chip,1);
if(!line){printf("get line failed\n");gpiod_chip_close(chip);return -1;}
if(gpiod_line_request_input(line,"RADAR_NOTIFY")<0){
printf("failed to request input\n");
gpiod_line_release(line);
gpiod_chip_close(chip);
return -1;
}
int spi=-1;
spi=open("/dev/spidev2.0",O_RDWR);
if(spi<0){
printf("open device failed\n");
return -1;
}
printf("open device success,spi=%d\n",spi);
uint8_t mode=SPI_MODE_0;
uint8_t lsb=0x00;
uint8_t bits=8;
uint32_t speed=60000000;
printf("mode:%d,lsb:%d\n",mode,lsb);
if(ioctl(spi,SPI_IOC_WR_MODE,&mode)<0){
close(spi);
gpiod_line_release(line);
gpiod_chip_close(chip);
return -1;
}
if(ioctl(spi,SPI_IOC_WR_LSB_FIRST,&lsb)<0){
close(spi);
gpiod_line_release(line);
gpiod_chip_close(chip);
return -1;
}
if(ioctl(spi,SPI_IOC_WR_BITS_PER_WORD,&bits)<0){
close(spi);
gpiod_line_release(line);
gpiod_chip_close(chip);
return -1;
}
if(ioctl(spi,SPI_IOC_WR_MAX_SPEED_HZ,&speed)<0){
close(spi);
gpiod_line_release(line);
gpiod_chip_close(chip);
return -1;
}
printf("spi initialized\n");
uint8_t *mosi=(uint8_t *)malloc(sizeof(uint8_t)*4);
uint8_t *miso=(uint8_t *)malloc(sizeof(uint8_t)*4);
printf("trying to awake radar\n");
struct spi_ioc_transfer spi_trans;
int status=-1;
int len=0;
memset(&spi_trans,0,sizeof(spi_trans));
spi_trans.speed_hz=60000000;
spi_trans.delay_usecs=0;
spi_trans.bits_per_word=8;
bool awake=false;
for(int i=0;i<10;i++){
mosi[0]=0x55;
mosi[1]=0xFF;
mosi[2]=0x55;
mosi[3]=0xFF;
len=4;
status=spi_transmit(spi,&spi_trans,mosi,miso,len,0);
for(int i=0;i<len;i++){
if(miso[i]==0x79){printf("radar has awaked:%02X\n",miso[i]);awake=true;break;}
}
if(awake){break;}
usleep(1000);
}
if(!awake){
printf("radar hasn't awaked\n");
gpiod_line_release(line);
gpiod_chip_close(chip);
close(spi);
return -1;
}
usleep(5000);
free(mosi);
free(miso);
int n=0,m=0;
len=4096;
miso=(uint8_t*)malloc(sizeof(uint8_t)*len);
struct timespec start,end;
clock_gettime(CLOCK_MONOTONIC,&start);
while(m++<100){
value=0;
while(value!=1){value=gpiod_line_get_value(line);}
// clock_gettime(CLOCK_MONOTONIC,&start);
n+=get_one_chirp(spi,&spi_trans,miso,line);
// value=0;
// while(value!=1){value=gpiod_line_get_value(line);}
}
printf("n:%d\n",n);
clock_gettime(CLOCK_MONOTONIC,&end);
long seconds=end.tv_sec-start.tv_sec;
long nanos=end.tv_nsec-start.tv_nsec;
if(nanos<0){
seconds--;
nanos+=1000000000;
}
double elapse=seconds+nanos*1e-9;
printf("elapse:%.9f sec\n",elapse);
free(miso);
gpiod_line_release(line);
gpiod_chip_close(chip);
close(spi);
return 0;
}
我刚刚将我c语言的读取代码的频率修改为60MHZ,试着接收100帧,每帧128KB,每帧需要接收45次(包含第一个增益因子的,43个datacube,一个datacube为3KB,一个传输完成的ack),100帧对应4500次,但是还是回存在我说的丢包。

我们这边使用SPI频率60M、30M、15M测试了一下,60M能够正常接收,30M正常接收,但是会接收一帧漏掉一帧,因为接收的周期太长,超过了100ms,15M不能正常接收,数据包数量小于预期,与您的现象一致
综上,如果SPI频率较低,可以尝试至少提高到30M以上
请问您SPI的频率是多少?
prj_config.h文件
/**
**************************************************************************************************
* @brief project config define.
* @attention
*
* Copyright (C) 2025 POSSUMIC TECHNOLOGY CO., LTD. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
* 3. Neither the name of POSSUMIC TECHNOLOGY CO., LTD. nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
**************************************************************************************************
*/
#ifndef _PRJ_CONFIG_H
#define _PRJ_CONFIG_H
/*
* The board supported by the SDK,
* please refer to platfromr/boards/board_config.h,
* MRS6130-P1806 will use uart0 as HIF and uart1 as printf com port,
* MRS6130-P1812/MRS6240-P2512 will use uart0 as printf & shell, SPI or UART1 as HIF
*/
#if CONFIG_BOARD_MRS6130_P1806
#define CONFIG_PRINTF_UART_NUM 1
#else
#define CONFIG_PRINTF_UART_NUM 0
#endif
/* Upload DataCube will cost more time */
#define CONFIG_R3_DATA_BOX_UPLOAD_DATA_CUBE 1
#if CONFIG_R3_DATA_BOX_UPLOAD_DATA_CUBE
#define HEAP_SZIE_DATA_CUBE (1024 * 12) /* data cube upload need 12K sram cache data */
#else
#define HEAP_SZIE_DATA_CUBE (1024 * 0)
#endif
/* Upload 1Dfft Data will cost more time and buffer
* if CONFIG_R3_DATA_BOX_UPLOAD_1DFFT_DATA == 1,frame period need config 100ms */
#define CONFIG_R3_DATA_BOX_UPLOAD_1DFFT_DATA 0
#if CONFIG_R3_DATA_BOX_UPLOAD_1DFFT_DATA
#define HEAP_SZIE_1D_CUBE (1024 * 16) /* if range fft = 512,need sram equal 512 * 4 * MIMO_RX_NUM(6240 is 8) = 16K */
#else
#define HEAP_SZIE_1D_CUBE (1024 * 0)
#endif
/* STATIC CONFIG USE SOFTWARE CFAR OR NOT */
#define SW_CFAR_ENABLE 0
/* Enable micro point out by default */
#define CONFIG_MMW_MICRO_POINT_CLOUD 0
#if CONFIG_MMW_MICRO_POINT_CLOUD
#define HEAP_SZIE_MiCRO (1024 * 78) /* micro motion need more sram */
#else
#define HEAP_SZIE_MiCRO (1024 * 0)
#endif
#define HEAP_SZIE_BASIC (1024 * 55) /* just running motion point cloud need 55K */
#define CAL_HEAP_SZIE_TOTAL HEAP_SZIE_DATA_CUBE + HEAP_SZIE_MiCRO + HEAP_SZIE_1D_CUBE
#define CONFIG_HEAP_SIZE CAL_HEAP_SZIE_TOTAL + HEAP_SZIE_BASIC
#define CONFIG_MMW_CTRL 1
#define CONFIG_MMW_DRIVER 1
#define CONFIG_MMW_CALIB_DATA_LOAD 1 /* load from flash */
#define CONFIG_HIF 1
#if CONFIG_BOARD_MRS6130_P1806
#define CONFIG_HIF_UART_PORT 0
#else
#define CONFIG_HIF_UART_PORT 1
#endif
#define CONFIG_HIF_DEVICE_COM_UART 1
#define CONFIG_HIF_DEVICE_WAKEUP_UART 1
#define CONFIG_HIF_DEVICE_COM_SPI 1
#define CONFIG_HIF_DEVICE_WAKEUP_SPI 1
#define CONFIG_HIF_DMA_PINGPONG 0
#define CONFIG_HIF_SEND_DMA 1
#define CONFIG_PM 0 /* PM is not support yet. */
#define CONFIG_PMU_EXTLDO_SLEEP_SW_SUBMODE 1
#endif /* _PRJ_CONFIG_H */
/*
**************************************************************************************************
* (C) COPYRIGHT POSSUMIC TECHNOLOGY
* END OF FILE
*/
r3_databox_2d_dsp.c文件
#include "mmw_ctrl.h"
#include "r3_databox_debug_tool.h"
#include "mmw_point_cloud_psic_lib.h"
#include "mmw_app_pointcloud.h"
#include "mmw_alg_pointcloud.h"
#include "mmw_alg_debug.h"
#include "mmw_type.h"
#include "log.h"
#include "r3_databox_2d_dsp.h"
#include "mmw_report.h"
#include "r3_databox_msg_handler.h"
#if CONFIG_MMW_MICRO_POINT_CLOUD
#include "mmw_alg_doa.h"
#include "mmw_app_micro_pointcloud.h"
#endif
#if CONFIG_MMW_MICRO_POINT_CLOUD
typedef struct micro_report_arg {
PointCloud3D *buffer;
uint32_t point_num;
int32_t micro_range_unit; /* cm-q4 */
} MmwMicroPointCloudOut_t;
#endif
Complex16_RealImag *g_1d_fft_data_buff = 0; /* store 1d fft data */
Databox1dFftDataConfig_t g_1d_fft_data_config; /* store 1d fft data config */
#if CONFIG_R3_DATA_BOX_UPLOAD_1DFFT_DATA
int r3_databox_obtain_1d_fft_data_init(void)
{
int8_t ret = 0;
uint16_t range_fft_num, doppler_fft_num;
mmw_fft_num_get(&range_fft_num, &doppler_fft_num);
/* config 1d data scope 1:0 - range_fft_num range bin 2:0 - 0 dop bin 3:all tx ants 4:all rx ants */
g_1d_fft_data_config.range_start = 0;
g_1d_fft_data_config.range_num = range_fft_num;
g_1d_fft_data_config.start_intv = 0;
g_1d_fft_data_config.end_intv = 0;
g_1d_fft_data_config.tx_id = MMW_ANT_ID_ALL;
g_1d_fft_data_config.rx_id = MMW_ANT_ID_ALL;
ret |= mmw_2dfft_obtain_1dfft_cfg(g_1d_fft_data_config.range_start, g_1d_fft_data_config.range_num, g_1d_fft_data_config.start_intv, g_1d_fft_data_config.end_intv, g_1d_fft_data_config.tx_id, g_1d_fft_data_config.rx_id);
g_1d_fft_data_config.intv_num = g_1d_fft_data_config.end_intv - g_1d_fft_data_config.start_intv + 1;
uint8_t config_tx_num = 0;
uint8_t config_rx_num = 0;
MmwPsicMimoRxNum_t mimo_rx_info;
mmw_psic_lib_sdk_get_tx_rx_num(&mimo_rx_info);
if (g_1d_fft_data_config.tx_id == MMW_ANT_ID_ALL)
{
config_tx_num = mimo_rx_info.ant_tx_num;
}
if (g_1d_fft_data_config.rx_id == MMW_ANT_ID_ALL)
{
config_rx_num = mimo_rx_info.ant_rx_num;
}
g_1d_fft_data_config.config_mimo_rx_num = config_tx_num * config_rx_num;
/* allocate the memory size according mmw_2dfft_obtain_1dfft_cfg */
mmw_process_mem_alloc((void **)&g_1d_fft_data_buff, sizeof(Complex16_RealImag) * g_1d_fft_data_config.config_mimo_rx_num * g_1d_fft_data_config.intv_num * g_1d_fft_data_config.range_num);
ret |= mmw_2dfft_set_1dfft_buffer(g_1d_fft_data_buff); /* regist pointer */
return ret;
}
void r3_databox_obtain_1d_fft_data_deinit(void)
{
mmw_process_mem_free((void**)&g_1d_fft_data_buff);
}
#endif
#if (CONFIG_MMW_MICRO_POINT_CLOUD)
/**
* @brief micro point cloud upload to RadarDebugTool
* if user use micro point cloud, enable macro "CONFIG_MMW_MICRO_POINT_CLOUD" in prj_config.h
* carti is geted from the result of "mmw_micro_point_process"
* the data type of carti is int16
* in "mmw_psic_debug_proto_report", use "PSIC_DBG_PROTO_DATA_FORMAT_SHORT" to upload micro point cloud
* */
__sram_text int micro_point_cloud_data_handler(uint32_t range_idx, int veloc_idx,
uint32_t snr_linear, MmwAngleInfo_t *angle, void *arg)
{
MmwMicroPointCloudOut_t *report = (MmwMicroPointCloudOut_t *)arg;
int32_t range_cm_q4 = range_idx * report->micro_range_unit;
PointCloud_Cart *cart = (PointCloud_Cart *)report->buffer;
int32_t range_cmq1 = (range_cm_q4 >> 3);
mmw_micro_frame_trans_radar_coord_to_user_coord(
(range_cmq1 * angle->sinValue_X) >> 16,
(range_cmq1 * angle->sinValue_Y) >> 16,
(range_cmq1 * angle->sinValue_Z) >> 16,
&cart[report->point_num]
);
return (++report->point_num >= MICRO_POINT_MAX);
}
#endif
__sram_text int r3_databox_2d_frame_cb(void *mmw_data, void *arg) {
/* Skip default 2 frames to wait for clutter coverage */
if (!r3_databox_obtain_skip_frame_status()) { /* return vaule of 0 indicates that the invalid data frames has skipped */
mmw_dsp_poweron();
//PointCloudBuffer_t *ptr_point_cloud_buffer;
r3_databox_upload_gain_factor_process(); /* upload fft gain if used auto gain */
#if CONFIG_R3_DATA_BOX_UPLOAD_1DFFT_DATA
r3_databox_upload_1d_fft_data(); /* upload range fft result in 2d frame mode */
#endif
#if SW_CFAR_ENABLE
ptr_point_cloud_buffer = mmw_point_cloud_process_sw_cfar();
#else
//ptr_point_cloud_buffer = mmw_point_cloud_process();
#endif
#if (CONFIG_MMW_MICRO_POINT_CLOUD)
bool micro_update = mmw_micro_point_frame();
/* auto gain function must be cleared manually as soon as gain factor is not used,
to make auto gain in next frame works well.
Hardware reuired gain factor cleared before chirp transmit period
*/
mmw_psic_auto_gain_clear();
MmwMicroPointCloudOut_t mpc_output;
uint16_t range_fft_num, doppler_fft_num;
uint32_t range_mm, range_reol_mm;
mmw_range_get(&range_mm, &range_reol_mm);
mmw_fft_num_get(&range_fft_num, &doppler_fft_num);
mpc_output.micro_range_unit = (range_mm << 4) / 10 / range_fft_num;
mpc_output.point_num = 0;
mpc_output.buffer = 0;
mmw_process_mem_alloc((void**)&mpc_output.buffer, MICRO_POINT_MAX * sizeof(*mpc_output.buffer));
/* mmw frames down sampling for micro frame.
* During down sampling period, MCU keeps storing micro frame, ‘micro_update’ will keep ‘0’,
* therefor process micro points when new micro frame is ready(‘micro_update’ = 1).
* */
if (micro_update) {
mmw_micro_point_process(micro_point_cloud_data_handler, (void*)&mpc_output);
mmw_micro_point_cloud_upload(mpc_output.buffer, mpc_output.point_num);
}
mmw_process_mem_free((void**)&mpc_output.buffer);
#else
/* auto gain function must be cleared manually as soon as gain factor is not used,
to make auto gain in next frame works well.
Hardware reuired gain factor cleared before chirp transmit period
*/
mmw_psic_auto_gain_clear();
#endif
/* TODO: Add user prorcess here */
//r3_databox_point_cloud_upload(ptr_point_cloud_buffer, ptr_point_cloud_buffer->point_cloud_num);
//mmw_process_mem_free((void**) &ptr_point_cloud_buffer->ptr_motion_point_cloud_data);
//mmw_process_mem_free((void**) &ptr_point_cloud_buffer);
//if ((mmw_point_cloud_get_user_cfg_const()->mmw_point_cloud_detection_config.clutter_rm_method == POINT_CLUTTER_REMOVAL_DC) &&
//(!mmw_point_cloud_get_user_cfg_const()->mmw_point_cloud_detection_config.clutter_halt_en)) {
//mmw_psic_dc_suppression_update();
//}
#if CONFIG_R3_DATA_BOX_UPLOAD_DATA_CUBE
uint32_t com_type = 0;
HIF_ParamGet(HIF_SET_COM_TYPE, &com_type, sizeof(com_type));
if(com_type == HIF_COM_TYPE_SPI) {
mmw_ctrl_data_cube_spi_report_cb(mmw_data, arg);
} else if(com_type == HIF_COM_TYPE_UART){
mmw_ctrl_data_cube_uart_report_cb(mmw_data, arg);
}
#endif
}else {
r3_databox_update_skip_frame_status(); /* count skipped frames */
/* when clutter_rm_method is DC,skip the last frame init DC */
//if (mmw_point_cloud_get_user_cfg_const()->mmw_point_cloud_detection_config.clutter_rm_method == POINT_CLUTTER_REMOVAL_DC && !r3_databox_obtain_skip_frame_status()) {
// mmw_clutter_halt_set(MMW_HALT_CLUTTER_UPDATE_ENABLE);
// mmw_psic_dc_suppression_init();
//if (!mmw_point_cloud_get_user_cfg_const()->mmw_point_cloud_detection_config.clutter_halt_en) {
/* mmw_psic_dc_suppression_init will clear cluuter and needs to be update once */
//mmw_psic_dc_suppression_update();
//}
//}
/* auto gain function must be cleared manually as soon as gain factor is not used,
to make auto gain in next frame works well.
Hardware reuired gain factor cleared before chirp transmit period
*/
mmw_psic_auto_gain_clear();
}
return 0;
}
__sram_text Complex16_RealImag *r3_databox_get_1d_fft_buffer(void)
{
return g_1d_fft_data_buff;
}
__sram_text Databox1dFftDataConfig_t r3_databox_get_1d_fft_config(void)
{
return g_1d_fft_data_config;
}
r3_databox_msg_handler.c文件
/**
**************************************************************************************************
* @brief project config define.
* @attention
*
* Copyright (C) 2025 POSSUMIC TECHNOLOGY CO., LTD. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
* 3. Neither the name of POSSUMIC TECHNOLOGY CO., LTD. nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
**************************************************************************************************
*/
#include "r3_databox_msg_handler.h"
#include "mmw_ctrl.h"
#include "hif.h"
#include "mmw_app_pointcloud.h"
#include "mmw_point_cloud_psic_lib.h"
#include "mmw_app_pointcloud_config.h"
#include "r3_databox_2d_dsp.h"
#include "r3_databox_1d_dsp.h"
#include "r3_databox_debug_tool.h"
#include <math.h>
#include "mmw_report.h"
#if CONFIG_MMW_MICRO_POINT_CLOUD
#include "mmw_alg_doa.h"
#include "mmw_app_micro_pointcloud.h"
#endif
static bool s_read_current_config_flag = false;
/*
* The fisrt and second frame after call mmw_start() contains invalid data, so we should bypass 2st frame
* This flag is set in r3_databox_startup_config() function, and count in r3_databox_1d/2d_frame_cb()
*/
static uint8_t s_r3_databox_skip_frame_status = R3_DATABOX_SKIP_FRAME_NUM;
DataBoxConfig_t g_databox_global_config =
{
.data_box_frame_config =
{
#if CONFIG_SOC_SERIES_RS624X
.mimo_mode = MMW_MIMO_2T4R,
#elif CONFIG_SOC_SERIES_RS613X
.mimo_mode = MMW_MIMO_1T3R,
#endif
.frame_type = 1, //2D work mode
.start_freq_mhz = 60000, //59GHZ
.max_trigger_range_mm = 25600, //25.6m
.range_resolution_mm = 400, //0.4m
.max_range_rate_mm = 12800, //12.8m/s
.vel_resolution_mm = 400, //0.4m/s
#if CONFIG_R3_DATA_BOX_UPLOAD_DATA_CUBE
#if CONFIG_BOARD_MRS6130_P1812 || CONFIG_SOC_SERIES_RS624X
.frame_period_ms = 100
#elif CONFIG_BOARD_MRS6130_P1806
.frame_period_ms = 2000
#endif
#else
.frame_period_ms = 100
#endif
}
};
int r3_databox_startup_config()
{
int ret = 0;
uint8_t mimo_mode = g_databox_global_config.data_box_frame_config.mimo_mode;
if(g_databox_global_config.data_box_frame_config.frame_type == 0) {
ret = mmw_mode_cfg(mimo_mode, MMW_WORK_MODE_1DFFT); /* config 1d work mode */
} else if (g_databox_global_config.data_box_frame_config.frame_type == 1) {
ret = mmw_mode_cfg(mimo_mode, MMW_WORK_MODE_2DFFT); /* config 2d work mode */
} else {
ret = 1;
}
if (ret) {
LOG_PRINT("mode cfg error! %d\n", ret);
return ret;
}
/* config start freq */
ret = mmw_freq_cfg(g_databox_global_config.data_box_frame_config.start_freq_mhz, 0);
if (ret) {
LOG_PRINT("start freq cfg error! %d\n", ret);
return ret;
}
/* config max det range and range res */
ret = mmw_range_cfg(g_databox_global_config.data_box_frame_config.max_trigger_range_mm, g_databox_global_config.data_box_frame_config.range_resolution_mm);
if (ret) {
LOG_PRINT("range cfg error! %d\n", ret);
return ret;
}
if(g_databox_global_config.data_box_frame_config.frame_type == 1) {
/* config max velocity and velocity res */
ret = mmw_velocity_cfg(g_databox_global_config.data_box_frame_config.max_range_rate_mm, g_databox_global_config.data_box_frame_config.vel_resolution_mm);
if (ret) {
LOG_PRINT("velocity cfg error! %d\n", ret);
return ret;
}
}
ret = mmw_chirp_num_cfg(1);//每个interval包含一个chirp
if (ret) {
LOG_PRINT("acc num cfg error! %d\n", ret);
return ret;
}
if (ret) {
LOG_PRINT("interval cfg error! %d\n", ret);
return ret;
}
ret=mmw_dop_fft_set(0);//关闭2D FFT
if (ret) {
LOG_PRINT("close dop_fft error! %d\n", ret);
return ret;
}
/* config frame period */
ret = mmw_frame_cfg(g_databox_global_config.data_box_frame_config.frame_period_ms, 0);
if (ret) {
LOG_PRINT("frame cfg error! %d\n", ret);
return ret;
}
uint32_t frame_period = 0;
uint32_t frame_num = 0;
ret = mmw_frame_get(&frame_period, &frame_num);
if (ret) {
LOG_PRINT("frame get error! %d\n", ret);
return ret;
}
frame_period = frame_period < 110 ? frame_period : 110;
frame_period -= 10;
HIF_ExtControl(HIF_SET_SEND_FRAME_TO, (void *)&frame_period, sizeof(frame_period));
//mmw_point_cloud_bb_config();
/* accord frame type register callback function */
if(g_databox_global_config.data_box_frame_config.frame_type == 0) {
ret = mmw_ctrl_callback_cfg(&r3_databox_1d_frame_cb, MMW_DATA_TYPE_1DFFT, NULL);
} else if (g_databox_global_config.data_box_frame_config.frame_type == 1) {
#if CONFIG_MMW_MICRO_POINT_CLOUD
mmw_coordinate_config(MMW_COORDINATE_TYPE_CART);
mmw_angle_mount_type_set(mmw_point_cloud_get_user_cfg_const()->mount_type);
mmw_micro_point_init();
mmw_micro_point_restart();
#endif
//mmw_point_cloud_init(); /* init the para of point cloud process */
#if SW_CFAR_ENABLE
mmw_fft_autogain_set(0); /* SW CFAR only support fix gain */
#endif
#if CONFIG_R3_DATA_BOX_UPLOAD_1DFFT_DATA
ret = r3_databox_obtain_1d_fft_data_init(); //init range fft result data that need to be reported in 2d frame mode
#endif
if (ret) {
LOG_PRINT("obtain_1d_fft_data_ini fail %d\n", ret);
}
ret = mmw_ctrl_callback_cfg(&r3_databox_2d_frame_cb, MMW_DATA_TYPE_2DFFT, NULL);
} else {
ret = 1;
}
if (ret) {
LOG_PRINT("mmw_ctrl_callback_cfg fail %d\n", ret);
}
r3_databox_reset_skip_frame_status(); /* reset the skipped frames status */
r3_databox_reset_gain_factor_frame_idx(); /* reset the gain_factor_frame_idx */
return 0;
}
static int r3_databox_start_ctrl_handler(HIF_MsgHdr_t *msg)
{
int ret = HIF_CMD_STATUS_SUCCESS;
uint8_t start = *((uint8_t *)(msg + 1));
if(start) {
ret = r3_databox_startup_config();
mmw_report_param_get();
ret = mmw_ctrl_start();
} else {
ret = mmw_sensor_stop();
int mmw_state = 0;
int to = 0;
do {
/* get mmw state, 4: runing */
mmw_state = can_mmw_configured();
if ((mmw_state != 4) && (mmw_event_process_completed())) {
/* alreay stop */
break;
} else {
/* prevent freezing, max 200ms */
if (to >= 200) {
break;
}
OSI_MSleep(1);
}
to++;
} while (1);
if (g_databox_global_config.data_box_frame_config.frame_type == 1) {
//mmw_point_cloud_deinit();
#if CONFIG_R3_DATA_BOX_UPLOAD_1DFFT_DATA
r3_databox_obtain_1d_fft_data_deinit();
#endif
#if CONFIG_MMW_MICRO_POINT_CLOUD
mmw_micro_point_deinit();
#endif
}
}
if(ret) {
ret = HIF_CMD_STATUS_IO;
}
return HIF_MsgResp(msg, 0, ret);
}
static uint8_t para_check(uint32_t para, uint32_t min, uint32_t max)
{
return (para >= min) && (para <= max);
}
static int r3_databox_single_cfg_handler(strMsgTlv *msgTlv)
{
int ret = MMW_ERR_CODE_INVALID_PARAM;
uint32_t tmp;
switch(msgTlv->type) {
case TLV_R3_DATA_BOX_CONFIG_MIMO_MODE:
{
#if CONFIG_SOC_SERIES_RS613X
if (para_check(msgTlv->value[0], MMW_MIMO_1T3R, MMW_MIMO_1T3R)) {
g_databox_global_config.data_box_frame_config.mimo_mode = msgTlv->value[0];
ret = 0;
}
#elif CONFIG_SOC_SERIES_RS624X
if (para_check(msgTlv->value[0], MMW_MIMO_2T4R, MMW_MIMO_2T4R)) {
g_databox_global_config.data_box_frame_config.mimo_mode = msgTlv->value[0];
ret = 0;
}
#else
#error "Please Choose Valid SOC Series"
#endif
break;
}
case TLV_R3_DATA_BOX_CONFIG_FRAME_TYPE:
{
if (para_check(msgTlv->value[0], 0, 1)) {
g_databox_global_config.data_box_frame_config.frame_type = msgTlv->value[0];
ret = 0;
}
break;
}
case TLV_R3_DATA_BOX_CONFIG_START_FREQ:
{
/* 1LSB = 1MHz */
tmp = (msgTlv->value[1] << 8) + msgTlv->value[0];
if (para_check(tmp, 57000, 64000)) {
g_databox_global_config.data_box_frame_config.start_freq_mhz = tmp;
ret = 0;
}
break;
}
case TLV_R3_DATA_BOX_CONFIG_TRIGGER_RANGE:
{
g_databox_global_config.data_box_frame_config.max_trigger_range_mm = (msgTlv->value[1] << 8) + msgTlv->value[0];
ret = 0;
break;
}
case TLV_R3_DATA_BOX_CONFIG_RANGE_RESOLUTION:
{
g_databox_global_config.data_box_frame_config.range_resolution_mm = (msgTlv->value[1] << 8) + msgTlv->value[0];
ret = 0;
break;
}
case TLV_R3_DATA_BOX_CONFIG_MAX_VELOCITY:
{
g_databox_global_config.data_box_frame_config.max_range_rate_mm = (msgTlv->value[1] << 8) + msgTlv->value[0];
ret = 0;
break;
}
case TLV_R3_DATA_BOX_CONFIG_VEL_RESOLUTION:
{
g_databox_global_config.data_box_frame_config.vel_resolution_mm = (msgTlv->value[1] << 8) + msgTlv->value[0];
ret = 0;
break;
}
case TLV_RE_DATA_BOX_CONFIG_FRAME_PERIOD:
{
g_databox_global_config.data_box_frame_config.frame_period_ms = (msgTlv->value[1] << 8) + msgTlv->value[0];
ret = 0;
break;
}
default:
ret = HIF_CMD_STATUS_UNSUPPORT;
break;
}
return ret;
}
static int r3_databox_cfg_msg_handler(HIF_MsgHdr_t *msg)
{
int ret = 0;
uint16_t offset = 0;
uint8_t *payload = (uint8_t *)(msg + 1);
strMsgTlv *msgTlv = NULL;
do{
msgTlv = (strMsgTlv *)(&payload[offset]);
ret = r3_databox_single_cfg_handler(msgTlv);
if (ret != 0) {
break;
}
offset += (msgTlv->len + 2);
}while(offset < msg->length);
return HIF_MsgResp(msg, 0, ret);
}
static int r3_databox_get_msg_handler(HIF_MsgHdr_t *msg)
{
int ret = 0;
strMsgTlv *msgTlv = (strMsgTlv *)(msg + 1);
s_read_current_config_flag = true;
ret = r3_databox_single_cfg_handler(msgTlv);
s_read_current_config_flag = false;
return HIF_MsgResp(msg, msgTlv->len+2 , ret);
}
int r3_databox_msg_init(void)
{
int status = 0;
status = HIF_MsgHdl_Regist(HIF_MSG_ID_START_CTRL, r3_databox_start_ctrl_handler);
status = HIF_MsgHdl_Regist(HIF_MSG_ID_MOTION_SENSOR_PARA_CFG, r3_databox_cfg_msg_handler);
status = HIF_MsgHdl_Regist(HIF_MSG_ID_MOTION_SENSOR_INFO_GET, r3_databox_get_msg_handler);
return status;
}
uint8_t r3_databox_obtain_skip_frame_status(void) {
return s_r3_databox_skip_frame_status;
}
void r3_databox_update_skip_frame_status(void) {
s_r3_databox_skip_frame_status--;
}
void r3_databox_reset_skip_frame_status(void) {
s_r3_databox_skip_frame_status = R3_DATABOX_SKIP_FRAME_NUM;
}
r3_databox_msg_handle.c这个文件与产品包的代码有较大出入,为避免我们修改与您的修改不同,麻烦您将这个修改后的文件发送一下吧
就是这个路径下的:RS6240\RS6x_7x_mmWave_sdk_V2.0.6\RS6x_7x_mmWave_sdk_V2.0.6\Software_Kit\02_SDK\psdf_sdk\project\mmwave\r3_databox,如下图所示

用的是哪个版本的产品包呢?我看了2.0.4和2.0.6没有能对上的代码哦
你好,我使用的是databox的固件,我对固件的修改如下:





我使用的是沁恒官网给的CH347T在linux下进行SPI通讯的驱动,使用这个驱动可以在linux下得到一个spidev设备,然后进行通讯。我的读取代码如下,其中计算checksum的32位校验码和官方的不一样,因为是小端存储,取数时从反着读,然后计算后存储也是反正存储,因此两次反抵消,我的计算逻辑就直接是正着读,正着存。但是不影响,因为我还没有使用,因为我没有使用到重传功能。然后spi的通讯速率我选择的是50MHZ,但是不影响,因为我也试过30MHZ,也会丢数据,并且如果想要读取100帧也是能够正常读取到这100帧的数据即12.5MB,但是有时会出现我帖子里的这种情况。
驱动网址:
https://github.com/WCHSoftGroup/ch34x_mphsi_master_linux#
代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdbool.h>
#include <sys/ioctl.h>
#include <linux/spi/spidev.h>
#include <gpiod.h>
#include <time.h>
uint8_t calc_check8(uint8_t *h){
uint8_t sum=h[0]+h[2]+h[3]+h[4]+h[5];
return ~sum;
}
uint32_t calc_check32(uint8_t *cmd,uint32_t len){
uint32_t wd=len/4;
uint32_t sum=0;
for(int i=0;i<wd;i++){
sum+=((cmd[i*4]<<24)|(cmd[i*4+1]<<16)|(cmd[i*4+2]<<8)|cmd[i*4+3]);
}
return ~sum;
}
int spi_transmit(int spi,struct spi_ioc_transfer *spi_trans,uint8_t *tx,uint8_t *rx,int len,uint8_t mode){
int status=-1;
if(mode==0){
spi_trans->tx_buf=(unsigned long)tx;
spi_trans->rx_buf=(unsigned long)rx;
spi_trans->len=len;
status=ioctl(spi,SPI_IOC_MESSAGE(1),spi_trans);
}else if(mode==1){
spi_trans->tx_buf=(unsigned long)tx;
spi_trans->rx_buf=0;
spi_trans->len=len;
status=ioctl(spi,SPI_IOC_MESSAGE(1),spi_trans);
}else if(mode==2){
spi_trans->tx_buf=0;
spi_trans->rx_buf=(unsigned long)rx;
spi_trans->len=len;
status=ioctl(spi,SPI_IOC_MESSAGE(1),spi_trans);
}
return status;
}
int get_one_chirp(int spi,struct spi_ioc_transfer *spi_trans,uint8_t *miso,struct gpiod_line *line){
uint8_t poll_cmd[14]={0xA5,0x35,0x15,0x0C,0x04,0x00,0x02,0x00,0x2D,0x00,0xE8,0xF3,0xCE,0xFF};
int len=14,status=0,value=0,n=0;
status=spi_transmit(spi,spi_trans,poll_cmd,NULL,len,1);
usleep(2000);
bool more=false;
uint8_t header[6];
uint32_t checksum=0;
for(int i=0;i<poll_cmd[8];i++){
value=0;
while(value!=1){value=gpiod_line_get_value(line);}
status=spi_transmit(spi,spi_trans,NULL,header,6,2);
if(header[0]==0xA5){
n+=1;
}else{
continue;
}
len=((header[5]&0x0F)<<8)|header[4]+4;
more=((header[2]&0x20)==0x20)?true:false;
usleep(200);
status=spi_transmit(spi,spi_trans,NULL,miso,len,2);
printf("i:%d,header:",i);
for(int i=0;i<6;i++){printf("%02X ",header[i]);}
printf("\n");
for(int i=0;i<256;i++){printf("%02X ",miso[i]);}
printf("\n");
value=gpiod_line_get_value(line);
if(more==1&&value==0){return 0;}
if(more!=1){
usleep(50);
value=gpiod_line_get_value(line);
if(value==1){
poll_cmd[8]=45-i-1;
checksum=calc_check32(&poll_cmd[2],8);
poll_cmd[10]=checksum>>24;
poll_cmd[11]=(checksum>>16)&0xFF;
poll_cmd[12]=(checksum>>8)&0xFF;
poll_cmd[13]=(checksum&0xFF);
status=spi_transmit(spi,spi_trans,poll_cmd,NULL,14,1);
usleep(2000);
}else{
return n;
}
}
}
return n;
}
int main(){
struct gpiod_chip *chip;
struct gpiod_line *line;
int value=0;
chip=gpiod_chip_open_by_name("gpiochip2");
if(!chip){printf("open gpio failed\n");return -1;}
line=gpiod_chip_get_line(chip,1);
if(!line){printf("get line failed\n");gpiod_chip_close(chip);return -1;}
if(gpiod_line_request_input(line,"RADAR_NOTIFY")<0){
printf("failed to request input\n");
gpiod_line_release(line);
gpiod_chip_close(chip);
return -1;
}
int spi=-1;
spi=open("/dev/spidev2.0",O_RDWR);
if(spi<0){
printf("open device failed\n");
return -1;
}
printf("open device success,spi=%d\n",spi);
uint8_t mode=SPI_MODE_0;
uint8_t lsb=0x00;
uint8_t bits=8;
uint32_t speed=50000000;
printf("mode:%d,lsb:%d\n",mode,lsb);
if(ioctl(spi,SPI_IOC_WR_MODE,&mode)<0){
close(spi);
gpiod_line_release(line);
gpiod_chip_close(chip);
return -1;
}
if(ioctl(spi,SPI_IOC_WR_LSB_FIRST,&lsb)<0){
close(spi);
gpiod_line_release(line);
gpiod_chip_close(chip);
return -1;
}
if(ioctl(spi,SPI_IOC_WR_BITS_PER_WORD,&bits)<0){
close(spi);
gpiod_line_release(line);
gpiod_chip_close(chip);
return -1;
}
if(ioctl(spi,SPI_IOC_WR_MAX_SPEED_HZ,&speed)<0){
close(spi);
gpiod_line_release(line);
gpiod_chip_close(chip);
return -1;
}
printf("spi initialized\n");
uint8_t *mosi=(uint8_t *)malloc(sizeof(uint8_t)*4);
uint8_t *miso=(uint8_t *)malloc(sizeof(uint8_t)*4);
printf("trying to awake radar\n");
struct spi_ioc_transfer spi_trans;
int status=-1;
int len=0;
memset(&spi_trans,0,sizeof(spi_trans));
spi_trans.speed_hz=50000000;
spi_trans.delay_usecs=0;
spi_trans.bits_per_word=8;
bool awake=false;
for(int i=0;i<10;i++){
mosi[0]=0x55;
mosi[1]=0xFF;
mosi[2]=0x55;
mosi[3]=0xFF;
len=4;
status=spi_transmit(spi,&spi_trans,mosi,miso,len,0);
for(int i=0;i<len;i++){
if(miso[i]==0x79){printf("radar has awaked:%02X\n",miso[i]);awake=true;break;}
}
if(awake){break;}
usleep(1000);
}
if(!awake){
printf("radar hasn't awaked\n");
gpiod_line_release(line);
gpiod_chip_close(chip);
close(spi);
return -1;
}
usleep(5000);
free(mosi);
free(miso);
int n=0,m=0;
len=4096;
miso=(uint8_t*)malloc(sizeof(uint8_t)*len);
struct timespec start,end;
clock_gettime(CLOCK_MONOTONIC,&start);
while(m++<2){
n+=get_one_chirp(spi,&spi_trans,miso,line);
value=0;
while(value!=1){value=gpiod_line_get_value(line);}
}
printf("n:%d\n",n);
clock_gettime(CLOCK_MONOTONIC,&end);
long seconds=end.tv_sec-start.tv_sec;
long nanos=end.tv_nsec-start.tv_nsec;
if(nanos<0){
seconds--;
nanos+=1000000000;
}
double elapse=seconds+nanos*1e-9;
printf("elapse:%.9f sec\n",elapse);
free(miso);
gpiod_line_release(line);
gpiod_chip_close(chip);
close(spi);
return 0;
}
您好:
这边需要您提供一下雷达固件、固件配置(帧周期、COM类型及频率等),以便复现问题进行分析
你好:
我请我们驱动同事来看一下,麻烦你把使用的固件、波形配置和操作方法描述一下,我们这边方便复现,谢谢。