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.

For all the C guys out there. Need pointer advice.

I'm trying to calculate the CRC of my flash memory.  I'm trying to start on address 0x3F7FFF but I'm going off into the weeds. I want buf to equal 0x3F7FFF so that *buf = the data at 0x3F7FFF but the way I have it, *buf = 0x3F7FF. I'm certain it's a pointer issue. Here's the code below. How do I get *buf to be the data @ 0x3F7FFF?

Thanks,

Rick

 

unsigned short crc16(Uint32*, Uint32);

 

unsigned short CRC;

Uint32 Flash = 0x3F7FFF;

Uint32 *FlashAddr;

FlashAddr = &Flash;

CRC = crc16(FlashAddr, 0x3FFF);

 

// crc16

unsigned short crc16(Uint32 *buf, Uint32 len ) {

unsigned short crc = 0;

while( len-- ) {

int i;

     crc ^= *buf++ << 8;

     for( i = 0; i < 8; ++i ) {

          if( crc & 0x8000 )

          crc = (crc << 1) ^ 0x1021;

          else

          crc = crc << 1;

          }

     }

return crc;

}

  • What is the address of the variable Uint32 Flash?  I would find it very coincidental that the variable Flash resides at address 0x3F7FF, but please check this.

    The reason I ask is that I interpret the following statement you have :

    FlashAddr = &Flash ;

    as assigning the address of the variable Flash to the contents of FlashAddr rather than the value pointed to by contents of the variable Flash.

    I would have used :

    FlashAddr = 0x3F7FFFF ;

  • Exactly what I discovered.  I know I'm doing the pointer wrong and *FlashAddr = 0x3F7FFF when I want FlashAddr = 0x3F7FFF.  However, when I try to put in FlashAddr = 0x3F7FFF, I get a complaint from the compiler that I can't load a long into a pointer.

    When I make FlashAddr an int32 (rather than a pointer), make FlashAddr = 03F7FFF, and fix the function calls the compiler complains that that "operand of * must be a pointer" on this line of the function:

    crc ^= *buf++ << 8;

    If I don't fix the function calls (leave them as pointers) the compiler complains that "Uint32 is incompatible with Uint32 *" referring to the calling function:

    CRC = crc16(FlashAddr, 0x3FFF);

     

  • You could cast FlashAddr during the function call, as in :

    CRC = crc16((Uint32 *)FlashAddr, 0x3FFF) ;

  • I think I've got it but I'm not sure.  At least I no longer have a random number generator.  Here is what I have now: 

    1321.CRC.txt
    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    unsigned short crc16(Uint32*, Uint16);
    // Global variables
    unsigned short CRC;
    Uint32 Flash = 0x3F7FFF;
    Uint32 *FlashAddr;
    main()
    {
    FlashAddr = &Flash;
    CRC = crc16(FlashAddr, 0x3FFD);
    Fail(); // Just so I stop after the calculation.
    }
    unsigned short crc16(Uint32 *buf, Uint16 len )
    {
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    I realize it's a little convoluted but I got the same results when I used the casting.  I'll clean it up and cast it later as soon as I solve the last problem.  I get the same CRC each time unless I recompile.  Then I get a new CRC that stays the same each time until I recompile again.  Is there something that happens in flash (so far I'm still running out of ram) that might change it?

     

    P.S. I'm having trouble copying and pasting code into E2E.

  • I think you should just cast the constant when you assign it like this

    Uinit32* flash_addr = (Uint32*)0x3F7FFF;

    Then the type checking should all work out.

    Jim Noxon

     

  • There is nothing inherent in flash that should change from compile to compile, unless something in your application is actually allocated to a region of memory in flash.  Although you have not stated this specifically, I assume you are using a C2000 device.

    Take a look at the map file that can be generated from the code generation tools.  This will indicate where variables, functions, etc. are linked to and will give you an idea if something is being allocated to flash which might change from compile to compile.

  • The code in your attachment "1321.CRC.txt" is doing the calculation on undefined memory.

    Uint32 Flash = 0x3F7FFF;
    Uint32 *FlashAddr;
    FlashAddr = &Flash;


    This means the variable FlashAddr will contain the address of the variable Flash. Not the contents of the variable Flash. The calculation will start at the address of the variable Flash and proceed for 0x3FFD x 4 bytes. A lot of undefined memory.

    Jim's suggestion is the usually way of assigning an arbitary address to a pointer variable, eg.

    Uinit32* flash_addr = (Uint32*)0x3F7FFF;

    Typically, usually #define macros are used for address constants.

    #define FLASH_BASE ((Uint32*)0x3F7FFF)
    #define FLASH_SIZE 0x3FFD
    CRC = crc16(FLASH_BASE, FLASH_SIZE);


    Another way would be define the address in the linker and reference it externally defined:

    extern unsigned char flash_begin[];
    extern unsigned char flash_end[];
    CRC = crc16(flash_begin, flash_end-flash_begin);

    I am not sure what processor you are using but you are using an odd address for your pointer to Uint32. Usually 32 bit integers are aligned to the nearest even 4 byte address. An address such as 0x3F7FFF would be 0x3F7FFC or 0x3F80000 depending on your intent.

    Also the auto-increment in your CRC calc is bit difficult to predict. Auto-increment on a Uint32 pointer will move the address by 4.  Auto-increment on a Uint16 pointer will move the address by 2. You may be CRC'ing every 2nd or 4th byte. Your CRC algorithm is for a Big Endian processor and should be done one 8 bit byte at a time, Assumes the usual sizes for types. DSPs such as the C5000 series have unconventions sizes for char, int, long.

  • Thanks Norman,

    I spent a lot of time going back and forth on the code and by the time I posted my message, my ending address had become my starting address.  I figured this out Friday (hey, I'm a hardware engineer).  I also figured out that the code wasn't incrementing the address (it does now).  My last item to fix will be why my data is 0x4000 when I should be seeing 0xFFFF in the memory.  I'll work on this today.

    The original code for CRC was pulled off the internet because I had never used CRC before.  The processor I'm using is the SM320F2808.