EMC
Last Updated: Oct 15th, 2008 - 11:04:30
|
See this
article in our Digital Edition Download a
pdf of this article (right click to save the
pdf)
Ask any embedded software
engineer about EMC and they’ll probably say that it’s the hardware
engineer’s responsibility (those that know what EMC means in the first
place). However, try running any piece of microprocessor based hardware
without code and you’ll see a significant difference in the EMC
characteristics (not to mention a complete lack of functional
performance) than the same product with code. Therefore it is obvious
that the software does have an impact on the EMC performance of a
product, but the biggest problem is that most of the software impact is
difficult to quantify, and even more difficult for software people to
accept and take any responsibility for.
There are, of course, limits. All the great software in the world can’t
compensate for a poor PCB design or a bad electrical circuit. But,
assuming the hardware itself has been designed intelligently, there is
a lot of benefit in considering the EMC impact of embedded software.
(Note to readers: firmware will be used in this article for embedded
software, and by this I mean software that contains the embedded
function of a product and not platform code that is easy to change [i.e. not an embedded PC]).
Proof Positive
The traces in Figure 1 are taken from the same piece of Telematics
hardware running two different application programs. The first was a
speaking navigation system, and the second a silent stolen vehicle
tracking product. It might be obvious that a speaking version would
have higher emissions than a non-speaking version, but over the
frequency range 30-200MHz? (Note: both had the same test harness and
connected hardware, including speaker, for the test.) Clearly a
completely different piece of software running on the same hardware
platform can have significant differences in the EMC profile, although
both passed the same immunity requirements (60V/m).
Figure 1: Same hardware, different
firmware has a significant impact on measured radiated emissions (note:
audio output is generating emissions in the 100MHz range).
What about the same software running on the same platform? Just to
illustrate how sensitive a product’s EMC can be to software, the trace
in Figure 2 is the difference between the same software, running on the
same hardware, but with different compiler settings. Due to
confidentiality I am only allowed to show the magnitude of the
difference between the 2 compiler options and not the absolute levels.
However, this shows that even making the same software a little more
compact (for the ever present “future expansion”) has an impact on the
radiated emissions profile, with over ±10dB of difference that can be
observed between the two compiler versions. Worse still, this type of
impact is not only almost impossible to predict, but neither version
offers significant benefit over the other, and both have equally
positive and negative impacts on the EMC performance.
Figure 2: Same hardware, same firmware, different compiler options alone has an impact on measured radiated emissions.
Programming Issues for EMC
A program within a system, microcontroller, or even a simple logic
controller can have an influence on the immunity as well as the
emissions of a system. Immunity is often easiest to consider, as many
error checking and code validation routines already exist to ensure
that corrupted transmissions are not accepted. Hence, many programmers
are already aware of the issues of firmware immunity, although they may
not have considered this as an EMC issue.
On the emissions side, it is more likely to be a case of acknowledging
the best practices for addressing and operating the hardware from
firmware codes. For example, setting a UART to tri-state from input,
then to outputs, may reduce the transient power demand, compared to a
direct input-to-output change of state. This is generally known as
defensive programming.
Many techniques, such as a watchdog function, do not actually improve
emissions or immunity but simply provide a controlled method of
recovery. Techniques involving simple known recovery states are usually
less program intensive than performance improving techniques. The
latter tend to have a higher programming overhead (i.e., require more
code to execute) and more memory for storage.
Immunity Issues in Programming
It is much easier to understand how the firmware in a product impacts
on immunity than emissions, but conversely it is relatively easy to
prove the emissions impact of code, given adequate testing resources
(see Figures 1 and 2). Often, the impact of immunity programming is
difficult to quantify and determine effectiveness without expensive and
time consuming testing, typically well beyond what most companies are
prepared to invest in. Once a product meets its essential EMC
requirements, few companies test to failure to determine the immunity
safety margin.
Watchdog Programming
When incorporating a watchdog circuit into a design, some programming
may be required for the timer reset of the watchdog. If possible, the
code should poll the watchdog pin once per program cycle. This is not
too much of a problem with short microcontroller code or sequential
routines but, with general operation processors and long programs, this
may be difficult. There may therefore need to be additional timed
interrupts or hardware generated interrupts to address the watchdog
(e.g. dedicated watchdog interrupt handling code, as shown in Figure 3).
Figure 3: Software reset watchdog routine
The watchdog timer must be short enough to ensure non-catastrophic
failure of the circuit, and long enough not to interfere with
functionality of the program (durations between 10ms and 2s are typical
for watchdog timers). The trade-off in timing can be difficult to gauge
correctly for some coding. Processors with a Harvard bus structure
(independent data and instruction busses) are easier in this respect,
as each instruction is known to require a single clock cycle. Therefore
code timing is simple—just count the instructions and divide by the
clock frequency:
A potential problem could occur if the watchdog code is not included
within the sleep cycle for those processors with low power sleep modes.
When the processor goes into sleep mode and the internal clock
frequency is reduced, unless the watchdog interrupt or poll function is
similarly adjusted, a reset could be implemented simply because the
sleep mode was activated. (I have seen this more frequently than I like
to admit, even when accompanied by the common solution of removing the
watchdog to solve the problem.)
Watchdog programming has memory overhead since it requires additional
program routines or interrupts. This may not be possible with fixed
memory microcontrollers and a hardware solution may be required.
Likewise, in real time operating systems (RTOS), interrupts or
software-based polling may not be possible due to their effect on
program functionality.
One simple hardware solution is to monitor lines that are known to
change frequently, such as the lowest order address or data line, and
use this for the watchdog polling line (Figure 4). The biggest problem
here is ensuring that these lines will always change with variable code
and within the watchdog timing regime. The advantage of hardware is
that it requires no programming, and therefore less memory. The
disadvantage is the increase in component count to implement the
function. It is most likely to cost more in development time to
implement the watchdog function in software than in hardware, but code
is generally the best implementation, especially as even a crashed
program could continue to toggle the lines a hardware based watchdog
system is monitoring.
Figure 4: A hardware watchdog based on low count line activity needs careful implementation.
The most effective reset coding for a watchdog timer is to dedicate an
output pin of the microprocessor to the watchdog (Figure 5). This pin
should be set and cleared alternatively as the program routines are
executed (Figure 6). By using an AC coupled watchdog set and reset, if
the code loops within a single routine that includes a watchdog set
command, the watchdog is still effective and this single port condition
status and will operate the reset. This effectively doubles the
robustness of the watchdog with only a small code overhead (alternating
port set and port clear commands).
Figure 5: By using an AC coupled watchdog, static “reset” states are also captured.
Figure 6: AC coupled watchdog needs closer control of set/reset activity of watchdog line, hence has a higher code overhead.
Refresh Port Connections
The data direction registers and the input/output port data registers
are usually located near the edge of the processor’s package (if
included in the microprocessor itself), and may be connected directly
to the external circuits. Consequently, these are highly likely to have
noise on their lines. A simple way of minimizing this noise disturbing
the data settings and propagating into the microprocessor IC or system
is to refresh these registers regularly.
The action of the microprocessor rewriting these data registers
stabilizes the interfaced circuits and minimises the risk that noise on
these ports is corrupting other internal registers. This is a simple
task to perform regularly and involves minimal programming overhead,
just occasional write commands to the ports and data registers.
Some care does need exercising to ensure that writing the port status
is appropriate to the program activity at each re-write command. It
cannot be assumed that the value in the port status is the correct
setting, so a read and then re-write could result in enforcing an
erroneous setting.
Polling Interface Ports and Oversampling
Input and output to interfaced functions usually occurs at a much
slower rate than the microprocessor clock. This enables the
microprocessor to poll these pins several times to ensure that either
the level is set for an output or that the incoming signal is stable.
This is analogous with the types of over sampling used in digital audio
circuits (e.g., CD players).
The microprocessor can be programmed with an over sampling scheme,
either to ignore the first and last and take the mean of a middle
sample, for instance, or simple average. The actual scheme for polling
can be left to the programmer and will depend on the type of interface
being addressed (e.g., audio, keyboard, serial data link) and the
processing rate.
This type of programming has a code space and run time overhead, as it
requires several repeats of an operation plus usually some mathematical
interpretation. The result is an improved immunity to noisy input
signals and less susceptible output ports. This may best be implemented
using a dedicated input/output microcontroller with this type of
software programmed on-chip rather than as an auxiliary program for a
main processor.
Dedicated input/output interface controllers are quite popular in
larger systems; hence adding local code to improve the immunity should
be relatively easy. The same code could then be used for any system
with that type of interface controller making the immunity improvement
portable to other systems.
Token Passing
Token passing is a deliberate method of ensuring that the program is
progressing in a controlled manner and has not been jumped into due to
a code corruption. This requires additional programming steps at each
critical subroutine or program block within the final program.
Token passing requires a token (value) to be either updated in memory
or in a register. As each routine is called, it checks to ensure that
the call is from the previous set of code by comparing the token with a
programmed value or memory location. If a jump has occurred
prematurely, the token will not be set correctly; likewise, if the call
has come from a random corruption, the token will be in the wrong
state. On the discovery of a wrong token, a reset routine is initiated.
The advantages of token passing over other methods are that the program
continuously looks for errors, rather than waiting for an error to
occur, and the token itself can be used to reset to a predefined
location in the program. It may not be necessary to completely reset
the system depending on the location of the error and the token value.
This obviously saves program time but also gives a genuine level of
immunity rather than a simple reset-on-error recovery. The extra
programming overhead is in adding the compare program to the start of
each sub-routine and the token update to the end, plus any error
handling software control if a system reset is to be avoided, as
follows:
| Code |
| Comment | | ... |
|
| | :sub21 |
| start of sub routine | | LDA | &token | load accumulator with token | | LDB | &value | load correct token value | | CMP |
| compare token and value | | BNE | #reset | jump to reset routine if token incorrect | | XXX |
| otherwise proceed with program | | ... |
|
| | XXX |
|
| | LDA | &token | load token | | INC |
| increment token value for next routine | | STA | &token | save token | | :end_sub21 |
| end of sub routine program | | ... |
|
|
If attempting to use the token passing technique to recover to a known
program position, more programming effort will be required and probably
several tokens to ensure register and flag conditions are suitable for
re-entry into areas of code. Using the token value alone is
insufficient to reset routines where register or memory writes have
occurred, as these will most likely be incorrectly set.
Unused Memory Addresses
In most applications it is impossible to exactly fill all memory
locations, either ROM or RAM. These locations could be accessed due to
a software or hardware addressing error caused by a corrupted code.
These unused memory locations should therefore have a known operation
placed in them, usually either a no operation (NOP) or an unconditional
jump to a reset routine (JMP RESET), as follows:
| Address | Code | Comment | | 0000 | XXX | functional program area | | ... |
|
| | 00FA | XXX | end of program area | | 00FB | NOP | start of unused memory block | | 00FC | NOP |
| | ... |
|
| | 010F | JMP RESET | jump to reset routine | | 0110 | XXX | functional program area | | ... |
|
|
Where blocks of memory are unused, the jump to reset should be at the
bottom of the memory with no operation commands above. These blocks may
be scattered about the ROM/RAM locations and need to be carefully
mapped if this type of feature is to be used.
Writing these areas will be required by the initialization program if
they are in RAM locations. There is of course the possibility that a
corrupted write code could rewrite these NOP instructions in the RAM
space, similarly with the program itself, but it is impossible to
program for all eventualities and a reasonable trade-off between
effectiveness and efficiency of programming has to be drawn.
This technique requires only a small amount of additional programming
to the start-up (boot) routine and should not require any run time
program overhead. The filling of unused memory locations has become a
relatively common feature of some compilers. Whether these put a reset
vector jump at the end of this filled space is difficult to determine,
so they may only offer a half satisfactory solution.
Code Ghosting
This is one of the most memory intensive and possibly expensive
techniques, usually reserved for fault tolerant software. The technique
requires each code or data value to be stored in two parallel locations
(either in identical or in complement form). The code or data is then
compared to its ghost value prior to use.
The potential for EMI causing both codes to be corrupted is extremely
low; however, the microprocessor still has no way of knowing which of
the two codes is correct and which is corrupt. The microprocessor would
have to handle a code mismatch by reloading to check if the error was
in the load operation, or abort to a known routine if the error is in
the stored memory values, as follows:
| Code |
| Comment | | ... |
|
| | :sub32 |
| start of sub routine | | LDA | &code | load accumulator with code value | | LDB | &ghost | load ghost value | | CMP |
| compare value and ghost | | BNE | #error | jump to error routine if values do not match | | XXX |
| otherwise proceed with program | | ... |
|
|
This method is a memory implementation of the over-sampling technique
and could be extended if necessary, although at some cost if there is a
lot of code (i.e., 3 or 4 copies could be used for comparison). If
multiple ghost values are used, a mathematical method of selecting the
correct value could be applied (e.g., numerical digital average of each
bit). The method can also be selectively applied to code or data values
from a known problematic location or EMC critical area of the system or
program.
Other Techniques
There are other techniques that are more specific to the hardware being
used and the best methods of operating interfaces and associated
circuits (for example, the interface with a tristate setting mentioned
in the first part of this section). If a setting of the port from
logical outputs to inputs causes a large switch in internal states of
an IC, resulting in a large current demand, an intermediate state may
be available that has only a fraction of the transient current demand
when switched (Figure 7). Using the intermediate state between
transitions requires only one additional code instruction and will
reduce transient supply demand and hence conducted noise levels.
Figure 7: Where a tri-state operation is available, lower transition currents can be achieved.
The intermediate state transition technique may be applicable to other
circuits, such as clearing selective flags prior to rewriting, and may
save the number of actual data or address lines driven, thereby again
reduce transient demand. Actual transient savings in many circuits will
be negligible, and the idea is best reserved for those functions that
are known to require larger current supply (e.g., line drivers,
interface circuits and bidirectional ports).
Another technique that can help with interfaces is to use a coding
scheme, such as Manchester coding, which has only a few frequencies in
the transmission. In Manchester coding, only 2 frequencies are used: a
‘1’ is indicated by a single transition, and a ‘0’ by a double
transition within the clock cycle (Figure 8). The signal is therefore
always changing state, and a latched condition or end of transmission
are also easy to detect. The receiving circuit can potentially
determine if the sender is experiencing EMC problems. With standard
non-return to zero (NRZ) coding, the frequencies present in the
transmission
can be from the clock frequency to whatever the maximum bit code length
period is (i.e., 1/8 the clock frequency for an 8-bit code, as shown in
Figure 9).
Figure 8: An non-return to zero (NRZ) coding has a wide possible frequency content, depending on the value of the bit stream.
Figure 9: Manchester coding has only 2 frequencies for all bit stream values.
Manchester coding makes filtering easier, if required, and allows for a
simpler method of triggering on levels rather than edges that will also
improve immunity. The clock of the transmission circuit is derivable
from the signal; hence, using a fixed offset delay, a level triggered
receive circuit is easy to implement in either software (using a delay
routine) or in hardware (using a delay line).
Converting standard edge triggered circuits to level triggered is
possible at specific ports by using a software code delay to allow the
value to settle prior to reading. The length of delay will depend on
the function, but should allow the ringing or overshoot to settle and
consequently not affect the value read at the port (Figure 10). A
typical settling time should be 10% of the maximum clock period. This
can also be implemented in hardware using a delayed latch trigger, with
the data ready signal coming from the delayed latch set condition
(Figure 11).
Figure 10: Setting the port prior to reading can flush any noise built on the terminal pins when in a high impedance state.
Figure 11: Delayed port read is equivalent to a software low pass filter.
It is generally easier to give these examples in assembler or in a flow
diagram as it is easier to understand what any target microprocessor is
expected to do, but the concepts are not exclusive to assembler and
should, in most parts, be able to be coded in any higher level
language. While it is true that some compilers may make some of these
possible methods difficult, others can be available as a compiler
option (certainly a feature such as fill unused memory with NOP can be
found in many modern compilers).
Nothing Comes for Free
Many think software changes and improvements are free, but this is
simply not true. While these techniques have obvious overhead costs in
thinking about the issues, and will possibly slow code development down
while they are implemented, there will also be some increase in code
size and hence memory requirements. The magnitude of the increase
required for each technique is difficult to specify with any great
accuracy, as it will depend on the code structure, complexity and even
function to some extent. However, Table 1 gives a “rough guide” to what
impact in code size terms the techniques discussed here might have.
| Technique | Code Increase | | Unused Memory Fill | 0% | | Token Passing | 5-15% | | Port Delay | 1% | | Port Refresh | 2-5% | | Oversampling | 2-5% | | Ghost Coding | 10-30% |
Table 1
“EMC is Not a Software Issue”
This is a response that often prevents these techniques from being
implemented, and certainly few software engineers will accept any
responsibility for EMC. Many of the defensive techniques are often seen
as “hacks” for poor hardware implementation, but the evidence at the
start of this article for the impact of software on EMC is clear. This
will not make it any easier to get your software people to accept these
methods, or to recognize that they can impact the EMC of a product at
all.
The greatest problem is the difficulty in quantifying the benefits, as
these will vary from product to product. For example, I can not suggest
that using a tri-state intermediate condition will reduce your
emissions by 20dB, since there is simply no easy way to put a figure on
this and, if your emissions are very low anyway, the chances are there
would be no noticeable impact. But it is better to start with the best
conditions possible than to wait until the test results come back
negative and have to search for ideas to improve the product with a
launch date looming. On the other side of the coin, if results are
close to the limit, a software change may be a lower cost solution than
filters and a new hardware revision.
Martin O’Hara runs the Automotive EMC Network (www.autoemc.net), and can be reached at news@autoemc.net.
© 2007 Conformity
Top of Page
|