What does that mean? #define SOMENAME ((uint32_t *)0x130010f0

Viewed 147

I'm trying to understand some sample C code that I got with my microcontroller board. I have a really hard time to understand that whole pointer thing. I read a lot of posts in this forum and I also read several tutorials and slowly I get the hang of it :) But... In my sample code there is the following line of code, which I could not decrypt with any information that I have found yet.

#define SOMENAME ((uint32_t *)0x130010f0)

I understood, that #define simply replaces all occurrences of SOMENAME in the compiled code with the respective statement (don't know if this is correctly explained, but I really think I got what this is doing).

Now, what I could imagine, what the rest of the statement means is the following:

SOMENAME is now a pointer to the address 0x130010f0 but without being an actual variable.

Is this correct? And I could kind of use it for example as: printf("value at address 0x130010f0: %p",SOMENAME) because the compiler would replace it with printf("value at address 0x130010f0: %p",((uint32_t *)0x130010f0)) and this gives the value stored at that address? What would be the print statement if I want the address of that pointer? I can't, right? Because the pointer does not have an address as it is not a variable? Very confusing...

The example is quite complex and this definition is also part of other definitions which are pointers to structs of structs of structs, therefore this "simple" example. Below you can find the "whole" structure:

#define ROM_API_TREE ((uint32_t *)0x130010f0)
#define BOOTLOADER_POINTER ((bootloader_tree_t *)ROM_API_TREE)

flash_driver_interface_t *FLASH_API_TREE
#define FLASH_API_TREE BOOTLOADER_POINTER->flashDriver

typedef struct BootloaderTree{
 ...
 const flash_driver_interface_t *flashDriver;
} bootloader_tree_t

typedef struct FlashDriverInterface{
 ...
 status_t (*ffr_get_uuid)(flash_config_t *config, uint8_t *uuid);
} flash_driver_interface_t

/*
* I actually want to understand that statement, but as I fail 
* already at the beginning, I posted this question
*/
status_t = FLASH_API_TREE->ffr_get_uuid(config,uuid);
3 Answers

You are correct that SOMENAME get replaced by the preprocessor with ((uint32_t *)0x130010f0). What this gives you is a pointer to a uint32_t, and the value of that pointer is 0x130010f0.

When you then do this:

printf("value at address 0x130010f0: %p",SOMENAME);

You'll actually print the value of the pointer, i.e. 0x130010f0, not what it points to. For that you would need to dereference it, i.e.:

printf("value at address 0x130010f0: %u", *SOMENAME);

This however assumes that 0x130010f0 is a valid address that can be dereferenced and read. This will typically only be the case in some particular embedded environment where the implementation allows it.

As i saw, you basically could understand many things behind the Pointers. The SOMENAME is a macro not a variable right. Before i get to the code, a pointer in general is nothing else but a variable that contains an adress instead of having a value.

printf("value at address 0x130010f0: %p",SOMENAME); is wrong because the %p expects a value not an Adress and you are passing the adress to it, so you all you have to do is to dereference it using the *.
When you write (uint32_t *)0x130010f0 you are casting the adress to the type writteb between parentheses.

Whenever it gets complicated while using pointers try to remember this small example:

int a = 10;
int *p = &a;// declare pointer of type integer. This is valid, adress of an integer variable contains adress of integer variable
int *j; //declare pointer of type integer
j = &a; //correct, because j expects an adress.
*j = &a; //wrong *j expects a value
 
printf("value of p: %p", *p);
printf("adress of p: %p", p); //or &p

This shows that your microcontroller board has a program accessible 32-bit device.

I say 'accessible' because this device could be readable, writable or both.

I use the kinda general term 'device' because it could be all kinds of things. Quite often it's a register that simply stores a value, but it could also be a FIFO chip returning the next stored value at every read.

Assuming it's a register: These registers often consist of separate bits or small groups of bits to represent some function. In that case you'd see bitfield struct declarations that look like this (two 16-bit fields as example):

struct {
    uint32_t someField : 16;
    uint32_t otherField : 16;
} fields;
Related