I want to transmit CAN frames on a Kinetis KE06. When I send the frame its payload is total junk. I have confirmed the wrong data in loopback mode and with a logic analyzer (connected to tranceiver TX pin). The identifier (both standard and extended) is always correct and the length is always correct. Junk payload stays always the same, but differs across power cycles.
This is my transmit code:
static void can_transmit(uint32_t identifier, bool identifier_is_extended,
const uint8_t *payload, uint8_t payload_length) {
uint8_t empty_buffer_mask = MSCAN->CANTFLG & MSCAN_CANTFLG_TXE_MASK;
if (!empty_buffer_mask) {
debugf("TX busy, dropping frame");
return;
}
//select transmit buffer
MSCAN->CANTBSEL = MSCAN_CANTBSEL_TX(empty_buffer_mask);
debugf("Buffers available %02X selected %02X, payload length %d", empty_buffer_mask, MSCAN->CANTBSEL, payload_length);
if (identifier_is_extended) {
MSCAN->TEIDR0 = identifier >> 21;
MSCAN->TEIDR1 = ((identifier >> (20/*source bit position*/- 7/*destination bit position*/))
& MSCAN_TEIDR1_TEID20_TEID18_MASK)
| ((identifier >> (17 - 2)) & MSCAN_TEIDR1_TEID17_TEID15_MASK)
| MSCAN_TEIDR1_TEIDE_MASK;
MSCAN->TEIDR2 = identifier >> 7;
MSCAN->TEIDR3 = identifier << 1; //TODO: check the RTR flag
} else {
MSCAN->TSIDR0 = (uint8_t) (identifier >> 3); //this register holds bits 10-3 of the ID
MSCAN->TSIDR1 = (identifier & 0x7) << MSCAN_TSIDR1_TSID2_TSID0_SHIFT;
MSCAN->TSIDR1 |= MSCAN_TSIDR1_TSRTR_MASK; //set remote transmit request flag
// ^^^^^^^^^ THIS IS WRONG - see answer ^^^^^^^^^^^^
}
for (uint8_t i = 0; i < 8; i++){
MSCAN->TEDSR[i] = i; //transmit fixed data
debugf("TEDSR[%ld] = %02X", i, MSCAN->TEDSR[i]);
}
MSCAN->TDLR = 8;//payload_length;
MSCAN->TBPR = 0; //priority of this buffer
_rx_busy = false;
//enable transmission of this buffer
uint8_t transmit_flag = MSCAN->CANTBSEL & MSCAN_CANTFLG_TXE_MASK;
debugf("transmit flag = %02X", transmit_flag);
MSCAN->CANTFLG = transmit_flag;
}
It seems like the write to TEDSR does not take effect. What am I doing wrong?