Home  >  Article  >  Several practical embedded development routines and techniques

Several practical embedded development routines and techniques

嵌入式Linux充电站
嵌入式Linux充电站forward
2023-07-31 15:04:30736browse

There are many techniques for developing high-reliability embedded systems, from well-regulated development cycles to rigorous execution and system checks.

Introducing 7 tips that are easy to operate and can be used for a long time. They are very helpful in ensuring that the system runs more reliably and catching abnormal behaviors
Tip 1 - Fill the ROM with known values
Software developers tend to be a very optimistic bunch and just want their code to run faithfully for a long time and that's it. It seems to be quite rare for a microcontroller to jump out of the application space and execute in an unintended code space. However, the chance of this happening is no less likely than a buffer overflow or a bad pointer losing its reference. It does happen! The system behavior after this happens will be undefined, because the memory space is all 0xFF by default, or because the memory area is usually not written, the value in it may only be known to God.
However, there are quite complete linker or IDE techniques that can be used to help identify such events and recover the system from them. The trick is to use the FILL command to fill the unused ROM with a known bit pattern. To fill unused memory, there are many different possible combinations that can be used, but if you want to build a more reliable system, the most obvious choice is to place ISR fault handlers in these locations. If something goes wrong with the system and the processor starts executing code outside of program space, the ISR is triggered and provides an opportunity to store processor, register, and system state before deciding on corrective action.
Tip 2 - Check the CRC of the application
A great benefit for embedded engineers is that our IDE and tool chain can automatically generate application or memory space checksums (Checksums) based on this Checksums verify that the application is intact. Interestingly, in many of these cases, the checksum is only used when loading the program code onto the device.
However, if the CRC or checksum remains in memory, then verifying that the application is still intact on startup (or even periodically for long-running systems) is a sure way to ensure A great way to prevent unexpected things from happening.
Now the probability of a programmed application changing is very small, but considering the billions of microcontrollers shipped every year and the potentially harsh working environment, the application crashes The chance is not zero. More likely, a flaw in the system could cause a flash write or flash erase to occur on a sector, thereby compromising 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, hardware can fail. (Fortunately software never fails, it just does what the code tells it to do, whether that's right or wrong). Verifying that there are no problems internal or external to the RAM at boot is a good way to ensure that the hardware is functioning as expected.
There are many different ways to perform a RAM check, but a common method is to write to a known pattern and then wait a short period of time before reading it back. The result should be that what is read is what is written. The truth is that in most cases the RAM check passes, which is what we want. However, there is a very small possibility that the check will not pass, which provides an excellent opportunity for the system to flag a hardware problem.
Tip 4 - Use the Stack Monitor
For many embedded developers, the stack seems to be a rather mysterious force. When strange things started happening, the engineers were finally stumped and started thinking, maybe there was something going on in the stack. The result is blindly adjusting the size and position of the stack, etc. But the error is often stack-agnostic, but how can one be so sure? After all, how many engineers have actually performed worst-case stack size analysis?
The stack size is statically allocated at compile time, but the stack is used in a dynamic manner. As the code executes, variables, return addresses, and other information needed by the application are continuously stored on the stack. This mechanism causes the stack to grow continuously within its allocated memory. However, this growth sometimes exceeds the capacity limit determined at compile time, causing the stack to corrupt data in adjacent memory areas.
One way to be absolutely sure that your stack is working properly is to implement a stack monitor as part of your system's "health" code (how many engineers do this?). The stack monitor creates a buffer area between the stack and the "other" memory area, filled with known bit patterns. The monitor then continuously monitors the pattern for any changes. If that bit pattern changes, it means the stack has grown too large and is about to push the system into a dark hell! At this point the monitor can record event occurrences, system status, and any other useful data for later use in diagnosing problems.
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 turned off intentionally by developers. A quick search on the web shows 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 gain!
Tip 5 - Using MPU
In the past, it was difficult to find a memory protection unit (MPU) in a small and cheap microcontroller, but that is starting to change. Microcontrollers from high-end to low-end now have MPUs, and these MPUs provide embedded software developers with an opportunity to greatly improve the robustness of their firmware.
MPUs have increasingly been coupled to the operating system in order to create memory spaces where processing is separated, or tasks can execute their code without fear of being stomped on. If something does happen, the uncontrolled processing will be canceled and other protective measures will be implemented. Keep an eye out for microcontrollers with this component, and if so, take advantage of this feature.
Tip 6 - Build a powerful watchdog system
One of the most popular watchdog implementations you will often find is that where the watchdog is enabled (this is a A good start), but is also where the watchdog can be cleared with a periodic timer; the timer's enablement is completely isolated from anything that happens in the program.
The purpose of using the watchdog is to help ensure that if an error occurs, the watchdog will not be cleared, that is, when work is suspended, the system will be forced to perform a hardware reset ( hardware reset) for recovery. Using a timer independent of system activity allows the watchdog to remain cleared even if the system fails.
Embedded developers need to carefully consider and design how application tasks are integrated into the watchdog system. For example, one technique might allow each task that runs for a certain period of time to indicate that it successfully completed its task. In this event, the watchdog is not cleared and is forced to reset. There are also more advanced techniques such as using an external watchdog processor, which can be used to monitor how the main processor is performing and vice versa.
For a reliable system, it is important to establish a powerful watchdog system. Because there are too many technologies, it is difficult to fully cover them in these paragraphs, but I will publish related articles on this topic in the future.
## Tip 7 - Avoid Volatile Memory Allocation
Engineers who are not used to working in resource-limited environments may be tempted to exploit the features of their programming language that allow them to use volatile memory allocation. After all, this is a technique often used in calculator systems, where memory is allocated only when necessary. For example, when developing in C, engineers may tend to use malloc to allocate space on the heap. An operation will be performed, and once completed, free can be used to return the allocated memory so that the heap can be used. 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 lead to memory leaks or memory fragmentation. If these problems arise, most embedded systems do not have the resources or knowledge to monitor the heap or handle it properly. And when they do, what happens if an application makes a request for space but the requested space is not available?
The problems caused by using volatile memory allocation are very complicated, and it can be said to be a nightmare to deal with these problems properly! An alternative is to simply allocate memory directly in a static manner. For example, instead of requesting a memory buffer of this size via malloc, simply create a buffer in your program that is 256 bytes long.This allocated memory is maintained throughout the lifetime of the application without concerns about heap or memory fragmentation issues.
in conclusion

These are just some of the ways developers can start building more reliable embedded systems. There are many other techniques, such as utilizing good coding standards, detecting bit flips, performing array and pointer bounds checking, and using assertions. All of these techniques are the secret that allow designers to develop more reliable embedded systems

The above is the detailed content of Several practical embedded development routines and techniques. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:嵌入式Linux充电站. If there is any infringement, please contact admin@php.cn delete