Byte Me
Byte Me

Reputation: 27

C address offsets

So I'm trying to ORR some bits in a register on a micro controller. Up until now I've been using Assembly, now I'm using C I'm hitting some walls.

So in ASM if I wanted to access a register with an offset such as. GPIO_PORT_F and offset GPIO_DATA I would use the following code.

LDR R0,=GPIO_PORT_F ;load the base
LDR R1, [R0, #GPIO_DATA] ;load the offset
ORR R1, 0x1 ;ORR it with a value
STR R1, [R0, #GPIO_DATA] ;store back

This is the exact operation I want to perform but in C. This is what I have.

GPIO_PORT_F is defined like #define GPIO_PORT_F (*((unsigned long *)0x40025000))

(GPIO_PORT_F+GPIO_DATA) = (GPIO_PORT_F+GPIO_DATA) | inMask;

I get an error "expression must be a modifiable lvalue"

What am I doing wrong here, I'm using it's my attempt at offsetting.

Upvotes: 0

Views: 177

Answers (2)

Jens Gustedt
Jens Gustedt

Reputation: 78973

If I see it correctly you want to load a value from memory, ORR it with some value and then write it back to the same place.

Once you have correctly declared a pointer variable porta with the correct pointer type (probably something like uint32_t volatile* or so) you'd do

porta = (uint32_t*)GPIO_PORT_F; // convert the base
porta[GPIO_DATA] |= MASK;       // ORR it and store it back

The only thing that you'd have to worry is if the GPIO_DATA offset is accounted in bytes or words. If it is in bytes replace the second line by

porta[GPIO_DATA/sizeof *porta] |= MASK;       // ORR it and store it back

Upvotes: 0

IllusiveBrian
IllusiveBrian

Reputation: 3234

An assignment operation generally can't have the result of another operation on the left side. Without going too deeply into the difference between an lvalue and an rvalue, the value on the left side of the assignment operator must be modifyable, which the result of an addition operator is not (more on lvalues v rvalues in the answer to this question). I presume PORTA+GPIO_DIR is pointer arithmetic, so perhaps something like:

PORTA[GPIO_DIR] = *(PORTA+GPIO_DIR)|inMask; 

PORTA[GPIO_DIR] and *(PORTA+GPIO_DIR) both result in the same lvalue, that is the element at index GPIO_DIR in array PORTA. I've included both so you can decide which you prefer, though usually the left one is used.

Upvotes: 1

Related Questions