These are macro definitions in the ST library, and are defined as follows:
#define __I volatile const /*!< defines 'read only' permissions */
#define __O volatile /*!< defines 'write only' permissions */
#define __IO volatile /*!< defines 'read / write' permissions */
Obviously, these three macro definitions are used to replace volatile and const, so we must first understand the role of these two keywords:
Volatile
simply means not allowing the compiler to optimize, that is, every time a value is read or modified, it must be read or modified from memory or registers again.
Generally speaking, volatile is used in the following places:
1. Variables modified in interrupt service routines for detection by other programs need to be added with volatile;
2. Flags shared between tasks in a multitasking environment should be added with volatile;
3. Memory-mapped hardware registers usually also need to be added with volatile instructions, because each read and write to it may have different meanings;
I think this is the most basic issue that distinguishes C programmers from embedded system programmers. Embedded guys often deal with hardware, interrupts, RTOS, etc., all of which require the use of volatile variables. Not understanding the implications of volatile can spell disaster. Assuming the interviewee answered this question correctly (well, doubt it), I'll dig a little deeper to see if this guy really understands the full significance of volatile.
1) Can a parameter be both const and volatile? Explain why.
2); Can a pointer be volatile? Explain why.
3); What's wrong with the following function:
int square(volatile int *ptr)
{
return *ptr * *ptr;
}
1) Yes. An example is a read-only status register. It is volatile because it can be changed unexpectedly. It is const because the program should not try to modify it.
2); Yes. Although this is not very common. An example is when a service routine modifies a pointer to a buffer.
3) This code is a bit perverted. The purpose of this code is to return the square of the value pointed to by pointer *ptr. However, since *ptr points to a volatile parameter, the compiler will generate code similar to the following:
int square(volatile int *ptr)
{
int a,b;
a = *ptr;
b = *ptr;
return a * b;
}
Since the value of *ptr may be changed unexpectedly, a and b may be different. As a result, this code may not return the square value you expect! The correct code is as follows:
long square(volatile int *ptr)
{
int a;
a = *ptr;
return a * a;
}
const
read-only variables, that is, variables are stored in read-only static storage. During compilation, if you try to modify a read-only variable, the compiler will prompt an error, which can prevent accidental modification. Both
const and define
can be used to define constants, but when const is defined, the type of the constant is defined, so it is more precise (in fact, const defines a read-only variable, not a constant). #define is just a simple text replacement. In addition to defining constants, it can also be used to define some simple functions, which is a bit similar to built-in functions. Constants defined by const and define can be placed in header files. (Note: can be declared multiple times, but can only be defined once)
const and pointers
int me;
const int * p1=&me; //p1 is mutable, *p1 is immutable const modifies *p1, that is, *p1 is immutable
int * const p2=&me; //p2 is immutable, *p2 is mutable const modifies p2, that is, p2 is immutable
const int *const p3=&me; //p3 is immutable, *p3 is also immutable The first const modifies *p3, and the second const modifies p3, both of which are immutable
The usage of volatile and const was introduced earlier. I wonder if you understand it? After understanding it, the following explanation will be easier:
__I: input port. Since it is an input, the value of the register can be modified externally at any time, so it cannot be optimized and must be read from the register again every time. It cannot be written, that is, read-only, otherwise it is not input but output.
__O: Output port, which cannot be optimized. Otherwise, if you output the same value twice in a row, the compiler will think that there is no change and ignore the latter output. If the value is modified externally between the two outputs, it will affect the output.__
IO: Input and output port, same as above
Why add underscores?
The reason is: to avoid naming conflicts
Generally, macro definitions are capitalized, but because there are fewer letters here, underscores are added to distinguish them. This generally avoids naming conflicts, because few people name them this way, and those who name them this way must know what they are used for.
When writing large projects, you will often find that there are always naming conflicts, either global variable conflicts or macro definition conflicts, so we should try to avoid these problems, otherwise we don’t know where the problem is when something goes wrong.
Volatile is generally used in the following three aspects:
1. Interrupt flag
2. Variables shared by multiple threads
3. Status registers
from ouravr Wildfire M3
Previous article:FreeModbus ported to STM32 to implement Modbus RTU communication
Next article:STM32 CRC ST Library 3.0.0
Recommended ReadingLatest update time:2024-11-16 07:54
- Popular Resources
- Popular amplifiers
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- Innolux's intelligent steer-by-wire solution makes cars smarter and safer
- 8051 MCU - Parity Check
- How to efficiently balance the sensitivity of tactile sensing interfaces
- What should I do if the servo motor shakes? What causes the servo motor to shake quickly?
- 【Brushless Motor】Analysis of three-phase BLDC motor and sharing of two popular development boards
- Midea Industrial Technology's subsidiaries Clou Electronics and Hekang New Energy jointly appeared at the Munich Battery Energy Storage Exhibition and Solar Energy Exhibition
- Guoxin Sichen | Application of ferroelectric memory PB85RS2MC in power battery management, with a capacity of 2M
- Analysis of common faults of frequency converter
- In a head-on competition with Qualcomm, what kind of cockpit products has Intel come up with?
- Dalian Rongke's all-vanadium liquid flow battery energy storage equipment industrialization project has entered the sprint stage before production
- Allegro MicroSystems Introduces Advanced Magnetic and Inductive Position Sensing Solutions at Electronica 2024
- Car key in the left hand, liveness detection radar in the right hand, UWB is imperative for cars!
- After a decade of rapid development, domestic CIS has entered the market
- Aegis Dagger Battery + Thor EM-i Super Hybrid, Geely New Energy has thrown out two "king bombs"
- A brief discussion on functional safety - fault, error, and failure
- In the smart car 2.0 cycle, these core industry chains are facing major opportunities!
- The United States and Japan are developing new batteries. CATL faces challenges? How should China's new energy battery industry respond?
- Murata launches high-precision 6-axis inertial sensor for automobiles
- Ford patents pre-charge alarm to help save costs and respond to emergencies
- New real-time microcontroller system from Texas Instruments enables smarter processing in automotive and industrial applications
- [Fudan Micro FM33LG0 Series Development Board Review] Driving RGB TFT Display
- Thank you for being there + thank you for everyone who appears in my life
- Use NucleiStudio to import GD32VF103_Demo_Suites routine
- [Project source code] Operating FPGA side registers under FPGA-based Linux
- Newbies need help with a few questions about RA2A1
- The virtual machine started to freeze again
- cortex-M4 K66 implements PPIT timing interrupt source program
- How to solve the problem of solder balls caused by mismatched pads during production
- How speakers work
- [Home smart lighting control and indoor environment monitoring system]--4. [RSL10] I2C control PCA9685 PWM output