//
Welcome to the IT Research Institute column, where Huamei will share practical knowledge about embedded systems, IoT, Java, and more every Thursday. We hope everyone can gain insights and progress further in their professional journey!
Becoming a formal embedded development engineer is a challenging process, from a well-defined development cycle to strict execution and system checks. There are many techniques for developing high-reliability embedded systems.
Huamei introduces you to 7 easy-to-operate and long-lasting tips that are very helpful for ensuring the system runs more reliably and captures abnormal behaviors.
#
Tip 1: Fill ROM with Known Values
It seems quite rare for a microcontroller to jump out of the application space and execute in an unintended code space. However, the chances of this happening are not less than buffer overflows or erroneous pointer dereferences, and the system behavior after such an occurrence will be uncertain. By default, memory space is 0xFF, or the values may be unknown because the memory area has not been written, but there are quite complete linker or IDE techniques that can help identify such events and recover the system.
The trick is to use the FILL command to fill unused ROM with known bit patterns. There are many different combinations to fill unused memory, but if you want to build a more reliable system, the most obvious choice is to place ISR fault handlers in these locations. If the system encounters an error, the processor will start executing code outside of the program space, triggering the ISR and providing an opportunity to store the processor, register, and system state before deciding on corrective actions.
#
Tip 2: Check Application CRC
For embedded engineers, there is a great advantage: our IDE and toolchains can automatically generate checksums for applications or memory spaces, allowing us to verify the integrity of the application based on this checksum. However, in many cases, checksums are only used when loading program code onto the device. If the CRC or checksum is kept in memory, verifying the application at startup (or even periodically for long-running systems) is an excellent way to ensure that unexpected events do not occur.
Now, the probability of a programmed application changing is very low, but considering the billions of microcontrollers delivered each year and the potentially harsh working environments, the chance of application crashes is not zero. More likely, a defect in the system might cause a sector to undergo flash writes or erases, compromising the integrity of the application.
#
Tip 3: Perform RAM Checks at Startup
To build a more reliable and robust system, ensuring that the system hardware works correctly is crucial. After all, hardware can fail (thankfully, software never fails; it only does what the code tells it to do, whether right or wrong). Verifying that RAM has no issues, whether internal or external, at startup is a good way to ensure hardware operates as expected.
There are many different methods to perform RAM checks, but a common method is to write a known pattern and then wait a short while before reading it back; the result should match what was written. In most cases, RAM checks pass, which is the desired result, but there is a very small chance that the check could fail, which provides an excellent opportunity to indicate hardware issues in the system.
#
Tip 4: Use a Stack Monitor
For many embedded developers, the stack seems like a rather mysterious force. When strange things start happening, engineers are finally stumped and begin to wonder if something went wrong with the stack, resulting in blind adjustments to the stack size and position, etc., but the error is often unrelated to the stack.
After all, how many engineers have really performed worst-case stack size analysis? The stack size is statically allocated at compile time, but the stack is used dynamically. 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 within its allocated memory. However, this growth can sometimes exceed the capacity limits determined at compile time, leading to stack corruption of adjacent memory areas.
One way to ensure the stack works correctly is to implement a stack monitor as part of the system’s “health” code. The stack monitor creates a buffer area between the stack and other memory areas and fills it with known bit patterns. The monitor then continuously checks for changes to the pattern. If the bit pattern changes, it means the stack has grown too large, and the monitor can log the occurrence, system state, and any other useful data for later diagnosis. Most real-time operating systems (RTOS) or microcontroller systems with memory protection units (MPUs) provide stack monitors. Scarily, these features are often disabled by default or frequently intentionally turned off by developers. A quick search online reveals that many people recommend turning off stack monitors in real-time operating systems to save 56 bytes of flash space, which is a costly practice!
#
Tip 5: Use MPU
In the past, it was difficult to find a memory protection unit (MPU) in a small and inexpensive microcontroller, but this situation has begun to change. Now, from high-end to low-end microcontrollers, MPUs are available, providing embedded software developers with an opportunity to significantly enhance the robustness of their firmware. MPUs have gradually been coupled with operating systems to establish memory spaces where processes are separated, or tasks can execute their code without fear of being stomped on. If something does happen, uncontrolled processing will be canceled, and other protective measures will be executed. Keep an eye out for microcontrollers with this component, and if available, make full use of its features.
#
Tip 6: Establish a Robust Watchdog System
The purpose of using a watchdog is to assist in ensuring that if an error occurs, the watchdog is not reset, meaning that when work halts, the system will be forced to perform a hardware reset to recover. Using a timer independent of system activity allows the watchdog to remain unreset even if the system fails. Embedded developers need to carefully consider and design how application tasks integrate into the watchdog system.
For example, a technique can be used where each task running within a certain period indicates that it can successfully complete its task. In this case, the watchdog is not reset, and a forced reset occurs. There are also more advanced techniques, such as using an external watchdog processor that can monitor how the main processor performs, and vice versa. Establishing a robust watchdog system is crucial for a reliable system.
#
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 languages that allow them to allocate volatile memory. After all, this is a technique commonly used in computing systems, where memory is only allocated when necessary. For example, when developing in C, engineers may tend to use malloc to allocate space on the heap. An operation is performed, and once completed, the allocated memory can be returned using free for heap use.
In resource-constrained systems, this can be a disaster! One issue with using volatile memory allocation is that errors or improper techniques can lead to memory leaks or fragmentation. Most embedded systems do not have the resources or knowledge to monitor the heap or handle it properly. And when these issues occur, what happens if the application requests space but the requested space is unavailable?
The problems arising from using volatile memory allocation are complex, and to handle them properly, an alternative method is to simplify memory allocation statically. For example, simply establish a buffer of 256 bytes in the program instead of requesting a memory buffer of that size via malloc. This allocated memory can persist throughout the application’s lifecycle, and there will be no concerns regarding heap or memory fragmentation.
Hua Qing Yuan Jian
Helping many students achieve their IT dreams
Realizing high salary dreams
Hua Qing Yuan Jian’s 12 centers nationwide are synchronously linked, collaborating with thousands of IT companies and hundreds of partner universities with which we have worked closely for 18 years to jointly launch the “Full Salary Attack, Waiting for You—Hua Qing Yuan Jian 2022 Autumn Talent Recruitment Fair”.
Gathering well-known companies from across the country, offering excellent benefits, high-value positions, and a high match between job positions and academic specialties, meeting your employment needs, accurately delivering positions, and assisting you in getting the first offer of autumn.
Previous Recommendations
●
In the autumn recruitment season, why can this position offer an annual salary of over 250,000?
●
Monthly salary of 17k, annual salary of 230,000! Difficulty in employment? Choosing the right direction is very important.
●
Here comes the strategy for passing the game! Quickly share it with your friends…
Leave a Comment
Your email address will not be published. Required fields are marked *