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
There were some valuable remarks concerning the MSP430. Here, my two cents concerning the array at a specified memory location:
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;
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With