56F8037 CAN TX problems

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

56F8037 CAN TX problems

856 Views
Law
Contributor I

Hi there,

 

I am having a bit of trouble with the MSCAN module in the 56F8037. In particular, I am currently trying to get it to transmit data.

I have this sort of working, in that I can transmit data ok at various speeds and recieve it on my PC but I am having trouble with sending more than 3 lots of data and I think it is related to the transmit buffers.

For example, I have set up my controller to just send some static data over the CAN module to test if it was working. This was something like: (I populated all bytes in between - they are just omitted for clarity)

 

outData[0] = 11;  to outData[7] = 18;        // Populate tx data

can_Send_Pkt(outData, toID, fromID);   // Send it off

outData[0] = 21;  to outData[7] = 28;

can_Send_Pkt(outData, toID, fromID);

outData[0] = 31;  to outData[7] = 38;

can_Send_Pkt(outData, toID, fromID);

outData[0] = 41;  to outData[7] = 48;

can_Send_Pkt(outData, toID, fromID);

 

And so on, up to 71,...,78.

All I recieve on the other end of the CAN bus is the data from

11,...,18

21,...,28

31,...,38

 

And it will just keep repeating this. (ie 11, 12, 13, 14, 16, 17, 18)

 

It seems as though I can write to the tx data buffer once, then that is all. The datasheet says that the only way to clear out a tx data buffer is by writing to it. I do think something is screwy in the way I am putting data into the tx Buffers and I also think my selection of TX buffer is a bit suspect, but I cannot put my finger on it.

I wonder if anyone could take a quick look at my code below and see if they can see something I cannot.

The code is based on the Quickstart example and some other stuff I lifted from the depths of the Codewarrior directory.

 

I have included 2 versions of my testing code below. The top one gives the above results. The bottom one just transmits one register. I believe the bottom one is a step in the right direction.

 

 

1st try:

 

 
// ------------------------------------------------ CAN - TX READY ISR -----------------------------------
#pragma interrupt on
void CAN_TxRdy_ISR(void)  
{
 
    
    // what tx buffers are empty?  
    UWord16 tint = ioctl(MSCAN, MSCAN_READ_TINT_FLAGS, NULL);        // AVailable buffers
 
 
    // disable interrupts handled
    ioctl(MSCAN, MSCAN_TINT_DISABLE, tint);
 
}
 
#pragma interrupt off
 
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
 
 
 
static void send_CAN_Pkt(UWord16 outMode, UWord16 txCmd, UWord16 outID, UWord16* sndData) {
    static UWord32 outIdCAN;
    static UWord16 txbuff;
    
    // Select the next available TX buffer
    txbuff = ioctl(MSCAN, MSCAN_SELECT_NEXT_TXBUFF, NULL);
 
    if(txbuff) {
        // Pointer to TX buffer
        register UWord16* pdT = ioctl(MSCAN_TB, MSCANMB_GET_DATAPTR, NULL);
 
                
        pdT[0] = sndData[0];
        pdT[1] = sndData[1];
        pdT[2] = sndData[2];
        pdT[3] = sndData[3];
        pdT[4] = sndData[4];
        pdT[5] = sndData[5];
        pdT[6] = sndData[6];
        pdT[7] = sndData[7];
 
        outID = ((ecID << 4) & FROM_MASK) | (outMode << 8);    // (1 << 8) is the Mode part. Change to (Mode << 8)
         
        ioctl(MSCAN_TB, MSCANMB_SET_ID, outID);
        ioctl(MSCAN_TB, MSCANMB_SET_LEN, 8);
 
        // transmit buffer
        ioctl(MSCAN, MSCAN_TRANSMIT, txbuff);  
 
        // enable tx-finished interrupt
        ioctl(MSCAN, MSCAN_TINT_ENABLE, txbuff);         
    }
}

 

 

 

-------------------------

2nd try

 

 

 

 

 

// ------------------------------------------------ CAN - TX READY ISR -----------------------------------
#pragma interrupt on
void CAN_TxRdy_ISR(void)  
{
    register UWord16 txbNum;
    register UWord16 bflag;

    
    UWord16 tEmpty = ioctl(MSCAN, MSCAN_READ_TINT_FLAGS, NULL);        // AVailable buffers
 
    
    for (txbNum=0; txbNum<3; txbNum++) {

        register UWord16* pdT = ioctl(MSCAN_TB, MSCANMG_GET_DATAPTR, NULL);
        bflag = 1 << txbNum;    
 
        if(ioctl(MSCAN, MSCAN_SELECT_TXBUFF, bflag)){  // Is the current buffer empty?
            pdT[0] = outData[0];
            pdT[1] = outData[1];
            pdT[2] = outData[2];            // outData is defined up top as a global var for now.
            pdT[3] = outData[3];
            pdT[4] = outData[4];
            pdT[5] = outData[5];
            pdT[6] = outData[6];
            pdT[7] = outData[7];
            ioctl(MSCAN, MSCAN_TRANSMIT, bflag);
            tEmpty &= ~bflag;        // this buffer is no longer empty
            
        }
 
    
    }
   
    // disable interrupts handled
    ioctl(MSCAN, MSCAN_TINT_DISABLE, tEmpty);
}
 
#pragma interrupt off






 //-------------------------------------
static void send_CAN_Pkt(UWord16 outMode, UWord16 txCmd, UWord16 outID, UWord16* sndData) {
    static UWord32 outIdCAN;
    static UWord16 txbuff;
    
    outData[0] = sndData[0];
    outData[1] = sndData[1];
    outData[2] = sndData[2];
    outData[3] = sndData[3];
    outData[4] = sndData[4];
    outData[5] = sndData[5];
    outData[6] = sndData[6];
    outData[7] = sndData[7];
 
    outID = ((ecID << 4) & FROM_MASK) | (outMode << 8);    // (1 << 8) is the Mode part. Change to (Mode << 8)
      
    ioctl(MSCAN_TB, MSCANMB_SET_ID, outID);
    ioctl(MSCAN_TB, MSCANMB_SET_LEN, 8);            // just 8 bytes at the moment
 
    ioctl(MSCAN, MSCAN_TINT_ENABLE, MSCAN_TXEMPTY_ALL);     // Enable the interrupt
 
}

 

 

 

 

Apologies for the wall of text....

Thanks in advance!

 

Laurence M

Labels (1)
Tags (1)
0 Kudos
1 Reply

399 Views
Law
Contributor I

Hi again everyone,

 

Well, I have figured out what was wrong with my code. A hilarious oversight on my part.

Anyway, for those who might happen to have a similar problem in the future, dont forget to wait and

see if your send buffers are actually empty...

 

In the send_Can_pkt routine, I had the line:

 

   // Select the next available TX buffer
    txbuff = ioctl(MSCAN, MSCAN_SELECT_NEXT_TXBUFF, NULL);

 

This returns 0 if no buffers are found to be ready. Of course none were found after transmitting 3 blocks of data, so it merrily

returned zero, and would then skip over the if statement and re-enable the TX irq. Which would send the same 3 blocks again.

As a temporary solution, I have used:

while(ioctl(MSCAN, MSCAN_SELECT_NEXT_TXBUFF, NULL) == 0) {

// do nothing

}

// now populate buffers

 

This works for testing, but opens up the possibility to get stuck in an endless loop, waiting for a buffer to become available.

 

Now Im off to find a solution for that!

 

Bye

0 Kudos