硬件平台:tq2440
开发环境:Ubuntu⑶.11
u-boot版本:2014.10
本文允许转载,请注明出处:http://blog.csdn.net/fulinus
1、蜂鸣器asm汇编程序:
/***********************************************************************
* 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文件与昨天的文件1样,只是将履行文件名改了1下:
BINAME = beep
2、ARM汇编和C语言结合
从asm中跳转到C函数中也是1个重要的技术要点,我们在ARM汇编程序中要做以下工作
1、关看门狗;
2、屏蔽中断;
3、跳转到C代码中的main函数中去。
1、ARM汇编程序
/***********************************************************************
* 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
2、C语言程序
/***********************************************************************
* 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:
"
"subs %0, %1, #1
"
"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汇编的代码段放在首位,因此需要告知编译器如何编译和连接。有1个lds文件,该文件中的内容决定程序中各个代码段的位置摆放关系,可以在下面的makefile文件中看到是如何将该文件传给编译器的。
3、lds文件
/***********************************************************************
* 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)
}
4、makefile文件
# ***********************************************************************
# * 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⑵012.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
即是beep.lds文件。
5、编译运行
编译以后通过J-link将beep.bin程序烧了录到SDRAM中去履行:
h
speed 12000
loadbin D:kupan empeep.bin 0x33000000
setpc 0x33000000
g
你就能够听到天籁之音了!
3、led跑马灯的ARM汇编与C语言程序
LED跑马灯C程序以下:
/***********************************************************************
* 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:
"
"subs %0, %1, #1
"
"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);
}
}
其他部份文件雷同,稍作修改。