Detailed explanation of assert_param() function in stm32

Publisher:MysticalWhisperLatest update time:2017-10-09 Source: eefocusKeywords:stm32 Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

When using the stm32 library function, you will almost always find the assert_param() function. This function is used to determine whether there is an error in the parameter. What is the specific error? I will post a picture later.


The assert_param() function is defined in stm32f10x_conf.h:


#ifdef USE_FULL_ASSERT

#define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__))

void assert_failed(uint8_t* file, uint32_t line);

#else

#define assert_param(expr) ((void)0)

#endif 

The above code is part of stm32f10x_conf.h. Let's look at the following code:


RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE);

This function enables the clocks of GPIOB and GPIOE ports. GPIOB and GPIOE belong to APB2 peripherals, so use the function RCC_APB2PeriphClockCmd (xxx, xxx) to enable them. Let's take a look at the RCC_APB2PeriphClockCmd (xxx, xxx) function:

void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState)

{

assert_param(IS_RCC_APB2_PERIPH(RCC_APB2Periph));

assert_param(IS_FUNCTIONAL_STATE(NewState));

if (NewState != DISABLE)

  {

  RCC->APB2ENR |= RCC_APB2Periph;

  }

  else

  {

RCC->APB2ENR &= ~RCC_APB2Periph;

}

}

In this function, we can see the function we are going to learn today. Here we will analyze function 1 and use the point to lead the whole.

1. assert_param(IS_RCC_APB2_PERIPH(RCC_APB2Periph));

2. assert_param(IS_FUNCTIONAL_STATE(NewState));

The parameter in function 1 is IS_RCC_APB2_PERIPH (RCC_APB2Periph). Let's enter this function and see:

This is a macro definition

#define IS_RCC_APB2_PERIPH(PERIPH) ((((PERIPH) & 0xFFC00002) == 0x00) && ((PERIPH) != 0x00))

Let's calculate it. PERIPH is the parameter we passed RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE.

RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE = 0x00000008 | 0x00000040

(PERIPH) & 0xFFC00002 = 0x00, so ((((PERIPH) & 0xFFC00002) == 0x00) && ((PERIPH) != 0x00)) = 1

So it is equivalent to assert_param(1);

Let's look at the part of the stm32f10x_conf.h code in reverse. If USE_FULL_ASSERT is defined, then

#define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__))

If USE_FULL_ASSERT is not defined, then #define assert_param(expr) ((void)0) will be defined. Why is this? It is because users may enter wrong parameters during the code debugging phase and errors may occur. Generally, such errors are not detected. Therefore, when we want to check such errors, we define USE_FULL_ASSERT. When we complete the project and start production, the code will definitely not have such errors. We do not need the program to check our parameters, so we do not need to define USE_FULL_ASSERT. This will make our code smaller.

So we open the comments in stm32f10x_conf.h, so that we can check the parameters required to be checked in our code. When there is no error in our parameters, it is equivalent to assert_param(1);. Enter the function assert_param(); and observe that (void)0 will be executed, which means nothing will be executed, because there is no error in the parameters at this time.

We now need to create an error and observe how the function is executed.

Now we pass a wrong parameter

RCC_APB2PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);

Let's calculate, RCC_APB1Periph_TIM3 = 0x00000002

(PERIPH) & 0xFFC00002)! = 0x00

So IS_RCC_APB2_PERIPH(PERIPH) returns 0

So it is equivalent to assert_param(0);

Enter assert_param(); function observation

#define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__))

The function assert_failed((uint8_t *)__FILE__, __LINE__) will be executed. Let's explain what this function does. This function is for users to play with. You can do whatever you want in this function. Its prototype is not in the program. Anyway, I didn't find it. Later, I saw an article on the Internet. He said that he found it in the official example main.c, so I copied it to my main.c. The function prototype is as follows:

void assert_failed(u8* file, u32 line)

  //User can add his own implementation to report the file name and line number,

  // ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) 
  //Users can add error information here: for example, print out the wrong file name and line number

  // Infinite loop 
  while (1)
  {
  }
}


This function can print out the file and line number of our parameter errors when the program is running. I modified this function to:

void assert_failed(u8* file, u32 line) 

printf("Wrong parameters value: file %s on line %d\r\n", file, line);

}

You can also add other functions. As long as the error message can be displayed, it is ok. It does not necessarily have to be displayed through the serial port.

If the parameters are wrong, the file and line number of the error will be printed to the serial port. The following figure shows the error information printed by the serial port:

Detailed explanation of assert_param() function in stm32

The error file is stm32f10x_rcc.c line number 1098. Let's see if there is a parameter error in the program, as shown below:

Detailed explanation of assert_param() function in stm32
There is indeed a parameter error here, because the parameter we passed is

RCC_APB2PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);


I have basically finished the introduction here, and will introduce a few points below.


1. The __FILE__ and __LINE__ parameters of the assert_failed((uint8_t *)__FILE__, __LINE__) function may be built-in to the C language. I don’t know how to get the file and line number of the error parameters.


2. Suppose the parameter we pass is RCC_APB2PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); Although RCC_APB1Periph_TIM2 belongs to APB1, the error parameter cannot be printed when the program is running, because RCC_APB1Periph_TIM2 and RCC_APB2Periph_AFIO are both equal to 0x00000001. You can go to the stm32f10x_rcc.h file to see. So when you use the parameter check function, you have to pay attention to whether the parameters are wrong. The official error check function is not omnipotent.


Keywords:stm32 Reference address:Detailed explanation of assert_param() function in stm32

Previous article:S3C2440 external SDRAM
Next article:STM32F103 analog IIC

Recommended ReadingLatest update time:2024-11-17 04:58

STM32 Oscilloscope Signal Generator
There are already many stm32 oscilloscopes on the Internet. I still want to publish my design ideas here. This project has been prepared for a long time. First of all, I would like to thank the previous team. I feel very much that Mr. Chen and Mr. Qin, two experienced embedded engineers, have obtained a lot of conside
[Microcontroller]
STM32 Oscilloscope Signal Generator
STM32 CAN filtering principle
 
[Microcontroller]
STM32 CAN filtering principle
STM32 CAN controller
Introduction to CAN CAN is the abbreviation of Controller Area Network (hereinafter referred to as CAN), which is an ISO internationally standardized serial communication protocol. In the current automotive industry, various electronic control systems have been developed due to the requirements of safety, comfort, con
[Microcontroller]
STM32 ADC accuracy description
All the following descriptions are from the "STM32F103xx Data Sheet" (7th edition, May 2008). There is no new information here, just a translation of the corresponding part of the data sheet. When reading the various parameters in this data sheet, you must first understand how these parameters are obtained. Accordin
[Microcontroller]
STM32 ADC accuracy description
Detailed explanation of hex file stm32
Let's first analyze the operation of "Method 1" in detail: 1. We set the compiler to compile the program (as shown in the figure). This setting means downloading the program to the beginning of 0x0800 0000 of the flash, and then compiling the program 2. After compiling the program, find the compiled .hex file in the
[Microcontroller]
Detailed explanation of hex file stm32
Interrupt priority concept in STM32 (Cortex-M3)
There are two concepts of priority in STM32 (Cortex-M3) - preemptive priority and response priority. Some people call response priority "sub-priority" or "sub-priority". Each interrupt source needs to be assigned these two priorities. An interrupt with a high preemptive priority can be responded to during the processi
[Microcontroller]
[STM32] PWM output of general timer (Example: PWM output)
STM32F1xx official information: "STM32 Chinese Reference Manual V10" - Chapter 14 General Timer General Purpose Timer PWM Overview STM32 timer output channel pins Channel Pin Here we take TIM3 as an example. The general timers of STM32 are divided into TIM2, TIM3, TIM4, and TIM5, and each timer has 4 independ
[Microcontroller]
[STM32] PWM output of general timer (Example: PWM output)
STM32 USB firmware library structure
The structure of the STM32 USB firmware library is shown in the figure below: It can be seen that the STM32 USB firmware library is divided into 3 layers: Low Layer, Medium Layer and High Layer. The following analyzes the roles of these three layers:   (1) Low Layer usb_regs(.h,.c): implements the hardware
[Microcontroller]
Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号