Briefly develop embedded system skills for higher reliability

Just like people in a very distant age, their thoughts are still very conservative, and they are bound to enjoy the comfort of their own pure land. It is always believed that the Tianyuan area has been living in a dull and fulfilling life, and it seems that Liu Wei, who is in the Dream of Red Mansions, has dazzled into the Grand View Garden. For 75 years ago, the traditional concept of people was still relatively strong. For those people of that era, the education they received should be different. For those times, the materials were relatively scarce, and the technology was relatively backward. There is no such thing as big data, cloud computing, the Internet and the mobile Internet.

Briefly develop embedded system skills for higher reliability

There are many techniques for developing highly reliable embedded systems, from well-developed development cycles to strict implementation and system checks. This article describes seven easy-to-use and long-lasting techniques that are useful for ensuring that the system runs more reliably and captures anomalous behavior.

Tip 1 - Fill the ROM with a known value

Software developers are often very optimistic people, just let their code run faithfully for a long time, and that's it. It seems quite rare for a microcontroller to jump out of the application space and execute it in an unintended code space. However, the chances of this happening are no less than the buffer overflow or the wrong pointer loses the reference. It does happen! The behavior of the system after this happens will be undefined, because the memory space is 0xFF by default, or because the memory area is usually not written, the value may only be known to God.

However, there are fairly comprehensive linker or IDE tricks that can be used to help identify such events and recover from them. The trick is to use the FILL command to fill a known bit pattern with unused ROM. To populate unused memory, there are many different possible combinations to use, but if you want to build a more reliable system, the most obvious option is to place the ISR fault handler at these locations. If something goes wrong with the system and the processor begins executing code outside of program space, it triggers the ISR and provides an opportunity to store the processor, registers, and system state before deciding to correct the action.

Tip 2 - Check the application's CRC

A big benefit for embedded engineers is that our IDE and toolchain can automatically generate an application or memory checksum (Checksum) to verify that the application is intact based on this checksum. Interestingly, in many of these cases, the checksum is only used when the program code is loaded into the device.

However, if the CRC or checksum remains in memory, then verifying that the application is still intact at startup (or even for a long-running system) is an excellent way to ensure that unexpected things don't happen. The probability of a programmed application changing now is small, but considering the billions of microcontrollers delivered each year and potentially poor work environments, the chances of an application crash are not zero. More likely, a defect in the system can cause flash writes or flash erases in a sector, thereby damaging the integrity of the application.

Tip 3 - Perform a RAM check at startup

In order to build a more reliable and solid system, it is very important to ensure that the system hardware is working properly. After all, the hardware will fail. (Fortunately, the software never fails, the software only does what the code wants it to do, whether it is correct or wrong). Verifying that there is no problem inside or outside of the RAM at startup is a good way to ensure that the hardware can function as expected.

There are many different ways to perform a RAM check, but the usual method is to write a known pattern and wait for a short time before reading back. The result should be what you read is written. The truth is that in most cases the RAM check is passed, which is what we want. However, there is also a very small possibility that the inspection will not pass, which provides an excellent opportunity for the system to indicate hardware problems.

Tip 4 - Using a Stack Monitor

For many embedded developers, the stack seems to be a pretty mysterious force. When strange things started to happen, the engineers were finally stumped, and they started thinking, maybe something happened on the stack. The result is blindly adjusting the size and position of the stack, and so on. But the error is often unrelated to the stack, but how can it be so determined? After all, how many engineers actually did the worst-case stack size analysis?

The stack size is statically allocated at compile time, but the stack is used dynamically. As the code executes, the variables, returned addresses, and other information the application needs are continuously stored on the stack. This mechanism causes the stack to grow in its allocated memory. However, this growth sometimes exceeds the capacity limit determined at compile time, causing the stack to corrupt data in adjacent memory regions.

One way to absolutely ensure that the stack works properly is to implement the stack monitor as part of the system's "health" code (how many engineers will do this?). The stack monitor creates a buffer area between the stack and the "other" memory area and fills in the known bit pattern. The monitor then constantly monitors the pattern for any changes. If this bit pattern changes, it means that the stack is growing too much, and the system is about to be pushed to the dark hell! At this point the monitor can record the occurrence of the event, the system status, and any other useful data for later diagnosis of the problem.

A stack monitor is provided in most real-time operating systems (RTOS) or microcontroller systems that implement a memory protection unit (MPU). The scary thing is that these features are turned off by default, or are often intentionally closed by developers. A quick search on the network reveals that many people recommend turning off the stack monitor in the real-time operating system to save 56 bytes of flash space. Wait, this is not worth the effort!

Briefly develop embedded system skills for higher reliability

Tip 5 - Using MPU

In the past, it was difficult to find a Memory Protection Unit (MPU) in a small, inexpensive microcontroller, but this has begun to change. MPUs are now available from high-end to low-end microcontrollers, and these MPUs offer embedded software developers an opportunity to dramatically increase their firmware robustness.

The MPU has gradually been coupled to the operating system to create memory space where the processing is separate, or tasks can execute their code without worrying about being stomped on. If there really happen, uncontrolled process will be canceled, also performs other protective measures. Please pay attention to the microcontroller with this component, if any, please take advantage of this feature.

Tip 6 - Build a powerful watchdog system

One of the most popular watchdog implementations you'll often find is where the watchdog is enabled (this is a good start), but it can also be done with a periodic timer. The watchdog is cleared; the timer is enabled to be completely isolated from anything that occurs in the program. The purpose of using the watchdog is to help ensure that if an error occurs, the watchdog will not be cleared, ie when the work is suspended, the system will be forced to perform a hardware reset to recover. Using a timer independent of system activity keeps the watchdog clear, even if the system has failed.

Embedded developers need to think carefully and design how application tasks are integrated into the watchdog system. For example, there is a technique that allows each task that runs within a certain period of time to indicate that they can successfully complete their tasks. In this event, the watchdog is not cleared and forced to be reset. There are also some more advanced techniques, such as using an external watchdog processor, which can be used to monitor how the main processor behaves and vice versa.

For a reliable system, it is important to build a powerful watchdog system. Because there are too many technologies, it is difficult to fully cover them in these paragraphs, but for this topic, the author will publish relevant articles in the future.

Tip 7 - Avoid volatile memory allocation

Engineers who are not accustomed to working in resource-constrained environments may attempt to use the features of their programming language, which allows them to use volatile memory allocation. After all, this is a technique often used in calculator systems where memory is only allocated when necessary. For example, when developing in C, engineers may prefer to use malloc to allocate space on the heap. There is an operation to execute, once completed, you can use free to return the allocated memory for the heap to use.

In a resource-constrained system, this could be a disaster! One of the problems with using volatile memory allocation is that errors or improper techniques can cause memory leaks or memory fragmentation. If these problems occur, most embedded systems do not have the resources or knowledge to monitor the heap or handle it properly. And when they happen, what happens if the application asks for space but does not have the requested space available?

The problems caused by the use of volatile memory allocation are very complicated. It is a nightmare to properly handle these problems! An alternative approach is to simplify the allocation of memory directly in a static manner. For example, instead of simply creating a buffer that is 256 bytes long in the program, instead of requesting a memory buffer of this size via malloc. This allocated memory can be maintained throughout the life of the application without the concerns of heap or memory fragmentation issues.

in conclusion

These are just a few of the ways that developers can start building more reliable embedded systems. There are many other techniques, such as using good coding standards, bit flip monitoring, execution array and pointer boundary checking, and using assertions. All of these technologies allow designers to develop the secrets of more reliable embedded systems.

Health Care

C&Q Technology (Guangzhou) Co.,Ltd. , https://www.gzcqteq.com