#define RegisterX_Address (*((volatile unsigned int*)0x400253FC))
I need to understand what this (*((volatile unsigned int*)0x400253FC)) in C, I understands that is a pointer pointing to the address of one of the registers but why is it written like this???
On whatever platform this is, memory address 0x400253FC contains 1 int worth of data.
If you dereference 0x400253FC, you get that value.
This is likely used for something like:
unsigned int GetCPUTemperature()
{
unsigned int temp;
temp = RegisterX_Address;
return temp;
}
It is not terribly common to have data mapped directly to a specific memory address, but happens in embedded development regularly.
The volatile keyword tells the compiler it cannot cache, store or reuse the value it gets. It must retrieve the value from memory on each access, because whatever is writing data there will update the value regularly and outside the scope of the program.
It's a macro to access a (probably) memory-mapped I/O pin.
The compiler or hardware itself knows that specific addresses of memory have an additional purpose. When your source code reads from that register it's really reading the value off of an input pin, a wire hooked up directly to the processor. That address is special, and these sort of things are typically exclusively tied to that particular hardware. (Which is why you need a shmorgas board of different drivers for different hardware and they're not all conveniently interchangeable). For all the misdirection and generalization that higher levels perform, at some point you need to direct read and writes to actual hardware with actual addresses.
The inner * is declaring it as a pointer. The outer * is dereferencing it. And yeah, pointers in C are one of the most confusing parts of the language. The * symbol has two jobs really; one is during declarations, where it describes a chunk of data. And explicitly casting is declaration: (volatile unsigned int*). That forces the compiler to treat the hex value as a pointer to a volatile unsigned integer. The second, in execution when using this macro: *(myPointer), that pointer is dereferenced, so rather than using the value 0x400253FC, you're looking at the data that lives at ADDRESS 0x400253FC in memory. Which isn't even memory since it's probably mapped to HW. (It depends. Either way it's still called a register in ICDs. I think of registers as the specific registers on the chip, what assembly can use directly as opposed to going through the MMU. But everything is a "register" to the HW guys, they use it like we use "address").
And I'm guessing it's an I/O pin because it's volatile. This a an instruction to the compiler not to make presumptions when optimizing because it's value can change behind it's back. Like when hardware gets a signal. Or when an output line automatically resets low. Volatile variables are also used for shared memory between threads, but on a microcontroller it's typically I/O.
Just try it:
#define RegisterX_Address (*((volatile unsigned int*)0x400253FC))
unsigned int fun ( void )
{
return(RegisterX_Address);
}
gives:
00000000 <fun>:
0: 4b01 ldr r3, [pc, #4] ; (8 <fun+0x8>)
2: 6818 ldr r0, [r3, #0]
4: 4770 bx lr
8: 400253fc
It is simpler to write than:
volatile unsigned int *RegisterX_Address;
RegisterX_Address = (volatile unsigned int *)0x400253FC;
return(*RegisterX_Address);
That is why it is written that way. Plus as written it doesn't consume memory as a variable.
It is written like that because that is what happens to work on the particular compilers used with that particular microcontroller. Most likely, the volatile serves as an indication to the compiler that it shouldn't make optimizations that would result in not actually reading the hardware register.
Related
I am creating an emulator for an instruction set architecture, and I needed to implement a stack structure. I decided that my %eip, %ebp and %esp would be int pointers. However, there are situations where I need to store memory addresses on the stack, in which case this memory would be encoded as an integer value. But when I return this value, I need to put it back into my instruction pointer, which is implemented as an int pointer. C will not let me assign my integer to my int pointer, so I have no way of recovering these memory addresses from the "stack". Any suggestions?
To assign an int value to an int * object, use an explicit cast, as in:
destination = (int *) source;
Your question says “C will not let me assign my integer to my int pointer” but fails to state exactly what the problem is. Presumably you are getting some diagnostic message from the compiler. This would be because assigning an int value to an int * object violates the C standard’s constraints for assignments. The code above shows how to work around that.
That solves the immediate problem of the compiler diagnostic. However, there can be various issues with using int values as containers for pointers, including the possibility of trap values and discrepancies between the sizes of pointers and integers. Provided that int and int * are the same size, using an int to hold an int * is not unlikely to work, but you should be sure of the properties of your C implementation.
I decided that my %eip, %ebp and %esp would be int pointers.
This is not a sound architectural decision. You need to reconsider it.
The size of a pointer is architecture-dependent -- in particular, an int * will be 64 bits wide on a 64-bit system. By contrast, all of these registers are 32 bits wide by definition. Using a 64-bit pointer to store their values will result in unexpected behavior.
These registers are not required to be aligned to an integer. In particular, EIP is (at best) aligned to an instruction, and will be incremented by one byte when running 1-byte instructions. Deferencing an int * which is not properly aligned will cause an unaligned access fault on many systems.
There is no hard architectural distinction between any of the integer registers (EA/B/C/DX, ESP, EBP, ESI, EDI). All of them can be referenced in an ModRM encoding, and can be treated as either a numeric value or an address, depending on the context. Singling ESP and EBP out will unnecessarily complicate your emulator, and is likely to create a lot of obnoxious special cases in your code.
Note that, as you are emulating a 32-bit system on what might not be a 32-bit platform, you will need some way of translating addresses within the emulated system to "real" addresses in the host process. There are a number of different ways of doing this; which one is most appropriate for you will depend on your specific goals.
It is implementation defined but if the integer width is not smaller than the pointer - you can use it this way.
Some people say that the using ptrdiff_t and NULL pointer as a reference is more portable and safer.
ptrdiff_t myptrdiff = myptr - (type_of_myptr *)NULL;
myptr = myptrdiff + (type_of_myptr *)NULL;
I am trying to access the PMC_PCER0 and enable it for PID14 on an ARM Cortex M3. I am asked to make a void function that reads a button and "returns" (as my professor insists to call it) its value. Anyway, here is the problem:
void readButton( unsigned int *button)
{
do something yo;
}
I have an address for PMC_PCER0 and let's suppose for the sake of the question it is at 0xfff123da and this PMC_PER0 has 32 PIOs, one of which is PID and happens to start at the 14th place, so I need to activate this one.
In order to activate it, do I need to mask PMC_PCER0 using the `or operator?
I know I can define PMC_PCER0 as follows
#define PMC_PCER0 (0xfff123da)
However, this will just give PMC_PCER0 the value of 0xfff123da, but what I want to do is PMC_PCER0 to actually have that address. And later I want to mask it. I'd appreciate it if you explained it in details.
so how do you load or store something at some address in C? You need an array or pointer right? How do you assign a pointer an address?
unsigned int *p;
...
p = (unsigned int *)0x12345678;
And then *p = 10; will write a 10 to that address right? or p[0] = 10;, elementary C language programming, has nothing to do with microcontrollers or operating systems.
The problem you end up with though is optimizers. if *p or p[0] is not used later then there is no reason at all to generate code. even if it does generate code there is no guarantee that it actually does the store or load
void myfun ( unsigned int x )
{
unsigned int *p;
p = (unsigned int *)0x12345678;
*p = x;
}
How do you tell the compiler or how do you use the language to ask the compiler to actually do a memory operation?
volatile unsigned int *p;
p = (unsigned int *)0x12345678;
so try making your define look something like this
#define PMC_PCER0 (*((volatile unsigned int *)0xfff123da))
AND understand that that is still not a guarantee that the 1) compiler will do a bus operation 2) that the bus operation will be the size you desire. if you want to guarantee such things then instead
#define PMC_PCER0 (0xfff123da)
and make a small asm file to link into the project, or put this in your bootstrap.
.thumb_func
.globl PUT32
PUT32:
str r1,[r0]
bx lr
.thumb_func
.globl GET32
GET32:
ldr r0,[r0]
bx lr
and then use it
void myfun ( unsigned int x )
{
PUT32(PMC_PCER0,x);
}
This has a performance cost, but it has significant benefits as well, first off being the compiler if remotely compliant must perform the function calls in order and all of them. so you are insured you get your load or store and you are insured it is of the right size. Second all of your accesses to peripherals and other special addresses are controlled through an abstraction layer that when placed on a chip simulator or on top of a operating system, or when doing your own testing against a handmade test bench (emulator) you already have an abstraction layer at the C function level that is easy to port. if you want to debug what is going on, you can use this abstraction layer to insert breakpoints or printfs or whatever.
Take it or leave it, it took me years to trip up the compiler into not generating the right instructions using the volatile trick. If you dont learn at least a little assembly language, and dont regularly disassemble the tool produced code, you will struggle more than necessary when something goes wrong like the wrong instruction being generated by the compiler or items being loaded to the wrong places by the linker (chip doesnt boot, program hangs, etc). THEN with that how to move the toolchain past the problem.
Yes I know your desired function is a load not a store, I assume you can figure it out from here.
This was all elementary C language programming stuff, possibly why nobody wanted to jump in and answer. Also the libraries that come free for the microcontroller you are using and for all other families and brands uses these kinds of tricks although some of them are a bit scary so take them with a grain of salt (or use them as a reference and not necessarily directly as you may end up owning their issues and maintenance).
i have limited RAM in my microController.(using arm gcc)
i should write my code as efficient as possible. consider function blew :
int foo(uint32_t a , float b)
{
.....
return 0;
}
so I have two arguments a and b. now if I change the arguments to *a and *b is the function takes less ram than the first function during execution :
int foo(uint32_t *a,float *b)
{
....
return 0;
}
what if the arguments become String or array ( of int, float ....)??
any references would be great. thanks
You can actually waste memory when using pointers. This is for 2 reasons.
1. Register optimization lost
Code which calls foo must take address of the variable to pass as parameter. If passed variable is local, it could be in register but because you take its address it must be placed on stack. In general, using variable in register is faster than using variable in stack.
2. Value of variable unknown after call
When you give address of variable function, compiler no longer knows if variable is modified, and must refresh it if it's read again.
uint32_t u = 1;
float f = 2.0f;
foo(&u, &f); // 1. Address taken, u and f cannot be register variables
// 2. What is value of u now? It must refreshed from memory before addition happens
u++;
Bottom line: do not take address of primitive types unless you have to.
Strings and arrays are already passed using address, so there is no other option.
ARM's Procedure Call Standard defined in Application Binary Interface (ABI) states that the first four word-sized parameters passed to a function will be transferred in registers R0-R3.
Since pointers are also 32-bit in size, there is not that much difference between these two signatures.
int foo(uint32_t a, float b)
int foo(uint32_t *a, float *b)
Both will have a in r0, b in r1 and return value in r0 again.
ARM is a RISC architecture it has many registers and with trivial functions you may even get away from touching any memory at all.
If you are working with micro controllers it is a better idea to check if you should really use floating points. Since they might not be natively supported by the core you are targeting for.
I would check ARM Cortex-A Series Programmer's Guide (most of it applies to micro controllers as well), especially chapters 15 and 17 to learn more about tricks for ARM application development.
I met this question in an interview. I have no such experience.
So if we have two registers. One with address 0x11111111 and the other 0x22222222. We want to read and write it. The first one is a 32-bit register while the second one is 64-bit. How do we do it in C? Can anyone just give me an example?
Thanks,
You can use some kind of pointer or other, for example:
#include <stdint.h>
uint32_t volatile * p = (uint32_t volatile *) 0x11111111;
uint64_t volatile * q = (uint64_t volatile *) 0x22222222;
++*p; // read-modify-write
(Note that this specific example is almost certainly bogus, since neither address seems to be aligned properly for the respective type.)
As you say, qualifying the pointers as volatile is necessary if the values stored at those addresses can change from outside your program; with volatile you tell the compiler that no assumptions may be made about the value (e.g. constant propagation or common subexpression elimination may not be done for volatile values).
What is wrong with the following code:
unsigned int *ptr;
ptr=(unsigned int*)0x1234;
*ptr=10;
/*do someting*/
*ptr=100;
Imp point, I have read the memory map of the microcontroller, and this location can be very much used by the programmer, so the case of not-owning-the-memory is ruled out.
All I want to find out is, can I use the above method to directly access a memory location?
Thanks in advance.
Yes it is fine, unless (as you said) you are within accessible memory range.
Also I would like to add, since you mentioned microcontroller, if this is address of a SFR or a GPR then its alias (using #define)must already be defined in the header for the controller, so it is better you use that alias, for improved readability/understandability and portability.
EDIT : (As Vlad pointed out in the comment)
Using volatile will make your program more safe & reliable, as compiler will not optimize out immediate memory write, and you can be sure that the value you write is immediately written to the location you want.
Yes you can use it, but be aware of the alignment issues. Depending in your microcontroller following might happen:
uint16_t * p1 = (uint16_t *)0x8;
uint16_t * p2 = (uint16_t *)0x9;
*p1 = 1; // Ok
*p2 = 1; // Unaligned access -> Crash or something else
ARM for example requires that 16-bit variables are aligned on even addresses (divisible by 2).