-
Notifications
You must be signed in to change notification settings - Fork 36
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
swap_uint_length improperly does byte-level swap in bit mode when little endian is selected #1110
Comments
my opinion now may differ from what i wrote up in the github issue ticket above at the top of RaceCapture-Pro_firmware/src/CAN/can_mapping.c Lines 26 to 30 in b34d101
RaceCapture-Pro_firmware/src/CAN/CAN.c Lines 65 to 67 in fa3f884
The ARM cortex is little endian so at the top of the Based on the code it seems belief is that this swap_uint64 call converts the data from little to big endian. However what it is actually doing is converting from network-byte-order to host-byte-order. Which allows you to mask off certain bytes and get values that make sense when de-referenced in the host processor. However lets consider what this does to the value in memory: On the wire the CAN message is represented as 8 bytes:
So lets take the case of the E46 wheel speed sensors which use the first 8 bits of Byte1 and the first 4 bits of Byte2. If we expand what is happening in memory you are actually end up selecting the trailing 4 bits of Byte2 and all 8 bits of Byte1. so tl;dr - What I would propose is:
|
Hi eacman, This here is working well fro me: float canmapping_extract_value(uint64_t raw_data, const CANMapping *mapping)
// uint32_t raw_value = (raw_data >> (64 - offset - length)) & bitmask;
// TODO_RB: Important for non byte even values !!!
} |
When a CAN mapping is configured in bit mode and the data on the bus is formatted Least Significant Bit the
swap_uint_length
function does an endian (byte level) swap when in fact it needs to be doing a Most Significant Bit to Least Significant Bit conversion.Lets use the decimal number 4099 as an example. 4099 encoded in binary is:
1000000000011 (13 bits Most Significant Bit)
"On the wire" it will be:
1100000000001 (13 bits Least Significant Bit)
Entering the
canmapping_extract_value
function that Least Significant Bit value will be embedded in that 64bit uint somewhere (as indicated by length/offset), carved out by a bitmask to a uint_32 native to the host processor.What I believe is happening is the
swap_uint_length
is treating that 13 bit value as a 16 bit short and doing a byte swap soswap_unit_length
is basically doing the following00011000 00000001 (0-padded to 16 bit value from above)
00000001 00011000 (byte swapped)
which equals 280 not 4099
What I believe needs to happen is that the whole uint_16 needs to be shifted left to a byte boundary (in this case 3 bits) and the order of the BITS in each byte reversed. Then the bytes themselves need to be swapped.
Demonstrated:
00011000 00000001 (0-padded to 16 bit value from above)
11000000 00001000 (whole uint_16 value shifted left by 3 bits to)
00000011 00010000 (both upper and lower bytes BITS rotated)
00010000 00000011 (byte swapped)
RaceCapture-Pro_firmware/src/CAN/can_mapping.c
Line 46 in b34d101
The text was updated successfully, but these errors were encountered: