CAN bus multiframe transport protocol always receive ABORT reason timeout

272 views Asked by At

I'm attempting to use a simple processor and a MCP2515 CAN controller over SPI communication. I have no problems sending or receiving single frame CAN messages. However, when I try either global BAM messaging or using the Transport Protocol, I cannot get the multiframe data through to the other side.

Example:

  • Transport Protocol J1939 / ISO11783, send TP announcement message PDU 236 (RTS)- with number bytes and number packets required, say 10 packets.
  • Receive TP clear to send (CTS) PDU 236 from receiver with OK and flagged to send all 10 packets.
  • I then send each packet in PDU 235 frames, (tried with varying time delays from 0 to 200 msec).
  • Then a short time with no response, then I get PDU 236 with ABORT code and reason timeout.

Now I thought about the MCP2515 having 3 send buffers. Perhaps as I loaded them they were sent out of sequence. So I modified the code to use buffer[0] on the MCP2515 only by waiting until that buffer is flagged as empty before loading the next frame. This should make frame sequence a certainty.

Any leads here would be appreciated. The goal is simply to get the receiving end (which is any number of manufacturer display systems) to read the data and send a EOF response showing the data was received. This is not happening as of now.

//function to organize and send multi-packets with flow control protocol
bool ISO11783DATA::sendTPCM(byte reqADDR, byte* buff, uint16_t noBytes, uint32_t PGN, byte priority)        
{
    if(busONstate == true)
    {
        RECEIVE_CTS     cts;
        MFMESSOUT       outmess;
        //load frames
        uint8_t noFrames = outmess.loadBuffers(buff, noBytes);

        uint16_t byteCounter = 0;

        cts.PGN = PGN;  //set to compare with rx messages

        ISO_TPCM_RTS(reqADDR, noFrames, noBytes, PGN, priority);    //announce multiframe header
        if(*diagnostics == true)
        {
            informln(F("sent TCPM announcement"));
            inform(F("noFrames= ")); inform(noFrames); inform(F(" noBytes= ")); informln(noBytes);
        }
        bool clearToSend = false;
        bool messageComplete = false;
        unsigned long timeOUT = millis();   //break timer

        while(messageComplete == false)
        {
            if( millis()-timeOUT > 3000UL)//1250UL)  //time out break
            {
                ISO_TPCM_ABORT(reqADDR, priority, PGN);
                if(*diagnostics == true){informln(F("tcpm send timeout error"));}
                return false;
            }

            if(clearToSend == true) //load next frame and send 
            {
                clearToSend = false;
                uint8_t frameIndex = cts.next2Send-1;//if says send#1 send index 0

                for(uint8_t cntout = 0; cntout<cts.no2Send; cntout++)
                {
                    byte bytesInMessage = 7;
                    if( frameIndex == cts.no2Send-1 ){bytesInMessage = outmess.noInLastFrame;}


                    if(*diagnostics == true)
                    {
                        inform(F("sending multipacket data number ")); informln(frameIndex+1);
                        inform("no in this frame ="); informln(bytesInMessage);
                        //inform("no in last frame ="); informln(outmess.noInLastFrame);
                        byteCounter += bytesInMessage;
                        inform(F("sent bytes= ")); informln(byteCounter);
                    }
                    ISO_TP_DATA(reqADDR, frameIndex+1, bytesInMessage+1, outmess.data[frameIndex], priority);  //send packet
                    frameIndex++;   //send number it allowed then wait for CTS again
                    timeOUT = millis();
                    //if(cts.no2Send > 1 && cntout<cts.no2Send){delay(10);} //only delay till next send time unless done
                }
            }//end CST true

            //listen for CTS EOF or ABORT
            if(pCAN0->available() > 0 ){pCAN0->readCANbus();}//checks int pin reads in and flags can buffers
            for(int n=0; n<numberCanBuffers; n++)
            {
                if(pCAN0->isoFrame[n].newData == true)
                {
                    pCAN0->isoFrame[n].newData= false;
                    int action = ID_CAN_MESSAGEinloop( pCAN0->isoFrame[n], cts );   //checks data in frame now, returns new cts info if multiframe response, since waiting must not initiate another multiframe
                    if(action == CTS && cts.PGN == PGN) //filters so response is for this node and tx message
                    {
                        timeOUT = millis(); //reset timeout since new rx message
                        clearToSend = true; //ready to send more
                    }
                    if(action == EOF && cts.PGN == PGN)
                    {
                        timeOUT = millis();//reset timeout since new rx message
                        messageComplete = true;
                        //inform("noByes "); inform(cts.bytesReceived); inform("\tnoPackets "); inform(cts.packetsReceived); inform("\PGN "); informln(cts.PGN);
                        return true;
                    }
                    if(action == ABORT && cts.PGN == PGN)
                    {
                        inform("ordered Abort   "); informln(cts.PGN);
                        return false;
                    }
                }
            }//end for check rx buffers


        }//end while mess complete false loop
    }//end if bus on
    return false;
}//end TCPM
//---------------------------------------------------------------------
//returns to state ability to load tx buffer mcp2515
bool ISO11783DATA::send_singleFrame_Buff(byte* buf, byte priority, byte PDUF, byte PDUS, byte datalength, byte datapage, int TXindex)
{
    unsigned long timeout = millis();
    CAN_ID_t out;
    out.PRIORITY     = priority;
    out.extDATAPAGE  = 0;
    out.DATAPAGE     = datapage;
    out.PDU_FORMAT   = PDUF;
    out.PDU_SPECIFIC = PDUS;
    if(nodeADDRresolved == true){out.SRC_ADDR = nodeADDR;}
    else{out.SRC_ADDR = 254;}
    out.DATA_LENGTH  = datalength;
    out.RTR          = 0;
    out.IDExt        = 1; //true
    out.buffer[0] = buf[0];
    out.buffer[1] = buf[1];
    out.buffer[2] = buf[2];
    out.buffer[3] = buf[3];
    out.buffer[4] = buf[4];
    out.buffer[5] = buf[5];
    out.buffer[6] = buf[6];
    out.buffer[7] = buf[7];
    //check if buffer ready
    while(pCAN0->sendFrame(out, TXindex) == false)
    {
        if(millis() - timeout >= 1250UL){return false;}
    }
    return true;
}//end send single frame from selected mcp2515 txbuff
//-----------------------------------------------------------------------
    bool MPC2515CANBUS::sendFrame(CAN_ID_t struc, int index)
{
    byte buffer[14];
    if(struc.IDExt > 0)
    {
        encode_CAN_TxBufferExtended(buffer, (byte)struc.PRIORITY, (byte)struc.extDATAPAGE,  (byte)struc.DATAPAGE, (byte)struc.PDU_FORMAT, (byte)struc.PDU_SPECIFIC,
                                                        (byte)struc.SRC_ADDR, struc.RTR, (byte)struc.DATA_LENGTH,
                                                        struc.buffer[7], struc.buffer[6],struc.buffer[5],struc.buffer[4],struc.buffer[3],struc.buffer[2],struc.buffer[1],struc.buffer[0]);
    }
    if(struc.IDExt == 0)
    {
        encode_CAN_TxBufferStandard(buffer, (unsigned int)struc.PGN,  (byte)struc.SRC_ADDR, struc.RTR, (byte)struc.DATA_LENGTH,
                                    struc.buffer[7], struc.buffer[6],struc.buffer[5],struc.buffer[4],struc.buffer[3],struc.buffer[2],struc.buffer[1],struc.buffer[0]);

    }
    return sendCANmessage(buffer, index);
}
//------------------------------------------------------
bool MPC2515CANBUS::sendCANmessage(byte* buffer, int index)
{
      if(checkCANTXbuf(index) != 0) //buffer not yet sent // function checks flag bit to see if buffer is empty or not
      {
          informln("txbuff not ready");
          return false;
      }
      byte ADDR;
      if(index == 0){ADDR = 0x31;}
      if(index == 1){ADDR = 0x41;}
      if(index == 2){ADDR = 0x51;}
      digitalWrite(CS_can, LOW);
      SPI.transfer(WRITE);
      SPI.transfer(ADDR);
      for(int n=0; n<13; n++){SPI.transfer(buffer[n]);}
      digitalWrite(CS_can, HIGH);
      RTSbuffer(index);
      return true;
}
//---------------------------------------------------------------------

0

There are 0 answers