硬件平台:tq2440
开发环境:Ubuntu-3.11
u-boot版本:2014.10
本文允许转载,请注明出处:http://blog.csdn.net/fulinus
/*********************************************************************** * File: beep.S * Version: 1.0.0 * Copyright: 2014 (c) fulinux <fulinux@sina.com> * Description: This ASM code used to turn beep on/off on TQ2440 board ***********************************************************************/ #define GPBCON 0x56000010 #define GPBDAT 0x56000014 #define GPBUP 0x56000018 #define DELAY 0X40000000 .text .align 2 .global _start _start: /*Set GPB5,GPB6,GPB7,GPB8 as GPIO OUTPUT mode*/ ldr r0, =GPBCON ldr r1, [r0] bic r1, r1, #0x03 /*Set GPBCON for GPB0 as 00 */ orr r1, r1, #0x01 /*Set GPBCON for GPB0 as GPIOOUT, 0x01*/ str r1, [r0] /*Set internal pullup resister*/ ldr r0, =GPBUP ldr r1, [r0] @orr r1, r1, #0x01 /*Set bit 0, disable pullup resister*/ bic r1, r1, #0x01 /*Clear bit 0, enable pullup resister*/ str r1, [r0] loop: /*Turn off beep*/ ldr r2, =GPBDAT ldr r3, [r2] orr r3, r3, #1 /*Set bit 0 as high level*/ str r3, [r2] ldr r0, =DELAY /*Sleep for a while*/ bl delay /*Turn on beep*/ ldr r3, [r2] bic r3, r3, #1 /*Set bit 0 as high level*/ str r3, [r2] ldr r0, =DELAY /*Sleep for a while*/ bl delay b loop /*Loop running*/ delay: sub r0, r0, #1 cmp r0, #0x0 bne delay mov pc, lr
该程序主要是根据昨天led.S程序修改而来。makefile文件与昨天的文件一样,只是将执行文件名改了一下:
BINAME = beep
从asm中跳转到C函数中也是一个重要的技术要点,我们在ARM汇编程序中要做如下工作
1、关看门狗;
2、屏蔽中断;
3、跳转到C代码中的main函数中去。
/*********************************************************************** * File: start.S * Version: 1.0.0 * Copyright: 2011 (c) Guo Wenxue <guowenxue@gmail.com> * Description: This ASM used to disable watch dog and interrupt, then call C code to * turn the buzzer on/off on FL2440 board. * ChangeLog: 1, Release initial version on "Mon Mar 21 21:09:52 CST 2011" * ***********************************************************************/ #define pWTCON 0x53000000 /* Watch dog register address */ #define INTMSK 0x4A000008 /* Interupt-Controller base addresses */ #define INTSUBMSK 0x4A00001C .text .align 2 .global _start _start: /* Disable watch dog */ ldr r0, =pWTCON /*Save pwTCON address in r0*/ mov r1, #0x0 /*Set r1=0x0*/ str r1, [r0] /*Move the data in r1 to the address specify by r0*/ /* mask all IRQs by setting all bits in the INTMR - default */ mov r1, #0xffffffff ldr r0, =INTMSK str r1, [r0] ldr r0, =INTSUBMSK ldr r1, =0x7fff /*There are 15 bits used in INTSUBMSK on S3C2440*/ str r1, [r0] bl main halt_loop: b halt_loop
/*********************************************************************** * File: beep.c * Version: 1.0.0 * Copyright: 2011 (c) Guo Wenxue <guowenxue@gmail.com> * Description: This C code used to turn buzzer on/off on FL2440 board * ChangeLog: 1, Release initial version on "Mon Mar 21 21:09:52 CST 2011" * ***********************************************************************/ #define GPBCON (*(unsigned long volatile *)0x56000010) #define GPBDAT (*(unsigned long volatile *)0x56000014) #define GPBUP (*(unsigned long volatile *)0x56000018) #define BEEP 0 /*Buzzer us GPB0 */ #define DELAY_TIME 40000000 static inline void delay (unsigned long loops) { __asm__ volatile ("1:\n" "subs %0, %1, #1\n" "bne 1b":"=r" (loops):"0" (loops)); } int main(void) { GPBCON = (GPBCON|0x3)&0x1; /* Set GPB0 as GPIO output mode(0x01) */ GPBUP &= ~1; /* Enable pullup resister */ GPBDAT |= 0x560; while(1) { GPBDAT &= ~(1<<BEEP); /* Set Beep GPIO as low level */ delay(DELAY_TIME); GPBDAT |= 1<<BEEP; /* Set Beep GPIO as high level */ delay(DELAY_TIME); } }
显然,我们这里首先需要执行ARM汇编程序,再由汇编程序跳转到C程序中,但是编译器并不清楚是将C语言的代码段还是将ARM汇编的代码段放在首位,因此需要告知编译器如何编译和连接。有一个lds文件,该文件中的内容决定程序中各个代码段的位置摆放关系,可以在下面的makefile文件中看到是如何将该文件传给编译器的。
/*********************************************************************** * File: beep.lds * Version: 1.0.0 * Copyright: 2011 (c) Guo Wenxue <guowenxue@gmail.com> * Description: Cross tool link text, refer to u-boot.lds * ChangeLog: 1, Release initial version on "Mon Mar 21 21:09:52 CST 2011" ***********************************************************************/ OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") OUTPUT_ARCH(arm) ENTRY(_start) SECTIONS{ . = 0x33000000; .text : { start.o(.text*) /* by fulinux modified */ *(.text*) *(.rodata) } .data ALIGN(4): { *(.data) } .bss ALIGN(4): { *(.bss) }
# *********************************************************************** # * File: makefile # * Version: 1.0.0 # * Copyright: 2011 (c) Guo Wenxue <guowenxue@gmail.com> # * Description: Makefile used to cross compile the ASM and C source code # * ChangeLog: 1, Release initial version on "Mon Mar 21 21:09:52 CST 2011" # * # *********************************************************************** BINAME = beep TEXTBASE = 0x33000000 CROSS = /opt/buildroot-2012.08/arm920t/usr/bin/arm-linux- CC = $(CROSS)gcc LD = $(CROSS)ld AR = $(CROSS)ar OBJCOPY = $(CROSS)objcopy OBJDUMP = $(CROSS)objdump STRIP = $(CROSS)strip READELF = $(CROSS)readelf CFLAGS = -g -O2 -Wall -nostdinc -nostdlib -fno-builtin AFLAGS = $(CFLAGS) -D__ASSEMBLY__ LDSCRIPT = ${BINAME}.lds LDFLAGS = -nostartfiles -T $(LDSCRIPT) -Ttext $(TEXTBASE) SRC_C = $(wildcard *.c) SRC_S = $(wildcard *.S) OBJ_C = $(patsubst %.c,%.o,$(SRC_C)) OBJ_S = $(patsubst %.S,%.o,$(SRC_S)) OBJ_ALL = $(OBJ_C) $(OBJ_S) .PHONY : all all: ${OBJ_ALL} ${LD} $(LDFLAGS) -o ${BINAME}.elf ${OBJ_ALL} ${OBJCOPY} -O binary -S ${BINAME}.elf ${BINAME}.bin rm -f *.elf *.o %.o: %.S $(CC) $(AFLAGS) -c -o $@ $< %.o: %.c $(CC) $(CFLAGS) -c -o $@ $< install: cp ${BINAME}.bin ~/winxp -f --reply=yes clean: rm -f *.elf *.o rm -f ${BINAME}.bin
LDSCRIPT = ${BINAME}.lds
编译之后通过J-link将beep.bin程序烧了录到SDRAM中去执行:
h speed 12000 loadbin D:\kupan\temp\beep.bin 0x33000000 setpc 0x33000000 g
/*********************************************************************** * File: led.c * Version: 1.0.0 * Copyright: 2011 (c) Guo Wenxue <guowenxue@gmail.com> * Description: This C code used to turn LED0~LED4 on on FL2440 board * ChangeLog: 1, Release initial version on "Mon Mar 21 21:09:52 CST 2011" * Modify: fulinux@sina.com ***********************************************************************/ #define GPBCON (*(unsigned long volatile *)0x56000010) #define GPBDAT (*(unsigned long volatile *)0x56000014) #define GPBUP (*(unsigned long volatile *)0x56000018) #define LED0 5 /*LED0 use GPB5*/ #define LED1 6 /*LED1 use GPB6*/ #define LED2 7 /*LED2 use GPB7*/ #define LED3 8 /*LED3 use GPB8*/ #define DELAY_TIME 40000000 static inline void delay (unsigned long loops) { __asm__ volatile ("1:\n" "subs %0, %1, #1\n" "bne 1b":"=r" (loops):"0" (loops)); } void led_init(void) { /* Set GPB5,GPB6,GPB7,GPB8 as GPIO mode(0x01) */ GPBCON = (GPBCON & ~0x3FC00) | 0x15400; GPBUP &= ~0x01E0; /* Set GPB5,GPB6,GPB7,GPB8 as high level, to turn LED0,LED1,LED2,LED3 off */ GPBDAT |= 0x01E0; } void led_off(void) { /* Set GPB5,GPB6,GPB7,GPB8 as high level, to turn LED0,LED1,LED2,LED3 off */ GPBDAT |= 0x01E0; delay(DELAY_TIME); } void led_on(int led) { /* Turn LED0 on */ GPBDAT &= ~(1<<led); delay(DELAY_TIME); } int main(void) { led_init(); while(1) { led_off(); led_on(LED0); led_on(LED1); led_on(LED2); led_on(LED3); } }
u-boot-2014.10移植第4天----裸机蜂鸣器程序
原文地址:http://blog.csdn.net/fulinus/article/details/40432251