Hardware CRC calculation for data in TC23x

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
Not applicable
Hello All,

Is there any specific register which will do the Hardware CRC calculation for the input data provided in TC 234 micro?Please suggest.
0 Likes
4 Replies
µC_Wrangler
Employee
Employee
50 solutions authored 100 sign-ins 25 likes received
The TC234 doesn't have the Flexible CRC Engine, but it does have the CRC32 instruction, and the CRC32 used by the DMA engine. Here's some sample code that calculates the CRC32 of 0xA0018000 through 0xA009FFBF, first using the CRC32 instruction, and then using DMA.


/*****************************************************
*
* DMA_CRC32.c
*
* Description : This program uses the AURIX DMA peripheral to calculate the CRC-32 over a range of memory.
* - DMA linked lists minimize CPU overhead.
* - Block transfers (BLKM) are used to handle over 512K in a single transaction.
* - The second transaction handles the remainder memory range.
* - The DMA completion service request is routed to a CPU interrupt.
*/

#include
#include "platform_types.h"
#include "Ifx_reg.h"

#define DMA_CHANNEL_CRC32 (0)
#define ISR_PRIORITY_1 (1U)

const Ifx_DMA *dmaSFR = &MODULE_DMA;

extern const Ifx_DMA_CH CRC32_SCAN;
extern const Ifx_DMA_CH CRC32_SCAN_A009FFC0;
extern const Ifx_DMA_CH CRC32_DONE;
extern const Ifx_DMA_CH CRC32_FINISH;

volatile uint32 dummy_word;

volatile uint32 dma_done = 0;

#pragma align 32

// *** Scan starts at 0xA0018000 ***
// Do as much as possible in one DMA move, and then handle the remainder in a second move
// move 0x10 times per transfer
// times 4 bytes each
// times 0x21FF transfers
// 0x10 * 4 * 0x21FF = 0x87FC0 bytes
// A0018000, fill 0x87FC0 bytes = A0018000-A009FFBF

const Ifx_DMA_CH CRC32_SCAN =
{
.SADR.U = (uint32) 0xA0018000, // read application memory
.DADR.U = (uint32) &dummy_word, // write into dummy word

.ADICR.B.SHCT = 0xD, // DMA accumulated linked list
.ADICR.B.INCS = 1, // Increment source after each transfer
.ADICR.B.DCBE = 1, // Enable destination circular buffer (won't change destination since CBLD=0)

.CHCFGR.B.TREL = 0x21FF,// Transfer reload
.CHCFGR.B.CHDW = 2U, // 32-bit transfer
.CHCFGR.B.BLKM = 4, // each transfer has 16 DMA moves
.CHCFGR.B.RROAT = 1, // Reset TSRz after DMA transaction (not single transfer)

.CHCSR.B.SCH = 1, // Set transaction request to start immediately

.SHADR.U = (uint32) &CRC32_SCAN_A009FFC0,
};

// Handle the remainder in a second DMA move

const Ifx_DMA_CH CRC32_SCAN_A009FFC0 =
{
.SADR.U = (uint32) 0xA009FFC0, // read application memory
.DADR.U = (uint32) &dummy_word, // write into dummy word

.ADICR.B.SHCT = 0xD, // DMA accumulated linked list
.ADICR.B.INCS = 1, // Increment source after each transfer
.ADICR.B.DCBE = 1, // Enable destination circular buffer (won't change destination since CBLD=0)
.ADICR.B.INTCT = 2, // raise service request when finished

.CHCFGR.B.TREL = 15, // Transfer reload
.CHCFGR.B.CHDW = 2U, // 32-bit transfer
.CHCFGR.B.RROAT = 1, // Reset TSRz after DMA transaction (not single transfer)

.CHCSR.B.SCH = 1, // Set transaction request to start immediately

.SHADR.U = (uint32) &CRC32_FINISH,
};

const Ifx_DMA_CH CRC32_FINISH =
{
.SADR.U = (uint32) NULL,
.DADR.U = (uint32) NULL,

.ADICR.B.SHCT = 0xD, // DMA accumulated linked list
.ADICR.B.INCS = 1, // Increment source after each transfer
.ADICR.B.DCBE = 1, // Enable destination circular buffer (won't change destination since CBLD=0)

.CHCFGR.B.TREL = 0,
.CHCFGR.B.CHDW = 2U, // 32-bit transfer

.SHADR.U = (uint32) NULL,
.CHCSR.B.SCH = 0, // TRANSACTION DOES NOT START IMMEDIATELY - end of list
};

#pragma align restore



extern void _endinit_clear( void );
extern void _endinit_set( void );
extern void _safety_endinit_clear( void );
extern void _safety_endinit_set( void );

static void DMA_Start( void );


int main(void)
{
__enable(); // Enable interrupts

DMA_Start();

for( ;; )
{
}
}


void __interrupt(ISR_PRIORITY_1) dma_isr( void )
{
// User code here!
dma_done = 1;
}



static void DMA_Start( void )
{
volatile unsigned int dummy;

_endinit_clear();
DMA_CLC.U = 0x0000; // Enable module clock and ctrl.
dummy = DMA_CLC.U; // Read back ensures buffers are flushed
SRC_DMACH0.B.SRPN = ISR_PRIORITY_1; // Route VADC service request line 0 to ISR priority
SRC_DMACH0.B.TOS = 0; // service control: CPU
SRC_DMACH0.B.SRE = 1; // service request enable
_endinit_set();

// Calculate the CRC32 with the CRC32 instruction (all CPU)
{
uint32 i;
uint32 *src;
uint32 crc=0;
src = (uint32 *) 0xA0018000;
for( i=0; i<556992/4; i++ )
{
crc = __crc32(crc,*src++);
}
P10_OUT.B.P6 = (crc & 1);
}

// Calculate the CRC32 using DMA
// - Set up DMA channel 0
{
uint32 i;
uint32 *src, *dst;

src = (uint32 *)&CRC32_SCAN;
dst = (uint32 *)&MODULE_DMA.CH[DMA_CHANNEL_CRC32];

for (i=0; i<(sizeof(Ifx_DMA_CH)/4); i++) {*dst++ = *src++;}
}

// You could go off and do something more useful instead of just polling for completion
// - dma_done is set by the DMA channel interrupt service routine
//
while( dma_done == 0 )
{
__nop();
__nop();
__nop();
}
}
0 Likes
Not applicable
Hello,

I have been trying to use the FCE from an AURIX TC27x but I havent been able to write to the registers:

As example I am using the following:

Mcal_ResetENDINIT();
FCE_CFG0.U = (T_U32)0x00000740u;
Mcal_SetENDINIT();

Or something like this:

Mcal_ResetSafetyENDINIT_Timed (150000);
FCE_ACCEN0.U = (T_U32)0xF0003FFFu;
Mcal_SetSafetyENDINIT_Timed();

The Mcal is for setting the ENDINIT and I am also confirming that I am in Supervisor mode: CSFR.IO

Interesting is the DMI is showing a SBE, which I think is Store Bus Error?

Any ideas?

Thanks!

Federico
0 Likes
µC_Wrangler
Employee
Employee
50 solutions authored 100 sign-ins 25 likes received
freyes wrote:
I have been trying to use the FCE from an AURIX TC27x but I havent been able to write to the registers

Hello Federico. Have you enabled the FCE peripheral first? Most peripherals are disabled by default. Any attempt to write to a peripheral register where the peripheral is disabled (other than the CLC register) will result in a bus error.

_endinit_clear();
FCE_CLC.U = 0x0000; // Enable module clock and ctrl.
dummy = FCE_CLC.U; // Read back ensures write oper.
_endinit_set();
0 Likes
Not applicable
Thanks for your reply Neal, this actually solved my issue. Another issue I had is that we enable MPU so I had to create a write peripheral call to write to those addresses:

Mcal_ResetENDINIT();
osWritePeripheral32 (FCE_CVN, (vuint32)(&(MODULE_FCE0)), 0x00000002); // MODULE_FCE0.CLC.B.DISR = 0U;
Mcal_SetENDINIT();
0 Likes