cancel
Showing results for 
Search instead for 
Did you mean: 

hi guys, I'm trying to define a register range for uint32_t array. I couldn't find a place online that explain in properly. do you know a way to do so?

Gbasi.1
Associate II

uint32_t REG_INIT[32];//// i dont think it is necessery that only for explanation

#define MainAddr     ((uint64_t)0x801FEC0)

#define step 0x8

#define BiasRefInit *(uint64_t *)(MainAddr+0*step)

#define BiasRefFinal *(uint64_t *)(MainAddr+1*step)

#define PowerRecycles *(uint64_t *)(MainAddr+2*step)

#define REG_INIT[32]   *(uint64_t *)(MainAddr+3*step)/// i wont to set a 32 regs range to "reg init".

14 REPLIES 14
alister
Lead

Assuming GCC.

https://stackoverflow.com/questions/4067811/how-to-place-a-variable-at-a-given-absolute-address-in-memory-with-gcc

http://blog.atollic.com/using-gnu-gcc-on-arm-cortex-devices-placing-code-and-data-on-special-memory-addresses-using-the-gnu-ld-linker

And many other places.

Specifying the address in the C source code is poor practice. Especially if text or rom data could be placed there. Better to create a section for it in your link command file.

The variables you place in the section may be scalars, arrays or structures.

TDK
Guru

In C++, you can just create variable references to those memory locations:

const uint32_t MainAddr = 0x801FEC0;
const uint32_t step = 0x08;
 
uint64_t & BiasRefInit = (uint64_t *) (MainAddr + 0 * step);
uint64_t & BiasRefFinal = (uint64_t *) (MainAddr + 1 * step);
uint64_t & PowerRecycles = (uint64_t *) (MainAddr + 2 * step);
uint64_t * REG_INIT = (uint64_t *) (MainAddr + 3 * step);
 
// for example:
BiasRefInit = 1;
BiasRefFinal = 2;
PowerRecycles = 3;
REG_INIT[0] = 4;
REG_INIT[1] = 5;

In C you have to use pointers:

const uint32_t MainAddr = 0x801FEC0;
const uint32_t step = 0x08;
 
uint64_t * BiasRefInitPtr = (uint64_t *) (MainAddr + 0 * step);
uint64_t * BiasRefFinalPtr = (uint64_t *) (MainAddr + 1 * step);
uint64_t * PowerRecyclesPtr = (uint64_t *) (MainAddr + 2 * step);
uint64_t * REG_INIT = (uint64_t *) (MainAddr + 3 * step);
 
// for example:
*BiasRefInitPtr = 1;
*BiasRefFinalPtr = 2;
*PowerRecyclesPtr = 3;
REG_INIT[0] = 4;
REG_INIT[1] = 5;

If you feel a post has answered your question, please click "Accept as Solution".

thank you very much, so for example if i want to set more uint64_t vars after that, do i need to skip on the next 32 addresses?

example:

uint64_t * REG_INIT = (uint64_t *) (MainAddr + 3 * step);

uint64_t * example = (uint64_t *) (MainAddr + (3+32) * step);

and one more ques,

why did u changed the pointer, i want the parameters be the content of the given address, isnt it needs to be written like the follow?

#define BiasRefInit *(uint64_t *)(MainAddr+0*step)

(C- language)

Gbasi.1
Associate II

It is important to mention that i writing it in main.h!!

TDK
Guru

> so for example if i want to set more uint64_t vars after that, do i need to skip on the next 32 addresses?

A uint64_t is 8 bytes in length, so you would need to skip 32*8=128 bytes.

Some processors will require uint64_t to be aligned to 8-byte boundaries. Yours is not, so this may be an issue. Handing of uint64_t is done in software as it's not natively supported on most STM32 chips. Use uint32_t instead if you can.

> why did u changed the pointer, i want the parameters be the content of the given address, isnt it needs to be written like the follow?

Using #defines also works. I don't like to use #defines unless absolutely necessary. Your choice. I would add parenthesis to avoid potential order of operations issues.

#define BiasRefInit (*(uint64_t *)(MainAddr+0*step))

If you feel a post has answered your question, please click "Accept as Solution".
turboscrew
Senior III

Do I get it correctly: you want to give pointer constants to some HW registers?

Then the point is to add step count to a uint64_t POINTER, not the address value.

(uint64_t *)(1000 + 1) points to address 1001

((uint64_t *) 1000) + 1 points to address 1008 (0ne uint64 forward from 1000).

like

#define BiasRefFinal *((uint64_t *)MainAddr)+1)

or

just change the base value to pointer

#define MainAddr    ((uint64_t *)0x801FEC0)

#define BiasRefFinal *(MainAddr+1)

 (I take it that the step was supposed to take care of the size of uint64_t.)

This:

#define REG_INIT[32] ...

probably doesn't do what you expect. You don't #define variables. The definitions are all (text substitution) macros.

If, what you really are after, is an array of adjacent 64-bit registers:

uint64_t *reg_init = ((uint64_t *)0x801FEC0); // 'reg_init' is pointer to uint64_t.

now 'reg_init points to the first 64-bit entity - that is reg_init[0] is the 64-bit contents of address 0x801FEC0.

reg_init[i] is the 64-bit contents of address 0x801FEC0 + i*sizeof(uint64_t).

Note that in C array[i] is a syntactic construction that is DEFINED to be *(array + i) and like for any pointer to type, pointer + integer is the same as

pointer + offset to i:th element of the size of the type.

 Also array name is the pointer to the first element of the array.

 *array is the same as array[0]

Whatever they say, C is pretty much based on the architecture of PDP computers.

:D

Nikita91
Lead II

Why not something like:

typedef struct
{
	uint64_t	BiasRefInit ;
	uint64_t	BiasRefFinal  ;
	uint64_t	PowerRecycles   ;
	uint32_t	REG_INIT[32] ;
	
} myStruct_t ;
 
myStruct_t * pMyStruct = (myStruct_t *) 0x801FEC0 ;
 
void fn ()
{
	pMyStruct->BiasRefFinal = 0 ;
}

 

No need. The REG_INIT also refers to 64-bit entities.

It was supposed to be array of 32 registers (I guess).

273/5000

I presented this as an alternative to using #define and to manual offset calculation based on "step" and multiplication: not easy to understand and maintain.

For the type of REG_INIT it is enough to change its type in the structure: easy and no computation.