uboot学习:orangepi one使用汇编点亮LED

1、编写Makefile
链接时使用-T参数指明链接器脚本

CC = arm-linux-gnueabihf-gcc
LD = arm-linux-gnueabihf-ld
OBJCOPY = arm-linux-gnueabihf-objcopy

all : start.o
	$(LD) -Tgboot.lds -o gboot.elf $^
	$(OBJCOPY) -O binary gboot.elf gboot.bin

%.o : %.S
	$(CC) -g -c $^
%.o : %.c
	$(CC) -g -c $^


clean:
	rm -rf gboot.elf gboot.bin *.o

2、编写链接器脚本gboot.lds
指定输出格式,使用的架构,定义代码段、数据段、bss段

OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)	/*指明运行的第一个文件中的_start*/
SECTIONS
{
	. = 0x00000000;

	. = ALIGN(4);
	.text :
	{
		start.o(.text*) 	/*指明运行的第一个文件是start.o*/
		*(.text*)
	}

	. = ALIGN(4);
	.data :
	{
		*(.data*)
	}

	. = ALIGN(4);
	bss_start = .;
	.bss :
	{
		*(.bss*)
	}
	bss_end = .;
	
}

3、编写start.S点亮LED
led使用原理图中的STATUS-LED
在这里插入图片描述
对应的GPIO为PA15
在这里插入图片描述
查看GPIO控制寄存器和数据寄存器地址
在这里插入图片描述

PA15控制寄存器,最高位配置001时为输出模式
在这里插入图片描述
PA15数据寄存器
在这里插入图片描述

编写start.S点亮LED

.global _start

_start :

/*循环闪烁*/
main_loop :
	bl led_on
	bl delay
	bl led_off
	bl delay
	b main_loop


#define PACFG1		0x01C20804
#define PADAT		0x01C20810

led_on :
	ldr r0, = 0x17777777   /* 这里ldr 为伪指令 */
    ldr r1, = PACFG1
    str r0, [r1]          /* 寄存器间接寻址 将r0的值给r1所指地址的内存中,配置GPIO PA15为输出模式  */

    ldr r0, = (1<<15) 	  /* PA15, 在数据寄存器的第15位输出高电平 */
    ldr r1, = PADAT
    str r0, [r1]          /* 点亮 */
    mov pc, lr

led_off :
	ldr r0, = 0x17777777   /* 这里ldr 为伪指令 */
    ldr r1, = PACFG1
    str r0, [r1]          /* 寄存器间接寻址 将r0的值给r1所指地址的内存中,配置GPIO PA15为输出模式  */

    ldr r0, = (0<<15)	 	  /* PA15, 在数据寄存器的第15位输出低电平 */
    ldr r1, = PADAT
    str r0, [r1]          /* 灭灯 */
    mov pc, lr

delay:
    mov r2, #0x40000
    mov r3, #0
delay_loop:
    sub r2, r2, #1    /* r2=r2-1  */
    cmp r2, r3        /* cmp 比较r2 r3 如果相等 Z 为1  */
    bne delay_loop    /* bne 为当Z为1时执行跳转  bne 为 b+后缀  */
    mov pc, lr        /* 函数调用返回  mov 为 寄存器间寻址  */    






执行make编译,编译完成生成gboot.bin文件,直接烧写到SD卡,从SD卡启动没有点亮LED

4、需要添加校验
校验代码mksunxiboot.c

/*
 * (C) Copyright 2007-2011
 * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
 * Tom Cubie <tangliang@allwinnertech.com>
 *
 * a simple tool to generate bootable image for sunxi platform.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307 USA
 */

#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>

typedef unsigned char u8;
typedef unsigned int u32;

/* boot head definition from sun4i boot code */
typedef struct boot_file_head
{
	u32  jump_instruction;   // one intruction jumping to real code
	u8   magic[8];           // ="eGON.BT0" or "eGON.BT1",  not C-style string.
	u32  check_sum;          // generated by PC
	u32  length;             // generated by PC
	u32  pub_head_size;      // the size of boot_file_head_t
	u8   pub_head_vsn[4];    // the version of boot_file_head_t
	u8   file_head_vsn[4];   // the version of boot0_file_head_t or boot1_file_head_t
	u8   Boot_vsn[4];        // Boot version
	u8   eGON_vsn[4];        // eGON version
	u8   platform[8];        // platform information
}boot_file_head_t;

#define BOOT0_MAGIC                     "eGON.BT0"
#define STAMP_VALUE                     0x5F0A6C39
/* check sum functon from sun4i boot code */
int gen_check_sum( void *boot_buf )
{
	boot_file_head_t  *head_p;
	u32 length;
	u32 *buf;
	u32 loop;
	u32 i;
	u32 sum;

	head_p = (boot_file_head_t *)boot_buf;
	length = head_p->length;
	if( ( length & 0x3 ) != 0 )                   // must 4-byte-aligned
		return -1;
	buf = (u32 *)boot_buf;
	head_p->check_sum = STAMP_VALUE;              // fill stamp
	loop = length >> 2;
	/* calculate the sum */
	for( i = 0, sum = 0;  i < loop;  i++ )
		sum += buf[i];

	/* write back check sum */
	head_p->check_sum = sum;

	return 0;
}

#define ALIGN(x,a)      __ALIGN_MASK((x),(typeof(x))(a)-1)
#define __ALIGN_MASK(x,mask)    (((x)+(mask))&~(mask))

#define SUN4I_SRAM_SIZE (24 * 1024)
#define SRAM_LOAD_MAX_SIZE (SUN4I_SRAM_SIZE - sizeof(boot_file_head_t))
#define BLOCK_SIZE 512
struct boot_img {
	boot_file_head_t header;
	char code[SRAM_LOAD_MAX_SIZE];
	char pad[BLOCK_SIZE];
};

int main(int argc, char * argv[])
{
	int fd_in, fd_out;
	struct boot_img img;
	unsigned file_size, load_size;
	int count;

	if(argc < 2) {
		printf("\tThis program makes an input bin file to sun4i bootable image.\n"
				"\tUsage: %s input_file out_putfile\n", argv[0]);
		return EXIT_FAILURE;
	}

	fd_in = open(argv[1], O_RDONLY);
	if(fd_in < 0) {
		perror("Open input file:");
		return EXIT_FAILURE;
	}

	fd_out = open(argv[2], O_WRONLY|O_CREAT, 0666);
	if(fd_out < 0) {
		perror("Open output file:");
		return EXIT_FAILURE;
	}

	memset((void *)img.pad, 0, BLOCK_SIZE);

	/* get input file size */
	file_size = lseek(fd_in, 0, SEEK_END);
	printf("File size: 0x%x \n", file_size);

	if(file_size > SRAM_LOAD_MAX_SIZE) {
		load_size = SRAM_LOAD_MAX_SIZE;
	} else {
		load_size = ALIGN(file_size, sizeof(int));
	}
	printf("Load size: 0x%x \n", load_size);

	/* read file to buffer to calculate checksum */
	lseek(fd_in, 0, SEEK_SET);
	count = read(fd_in, img.code, load_size);
	printf("Read 0x%x bytes\n", count);

	/* fill the header */
	img.header.jump_instruction =    /* b instruction */
			0xEA000000 |             /* jump to the first instruction after the header */
			(
				(sizeof(boot_file_head_t) / sizeof(int) - 2)
				& 0x00FFFFFF
			);
	memcpy(img.header.magic, BOOT0_MAGIC, 8);    /* no '0' termination */
	img.header.length = ALIGN(load_size + sizeof(boot_file_head_t), BLOCK_SIZE);
	gen_check_sum((void *)&img);

	count = write(fd_out, (void *)&img, img.header.length);
	printf("Write 0x%x bytes\n", count);

	close(fd_in);
	close(fd_out);

	return EXIT_SUCCESS;
}

编译mksunxiboot.c文件,注意这里不是交叉编译
gcc mksunxiboot.c -o mksunxiboot

添加校验
./mksunxiboot gboot.bin gboot-sdcard.bin

烧写到sd卡启动
sudo dd if=gboot-sdcard.bin of=/dev/sdb bs=1k seek=8

全部代码可以在以下链接下载:
https://download.csdn.net/download/wujiewei2342/11005419

5、总结
为学习uboot铺垫
1、链接器脚本是在Makefile中指定的,uboot也是
2、这里start.S没有关闭看门狗,因为orangepi one看门狗是默认关闭的
3、点亮led方便移植uboot时进行调试

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值