Файл: ARM cross development with Eclipse, version 2 (J.P. Lynch, 2005).pdf
ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 12.06.2025
Просмотров: 684
Скачиваний: 1
Click on “Next” to accept c:/cygwin/usr/local/bin as the OCDRemote installation directory.
Clicking on “Install” will complete the OCDRemote installation.
The Wizard completion screen lets you restart your computer to put OCDRemote into the Windows registry.
Just like the Philips ISP Flash Utility, we should install the Macraigor OCDremote utility as an “external tool” that can be accessed easily from the Eclipse CDT RUN pull-down menu.
Start up Eclipse and, if necessary, switch to the C/C++ perspective by clicking “Window – Open Perspective – Other – C/C++.”
Switching perspectives brings up the C/C++ window (perspective) and this will be remembered when you re-enter Eclipse.
In a procedure similar to installing the Philips Flash Utility as an “External Tool”, click on “Run – External Tools – External Tools …” This will bring up the External Tools dialog.
Click on “New” and replace the name with OCDremote. Use the “browse file system” to find it. It should be in the directory c:/cygwin/usr/local/bin.
The arguments needed to properly start the OCDremote are as follows:
-cARM7TDMI-S |
specifies the CPU being accessed |
-p8888 |
specifies the pseudo TCP-IP port being used |
-dWIGGLER |
specifies the JTAG hardware being used |
-a1 |
specifies LPT1 for the Wiggler |
-s7 |
specifies next-to-slowest speed |
It’s a good idea to not tamper with these values. Click on “Apply” to finish the setup.
Just like the Philips LPC2000 Flash Utility, we’d like to include the OCDremote application in our list of “favorite” External Tools. This allows us to quickly start the OCDremote JTAG server from within Eclipse.
Click on “Run – External Tools – Organize Favorites”
Now click on “Add…” in the Organize External Tools … window and follow that by checking “OCDremote” in the Add External Tools Configurations: window. Click on “OK” to add the OCDremote to the list of favorites.
Now verify that the OCDremote is in the list of External Tools favorites. Click on “Run – External Tools” and see that it’s now included in the list of favorites.
Now is a good time to point out that there’s a handy shortcut button in Eclipse to run the External Tools. Click on the External Tools button’s down arrow to expand the list of available tools.
Click on either of the external tools to start them running.
10 Verifying the PATH Settings
There is one final and very crucial step to make before we complete our tool building. We have to ensure that the Windows PATH environment variable has entries for the Cygwin toolset, the GNUARM toolset and the OCDremote JTAG server.
These are the three paths that must be present in the Windows environment:
c:\cygwin\bin
c:\program files\gnuarm\bin c:\cygwin\usr\local\bin
To verify that these paths are present in Windows and to make changes if required, start the Windows Control Panel by clicking “Start – Control Panel”.
Now click on the “Advanced” tab below.
Now click on the “Environment Variables” button.
In the Environment Variables window, find the line for “Path” in the System Variables box on the bottom, click to select and highlight it and then click on “Edit”.
Take a very careful look at the “Edit System Variable” window (the Path Edit, in this case).
You should see the following paths specified, all separated by semicolons. The path is usually long and complex; you may find the bits and pieces for GNUARM interspersed throughout the path specification. I used cut and paste to place all my path specifications at the beginning of the specification (line); this is not really necessary.
You should see the following paths specified.
c:\cygwin\bin;c:\program files\gnuarm\bin;c:\cygwin\usr\local\bin
If any of the three is not present, now is the time to type them into the path specification.
I’ve found that not properly setting up the Path specification is the most common mistake made in configuring Eclipse to do cross-development.
This completes the setup of Eclipse and all the ancillary tools required to cross develop embedded software for the ARM microcomputer family (Philips LPC2000 family in specific).
If you stayed with me this far, your patience will soon be rewarded!
Or as Yoda would say, “Rewarded soon, your patience will be!”
11 Creating a Simple Eclipse Project
At this point, we have a fully-functioning Eclipse IDE capable of building C/C++ programs for the ARM microprocessor (specifically for the Olimex LPC-P2106 prototype board).
We will now create an Eclipse C project called “demo2106_blink_flash” that will blink the board’s red LED_J which is I/O port P0.7. This demo uses no interrupts and runs totally out of onboard flash memory. It has been intentionally designed to be as simple and as straightforward as possible.
Click on our Eclipse desktop icon to start Eclipse.
Eclipse should start and present the C/C++ perspective as shown below. If not, select “Window - Open Perspective – Other - C/C++” to change to the C++ perspective.
To create a project, select File – New – New Project - Standard Make C Project from the File pull-down menu and click “Next” to continue.
You should see the “New Project” dialog box and enter the project name (demo2106_blink_flash) in the box as shown below. Click on Next to continue.
The New Project dialog box appears next. If you click on the “Make Builder” tab, you’ll notice that Eclipse build command is “make.” Make is provided by the Cygwin GNU tools.
Take the default on the “Build Command”, Eclipse will always issue a “make” command to build your project.
These are the targets that “make” will run when you hit the Build All, Build Project or Clean toolbar buttons.
Let’s remind ourselves that we installed the Cygwin GNU tools earlier in the tutorial and the Windows Explorer will show that the make.exe file is indeed in the directory c:/cygwin/bin, as shown below.
This is a good time to point out the differences between “Build All”, “Build Project” and “Clean.”
Build All |
Will execute the command “make clean all.” |
It will first clean (delete) all object, list and output files. |
|
Then it will rebuild everything, whether needed or not. |
|
Build Project |
Will execute the command “make all.” |
This will not clean (delete) anything. |
|
It will only compile those source files that are “out-of-date.” |
|
Clean |
Will execute the command “make clean.” |
Will clean (delete) all object, list and output files. |
This is no different from opening up a DOS command window and typing the command in directly, such as.
> make clean all
If you click “Finish” on the “New Project” dialog, Eclipse will return to the C/C++ Perspective.
Now the C/C++ perspective shows a bona fide project in the “C/C++ projects” box on the left. As of now, there are no source files created.
We can now use Eclipse/CDT’s import feature to copy the source files into the project.
Assuming that you successfully unzipped the “demo2106_blink_flash.zip” project files associated with this tutorial to an empty directory such as c:/scratch, you should have the following source and make files in that directory.
Click on the “File” pull-down menu and then click on “Import.” Then in the “Import” window, click on “File System.”
When the “Import – File System” window appears, click on the “Browse” button. Hunt for the sample project which is stored in the c:/scratch/ directory.
Click on the directory “scratch” and hit the “OK” button in the “Import from directory” window on the left below.
Click on “Select All” in the Import window below right to get the source files selected for import into our project.
Now we have to indicate the destination for our source files. Click on “Browse” on the line to the right that says “Into Folder:”
The proper destination folder appears in the Import Into Folder window below.
Click on the folder name “demo2106_blink_flash” and click “OK.” The directory name “demo2106_blink_flash” should appear in the text box.
Now the Import dialog is completely filled out; we can click on “finish” to actually import the source files into our project.
Now the C/C++ perspective main screen will reappear. Click on the “+” expand symbol in the navigator pane to see if our files have been transferred.
Success is at hand, the expanded Projects view in the Navigator pane on the left shows our imported files.
This is a good place to identify the imported source files.
Description of Project Files
lpc210x.h |
Standard LPC2106 header file |
crt.s |
Startup assembler file |
main.c |
Main C program |
makefile |
GNU makefile |
demo2106_blink_flash.cmd |
GNU Linker script file |
12 Description of the LPC210X.H Include File
Let’s look at the lpc210x.h header file. Double-click on it in the Project pane on the left’
ARM peripherals are memory-mapped, so all I/O registers are defined in this file so you don’t have to type in the absolute memory addresses.
13 Description of the Startup File CRT.S
Now let’s look on the startup assembler file, crt.s. Double-click on it.
This part of the crt.s file has some symbols set to the various stack sizes and mode bits.
This part of the crt.s file sets up the interrupt vectors.
Note that all of the code and data that follows goes into the .text section. It is also in ARM 32-bit code (not Thumb).
One label is made global, _startup. This will be available to other modules in the project and will also appear in the map.
The GNU assembler doesn’t require you .extern anything. If a symbol is not defined in the assembler file, it is automatically assumed to be external.
The vector table is 32 bytes long and is required to be placed at address 0x000000.
You will see later in this tutorial that the interrupt service routines referenced in the
Vector Table are just endless-loop stubs in the main.c function and the interrupts are turned off.
The NOP instruction at address 14 is an empty spot to hold the checksum. Page 179 of the Philips LPC2106 manual states:
The reserved ARM interrupt vector location (0x0000 0014) should contain the 2’s complement of the check-sum of the remaining interrupt vectors. This causes the checksum of all of the vectors together to be 0.
Before you fall on your sword, you’ll be happy to know that the Philips Flash Loader will calculate that checksum and insert it for you. That’s why we show it as a NOP.
This part of the crt.s file sets up the various interrupt modes and stacks.
The label Reset_Handler is the beginning of the code. Recall that the first interrupt vector at address 0x000000 loads the PC with the contents of the address Reset_Addr, which contains the address of the startup code at the label Reset_Handler. This trick, used in the entire vector table, loads a 32-bit constant into the PC and thus can jump to any address in memory space.
_vectors: |
ldr PC, Reset_Addr |
: |
|
Reset_Addr: |
.word Reset_Handler |
Whenever the LPC2106 is reset, the instruction at 0x000000 is executed first; it jumps to Reset_Handler. From that point, we are off and running!
The first part of the startup code above sets up the stacks and the mode bits.
The symbol _stack_end will be defined in the linker command script file demo2106.cmd. Here is how it will be defined. Knowing that the Philips ISP Flash
Loader will use the very top 288 bytes of RAM for its internal stack and variables, we’ll start our application stacks at 0x4000FEE0.
(Note: 0x40010000 – 0x120 = 0x4000FEE0)
/* define a global symbol _stack_end, placed at the very end of RAM (minus 4 bytes) */ stack_end = 0x4000FEE0 – 4;
Working that out with the Windows calculator, the _stack_end is placed at 4000FEDC.
The code snippet that sets up the stacks and modes is a bit complex, so let’s explain it a bit.
First we load R0 with the address of the end of the stack, as described above.
ldr r0, =_stack_end
Now we put the ARM into Undefined Instruction mode by setting the MODE_UND bit in the Current Program Status Register (CPSR). The four modes undefined, irq, abort and svc all have their own private copies of R13 (sp) and r14 (link return). The FIQ mode has private copies of registers R8 – R14. Thus, by writing R0 into the stack pointer sp
(R13), it will use 0x4000FEDC as the initial stack pointer if we ever have processing of an undefined instruction. By subtracting the undefined stack size (4 bytes) from R0, we’re limiting the stack for UND mode to just 4 bytes.
msr |
CPSR_c, #MODE_UND|I_BIT|F_BIT |
/* This puts the CPU in undefined mode */ |
mov |
sp, r0 |
/* stack pointer for UND mode is 0x40000FEDC */ |
sub |
r0, r0, #UND_STACK_SIZE |
/* Register R0 is now 0x4000FED8 */ |
Now we put the ARM into Abort mode by setting the MODE_ABT bit in the CPSR. As mentioned above, abort mode has its own private copies of R13 and R14. We now set the abort mode stack pointer to 0x4000FED8. Again by subtracting the abort stack size from R0, we’re limiting the stack for ABT mode to just 4 bytes.
msr |
CPSR_c, #MODE_ABT|I_BIT|F_BIT |
/* this puts CPU in Abort mode */ |
mov |
sp, r0 |
/* stack pointer for ABT mode is 0x4000FED8 */ |
sub |
r0, r0, #ABT_STACK_SIZE |
/* Register R0 is now 0x4000FED4 */ |
Now we put the ARM into FIQ (fast interrupt) mode by setting the MODE_FIQ bit in the CPSR. As mentioned above, FIQ mode has its own private copies of R14 through R8. We now set the abort mode stack pointer to 0x4000FED4. Again by subtracting the abort stack size from R0, we’re limiting the stack for FIQ mode to just 4 bytes. We’re not planning to support FIQ interrupts in this example.
msr |
CPSR_c, #MODE_FIQ|I_BIT|F_BIT |
/* this puts CPU in FIQ mode */ |
mov |
sp, r0 |
/* stack pointer for FIQ mode is 0x4000FED4 |
sub |
r0, r0, #FIQ_STACK_SIZE |
/* Register R0 is now 0x4000FED0 */ |
Now we put the ARM into IRQ (normal interrupt) mode by setting the MODE_IRQ bit in the CPSR. As mentioned above, IRQ mode has its own private copies of R13 and R14. We now set the IRQ mode stack pointer to 0x4000FDE0. Again by subtracting the IRQ stack size from R0, we’re limiting the stack for IRQ mode to just 4 bytes. We’re not planning to support IRQ interrupts in this example.
msr |
CPSR_c, #MODE_IRQ|I_BIT|F_BIT |
/* this puts the CPU in IRQ mode */ |
mov |
sp, r0 |
/* stack pointer for IRQ mode is 0x4000FED0 */ |
sub |
r0, r0, #IRQ_STACK_SIZE |
/* R0 is now 0x4000FECC */ |