For an embedded system I am writing code in c to validate a received byte array based on the provided CRC. The system is active in an RTU Modbus.
In my unit test I have the following (correct) byte array:
unsigned char frame[7] = { 0x01, 0x04, 0x02, 0x03, 0xFF, 0x80, 0xF9 }
The last two bytes are the provided CRC code that I want to validate.
My approach is to split the received array into two arrays. The first array being n-2 in length and the second array being 2 in length. Afterwards, create my own CRC code based on the first array, and finally I want to validating if the second array and my own CRC code are the same.
This is the code I have right now:
bool validateCrc16ModbusFrame(unsigned char frame[])
{
// A valid response frame consists of at least 6 bytes.
size_t size = sizeof frame;
if (size < 6) {
return false;
}
// Split the frame into the 'bytes to check' and the 'provided CRC.'
int newSize = size - 2;
unsigned char* bytesToCheck = (unsigned char*)_malloca(newSize + 1); // Not sure about this line.
char providedCrc[2];
memcpy(bytesToCheck, frame, newSize * sizeof(int));
memcpy(providedCrc, &frame[newSize], 2 * sizeof(int));
// Calculate the CRC with the bytes to check.
uint16_t calculatedCrc = calculateCrc16Modbus(bytesToCheck, newSize); // This function calculates the correct CRC code.
_freea(bytesToCheck); // Not sure about this line.
// The CRC is provided as two uint8_t bytes. Convered the two uint8_t to one uint16_t.
uint8_t firstByteProvidedCrc = providedCrc[0];
uint8_t secondByteProvidedCrc = providedCrc[1];
uint16_t uint16ProvidedCrc = ((uint16_t)firstByteProvidedCrc << 8) | secondByteProvidedCrc;
// Compare the provided CRC and the calculated CRC.
bool result = uint16ProvidedCrc == calculatedCrc;
return result;
}
But when I run the test code it crashes with the message '!! This test has probaly CRASHED !!' When I debug the test code I get an exception with the message 'TestProjectName.exe has triggered a breakpoint.' I think the problem arises from creating and/or freeing the memory for the dynamic byte array.
Anyone know what I'm doing wrong?
Thanks in advance.
Kind regards, Frenk
The problem is the memcpy calls are multiplying newsize by sizeof(int), when only newsize+1 characters are allocated. They should probably be:
memcpy(bytesToCheck, frame, newSize); /* no sizeof(int) */
memcpy(providedCrc, &frame[newSize], 2); /* no sizeof(int) */
Also you don't need to copy or split the array. You can calculate the CRC on the original array including the appended CRC, and the resulting CRC will be zero if the CRC is not post complemented, or some non-zero constant value if the CRC is post complemented.
Related
I am trying to write a function which uses only pointer-based logic to search through a region of memory (baseAddr) for a certain byte (Byte), counts the occurrences, and stores the offsets in an array (Offsets). Here is what I have so far:
uint8_t findBytes( uint16_t* const Offsets, const uint8_t* const baseAddr,
uint32_t length, uint8_t Byte) {
uint8_t bytesRead = 0;
int count = 0;
while (bytesRead < length) {
if ((baseAddr + bytesRead) == Byte) {
*(Offsets + count) = bytesRead;
count++;
}
bytesRead++;
}
return count;
}
For whatever reason, I always get stuck in an infinite loop if I use (bytesRead < length). Length is always 1024. What exactly is wrong with this code? I am still learning the proper uses of pointers, so I'm 99% sure it's to do with that.
bytesRead is a uint8_t, which has a maximum value of 255. If you have a uint32_t length, your offset should be the same data type. And since potentially every byte could be a match, your count (return value) also needs to be the same type, as does the offsets array.
More problems:
if ((baseAddr + bytesRead) == Byte)
You're not dereferencing the pointer here, you're only checking its value. Your compiler should be issuing a warning here for the type mismatch.
Try:
if (*(baseAddr + bytesRead) == Byte)
Finally, you need to make sure offsets points at enough memory. Again, potentially *every byte could match, which means offsets should be the same length (in elements) as the input data.
I'm new to C and I created some code that doesn't work...
I get a warning while initLetterLib(): integer conversion resulted in truncation
I try to memcpy my libraryLetter into my outputLED, but it doesn't work.
I just get 0x00 into my outputLED.
I tried to copy something else in outputLED - this worked really fine.
But I dont get why there is a problem with my libraryLetters...
#define LETTER_WIDTH 6
typedef unsigned char letter[LETTER_WIDTH];
letter libraryLetters[128];
void initLetterLib(){
*libraryLetters[0x20] = 0x000000000000; // Blank
*libraryLetters['A'] = 0xFE909090FE00;
*libraryLetters['H'] = 0xFE101010FE00;
*libraryLetters['L'] = 0xFE0202020200;
*libraryLetters['O'] = 0xFE828282FE00;
*libraryLetters['U'] = 0xFE020202FE00;
*libraryLetters['R'] = 0xFE9894946200;
*libraryLetters['Z'] = 0x868A92A2C200;
*libraryLetters['I'] = 0x0000FE000000;
*libraryLetters['F'] = 0xFE9090808000;
}
// takes a String and generates the outputsequence for LEDs
unsigned char * stringToLEDText(char* textString)
{
static unsigned char outputLED[LED_STEPS];
unsigned char i = 0; // index
// check length of string text
unsigned short length = strlen(textString);
// if more than 10 letters are used return error
if (length > LETTERS_LED_OUTPUT)
{
printf("Error: Too much letters. Just 10 Letters are allowed\n");
return 0;
}
// through complete string
for (i = 0; i < length; i++)
{
memcpy(&outputLED[i * LETTER_WIDTH], &(libraryLetters[textString[i]]),
LETTER_WIDTH);
}
// fills rest with 0
for (i = length * LETTER_WIDTH; i < LED_STEPS; i++)
{
outputLED[i] = 0x00;
}
return outputLED;
}
Any ideas?
Thanks
Fabian
Your code doesn't make much sense. First of all, hiding an array behind a typedef is not a good idea. Get rid of that.
Using the default "primitive data types" of C is not a good idea either, since these are non-portable and of varied length. Instead use the stdint.h types. This is pretty much mandatory practice in embedded systems programming.
As for the actual problem, you can't assign an array like this
*libraryLetters[0x20] = 0x000000000000;
This doesn't make any sense. You are telling the compiler to store a 64 bit integer in the first byte of your 6 byte array. What you probably meant to do is this:
const uint8_t letters [128][LETTER_WIDTH] =
{
[0x20] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
['A'] = {0xFE, 0x90, 0x90, 0x90, 0xFE, 0x00};
...
};
Assuming this is a symbol table for some display. If so it should be const and allocated in flash.
*libraryLetters[x] is of type unsigned char and you are trying to assign a number to it outside the range of an unsigned char.
It looks like you are trying to assign a sequence of 6 bytes to *libraryLetters[x]. One way to do that is using memcpy, for example:
memcpy(libraryLetters['A'], "\xFE\x90\x90\x90\xFE\x00", 6);
You define your letter type as unsigned char which will only hold a single byte, but then you attempt to store a 6 byte integer. So you only get the last byte, which is zero in all your letters, if you want to be able to use an arbitrary length of the letter array. Otherwise, it will be much easier to use a 64-byte type, as suggested in the comments.
Instead, you should add the letters as
libraryLetters['H'][0] = 0xFE;
libraryLetters['H'][1] = 0x90;
...
Or you could use memcpy(libraryLetters['A'], letter_number, LETTER_WIDTH) as suggested by Ian Abbott.
I have a problem that I'm having difficulty solving.
I have a union that contains a buffer with a struct mapping the bits of the buffer. Something along the lines of (it is pragma packed of course):
union
uint32 buf[512]
struct
uint8_t pad[256];
uint32_t data[256];
the buf[] part is intended to be passed to the Linux spi driver as a Receive buffer. The issue I'm having is, depending on my transmits, the size of the padding I receive back is variable, and because of this it isn't straight forward to access using the union.
What i need to do is to be able to pass buf[] at a specific index to the spi driver, I.E the Rx buffer begins at buf[128] instead of buf[0]. This isn't always equal, so i have an equation that tells me where i need the start point to be which is &(buf[0]+padmax-padsize]) which should result in a value between buf[0] and buf[256]. However, the issue is the spi driver expects the argument of the transfer buffer to contain a pointer to a buffer, and passing it the straight address isn't giving me what i want.
I have also tried assigning a pointer to the address of the above equation and passing that to the rxbuffer part of the spi struct and it again doesn't give me what i want.
Is it possible to create an array that is a subset of another array, starting at a specified address of the outer array? I think this may solve my problem but I'm also afraid of the memory implications of that
The reason is most likely that you're calculating the address in 32-bit units (in units of buf elements), not bytes as you expect, based on the arithmetic.
Let's simplify the situation, and say the structure is just
#define MAX_PAD 256
#define MAX_DATA 256
struct spi_data {
uint8_t pad[MAX_PAD];
uint32_t data[MAX_DATA];
};
and that you want to implement a function similar to
size_t spi_recv(int fd, struct spi_data *ref, size_t pad, size_t data)
where
fd is the file descriptor to read() from
ref is a pointer to the struct spi_data to be used
pad is the number of padding entries filled at the end of the ref->pad[] array
data is the number of entries filled at the beginning of the ref->data[] array
the return value is the number of data entries received (completely filled)
Consider the following (argument checks for fd == -1, ref == NULL, pad > MAX_PAD, data > MAX_DATA omitted for simplicity):
size_t spi_recv(int fd, struct spi_data *ref, size_t pad, size_t data)
{
ssize_t n;
n = read(fd, &ref->pad[sizeof ref->pad / sizeof ref->pad[0] - pad],
pad * sizeof ref->pad[0] + data * sizeof ref->data[0]);
if (n == -1) {
/* Error; errno already set */
return 0;
} else
if (n < 0) {
/* Should never occur, but let's be paranoid */
errno = EIO;
return 0;
} else
if (n < pad * sizeof ref->pad[0]) {
/* Only partial padding received */
errno = 0;
return 0;
} else {
/* Zero or more data words received */
errno = 0;
return (n - pad * sizeof ref->pad[0]) / sizeof ref->data[0];
}
}
The pointer to the last pad elements of padding is
&ref->pad[sizeof ref->pad / sizeof ref->pad[0] - pad])
which is essentially equivalent to &(ref->pad[MAX_PAD - pad]), except that instead of the MAX_PAD macro, we use (sizeof ref->pad)/(sizeof ref->pad[0]) to evaluate the number of members declared for the ref->pad[] array. (This only works if ref->pad is an array; it does not work if it is a pointer.)
As usual, read() takes the number of bytes -- not elements of ref->pad or ref->data -- as a parameter, so we need to multiply the element counts by their respective element sizes in bytes; thus, the number of bytes in pad elements of padding and data elements of data is pad * sizeof ref->pad[0] + data * sizeof ref->data[0].
Since the function returns the number of complete data words received, the number of padding bytes must be subtracted from the return value, then divided by the data element type (integer division rounding down), to get the number of complete data words.
I don't think the above interface is optimal, however. I particularly dislike the possibility of the SPI transfer ending with a partial word; the above interface does not let the caller detect such a situation reliably.
If you use spidev, the ioctl() interface would be much better to use. For one, you could use SPI_IOC_MESSAGE(2) to read the padding and the data into separate buffers, or even SPI_IOC_MESSAGE(3) to write a command, followed by a read to the padding buffer and another to the data buffer. The Linux-Sunxi Wiki page has a pretty simple example of this kind of usage here, except that it uses single reads instead of reading padding into a separate buffer. However, it should be quite simple to extend the examples to do that.
I'm trying to interpret WebSocket Frames that I get over a TCP connection. I want to do this in pure C (so no reinterpret_cast). The Format is specified in IEEE RFC 6455. I want to fill the following struct:
typedef struct {
uint8_t flags;
uint8_t opcode;
uint8_t isMasked;
uint64_t payloadLength;
uint32_t maskingKey;
char* payloadData;
} WSFrame;
with the following Function:
static void parseWsFrame(char *data, WSFrame *frame) {
frame->flags = (*data) & FLAGS_MASK;
frame->opcode = (*data) & OPCODE_MASK;
//next byte
data += 1;
frame->isMasked = (*data) & IS_MASKED;
frame->payloadLength = (*data) & PAYLOAD_MASK;
//next byte
data += 1;
if (frame->payloadLength == 126) {
frame->payloadLength = *((uint16_t *)data);
data += 2;
} else if (frame->payloadLength == 127) {
frame->payloadLength = *((uint64_t *)data);
data += 8;
}
if (frame->isMasked) {
frame->maskingKey = *((uint32_t *)data);
data += 4;
}else{
//still need to initialize it to shut up the compiler
frame->maskingKey = 0;
}
frame->payloadData = data;
}
The code is for the ESP8266, so debugging is only possible with printfs to the serial console. Using this method, I discovered that the code crashes right after the frame->maskingKey = *((uint32_t *)data); and the first two ifs get skipped, so this is the first time I cast a pointer to another pointer.
The data is not \0 terminated, but i get the size in the data received callback. In my test, I'm trying to send the message 'test' over the already established WebSocket, and the received data length is 10, so:
1 byte flags and opcode
1 byte masked and payload length
4 bytes masking key
4 bytes payload length
At the point the code crashes, I expect data to be offsetted by 2 bytes from the initial position, so it has enough data to read the following 4 bytes.
I did not code any C for a long time, so I expect only a small error in my code.
PS.: I've seen a lot code where they interpret the values byte-by-byte and shift the values, but I see no reason why this method should not work either.
The problem with casting a char* to a pointer to a larger type is that some architectures do not allow unaligned reads.
That is, for example, if you try to read a uint32_t through a pointer, then the value of the pointer itself has to be a multiple of 4. Otherwise, on some architectures, you will get a bus fault (e.g. - signal, trap, exception, etc.) of some sort.
Because this data is coming in over TCP and the format of the stream / protocol is laid out without any padding, then you will likely need to read it out from the buffer into local variables byte by byte (e.g. - using memcpy) as appropriate. For example:
if (frame->isMasked) {
mempcy(&frame->maskingKey, data, 4);
data += 4;
// TODO: handle endianness: e.g.: frame->maskingKey = ntohl(frame->maskingKey);
}else{
//still need to initialize it to shut up the compiler
frame->maskingKey = 0;
}
There's two problems:
data might not be correctly aligned for uint32_t
The bytes in data might not be in the same order as your hardware uses for value representation of integer. (sometimes called "endianness issue").
To write reliable code, look at the message specification to see which order the bytes are coming in. If they are most-significant-byte first then the portable version of your code would be:
unsigned char *udata = (unsigned char *)data;
frame->maskingKey = udata[0] * 0x1000000ul
+ udata[1] * 0x10000ul
+ udata[2] * 0x100ul
+ udata[3];
This might look like a handful at first, but you could make an inline function that takes a pointer as argument, and returns the uint32_t, which will keep your code readable.
Similar problem applies to your reads of uint16_t.
I'm working on an assignment that decodes a secret message stored in a PPM format picture. The first thing i need to do is find the length of the message, which is hidden in a single byte spread across the first 8 data bytes of the picture. After I have this, my logic is to create a method where I have a loop that shifts the bits 7 spots, records the first one, and when there are 8 bits, return the char that they represent.
So right now I'm trying to understand how this would work.
I was trying to get the value for the length of the hidden message.
I tried to do this manually to see how all the bits behaved.
fgets(str,64,fp);
char length[7];
length[0] = str[7];
length[1] = str[15];
length[2] = str[23];
length[3] = str[31];
length[4] = str[39];
length[5] = str[47];
length[6] = str[55];
length[7] = str[63];
printf(length);
So since the length is hidden in the lowest level bit of 8 bytes i used fgets(str,64,fp); and then stored each 8th value in an array. This returns "enpm0dp".
When I changed the array to int, the output was an arrow.
Can someone explain to me how to store bits into a byte and then return the char that corresponds to this value? Do i use an array of 8 bits? or store them in a string?
You seem to think that fgets() counts length in bits (64 for 8 bytes), but it really doesn't; it counts in characters. See the documentation.
Next, you seem to think that str is ana rray of bits, but arrays of bits don't exist like that in C.
You're going to have to consider an array of characters, which we'll assume is bytes:
unsigned char str[8];
if(fgets(str, sizeof str, fp))
{
unsigned char length = 0, i;
for(i = 0; i < sizeof str; ++i)
{
length >>= 1;
length |= str[i] & 0x80;
}
}