7 Skills Must Know in the Design and Development of Embedded Motherboard
2019-04-20
Becoming a formal embedded motherboard design and development engineer is a hard process, requiring developers to maintain and manage every bit and byte of the system. There are many technologies for developing highly reliable embedded systems, ranging from standardized development cycle to strict implementation and system inspection. Today, I will introduce seven easy to operate and long-term skills, which are very helpful to ensure that the system runs more reliably and catch abnormal behaviors.
Tip 1 - Populate ROM with known values
Software developers are usually very optimistic people, as long as their code runs faithfully for a long time, that's all. It seems quite rare for a microcontroller to jump out of the application space and execute in an unexpected code space. However, there are no fewer opportunities for this to happen than a cache overflow or a missing reference to an error pointer. It does happen! The system behavior 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 may be known only by 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 a known bit pattern with an unused ROM. To fill unused memory, there are many different possible combinations that can be used. However, 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 in the system, the processor starts to execute code outside the program space, which will trigger the ISR and provide an opportunity to store the processor, registers, and system status before deciding on corrective actions
Tip 2 - Check the CRC of the application
A great advantage for embedded engineers is that our IDE and tool chain can automatically generate an application or memory space checksum to verify whether the application is intact. Interestingly, in many of these cases, checksums are used only when 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 verifying a long-running system) is an excellent way to ensure that nothing unexpected happens. Now, the probability of a programmed application changing is very small, but considering the billions of microcontrollers delivered every year and the possible harsh working environment, the chance of medical instrument application crashing is not zero. More likely, a defect in the system may lead to flash writing or flash erasure of a sector, thus damaging the integrity of the application.
Tip 3 - Perform RAM checks at startup
In order to establish a more reliable and solid system, it is very important to ensure that the system hardware works normally. After all, the hardware will fail. (Fortunately, the software will never fail. The software will only do what the code asks it to do, whether it is correct or wrong.). It is a good way to ensure that the hardware can operate as expected by verifying that there is no problem inside or outside RAM at startup.
There are many different methods to perform RAM checking, but the common method is to write a known mode, and then wait for a short period of time to read back. The result should be that what you read is what you write. The truth is that RAM check is passed in most cases, which is also the result we want. But there is also a very small possibility that the check fails, which provides an excellent opportunity for the system to identify hardware problems.
Tip 4 - Using the Stack Monitor
For many embedded developers, the stack seems to be a rather mysterious force. When strange things began to happen, engineers were finally baffled, and they began to think, maybe something happened in the stack. The result is blindly adjusting the size and position of the stack, and so on. But this error is often stack independent, but how can we be so sure? After all, how many engineers have actually performed 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 required by the application are constantly stored in 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 destroy data in adjacent memory regions.
One way to absolutely ensure that the stack works is to implement a stack monitor as part of the system's "health care" code (how many engineers do this?). The stack monitor creates a buffer area between the stack and the "other" memory area and populates it with known bit patterns. Then the monitor will constantly monitor whether there is any change in the pattern. If the bit pattern changes, it means that the stack has grown too much, and the system will be pushed to the dark hell! At this time, the monitor can record the event occurrence, system status and any other useful data for future problem diagnosis.
Stack monitors are provided in most real-time operating systems (RTOS) or microcontroller systems that implement memory protection units (MPUs). Terrible is that these functions are turned off by default, or are often intentionally turned off by developers. A quick search on the network shows that many people suggest turning off the stack monitor in the real-time operating system to save 56 bytes of flash memory space, etc. This is not worth the loss!
Tip 5 - Using MPU
In the past, it was difficult to find a memory protection unit (MPU) in a small and cheap microcontroller, but this situation has begun to change. Now, MPUs have been available in micro controllers from high-end to low-end, and these MPUs provide embedded software developers with an opportunity to greatly improve the robustness of their firmware.
MPU has been gradually coupled with the operating system to establish memory space, in which the processing is separated, or the task can execute its code without worrying about being stopped on. If something happens, the uncontrolled processing will be canceled and other protective measures will be implemented. Please pay attention to the microcontrollers with such components, if any, please make more use of this feature.
Tip 6 - Build a strong watchdog system
One of the most popular watchdog implementations you will often find is where the watchdog is enabled (which is a good start), but also where you can reset the watchdog with a periodic timer; Timer activation is 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 reset, that is, when the work is suspended, the system will be forced to perform hardware reset to recover. Using a timer that is independent of system activity allows the watchdog to remain clear even if the system has failed.
The embedded motherboard developers need to carefully consider and design how to integrate the application tasks into the watchdog system. For example, there is a technique that may allow each task running within a certain period of time to indicate that it can successfully complete its task. In this event, the watchdog is not reset and is forced to reset. There are also some more advanced technologies, 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 establish a strong watchdog system.
Tip 7 - Avoid volatile memory allocation
Engineers who are not used to working in resource limited environments may try to use the features of their programming language, which allows them to use volatile memory allocation. After all, this is a technology often used in calculator systems, where memory is allocated only when necessary. For example, when developing in C, engineers may prefer to use malloc to allocate space on the heap. An operation will be executed. Once it is completed, you can use free to return the allocated memory for the use of the heap.
In a resource constrained system, this may be a disaster! One of the problems with volatile memory allocation is that incorrect or improper techniques can lead to memory leaks or memory fragmentation. For more information, Penguin Love Bar Jiuling wants to be strange. If these problems occur, most embedded systems do not have the resources or knowledge to monitor the heap or properly handle it. When they happen, what happens if the application asks for space, but there is no space to use?
The problems caused by using volatile memory allocation are very complex. It can be said that it is a nightmare to properly handle these problems! An alternative is to simplify memory allocation directly in a static way. For example, simply create a 256 byte buffer in the program instead of requesting a memory buffer of this size via malloc. This allocated memory can be maintained throughout the life cycle of the application without concerns about heap or memory fragmentation.
The above embedded motherboard design and development tutorial can enable developers to obtain better embedded system methods. All these technologies are the secret for designers to develop more reliable embedded systems.