Abstract
infineon 下位机代码处理流程概览, 以 MCU7 为案例
Referance
Infineon-Infineon-XENSIVTM_KIT_CSK_BGT60TR13C-UserGuide-UserManual-v01_00-EN.pdf
目录结构
Radar Development Kit\3.3.1.202211181510\assets\software\firmware-rbb7\Firmware\sources\targets\atmel> tree .
├─subprojects
│ └─RadarBaseboardMCU7
│ └─bsp
│ ├─atr22
│ ├─avian
│ └─ltr11
└─target_platform
├─contrib
│ ├─ASF
│ │ ├─common
│ │ │ ├─boards
│ │ │ │ └─user_board
│ │ │ ├─services
│ │ │ │ ├─clock
│ │ │ │ │ └─sams70
│ │ │ │ ├─ioport
│ │ │ │ │ └─sam
│ │ │ │ ├─serial
│ │ │ │ │ └─sam_uart
│ │ │ │ ├─sleepmgr
│ │ │ │ │ └─sam
│ │ │ │ └─usb
│ │ │ │ ├─class
│ │ │ │ │ └─cdc
│ │ │ │ │ └─device
│ │ │ │ └─udc
│ │ │ └─utils
│ │ │ ├─interrupt
│ │ │ └─stdio
│ │ │ └─stdio_serial
│ │ ├─sam
│ │ │ ├─drivers
│ │ │ │ ├─afec
│ │ │ │ ├─efc
│ │ │ │ ├─matrix
│ │ │ │ ├─pio
│ │ │ │ ├─pmc
│ │ │ │ ├─pwm
│ │ │ │ ├─qspi
│ │ │ │ ├─rstc
│ │ │ │ │ └─example1
│ │ │ │ ├─spi
│ │ │ │ ├─tc
│ │ │ │ ├─twihs
│ │ │ │ ├─uart
│ │ │ │ ├─usart
│ │ │ │ ├─usbhs
│ │ │ │ └─xdmac
│ │ │ ├─services
│ │ │ │ └─flash_efc
│ │ │ └─utils
│ │ │ ├─cmsis
│ │ │ │ └─sams70
│ │ │ │ ├─include
│ │ │ │ │ ├─component
│ │ │ │ │ ├─instance
│ │ │ │ │ └─pio
│ │ │ │ └─source
│ │ │ │ └─templates
│ │ │ │ └─gcc
│ │ │ ├─fpu
│ │ │ ├─header_files
│ │ │ ├─linker_scripts
│ │ │ │ └─sams70
│ │ │ │ └─sams70q21
│ │ │ │ └─gcc
│ │ │ ├─make
│ │ │ ├─preprocessor
│ │ │ └─syscalls
│ │ │ └─gcc
│ │ └─thirdparty
│ │ └─CMSIS
│ │ ├─Include
│ │ └─Lib
│ │ └─GCC
│ ├─config
│ └─debug_scripts
│ └─gcc
└─impl
├─custom
├─ids
├─peripherals
└─serial
进入到 RadarBaseboardMCU7
这里一共对应三款雷达板
- atr22
- avian
- ltr11
RadarBaseboardMCU7
└─bsp
├─atr22
├─avian └─ltr11
RadarBaseboardMCU7:: main.c
标题格式
dir
::file.c
or(file.h
) :: function :: interfunction….
进入到 main 函数中, main 函数中结构很简单
int main(void)
{
// Board构造函数, 只调用这里只调用一次
();
Board_Constructor
/* Loop forever */
while (1)
{
();
Board_run}
}
RadarBaseboardMCU7:: main.c :: Board_Constructor
该函数是 board 构造(init), 在该函数的Platform_Constructor()
初始化平台, 创建低级接口
void Platform_Constructor(void)
{
();
System_init();
System_disableWatchdog
();
SysTimer_init
();
System_startUSB
();
PlatformInterfaces_Constructor
();
Timer_Constructor}
接下来是对底板(atmel
)的判断, 判断地板的类型, 这些参数配置在BoardDefinition.h
中, 后续如果添加版本, 只需要修改这里的定义即可.
// 如果不是Rev. A, 将原本BOARD_NAME_BASE的位置截断.
if (!Sams70RevisionA())
{
// If this is not Rev. A, trim the suffix from the board name
.name[sizeof(BOARD_NAME_BASE) - 1] = '\0';
boardInfo}
BoardDefinition.h
对板子信息进行描述, 方便后期移植工作.
// BOARD_NAME will be trimmed to BOARD_NAME_BASE in Board.c depending on silicon revision
#define BOARD_NAME_BASE "RadarBaseboardMCU7"
#define BOARD_NAME BOARD_NAME_BASE " (Rev. A)"
#define BOARD_VID 0x058B
#define BOARD_PID 0x0251
//#define BOARD_EEPROM_ADDRESS_24CW128X 0x50
#define COMMUNICATION_SERIAL
#include "../../../version.h"
后边是对gpio
, spi
,i2c
的构造, 这里的代码写的很巧妙, 分别在上层创建对应各个外设的类(结构体), 但是实际上该类掉用的是bsp
的接口, 这么做将 bsp 和上层接口进行分离, 使得 bsp 做出修改后, 只要接口不做调整, 上层应用也无需做出调整. IGpio
前面的 I
应该是Interface
的意思.
*gpio = &PlatformGpio;
IGpio *spi = &PlatformSpi;
ISpi *i2c = &PlatformI2c; II2c
紧接着是对雷达接口的创建, 和上面的操作类似.
*radar = NULL; IRadar
下面是对, 板子的类型做出检测:HatvanPlus 或 HatvanLegacy(MCU7
)
是对板子的一个类型的判断, 判断有几个 connecter, MCU7 上, 有两个链接器, 但是只能初始化一个.
/* 检测板类型:HatvanPlus 或 HatvanLegacy。
*
* 用于检测的引脚:
* 在标记为 BoardID 并连接到下拉的 HatvanPlus 上;
* 在标记为S2_SPI_DIR并连接到引体向上的 HatvanLegacy 上,
* 作为第二电平转换器电路的一部分。
*
* 解决方法:需要使能 LDO2 以提供 3.3v
* 用于上拉偏置,实现精确检测。
*/
// detect board type
const bool isHatvanLegacy = Board_isHatvanLegacy();
if (isHatvanLegacy)
{
= &ShieldConnectorDefinitionHatvanLegacy[0];
ShieldConnectorDefinition = &BoardSpiDefinitionHatvanLegacy[0];
BoardSpiDefinition = &BoardRadarPinsConfigAvianHatvanLegacy[0];
BoardRadarPinsConfigAvian = ARRAY_SIZE(ShieldConnectorDefinitionHatvanLegacy);
m_shieldConnectorCount }
else
{
// HatvanPlus has two different kinds of connectors and just one is initialized
if (Board_isHatvanPlusV9Connected())
{
= &ShieldConnectorDefinitionHatvanPlus[1];
ShieldConnectorDefinition = &BoardSpiDefinitionHatvanPlus[1];
BoardSpiDefinition = &BoardRadarPinsConfigAvianHatvanPlus[1];
BoardRadarPinsConfigAvian }
else
{
= &ShieldConnectorDefinitionHatvanPlus[0];
ShieldConnectorDefinition = &BoardSpiDefinitionHatvanPlus[0];
BoardSpiDefinition = &BoardRadarPinsConfigAvianHatvanPlus[0];
BoardRadarPinsConfigAvian }
= 1;
m_shieldConnectorCount }
因为上面对板子类型进行判断, 所以才得到 spi
的一个具体配置信息, 才能后进行初始化工作, 代码如下.
(BoardSpiDefinition, m_shieldConnectorCount); PlatformSpi_initialize
对spi
配置完成后对 led 进行配置, 配置 led 的一个状态表, 以及当前状态的设置.
();
LedSequence_Constructor(LED_STATUS_OPERATING); LedSequence_setStatus
检查核心板(radar 部分(shield))连接器是否存在配置错误 只有当扩展板具有 I2C 上拉时,才能检测到镜像连接 , OC 引脚上的其他意外电平被解释为错误的配置
if (Board_detectShields() == E_SUCCESS)
{
/*
使用 SPI 和 I2C 检查已知设备是否存在,
尝试读取芯片 ID 并按以下顺序实例化相应的驱动程序
(每个实例化只有一个设备)
- Avian (SPI) mcu 7 版本调用这个!!!!!
- LTR11 (SPI)
- ATR22 (I2C)
*/
= Board_detectRadar(gpio, spi, i2c, &m_data);
radar }
通信协议等外设, 继续正常初始化,这样即使没有检测到设备,I2C、SPI、GPIO 等也可以使用. 是能通信接口.
// Enable communication interface
(gpio, spi, m_data, i2c);
RequestHandler_Constructor();
ProtocolHandler_Constructor(); CommandHandlerRadar_Constructor
判断 radar 所有外设是否配置完成, 如果配置完成, 设置数据回调函数, 让回调函数来处理数据, 回调了函数Board_dataCallback
, 其中封装了一帧的数据, 并发送给上层的操作.
if (radar != NULL)
{
(radar);
Commands_IRadar_register
// register callback function to handle arriving data
->registerCallback(Board_dataCallback, NULL);
m_data}
到此整块板子(雷达
和主控
) 的各部分件构造全部完成
RadarBaseboardMCU7:: main.c :: Board_run()
该部分, 是雷达各部分初始化工作,以及使能完成后, 对各中操作的监听, 以及响应的中断处理函数.
/* Loop forever */
while (1)
{
();
Board_run}
进入到Board_run
函数中, Platform_run
函数中没有任何操作, 预留给用户进行编写运行过程中的相关状态操作(猜测).
// needs to be called for state machines, etc.
(); Platform_run
接下来的三个函数是针对三款不同的 60G mmwave(Avian
, ltr11
, atr22
)进行执行响应的操作, 但是如果没有创建对应的实力的话, 函数会直接返回, 不会执行任何操作.
// these run functions can just be called unconditionally, since they will immediately return by default if they are not initialized
();
DataAvian_run();
DataLtr11_run(); DataAtr22_run
这里的案例是avian
系列的, 所以进入到该函数中其他两个函数在该平台下, 直接返回, 无任何操作.
DataAvian_run 函数中, 先判断是够构建该实力, 判断该变量是否被实例化, 如果没有实例化, 没有实例化的默认值为NULL
, 所以该函数直接反回, DataLtr11_run
和 DataAtr22_run
中的该部分操作也类似.
if (!m_callback)
{
return;
}
接下来是将雷达数据区遍历, 这里最大支持一个数据.
for (unsigned int index = 0; index < DATA_AVIAN_MAX_COUNT; index++)
检查雷达运行状态
if (!self->running)
{
continue;
}
检查数据队列中的数据, 是否有数据
/* Check if new data packets have been fetched into the queue */
*queue = &self->queue;
Queue_t const uint32_t written = queue->written;
const uint32_t read = queue->read;
if (read == written)
{
// queue is empty
continue;
}
往上层发送数据, 上位机.
/* Transmit enqueued data packets to upper layers */
const uint32_t idx_read = queue->idx_read;
const uint32_t max_packets = queue->max_packets;
const uint32_t packet_size = queue->packet_size;
const uint32_t payload_size = queue->payload_size;
uint8_t *payload = &queue->buffer[idx_read * packet_size];
const queue_packet_header_t *header = &queue->packetHeaders[idx_read];
const uint64_t timestamp = chrono_ticks_to_microseconds(header->ticks);
检查是否溢出, 数据可能来自不同的 frame, 如果来自不同 frame, 判断会不会导致 FIFO 溢出.
/* Check if FIFO overflow or underflow condition occurred */
bool errors = false;
if (self->frameSlices > 1)
{
// In case a frame is being aggregated, check all slices in the queue
uint32_t idx_write = queue->idx_write;
for (uint32_t i = idx_read; i < idx_write; i++)
{
const queue_packet_header_t *sliceHeader = &queue->packetHeaders[i];
= fifo_overflow(sliceHeader->gsr0);
errors if (errors)
{
break;
}
}
}
else
{
// If no aggregation, just check the next slice in the queue
= fifo_overflow(header->gsr0);
errors }
如果存在错误, 将雷达停止, 回调溢出错误函数, 记录当前时间错, 和 FIFO 索引.然后继续往下运行
if (errors)
{
(self->index);
DataAvian_stop(ERR_FIFO_OVERFLOW, self->index, timestamp);
errorCallbackcontinue;
}
检查队列中是否有完整的数据帧, 如果没有回调函数还不能被调用.
const uint32_t slicesAvailable = written - read;
if (slicesAvailable < self->frameSlices)
{
// complete frame is not yet available
, 就是错误与否都往上发送
这里的如果错误的逻辑还没有写continue;
}
将队列中的数据进行发送
(m_arg, payload, payload_size * self->frameSlices, self->index, timestamp); m_callback
更新读取的索引, 和已读数量, 并且释放上一帧已经发送的数据
->idx_read = (idx_read + self->frameSlices) % max_packets;
queue->read = read + self->frameSlices; queue
如果数据队列已满, 数据获取请求可能会被挂起, 没有被挂起则每次回调后更新指针.
if (self->pending)
{
(self, false);
DataAvian_fetchCallback->pending--;
self}