Файл: Introduction to microcontrollers (G. Gridling, 2006).pdf
ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 14.06.2025
Просмотров: 1064
Скачиваний: 2
2.2. MEMORY |
29 |
erase them, a UV light source is needed. Obviously, a technological improvement was in order.
The EEPROM (Electrically Erasable and Programmable ROM) has all the advantages of an EPROM without the hassle. No special voltage is required for programming anymore, and – as the name implies – no more UV light source is needed for erasing. EEPROM works very similar to EPROM, except that the electrons can be removed from the floating gate by applying an elevated voltage.
We got a little carried away there when we claimed that no special voltage is necessary: An elevated voltage is still needed, but it is provided on-chip via so-called charge pumps, which can generate higher voltages than are supplied to the chip externally.
Of course, EEPROMs have their limitations, too: They endure a limited number of write/erasecycles only (usually in the order of 100.000 cycles), and they do not retain their information indefinitely, either.
EEPROMs are used quite regularly in microcontroller applications. However, due to their limited write endurance, they should be used for longer term storage rather than as scratch memory. One example where EEPROMs are best used is the storage of calibration parameters.
Flash
Now, EEPROM seems to be the perfect choice for non-volatile memory. However, there is one drawback: It is rather expensive. As a compromise, Flash EEPROM is available. Flash is a variant of EEPROM where erasing is not possible for each address, but only for larger blocks or even the entire memory (erased ‘in a flash’, so to speak). That way, the internal logic is simplified, which in turn reduces the price considerably. Also, due to the fact that it is not possible to erase single bytes, Flash EEPROM is commonly used for program, not data memory. This, in turn, means that reduced endurance is acceptable – while you may reprogram a data EEPROM quite often, you will usually not reprogram a microcontroller’s program Flash 100.000 times. Therefore, Flash-EEPROMs often have a lower guaranteed write/erase cycle endurance compared to EEPROMs – about 1.000 to 10.000 cycles. This, too, makes Flash-EEPROMs cheaper.
NVRAM
Finally, there is a type of memory that combines the advantages of volatile and non-volatile memories: Non-Volatile RAM (NVRAM). This can be achieved in different ways. One is to just add a small internal battery to an SRAM device, so that when external power is switched off, the SRAM still retains its content. Another variant is to combine a SRAM with an EEPROM in one package. Upon power-up, data is copied from the EEPROM to the SRAM. During operation, data is read from and written to the SRAM. When power is cut off, the data is copied to the EEPROM.
2.2.3Accessing Memory
Many microcontrollers come with on-chip program and data memory. Usually, the program memory will be of the Flash-EEPROM type, and the data memory will be composed of some SRAM and some EEPROM. How does a particular address translate in terms of the memory addressed? Basically, there are two methods:
• Each memory is addressed separately, see Figure 2.7.
30 |
CHAPTER 2. MICROCONTROLLER COMPONENTS |
|||||
Flash |
EEPROM |
SRAM |
||||
$0000 |
$0000 |
$0000 |
||||
32K |
16K |
16K |
||||
$1FFF |
$1FFF |
|||||
$3FFF
Figure 2.7: Separate Memory Addressing.
The address ranges of the three different memory types can be the same. The programmer specifies which memory is to be accessed by using different access methods. E.g., to access EEPROM, a specific EEPROM-index register is used.
• All memory types share a common address range, see Figure 2.8.
SRAM
$0000 |
$0000 |
||
16K |
|||
$1FFF |
|||
$1FFF |
|||
EEPROM |
$2000 |
||
$0000 |
|||
16K |
$3FFF |
||
$4000 |
|||
$1FFF |
|||
Flash |
|||
$0000 |
|||
32K |
|||
$7FFF |
|||
$3FFF
Figure 2.8: Different memory types mapped into one address range.
Here, the programmer accesses EEPROM in the same way as SRAM. The microcontroller uses the address to decide which memory the access goes to. For example, EEPROM could be assigned an address range of 0x1000 – 0x2000, while SRAM shows up in the range 0x2000 – 0x3000. Now, when the programmer accesses address 0x1800, the microcontroller knows that this is in the EEPROM range, and therefore it will access the EEPROM. While this method is very straightforward, it is also inherently less safe: A wrong address can lead to the wrong type of memory being accessed. This would be especially dangerous if you were to inadvertently access the EEPROM instead of SRAM – with frequent access, the EEPROM could wear out in
2.2. MEMORY |
31 |
a matter of minutes. Separate memory addressing, on the other hand, comes with an implicit protection against access to the wrong type of memory.
When accessing byte-addressed memory word-wise, there is a special pitfall to be considered: Suppose a 16 bit controller writes a word (two bytes) into SRAM, say at address 0x0100. The word consists of a low and a high byte. Now, in what order are the bytes to be written? There are two variants: the low byte could go to 0x0100 and the high byte to the next address (0x0101), or the other way around. That is the problem of endianness:
Big Endian: Big Endian architectures store the high byte first. So, if you write the word 0x1234 to address 0x0100, the high byte 0x12 goes to address 0x0100, and the low byte 0x34 to address 0x0101. The name is derived from this order: The Big End of the word is stored first – therefore, it is called Big Endian.
Little Endian: Little Endian architectures access memory the other way around (Little End of the word first). Here, the low byte is stored first. Writing 0x1234 at address 0x0100 on a little endian architecture writes 0x34 to address 0x0100 and 0x12 to address 0x0101.
Note carefully, however, that this difference in the ordering of high and low is only relevant on a byte level. The bits within a byte are numbered from right to left on both architectures. So, the least significant bit is always the rightmost one.
2.2.4Exercises
Exercise 2.2.1 Assume that the values (1, 2, 3, 4) are stored at the memory (byte) addresses 0, 1, 2, 3. You load the word from address 1 into register R1 (assume that unaligned access is possible). Which (hexadecimal) value does R1 have if the architecture is big endian?
Exercise 2.2.2 What are the advantages of PROM over ROM? Are there any disadvantages?
Exercise 2.2.3 Why do EPROMs have a window, whereas EEPROMs do not have a window? What is the window used for?
Exercise 2.2.4 What is the difference between an EEPROM and a Flash-EEPROM?
Exercise 2.2.5 Assume you have an EEPROM that is specified for 100,000 write cycles. You want to store the daily exchange rate for some currency. For how many years can you use the EEPROM? Would it be sensible to put the EEPROM into a socket to be able to exchange it easily? What if you have to update the exchange rate hourly?
Exercise 2.2.6 What are the advantages and disadvantages of a RAM compared to an EEPROM?
Exercise 2.2.7 Why do microcontrollers use SRAMs and not DRAMs?
Exercise 2.2.8 Why does the NVRAM not copy every write access into the EEPROM? Would that not be more secure?
Exercise 2.2.9 When is an OTP memory useful? Would you put a controller with OTP memory into a cell phone?
Exercise 2.2.10 Assume that you have the loop for (i=100; i>=0; i--) in your C program. The loop variable i is inadvertently stored in EEPROM instead of SRAM. To make things worse, you implemented the loop with an unsigned variable i, so the loop will not stop. Since the access is now to the slow EEPROM, each iteration of the loop takes 10 ms.
32 |
CHAPTER 2. MICROCONTROLLER COMPONENTS |
When you start the program, your program hangs itself in the loop. You need 10 seconds to observe that the program is buggy and then start debugging. All the while, your program keeps running on the controller. How much time do you have to find the infinite-loop bug before you exhaust the guaranteed number of write cycles of your EEPROM? What can you do to prevent the controller from executing your faulty loop while you debug?
2.3. DIGITAL I/O |
33 |
2.3 Digital I/O
Digital I/O, or, to be more general, the ability to directly monitor and control hardware, is the main characteristic of microcontrollers. As a consequence, practically all microcontrollers have at least 1-2 digital I/O pins that can be directly connected to hardware (within the electrical limits of the controller). In general, you can find 8-32 pins on most controllers, and some even have a lot more than that (like Motorola’s HCS12 with over 90 I/O pins).
I/O pins are generally grouped into ports of 8 pins, which can be accessed with a single byte access. Pins can either be input only, output only, or —most commonly,— bidirectional, that is, capable of both input and output. Apart from their digital I/O capabilities, most pins have one or more alternate functions to save pins and keep the chip small. All other modules of the controller which require I/O pins, like the analog module or the timer, use in fact alternate functions of the digital I/O pins. The application programmer can select which function should be used for the pin by enabling the functionality within the appropriate module. Of course, if a pin is used for the analog module, then it is lost for digital I/O and vice versa, so the hardware designer must choose carefully which pins to use for which functions.
In this section, we will concentrate on the digital I/O capability of pins. Later sections will cover the alternate functions. First, let us explain what we mean by “digital”: When we read the voltage level of a pin with a voltmeter (with respect to GND), we will see an analog voltage. However, the microcontroller digitizes this voltage by mapping it to one of two states, logical 0 or logical 1. So when we talk about digital I/O, we mean that the value of the pin, from the controller’s perspective, is either 1 or 0. Note that in positive-logic, 1 corresponds to the “high” state (the more positive resp. less negative state) of the line, whereas 0 corresponds to the “low” state (the less positive resp. more negative state). In negative-logic, 1 corresponds to “low” and 0 to “high”. Microcontrollers generally use positive-logic.
As far as digital I/O is concerned, three registers control the behavior of the pins:
Data Direction Register (DDR): Each bidirectional port has its own DDR, which contains one bit for each pin of the port. The functionality of a pin (input or output) is determined by clearing or setting its bit in the DDR. Different pins of a port may be configured differently, so it is perfectly okay to have three pins configured to output and use the other five as inputs. After a reset, the DDR bits are generally initialized to input. Reading the register returns its value.
Port Register (PORT): This register is used to control the voltage level of output pins. Assuming a pin has been configured to output, then if its bit in the PORT register is set, the pin will be high; if the bit is cleared, the pin will be low. To avoid overwriting the other bits in the port when setting a particular bit, it is generally best to use the controller’s bit operations. Otherwise, you must use a read-modify-write access and hence must ensure that this access is not interrupted.
For output pins, reading the register returns the value you have written. For input pins, the functionality depends on the controller. Some controllers allow you to read the state of input pins through the port register. Other controllers, e.g. the ATmega16, use the port bits for other purposes if the corresponding pins are set to input, so here you will read back the value you have written to the register.
Port Input Register (PIN): The PIN register is generally read-only and contains the current state (high or low) of all pins, whether they are configured as output or as input. It is used to read the state of input pins, but it can also be used to read the state of output pins to verify that the output was taken over correctly. A write to this register generally has no effect.
34 |
CHAPTER 2. MICROCONTROLLER COMPONENTS |
Read-Modify-Write Access
A read-modify-write access is used to modify some bits within a byte without changing the others in situations where bit operations are not an option. The idea is to (1) read the whole byte, (2) change the bits you are interested in while keeping the states of the other bits, and (3) write the resulting value back. Hence, the whole operation consists of at least three instructions, possibly even more.
Within a single-taskinga microprocessor that just accesses memory locations, this is not a problem. However, in a multi-tasking system, or in a hardware-based system where register contents may be modified by the hardware, read-modify-write operations must be used with care. First of all, there is the question of how many sources can modify the byte in question. Obviously, your task code can modify it. If there is another source that can modify (some other bits of) the byte “concurrently”, e.g. in a multi-tasking system, then you can get a write conflict because Task1 reads and modifies the value, but gets interrupted by Task2 before it can write back the value. Task2 also reads the value, modifies it, and writes back its result. After that, Task1 gets back the CPU and writes back its own results, thus overwriting the modifications of Task2! The same problem can occur with a task and an ISR. In such a case, you must make sure that the read-modify-write operation is atomic and cannot be interrupted.
If the byte is an I/O register, that is, a register which controls and/or can be modified by hardware, the problem is even more urgent because now the hardware may modify bits anytime. There is also the problem that registers may be used for two things at once, like an I/O register that can function as a status register during read accesses and as a control register for write accesses. In such a case, writing back the value read from the register would most likely have undesired effects. Therefore, you must be especially careful when using I/O registers within read-modify-write operations.
aWe have not introduced the notion of tasks up to now, since we concentrate on small systems which will most likely not run an operating system. However, this discussion can be generalized to operating systems as well, so we use the term “task” here and trust that you know what we mean.
Let us stress again that each bit in these registers is associated with one pin. If you want to change the settings for one pin only, you must do so without changing the settings of the other bits in the register. The best way to do this, if it is supported by your controller, is to use bit operations. If you have to use read-modify-write operations on the whole register, at least make certain that the register’s contents will not change during the operation and that it is okay to write back to the register what you have read from it.
2.3.1Digital Input
The digital input functionality is used whenever the monitored signal should be interpreted digitally, that is, when it only changes between the two states “high” (corresponding to logic 1) and “low” (corresponding to 0). Whether a given signal should be interpreted as high or low depends on its voltage level, which must conform to the controller’s specifications, which in turn depend on the operating voltage of the controller. For example, the operating voltage VCC of the ATmega16 must be within the interval [4.5, 5.5] V, its input low voltage must be within [-0.5, 0.2VCC] V, and its input
2.3. DIGITAL I/O |
35 |
high voltage must be within [0.6VCC, VCC+0.5] V. This leaves the interval (0.2VCC, 0.6VCC) within which the signal is said to be undefined.
Digital Sampling
Since the digital signal is just a voltage value, the question arises how this voltage value is transformed into a binary value within a register. As a first solution, we could simply use latches for the PIN register and latch the current state of the pin into the register. If the latch is triggered by the system clock, it will store the current state at the beginning of every cycle. Naturally, since we can only sample with the granularity of the system clock, this means that we may recognize a state change only belatedly. We may even miss impulses altogether if they are shorter than a clock cycle, see Figure 2.9.
clock
w.c. delay
signal
PIN
Figure 2.9: Sampling an input signal once every clock cycle.
The delay introduced by the sampling granularity is dlatch = (0, 1] clock cycles. Note that zero is left out here, since it is not certain what happens when a signal changes at the same time as the sampling clock edge. It may get sampled, or it may not get sampled. It is therefore prudent to leave zero out of the interval. With the same reasoning, impulses should be longer than a clock cycle to be recognized with certainty. In the remaining text, we will use din = (dminin , dmaxin ] to denote the input delay interval, where dminin forms the lower bound on the input delay, and dmaxin denotes its upper bound.
Although this sampling technique looks quite useful and forms the basis of the controller’s input circuitry, it is unsuited to deal with a situation often encountered in real systems: What happens if the signal is slow to change? After all, the signal is generated by the hardware, which may behave unpredictably, so we do not have any guarantee that signal changes will be fast and may run into the problem that the signal is undefined when we try to latch. In this case, our simple solution runs head-long into the problem of meta-stability: A latch that gets an undefined voltage level as input has a certain probability p to enter and remain in a meta-stable state, in which it may output either high, or low, or an undefined value, or oscillate. Obviously, the last two options are disastrous for the controller and hence for the application and must be avoided, especially in safety-critical systems. To decrease the probability of such an occurence, the digital input circuitry of a controller generally first uses a Schmitt-trigger to get well-defined edges and filter out fluctuations in the input voltage. This restricts the problem to the short periods during which the Schmitt-trigger switches its output.
To reduce the probability of meta-stability even further, one or more additional latches may be set in series between the Schmitt-trigger and the PIN register latch. Such a construct is called a synchronizer. Figure 2.11 shows a block diagram of the resulting circuitry. Each additional synchronizer latch has the probability p to enter a meta-stable state if presented with an undefined input, so the whole chain of k latches including the PIN latch has probability pk 1 to pass on the meta-stable
36 |
CHAPTER 2. MICROCONTROLLER COMPONENTS |
Schmitt-trigger
Schmitt-triggers are components that can be used to “digitize” analog input signals. To do so, the Schmitt-trigger has two threshold voltages Vlo and Vhi, Vlo <Vhi, and changes its output from logical 0 to logical 1 only if the input signal rises above Vhi. To make the Schmitt-trigger change from 1 to 0, however, the signal must fall below Vlo. As a result, the Schmitt-trigger does not forward small voltage fluctuations, and its output always has short and well-defined rising and falling times regardless of the input signal, see Figure 2.10.
V unbounded |
|
Vhi |
input signal |
Vlo |
t |
V |
bounded |
Schmitt−trigger |
output |
t |
Figure 2.10: Input and Output of a Schmitt-trigger.
state all to way to the controller. In practice, one synchronizer latch generally suffices to bring the probability down to an acceptable level (but it will never be zero, no matter how many latches are used).
Schmitt− |
Synchr. |
Synchr. |
PIN |
||||||||||||||||||||
input |
trigger |
Latch |
Latch |
Latch |
|||||||||||||||||||
D Q |
D Q |
D Q |
|||||||||||||||||||||
signal |
|||||||||||||||||||||||
Q |
Q |
Q |
|||||||||||||||||||||
system clock
Figure 2.11: Block diagram of the basic input circuitry of a controller.
You may already have spotted the disadvantage of the synchronizer stage: It prolongs the time until a signal change is passed on to the controller by a constant dsync, which is simply the number of cycles it takes to pass a latched value from the first synchronizer latch to the PIN latch. Hence, din = dlatch + dsync. The ATmega16 controller, for instance, uses one synchronizer latch which is triggered by the falling edge of the system clock (whereas everything else is triggered by the rising edge). Hence, the synchronizer stage adds a delay of half a clock cycle, and the delay bounds for the ATmega16 become dminin = 0.5 and dmaxin = 1.5 clock cycles3.
3Note that we ignore the propagation delays of the Schmitt-trigger and the PIN latch here, which add an additional couple of nanoseconds (about 20-30).