<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
开发环境: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\n", 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\n", 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\n", 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\n", |
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>\n"); 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灯。