码迷,mamicode.com
首页 > 其他好文 > 详细

u-boot-2014.10移植第4天----裸机蜂鸣器程序

时间:2015-01-22 09:28:10      阅读:226      评论:0      收藏:0      [点我收藏+]

标签:u-boot   移植   arm汇编   c语言   lds   

硬件平台:tq2440

开发环境:Ubuntu-3.11

u-boot版本:2014.10

本文允许转载,请注明出处:http://blog.csdn.net/fulinus


一、蜂鸣器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文件与昨天的文件一样,只是将执行文件名改了一下:

BINAME = beep

二、ARM汇编和C语言结合

从asm中跳转到C函数中也是一个重要的技术要点,我们在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:\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文件中看到是如何将该文件传给编译器的。

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-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

即是beep.lds文件。

5、编译运行

编译之后通过J-link将beep.bin程序烧了录到SDRAM中去执行:

h  
speed 12000  
loadbin D:\kupan\temp\beep.bin 0x33000000  
setpc 0x33000000  
g

你就可以听到天籁之音了!



三、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:\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天----裸机蜂鸣器程序

标签:u-boot   移植   arm汇编   c语言   lds   

原文地址:http://blog.csdn.net/fulinus/article/details/40432251

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!