C contiguous data arrays - arrays

Say I have 2 arrays of data:
const uint8_t data1[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
const uint8_t data2[] = {0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};
I would like to be able to read these individually, but also as one contiguous block of data.
eg: I could access data1[8] in the same way as data[0].
Reason: I have various const data definitions in some individual .c files that I'd rather not touch (font bitmaps) but I'd like to append some extra data to them (extra special characters). So I'd like to
#include <original font file>
const uint8_t extrafonts[] = {<more font bitmaps>};
Can this be done?

The only way to guarantee contiguous allocation in C is to use arrays of arrays. In this case it would seem that a const uint8_t [2][8] would solve all your problems, so use that if possible.
Otherwise, more advanced solutions could use structs and unions. These guarantee an order of allocation but come with the disadvantage that the compiler can insert padding anywhere. In this specific case it wouldn't be a problem on any real-world computer, since chunks of 8 bytes are aligned. If you have a standard C compiler, you can do this:
#include <inttypes.h>
#include <stdio.h>
typedef union
{
struct
{
uint8_t data1 [8];
uint8_t data2 [8];
};
uint8_t data [16];
} data_t;
int main (void)
{
const data_t data =
{
.data1 = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07},
.data2 = {0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f},
};
for(size_t i=0; i<16; i++)
{
printf("%.2"PRIx8" ", data.data[i]);
}
}
Now you can access the arrays individually through data.data1/data.data2 or as one, with data.data.
In cases where you worry about struct padding, you'll have to add some non-standard #pragma pack(1) or similar compiler-specific instruction.

There is another alternative that might be applicable to your use case: Use external preprocessing.
Use your favorite scripting language with some regular expression magic to read original font source file, and append extra font data at the end of array. Then save it to new file and use that in compilation instead.
This might seem a lot of work at first, but c files which are generated by tools (which I assume is the case with your font bitmaps) tend to have predictable format that is not too hard to parse.

You could probably use:
struct ArrayPair
{
uint8_t data1[8];
uint8_t data2[8];
};
const struct ArrayPair data =
{
{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 },
{ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }
};
Now you can probably get away with using:
data.data1[8]
It isn't very elegant. Your requirement is not sensible.

You said that these are 2 global arrays on different source files. So I am ignoring any options where you can group these with unions or structures.
Now the bad news: There is absolutely no guarantee that 2 global variables will end up next to each other in memory with standard C rules.
You can do this, but you need to use compiler specific extensions instead. You need to:
Use manual memory placement to place variables next to each other.
Disable any optimizations or other compiler features that might break your code because you are accessing array out of bounds.
Note that I am assuming that you are in system where resources are limited, for example, some embedded system. If that is not the case, then simply create third array, and merge 2 arrays at program startup.

Related

Defining array of bytes for use to call later in C program

Initializing a SI labs radio, the software develops a header file as well as a patch file. first part is, depending on the patch file it outputs different ways. here is a snippet of each patch:
Rev B patch:
#define SI446X_PATCH_CMDS \
{ 0x04,0x11,0xF7,0x76,0x00,0x00,0xA6,0x82 }, \
{ 0x05,0x61,0xE6,0x82,0x5E,0xB7,0xFB,0x93 }, \
{ 0x05,0x1E,0x12,0xBD,0x5A,0xC2,0x52,0x41 }, \
{ 0xE7,0xF4,0xDF,0x6A,0x24,0xD9,0xBA,0x31 }, \
OR
Rev C patch:
#define SI446X_PATCH_CMDS \
0x08,0x04,0x21,0x71,0x4B,0x00,0x00,0xDC,0x95, \
0x08,0x05,0xA6,0x22,0x21,0xF0,0x41,0x5B,0x26, \
0x08,0xE2,0x2F,0x1C,0xBB,0x0A,0xA8,0x94,0x28, \
0x08,0x05,0x87,0x67,0xE2,0x58,0x1A,0x07,0x5B, \
Now this will be hardcoded into the software and either one commented out. but it must have been done this way for a reason and i dont understand it. for initial testing i placed each line of 8 bytes (as it needs to be pushed over SPI this way) into an array and then created a pointer to the array since the length isnt necessary as they are all 8 bytes like i said. iss there a more intelligent way i should cade this based on the way it is presented?
uint8_t array_1[8] = { 0x04, 0x11, 0xF7, 0x76, 0x00, 0x00, 0xA6, 0x82 };
uint8_t array_2[8] = { 0x05, 0x61, 0xE6, 0x82, 0x5E, 0xB7, 0xFB, 0x93 };
uint8_t *theArrays[] = { array_1, array_2, array_3, array_4, array_5, array_6,
array_7, array_8, array_9, array_10, array_11, array_12, array_13,
I then program the SPI using this code and manually typed in the qty into a for loop as i cant get sizeof from the pointer array.
HAL_SPI_Transmit(&hspi1, theArrays[i], 8, 50);
These macros just make things a bit easier.
Assuming the number of (sub)arrays in both macros matches the number of arrays in your array of pointers, your code would look like this in full version:
uint8_t array_1[8] = { 0x04, 0x11, 0xF7, 0x76, 0x00, 0x00, 0xA6, 0x82 };
uint8_t array_2[8] = { 0x05, 0x61, 0xE6, 0x82, 0x5E, 0xB7, 0xFB, 0x93 };
uint8_t array_3[8] = ...
uint8_t array_4[8] = ...
uint8_t array_...
uint8_t array_12[8] = ...
uint8_t array_13[8] = ...
uint8_t *theArrays[] = { array_1, array_2, array_3, array_4, array_5, array_6,
array_7, array_8, array_9, array_10, array_11, array_12, array_13,
...
HAL_SPI_Transmit(&hspi1, theArrays[i], 8, 50);
With these macros (stored in some nice header) you can just do this:
Revision B:
#define SPI_MESSAGE_SIZE 8
const uint8_t theArray[][SPI_MESSAGE_SIZE] = {SI446X_PATCH_CMDS};
_Static_assert(sizeof theArray/sizeof *theArray == SOME_EXPECTED_SIZE, "SI446X_PATCH_CMDS corrupt");
...
HAL_SPI_Transmit(&hspi1, theArrays[i], SPI_MESSAGE_SIZE, 50);
or in case of Revision C
#define SPI_MESSAGE_SIZE 8
const uint8_t theArray[] = {SI446X_PATCH_CMDS};
_Static_assert(sizeof theArray/sizeof *theArray == SOME_EXPECTED_SIZE, "SI446X_PATCH_CMDS corrupt");
...
// For Rev C, the array contains a <length> byte before the SPI data.
// Adjust addressing accordingly
uint8_t len = theArrays[i*(SPI_MESSAGE_SIZE+1)];
HAL_SPI_Transmit(&hspi1, &theArrays[i*(SPI_MESSAGE_SIZE+1)+1], len, 50);
The static assert was suggested by Lundin. I am not aware of the correct value to compare but there should be some useful define somewhere in Silabs Radio's headers.

Determine which variable use at runtime in Embedded C

There are two different makefiles for this firmware that I am working on.
Data Version 1 and Data Version 2. Both versions are using the same file called ble_communication.c in each own make file.
To differentiate between the two versions, we have two variables declared inside ble_communication.c
static uint8_t data_version1[] = {0x00, 0x00, 0x00, 0x00, 0x00};
static uint8_t data_version2[] = {0x01, 0x00, 0x00, 0x00, 0x00};
Inside the ble_communication.c file we have a function called
uint32_t start_broadcasting(void)
{
send_beacon(OPCODE, 0, /* determine data version here to send at runtime */, key);
}
My question is since we are using the same file ble_communication.c for both versions of the build, how can the code select which variable to use for its build during the runtime of the code? If it's Data Version 1, I want it to use data_version1[] and if's is Data Version 2 it uses data_version2[].
I can't use #ifndef switch statements as I am not allowed to use them due to the new design guidelines
To be honest, I would prefer to use the #ifdef, but here is a workaround for you.
Create two files with the desired data and select the required file at build time, using the makefile.
First, prepare two C files, ble_communication_data1.c and ble_communication_data2.c. Feel free to choose a clearer name.
Place the required data in each C file, but keep the names the same.
ble_communication_data1.c
uint8_t ble_communication_data[5] = {0x00, 0x00, 0x00, 0x00, 0x00};
ble_communication_data2.c
uint8_t ble_communication_data[5] = {0x01, 0x00, 0x00, 0x00, 0x00};
Create a header file to access the data:
ble_communication_data.h
extern uint8_t ble_communication_data[5];
Modify the ble_communication.c so that it uses the common variable name:
#include "ble_communication_data.h"
uint32_t start_broadcasting(void)
{
send_beacon(OPCODE, 0, ble_communication_data, key);
}
Finally, in each of the makefiles, add the correct ble_communication_data C file to the list of files to be compiled.

How to append another HEX value at the end of an existing byte array in C

I have searched on google and checked my findings on https://www.onlinegdb.com/
But so far, I am not satisfied with my trials and errors. Perhaps, I didn't know how to ask.
I am sure that this could be already very known by many people.
Normally I am reading HEX values from UART communication and placing in a buffer array.
But, for making things simpler, I give you that code snippet;
uint8_t buffer[20] = {0x7E, 0x00, 0x07, 0xAA, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0xCC};
uint8_t newValue = 0x55;
My goal is to append newValue on buffer and that new value has to be seen after the last array value which is 0xCC in this case.
So, my question is how to do that efficiently?
Note that: One of my trials (works OK but not as I wanted);
buffer[11] = newValue ;
for(int i=0;i<sizeof(buffer);i++)
printf("%02x", buffer[i]);
But, then I need to know the position of the last value and increase the position by one which is 11 (0 based counting) in this case.

Generating machine code from C

Sorry if these are naive questions - I have very little understanding of how C really works at the low level.
So I'm generating machine code to write to some mmap'd memory for execution. I'm confused about the use of hexadecimal literals for generating machine code.
Consider the assembly instruction (AT&T syntax): cmove %edx, %ecx. This has the machine code representation 0x0F44CA.
So, would doing something like:
char opcode[3] { 0x0F, 0x44, 0xCA };
represent the correct binary string under when 'under the hood'? I suspect it might not, since apparently hexadecimal literals in C are stored as integers. My concern is that, since integers are 32-bit, the actual values getting stored are
0x0000000F 0x00000044 0x000000CA
Which is something completely different from what I need.
Another concern I have is, does the type I give to the array affect the value actually being stored? So would
uint8_t opcode[3] { 0x0F, 0x44, 0xCA };
or
int opcode[3] { 0x0F, 0x44, 0xCA };
be any different from
char opcode[3] { 0x0F, 0x44, 0xCA };
under the hood?
uint8_t opcode[3] = { 0x0F, 0x44, 0xCA };
will store your values as 8-bit values 'bytes' in the order you gave them.
It is the same as
unsigned char opcode[3] = { 0x0F, 0x44, 0xCA };
But using an 'int' type is as you said
0000000F00000044000000CA
or
0F00000044000000CA000000
depending on the endianess of your system.
I did not get your actual problem but I think these two points may help you for better understanding of machine code.
Use objdump and you will get machine code and assembly code
together to understand what is happening.
objdump -d prog.o
Read this article http://csapp.cs.cmu.edu/public/ch3-preview.pdf
I hope this will help you somewhat.

Best way to define 2 bytes for easy use with array initialization / comparing in C?

Again, I am fairly new to C so forgive the simplicity / stupidity of this question. Anyway, here it goes. What is the best way to #define a 2 byte macro (i.e. #define MSGID 0xABCD) in C that is easy to put inside a byte array but also compare the contents of with if statements?
To clarify this, take the 0xABCD example again. Say I want to do an:
unsigned char test_msg[] = { 0x00, 0x01, 0x02, MSGID, 0x03, 0x04, 0x05 };
With how I defined it above, it won't work because it's defined as a large int and gcc truncates it to an unsigned type. When I define it as #define MSGID 0xAB,0xCD it seems to work fine, but I don't understand what the comma does there and that doesn't look very clean. Another option I found that works, but also not clean, is splitting it like #define MSGIDCLASS 0xAB then #define MSGID 0xCD.
I would also like to compare these MSGID bytes and at the moment I'm having to constantly do an if(data[n] == MSGIDCLASS && data[n+1] == MSGID) ... for every message I need to parse and respond to. I was wondering if there was an easier way of doing this, that's all. If not, I'll leave it as is. Thanks again for the help. Sorry for not using the code sample tags, didn't think they were necessary with one liners.
#define's simply get replaced with their contents. So when you use commas the final code becomes:
unsigned char test_msg[] = { 0x00, 0x01, 0x02, 0xAB, 0xCD, 0x03, 0x04, 0x05 };
That's why it seems to work.
Instead, defining MSGIDHI and MSGIDLO components separately allows you to both use and compare easily. And you can define MSGID as:
#define MSGIDLO 0xCD
#define MSGIDHI 0xAB
#define MSGID (MSGIDLO | (MSGIDHI << 8))
This way you can use them in any form you want.
Sometimes you may prefer a solution without a preprocessor instead, like this:
enum {MSGID = 0xABCD};
// in C++ you can use const int MSGID = 0xABCD instead, not sure about C
unsigned char test_msg[] = { 0x00, 0x01, 0x02, MSGID>>8, MSGID&0xff, 0x03, 0x04, 0x05 };
If your message-ID's are really composed of a Class and an ID, and that separation is not just made to split them into two bytes, then you could do the following:
Keep the separate class and ID values
Use those separate val;ues to fill in in the messages
Use the following macros to compare them:
#define MSGID(msgClass, ID) (((msgClass) << 8) | (ID))
#define GET_MSGID(data, n) (((data)[n] << 8) | (data)[(n)+1])
You use them like this:
#define MSGCLASS_A 0xAB
#define MSGID_B 0xCD
unsigned char test_msg[] = { 0x00, 0x01, 0x02, MSGCLASS_A, MSGID_B, 0x03, 0x04, 0x05 };
if (GET_MSGID(test_msg, 0) == MSG_ID(MSGCLASS_A, MSGID_B))
{
// matched message
}
If your message-ID's are really just a 16-bit number, you could do the following:
Use a single define for your message-ID's
Use the following macros to insert/extract them from a message:
#define MSGID(ID) (((ID) >> 8) & 0xFF), ((ID) & 0xFF) /* For static message definitions */
#define ADD_MSGID(data, n, ID) do { (data)[n] = (((ID) >> 8) & 0xFF; (data)[(n)+1] = ((ID) & 0xFF; } while (0)
#define GET_MSGID(data, n) (((data)[n] << 8) | (data)[(n)+1])
You use them like this:
#define MSGID_A 0xABCD
unsigned char test_msg[] = { 0x00, 0x01, 0x02, MSGID(MSGID_A), 0x03, 0x04, 0x05 };
// or: ADD_MSGID(test_msg, 0, MSGID_A)
if (GET_MSGID(test_msg, 0) == MSGID_A)
{
// matched message
}
The comma in the MSGID macro is handled just like any comma separating initialisers for an array, because macros just perform a textual replacement before the compiler parses the code.

Resources