Keil uVision5
Experiments 1 and 2 are pure ARM assembly. They run in Keil's built-in simulator on a generic ARM Cortex-M4 (ARMCM4), so you need no board. This guide installs Keil, builds a project from an empty folder, runs a tiny program, and shows you the debugger windows you will use in every lab. The lab PCs already have Keil installed.
Windows only
Keil uVision5 runs on Windows. On a Mac, use a Windows virtual machine (Parallels, UTM or VMware Fusion) or a lab PC.
The whole thing in 30 seconds (once you've done it before)
- Project → New µVision Project… → new folder → name it → Save.
- Device: ARM → ARM Cortex M4 → ARMCM4 → OK.
- Run-Time Environment: tick nothing → OK.
- Right-click Source Group 1 → Add New Item… → Asm File (.s) →
main.s. - Alt+F7: Target → default compiler version 6; Asm → armasm (Arm Syntax); Debug → Use Simulator, untick Run to main().
- F7 to build, Ctrl+F5 to debug, F11 to step.
Step 1: Install Keil MDK
- Download MDK from keil.arm.com. The free Community or evaluation edition is enough: its 32 KB code limit is far more than any program in this lab.
- Run the installer as administrator and accept the defaults.
- When it finishes, the Pack Installer opens and updates its index. Wait until the status bar says ONLINE.
- The ARMCM4 device comes from the ARM::Cortex_DFP pack, which MDK normally installs for you. If it is not listed under Packs, search for
ARMCM4and click Install.
Step 2: Make a folder for the project
Keil creates several files per project, so give each experiment its own folder. For example:
C:\ENCS5101\Exp1Keep the path simple
Avoid spaces, Arabic letters and OneDrive-synced folders (such as Desktop or Documents when OneDrive is on). Long or unusual paths are the most common cause of strange build errors. C:\ENCS5101\... is safe.
Step 3: Create the project
- Open Keil uVision5.
- If a previous project opens automatically, close it with Project → Close Project.
- Click Project → New µVision Project….
- Browse to your folder (
C:\ENCS5101\Exp1), type a name such asexp1and click Save.
uVision5 with no project open and the Project menu dropped down, "New µVision Project..." highlighted.
public/screenshots/keil/01-new-project-menu.pngThe "Create New Project" save dialog, inside C:\ENCS5101\Exp1, with "exp1" in the File name box.
public/screenshots/keil/02-save-project.pngStep 4: Choose the ARMCM4 device
The Select Device for Target window opens right after you save.
- Make sure the drop-down at the top-left says Software Packs.
- Expand ARM → ARM Cortex M4 and select ARMCM4.
- Click OK.
"Select Device for Target 'Target 1'..." window with the tree expanded to ARM → ARM Cortex M4 → ARMCM4 and ARMCM4 selected. The description pane on the right should mention the Cortex-M4.
public/screenshots/keil/03-select-armcm4.pngARMCM4 vs. ARMCM4_FP
Either works for these experiments. ARMCM4_FP also has the floating-point unit, which experiments 1 and 2 do not use. Pick plain ARMCM4.
I don't see "ARM Cortex M4" in the list
The ARM::Cortex_DFP pack is missing. Click Cancel, open Project → Manage → Pack Installer…, search for ARMCM4, click Install next to ARM::Cortex_DFP, then go back to Project → Options for Target → Device to choose it.
Step 5: Skip the Run-Time Environment
Next, the Manage Run-Time Environment window opens. It offers ready-made software such as a startup file.
Leave every box unticked and click OK.
The "Manage Run-Time Environment" window with CMSIS and Device collapsed and nothing ticked. Highlight the OK button.
public/screenshots/keil/04-rte-empty.pngWhy nothing?
In experiments 1 and 2 your own program provides the vector table (the RESET area with __Vectors and Reset_Handler). If you also tick Device → Startup, Keil adds a second vector table and the build fails with Symbol __Vectors multiply defined. You can reopen this window at any time from Project → Manage → Run-Time Environment….
Step 6: Add an assembly source file
The Project panel on the left now shows Target 1 → Source Group 1, empty.
- Right-click Source Group 1 → Add New Item to Group 'Source Group 1'….
- Choose Asm File (.s).
- Name it
main.sand click Add.
Project panel with Target 1 expanded, right-click menu open on "Source Group 1", "Add New Item to Group 'Source Group 1'..." highlighted.
public/screenshots/keil/05-add-new-item-menu.png"Add New Item to Group" dialog with "Asm File (.s)" selected and "main.s" in the Name box.
public/screenshots/keil/06-add-asm-file.pngmain.s opens in the editor. Paste this test program and press Ctrl+S:
AREA RESET, CODE, READONLY
EXPORT __Vectors
__Vectors
DCD 0x20001000 ; Initial stack pointer
DCD Reset_Handler ; Reset vector: execution starts here
AREA MYCODE, CODE, READONLY
ENTRY
EXPORT Reset_Handler
Reset_Handler
MOV R0, #5 ; R0 = 5
MOV R1, #7 ; R1 = 7
ADDS R2, R0, R1 ; R2 = R0 + R1 = 12, and update the flags
SUBS R3, R0, R0 ; R3 = 0, so the Z flag becomes 1
STOP B STOP ; Loop here forever
ENDEvery program in experiments 1 and 2 has this same shape:
| Part | What it does |
|---|---|
AREA RESET | The vector table. The first word is the initial stack pointer; the second is the address of the first instruction to run. |
AREA MYCODE + ENTRY | Your code. Reset_Handler is where the processor starts after reset. |
STOP B STOP | An infinite loop. There is no operating system to "return" to, so a program must never run off the end. |
END | Tells the assembler the file is finished. Anything after it is ignored. |
Indentation matters
In Keil assembly, labels (__Vectors, Reset_Handler, STOP) start in the first column. Instructions and directives (AREA, MOV, DCD…) must be indented by at least one space or tab. An unindented MOV is read as a label and causes errors.
Step 7: Set the project options
Open Project → Options for Target 'Target 1'… (Alt+F7, or the magic-wand icon in the toolbar). You only need to touch three tabs.
Target tab
Check that ARM Compiler says Use default compiler version 6. Leave the memory areas as they are (IROM1 at 0x0, IRAM1 at 0x20000000).
Options for Target 'Target 1', Target tab. Highlight "ARM Compiler: Use default compiler version 6" and the IROM1/IRAM1 rows.
public/screenshots/keil/07-options-target.pngAsm tab
Set Assembler Option to armasm (Arm Syntax). The lab code uses Arm syntax (AREA, DCD, END); the other choices expect GNU syntax and reject it.
Options for Target, Asm tab, with the "Assembler Option" drop-down set to "armasm (Arm Syntax)". Highlight the drop-down.
public/screenshots/keil/08-options-asm.pngDebug tab
- On the left half, select Use Simulator.
- Untick Run to main(). There is no
mainin an assembly program. - Click OK.
Options for Target, Debug tab, with "Use Simulator" selected on the left and "Run to main()" unticked. Highlight both.
public/screenshots/keil/09-options-debug-simulator.pngStep 8: Build
Click Project → Build Target (F7, or the icon with a downward arrow into a box). Watch the Build Output panel at the bottom. A good build ends with:
".\Objects\exp1.axf" - 0 Error(s), 0 Warning(s).uVision with main.s open and the Build Output panel at the bottom showing a successful build ending in "0 Error(s), 0 Warning(s)". Highlight the Build toolbar button and the final line.
public/screenshots/keil/10-build-output.pngIf there are errors, double-click the first error line in Build Output: Keil jumps to the line that caused it. Always fix the first error first; later ones are often caused by it. See Troubleshooting for the usual suspects.
Step 9: Run it in the debugger
Start the debugger with Debug → Start/Stop Debug Session (Ctrl+F5, or the magnifier-over-a-chip icon). Click OK on the EVALUATION MODE notice if it appears.
The layout changes. The yellow arrow in the editor marks the next instruction to run: the first MOV in Reset_Handler.
The full uVision window in a debug session, labelled: Registers window (left), Disassembly (top), editor with the yellow arrow on the first MOV, Command window (bottom left), and the debug toolbar (Reset, Run, Stop, Step, Step Over, Step Out).
public/screenshots/keil/11-debug-session-overview.pngStep through the program
Press Step (F11) once per instruction and watch the Registers window. The registers that just changed are highlighted in blue.
- After the first step,
R0=0x00000005. - After the second,
R1=0x00000007. - After
ADDS,R2=0x0000000C(12 in decimal). - After
SUBS,R3=0x00000000. Expand xPSR: the Z flag is now1.
Registers window after stepping past SUBS: R0=5, R1=7, R2=0x0C, R3=0, and xPSR expanded showing the N, Z, C, V bits with Z = 1. Highlight the changed registers.
public/screenshots/keil/12-registers-after-adds.pngThe controls you'll use every lab
| Action | Key | What it does |
|---|---|---|
| Step | F11 | Run one instruction. Enters subroutines (BL). |
| Step Over | F10 | Run one instruction, but treat a BL call as a single step. |
| Step Out | Ctrl+F11 | Run until the current subroutine returns. |
| Run | F5 | Run until a breakpoint (or forever). |
| Stop | toolbar ⏹ | Pause a running program. |
| Reset | toolbar RST | Go back to the start of the program. |
| Breakpoint | F9 | Toggle a breakpoint on the current line. Clicking the grey margin left of a line does the same. |
| Run to cursor | Ctrl+F10 | Run until the line the cursor is on. |
| End debugging | Ctrl+F5 | Leave the debugger and go back to editing. |
Edits need a rebuild
You cannot edit and continue. To change the program: stop debugging (Ctrl+F5), edit, rebuild (F7), and start debugging again.
Look at memory
From Example 2 of Experiment 1 on you load and store data. To see memory:
- View → Memory Windows → Memory 1.
- Type an address in the Address box, such as
0x20000000(start of RAM), and press Enter. - Right-click inside the window to change how values are shown (for example Unsigned → Int to see 32-bit words instead of bytes).
You can also type a label from your program, such as Reset_Handler, in the address box.
The Memory 1 window docked at the bottom with 0x20000000 in the Address box, right-click menu open on Unsigned → Int.
public/screenshots/keil/13-memory-window.pngOther useful views
- View → Disassembly Window: the actual machine instructions, with their addresses and encodings. Useful when the assembler expands a pseudo-instruction such as
LDR R0, =valueorMOV32. - View → Watch Windows → Watch 1: type a register or label name to keep an eye on it.
- In the Registers window, Internal → States counts clock cycles and Sec shows elapsed time.
Step 10: Reuse the project for more examples
Each experiment has several examples, and each one has its own RESET vector table, so only one of them can be in the build at a time. Two good ways to handle this:
- One project per experiment, one file per example. Add each example as its own
.sfile. Right-click every file you are not running → Options for File '…' → untick Include in Target Build. The excluded files show a small red mark in the Project panel. - One project per example. Repeat this guide in a new folder. Slower, but impossible to mix up.
The "Options for File 'example2.s'" dialog with "Include in Target Build" unticked, and the Project panel behind it showing two .s files, one marked as excluded.
public/screenshots/keil/14-exclude-from-build.pngWhat's in the project folder
| File/folder | What it is |
|---|---|
exp1.uvprojx | The project. Double-click this to reopen the project later. |
exp1.uvoptx | Your window layout and debug settings. |
main.s | Your source code. |
Objects\, Listings\ | Build output. Safe to delete; Keil recreates them on the next build. |
To hand in a project, zip the whole folder. Delete Objects\ first to keep it small.
Troubleshooting
| Message or symptom | Cause and fix |
|---|---|
Symbol __Vectors multiply defined | Either Device → Startup is ticked in the Run-Time Environment (Step 5), or two example files are both in the build (Step 10). |
error: unknown directive / unexpected token on AREA | The assembler is set to GNU syntax. Set Asm → Assembler Option to armasm (Arm Syntax) (Step 6). |
A1163E: Unknown opcode on a line that looks fine | The instruction isn't indented, so it was read as a label. Indent it. |
A1167E: Invalid line start | A label is indented, or there is a stray character in the first column. Labels go in column one. |
L6236E: No section matches selector - no section to be FIRST/LAST | The vector table is missing. Check your file starts with AREA RESET and that the file is in the build. |
*** error 65: access violation at 0x40... while running | The program touched a peripheral address (0x400xxxxx). The generic ARMCM4 simulator has no peripherals, so only use RAM (0x20000000 up) and your own code. |
| The file has no syntax colouring and isn't built | It was saved without the .s extension. Remove it from the project, rename it to main.s, and add it back with Add Existing Files to Group…. |
| Nothing happens when you press Step | You're not in a debug session. Press Ctrl+F5 first. |