AnsweredAssumed Answered

Potential CAN STM32F10x Bug

Question asked by menecken on Feb 23, 2014
Latest reply on Feb 25, 2014 by belomutskiy.andrey
Dear all,

I'm having problems to understand what's happening. While searching for the cause of the error I started from the scratch - the code is stripped down to the bare minimum. I think any cross interference can be excluded.

I use two different methods for sending CAN-messages. One to send raw CAN-messages directly and one to send CAN-messages according to ISO15765-2 (calling the other).

The problem is: If I send a raw CAN-message before I'm calling the ISO15765-2 method to send another message, the same message (first one) will be transmitted over and over (/eventually) again (when I call the ISO15765-2 method) although even the debugger shows the right values in uint8_t CAN_Transmit(CAN_TypeDef* , CanTxMsg*) from stm32f10x_can.c.

The code I use for sending a CAN-Message is:
uint8_t NCAN_Send(CanTxMsg* pCanMsg)
{
    // check if at least one of the three transmission mailboxes is ready \TODO timeout
    while(!(CAN1->TSR & CAN_TSR_TME0 || CAN1->TSR & CAN_TSR_TME1 || CAN1->TSR & CAN_TSR_TME2))
    {}
 
    if ( CAN_Transmit(CAN1, pCanMsg) != CAN_TxStatus_NoMailBox)
    {
        nMsgs++;
 
        NCanTxMsg outgoing;
 
        outgoing.CanMsg = *pCanMsg;
        outgoing.nCanMsg = nMsgs;
 
        // use outgoing for logging purposes...
 
        return SUCCESS;
    }
 
    return ERROR;
}

The code I use for sending a CAN message according to ISO15765-2 is
uint8_t NISO15765_TransmitExtendedStart(NProtocolDataUnit* pdu)
{

    CanTxMsg outgoing;
    outgoing.IDE = CAN_Id_Standard; // set to standard 11-Bit identifier
    outgoing.DLC = 8;               // datalength of single CAN-Messages is always 8
 
    outgoing.StdId = 0x600 | pdu->srcId;    // set source id, \test if 6| should be done here or in application layer
    outgoing.Data[0] = pdu->destId;     // set the dest ID
 
    if (pdu->length <= (NCAN_MAX_DATABYTES_PER_MSG - uiHeaderSizeSF))   // we only have 6 databytes left
    {
        // set single Frame, high nibble (Bits 7-4)
        outgoing.Data[1] = ISO15765_PCITYPE_SF;
 
        // set datalen, low nibble (Bits 3-0)
        outgoing.Data[1] |= pdu->length;
 
        // copy the userdata
        int i;
        for (i = 0; i < pdu->length; ++i)
        {
            outgoing.Data[2+i] = pdu->Data[i];
        }
 
        // fill up with 0xFF
        for (i = pdu->length; i < (NCAN_MAX_DATABYTES_PER_MSG - uiHeaderSizeSF); ++i)
        {
            outgoing.Data[2+i] = 0xFF;
        }
 
        // send the message
        return NCAN_Send(&outgoing);
    }
}

So if I call only
NProtocolDataUnit PDU;
 
PDU.destId = 0x12;
PDU.srcId = 0xF1;
PDU.length = 3;
PDU.Data[0] = 0x09;
PDU.Data[1] = 0x00;
PDU.Data[2] = 0x00;
 
uint8_t res = NISO15765_TransmitExtendedStart(&PDU);

everything works just fine, I'll receive a 6F1,8,12 03 09 00 00 FF FF FFBUTif I call
CanTxMsg Mainoutput;
 
Mainoutput.DLC = 4;
Mainoutput.Data[0] = 0x21;
Mainoutput.Data[1] = 0x23;
Mainoutput.Data[2] = 0x24;
Mainoutput.Data[3] = 0x25;
Mainoutput.IDE = CAN_Id_Standard;
Mainoutput.RTR = 0;
Mainoutput.StdId = 0x11;
NCAN_Send(&Mainoutput);
 
NProtocolDataUnit PDU;
PDU.destId = 0x12;
PDU.srcId = 0xF1;
PDU.length = 3;
PDU.Data[0] = 0x09;
PDU.Data[1] = 0x00;
PDU.Data[2] = 0x00;
uint8_t res = NISO15765_TransmitExtendedStart(&PDU);
res = NISO15765_TransmitExtendedStart(&PDU);
res = NISO15765_TransmitExtendedStart(&PDU);
res = NISO15765_TransmitExtendedStart(&PDU);
res = NISO15765_TransmitExtendedStart(&PDU);
res = NISO15765_TransmitExtendedStart(&PDU);
res = NISO15765_TransmitExtendedStart(&PDU);

I'll get
11;4;21 23 24 25             
6F1;8;12 03 09 00 00 FF FF FF 
6F1;8;12 03 09 00 00 FF FF FF 
6F1;4;21 23 24 25             
6F1;8;12 03 09 00 00 FF FF FF 
6F1;8;12 03 09 00 00 FF FF FF 
6F1;4;21 23 24 25             
6F1;8;12 03 09 00 00 FF FF FF 


So it seems to me, that the uC uses sometimes (?) the old value?

And what makes it even more strange is: If I use 
uint8_t NCAN_Send(CanTxMsg* pCanMsg)
{
    // check if at least one of the three transmission mailboxes is ready \TODO timeout
    while(!(CAN1->TSR & CAN_TSR_TME0 || CAN1->TSR & CAN_TSR_TME1 || CAN1->TSR & CAN_TSR_TME2))
    {}
 
    if ( CAN_Transmit(CAN1, pCanMsg) != CAN_TxStatus_NoMailBox)
    {
        return SUCCESS;
    }
 
    return ERROR;
}
it works just fine. And if I'm using
uint8_t NCAN_Send(CanTxMsg* pCanMsg)
{
    // check if at least one of the three transmission mailboxes is ready \TODO timeout
    while(!(CAN1->TSR & CAN_TSR_TME0 || CAN1->TSR & CAN_TSR_TME1 || CAN1->TSR & CAN_TSR_TME2))
    {
        int doesNotMakeSense = 1;
    }
 
    if ( CAN_Transmit(CAN1, pCanMsg) != CAN_TxStatus_NoMailBox)
    {
        return SUCCESS;
    }
 
    return ERROR;
}
It stops sending after the first (raw) CAN message - although the while loop is passed.

Does anybody have any idea what the problem could be? I'm on CooCox CoIDE 1.7.6. and I'm compiling with GNU tools 4.8 2013q4.

Thank you so much in advance!

Outcomes