1. 运行时间
FUNC(void, MemTst_CODE) MemTst_Cyclic1000ms(void) /* PRQA S 0624, 3206 */ /* MD_Rte_0624, MD_Rte_3206 */
{
uint32 t1;
uint32 t2;
#if MEMTST_COMPLIE_COMMAND
t1 = REALTIME_STM_IN_US;
FlsTst_Check_Sum();
t2 = REALTIME_STM_IN_US;
memt_data.times[i] = t2 - t1;
#endif
FlsTst_TxManager();
i += 1;
}
对执行FCE引擎加速的函数FlsTst_Check_Sum()进行计算时间测试。经过多次测试,得出平均计算时间为126777微秒,0.12s。最大、最小值上下浮动不超过1000微秒。传统的通过CRC TABLE方式计算的时间为700645微秒,0.7s,提升计算速度70%。
2. 底层原理与优势
FCE(Flexible CRC Engine)是专用于微控制器中用于硬件CRC计算的模块。相比于软件实现,FCE通过硬件加速器计算CRC,极大提高了计算效率。具体来讲,硬件实现通常包括一个 移位寄存器 和一个 反馈多项式,它们协同工作来处理输入数据并生成 CRC 值。此外,**FCE利用DMA(直接内存访问)来搬运数据,用户输入数据后,DMA驱动会使用专为CRC计算的DMA通道传输数据(EB Treos配置)。这个过程无需CPU的参与,数据流完全由DMA接管,大大减小了CPU资源的占用。DMA传输是硬件执行,所以在传输完成后会自动触发DMA中断(Dma_ChInterruptHandler)。需要注意的是,要在达芬奇中配置对应DMA通道的中断,且优先级不能在所有DMA传输通道中最低,否则无法调用中断函数,进而无法通过用户自定义的回调函数来返回CRC结果。
由于使用DMA控制器管理数据,CPU不再需要逐字节加载数据,从而释放出大量的处理资源,CPU可以专注于其他任务。此外,DMA能够快速搬移大块数据,避免了CPU数据加载和处理的瓶颈,大幅度提高了传输速度。综上,FCE结合DMA的CRC计算可以减小CPU资源消耗、减小传输延迟、提高传输速度。
3. 实施细节与DTC置出
根据*MC-ISAR_TC3xx_UM_Dma.pdf,MC-ISAR_TC3xx_UM_Crc.pdf,*的等Infenion提供的文档进行EB Treos中Crc, DMA模块配置。在达芬奇中进行自己定义的DMA通道的中断函数,同时修改该中断函数优先级(增加),需要在UDE调试工具中查看**Dma_ChInterruptHandler是否被调用。**且如果Crc.c中没有Crc_DmaCalculateCRC32,即DMA相关函数,在Infenioin中将相关函数Copy到Vector公司当下Crc.c模块下。
由于DMA每次只能搬运16K的数据,且数据需要4byte对齐所以在数据传输时需要将数据分块传输,且需要等待DMA中断触发后进行下一次分块的传输,建议代码中加入以下代码等待DMA Channel 释放,否则只能将第一块数据搬运,后续搬运会显示CRC_BUSY。导致计算CRC结果不完整,置出ROM ERROR DTC。
while (!memt_data.is_transfer_complete)
{
memt_data.DEvent = Dma_GetEvents(13U);
}
if (memt_data.is_first_run_checksum == TRUE)
{
len = APP_APPLICATION_END_ADDR - APP_APPLICATION_START_ADDR + 1uL;
/* Partition calculation to adapt to the maximum transfer byte
of DMA (CRC_DMA_MAXLENGTH) */
memt_data.remaining_length = len;
memt_data.crc_result = MEMT_CRC_START_VAL;
memt_data.is_first_run_checksum = TRUE;
memt_data.current_address = (uint8 *)APP_APPLICATION_START_ADDR;
}
while (memt_data.remaining_length > 0)
{
memt_data.chunk_size = (memt_data.remaining_length >
CRC_DMA_MAXLENGTH_ALIGNED)
? CRC_DMA_MAXLENGTH_ALIGNED
: ((memt_data.remaining_length / 4) * 4);
memt_data.test_flag = Crc_DmaCalculateCRC32(memt_data.current_address,
memt_data.chunk_size, memt_data.crc_result, memt_data.is_first_crc_result);
while (!memt_data.is_transfer_complete)
{
memt_data.DEvent = Dma_GetEvents(13U);
}
memt_data.crc_result = memt_data.app_checksum_value; // KEY change:onlyyyy...
memt_data.remaining_length -= memt_data.chunk_size;
memt_data.current_address += memt_data.chunk_size;
memt_data.is_first_crc_result = FALSE;
memt_data.is_transfer_complete = FALSE; /* Only open when triggering ISR interrupt. */
由于分块传输,所以将要计算的APP起始地址、每次传输的块以及剩余APP长度设置为全局变量。等待While循环结束后进行大小端转换。
需要注意,Crc_DmaCalculateCRC32是不直接返回CRC Value的,它是由DMA 中断函数在数据传输完成后调用的回调函数来返回的,这个函数用户自己定义即可,如下图所示。
/* This function will call automaticly by pointer.
Called by [Crc_DmaTransferIsr] defined in Crc.c. */
void Mem_CrcNofitCore0(uint32 res)
{
memt_data.is_transfer_complete = TRUE;
// is_call_times += 1;
memt_data.app_checksum_value = res;
return res;
};
DTC置出
上位机刷写app.hex无ROM Error DTC
ROM Error DTC置出—-修改hexview checksum值
4. 其他
优先级配置
Os_Hal_Cat1InterruptEntry(0, 76, ISR_DMACH12SR)
Os_Hal_Cat1InterruptEntry(0, 68, ISR_DMACH13SR)