Welcome to the Embedded Systems Programming course. My name is Miro Samek and in this lesson I'm going to show you how computers count. Here and throughout this course I'm going to use the free evaluation version of the IAR toolset that we have downloaded and installed in lesson zero. To create your first project, launch IAR EWARM and select "Project->Create New Project" menu. Expand the C project types, select main, and click OK This opens the file explorer, where you need to choose the directory for your project. I recommend that you create the "embedded_programming" directory on your C: drive for the entire course, within which you will add sub-directories for each lesson. To do this, click on the C: drive and then click on "New folder". Next, double-click on the newly created folder and create a subdirectory "lesson1" for this lesson. Double-click on the lesson1 sub-directory to get inside it, and type the name of the project. For this course, name this project generically "project". Finally, click Save. As you can see, the project contains a generated main.c file, which I will explain in a minute. But first, let's check how the directories and files look on your disk. To finish configuring your project, you need to adjust a few parameters. Click on the "Projects->Options" menu. In the Target tab, you need to adjust the processor variant. Select Device and click on the selection button. Choose Texas Instruments, LM4F family, and LM4F120H5QR device from the list. Next, select the the C/C++ Compiler category. Here you can see that the default language is C and that the C dialect is C99. In this course, I will teach you this newer dialect of C. Finally, click on the Optimizations tab and make sure that the optimization level is set to low, which is the default. A couple of our first programs won't work correctly at higher optimization levels, until I show you how to write code that works even if highly optimized. As you are running the IAR toolset for the first time, you should also spend a minute to tailor it to your preferences. Click on Tools->Options... menu. Here, you can change the fonts, for example I prefer my fixed-width font to be Lucida Console. In the Editor section, increase the indentation to 4 spaces and select spaces instead of tabs. I strongly recommend avoiding tabs in your code, because they are rendered differently on different devices, such as printers. So, finally we can get to the code generated by the IAR toolset. Let's try first to validate that this indeed is a valid C code. You do this by compiling the code, that is running it through a program called the compiler. In the Project menu select the Make option and note that its keyboard shortcut is F7. You will use the F7 shortcut quite frequently. Since it is the first time you bulid this project, the tool asks for the workspace name. Type a generic name "workspace" and hit return. The build completes with zero errors and zero warnings, so congratulations for your first legal C program. Now, let's reformat the generated code to use the "line-saver" bracing placement and indentation of 4 spaces, which I prefer. The compiler doesn't really care about any of this formatting and would accept just as well the code formatted as one long line. But the formatting makes quite a big difference to humans who need to read and maintain the code. But obviously not everything you do to the code is legal C. For example, let's type something illegal and compile again by pressing F7. This time, the compiler reports errors. When you double click on the error report, the toolset brings you right to the offending place in the code, which is rather cool. After removing the problem, it's a good practice to ask the compiler to check you again by pressing F7. I'd like to convince you from the get go that the compiler is your best friend constantly watching over your shoulder. All you need to do is give him a chance to help you by frequently pressing F7. Now, let's define a counter variable, which I will use to show you how computers count. A variable is a location in computer memory to store a value, such as a number. In C, you have to define a variable, before you can use it. You do this by specifying the type of the variable followed by the name and optionally the initial value. According to my own advice, let's check right away if the compiler accepts the variable definition. Well, kind of. The are no errors, but there is one warning that the variable counter has been declared but never referenced. That's true, so let's move on. Now, let's increment the variable counter by one from it's current value. C has a special operator ++ for it, called pre-increment. As usual, I let the compiler check that the code still compiles. As we want to watch how the computer will count, let's increment the counter several more times. Let's compile one last time by pressing F7. Now I will show you how to run this program. First, make sure that the project is configured for the Simulator. Actually, you can tell it by the presence of the Simulator menu at the top, but to double-check, click the Project->Options menu. In the Debugger category, you should see the Simulator selection. You have two options to run the program. Either through the "Project->Download and Debug" menu, or by the toolbar button, which I will use. Now, the IAR toolset has switched to the debugger mode. Let's make sure that the following debugger views are visible: Disassembly, Memory, Register, and Locals. Let's re-arrange the debugger windows so we have the best view inside the simulated ARM Cortex-M4 processor. First, let's take a look inside the Disassembly view. This view shows the machine instructions that the compiler generated from your program. The processor is stopped at the highlighted instruction, which is the beginning of your main function. The machine instructions, as anything else inside a computer are just numbers. The symbols to the right of the instructions are so called instruction mnemonics, and are added by the debugger to improve readability. The column of numbers left to the instructions are the memory addresses of the instructions. Memory addresses are simply numberes assigned to bytes in memory. To convince you that the instructions are really just numbers in memory, let's take a look at the Memory view. You can think of memory as a big table of bytes, which are numbered sequentially starting from zero. These sequential numbers, called the addresses, are shown in the column of numbers along the left edge of the memory view. To better recognize the machine instruction in the memory, let's change the view to 2xUnits, because most of the ARM Cortex instructions occupy 2 bytes in memory. Now, you should easily recognize the instructions. For example, at address 0x40 you see the same number as in the dissassebly view. The same is true for instructions at addresses 0x42 through 0x50. All right, so let's step through the code one C line at a time. To do this click inside the code view and click on the step-into button. As you can see the current instruction advanced by one, and the value of the "counter" variable changed to zero. Also, if you look carefully, the value of the PC register has changed to 0x42. PC stands for "Program Counter", because it counts the instructions and always holds the address of the current instruction. Now, let's click the step-into button again to execute the next instruction. This time, the value of the variable "counter" has incremented to 1. The Locals view tells you also that the "counter" variable is located in the R1 register. Indeed, when you check the register view, you can see that the value of R1 is 1. But what are these registers, anyway? Well, if you ever used a simple calculator you already should have a good idea, because registers in a microprocessors are very similar to the calculator's memory register. Typically, you can add, recall, and clear the memory register of a calculator. The ARM Cortex-M processor has 16 such registers, which are named R0 through R15, whereas R15 is the other name of the PC. All these registers can hold 32-bit numbers. The importance of these registers lies in the fact that machine instructions can manipulate the registers directly, typically in just one clock cycle. You've already seen two examples of instructions manipulating registers: moving a zero to R1, or adding 1 to R1. Let's keep stepping through the code and watch the "counter" variable increment. Everything seems to work as expected, but something interesting happens when the counter reaches 10. As you recall, the counter is located in the R1 register, but at value 10 the Locals and the Register views seem to go out of synch, because R1 shows value A. This requires some explanation. The Locals view shows the value of the Counter in the decimal system, which people adopted because regular people have 10 fingers. However, C programmers grow 16 fingers after a while on the job. Here, for example, is the picture of my hands after programming in C for over 20 years. Programmers find it much more natural to work in the hexadecimal system, because it maps perfectly to the binary system underlying all computers. As you can see in this comparison between decimal, binary, and hexadecimal, a single hexadecimal digit represents a group of 4 bytes, called a "nibble". In contrast, decimal system needs two digits for numbers above 9. The strange looking "0x" prefix in front of every hexadecimal digit is the C-language convention of encoding hex numbers. At the bottom of the picture, you can see an example of applying the table above to encode a string of 32-bits into hexadecimal. The bits are grouped in 4 packs of 8, which are called bytes, each byte contains two 4-bit "nibbles". As I just explained, the nibbles map directly to hex digits. For example, the nibble 1010 maps to the hex digit A, the nibble 0101 to hex digit 5, and so on. In the end, the whole 32-bit binary string is equivalent to 0x260F3E5A. So, now I hope that the debug views make much more sense to you becasue most of them show hex numbers, as you can tell by the 0x prefix. Now, before letting your program increment the "counter", let's cheat a bit to test what happens when the number gets really big. That's actually very easy to do in the debugger, because you can manually change any variable, by clicking on it and typing a new value. Type in 0x7FFFFFFF and press return. This turns out to be a big number in decimal. Now, let your program increment the counter by one. Oops, something very strange happened. You counter becomes a huge negative number in decimal, while it is 0x80 00 00 00 in the R1 register. Again, this requires some explanation. The counter variable has been declared as an integer (int), which in C is a signed number, meaning that it can hold both positive and negative values. It turns out that computers represent negative numbers in a rather peculiar way, called the "2's complement representation". This circular graph explains how it works. Every arrow in the diagram represents increment by one. For small positive numbers, everything works as expected until the number fills all the bits but the most significant one. This is the largest positive value a 32-bit signed number can represent. When you increment this number by one, you overflow to the most significant bit, at which point the number becomes negative. In fact, it becomes the smallest negative number you can represent with 32-bits. From there, when you keep incrementing, the value becomes less negative, until you fill all the bits, at which point you reach -1. When you increment -1, you get zero again and the cycle repeats. So, back to our debug session, let's set the counter value to -1 and watch the content of the R1 register. Next, let your program increment the counter one more time, and close the cycle by making the counter zero again. Exit the debugger by pressing the 'X' button. As a homework I'd like you to study counting of unsigned integers. To do this, you need to modify the type of the counter variable to unsigned int, recompile and start the debugger, just like we did earlier in this lesson. Finally, as the last step of this lesson, I promised to show you how to run the code on the Launchpad board. To do this, you need to modify the project options. Click on Project->Options menu. In the dialog box, choose the Debugger category. From the drop-down list, select the TI-Stellaris option. Next, click on the Download tab and check the Use Flash loader option as well as the Verify download option. Click OK. At this point, you need to connect the Launchpad board to your computer by means of the provided USB cable. If this is the first time you connect the board, allow a minute or two for the installation of the USB driver for the USB debugger. The board is pre-loaded with a demo program that blinks the LED. Now you can download your code to the flash memory of your board and start debugging in the exact same way as you did on the simulator. This is rather cool, when you think about it, and is only possible, because both the USB debugger on the board and the microcontroller itself has a special circuitry to provide this capability for you. Please note that your program stays permanently programmed inside the microcontroller, so it count but it won't blink anymore. Don't despair, though. we will make it blink and much more in the future. This concludes this lesson about counting. In the next lesson I'll show you how to replace the repetitions of instructions with a loop and I'll show you all sorts of ways to change the control flow through your code. Stay tuned and visit state-machine.com/quickstart for the class notes and project file downloads. --- Course web-page: http://www.state-machine.com/quickstart YouTube playlist of the course: http://www.youtube.com/playlist?list=PLPW8O6W-1chwyTzI3BHwBLbGQoPFxPAPM