collin80/esp32_can

Guru Meditation Error in `task_MCPCAN`

driftregion opened this issue · 2 comments

I wrote a callback function for CANCOMMON.setGeneralCallback. It forwards specific frames from one CAN bus to another. The base case looks like this:

void forward_frame(CAN_FRAME *frame)
{
	if (frame->id == 0xbaa)
	{
		CAN0.sendFrame(*frame);
	}
}

...

CAN1.setGeneralCallback(&forward_frame);

This works fine when forwarding frames from CAN1 (MCP) to CAN0 (native). However, when forwarding frames in the other direction, I get the following traceback reported over serial:
(Note: no CAN id's are forwarded in BOTH directions, so I'm fairly certain this isn't the result of an infinite loopback)

Guru Meditation Error: Core  0 panic'ed (InstrFetchProhibited). Exception was unhandled.
Core 0 register dump:
PC      : 0x00000000  PS      : 0x00060e30  A0      : 0x800d7aa4  A1      : 0x3ffdcd20  
A2      : 0x00000000  A3      : 0x3ffdcd60  A4      : 0x3ffc45ec  A5      : 0x00000000  
A6      : 0x3ffe6544  A7      : 0x00060623  A8      : 0x800d7a5f  A9      : 0x00000001  
A10     : 0x3ffdcd60  A11     : 0xffffffff  A12     : 0xffffffff  A13     : 0x00000001  
A14     : 0x00060e20  A15     : 0x00000000  SAR     : 0x00000000  EXCCAUSE: 0x00000014  
EXCVADDR: 0x00000000  LBEG    : 0x4000c2e0  LEND    : 0x4000c2f6  LCOUNT  : 0x00000000  

Backtrace: 0x00000000:0x3ffdcd20 0x400d7aa1:0x3ffdcd60 0x400888b5:0x3ffdcfa0

Here, decoded with EspExceptionDecoder:

PC: 0x00000000
EXCVADDR: 0x00000000

Decoding stack results
0x400d7aa1: task_MCPCAN(void*) at /home/n/Arduino/libraries/esp32_can/src/mcp2517fd.cpp line 108
0x400888b5: vPortTaskWrapper at /Users/ficeto/Desktop/ESP32/ESP32/esp-idf-public/components/freertos/port.c line 143

got it:
sendCallback is aborting because there is no callback specified for that mailbox, only a general callback. I got this to work as (i) expected it would by making the following change:

void MCP2517FD::sendCallback(CAN_FRAME_FD *frame)
{
    //frame buffer
    CANListener *thisListener;
    int mb;
    int idx;
    CAN_FRAME stdFrame;
    bool isFD = false;

    if (!fdToCan(*frame, stdFrame)) isFD = true;

    mb = (frame->fid & 0xFF);
    if (mb == 0xFF) mb = -1;

    if (frame->fid & 0x80000000ul) //object callback
    {
        idx = (frame->fid >> 24) & 0x7F;
        thisListener = listener[idx];
        if (isFD) thisListener->gotFrameFD(frame, mb);
        else thisListener->gotFrame(&stdFrame, mb);
    }
    else //C function callback
    {
        (*cbGeneral)(&stdFrame);
        // if (isFD)
        // {
        //   if (mb > -1) (*cbCANFrameFD[mb])(frame);
        //   else (*cbGeneralFD)(frame);
        // }
        // else
        // {
        //   if (mb > -1) (*cbCANFrame[mb])(&stdFrame);
        //   else (*cbGeneral)(&stdFrame);
        // }
    }
}

@collin80 , I'm closing this because I've found my mistake.
I'd like to ask: what is the intended use of a mailbox callback?

The intended use is to allow people to get targeted messages straight to a function without needing to do anything else. For instance, one might create a filter that allows a specific power train message through, say id 0x11D. With a mailbox callback you can set the library to immediately call a function in your program when 0x11D messages come in. This is just a convenience thing as obviously otherwise you could read incoming can frames and use switch/case or if blocks to process messages based on their ID.