Becoming a formal embedded motherboard design and development engineer is a laborious process that requires developers to maintain and manage every bit and byte of the system. From well-regulated development cycles to rigorous execution and system inspections, there are many techniques for developing highly reliable embedded systems. Here are seven easy-to-use, long-lasting tips that can go a long way toward making your system run more reliably and catching unusual behavior.
Tip 1 - Fill ROM with known values
Software developers tend to be a very optimistic bunch and just keep their code running faithfully for a long time, that's all. It seems to be fairly rare for a microcontroller to jump out of the application space and execute in an unintended code space. However, this is no less likely to happen than a cache overflow or an error pointer losing a reference. It does happen! The behavior of the system after this happens will be uncertain, because the memory space is 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 fairly 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 a known bit pattern without ROM. There are many different possible combinations you can use to populate unused memory, but if you want to build a more reliable system, the most obvious choice is to place an ISR fault handler in these locations. If something goes wrong in the system, the processor starts executing code outside of program space, triggering the ISR and providing an opportunity to store processor, register, and system state before deciding on corrective action
Tip 2 -- Check your application's CRC
A great benefit for embedded engineers is that our IDE and toolchain can automatically generate an application or memory space Checksum against which to verify that the application is sound. 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 is kept in memory, verifying that the application is still intact at startup (or even periodically for a long-running system) is an excellent way to ensure that the unexpected doesn't happen. The probability of a programmed application changing is now small, but considering the billions of microcontrollers delivered each year and the potentially harsh working environment, the chance of a medical device application crashing is not zero. More likely, a flaw in the system could cause a flash write or flash erase to occur in a sector, thus 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 important to ensure that the system hardware is working properly. After all, hardware can fail. (Fortunately, software never fails; it does what the code tells it to do, whether it's right or wrong.) Verifying that there are no problems inside or outside the RAM at boot time is a good way to ensure that the hardware works as expected.
There are many different ways to perform a RAM check, but a common approach is to write 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 RAM checks pass in most cases, and that's what we want. However, there is also a very small chance 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 start to happen, the engineers are finally stumped, and they start thinking that maybe something is going on in the stack. The result is mindlessly adjusting the size and position of the stack, and so on. But the error is often stack independent, but how can you be so sure? After all, how many engineers have actually performed a 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 required by the application are continuously stored on the stack. This mechanism causes the stack to grow in the memory it allocates. However, this growth can sometimes exceed the capacity limits determined at compile time, causing the stack to corrupt data in adjacent memory regions.
One way to absolutely ensure that the stack is working properly is to implement a stack monitor as part of your system's "health" code (how many engineers do that?). . The stack monitor creates a buffer area between the stack and the "other" memory area and populates it with known bit patterns. The monitor will then constantly monitor the pattern for any changes. If the bit pattern changes, it means that the stack has grown too large and is about to push the system into the dark hell! At this point, the monitor can record the occurrence of events, the state of the system, and any other useful data for later diagnosis of the problem.
Stack monitors are available 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 turned off by developers. A quick search on the web reveals that many people recommend turning off the stack monitor in the real-time operating system to save 56 bytes of flash memory space, etc., which is not worth the cost!
Tip 5 - Use the MPU
In the past, it was difficult to find a memory protection unit (MPU) in a small and inexpensive microcontroller, but this is starting to change. Microcontrollers from the high end to the low end already have MPUs, and these MPUs offer embedded software developers an opportunity to greatly improve the robustness of their firmware.
The MPU has gradually been coupled to the operating system in order to establish a memory space where processing is all separated, or where tasks can execute their code without fear of being stomped on. If something does happen, uncontrolled processing is cancelled and other protective measures are implemented. Keep an eye out for microcontrollers with this component, and if so, take advantage of this feature.
Tip 6 - Build a strong watchdog system
One of the most popular watchdog implementations you'll often find is where the watchdog is enabled (which is a good start), but also where the watchdog can be zeroed out with a periodic timer; Timer enablement is completely isolated from any situation that occurs in the program. The purpose of using a watchdog is to help ensure that if an error occurs, the watchdog is not zeroed out, i.e. when work is suspended, the system is forced to perform a hardware reset in order to recover. Using a timer that is independent of system activity allows the watchdog to stay clear even when the system has failed.
Embedded motherboard developers need to carefully consider and design how application tasks are integrated into watchdog systems. For example, one technique might allow each task that runs for a certain period of time to indicate that they can successfully complete their tasks. In this event, the watchdog is not cleared and is forced to reset. There are also more advanced techniques, such as the use of 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 have a strong watchdog system.
Tip 7 - Avoid volatile memory allocation
Engineers who are not used to working in a resource-limited environment may try to use features of their programming language that allow them to use volatile memory allocation. After all, this is a technique commonly used in calculator systems, where memory is allocated only when it is necessary. For example, when developing in C, engineers may prefer to use malloc to allocate space on the heap. An operation is executed, and once completed, the allocated memory can be returned using free for heap use.
In resource-constrained systems, this can be a disaster! One of the problems with using volatile memory allocation is that faulty 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 properly handle it. And when they do, what happens if the application makes a request for space, but no requested space is available?
The problems arising from using volatile memory allocation are complex, and dealing with them properly can be a nightmare! An alternative approach is to simplify the allocation of memory directly and statically. For example, simply create a buffer in the program that is 256 bytes long, rather than requesting an in-memory buffer of that size via malloc. This allocated memory can be maintained throughout the life of the application without concerns about heap or memory fragmentation.
The above embedded motherboard design and development tutorial can allow the development of technology personnel to get better embedded system methods. All of these technologies are secrets that allow designers to develop more reliable embedded systems.
Previous : It's already gone.
Next: Optical fiber temperature sensor for temperature monitoring during microwave oven heating
Contact Us
Hello, if you have any further questions, please leave your contact information. Our company will send a professional customer manager to serve you. Thank you for your support and we look forward to cooperation!