<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
开发环境:win7 64位 + VMware12 + Ubuntu14.04 64位
工具链:linaro提供的gcc-linaro-6.1.1-2016.08-x86_64_arm-linux-gnueabi
要移植的u-boot版本:u-boot-2016-11
Tiny4412开发板硬件版本为:
底板: Tiny4412/Super4412SDK 1506
核心板:Tiny4412 - 1412
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
在上一节中我们为tiny4412开发板添加相应目录文件,并且可以顺利编译通过生成.bin文件。接下来我们通过点亮tiny4412核心板上的LED灯开始调试u-boot。
1、Tiny4412 LED硬件原理图与exynos4412相关引脚寄存器
从Tiny4412-1412-Schematic.pdf原理图上可以看到板子上的四个LED硬件连接如下图所示:
LED1~LED4分别跟GPM4_0~GPM4_3相接。
exynos4412 GPM4相关的寄存器如下:
现在我们只是想简单的点亮exynos4412 GPM4管脚上的LED灯,需要设置GPM4CON和GPM4DAT寄存器,这两个寄存器的相关描述如下:
2、添加LED灯代码
在arch/arm/cpu/armv7/start.S中添加点亮LED的代码。
diff --git a/arch/arm/cpu/armv7/start.S b/arch/arm/cpu/armv7/start.S index 691e5d3..4496f2f 100755 --- a/arch/arm/cpu/armv7/start.S +++ b/arch/arm/cpu/armv7/start.S @@ -47,6 +47,7 @@ save_boot_params_ret: orr r0, r0, #0xc0 @ disable FIQ and IRQ msr cpsr,r0
+ bl light_led /* * Setup vector: * (OMAP4 spl TEXT_BASE is not 32 byte aligned. @@ -63,6 +64,8 @@ save_boot_params_ret: mcr p15, 0, r0, c12, c0, 0 @Set VBAR #endif
+ + /* the mask ROM code should have PLL and others stable */ #ifndef CONFIG_SKIP_LOWLEVEL_INIT bl cpu_init_cp15 @@ -272,3 +275,18 @@ ENTRY(cpu_init_crit) b lowlevel_init @ go setup pll,mux,memory ENDPROC(cpu_init_crit) #endif + + .globl light_led +light_led: + ldr r0,=0x110002E0 @ set GPM4CON Register + ldr r1,=0x00001111 @ Configurate GPM4_0<A1>GPM4_1<A2>GPM4_2<A2>GPM4_3 output + str r1,[r0] + + ldr r0,=0x110002E4 @ set GPM4DAT Register +@ mov r1,#0xFE @ light All led1 on +@ mov r1,#0xFD @ light All led2 on +@ mov r1,#0xFB @ light All led3 on +@ mov r1,#0xF7 @ light All led4 on + mov r1,#0xF0 @ light All led on + str r1,[r0] + mov pc, lr
|
3、修改board/samsung/tiny4412/tools/mktiny4412spl.c文件,用于生成BL2
(在《X-003 FriendlyARM tiny4412 uboot移植之添加相应目录文件》中已经修改好了mktiny4412spl.c文件,这步可以省略)
diff --git a/board/samsung/tiny4412/tools/mktiny4412spl.c b/board/samsung/tiny4412/tools/mktiny4412spl.c index 3ed20ef..c3a3e29 100755 --- a/board/samsung/tiny4412/tools/mktiny4412spl.c +++ b/board/samsung/tiny4412/tools/mktiny4412spl.c @@ -1,5 +1,6 @@ /* - * Copyright (C) 2011 Samsung Electronics + * 2016 + * Author AP0904225 <ap0904225@qq.com> * * SPDX-License-Identifier: GPL-2.0+ */ @@ -13,11 +14,9 @@ #include <sys/stat.h>
#define BUFSIZE (16*1024) -#define IMG_SIZE (16*1024) -#define SPL_HEADER_SIZE 16 +#define IMG_SIZE ( (14*1024)- 4 ) #define FILE_PERM (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) -#define SPL_HEADER "S5PC210 HEADER " /* * Requirement: * IROM code reads first 14K bytes from boot device. @@ -37,7 +36,8 @@ int main(int argc, char **argv) int i, len; unsigned char buffer[BUFSIZE] = {0}; int ifd, ofd; - unsigned int checksum = 0, count; + unsigned int checksum = 0; + unsigned int count = 0;
if (argc != 3) { printf(" %d Wrong number of arguments ", argc); @@ -52,7 +52,7 @@ int main(int argc, char **argv) }
ofd = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, FILE_PERM); - if (ifd < 0) { + if (ofd < 0) { fprintf(stderr, "%s: Can't open %s: %s ", argv[0], argv[2], strerror(errno)); if (ifd) @@ -63,12 +63,9 @@ int main(int argc, char **argv) len = lseek(ifd, 0, SEEK_END); lseek(ifd, 0, SEEK_SET);
- memcpy(&buffer[0], SPL_HEADER, SPL_HEADER_SIZE); - - count = (len < (IMG_SIZE - SPL_HEADER_SIZE)) - ? len : (IMG_SIZE - SPL_HEADER_SIZE); + count = (len < IMG_SIZE )? len : IMG_SIZE; //14K-4
- if (read(ifd, buffer + SPL_HEADER_SIZE, count) != count) { + if (read(ifd, buffer, count) != count) { fprintf(stderr, "%s: Can't read %s: %s ", argv[0], argv[1], strerror(errno));
@@ -80,14 +77,11 @@ int main(int argc, char **argv) exit(EXIT_FAILURE); }
- for (i = 0; i < IMG_SIZE - SPL_HEADER_SIZE; i++) - checksum += buffer[i+16]; - - *(ulong *)buffer ^= 0x1f; - *(ulong *)(buffer+4) ^= checksum; - - for (i = 1; i < SPL_HEADER_SIZE; i++) - buffer[i] ^= buffer[i-1]; + for(i = 0;i < IMG_SIZE;i++) + { + checksum += (unsigned char)(buffer[i]); + } + *(unsigned int*)(buffer+i) = checksum;
if (write(ofd, buffer, BUFSIZE) != BUFSIZE) { fprintf(stderr, "%s: Can't write %s: %s ",
|
4、拷贝sd_fuse文件夹到u-boot根目录下
sd_fuse文件夹下包含的文件有:
4.1、exynos4412启动所需的二进制固件:E4412_N.bl1.bin、E4412_tzsw.bin
4.2、fast_fuse.sh
# # Copyright (C) 2011 Samsung Electronics Co., Ltd. # http://www.samsung.com/ # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 as # published by the Free Software Foundation. # ####################################
if [ -z $1 ] then echo "usage: ./sd_fusing.sh <SD Reader's device file>" exit 0 fi
if [ -b $1 ] then echo "$1 reader is identified." else echo "$1 is NOT identified." exit 0 fi
#################################### #<verify device>
BDEV_NAME=`basename $1` BDEV_SIZE=`cat /sys/block/${BDEV_NAME}/size`
if [ ${BDEV_SIZE} -le 0 ]; then echo "Error: NO media found in card reader." exit 1 fi
if [ ${BDEV_SIZE} -gt 32000000 ]; then echo "Error: Block device size (${BDEV_SIZE}) is too large" exit 1 fi
#################################### # check files
E4412_UBOOT=../../u-boot.bin MKBL2=../mkbl2
if [ ! -f ${E4412_UBOOT} ]; then echo "Error: u-boot.bin NOT found, please build it & try again." exit -1 fi
if [ ! -f ${MKBL2} ]; then echo "Error: can not find host tool - mkbl2, stop." exit -1 fi
#<make bl2> ${MKBL2} ${E4412_UBOOT} bl2.bin 14336
#################################### # fusing images
bl2_position=17 uboot_position=49
#<BL2 fusing> echo "---------------------------------------" echo "BL2 fusing" dd iflag=dsync oflag=dsync if=./bl2.bin of=$1 seek=$bl2_position
#<u-boot fusing> echo "---------------------------------------" echo "u-boot fusing" dd iflag=dsync oflag=dsync if=${E4412_UBOOT} of=$1 seek=$uboot_position
#<flush to disk> sync
#################################### #<Message Display> echo "---------------------------------------" echo "U-boot image is fused (at `date +%T`) successfully." echo "Eject SD card and insert it again." |
4.3、sd_fdisk.c
/* * Copyright (c) 2010 Samsung Electronics Co., Ltd. * http://www.samsung.com/ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */
#include <stdio.h> #include <stdlib.h> #include <string.h>
#define BLOCK_SIZE 512 #define BLOCK_END 0xFFFFFFFF #define _10MB (10*1024*1024) #define _100MB (100*1024*1024) #define _8_4GB (1023*254*63)
#define CHS_MODE 0 #define LBA_MODE !(CHS_MODE)
typedef struct { int C_start; int H_start; int S_start;
int C_end; int H_end; int S_end;
int available_block; int unit; int total_block_count; int addr_mode; // LBA_MODE or CHS_MODE } SDInfo;
typedef struct { unsigned char bootable; unsigned char partitionId;
int C_start; int H_start; int S_start;
int C_end; int H_end; int S_end;
int block_start; int block_count; int block_end; } PartitionInfo;
///////////////////////////////////////////////////////////////// int calc_unit(int length, SDInfo sdInfo) { if (sdInfo.addr_mode == CHS_MODE) return ( (length / BLOCK_SIZE / sdInfo.unit + 1 ) * sdInfo.unit);
else return ( (length / BLOCK_SIZE) ); }
///////////////////////////////////////////////////////////////// void encode_chs(int C, int H, int S, unsigned char *result) { *result++ = (unsigned char) H; *result++ = (unsigned char) ( S + ((C & 0x00000300) >> 2) ); *result = (unsigned char) (C & 0x000000FF); }
///////////////////////////////////////////////////////////////// void encode_partitionInfo(PartitionInfo partInfo, unsigned char *result) { *result++ = partInfo.bootable;
encode_chs(partInfo.C_start, partInfo.H_start, partInfo.S_start, result); result +=3;
*result++ = partInfo.partitionId;
encode_chs(partInfo.C_end, partInfo.H_end, partInfo.S_end, result); result += 3;
*((int *)result) = partInfo.block_start; result += 4;
*((int *)result) = partInfo.block_count; }
///////////////////////////////////////////////////////////////// void get_SDInfo(int block_count, SDInfo *sdInfo) { int C, H, S;
int C_max = 1023, H_max = 255, S_max = 63; int H_start = 1, S_start = 1; int diff_min = 0, diff = 0;
if(block_count >= _8_4GB) sdInfo->addr_mode = LBA_MODE; else sdInfo->addr_mode = CHS_MODE;
if (sdInfo->addr_mode == CHS_MODE) { diff_min = C_max;
for (H = H_start; H <= H_max; H++) for (S = S_start; S <= S_max; S++) { C = block_count / (H * S);
if ( (C <= C_max) ) { diff = C_max - C; if (diff <= diff_min) { diff_min = diff; sdInfo->C_end = C; sdInfo->H_end = H; sdInfo->S_end = S; } } } } else { sdInfo->C_end = 1023; sdInfo->H_end = 254; sdInfo->S_end = 63; }
sdInfo->C_start = 0; sdInfo->H_start = 1; sdInfo->S_start = 1;
sdInfo->total_block_count = block_count; sdInfo->available_block = sdInfo->C_end * sdInfo->H_end * sdInfo->S_end; sdInfo->unit = sdInfo->H_end * sdInfo->S_end; }
///////////////////////////////////////////////////////////////// void make_partitionInfo(int LBA_start, int count, SDInfo sdInfo, PartitionInfo *partInfo) { int temp = 0; int _10MB_unit;
partInfo->block_start = LBA_start;
if (sdInfo.addr_mode == CHS_MODE) { partInfo->C_start = partInfo->block_start / (sdInfo.H_end * sdInfo.S_end); temp = partInfo->block_start % (sdInfo.H_end * sdInfo.S_end); partInfo->H_start = temp / sdInfo.S_end; partInfo->S_start = temp % sdInfo.S_end + 1;
if (count == BLOCK_END) { _10MB_unit = calc_unit(_10MB, sdInfo); partInfo->block_end = sdInfo.C_end * sdInfo.H_end * sdInfo.S_end - _10MB_unit - 1; partInfo->block_count = partInfo->block_end - partInfo->block_start + 1;
partInfo->C_end = partInfo->block_end / sdInfo.unit; partInfo->H_end = sdInfo.H_end - 1; partInfo->S_end = sdInfo.S_end; } else { partInfo->block_count = count;
partInfo->block_end = partInfo->block_start + count - 1; partInfo->C_end = partInfo->block_end / sdInfo.unit;
temp = partInfo->block_end % sdInfo.unit; partInfo->H_end = temp / sdInfo.S_end; partInfo->S_end = temp % sdInfo.S_end + 1; } } else { partInfo->C_start = 0; partInfo->H_start = 1; partInfo->S_start = 1;
partInfo->C_end = 1023; partInfo->H_end = 254; partInfo->S_end = 63;
if (count == BLOCK_END) { _10MB_unit = calc_unit(_10MB, sdInfo); partInfo->block_end = sdInfo.total_block_count - _10MB_unit - 1; partInfo->block_count = partInfo->block_end - partInfo->block_start + 1;
} else { partInfo->block_count = count; partInfo->block_end = partInfo->block_start + count - 1; } } }
///////////////////////////////////////////////////////////////// int get_sd_block_count(char *devicefile) { FILE *fp; char buf[128];
int block_count = 0; int nbytes = 0;
char *t = "/sys/block/"; char sd_size_file[64];
strcpy(sd_size_file, t); strcat(sd_size_file, &devicefile[5]); strcat(sd_size_file, "/size");
fp = fopen(sd_size_file, "rb"); nbytes = fread(buf, 1, 128, fp); fclose(fp);
block_count = atoi(buf);
return block_count; }
///////////////////////////////////////////////////////////////// int main(int argc, char *argv[]) { FILE *fp;
int total_block_count; int block_start = 0, block_offset = 0;
SDInfo sdInfo; PartitionInfo partInfo[4];
unsigned char mbr[512];
if (argc != 2) { printf("Usage: sd_fdisk <device_file> "); return -1; } /////////////////////////////////////////////////////////// memset((unsigned char *)&sdInfo, 0x00, sizeof(SDInfo));
/////////////////////////////////////////////////////////// total_block_count = get_sd_block_count(argv[1]); get_SDInfo(total_block_count, &sdInfo); /* /////////////////////////////////////////////////////////// // 반드시 Unit단위로 먼저 계산한다. block_start = calc_unit(_10MB, sdInfo); block_offset = calc_unit(_100MB, sdInfo);
/////////////////////////////////////////////////////////// partInfo[0].bootable = 0x00; partInfo[0].partitionId = 0x83;
make_partitionInfo(block_start, block_offset, sdInfo, &partInfo[0]);
/////////////////////////////////////////////////////////// block_start += block_offset;
partInfo[1].bootable = 0x00; partInfo[1].partitionId = 0x83;
make_partitionInfo(block_start, block_offset, sdInfo, &partInfo[1]);
/////////////////////////////////////////////////////////// block_start += block_offset; partInfo[2].bootable = 0x00; partInfo[2].partitionId = 0x83;
make_partitionInfo(block_start, block_offset, sdInfo, &partInfo[2]); */ /////////////////////////////////////////////////////////// // block_start += block_offset; block_start = calc_unit(_10MB, sdInfo);
block_offset += BLOCK_END; partInfo[3].bootable = 0x00; partInfo[3].partitionId = 0x0C;
make_partitionInfo(block_start, BLOCK_END, sdInfo, &partInfo[3]);
/////////////////////////////////////////////////////////// memset(mbr, 0x00, sizeof(mbr)); mbr[510] = 0x55; mbr[511] = 0xAA;
// encode_partitionInfo(partInfo[0], &mbr[0x1CE]); // encode_partitionInfo(partInfo[1], &mbr[0x1DE]); // encode_partitionInfo(partInfo[2], &mbr[0x1EE]); encode_partitionInfo(partInfo[3], &mbr[0x1BE]);
fp = fopen("sd_mbr.dat", "wb"); fwrite(mbr, 1, sizeof(mbr), fp); fclose(fp);
return 0; } |
4.4、sd_fusing.sh
# # Copyright (C) 2011 Samsung Electronics Co., Ltd. # http://www.samsung.com/ # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 as # published by the Free Software Foundation. # ####################################
if [ -z $1 ] then echo "usage: ./sd_fusing.sh <SD Reader's device file>" exit 0 fi
if [ -b $1 ] then echo "$1 reader is identified." else echo "$1 is NOT identified." exit 0 fi
#################################### #<verify device>
BDEV_NAME=`basename $1` BDEV_SIZE=`cat /sys/block/${BDEV_NAME}/size`
if [ ${BDEV_SIZE} -le 0 ]; then echo "Error: NO media found in card reader." exit 1 fi
if [ ${BDEV_SIZE} -gt 32000000 ]; then echo "Error: Block device size (${BDEV_SIZE}) is too large" exit 1 fi
#################################### # check files
#################################### # fusing images
signed_bl1_position=1 bl2_position=17 uboot_position=49 tzsw_position=705
#<BL1 fusing> echo "---------------------------------------" echo "BL1 fusing" dd iflag=dsync oflag=dsync if=./E4412_N.bl1.bin of=$1 seek=$signed_bl1_position
#<tiny4412-spl.bin fusing> echo "---------------------------------------" echo "tiny4412-spl.bin fusing" dd iflag=dsync oflag=dsync if=./spl/tiny4412-spl.bin of=$1 seek=$bl2_position
#<u-boot fusing> #echo "---------------------------------------" #echo "u-boot fusing" #dd iflag=dsync oflag=dsync if=${E4412_UBOOT} of=$1 seek=$uboot_position
#<TrustZone S/W fusing> #echo "---------------------------------------" #echo "TrustZone S/W fusing" #dd iflag=dsync oflag=dsync if=./E4412_tzsw.bin of=$1 seek=$tzsw_position
#<flush to disk> sync
#################################### #<Message Display> echo "---------------------------------------" echo "U-boot image is fused successfully." echo "Eject SD card and insert it again." |
5、u-boot根目录下添加编译脚本文件build-tiny4412.sh
echo "*******clean*********" make distclean
echo "------------config tiny4412------------" make ARCH=arm tiny4412_defconfig
echo "----------------building--------------------" make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi-
|
在u-boot根目录下执行build-tiny4412.sh编译完成后,会生成spl/tiny4412-spl.bin,通过SD卡烧写脚本sd_fusing.sh把E4412_N.bl1.bin和tiny4412-spl.bin烧写到相应的位置。把SD卡插到tiny4412开发板的SD卡槽上,选择从SD卡启动,开发板上电后应该可以看到点亮了相应的LED灯。