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