系列文章目录
移植Linux0.11到Hi3518EV200开发板之GPIO操作
前言
通过基础实验点亮LED灯,可以熟悉目标硬件平台的一些基础知识:比如内存地址空间范围,复用引脚如何配置、GPIO如何操作、如何编写裸机的Makefile等。
1. 裸机程序的执行流程
? 裸机程序skymixos.bin的功能只是简单的点亮2盏LED,是由u-boot加载执行的,就像嵌入式Linux由u-boot加载执行一样。
2. 实现分析
2.1 硬件原理图
引脚标识? ? ? ? ? ? ? ? ? ? ? ? GPIO? ? ? ? ? ? ? ? ? ? ? ? 备注
------------------------------------------------------------------------------------------------------------
PWM1/GPIO7_3? ? ? ? ? ? GPIO7_3? ? ? ? ? ? ? ? 拉低,点亮LED
PWM2/GPIO7_4? ? ? ? ? ? ?GPIO7_4? ? ? ? ? ? ? ?拉低,点亮LED
------------------------------------------------------------------------------------------------------------
从原理图中可以看出,要点亮LED,只需要将海思上对应的GPIO输出低电平即可。对于GPIO的操作一般分为以下几步:
- 将对应的复用引脚配置为GPIO功能
- 将GPIO配置为输出,然后即可输出高低电平
2.2 代码分析
? 从上面的执行流程可以看出,可执行程序skymixos.bin是u-boot执行后加载执行的。因此,此时的硬件平台已经完成了CPU,内存相关的初始化。在执行C代码执行,我们简单的设置一下栈指针寄存器就可以跳转到C代码执行。head.S就是使用汇编代码完成最简单的初始化,就跳转到C代码执行:
head.S实现代码如下:
.extern main
.text
.global _start
_start:
ldr sp, =0x84000000 /* 将栈设置在内存地址0x84000000处 */
ldr lr, =halt_loop /* 设置跳转返回的目标 */
ldr pc, =main /* 跳转到main标号处执行 */
halt_loop:
b halt_loop /* 从main函数返回后将在此处死循环 */
main函数在main.c中实现,点亮LED的代码也是在main中调用led_test实现的。
#include "platform.h"
#include "osal_io.h"
/*
* muxctrl_reg59 0x0ec bit[0] 0: PWM1; 1: GPIO7_3
* muxctrl_reg60 0x0f0 bit[1:0] 00: PWM2; 01: GPIO7_4; 10: SPI1_CSN1; 其他: 保留
*/
#define MUXCTRL_REG59_OFF 0x0EC
#define MUXCTRL_REG60_OFF 0x0F0
static void pinmux_init()
{
/* 将控制LED的两个GPIO复用引脚配置为GPIO功能 */
OSAL_WRITEL(0x1, IO_CONFIG_REG_BASE + MUXCTRL_REG59_OFF);
OSAL_WRITEL(0x1, IO_CONFIG_REG_BASE + MUXCTRL_REG60_OFF);
}
void led_test()
{
pinmux_init();
OSAL_WRITEL(1 << 3 | 1 << 4, GPIO7_REG_BASE + 0x400);
OSAL_WRITEL(0x00, GPIO7_REG_BASE + 0x3FC); // 点亮2盏LED
}
int main(void)
{
led_test();
return 0;
}
这个裸机程序的Makefile的实现也很简单:
CROSS_COMPLIE_PREFIX=arm-himix200-linux-
CC = ${CROSS_COMPLIE_PREFIX}gcc
LD = ${CROSS_COMPLIE_PREFIX}ld
AR = ${CROSS_COMPLIE_PREFIX}ar
OBJCOPY = ${CROSS_COMPLIE_PREFIX}objcopy
OBJDUMP = ${CROSS_COMPLIE_PREFIX}objdump
INCLUDEDIR := $(shell pwd)/include
CFLAGS := -Wall -O2
CPPFLAGS := -nostdinc -I$(INCLUDEDIR)
export CC LD AR OBJCOPY OBJDUMP INCLUDEDIR CFLAGS CPPFLAGS
TARGET := skymixos
objs := head.o main.o led.o
${TARGET}.bin: $(objs)
${LD} -T${TARGET}.lds -o ${TARGET}_elf $^
${OBJCOPY} -O binary -S ${TARGET}_elf $@
${OBJDUMP} -D -m arm ${TARGET}_elf > ${TARGET}.dis
%.o:%.c
${CC} $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
%.o:%.S
${CC} $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
clean:
rm -f ${TARGET}.bin ${TARGET}_elf ${TARGET}.dis *.o
在Makefile中指定了链接脚本为skymixos.lds,而在链接脚本中指定程序的链接地址以及各段的排布。
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
. = 0x82000000;
. = ALIGN(4);
.text :
{
__text_start = .;
head.o
__init_end = .;
ASSERT(((__init_end - __text_start) < 0x4000), "init sections too big!");
*(.text)
}
. = ALIGN(4);
.rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
. = ALIGN(4);
.data : { *(.data) }
. = ALIGN(4);
.got : { *(.got) }
__u_boot_cmd_start = .;
.u_boot_cmd : { *(.u_boot_cmd) }
__u_boot_cmd_end = .;
. = ALIGN(4);
__bss_start = .;
.bss : { *(.bss) }
_end = .;
}
参考u-boot的实现。起始的链接地址为0x82000000,测试时,使用tftp将程序skymixos.bin加载到0x82000000处执行即可。
2.3 测试
? 开发板上电后,进入u-boot的交互模式。通过tftp下载skymixos.bin到内存地址0x82000000处执
行。
SPI Nor(cs 0) ID: 0xc2 0x20 0x18
Block:64KB Chip:16MB Name:"MX25L128XX"
SPI Nor total size: 16MB
Cannot found a valid SPI Nand Device
MMC:
EMMC/MMC/SD controller initialization.
Card did not respond to voltage select!
No EMMC/MMC/SD device found !
In: serial
Out: serial
Err: serial
Hit any key to stop autoboot: 0
hisilicon # tftp 0x82000000 skymixos.bin
Hisilicon ETH net controler
MAC: 00-00-23-34-45-66
eth0 : phy status change : LINK=DOWN : DUPLEX=FULL : SPEED=100M
eth0 : phy status change : LINK=UP : DUPLEX=FULL : SPEED=100M
TFTP from server 192.168.1.103; our IP address is 192.168.1.100
Download Filename 'skymixos.bin'.
Download to address: 0x82000000
Downloading: #################################################
done
Bytes transferred = 116 (74 hex)
hisilicon # go 0x82000000
## Starting application at 0x82000000 ...
1
?执行程序skymixos.bin后,2盏LED被电亮!!!
3. 附录
HI3518EV200 SoC内部结构:
GPIO寄存器:
?
总结
? 通过简单裸机点亮LED的裸机程序为后面Linux0.11移植奠定了基础。千里之行,始于足下!!!
|