if ( FLEXCAN_get_code(code) == FLEXCAN_MB_CODE_TX_INACTIVE ) {
if (!(imask & (1ULL << mb_num))) writeIMASKBit(mb_num); /* enable interrupt for MB if not enabled */
writeIFLAGBit(mb_num); /* clear IFLAG <--- this line */
if ( !txBuffer.size() ) continue; /* no queues available, continue next mailbox check */
[ATTACH]20258._xfImport[/ATTACH]
FCTP_FUNC void FCTP_OPT::flexcan_interrupt() {
CAN_message_t msg; // setup a temporary storage buffer
uint64_t imask = readIMASK(), iflag = readIFLAG();
[COLOR="#FF0000"]writeIMASK(0ULL); /* Added by MSADIE - prevent preemption by FlexCAN (I think!?) */[/COLOR]
if ( !(FLEXCANb_MCR(_bus) & (1UL << 15)) ) { /* if DMA is disabled, ONLY THEN you can handle FIFO in ISR */
if ( (FLEXCANb_MCR(_bus) & FLEXCAN_MCR_FEN) && (imask & FLEXCAN_IMASK1_BUF5M) && (iflag & FLEXCAN_IFLAG1_BUF5I) ) { /* FIFO is enabled, capture frames if triggered */
volatile uint32_t *mbxAddr = &(*(volatile uint32_t*)(_bus + 0x80 + (0 * 0x10)));
uint32_t code = mbxAddr[0];
msg.len = (code & 0xF0000) >> 16;
msg.flags.remote = (bool)(code & (1UL << 20));
msg.flags.extended = (bool)(code & (1UL << 21));
msg.timestamp = code & 0xFFFF;
msg.id = (mbxAddr[1] & 0x1FFFFFFF) >> ((msg.flags.extended) ? 0 : 18);
msg.idhit = code >> 23;
for ( uint8_t i = 0; i < (8 >> 2); i++ ) for ( int8_t d = 0; d < 4 ; d++ ) msg.buf[(4 * i) + 3 - d] = (uint8_t)(mbxAddr[2 + i] >> (8 * d));
msg.bus = busNumber;
msg.mb = FIFO; /* store the mailbox the message came from (for callback reference) */
(void)FLEXCANb_TIMER(_bus);
writeIFLAGBit(5); /* clear FIFO bit only! */
if ( iflag & FLEXCAN_IFLAG1_BUF6I ) writeIFLAGBit(6); /* clear FIFO bit only! */
if ( iflag & FLEXCAN_IFLAG1_BUF7I ) writeIFLAGBit(7); /* clear FIFO bit only! */
frame_distribution(msg);
ext_output1(msg);
ext_output2(msg);
ext_output3(msg);
if (fifo_filter_match(msg.id)) struct2queueRx(msg);
}
}
uint8_t exit_point = 64 - __builtin_clzll(iflag | 1); /* break from MSB's if unset, add 1 to prevent undefined behaviour in clz for 0 check */
int8_t first_tx_found = -1;
for ( uint8_t mb_num = mailboxOffset(); mb_num < FLEXCANb_MAXMB_SIZE(_bus); mb_num++ ) {
if ( !txBuffer.size() ) { /* if transmits exist, don't skip any mailboxes */
if ( mb_num >= exit_point ) break; /* early exit from higher unflagged mailboxes */
if (!(imask & (1ULL << mb_num))) continue; /* don't read non-interrupt mailboxes */
if (!(iflag & (1ULL << mb_num))) continue; /* don't read unflagged mailboxes */
}
volatile uint32_t *mbxAddr = &(*(volatile uint32_t*)(_bus + 0x80 + (mb_num * 0x10)));
uint32_t code = mbxAddr[0];
if ( (FLEXCAN_get_code(code) >> 3) && (first_tx_found == -1) ) first_tx_found = mb_num; /* set absolute first TX mailbox found */
if ( FLEXCAN_get_code(code) == FLEXCAN_MB_CODE_RX_EMPTY ) {
/* there are no flags for EMPTY reception boxes, however, when sending remote
frames, the mailboxes switch to RX_EMPTY and trigger the flag */
if (!(iflag & (1ULL << mb_num))) continue; /* only process the flagged RX_EMPTY mailboxes */
writeIFLAGBit(mb_num); /* clear IFLAG */
mbxAddr[0] = FLEXCAN_MB_CS_CODE(FLEXCAN_MB_CODE_TX_INACTIVE);
}
if ( FLEXCAN_get_code(code) == FLEXCAN_MB_CODE_TX_INACTIVE ) {
[COLOR="#FF0000"] if (!(imask & (1ULL << mb_num))) {
imask |= (1ULL << mb_num); /* enable interrupt for MB if not enabled */
} /* Changed by MSADIE - enable via "imask" instead of "writeIMASKBit()"*/[/COLOR]
if ( !txBuffer.size() ) {
[COLOR="#FF0000"]writeIFLAGBit(mb_num); /* Added by MSADIE - clear IFLAG */[/COLOR]
[COLOR="#FF0000"]/* This fixes what I believe is an unrelated bug */[/COLOR]
continue; /* no queues available, continue next mailbox check */
}
uint8_t buf[sizeof(CAN_message_t)];
txBuffer.peek_front(buf, sizeof(CAN_message_t));
memmove(&msg, buf, sizeof(msg));
if ( (msg.seq) && (mb_num != first_tx_found) && (!msg.flags.remote) ) continue; /* only offload sequential frames to absolute first mailbox */
else if ( msg.mb == -1 ); /* write to any available mailbox */
else if ( msg.mb == mb_num ); /* write to a specific mailbox */
else continue; /* if it didn't pass last condition, it is not the specific mailbox, keep scanning till then */
/* if transmitting sequential frames, don't assume pending remote frame transmissions
arn't processing, otherwise the swap to RX_EMPTY would cause the next MB to transmit
the sequential, essentially consuming 2 mailboxes for sequential writes. This prevents
this issue by checking next cycle after current transmissions in the status register */
if ( msg.seq && FLEXCANb_ESR1(_bus) & (1UL << 6) ) continue;
txBuffer.pop_front(); /* clear on write */
writeIFLAGBit(mb_num); /* clear IFLAG */
mbxAddr[0] = FLEXCAN_MB_CS_CODE(FLEXCAN_MB_CODE_TX_INACTIVE);
mbxAddr[1] = (( msg.flags.extended ) ? ( msg.id & FLEXCAN_MB_ID_EXT_MASK ) : FLEXCAN_MB_ID_IDSTD(msg.id));
code = msg.len << 16;
if ( msg.flags.remote ) code |= (1UL << 20);
if ( msg.flags.extended ) code |= (3UL << 21);
for ( uint8_t i = 0; i < (8 >> 2); i++ ) mbxAddr[2 + i] = (msg.buf[0 + i * 4] << 24) | (msg.buf[1 + i * 4] << 16) | (msg.buf[2 + i * 4] << 8) | msg.buf[3 + i * 4];
mbxAddr[0] = code | FLEXCAN_MB_CS_CODE(FLEXCAN_MB_CODE_TX_ONCE);
}
else if ( ( FLEXCAN_get_code(code) == FLEXCAN_MB_CODE_RX_FULL ) ||
( FLEXCAN_get_code(code) == FLEXCAN_MB_CODE_RX_OVERRUN ) ) {
/* treat receptions normally if transmit queue exists */
if (!(imask & (1ULL << mb_num))) continue; /* don't read non-interrupt mailboxes */
if (!(iflag & (1ULL << mb_num))) continue; /* don't read unflagged mailboxes */
msg.flags.extended = (bool)(code & (1UL << 21));
msg.id = (mbxAddr[1] & 0x1FFFFFFF) >> ((msg.flags.extended) ? 0 : 18);
if ( FLEXCAN_get_code(code) == FLEXCAN_MB_CODE_RX_OVERRUN ) msg.flags.overrun = 1;
msg.len = (code & 0xF0000) >> 16;
msg.mb = mb_num;
msg.timestamp = code & 0xFFFF;
msg.bus = busNumber;
for ( uint8_t i = 0; i < (8 >> 2); i++ ) for ( int8_t d = 0; d < 4 ; d++ ) msg.buf[(4 * i) + 3 - d] = (uint8_t)(mbxAddr[2 + i] >> (8 * d));
mbxAddr[0] = FLEXCAN_MB_CS_CODE(FLEXCAN_MB_CODE_RX_EMPTY) | ((msg.flags.extended) ? (FLEXCAN_MB_CS_SRR | FLEXCAN_MB_CS_IDE) : 0);
(void)FLEXCANb_TIMER(_bus);
writeIFLAGBit(mb_num);
if ( filter_match((FLEXCAN_MAILBOX)mb_num, msg.id) ) struct2queueRx(msg); /* store frame in queue */
frame_distribution(msg);
ext_output1(msg);
ext_output2(msg);
ext_output3(msg);
}
}
FLEXCANb_ESR1(_bus) |= FLEXCANb_ESR1(_bus);
asm volatile ("dsb");
[COLOR="#FF0000"]writeIMASK(imask); /* Added by MSADIE disable new interrupts */[/COLOR]
}
[ATTACH]20262._xfImport[/ATTACH]
[ATTACH]20278._xfImport[/ATTACH]
Time Chn ID Dir DLC Data Bus Idle Frame Duration Diff Time
5.776020 CAN 1 123 Rx 8 00 00 00 00 00 00 00 00 0.250 ms (125 bits) 0.000000
5.776272 CAN 1 123 Rx 8 00 00 00 00 00 00 00 00 0.002 ms 0.250 ms (125 bits) 0.000252
5.776524 CAN 1 123 Rx 8 00 00 00 00 00 00 00 00 0.002 ms 0.250 ms (125 bits) 0.000252
5.776776 CAN 1 123 Rx 8 00 00 00 00 00 00 00 00 0.002 ms 0.250 ms (125 bits) 0.000252
5.777029 CAN 1 123 Rx 8 00 00 00 00 00 00 00 00 0.002 ms 0.250 ms (125 bits) 0.000252
Time Chn ID Dir DLC Data Bus Idle Frame Duration Diff Time
4.537827 CAN 1 123 Rx 8 00 00 00 00 00 00 00 00 0.250 ms (125 bits) 0.000000
4.538077 CAN 1 123 Rx 8 00 00 00 00 00 00 00 00 0.000 ms 0.250 ms (125 bits) 0.000250
4.538328 CAN 1 123 Rx 8 00 00 00 00 00 00 00 00 0.000 ms 0.250 ms (125 bits) 0.000250
4.538578 CAN 1 123 Rx 8 00 00 00 00 00 00 00 00 0.000 ms 0.250 ms (125 bits) 0.000250
4.538828 CAN 1 123 Rx 8 00 00 00 00 00 00 00 00 0.000 ms 0.250 ms (125 bits) 0.000250
Time Chn ID Dir DLC Data Bus Idle Frame Duration Diff Time
3.452732 CAN 1 0 Rx 8 08 00 00 00 00 00 00 00 0.254 ms (127 bits) 0.000000
3.452984 CAN 1 7FF Rx 8 00 00 00 00 00 00 00 00 0.000 ms 0.252 ms (126 bits) 0.000252
3.453237 CAN 1 0 Rx 8 09 00 00 00 00 00 00 00 0.000 ms 0.252 ms (126 bits) 0.000252
3.453493 CAN 1 7FE Tx 8 00 00 00 00 00 00 00 00 0.000 ms 0.254 ms (127 bits) 0.000256
3.453745 CAN 1 0 Rx 8 08 01 00 00 00 00 00 00 0.000 ms 0.254 ms (127 bits) 0.000252
3.454001 CAN 1 7FE Tx 8 00 00 00 00 00 00 00 00 0.000 ms 0.254 ms (127 bits) 0.000256
3.454251 CAN 1 0 Rx 8 09 01 00 00 00 00 00 00 0.000 ms 0.252 ms (126 bits) 0.000250
3.454501 CAN 1 7FF Rx 8 00 01 00 00 00 00 00 00 0.000 ms 0.250 ms (125 bits) 0.000250
3.454755 CAN 1 0 Rx 8 08 02 00 00 00 00 00 00 0.000 ms 0.254 ms (127 bits) 0.000254
3.455007 CAN 1 7FF Rx 8 00 02 00 00 00 00 00 00 0.000 ms 0.252 ms (126 bits) 0.000252
3.455257 CAN 1 0 Rx 8 09 02 00 00 00 00 00 00 0.000 ms 0.250 ms (125 bits) 0.000250
Time Chn ID Dir DLC Data Bus Idle Frame Duration Diff Time
2.995827 CAN 1 0 Rx 8 08 00 00 00 00 00 00 00 0.254 ms (127 bits) 0.000000
2.996079 CAN 1 0 Rx 8 09 00 00 00 00 00 00 00 0.000 ms 0.252 ms (126 bits) 0.000252
2.996333 CAN 1 0 Rx 8 08 01 00 00 00 00 00 00 0.000 ms 0.254 ms (127 bits) 0.000254
2.996585 CAN 1 0 Rx 8 09 01 00 00 00 00 00 00 0.000 ms 0.252 ms (126 bits) 0.000252
2.996839 CAN 1 0 Rx 8 08 02 00 00 00 00 00 00 0.000 ms 0.254 ms (127 bits) 0.000254
2.997089 CAN 1 0 Rx 8 09 02 00 00 00 00 00 00 0.000 ms 0.250 ms (125 bits) 0.000250
2.997345 CAN 1 7FE Tx 8 00 00 00 00 00 00 00 00 0.000 ms 0.254 ms (127 bits) 0.000256
2.997599 CAN 1 7FE Tx 8 00 00 00 00 00 00 00 00 0.000 ms 0.254 ms (127 bits) 0.000254
2.997849 CAN 1 7FF Rx 8 00 02 00 00 00 00 00 00 0.000 ms 0.252 ms (126 bits) 0.000250
2.998101 CAN 1 7FF Rx 8 00 00 00 00 00 00 00 00 0.000 ms 0.252 ms (126 bits) 0.000252
2.998352 CAN 1 7FF Rx 8 00 01 00 00 00 00 00 00 0.000 ms 0.250 ms (125 bits) 0.000250
#include <FlexCAN_T4.h>
FlexCAN_T4<CAN1, RX_SIZE_256, TX_SIZE_16> myCan;
void sendSeqBurst() {
CAN_message_t myMsgMB8;
CAN_message_t myMsgMB9;
CAN_message_t myMsg7FF;
// High priority messages
myMsgMB8.id = 0x000;
myMsgMB8.seq = 0; // Set to 1 -> bus idle for 1 bit between messages
myMsgMB8.mb = 8;
myMsgMB8.buf[0] = 8;
myMsgMB9.id = 0x000;
myMsgMB9.seq = 0; // Set to 1 -> bus idle for 1 bit between messages
myMsgMB9.mb = 9;
myMsgMB9.buf[0] = 9;
// Low priority message acting as "interference"
myMsg7FF.id = 0x7FF;
myMsg7FF.seq = 0;
myMsg7FF.mb = -1;
// Write series of high priority messages
for ( int i = 0; i < 3; i++) {
myCan.write(myMsgMB8);
myCan.write(myMsgMB9);
myMsgMB8.buf[1]++;
myMsgMB9.buf[1]++;
}
// Write series of low priority messages
for ( int i = 0; i < 3; i++) {
myCan.write(myMsg7FF);
myMsg7FF.buf[1]++;
}
}
void setup() {
pinMode(20, OUTPUT); digitalWriteFast(20, LOW); /* optional tranceiver silent pin: HIGH = Silent */
pinMode(13, OUTPUT);
myCan.begin();
myCan.setBaudRate(500000);
delay(1000);
sendSeqBurst();
}
void loop() {
// do nothing
}
bool setMBUserFilter(FLEXCAN_MAILBOX mb_num, uint32_t id1, uint32_t mask);
bool setMBUserFilter(FLEXCAN_MAILBOX mb_num, uint32_t id1, uint32_t id2, uint32_t mask);
bool setMBUserFilter(FLEXCAN_MAILBOX mb_num, uint32_t id1, uint32_t id2, uint32_t id3, uint32_t mask);
bool setMBUserFilter(FLEXCAN_MAILBOX mb_num, uint32_t id1, uint32_t id2, uint32_t id3, uint32_t id4, uint32_t mask);
bool setFIFOUserFilter(uint8_t filter, uint32_t id1, uint32_t mask, const FLEXCAN_IDE &ide, const FLEXCAN_IDE &remote = NONE);
bool setFIFOUserFilter(uint8_t filter, uint32_t id1, uint32_t id2, uint32_t mask, const FLEXCAN_IDE &ide, const FLEXCAN_IDE &remote = NONE);
bool setFIFOUserFilter(uint8_t filter, uint32_t id1, uint32_t id2, uint32_t id3, uint32_t mask, const FLEXCAN_IDE &ide, const FLEXCAN_IDE &remote = NONE);
bool setFIFOUserFilter(uint8_t filter, uint32_t id1, uint32_t id2, uint32_t id3, uint32_t id4, uint32_t mask, const FLEXCAN_IDE &ide, const FLEXCAN_IDE &remote = NONE);
[ATTACH]20405._xfImport[/ATTACH]
// demo: CAN-BUS Shield, send data
// loovee@seeed.cc
#include <mcp_can.h>
#include <SPI.h>
/*SAMD core*/
#ifdef ARDUINO_SAMD_VARIANT_COMPLIANCE
#define SERIAL SerialUSB
#else
#define SERIAL Serial
#endif
// the cs pin of the version after v1.1 is default to D9
// v0.9b and v1.0 is default D10
const int SPI_CS_PIN = 9;
MCP_CAN CAN(SPI_CS_PIN); // Set CS pin
void setup() {
SERIAL.begin(115200);
while (CAN_OK != CAN.begin(CAN_500KBPS)) { // init can bus : baudrate = 500k
SERIAL.println("CAN BUS Shield init fail");
SERIAL.println(" Init CAN BUS Shield again");
delay(100);
}
SERIAL.println("CAN BUS Shield init ok!");
}
unsigned char stmp[8] = {0, 0, 0, 0, 0, 0, 0, 0};
void loop() {
// send data: id = 0x00, standrad frame, data len = 8, stmp: data buf
stmp[7] = stmp[7] + 1;
if (stmp[7] == 100) {
stmp[7] = 0;
stmp[6] = stmp[6] + 1;
if (stmp[6] == 100) {
stmp[6] = 0;
stmp[5] = stmp[6] + 1;
}
}
CAN.sendMsgBuf(0x00, 0, 8, stmp);
delay(100); // send data per 100ms
}
// END FILE
Just added wake up on traffic support.
You can call:
in your code to goto sleep. The loop() will stop scrolling after shorting out the CAN lines when the wfi enters sleep. Removing the short on the CAN lines restores the CAN network, and Teensy 4 will self-wake when data starts rolling on the busCode:asm(" wfi");
Code:[ATTACH]20158[/ATTACH]
In file included from /Applications/Teensyduino.app/Contents/Java/hardware/teensy/avr/libraries/FlexCAN_T4/FlexCAN_T4.h:500:0,
from /Users/Rezo/Documents/Arduino/T4/CAN_T4_MB_interval_3.5_v2.5.2.03/CAN_T4_MB_interval_3.5_v2.5.2.03.ino:8:
/Applications/Teensyduino.app/Contents/Java/hardware/teensy/avr/libraries/FlexCAN_T4/FlexCAN_T4FD.tpp: In member function 'void FlexCAN_T4FD<_bus, _rxSize, _txSize>::begin()':
/Applications/Teensyduino.app/Contents/Java/hardware/teensy/avr/libraries/FlexCAN_T4/FlexCAN_T4FD.tpp:67:9: warning: there are no arguments to 'setTx' that depend on a template parameter, so a declaration of 'setTx' must be available [-fpermissive]
setTx(); setRx();
^
/Applications/Teensyduino.app/Contents/Java/hardware/teensy/avr/libraries/FlexCAN_T4/FlexCAN_T4FD.tpp:67:18: warning: there are no arguments to 'setRx' that depend on a template parameter, so a declaration of 'setRx' must be available [-fpermissive]
setTx(); setRx();
^
In file included from /Applications/Teensyduino.app/Contents/Java/hardware/teensy/avr/libraries/FlexCAN_T4/FlexCAN_T4.h:500:0,
from /Users/re/Documents/Arduino/T4/CAN_T4_MB_interval_3.5_v2.5.2.03/CAN_T4_MB_interval_3.5_v2.5.2.03.ino:8:
/Applications/Teensyduino.app/Contents/Java/hardware/teensy/avr/libraries/FlexCAN_T4/FlexCAN_T4FD.tpp: At global scope:
/Applications/Teensyduino.app/Contents/Java/hardware/teensy/avr/libraries/FlexCAN_T4/FlexCAN_T4FD.tpp:313:52: error: no 'void FlexCAN_T4FD<_bus, _rxSize, _txSize>::setTx(FLEXCAN_PINS)' member function declared in class 'FlexCAN_T4FD<_bus, _rxSize, _txSize>'
FCTPFD_FUNC void FCTPFD_OPT::setTx(FLEXCAN_PINS pin) {
^
/Applications/Teensyduino.app/Contents/Java/hardware/teensy/avr/libraries/FlexCAN_T4/FlexCAN_T4FD.tpp:334:52: error: no 'void FlexCAN_T4FD<_bus, _rxSize, _txSize>::setRx(FLEXCAN_PINS)' member function declared in class 'FlexCAN_T4FD<_bus, _rxSize, _txSize>'
FCTPFD_FUNC void FCTPFD_OPT::setRx(FLEXCAN_PINS pin) {
^
Error compiling for board Teensy 4.0.