Yes, SSM over an ISOTP layer will get you what you want.
Doing a Single "Byte" or "U8" read is very easy
The layout goes [0xA8,0x00,ptra<<16,ptra<<8,ptra]. where prta is a 24 bit point to your reading object.
This takes 5 bytes in the ISOTP layer, then 6 bytes total on CAN Physical Layer
0x7E0 [DLC=7], data{ (PCI_SINGLE<<4) + (tx->size&0x07), 0xA8,0x00,ptra<<16,ptra<<8,ptra}
This is effectively sending a "Single ISO" Frame, where the payload of the "SSM" message is 7 bytes or less.
What is complicated is when you want to ask for multiple U24 points to read larger datatypes inside the ECU.
[0xA8,0x00,ptra<<16,ptra<<8,ptra,ptrb<<16,ptrb<<8,ptrb]
lets say you want to SSM request ptra, then ptrs ( which would be 1 byte away as an example to get a U16)
This is 8 items, and thus ISOtp needs to include sending a First Frame, wait for the FLOW, then send the consecutive frames.
I ending up making an external bare metal device that does this all for me, polling for response @ 200uSec / 5khz. This then pumps up straight up CAN messages to RCP directly. Lua was going to be too slow, and requires tight coupling of the ISOtp layer.
I could consider porting and placing all of this inside a branch build of RCP, but it might be skew the product a bit and make it too specific for Subarus'.
Code: Select all
void sendIsoSingleFrame(IsoTpMessage* tx)
{
uint8_t t = 0;
if(tx->size <= 7)
{
isotp_can_tx.id = tx->id; /* standard frame */
isotp_can_tx.dlc = 8;/* Length = 8 */
isotp_can_tx.data8[0] = (PCI_SINGLE<<4) + (tx->size&0x07);
while(t<tx->size)
{
isotp_can_tx.data8[1+t] = tx->payload[t];
t++;
}
CAN_Write ( CAN_BUS1, &isotp_can_tx);
}
}
void sendIsoFlowFrame(uint32_t id, uint8_t iso_flow, uint8_t iso_block, uint8_t times)
{
isotp_can_tx.id = id; /* standard frame */
isotp_can_tx.data8[0] = (PCI_FLOW_CONTROL_FRAME<<4) + (iso_flow&0x07);
isotp_can_tx.data8[1] = iso_block;
isotp_can_tx.data8[2] = times;
isotp_can_tx.data8[3] = 0x00;
isotp_can_tx.data8[4] = 0x00;
isotp_can_tx.data8[5] = 0x00;
isotp_can_tx.data8[6] = 0x00;
isotp_can_tx.data8[7] = 0x00;
CAN_Write ( CAN_BUS1, &isotp_can_tx);
}
void sendIsoFirstFrame(IsoTpMessage* tx )
{
uint8_t t = 0;
isotp_can_tx.id = tx->id; /* standard frame */
isotp_can_tx.data8[0] = (PCI_FIRST_FRAME<<4) + ((tx->size>>8)&0x0F);
isotp_can_tx.data8[1] = ((tx->size)&0xFF);
tx->index = 1;
while(t<6)
{
isotp_can_tx.data8[2+t] = tx->payload[t];
t++;
}
tx->dataIndex += t;
CAN_Write ( CAN_BUS1, &isotp_can_tx);
}
void sendIsoConsecutiveFrame(IsoTpMessage* tx )
{
uint8_t t = 0;
isotp_can_tx.id = tx->id; /* standard frame */
isotp_can_tx.data8[0] = (PCI_CONSECUTIVE_FRAME<<4) + ((tx->index)&0x0F);
tx->index++;
if(tx->index>15)
{
tx->index = 0;
}
while((t < 7) && ((t+tx->dataIndex) < tx->size))
{
isotp_can_tx.data8[1+t] = tx->payload[t + tx->dataIndex];
t++;
}
tx->dataIndex += t;
CAN_Write ( CAN_BUS1, &isotp_can_tx);
}