Welcome to the Embedded Systems Programming course. My name is Miro Samek
and in this lesson I'm going to show you how to blink the LED on the Stellaris Launchpad board.
For this lesson, I highly recommend that you download the User Manual of the board from
the link I provide in the class notes for this video.
If you don't have the board, you can still follow along in the Simulator, but your debugger
views will be slightly different, and of course, you won't see the LED blink.
The manual describes how to connect the board to your computer via the provided USB cable.
For today, you are mostly interested in the very nice, Red-Green-Blue User LED located
at the right edge of the board.
The manual explains how the components on the board are connected to the microcontroller.
Among others, you can see that the User LED is connected to GPIO, which means General
Purpose Input-Output.
At the end of the manual, you can find the schematics of the board.
On the first page of the schematics you can see that the R, G, and B components, of the
User LED are powered by transistors, which are controlled by outputs LED_R, LED_G, and
LED_B, respectively.
You can see these outputs again higher up in the schematics, where they connect to the
microcontroller pins labeled Pin F1, Pin F2, and Pin F3. The the letter F, in this case
stands, for GPIO-F.
So now, that you have some idea of how the LED is connected, let's prepare the IAR project
for this lesson. As usual, let's start with making a copy of the previous lesson3-project
and renaming it to lesson4. If you don't have the lesson3-project, you can get it online
from state-machine.com/quickstart.
Get inside the new lesson4 directory and double-click on the workspace file to open the IAR toolset.
If you don't have the IAR toolset, go back to lesson 0.
If you have the Launchpad board, you should connect it to your PC now and make sure that:
the debugger is configured for the TI Stellaris interface, and that the Download tab has the
"Use flash loader" option checked.
If you don't have the board, configure the Debugger for Simulator and follow along.
Also, if you're using the board, please click on the TI Stellaris menu and check the "Reset
will do system reset" option, so that the board will always start from clean reset.
Finally, please rebuild the project entirely, to prevent the IAR from pulling in the main.c
file from the previous lesson3 project.
Now, let's go to the debugger and review quickly how the processor uses various addresses.
First, a the low addresses starting with 0, you can see the machine instructions. This
is the compiled code of your program, which is stored permanently inside the microcontroller.
This means that the low addresses starting from 0 are mapped to the Flash memory.
You also already know that the addresses starting from 0x2 are used for variables, such as the
counter variable. That means that address 0x2 followed by all zeros marks the start
of the Random Access Memory (RAM). Indeed, you can see a "whole" in the addresses right
before the beginning of RAM, which simply means that the debugger could not read anything
from these addresses, most likely because they are unused.
When you probe further, at the address 0x2000,8000, you can see that the RAM ends--so it is an
"island" extending for 0x8000 addresses, which is 32KB in decimal. This means that this microcontroller
has 32KB of RAM.
This is as much you know about the addresses at this point. However, in order to blink
the LED, which is your goal of this lesson, you need to learn more. Ideally, you need
to know the "map" of all the various continents and islands, such as the RAM island, in the
address space.
The document that describes the "memory map" of your microcontroller and much more in excruciating
detail is called the "data sheet". I highly recommend that you download the datasheet
for the specific LM4F microcontroller on your Launchpad board from the link I provide in
the class notes.
But I need to warn you right away, that datasheets tend to be huge. This particular one is over
1200 pages long, which is still relatively short as the datasheets go. Luckily, these
documents are not intended to be read cover-to-cover. In fact, a large part of being an embedded
systems engineer consists of knowing *how* to find your way around the datasheets so
that you can find the information you need quickly. I hope that you to pick up these
skill gradually as you participate in this course.
So for example, to find the "memory map" of your microcontroller, simply search the datasheet
for the string "memory map".
So, here it is. The memory map of a typical modern ARM Cortex-M microcontroller. This
is a very nice and simple linear address space without any segments or memory banks. If you
worked with other microcontrollers, especially the older 8-bitters, I hope you appreciate
the simplicity of a linear 32-bit address space.
I hope you recognize the first "island" on this map - called "on-chip flash" from address
0 to 3,FFFF which corresponds to 256KB of flash memory.
You should also recognize the familiar RAM island starting 0x2 followed by all zeroes,
which is named here "Bit-banded on-chip S-RAM", whereas S-RAM stands for Static-RAM.
In the Perhipherals "continent", you should note the GPIO ports. These islands are interesting,
because you are looking for "GPIO Port F" to control your LED.
Keep looking further down the memory map. Hey! Here is "GPIO Port-F" that you've been
looking for! Copy the starting address to the clipboard and go back to the IAR debugger.
Paste the starting address of GPIO-F to the memory view and watch what comes up.
Oops, this address range of GPIO-F advertised in the datasheet appears empty. If this happens
to you, don't despair. The typical reason is that the hardware block is switched off
by default to save power. The technique of blocking the clock signal to certain parts
of the chip, called clock-gating, is a very common practice in modern microcontrollers.
So, first you need to discover how to turn the GPIO-F block on, which means you need
to go back to the datasheet.
Go back to the beginning of the document and search for the string "clock gating".
Oh, here is something interesting, let's go to that page.
Let's search for the string GPIO in this section...
Oh, here it is: the GPIO Glock gating control register.
Let's take a closer look at the register description, because this is a very typical format commonly
used in datasheets. The register is shown as a block of bits, always numbered from zero.
The type of each bit is indicated, whereas RO means Read-Only, R/W means Read-Write,
and WO would mean write-only.
The logically related groups of bits are documented below the register block picture, starting
from the most significant bit. For you, the most interesting is the description of bit
5, because this bit enables the clock to GPIO Port F. This confirms that this register is
exactly what you've been looking for.
Copy the base address of the register to the Clipboard and notice that the additional offset
0x608 needs to be added to the base to get the complete register address.
Go back to the debugger, and open the additional memory view called Symbolic Memory to set
bit-5 in the clock-gating register, while simultaneously watching the GPIO-F start address
in the original memory view.
Paste the clock-gating register base address from the datasheet to the symbolic memory
view and don't forget to add to it the 0x608 offset.
Now, go to the highlighted clock-gating register and edit it's value to set bit-5, which, as
you remember from lesson 1 about counting is 20 hexadecimal. Hit enter.
Hey, the GPIO-F hardware block wakes up!
You are getting really close to being able to blink the LED, but you are not quite there
yet. As you should read it in the GPIO section of the datasheet, you still need to configure
the GPIO-F bits 1, 2, and 3, which drive Red, Blue, and Red colors, respectively, as digital
outputs.
To set the pins direction as output, scroll down within the GPIO-F address block to the
address 0x40025400 and set the bits 1, 2, and 3 to 1, which corresponds to 1110 in binary,
and E in hex.
Additionally, to set the function for the pins as digital output, scroll further down
within the GPIO-F address block to the address 0x4002551C and again set the bits 1, 2, and
3 to 1.
So, finally, you can try to control the LED. You do this throughout the GPIO-F Data register
located at 0x400253FC.
Scroll up to this register, and first set just the bit 1, by writing hex-2 to the lowest
nibble, again remembering that the bits are always counted from 0.
Hey, it worked! The red LED lights up. You should give yourself a big pat on the back.
Try to turn the LED off by writing 0. Cool.
How about setting bit 2, by writing hex 4. Wow, the LED turned blue--you are rocking.
How about setting bit 3, by writing hex 8. You got it too.
The heavy-lifting is really over, because coding this all up in C will be a piece of
cake. All there is to controlling the LED boils down to writing numbers to specific
memory addresses and this you already know how to do with pointers. Specifically, you
are going to use the pointer-hack that I showed you at the end of lesson-3, because this technique
allows you to write any number to any memory address you choose.
Clean the code up to leave only the pointer stuff.
Actually, you won't even need the separate pointer variable, because you can de-reference
the pointer-cast, as you will see in a minute.
In lesson-3 you used pointers to int. But ARM registers are unsigned, so change the
pointer type to unsigned int.
Replace the fabricated address from lesson-3 with the address of the clock-gating system
register that you used to turn the GPIO-F block on.
Enclose the whole pointer cast in parentheses and notice that this whole thing is a pointer
to unsigned int. If so, then you should be able to de-reference this pointer by means
fo the star operator, just as you see in the line below.
Now, you can write to the pointer. As you recall from the experiment in the debugger,
you need to set bit 5, that is hex 20 into this register. The value should be unsigned,
which you indicate by the U suffix.
Get rid of the no longer used p_int pointer and check if the compiler likes your code
by pressing F7
All right, so you now can press on with the next register, which was the GPIO-F pin-direction
register, where you need to set bits 1, 2, and 3 by writing hex-E.
Finally, the GPIO-E configuration requires also setting bits 1,2, and 3 in the digital-function
register.
With this done, you can turn the red-color LED on and off by setting and clearing bit
1, in the GPIO-F data register.
Actually, if you want to really blink the LED, you can't turn it on and off just once,
but you need to keep doing this forever. To do this, you can wrap a while loop around
the code for turning the LED on and off. The constant 1 in place of the condition means
that the condition is always true, so the loop runs forever.
When you compile this code, you get a warning that the return statement downstream from
the endless while is unreachable, which is true.
Let's test this code on the Launchpad board.
Note that setting the clock-gating register wakes up the GPIO-F block, as expected.
Here you see that the red LED lights up
And now it goes dark again
The endless loop also seems to be working
Well, if everything looks so good, let's run the code at full speed by pressing the Go
button.
What the heck, the LED stays on all the time.
Let's break into the code by pressing the Break button and single-step again.
This time everything is fine, yet when you run at full speed the blinking stops?
Do you know what's the problem here?
Yes, you are right, the program just runs too fast fast for a human eye to notice the
rapid blinking of the LED. We need to slow the program down.
For this, you can use the counting while-loop that you learned in lesson-2. A loop like
this wastes a lot of CPU cycles, but the delay can be controlled by setting the upper limit
in the condition of the while.
Note that you need a delay both after turning the LED on and after turning it off again.
OK, so let's give it a try.
This concludes the lesson about blinking an LED. Even though it might not seem like much,
this is a very significant milestone in your embedded career. So congratulations!
In the next lesson you will learn how to improve the blinky program by using the C preprocessor
and the volatile keyword.
If you like this channel, please subscribe to stay tuned. You can also visit state-machine.com/quickstart
for the class notes and project file downloads.