Although many embedded engineers are full of hopes and dreams, high-reliability code is not a one-step process. It is a painstaking process that requires developers to maintain and manage every bit and byte of the system. When an application is identified as "successful", there is usually a feeling of relief, but just because the software is operating normally under controlled conditions does not mean that it will function normally tomorrow or a year later.

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 fill unused memory, there are many different possible combinations you can use, but if you want to establish a more reliable system, the most obvious choice is to place 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.

Additional information on how to use the FILL command and alternative strategies for its use can be found in "Using the FILL Command to Improve Code Integrity" (http://).

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 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.

There is a memtest C module, which Michael Barr wrote in 2000, which saves engineers the time it takes to consider RAM testing. The module can be downloaded here ( http:// ).

Tip #4 - Using the 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!

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 something happens, uncontrolled processing will be cancelled and other protections will be implemented. 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.

A battery charging contact consists of a base plate, which is installed on the floor or laterally at a bracket adjacent of the AGV runway, and a current collector which is installed on the vehicle.

 

A Battery Charger supplies current to the base plate. Once the AGV is in charging position and the collector has made contact with the base plate, the AGV computer turns on the current.

The base plate has chamfered entry/exit ramps to facilitate smooth drive-on/drive-off of the spring loaded collector.

Battery Charging Contacts

Battery Charging Contacts,Agv Battery Charging Support,Charging Contacts For Battery,200A Battery Charging System

Xinxiang Taihang Jiaxin Electric Tech Co., Ltd , https://www.chargers.be