简体   繁体   中英

Declaring 2D integer array at specific memory location with C

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 X sizeof(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 2 X*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.

  1. 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 
  1. In your C code:
unsigned __attribute__((section(".shared_mem_section"))) DetSampleSet[NSENSORS][E_RING_BUFFER_SIZE];

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM