Chinaunix首页 | 论坛 | 博客
  • 博客访问: 456644
  • 博文数量: 73
  • 博客积分: 3593
  • 博客等级: 中校
  • 技术积分: 912
  • 用 户 组: 普通用户
  • 注册时间: 2009-10-14 11:32
文章分类

全部博文(73)

文章存档

2013年(2)

2012年(20)

2011年(25)

2010年(12)

2009年(14)

分类: 嵌入式

2010-03-17 19:38:51

最简单程序是点几盏LED灯,相对于C语言的Hello World吧。程序只能用汇编写而不能用C语言写,因为内存还没有初始化堆栈不能用(也有人拿cache当ram用的,那需要写更多的汇编代码就此排除)。编译工具只需要gcc就可以,不用Keil、ADS这些IDE。IDE隐藏了链接和加载过程,直接使用gcc可以更了解linker/loader。

broadcom bcm4748 demo板上有gpio1/gpio2/gpio143个io上接了LED,高电平点亮。
先设置GPIO为输出,再输出高电平。宏定义如下:
/*
 *broadcom demo board have 3 leds:
 *    io1 -> D402, io2 -> D403, io14 -> D400
 */
#define chipc_base  (0xa0000000 + 0x18000000)
#define gpio_out_data    (chipc_base + 0x64)
#define gpio_out_en    (chipc_base + 0x68)

#define leds_on        ( (1 << 1) | (1 << 2)  | (1 << 14) )
 #define leds_off        (~(leds_on))
#define d402_on        ( 1 << 1)
#define d403_on        ( 2 << 1)
#define d400_on        ( 14 << 1)
#define d402_off    ( ~(1 << 1) )
#define d403_off    ( ~(2 << 1) )
#define d400_off    ( ~(14 << 1) )

#define    set_io_out()    \
        la    t0, gpio_out_en; \
        la    t1, leds_on; \
        lw    t2, 0(t0) ; \
        or    t2, t2, t1; \
        sw    t2, 0(t0) ; \
        lw    t2, 0(t0)

#define all_led_on()    \
        la    t0, gpio_out_data; \
        la    t1, leds_on; \
        lw    t2, 0(t0) ; \
        or    t2, t2, t1; \
        sw    t2, 0(t0) ; \
        lw    t2, 0(t0)
       
#define all_led_off()    \
        la    t0, gpio_out_data; \
        la    t1, leds_off; \
        lw    t2, 0(t0) ; \
        and    t2, t2, t1; \
        sw    t2, 0(t0) ; \
        lw    t2, 0(t0)
       
#define led402_on()    \
        la    t0, gpio_out_data; \
        la    t1, d402_on; \
        lw    t2, 0(t0) ; \
        or    t2, t2, t1; \
        sw    t2, 0(t0) ; \
        lw    t2, 0(t0)

#define led403_on()    \
        la    t0, gpio_out_data; \
        la    t1, d403_on; \
        lw    t2, 0(t0) ; \
        or    t2, t2, t1; \
        sw    t2, 0(t0) ; \
        lw    t2, 0(t0)
   
#define led400_on()    \
        la    t0, gpio_out_data; \
        la    t1, d400_on; \
        lw    t2, 0(t0) ; \
        or    t2, t2, t1; \
        sw    t2, 0(t0) ; \
        lw    t2, 0(t0)
       
#define led402_off()    \
        la    t0, gpio_out_data; \
        la    t1, d402_off; \
        lw    t2, 0(t0) ; \
        and    t2, t2, t1; \
        sw    t2, 0(t0) ; \
        lw    t2, 0(t0)
       
#define led403_off()    \
        la    t0, gpio_out_data; \
        la    t1, d403_off; \
        lw    t2, 0(t0) ; \
        and    t2, t2, t1; \
        sw    t2, 0(t0) ; \
        lw    t2, 0(t0)
       
#define led400_off()    \
        la    t0, gpio_out_data; \
        la    t1, d400_off; \
        lw    t2, 0(t0) ; \
        and    t2, t2, t1; \
        sw    t2, 0(t0) ; \
        lw    t2, 0(t0)
//////////////////////////////////////

在cpu上电复位入口点LED,然后就死循环。
#include "led.h"

     .text
    .globl      __mips_entry
__mips_entry :

    set_io_out();
    all_led_on();

1:    j 1b
    nop
////////////////////////////////////

Makefile文件内容如下,支持big/little endian编译开关。
#CROSS_COMPILE = mipsel-bcm-linux-
CROSS_COMPILE = sde-


# Tools.
#
AS        = $(CROSS_COMPILE)as
LD        = $(CROSS_COMPILE)ld
CC        = $(CCACHE) $(CROSS_COMPILE)gcc
CPP        = $(CROSS_COMPILE)cpp
AR        = $(CROSS_COMPILE)ar
NM        = $(CROSS_COMPILE)nm
STRIP        = $(CROSS_COMPILE)strip
OBJCOPY        = $(CROSS_COMPILE)objcopy
OBJDUMP        = $(CROSS_COMPILE)objdump

CFG_LITTLE ?= 0

# Toolchain prefix
ifeq ($(CFG_LITTLE), 1)
LD_SCRIPT = leds_little.lds
MIPS_CFLAGS = -EL
BIN_FILE = led_little.bin
MAP_FILE = led_little.map
else
LD_SCRIPT = leds_big.lds
MIPS_CFLAGS = -EB
BIN_FILE = led_big.bin
MAP_FILE = led_big.map
endif

MIPS_CFLAGS += -mabi=eabi -mlong32 -msoft-float
MIPS_CFLAGS += -march=mips32 -mgp32

CFLAGS += $(MIPS_CFLAGS)
CFLAGS += -mno-abicalls -fno-pic
AFLAGS += $(MIPS_CFLAGS)
LDFLAGS += -Bstatic -T $(LD_SCRIPT)

all: clean
    @echo "make led project now!"
    $(CC) $(CFLAGS) -c  led.S -o led.o
    $(LD) $(LDFLAGS) -Bstatic -Map $(MAP_FILE)  led.o
    $(OBJCOPY) -O binary -S a.out $(BIN_FILE)    -R .comment -R .stab -R .stabstr
   
#$(OBJCOPY) -O binary -R .reginfo -R .note -R .comment -R .mdebug -S led led.bin
   
clean:
    rm -fr *.o *.map *.bin a.out
////////////////////////////////////////

linker脚本(little endian)如下:
OUTPUT_FORMAT("elf32-tradlittlemips", "elf32-tradlittlemips", "elf32-tradlittlemips")
OUTPUT_ARCH(mips)

/*
 * 强制要求所有的MIPS平台都使用这个入口函数。
 */
ENTRY(__mips_entry)
SECTIONS
{
    /*
     * 运行于ROM的代码, 包含最初的初始化操作.
     * 通常包括CPU驱动初始化,Cache初始化,DRAM控制器初始化等.
     * 另外还包含一段数据搬移代码, 用于将后面的Text,data等数据从ROM搬移到RAM中.
     */
        . = 0xBFC00000;
        .text :
        {
        *(.text)
        *(.text.*)
        }
}
/////////////////////////////////////////

big endian linker脚本基本同上,不同的是:
OUTPUT_FORMAT("elf32-tradbigmips", "elf32-tradbigmips", "elf32-tradbigmips")
////////////////////////////////////////////////////////////////////////////

阅读(2029) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~