So, our code points to the RCC boundary address
(RCC), accesses a member of the structure within the
boundary address space (AHBENR), and changes its value
by setting a bit (RCC_AHBENR_GPIOCEN).
Now that the GPIOC bus clock is running, let’s move
on and set up the GPIO pins PC8 and PC9. We must
write some code to define each pin’s mode (input or
output), output type (open drain or push-pull), speed, and
pull-up status. Here is the code to define the mode:
#define RCC_AHBENR_GPIOCEN
((uint32_t)0x00080000)
// PC8,PC9 = output mode
GPIOC->MODER |= (GPIO_MODER_MODER8_0);
GPIOC->MODER |= (GPIO_MODER_MODER9_0);
■ Screenshot 6. This capture of the RCC reset and clock
control structure was pulled from the stm32f0xx.h header
file. We are interested in the AHB entry.
Let’s break down the clock enable code. Take a look
at Screenshot 6, which is a capture of the RCC (Reset and
GPIOC runs on the AHB2 bus in the boundary
address space 0x48000800–0x48000BFF. This is verified
by address entries in the stm32f0xx.h header file:
Clock Control) structure contained within the stm32f0xx.h
header file. The RCC peripheral operates on the AHB1
bus with a boundary address space of 0x4002100 –
0x400213FF. This boundary address is defined as the
RCC_BASE within the stm32f0xx.h header file:
#define PERIPH_BASE ((uint32_t)0x40000000)
#define AHB2PERIPH_BASE (PERIPH_BASE +
0x08000000)
#define GPIOC_BASE (AHB2PERIPH_BASE +
0x00000800)
#define PERIPH_BASE ((uint32_t)0x40000000)
#define APBPERIPH_BASE PERIPH_BASE
#define AHBPERIPH_BASE (PERIPH_BASE +
0x00020000)
#define RCC_BASE (AHBPERIPH_BASE +
0x00001000)
Now, we can once again define the pointer to the
structure:
#define GPIOC ((GPIO_TypeDef *) GPIOC_BASE)
Now that we have the boundary address, we can
define RCC as a pointer to a structure. The structure is
located at address RCC_BASE:
Screenshot 7’s first entry is our structure
element/register of interest (MODER). You can also see
the other GPIO pin properties whose knobs we will need
to twist.
#define RCC ((RCC_TypeDef *) RCC_BASE)
Here are the GPIO mode bits that will configure PC8
and PC9 as outputs:
We can use the structure pointer to access elements
within the RCC address space. These elements are defined
in Screenshot 6 and consist of a set of registers.
#define GPIO_MODER_MODER8_0
((uint32_t)0x00010000)
#define GPIO_MODER_MODER9_0
((uint32_t)0x00040000)
Registers are normally made up of a number of bits.
We want to control bits within the registers. In this case,
we want to set a bit that enables the GPIOC bus clock:
The GPIO pins are configured as push-pull by default
on power-up or reset. So, the code we are writing is
academic. We’ll write it anyway:
// push-pull output
GPIOC->OTYPER &= ~(GPIO_OTYPER_OT_8);
GPIOC->OTYPER &= ~(GPIO_OTYPER_OT_9);
Note that we cleared the output type bits (&= )
versus setting them (|=). If you are an AVR programmer,
this type of bit set/clear coding is something you do quite
often. I think you’ve got the idea. So, here’s all of the
GPIO configuration code:
■ Screenshot 7. The GPIO structure elements necessary to
configure all of the STM32F030R8T6’s GPIO subsystems are
defined here.
// Enable GPIOC Peripheral clock
RCC->AHBENR |= RCC_AHBENR_GPIOCEN;
// PC8,PC9 = output mode
GPIOC->MODER |= (GPIO_MODER_MODER8_0);
GPIOC->MODER |= (GPIO_MODER_MODER9_0);
// push-pull output
GPIOC->OTYPER &= ~(GPIO_OTYPER_OT_8);
50 February 2016