Hi there,
finally I found the cause for following problem:
when fast sending out several CAN messages using the write-function of the mbed API, the first message gets transmitted, followed by the fourth message. The last two transmitted messages are message 2 and 3. The reason for this is that function can_write from can_api.c makes use of the LPC1768's three TX buffers. It starts by trying to write the current message into the first buffer. If this is impossible because of a not completed transaction, it tries the second buffer. So this is what happens when several CAN messages with the same ID are sent to the can_write function:
- all buffers are empty
- message 1 is stored into buffer 1, transmit is started
- message 2 can't be stored into buffer 1 as transmit is not completed, buffer 2 is used instead
- message 3 therefore is stored into buffer 3
- message 4 can't be written to any of the buffers as the first transaction is not yet completed, so can_write returns error
- this error is processed by user software using some sort of blocking while(!can.write(msg));
- as soon as message 1 has been completey transmitted, message 4 gets stored into buffer 1 and will be transmitted next (the CAN logic is set up to use the message ID for determining the priority of the TX buffers)
- message 2 and 3 will be transmitted if user application slows down the message creation
(so that between two new messages at least one CAN message can be completely sent out by CAN hardware - this depends on bus traffic and baudrate) or completely stops it
To prevent this, I commented out the attempt of writing into buffer 2 and 3. Instead, only the first buffer is used. This is fine for my application as it comes with a software ringbuffer for the outgoing CAN messages. A more subtle fix would be to keep track of how old the messages in the three buffers are and then use priorities to ensure the correct transmit order.
Fixed problematic function
int can_write(can_t *obj, CAN_Message msg, int cc) {
unsigned int CANStatus;
CANMsg m;
can_enable(obj);
m.id = msg.id ;
m.dlc = msg.len & 0xF;
m.rtr = msg.type;
m.type = msg.format;
memcpy(m.data, msg.data, msg.len);
const unsigned int *buf = (const unsigned int *)&m;
CANStatus = obj->dev->SR;
if (CANStatus & 0x00000004) {
obj->dev->TFI1 = buf[0] & 0xC00F0000;
obj->dev->TID1 = buf[1];
obj->dev->TDA1 = buf[2];
obj->dev->TDB1 = buf[3];
if(cc) {
obj->dev->CMR = 0x30;
} else {
obj->dev->CMR = 0x21;
}
return 1;
}
/*
else if (CANStatus & 0x00000400) {
obj->dev->TFI2 = buf[0] & 0xC00F0000;
obj->dev->TID2 = buf[1];
obj->dev->TDA2 = buf[2];
obj->dev->TDB2 = buf[3];
if (cc) {
obj->dev->CMR = 0x50;
} else {
obj->dev->CMR = 0x41;
}
return 1;
}
else if (CANStatus & 0x00040000) {
obj->dev->TFI3 = buf[0] & 0xC00F0000;
obj->dev->TID3 = buf[1];
obj->dev->TDA3 = buf[2];
obj->dev->TDB3 = buf[3];
if (cc) {
obj->dev->CMR = 0x90;
} else {
obj->dev->CMR = 0x81;
}
return 1;
}
*/
return 0;
}
With best regards,
Stefan.
Hi there,
finally I found the cause for following problem:
when fast sending out several CAN messages using the write-function of the mbed API, the first message gets transmitted, followed by the fourth message. The last two transmitted messages are message 2 and 3. The reason for this is that function can_write from can_api.c makes use of the LPC1768's three TX buffers. It starts by trying to write the current message into the first buffer. If this is impossible because of a not completed transaction, it tries the second buffer. So this is what happens when several CAN messages with the same ID are sent to the can_write function:
To prevent this, I commented out the attempt of writing into buffer 2 and 3. Instead, only the first buffer is used. This is fine for my application as it comes with a software ringbuffer for the outgoing CAN messages. A more subtle fix would be to keep track of how old the messages in the three buffers are and then use priorities to ensure the correct transmit order.
Fixed problematic function
With best regards, Stefan.