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_5400

Uma 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

🌱 Back to Garden