Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 7

Navigating STM32 Reference Manuals & Datasheets

Recommended resources

Welcome back! In our last lesson, you mastered on-chip debugging, learning to pause your code and inspect the microcontroller's internal state, including its hardware registers. You saw firsthand how a line of C code can flip a bit in a register like GPIOC->ODR.

This lesson answers the crucial follow-up question: "How did we know to use GPIOC->ODR in the first place?" Today, we will learn one of the most essential skills of a professional embedded engineer: navigating the official documentation to find the exact information needed to control the hardware.

This lesson directly addresses the final learning outcome of our first module: Use the STM32 reference manual and datasheets to find peripheral register information.

Instead of relying on tutorials or pre-written code, you will learn to "read the map" of the microcontroller. This skill will empower you to interface with any peripheral—from a simple GPIO to a complex CAN controller—by understanding the hardware from the source of truth.

1. The Engineer's Toolkit: Datasheet vs. Reference Manual

For any given microcontroller, the manufacturer provides two primary documents. Understanding the role of each is the first step.

  • Datasheet (DS): This document focuses on the physical and electrical characteristics. Think of it as the hardware specification. You'll find information like pinout diagrams, voltage ratings, current consumption, and timing characteristics of signals.
  • Reference Manual (RM): This document describes the functional and programming model. It explains how the peripherals work and how you, the programmer, can control them through their registers. This is where we will spend most of our time.

For your STM32F103C8T6, the specific documents are the "STM32F103x8/xB Datasheet" and the "RM0008 Reference Manual". A quick web search will lead you to them on the STMicroelectronics website. It's a good practice to download and keep these PDFs handy.

To see a quick breakdown of this distinction, watch the following clip.

Bare Metal STM32 #1: Introduction & Write a GPIO driver to blink LED

This video segment concisely explains the difference between a datasheet and a reference manual, which is the foundational knowledge for navigating documentation.

Watch from 02:56 to 03:53. The key takeaway is understanding which document to open for electrical specifications versus programming information.


2. A Method for Navigating the Manual

At over 1,000 pages, the reference manual is not meant to be read from start to finish. It's a look-up guide. An effective engineer knows how to find information efficiently. The manual follows a logical hierarchy that, once understood, makes it much easier to navigate.

STM32 Memory and Bus Architecture Diagram
This diagram from the reference manual shows the high-level architecture. The CPU core and DMA are 'masters' that can access 'slave' peripherals like Flash, SRAM, and GPIOs through a system of buses (AHB, APB).

Based on this architecture, here is a systematic approach to finding register information, which we will follow for the rest of this lesson:

  1. Find the Peripheral in the Memory Map: Every peripheral is located at a specific range of memory addresses. The memory map tells you the base address for each one.
  2. Enable the Peripheral's Clock (RCC): To save power, all peripherals are disabled by default. You must first enable the clock to the peripheral you want to use in the Reset and Clock Control (RCC) registers.
  3. Find the Peripheral's Register Map: Go to the specific chapter for your peripheral (e.g., GPIO, UART). There you will find a list of its control registers and their offsets from the peripheral's base address.
  4. Decode the Register's Bitfields: Each register is 32 bits wide, with different bits or groups of bits (called bitfields) controlling specific functions. The manual describes the function of every bit.

Let's put this method into practice by re-discovering how to blink the onboard LED on PC13.


3. Practical Application: Finding the Registers for a Blinky

We will now walk through the process of finding the exact addresses and bit values needed to configure and toggle a GPIO pin.

Step 1: Locating the Memory Map

First, we need to know where the GPIO Port C and the RCC peripherals "live" in memory. This information is in the memory map section of the reference manual.

C Bare Metal Programming on STM32F103 — Booting up

This article provides a clear, text-based walkthrough of our goal. We'll start by reading the section that explains how to locate the peripheral base addresses.

Read the section titled 'Controlling a GPIO'. Focus on how the author uses the memory map table in the reference manual to find the base addresses for RCC (0x40021000) and GPIO Port C (0x40011000).

You've now established the starting memory addresses for the hardware blocks you need to control.

Step 2: Enabling the GPIO Clock via RCC

With the base address for RCC known, our next task is to find the specific register and bit within the RCC block that powers on GPIO Port C.

This video demonstrates exactly how to do this.

Bare Metal STM32 #1: Introduction & Write a GPIO driver to blink LED

The following clip will show you how to navigate from the block diagram to the RCC chapter in the reference manual to find the exact register and bit needed to enable the clock for a GPIO port.

Watch from 05:53 to 08:17. Pay close attention to these steps: Identifying that GPIOs are on the APB2 bus (for the F1 series). Finding the 'RCC_APB2ENR' (APB2 peripheral clock enable register) in the RCC register list. Noting its offset (0x18). Identifying that Bit 4 ('IOPCEN') is the one that enables the clock for IO port C.

At this point, you can calculate the absolute address of the register: RCC_BASE (0x40021000) + OFFSET (0x18) = 0x40021018. To enable the clock, you would write a 1 to bit 4 of this register.

Step 3: Configuring the GPIO Pin

Now that Port C has power, we can configure pin 13 as an output and then control its state. This involves finding the correct registers within the GPIOC block.

STM32 GPIO Internal Block Diagram
This block diagram of a GPIO pin shows the internal logic. The registers we manipulate, like the Mode registers (`CRL`/`CRH`) and the Output Data Register (`ODR`), directly control this circuitry.

The process is identical: find the chapter, find the register map, and decode the bits.

Bare Metal STM32 #1: Introduction & Write a GPIO driver to blink LED

This final video segment completes our investigation by showing how to find the GPIO registers for setting the pin mode and toggling its output.

Watch from 08:17 to 10:58. Focus on: Finding the GPIO chapter and its register list. Identifying the 'GPIOx_CRH' (Port configuration register high) for pins 8-15 and its offset (0x04). Understanding that bits 20-23 control PC13 and what values set it to output mode. Identifying the 'GPIOx_ODR' (Output data register) at offset 0x0C and how bit 13 controls the pin's state.

Test your understanding!

Using the method you've just learned and the reference manual PDF (RM0008), find the information needed to configure pin PA5 (Port A, Pin 5) as a general-purpose output.

What are the names of the two registers you need to modify, and which specific bits in each register are relevant?

Show answer
  1. Enable Clock: You first need to enable the clock for GPIO Port A. In the RCC_APB2ENR register, you would set bit 2 (IOPAEN) to 1.
  2. Configure Mode: Since pin 5 is in the lower half (0-7), you use the GPIOA_CRL register. The bits controlling pin 5 are bits 20-23 (CNF5[1:0] and MODE5[1:0]). To set it as a general-purpose push-pull output, you would set these bits according to the table in the manual (e.g., 00 for push-pull and 01/10/11 for the desired speed).

4. From Raw Addresses to Professional Code

Writing code with direct memory addresses like *(volatile uint32_t *)0x4001100C |= (1 << 13); is tedious, hard to read, and prone to errors. The industry standard is to use predefined structures provided by the MCU vendor.

These are found in a device-specific header file (e.g., stm32f103x6.h for your board) that is part of the CMSIS (Cortex Microcontroller Software Interface Standard). This file contains C struct definitions that perfectly mirror the register layouts you just researched.

For example, a GPIO_TypeDef struct is defined like this:

typedef struct
{
  volatile uint32_t CRL;    // Offset 0x00
  volatile uint32_t CRH;    // Offset 0x04
  volatile uint32_t IDR;    // Offset 0x08
  volatile uint32_t ODR;    // Offset 0x0C
  // ...and so on
} GPIO_TypeDef;

The compiler automatically handles the offsets. The header file also defines pointers to the base addresses, like GPIOC, which points to 0x40011000.

This allows you to write clean, readable, and professional code:
GPIOC->ODR |= (1 << 13);

This is the code you've been using, but now you understand exactly where it comes from: it is a direct, high-level representation of the hardware layout described in the reference manual.


Conclusion

Congratulations on completing the first module! You have now unlocked one of the most powerful skills in embedded systems. You are no longer just a user of code; you are an engineer who can interface directly with the silicon.

Key Takeaways:

  • The Datasheet is for electrical specs; the Reference Manual (RM) is for programming.
  • There is a systematic process for finding register information: Memory Map -> RCC -> Peripheral Registers -> Bitfields.
  • Every peripheral must have its clock enabled via RCC before it can be used.
  • Registers are located at a base address + offset.
  • Professional code uses CMSIS header files to map these registers to C structs, abstracting away the raw memory addresses.

Preview of the Next Lesson:
We will immediately put this new skill to use. In the first lesson of Module 2, we will dive deep into the Reset and Clock Control (RCC) peripheral. Using the reference manual as our guide, you will learn to configure the microcontroller's core clock, switching from the less accurate internal oscillator (HSI) to a precise external crystal (HSE), and then use the debugger to verify that your system is running at the exact frequency you commanded.