嵌入式的HelloWorld

最简单程序是点几盏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")


<script>window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSize":"16"},"share":{}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];</script>
阅读(1105) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~
评论热议
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值