Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to place an array at a specific memory location that is provided from a variable?

For an embedded system project, an array is supposed to be placed in RAM. I have split the device's RAM into two sections, one which stores globals and other data, and another section, RAM_DATA, which I wish to store two arrays (a source location and a destination location).

There is a global value mem_val that is set to the start of the RAM_DATA address, and now wanted to make the source array begin at the location which is stored held in location.

From what I have garnered from online sources, they utilize the stdint.h header file to use uintptr_t and uint32_t values to set start of the array. When debugging the program, the array does not start at this value, and was inquiring about how to fix this problem. Here is some code that is relevant to the question.

volatile uintptr_t mem_val = 0x0219;

 int main(void)
 {
      char cur_loc[128];
      uint32_t *cur_loc = (void *)mem_val;
      ...
      return 0;
 }

Obviously there is something wrong with the array initialization and then making it pointer, but beyond that, is there a method of making the array cur_loc begin at the value given to mem_val? If it helps, I am working with a Texas Instruments MSP430 embedded device. Thank you

like image 504
nice_remark Avatar asked Oct 21 '25 04:10

nice_remark


1 Answers

There were some valuable remarks concerning the MSP430. Here, my two cents concerning the array at a specified memory location:

  1. volatile uintptr_t mem_val = 0x0219;: If I got it right the address shall be "burnt" into binary. Hence volatile doesn't make sense but const would:

    const uintptr_t mem_val = 0x0219;`

    Instead, (assuming the fix address is in an I/O range mapped into address space) it makes much more sense to mark the contents of array/pointer as volatile:

    volatile uint32_t *cur_loc = (void*)mem_val;
  2. The below is a "duplicate symbol error":

    char cur_loc[128];
    uint32_t *cur_loc = (void *)mem_val;

    Actually, the 2nd line is fully sufficient as pointers can be used like arrays. C hasn't any bound checking per standard. Hence, the pointer to uint32_t can be used like an array of uint32_t elements.

  3. With some extra parentheses, it is even possible to set the address of an array:

    volatile uint32_t (*curLoc)[128 / sizeof (uint32_t)] = (void*)mem_val;

    But, to access the array the "contents" operator has to be used always: (*curLoc)[i]. Not to mention, that the parentheses are essential (*curLoc[i] does it wrong).

So, I made a little sample (for 3. as "counter-example" and to practice my C-typing abilities):

#include <stdint.h>
#include <stdio.h>

int main()
{
  char storage[32] = {
    '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07',
    '\x08', '\x09', '\x0a', '\x0b', '\x0c', '\x0d', '\x0e', '\x0f',
    '\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17',
    '\x18', '\x19', '\x1a', '\x1b', '\x1c', '\x1d', '\x1e', '\x1f'
  };
  const uintptr_t mem_val
    = (uintptr_t)&storage; /* 0x0219 <- a fix address wouldn't work on wandbox. */
  enum { size = sizeof storage / sizeof (uint32_t) };
  printf("size: %u\n", size);
  /* using pointer */
  volatile uint32_t *pCurLoc = (uint32_t*)mem_val;
  for (unsigned i = 0; i < size; ++i) printf(" %08x", pCurLoc[i]);
  puts("");
  /* using array */
  volatile uint32_t (*curLoc)[size] = (void*)mem_val;
  for (unsigned i = 0; i < size; ++i) printf(" %08x", (*curLoc)[i]);
  puts("");
  /* done */
  return 0;
}

Output:

size: 8
 03020100 07060504 0b0a0908 0f0e0d0c 13121110 17161514 1b1a1918 1f1e1d1c
 03020100 07060504 0b0a0908 0f0e0d0c 13121110 17161514 1b1a1918 1f1e1d1c

Live Demo on wandbox

like image 172
Scheff's Cat Avatar answered Oct 22 '25 18:10

Scheff's Cat