4

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

nice_remark
  • 325
  • 3
  • 12
  • Sounds like XY-problem. These addresses should not change between the runs, so they can be fixed and given by the linker script. I presume you have one? Then you define your sections there. The array in question is allocated on stack at all, so it is not really clear what you are trying to do here. Perhaps copy it to a static location? – Eugene Sh. Jun 19 '18 at 17:09
  • 4
    `0x0219` - is this the real address? If so, it's unaligned. You need 2 byte alignment on the 16-bit msp430 platforms for `uint32_t`, for example, `0x0220`. – kfx Jun 19 '18 at 17:11
  • @kfx, I don't know why, but moving it to `0x0220` made it work, thanks for the tip. – nice_remark Jun 19 '18 at 17:20
  • @EugeneSh. I have modified the linker script to include the RAM_DATA section and included some `#pragma` statements which specifies that the arrays are to be stored in the RAM_DATA section – nice_remark Jun 19 '18 at 17:21
  • You need to use a Linker Command file. In that file you can specify all the details of where everything is located. Make a specific Memory Section in the linker command file for each array, then in the source code, reference the name of the Memory Section. The – user3629249 Jun 20 '18 at 16:00

1 Answers1

3

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

Scheff's Cat
  • 19,528
  • 6
  • 28
  • 56
  • this: `const uintptr_t mem_val = 0x0219;` is saying that where the pointer points is a constant value I suspect you really want: `uintptr_t const mem_val = 0x0219;` which says the pointer is a constant. – user3629249 Jun 20 '18 at 16:03
  • @user3629249 [`uintptr_t`](https://en.cppreference.com/w/c/types/integer) is an _unsigned integer type capable of holding a pointer_. This in mind, it shouldn't make a difference whether the `const` comes before or after. (`const int` is the same like `int const` in opposition to `const int*` is **not** the same like `int *const`.) – Scheff's Cat Jun 20 '18 at 16:27