I am seeking for an advice for creating a frame of unsigned char
values using a structure which is to be used in an Embedded system
application which is having less RAM.
Eg. I am having 10 bytes RAM(say). Need to create a frame(frame1)
within the RAM memory dynamically using structures in c and print
it and then free it. Then create (frame2), print and then free it
within the same 10 bytes of RAM memory. This is an interview
question for me.
My answer:
struct frame1 /* first frame */
{
unsigned char value1; /* Structure members*/
unsigned char value2;
unsigned char value3;
unsigned char value4;
/* created upto 10 values (say value10)*/
}*p;
p = (struct frame1*)malloc(sizeof(struct frame1)); /* dynamically
allocating memory for frame1 */
p->value1 = 0x10; /* Assigning values to the members */
p->value2 = 0x20;
p->value3 = 0x30;
p->value4 = 0x40;
/* Given upto 10 values */
/*print it*/
free(p);
/* Then created another structure for frame2 done the same as above
and freed it */
I am not sure what the interviewer expected from me. But I have
written based on the suggestions he gave.
The Interviewer said like it's ok to do like this in one angle. But
it looks like very basic level of code in terms of structure. So he
need to do it in advanced level. Kindly help me how to handle this.
Thanks in advance!
Related
Abstract:
I need to copy all elements of a struct containing a float array into a byte buffer, in order to send it out via UART. The next call of malloc after the copy operation leads (allways) to a hard fault, which is a good indicator that somewhere the memory gets corrupted, but I have no clue where this could happen (after 2 days debugging ...)
Description:
I have a nested Typtedef, that contains a float array:
#define DRV_SCALE_MAXSZ 32
#define DRV_CHANNELS 2
typedef struct {
float x1;
float step;
uint8_t aSz;
float Y[DRV_SCALE_MAXSZ];
} DRV_linscale_TDS;
typedef struct {
DRV_linscale_TDS scale;
uint32_t active;
} DRV_ChScale_TDS;
DRV_ChScale_TDS DRV_scale[DRV_CHANNELS] = {0,}; // Channel Scales
And I need to copy the whole content of either DRV_scale[0] or [1] into a byte buffer, in order to send it out via UART.
As a little extra complication I copy it element by element, with a copy function, that reverts the bytes of the value if necessary:
#define TXBUFSZ 255
volatile uint8_t TxBuf[TXBUFSZ] = {0,};
void FillTxBuf(uint8_t idx, uint8_t *pBo) {
if(idx < DRV_CHANNELS) {
volatile uint8_t *pDst = TxBuf;
*pDst++ = DRV_SCALE_MAXSZ;
*pDst++ = DRV_scale[idx].active;
pDst += COM_ElementCopyU32((uint8_t*)&DRV_scale[idx].scale.x1, pDst, pBo);
pDst += COM_ElementCopyU32((uint8_t*)&DRV_scale[idx].scale.step, pDst, pBo);
*pDst++ = DRV_scale[idx].scale.aSz;
uint8_t i = *pDst;
float *pSrc = DRV_scale[idx].scale.Y;
while(i--) {
pDst += COM_ElementCopyU32((uint8_t*)pSrc, pDst, pBo);
pSrc++;
}
}
}
Note: the code above is a shrinked version just for explanation. In reality TxBuf[TXBUFSZ] is a static preallocated byte buffer (declared extern in the header file, and defined in the c file)
The function COM_ElementCopyU32 looks like this:
uint8_t COM_ElementCopyU32(volatile uint8_t* pSrc, volatile uint8_t* pDst, uint8_t* ByteOrder) {
// #brief copy data from Source to Destination and revert bytes if necessary
// #param U8* pSrc: Pointer to data Source Buffer
// #param U8* pDst: Pointer to Destination Buffer
// #param U8 ByteOder: 0 = little endian, 1=big endian
// #return u16 number of copied bytes
if(pSrc && pDst) {
if(*ByteOrder != isBigEndian) {
pDst[0] = pSrc[3];
pDst[1] = pSrc[2];
pDst[2] = pSrc[1];
pDst[3] = pSrc[0];
} else {
pDst[0] = pSrc[0];
pDst[1] = pSrc[1];
pDst[2] = pSrc[2];
pDst[3] = pSrc[3];
}
}
return(sizeof(uint32_t));
}
The issue:
as soon as the line
pDst += COM_ElementCopyU32((uint8_t*)pSrc, pDst, pBo);
is involved, the call of FillTxBuf() leads to an hard fault with the next call of malloc(). The next malloc() comes immediately after FillTxBuf() when the CRC32 is appended to the byte stream. The general workflow is: check the incoming request, fill the Tx Buffer, append the CRC32 and send it out.
What have i tried to solve this so far?
Well, i tried a lot:
I removed the line mentioned above. As long i do not copy any bytes
from DRV_scale[idx].scale.Y to TxBuf[] in the while loop is
disabled, anything works fine.
I replaced float pSrc = DRV_scale[idx].scale.Y; with * float pSrc =
DebugArray; where DebugArray is a "stand alone" static pre-allocated
float array of the same size as DRV_scale[idx].scale.Y (32
Elements) and anything works fine
I tried to copy the Elements from DRV_scale[idx].scale.Y to
another float array (lets call it "DupArray"), which worked fine but
when I tried to copy "DupArray" bytewise into TxBuf[] it crashes.
and I tried to copy the Elements from DRV_scale[idx].scale.Y to
TxBuf[] in another function, right after Hardware initialisation, using the same code (copy & paste), it worked fine
I tried several versions of the DRV_linscale_TDS Typdef, with the
Byte variable at the end and at the beginning, with no effect
I checked if there would be a buffer overflow in the while loop, but
as expected there is none, as the total number of copied bytes is
~100, so there are 155 bytes "free" (note: the overrun prevention
code is still in the original code but left out here for better
readability)
I have no clue what's going on here. Each part of the code - when I debug it separatey - works fine. Copying the original Array to another float preallocated float array works fine, copying the float array to a byte array and writing it back works fine. Just if I do exactly that, whats working fine verywhere else, in that particular function, it generates a hard fault.
Through all the testing and debugging it points out clearly: the hard fault only happens, when I try to copy DRV_scale[idx].scale.Y into TxBuf[], anything else works without problems.
One might say: well, then somewhere before FillTxBuf() TxBuf[] gets corrupted, but why works anything flawless in FillTxBuf() when I use a different float array than DRV_scale[idx].scale.Y?
Remarks:
One possible workaround would most probably be to split up the struct and use separate preallocated "stand alone" float arrays. The reason why I glued it together in one variable is, that this variable is written to flash and I'd really like the approach FlashWrite(VariablePointer, SizeInBytes) ...
If there is no other option, i will have to separate it, but I'd really like to understand in which pitfall I stumbled in ...
The Question:
Where could I search?
I have no idea about the problem but you can use union to send struct data within a array. Here is an example;
typedef union
{
your struct object; (should be packed
struct)
uint8_t uartBuff[your struct size];
}unExample;
Variables in union use same memory address via this you can easily send your data.
hardfault errors always because of pointer-alingment
i usually use my own library for binary serialize in c
this library can help you
it's have examples in c and for STM32F4 already
it's support endiness and have configuration part for customization
I am writing in C on a BeagleBone Black MCU.
I need to create a 2D unsigned int array to store some collected analog data from two sensors.
Currently I have individual unsigned int arrays for each sensor's data but I'd like to change this to have one variable that is 2 dimensions with one dimension being the sensor the data originated from.
Here's what I have so far and it works just fine. (Apologies if this isn't formatting correctly. I tried to bold the code but it doesn't seem to work in Chrome the way I'd expect.)
#define SHARE_MEM 0x10000
#define E_RING_BUFFER_SIZE 200
volatile unsigned int *DetTSampleSet = (unsigned int *) SHARE_MEM;
volatile unsigned int *DetBSampleSet = (unsigned int *) (SHARE_MEM + (E_RING_BUFFER_SIZE * sizeof(unsigned int)));
I believe this code ensures that DetBSampleSet is located immediately after DetTSampleSet with no overlap. It works fine. I am able to use these variables like this.
int pnr;
for (pnr = 0; pnr <10;pnr++)
{
// do some stuff to get RawAnalog from sensor T.
DetTSampleSet[pnr] = RawAnalog;
// do some stuff to get RawAnalog from sensor B.
DetBSampleSet[pnr] = RawAnalog;
}
What I want is this.
int pnr;
for (pnr = 0; pnr <10; pnr++)
{
// do some stuff to get RawAnalog from sensor T (0)
DetSampleSet[0][pnr] = RawAnalog;
// do some stuff to get RawAnalog from sensor B (1)
DetSampleSet[1][pnr] = RawAnalog;
I think I can just declare this as the first variable in this memory space like this.
#define SHARE_MEM 0x10000
#define E_RING_BUFFER_SIZE 200
volatile unsigned int *DetSampleSet = (unsigned int *) SHARE_MEM
If I do then, I don't think I have to worry about how this data is actually structured in memory as in
are the first four bytes DetSampleSet[0][0] and the next four bytes DetSampleSet[0][1] or DetSampleSet[1][0] because I don't plan to access this data with any pointers/addresses?
However, if I want to declare another variable in memory adjacent to this variable with no overlap, do I just double the size offset like this?
volatile unsigned int *NewIntVariableAfterFirstOne = (unsigned int *) (SHARE_MEM + (E_RING_BUFFER_SIZE * 2 * sizeof(unsigned int)));
Thanks for any and all help and your patience as I'm getting back into C after nearly 30 years.
I appreciate the comments and answers. I've tried to post a response but it seems I can't comment at length but have to add to my original question. So here goes...
So, I readily admit to getting lost sometimes in the declaration of pointers like this. The original code I posted works fine. I need to declare multiple variables in this memory space so my primary concern is to declare them properly so as to not overwrite one. Basically, ensure the start of the next variable declared is past the end of the one declared prior. So, for example, if the pointer to integer variable A is to be used as a 1-D array of X elements, then Xsizeof(int) should be a safe start of the next variable, say integer variable B. Right? And if I want to use variable A as an array to be accessed as a 2-D array, then I would just do 2X*sizeof(int) to get the start of the next variable after A, right?
Supposing that it is a valid and appropriate thing in the first place, according to your C implementation, to create a pointer value in the way you are doing, what you need is a to declare your pointer as a pointer to an array, and cast appropriately:
#define SHARE_MEM 0x10000
#define E_RING_BUFFER_SIZE 200
volatile unsigned int (*DetSampleSet)[E_RING_BUFFER_SIZE] =
(unsigned int (*)[E_RING_BUFFER_SIZE]) SHARE_MEM;
You should then be able to access the block by doubly indexing DetSampleSet, just as you say you want, with all the values for DetSampleSet[0] laid out in memory contiguously, and immediately preceding those for DetSampleSet[1].
I would rather suggest to use when accessing hardware fixed size integers
You can use the pointer to array:
#define SHARE_MEM 0x10000
#define E_RING_BUFFER_SIZE 200
typedef int32_t buff[E_RING_BUFFER_SIZE];
#define DetSampleSet ((volatile buff *)SHARE_MEM)
//example usage
int32_t foo(size_t sample, size_t sensor)
{
return DetSampleSet[sensor][sample];
}
#define is used to avoid unnecessary memory reads.
https://godbolt.org/z/c45rKvvvh
EDIT. The comments have changed the requirements. You need to change linkerscript.
Add memory area (length gas to be set by you as I do not know how bit it is):
MEMORY
{
/* the stuff which was already here */
SHAREDMEM (rw) : ORIGIN = 0x10000, LENGTH = 32M
}
In the sections add new section
.shared_mem_section (NOLOAD):
{
shared_mem_section_start = .;
KEEP(*(.shared_mem_section))
KEEP(*(.shared_mem_section*))
shared_mem_section_end = .;
} > SHAREDMEM
In your C code:
unsigned __attribute__((section(".shared_mem_section"))) DetSampleSet[NSENSORS][E_RING_BUFFER_SIZE];
In build_uart_frame() , I call calcFCS() which calculates an XOR of all the bytes in the struct members(len, cmd0, cmd1 and data).
I do not think the struct is padded therefore will calling calcFCS() be an issue? Could somebody explain what is the issue in relation to struct padding as I don't understand its role here and secondly how can I do this operation correctly?
Thank you
typedef struct uart_frame {
uint8_t sof; /* 1 byte */
uint8_t len; /* 1 bytes */
uint8_t cmd0; /* 1 byte */
uint8_t cmd1;
char data[11]; /* 0 -250 byte */
unsigned char fcs; /* 1 byte */
} uart_frame_t;
//-------------------------------------------------------------------------
// Global uart frame
uart_frame_t rdata;
//-------------------------------------------------------------------------
unsigned char calcFCS(unsigned char *pMsg, unsigned char len) {
unsigned char result = 0;
while(len--) {
result ^= *pMsg++;
}
return(result);
}
//-------------------------------------------------------------------------
// Worker code to populate the frame
int build_uart_frame() {
uart_frame_t *rd = &rdata; //pointer variable 'rd' of type uart_frame
// common header codes
rd->sof = 0xFE;
rd->len = 11;
rd->cmd0 = 0x22;
rd->cmd0 = 0x05;
snprintf(rd->data, sizeof(rd->data), "%s", "Hello World");
rd->fcs = calcFCS((unsigned char *)rd, sizeof(uart_frame_t) - 1); //issue with struct padding
return 0;
}
Given your very specific example, it is unlikely that padding will be an issue, since all data types are bytes. Padding is mostly an issue when you use larger data types, because those should typically not be allocated at misaligned addresses.
Yet that is no guarantee: the compiler could in theory decide to replace a char with an int if it thinks that will get faster code. It is free to insert any amount of padding anywhere in a struct, except at the very top.
This is why structs are unsuitable to describe memory maps or data protocols. You will have to ensure that no padding is present and preferably do so portably. The best way to ensure this is a standard C compile-time assert:
_Static_assert(sizeof(uart_frame_t) == offsetof(uart_frame_t, fcs)+sizeof(unsigned char),
"Padding detected");
Here the size of the whole struct is checked against the byte position of the last struct member + the size of that member. If they are the same, there was no padding.
Now of course this only prevents your code from compiling and misbehaving, it doesn't solve the actual problem. Unfortunately there is no portable way to block padding. #pragma pack(1) is common but non-standard. __attribute__((packed)) is another compiler-specific command for this.
Ensuring that no packing is present on the given system where the code is compiled is usually enough.
Also, some of the more exotic systems (MIPS, SPARC etc) don't even support misaligned reads, meaning that misaligned access will not just mean slower code, but a run-time bus error crash.
The only way to safely ensure maximum portability of code using structs, is to write serialize/de-serialize routines that manually copies every member to/from a raw byte array:
void uart_serialize (const uart_frame_t* frame, uint8_t* raw)
{
raw[0] = frame->sof;
raw[1] = frame->len;
...
memcpy(&raw[4], frame->data, 11);
...
}
The downside of such methods is that they obviously adds some execution time, so I would only use them for code that I know needs to be ported to all kinds of different systems.
I am working on a micro controller, so, no malloc. Actually, I want to create a memory manager, so I am kinda implementing the malloc function for later use and using the BLOCK strategy to get it, like FreeRTOS does.
typedef struct BLOCK {
unsigned char used; // If 1 block is used, if 0 it's free to use
unsigned long offset; // Offset of the starting block
unsigned long size; // Size of this block
struct BLOCK * next; // Pointer to the next block
} BLOCK_t;
#define MAX_PROGRAMS 3
#define BLOCKS_NEEDED (MAX_PROGRAMS * 2) + 1
BLOCK_t blocks[BLOCKS_NEEDED]; // Not allocating 7 * sizeof(BLOCK)
This BLOCK is a linked list and I want to create (allocate) a fixed amount of them and set the first blocks[0] only. The next ones will be created in execution time, when memory is allocated.
Thanks in advance.
EDIT: In case the title is not clear enough, I want to compiler to assign some memory space to my array (fixed location and size) but I don't want to initialize it with data because I will get the data in run-time, so I want an array of 7 BLOCKs with empty data. The code above shows my attempt to do it, I declared the array, but I assume that declaring an array doesn't give you the space needed. How can I achieve this ? How can I get the compiler to give me that space ?
EDIT 2: This would be tha Java code to do it.
private static int MAX_PROGRAMS = 3;
private static int BLOCKS_NEEDED = (MAX_PROGRAMS * 2) + 1:
Block myBlockList[] = new Block[BLOCKS_NEEDED];
This get the space for myBlockList even though the list is empty and each item is uninitialized, but I have the space already.
All you want to do is allocate memory automatically on the stack.
#include <stdio.h>
#define blockcontent_size 1024
#define blockcount 3
typedef struct
{
unsigned char used;
unsigned long offset;
unsigned long size;
unsigned data[blockcontent_size];
} BLOCK;
BLOCK blocks[blockcount];
int main()
{
printf("memory available in one block %u\n", sizeof(blocks[0].data));
printf("memory used for one block %u\n", sizeof(BLOCK));
printf("memory used for all blocks %u\n", sizeof(blocks));
return 0;
}
You actually do not need a linked list, you can just use the index.
Is this close to what you are asking?
#LPs quote:
Using c writing BLOCK_t blocks[BLOCKS_NEEDED]; you are declaring the array and sizeof(BLOCK_t)*BLOCKS_NEEDED bytes are occupied by the array.
So my statement :
BLOCK_t blocks[BLOCKS_NEEDED]; // Not allocating 7 * sizeof(BLOCK)
was false, it actually does allocate the space.
I have a packet from a server which is parsed in an embedded system. I need to parse it in a very efficient way, avoiding memory issues, like overlapping, corrupting my memory and others variables.
The packet has this structure "String A:String B:String C".
As example, here the packet received is compounded of three parts separated using a separator ":", all these parts must be accesibles from an structure.
Which is the most efficient and safe way to do this.
A.- Creating an structure with attributes (partA, PartB PartC) sized with a criteria based on avoid exceed this sized from the source of the packet, and attaching also an index with the length of each part in a way to avoid extracting garbage, this part length indicator could be less or equal to 300 (ie: part B).
typedef struct parsedPacket_struct {
char partA[2];int len_partA;
char partB[300];int len_partB;
char partC[2];int len_partC;
}parsedPacket;
The problem here is that I am wasting memory, because each structure should copy the packet content to each the structure, is there a way to only save the base address of each part and still using the len_partX.
How about replacing the (:) with a 0, and add a null to the end - then you have three char * to pass around. You will need to deal with 0 length strings, but that might solve it
To avoid corrupting memory and other variables, you generally declare large data buffers as statics and place them at file scope, then allocate a separate RAM segment for them. Having them sitting on the stack is a bad idea in any embedded system.
You need to consider whether there is an alignment requirement for the CPU and whether the code should be portable or not. The compiler is free to add any number of padding bytes anywhere in that struct, meaning you may not be able to do this:
parsedPacket pp;
memcpy(&pp, raw_data, sizeof(parsedPacket )) ;
For this reason, structs are generally a bad choise for storing data packages. The safest solution is this:
/* packet.h */
typedef struct parsedPacket_struct {
uint8_t* partA;
uint8_t* partB;
uint8_t* partC;
uint16_t len_partA;
uint16_t len_partB;
uint16_t len_partC;
}parsedPacket;
#define MAX_PART_A 2
#define MAX_PART_B 300
#define MAX_PART_C 2
void packet_receive (parsedPacket* packet);
/* packet.c */
static uint8 partA[MAX_PART_A];
static uint8 partB[MAX_PART_B];
static uint8 partC[MAX_PART_C];
void packet_receive (parsedPacket* packet)
{
/* receive data from server */
...
packet->len_partA = ...;
packet->len_partB = ...;
packet->len_partC = ...;
packet->partA = partA;
packet->partB = partB;
packet->partC = partC;
memcpy(partA, A_from_server, packet->len_partA);
memcpy(partB, B_from_server, packet->len_partB);
memcpy(partC, C_from_server, packet->len_partC);
}
This can be extended to contain several static buffers if needed, ie a static array of arrays for each buffer. As you are dealing with large amounts of data in an embedded system, you can never allow the program to stack the buffers at a whim. The maximum amount of copies of a received packet must be determined during program design.
I'm not sure why you think your approach is wasting memory, but here's what I would do if I were feeling especially hacky:
typedef struct {
char *a, *b, *c;
char data[1]; // or 0 if your compiler lets you, or nothing in C99
} parsedPacket;
This is called a flexible array member. Basically, when you allocate memory for your struct, you do this:
parsedPacket *p = malloc(offsetof(parsedPacket, data[N]));
N above becomes the amount of data your array needs, i.e. how long the string you read is. This allocates the struct so that the data member has enough size for your entire string of data. Then, copy the string you recieve into this member, replace ':' characters with '\0', and set a to the first string (i.e. p->a = p->data), b to the second (p->b = p->data + strlen(p->a) + 1) and c to the third. Of course, you can make this process easier by doing it all at once:
size_t current = 0;
p->a = p->data;
p->b = p->c = NULL;
while(1)
{
int i = getc();
if(i == '\n' || i == EOF) break; // or whatever end conditions you expect
if(i == ':')
{
p->data[current] = '\0';
++current;
if(p->b == NULL) p->b = &p->data[current];
else if(p->c == NULL) p->c = &p->data[current];
else /* error */;
}
else
{
p->data[current] = i;
}
}
The type of each len_partN should be a type that can count up to the length of partN. E.g.:
typedef struct parsedPacket_struct {
char partA[300];unsigned short len_partA; // unsigned shorts have < 32k distinct values
char partB[300];unsigned short len_partB;
char partC[300];unsigned short len_partC;
}parsedPacket;
This seems like a design decision. If you want the struct to be easy to create, use the above approach, but beware its drawbacks (like "what if B has more than 300 chars?").