C language skills in microcontroller development (Part 1)

Publisher:CrystalSparkleLatest update time:2023-01-09 Source: zhihu Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

1 Introduction

There are many books on the market that introduce C language and programming methods, but there are few introductions on how to write high-quality embedded C programs, especially for writing high-quality C programs for microcontrollers such as microcontrollers, ARM7, and Cortex-M3. The method is almost blank. This article is intended for low-level programmers who use microcontrollers such as microcontrollers, ARM7, and Cortex-M3.

Writing high-quality embedded C programs is not easy. It is closely related to the designer's thinking and experience accumulation. Embedded C programmers not only need to be familiar with the characteristics and defects of hardware, but also need to go deep into programming in a language and not just superficially. In order to operate the hardware more conveniently, you also need to have an in-depth understanding of the compiler.

This article will discuss how to write high-quality embedded C programs from the aspects of language features, compilers, defensive programming, testing, and programming ideas. Unlike many magazines and books, this article provides a large number of real-life examples, code snippets, and bibliographies. It not only introduces what should be done, but also focuses on how to do it and why. Writing high-quality embedded C programs involves a wide range of topics and requires programmers to accumulate experience over a long period of time. This article hopes to shorten this process. 2. C language features

Language is the cornerstone of programming. The C language is weird and has various traps and flaws. It requires programmers to practice for many years to reach a relatively perfect level. Although there are many books, magazines, and special topics that have discussed the pitfalls and shortcomings of the C language, this does not prevent this section from discussing it again.

There are always a large number of beginners who fall into these traps and defects one after another, and civilian equipment, industrial equipment and even aerospace equipment are no exception. This section will review them again with specific examples, hoping to attract enough attention. An in-depth understanding of C language features is the basis for writing high-quality embedded C programs.

2.1 There are traps everywhere

2.1.1 Honest mistake

1) "=" and "=="

Most people may have encountered the mistake of writing the comparison operator "==" as the assignment operator "=", such as the following code:

1. if(x=5)

2. {

3. //Other codes

4. }

The original intention of the code is to compare whether the variable x is equal to the constant 5, but "==" was mistakenly written as "=", and the if statement is always true. Most current compilers will issue a warning message if an assignment operator appears in a logical judgment expression. For example, keil MDK will give a warning: "warning: #187-D: use of "=" where"==" may have been intended", but not all programmers will notice such warnings, so experienced programs Developers use the following code to avoid such errors:

1. if(5==x)

2. {

3. //Other codes

4. }

Put the constant to the left of the variable x. Even if the programmer mistakenly writes '==' instead of '=', the compiler will generate a syntax error message that no one can ignore: Cannot assign a value to a constant!

2) Compound assignment operator

Although compound assignment operators (+=, *=, etc.) can make expressions more concise and potentially produce more efficient machine code, some compound assignment operators can also bring hidden bugs to the program, such as "+ =”It is easy to mistakenly write “=+”, the code is as follows:

  1. tmp=+1;

The original intention of the code is to express tmp=tmp+1, but the compound assignment operator "+=" is mistakenly written as "=+": the positive integer constant 1 is assigned to the variable tmp. The compiler will happily accept this type of code without even generating a warning.

If you can find this bug during the debugging phase, you should really celebrate, otherwise it is likely to become a major hidden bug that is not easy to detect.

Similar problems exist with the compound assignment operator "-=".

3) Others are easy to write by mistake

  • Chinese punctuation used

  • The header file declaration statement forgets to end with a semicolon at the end.

  • Logical AND && and bitwise AND&, logical or || and bitwise OR|, logical NOT! Negate the sum~

  • Letter l and number 1, letter O and number 0

These miswritings are actually easily detected by the compiler. You only need to pay attention to the prompt information of the compiler and you can quickly solve them.

Many software bugs originate from input errors. When searching on Google, some result list items come with a warning indicating that Google believes it contains malicious code. If you searched Google early in the morning on January 31, 2009, you would have seen that for 55 minutes that morning, Google's search results labeled every site as harmful to your PC.

This involves all sites across the Internet, including all of Google's own sites and services. Google's malware detection feature identifies dangerous sites by looking them up on a list of known attackers. On the morning of January 31, an update to this list accidentally included a slash ("/").

All URLs contain a slash, and the anti-malware feature interprets this slash to mean that all URLs are suspicious, so it happily adds a warning to every site in the search results. It's rare to see such a simple input error lead to such strange and widespread consequences, but the program is like this, and there is no room for negligence.

2.1.2 Array subscript

Arrays are often an important factor causing program instability. The confusion of C language arrays is inseparable from the fact that array subscripts start from 0. You can define int test[30], but you must not use the array element test[30] unless You know exactly what you are doing.

2.1.3 The easily overlooked break keyword

1) A break that cannot be omitted

The switch...case statement can easily implement a multi-branch structure, but be careful to add the break keyword at the appropriate location. Programmers often miss adding break, causing multiple case statements to be executed sequentially. This may be a flaw of C.

For switch...case statements, from a probability theory perspective, most programs only need to execute one matching case statement at a time, and each such case statement must be followed by a break. It is somewhat unnatural to complicate high-probability events.

2) Breaks cannot be added randomly

The break keyword is used to jump out of the nearest loop statement or switch statement , but programmers often don't pay enough attention to this.

On January 15, 1990, a switch in the AT&T telephone network in New York went down and restarted, causing its neighboring switches to fail, and so on, one after another. Soon, the 114 switch was down and restarting every six seconds. , 60,000 people cannot make long-distance calls for nine hours.

The solution at the time: Engineers reinstalled the previous software version. . . The subsequent accident investigation found that this was caused by the misuse of the break keyword. "C Expert Programming" provides a simplified version of the source code of the problem:

1. network code()

2. {

3. switch(line)

4. {

5. case THING1:

6. {

7. doit1();

8. } break;

9.case THING2:

10. {

11. if(x==STUFF)

12. {

13. do_first_stuff();

14. if(y==OTHER_STUFF)

15. break;

16. do_later_stuff();

17. } /*The purpose of the code is to jump here... ...*/

18. initialize_modes_pointer();

19. } break;

20.default:

21. processing();

22. } /*… …but actually jumps here. */

23. use_modes_pointer(); /*Cause modes_pointer is not initialized*/

twenty four. }

The programmer wanted to break out of the if statement, but he forgot that the break keyword actually jumps out of the nearest loop statement or switch statement. Now it jumps out of the switch statement and executes the use_modes_pointer() function. However, the necessary initialization work has not been completed, laying the groundwork for future program failures.

2.1.4 Unexpected octal system

Assign an integer constant to a variable. The code is as follows:

  1. int a=34, b=034;

Are variables a and b equal?

The answer is not equal. We know that hexadecimal constants are prefixed with '0x', and decimal constants do not need a prefix, but what about octal constants? It is different from the decimal and hexadecimal representation methods. It is prefixed by the number '0', which is somewhat strange: the three hexadecimal representation methods are completely different.

If the octal system also uses numbers and letters to express prefixes like the 16 system, it may be more conducive to reducing software bugs. After all, the number of times you use the octal system may not be used incorrectly! The following shows an example of misuse of octal, and the last array element is assigned an incorrect value:

1. a[0]=106; /*Decimal number 106*/

2. a[1]=112; /*Decimal number 112*/

3. a[2]=052; /*actually 42 in decimal, intended to be 52 in decimal*/

2.1.5 Pointer addition and subtraction operations

**The addition and subtraction operations of pointers are special. **The following code runs on a 32-bit ARM architecture. After execution, what are the values ​​of a and p?

1. int a=1;

2. int *p=(int *)0x00001000;

3. a=a+1;

4.p=p+1;

For the value of a, it is easy to determine that the result is 2, but the result of p is 0x00001004. After the pointer p is increased by 1, the value of p increases by 4. Why is this? The reason is that when pointers perform addition and subtraction operations, the data type of the pointer is used as the unit. p+1 is actually calculated according to the formula p+1*sizeof(int). If you don't understand this, you can easily make mistakes when using pointers to directly manipulate data.

A certain project used the following code to initialize zero operations on continuous RAM, but during operation it was found that some RAMs were not actually cleared.

1. unsigned int *pRAMaddr; //Define address pointer variable

[1] [2] [3] [4] [5] [6] [7]
Reference address:C language skills in microcontroller development (Part 1)

Previous article:C language skills in microcontroller development (Part 2)
Next article:Microcontroller IO port design skills

Latest Microcontroller Articles
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号