LPC17xx ARM Cortex M3 Assembly Language Example

December 30, 2018 | Author: Dany Gremory | Category: Arm Architecture, Assembly Language, Instruction Set, Office Equipment, Computing
Share Embed Donate

Short Description

LPC17xx ARM Cortex M3 Assembly Language Example...


LPC17xx ARM Cortex M3 Assembly Assembly Language Example Table of Contents 1 Abstract 2 The hardware h ardware 2.1 Add Headers 2.2 Serial port 3 The software tools 3.1 The assembler and linker 3.2 The preprocessor 4 The assembly language program 4.1 Source code listing 4.2 Notes about the source code 5 Assembling and linking 6 Burning the flash with a JTAG connector 7 Burning the flash through the serial bootloader 8 Other files 8.1 The link file 8.2 The OpenOCD configur configurati ation on file 8.3 Bonus B onus section 9 Download 10 Dead ends 10.1 Using Code Red to program the flash 10.2 Using an Olimex JTAG probe with OpenOCD 10.3 Verify error with lpc21isp version 1.79 11 Conclusi C onclusion on

1 Abstract This note describes an LED blinking program written in assembly language for the LPC17xx family of  ARM Cortex C ortex M3 chips. As written, written, it runs runs on the LPCXpresso LPC Xpresso LPC1769 board (where the LED is on Port 0, bit 22). To run on other LPC17xx boards where an LED is on a different port pin, either adjust this code to use a different port pin or else use a logic probe on Port 0, bit 22, as a temporary LED, and run the program as-is. It shows the commands for assembling and linking with the GNU assembler and linker and also the commands for burning the program into the board's flash memory via a JTAG connector and the OpenOCD software or with the lpc21isp serial bootloader (flash) utility. The binary file is also included in case you would like to jump right to burning it into flash.

2 The hardware

I used the LPCXpresso LPC1769 board. I do not recommend the LPCXpresso boards and suggest you get a different LPC17xx board instead. On the LPCXpresso board, an LED is connected to bit 22 of Port 0. This is labeled "LED2". It is near J636. When Port 0 bit 22 is high, the LED lights up. Below, I describe some hardware modifications (basically soldering some headers for easy access and adding a serial adapter) . You may not need to do even this much if  you use an LPCXpresso board but can burn the flash successfully from the Code Red IDE you use an LPCXpresso board in some sort of a base board that supplies a serial adapter and/or a JTAG connector you use a different LPC17xx board with a JTAG adapter or a serial port adapter

2.1 Add Headers I cut the traces on the bottom of the board between the LPC-Link part of the board and the LPC1769 part of  the board. Then, I soldered a 16-pin header (2x8, double row, 8 pins in each row) and shorted pins 1 and 2 together (3.3V) and shorted pins 15 and 16 together (ground) (or, just don't cut those two traces). Pins 1, 2, 15, and 16 provide a convenient place to pick up power and ground for the serial adapter. This header is labeled J4 on the board. I also soldered a single-row 27-pin header on each edge of the LPC1769 side of the board to give easy access to the serial port pins and other pins. This header is labeled J6 on the board.

2.2 Serial port In order to use the chip's built-in serial bootloader, I wired a serial adapter to UART0 so I could program the flash with the lpc21isp flash utility. You can get such an adapter from SparkFun (http://www.sparkfun.com/). I built my own with two gates of a 4049 chip (a real 4049, not a 74HC4049, because we need it to run at 3.3 volts) and some resistors.

3 The software tools I did not use the Code Red IDE. I tried it briefly but I did not get along well with it. Because of this, I cannot recommend the LPCXpresso boards. The software described here, needed to preprocess, assemble, link, and burn the demo program into the ARM Cortex board, runs on Linux. If you do not have Linux available, it can be as simple as temporarily booting an Ubuntu live CD (see details at http://pygmy.utoh.org/riscy/) and installing the "Bundle of  Tools".

3.1 The assembler and linker We use (parts of) the GNU toolchain, running on Linux (such as Ubuntu 10.04). In particular we need the GNU "binutils" package, which includes the ARM assembler and linker and some utilities to manipulate the output files. We do not need the C or C++ compiler. This is a cross assembler. It runs on a PC (such as a typical desktop or laptop with an Intel CPU) but produces code for an ARM CPU.

If you don't have GNU binutils for the ARM installed, you can download my "Bundle of Tools" at http://pygmy.utoh.org/riscy/ .

3.2 The preprocessor The GNU ARM assembler prefers to use the at-sign for comments. I prefer to use the semicolon for comments. So, I write the assembly language program using semicolons for comments then run the program through a preprocessor that converts semicolons to at-signs before feeding the program to the AR M assembler. The preprocessor program is named preasm.tcl and is included in the tools bundle mentioned in the previous section. If you prefer, you can manually convert the semicolons to at-signs.

4 The assembly language program 4.1 Source code listing Here is the program source code (from the file named led-lpc17xx.asm  ). ;;; ;;; ;;; ;;; ;;; ;;;

led-lpc17xx.asm  written by Frank Sergeant [email protected] http://pygmy.utoh.org/riscy This program is in the public domain. See http://pygmy.utoh.org/riscy/cortex/ for notes about the program and how to assemble, link, and burn to flash.

;;; Blink the LED on the LPCXpresso LPC1769 ARM Cortex M3 board ;;; (or any LPC17xx ARM board with perhaps minor modifications). ;;; The LED on the Xpresso board is labeled LED2 and is just to the ;;; left of (inside of) J6-36. It is connected to P0.22. The LED is ;;; on when P0.22 is high. ;;; Directives .thumb .syntax unified

; (same as saying '.code 16')

;;; Equates .equ LED_MASK, 0x00400000 ; i.e., bit 22 .equ PINSEL0, .equ PINSEL1, .equ .equ .equ .equ .equ

0x4002C000 0x4002C004



0x2009C000 ; port direction, 0 (default) = input 0x2009C010 ; port direction, 0 (default) = input 0x2009C014 0x2009C018 0x2009C01C 0x10004000 800000

.section .text .org 0 ;;; Vectors vectors: .word .word .word .word .word .word .word

STACKINIT _start + 1 _nmi_handler + 1 _hard_fault + 1 _memory_fault + 1 _bus_fault + 1 _usage_fault + 1

; stack pointer value when stack is empty ; reset vector (manually adjust to odd for thumb) ; ; ; ; ;

 _start: ldr r6, = PINSEL1 ;; set P0.22 as a GPIO pin ;; P0.22 is controlled by bits 13:12 of PINSEL1 ;; xxxx xxxx xxxx xxxx xx11 xxxx xxxx xxxx ;; 0 0 0 0 3 0 0 0 ldr r0, [r6] bic r0, r0, # 0x00003000 str r0, [r6]

; clear bits 13:12 to force GPIO mode

;; set LED output pin (i.e. P0.22) as an output ldr r6, = FIO0DIR ; for PORT0 mov r0, # LED_MASK ; all inputs except for pin 22 str r0, [r6] ;; r0 still contains LED_MASK ldr r5, = FIO0CLR ldr r6, = FIO0SET loop: str r0, [r5] ldr r1, = LEDDELAY

; clear P0.22, turning off LED

delay1: subs r1, 1 bne delay1 str r0, [r6] ldr r1, = LEDDELAY

; set P0.22, turning on LED

delay2: subs r1, 1 bne delay2 b loop  _dummy:  _nmi_handler:  _hard_fault:  _memory_fault:  _bus_fault:  _usage_fault:

; continue forever ; if any int gets triggered, just hang in a loop

add r0, 1 add r1, 1 b _dummy

4.2 Notes about the source code The goal for this program (other than blinking the LED) is to start with a very simple program. This lets us check out our toolchain, our flash utility and/or JTAG connector and software, and our mental model of  how it all works without getting bogged down in unnecessary complexities. For example, we do not use subroutines. We only set up the hardware stack because the ARM Cortex loads the stack pointer automatically. We hard-code the output port configuration register (rather than setting just the bits we need for the LED pin). We do not alter the clock source or speed (we use the default internal 4 MHz clock). We  just want something to run now  ! The LPC1769 MCU uses the "Thumb-2" instruction set, not the "ARM" instruction set. Even though the .thumb directive is equivalent to the .code 16 directive, the processor is still a 32-bit processor. We define some symbolic constants, including the initial stack value ( STACKINIT) and the LED delay value (LEDDELAY). If, after getting the program to run, you would prefer to make the LED blink faster or slower, then change the value of LEDDELAY. The program starts at address zero (0x0000 0000) with the vector table. Each vector table slot is 4 bytes long. The first entry is the initial value for the stack pointer. We use 0x1000 4000 for the initial stack value. The second slot in the vector table holds the address where program execution will begin. In this case, it is at the label _start . Actually, we adjust the address slightly in the vector table by adding 1 to it to make it odd. This is required because, in Thumb mode, a value loaded into the program counter must have its least significant bit set. I suppose there is a way to avoid doing this by putting the vectors is a special section and giving the linker certain command options and/or using an assembler directive. We fill in several more slots in the vector table for various exceptions. They all point to a loop at the end of  the program. We do not expect any of these exceptions to be triggered, but if they are, the program will just hang in a loop, incrementing two registers (so we will have something to look at if we are tracing the program in a debugger). The rest of the logic should be straightforward. We alternately write a "1" bit to the FIOCLR and the FIOSET registers to turn bit 22 of Port 0 on and off (to turn the LED off and on), killing time so the LED flashes at exactly the speed we like best (adjust LEDDELAY to your personal taste).

5 Assembling and linking Assuming you have the assembler and linker and other tools installed where I install them, here are the commands to preprocess, assemble, link, and build a binary: $ $ $ $

/usr/local/bin/preasm.tcl led-lpc17xx.asm led-lpc17xx.s /usr/local/arm/bin/arm-elf-as -mcpu=cortex-m3 -mthumb -mapcs-32 -gstabs -ahls=led/usr/local/arm/bin/arm-elf-ld -v -T lpc17xx.ld -nostartfiles -o led-lpc17xx.elf le /usr/local/arm/bin/arm-elf-objcopy -O binary led-lpc17xx.elf led-lpc17xx.bin

The goal is to produce the file led-lpc17xx.bin to burn into the MCU's flash memory.

6 Burning the flash with a JTAG connector (I used the serial bootloader instead. See the next section.) You can use any method you prefer to burn led-lpc17xx.bin into the flash. Here is how I might do it if I had a working JTAG connection to the LPCXpresso board, using OpenOCD and the Olimex ARM USB Tiny JTAG adaptor (http://olimex.com/dev/arm-usb-tiny.html ): Open a terminal and start the OpenOCD daemon with $ openocd -f openocdlpc17xx.cfg

In another terminal, connect to the daemon with $ telnet localhost 4444

Then in the telnet terminal, type the following commands (not all are necessary) > help run above to see all OpenOCD commands > halt > poll > flash erase_sector 0 0 0 erase sector 0 (where we will load our new program) > flash info 0 > flash erase_check 0 hopefully this shows we erased sector 0 successfully > flash write_bank 0 led-lpc17xx.bin 0 > mdw 0 7 above displays the 7 vector slots as 32-bit words, note all slots except the first have the least significant bit set > mdb 0 28 above displays the 7 vector slots as 28 bytes (note, little endian) > cortex_m3 disassemble 0x1c 0x20 above disassembles the program starting at the label "_start" > reset init > resume

7 Burning the flash through the serial bootloader I used a serial connection on the PC (on /dev/ttyS1 in my case), along with the lpc21isp flash utility, to program the flash with this command: lpc21isp

-donotstart -verify -bin led-lpc17xx.bin

/dev/ttyS1 38400 4000

I used a serial adapter to convert the LPC1769 chip's UART0 TTL-level signals to RS232-level signals (or close enough). I made the adapter with a 4049 hex inverter chip, using one gate for Rx and one gate for Tx with a resistor on the inputs to provide a little current-limiting protection. I picked up power and ground from J4-2 and J4-16. I picked up Tx and Rx from J6-22 and J6-21.

I also set up two jumper wires: one on J6-4 (nRESET) The chip can be reset by briefly touching the other end of this jumper to J6-1 (ground), eliminating the need to unplug and replug the USB connector in order to reset the board one on J6-51 (Port 2, bit 10) If this pin is low when the chip comes out of reset, the chip goes into serial bootloader mode. The sequence to program the flash is this  jump J6-51 (bootloader) to J6-54 (ground) type in the lpc21isp command briefly touch the jumper from J6-4 (nRESET) to J6-1 (ground) to reset the chip see that lpc21isp runs successfully (do we need to ignore the verify failure message? See the "Dead end" section below.) remove the jumper from J6-51 again briefly touch the jumper from J6-4 to J6-1 to reboot the chip in non-bootloader mode watch the LED blink

8 Other files You need several other files, whose contents are listed below. See the next section for the download bundle. 8.1 The link file


/* Simple linker script for the NXP LPC1769 ARM Cortex M3. Link the text of the program into on-board flash and use on-board RAM for data and stack. */ SECTIONS { /* interrupt vectors start at zero */ . = 0x0; /* start of flash */ .text :





/* constant data follows code but still in flash */ .data : { *(.data) *(.rom) } /* internal RAM starts at 0x10000000 */ . = 0x10000000; .ram : { *(.ram) }


.bss : { *(.bss) *(.ram) }


8.2 The OpenOCD configuration file openocdlpc17xx.cfg # This file is for use with the LPCXpresso LPC1769 board. # It is named openocdlpc17xx.cfg. Run it this way: # $ openocd -f openocdlpc17xx.cfg # This is the JTAG connector I use source [find interface/olimex-jtag-tiny.cfg] # This is close enough to the board I use source [find target/lpc1768.cfg] # tell gdb our flash memory map and enable flash programming gdb_memory_map enable gdb_flash_program enable # Note, on the JTAG interface I wired up to the LPCXpresso board, the # nTRST is not available. Do we need to tell OpenOCD about that? # I don't know whether the following would help or not #reset_config srst_only

8.3 Bonus section

This note does not go into the details of using the GNU debugger (GDB) with this board and JTAG. If you manage to get a working JTAG/OpenOCD connection to your board, see the "Bonus section" of  http://pygmy.utoh.org/riscy/cortex/led-stm32.html  for some hints about setting up the GDB configuration files.

9 Download The file http://pygmy.utoh.org/riscy/cortex/led-lpc17xx.zip contains led-lpc17xx.html this file openocdlpc17xx.cfg the JTAG/OpenOCD configuration file lpc17xx.ld the linker file led-lpc17xx.asm the LED blinking program source code led-lpc17xx.s the preprocessed LED blinking program source code led-lpc17xx.lst the listing file produced by the assembler led-lpc17xx.bin the binary ready to burn into the MCU's flash

Also, the GNU binutils compiled on 32-bit Ubuntu 10.04 to cross assemble for the ARM (and ARM Cortex) along with the preprocessor are available at http://pygmy.utoh.org/riscy/ – look for "The Bundle of  Tools".

10 Dead ends 10.1 Using Code Red to program the flash Although I found the "Program Flash" tool bar button, and could make it apparently go through the steps to burn led-lpc17xx.bin, it didn't seem to work. (Of course, if you try this after you cut the traces between the LPC-Link side and the LPC1769 side, you need to jumper them again. For example, solder a 2x8 header into J4 then use shorting blocks on all 8 pairs). If you should get this working, and especially if you are then able to tell Code Red that led-lpc17xx.s is the source code file, and are then able to step through it in the Code Red debugger, please email me with full details as to how you did it.

10.2 Using an Olimex JTAG probe with OpenOCD After cutting the traces and installing the 2x8 header for J4, and soldering in the 2x27 header (well, two separate 1x17 headers) for J6, I wired up an adapter to the board for my Olimex USB-TINY JTAG adapter and tried working with it with OpenOCD. I did succeed in dumping memory, but attempting to program the flash and/or to single step failed.

Here is how I wired my connector, showing where I picked up the JTAG signals.     (LPC J4-2) 3.3v n/c (LPC J4-10) (LPC J4-4) (LPC J4-6) n/c (LPC J4-8) (LPC J4-12) n/c n/c  

JTAG Top View .--------------------------------. | | | 1 Vref Vtarget 2 | 3.3v | | | 3 NTRST GND 4 | | | | 5 TDI GND 6 | | | | 7 TMS GND 8 | | | | 9 TCK GND 10 | | | |11 RTCK GND 12 | | | |13 TDO GND 14 | | | |15 RST GND 16 | | | |17 DBGRQ GND 18 | | | |19 DBGACK GND 20 | GND (LPC J4-16) | | `--------------------------------'

I didn't bother with any pull-ups or pull-downs, assuming the signals that needed that were already pulled up or down on the LPCXpresso board itself. That I was able to communicate through this adapter (the mdw command to dump memory) seems to support this assumption. I understand the RTCK signal is not needed. I really wanted to connect the NTRST signal, which apparently comes from the LPC1769 chip's pin 100, but I could not find where the LPCXpresso board brought that signal out to any connector and I did not want to try soldering to the tiny pins of the LPC1769 chip. If you find that NTRST/pin 100 is in fact accessible somewhere on the board, please tell me where. If you are able to get "real" JTAG (as opposed to the proprietary Code Red version) working with this board, please tell me how you did it.

10.3 Verify error with lpc21isp version 1.79 This is not necessarily a dead end. I did successfully program the flash so that the LED blinking program would run. I used this command lpc21isp

-donotstart -verify -bin led-lpc17xx.bin

/dev/ttyS1 38400 4000

and it reported a verification failure. What I would like to know is whether the my particular LPC1769 chip does indeed have some bad flash (but not in places that would prevent the LED blinking program from running) or if the lpc21isp program (version 1.79) is failing to verify flash that in fact is programmed successfully.

An obvious experiment, which I have not tried yet, is to slow down the baudrate, using somethink like lpc21isp

-donotstart -verify -bin led-lpc17xx.bin

/dev/ttyS1 1200 4000

So, if you use lpc21isp to program the flash in an LPCXpresso board, please email me to tell me how it worked for you.

11 Conclusion Please email me with any comments or corrections or questions (or answers). Author: Frank Sergeant Date: 2011-02-17 Thu HTML generated by org-mode 6.21b in emacs 23

View more...


Copyright ©2017 KUPDF Inc.