LPC2378 Assembly Demos Here are several very small example assembly language files for the NXP LPC2378 ARM chip. They were developed on the Olimex LPC-P2378 board. It should be easy to convert them to any other development board using the LPC2378 chip. A few more changes might be necessary to run some of them on other chips such as the LPC2106. The first several examples blink the status LED. If you are using a different board, you should change the code related to the output pin. The Olimex board connects the LED to pin 19 of port 1 (P1.19). A low turns on the LED. A high turns off the LED. If your board does not have a convenient LED to blink, just pick some otherwise unused pin and put a logic probe on the pin to see it blink. Note, the bootloader always runs when the chip reboots. It decides (based on the state of the ISP (in-system programming) pin and some other criteria) whether to attempt to download a new program via the serial port or whether to jump to the existing application program in the chip's flash memory. * Example programs led1.asm This accepts the environment almost entirely as the bootloader leaves it. It does tell the chip to use fast I/O rather than "legacy" slow I/O, since we need to know which I/O instructions to use to blink the LED. It doesn't try to change or set the clock source or clock speed. It doesn't set up any stacks. It just uses an arbitrary delay value in a register to time the blinking. led2.asm This is just like led1.asm except it makes an effort to calculate (but not to change) the clock speeds involved. If the assumptions used for the calculations are correct, the LED should blink at the speed you request by the setting for SECONDS. If you set SECONDS to 10, then the LED should be on for 10 seconds then off for 10 seconds then off for 10 seconds then ... led3.asm This is like led2.asm except it uses the timer for the delay between blinks. It is an example of setting up a timer and polling it for timeout. It doesn't use interrupts. led4.asm Finally, in this version, we explicitly set up the clock source to be the main oscillator which uses the 12 MHz crystal. The first three used whatever clock source the bootloader used, i.e. the internal RC oscillator. ser1.asm This still blinks the LED but its main purpose is to exercise the serial port in a very simple fashion: it transmits the letter Q every time the LED turns on or off. It sets up the clocks as in led4.asm and sets the baudrate based on the clocks and the value of BAUDRATE. It does not attempt to set up the partial baudrate divisor. See the notes under ser2.asm related to the terminal program. ser2.asm This is an even simpler serial port example. It ignores clocks, ports, etc. It uses the autobaud feature of the LPC2378 chip to set up the baudrate. The program waits for you to type an A (yes, it must be an upper case A). At the first A, the chip sets the baudrate automatically to match that of the terminal on your PC. then it transmits the string "Qabc". Thereafter, it waits for you to type another A and then again transmits "Qabc" ... Note, if you download the program using the lpc_prog flash utility, it goes into a simple terminal automatically. This is because the make file uses the -t option. If you use this simple terminal program, it is not enough to type the A. You must also press Enter. It looks like this terminal is line oriented rather than character oriented. Note, if you use the minicom terminal (under Linux etc.), you do not need to press Enter after the A as minicom is character oriented. However, minicom asserts the DTR and RTS lines. This means you cannot use minicom unless you remove the ISP_E and RST_E jumpers on the Olimex P-2378 board. Otherwise, the board will stay in reset and the program will never run. (If you know how to tell minicom to leave DTR and RTS inactive, please tell me.) ser3.asm Set up a stack (so we can use subroutines). Set up the clock to use the external 12 MHz crystal (with PLL off). Set up the serial port to use the fractional divisor register so we can get accurate baud rates up to 115,200 bps. Equates in the program show the calculations involved. * Binaries The binary versions of the above are included (e.g. ser3.bin) in case you would like to burn them into flash quickly without installing binutils to get the assembler etc. However, if you are using a bootloader that requires a different form than *.bin, you may still need to install binutils in order to convert *.bin to *.srec or whatever your downloader needs. * Why These example programs might be useful for understanding how to change clocks and calculate the various clock speeds and also for understanding how to set up the serial port. Plus they let you exercise the hardware with "known good" programs. (I think they are known good. If you find errors, please let me know.) * Preprocessor These programs are written using the semicolon (;) as the comment character. The GNU ARM assembler prefers the at-sign (@) as the comment character. The makefile takes care of this by running a preprocessor program to convert semicolons to at-signs. That's the purpose of preasm.lisp. Of course, you can convert it to run under other Lisps, but as set up, it requires CLISP. CLISP is very easy to install under Linux (and other Unixes). For example, to install under Debian, at a shell prompt, type apt-get install clisp CLISP is also easy to install under Microsoft Windows. If you would prefer not to install CLISP, all you need to do is write a simple preprocessor in any language you like that takes the *.asm file and produces an *.s file but with semicolons changed to at-signs. You could even do it manually with an editor. * Assembler These programs require the GNU ARM assembler. This is included in the binutils package. You can install a binary version ARM version of it for Linux or you can compile it yourself. See various links on my web site or do a web search for something like "binutils ARM". * Flash utilities Once a program is assembled, producing an *.elf file and an *.bin and/or *.hex and/or *.srec version, you need to burn the program into the LPC chip's flash memory. The two serial download programs (flash utilities) I have been using are lpc21isp and lpc_prog. I have also been using the openOCD program with a JTAG cable. If you type make led1.dl it will assemble, link, create the *.bin version, and attempt to download led1.bin to the flash using lpc21isp. On the other hand, if you type make led1.dls it will assemble, link, create the *.srec version, and attempt to download led1.srec to the flash using lpc_prog. On the third hand, if you type make led1.jtag it will assemble, link, create the *.bin version, and attempt to download led1.bin to the flash using the burn.sh script. Of course, you would need to have openOCD (and netcat) installed. I am not completely happy with the burn.sh script. It just puts in an arbitrary delay of 1 second between commands. Sometimes the commands fail, so watch for error message and type 'make led1.jtag' again. I may do this "right" someday. Meanwhile this is still very convenient. You could also start openOCD in a terminal and start a telnet connection to it in another terminal and type the commands directly in the telnet session. * Installation Pick a directory, unzip asm-demos-YYYYMMDD-HHMM.zip into that directory. (And, of course, the ARM binutils and a flash utility and possibly CLISP need to be installed also.) Then, edit the makefile if you need to change the paths to your assembler, etc. * Make Open a terminal (shell). Move to the directory where you installed the files. Type make led1.s to run just the preprocessor make led1.o to run the assembler, creating the object file make led1.dl to download using lpc21isp make led1.dls to download using lpc_prog make led1.jtag to download using openOCD and the JTAG cable Of course, you do not need to do each step separately. Simply typing make led1.dls will do it all (at least the parts that need doing). * GNU Debugger (gdb) I have included the file .gdbinit as an example. If you use gdb, be sure to edit it to fix up the paths for your environment. * Errors Please email me if you find any typos or errors in these examples or their documentation. -- Frank frank@pygmy.utoh.org http://pygmy.utoh.org/riscy