cancel
Showing results for 
Search instead for 
Did you mean: 

Potential CAN STM32F10x Bug

bernhard
Associate II
Posted on February 23, 2014 at 16:05

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 inuint8_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 FF

.

BUTif 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 tools4.8 2013q4.

Thank you so much in advance!

#can #bug #coide

3 REPLIES 3
arro239
Senior
Posted on February 24, 2014 at 03:37

I do not have an answer for your question, but I am curious what are you working on :)

ISO 15765-2 is OBDII over CAN is it? I am playing with something more or less from the same field. Too bad there are no Private Messages here :(
bernhard
Associate II
Posted on February 24, 2014 at 10:18

OBD-II over CAN (mostly, except for multiframe stuff like a VIN request) works without ISO15765-2. The ISO is needed though if you want to communicate with the car using KWP2000 or UDS, cause then you need the ISO (which defines transport layer) in order to be able to transmit messages > 8 Byte.

arro239
Senior
Posted on February 25, 2014 at 02:23

Man, we need you on the rusEfi.com project!

http://rusefi.com/images/Frankenstein/20140224_state.jpg