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.

MSP430FR2355: CRC msp hardware issue

Part Number: MSP430FR2355


How do you flush the CRC engine?  It appears that putting 6 bytes of different data through it every 27ms produces the first CRC and then every corresponding CRC after that is the same...

  • I don't see your symptom as described. I hacked up the CRC example to run 6 triplets of data through the CRC unit. The results were all different (except for one duplicate I introduced) and all matched the software-computed CRCs. 

    You probably need to show what you were doing to encounter this.

    //  Started life as msp430fr235x_CRC.c. Edited for brevity.
    #include <msp430.h>
    unsigned int CRC_Init = 0xFFFF;
    unsigned int i, j;
    unsigned success;
    #define CRC_M   6       // 6 rows
    #define CRC_N   3       // 3 cols
    //  These are from the example, but broken up into 5 groups of 3.
    unsigned int CRC_Input[CRC_M][CRC_N]= {
                               0x0fc0, 0x1096, 0x5042,
                               0x0010, 0x7ff7, 0xf86a,
                               0xb58e, 0x7651, 0x8b88,
                               0x0010, 0x7ff7, 0xf86a,  // Duplicate
                               0x0679, 0x0123, 0x9599,
                               0xc58c, 0xd1e2, 0xe144
    };
    unsigned int CRC_Results;
    unsigned int SW_Results;
    unsigned int CRC_New;
    unsigned sw_res[CRC_M], hw_res[CRC_M];
    
    // Software Algorithm Function Definition (down at the bottom)
    unsigned int CCITT_Update(unsigned int, unsigned int);
    
    int main(void)
    {
        WDTCTL = WDTPW | WDTHOLD;               // Stop watchdog timer
        unsigned mask = 0x0001;
        P1OUT &= ~BIT0;                         // Clear P1.0 output state
        P1DIR |= BIT0;                          // Set P1.0 to output direction
        PM5CTL0 &= ~LOCKLPM5;                   // Engage GPIOs
        for(i=0 ; i < CRC_M ; i++)              // 6 test cases
        {
            CRCINIRES = CRC_Init;                   // Init CRC with 0xFFFF
            for (j = 0 ; j < CRC_N ; ++j)
            {
                CRCDIRB = CRC_Input[i][j];         // Input data in CRC
                __no_operation();
            }
            CRC_Results = CRCINIRES;                // Save results (per CRC-CCITT standard)
    
            CRC_New = CRC_Init;                     // Put CRC Init value into CRC_New
            for (j = 0 ; j < CRC_N ; ++j)
            {
                // Input values into Software algorithm (requires 8-bit inputs)
                // Clear upper 8 bits to get lower byte
                unsigned int LowByte = (CRC_Input[i][j] & 0x00FF);
                // Shift right 8 bits to get upper byte
                unsigned int UpByte = (CRC_Input[i][j] >> 8);
                // First input lower byte
                CRC_New = CCITT_Update(CRC_New,LowByte);
                // Then input upper byte
                CRC_New = CCITT_Update(CRC_New,UpByte);
            }
            SW_Results = CRC_New;
    
            // Compare data output results
            if(CRC_Results==SW_Results)             // if data is equal
            {
                P1OUT |= BIT0;                      // set the LED
                success |= mask;                    // Got one right
            }
            else
            {
                P1OUT &= ~BIT0;                     // if not, clear LED
                while (1) /*EMPTY*/;                // Halt on failure
            }
            mask <<= 1;
            sw_res[i] = SW_Results;
            hw_res[i] = CRC_Results;
        }
        while(1);                               // Stall here forever
    }
    
    // Software algorithm - CCITT CRC16 code
    unsigned int CCITT_Update(unsigned int init, unsigned int input)
    {
        unsigned int CCITT;
        CCITT =(unsigned char)(init >> 8)|(init << 8);
        CCITT ^= input;
        CCITT ^= (unsigned char)(CCITT & 0xFF) >> 4;
        CCITT ^= (CCITT << 8) << 4;
        CCITT ^= ((CCITT & 0xFF) << 4) << 1;
        return CCITT;
    }
    

  • Well I'll do my best to show....Lots of code so I will taylor it down in the hopes you may see something.  In short mssg[8]....The code sends out four 8 byte blocks....One every ~27ms....I see these 4 distinct groups on the logic analyzer....I also see P5OUT bits 1 toggling about 2us after each case statement is entered and lasting for about 7.5us before returning high (5.1 is entry and exit out of CRC)....the first CRC I see on the logic analyzer is unique, however the next three CRCs on the next 3 UNIQUE patterns are the same....This second CRC is different from the first block of 8.  Essentially it seems as if the data going through the CRC for group 2-4 is the same yet my logic analyzer and the debugger (when I break it appropriately) show that all the packets are unique.  Now one caveat that I did just notice and haven't put my finger on is that I see entry and exit 5x in/out of CRC module

    some defn:

        pTx = mssg;
        pRx = incoming;
        pSysID = systemID;
        mssg[0] = (permanent_Info[0]);
        mssg[1] = (permanent_Info[1]);
        mssg[2] = (permanent_Info[2]);
        mssg[3] = (permanent_Info[3]);
    

    Here is code:

    
    
                if (!swInfo.err && (swInfo.twoSec & 0x0080)) {
                    if (!flag) {
                        p_Seq = systemIdentification(systemID);
                        flag = T;
                    }
                    switch (i) {
                    case 0:
                        P5OUT ^= BIT0;
                        mssg[4] = (0xC0);
                        mssg[5] = *p_Seq;
                        break;
                    case 1:
                        P5OUT ^= BIT0;
                        mssg[4] = (0xA0);
                        mssg[5] = *(p_Seq + 1);
                        break;
                    case 2:
                        P5OUT ^= BIT0;
                        mssg[4] = (0x90);
                        mssg[5] = *(p_Seq + 2);
                        break;
                    case 3:
                        P5OUT ^= BIT0;
                        mssg[4] = (0x88);
                        mssg[5] = *(p_Seq + 3);
                        break;
                    default : break;
                    }
                    i++;
                    CRC_Result = CRC(pTx);
                    mssg[6] = (char)((CRC_Result >> 8) & 0xFF);
                    mssg[7] = (char)(CRC_Result & 0xFF);
                    volumeButtonReleased = 3;
                }
            }
    
            if (!radioBusy) {
                if ((volumeButtonReleased == 3)) {
                    if (i <= 4) {
                        pTx = mssg;
                        UCA1IE |= UCTXIE;  //send out message
                        __bis_SR_register(LPM3_bits);
                    }
                    else {
                        UCA1IE &= ~UCTXIE;
                        i = 0;
                        pTx = mssg;
                        currentSwState = 0;
                        swInfo.anySw = F;
                        swInfo.err = F;
                        swInfo.twoSec = 0;
                        memset(swInfo.hits, 0, sizeof(swInfo.hits));
                        mssgPopulated = F;
                        volumeButtonReleased = 0;
                        P2IFG &= ~0x06;
                        P1IFG &= ~0xFE;
                    }
                }
            }
    

    Here is the CRC function:

    unsigned int CRC (char *payload) {
        unsigned int CRC_Result;
        unsigned int i, k;
        const unsigned int CRC_Init = 0xFFFF;
        P5OUT &= ~BIT1;
        CRCINIRES = CRC_Init;
        for(i=0; i<PAYLOAD_SIZE ;i+=2)
        {
          k = (*(payload + i)<<8) | *(payload + (i+1));
          CRCDIRB = k; //input data into CRC
          __no_operation();
        }
        CRC_Result = CRCINIRES;
        P5OUT |= BIT1;
        return CRC_Result;
    }
    

  • >        CRC_Result = CRC(pTx); 

    As I recall, pTx is a walking pointer. After walking through each packet, it probably points to the end of the packet -- random but probably static data. Try:

    >        CRC_Result = CRC(mssg);
     
  • pTx isn't a walking pointer....A breakpoint at VolumeButtonReleased shows pointer aligns with mssg and all data except the CRC look good....Not sure what it means yet but it is very telling that packet 1 always returns a unique pattern BUT packet 2 - 4 ALWAYS returns 0x0E10....this either clearly points to static data being used (although I am inclined to not think so as the mssg and pointer look good) OR the code I am using for the function is bad somehow....Can you see anything that stands out with this function :

    PAYLOAD SIZE is 6 -- after CRC produces 2 bytes the mssg becomes 8 bytes....Am I doing anything wrong with type casting or concatenation?

    unsigned int CRC (char *payload) {
        unsigned int CRC_Result;
        unsigned int i, k;
        const unsigned int CRC_Init = 0xFFFF;
        P5OUT &= ~BIT1;
        CRCINIRES = CRC_Init;
        for(i=0; i<PAYLOAD_SIZE ;i+=2)
        {
          k = (*(payload + i)<<8) | *(payload + (i+1));
          CRCDIRB = k; //input data into CRC
          __no_operation();
        }
        CRC_Result = CRCINIRES;
        P5OUT |= BIT1;
        return CRC_Result;
    }
    

  • What does pTx look like the second time you call CRC()? I'm guessing it points to &mssg[6]. (Otherwise you wouldn't have a need to refresh it before sending the packet.)

  • Bruce...

    After carefully looking at what you said....short answer ....You were right!!!  Thank you!  My tx isr increments ptx then breaks after the mssg hits ptx + 7....i don't reset it until I get into the (i <= 4) statement above to send the message.

    You've been a great help

    Thanks again

    Steve

**Attention** This is a public forum