Subtitles section Play video
Welcome to the Modern Embedded Systems Programming course. My name is Miro Samek and in this
lesson I have decided to finally give in to the popular demand and switch the development
toolset from IAR to the free and unlimited GNU-ARM compiler and the Eclipse-based Integrated
Development Environment.
The switch of the toolset is actually a good opportunity to review the code and to see
what "code portability" means in practice. As you will see, much of the code you've written
so far will work with GNU-ARM without any changes, mostly due to the compliance with
the Cortex Microcontroller Software Interface Standard (CMSIS). However, a few IAR-specific
extensions in the startup code as well as board-support package will have to be replaced
with the GNU compiler equivalents.
So, today let's start with downloading and installing a development toolset for GNU-ARM.
Actually, there are many choices of such toolsets, but you need to look for a toolset that supports
your board. Here, the most important factor is the support for the specific debugger interface,
which in case of the TivaC LaunchPad board is the Stellaris-ICDI.
Since the board comes from Texas Instruments, the logical place to look is the TI.com website,
where indeed you can find the toolset called Code Composer Studio (CCS).
As usual these days, instead of giving you a specific fixed URL for downloading CCS,
which most likely won't work in a few weeks from now, I recommend using the search box.
So, when you search for CCS, you quickly find the right web-page.
In the download section, you can read that the CCS tool can be used for free with no
limits with the GNU-GCC toolset.
Click on the Windows download, which will lead you to the registration page and some
more forms to fill to comply with the export control regulations.
Eventually, however, you should be able to download the CCS setup program for windows.
You need to launch it and agree to the licensing terms.
In the next step you can choose the installation directory. You can leave the default, or choose
your own destination, but I would strongly recommend against using directory names with
spaces or any non-standard characters.
The following step allows you to choose the CCS components. Here you need to expand the
32-bit ARM MCUs and select the Tiva-C Series support. Also, you need to explicitly select
the GCC ARM Compiler.
You don't need to make any more choices, so finally click Finish to start the installation,
which can take a couple of minutes.
When you launch Code Composer Studio, it will ask you for the location of the "workspace".
The concept of a "workspace" is common in all toolsets based on Eclipse and is intended
to group together related projects.
From what I see, most people tend to use one default workspace for everything they do,
but I recommend that you use separate workspaces for your different project groups. Specifically,
I recommend that you use a dedicated workspace for this Embedded Programming Course.
Since I keep all the projects for this course in the directory "embedded_programming", I
also create the CCS workspace there, in the "ccs" subdirectory.
So finally you are ready to create your first project. This part is specific to this particular
re-packaging of Eclipse as Code Composer Studio, but the general process is similar in all
Eclipse based Integrated Development Environments.
The first selection you make for a new project is the embedded target. Here you need to choose
the Tiva-C family and the specific TM4C MCU within the family that is soldered on your
TivaC LaunchPad board.
Next, you choose the connection to the target, which in case of your LanchPad is the Stellaris-ICDI.
Please note that the support for this particular debugger interface was the primary reason
you selected the CCS toolset in the first place.
In the next step, you need to name the project. Here, I suggest a generic name "lesson" for
projects belonging to this Embedded Programming Course. This name will be fitting for all
upcoming lessons, because you will simply clone this original project instead of creating
a new project from scratch each time.
For the same reason, you also cannot create the project in the default location inside
the workspace directory. Instead, you create the project in the directory where you keep
all previous lessons. On my machine this is "embedded_programming", but it can be different
on your computer.
To finish with the project location, you need to add the lesson19 sub-directory for this
particular project
The next and final step is critical. Here, you need to select the GNU toolset instead
of the default TI compiler for ARM.
When you click Finish, CCS will create your "lesson" project in the workspace and in the
"lesson19" directory on disk.
You can build the project by clicking on the hammer button at the top. As you can see,
the build process succeeds with 0 problems.
So, let's take a quick look at the code that CCS has generated for this project.
First, you get the main.c file with the empty main() function.
Second, is the startup code, which is very typical for code supplied by silicon vendors.
Unfortunately, it has all the shortcomings that I've covered in lessons 13, 14, and 15.
For starters, this startup code uses proprietary exception names that are not compliant with
CMSIS.
Also, the vector table requires editing every time you start or stop using a given interrupt
handler. For example, to use the SysTick_Handler interrupt, you would need to modify the appropriate
entry in the vector table, and you would also need to declare a prototype of the handler
at the top of the file.
And finally, the provided implementation of the exception handlers contains endless loops
that tie up the CPU. In other words, if any of such exception handler is ever executed,
the system will freeze, which the user will perceive as denial of service. This is not
acceptable in any production-grade code.
The generated code also contains the file with the extension .lds, which is the linker
script. The purpose of this file is to tell the linker where ROM and RAM are located in
the address space and where to place various program sections. You saw an example of a
linker script for the IAR toolset in lesson 14. Here you have a linker script for the
GNU toolset.
This is again a beaten-path linker script, which matches the startup code.
Among others, it allocates the stack as the last section in RAM. In my opinion this is
a mistake, because stack grows toward the lower addresses on ARM, and so a stack overflow
could damage the RAM sections above it. In fact, this seems the likely cause of failure
in the infamous Toyota unintended acceleration cases, as I have described in the article
"Are we shooting ourselves in the foot with stack overflow?". I provide a link to this
article in the comment section for this video.
So, it seems that the code generated by CCS is not terribly usable, but the good news
is that you can fix all the issues in it by applying the lessons you've learned so far.
The first thing then is to copy all the relevant code from the previous lesson18 to the lesson19
folder. The usable files are: bsp.h, bsp.c, main.c, startup_tm4c.c, and the master header
file for your TM4C MCU.
Interestingly, the files copied to the lesson19 folder immediately show up inside your project.
This is how all Eclipse projects behave. All source files in the project directory are
automatically included in the project and you don't need to explicitly add them as it
was the case in the IAR Embedded Workbench IDE.
This Eclipse policy has its disadvantages too, however.
For example, now you have two startup files in the project, so you need to delete one
of them.
So let's try to build this project.
This time you get some errors.
The first error is that the compiler cannot find the include file "core_cm4.h". This file
is part of the CMSIS, which is not directly available in Code Composer Studio, as it was
in IAR Embedded Workbench.
This is not a big problem, as you can easily provide CMSIS yourself.
Here, I have prepared for you a directory CMSIS, which contains the core header files
in the sub-directory Include.
You should copy the CMIS directory into the folder where you keep the lessons of this
video course. That way you can re-use CMSIS in all upcoming lessons.
Of course copying a directory is not enough, because you also need to tell the compiler
to look for include files in this new directory CMSIS/Include.
You accomplish this by means of the project Properties dialog box, which you open by right-clicking
on the project and selecting the Properties pop-up menu.
Specifically, you need to choose the Directories property in the GNU Compiler group, where
you find the "include paths" pane.
To add a new include directory, click on the plus button.
The first, easy way is to simply browse your file system for the CMSIS/Include directory.
But the big drawback of doing this is that you add an *absolute* include path, which
will only work on your computer with this specific C:\\embedded_programming\\CMSIS directory.
A much better approach is to create a *relative* include path, which will work on any computer.
The Eclipse IDE allows you to create relative paths by means of system variables. Specifically,
in the list of these variables, you can choose PROJECT_LOC, which will create paths relative
to the project location.
From the project location, you need to go one level up, and then you append CMSIS/Include.
Regarding the use of directory separators, on Windows you can use either back-slashes
or forward-slashes. I use forward-slashes, because they seem more universal.
When you build again, you see that the previous include error is gone, but you got a bunch
of new errors.
As it turns out, most of these new errors come from the startup code. This should not
be actually that surprising, because this code was written with IAR-specific extensions
to the C language, which the GNU compiler does not recognize.
So, here I have prepared for you the startup code, which was re-written with the GNU-specific
extensions to the C language.
As you will see in a minute, the startup code must closely match the linker script, so I
included a matching linker script as well.
To include these files in the project is simply copy them over to the lesson19 directory.
I need to allow overwriting the previous linker script and I also need to remove the previous
startup code.
When you switch over to the Eclipse IDE, you can see that the project is immediately updated
with the new files.
Let's quickly review the code, so that you know how it works.
First, in contrast to the old file, the new GNU-specific startup code is compliant with
the latest CMSIS 4.3.0.
When you scroll down to the vector table, you can see that it has a special attribute
section(.isr_vector). This is a GNU-specific extension, which tells the compiler to place
the following symbol--the vector table in this case--in the specified section.
To see where this section is, you can open the new GNU linker script, where you can see
that .isr_vector is the first section in ROM.
The ROM section, in turn, is located at address 0, so the vector table at the beginning of
ROM is also at zero, which is exactly what the ARM CPU needs.
As you hopefully remember from lesson-15, the first element of the ARM vector table
is the initial top of stack. So, here you see an ampersand, meaning address of, __stack_end__
cast on an int.
The symbol __stack_end__ comes again from the linker script. Indeed, when you scroll
a bit down, you can see the .stack section as the first section in RAM.
Contrary to the beaten-path approach of putting the stack at the last section in RAM, I recommend
placing it at the first section. That way, a stack overflow won't be able to damage any