creating a data structure at specific memory location in c - c

I'm working on an embedded mcu that has two cores which can both see an area of memory beginning at 0x80000000.
The ADC is connected to one core and a radio is connected to another. I want to write the data value received by the ADC to this memory address so that the other core can read it.
Would somebody be able to help me figure out how to do this? The is no micro OS, it is bare metal.
Would I create a pointer to struct at a specific address?
I have two values in an array, how would I get them into the struct?
#define NUM_SAMPLES_POLLED (2)
uint16_t samples_polled[NUM_SAMPLES_POLLED]

In this case you'd assign the address directly to a pointer:
char *memdata = (char *)0x80000000;
Keep in mind that this behavior is implementation defined.

How can I create an array at this exact address with some values?
The C language does not define any mechanism for assigning variables to specific addresses. Indeed, no such mechanism would likely be viable in a hosted C implementation, for substantially all modern hosted implementations rely on an underlying OS with virtual memory.
Inasmuch as you are presumably writing for a freestanding implementation (given that the target is an embedded MCU), it is likely that there is a mechanism for what you ask. The one suggested by #dbush would then be a good candidate, but only by checking your documentation can you be sure.

It would be better to read your tool-chain's documentation on defining and using shared memory.

Array is not an object. Array in "c" is just a representation of data. so you cannot create it or destroy(or release it). you can just access it, i.e read and/or write.
void* ptr=(void*)0x80000000;
int* arr_of_int = (int*)ptr; //access memory location as array of int
arr_of_int[0] = 0x100; //write value to your array
int i = arr_of_int[10] ; // read value from array
or
char* arr_of_char = (char*)ptr; // access memory as array of char
arr_of_char[0] = 'A';
you have to make sure that you are actually allowed to access this address from with in your program as OS kernel(if you are running code as user program) will forbid direct physical addressing. In that case you need to use address translation function to calculate virtual address corresponding to physical address.

Related

PeekInt, PokeInt, Peek, Poke equivalent in C from BASIC

I was wondering what is the equivalent of the command Peek and Poke (Basic and other variants) in C. Something like PeekInt, PokeInt (integer).
Something that deals with memory banks, I know in C there are lots of ways to do this and I am trying to port a Basic program to C.
Is this just using pointers? Do I have to use malloc?
Yes, you will have to use pointers. No, it does not necessarily involve malloc.
If you have a memory address ADDRESS and you want to poke a byte value into it, in C that's
char *bytepointer = ADDRESS;
*bytepointer = bytevalue;
As a concrete example, to poke the byte value 0h12 to memory address 0h3456, that would look like
char *bytepointer = 0x3456;
*bytepointer = 0x12;
If on the other hand you want to poke in an int value, that looks like
int *intpointer = ADDRESS;
*intpointer = intvalue;
"Peeking" is similar:
char fetched_byte_value = *bytepointer;
int fetched_int_value = *intpointer;
What's happening here is basically that these pointer variables like bytepointer and intpointer contain memory addresses, and the * operator accesses the value that the pointer variable points to. And this "access" can be either for the purpose of fetching (aka "peeking"), or storing ("poking").
See also question 19.25 in the C FAQ list.
Now, with that said, I have two cautions for you:
Pointers are an important but rather deep concept in C, and they can be tricky to understand at first. If you've never used a pointer, if you haven't gotten to the Pointers chapter in a good C textbook, the superficial introduction I've given you here isn't going to be enough, and there are all sorts of pitfalls waiting for you if you don't learn about them first.
Setting a pointer to point to an absolute, numeric memory address, and then accessing that location, is a low-level, high-powered technique that ends up being rather rare these days. It's useful (and still commonly used) if you're doing embedded programming, if you're using a microcontroller to access some hardware, or perhaps if you're writing an operating system. In more ordinary, "applications" level programming, on the other hand, there just aren't any memory addresses which you're allowed to access in this way.
What values do you want to peek or poke, to accomplish what? What is that Basic program supposed to do? If you're trying to, for example, poke values into display memory so they show up on the screen, beware that on a modern operating system (that is, anything newer than MS-DOS), it doesn't work that way any more.
Yes, its exactly pointers.
to read from the location pointed by some pointer code value = *pointer. (peek)
to write to that location, code *pointer = value. (poke)
notice the asterisk sign before pointer.
malloc is used when you need to allocate runtime memory in heap, but its not the only way to get a memory pointer. you can get a pointer simply by using & before name of a variable.
int value = 2;
int *myPointer = &value;
remember to free any memory allocated with malloc after you are done with it. See also the valgrind tool.
also I recommend to stick with non malloc solution because of its simplicity and easy maintenance.
you can call a function many time to allocate new memory for its local variables and work with them.
The concept of peek/poke (to directly access memory) in C is irrelevant - you probably don't need them and if you do you really should ask a specific question about the code you are trying to write. If you are building 32 or 64 bit code for a modern platform, peek() / poke() are largely irrelevant in any event and unlikely to do what you expect - unless you expect a memory protection fault! You will be digging out some antique compiler if you are building 16-bit x86 "real-mode" code.
C is a systems-level language and as such operating directly on memory fundamental to the language. It is also a compiled rather than interpreted language and you would normally access a memory location through a variable/symbol and let the linker resolve/locate its address. However in some cases (in embedded systems code or kernel level device drivers for example) you might need to access a specific physical address which you might do as follows:
#include <stdint.h>
const uint16_t* const KEYBOARD_STATE_FLAGS_ADDR = ((uint16_t*)0x0417) ;
...
// Peek keyboard state
keyboard_flags = *KEYBOARD_STATE_FLAGS_ADDR ;
If you really want functions to observe/modify arbitrary address locations then for example:
uint16_t peek16( uint32_t addr )
{
return *((uint16_t*)addr) ;
}
void poke16( uint32_t addr, uint16_t value )
{
*((uint16_t*)addr) = value ;
}
... and perhaps corresponding implementations for 8, 32 and even 64 bit access. However good luck avoiding a SEG-FAULT exception on a modern system where memory is virtualised and protected - as I said it largely makes no sense.
Something that deals with memory banks,
I assume given the [qbasic] tag that you are referring to 16-bit x86 segment:offset addressing rather than "memory banks" - that is an architecture specific thing, irrelevant on modern systems. If you really need to deal with that (i.e. are targeting 16-bit x86 C code), you need to mention that - it is a very different issue, specific to a particular obsolete architecture. You would also need to specify what compiler you are using, because it involves non-standard compiler extensions (and to be frank, techniques I have long forgotten; it would be software archaeology).
Is this just using pointers?
Essentially yes, in C pointers are addresses, but in 16-Bit x86 code there is the added complication of the segmented memory architecture and the concept of near and far pointers. If you are porting this code to a modern system, it is unlikely to be a simple matter of porting peek/poke commands verbatim - they are unlikely to work. If you are are just translating 16-bit QBasic code to 16-bit C - why?!
Do I have to use malloc?
No - or at least that depends on the semantics of the code you are porting, but unlikely, and it is not relevant to peek/poke specifically. malloc allocates memory from a system heap and provides its address - which is non-deterministic. peek/poke are a means of accessing specific memory addresses.
In the end it is probably not a matter of directly implementing the peek/poke commands in the code you are porting, and whether that would work or not would depend on the platform and architecture you are porting the code to. Most likely you would be better off looking at the higher level semantics of the code you are porting and implementing that in a manner that suits the platform you are targeting or better be platform independent and therefore portable.
Basically when porting you should ask your self what does this bit of code do, and port that rather than a line-by-line translation. And that consideration should be done at as high a level as possible to make the best use of the target language an/or its library. peek/poke were typically used for either accessing machine features no exposed through some higher lever interface, or for directly accessing hardware or video-buffers. On a modern platform much of that is either unnecessary or won't work - and probably both.

Is it possible to allocate a single byte of memory at a specific address?

Is it possible to allocate a single byte of memory at a specific desired address, say 0x123?
This suggests follow up questions:
Is it possible to know if a specific address has already been malloced?
Some complications could be:
The byte at the desired address 0x123 was already malloc'ed. In this case, can I move the byte value elsewhere and notify the compiler (or whatever's keeping track of these things) of the new address of the byte?
The byte at the desired address 0x123 was malloc'ed along with other bytes. E.g. char *str = malloc(8); and str <= 0x123 < str + 8, or in other words, 0x123 overlaps some portion of already malloc'ed memory. In this case, is it possible to move the portion of malloc'ed memory elsewhere and notify the compiler (or whatever's keeping track of these things)?
There are also several variations:
Is this possible if the desired address is known at compile time?
Is this possible if the desired address is known at run time?
I know mmap takes a hint addr, but it allocates in multiples of the pagesize and may or may not allocate at the given hint addr.
It is possible to assign a specific value to a pointer as follows:
unsigned char *p = (unsigned char *)0x123;
However dereferencing such a pointer will almost certainly result in undefined behavior on any hosted system.
The only time such a construct would be valid is on an embedded system where it is allowed to access an arbitrary address and the implementation documents specific addresses for specific uses.
As for trying to manipulate the inner workings of a malloc implementation, such a task is very system specific and not likely to yield any benefit.
The are operating-system-specific ways to do this. On Windows, you can use VirtualAlloc (with the MEM_COMMIT | MEM_RESERVE flags). On Linux, you can use mmap (with the MAP_FIXED_NOREPLACE flag). These are the operating system functions which give you full control over your own address space.
In either case, you can only map entire pages. Addresses only become valid and invalid a page at a time. You can't have a page that is only half valid, and you can't have a page where only one address is valid. This is a CPU limitation.
If the page you want is already allocated, then obviously you can't allocate it again.
On both Windows and Linux, you can't allocate the first page. This is so that accesses to NULL pointers (which point to the first page) will always crash.
Is it possible to allocate a single byte of memory at a specific desired address, say 0x123?
Generally: no. The C language doesn't cover allocation at specific addresses, it only covers how to access a specific address. Many compilers do provide a non-standard language extensions for how to allocate at a fixed address. When sticking to standard C, the actual allocation must either be done:
In hardware, by for example having a MCU which provides a memory-mapped register map, or
By the system-specific linker, through custom linker scripts.
See How to access a hardware register from firmware? for details.
malloc doesn't make any sense in either case, since it exclusively uses heap allocation and the heap sits inside a pre-designated address space.

Access to a specific memory address

I'm a new C programmer, still learning the language itself.
Anyway -
I'm trying to access a specific memory address.
I've written this code:
#include <stdio.h>
int main()
{
int* p = (int*) 0x4e0f68;
*p = 12;
getchar();
}
When I try to access a specific memory address like that, the program crashes.
I don't know if this information is relevant, but I'm using Windows 7 and Linux Ubuntu.
(I've tried this code only on Windows 7).
Any explanations why the program crashes?
How can I access a specific memory address (an address which is known at compile-time, I don't mean to dynamic memory allocation)?
Thanks.
That's memory you don't own and accessing it is undefined behavior. Anything can happen, including crashing.
On most systems, you'd be able to inspect the memory (although technically still undefined behavior), but writing to it is a whole different story.
Strictly speaking you cannot create a valid pointer like this. Valid pointers must point to valid objects (either on your stack or obtained from malloc).
For most modern operating systems you have a virtual memory space that only your process can see. As you request more memory from the system (malloc, VirtualAlloc, mmap, etc) this virtual memory is mapped into real usable memory that you can safely read and write to. So you can't just take an arbitrary address and try to use it without OS cooperation.
An example for windows:
#include <windows.h>
#include <stdio.h>
int main(void)
{
SYSTEM_INFO sysinfo;
GetSystemInfo(&sysinfo);
unsigned pageSize = sysinfo.dwPageSize;
printf("page size: %d\n", pageSize);
void* target = (void*)0x4e0f68;
printf("trying to allocate exactly one page containing 0x%p...\n", target);
void* ptr = VirtualAlloc(target, pageSize, MEM_COMMIT, PAGE_READWRITE);
if (ptr)
printf("got: 0x%p\n", ptr); // ptr <= target < ptr+pageSize
else
printf("failed! OS wont let us use that address.\n");
return 0;
}
Note that this will give you different results on different runs. Try it more than once.
Just to clrify one phrase the OP wrote: strictly speaking, no address associated to a program (code or data) is known at compile time. Programs usually are loaded at whatever address the OS determines. The final address a program sees (for example, to read a global variable) is patched by the OS in the very program code, using some sort of relocation table. DLL functions called by a program have a similar mechanism, where the IDATA section of the executable is converted into a jump table to jump to the actual address of a function in a DLL, taking the actual addresses from the DLL in memory.
That said, it is indeed possible to know by advance where a variable will be placed, if the program is linked with no relocation information. This is possible in Windows, where you can tell the linker to load the program to an absolute virtual address. The OS loader will try to load your program to that address, if possible.
However, this feature is not recommended because it can lead to easily exploiting possible security holes. If an attacker discovers a security hole in a program and try to inject code into it, it will be easier for him if the program has all its variables and functions in specific addresses, so the malicious code will know where to make patches to gain control of that program.
What you're getting is a segfault - when you're trying to access memory you don't have permission to access. Pointers, at least for userspace, must point to some variable, object, function, etc. You can set a pointer to a variable with the & operator - int* somePtr = &variableToPointTo, or to another pointer - int* someNewPtr = somePtr. In kernel mode (ring 0) or for OS development, you can do that, BUT IT IS NOT ADVISED TO DO SO. In MS-DOS, you could destroy your machine because there was no protection against that.

How to store a variable at a specific memory location?

As i am relatively new to C , i have to use for one of my projects the following:
i must declare some global variables which have to be stored every time the program runs at the same memory address.
I did some read and i found that is i declare it "static" it will be stored at the same memory location.
But my question is: can i indicate the program where to store that variable or not.
For example : int a to be stored at 0xff520000. Can this thing be done or not? i have searched here but did not found any relevant example. If their is some old post regarding this, please be so kind to share the link .
Thank you all in advance.
Laurentiu
Update: I am using a 32uC
In your IDE there will be a memory map available through some linker file. It will contain all addresses in the program. Read the MCU manual to see at which addresses there is valid memory for your purpose, then reserve some of that memory for your variable. You have to read the documentation of your specific development platform.
Next, please note that it doesn't make much sense to map variables at specific addresses unless they are either hardware registers or non-volatile variables residing in flash or EEPROM.
If the contents of such a memory location will change during execution, because it is a register, or because your program contains a bootloader/NVM programming algorithm changing NVM memory cells, then the variables must be declared as volatile. Otherwise the compiler will break your code completely upon optimization.
The particular compiler most likely has a non-standard way to allocate variables at specific addresses, such as a #pragma or sometimes the weird, non-standard # operator. The only sensible way you can allocate a variable at a fixed location in standard C, is this:
#define MY_REGISTER (*(volatile uint8_t*)0x12345678u)
where 0x12345678 is the address where 1 byte of that is located. Once you have a macro declaration like this, you can use it as if it was a variable:
void func (void)
{
MY_REGISTER = 1; // write
int var = MY_REGISTER; // read
}
Most often you want these kind of variables to reside in the global namespace, hence the macro. But if you for some reason want the scope of the variable to be reduced, then skip the macro and access the address manually inside the code:
void func (void)
{
*(volatile uint8_t*)0x12345678u = 1; // write
int var = *(volatile uint8_t*)0x12345678u; // read
}
You can do this kind of thing with linker scripts, which is quite common in embedded programming.
On a Linux system you might never get the same virtual address due to address space randomization (a security feature to avoid exploits that would rely on knowing the exact location of a variable like you describe).
If it's just a repeatable pointer you want, you may be able to map a specific address with mmap, but that's not guaranteed.
Like was mentioned in other answers - you can't.
But, you can have a workaround. If it's ok for the globals to be initialized in the main(), you can do something of this kind:
int addr = 0xff520000;
int main()
{
*((int*)addr) = 42;
...
return 0;
}
Note, however, that this is very dependent on your system and if running in protected environment, you'll most likely get a runtime crash. If you're in embedded/non-protected environment, this can work.
No you cannot tell it explicitly where to store a variable in memory. Mostly because on modern systems you have many things done by the system in regards to memory, that is out of your control. Address Layout Randomization is one thing that comes to mind that would make this very hard.
according your compiler if you use XC8 Compiler.
Simply you can write int x # 0x12 ;
in this line you set x in the memory location 0x12
Not at the C level. If you work with assembly language, you can directly control the memory layout. But the C compiler does this for you. You can't really mess with it.
Even with assembly, this only controls the relative layout. Virtual memory may place this at any (in)convenient physical location.
You can do this with some compiler extensions, but it's probably not what you want to do. The operating system handles your memory and will put things where it wants. How do you even know that the memory address you want will be mapped in your program? Ignore everything in this paragraph if you're on an embedded platform, then you should read the manual for that platform/compiler or at least mention it here so that people can give a more specific answer.
Also, static variables don't necessarily have the same address when the program runs. Many operating systems use position independent executables and randomize the address space on every execution.
You can declare a pointer to a specific memory address, and use the contents of that pointer as a variable I suppose:
int* myIntPointer = 0xff520000;

Can we assign a value to a given memory location?

I want to assign some value (say 2345) to a memory location(say 0X12AED567). Can this be done?
In other words, how can I implement the following function?
void AssignValToPointer(uint32_t pointer, int value)
{
}
The fact that you are asking this question kind of indicates that you're in over your head. But here you go:
*(int *)0x12AED567 = 2345;
The answer depends on some factors. Is your program running on an operating system? If yes, does the OS implement memory segmentation?
If you answered yes to both questions, trying to access a memory area that is not mapped or that it doesn't have permission to write will cause a memory access violation (SIGSEGV on POSIX based systems). To accomplish that, you have to use a system specific function to map the region of memory that contains this exact address before trying to access it.
Just treat the memory location as a pointer
int* pMemory = OX12AED567;
*pMemory = 2345;
Note: This will only work if that memory location is accessible and writable by your program. Writing to an arbitrary memory location like this is inherently dangerous.
C99 standard draft
This is likely not possible without implementation defined behavior.
About casts like:
*(uint32_t *)0x12AED567 = 2345;
the C99 N1256 standard draft "6.3.2.3 Pointers" says:
5 An integer may be converted to any pointer type. Except as previously specified, the
result is implementation-defined, might not be correctly aligned, might not point to an
entity of the referenced type, and might be a trap representation. 56)
GCC implementation
GCC documents its int to pointer implementation at: https://gcc.gnu.org/onlinedocs/gcc-5.4.0/gcc/Arrays-and-pointers-implementation.html#Arrays-and-pointers-implementation
A cast from integer to pointer discards most-significant bits if the pointer representation is smaller than the integer type, extends according to the signedness of the integer type if the pointer representation is larger than the integer type, otherwise the bits are unchanged.
so the cast will work as expected for this implementation. I expect other compilers to do similar things.
mmap
On Linux you can request allocation of a specific virtual memory address](How does x86 paging work?) with the first argument of mmap, man mmap reads:
If addr is NULL, then the kernel chooses the (page-aligned) address at which to create the mapping; this is the most portable method of creating a new mapping. If addr is not NULL, then the kernel takes it as a hint about where to place the mapping; on Linux, the kernel will pick a nearby page boundary (but always above or equal to the value specified by /proc/sys/vm/mmap_min_addr) and attempt to create the mapping there. If another mapping already exists there, the kernel picks a new address that may or may not depend on the hint. The address of the new mapping is returned as the result of the call.
So you could request for an address and assert that you got what you wanted.
As far as C is concerned, that's undefined behaviour. My following suggestion is also undefined behaviour, but avoids all the type-based and aliasing-based problems: Use chars.
int a = get_value();
char const * const p = (const char * const)&a;
char * q = (char *)0x12345;
memcpy(q, p, sizeof(int));
Alternatively, you can access bytes q[i] directly. (This is the part that is UB: the pointer q was not obtained as the address-of an actual object or as the result of an allocation function. Sometimes this is OK; for instance if you're writing a free-standing program that runs in real mode and accesses the graphics hardware, you can write to the graphics memory directly at a well-known, hard-coded address.)
You've indicated, that the address is a physical address, and that your code is running in a process.
So if you're
in kind of high level operating system, e.g. Linux, you'd have to get a mapping into the physical address space. In Linux, /dev/mem does that for you.
within the kernel or without operating system and with a MMU, you have to translate the physical address into a virtual address. In the Linux kernel, phys_to_virt() does that for you. In the kernel, I assume, this address is always mapped.
within the kernel or without operating system and without MMU, you write directly to that address. There's no mapping to consider at all.
Now, you have a valid mapping or the physical address itself, that you pass to your function.
void AssignValToPointer(uint32_t pointer, int value)
{
* ((volatile int *) pointer) = value;
}
You might want to add the volatile keyword as the compiler might optimize the write-operation away if you do not read from that location afterwards (likely case when writing to a register of a memory-mapped hardware).
You might also want to use the uintptr_t data type instead of uint32_t for the pointer.
With the proviso that it's not portable or safe (at all):
*((int *)0x12AED567) = 2345;

Resources