Configuração de Registradores em C

Este tópico é uma alteração do exemplo demonstrado anteriormente com funções em assembly.

Acessando Registradores Mapeados em Memória

Os registradores estão mapeados em memória e portanto são acessados a partir de endereços únicos. Isto é, cada registrador possui uma posição fixa na memória. Para entender a estrutura básica de um registrador e as operações para configurá-los, acesse o conteúdo sobre programação de periféricos mapeados em memória.

Utilizando a linguagem C, basta indicar o endereço e realizar o acesso via ponteiro:

*endereço = valor;

Tal procedimento é mostrado a seguir.

#include <stdint.h>

#define SIM_SCGC5 (*(volatile uint32_t *)0x40048038)
#define PORTB_PCR18 (*(volatile uint32_t *)(0x4004A000 + 4*18))
#define GPIOB_PDOR (*(volatile uint32_t *)0x400FF040)
#define GPIOB_PSOR (*(volatile uint32_t *)0x400FF044)
#define GPIOB_PCOR (*(volatile uint32_t *)0x400FF048)
#define GPIOB_PTOR (*(volatile uint32_t *)0x400FF04C)
#define GPIOB_PDIR (*(volatile uint32_t *)0x400FF050)
#define GPIOB_PDDR (*(volatile uint32_t *)0x400FF054)
#define RED_MASK (1 << 18)


void redon(void){
	//ativar o bit 18 do registrador PCOR.
	//GPIOB_PCOR = (RED_MASK);
	
	//ou desativar somente o bit 18 do registrador PDOR
	GPIOB_PDOR = GPIOB_PDOR & ~(RED_MASK);
}

void redoff(void){
	//ativar o bit 18 do registrador PSOR.
	//GPIOB_PSOR = (RED_MASK);
	
	//ou ativar somente o bit 18 do registrador PDOR
	GPIOB_PDOR = GPIOB_PDOR | (RED_MASK);
}

void init_gpio(void){
	//ativar somente o bit 10 do registrador SCGC5.
	SIM_SCGC5 = SIM_SCGC5 | (1 << 10);
	
	//ativar o bit 8 do registrador PORTB_PCR18
	PORTB_PCR18 = (1 << 8);
	
	//ativar o bit 18 do registrador PDDR
	GPIOB_PDDR = (RED_MASK);
}


int main()
{
	//configurações iniciais
	init_gpio();
	
	while(1){
		//programa em loop infinito
		redon();
		redoff();
	}
	
	return 0;
}

Encapsulando Registradores

Os registradores podem ser agrupados em uma estrutura de dados para facilitar o acesso. Por exemplo, os registradores GPIOB_PDOR até GPIOB_PDDR estão posicionados sequencialmente na memória. Esse grupo de registradores é denominado GPIOB.

struct GPIO{
	uint32_t PDOR;
	uint32_t PSOR;
	uint32_t PCOR;
	uint32_t PTOR;
	uint32_t PDIR;
	uint32_t PDDR;
};

Com o novo tipo de dado, basta associar o nome do módulo ao endereço base da mesma.

#define GPIOB ((volatile struct GPIO *)0x400FF040)

Cabe ressaltar que utilizando essa técnica outros módulos de GPIO podem ser acessados, pois apresentam a mesma sequência. Isto é, a estrutura do módulo é a mesma, a única diferença é o endereço dos registradores.

#include <stdint.h>

#define SIM_SCGC5 (*(volatile uint32_t *)0x40048038)
#define PORTB_PCR18 (*(volatile uint32_t *)(0x4004A000 + 4*18))

struct GPIO{
	uint32_t PDOR;
	uint32_t PSOR;
	uint32_t PCOR;
	uint32_t PTOR;
	uint32_t PDIR;
	uint32_t PDDR;
};

#define GPIOB ((volatile struct GPIO *)0x400FF040)
	
#define RED_MASK (1 << 18)


void redon(void){
	//ativar o bit 18 do registrador PCOR.
	//GPIOB->PCOR = (RED_MASK);
	
	//ou desativar somente o bit 18 do registrador PDOR
	GPIOB->PDOR = GPIOB->PDOR & ~(RED_MASK);
}

void redoff(void){
	//ativar o bit 18 do registrador PSOR.
	//GPIOB->PSOR = (RED_MASK);
	
	//ou ativar somente o bit 18 do registrador PDOR
	GPIOB->PDOR = GPIOB->PDOR | (RED_MASK);
}

void init_gpio(void){
	//ativar somente o bit 10 do registrador SCGC5.
	SIM_SCGC5 = SIM_SCGC5 | (1 << 10);
	
	//ativar o bit 8 do registrador PORTB_PCR18
	PORTB_PCR18 = (1 << 8);
	
	//ativar o bit 18 do registrador PDDR
	GPIOB->PDDR = (RED_MASK);
}


int main()
{
	//configurações iniciais
	init_gpio();
	
	while(1){
		//programa em loop infinito
		redon();
		redoff();
	}
	
	return 0;
}

Last updated