This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TMS570LS3137: CRC with Auto Mode utilizing DMA

Part Number: TMS570LS3137

Hi,

In my bootloader I want to utilize embedded CRC Controller to calculate the CRC of the application image before jumping to it.

I think Auto mode with DMA would be fastest.

could TI provide sample code calculating single CRC of a large flash region? (let's say the application image is larger than 1 MB)

I want to produce single CRC, not multiple for every 1Kb etc.

thank you in advance

  • Hello,

    Yes, you can use AUTO mode to check the CRC in the background of CPU. You don't have to perform the CRC calculation and checking every 1KByte.

    Program the PCOUNT to 1MBytes and SCOUNT to 1. I will write an example for you.
  • thank you, looking forward to the example.
  • Hi,

    in the following URL www.ti.com/.../spna235, the file CRC64_calc.c and function calc_crc64() works on 64-bit data.

    let's say the size of the application image is NOT multiple of 8, let's say "app_size mode 8 = 4". how do I include the remaining 4 bytes into CRC calculation? I am asking about the second case below.

    1- app_size = 800 bytes => calc_crc64(100)
    2- app_size = 804 bytes => calc_crc64(100), but what about 4 bytes leftover?

    thanks,
  • Hello,

    This is a example:

    /* USER CODE BEGIN (2) */
    #define FRAME_COUNT 4096
    #define ELEMENT_COUNT 32 /*64-bit double-word*/

    g_dmaCTRL dma_config; // dma control packet configuration stack

    /* USER CODE END */

    int main(void)
    {
    /* USER CODE BEGIN (3) */
    /*clear the ESM error manually*/
    esmREG->SR1[2] = 0x00000008U;
    esmREG->SSR2 = 0x00000008U;
    esmREG->EKR = 0x0000000A;
    esmREG->EKR = 0x00000005;

    _enable_IRQ();

    crcInit();
    crcREG1->PCOUNT_REG1 = FRAME_COUNT * ELEMENT_COUNT; /* 4096*32 doublewords, 1MBytes */
    crcREG1->SCOUNT_REG1 = 1;
    crcEnableNotification(crcREG1,1);

    dmaEnable();

    dma_config.SADD = 0x00020000; /*application starting address*/
    dma_config.DADD = (uint32_t)&(crcREG1->PSA_SIGREGL1);
    dma_config.CHCTRL = 0;
    dma_config.FRCNT = FRAME_COUNT;
    dma_config.ELCNT = ELEMENT_COUNT;

    dma_config.ELDOFFSET = 0;
    dma_config.ELSOFFSET = 0;
    dma_config.FRDOFFSET = 0;
    dma_config.FRSOFFSET = 0;
    dma_config.PORTASGN = 1;
    dma_config.RDSIZE = ACCESS_64_BIT;
    dma_config.WRSIZE = ACCESS_64_BIT;
    dma_config.TTYPE = BLOCK_TRANSFER;
    dma_config.ADDMODERD = ADDR_INC1;
    dma_config.ADDMODEWR = ADDR_FIXED;
    dma_config.AUTOINIT = AUTOINIT_OFF;

    // setting dma control packets for receive
    dmaSetCtrlPacket(DMA_CH0, dma_config);
    dmaSetChEnable(0,DMA_SW);

    while(1);
    /* USER CODE END */

    return 0;
    }
  • From the example, if the leftover is less than 8 bytes, zeros will be appended.
  • Thank you QJ.

    I decided to go with Semi-CPU mode . Odd thing is that the first time I calculate CRC , PSA_SECSIGREGL1/H1 are 0x0 and some value stored in PSA_SIGREGL1/H1. However on subsequent calculations, PSA_SIGREGL1/H1 are 0x0, and PSA_SECSIGREGL1/H1 have the value I observed in PSA_SECSIGREGL1/H1 after calculatingCRC for the first time.

    In Semi-CPU mode, I know I should read PSA_SECSIGREGL1/H1 to get the CRC value.

    No idea why CRC value is stored in PSA_SIGREGL1/H1 for the first CRC calculation?

    here is what I got:

    int main()

    {

    ..

    rtiInit();

    sciInit();

    /** - configuring crc  */

    crcInit();

    sciEnableNotification ( sciREG, SCI_RX_INT         );

    sciEnableNotification ( sciREG, SCI_TX_INT         );

    rtiEnableNotification ( rtiNOTIFICATION_COMPARE0   );

    _enable_IRQ();

    ..

    crc_tms570(start_address, size); 

    // PSA_SECSIGREGL1/H1 are 0x0 and some value stored in PSA_SIGREGL1/H1, let's say X and Y

    crc_tms570(start_address, size);

    // PSA_SIGREGL1/H1 are 0x0, and PSA_SECSIGREGL1/H1 have X and Y

     

    crc_tms570(start_address, size);

    // PSA_SIGREGL1/H1 are 0x0, and PSA_SECSIGREGL1/H1 have X and Y

    }

    uint64_t crc_tms570(uint32_t start_address, uint32_t size)
    {
    volatile uint32_t counter = 0;
    uint32_t Pcount = size / 8;
    /** - Setup the Channel mode */
    crcREG->CTRL2=0x00000000;
    crcREG->CTRL2 |= (CRC_SEMI_CPU);

    dmaEnable();

    crcREG->CTRL2 &=0xFFFFFFFCU;
    crcREG->CTRL2 |= CRC_SEMI_CPU;
    crcREG->PCOUNT_REG1 = Pcount;
    crcREG->SCOUNT_REG1 = 1;

    crcChannelReset(crcREG, 0);

    /* - assigning dma request: channel-0 with request line - 26 */
    dmaReqAssign(DMA_CH0, 26 );
    /* - configuring dma control packets */
    dmaConfigCtrlPacket(start_address, (uint32_t)(&(crcREG->PSA_SIGREGL1)), Pcount, ADDR_INC1, ADDR_FIXED, AUTOINIT_ON);
    /* - setting dma control packets */
    dmaSetCtrlPacket(DMA_CH0, g_dmaCTRLPKT);
    /* - setting the dma channel to trigger on s/w request */
    dmaSetChEnable(DMA_CH0, DMA_SW);

    while ((crcREG->BUSY & 0x1))
    {
    counter++;
    if ((counter % 0x20000) == 0)
    {
    dwdReset();
    }
    }

    dmaDisable();
    // at first call to this crc_tms570(), PSA_SECSIGREGL1/H1 are 0x0 and some value stored in PSA_SIGREGL1/H1
    uint64_t crc_actual = (((uint64)crcREG->PSA_SIGREGL1 << 32U) | (uint64)crcREG->PSA_SIGREGH1);
    // however on subsequent calls to this crc_tms570(), PSA_SIGREGL1/H1 are 0x0, and PSA_SECSIGREGL1/H1 have some value
    // PSA_SECSIGREGL1/H1 should store CRC value no matter first or latter calls
    // so, why are CRC values stored in PSA_SIGREGL1/H1 for the first CRC calculation
    //uint64_t crc_actual = (((uint64)crcREG->PSA_SECSIGREGL1 << 32U) | (uint64)crcREG->PSA_SECSIGREGH1);
    return crc_actual; 
    }

  • Hello,

    You are right, in semi-CPU mode, the CPU should read from the PSA sector signature register instead of reading from PSA signature register.

    In Semi-CPU mode, when one sector of data patterns is compressed, CRC controller generates a compression complete interrupt. The signature stored at the PSA Signature Register is copied to the PSA Sector Signature Register and PSA Signature Register is then cleared out to all zeros.

    The value in PSA sector signature register should be read in the ISR of compression complete interrupt. Before that, the PSA_SECSIGREG is not updated.
  • Hi,

    I see "BAD0BAD0" pattern on all CRC related registers on some certain cases. And the CCS debugging session becomes unrespons've.
    I am trying Semi-CPU mode.
    What would be causing CRC registers to have this "BAD0BAD0" pattern?

    thanks,
  • Hello,

    The device loses the JTAG connection, or the CRC module is disabled. The CCS is not able to read the content of the CRC registers.
  • It looks like the device is going through a system reset. Can you probe the nRST pin to see if it goes low when this happens?

  • I don;t see the "BAD0BAD0" pattern any more. however CRc complete interrupt  does not fire sometimes. Could you please review the function  below? Not sure what I am doing wrong?

    int main()
    {.....
    crcInit();
    enableCRCNotification(CrcREG, CRC_CH1_CC);

    ......}

    static uint64_t crc_64(uint32_t start_address, uint32_t size)
    {
    uint32_t Pcount = size / 8;

    /** - Setup the Channel mode */
    crcREG->CTRL2=0x00000000;
    crcREG->CTRL2 |= (CRC_SEMI_CPU);

    dmaEnable();

    crcREG->CTRL2 &=0xFFFFFFFCU; // ch 0
    crcREG->CTRL2 |= CRC_SEMI_CPU;
    crcREG->PCOUNT_REG1 = Pcount;
    crcREG->SCOUNT_REG1 = 1;

    crcChannelReset(crcREG, 0);

    /* - assigning dma request: channel-0 with request line - 26 */
    dmaReqAssign(DMA_CH0, 26 );
    /* - configuring dma control packets */
    dmaConfigCtrlPacket(start_address, (uint32_t)(&(crcREG->PSA_SIGREGL1)), Pcount, ADDR_INC1, ADDR_FIXED, AUTOINIT_OFF);
    /* - setting dma control packets */
    dmaSetCtrlPacket(DMA_CH0, g_dmaCTRLPKT);
    /* - setting the dma channel to trigger on s/w request */
    dmaSetChEnable(DMA_CH0, DMA_SW);

    while ((dmaREG->GCTRL & (1 << 14)) && (crcREG->BUSY & 0x1));

    dmaDisable();

    uint64_t crc = crcGetSectorSig(crcREG, 0);
    /* Clear CH1_CCIT bit */
    crcREG->STATUS = CRC_CH1_CC;
    return crc;
    }

    static void dmaConfigCtrlPacket(uint32_t sadd,uint32_t dadd,uint32_t dsize,uint8_t ADD_RD_MODE,uint8_t ADD_WR_MODE,uint8_t AIM)
    {
    g_dmaCTRLPKT.SADD = sadd; /* source address */
    g_dmaCTRLPKT.DADD = dadd; /* destination address */
    g_dmaCTRLPKT.CHCTRL = 0; /* channel control */
    g_dmaCTRLPKT.FRCNT = 1; /* frame count */
    g_dmaCTRLPKT.ELCNT = dsize; /* element count */
    g_dmaCTRLPKT.ELDOFFSET = 0; /* element destination offset */
    g_dmaCTRLPKT.ELSOFFSET = 0; /* element destination offset */
    g_dmaCTRLPKT.FRDOFFSET = 0; /* frame destination offset */
    g_dmaCTRLPKT.FRSOFFSET = 0; /* frame destination offset */
    g_dmaCTRLPKT.PORTASGN = 4; /* port b */
    g_dmaCTRLPKT.RDSIZE = ACCESS_64_BIT; /* read size */
    g_dmaCTRLPKT.WRSIZE = ACCESS_64_BIT; /* write size */
    g_dmaCTRLPKT.TTYPE = BLOCK_TRANSFER ; /* transfer type */
    g_dmaCTRLPKT.ADDMODERD = ADD_RD_MODE; /* address mode read */
    g_dmaCTRLPKT.ADDMODEWR = ADD_WR_MODE; /* address mode write */
    g_dmaCTRLPKT.AUTOINIT = AIM; /* autoinit */
    }

  • Hello,

    I don't see the problem in your code.
  • What I have observed further:

    crcREG->SCOUNT_REG1 = 1;

    crcREG->Pcount <= 0x0FFF8 / 8 (65528 /8) -----> CRC isin sector signature register and correct

    crcREG->Pcount > =(0x10000 / 8) (65536 /8) ----> sector signature register is 0

    I want to calculate CRC of , let's say 1MB of data. Sector count of 1 and pattern count of (1MB /8). But my observation tells me that I am stuck to pattern count of (65528 /8).
    TRM tells me that 20 bits are designated for pattern count , so I should be able to assign (1MB/8) to pattern count register and it should work.

    Please help me figure out why CRC calculation works if Pcount is less than or equal to (0x0FFF8 / 8)[ (65528 /8)] ?

    And how could I achieve my goal of single CRC for at least 1MB of data [1 sector and pcount of at least (1MB/8)]?

    thank you in advance,
  • Hello,

    The maximum frame count for DMA transfer is 0x1FFF. If the frame count and element count are in the valid range, the CRC calculation works.

  • Hello,

    You can use PCOUNT=1MByte/8, FCOUNT=0xFFF8/8, and ECOUNT=PCOUNT/FCOUNT.