Why to type case absolute memory address in embedded c?

Viewed 251

I'm curious to understand WHY do we need to type-cast an absolute physical memory address and what are its implications to compiler, if we do type-cast the address or if we don't?

I came across following code while figuring out different ways of accessing an absolute physical address.

E.g. Here we have an address 0x40020C00 which points to PORTA (there are multiple such ports as shown below).

If we're to access one of the offsets of this address to write some bits (in order to configure an I/O pin as input / output and then just toggle an LED) we can code it something like this:

typedef struct
{
  uint32_t MODER;   // mode register,                     offset: 0x00
  uint32_t OTYPER;  // output type register,              offset: 0x04
  uint32_t OSPEEDR; // output speed register,             offset: 0x08
  uint32_t PUPDR;   // pull-up/pull-down register,        offset: 0x0C
  uint32_t IDR;     // input data register,               offset: 0x10
  uint32_t ODR;     // output data register,              offset: 0x14
  uint32_t BSRR;    // bit set/reset register,            offset: 0x18
  uint32_t LCKR;    // configuration lock register,       offset: 0x1C
  uint32_t AFRL;    // GPIO alternate function registers, offset: 0x20
  uint32_t AFRH;    // GPIO alternate function registers, offset: 0x24
} GPIO_t;

volatile GPIO_t*   const portd       = (GPIO_t*)0x40020C00;

int main(void)
{
  *rcc_ahb1enr |= (1 << 3); // enable PortD's clock

  uint32_t moder = portd->MODER;
  moder |= (1 << 16);
  moder &= ~(1 << 17);
  portd->MODER = moder;

  while (1) {
    portd->ODR |= (1 << 8);  // led-on
    sleep(500);
    portd->ODR &= ~(1 << 8); // led-off
    sleep(500);
  }
}

My question is:

In this line, volatile GPIO_t* const portd = (GPIO_t*)0x40020C00; why are we type casting the absolute memory address (0x40020C00) with the return type (GPIO_t*) of the data, when the pointer has the correct return type?

Note: I am aware of why it is coded up as volatile and const pointer(i.e. since it is an absolute physical address of the register, we dont want compiler to optimize out the variables used to access these addresses and we make a promise not to change the pointer address.)

I appreciate the explanation/answers and Thanks in advance!

1 Answers

The cast is necessary because you're converting between two types where the language doesn't allow for an implicit conversion.

The constant 0x40020C00 has type int. And while an int can be implicitly converted to other integer types, it can't be implicitly converted to a pointer. So you need to apply a cast.

Related