Home > Enterprise >  receiving and merging the file fragments over the CAN message
receiving and merging the file fragments over the CAN message

Time:04-20

I made a simple code for streaming & transferring a file over 8 bytes CAN message via the CAN Bus,

my code in c is as follows, however, my question is how to merge the fragmented file without any sequence controller? how do I check the CRC of the receiving file? since the CAN standard has its own acknowledgment, would that be sufficient for such huge streaming of a file?

typedef struct {
    union {
        struct {
            
            uint32_t extd: 1;          
            uint32_t rtr: 1;           
            uint32_t ss: 1;             
            uint32_t self: 1;            
            uint32_t dlc_non_comp: 1;   
            uint32_t reserved: 27;      
        };
        
        uint32_t flags;                 
    };
    uint32_t identifier;                
    uint8_t data_length_code;            
    uint8_t data[TWAI_FRAME_MAX_DLC];     
} CAN_message_t;

#define destinationNode 20000x

CAN_message_t msg;
              msg.identifier=destinationNode;
              msg.data_length_code=8

File date = file.open("/data.bin");
uint8_t *p=date;
 while(p){
    char buffer[8];
    memcpy(buffer, (p 8), 8);
    CAN_transmit(&msg);
    p =8; 
 }




========================================================= edit code open the file and send the size and start point to the following function and then close the file

#define SEQUENCE_START    1000000

bool stream(size_t filesize,uint8_t *p){
uint32_t identifer=SEQUENCE_START;
twai_message_t message;
 while(filesize<8) {
                    memcpy(message.data, (p 8), 8);
                    message.identifier=identifer;                 
                    message.data_length_code=8;           
                    if( twai_transmit(&messageOutRPM, pdMS_TO_TICKS(1)) == ESP_OK){
                                                                                     p =8;
                                                                                    identifer  ; 
                                                                                    filesize-=8;
                                                                                    }
                    }
 if(filesize>0)   {
                    memcpy(message.data, (p filesize), filesize);
                    message.identifier=identifer;                 
                    message.data_length_code=filesize;           
                    if( twai_transmit(&messageOutRPM, pdMS_TO_TICKS(1)) == ESP_OK) return true;
                    }  
   return true;                                
}

CodePudding user response:

how to merge the fragmented file without any sequence controller?

There is absolutely no guarantee by CAN bus that the sent frames will be received. They might have CAN errors on the bus preventing some frames to be sent out.

Automotive engineers need to send files over the CAN network in order to implement software updates. To do that, they need to send frames which are way larger than 8 bytes. They defined a small Transport Protocol on the top of CAN: ISO-15765, usually named ISO-TP.

In this protocol, the frames are sent by group. The number of elements in the group is defined during the exchange and can possibility change during the frame transfer.

To give you an example of the communication flow:

SENDER -> RECEIVER: request to send a 800 bytes frame
SENDER <- RECEIVER: accepted, please group the frames by 4
SENDER -> RECEIVER: send part 1
SENDER -> RECEIVER: send part 2
SENDER -> RECEIVER: send part 3
SENDER -> RECEIVER: send part 4
SENDER <- RECEIVER: well-received, continue
SENDER -> RECEIVER: send part 5
SENDER -> RECEIVER: send part 6
SENDER -> RECEIVER: send part 7
SENDER -> RECEIVER: send part 8
SENDER <- RECEIVER: well-received, continue but please group by 8
SENDER -> RECEIVER: send part 9
SENDER -> RECEIVER: send part 10
SENDER -> RECEIVER: send part 11
SENDER -> RECEIVER: send part 12
SENDER -> RECEIVER: send part 13
SENDER -> RECEIVER: send part 14
SENDER -> RECEIVER: send part 15
SENDER -> RECEIVER: send part 16
SENDER <- RECEIVER: well-received, continue

In order to identify which part of the frame is being transmitted, a byte is used as a frame counter. It's a rolling counter, the point is to make sure the completeness of the data. If the frames are not received in the correct order, it does not matter much, as the software is able to determine that no frame has been lost.

[...] long exchange
SENDER -> RECEIVER: FD 00 00 00 00 00 00 00  part N 0
SENDER -> RECEIVER: FE 00 00 00 00 00 00 00  part N 1
SENDER -> RECEIVER: FF 00 00 00 00 00 00 00  part N 2
SENDER -> RECEIVER: 00 00 00 00 00 00 00 00  part N 3
                    ^^
                     Rolling counter, just 1 byte

This transport layer is usually quite generic, it's frequent to see it available as a library provided by the CAN tool provider. You can also find some Open Source implementations.

since the CAN standard has its own acknowledgment, would that be sufficient for such huge streaming of a file

Actually, CAN bus has its own CRC at physical level, it should be enough for most cases. But if one want to add a custom checksum, one just need to define its length and prepend or append it to the data. Then, the receiver can re-calculate the CRC just after the completion of the transfer.

CodePudding user response:

This code is questionable for several reasons.

  • First of all, bit-fields are poorly standardized and the bit order may not be the one you expect.

  • Second, the struct as you posted it will very likely contain padding after data_length_code so writing/reading it to some binary file will be problematic and non-portable.

  • At any rate I doubt p 8 will ever be correct, because even if there is no padding sizeof(uint32_t) sizeof(uint32_t) puts us at the data_length_code member, not the data. Why would you want to copy the DLC and 7 bytes into some buffer? This is a bug.


since the CAN standard has its own acknowledgment, would that be sufficient for such huge streaming of a file?

You may want something as CRC32 to ensure there are no corruptions of the file. For the CAN transfer itself you don't need CRC since CAN comes with CRC-15 built-in.

But note that a CRC in the CAN data may be necessary in case of ugly hardware solutions with external CAN controllers. Such legacy solutions involve an exposed SPI bus which has no built-in error control what so ever. Modern electronics only use external CAN controllers in case one is stuck with some exotic MCU that must be used for other reasons, but it doesn't come with CAN on-chip.

  • Related