Could you provide an example of how to configure and use filters with the FIFO?
Trying to use the FIFO blocks mboxes, both polled and interrupt driven.
Initialization:
Added to experiment with the FIFO:Code:void MCOUSER_ResetCommunication(void){ int i; gTimCnt = GTIMCNT; // Initialize global timer canbus1.begin(); // Must be first JGH canbus1.setMaxMB(16); canbus1.setMBFilter(REJECT_ALL); canbus1.setBaudRate(1000*BAUDRATE); for(i = 0; i < (NR_OF_RPDOS + 2); i++) { // NMT and SDO will use the first two boxes. canbus1.setMB((FLEXCAN_MAILBOX)i, RX, STD); if(i > 1){ canbus1.onReceive((FLEXCAN_MAILBOX)i, canbus_isr); // Get all RPDOs via interrupt. canbus1.enableMBInterrupt((FLEXCAN_MAILBOX)i); } } for(; i < (NR_OF_RPDOS + NR_OF_TPDOS); i++) { canbus1.setMB((FLEXCAN_MAILBOX)i, TX, STD); } // For sync #ifdef SYNC canbus1.setMB((FLEXCAN_MAILBOX)i, RX, STD); canbus1.setMBFilter((FLEXCAN_MAILBOX)i, 0x080); canbus1.onReceive((FLEXCAN_MAILBOX)i, canbus_sync); canbus1.enableMBInterrupt((FLEXCAN_MAILBOX)i); #endif // BAUDRATE,Node_ID,HEARTRATE defined at the top of this file. JGH MCO_Init(BAUDRATE,Node_ID,HEARTRATE); // Default base receive COBs are 0x200, 0x300, 0x400, and 0x500 // Calling MCO_InitRPDO or MCO_InitTPDO with COB-ID 0 results in default // RPDO1, default ID (0x200+nodeID), 4 bytes MCO_InitRPDO(1, 0, 4, &target_speed); // RPDO2, default ID (0x300+nodeID), 4 bytes MCO_InitRPDO(2, 0, 4, &acceleration); //BYTE PDO_NR, WORD CAN_ID, WORD event_time, WORD inhibit_time, BYTE len, BYTE offset // TPDO1, default ID (0x180+nodeID), 100ms event, 5ms inhibit, 4 bytes // Transmit trigger: COS (change-of-state) with 250ms inhibit time MCO_InitTPDO(1, 0, 0, 5, 4, &control_word); // TPDO2, default ID (0x280+nodeID), 100ms event, 5ms inhibit, 4 bytes // Transmit trigger: COS (change-of-state) with 250ms inhibit time MCO_InitTPDO(2, 0, 0, 5, 4, &status_word); // TPDO3, default ID (0x380+nodeID), 100ms event, 5ms inhibit, 4 bytes // Transmit trigger: COS with 100ms inhibit time, but if there is no COS within // 1000ms, message gets triggered, too MCO_InitTPDO(3, 0, 0, 5, 4, &target_speed); // TPDO4, default ID (0x480+nodeID), 100ms event, 5ms inhibit, 4 bytes // Transmit trigger: COS with 100ms inhibit time, but if there is no COS within // 1000ms, message gets triggered, too MCO_InitTPDO(4, 0, 0, 5, 4, &acceleration); } /************************************************************************** DOES: ISR for RPDO mailboxes. Writes message content to the correct PDO if the state_machine state permits. JGH RETURNS: nothing **************************************************************************/ void canbus_isr(const CAN_message_t &msg) { int i; if(gMCOConfig.heartbeat_msg.BUF[0] != 5) return; // Only receive in operational state. i = mbox_to_RPDO[msg.mb]; // This tells us what RPDO this mbox goes with. if(gRPDOConfig[i].len != msg.len) return; // Not a valid message. Should set an error. JGH memcpy(gRPDOConfig[i].offset, msg.buf, gRPDOConfig[i].len); }
NMTs (id 0x000) and SDOs (id 0x607) are polled with this:Code:canbus1.enableFIFO(); canbus1.disableFIFOInterrupt(); canbus1.setFIFOFilter(REJECT_ALL); canbus1.enhanceFilter(FIFO); canbus1.setFIFOFilter(7, 0x123, STD);
RPDOs are handled by the ISR.Code:BYTE MCOHW_PullMessage(CAN_MSG *pReceiveBuf){ // pointer to a single message sized buffer to hold the received message // variable declarations BYTE Length; BYTE i; CAN_message_t msg; if(canbus1.readMB(msg)){ pReceiveBuf->ID = msg.id; pReceiveBuf->LEN = msg.len; // Read data bytes and write to buffer for (i=0; i < msg.len; i++){ // copy bytes *(BYTE *)(pReceiveBuf->BUF+i) = msg.buf[i]; } return (1); } else { // return 0, no message received return (0); } }
The FIFO is read with this:
Everything works fine with the experimental FIFO stuff commented out. The FIFO code works as expected but when it's enabled all mboxes are blocked.Code:CAN_message_t mesg; if(canbus1.readFIFO(mesg)) { Serial.print("ID "); Serial.print(mesg.id, HEX); Serial.print(" Filter "); Serial.print(mesg.idhit, HEX); Serial.print(" LEN: "); Serial.print(mesg.len); Serial.print(" Buffer: "); for ( uint8_t i = 0; i < mesg.len; i++ ) { Serial.print(mesg.buf[i], HEX); Serial.print(" "); } Serial.println(); }
Uncommenting just the FIFO initialization blocks the mboxes.
Last edited by John Hasler; 01-30-2023 at 12:24 AM.
It appears that the FIFO grabs the first 8 mboxes even if they are already allocated.
Hi
I have taken a lot of time to find a solution for my problem. I didn't find it.
I use the following filter:
Can.setFIFOFilter(0, 0x18DAF100, EXT);
How is it possible to erase this filter to get all messages? I need this filter only for a short time.
First - filter then all messages
Thanx
Gary
Gary, based on looking at the library, try:Also, in case you weren't aware,Code:Can.setFIFOFilter(Accept_All);is an easy way to see what's going on with the mailboxes and filters.Code:Can.MailboxStatus();
Hi msadie
Thanks a lot. This is was im looking for. Perfect...
Greetings
Gary
Hello,
I am trying to run a Teensy 4.1 with two SN65HVD230 transceivers to talk to two can networks.
I have no issues with getting CAN1 working on the 125k can network, but I cant get CAN2 to connect to my 83.3k network.
I am using the Flexcan_T4 Library.
Example:
FlexCAN State: Idle, FLT_CONF: Error Active
In GetStatus gMCOHW_status = 1
Receive errors = 0
Transmit errors = 0
error.ESR1 = 40080
FlexCAN State: Receiving, FLT_CONF: Error Active
In GetStatus gMCOHW_status = 1
Receive errors = 0
Transmit errors = 0
error.ESR1 = 40008
FlexCAN State: Idle, FLT_CONF: Error Active
In GetStatus gMCOHW_status = 1
Receive errors = 0
Transmit errors = 0
error.ESR1 = 40080
gMCOHW_status = 1 means that the error variable contained no errors.
I'm using a Teensy 3.6 running my heavily-hacked version of Microcanopen (no threads or interrupts: polling only). It is sending a TPDO every millisecond and receiving an RPDO sent by this script:
while true; do sleep .001; cansend can0 307#ffffffff; done
The bus master is canopend from Canopennode running under Linux on a pc connected to the Teensy by an 8devices USB to CAN converter.
The relevant code from the Canopen implementation:
I'm using the FIFO with 8 filters allocated and with enhanceFilter(FIFO). The other mboxes are configured for transmit with TPDOs being sent via write(). It all works quite well but for this oddity.Code:uint8_t MCOHW_GetStatus(void) { CAN_error_t error; bool cerr = false, erpa = false, boff = false; int state = CO_INTERFACE_ACTIVE; // Is this the right thing to do if no errors? gMCOHW_status &= INIT; // Clear CAN status but leave INIT state unchanged if(canbus1.error(error, PRINT_ERRORS)){ // PRINT_ERRORS is defined in mco.h // Evidently returns zero quickly if there are no errors cerr = error.BIT1_ERR || error.BIT0_ERR || error.ACK_ERR || error.CRC_ERR \ || error.FRM_ERR || error.STF_ERR; if ((error.ESR1 & 0x30) == 0x0) { // Copied from FlexCAN_T4 erpa = 0; // Error active state = CO_INTERFACE_ACTIVE; } else if ((error.ESR1 & 0x30) == 0x1) { // Copied from FlexCAN_T4 erpa = 1; // Error passive Serial.println("MCOHW_GetStatus: Error passive"); state = CO_INTERFACE_LISTEN_ONLY; } else { boff = 1; // Bus off Serial.println("MCOHW_GetStatus: Bus off"); state = CO_INTERFACE_BUS_OFF; } gMCOHW_status |= cerr << 1; gMCOHW_status |= erpa << 2; gMCOHW_status |= error.TX_WRN << 3; gMCOHW_status |= error.RX_WRN << 4; gMCOHW_status |= boff << 7; Serial.print("In GetStatus gMCOHW_status = "); Serial.println(gMCOHW_status, BIN); // JGH debug Serial.print("Receive errors = "); Serial.println(error.RX_ERR_COUNTER); Serial.print("Transmit errors = "); Serial.println(error.TX_ERR_COUNTER); Serial.print("error.ESR1 = "); Serial.println(error.ESR1, HEX); } if((gMCOConfig.CANinterfaceState == CO_INTERFACE_BUS_OFF) && (state != CO_INTERFACE_BUS_OFF)) { Serial.println("MCOHW_GetStatus: Recovered from BUS_OFF"); MCO_Handle_EMCY(CO_EMC_BUS_OFF_RECOVERED); } gMCOConfig.CANinterfaceState = state; return gMCOHW_status; }
I can provide more code, of course, but the total is about 2100 lines.
Last edited by John Hasler; 03-01-2023 at 01:01 AM.
So canbus1.error() returns true, but once the errors print, there are none?
Am I understanding this correctly? If so, can you post the canbus.error() function?
The error() function is part of FlexCAN_T4.
Code:FCTP_FUNC bool FCTP_OPT::error(CAN_error_t &error, bool printDetails) { if ( !busESR1.size() ) return 0; NVIC_DISABLE_IRQ(nvicIrq); error.ESR1 = busESR1.read(); error.ECR = busECR.read(); if ( (error.ESR1 & 0x400C8) == 0x40080 ) strncpy((char*)error.state, "Idle", (sizeof(error.state) - 1)); else if ( (error.ESR1 & 0x400C8) == 0x0 ) strncpy((char*)error.state, "Not synchronized to CAN bus", (sizeof(error.state) - 1)); else if ( (error.ESR1 & 0x400C8) == 0x40040 ) strncpy((char*)error.state, "Transmitting", (sizeof(error.state) - 1)); else if ( (error.ESR1 & 0x400C8) == 0x40008 ) strncpy((char*)error.state, "Receiving", (sizeof(error.state) - 1)); error.BIT1_ERR = (error.ESR1 & (1UL << 15)) ? 1 : 0; error.BIT0_ERR = (error.ESR1 & (1UL << 14)) ? 1 : 0; error.ACK_ERR = (error.ESR1 & (1UL << 13)) ? 1 : 0; error.CRC_ERR = (error.ESR1 & (1UL << 12)) ? 1 : 0; error.FRM_ERR = (error.ESR1 & (1UL << 11)) ? 1 : 0; error.STF_ERR = (error.ESR1 & (1UL << 10)) ? 1 : 0; error.TX_WRN = (error.ESR1 & (1UL << 9)) ? 1 : 0; error.RX_WRN = (error.ESR1 & (1UL << 8)) ? 1 : 0; if ( (error.ESR1 & 0x30) == 0x0 ) strncpy((char*)error.FLT_CONF, "Error Active", (sizeof(error.FLT_CONF) - 1)); else if ( (error.ESR1 & 0x30) == 0x1 ) strncpy((char*)error.FLT_CONF, "Error Passive", (sizeof(error.FLT_CONF) - 1)); else strncpy((char*)error.FLT_CONF, "Bus off", (sizeof(error.FLT_CONF) - 1)); error.RX_ERR_COUNTER = (uint8_t)(error.ECR >> 8); error.TX_ERR_COUNTER = (uint8_t)error.ECR; if ( printDetails ) printErrors(error); NVIC_ENABLE_IRQ(nvicIrq); return 1; }
Hi, I am programming two teensys 4.1 and I am using this library. While I was programming, I was trying to check if there are any CAN messages available in my loop() like this:
void loop() {
// Check if there are any CAN messages available
if (can0.available()) {
// Read the CAN message
CAN_message_t msg;
can0.read(msg);
But there is no function "available()". Is there any function that does what I want to do or if I need to use another approach what would that be?
@jmlima44 mine works like this:
Code:#include <FlexCAN_T4.h> CAN_message_t can_fwd_car; FlexCAN_T4<CAN2, RX_SIZE_32, TX_SIZE_32> can_master; void setup() { // put your setup code here, to run once: can_master.begin(); can_master.setBaudRate(125000); } void loop() { // put your main code here, to run repeatedly: if (can_master.read(can_fwd_car)) { // do something with the data in can_fwd_car } // rest of code }