Appendix B: Running Keil Tools
Appendix B: Running Keil Tools
B.1 INTRODUCTION
The RealView Microcontroller Development Kit that is available from http://www.
keil.com/demo simulates not only an ARM microprocessor but a complete micro-
controller. A wide variety of microcontrollers are available in the tools, and their
peripherals can be driven with inputs to exercise I/O pins, A/D converters, UARTs,
etc. For the purpose of simulating the microcontrollers described in each chapter,
we’ll need a way to write assembly code without having to read one hundred pages
of manuals, so here’s where we bend the rules a bit. While Keil does not formally
support building projects in assembly only, it can be done quite easily and the tools
provide a nice development environment in which to build your code. There is, how-
ever, a rather heretical approach taken when using the RVMDK tools to write only
assembly. For starters, code begins at address 0x00000000 on the ARM7TDMI,
which is where the exception vector table normally sits, so we can put code there
as long as we don’t require exception handling. Second, the tools normally expect a
default reset handler to be in place, and we don’t really want to use that. We therefore
create our program in such a way that the tools believe it to be the reset handler.
Writing code for the Cortex-M4 works the same way—we will be leaving out excep-
tion handlers and assembly code normally created when compiling C code. To run
a simple program, you first need to specify a particular device to simulate. You then
create a project, write your code, and add it to your project. Finally, you build the
project and start up the debugger to step through your code. NB: This appendix uses
Version 4.73, so if you are using Version 5.0 or above, be sure to download the soft-
ware pack that supports the legacy ARM7 and ARM9 microcontrollers.
399
400 Appendix B
that you can save (see the µVision IDE User’s Guide included with the software for
all the different options available). You might wish to create a new folder for each
project, just to keep things simple.
At this point the tools will ask you to specify a device to simulate. To continue our
example, choose one of the LPC21xx parts from NXP, such as the LPC2104. This
is an ARM7-based microcontroller with a few peripherals. You will find all of the
available parts in the device database window shown in Figure B.3. Scroll down until
you come to the NXP parts and select LPC2104. Notice that the tools detail all of the
peripherals and memory options when you choose the device. When you click OK,
a dialog box will appear asking if you want to include startup code for this device.
Click No, since we are only making a small assembly program and will not need all
of the initialization code.
example. The latest versions of RVMDK now require a reset handler to be found,
and normally this is included in the startup file. However, we have elected not to
use this file, so the workaround is to mark your assembly code as the reset handler
and declare it globally. Notice the first line of code is the GLOBAL directive. You
should also call the block of code reset (or Reset—it is case insensitive) with the
AREA directive. After the ENTRY directive, the label Reset _ Handler should
be placed at the top of your code. You can follow this with another label if you like,
say Main or MyCode, but just be sure to include the first label. The remaining code
would appear as examples do in the book. Choose Save As from the File menu, and
give it a name, such as My First Program.s, being sure to include the “.s” extension
on the file. The window should change, showing legal instructions in boldface type,
and comments and constants in different colors.
The assembly file must be added to the project. In the Project Workspace win-
dow on the left, click on the plus sign to expand the Target 1 folder. Right click on
the Source Group 1 folder, then choose Add Files to Group “Source Group 1” as
402 Appendix B
shown in Figure B.5. A dialog box will appear. In the dropdown menu called Files of
Type, choose Asm Source file to show all of the assembly files in your folder. Select
the file you just created and saved. Click Add, and then Close.
This puts you into a debug session (shown in Figure B.6) and produces new win-
dows, including the Register window and the Memory window. You can single-step
through the code, watching each instruction execute by clicking on the Step Into
button on the toolbar or choosing Step from the Debug menu. At this point, you can
also view and change the contents of the register file, and view and change memory
locations by typing in the address of interest. When you are finished, choose Start/
Stop Debug Session again from the Debug menu. Once you’ve completed a simple
example, go back and read the µVision IDE User’s Guide, which is available in the
Help menu. Many integrated development environments are similar, so if you have
already used one from a different vendor, you may find this one very familiar.
microcontroller with a number of peripherals. You will find all of the available parts
in the device database window shown in Figure B.9. Scroll down until you come to
the TI parts and select LM4F120H5QR. Notice that the tools detail all of the periph-
erals and memory options when you choose the device. When you click OK, a dialog
box will appear asking if you want to include startup code for this device. Click Yes,
since we can make a running example quickly using the initialization code.
will need to delete the code between the labels Reset_Handler and NmiSR. Add your
code after the label Reset_Handler, adding an ENTRY directive so that the code
looks like that in Figure B.10.
Comment out the code in the section for handling stack and heap memory loca-
tions, since we won’t immediately need any of this. Simply add a semicolon to the
beginning of each line, so that the code looks like:
;*************************************************************
;
; The function expected of the C library startup code for
; defining the stack and heap memory locations. For the C
; library version of the startup code, provide this function
; so that the C library initialization code can find out
; the location of the stack and heap.
;
;*************************************************************
; IF :DEF: __MICROLIB
; EXPORT __initial_sp
; EXPORT __heap_base
; EXPORT __heap_limit
; ELSE
; IMPORT __use_two_region_memory
; EXPORT __user_initial_stackheap
;__user_initial_stackheap
; LDR R0, =HeapMem
; LDR R1, =(StackMem + Stack)
; LDR R2, =(HeapMem + Heap)
; LDR R3, =StackMem
; BX LR
; ENDIF
406 Appendix B