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.

TMS570LC4357 Bank 7 Linker Generated ECC

Other Parts Discussed in Thread: TMDX570LC43HDK

Hi,

I'm using Bank 7 as Flash data storage and not using FEE driver.

I have some const data which is located in Bank7, this uses the linker script to assign the Flash location of the const data and calculate the ECC.

Attached is an example BlinkyNV project to demonstrate the issue, the const data is a string "Some Stuff to Store in NV".

When the project is programmed into a TMDX570LC43HDK the const data appears correct at the beginning of flash Bank 7 like this

The associated ECC looks like this (looking at the first 4 bytes)

When the example try's to read the const data the Error LED turns on, this shouldn't happen because the ECC should be correct from the linker.

If the sector is erased using the F021 API and the data written back to the same location with auto generate ECC the data is identical to above and looks like this

but the the associated ECC looks like this

As you can see the Auto generated ECC (first 4 bytes) is different from the Linker generated ECC

Resetting the project any subsequent reads of the const data don't cause the Error LED to turn on so the ECC must be correct.

Can you please help explain why there appears to be a problem with the Linker generated ECC for Bank 7.

Kind regards,

Stu

0412.rtiBlinkyNV.zip

  • Hi Stu,

    I can recreate the ECC calculation done by auto-ecc but in the process had to 're-learn' the fact that the flash array on this particular part is natively be-8 or le (not sure which exactly).

    Anyway the calculation has some byte-swapping in it that is different than the calculation on the TCM parts and is not readily apparent from the TRM.

    This C program does the calculation and gives the 2nd result:

    // Win32Project1.cpp : Defines the entry point for the console application.
    //
    
    #include "stdafx.h"
    
    unsigned int eccdat[] = { 0x1FC0007F, 0x00FFFF00, 0xFF0000FF,
    					      0x003FFF80, 0xFF0000FF, 0xFF0000FF,
    					      0x1FC07F80, 0xFF00FF00, 0xFF00FF00,
    					      0x0FC19F83, 0xC0FCC0FC, 0xC0FCC0FC,
    					      0x13C6A78D, 0x38E338E3, 0x38E338E3,
    					      0x14DAA9B5, 0xA699A699, 0xA699A699,
    					      0x1D68BAD1, 0x15571557, 0x15571557,
    					      0x0A7554EA, 0xB4D1B4D1, 0x4B2E4B2E };
    
    unsigned int byteswap(unsigned int val) {
    	unsigned int retval;
    	retval = ((val & 0x000000FF) << 24);
    	retval = retval | ((val & 0x0000FF00) << 8);
    	retval = retval | ((val & 0x00FF0000) >> 8);
    	retval = retval | ((val & 0xFF000000) >> 24);
    	return retval;
    }
    
    int main()
    {
    
    	int i, j, k;
    
    	unsigned int w1, w2, w3, w4, w5, r;
    
    	unsigned int a1[] = { 0xF0200000, 0xF0200008, 0xF0200010, 0xF0200018 };
    	unsigned int d1[] = { 0x536F6D65, 0x66662074, 0x6F726520, 0x56000000 };
    	unsigned int d2[] = { 0x20537475, 0x6F205374, 0x696E204E, 0x00000000 };
    
    	unsigned int am = 0xfffffff8;
    
    
    	for (k = 0; k < 4; k++)
    	{
    		r = 0;
    
    		for (i = 0; i < 8; i++) {
    			w1 = (eccdat[3 * i + 0]);
    			w2 = (eccdat[3 * i + 1]);
    			w3 = (eccdat[3 * i + 2]);
    
    			w1 = w1 << 3;
    			w1 = w1 & a1[k] & am;
    
    			w2 = w2 & byteswap(d2[k]);
    			w3 = w3 & byteswap(d1[k]);
    
    			w4 = 0;
    			w5 = 0x80000000;
    
    			for (j = 0; j < 32; j++)
    			{
    				if ((w5 & w1) != 0)
    				{
    					w4 = w4 ^ 0x01;
    				}
    				if ((w5 & w2) != 0)
    				{
    					w4 = w4 ^ 0x01;
    				}
    				if ((w5 & w3) != 0)
    				{
    					w4 = w4 ^ 0x01;
    				}
    				w5 = w5 >> 1;
    			}
    
    			r = (r << 1) + w4;
    
    		}
    
    		r = r ^ 0x0c;
    
    		printf("res = 0x%x\n", r);
    
    	}
        return 0;
    }
    

    Yields

    I need to look now into what's going on in the compiler/linker.  It may be a setting that needs to be different or may be an issue we need to file a bug report on.  Not sure yet.

    Best Regards,
    Anthony

  • I also rebuilt your project and can get the same result when using linker ECC.

    Only doubt I haven now is whether the problem is in the file or in the loader. I haven't been able to use the objdump or armdis utility to dump the contents of the .out file and actually show the data section at 0xF0200000 or the .ecc3 at 0xF0100000 yet. not sure why.
  • Ok that was my mistake - there was a file "rtiBlinky.out" in the folder and I kept hitting it w. command completion instead of 'rtiBlinkyNV.out'.

    When I disassemble NV.out,  I can see that the ecc values are wrong in the disassembly of the .out file.

    So it's an issue now either with the linker or the linker command file ..  I'll have to check that there isn't some missing switch or option needed.

    But, I have tried the C program above implementing the TRM algorithm and none of the combinations of 'mistakes' in endian are coming up w. the values below so I am thinking some other issue may be at play.

  • Ok actually I can reproduce the linker results if I take my program and change the address mask
    from:
    unsigned int am = 0xfffffff8;
    to:
    unsigned int am = 0x00fffff8;

    So I am fairly certain this is a bug in the linker now. This LC4357 takes more address lines into account than the previous generation for better protection - and probably the linker didn't comprehend all of the upper bits.... Many times bank 7 is left erased for FEE use - so it makes some sense for this issue to have escaped for so long.

    EDIT:  Filed a bug report on the linker:  SDSCM00052814

    I would be confident in the ECC computed on the lower banks.   Just the addresses with non-zero upper 8 or 16 bits of address are likely an issue.

  • Thanks Anthony, glad you can replicate the issue and validate it in your calculation.

    As this appears to be a bug in the linker I bet I can't define a separate ECC algorithm in the linker script with a different mask for the Bank 7 ECC as a work around until the linker is fixed can I?
  • Hi Anthony,

    How can I track the progress of bug SDSCM00052814? If I search for it on the compiler defect databases is can't be found.
    Do you have an general idea of time it normally takes for a Linker bug to be fixed and released?

    Thanks,
    Stu
  • Hi Stu,

    It's not yet been accepted by the compiler team. They have to accept it and turn on a flag to make it visible.
    It should show up in a matter of time.

    I don't know how long it will take to get this fixed. At this point - I would probably suggest opening a thread on the Compiler forum asking for the disposition and timing of a resolution to SDSCM00052814.

    Thanks and Best Regards,
    Anthony
  • This ECC algorithm was not part of the specification that the compiler team used to develop the linker ECC implementation.  This new algorithm must be considered a change in the specification, and thus an enhancement request.  SDSCM00052814 will be changed to an enhancement request and will go through those channels.

    There is a backdoor in the implementation that you can use to realize this new algorithm.  Use this algorithm specification:

    ECC {
    algo_name : address_mask = 0xffffffff
                hamming_mask = /* address */
                               0x53aaa750, 0xeb45d688,
                               0xa6d54da8, 0x9e353c68,
                               0x7e0cfc18, 0xfe03fc00,
                               0x01fffc00, 0xfe0003f8,
                               /* upper */
                               0x2E4B2E4B, 0x57155715,
                               0x99A699A6, 0xE338E338,
                               0xFCC0FCC0, 0x00FF00FF,
                               0xFF0000FF, 0xFF0000FF,
                               /* lower */
                               0xD1B4D1B4, 0x57155715,
                               0x99A699A6, 0xE338E338,
                               0xFCC0FCC0, 0x00FF00FF,
                               0xFF0000FF, 0x00FFFF00,
                parity_mask = 0x0c
                mirroring = F021
    }
    

    If you value your sanity, do not ask where the constants come from.