国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

基于全志A33開(kāi)發(fā)板linux系統(tǒng)移植學(xué)習(xí)記錄(Boot0)

這篇具有很好參考價(jià)值的文章主要介紹了基于全志A33開(kāi)發(fā)板linux系統(tǒng)移植學(xué)習(xí)記錄(Boot0)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

基于全志A33開(kāi)發(fā)板linux系統(tǒng)移植學(xué)習(xí)記錄

第一章 Boot0基于ARMGCC的編譯與修改



前言

入行快兩年,希望通過(guò)學(xué)習(xí)系統(tǒng)移植鞏固下相關(guān)的知識(shí),目標(biāo)板使用基于全志A33 的astar-parrot開(kāi)發(fā)板,開(kāi)始本來(lái)想著使用Boot0來(lái)加載uboot,但后期發(fā)現(xiàn)為了代碼統(tǒng)一和便捷性,最終還是選擇了SPL作為跳板,但Boot0流程相對(duì)清晰,所以將對(duì)其做的工作貼出來(lái)便于理解。


一、全志A33簡(jiǎn)介以及上電引導(dǎo)流程

  • 硬件方面:A33芯片采用四核基于Cortex- A7架構(gòu)的處理器,支持高清1080P視頻處理,并支持各種主流視頻標(biāo)準(zhǔn),如H.264、VP8、MPEG1/2/4、JPEG/MJPEG,支持RGB/LVDS和LCD接口。256KB一級(jí)緩存和512KB二級(jí)緩存…
    軟件方面:適配全志原廠基于openWrt構(gòu)建的Tina系統(tǒng):采用uboot2011,Linux3.4版本,可支持Android4.3,

上電流程:

  • 芯片支持五種種引導(dǎo)方式,分別是NAND Flash,eMMC NAND,SPI Nor Flash,SD卡(SDC 0/2)和USB。但如果要直接從USB啟動(dòng)系統(tǒng),由內(nèi)部上拉50k電阻的UBOOT_SEL引腳需要被拉低。具體引導(dǎo)流程可由下圖說(shuō)明:

  • Soc內(nèi)部SROM區(qū)固化一段代碼,上電首先執(zhí)行這段代碼,其主要是判斷啟動(dòng)介質(zhì)并將介質(zhì)中的部分代碼搬運(yùn)至內(nèi)部SRAM中(SRAM A1區(qū)域,最大32KB,相關(guān)控制器已經(jīng)初始化)并mv PC跳轉(zhuǎn),判斷的順序就是上圖所示。由于目標(biāo)板使用mmc存儲(chǔ)方式,并向外提供了SD卡插槽,為了保證不燒磚(由于移植過(guò)程中去掉了fel mode,相對(duì)不是很安全),首先利用工具將廠商提供的鏡像燒錄至mmc(SDC2)中,然后后面利用TF卡,將編譯好的bin檔dd到sd卡偏移16sector的位置,(SDC0)啟動(dòng)移植代碼(SDC0優(yōu)先級(jí)高,所以不會(huì)有影響),

二、Boot0編譯器修改大致流程

1.Boot0大體流程

根據(jù)上述A33的啟動(dòng)方式描述,由于主體u-boot占用內(nèi)存遠(yuǎn)遠(yuǎn)大于其SRAM容量,所以Boot0的主要作用就是運(yùn)行在SRAM中,初始化啟動(dòng)介質(zhì),初始化外部DDR,并搬運(yùn)uboot到DDR最后跳轉(zhuǎn)。源碼github:https://github.com/wangzl-coder/sunxi-basicLoader.git

2.此部分需做的工作

Boot0是比較簡(jiǎn)單但非常底層的裸機(jī)程序,SOC廠商發(fā)布的Boot0源碼是基于cygwin+armcc進(jìn)行編譯,為了后續(xù)的方便,我們需要修改并重新編譯,而由于armcc的非開(kāi)源性,所以第一步是將其轉(zhuǎn)換標(biāo)準(zhǔn),使用ARM GCC編譯方式編譯。

3.修改流程

(1)編譯環(huán)境的搭建部分省略,選用arm通用編譯器arm-linux-gnueabi-,首先新建armgcc配置文件,添加如下:

#/*
#*********************************************************************************************************
#*                                                    MELIS
#*                                    the Easy Portable/Player Develop Kits
#*                                               Compiler Module
#*
#*                                    (c) Copyright 2006-2010, kevin.z China
#*                                             All Rights Reserved
#*
#* File    : crosstool.cfg
#* By      : kevin.z
#* Version : v1.0
#* Date    : 2010-9-7 10:38
#* Descript: configuration script for RVDS compiler
#* Update  : date                auther      ver     notes
#*
#*********************************************************************************************************
#*/
#

#工具鏈配置
CROSSTOOL   = ARMGCC

LICHEEPATH      = $(SDKROOT)/../../tools/pack/chips/$(ARCH)
WORKSPACEPATH   = $(SDKROOT)/../pack/chips/$(ARCH)
WORKTOOLS       = $(SDKROOT)/pctools

ifeq ($(CROSSTOOL), ARMRVDS)

#===============================================================
#RVDS編譯器參數(shù)配置
#===============================================================


else


ifeq ($(CROSSTOOL), ARMGCC)

#===============================================================
#GNU編譯器參數(shù)配置
#===============================================================
CROSS_COMPILE ?= arm-linux-gnueabi-
#編譯器
CC          = $(CROSS_COMPILE)gcc
#編譯器參數(shù)
CFLAGS      =  

#打包庫(kù)
AS          = $(CROSS_COMPILE)as
#打包庫(kù)參數(shù)
ASFLAGS     =

#鏈接器
LD        = $(CROSS_COMPILE)ld
#鏈接器參數(shù)
LKFLAGS     =

#objcopy
OBJCOPY        = $(CROSS_COMPILE)objcopy
#加載器參數(shù)
OBJCOPY_FLAGS     = -O binary -S

else

error:
	$(error CROSSTOOL configuration is invalid!!!)

endif
endif

(2) 修改相關(guān)文件格式:根據(jù)gnuc標(biāo)準(zhǔn),首先將所有匯編文件后綴修改為.S(大寫(xiě)),將目錄標(biāo)識(shí)符"“修改linux格式”/"。
(3)boot0/make.cfg 添加編譯,鏈接參數(shù)

ifeq ($(CROSSTOOL), ARMGCC)

#===============================================================================
#使用GNU-GCC編譯器
#===============================================================================

CFLAGS += -O2 -Wno-nonnull-compare -fno-strict-aliasing -fno-stack-protector -Werror -Wall $(INCLUDES) 

LDFLAGS += -T./config/sun8iw5p1.lds -static

(4)添加鏈接腳本,_start段作為起始段,將頭校驗(yàn)段鏈接在起始位置,此處首先需要對(duì)head自定義段,boot0/Boot0_head.c:

#include "boot0_i.h"

#define   DDR3_USED

const boot0_file_head_t  BT0_head __attribute__((__section__(".bt0_head")))= {
									{
	  /* jump_instruction */      		( 0xEA000000 | ( ( ( sizeof( boot0_file_head_t ) + sizeof( int ) - 1 ) / sizeof( int ) - 2 ) & 0x00FFFFFF ) ),	// one intruction jumping to real code
										BOOT0_MAGIC,		// ="eGON.BT0" or "eGON.BT1",  not C-style string.
										STAMP_VALUE,		// generated by PC
		#ifdef ALIGN_SIZE_8K
										0x2000,
		#else
										0x8000,			// generated by PC
		#endif
										sizeof( boot_file_head_t ),	// the size of boot_file_head_t
										BOOT_PUB_HEAD_VERSION,		// the version of boot_file_head_t
										0,							 // the return value
										0,							// run addr
										EGON_VERSION,					// eGON version
										{
											0, 0, '3','.','1','.','0',0	// platform information
										},
									},
#ifdef  DDR3_USED
									{
										sizeof( boot0_private_head_t ),	// the size of prvt_head
										BOOT0_PRVT_HEAD_VERSION,			// the version of boot0_private_head_t
										/******DRAM patameters for initialising dram. Original values is arbitrary******/
										{ 	
											/***normal configuration******/
											552, 				//dram_clk
											3, 				//dram_type
											0x3bbb,				//dram_zq
											1,				//dram_odt_en
											0x10F20200,				//dram_para1
											0x00,				//dram_para2

											/****timing configuration*****/
											0x1840,				//dram_mr0
											0x40,				//dram_mr1
											0x8,			//dram_mr2
											0,			//dram_mr3
											0x0048A192,				//dram_tpr0
											0x01B1B18d,				//dram_tpr1
											0x00076052,				//dram_tpr2
											0x0,				//dram_tpr3
											0x0,				//dram_tpr4
											0x0,				//dram_tpr5
											0x0,				//dram_tpr6
											0x0,				//dram_tpr7
											0x0,				//dram_tpr8
											0x0,				//dram_tpr9
											0x0,				//dram_tpr10
											0x0,				//dram_tpr11
											168,				//dram_tpr12
											0x10900,				//dram_tpr13
										},							
										3,								// UART控制器編號(hào)
										{
											{ 8, 6, 3, 1, 0xff, 0xff, {0, 0} },	// UART控制器(調(diào)試打印口)數(shù)據(jù)信息 tx
											{ 8, 7, 3, 1, 0xff, 0xff, {0, 0} }		// UART控制器(調(diào)試打印口)數(shù)據(jù)信息 rx
										},
										0,									// jtag 1 : enable,  0 : disable
										{
											{ 0, 0, 0, 0, 0, 0, {0, 0} },
											{ 0, 0, 0, 0, 0, 0, {0, 0} },
											{ 0, 0, 0, 0, 0, 0, {0, 0} },
											{ 0, 0, 0, 0, 0, 0, {0, 0} },
											{ 0, 0, 0, 0, 0, 0, {0, 0} },
										},							// 保存JTAG的全部GPIO信息
										{
											{ 6, 0, 2, 1, 2, 0, {0, 0} },	
											{ 6, 1, 2, 1, 2, 0, {0, 0} },
											{ 6, 2, 2, 1, 2, 0, {0, 0} },
											{ 6, 3, 2, 1, 2, 0, {0, 0} },
											{ 6, 4, 2, 1, 2, 0, {0, 0} },
											{ 6, 5, 2, 1, 2, 0, {0, 0} },			// 存儲(chǔ)設(shè)備 GPIO信息
										},

										/****用戶(hù)保留數(shù)據(jù)信息****/
										{ 
											0,
										}					
									}
#else
									{
										sizeof( boot0_private_head_t ),
										BOOT0_PRVT_HEAD_VERSION,
										{ 0x40000000,
											1024,
											180,
											1,
											1,
											0,
											(__dram_type_e)1,
											16,
											10,
											14,
											4,
											3,
											0,
											16,
											1024
										},
										0,
										{
											{ 2, 22, 4, 1, 1, 0, 0, 0},
											{ 2, 23, 4, 1, 1, 0, 0, 0}
										},
										0,
										{ 0 },
										{ 0 },
										{ 0 }
									}
#endif
								};

將BT0_head 放入.bt0_head段,鏈接腳本如下boot0/config/sun8iw5p1.lds:

OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)

SECTIONS
{
	. = 0x00000000;
	. = ALIGN(4);
	.head :
	{
		./Boot0_head.o(.bt0_head)
	}
	.text :
	{
		./Boot0.o(.text*)
		*(.text*)
	}
	.data :
	{
		*(.data*)
	}
	.rodata :
	{
		*(.rodata*)
	}
	.bss :
	{
		*(.bss*)
	}
}

比較簡(jiǎn)單,主要是為了指定鏈接參考地址Boot0.o的.text(_start)以及頭部數(shù)據(jù).bt0_head,bt0_head第一個(gè)成員變量將是SROM中mv PC的位置,所以這里放入一個(gè)跳轉(zhuǎn)指令0xEA…,指令后面跟當(dāng)前PC的偏移量(單位為字,所以要除以sizeof(int)),這里要注意流水線問(wèn)題,由于是三級(jí)流水,當(dāng)前PC指針的位置應(yīng)該在執(zhí)行代碼地址的兩個(gè)字后,所以此處需要減去2,通過(guò)這個(gè)跳轉(zhuǎn)指令可以跳轉(zhuǎn)到head結(jié)構(gòu)體之后的第一個(gè)地址(_start)處運(yùn)行,還有BT0_head這個(gè)變量需要在其他任意地方引用一次,否則編譯器鏈接時(shí)可能會(huì)把它優(yōu)化掉。

(5)C標(biāo)準(zhǔn)庫(kù)函數(shù)引用問(wèn)題

可能沒(méi)有找到合適的編譯器版本,在使用C標(biāo)準(zhǔn)庫(kù)函數(shù)(如memset)時(shí),會(huì)導(dǎo)致死機(jī)的問(wèn)題,經(jīng)過(guò)后續(xù)驗(yàn)證,發(fā)現(xiàn)只有在操作字節(jié)數(shù)大于某些值時(shí)才會(huì)死機(jī),不明原因,除此還有除法的使用問(wèn)題,會(huì)編譯報(bào)錯(cuò),網(wǎng)上查找說(shuō)鏈接時(shí)需要鏈接libgcc庫(kù),但試了很多方法都不行,所以針對(duì)這兩個(gè)方法只能用最麻煩但是最保險(xiǎn)的方式處理
首先針對(duì)memset等函數(shù)使用問(wèn)題,摒棄了libc的實(shí)現(xiàn),自己實(shí)現(xiàn)這些操作:sunxi-basicLoader/boot0/lib/extra_libc//extra_string.h:

#ifndef __EXTRA_STRING_H__
#define __EXTRA_STRING_H__

#define NULL 0

void *memset(void *s, int val, unsigned int count);

void *memcpy(void *dest, const void *src, unsigned int count);

int strncmp(const char *src1, const char *src2, unsigned int count);

char *strcpy(char *dest, const char *src);

#endif

sunxi-basicLoader/boot0/lib/extra_libc/memcpy.c:

#include "extra_string.h"


void *memcpy(void *dest, const void *src, unsigned int count)
{
	char *tmp_dest = NULL;
	const char *tmp_src = NULL;
	if(dest == NULL || src == NULL)
		return NULL;
	tmp_dest= (char*) dest;
	tmp_src = (const char*) src;
	while(count--)
		*tmp_dest++ = *tmp_src++;
	
	return dest;
}

sunxi-basicLoader/boot0/lib/extra_libc/memset.c:

#include "extra_string.h"


void *memset(void *s, int val, unsigned int count)
{
	char * tmp = NULL;

	if(s == NULL)
		return NULL;

	tmp = (char *) s;
	while(count--)
		*tmp++ = val;

	return s;

}

sunxi-basicLoader/boot0/lib/extra_libc/strcpy.c:

#include "extra_string.h"


char *strcpy(char *dest, const char *src)
{
    char * tmp_dest = NULL;
    const char * tmp_src = NULL;
    if(dest == NULL || src == NULL)
        return NULL;
    
    if(dest == src)
        return dest;

    tmp_dest = dest;
    tmp_src = src;
	while((*tmp_dest++ = *tmp_src++) != '\0');

    return dest;
}

sunxi-basicLoader/boot0/lib/extra_libc/strncmp.c:

#include "extra_string.h"


int strncmp(const char *s1, const char *s2, unsigned int count)
{
	int val;
	const char *tmp_s1 = NULL;
	const char *tmp_s2 = NULL;
	if(s1 == NULL || s2 == NULL)
	{
		return -1;
	}
	tmp_s1 = s1;
	tmp_s2 = s2;
	while(count--)
	{
		if((val = *tmp_s1 - *tmp_s2++) != 0 || *tmp_s1++ == 0)
		{
			break;
		}
	}

	return val;

}

第二個(gè)就是除法的問(wèn)題,兩種處理方式,如果除數(shù)是2的n次方,在編譯時(shí)指定優(yōu)化等級(jí)-O2 ,編譯器會(huì)將其轉(zhuǎn)換成移位運(yùn)算(>>n),如果不是,只能采用最原始的方法,將其轉(zhuǎn)換為乘法(由于商值都是整型),例如下面:

mmc->lba = mmc->capacity/mmc->read_bl_len;

可以乘法轉(zhuǎn)換:

	while((mmc->read_bl_len * i> mmc->capacity))
	{
		i++;
	}
	mmc->lba = i;

(6)頭校驗(yàn):
>前面放在起始位置的head數(shù)據(jù)主要用于SROM代碼的啟動(dòng)校驗(yàn),主要包括magic字符串以及校驗(yàn)和,由于校驗(yàn)和只能在編譯完成后才能計(jì)算設(shè)定,所以必須要寫(xiě)一個(gè)基于主機(jī)(Ubuntu等)平臺(tái)的工具對(duì)二進(jìn)制文本進(jìn)行操作,添加文件sunxi-basicLoader/pctools/mkboot0.c:

#include <stdio.h>
#include "string.h"


#define STAMP_VALUE         0x5F0A6C39
#define GET_OFFSET(struct_p,child)  (unsigned long int)(&(((struct_p *)0x00000000)->child))

typedef struct _boot0_standard_head_t
{
	unsigned int  jump_instruction;   // one intruction jumping to real code
	unsigned char   magic[8];           // ="eGON.BT0" or "eGON.BT1",  not C-style string.
	unsigned int  check_sum;          // generated by PC
	unsigned int  length;             // generated by PC
	unsigned int  pub_head_size;      // the size of boot_file_head_t
	unsigned char   pub_head_vsn[4];    // the version of boot_file_head_t
	unsigned int  ret_addr;           // the return value
	unsigned int  run_addr;           // run addr
	unsigned char   eGON_vsn[4];        // eGON version
	unsigned char   platform[8];        // platform information
}boot0_standard_head_t;


static int func_checkSum(int *buffer,int length)
{
	int sum = 0;
	int index = 0;
	for(index = 0;index < length;index++)
	{
		sum += buffer[index];
	}
	return sum;
}


int main(int argc,char* argv[])
{
	boot0_standard_head_t boot0_head;
	FILE *input_file;
	FILE *output_file;
	fpos_t input_pos;
	int buffer[256];
	int read_num = 0;
	int write_num = 0;
	int write_total = 0;
	int sum = 0;
	unsigned int headSum_off = 0;
	int ret = 0;


	if(argc != 3)
	{
		printf("input param error! \r\n");
		return -1;
	}
	
	if((input_file = fopen(argv[1],"r")) == NULL)
	{
		printf("cannot find file %s \r\n",argv[1]);
		ret = -1;
		goto src_open_failed;
	}
	
	if((output_file = fopen(argv[2],"w+")) == NULL)
	{
		printf("create file %s failed \r\n",argv[2]);
		ret = -1;
		goto dest_open_failed;
	}
	
	if(fread(&boot0_head,sizeof(boot0_head),1,input_file) != 1)
	{
		printf("read boot0_head not enough! read_num is %d \r\n",read_num);
		ret = -1;
		goto read_cp_failed;
	}
	
	printf("current magic is %s \r\n",boot0_head.magic);
	printf("STAMP_VALUE is %x \r\n",boot0_head.check_sum);
	printf("current align size is %x \r\n",boot0_head.length);
	fseek(input_file,0,SEEK_END);
	fgetpos(input_file,&input_pos);
	printf("input file size is %ld \r\n",input_pos.__pos);
	
	if(boot0_head.check_sum != STAMP_VALUE)
	{
		printf("STAMP_VALUE check failed !\r\n");
		ret = -1;
		goto read_cp_failed;
	}
	
	if(boot0_head.length < input_pos.__pos)
	{
		printf("boot0_head.length too low! \r\n");
		ret = -1;
		goto read_cp_failed;
	}
	rewind(input_file);
	rewind(output_file);
	memset(buffer,0x0,sizeof(buffer));
	while((read_num = fread(buffer,1,sizeof(buffer),input_file)) > 0)
	{
			fwrite(buffer,sizeof(char),read_num,output_file);
			write_total += read_num;
			sum += func_checkSum(buffer,read_num/sizeof(buffer[0]));
			printf("copy file %d bytes \r\n",write_total);
			memset(buffer,0x0,sizeof(buffer));
	}
	
	if(write_total != input_pos.__pos)
	{
		printf("write error ! \r\n");
	}
	
	if(boot0_head.length > write_total)
	{
		printf("need add %d bytes 0x0 to the end of %s !! \r\n",boot0_head.length - write_total,argv[2]);
		fseek(output_file,0,SEEK_END);
		memset(buffer,0x0,sizeof(buffer));
		while(1)
		{
			write_num = ((boot0_head.length - write_total) > sizeof(buffer))?sizeof(buffer):(boot0_head.length - write_total);
			fwrite(buffer,1,write_num,output_file);
			write_total +=write_num;
			if(write_total == boot0_head.length)
				break;
		}
	}
	headSum_off = GET_OFFSET(boot0_standard_head_t,check_sum);
	printf("mkboot0 success\r\n write to %s total %d bytes ,check_sum is %x \r\n",argv[2],write_total,sum);
	fseek(output_file,headSum_off,SEEK_SET);
	fwrite(&sum,sizeof(int),1,output_file);


read_cp_failed:
	fclose(output_file);
dest_open_failed:
	fclose(input_file);
src_open_failed:
	return ret;
}

由于SROM根據(jù)頭部文件結(jié)構(gòu)體的length變量判斷加載字節(jié)數(shù),這里我們同樣判斷生成bin文檔的length,根據(jù)length輸出文件,空位補(bǔ)零。gcc編譯運(yùn)行,會(huì)將校驗(yàn)和寫(xiě)入結(jié)構(gòu)體對(duì)應(yīng)位置處。

(7)其他細(xì)節(jié)修改:armgcc編譯流程的大體搭建就是這些,當(dāng)然還有很多細(xì)節(jié)的東西需要實(shí)際編譯或者燒錄運(yùn)行時(shí)才能發(fā)現(xiàn)。

三、Boot0調(diào)試

編譯通過(guò)完成后,生成boot0_sdcard_sun8iw5p1.bin,dd if=boot0_sdcard_sun8iw5p1.bin of=/dev/sdb(根據(jù)sd掛載名稱(chēng)) bs=1024 seek=8將其燒錄到sd卡第16扇區(qū),插卡上電即可開(kāi)始調(diào)試,前面說(shuō)到Boot0主要工作就是初始化DDR,加載uboot并跳轉(zhuǎn),其主要代碼如下sunxi-basicLoader/boot0/Boot0_C_part.c:

/*
************************************************************************************************************************
*                                                         eGON
*                                         the Embedded GO-ON Bootloader System
*
*                             Copyright(C), 2006-2008, SoftWinners Microelectronic Co., Ltd.
*											       All Rights Reserved
*
* File Name : Boot0_C_part.c
*
* Author : Gary.Wang
*
* Version : 1.1.0
*
* Date : 2007.12.18
*
* Description :
*
* Others : None at present.
*
*
* History :
*
*  <Author>        <time>       <version>      <description>
*
* Gary.Wang       2007.11.09      1.1.0        build the file
*
* Gary.Wang       2007.12.18      1.1.0        remove "BT0_self_rcv"
*
************************************************************************************************************************
*/
#include "boot0_i.h"

#include "extra_string.h"

#define BOOT_FEL_FLAG  (0x5AA5A55A)

extern const boot0_file_head_t  BT0_head;
static void clear_ZI( void );
static void print_version(void);

extern unsigned int  get_fel_flag(void);
extern void show_rtc_reg(void);
extern void  clear_fel_flag(void);




/*******************************************************************************
*函數(shù)名稱(chēng): Boot0_C_part
*函數(shù)原型:void Boot0_C_part( void )
*函數(shù)功能: Boot0中用C語(yǔ)言編寫(xiě)的部分的主流程
*入口參數(shù): void
*返 回 值: void
*備    注:
*******************************************************************************/
void Boot0_C_part( void )
{
	__u32 status;
	__s32 dram_size;
	
	int   ddr_aotu_scan = 0;
	
    __u32 fel_flag;

//	move_RW( );
	clear_ZI( );

	bias_calibration();
#if defined(CONFIG_ARCH_SUN9IW1P1) || defined(CONFIG_ARCH_SUN8IW6P1)
    //do nothing
#else
    timer_init();
#endif

    UART_open( BT0_head.prvt_head.uart_port, (void *)BT0_head.prvt_head.uart_ctrl, 24*1000*1000 );
	if( BT0_head.prvt_head.enable_jtag )
    {
		jtag_init( (normal_gpio_cfg *)BT0_head.prvt_head.jtag_gpio );
    }
	msg("HELLO! BOOT0 is starting!\n");
	print_version();

#ifdef CONFIG_ARCH_SUN7I
	reset_cpux(1);
#endif


    fel_flag = get_fel_flag();
    show_rtc_reg();
    if(fel_flag == BOOT_FEL_FLAG)
    {
        clear_fel_flag();
    	msg("eraly jump fel\n");
    	pll_reset();
    	__msdelay(10);

    	jump_to( FEL_BASE );
    }



	mmu_system_init(EGON2_DRAM_BASE, 1 * 1024, EGON2_MMU_BASE);
	mmu_enable();


    ddr_aotu_scan = 0;
//	dram_para_display();
	dram_size = init_DRAM(ddr_aotu_scan, (void *)BT0_head.prvt_head.dram_para);
	if(dram_size)
	{
	    //mdfs_save_value();
		msg("dram size =%d\n", dram_size);
	}
	else
	{
		msg("initializing SDRAM Fail.\n");
		mmu_disable( );

		pll_reset();
		jump_to( FEL_BASE );
	}
#if defined(CONFIG_ARCH_SUN9IW1P1)
	__msdelay(100);
#endif

#ifdef CONFIG_ARCH_SUN7I
    check_super_standby_flag();
#endif

#if SYS_STORAGE_MEDIA_TYPE == SYS_STORAGE_MEDIA_NAND_FLASH
		status = load_Boot1_from_nand( );         // 載入Boot1
#elif SYS_STORAGE_MEDIA_TYPE == SYS_STORAGE_MEDIA_SPI_NOR_FLASH
		status = load_boot1_from_spinor( );         // 載入Boot1
#elif SYS_STORAGE_MEDIA_TYPE == SYS_STORAGE_MEDIA_SD_CARD
		//dram參數(shù)拷貝
		memcpy((void *)DRAM_PARA_STORE_ADDR, (void *)BT0_head.prvt_head.dram_para, SUNXI_DRAM_PARA_MAX * 4);
		status = load_boot1_from_sdmmc( (char *)BT0_head.prvt_head.storage_data );  // 載入boot1
#else
		#error The storage media of Boot1 has not been defined.
#endif


	msg("Ready to disable icache.\n");

	mmu_disable( );                               // disable instruction cache

	if( status == OK )
	{

		//跳轉(zhuǎn)之前,把所有的dram參數(shù)寫(xiě)到boot1中
		set_dram_para((void *)&BT0_head.prvt_head.dram_para, dram_size);
		msg("Jump to secend Boot.\n");

		jump_to( UBOOT_BASE );                    // 如果載入Boot1成功,跳轉(zhuǎn)到Boot1處執(zhí)行
	}
	else
	{
//		disable_watch_dog( );                     // disable watch dog

		pll_reset();
		msg("Jump to Fel.\n");
		jump_to( FEL_BASE );                      // 如果載入Boot1失敗,將控制權(quán)交給Fel
	}
}

移植的基本思想:先把串口拉起來(lái)先跑,有問(wèn)題處理問(wèn)題,所以第一步先配置uart,我這里硬件上使用uart3作為調(diào)試串口,根據(jù)源碼追一下uart的初始化,

 UART_open( BT0_head.prvt_head.uart_port, (void *)BT0_head.prvt_head.uart_ctrl, 24*1000*1000 );

void UART_open( __s32 uart_port, void  *uart_ctrl, __u32 apb_freq )
{
  	__u32   temp=0, i;
  	__u32   uart_clk;
  	__u32   lcr;
  	volatile unsigned int   *reg;

	port = uart_port;

	// config clock
	if(port > 7)
	{
		return ;
	}
	reg = (volatile unsigned int *)0x01c2006C;
	*reg &= ~(1 << (16 + port));
	for( i = 0; i < 100; i++ );
	*reg |=  (1 << (16 + port));

	(*(volatile unsigned int *)0x01c202D8) |= (1 << (16 + port));
	// config uart gpio
	// config tx gpio
	boot_set_gpio((void *)uart_ctrl, 2, 1);
    // Set Baudrate
    uart_clk = ( apb_freq + 8*UART_BAUD ) / (16*UART_BAUD);
    lcr = UART_REG_LCR(port);
    UART_REG_HALT(port) = 1;
    UART_REG_LCR(port) = lcr | 0x80;
    UART_REG_DLH(port) = uart_clk>>8;
    UART_REG_DLL(port) = uart_clk&0xff;
    UART_REG_LCR(port) = lcr & (~0x80);
	UART_REG_HALT(port) = 0;
    // Set Lin Control Register
    temp = ((PARITY&0x03)<<3) | ((STOP&0x01)<<2) | (DLEN&0x03);
    UART_REG_LCR(port) = temp;

    // Disable FIFOs
    UART_REG_FCR(port) = 0x06;
}

可以看出來(lái),uart初始化使用bt_head成員變量初始化其GPIO以及uart控制器,這里需要配置使用uart的GPIO復(fù)用功能,對(duì)照芯片手冊(cè),uart3 tx使用GPH_6,rx使用GPH_7,在 BT0_head中配置uart:

3,								// UART控制器編號(hào)
										{
											{ 8, 6, 3, 1, 0xff, 0xff, {0, 0} },	// UART控制器(調(diào)試打印口)數(shù)據(jù)信息 tx
											{ 8, 7, 3, 1, 0xff, 0xff, {0, 0} }		// UART控制器(調(diào)試打印口)數(shù)據(jù)信息 rx
										},

DDR配置與時(shí)序:

/***normal configuration******/
											552, 				//dram_clk
											3, 				//dram_type
											0x3bbb,				//dram_zq
											1,				//dram_odt_en
											0x10F20200,				//dram_para1
											0x00,				//dram_para2

											/****timing configuration*****/
											0x1840,				//dram_mr0
											0x40,				//dram_mr1
											0x8,			//dram_mr2
											0,			//dram_mr3
											0x0048A192,				//dram_tpr0
											0x01B1B18d,				//dram_tpr1
											0x00076052,				//dram_tpr2
											0x0,				//dram_tpr3
											0x0,				//dram_tpr4
											0x0,				//dram_tpr5
											0x0,				//dram_tpr6
											0x0,				//dram_tpr7
											0x0,				//dram_tpr8
											0x0,				//dram_tpr9
											0x0,				//dram_tpr10
											0x0,				//dram_tpr11
											168,				//dram_tpr12
											0x10900,				//dram_tpr13

使用SDC0啟動(dòng),同樣根據(jù)芯片手冊(cè),配置其GPIO:

{
											{ 6, 0, 2, 1, 2, 0, {0, 0} },	
											{ 6, 1, 2, 1, 2, 0, {0, 0} },
											{ 6, 2, 2, 1, 2, 0, {0, 0} },
											{ 6, 3, 2, 1, 2, 0, {0, 0} },
											{ 6, 4, 2, 1, 2, 0, {0, 0} },
											{ 6, 5, 2, 1, 2, 0, {0, 0} },			// 存儲(chǔ)設(shè)備 GPIO信息
										},

期間遇到sd卡驅(qū)動(dòng)失敗的問(wèn)題,調(diào)試發(fā)現(xiàn)mmc->capacity容量是零,經(jīng)過(guò)很長(zhǎng)時(shí)間的調(diào)試,對(duì)照sanDisk的Spc,兩者通訊正常且sd卡的相關(guān)寄存器都讀取正常,發(fā)現(xiàn)capacity計(jì)算方法出現(xiàn)問(wèn)題:

while((mmc->read_bl_len * i > mmc->capacity))
	{
		i++;
	}
	mmc->lba = i;

這里需要計(jì)算sd卡block的數(shù)量,應(yīng)該是capacity有多少個(gè)bl_len,所以正確方法應(yīng)該如下:

while((mmc->read_bl_len * i < mmc->capacity))
	{
		i++;
	}
	mmc->lba = i;

一步一步調(diào)試之后,直到打印出現(xiàn)sdcard0 init ok說(shuō)明整個(gè)Boot0工作正常,后面對(duì)于uboot的操作,由于sd卡中尚未燒錄uboot,所以校驗(yàn)失敗,后續(xù)用移植后的uboot校驗(yàn),正確跳轉(zhuǎn)并執(zhí)行,Boot0工作到此結(jié)束。


總結(jié)

Boot0代碼雖然不是那么的復(fù)雜,但移植過(guò)程中確實(shí)遇到不少麻煩,牽扯到方方面面,雖然后期舍棄了Boot0方式,但是對(duì)其調(diào)試修改的過(guò)程確實(shí)能收獲不少,后續(xù)任務(wù)是uboot和linux kernel的操作,加油!文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-403164.html

到了這里,關(guān)于基于全志A33開(kāi)發(fā)板linux系統(tǒng)移植學(xué)習(xí)記錄(Boot0)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶(hù)投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 基于RK3588的嵌入式linux系統(tǒng)開(kāi)發(fā)(二)——uboot源碼移植及編譯

    基于RK3588的嵌入式linux系統(tǒng)開(kāi)發(fā)(二)——uboot源碼移植及編譯

    ??????? 由于官方的SDK占用空間較大(大約20GB左右),需要聯(lián)系相關(guān)供應(yīng)商提供,且官方的SDK通過(guò)各種腳本文件進(jìn)行集成編譯,難以理解系統(tǒng)開(kāi)發(fā)的詳細(xì)過(guò)程。本章介紹直接從官方Github網(wǎng)站下載源碼進(jìn)行移植,進(jìn)行uboot移植及編譯,具體內(nèi)容如下所述: 1.進(jìn)入官方的github網(wǎng)

    2024年01月16日
    瀏覽(27)
  • [ARM+Linux] 基于全志h616外設(shè)開(kāi)發(fā)筆記

    [ARM+Linux] 基于全志h616外設(shè)開(kāi)發(fā)筆記

    修改用戶(hù)密碼 配置網(wǎng)絡(luò) nmcli dev wifi? 命令掃描周?chē)鶺IFI熱點(diǎn) ? nmcli dev wifi connect ?xxx? password xxx 命令 連接WiFi 查看ip地址的指令: ifconfig ip addr show wlan0 SSH登錄 ????????這是企業(yè)開(kāi)發(fā)調(diào)試必用方式,比串口來(lái)說(shuō)不用接線,前提是接入網(wǎng)絡(luò)并獲得板子IP 地址,且系統(tǒng)做了SSH的

    2023年04月21日
    瀏覽(19)
  • linux(全志F1C100S/F1C200S)系列02:移植LCD st7789驅(qū)動(dòng),LVGL8.3移植

    linux(全志F1C100S/F1C200S)系列02:移植LCD st7789驅(qū)動(dòng),LVGL8.3移植

    st7789V中指定了rst與dc引腳,pio 4 3 對(duì)應(yīng)PE3,pio 4 5對(duì)應(yīng)PE5; 詳細(xì)配置方式見(jiàn)鏈接:全志 :gpio使用 需要根據(jù)自身硬件配置。 Tips:更改 spi-max-frequency = 32000000 - spi-max-frequency = 100000000; 和 fps = 30; 改為 fps = 60; 感謝樓下老哥提示。 rotate = 90;根據(jù)屏幕方向更改。 只需要更改下面的三個(gè)地

    2024年01月18日
    瀏覽(23)
  • 嵌入式Linux底層系統(tǒng)開(kāi)發(fā) +系統(tǒng)移植+內(nèi)核文件系統(tǒng)(基礎(chǔ))

    嵌入式Linux底層系統(tǒng)開(kāi)發(fā) +系統(tǒng)移植+內(nèi)核文件系統(tǒng)(基礎(chǔ))

    搭建交叉編譯開(kāi)發(fā)環(huán)境 bootloader的選擇和移植 kernel的配置、編譯、移植和調(diào)試 根文件系統(tǒng)的制作 前兩個(gè)要點(diǎn)通常芯片廠家提供。后邊兩個(gè)要點(diǎn)是公司的工作重點(diǎn)。 學(xué)習(xí)方法:先整體后局部,層層推進(jìn) 如何編譯—如何添加命令和功能—如何定義自己的開(kāi)發(fā)板。 移植的基本步

    2024年02月03日
    瀏覽(101)
  • 【嵌入式Linux項(xiàng)目】基于Linux的全志H616開(kāi)發(fā)板智能家居項(xiàng)目(語(yǔ)音控制、人臉識(shí)別、安卓APP和PC端QT客戶(hù)端遠(yuǎn)程操控)有視頻功能展示

    【嵌入式Linux項(xiàng)目】基于Linux的全志H616開(kāi)發(fā)板智能家居項(xiàng)目(語(yǔ)音控制、人臉識(shí)別、安卓APP和PC端QT客戶(hù)端遠(yuǎn)程操控)有視頻功能展示

    目錄 一、功能需求 二、開(kāi)發(fā)環(huán)境 1、硬件: 2、軟件: 3、引腳分配: 三、關(guān)鍵點(diǎn) 1、設(shè)計(jì)模式之工廠模式 2、線程 3、wiringPi庫(kù)下的相關(guān)硬件操作函數(shù)調(diào)用 4、語(yǔ)音模塊的串口通信 5、攝像頭的實(shí)時(shí)監(jiān)控和拍照功能 6、人臉識(shí)別 7、qt程序跨平臺(tái)運(yùn)行(編譯成安卓APP) 四、編譯和

    2024年02月15日
    瀏覽(24)
  • 基于ubuntu-base構(gòu)建根文件系統(tǒng)并移植到RK3568開(kāi)發(fā)板

    基于ubuntu-base構(gòu)建根文件系統(tǒng)并移植到RK3568開(kāi)發(fā)板

    前言 一、使用ubuntu-base構(gòu)建根文件系統(tǒng) 1、到ubuntu官網(wǎng)獲取 ubuntu-base-18.04.5-base-arm64.tar.gz 2、將獲取的文件拷貝到ubuntu虛擬機(jī),新建目錄,并解壓。 3、安裝qemu-user-static 4、設(shè)置軟件源 5、配置DNS 6、掛載ubuntu-base文件系統(tǒng) 7、安裝必要軟件 8、安裝桌面環(huán)境 9、修改root用戶(hù)密碼

    2024年02月01日
    瀏覽(29)
  • 全志F1C100s主線linux入坑記錄 (6)音視頻播放(視頻播放軟解)

    全志F1C100s主線linux入坑記錄 (6)音視頻播放(視頻播放軟解)

    百度網(wǎng)站 (1)下載安裝聲卡補(bǔ)丁 參考挖坑網(wǎng)大神提供的聲音驅(qū)動(dòng)以及聲音卡驅(qū)動(dòng)補(bǔ)丁文件下載文件下載 全志F1C100s聲卡補(bǔ)丁 解壓文件打上補(bǔ)丁 (2)配置聲卡 修改設(shè)備樹(shù)文件添加聲卡節(jié)點(diǎn) 內(nèi)核配置 (3)linux內(nèi)核編譯燒錄 可以看到聲卡已經(jīng)掛載了 (4)使用聲卡 安裝alsa-u

    2024年02月07日
    瀏覽(45)
  • 【移植Ardupilot的日志記錄方法到linux上】

    【移植Ardupilot的日志記錄方法到linux上】

    采用二進(jìn)制文件記錄,可在mission planer查看 支持所有數(shù)據(jù)類(lèi)型記錄 精巧移植方便 可直接在地面站繪制曲線查看 可導(dǎo)出生成mat文件在matlab上分析 提供的日志目標(biāo)結(jié)構(gòu) 日志頭 日志消息類(lèi)型 消息長(zhǎng)度 日志消息名稱(chēng) 數(shù)據(jù)類(lèi)型標(biāo)識(shí) 數(shù)據(jù)標(biāo)簽 數(shù)據(jù)單位 數(shù)據(jù)格式 數(shù)據(jù)結(jié)構(gòu)體定義:

    2024年02月01日
    瀏覽(22)
  • 記錄一下基于jeecg-boot3.0的待辦消息移植記錄

    記錄一下基于jeecg-boot3.0的待辦消息移植記錄

    ? ? 因?yàn)橹皼](méi)有記錄,所以還要看代碼進(jìn)行尋找,比較費(fèi)勁,所以今天記錄一下: 1、后端 SysAnnouncementController 下面函數(shù)增加待辦的幾個(gè)顯示內(nèi)容給前端用 ?具體代碼如下: 2、前端 HeaderNotice.vue 文件 獲取系統(tǒng)消息里增加待辦內(nèi)容 ? 同時(shí)顯示的地方做調(diào)整,包括樣式與內(nèi)容

    2024年02月12日
    瀏覽(90)
  • linux驅(qū)動(dòng)開(kāi)發(fā)入門(mén)(學(xué)習(xí)記錄)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包