CodeWarrior simulator demo The code can be written in C language (higher level) as well as in Assembly language (lower level). General C commands are applied across microcontroller families as opposed to assembly commands, which are family specific. Assembly commands may vary within a microcontroller family as well depending upon the functionality being provided by that microcontroller. To see the code written in C, double-click on demo.mcp or open it with CodeWarrior. From the Folder tree on the left double click on main.c which can be found under the Sources folder. The following code should be displayed: /********************************************/ /* The following code demonstrates the use of the */ /* pushbuttons located on Port AD bits 0 & 1. */ /* Pressing the Bit 1 button will increase the counter */ /* number by one. Pressing the Bit 0 button will */ /* decrease the counter by one. Then the counter */ /* number will be displayed by a 7-segment display */ /* */ /* Code writen by : Min kyu Song */ /* Oct 2005 */ /********************************************/ #include <hidef.h> /* common defines and macros */ #include <mc9s12c32.h> /* derivative information */ #include "main_asm.h" /* interface to the assembly module */ #pragma LINK_INFO DERIVATIVE "mc9s12c32" void Delay(int j) {.. } //Base Delay /** Display integer number on a 7-segment display **/ /** Port T is used as the output ports for this.*/ void segment_display( int i) {.. } void main(void) { int counter = 0; ATDDIEN = 0x03; //Set Pin0 & Pin1 as Digital 1
.. } DDRAD = 0xFC; DDRT = 0xFF; //Set Pin0 & Pin1 as Input //Set PORTT as Output For the Assembly program, open assembly_demo.mcp using CodeWarrior. The folder tree on the left contains three important files, starting with the Readme file where details about the project are summarized or important directions are given for the reader. The file containing the code is called main.asm (under Sources), and is appropriately indented and commented to show the program organization, so it is easier to understand. ; DIRECTIVES XDEF Entry ABSENTRY Entry INCLUDE 'mc9s12c32.inc' ROMStart EQU $4000 ORG ROMStart ; Export symbols, program execution begins at the label 'Entry' ; I/O Device Mapping ; Absolute address to place code/constant data ; Set start of program in ROM ; INITIALIZATION PORTION Entry: ; Program execution begins at label Entry clrb ; Sets Register B contents as 0 ldaa #$FF staa DDRT ; Sets Port T for Outputs to the 7 segment ldaa #$01 staa DDRS ; Sets bit 0 of Port S as an Output ldaa #$01 ; to select the 7 segment display The part of the code shown above demonstrates good program organization and indentation, as opposed to haphazard code. Main: ldaa PTAD cmpa #$01 beq Subrout bra Main ; Inputs from Port AD (push button) ; Checks if the push button has been pressed ; If it has been pressed, branches to Subrout ; to output the digit at Port T ; If not pressed, goes back and checks again, ; keeps repeating until pressed. Through comments, it is important to show why something is being done besides stating what is being done, for understandability and reusability of code. 2
The third important file in the folder tree is the mc9s12c32.inc file (under Libraries), which has the I/O map for the microcontroller. This is an essential file for program development as it gives a quick reference to the addresses where the ports have been mapped (it can be searched using the ctrl + F shortcut). To enter the debugging mode and run the simulator you can simply hit F5 or select Debug from the Project menu on top. This should open a new window that looks like this: Here you can see 8 windows Source, Procedure, Data:1, Data:2, Assembly, Register, Memory and Command. A detailed explanation of each window is given below. Source Here you can see the C code that currently is loaded into the simulator. The current line of code that it is executed is highlighted Procedure This shows the current procedure the simulator is executing. 3
Data:1,2 Data segment where you can select which variables to show. The scope of each window can be changed to Global, Local and User. Assembly Here you can see the assembly version of the C code and the address of each assembly instruction. The current assembly instruction that is executed is highlighted. Register Shows the contents of the CPU registers, indexes, program counter, stack pointer and condition register. Memory Here you can find all the memory locations within the microprocessor (Ram & Flash). Command Shows the status of the debugger and simulator and also commands can be typed here. Type Help in that window for more information. On the top you will notice the following controls Start/Continue simulation Step Out Of Stop Execution Single C step Assembly Step Reset Target Step Over 4
With these controls you can run the debugger and simulator step by step to see if everything is working correctly. Also at the bottom you can see the following information Internal bus frequency Selected microcontroller Current execution time Debugger/Simulator Status By left-clicking on the internal bus frequency a window will pop up from which you can change the oscillator frequency, display execution time in milliseconds or CPU cycles. Clicking on the Current execution time will reset it. This can be useful when we want to measure the time or clock cycles it takes to execute a part or all of the code. Running the simulator/debugger To begin click on the single step. You will see that the source window will change and display the initialization code for the microprocessor. Continue clicking on single step until you return to your code. Once you can see your code you will notice that the DATA:1 window will have the following You can expand these variables by clicking on the + next to each. Above you can see the contents of PTT (i.e Port T). The line of code that will be executed in our example will be 5
DDRT = 0xFF; By performing a single step you will be able to see that DDRT will now get the value of 0xFF. Remember to expand DDRT in the Data:1 window to see this. The next instruction executed is PTT = 0xFF; Again you can see that this command is executed correctly by looking at the contents of PTT. On the following step the Delay() subroutine is called. The delay creates a loop that is repeated 30000 times, of course this will take too long to end so by clicking Step Out Of the simulator will exit the loop and wait for the next step. This can be useful when we want to check whether there isn t an unintentional infinite loop in our code. Repeating the above procedure the normal operation of the rest of the code can be verified and in case of any errors these can be corrected. Using breakpoints Breakpoints can be useful when we want to execute up to a certain instruction and halt the execution of the code. To set a breakpoint simply right-click on the instruction you wish to set the breakpoint and select Set 6
Breakpoint. You will see a red arrow on the instruction which indicates that there is an active breakpoint there. The red arrow can also be seen in the Assembly window. To remove a breakpoint right-click on the red arrow and select Delete Breakpoint. Alternatively you can disable temporarily the breakpoint and enable it at a later time by right clicking on the arrow and selecting Disable Breakpoint Set the breakpoint at the second call of the Delay() subroutine, Reset the simulator by clicking on the Reset button and then click on the Start/continue button. You will notice that the code execution will halt right on the breakpoint. 7
The same effect as above can be achieved by right clicking on the second Delay() call and selecting Run to Cursor. However breakpoints are more efficient when we need to halt program execution repeatedly. You can have more than one breakpoints at a time. Measuring execution time Unlike assembly it s difficult to measure execution time for C based programs. The simulator has features that allow accurate measurement of execution time for both C and assembly based programs. The execution time can be measured in milliseconds or clock cycles. Assume that we want to know what is the actual delay of the Delay() subroutine. In order to do this we can use breakpoints and the execution time which was described earlier. Set two breakpoints one on the first Delay() call and the other on the instruction following the call. It should look like this: Now click on the Start/continue button and the program execution will halt on the Delay() line. Before continuing we need to reset the execution counter on the bottom of the screen. Double click the counter to reset it. Now by clicking on the Start/continue button again the execution will halt on the next line. The execution counter now shows the time needed to run the Delay() subroutine once. For this example execution time is 180009 cycles or 45.002mS. It was explained previously how to change the execution time to display cycles or ms. Adding Components The CodeWarrior debugging environment allows you to simulate many components like LEDs, pushbuttons, LCD and 7-segment display. In order to insert such components first you need to run the simulator/debugger. From the developing environment simply hit F5 or Project Debug as explained before. The from the Component menu select Open. 8
The following window will pop-up This is a list of the components the demo version of CodeWarrior has to offer. For the example code loaded we can simulate Push Buttons and 7- segment display or LEDs. To insert them select Push_buttons, Segment_display and lo_led component from the list and click OK. The components should now appear in the debugging environment. Before using this component you need to set it up so that it will be connected to the port you want to use. Right-click on the LED component and select Setup. You will get this window 9
Here you have to provide the address for the port in hexadecimal notation and also the address for the Data Direction Register(DDR) for the port you will be using. To find the address for a given port look in the Family Data Sheet (one of the two documents you download in Homework 1) in Table 1-1 PIM (port integration module) and chapter 2 Figure 2.2. The base address for the port integration module is 240 hex. The offset for PORT T data register is 0x0000. Therefore PORT T is at 240 hex. The Data Direction Register (DDR) for PORT T is at offset 0x0002 + base of module which is at 242 hex. Now if you run the example program we used before you will se that the LED will turn ON and OFF. You can save your settings for the current project in debugging mode so you don t have to add the components each time you compile your code. Other settings for Segment_display and Push button are shown below. Push_buttons Segment_display For more information on how to use the other components you can look in the CodeWarrior help file. Updated: 9/14/2006, UU 10