âšď¸ Skipped - page is already crawled
| Filter | Status | Condition | Details |
|---|---|---|---|
| HTTP status | PASS | download_http_code = 200 | HTTP 200 |
| Age cutoff | PASS | download_stamp > now() - 6 MONTH | 0.5 months ago |
| History drop | PASS | isNull(history_drop_reason) | No drop reason |
| Spam/ban | PASS | fh_dont_index != 1 AND ml_spam_score = 0 | ml_spam_score=0 |
| Canonical | PASS | meta_canonical IS NULL OR = '' OR = src_unparsed | Not set |
| Property | Value |
|---|---|
| URL | https://users.ece.utexas.edu/~valvano/Volume1/IntroToEmbSys/Ch1_Introduction.html |
| Last Crawled | 2026-03-24 13:06:58 (14 days ago) |
| First Indexed | 2024-03-31 08:05:47 (2 years ago) |
| HTTP Status Code | 200 |
| Meta Title | Chapter 1: Introduction to Embedded Systems |
| Meta Description | null |
| Meta Canonical | null |
| Boilerpipe Text | Chapter
1: Introduction to Embedded Systems
Jonathan Valvano and Ramesh
Yerraballi
This chapter covers the basic foundation concepts
needed to build upon in this course. Specifically we will look at
embedded systems, number representation, digital logic, embedded system
components, and computer architecture: the Central Processing Unit
(Arithmetic Logic Unit, Control Unit and Registers), the memory and the
Instruction Set Architecture (ISA).
Table of Contents:
1.1.
Embedded Systems
1.2.
Binary Information Implemented with MOS transistors
1.3.
Numbers
1.4.
Introduction to Computers
1.5.
I/O Ports
1.6.
Memory
1.7.
Instruction Set Architecture
1.8.
Designing a NOT gate using a LaunchPad
Video
1.0
. Introduction, Examples of Embedded Systems
Â
Reference material relative to this chapter:
Digital
logic
Assembly
reference
Embedded Software in C for an ARM Cortex M
TM4C123 LaunchPad Users Manual
To better understand the expression embedded
microcomputer system, consider each word separately. In this context,
the word âembeddedâ means hidden inside so one canât
see it. The term âmicroâ means small, and a
âcomputerâ contains a processor, memory, and a means to
exchange data with the external world. The word âsystemâ
means multiple components interfaced together for a common purpose.
Systems have structure, behavior, and interconnectivity operating in a
framework bound by rules and regulations. Another name for embedded
systems is
Cyber-Physical Systems
, introduced in 2006 by Helen
Gill of the National Science Foundation, because these systems combine
the intelligence of a computer with the physical objects of our world.
As shown in Figure 1.1.1, the term embedded microcomputer system refers
to a device that contains one or more microcomputers inside.
Microcontrollers
,
which are complete computers incorporating the processor, RAM, ROM and
I/O ports into a single package, are often employed in an embedded
system because of their low cost, small size, and low power
requirements.Â
Figure 1.1.1. An embedded system includes a
microcomputer interfaced to external physical devices.
An
embedded system
includes a microcomputer
with mechanical, chemical, and electrical devices attached to it,
programmed for a specific dedicated purpose, and packaged up as a
complete system. Any electrical, mechanical, or chemical system that
involves inputs, decisions, calculations, analyses, and outputs is a
candidate for implementation as an embedded system. Electrical,
mechanical, and chemical sensors collect information. Electronic
interfaces convert the sensor signals into a form acceptable for the
microcomputer. For example, a tachometer is a sensor that measures the
revolutions per second of a rotating shaft. Microcomputer software
performs the necessary decisions, calculations, and analyses. Additional
interface electronics convert the microcomputer outputs into the
necessary form. Actuators can be used to create mechanical or chemical
outputs. For example, an electrical motor converts electrical power into
mechanical power.
If the embedded system is connected to the
internet, it is classified as an
Internet of Things
(IoT).
Video
1.1.1. Components of an embedded system
Figure 1.1.2. Embedded systems have computers hidden
inside.
:
What is an embedded system?
1.2. Binary Information Implemented with MOS
transistors
Information is stored on the computer in binary
form. A binary bit can exist in one of two possible states. In positive
logic, the higher voltage is called the â1â, true, asserted,
or high state. The lower voltage is called the â0â, false,
not asserted, or low state. Figure 1.2.1 shows the output of a typical
complementary metal oxide semiconductor (CMOS) circuit. The left side
shows the condition with a true bit at the output, and the right side
shows a false at the output. The output of each digital circuit consists
of a p-type MOS transistor âon top ofâ an n-type MOS
transistor. In digital circuits, each transistor is either on or off. If
the transistor is on, it is equivalent to a short circuit between its
two output pins. Conversely, if the transistor is off, it is equivalent
to an open circuit between its outputs pins.
Figure 1.2.1. A binary bit at the output is true if
a voltage is present and false if the voltage is 0.
:
What would have if both transistors
were on in Figure 1.2.1?
:
What would have if both transistors
were off in Figure 1.2.1?
Every family of digital logic is different, but on
the TM4C microcontrollers from TI powered with 3.3 V supply, a voltage
between 2.145 and 5 V is considered high. In general we define V
IH
as smallest input voltage considered high. A voltage between 0 and 1.155
V is considered low, as drawn in Figure 1.2.2. In general we define V
IL
as largest input voltage considered high. Separating the two regions by
0.99 V allows digital logic to operate reliably at very high speeds. The
design of transistor-level digital circuits is beyond the scope of this
book. However, it is important to know that digital data exist as binary
bits and encoded as high and low voltages.
Figure 1.2.2. Mapping between analog voltage and the
corresponding digital meaning on the TM4C.
If the information we wish to store exists in more
than two states, we use multiple bits. A collection of 2 bits has 4
possible states (00, 01, 10, and 11). A collection of 3 bits has 8
possible states (000, 001, 010, 011, 100, 101, 110, and 111). In
general, a collection of n bits has 2
n
states. For example, a
byte contains eight bits and is built by grouping eight binary bits into
one object, as shown in Figure 1.2.3. Another name for a collection of
eight bits is octet (octo is Latin and Greek meaning 8.) Information can
take many forms, e.g., numbers, logical states, text, instructions,
sounds, or images. What the bits mean depends on how the information is
organized and more importantly how it is used. This figure shows one
byte in the state representing the binary number 01100111, which could
mean 103. As a character, this same collection of bits represents the
letter âgâ. Again, the output voltage 3.3V means true or 1,
and the output voltage of 0V means false or 0.
Figure 1.2.3. A byte is comprised of 8 bits, in this
case representing the binary number 01100111.
:
Why is there a gap between V
IL
and V
IH
?
:
The TM4C123 is powered at 3.3V. Can you
think of a reason to reduce the supply voltage to 1.65V?
1.3. Numbers
A great deal of confusion exists over the
abbreviations we use for large numbers. In 1998 the International
Electrotechnical Commission (IEC) defined a new set of abbreviations for
the powers of 2, as shown in Table 1.3.1. These new terms are endorsed
by the Institute of Electrical and Electronics Engineers (IEEE) and
International Committee for Weights and Measures (CIPM) in situations
where the use of a binary prefix is appropriate. The confusion arises
over the fact that the mainstream computer industry, such as Microsoft,
Apple, and Dell, continues to use the old terminology. According to the
companies that market to consumers, a 1 GHz is 1,000,000,000 Hz but 1
Gbyte of memory is 1,073,741,824 bytes. The correct terminology is to
use the SI-decimal abbreviations to represent powers of 10, and the
IEC-binary abbreviations to represent powers of 2. The scientific
meaning of 2 kilovolts is 2000 volts, but 2 kibibytes is the proper way
to specify 2048 bytes. The term
kibibyte
is a contraction of
kilo binary byte and is a unit of information or computer storage,
abbreviated KiB.
1 KiB = 2
10
bytes = 1024 bytes
1 MiB = 2
20
bytes = 1,048,576 bytes
1 GiB = 2
30
bytes = 1,073,741,824 bytes
These abbreviations can also be used to specify the
number of binary bits. The term
kibibit
is a contraction of kilo
binary bit, and is a unit of information or computer storage,
abbreviated Kibit.
A
mebibyte
(1 MiB is 1,048,576 bytes) is
approximately equal to a megabyte (1 MB is 1,000,000 bytes), but
mistaking the two has nonetheless led to confusion and even legal
disputes. In the engineering community, it is appropriate to use terms
that have a clear and unambiguous meaning.
Value
SIÂ Â Â Â Â Â Â Â Â
Decimal
SIÂ Â Â Â Â Â Â Â Â
Decimal
Value
IECÂ Â Â Â Â Â Â Â Â
Binary
IECÂ Â Â Â Â Â Â Â Â
Binary
1000
1
k
kilo-
1024
1
Ki
kibi-
1000
2
M
mega-
1024
2
Mi
mebi-
1000
3
G
giga-
1024
3
Gi
gibi-
1000
4
T
tera-
1024
4
Ti
tebi-
1000
5
P
peta-
1024
5
Pi
pebi-
1000
6
E
exa-
1024
6
Ei
exbi-
1000
7
Z
zetta-
1024
7
Zi
zebi-
1000
8
Y
yotta-
1024
8
Yi
yobi-
Table
1.3.1. Common abbreviations for large numbers.
To solve problems using a computer we need to
understand numbers and what they mean. Each digit in a
decimal
number has a place and a value. The
place
is a power of 10
and the
value
is selected from the set {0, 1, 2, 3, 4, 5, 6, 7,
8, 9}. A decimal number is simply a combination of its digits multiplied
by powers of 10. For example
                              Â
1984
= 1
â˘
10
3
+ 9
â˘
10
2
+ 8
â˘
10
1
+ 4
â˘
10
0
Fractional values can be represented by using the
negative powers of 10. For example,
                              Â
273.15
= 2
â˘
10
2
+ 7
â˘
10
1
+ 3
â˘
10
0
+ 1
â˘
10
-1
+ 5
â˘
10
-2
In a similar manner, each digit in a
binary
number has a place and a value. In binary numbers, the place
is a power of 2, and the value is selected from the set {0, 1}. A binary
number is simply a combination of its digits multiplied by powers of 2.
To eliminate confusion between decimal numbers and binary numbers, we
will put a subscript 2 after the number to mean binary. Because of the
way the microcontroller operates, most of the binary numbers in this
class will have 8, 16, or 32 bits. An 8-bit number is called a
byte
,
and a 16-bit number is called a
halfword
. For example, the 8-bit
binary number for 106 is
          Â
0
1
1
0
1
0
1
0
2
=
0
â˘
2
7
+
1
â˘
2
6
+
1
â˘
2
5
+
0
â˘
2
4
+
1
â˘
2
3
+
0
â˘
2
2
+
1
â˘
2
1
+
0
â˘
2
0
=
64
+
32
+
8
+
2
= 106
:
What is the numerical value of the
8-bit binary number 11111111
2
?
Video
1.3.1
. Binary representation
Interactive Tool 1.1
You have already learned
how to convert from a binary number to its decimal representation. All
you need to do is to calculate its value by multiplying each coefficient
by its placeholder values and summing all of them together. If you want
to practice, first think of an 8-digit binary number, and next type into
the box from 1 to 8 binary digits. Try to calculate the decimal
representation in your head. Then click "convert" to check your result.
Binary is the natural language of computers but a
big nuisance for us humans. To simplify working with binary numbers,
humans use a related number system called
hexadecimal
, which
uses base 16. Just like decimal and binary, each hexadecimal digit has a
place and a value. In this case, the place is a power of 16 and the
value is selected from the set {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C,
D, E, F}. As you can see, hexadecimal numbers have more possibilities
for their digits than are available in the decimal format; so, we add
the letters A through F, as shown in Table 1.3.2. Hexadecimal
representation is a convenient
mechanism for us humans to define binary information, because it is
extremely simple for humans to convert back and forth between binary and
hexadecimal.
Video
1.3.2
. Hexadecimal representation
Hex Digit
DecimalÂ
Value
Binary Value
0
0
0000
1
1
0001
2
2
0010
3
3
0011
4
4
0100
5
5
0101
6
6
0110
7
7
0111
8
8
1000
9
9
1001
A or a
10
1010
B or b
11
1011
C or c
12
1100
D or d
13
1101
E or e
14
1110
F or f
15
1111
Table 1.3.2. Definition of hexadecimal
representation.
For example, the hexadecimal number for the 16-bit
binary 0001 0010 1010 1101 is
                              Â
0x12AD
= 1
â˘
16
3
+ 2
â˘
16
2
+ 10
â˘
16
1
+ 13
â˘
16
0
= 4096+512+160+13 = 4781
Interactive Tool 1.2
You have already learned how to convert from
a hexadecimal number to its decimal representation. All you need to do
is to calculate its value by multiplying each coefficient by its
placeholder values and summing all of them together. If you want to
practice, Choose an 4-digit hexadecimal number number. Try to calculate
the decimal representation. Then type the number in the following field
and click "convert" to check your result.
:
What is the numerical value of the
8-bit hexadecimal number 0xFF?
:
Convert the binary numberÂ
01000101
2
to hexadecimal.
:
Convert the binary number 110010101011
2
to
hexadecimal.
:
Convert the hex number 0x40 to binary.
:
Convert the hex number 0x63F to binary.
:
How many binary bits does it take to
represent 0x123456?
Precision
is the number of distinct or
different values. We express precision in alternatives, decimal digits,
bytes, or binary bits.
Alternatives
are defined as the total
number of possibilities. For example, an 8-bit number format can
represent 256 different numbers. An 8-bit
digital to analog
converter
 (DAC) can generate 256 different analog outputs. An
8-bit
analog to digital converter
 (ADC) can measure 256
different analog inputs. Table 1.3.3 illustrates the relationship
between precision in binary bits and precision in alternatives. The
operation [[
x
]]
is defined as the greatest integer of
x
.
E.g., [[2.1]]Â [[2.9]]Â and [[3.0]] are all equal to 3. The
Bytes
column in Table 2.1 specifies how many bytes of memory it would take to
store a number with that precision assuming the data were not packed or
compressed in any way.
Binary
bits
Bytes
Alternatives
8
1
256
10
2
1024
12
2
4096
16
2
65536
20
3
1,048,576
24
3
16,777,216
30
4
1,073,741,824
32
4
4,294,967,296
n
[[n/8]]
2
n
Table 1.3.3. Relationship between bits, bytes and
alternatives as units of precision.
:
How many bytes of memory would it take
to store a 50-bit number?
A
byte
contains 8 bits as shown in Figure
1.3.1, where each bit b
7
,...,b
0
is binary and has the value 1
or 0. We specify b
7
as
the
most significant bit
or MSB, and b
0
as the least significant bit or LSB.
Figure 1.3.1. 8-bit binary format.
If a byte is used to represent an unsigned number,
then the value of the number is
              Â
                              Â
N
= 128
â˘
b
7
+ 64
â˘
b
6
+ 32
â˘
b
5
+ 16
â˘
b
4
+ 8
â˘
b
3
+ 4
â˘
b
2
+ 2
â˘
b
1
+ b
0
Notice that the significance of bit
n
is 2
n
.
There are 256 different unsigned 8-bit numbers. The smallest unsigned
8-bit number is 0 and the largest is 255. For example, 00001010
2
is 8+2 or 10. The least significant bit can tell us if the number is
even or odd.
:
Convert the binary number 01101001
2
Â
to
unsigned decimal.
:
Convert the hex number 0x54 to
unsigned decimal.
The
basis
of a number system is a subset
from which linear combinations of the basis elements can be used to
construct the entire set. The basis represents the âplacesâ
in a âplace-valueâ system. For positive integers, the basis
is the infinite set {1, 10, 100, âŚ}, and the âvaluesâ
can range from 0 to 9. Each positive integer has a unique set of values
such that the dot-product of the value vector times the basis vector
yields that number. For example, 2345 is (âŚ, 2,3,4,5)
¡
(âŚ,
1000,100,10,1),
which is 2*1000+3*100+4*10+5. For the unsigned 8-bit number system, the
basis elements are
              Â
                              Â
{1,
2, 4, 8, 16, 32, 64, 128}
The values of a binary number system can only be 0
or 1. Even so, each 8-bit unsigned integer has a unique set of values
such that the dot-product of the values times the basis yields that
number. For example, 69 is (0,1,0,0,0,1,0,1)
¡
(128,64,32,16,8,4,2,1),
which
equals 0*128+1*64+0*32+0*16+0*8+1*4+0*2+1*1. Conveniently, there is no
other set of 0âs and 1âs, such that set of values multiplied
by the basis is 69. In other words, each 8-bit unsigned binary
representation of the values 0 to 255 is unique.
One way for us to convert a decimal number into
binary is to use the basis elements. The overall approach is to start
with the largest basis element and work towards the smallest. More
precisely, we start with the most significant bit and work towards the
least significant bit. One by one, we ask ourselves whether or not we
need that basis element to create our number. If we do, then we set the
corresponding bit in our binary result and subtract the basis element
from our number. If we do not need it, then we clear the corresponding
bit in our binary result. We will work through the algorithm with the
example of converting 100 to 8-bit binary, see Table 2.4. We start with
the largest basis element (in this case 128) and ask whether or not we
need to include it to make 100? Since our number is less than 128, we do
not need it, so bit 7 is zero. We go the next largest basis element, 64
and ask, âdo we need it?â We do need 64 to generate our 100,
so bit 6 is one and we subtract 100 minus 64 to get 36. Next, we go the
next basis element, 32 and ask, âdo we need it?â Again, we
do need 32 to generate our 36, so bit 5 is one and we subtract 36 minus
32 to get 4. Continuing along, we do not need basis elements 16 or 8,
but we do need basis element 4. Once we subtract the 4, our working
result is zero, so basis elements 2 and 1 are not needed. Putting it
together, we get 01100100
2
(which means 64+32+4).
:
In this conversion algorithm, how can
we tell if a basis element is needed?
Observation:
If the least significant binary
bit is zero, then the number is even.
Observation:
If the right-most n bits (least
sign.) are zero, then the number is divisible by 2
n
.
Observation:
Consider an 8-bit unsigned
number system. If bit 7 is low, then the number is between 0 and 127,
and if bit 7 is high then the number is between 128 and 255.
:
Give the representations of the
decimal 45 in 8-bit binary and hexadecimal.
:
Give the representations of the
decimal 200 in 8-bit binary and hexadecimal.
Interactive Tool 1.3
There are a few techniques for converting
decimal numbers to binaries. One of them is consecutive divisions. We
start by dividing the decimal number by 2. Then we iteratively divide
the result (the quotient) by 2 until the answer is 0. The equivalent
binary is formed by the remainders of the divisions. The last remainder
found is the most significant digit. Enter a number between 0 and 255 in
the following field and click convert to see an example. Try to convert
a decimal number to binary.
One of the first schemes to represent signed
numbers was called
oneâs complement
. It was called
oneâs complement because to negate a number, we complement
(logical not) each bit. For example, if 25 equals 00011001
2
in binary, then â25 is 11100110
2
.
An 8-bit oneâs complement number can vary from â127 to +127.
The most significant bit is a sign bit, which is 1 if and only if the
number is negative. The difficulty with this format is that there are
two zeros +0 is 00000000
2
,
and â0 is 11111111
2
.
Another problem is that oneâs complement numbers do not have basis
elements. These limitations led to the use of twoâs complement.
The
twoâs complement
 number
system is the most common approach used to define signed numbers. It is
called twoâs complement because to negate a number, we complement
each bit (like oneâs complement), then add 1. For example, if 25
equals 00011001
2
in binary, then â25 is 11100111
2
.
If a byte is used to represent a signed twoâs complement number,
then the value of the number is
              Â
                              Â
N
= -128
â˘
b
7
+ 64
â˘
b
6
+ 32
â˘
b
5
+ 16
â˘
b
4
+ 8
â˘
b
3
+ 4
â˘
b
2
+ 2
â˘
b
1
+ b
0
Observation:
One usually means twoâs
complement when one refers to signed integers.
There are 256 different signed 8-bit numbers. The
smallest signed 8-bit number is -128 and the largest is 127. For
example, 10000010
2
equals -128+2 or -126.
:
Convert the signed binary number
11011010
2
to signed decimal.
:
Are the signed and unsigned decimal
representations of the 8-bit hex number 0x95 the same or different?
For the signed 8-bit number system the basis
elements are
              Â
                              Â
{1,
2, 4, 8, 16, 32, 64, -128}
Observation:
The most significant bit in a
twoâs complement signed number will specify the sign.
Notice that the same binary pattern of 11111111
2
could represent either 255 or â1. It is very important for the
software developer to keep track of the number format. The computer
cannot determine whether the 8âbit number is signed or unsigned.
You, as the programmer, will determine whether the number is signed or
unsigned by the specific assembly instructions you select to operate on
the number. Some operations like addition, subtraction, and shift left
(multiply by 2) use the same hardware (instructions) for both unsigned
and signed operations. On the other hand, divide, and shift right
(divide by 2) require separate hardware (instruction) for unsigned and
signed operations.
Observation:
To take the negative of a
twoâs complement signed number we first complement (flip) all the
bits, then add 1.
A second way to convert negative numbers into
binary is to first convert them into unsigned binary, then do a
twoâs complement negate. For example, we earlier found that +100
is 01100100
2
.
The twoâs complement negate is a two-step process. First we do a
logic complement (flip all bits) to get 10011011
2
.
Then add one to the result to get 10011100
2
.
:
Give the representations of -54
in 8-bit binary and hexadecimal.
:
Why canât you represent the
number 150 using 8-bit signed binary?
When dealing with numbers on the computer, it will
be convenient to memorize some
Powers of 2
as shown in Table
1.3.4.
exponent
decimal
2
0
1
2
1
2
2
2
4
2
3
8
2
4
16
2
5
32
2
6
64
2
7
128
2
8
256
2
9
512
2
10
1024
about
a thousand
2
11
2048
2
12
4096
2
13
8192
2
14
16384
2
15
32768
2
16
65536
2
20
about
a
million
2
30
about
a
billion
2
40
about
a
trillion
Table 1.3.4. Some powers of two that will be
useful to memorize.
:
Use Table 1.3.4 to determine the
approximate value of 2
32
?
 A
halfword
or
double byte
contains 16 bits, where each bit b
15
,...,b
0
is binary and has the value 1
or 0, as shown in Figure 1.3.2.
Figure 1.3.2. 16-bit binary format.
If a halfword is used to represent an unsigned
number, then the value of the number is
              Â
              Â
N
= 32768
â˘
b
15
+ 16384
â˘
b
14
+ 8192
â˘
b
13
+ 4096
â˘
b
12
                              Â
              Â
+
2048
â˘
b
11
+ 1024
â˘
b
10
+ 512
â˘
b
9
+ 256
â˘
b
8
                              Â
              Â
+
128
â˘
b
7
+ 64
â˘
b
6
+ 32
â˘
b
5
+ 16
â˘
b
4
+ 8
â˘
b
3
+ 4
â˘
b
2
+ 2
â˘
b
1
+ b
0
There are 65536 different unsigned 16-bit numbers.
The smallest unsigned 16-bit number is 0 and the largest is 65535. For
example, 0010000110000100
2
or 0x2184 is 8192+256+128+4 or 8580.
:
Convert the 16-bit binary number
0010000001101010
2
to unsigned decimal.
:
Convert the 16-bit hex number 0x1234
to unsigned decimal.
For the unsigned 16-bit number system the basis
elements are
              Â
                              Â
{1,
2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384,
32768}
:
Convert the unsigned decimal number
1234 to 16-bit hexadecimal.
:
Convert the unsigned decimal number
10000 to 16-bit binary.
There are also 65536 different signed 16-bit
numbers. The smallest twoâs complement signed 16âbit number
is â32768 and the largest is 32767. For example, 1101000000000100
2
or
0xD004 is â32768+16384+4096+4 or â12284.
If a halfword is used to represent a signed
twoâs complement number, then the value of the number is
              Â
              Â
N
= -32768
â˘
b
15
+ 16384
â˘
b
14
+ 8192
â˘
b
13
+ 4096
â˘
b
12
                              Â
              Â
+
2048
â˘
b
11
+ 1024
â˘
b
10
+ 512
â˘
b
9
+ 256
â˘
b
8
                              Â
              Â
+
128
â˘
b
7
+ 64
â˘
b
6
+ 32
â˘
b
5
+ 16
â˘
b
4
+ 8
â˘
b
3
+ 4
â˘
b
2
+ 2
â˘
b
1
+ b
0
:
Convert the 16-bit hex number 0x1234
to signed decimal.
:
Convert the 16-bit hex number 0xABCD
to signed decimal.
For the signed 16-bit number system the basis
elements are
              Â
            Â
{1,
2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384,
-32768}
Common Error:
An error will occur if you use
16-bit operations on 8-bit numbers, or use 8-bit operations on 16-bit
numbers.
Maintenance Tip:
To improve the clarity of
your software, always specify the precision of your data when defining
or accessing the data.
:
Convert the signed decimal number 1234
to 16-bit hexadecimal.
:
Convert the signed decimal number
â10000 to 16-bit binary.
A
word
on the ARM Cortex M will have 32
bits. Consider an unsigned number with 32 bits, where each bit b
31
,...,b
0
is binary and has the value 1 or 0. If a 32-bit number is used to
represent an unsigned integer, then the value of the number is
                              Â
N
= 2
31
â˘
b
31
+ 2
30
â˘
b
30
+ ... + 2
â˘
b
1
+ b
0
= sum(
2
i
â˘
b
i
) for i=0 to
31
There are 2
32
different unsigned 32-bit
numbers. The smallest unsigned 32-bit number is 0 and the largest is 2
32
-1.
This
range is 0 to about 4 billion. For the unsigned 32-bit number system,
the basis elements are
              Â
               Â
{1, 2, 4, ... , 2
29
, 2
30
, 2
31
}
If a 32-bit binary number is used to represent a
signed twoâs complement number, then the value of the number is
              Â
              Â
N = -2
31
â˘
b
31
+ 2
30
â˘
b
30
+ ... +
2
â˘
b
1
+ b
0
= -2
31
â˘
b
31
+
sum(
2
i
â˘
b
i
) for i=0 to
30
There are also 2
32
different signed
32-bit numbers. The smallest signed 32-bit number is -2
31
and
the largest is 2
31
-1. This range is about -2 billion to about
+2 billion. For the signed 32-bit number system, the basis elements are
                              Â
{1, 2, 4, ... ,
2
29
,
2
30
, -2
31
}
Interactive Tool 1.4
The computer does not distinguish between
signed and unsigned numbers in memory. The interpretation is yours to
make. Enter an 8-bit binary number in the following field and press
"show" to see its value if interpreted as signed or unsigned integer.
For convenience, you can also enter hexadecimal input with '0x' prefix.
Video 1.3.3. Signed versus unsigned numbers
1.4. Introduction to Computers
Video 1.4.1. Computer Organization
A
computer
combines a processor, random access memory (RAM), read only
memory (ROM), and input/output (I/O) ports. Computers are not
intelligent. Rather, you are the true genius. Computers are electronic
idiots. They can store a lot of data, but they will only do exactly what
we tell them to do. Fortunately, however, they can execute our programs
quite quickly, and they donât get bored doing the same tasks over
and over again.
Software
 is an ordered sequence of very
specific instructions that are stored in memory, defining exactly what
and when certain tasks are to be performed. It is a set of instructions,
stored in memory, that are executed in a complicated but well-defined
manner. The
processor
 executes the software by retrieving
and interpreting these instructions one at a time. A
microprocessor
 is
a small processor, where small refers to size (i.e., it fits in your
hand) and not computational ability.
A
microcomputer
 is
a
small computer, where again small refers to size (i.e., you can carry
it) and not computational ability. For example, a desktop PC is a
microcomputer. Small in this context describes its size not its
computing power. Consequently, there can be great confusion over the
term microcomputer, because it can refer to a very wide range of devices
from a PIC12C508, which is an 8-pin chip with 512 words of ROM and 25
bytes RAM, to the most powerful I7-based personal computer.
A
port
 is
a physical connection between the computer and its outside world. Ports
allow information to enter and exit the system. Information enters via
the input ports and exits via the output ports. Other names used to
describe ports are I/O ports, I/O devices, interfaces, or sometimes
just devices. A
bus
is a collection of wires used to pass
information between modules.
A very small microcomputer, called a
microcontroller
,
contains all the components of a computer (processor, memory, I/O) on a
single chip. As shown in Figure 1.4.1, the Atmel ATtiny, the Texas
Instruments MSP430, and the Texas Instruments TM4C123 are examples of
microcontrollers. Because a microcomputer is a small computer, this term
can be confusing because it is used to describe a wide range of systems
from a 6-pin ATtiny4 running at 1 MHz with 512 bytes of program memory
to a personal computer with state-of-the-art 64-bit multi-core processor
running at multi-GHz speeds having terabytes of storage.
The computer can store information in
RAM
 by
writing to it, or it can retrieve previously stored data by reading from
it. RAMs are
volatile
; meaning if power is interrupted and
restored the information in the RAM is lost.
Figure 1.4.1. A microcontroller is a complete
computer on a single chip.
Information is programmed into
ROM
using
techniques more complicated than writing to RAM. From a programming
viewpoint, retrieving data from a ROM is identical to retrieving data
from RAM. ROMs are nonvolatile; meaning if power is interrupted and
restored the information in the ROM is retained.
Figure 1.4.2 shows a simplified block diagram of a
microcontroller based on the
ARM
ÂŽ
Cortex
â˘
-M processor. It
is a
Harvard architecture
 because it has separate data and
instruction buses. Instructions are fetched from flash ROM using the
ICode
bus
at the same time as Data are exchanged with memory and I/O via
the
System bus
interface.
Figure 1.4.2. Harvard architecture of an ARM
ÂŽ
Cortex-M-based microcontroller.
:
What are the differences between a
microcomputer, a microprocessor, and a microcontroller?Â
:
What are three differences between RAM
and ROM?
1.5. I/O Ports
The external devices attached to the
microcontroller provide functionality for the system. A
pin
is
one wire on the microcontroller used for input or output. There are 43
I/O pins on the TM4C123. A
port
is a collection of pins. An
input
pin
is hardware on the microcontroller that allows information about
the external world to be entered into the computer. The microcontroller
also has hardware called an
output pin
to send information out
to the external world. Most of the pins shown in Figure 5.1.1 are
input/output ports.
Video 1.5.1. I/O Ports and Interfacing
An
interface
 is defined as the
collection of the I/O port, external electronics, physical devices, and
the software, which combine to allow the computer to communicate with
the external world. An example of an input interface is a switch, where
the operator toggles the switch, and the software can recognize the
switch position. An example of an output interface is a light-emitting
diode (LED), where the software can turn the light on and off, and the
operator can see whether or not the light is shining. There is a wide
range of possible inputs and outputs, which can exist in either digital
or analog form. In general, we can classify I/O interfaces into four
categories
     Â
Parallel
 - binary data are available simultaneously on a
group of lines
     Â
Serial
 - binary data are available one bit at a time on a
single line
     Â
Analog
 - data are encoded as an electrical voltage, current,
or power
     Â
Time
 - data are encoded as a period, frequency, pulse width,
or phase shift
The general purpose input output (GPIO) port is
simply a collection of pins, and allows the software to read data from
input pins and write data to output pins. The direction register allows
the software to specify whether a pin is an input or output.
Figure 1.5.2. A GPIO port allows for input and
output.
Figure 1.5.3. The TM4C123GH6PM six ports and 43
pins.
We will begin by interacting with Port F, because
the LaunchPad has two switches and one LED already connected. The 5 pins
of Port F are called PF4, PF3, PF3, PF2, PF1, and PF0. Figure 1.5.4
shows there are switches connected to PF4 and PF0. There is one 3-color
LED connected to PF3-PF2-PF1.
Figure 1.5.4. Switch and LED interfaces on the
LaunchPad Evaluation Board. The zero ohm resistors can be removed so the
corresponding pin can be used without connection to the external
circuits.
An
I/O register
is a location in memory with
which software can interface with the I/O port. Initialization is
executed once at the beginning. First, we turn on the clock in
SYSCTL_RCGCGPIO_R
by setting appropriate bits. Second, we wait about 25, which is two bus
cycles. Third, we write 1 into the corresponding
DIR
bit for
each pin we wish to make output. Conversely we write a 0 into the
corresponding
DIR
bit for each pin we wish to make input. To
use the two switches on PF4 and PF0, we will also set bits 4 and 0 of
the
PUR
register to activate an internal pull-up resistor.
Lastly, we set the
DEN
bits to 1 to enable data pins. If we
wish to input from a Port F GPIO pin we simply read from
GPIO_PORTF_DATA_R
.
Reading from
GPIO_PORTF_DATA_R
obtains the current values for
both input and output pins. If we wish to output to a Port F GPIO pin we
write to
GPIO_PORTF_DATA_R
. Writing to
GPIO_PORTF_DATA_R
affects
output pins but does not affect input pins. Table 1.5.1 shows the
addresses of some of the I/O registers needed to access Port F. The
other ports have similar I/O registers.
Address
  7 Â
  6 Â
  5 Â
  4 Â
  3 Â
  2 Â
  1 Â
  0 Â
NameÂ
0x400FE608
 -
 -
GPIOF
GPIOE
GPIOD
GPIOC
GPIOB
GPIOA
SYSCTL_RCGCGPIO_R
0x400253FC
 -
 -
 -
DATA
DATA
DATA
DATA
DATA
GPIO_PORTF_DATA_R
0x40025400
 -
 -
 -
DIR
DIR
DIR
DIR
DIR
GPIO_PORTF_DIR_R
0x40025510
 -
 -
 -
PUR
PUR
PUR
PUR
PUR
GPIO_PORTF_PUR_R
0x4002551C
 -
 -
 -
DEN
DEN
DEN
DEN
DEN
GPIO_PORTF_DEN_R
Table 1.5.1. I/O registers needed for GPIO Port F.
:
How does the software input from Port
F?
:
How does the software output to Port
F?
1.6. Memory
Figure 1.6.1 shows
the memory map of the TM4C123. A 32-bit entry requires four sequential
locations. The I/O ports exist as memory-mapped locations. I/O ports are
not memory, but we will write to an I/O port address to output and read
from an I/O port address to input.
Figure 1.6.1. Memory map. Each address contains 8
bits or 1 byte.
Video 1.6.1. Memory Map Layout
When we store 16-bit data into memory it requires
two bytes. Since the memory systems on most computers are byte
addressable (a unique address for each byte), there are two possible
ways to store in memory the two bytes that constitute the 16-bit data.
Many main-frame computers, like the z/Architecture, implement the
big
endian
approach that stores the most significant byte at the lower
address. Most smaller computers (desktops, laptops, phones and
microcontrollers) implement the
little endian
approach that
stores the least significant byte at the lower address. The Cortex-M
microcontrollers use the little endian format. Many ARM processors are
biendian
,
because they can be configured to efficiently handle both big and little
endian data. Instruction fetches on the ARM are always little endian.
Figure 1.6.2 shows two ways to store the 16-bit number 1000 (0x03E8) at
locations 0x20000850 and 0x20000851. We also could use either the big or
little endian approach when storing 32-bit numbers into memory that is
byte (8-bit) addressable. Figure 1.6.3 shows the big and little endian
formats that could be used to store the 32-bit number 0x12345678 at
locations 0x20000850 through 0x20000853.
Figure 1.6.2.
Example of big and little endian formats of a 16-bit number (the Cortex
M used little endian).
Figure 1.6.3. Example of big and little endian
formats of a 32-bit number (the Cortex M used little endian).
In the previous two examples, we normally would not
pick out individual bytes (e.g., the 0x12), but rather capture the
entire multiple byte data as one nondivisable piece of information. On
the other hand, if each byte in a multiple byte data structure is
individually addressable, then both the big and little endian schemes
store the data in first to last sequence. For example, if we wish to
store the four ASCII characters âLM3Sâ, which is 0x4C4D3353
at locations 0x2000.0850 through 0x2000.0853, then the ASCII
âLâ=0x4C comes first in both big and little endian schemes,
as illustrated in Figure 1.6.4.
Figure 1.6.4. Character strings are stored in the
same for both big and little endian formats.
The terms âbig and little endianâ come
from Jonathan Swiftâs satire
Gulliverâs Travels
. In
Swiftâs book, a Big Endian refers to a person who cracks their egg
on the big end. The Lilliputians were Little Endians because they
insisted that the only proper way is to break an egg on the little end.
The Lilliputians considered the Big Endians as inferiors. The Big and
Little Endians fought a long and senseless war over the best way to
crack an egg.
Common Error:
An error will occur when data is stored in Big Endian by one computer
and read in Little Endian format on another.
A
pseudo-op
is an assembler directive to
affect the assembly process. We use the
AREA
pseudo-op to
specify what information goes in RAM and what goes in ROM. We will use a
template similar to Program 1.6.1 for most assembly programs in this
class. The
EQU
pseudo-ops create symbols containing the address
of some the I/O port registers. The
AREA DATA
pseudo-op means the
following code will be placed in volatile RAM. The
SPACE
pseudo-op
allocates 4 bytes (in RAM) for the variable named
Stuff
. The
AREA |.text|
pseudo-op means the following code will be placed in
nonvolatile ROM. The
THUMB
pseudo-op tells the assembler to
create Thumb code. The
EXPORT
pseudo-op allows the label
Start
to be accessed from another file. In particular,
Start
will
be the place the software starts on power up or on reset. The
B Loop
instruction creates an infinite loop, typical of embedded systems,
causing the code between
Loop
and
B Loop
to be
executed over and over.
GPIO_PORTF_DATA_RÂ EQU 0x400253FC
GPIO_PORTF_DIR_RÂ Â EQU 0x40025400
GPIO_PORTF_PUR_RÂ Â EQU 0x40025510
GPIO_PORTF_DEN_RÂ Â EQU 0x4002551C
SYSCTL_RCGCGPIO_RÂ EQU 0x400FE608
     AREA DATA, ALIGN=4
;Global variables defined here, will go in RAM
Stuff SPACE 4
     AREA |.text|, CODE, READONLY, ALIGN=2
     THUMB
     EXPORT Start
Start
;assembly code to be executed once and first goes here
Loop
;assembly code to be executed over and over goes here
     B Loop   Â
     END     ; end of
file
Program 1.6.1. Template for assembly language
programs.
:
What is the purpose of the 4 in the
Stuff
SPACE 4
pseudo-op?
:
What is the purpose of the
AREA
Data
pseudo-op?
:
What is the purpose of the
AREA
|.text|
pseudo-op?
1.7. Instruction Set Architecture
Video 1.7.1. Instruction set
architecture.
This section is a brief introduction to the
ARMÂŽ Cortexâ˘-M instruction set architecture. There are many
ARM
ÂŽ
processors, and this class focuses on Cortex-M microcontrollers, which
executes Thumb
ÂŽ
 instructions
extended
with Thumb-2Â technology. This class will not describe in detail all
the Thumb instructions. Rather, we focus on only a subset of the Thumb
ÂŽ
instructions. This subset will be functionally complete without regard
to minimizing code size or optimizing for execution speed. Furthermore,
we will show the simple forms of instructions, but in many cases there
are specific restrictions on which registers can be used and the sizes
of the constants. Bookmark the following links and refer to them as you
write assembly programs
Quick Reference Assembly Guide
(ARM)
Assembly
ReferenceÂ
(Yerraballi/Valvano)
Cortex-M3/M4F Instruction Set
(Texas
Instruments)
The ARM Cortex-M Technical Reference Manual
(ARM)
1.7.1. Registers
Registers are high-speed storage inside the
processor. The registers are depicted in Figure 1.6.1. R0 to R12
are general purpose registers and contain either data or addresses.
Register R13 (also called the stack pointer, SP) points to the top
element of the stack. Register R14 (also called the link register, LR)
is used to store the return location for functions. The LR is also used
in a special way during exceptions, such as interrupts. Interrupts are
covered in Chapter 6. Register R15 (also called the program counter, PC)
points to the next instruction to be fetched from memory. The processor
fetches an instruction using the PC and then increments the PC.
Figure 1.6.1. Registers on
the ARM
ÂŽ
Cortex-M processor.
:
Where in memory should you put the stack?
I.e., does the SP point to RAM or ROM?
:
Where in memory should you put the
program? I.e., does the PC point to RAM or ROM?
The ARM Architecture
Procedure Call Standard
,
AAPCS, part of the ARM
Application Binary Interface
 (ABI),
uses registers R0, R1, R2, and R3 to pass input parameters into a C
function. Also according to AAPCS we place the return parameter in
Register R0.
There are three
status registers named Application Program Status Register (APSR), the
Interrupt Program Status Register (IPSR), and the Execution Program
Status Register (EPSR) as shown in Figure 1.7.2. These registers can be
accessed individually or in combination as the
Program Status
Register
 (PSR). The N, Z, V, C, and Q bits give information
about the result of a previous ALU operation. In general, the
N bit
 is
set after an arithmetical or logical operation signifying whether or not
the result is negative. Similarly, the
Z bit
 is set if the
result is zero. The
C bit
 means carry and is set on an
unsigned overflow, and the
V bit
 signifies signed
overflow. The
Q bit
 indicates that
âsaturationâ has occurred â while you might want to
look it up, saturated arithmetic is beyond the scope of this class.
Â
Figure 1.7.2.
The program status register of the ARM
ÂŽ
Cortex-M processor.
The
T bit
 will always be 1, indicating
the
ARM
ÂŽ
Cortex
â˘
-M
processor
is executing Thumb
ÂŽ
instructions. The ISR_NUMBER indicates which interrupt if any the
processor is handling. Bit 0 of the special register
PRIMASK
 is
the interrupt mask bit. If this bit is 1, most interrupts and exceptions
are not allowed. If the bit is 0, then interrupts are allowed. The
nonmaskable interrupt (NMI) is not affected by these mask bits. The
BASEPRI
 register
defines the priority of the executing software. It prevents interrupts
with lower or equal priority but allows higher priority interrupts. For
example if
BASEPRI
equals 3, then requests with level 0, 1, and
2 can interrupt, while requests at levels 3 and higher will be
postponed. A lower number means a higher priority interrupt. The details
of interrupt processing will be presented in Chapter 6.
1.7.2. Syntax
Assembly language instructions have four fields
separated by spaces or tabs. The
label field
 is optional
and starts in the first column and is used to identify the position in
memory of the current instruction. You must choose a unique name for
each label. The
opcode field
 specifies the processor
command to execute. The
operand field
 specifies where to
find the data to execute the instruction. Thumb instructions have 0, 1,
2, 3, or 4 operands, separated by commas. The
comment field
 is
also optional and is ignored by the assembler, but it allows you to
describe the software making it easier to understand. You can add
optional spaces between operands in the operand field. However, a
semicolon must separate the operand and comment fields. Good programmers
add comments to explain the software.
Label    Â
OpcodeÂ
Operands             Â
Comment
FuncÂ
MOV
 Â
R0,
#100Â Â Â
; 100 means maximum
    Â
BX
  Â
LRÂ Â Â Â Â Â Â
Observation:
A good comment explains why an
operation is being performed, how it is used, how it can be changed, or
how it was debugged. A bad comment explains what the operation does. The
comments in the above two assembly lines are examples of bad comments.
The assembly
source code
 is a text
file (with Windows file extension
.s
) containing a list of
instructions. The
assembler
 translates assembly source code
into
object code
, which are the machine
instructions executed by the processor. All object code is
halfword-aligned. This means instructions can be 16 or 32 bits wide, and
the program counter bit 0 will always be 0. The
listing
 is
a text file containing a mixture of the object code generated by the
assembler together with our original source code.
Address         Â
Object code       LabelÂ
OpcodeÂ
Operand               Â
comment
0x000005E2
F04F0164Â Func MOVÂ Â R1,#0x64
    ; R1=100
0x000005E6
FB00F001Â Â Â Â Â Â MULÂ Â
R0,R0,R1 Â Â Â Â ; R0=100*input
0x000005EA
F100000AÂ Â Â Â Â Â ADDÂ Â
R0,R0,#0x0AÂ ; R0=100*input+10
0x000005EE
4770Â Â Â Â Â Â Â Â Â Â
BXÂ Â Â
LRÂ Â Â Â Â Â Â Â Â Â
;
return 100*input+10
When we
build
 a project all files are
assembled or compiled then linked together. The address values shown in
the listing are relative to the particular file being assembled. When
the entire project is built, the files are linked together, and the
linker
 decides
exactly where in memory everything will be. After building the project,
it can be downloaded, which programs the object code into flash ROM. You
are allowed to load and execute software out of RAM. But for an embedded
system, we typically place executable instructions into nonvolatile ROM.
The listing you see in the debugger will specify the absolute address
showing you exactly where in memory your variables and instructions
exist.
1.7.3. Reading from and writing to memory
The first action we present is bringing a constant
value into a register. With immediate addressing mode, the data
itself is contained in the instruction. Once the instruction is fetched
no additional memory access cycles are required to get the data. Notice
the number 100 (0x64) is embedded in the machine code of the
MOV
instruction
shown in Figure 1.6.3.Â
    Â
MOVÂ Â R0,#100Â Â Â Â Â
; R0=100, immediate addressing
Figure 1.7.3. An example of immediate addressing
mode, data is in the instruction.
The constant value allowed by
MOV
is
limited to 16-bit values. On the other hand, the
LDR
instruction
can be used to bring any 32-bit value into a register. Notice the number
0x12345678 is not embedded in the machine code of the instruction, but
rather stored in ROM a short distance away, as shown in Figure 1.7.4.
The Keil assembler automatically places the constant in ROM and
calculates the appropriate PC-relative offset. At the time of execution,
the PC is pointing to the next instruction.
    Â
LDR
R0,=0x12345678 Â Â Â Â ; R0=0x12345678, PC-relative
addressing
Â
Figure 1.7.4. An example of using the LDR
instruction to load any constant into a register.
Video 1.7.2. Assembly language access to RAM and ROM variables.
A fundamental issue in program development is the
differentiation between data and address. When we put the number 100
into Register R0, whether this is data or address depends on how the 100
is used. As presented in Program 1.6.1, we created a 32-bit global
variable called
Stuff
. To write an initial value of 100 into
this variable will take three instructions. In this example, R0 has data
and R1 had an address. First, the
MOV
instruction brings the
desired value into R0. Second, the
LDR
instruction sets R1 to
point to the global variable
Stuff
. Lastly, the
STR
instruction
writes the value into the variable.
    Â
MOVÂ Â R0,#100Â Â Â Â
     LDRÂ
R1,=Stuff   ; R1 points to the variable Stuff
     STRÂ
R0,[R1]Â Â Â Â Â ; Stuff=100
Figure 1.7.5. It takes three instructions to write
to a global variable.
:
How would you modify the above
assembly code to write 0x0E to Port F?
To read the value of a variable into a register
will take two instructions. After executing these two instructions, R3
will have a copy of the value from the global
Stuff
. The first
LDR
instruction sets R2 to point to the global variable
Stuff
.
The second
LDR
instruction will read the value from the
variable.Â
    Â
LDR R2,=Stuff   ; R2 points to the variable
Stuff
     LDRÂ
R3,[R2]Â Â Â Â Â ; R3=Stuff
Figure 1.7.6. It takes two instructions to read from
a global variable.
:
How would you modify the above
assembly code to read from Port F?
An
aligned
access
 is an operation where a word-aligned address is used
for a word, dual word, or multiple word access, or where a
halfword-aligned address is used for a halfword access. Byte accesses
are always aligned. The address of an aligned word access will have its
bottom two bits equal to zero. An
unaligned
 word access
means we are accessing a 32-bit object (4 bytes) but the address is not
evenly divisible by 4. The following instructions support 32-bit
memory access:
 Â
LDR
                      Â
Load
32-bit
word
 Â
STR
                      Â
Store
32-bit
word
The address of an
aligned halfword access will have its bottom bit equal to zero. An
unaligned halfword access means we are accessing a 16-bit object (2
bytes) but the address is not evenly divisible by 2. The following
instructions support 16-bit memory access:
 Â
LDRH
                   Â
Load
16-bit unsigned halfword
 Â
LDRSH
                 Â
Load
16-bit
signed halfword (sign extend bit 15 to bits 31-16)
 Â
STRH
                   Â
Store
16-bit halfword
Transfers of one
byte are allowed for the following instructions:
 Â
LDRB
                   Â
Load
8-bit unsigned byte
 Â
LDRSB
                 Â
Load
8-bit
signed byte (sign extend bit 7 to bits 31-8)
 Â
STRB
                   Â
Store
8-bit byte
When loading a 32-bit register with an 8- or 16-bit
value, it is important to use the proper load, depending on whether the
number being loaded is signed or unsigned. This determines what is
loaded into the most significant bits of the register to ensure that the
number keeps the same value when it is promoted to 32 bits. When loading
an 8-bit unsigned number, the top 24 bits of the register will become
zero. When loading an 8-bit signed number, the top 24 bits of the
register will match bit 7 of the memory data (signed extend). Note that
there is no such thing as a signed or unsigned store. For example, there
is no
STRSH
;
there is only
STRH
.
This is because 8, 16, or all 32 bits of the register are stored to an
8-, 16-, or 32-bit location, respectively. No promotion occurs. This
means that the value stored to memory can be different from the value
located in the register if there is overflow. When using
STRB
to store an 8-bit number, be sure that the number in the register is 8
bits or less.
Â
Figure 1.7.6. Assume these memory contents for
Checkpoints 1.7.5 through 1.7.9.
:
Assume R0 equal 0x20000850 at the time
LDR R1,[R0]
is
executed. To what value will R1 become?
:
Assume R0 equal 0x20000850 at the time
LDRH R2,[R0]
is
executed. To what value will R2 become?
:
Assume R0 equal 0x20000850 at the time
LDRSH R3,[R0]
is
executed. To what value will R3 become?
:
Assume R0 equal 0x20000850 at the time
LDRB R4,[R0]
is
executed. To what value will R4 become?
:
Assume R0 equal 0x20000850 at the time
LDRSB R5,[R0]
is
executed. To what value will R5 become?
1.7.4. Logical Operations
Boolean Logic
has two states: true (1) and
false (0). A
binary operation
produces a single result given two
inputs. The logical and (&) operation yields a true result if both
input parameters are true. The logical or (|) operation yields a true
result if either input parameter is true. The exclusive or (^) operation
yields a true result if exactly one input parameter is true. The logical
operators are summarized in the table below. The logical instructions on
the ARM Cortex-M processor take two inputs, one from a register and the
other either from a register or from a constant. These operations are
performed in a bit-wise fashion on two 32-bit input parameters yielding
one 32-bit output result. The result is stored into the destination
register. For example, the calculation r=m&n means each bit is
calculated separately, r31=m31&n31, r30=m30&n30,...,
r0=m0&n0.
In C, when we write logical operations as
r=m&n; r=m|n; r=m^n; the logical operation occurs in a bit-wise
fashion also described by the table below. However, in C, we define the
Boolean functions as r=m&&n; r=m||n; For Booleans, the operation
occurs in a word-wise fashion. For example, r=m&&n; means r will
become zero if either m is zero or n is zero. Conversely, r will become
1 (any nonzero) if both m is nonzero and n is nonzero.
Â
 A
    BÂ
 A&BÂ
 A|B
 A^BÂ
 A&(~B)Â
 Rn Â
 Op2Â
 AND
 ORR
 EOR
  BIC
 0
  0
 0
 0
 0
 0
 0
  1
 0
 1
 1
 0
 1
  0
 0
 1
 1
 1
 1
  1
 1
 1
 0
 0
Table 1.7.1. Logical operations performed by the
Cortex-M processor.
All instructions place the result into the
destination register
Rd
. If
Rd
is omitted, the result
is placed into
Rn
, which is the register holding the first
operand. If the optional S suffix is added, the N and Z condition code
bits are updated on the result of the operation. The second operand is
either a register or a 12-bit immediate value. We use the
AND
instruction
to mask or select bits. We use the
ORR
instruction to set bits.
We use the
EOR
instruction to toggle bits (change from 0 to 1
or 1 to 0) bits. We use the
BIC
instruction to clear bits.
   AND Rd, Rn, Rm ;Rd=Rn&Rm
   AND Rd, Rn, #n ;Rd=Rn&n
   ORR Rd, Rn, Rm ;Rd=Rn|Rm
   ORR Rd, Rn, #n ;Rd=Rn|n
   EOR Rd, Rn, Rm ;Rd=Rn^Rm
   EOR Rd, Rn, #n ;Rd=Rn^n
   BIC Rd, Rn, Rm ;Rd=Rn&(~Rm)
   BIC Rd, Rn, #n ;Rd=Rn&(~n)
Assume Port F bit 1 (PF1) is an output. The
following example sets the PF1 pin high. Notice that this code will
leave the other pins unchanged.
 Â
// C version
    Â
GPIO_PORTF_DATA_R
= GPIO_PORTF_DATA_R | 0x02;
  ; assembly version
Â
  LDR R0,=GPIO_PORTF_DATA_R ;pointer to data
register
    Â
LDRÂ
R1,[R0]Â Â Â Â Â Â Â Â Â Â Â Â Â Â
;previous values
     ORRÂ
R1,R1,#0x02Â Â Â Â Â Â Â Â Â Â
;set bit 1Â Â Â Â
     STRÂ
R0,[R1]Â Â Â Â Â ; change output
Again, assume Port F bit 1 (PF1) is an output. The
following example clears the PF1 pin low, without changing any other
pins.
 Â
// C version
    Â
GPIO_PORTF_DATA_R
= GPIO_PORTF_DATA_R & ~0x02;
  ; assembly version
Â
  LDR R0,=GPIO_PORTF_DATA_R ;pointer to data
register
    Â
LDRÂ
R1,[R0]Â Â Â Â Â Â Â Â Â Â Â Â Â Â
;previous values
     BICÂ
R1,R1,#0x02Â Â Â Â Â Â Â Â Â Â
;clear bit 1Â Â Â Â
     STRÂ
R0,[R1]Â Â Â Â Â ; change output
:
How would you change the above
program to set the PF3 pin?
:
How would you change the above
program to toggle the PF2 pin?
1.7.5. Shift Operations
Like programming in C, the assembly shift
instructions take two input parameters and yield one output result. In
C, the left shift operator is << and the right shift operator is
>>. E.g., to left shift the value in m by n bits and store the
result in r we execute:
r = m<<n
. Similarly, to right shift
the value in m by n bits and store result r, we execute:
r=m>>n
.
Â
Figure 1.7.7. Shift operations move bits to the
right or left.
The
logical shift right
(LSR) is similar
to an unsigned divide by 2
n
, where n is the number of bits
shifted. A zero is shifted into the most significant position, and the
carry flag will hold the last bit shifted out. The right shift
operations do not round. For example, a right shift by 3 bits is similar
to divide by 8. However, 15 right-shifted three times (15>>3) is
1, while 15/8 is much closer to 2. In general, the LSR discards bits
shifted out, and the UDIV truncates towards 0. Thus, when using UDIV to
divide unsigned numbers by a power of 2, UDIV and LSR yield identical
results.
The
arithmetic shift right
(ASR) is
similar to a signed divide by 2
n
. Notice that the sign bit is
preserved, and the carry flag will hold the last bit shifted out. This
right shift operation also does not round. Again, a right shift by 3
bits is similar to divide by 8. However, -9 right-shifted three times
(-9>>3) is -2, while implementing -9 divided by 8 using the SDIV
instruction yields -1. In general, the ASR discards bits shifted out,
and the SDIV truncates towards 0.
The
logical shift left
(LSL) operation
works for both unsigned and signed multiply by 2
n
. A zero is
shifted into the least significant position, and the carry bit will
contain the last bit that was shifted out.
All shift instructions place the result into the
destination register Rd. Rm is the register holding the value to be
shifted. The number of bits to shift is either in register Rs, or
specified as a constant n. If the optional S suffix is specified, the N
and Z condition code bits are updated on the result of the operation.
The C bit is the carry out after the shift. These shift instructions
will leave the V bit unchanged.
Observation:
Use logic shift for unsigned
numbers and arithmetic shifts for signed numbers.
   LSR Rd, Rm, Rs ; logical shift right
Rd=Rm>>Rs (unsigned)
   LSR Rd, Rm, #n ; logical shift right
Rd=Rm>>n (unsigned)
   ASR Rd, Rm, Rs ; arithmetic shift right
Rd=Rm>>Rs (signed)
   ASR Rd, Rm, #n ; arithmetic shift right
Rd=Rm>>n (signed)
   LSL Rd, Rm, Rs ; shift left Rd=Rm<<Rs
(signed, unsigned)
   LSL Rd, Rm, #n ; shift left Rd=Rm<<n
(signed, unsigned)
:
If R0=0xC0123456, what will be the
value in R0 after
LSR R0,R0,#4
is executed?
:
If R0=0xC0123456, what will be the
value in R0 after
ASR R0,R0,#4
is executed?
:
If R0=0xC0123456, what will be the
value in R0 after
LSL R0,R0,#4
is executed?
1.7.6. Arithmetic Operations
When software executes arithmetic instructions,
the operations are performed by digital hardware inside the processor.
Even though the design of such logic is complex, we will present a brief
introduction, in order to provide a little insight as to how the
computer performs arithmetic. It is important to remember that
arithmetic operations (addition, subtraction, multiplication, and
division) have constraints when performed with finite precision on a
processor. An overflow error occurs when the result of an arithmetic
operation cannot fit into the finite precision of the register into
which the result is to be stored. If the optional S suffix is specified,
the N C V and Z condition code bits are updated on the result of the
operation.
The immediate value #n can be any 12-bit constant.
When Rd is absent, the result is placed back in Rn.
   ADD Rd, Rn, Rm ;Rd = Rn + Rm
  ADD Rd, Rn, #n ;Rd = Rn + n
  SUB Rd, Rn, Rm ;Rd = Rn - Rm
  SUB Rd, Rn, #n ;Rd = Rn - n
  CMP Rn, Rm    ;Rn - Rm
  CMP Rn, #n    ;Rn - n
 Â
The compare instruction CMP does not save the result of the
subtraction but always sets the condition code. The compare
instructions are used to create conditional execution, such as
if-then, for loops, and while loops.
If the optional S suffix is present, addition and
subtraction set the condition code bits as shown in the following table.
The addition and subtraction instructions work for both signed and
unsigned values. As designers, we must know in advance whether we have
signed or unsigned numbers. The computer cannot tell from the binary
which type it is, so it sets both C and V. Our job as programmers is to
look at the C bit if the values are unsigned and look at the V bit if
the values are signed.
 BitÂ
Name
Meaning after addition or subtraction
 N
Negative
Result is negative
 Z
Zero
Result is zero
 V
Overflow
Signed overflow
 C
Carry
Unsigned overflow
Table 1.7.2. Condition code bits contain the
status of the previous arithmetic operation.
Observation:
The carry bit, C, is set after
an unsigned addition when the result is incorrect. The carry bit, C, is
cleared after an unsigned subtraction when the result is incorrect.
Observation:
The overflow bit, V, is set
after a signed addition or subtraction when the result is incorrect.
Multiply (
MUL
) uses 32-bit operands and
produces a 32-bit result. This multiply instructions only save the
bottom 32 bits of the result. They can be used for either signed or
unsigned numbers, but no overflow flags are generated. If the Rd
register is omitted, the Rn register is the destination. If the S suffix
is added to
MUL
, then the Z and N bits are set according to the
result. The division instructions do not set condition code flags and
will round towards zero if the division does not evenly divide into an
integer quotient
   MUL Rd, Rn, Rm ;Rd = Rn * Rm
  UDIV Rd, Rn, Rm ;Rd = Rn / Rm (unsigned)
  SDIV Rd, Rn, Rm ;Rd = Rn / Rm (signed)
 Â
:
If one adds an n-bit number to
another n-bit number, how total bits are in the sum?
:
If one multiplies an n-bit number to
an m-bit number, how total bits are in the product?
1.7.7. Branch Instructions
Normally the computer executes one instruction
after another in a linear fashion. In particular, the next instruction
to execute is found immediately following the current instruction. We
use branch instructions to deviate from this straight line path. The
following lists a few of the many branch instructions. The conditional
branching must be preceded by an instruction that sets the condition
code bits.
   B   label ;unconditional
branch to label
   BEQ label ;branch to label if Z=1
   BNE label ;branch to label if Z=0
   BMI label ;branch to label if N=1
   BPL label ;branch to label if N=0
   BCS label ;branch to label if C=1
   BCC label ;branch to label if C=0
   BVS label ;branch to label if V=1
   BVC label ;branch to label if V=0
 Â
1.8. Designing a NOT gate using a LaunchPad
In this section we will combine many of the
concepts presented in this chapter to design, build and test a NOT gate
using the TM4C123 microcontroller. Any two GPIO pins could have been
used, but we chose PE0 as input and PE1 as output. The system will make
the PE1 output the logic NOT of the input on PE0. We will test the NOT
gate by using a switch on PE0 to generate an input signal, and use an
LED on PE1 to visualize the output. Basically if we press the switch,
the input on PE0 will be high. The system will make the output on PE1
low, and the LED will be off. Conversely, if we release the switch, the
input on PE0 will be low. The system will make the output on PE1 high,
and the LED will be on. The details of this circuit will be presented in
Chapter 3.
Â
Figure 1.8.1. Circuit to test NOT gate.
To use GPIO pins we must first initialize the port.
Program 1.8.1 initializes PE0 as input and PE1 as output. First, we turn
on the clock and wait two bus cycles for the clock to stabilize. Then,
we set the
DIR
register to 0x02, making PE1 an output and PE0
an input. Lastly, we set the
DEN
register to 0x03 to enable
both PE1 and PE0. The code in Program 1.8.1 will be executed once at the
start of the software, and before we access the data register of Port E
  LDR R0,=SYSCTL_RCGCGPIO_R
  LDR R1,[R0]    ;previous
  ORR R1,R1,#0x10 ;bit 4 is clock for E
  STR R1,[R0]    ;turn on clock for
E
  NOP ;wait
  NOP ;wait
  LDR R0,=GPIO_PORTE_DIR_R
  MOV R1,#0x02 ;PE1 output, PE0 input
  STR R1,[R0]
  LDR R0,=GPIO_PORTE_DEN_R
  MOV R1,#0x03 ;enable PE1,PE0
  STR R1,[R0]
Program 1.8.1. Initialization of Port E, making PE1
an output and PE0 an input.
Effective testing starts with the simplest
component. We begin by connecting the LED to PE1 and writing test code
to see if the software can control the LED state. The assembly code in
Program 1.8.2 will toggle the output on PE1. R0 points to the data
register for Port E. R1 contains the value of Port E, which we
read-toggle-write. R2 contains a large number, and is used to create a
long delay, so we can see the LED flash with our eyes. The accesses to
R3 will slow down the wait loop. The
SUBS
instruction
decrements the R2 counter and sets the Z bit when the counter reaches 0.
The
BNE
instruction will branch if the Z bit is not set (R2 is
not zero). The
B loop
instruction is an unconditional branch so
the code is repeated over and over.
  LDRÂ
R0,=GPIO_PORTE_DATA_R
loop
  LDR R1,[R0]    ;read all of
PortE
  EOR R1,R1,#0x02 ;toggle bit 1
  STR R1,[R0]    ;output to
PortE
  LDR R2,=1000000
wait
  MOV R3,#1000 ;dummy operation
  MOV R3,#2000 ;dummy operation
  MOV R3,#3000 ;dummy operation
  MOV R3,#4000 ;dummy operation
  SUBS R2,R2,#1
  BNE  wait
  B   loop
Program 1.8.2. Toggle the PE1 output.
The assembly code in Program 1.8.3 will create a
NOT gate, using PE0 as input and PE1 as output. First, we read all of
Port E. We select just bit 0 using the AND instruction with mask #1.
Next, we toggle bit 0 using the EOR instruction to implement the NOT
operation. We use the LSL instruction to move the information in bit 0
into the bit 1 location. Lastly we output to Port E, making the pin PE1
the logical NOT of the input from PE0.
  LDRÂ
R0,=GPIO_PORTE_DATA_R
loop
  LDR R1,[R0] ;Read Port E
  AND R1,R1,#1 ;mask, select PE0
  EOR R1,R1,#1 ;NOT
  LSL R1,R1,#1 ;move to bit 1
  STR R1,[R0] ;write Port E, sets PE1
  B   loop
Program 1.8.3. A NOT gate with PE0 as input and PE1
as output.
Finally, we connect the switch to PE0 and single
step through the code. We step through the loop with the switch not
pressed to see the LED come on, and with the switch pressed to see the
LED go off. If we connect a logic analyzer to PE1 and PE0, we test
dynamic behavior of the system. Running in simulation with a bus clock
of 16 MHz, we see it takes 3.4us for a change in input to propagate to
the output. This delay, of course, will depend on which of six
instructions in the loop are being executed when the input is changed.
The worst case would be to change during the AND instruction because it
would have to execute 10 instructions until the output changed:
AND-EOR-LSL-STR-B-LDR-AND-EOR-LSL-STR.
Â
Figure 1.8.2. Simulated logic analyzer signals
measuring propagation delay of the NOT gate.
Reprinted with approval from
Introduction
to Embedded Systems, 2022, ISBN: 978-1537105727
Embedded
Systems - Shape the World
by
Jonathan Valvano and Ramesh Yerraballi
is
licensed under a
Creative
Commons
Attribution-NonCommercial-NoDerivatives 4.0 International License
.
Based on a work at
http://users.ece.utexas.edu/~valvano/arm/outline1.htm
. |
| Markdown | Chapter 1: Introduction to Embedded Systems
Jonathan Valvano and Ramesh Yerraballi
This chapter covers the basic foundation concepts needed to build upon in this course. Specifically we will look at embedded systems, number representation, digital logic, embedded system components, and computer architecture: the Central Processing Unit (Arithmetic Logic Unit, Control Unit and Registers), the memory and the Instruction Set Architecture (ISA).
**Table of Contents:**
- [1\.1. Embedded Systems](https://users.ece.utexas.edu/~valvano/Volume1/IntroToEmbSys/Ch1_Introduction.html#1_1)
- [1\.2. Binary Information Implemented with MOS transistors](https://users.ece.utexas.edu/~valvano/Volume1/IntroToEmbSys/Ch1_Introduction.html#1_2)
- [1\.3. Numbers](https://users.ece.utexas.edu/~valvano/Volume1/IntroToEmbSys/Ch1_Introduction.html#1_3)
- [1\.4. Introduction to Computers](https://users.ece.utexas.edu/~valvano/Volume1/IntroToEmbSys/Ch1_Introduction.html#1_4)
- [1\.5. I/O Ports](https://users.ece.utexas.edu/~valvano/Volume1/IntroToEmbSys/Ch1_Introduction.html#1_5)
- [1\.6. Memory](https://users.ece.utexas.edu/~valvano/Volume1/IntroToEmbSys/Ch1_Introduction.html#1_6)
- [1\.7. Instruction Set Architecture](https://users.ece.utexas.edu/~valvano/Volume1/IntroToEmbSys/Ch1_Introduction.html#1_7)
- [1\.8. Designing a NOT gate using a LaunchPad](https://users.ece.utexas.edu/~valvano/Volume1/IntroToEmbSys/Ch1_Introduction.html#1_8)
[Video 1.0. Introduction, Examples of Embedded Systems](http://youtu.be/ZoHjGRtl39s)
**Reference material relative to this chapter:**
- [Digital logic](https://users.ece.utexas.edu/~valvano/Volume1/IntroToEmbSys/DigitalLogic.html)
- [Assembly reference](https://users.ece.utexas.edu/~valvano/Volume1/IntroToEmbSys/AssemblyReference.htm)
- [Embedded Software in C for an ARM Cortex M](http://users.ece.utexas.edu/~valvano/embed/toc1.htm)
- [TM4C123 LaunchPad Users Manual](http://users.ece.utexas.edu/~valvano/Volume1/TM4C123_LaunchPadUsersManual.pdf)
## 1\.1. Embedded Systems
To better understand the expression embedded microcomputer system, consider each word separately. In this context, the word âembeddedâ means hidden inside so one canât see it. The term âmicroâ means small, and a âcomputerâ contains a processor, memory, and a means to exchange data with the external world. The word âsystemâ means multiple components interfaced together for a common purpose. Systems have structure, behavior, and interconnectivity operating in a framework bound by rules and regulations. Another name for embedded systems is **Cyber-Physical Systems**, introduced in 2006 by Helen Gill of the National Science Foundation, because these systems combine the intelligence of a computer with the physical objects of our world. As shown in Figure 1.1.1, the term embedded microcomputer system refers to a device that contains one or more microcomputers inside. **Microcontrollers**, which are complete computers incorporating the processor, RAM, ROM and I/O ports into a single package, are often employed in an embedded system because of their low cost, small size, and low power requirements.

Figure 1.1.1. An embedded system includes a microcomputer interfaced to external physical devices.
An **embedded system** includes a microcomputer with mechanical, chemical, and electrical devices attached to it, programmed for a specific dedicated purpose, and packaged up as a complete system. Any electrical, mechanical, or chemical system that involves inputs, decisions, calculations, analyses, and outputs is a candidate for implementation as an embedded system. Electrical, mechanical, and chemical sensors collect information. Electronic interfaces convert the sensor signals into a form acceptable for the microcomputer. For example, a tachometer is a sensor that measures the revolutions per second of a rotating shaft. Microcomputer software performs the necessary decisions, calculations, and analyses. Additional interface electronics convert the microcomputer outputs into the necessary form. Actuators can be used to create mechanical or chemical outputs. For example, an electrical motor converts electrical power into mechanical power.
If the embedded system is connected to the internet, it is classified as an **Internet of Things** (IoT).
[Video 1.1.1. Components of an embedded system](http://youtu.be/5OJrQDgUmPM)

Figure 1.1.2. Embedded systems have computers hidden inside.
**Checkpoint 1.1.1 :** What is an embedded system?
## 1\.2. Binary Information Implemented with MOS transistors
Information is stored on the computer in binary form. A binary bit can exist in one of two possible states. In positive logic, the higher voltage is called the â1â, true, asserted, or high state. The lower voltage is called the â0â, false, not asserted, or low state. Figure 1.2.1 shows the output of a typical complementary metal oxide semiconductor (CMOS) circuit. The left side shows the condition with a true bit at the output, and the right side shows a false at the output. The output of each digital circuit consists of a p-type MOS transistor âon top ofâ an n-type MOS transistor. In digital circuits, each transistor is either on or off. If the transistor is on, it is equivalent to a short circuit between its two output pins. Conversely, if the transistor is off, it is equivalent to an open circuit between its outputs pins.

Figure 1.2.1. A binary bit at the output is true if a voltage is present and false if the voltage is 0.
**Checkpoint 1.2.1 :** What would have if both transistors were on in Figure 1.2.1?
**Checkpoint 1.2.2 :** What would have if both transistors were off in Figure 1.2.1?
Every family of digital logic is different, but on the TM4C microcontrollers from TI powered with 3.3 V supply, a voltage between 2.145 and 5 V is considered high. In general we define VIH as smallest input voltage considered high. A voltage between 0 and 1.155 V is considered low, as drawn in Figure 1.2.2. In general we define VIL as largest input voltage considered high. Separating the two regions by 0.99 V allows digital logic to operate reliably at very high speeds. The design of transistor-level digital circuits is beyond the scope of this book. However, it is important to know that digital data exist as binary bits and encoded as high and low voltages.

Figure 1.2.2. Mapping between analog voltage and the corresponding digital meaning on the TM4C.
If the information we wish to store exists in more than two states, we use multiple bits. A collection of 2 bits has 4 possible states (00, 01, 10, and 11). A collection of 3 bits has 8 possible states (000, 001, 010, 011, 100, 101, 110, and 111). In general, a collection of n bits has 2n states. For example, a byte contains eight bits and is built by grouping eight binary bits into one object, as shown in Figure 1.2.3. Another name for a collection of eight bits is octet (octo is Latin and Greek meaning 8.) Information can take many forms, e.g., numbers, logical states, text, instructions, sounds, or images. What the bits mean depends on how the information is organized and more importantly how it is used. This figure shows one byte in the state representing the binary number 01100111, which could mean 103. As a character, this same collection of bits represents the letter âgâ. Again, the output voltage 3.3V means true or 1, and the output voltage of 0V means false or 0.

Figure 1.2.3. A byte is comprised of 8 bits, in this case representing the binary number 01100111.
**Checkpoint 1.2.3 :** Why is there a gap between VIL and VIH?
**Checkpoint 1.2.4 :** The TM4C123 is powered at 3.3V. Can you think of a reason to reduce the supply voltage to 1.65V?
## 1\.3. Numbers
A great deal of confusion exists over the abbreviations we use for large numbers. In 1998 the International Electrotechnical Commission (IEC) defined a new set of abbreviations for the powers of 2, as shown in Table 1.3.1. These new terms are endorsed by the Institute of Electrical and Electronics Engineers (IEEE) and International Committee for Weights and Measures (CIPM) in situations where the use of a binary prefix is appropriate. The confusion arises over the fact that the mainstream computer industry, such as Microsoft, Apple, and Dell, continues to use the old terminology. According to the companies that market to consumers, a 1 GHz is 1,000,000,000 Hz but 1 Gbyte of memory is 1,073,741,824 bytes. The correct terminology is to use the SI-decimal abbreviations to represent powers of 10, and the IEC-binary abbreviations to represent powers of 2. The scientific meaning of 2 kilovolts is 2000 volts, but 2 kibibytes is the proper way to specify 2048 bytes. The term **kibibyte** is a contraction of kilo binary byte and is a unit of information or computer storage, abbreviated KiB.
1 KiB = 210 bytes = 1024 bytes
1 MiB = 220 bytes = 1,048,576 bytes
1 GiB = 230 bytes = 1,073,741,824 bytes
These abbreviations can also be used to specify the number of binary bits. The term **kibibit** is a contraction of kilo binary bit, and is a unit of information or computer storage, abbreviated Kibit.
A **mebibyte** (1 MiB is 1,048,576 bytes) is approximately equal to a megabyte (1 MB is 1,000,000 bytes), but mistaking the two has nonetheless led to confusion and even legal disputes. In the engineering community, it is appropriate to use terms that have a clear and unambiguous meaning.
| | | | | | | |
|---|---|---|---|---|---|---|
| *Value* | *SI Decimal* | *SI Decimal* | | *Value* | *IEC Binary* | *IEC Binary* |
| 10001 | k | kilo- | | 10241 | Ki | kibi- |
| 10002 | M | mega- | | 10242 | Mi | mebi- |
| 10003 | G | giga- | | 10243 | Gi | gibi- |
| 10004 | T | tera- | | 10244 | Ti | tebi- |
| 10005 | P | peta- | | 10245 | Pi | pebi- |
| 10006 | E | exa- | | 10246 | Ei | exbi- |
| 10007 | Z | zetta- | | 10247 | Zi | zebi- |
| 10008 | Y | yotta- | | 10248 | Yi | yobi- |
Table 1.3.1. Common abbreviations for large numbers.
To solve problems using a computer we need to understand numbers and what they mean. Each digit in a **decimal** number has a place and a value. The **place** is a power of 10 and the **value** is selected from the set {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}. A decimal number is simply a combination of its digits multiplied by powers of 10. For example
1984 = 1â˘103 + 9â˘102 + 8â˘101 + 4â˘100
Fractional values can be represented by using the negative powers of 10. For example,
273\.15 = 2â˘102 + 7â˘101 + 3â˘100 + 1â˘10\-1 + 5â˘10\-2
In a similar manner, each digit in a **binary** number has a place and a value. In binary numbers, the place is a power of 2, and the value is selected from the set {0, 1}. A binary number is simply a combination of its digits multiplied by powers of 2. To eliminate confusion between decimal numbers and binary numbers, we will put a subscript 2 after the number to mean binary. Because of the way the microcontroller operates, most of the binary numbers in this class will have 8, 16, or 32 bits. An 8-bit number is called a **byte**, and a 16-bit number is called a **halfword**. For example, the 8-bit binary number for 106 is
0 1 1 0 1 0 1 0 2 = 0â˘27 + 1â˘26 + 1â˘25 + 0â˘24 + 1â˘23 + 0â˘22 + 1â˘21 + 0â˘20 = 64 \+ 32 \+ 8 \+ 2 \= 106
**Checkpoint 1.3.1 :** What is the numerical value of the 8-bit binary number 111111112?
[Video 1.3.1. Binary representation](http://youtu.be/Rd2BEVNZdDo)
Interactive Tool 1.1
You have already learned how to convert from a binary number to its decimal representation. All you need to do is to calculate its value by multiplying each coefficient by its placeholder values and summing all of them together. If you want to practice, first think of an 8-digit binary number, and next type into the box from 1 to 8 binary digits. Try to calculate the decimal representation in your head. Then click "convert" to check your result.
Binary is the natural language of computers but a big nuisance for us humans. To simplify working with binary numbers, humans use a related number system called **hexadecimal**, which uses base 16. Just like decimal and binary, each hexadecimal digit has a place and a value. In this case, the place is a power of 16 and the value is selected from the set {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F}. As you can see, hexadecimal numbers have more possibilities for their digits than are available in the decimal format; so, we add the letters A through F, as shown in Table 1.3.2. Hexadecimal representation is a convenient mechanism for us humans to define binary information, because it is extremely simple for humans to convert back and forth between binary and hexadecimal.
[Video 1.3.2. Hexadecimal representation](http://youtu.be/kPnPCaDgz8A)
| | | |
|---|---|---|
| Hex Digit | Decimal Value | Binary Value |
| 0 | 0 | 0000 |
| 1 | 1 | 0001 |
| 2 | 2 | 0010 |
| 3 | 3 | 0011 |
| 4 | 4 | 0100 |
| 5 | 5 | 0101 |
| 6 | 6 | 0110 |
| 7 | 7 | 0111 |
| 8 | 8 | 1000 |
| 9 | 9 | 1001 |
| A or a | 10 | 1010 |
| B or b | 11 | 1011 |
| C or c | 12 | 1100 |
| D or d | 13 | 1101 |
| E or e | 14 | 1110 |
| F or f | 15 | 1111 |
Table 1.3.2. Definition of hexadecimal representation.
For example, the hexadecimal number for the 16-bit binary 0001 0010 1010 1101 is
0x12AD = 1â˘163 + 2â˘162 + 10â˘161 + 13â˘160 = 4096+512+160+13 = 4781
Interactive Tool 1.2
You have already learned how to convert from a hexadecimal number to its decimal representation. All you need to do is to calculate its value by multiplying each coefficient by its placeholder values and summing all of them together. If you want to practice, Choose an 4-digit hexadecimal number number. Try to calculate the decimal representation. Then type the number in the following field and click "convert" to check your result.
**Checkpoint 1.3.2 :** What is the numerical value of the 8-bit hexadecimal number 0xFF?
**Checkpoint 1.3.3 :** Convert the binary number 010001012 to hexadecimal.
**Checkpoint 1.3.4 :** Convert the binary number 1100101010112 to hexadecimal.
**Checkpoint 1.3.5 :** Convert the hex number 0x40 to binary.
**Checkpoint 1.3.6 :** Convert the hex number 0x63F to binary.
**Checkpoint 1.3.7 :** How many binary bits does it take to represent 0x123456?
**Precision** is the number of distinct or different values. We express precision in alternatives, decimal digits, bytes, or binary bits. **Alternatives** are defined as the total number of possibilities. For example, an 8-bit number format can represent 256 different numbers. An 8-bit **digital to analog converter** (DAC) can generate 256 different analog outputs. An 8-bit **analog to digital converter** (ADC) can measure 256 different analog inputs. Table 1.3.3 illustrates the relationship between precision in binary bits and precision in alternatives. The operation \[\[**x**\]\] is defined as the greatest integer of **x**. E.g., \[\[2.1\]\] \[\[2.9\]\] and \[\[3.0\]\] are all equal to 3. The **Bytes** column in Table 2.1 specifies how many bytes of memory it would take to store a number with that precision assuming the data were not packed or compressed in any way.
| | | |
|---|---|---|
| **Binary bits** | **Bytes** | **Alternatives** |
| 8 | 1 | 256 |
| 10 | 2 | 1024 |
| 12 | 2 | 4096 |
| 16 | 2 | 65536 |
| 20 | 3 | 1,048,576 |
| 24 | 3 | 16,777,216 |
| 30 | 4 | 1,073,741,824 |
| 32 | 4 | 4,294,967,296 |
| n | \[\[n/8\]\] | 2n |
Table 1.3.3. Relationship between bits, bytes and alternatives as units of precision.
**Checkpoint 1.3.8 :** How many bytes of memory would it take to store a 50-bit number?
A **byte** contains 8 bits as shown in Figure 1.3.1, where each bit b7,...,b0 is binary and has the value 1 or 0. We specify b7 as the **most significant bit** or MSB, and b0 as the least significant bit or LSB.

Figure 1.3.1. 8-bit binary format.
If a byte is used to represent an unsigned number, then the value of the number is
N = 128â˘b7 + 64â˘b6 + 32â˘b5 + 16â˘b4 + 8â˘b3 + 4â˘b2 + 2â˘b1 + b0
Notice that the significance of bit *n* is 2n. There are 256 different unsigned 8-bit numbers. The smallest unsigned 8-bit number is 0 and the largest is 255. For example, 000010102 is 8+2 or 10. The least significant bit can tell us if the number is even or odd.
**Checkpoint 1.3.9 :** Convert the binary number 011010012 to unsigned decimal.
**Checkpoint 1.3.10 :** Convert the hex number 0x54 to unsigned decimal.
The **basis** of a number system is a subset from which linear combinations of the basis elements can be used to construct the entire set. The basis represents the âplacesâ in a âplace-valueâ system. For positive integers, the basis is the infinite set {1, 10, 100, âŚ}, and the âvaluesâ can range from 0 to 9. Each positive integer has a unique set of values such that the dot-product of the value vector times the basis vector yields that number. For example, 2345 is (âŚ, 2,3,4,5)¡(âŚ, 1000,100,10,1), which is 2\*1000+3\*100+4\*10+5. For the unsigned 8-bit number system, the basis elements are
{1, 2, 4, 8, 16, 32, 64, 128}
The values of a binary number system can only be 0 or 1. Even so, each 8-bit unsigned integer has a unique set of values such that the dot-product of the values times the basis yields that number. For example, 69 is (0,1,0,0,0,1,0,1)¡(128,64,32,16,8,4,2,1), which equals 0\*128+1\*64+0\*32+0\*16+0\*8+1\*4+0\*2+1\*1. Conveniently, there is no other set of 0âs and 1âs, such that set of values multiplied by the basis is 69. In other words, each 8-bit unsigned binary representation of the values 0 to 255 is unique.
One way for us to convert a decimal number into binary is to use the basis elements. The overall approach is to start with the largest basis element and work towards the smallest. More precisely, we start with the most significant bit and work towards the least significant bit. One by one, we ask ourselves whether or not we need that basis element to create our number. If we do, then we set the corresponding bit in our binary result and subtract the basis element from our number. If we do not need it, then we clear the corresponding bit in our binary result. We will work through the algorithm with the example of converting 100 to 8-bit binary, see Table 2.4. We start with the largest basis element (in this case 128) and ask whether or not we need to include it to make 100? Since our number is less than 128, we do not need it, so bit 7 is zero. We go the next largest basis element, 64 and ask, âdo we need it?â We do need 64 to generate our 100, so bit 6 is one and we subtract 100 minus 64 to get 36. Next, we go the next basis element, 32 and ask, âdo we need it?â Again, we do need 32 to generate our 36, so bit 5 is one and we subtract 36 minus 32 to get 4. Continuing along, we do not need basis elements 16 or 8, but we do need basis element 4. Once we subtract the 4, our working result is zero, so basis elements 2 and 1 are not needed. Putting it together, we get 011001002 (which means 64+32+4).
**Checkpoint 1.3.11 :** In this conversion algorithm, how can we tell if a basis element is needed?
**Observation:** If the least significant binary bit is zero, then the number is even.
**Observation:** If the right-most n bits (least sign.) are zero, then the number is divisible by 2n.
**Observation:** Consider an 8-bit unsigned number system. If bit 7 is low, then the number is between 0 and 127, and if bit 7 is high then the number is between 128 and 255.
**Checkpoint 1.3.12 :** Give the representations of the decimal 45 in 8-bit binary and hexadecimal.
**Checkpoint 1.3.13 :** Give the representations of the decimal 200 in 8-bit binary and hexadecimal.
Interactive Tool 1.3
There are a few techniques for converting decimal numbers to binaries. One of them is consecutive divisions. We start by dividing the decimal number by 2. Then we iteratively divide the result (the quotient) by 2 until the answer is 0. The equivalent binary is formed by the remainders of the divisions. The last remainder found is the most significant digit. Enter a number between 0 and 255 in the following field and click convert to see an example. Try to convert a decimal number to binary.
##
One of the first schemes to represent signed numbers was called **oneâs complement**. It was called oneâs complement because to negate a number, we complement (logical not) each bit. For example, if 25 equals 000110012 in binary, then â25 is 111001102. An 8-bit oneâs complement number can vary from â127 to +127. The most significant bit is a sign bit, which is 1 if and only if the number is negative. The difficulty with this format is that there are two zeros +0 is 000000002, and â0 is 111111112. Another problem is that oneâs complement numbers do not have basis elements. These limitations led to the use of twoâs complement.
The **twoâs complement** number system is the most common approach used to define signed numbers. It is called twoâs complement because to negate a number, we complement each bit (like oneâs complement), then add 1. For example, if 25 equals 000110012 in binary, then â25 is 111001112. If a byte is used to represent a signed twoâs complement number, then the value of the number is
N = -128â˘b7 + 64â˘b6 + 32â˘b5 + 16â˘b4 + 8â˘b3 + 4â˘b2 + 2â˘b1 + b0
**Observation:** One usually means twoâs complement when one refers to signed integers.
There are 256 different signed 8-bit numbers. The smallest signed 8-bit number is -128 and the largest is 127. For example, 100000102 equals -128+2 or -126.
**Checkpoint 1.3.14 :** Convert the signed binary number 110110102 to signed decimal.
**Checkpoint 1.3.15 :** Are the signed and unsigned decimal representations of the 8-bit hex number 0x95 the same or different?
For the signed 8-bit number system the basis elements are
{1, 2, 4, 8, 16, 32, 64, -128}
**Observation:** The most significant bit in a twoâs complement signed number will specify the sign.
Notice that the same binary pattern of 111111112 could represent either 255 or â1. It is very important for the software developer to keep track of the number format. The computer cannot determine whether the 8âbit number is signed or unsigned. You, as the programmer, will determine whether the number is signed or unsigned by the specific assembly instructions you select to operate on the number. Some operations like addition, subtraction, and shift left (multiply by 2) use the same hardware (instructions) for both unsigned and signed operations. On the other hand, divide, and shift right (divide by 2) require separate hardware (instruction) for unsigned and signed operations.
**Observation:** To take the negative of a twoâs complement signed number we first complement (flip) all the bits, then add 1.
A second way to convert negative numbers into binary is to first convert them into unsigned binary, then do a twoâs complement negate. For example, we earlier found that +100 is 011001002. The twoâs complement negate is a two-step process. First we do a logic complement (flip all bits) to get 100110112. Then add one to the result to get 100111002.
**Checkpoint 1.3.16 :** Give the representations of -54 in 8-bit binary and hexadecimal.
**Checkpoint 1.3.17 :** Why canât you represent the number 150 using 8-bit signed binary?
When dealing with numbers on the computer, it will be convenient to memorize some **Powers of 2** as shown in Table 1.3.4.
| | |
|---|---|
| exponent | decimal |
| 20 | 1 |
| 21 | 2 |
| 22 | 4 |
| 23 | 8 |
| 24 | 16 |
| 25 | 32 |
| 26 | 64 |
| 27 | 128 |
| 28 | 256 |
| 29 | 512 |
| 210 | 1024 about a thousand |
| 211 | 2048 |
| 212 | 4096 |
| 213 | 8192 |
| 214 | 16384 |
| 215 | 32768 |
| 216 | 65536 |
| 220 | about a million |
| 230 | about a billion |
| 240 | about a trillion |
Table 1.3.4. Some powers of two that will be useful to memorize.
**Checkpoint 1.3.18 :** Use Table 1.3.4 to determine the approximate value of 232?
A **halfword** or **double byte**contains 16 bits, where each bit b15,...,b0 is binary and has the value 1 or 0, as shown in Figure 1.3.2.

Figure 1.3.2. 16-bit binary format.
If a halfword is used to represent an unsigned number, then the value of the number is
N = 32768â˘b15 + 16384â˘b14 + 8192â˘b13 + 4096â˘b12
\+ 2048â˘b11 + 1024â˘b10 + 512â˘b9 + 256â˘b8
\+ 128â˘b7 + 64â˘b6 + 32â˘b5 + 16â˘b4 + 8â˘b3 + 4â˘b2 + 2â˘b1 + b0
There are 65536 different unsigned 16-bit numbers. The smallest unsigned 16-bit number is 0 and the largest is 65535. For example, 00100001100001002 or 0x2184 is 8192+256+128+4 or 8580.
**Checkpoint 1.3.19 :** Convert the 16-bit binary number 00100000011010102 to unsigned decimal.
**Checkpoint 1.3.20 :** Convert the 16-bit hex number 0x1234 to unsigned decimal.
For the unsigned 16-bit number system the basis elements are
{1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768}
**Checkpoint 1.3.21 :** Convert the unsigned decimal number 1234 to 16-bit hexadecimal.
**Checkpoint 1.3.22 :** Convert the unsigned decimal number 10000 to 16-bit binary.
There are also 65536 different signed 16-bit numbers. The smallest twoâs complement signed 16âbit number is â32768 and the largest is 32767. For example, 11010000000001002 or 0xD004 is â32768+16384+4096+4 or â12284.
If a halfword is used to represent a signed twoâs complement number, then the value of the number is
N = -32768â˘b15 + 16384â˘b14 + 8192â˘b13 + 4096â˘b12
\+ 2048â˘b11 + 1024â˘b10 + 512â˘b9 + 256â˘b8
\+ 128â˘b7 + 64â˘b6 + 32â˘b5 + 16â˘b4 + 8â˘b3 + 4â˘b2 + 2â˘b1 + b0
**Checkpoint 1.3.23 :** Convert the 16-bit hex number 0x1234 to signed decimal.
**Checkpoint 1.3.24 :** Convert the 16-bit hex number 0xABCD to signed decimal.
For the signed 16-bit number system the basis elements are
{1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, -32768}
**Common Error:** An error will occur if you use 16-bit operations on 8-bit numbers, or use 8-bit operations on 16-bit numbers.
**Maintenance Tip:** To improve the clarity of your software, always specify the precision of your data when defining or accessing the data.
**Checkpoint 1.3.25 :** Convert the signed decimal number 1234 to 16-bit hexadecimal.
**Checkpoint 1.3.26 :** Convert the signed decimal number â10000 to 16-bit binary.
A **word** on the ARM Cortex M will have 32 bits. Consider an unsigned number with 32 bits, where each bit b31,...,b0 is binary and has the value 1 or 0. If a 32-bit number is used to represent an unsigned integer, then the value of the number is
N = 231 ⢠b31 + 230 ⢠b30 + ... + 2â˘b1 + b0 = sum(2i ⢠bi) for i=0 to 31
There are 232 different unsigned 32-bit numbers. The smallest unsigned 32-bit number is 0 and the largest is 232\-1. This range is 0 to about 4 billion. For the unsigned 32-bit number system, the basis elements are
{1, 2, 4, ... , 229, 230, 231}
If a 32-bit binary number is used to represent a signed twoâs complement number, then the value of the number is
N = -231 ⢠b31 + 230 ⢠b30 + ... + 2â˘b1 + b0 = -231 ⢠b31 + sum(2i ⢠bi) for i=0 to30
There are also 232 different signed 32-bit numbers. The smallest signed 32-bit number is -231 and the largest is 231\-1. This range is about -2 billion to about +2 billion. For the signed 32-bit number system, the basis elements are
{1, 2, 4, ... , 229, 230, -231}
Interactive Tool 1.4
The computer does not distinguish between signed and unsigned numbers in memory. The interpretation is yours to make. Enter an 8-bit binary number in the following field and press "show" to see its value if interpreted as signed or unsigned integer. For convenience, you can also enter hexadecimal input with '0x' prefix.
[Video 1.3.3. Signed versus unsigned numbers](http://youtu.be/kYxKjMAFDBE)
## 1\.4. Introduction to Computers
[Video 1.4.1. Computer Organization](http://youtu.be/LD1dd8uRfj4)
A **computer** combines a processor, random access memory (RAM), read only memory (ROM), and input/output (I/O) ports. Computers are not intelligent. Rather, you are the true genius. Computers are electronic idiots. They can store a lot of data, but they will only do exactly what we tell them to do. Fortunately, however, they can execute our programs quite quickly, and they donât get bored doing the same tasks over and over again. **Software** is an ordered sequence of very specific instructions that are stored in memory, defining exactly what and when certain tasks are to be performed. It is a set of instructions, stored in memory, that are executed in a complicated but well-defined manner. The **processor** executes the software by retrieving and interpreting these instructions one at a time. A **microprocessor** is a small processor, where small refers to size (i.e., it fits in your hand) and not computational ability.
A **microcomputer** is a small computer, where again small refers to size (i.e., you can carry it) and not computational ability. For example, a desktop PC is a microcomputer. Small in this context describes its size not its computing power. Consequently, there can be great confusion over the term microcomputer, because it can refer to a very wide range of devices from a PIC12C508, which is an 8-pin chip with 512 words of ROM and 25 bytes RAM, to the most powerful I7-based personal computer.
A **port** is a physical connection between the computer and its outside world. Ports allow information to enter and exit the system. Information enters via the input ports and exits via the output ports. Other names used to describe ports are I/O ports, I/O devices, interfaces, or sometimes just devices. A **bus** is a collection of wires used to pass information between modules.
A very small microcomputer, called a **microcontroller**, contains all the components of a computer (processor, memory, I/O) on a single chip. As shown in Figure 1.4.1, the Atmel ATtiny, the Texas Instruments MSP430, and the Texas Instruments TM4C123 are examples of microcontrollers. Because a microcomputer is a small computer, this term can be confusing because it is used to describe a wide range of systems from a 6-pin ATtiny4 running at 1 MHz with 512 bytes of program memory to a personal computer with state-of-the-art 64-bit multi-core processor running at multi-GHz speeds having terabytes of storage.
The computer can store information in **RAM** by writing to it, or it can retrieve previously stored data by reading from it. RAMs are **volatile**; meaning if power is interrupted and restored the information in the RAM is lost.

Figure 1.4.1. A microcontroller is a complete computer on a single chip.
Information is programmed into **ROM** using techniques more complicated than writing to RAM. From a programming viewpoint, retrieving data from a ROM is identical to retrieving data from RAM. ROMs are nonvolatile; meaning if power is interrupted and restored the information in the ROM is retained.
Figure 1.4.2 shows a simplified block diagram of a microcontroller based on the ARMÂŽ Cortexâ˘\-M processor. It is a **Harvard architecture** because it has separate data and instruction buses. Instructions are fetched from flash ROM using the **ICode bus** at the same time as Data are exchanged with memory and I/O via the **System bus** interface.
Figure 1.4.2. Harvard architecture of an ARMÂŽ Cortex-M-based microcontroller.
**Checkpoint 1.4.1 :** What are the differences between a microcomputer, a microprocessor, and a microcontroller?
**Checkpoint 1.4.2 :** What are three differences between RAM and ROM?
## 1\.5. I/O Ports
The external devices attached to the microcontroller provide functionality for the system. A **pin** is one wire on the microcontroller used for input or output. There are 43 I/O pins on the TM4C123. A **port** is a collection of pins. An **input pin** is hardware on the microcontroller that allows information about the external world to be entered into the computer. The microcontroller also has hardware called an **output pin** to send information out to the external world. Most of the pins shown in Figure 5.1.1 are input/output ports.
[Video 1.5.1. I/O Ports and Interfacing](http://youtu.be/R7RFjNFycyU)
An **interface** is defined as the collection of the I/O port, external electronics, physical devices, and the software, which combine to allow the computer to communicate with the external world. An example of an input interface is a switch, where the operator toggles the switch, and the software can recognize the switch position. An example of an output interface is a light-emitting diode (LED), where the software can turn the light on and off, and the operator can see whether or not the light is shining. There is a wide range of possible inputs and outputs, which can exist in either digital or analog form. In general, we can classify I/O interfaces into four categories
**Parallel** - binary data are available simultaneously on a group of lines
**Serial** - binary data are available one bit at a time on a single line
**Analog** - data are encoded as an electrical voltage, current, or power
**Time** - data are encoded as a period, frequency, pulse width, or phase shift
The general purpose input output (GPIO) port is simply a collection of pins, and allows the software to read data from input pins and write data to output pins. The direction register allows the software to specify whether a pin is an input or output.
****
Figure 1.5.2. A GPIO port allows for input and output.
****
Figure 1.5.3. The TM4C123GH6PM six ports and 43 pins.
We will begin by interacting with Port F, because the LaunchPad has two switches and one LED already connected. The 5 pins of Port F are called PF4, PF3, PF3, PF2, PF1, and PF0. Figure 1.5.4 shows there are switches connected to PF4 and PF0. There is one 3-color LED connected to PF3-PF2-PF1.
****
Figure 1.5.4. Switch and LED interfaces on the LaunchPad Evaluation Board. The zero ohm resistors can be removed so the corresponding pin can be used without connection to the external circuits.
An **I/O register** is a location in memory with which software can interface with the I/O port. Initialization is executed once at the beginning. First, we turn on the clock in **SYSCTL\_RCGCGPIO\_R** by setting appropriate bits. Second, we wait about 25, which is two bus cycles. Third, we write 1 into the corresponding **DIR** bit for each pin we wish to make output. Conversely we write a 0 into the corresponding **DIR** bit for each pin we wish to make input. To use the two switches on PF4 and PF0, we will also set bits 4 and 0 of the **PUR** register to activate an internal pull-up resistor. Lastly, we set the **DEN** bits to 1 to enable data pins. If we wish to input from a Port F GPIO pin we simply read from **GPIO\_PORTF\_DATA\_R**. Reading from **GPIO\_PORTF\_DATA\_R** obtains the current values for both input and output pins. If we wish to output to a Port F GPIO pin we write to **GPIO\_PORTF\_DATA\_R**. Writing to **GPIO\_PORTF\_DATA\_R** affects output pins but does not affect input pins. Table 1.5.1 shows the addresses of some of the I/O registers needed to access Port F. The other ports have similar I/O registers.
| | | | | | | | | | |
|---|---|---|---|---|---|---|---|---|---|
| Address | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | Name |
| 0x400FE608 | \- | \- | GPIOF | GPIOE | GPIOD | GPIOC | GPIOB | GPIOA | SYSCTL\_RCGCGPIO\_R |
| 0x400253FC | \- | \- | \- | DATA | DATA | DATA | DATA | DATA | GPIO\_PORTF\_DATA\_R |
| 0x40025400 | \- | \- | \- | DIR | DIR | DIR | DIR | DIR | GPIO\_PORTF\_DIR\_R |
| 0x40025510 | \- | \- | \- | PUR | PUR | PUR | PUR | PUR | GPIO\_PORTF\_PUR\_R |
| 0x4002551C | \- | \- | \- | DEN | DEN | DEN | DEN | DEN | GPIO\_PORTF\_DEN\_R |
Table 1.5.1. I/O registers needed for GPIO Port F.
**Checkpoint 1.5.1 :** How does the software input from Port F?
**Checkpoint 1.5.2 :** How does the software output to Port F?
## 1\.6. Memory
Figure 1.6.1 shows the memory map of the TM4C123. A 32-bit entry requires four sequential locations. The I/O ports exist as memory-mapped locations. I/O ports are not memory, but we will write to an I/O port address to output and read from an I/O port address to input.

Figure 1.6.1. Memory map. Each address contains 8 bits or 1 byte.
[Video 1.6.1. Memory Map Layout](http://youtu.be/u9UUVh8YoEg)
When we store 16-bit data into memory it requires two bytes. Since the memory systems on most computers are byte addressable (a unique address for each byte), there are two possible ways to store in memory the two bytes that constitute the 16-bit data. Many main-frame computers, like the z/Architecture, implement the **big endian** approach that stores the most significant byte at the lower address. Most smaller computers (desktops, laptops, phones and microcontrollers) implement the **little endian** approach that stores the least significant byte at the lower address. The Cortex-M microcontrollers use the little endian format. Many ARM processors are **biendian**, because they can be configured to efficiently handle both big and little endian data. Instruction fetches on the ARM are always little endian. Figure 1.6.2 shows two ways to store the 16-bit number 1000 (0x03E8) at locations 0x20000850 and 0x20000851. We also could use either the big or little endian approach when storing 32-bit numbers into memory that is byte (8-bit) addressable. Figure 1.6.3 shows the big and little endian formats that could be used to store the 32-bit number 0x12345678 at locations 0x20000850 through 0x20000853.

Figure 1.6.2. Example of big and little endian formats of a 16-bit number (the Cortex M used little endian).

Figure 1.6.3. Example of big and little endian formats of a 32-bit number (the Cortex M used little endian).
In the previous two examples, we normally would not pick out individual bytes (e.g., the 0x12), but rather capture the entire multiple byte data as one nondivisable piece of information. On the other hand, if each byte in a multiple byte data structure is individually addressable, then both the big and little endian schemes store the data in first to last sequence. For example, if we wish to store the four ASCII characters âLM3Sâ, which is 0x4C4D3353 at locations 0x2000.0850 through 0x2000.0853, then the ASCII âLâ=0x4C comes first in both big and little endian schemes, as illustrated in Figure 1.6.4.

Figure 1.6.4. Character strings are stored in the same for both big and little endian formats.
The terms âbig and little endianâ come from Jonathan Swiftâs satire Gulliverâs Travels. In Swiftâs book, a Big Endian refers to a person who cracks their egg on the big end. The Lilliputians were Little Endians because they insisted that the only proper way is to break an egg on the little end. The Lilliputians considered the Big Endians as inferiors. The Big and Little Endians fought a long and senseless war over the best way to crack an egg.
**Common Error:** An error will occur when data is stored in Big Endian by one computer and read in Little Endian format on another.
A **pseudo-op** is an assembler directive to affect the assembly process. We use the **AREA** pseudo-op to specify what information goes in RAM and what goes in ROM. We will use a template similar to Program 1.6.1 for most assembly programs in this class. The **EQU** pseudo-ops create symbols containing the address of some the I/O port registers. The **AREA DATA** pseudo-op means the following code will be placed in volatile RAM. The **SPACE** pseudo-op allocates 4 bytes (in RAM) for the variable named **Stuff**. The **AREA \|.text\|** pseudo-op means the following code will be placed in nonvolatile ROM. The **THUMB** pseudo-op tells the assembler to create Thumb code. The **EXPORT** pseudo-op allows the label **Start** to be accessed from another file. In particular, **Start** will be the place the software starts on power up or on reset. The **B Loop** instruction creates an infinite loop, typical of embedded systems, causing the code between **Loop** and **B Loop** to be executed over and over.
**GPIO\_PORTF\_DATA\_R EQU 0x400253FC GPIO\_PORTF\_DIR\_R EQU 0x40025400 GPIO\_PORTF\_PUR\_R EQU 0x40025510 GPIO\_PORTF\_DEN\_R EQU 0x4002551C SYSCTL\_RCGCGPIO\_R EQU 0x400FE608 AREA DATA, ALIGN=4 ;Global variables defined here, will go in RAM Stuff SPACE 4 AREA \|.text\|, CODE, READONLY, ALIGN=2 THUMB EXPORT Start Start ;assembly code to be executed once and first goes here Loop ;assembly code to be executed over and over goes here B Loop END ; end of file**
Program 1.6.1. Template for assembly language programs.
**Checkpoint 1.6.1 :** What is the purpose of the 4 in the **Stuff SPACE 4** pseudo-op?
**Checkpoint 1.6.2 :** What is the purpose of the **AREA Data** pseudo-op?
**Checkpoint 1.6.3 :** What is the purpose of the **AREA \|.text\|** pseudo-op?
## 1\.7. Instruction Set Architecture
[Video 1.7.1. Instruction set architecture.](http://youtu.be/VB8iLtfy3Cc)
This section is a brief introduction to the ARMÂŽ Cortexâ˘-M instruction set architecture. There are many ARMÂŽ processors, and this class focuses on Cortex-M microcontrollers, which executes ThumbÂŽ instructions extended with Thumb-2 technology. This class will not describe in detail all the Thumb instructions. Rather, we focus on only a subset of the ThumbÂŽ instructions. This subset will be functionally complete without regard to minimizing code size or optimizing for execution speed. Furthermore, we will show the simple forms of instructions, but in many cases there are specific restrictions on which registers can be used and the sizes of the constants. Bookmark the following links and refer to them as you write assembly programs
- [Quick Reference Assembly Guide](http://users.ece.utexas.edu/~valvano/Volume1/QuickReferenceCard.pdf) (ARM)
- [Assembly Reference](https://users.ece.utexas.edu/~valvano/Volume1/IntroToEmbSys/AssemblyReference.htm) (Yerraballi/Valvano)
- [Cortex-M3/M4F Instruction Set](http://users.ece.utexas.edu/~valvano/EE345L/Labs/Fall2011/CortexM_InstructionSet.pdf) (Texas Instruments)
- [The ARM Cortex-M Technical Reference Manual](http://users.ece.utexas.edu/~valvano/EE345L/Labs/Fall2011/CortexM4_TRM_r0p1.pdf) (ARM)
### 1\.7.1. Registers
Registers are high-speed storage inside the processor. The registers are depicted in Figure 1.6.1. R0 to R12 are general purpose registers and contain either data or addresses. Register R13 (also called the stack pointer, SP) points to the top element of the stack. Register R14 (also called the link register, LR) is used to store the return location for functions. The LR is also used in a special way during exceptions, such as interrupts. Interrupts are covered in Chapter 6. Register R15 (also called the program counter, PC) points to the next instruction to be fetched from memory. The processor fetches an instruction using the PC and then increments the PC.

Figure 1.6.1. Registers on the ARMÂŽ Cortex-M processor.
Checkpoint 1.7.1 : Where in memory should you put the stack? I.e., does the SP point to RAM or ROM?
**Checkpoint 1.7.2 :** Where in memory should you put the program? I.e., does the PC point to RAM or ROM?
The ARM Architecture **Procedure Call Standard**, AAPCS, part of the ARM **Application Binary Interface** (ABI), uses registers R0, R1, R2, and R3 to pass input parameters into a C function. Also according to AAPCS we place the return parameter in Register R0.
There are three status registers named Application Program Status Register (APSR), the Interrupt Program Status Register (IPSR), and the Execution Program Status Register (EPSR) as shown in Figure 1.7.2. These registers can be accessed individually or in combination as the **Program Status Register** (PSR). The N, Z, V, C, and Q bits give information about the result of a previous ALU operation. In general, the **N bit** is set after an arithmetical or logical operation signifying whether or not the result is negative. Similarly, the **Z bit** is set if the result is zero. The **C bit** means carry and is set on an unsigned overflow, and the **V bit** signifies signed overflow. The **Q bit** indicates that âsaturationâ has occurred â while you might want to look it up, saturated arithmetic is beyond the scope of this class.

Figure 1.7.2. The program status register of the ARMÂŽ Cortex-M processor.
The **T bit** will always be 1, indicating the ARMÂŽ Cortexâ˘\-M processor is executing ThumbÂŽ instructions. The ISR\_NUMBER indicates which interrupt if any the processor is handling. Bit 0 of the special register **PRIMASK** is the interrupt mask bit. If this bit is 1, most interrupts and exceptions are not allowed. If the bit is 0, then interrupts are allowed. The nonmaskable interrupt (NMI) is not affected by these mask bits. The **BASEPRI** register defines the priority of the executing software. It prevents interrupts with lower or equal priority but allows higher priority interrupts. For example if **BASEPRI** equals 3, then requests with level 0, 1, and 2 can interrupt, while requests at levels 3 and higher will be postponed. A lower number means a higher priority interrupt. The details of interrupt processing will be presented in Chapter 6.
### 1\.7.2. Syntax
Assembly language instructions have four fields separated by spaces or tabs. The **label field** is optional and starts in the first column and is used to identify the position in memory of the current instruction. You must choose a unique name for each label. The **opcode field** specifies the processor command to execute. The **operand field** specifies where to find the data to execute the instruction. Thumb instructions have 0, 1, 2, 3, or 4 operands, separated by commas. The **comment field** is also optional and is ignored by the assembler, but it allows you to describe the software making it easier to understand. You can add optional spaces between operands in the operand field. However, a semicolon must separate the operand and comment fields. Good programmers add comments to explain the software.
Label Opcode Operands Comment
**Func MOV** **R0, \#100 ; 100 means maximum**
**BX** **LR**
**Observation:** A good comment explains why an operation is being performed, how it is used, how it can be changed, or how it was debugged. A bad comment explains what the operation does. The comments in the above two assembly lines are examples of bad comments.
The assembly **source code** is a text file (with Windows file extension **.s**) containing a list of instructions. The **assembler** translates assembly source code into **object code**, which are the machine instructions executed by the processor. All object code is halfword-aligned. This means instructions can be 16 or 32 bits wide, and the program counter bit 0 will always be 0. The **listing** is a text file containing a mixture of the object code generated by the assembler together with our original source code.
Address Object code Label Opcode Operand comment
**0x000005E2 F04F0164 Func MOV R1,\#0x64 ; R1=100**
**0x000005E6 FB00F001 MUL R0,R0,R1 ; R0=100\*input**
**0x000005EA F100000A ADD R0,R0,\#0x0A ; R0=100\*input+10**
**0x000005EE 4770 BX LR ; return 100\*input+10**
When we **build** a project all files are assembled or compiled then linked together. The address values shown in the listing are relative to the particular file being assembled. When the entire project is built, the files are linked together, and the **linker** decides exactly where in memory everything will be. After building the project, it can be downloaded, which programs the object code into flash ROM. You are allowed to load and execute software out of RAM. But for an embedded system, we typically place executable instructions into nonvolatile ROM. The listing you see in the debugger will specify the absolute address showing you exactly where in memory your variables and instructions exist.
### 1\.7.3. Reading from and writing to memory
The first action we present is bringing a constant value into a register. With immediate addressing mode, the data itself is contained in the instruction. Once the instruction is fetched no additional memory access cycles are required to get the data. Notice the number 100 (0x64) is embedded in the machine code of the **MOV** instruction shown in Figure 1.6.3.
**MOV R0,\#100 ; R0=100, immediate addressing**
Figure 1.7.3. An example of immediate addressing mode, data is in the instruction.
The constant value allowed by **MOV** is limited to 16-bit values. On the other hand, the **LDR** instruction can be used to bring any 32-bit value into a register. Notice the number 0x12345678 is not embedded in the machine code of the instruction, but rather stored in ROM a short distance away, as shown in Figure 1.7.4. The Keil assembler automatically places the constant in ROM and calculates the appropriate PC-relative offset. At the time of execution, the PC is pointing to the next instruction.
**LDR R0,=0x12345678 ; R0=0x12345678, PC-relative addressing**

Figure 1.7.4. An example of using the LDR instruction to load any constant into a register.
[Video 1.7.2. Assembly language access to RAM and ROM variables.](http://youtu.be/bpHTIP1e57o)
A fundamental issue in program development is the differentiation between data and address. When we put the number 100 into Register R0, whether this is data or address depends on how the 100 is used. As presented in Program 1.6.1, we created a 32-bit global variable called **Stuff**. To write an initial value of 100 into this variable will take three instructions. In this example, R0 has data and R1 had an address. First, the **MOV** instruction brings the desired value into R0. Second, the **LDR** instruction sets R1 to point to the global variable **Stuff**. Lastly, the **STR** instruction writes the value into the variable.
**MOV R0,\#100 LDR R1,=Stuff ; R1 points to the variable Stuff STR R0,\[R1\] ; Stuff=100**
Figure 1.7.5. It takes three instructions to write to a global variable.
**Checkpoint 1.7.3 :** How would you modify the above assembly code to write 0x0E to Port F?
To read the value of a variable into a register will take two instructions. After executing these two instructions, R3 will have a copy of the value from the global **Stuff**. The first **LDR** instruction sets R2 to point to the global variable **Stuff**. The second **LDR** instruction will read the value from the variable.
**LDR R2,=Stuff ; R2 points to the variable Stuff LDR R3,\[R2\] ; R3=Stuff**
Figure 1.7.6. It takes two instructions to read from a global variable.
**Checkpoint 1.7.4 :** How would you modify the above assembly code to read from Port F?
An **aligned access** is an operation where a word-aligned address is used for a word, dual word, or multiple word access, or where a halfword-aligned address is used for a halfword access. Byte accesses are always aligned. The address of an aligned word access will have its bottom two bits equal to zero. An **unaligned** word access means we are accessing a 32-bit object (4 bytes) but the address is not evenly divisible by 4. The following instructions support 32-bit memory access:
**LDR** Load 32-bit word
**STR** Store 32-bit word
The address of an aligned halfword access will have its bottom bit equal to zero. An unaligned halfword access means we are accessing a 16-bit object (2 bytes) but the address is not evenly divisible by 2. The following instructions support 16-bit memory access:
**LDRH** Load 16-bit unsigned halfword
**LDRSH** Load 16-bit signed halfword (sign extend bit 15 to bits 31-16)
**STRH** Store 16-bit halfword
Transfers of one byte are allowed for the following instructions:
**LDRB** Load 8-bit unsigned byte
**LDRSB** Load 8-bit signed byte (sign extend bit 7 to bits 31-8)
**STRB** Store 8-bit byte
When loading a 32-bit register with an 8- or 16-bit value, it is important to use the proper load, depending on whether the number being loaded is signed or unsigned. This determines what is loaded into the most significant bits of the register to ensure that the number keeps the same value when it is promoted to 32 bits. When loading an 8-bit unsigned number, the top 24 bits of the register will become zero. When loading an 8-bit signed number, the top 24 bits of the register will match bit 7 of the memory data (signed extend). Note that there is no such thing as a signed or unsigned store. For example, there is no **STRSH**; there is only **STRH**. This is because 8, 16, or all 32 bits of the register are stored to an 8-, 16-, or 32-bit location, respectively. No promotion occurs. This means that the value stored to memory can be different from the value located in the register if there is overflow. When using **STRB** to store an 8-bit number, be sure that the number in the register is 8 bits or less.

Figure 1.7.6. Assume these memory contents for Checkpoints 1.7.5 through 1.7.9.
**Checkpoint 1.7.5 :** Assume R0 equal 0x20000850 at the time **LDR R1,\[R0\]** is executed. To what value will R1 become?
**Checkpoint 1.7.6 :** Assume R0 equal 0x20000850 at the time **LDRH R2,\[R0\]** is executed. To what value will R2 become?
**Checkpoint 1.7.7 :** Assume R0 equal 0x20000850 at the time **LDRSH R3,\[R0\]** is executed. To what value will R3 become?
**Checkpoint 1.7.8 :** Assume R0 equal 0x20000850 at the time **LDRB R4,\[R0\]** is executed. To what value will R4 become?
**Checkpoint 1.7.9 :** Assume R0 equal 0x20000850 at the time **LDRSB R5,\[R0\]** is executed. To what value will R5 become?
### 1\.7.4. Logical Operations
**Boolean Logic** has two states: true (1) and false (0). A **binary operation** produces a single result given two inputs. The logical and (&) operation yields a true result if both input parameters are true. The logical or (\|) operation yields a true result if either input parameter is true. The exclusive or (^) operation yields a true result if exactly one input parameter is true. The logical operators are summarized in the table below. The logical instructions on the ARM Cortex-M processor take two inputs, one from a register and the other either from a register or from a constant. These operations are performed in a bit-wise fashion on two 32-bit input parameters yielding one 32-bit output result. The result is stored into the destination register. For example, the calculation r=m\&n means each bit is calculated separately, r31=m31\&n31, r30=m30\&n30,..., r0=m0\&n0.
In C, when we write logical operations as r=m\&n; r=m\|n; r=m^n; the logical operation occurs in a bit-wise fashion also described by the table below. However, in C, we define the Boolean functions as r=m&\&n; r=m\|\|n; For Booleans, the operation occurs in a word-wise fashion. For example, r=m&\&n; means r will become zero if either m is zero or n is zero. Conversely, r will become 1 (any nonzero) if both m is nonzero and n is nonzero.
| | | | | | |
|---|---|---|---|---|---|
| A | B | A\&B | A\|B | A^B | A&(~B) |
| Rn | Op2 | AND | ORR | EOR | BIC |
| 0 | 0 | 0 | 0 | 0 | 0 |
| 0 | 1 | 0 | 1 | 1 | 0 |
| 1 | 0 | 0 | 1 | 1 | 1 |
| 1 | 1 | 1 | 1 | 0 | 0 |
Table 1.7.1. Logical operations performed by the Cortex-M processor.
All instructions place the result into the destination register **Rd**. If **Rd** is omitted, the result is placed into **Rn**, which is the register holding the first operand. If the optional S suffix is added, the N and Z condition code bits are updated on the result of the operation. The second operand is either a register or a 12-bit immediate value. We use the **AND** instruction to mask or select bits. We use the **ORR** instruction to set bits. We use the **EOR** instruction to toggle bits (change from 0 to 1 or 1 to 0) bits. We use the **BIC** instruction to clear bits.
` AND Rd, Rn, Rm ;Rd=Rn&Rm AND Rd, Rn, #n ;Rd=Rn&n ORR Rd, Rn, Rm ;Rd=Rn|Rm ORR Rd, Rn, #n ;Rd=Rn|n EOR Rd, Rn, Rm ;Rd=Rn^Rm EOR Rd, Rn, #n ;Rd=Rn^n BIC Rd, Rn, Rm ;Rd=Rn&(~Rm) BIC Rd, Rn, #n ;Rd=Rn&(~n)`
Assume Port F bit 1 (PF1) is an output. The following example sets the PF1 pin high. Notice that this code will leave the other pins unchanged.
**// C version** **GPIO\_PORTF\_DATA\_R = GPIO\_PORTF\_DATA\_R \| 0x02; ; assembly version**
**LDR R0,=GPIO\_PORTF\_DATA\_R ;pointer to data register**
**LDR R1,\[R0\] ;previous values ORR R1,R1,\#0x02 ;set bit 1 STR R0,\[R1\] ; change output**
Again, assume Port F bit 1 (PF1) is an output. The following example clears the PF1 pin low, without changing any other pins.
**// C version** **GPIO\_PORTF\_DATA\_R = GPIO\_PORTF\_DATA\_R & ~0x02; ; assembly version**
**LDR R0,=GPIO\_PORTF\_DATA\_R ;pointer to data register**
**LDR R1,\[R0\] ;previous values BIC R1,R1,\#0x02 ;clear bit 1 STR R0,\[R1\] ; change output**
**Checkpoint 1.7.10 :** How would you change the above program to set the PF3 pin?
**Checkpoint 1.7.11 :** How would you change the above program to toggle the PF2 pin?
### 1\.7.5. Shift Operations
Like programming in C, the assembly shift instructions take two input parameters and yield one output result. In C, the left shift operator is \<\< and the right shift operator is \>\>. E.g., to left shift the value in m by n bits and store the result in r we execute: **r = m\<\<n**. Similarly, to right shift the value in m by n bits and store result r, we execute: **r=m\>\>n**.

Figure 1.7.7. Shift operations move bits to the right or left.
The **logical shift right** (LSR) is similar to an unsigned divide by 2n, where n is the number of bits shifted. A zero is shifted into the most significant position, and the carry flag will hold the last bit shifted out. The right shift operations do not round. For example, a right shift by 3 bits is similar to divide by 8. However, 15 right-shifted three times (15\>\>3) is 1, while 15/8 is much closer to 2. In general, the LSR discards bits shifted out, and the UDIV truncates towards 0. Thus, when using UDIV to divide unsigned numbers by a power of 2, UDIV and LSR yield identical results.
The **arithmetic shift right** (ASR) is similar to a signed divide by 2n. Notice that the sign bit is preserved, and the carry flag will hold the last bit shifted out. This right shift operation also does not round. Again, a right shift by 3 bits is similar to divide by 8. However, -9 right-shifted three times (-9\>\>3) is -2, while implementing -9 divided by 8 using the SDIV instruction yields -1. In general, the ASR discards bits shifted out, and the SDIV truncates towards 0.
The **logical shift left** (LSL) operation works for both unsigned and signed multiply by 2n. A zero is shifted into the least significant position, and the carry bit will contain the last bit that was shifted out.
All shift instructions place the result into the destination register Rd. Rm is the register holding the value to be shifted. The number of bits to shift is either in register Rs, or specified as a constant n. If the optional S suffix is specified, the N and Z condition code bits are updated on the result of the operation. The C bit is the carry out after the shift. These shift instructions will leave the V bit unchanged.
**Observation:** Use logic shift for unsigned numbers and arithmetic shifts for signed numbers.
` LSR Rd, Rm, Rs ; logical shift right Rd=Rm>>Rs (unsigned) LSR Rd, Rm, #n ; logical shift right Rd=Rm>>n (unsigned) ASR Rd, Rm, Rs ; arithmetic shift right Rd=Rm>>Rs (signed) ASR Rd, Rm, #n ; arithmetic shift right Rd=Rm>>n (signed) LSL Rd, Rm, Rs ; shift left Rd=Rm<<Rs (signed, unsigned) LSL Rd, Rm, #n ; shift left Rd=Rm<<n (signed, unsigned)`
**Checkpoint 1.7.12 :** If R0=0xC0123456, what will be the value in R0 after **LSR R0,R0,\#4** is executed?
**Checkpoint 1.7.13 :** If R0=0xC0123456, what will be the value in R0 after **ASR R0,R0,\#4** is executed?
**Checkpoint 1.7.14 :** If R0=0xC0123456, what will be the value in R0 after **LSL R0,R0,\#4** is executed?
### 1\.7.6. Arithmetic Operations
When software executes arithmetic instructions, the operations are performed by digital hardware inside the processor. Even though the design of such logic is complex, we will present a brief introduction, in order to provide a little insight as to how the computer performs arithmetic. It is important to remember that arithmetic operations (addition, subtraction, multiplication, and division) have constraints when performed with finite precision on a processor. An overflow error occurs when the result of an arithmetic operation cannot fit into the finite precision of the register into which the result is to be stored. If the optional S suffix is specified, the N C V and Z condition code bits are updated on the result of the operation.
The immediate value \#n can be any 12-bit constant. When Rd is absent, the result is placed back in Rn.
`` The compare instruction CMP does not save the result of the subtraction but always sets the condition code. The compare instructions are used to create conditional execution, such as if-then, for loops, and while loops.
If the optional S suffix is present, addition and subtraction set the condition code bits as shown in the following table. The addition and subtraction instructions work for both signed and unsigned values. As designers, we must know in advance whether we have signed or unsigned numbers. The computer cannot tell from the binary which type it is, so it sets both C and V. Our job as programmers is to look at the C bit if the values are unsigned and look at the V bit if the values are signed.
| | | |
|---|---|---|
| Bit | Name | Meaning after addition or subtraction |
| N | Negative | Result is negative |
| Z | Zero | Result is zero |
| V | Overflow | Signed overflow |
| C | Carry | Unsigned overflow |
Table 1.7.2. Condition code bits contain the status of the previous arithmetic operation.
**Observation:** The carry bit, C, is set after an unsigned addition when the result is incorrect. The carry bit, C, is cleared after an unsigned subtraction when the result is incorrect.
**Observation:** The overflow bit, V, is set after a signed addition or subtraction when the result is incorrect.
Multiply (**MUL**) uses 32-bit operands and produces a 32-bit result. This multiply instructions only save the bottom 32 bits of the result. They can be used for either signed or unsigned numbers, but no overflow flags are generated. If the Rd register is omitted, the Rn register is the destination. If the S suffix is added to **MUL**, then the Z and N bits are set according to the result. The division instructions do not set condition code flags and will round towards zero if the division does not evenly divide into an integer quotient
` MUL Rd, Rn, Rm ;Rd = Rn * Rm UDIV Rd, Rn, Rm ;Rd = Rn / Rm (unsigned) SDIV Rd, Rn, Rm ;Rd = Rn / Rm (signed)`
**Checkpoint 1.7.15 :** If one adds an n-bit number to another n-bit number, how total bits are in the sum?
**Checkpoint 1.7.16 :** If one multiplies an n-bit number to an m-bit number, how total bits are in the product?
### 1\.7.7. Branch Instructions
Normally the computer executes one instruction after another in a linear fashion. In particular, the next instruction to execute is found immediately following the current instruction. We use branch instructions to deviate from this straight line path. The following lists a few of the many branch instructions. The conditional branching must be preceded by an instruction that sets the condition code bits.
` B label ;unconditional branch to label BEQ label ;branch to label if Z=1 BNE label ;branch to label if Z=0 BMI label ;branch to label if N=1 BPL label ;branch to label if N=0 BCS label ;branch to label if C=1 BCC label ;branch to label if C=0 BVS label ;branch to label if V=1 BVC label ;branch to label if V=0`
## 1\.8. Designing a NOT gate using a LaunchPad
In this section we will combine many of the concepts presented in this chapter to design, build and test a NOT gate using the TM4C123 microcontroller. Any two GPIO pins could have been used, but we chose PE0 as input and PE1 as output. The system will make the PE1 output the logic NOT of the input on PE0. We will test the NOT gate by using a switch on PE0 to generate an input signal, and use an LED on PE1 to visualize the output. Basically if we press the switch, the input on PE0 will be high. The system will make the output on PE1 low, and the LED will be off. Conversely, if we release the switch, the input on PE0 will be low. The system will make the output on PE1 high, and the LED will be on. The details of this circuit will be presented in Chapter 3.

Figure 1.8.1. Circuit to test NOT gate.
To use GPIO pins we must first initialize the port. Program 1.8.1 initializes PE0 as input and PE1 as output. First, we turn on the clock and wait two bus cycles for the clock to stabilize. Then, we set the **DIR** register to 0x02, making PE1 an output and PE0 an input. Lastly, we set the **DEN** register to 0x03 to enable both PE1 and PE0. The code in Program 1.8.1 will be executed once at the start of the software, and before we access the data register of Port E
` LDR R0,=SYSCTL_RCGCGPIO_R LDR R1,[R0] ;previous ORR R1,R1,#0x10 ;bit 4 is clock for E STR R1,[R0] ;turn on clock for E NOP ;wait NOP ;wait LDR R0,=GPIO_PORTE_DIR_R MOV R1,#0x02 ;PE1 output, PE0 input STR R1,[R0] LDR R0,=GPIO_PORTE_DEN_R MOV R1,#0x03 ;enable PE1,PE0 STR R1,[R0]`
Program 1.8.1. Initialization of Port E, making PE1 an output and PE0 an input.
Effective testing starts with the simplest component. We begin by connecting the LED to PE1 and writing test code to see if the software can control the LED state. The assembly code in Program 1.8.2 will toggle the output on PE1. R0 points to the data register for Port E. R1 contains the value of Port E, which we read-toggle-write. R2 contains a large number, and is used to create a long delay, so we can see the LED flash with our eyes. The accesses to R3 will slow down the wait loop. The **SUBS** instruction decrements the R2 counter and sets the Z bit when the counter reaches 0. The **BNE** instruction will branch if the Z bit is not set (R2 is not zero). The **B loop** instruction is an unconditional branch so the code is repeated over and over.
` LDR R0,=GPIO_PORTE_DATA_R loop LDR R1,[R0] ;read all of PortE EOR R1,R1,#0x02 ;toggle bit 1 STR R1,[R0] ;output to PortE LDR R2,=1000000 wait MOV R3,#1000 ;dummy operation MOV R3,#2000 ;dummy operation MOV R3,#3000 ;dummy operation MOV R3,#4000 ;dummy operation SUBS R2,R2,#1 BNE wait B loop`
Program 1.8.2. Toggle the PE1 output.
The assembly code in Program 1.8.3 will create a NOT gate, using PE0 as input and PE1 as output. First, we read all of Port E. We select just bit 0 using the AND instruction with mask \#1. Next, we toggle bit 0 using the EOR instruction to implement the NOT operation. We use the LSL instruction to move the information in bit 0 into the bit 1 location. Lastly we output to Port E, making the pin PE1 the logical NOT of the input from PE0.
` LDR R0,=GPIO_PORTE_DATA_R loop LDR R1,[R0] ;Read Port E AND R1,R1,#1 ;mask, select PE0 EOR R1,R1,#1 ;NOT LSL R1,R1,#1 ;move to bit 1 STR R1,[R0] ;write Port E, sets PE1 B loop`
Program 1.8.3. A NOT gate with PE0 as input and PE1 as output.
Finally, we connect the switch to PE0 and single step through the code. We step through the loop with the switch not pressed to see the LED come on, and with the switch pressed to see the LED go off. If we connect a logic analyzer to PE1 and PE0, we test dynamic behavior of the system. Running in simulation with a bus clock of 16 MHz, we see it takes 3.4us for a change in input to propagate to the output. This delay, of course, will depend on which of six instructions in the loop are being executed when the input is changed. The worst case would be to change during the AND instruction because it would have to execute 10 instructions until the output changed: AND-EOR-LSL-STR-B-LDR-AND-EOR-LSL-STR.

Figure 1.8.2. Simulated logic analyzer signals measuring propagation delay of the NOT gate.
Reprinted with approval from [Introduction to Embedded Systems, 2022, ISBN: 978-1537105727](https://www.amazon.com/Introduction-Embedded-Systems-Jonathan-Valvano/dp/1537105728)
[](http://creativecommons.org/licenses/by-nc-nd/4.0/deed.en_US)
Embedded Systems - Shape the World by [Jonathan Valvano and Ramesh Yerraballi](http://users.ece.utexas.edu/~valvano/) is licensed under a [Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License](http://creativecommons.org/licenses/by-nc-nd/4.0/deed.en_US).
Based on a work at <http://users.ece.utexas.edu/%7Evalvano/arm/outline1.htm>. |
| Readable Markdown | null |
| Shard | 65 (laksa) |
| Root Hash | 16797036158535431465 |
| Unparsed URL | edu,utexas!ece,users,/~valvano/Volume1/IntroToEmbSys/Ch1_Introduction.html s443 |