X-004 FriendlyARM tiny4412 uboot移植之点亮指路灯

时间:2023-03-09 05:14:05
X-004 FriendlyARM tiny4412 uboot移植之点亮指路灯

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 

开发环境: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硬件连接如下图所示:

X-004 FriendlyARM tiny4412 uboot移植之点亮指路灯

X-004 FriendlyARM tiny4412 uboot移植之点亮指路灯

LED1~LED4分别跟GPM4_0~GPM4_3相接。

exynos4412 GPM4相关的寄存器如下:

X-004 FriendlyARM tiny4412 uboot移植之点亮指路灯

现在我们只是想简单的点亮exynos4412 GPM4管脚上的LED灯,需要设置GPM4CON和GPM4DAT寄存器,这两个寄存器的相关描述如下:

X-004 FriendlyARM tiny4412 uboot移植之点亮指路灯

X-004 FriendlyARM tiny4412 uboot移植之点亮指路灯

X-004 FriendlyARM tiny4412 uboot移植之点亮指路灯

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_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灯。