Understanding Pointers in Microcontrollers

Understanding Pointers in Microcontrollers

Word Count: 6000 Content Quality Index: ⭐⭐⭐⭐⭐

Understanding Pointers in Microcontrollers

Abstract: Have you ever wondered where the functions and variables you write in Keil for microcontrollers end up? We often talk about the five areas of memory, but what exactly are those five areas? Where are they located on the chip? And why is it that after learning about pointers and structures in C, you still struggle with pointers to structures in 32-bit microcontrollers? If you have these questions, let’s explore them today!

Understanding Pointers in Microcontrollers
This image should be familiar to those who have studied STM32 microcontrollers. The STM32 chip we see has been packaged and consists mainly of the core and on-chip peripherals. If we compare it to a computer, the core and peripherals are similar to the CPU, motherboard, memory, graphics card, and hard drive in a computer. The chip and peripherals are connected by various buses. The controlled bus is connected to FLASH, RAM, and on-chip peripherals, and these functional components are arranged within a 4GB address space. The images above are the memory address mapping of the STM32F40XXX series microcontroller.
Our code is stored in FLASH (0x8000000~0x80FFFFF). The code consists of the various functions you write, while the variables declared in the program are stored in RAM. Local variables are released when the function finishes executing, while global variables are released when the program ends; this is a simple way to understand it.
The variables used by the CPU are stored in RAM. If you ask me what RAM is, it’s just a chip. It’s the SRAM area in Block1 of the image above. The CPU connects to the RAM chip via wires, allowing it to store and read data in the RAM chip. First, RAM needs an initial address. For STM32 microcontrollers, the starting address is 0x20000000. You may ask why we need to define an address. Only by defining the address can the CPU store data effectively. If there were no address, it would be random and chaotic…
Understanding Pointers in Microcontrollers
Understanding Pointers in Microcontrollers

1. Variables

1. Define an int type variable. By printing, we can see that the address where this variable is stored is: 0x20000000. This also confirms that the starting address of our memory is 0x20000000. Our defined variable ‘value’ is stored here.

Understanding Pointers in Microcontrollers
Understanding Pointers in Microcontrollers

2. Now define another variable.

By printing, we can see that this variable is stored at the address: 0x20000004. Since the int type occupies 4 bytes in memory, the second variable is stored at 0x20000004.

Understanding Pointers in Microcontrollers
Understanding Pointers in Microcontrollers

In summary, the two defined variables in memory look like this:

0x2000 0000 stores 0

0x2000 0004 stores 1

Understanding Pointers in Microcontrollers

2. Pointer Variables

Defining a pointer is essentially the same as defining a variable, except that a * is placed in front of the variable name.

Next, let’s define an int type pointer variable named p. Someone might ask, why does adding a * in front of the variable name make it a pointer?

Answer: It’s a convention established by the C language developers.

Defining a pointer is the same as defining a variable, and you can define various types.

Remember this phrase:

A pointer variable stores the address of a variable!
Therefore, assigning a value to a pointer naturally means giving it the address of the variable.
#include "sys.h"
#include "led.h"
#include "delay.h"
#include "usart.h"

int value = 0;
int value2 = 1;
int *p;

int main(void)
{ 
 uart_init(115200);
 delay_init();
 p=&value;// Copy the address of variable value to this pointer
 printf("Address of a: %p\n",p);// Print the address this pointer points to
 while(1)
 { 
 } 
}
Understanding Pointers in Microcontrollers
Understanding Pointers in Microcontrollers
Generally, the type of pointer variable should match the type of variable’s address it is assigned. For example, let’s define a char type pointer.
#include "sys.h"
#include "led.h"
#include "delay.h"
#include "usart.h"

int value = 0;
int value2 = 1;
int *p;// Define a pointer

char value3=1;
char *q;
 
int main(void)
{ 
 uart_init(115200);// Serial port initialization
 delay_init();
 
 p=&value;// Copy the address of variable value to this pointer
 q=&value3;// Copy the address of variable value3 to this pointer
 
 printf("Address of a: %p\n",q);// Print the address this pointer points to
 while(1)
 { 
 } 
}
What is the purpose of pointers as established by the C language developers?

3. What Are Pointers Used For?

1. Let’s first use pointers, and you will understand their utility later. Previously, we assigned the address of a variable to a pointer, and the C language developers specified that *{pointer variable name} represents the variable pointed to by this pointer.
What does that mean?
Referring to the program below, p=&value means that p holds the address of variable value, and then *p represents value.
#include "sys.h"
#include "led.h"
#include "delay.h"
#include "usart.h"

int value = 0;
int *p;// Define a pointer
 
int main(void)
{ 
 uart_init(115200);// Serial port initialization
 delay_init();
 
 p=&value;// Copy the address of variable value to pointer variable p
 
 printf("Address of a: %d\n",value);
 printf("Address of b: %d\n",*p);
 while(1)
 { 
 } 
}
Understanding Pointers in Microcontrollers
Understanding Pointers in Microcontrollers
Some might wonder… is that all?
Isn’t that just unnecessary?
Actually, I initially thought the same…
Since *p represents value, then *p=XXXX
Isn’t that equivalent to value=XXXX?
Understanding Pointers in Microcontrollers
Let’s look at the following example.
#include "sys.h"
#include "led.h"
#include "delay.h"
#include "usart.h"
int value = 0;
int *p;// Define a pointer 
int main(void)
{ 
 uart_init(115200);// Serial port initialization
 delay_init();
 
 p=&value;// Copy the address of variable value to pointer variable p
 printf("value of a: %d\n",value);
 
 *p=520; 
 
 printf("value of b: %d\n",value);
 while(1)
 { 
 } 
}
Understanding Pointers in Microcontrollers
Understanding Pointers in Microcontrollers
Still not feeling the utility of pointers? Don’t worry, just finish learning the basics. Without foundational knowledge, progress is impossible!
Have you ever seen a function that returns a pointer?

4. Function Pointers

First, take a look; if you don’t understand, keep reading.
#include "sys.h"
#include "led.h"
#include "delay.h"
#include "usart.h"

int value = 0;
int *p;// Define a pointer
 
int *function(void)
{
   return &value;// Return the address of value
}
 
int main(void)
{ 
 uart_init(115200);// Serial port initialization
 delay_init();
 
 p=function();// Call the function, which assigns the address of value to p
 
 printf("Address1 of a: %p\n",&value);// Print the address of value
 printf("Address2 of a: %p\n",p);// Print the address represented by p
 
    while(1)
 { 
 } 
}
Understanding Pointers in Microcontrollers
Understanding Pointers in Microcontrollers
Many people have used functions that return int or char, but adding a * after int or char might be unfamiliar to beginners. It simply means assigning addresses between pointers. Below is an example where p (an int* type pointer) is assigned the address represented by q.
Variables can be assigned to each other, and the same goes for pointers.
Essentially, the function ‘function’ returns an int* type pointer, which is assigned to p.
#include "sys.h"
#include "led.h"
#include "delay.h"
#include "usart.h"

int value = 0;
int *p;// Define a pointer
int *q;// Define another pointer
 
int main(void)
{ 
 uart_init(115200);// Serial port initialization
 delay_init();
 
 p=&value;// Assign the address of value to p 
 q=p;// Assign the address represented by p to q
 
 printf("Address1 of a: %p\n",&value);// Print the address of value
 printf("Address2 of a: %p\n",q);// Print the address represented by q
 
  while(1)
 { 
 } 
}
Understanding Pointers in Microcontrollers
Understanding Pointers in Microcontrollers
One more question: what is a function’s name?
We all know how to call a function like this:
#include "sys.h"
#include "led.h"
#include "delay.h"
#include "usart.h"

void function()
{
  printf("zhiguoxin\n");
}
int main(void)
{ 
 uart_init(115200);// Serial port initialization
 delay_init(); 
  function(); 
  while(1)
 { 
 } 
}
But have you seen this kind of calling?
#include "sys.h"
#include "led.h"
#include "delay.h"
#include "usart.h"

void (*fun)();

void function()
{
  printf("zhiguoxin\n");
}

int main(void)
{ 
 uart_init(115200);// Serial port initialization
 delay_init(); 
 
 fun = function;
  fun();
  while(1)
 { 
 } 
}
This uses a function pointer.
First, remember this phrase:
The function name is the address of that function!
Since it is an address, this address should be assignable to a pointer. Because it is the address of a function, the pointer we define must also be of a function type.
The function ‘void function()’ is one that has no return value and no parameters. We need to define a pointer of this type, which is simply void (*pointer variable name)(). The above defines fun as a pointer to a function without a return value and without parameters.
We can assign this function to the pointer variable. So fun=function means that the function pointer fun represents that function, making calling fun() equivalent to calling function().
If a function has parameters, what do we do? Easy, we just add them.
#include "sys.h"
#include "led.h"
#include "delay.h"
#include "usart.h"

void (*fun)(int a);

void function(int value)
{
  printf("value= %d\r
",value);
}

int main(void)
{ 
 uart_init(115200);// Serial port initialization
 delay_init(); 
 
 fun = function;// Assign function to fun
 fun(520);// fun is equivalent to function
  while(1)
 { 
 } 
}
Understanding Pointers in Microcontrollers
Understanding Pointers in Microcontrollers
If a function has a return value, what do we do? Just add it as well.
#include "sys.h"
#include "led.h"
#include "delay.h"
#include "usart.h"

int res;

int (*fun)(int a);

int function(int value)
{
  return value;
}
int main(void)
{ 
 uart_init(115200);// Serial port initialization
 delay_init(); 
 
 fun = function;// Assign function to fun
 res = fun(520);// fun is equivalent to function
 
 printf("res = %d",res);
  while(1)
 { 
 } 
}
Understanding Pointers in Microcontrollers
Understanding Pointers in Microcontrollers
To summarize:
Pointers essentially allow us to record the address of a variable or facilitate the transfer of addresses.
& represents the address operator.
* represents dereferencing.
&{variable name} : gets the address of that variable.
*{pointer variable name} : retrieves the value stored at the address represented by this pointer.
Next, let’s look at some common applications. Assign the address of an array to a pointer, and then manipulate the array using the pointer.
#include "sys.h"
#include "led.h"
#include "delay.h"
#include "usart.h"

char temp[3]={1,2,3};
char *p;

int main(void)
{ 
 uart_init(115200);// Serial port initialization
 delay_init(); 
 
  p=temp;// Assign the array name to pointer variable p, making p point to the first address of array temp
  
 printf("value0 = %d\r\n",*p);    // p represents the address of the first element of the array
 printf("value1 = %d\r\n",*(p+1));// p+1 represents the address of the second element of the array
 printf("value2 = %d\r\n",*(p+2));// p+2 represents the address of the third element of the array
  
 printf("temp[0] = %d\r\n",p[0]);// p[0] is equivalent to temp[0]
 printf("temp[1] = %d\r\n",p[1]);// p[1] is equivalent to temp[1]
 printf("temp[2] = %d\r\n",p[2]);// p[2] is equivalent to temp[2] 
  while(1)
 { 
 } 
}
Understanding Pointers in Microcontrollers
Understanding Pointers in Microcontrollers

5. Function Parameters as Pointers

#include "sys.h"
#include "led.h"
#include "delay.h"
#include "usart.h"

char temp[3]={1,2,3};

void function(char *value)
{
 printf("value0 = %d\r\n",value[0]);
 printf("value1 = %d\r\n",value[1]);
 printf("value2 = %d\r\n",value[2]);
}
int main(void)
{ 
 uart_init(115200);// Serial port initialization
 delay_init(); 
 
 function(temp);
  
  while(1)
 { 
 } 
}
Understanding Pointers in Microcontrollers
Understanding Pointers in Microcontrollers
The basic knowledge of pointers can be mastered through practice. The real application of pointers lies in code encapsulation. While beginners may not feel their utility, as you become a developer, you will realize that encapsulating many functional functions and leaving interfaces for calling them is essential in the future.
Encapsulation will heavily utilize pointers, function pointers, structure pointers, etc. Let me put it this way: 90% of programmers type letters and write code. When you start encapsulating, you write ideas, but a solid foundation of knowledge is necessary to achieve that.
Function pointers are quite common in our microcontroller programs, and combined with structures, they can elevate your code significantly. We will discuss this in the next issue.
Reply with: mcupointer to get the code examples from this article.
Understanding Pointers in Microcontrollers

1

“Methods for Job Hunting in Embedded Software Positions (Detailed)”

2

“Meituan Embedded Software Position Written Test Questions”

3

“How to Transition from Microcontrollers to Embedded Linux After 6 Years?”

Understanding Pointers in Microcontrollers

Understanding Pointers in Microcontrollers
Share this
Understanding Pointers in Microcontrollers
Like this
Understanding Pointers in Microcontrollers
View

Leave a Comment