Code Examples from Class: Difference between revisions

From Class Wiki
Jump to navigation Jump to search
No edit summary
No edit summary
Line 24: Line 24:
END
END
</nowiki>
</nowiki>



----
----
Line 236: Line 237:
END
END
</nowiki>
</nowiki>
----
*GPIO Example
<nowiki>
;---------------------------------------------------------------------------
;
; Programmer : Larry Aamodt
;
; File name : shell_2148.s
; Class : CPTR-215
; Language : ARM assembly
; Assembler : Keil
; Target MCU : NXP LPC-2148 on Embedded Artists board
; Date Written: 11/30/09
; change history: 11/30/09 LDA Updated with hardware start-up
; 12/03/09 LDA PWM register definitions added
; Description :
;
; Inputs :
;
; Outputs :
;
; Special :
; requirements
;
;
; NOTES:
;
;
;
;---------------------------------------------------------------------------

; Put application program definitions (i.e. equates) here:


; Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs

Mode_USR EQU 0x10
Mode_FIQ EQU 0x11
Mode_IRQ EQU 0x12
Mode_SVC EQU 0x13
Mode_ABT EQU 0x17
Mode_UND EQU 0x1B
Mode_SYS EQU 0x1F

I_Bit EQU 0x80 ; when I bit is set, IRQ is disabled
F_Bit EQU 0x40 ; when F bit is set, FIQ is disabled

; Memory addresses for standard GPIO definitions
IO0PIN EQU 0xE0028000
IO0SET EQU 0xE0028004
IO0DIR EQU 0xE0028008
IO0CLR EQU 0xE002800C
; Memory addresses for Pulse Width Modulation (PWM)
PWM_TCR EQU 0xE0014004 ; PWM_TCR Timer Control Register
PWM_PR EQU 0xE001400C ; PWM_PR Prescaler Register
PWM_MCR EQU 0xE0014014 ; PWM_MCR Match Control Register
PWM_MR0 EQU 0xE0014018 ; PWM_MR0 Match Register 0 (sets pulse period)
PWM_MR4 EQU 0xE0014040 ; PWM_MR4 Match Register 4 (sets pulse length)
PWM_MR6 EQU 0xE0014048 ; PWM_MR6 Match Register 6 (sets pulse length)
PWM_PCR EQU 0xE001404C ; PWM_CR Control Register
PWM_LER EQU 0xE0014050 ; PWM_LER Latch Enable Register

PINSEL0 EQU 0xE002C000 ; Pin connect block - port 0
PINSEL1 EQU 0xE002C004 ; Pin connect block - port 1

; Stack size definitions
UND_Stack_Size EQU 0x00000000
SVC_Stack_Size EQU 0x00000008
ABT_Stack_Size EQU 0x00000000
FIQ_Stack_Size EQU 0x00000000
IRQ_Stack_Size EQU 0x00000080
USR_Stack_Size EQU 0x00000400

ISR_Stack_Size EQU (UND_Stack_Size + SVC_Stack_Size + ABT_Stack_Size + \
FIQ_Stack_Size + IRQ_Stack_Size)

AREA STACK, NOINIT, READWRITE, ALIGN=3

Stack_Mem SPACE USR_Stack_Size
__initial_sp SPACE ISR_Stack_Size
Stack_Top


; Area Definition and Entry Point
; Startup Code must be linked first at Address at which it expects to run.

AREA RESET, CODE, READONLY
ARM


; Exception Vectors
; Mapped to Address 0.
; Absolute addressing mode must be used.
; Dummy Handlers are implemented as infinite loops which can be modified.

Vectors LDR PC, Reset_Addr
LDR PC, Undef_Addr
LDR PC, SWI_Addr
LDR PC, PAbt_Addr
LDR PC, DAbt_Addr
NOP ; Reserved Vector
; LDR PC, IRQ_Addr
LDR PC, [PC, #-0x0FF0] ; Vector from VicVectAddr
LDR PC, FIQ_Addr

Reset_Addr DCD Reset_Handler
Undef_Addr DCD Undef_Handler
SWI_Addr DCD SWI_Handler
PAbt_Addr DCD PAbt_Handler
DAbt_Addr DCD DAbt_Handler
DCD 0 ; Reserved Address
IRQ_Addr DCD IRQ_Handler
FIQ_Addr DCD FIQ_Handler

Undef_Handler B Undef_Handler
SWI_Handler B SWI_Handler
PAbt_Handler B PAbt_Handler
DAbt_Handler B DAbt_Handler
IRQ_Handler B IRQ_Handler
FIQ_Handler B FIQ_Handler

; Reset Handler

EXPORT Reset_Handler
Reset_Handler

; Setup Stack for each mode

LDR R0, =Stack_Top

; Enter Undefined Instruction Mode and set its Stack Pointer
MSR CPSR_c, #Mode_UND:OR:I_Bit:OR:F_Bit
MOV SP, R0
SUB R0, R0, #UND_Stack_Size

; Enter Abort Mode and set its Stack Pointer
MSR CPSR_c, #Mode_ABT:OR:I_Bit:OR:F_Bit
MOV SP, R0
SUB R0, R0, #ABT_Stack_Size

; Enter FIQ Mode and set its Stack Pointer
MSR CPSR_c, #Mode_FIQ:OR:I_Bit:OR:F_Bit
MOV SP, R0
SUB R0, R0, #FIQ_Stack_Size

; Enter IRQ Mode and set its Stack Pointer
MSR CPSR_c, #Mode_IRQ:OR:I_Bit:OR:F_Bit
MOV SP, R0
SUB R0, R0, #IRQ_Stack_Size

; Enter Supervisor Mode and set its Stack Pointer
MSR CPSR_c, #Mode_SVC:OR:I_Bit:OR:F_Bit
MOV SP, R0
SUB R0, R0, #SVC_Stack_Size

; Enter User Mode and set its Stack Pointer
MSR CPSR_c, #Mode_USR

MOV SP, R0
SUB SL, SP, #USR_Stack_Size


; User program code goes here

main
ldr sp, = Stack_Mem ; load stack pointer
ldr r1, =PINSEL0
mov r0, #0 ; set P0.0 to P0.15 as GPIO
str r0,[r1]
ldr r1, =IO0DIR ; Get ready to set direction of data
ldr r0, =0xffff ; output
str r0, [r1] ; set the direction
ldr r1, =IO0PIN ; load the address of the port0
mov r0, #0
next
str r0, [r1]
add r0, r0, #1
ldr r2, =0x200
delay
subs r2,r2,#1
bne delay
b next


AREA Thedata, DATA, READWRITE
ALIGN
datastart EQU 0x40000004
SPACE 20
;FILL 20, 0xff ; Why is this stored at 0x50 instead of 0x58?
; Or maybe a better question: How do I set data at
; a specific memory location?

END
<\nowiki>

Revision as of 14:04, 19 November 2013

  • Factorial
; Factorial Calculation
; The answer is in R10

; Rob Frohne 2013

	GLOBAL Reset_Handler 
	AREA Factorial, CODE, READONLY
	ENTRY

Reset_Handler
		movs r8, #0 ; Take the factorial of this number, n.
		mov r10, #1	 ; 0! and 1! are 1
		beq stop   ; If r8 is zero we are done
		cmp r8, #1	 ; If r8 is 1, 
		beq stop	  ; we are done
		subs r9, r8, #1	; n-1
loop	mulne r10, r9, r8 ; n(n-1)
		mov r8, r10
		subs r9, r9, #1
		bne loop
stop 	b stop
		END



  • 64 Bit Add
VAL1A EQU 0xffffffff
VAL1B EQU 0x0000000f
VAL2A EQU 0x00000001
VAL2B EQU 0x00000001
	AREA LongAdd, CODE
	ENTRY
		ldr R0, = VAL1A
		ldr R1, = VAL1B
		ldr R2, = VAL2A
		ldr R3, = VAL2B
		adds R8,R0,R1
		adcs R9,R1,R3
stop 	b stop
	END

  • Copy to RAM
   AREA Exaddress, CODE, READONLY
   EXPORT Reset_Handler
Reset_Handler
   LDR R9, =list
   mov R7, #4 ; number in list
   ldr r6, =datastart 
loop
   ldr r8,[r9],#4
   str r8,[r6],#4
   subs r7,r7,#1
   bne loop
 
stop b stop
   ALIGN
list DCW 0x1111, 0x2222, 0x3333, 0x4444, 0x5555
   ALIGN
string DCB "This is a test.",0 ; This string is not used in the copy to ram program
string2 DCB 'T','h','i' ; This string2 is not used in the copy to ram program
   ALIGN
   AREA Thedata, DATA, NOINIT, READWRITE
datastart SPACE 20
 
   END

  • Subroutine Example1
; First Subroutine Example
; This program demonstrates using a subroutine,
; saving registers on the stack, etc.

; Rob Frohne, 1/3/2013

stack_start EQU 0x40001000
   AREA Subroutine_Example, CODE

   ENTRY

Start
   ldr sp, =stack_start ; Tell where we will place the stack.
                        ; (It goes down (lower addresses from here.)
   mov r1, #1 ; Store some numebers in some registers
   mov r2, #2
   mov r3, #3
   bl subroutine
stop b stop

; This subroutine saves the registers,
; messes up the registers locally,
; then restores the registers and returns.
subroutine
   stmfd sp!, {r1-r2,lr} ; save used registers and the link register (r14)
   mov r1,#0xffffffff ; mess up the registers
   mov r2, r1
   ldmfd sp!, {r1,r2,pc} ; pop the stack and return 
   END

  • Minimum of a Signed Number
; This program finds the minimum of a list of constant words in signed format
; The result is in r3 at the end of the routine.
; Rob Frohne 10/30/2013

	AREA Program, CODE, READONLY

	ENTRY

	ldr r0,=end		; load the beginning address of the code & initialize it as the pointer.
	ldr r2,=begin	; load the ending address of the code.
	mov r3,#0x7fffffff ; Initialize r3 as the most positive number.

loop	
	ldr r6,[r2],#4 ; load the next data into r6 and post increment r2 for the next data.
	cmp r6,r3 ; Find out if r6 > r3. result from r6-r3  like subs r7,r6,r3 without r6 necessary.
	bgt no_update	 ; If it is no update.
	mov r3,r6		; update if r6 is lower than r3.
no_update
	cmp r0,r2  ;  are we at the end yet
	bne loop		   ; if r7 != 0 then keep looping

stop b stop
ALIGN
begin
	DCD 0x8fffffff, 0x55555555, 0x44444444, 0x77777777, 0xffffffff
end	
	END 

  • Compare Two Null Terminated Strings
; Subroutine to compare two null terminated ASCII strings.
; The address where the two strings start are in r0 and r1
; The return is in r0, 1 for match and 0 for don't match.
; If they don't match, r1 gives the number of the first 
; character that didn't match, starting with 0.
; r2 and r3 are not protected.
; Rob Frohne 11/6/2013
stack_start EQU 0x40001000
	AREA String_Compare, CODE
    ENTRY
Start
	ldr sp, =stack_start ; Tell where we will place the stack.
                        ; (It goes down (lower addresses from here.)
	ldr r0, =string1
	ldr r1, =string2
	bl compare_strings
stop b stop

compare_strings
	stmfd sp!, {r2,r4,r5,lr} ; save used registers and the link register (r14)
	mov r2, #0 ; Initialize the counter for the first position.
loop
	ldrb r4,[r0],#1
	ldrb r5,[r1],#1
	cmp r5,r4
	bne do_not_match
	cmp r4, #0 ; check for end of string.
	beq match
	add r2, #1
	b loop
do_not_match
	mov r0, #0 ; don't match
	b finish
match
	mov r0, #1
finish
	mov r1,r2 ; Move the count into the result register.	
	ldmfd sp!, {r2,r4,r5,pc} ; pop the stack and return 
string1 
	DCB "This is the first string.",00	; For testing purposes.
	ALIGN
string2 
	DCB "This is the first string.",00
	ALIGN
        END

  • BCD Add
; Subroutine to add two BCD numbers in 32 bit form with each nibble
; representing a digit.
; locals: r8 for digit counter, mask 0xf, r5 & r6 for masked addends,
; working BCD_carry, r7 for
; working result in r4
; the summed digits go in r3
; inputs: r0+r1
; outupts: r0 result and r1 carry
; only r4-r8 are saved.
; Rob Frohne 11/12/13
stack_start EQU 0x40001000
	AREA ADD_BCD, CODE
    ENTRY
Start
	ldr sp, =stack_start ; Tell where we will place the stack.
                        ; (It goes down (lower addresses from here.)
	ldr r0, =0x12345678	  ; The two numbers to add.
	ldr r1, =0x87654321
	bl bcd_add
stop b stop

bcd_add	; The subroutine
	stmfd sp!, {r4-r8,lr}
	mov r8, #8 ; Set the counter to move through the eight digits
	mov r7, #0 ; Set the carry to zero to start with
	mov r3, #0	; This is where the resulting digits of the sum are stored.
loop
	and r5, r0, #0xf  ; mask for the rightmost digit.
	and r6, r1, #0xf
	add r4, r5, r7 ; add carry
	add r4, r4, r6 ; r4=r5+r6
	subs r4, r4, #10 ; Subtract 10 (base 10) to see if there is a carry.
	bmi no_carry
	mov r7, #1 ; set the carry
	b roll_to_next_digit
no_carry
	mov r7, #0 ; set carry to zero
	add r4, r4, #10 ; Add the 10 back in as there was no carry needed.
roll_to_next_digit
	orr r3, r3, r4 ; Add thise digits into the sum.
	ror r0, #4
	ror r1, #4
	ror r3, #4
	subs r8, r8, #1	 ; Decrement digit counter
	bne loop	  ; If it isn't zero do the next digit.
	mov r0, r3 ; Set the output registers. r0 is result. r1 is carry.
	mov r1, r7
	ldmfd sp!, {r4-r8,pc}
	END


  • GPIO Example
<nowiki>
---------------------------------------------------------------------------
Programmer
Larry Aamodt
File name
shell_2148.s
Class
CPTR-215
Language
ARM assembly
Assembler
Keil
Target MCU
NXP LPC-2148 on Embedded Artists board
Date Written
11/30/09
change history
11/30/09 LDA Updated with hardware start-up
12/03/09 LDA PWM register definitions added
Description
Inputs
Outputs
Special
requirements
NOTES
---------------------------------------------------------------------------
Put application program definitions (i.e. equates) here


Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs

Mode_USR EQU 0x10 Mode_FIQ EQU 0x11 Mode_IRQ EQU 0x12 Mode_SVC EQU 0x13 Mode_ABT EQU 0x17 Mode_UND EQU 0x1B Mode_SYS EQU 0x1F

I_Bit EQU 0x80  ; when I bit is set, IRQ is disabled F_Bit EQU 0x40  ; when F bit is set, FIQ is disabled

Memory addresses for standard GPIO definitions

IO0PIN EQU 0xE0028000 IO0SET EQU 0xE0028004 IO0DIR EQU 0xE0028008 IO0CLR EQU 0xE002800C

Memory addresses for Pulse Width Modulation (PWM)

PWM_TCR EQU 0xE0014004  ; PWM_TCR Timer Control Register PWM_PR EQU 0xE001400C  ; PWM_PR Prescaler Register PWM_MCR EQU 0xE0014014  ; PWM_MCR Match Control Register PWM_MR0 EQU 0xE0014018  ; PWM_MR0 Match Register 0 (sets pulse period) PWM_MR4 EQU 0xE0014040  ; PWM_MR4 Match Register 4 (sets pulse length) PWM_MR6 EQU 0xE0014048  ; PWM_MR6 Match Register 6 (sets pulse length) PWM_PCR EQU 0xE001404C  ; PWM_CR Control Register PWM_LER EQU 0xE0014050  ; PWM_LER Latch Enable Register

PINSEL0 EQU 0xE002C000  ; Pin connect block - port 0 PINSEL1 EQU 0xE002C004  ; Pin connect block - port 1

Stack size definitions

UND_Stack_Size EQU 0x00000000 SVC_Stack_Size EQU 0x00000008 ABT_Stack_Size EQU 0x00000000 FIQ_Stack_Size EQU 0x00000000 IRQ_Stack_Size EQU 0x00000080 USR_Stack_Size EQU 0x00000400

ISR_Stack_Size EQU (UND_Stack_Size + SVC_Stack_Size + ABT_Stack_Size + \

                        FIQ_Stack_Size + IRQ_Stack_Size)
               AREA    STACK, NOINIT, READWRITE, ALIGN=3

Stack_Mem SPACE USR_Stack_Size __initial_sp SPACE ISR_Stack_Size Stack_Top


Area Definition and Entry Point
Startup Code must be linked first at Address at which it expects to run.
               AREA    RESET, CODE, READONLY
               ARM


Exception Vectors
Mapped to Address 0.
Absolute addressing mode must be used.
Dummy Handlers are implemented as infinite loops which can be modified.

Vectors LDR PC, Reset_Addr

               LDR     PC, Undef_Addr
               LDR     PC, SWI_Addr
               LDR     PC, PAbt_Addr
               LDR     PC, DAbt_Addr
               NOP                            ; Reserved Vector 
LDR PC, IRQ_Addr
               LDR     PC, [PC, #-0x0FF0]     ; Vector from VicVectAddr
               LDR     PC, FIQ_Addr

Reset_Addr DCD Reset_Handler Undef_Addr DCD Undef_Handler SWI_Addr DCD SWI_Handler PAbt_Addr DCD PAbt_Handler DAbt_Addr DCD DAbt_Handler

               DCD     0                      ; Reserved Address 

IRQ_Addr DCD IRQ_Handler FIQ_Addr DCD FIQ_Handler

Undef_Handler B Undef_Handler SWI_Handler B SWI_Handler PAbt_Handler B PAbt_Handler DAbt_Handler B DAbt_Handler IRQ_Handler B IRQ_Handler FIQ_Handler B FIQ_Handler

Reset Handler
               EXPORT  Reset_Handler

Reset_Handler

Setup Stack for each mode
               LDR     R0, =Stack_Top
Enter Undefined Instruction Mode and set its Stack Pointer
               MSR     CPSR_c, #Mode_UND:OR:I_Bit:OR:F_Bit
               MOV     SP, R0
               SUB     R0, R0, #UND_Stack_Size
Enter Abort Mode and set its Stack Pointer
               MSR     CPSR_c, #Mode_ABT:OR:I_Bit:OR:F_Bit
               MOV     SP, R0
               SUB     R0, R0, #ABT_Stack_Size
Enter FIQ Mode and set its Stack Pointer
               MSR     CPSR_c, #Mode_FIQ:OR:I_Bit:OR:F_Bit
               MOV     SP, R0
               SUB     R0, R0, #FIQ_Stack_Size
Enter IRQ Mode and set its Stack Pointer
               MSR     CPSR_c, #Mode_IRQ:OR:I_Bit:OR:F_Bit
               MOV     SP, R0
               SUB     R0, R0, #IRQ_Stack_Size
Enter Supervisor Mode and set its Stack Pointer
               MSR     CPSR_c, #Mode_SVC:OR:I_Bit:OR:F_Bit
               MOV     SP, R0
               SUB     R0, R0, #SVC_Stack_Size
Enter User Mode and set its Stack Pointer
               MSR     CPSR_c, #Mode_USR
               MOV     SP, R0
               SUB     SL, SP, #USR_Stack_Size


User program code goes here

main ldr sp, = Stack_Mem ; load stack pointer ldr r1, =PINSEL0 mov r0, #0  ; set P0.0 to P0.15 as GPIO str r0,[r1] ldr r1, =IO0DIR ; Get ready to set direction of data ldr r0, =0xffff ; output str r0, [r1] ; set the direction ldr r1, =IO0PIN ; load the address of the port0 mov r0, #0 next str r0, [r1] add r0, r0, #1 ldr r2, =0x200 delay subs r2,r2,#1 bne delay b next


AREA Thedata, DATA, READWRITE ALIGN datastart EQU 0x40000004 SPACE 20 ;FILL 20, 0xff ; Why is this stored at 0x50 instead of 0x58? ; Or maybe a better question: How do I set data at ; a specific memory location?

		END

<\nowiki>