Tomando como exemplo o registrador de controle de direção (GPIODIR) da PORTF do microcontrolador TM4C123GH6PM:

Calculando o endereço físico do GPIODIR da PORTF:
Base address of PORTF = 0x40025000
Offset address of GPIODIR = 0x400 //page number 663 TM4C123GH6PM datasheet
GPIOFDIR Physical address = 0x40025000+0x400 = 0x4002_5400Uma alternativa para lidar com esse endereço em código seria atribuir à um ponteiro:
Unsigned int * GPIO_PORTF_DIR_R = (unsigned int*)0x40025400;Utilizando uma operação de “pointer dereference” é possível modificar o valor em memória:
*GPIO_PORTF_DIR_R = 0xF0;Com essa técnica é necessário manter e controlar os ponteiros, gastando memória, o que pode vir a ser um problema.
Analogamente, podemos escrever na memória diretamente. :
// write value 0xF0 to GPIOFDIR register
(* ( ( volatile unsigned int * ) 0x40025400 ) ) = 0xF0;
//read value GPIOFDIR register memory address and store it in variable data.
data = (* ( ( volatile unsigned int * ) 0x40025400 ) ) ;Utilizando essa alternativa, não é necessário utilizar ponteiros, o que representa uma economia de memória considerável se considerada a necessidade de se escrever/ler o valor de muitos registradores. Para tornar o código mais elegante e legível, a prática é utilizar diretivas #define :
#define GPIO_PORTF_DIR_R (*( ( volatile unsigned int * )0x40025400 ) )Desta forma, as operações podem ser feitas através de um código mais limpo sem desperdícios de memória:
GPIO_PORTF_DIR_R = 0xF0; // Write to GPIOFDIR
data = GPIO_PORTF_DIR_R; // Read from GPIOFDIR