基于全志A33开发板linux系统移植学习记录

第一章 Boot0基于ARMGCC的编译与修改


文章目录

  • 基于全志A33开发板linux系统移植学习记录
  • 前言
  • 一、全志A33简介以及上电引导流程
  • 二、Boot0编译器修改大致流程
    • 1.Boot0大体流程
    • 2.此部分需做的工作
    • 3.修改流程
  • 三、Boot0调试
  • 总结

前言

入行快两年,希望通过学习系统移植巩固下相关的知识,目标板使用基于全志A33 的astar-parrot开发板,开始本来想着使用Boot0来加载uboot,但后期发现为了代码统一和便捷性,最终还是选择了SPL作为跳板,但Boot0流程相对清晰,所以将对其做的工作贴出来便于理解。


一、全志A33简介以及上电引导流程

  • 硬件方面:A33芯片采用四核基于Cortex- A7架构的处理器,支持高清1080P视频处理,并支持各种主流视频标准,如H.264、VP8、MPEG1/2/4、JPEG/MJPEG,支持RGB/LVDS和LCD接口。256KB一级缓存和512KB二级缓存…
    软件方面:适配全志原厂基于openWrt构建的Tina系统:采用uboot2011,Linux3.4版本,可支持Android4.3,

上电流程:

  • 芯片支持五种种引导方式,分别是NAND Flash,eMMC NAND,SPI Nor Flash,SD卡(SDC 0/2)和USB。但如果要直接从USB启动系统,由内部上拉50k电阻的UBOOT_SEL引脚需要被拉低。具体引导流程可由下图说明:























Yes






No






Yes






No






Yes






No






Yes






No






No






Yes









Power up





UBOOT_SEL==0 ?





SDC0 Boot





NAND Flash Boot





SDC2 Boot





SPI Boot







Boot Ok,run other firmware







USB boot operation






  • Soc内部SROM区固化一段代码,上电首先执行这段代码,其主要是判断启动介质并将介质中的部分代码搬运至内部SRAM中(SRAM A1区域,最大32KB,相关控制器已经初始化)并mv PC跳转,判断的顺序就是上图所示。由于目标板使用mmc存储方式,并向外提供了SD卡插槽,为了保证不烧砖(由于移植过程中去掉了fel mode,相对不是很安全),首先利用工具将厂商提供的镜像烧录至mmc(SDC2)中,然后后面利用TF卡,将编译好的bin档dd到sd卡偏移16sector的位置,(SDC0)启动移植代码(SDC0优先级高,所以不会有影响),

二、Boot0编译器修改大致流程

1.Boot0大体流程

根据上述A33的启动方式描述,由于主体u-boot占用内存远远大于其SRAM容量,所以Boot0的主要作用就是运行在SRAM中,初始化启动介质,初始化外部DDR,并搬运uboot到DDR最后跳转。源码github:https://github.com/wangzl-coder/sunxi-basicLoader.git

2.此部分需做的工作

Boot0是比较简单但非常底层的裸机程序,SOC厂商发布的Boot0源码是基于cygwin+armcc进行编译,为了后续的方便,我们需要修改并重新编译,而由于armcc的非开源性,所以第一步是将其转换标准,使用ARM GCC编译方式编译。

3.修改流程

(1)编译环境的搭建部分省略,选用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   = ARMGCCLICHEEPATH      = $(SDKROOT)/../../tools/pack/chips/$(ARCH)
WORKSPACEPATH   = $(SDKROOT)/../pack/chips/$(ARCH)
WORKTOOLS       = $(SDKROOT)/pctoolsifeq ($(CROSSTOOL), ARMRVDS)#===============================================================
#RVDS编译器参数配置
#===============================================================elseifeq ($(CROSSTOOL), ARMGCC)#===============================================================
#GNU编译器参数配置
#===============================================================
CROSS_COMPILE ?= arm-linux-gnueabi-
#编译器
CC          = $(CROSS_COMPILE)gcc
#编译器参数
CFLAGS      =  #打包库
AS          = $(CROSS_COMPILE)as
#打包库参数
ASFLAGS     =#链接器
LD        = $(CROSS_COMPILE)ld
#链接器参数
LKFLAGS     =#objcopy
OBJCOPY        = $(CROSS_COMPILE)objcopy
#加载器参数
OBJCOPY_FLAGS     = -O binary -Selseerror:$(error CROSSTOOL configuration is invalid!!!)endif
endif

(2) 修改相关文件格式:根据gnuc标准,首先将所有汇编文件后缀修改为.S(大写),将目录标识符"“修改linux格式”/"。
(3)boot0/make.cfg 添加编译,链接参数

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段作为起始段,将头校验段链接在起始位置,此处首先需要对head自定义段,boot0/Boot0_head.c:

#include "boot0_i.h"#define   DDR3_USEDconst 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 codeBOOT0_MAGIC,        // ="eGON.BT0" or "eGON.BT1",  not C-style string.STAMP_VALUE,        // generated by PC#ifdef ALIGN_SIZE_8K0x2000,#else0x8000,          // generated by PC#endifsizeof( boot_file_head_t ),   // the size of boot_file_head_tBOOT_PUB_HEAD_VERSION,     // the version of boot_file_head_t0,                             // the return value0,                          // run addrEGON_VERSION,                  // eGON version{0, 0, '3','.','1','.','0',0    // platform information},},
#ifdef  DDR3_USED{sizeof( boot0_private_head_t ),   // the size of prvt_headBOOT0_PRVT_HEAD_VERSION,          // the version of boot0_private_head_t/******DRAM patameters for initialising dram. Original values is arbitrary******/{   /***normal configuration******/552,                 //dram_clk3,                //dram_type0x3bbb,              //dram_zq1,             //dram_odt_en0x10F20200,                //dram_para10x00,               //dram_para2/****timing configuration*****/0x1840,               //dram_mr00x40,             //dram_mr10x8,          //dram_mr20,            //dram_mr30x0048A192,               //dram_tpr00x01B1B18d,              //dram_tpr10x00076052,              //dram_tpr20x0,             //dram_tpr30x0,             //dram_tpr40x0,             //dram_tpr50x0,             //dram_tpr60x0,             //dram_tpr70x0,             //dram_tpr80x0,             //dram_tpr90x0,             //dram_tpr100x0,                //dram_tpr11168,                //dram_tpr120x10900,                //dram_tpr13},                         3,                             // UART控制器编号{{ 8, 6, 3, 1, 0xff, 0xff, {0, 0} },  // UART控制器(调试打印口)数据信息 tx{ 8, 7, 3, 1, 0xff, 0xff, {0, 0} }      // UART控制器(调试打印口)数据信息 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} },           // 存储设备 GPIO信息},/****用户保留数据信息****/{ 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*)}
}

比较简单,主要是为了指定链接参考地址Boot0.o的.text(_start)以及头部数据.bt0_head,bt0_head第一个成员变量将是SROM中mv PC的位置,所以这里放入一个跳转指令0xEA…,指令后面跟当前PC的偏移量(单位为字,所以要除以sizeof(int)),这里要注意流水线问题,由于是三级流水,当前PC指针的位置应该在执行代码地址的两个字后,所以此处需要减去2,通过这个跳转指令可以跳转到head结构体之后的第一个地址(_start)处运行,还有BT0_head这个变量需要在其他任意地方引用一次,否则编译器链接时可能会把它优化掉。

(5)C标准库函数引用问题

可能没有找到合适的编译器版本,在使用C标准库函数(如memset)时,会导致死机的问题,经过后续验证,发现只有在操作字节数大于某些值时才会死机,不明原因,除此还有除法的使用问题,会编译报错,网上查找说链接时需要链接libgcc库,但试了很多方法都不行,所以针对这两个方法只能用最麻烦但是最保险的方式处理
首先针对memset等函数使用问题,摒弃了libc的实现,自己实现这些操作:sunxi-basicLoader/boot0/lib/extra_libc//extra_string.h:

#ifndef __EXTRA_STRING_H__
#define __EXTRA_STRING_H__#define NULL 0void *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;}

第二个就是除法的问题,两种处理方式,如果除数是2的n次方,在编译时指定优化等级-O2 ,编译器会将其转换成移位运算(>>n),如果不是,只能采用最原始的方法,将其转换为乘法(由于商值都是整型),例如下面:

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

可以乘法转换:

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

(6)头校验:
>前面放在起始位置的head数据主要用于SROM代码的启动校验,主要包括magic字符串以及校验和,由于校验和只能在编译完成后才能计算设定,所以必须要写一个基于主机(Ubuntu等)平台的工具对二进制文本进行操作,添加文件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 codeunsigned char   magic[8];           // ="eGON.BT0" or "eGON.BT1",  not C-style string.unsigned int  check_sum;          // generated by PCunsigned int  length;             // generated by PCunsigned int  pub_head_size;      // the size of boot_file_head_tunsigned char   pub_head_vsn[4];    // the version of boot_file_head_tunsigned int  ret_addr;           // the return valueunsigned int  run_addr;           // run addrunsigned char   eGON_vsn[4];        // eGON versionunsigned 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根据头部文件结构体的length变量判断加载字节数,这里我们同样判断生成bin文档的length,根据length输出文件,空位补零。gcc编译运行,会将校验和写入结构体对应位置处。

(7)其他细节修改:armgcc编译流程的大体搭建就是这些,当然还有很多细节的东西需要实际编译或者烧录运行时才能发现。

三、Boot0调试

编译通过完成后,生成boot0_sdcard_sun8iw5p1.bin,dd if=boot0_sdcard_sun8iw5p1.bin of=/dev/sdb(根据sd挂载名称) bs=1024 seek=8将其烧录到sd卡第16扇区,插卡上电即可开始调试,前面说到Boot0主要工作就是初始化DDR,加载uboot并跳转,其主要代码如下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);/*******************************************************************************
*函数名称: Boot0_C_part
*函数原型:void Boot0_C_part( void )
*函数功能: Boot0中用C语言编写的部分的主流程
*入口参数: 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
#elsetimer_init();
#endifUART_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_SUN7Ireset_cpux(1);
#endiffel_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_SUN7Icheck_super_standby_flag();
#endif#if SYS_STORAGE_MEDIA_TYPE == SYS_STORAGE_MEDIA_NAND_FLASHstatus = load_Boot1_from_nand( );         // 载入Boot1
#elif SYS_STORAGE_MEDIA_TYPE == SYS_STORAGE_MEDIA_SPI_NOR_FLASHstatus = load_boot1_from_spinor( );         // 载入Boot1
#elif SYS_STORAGE_MEDIA_TYPE == SYS_STORAGE_MEDIA_SD_CARD//dram参数拷贝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.
#endifmsg("Ready to disable icache.\n");mmu_disable( );                               // disable instruction cacheif( status == OK ){//跳转之前,把所有的dram参数写到boot1中set_dram_para((void *)&BT0_head.prvt_head.dram_para, dram_size);msg("Jump to secend Boot.\n");jump_to( UBOOT_BASE );                    // 如果载入Boot1成功,跳转到Boot1处执行}else{
//      disable_watch_dog( );                     // disable watch dogpll_reset();msg("Jump to Fel.\n");jump_to( FEL_BASE );                      // 如果载入Boot1失败,将控制权交给Fel}
}

移植的基本思想:先把串口拉起来先跑,有问题处理问题,所以第一步先配置uart,我这里硬件上使用uart3作为调试串口,根据源码追一下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 clockif(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 gpioboot_set_gpio((void *)uart_ctrl, 2, 1);// Set Baudrateuart_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 Registertemp = ((PARITY&0x03)<<3) | ((STOP&0x01)<<2) | (DLEN&0x03);UART_REG_LCR(port) = temp;// Disable FIFOsUART_REG_FCR(port) = 0x06;
}

可以看出来,uart初始化使用bt_head成员变量初始化其GPIO以及uart控制器,这里需要配置使用uart的GPIO复用功能,对照芯片手册,uart3 tx使用GPH_6,rx使用GPH_7,在 BT0_head中配置uart:

3,                             // UART控制器编号{{ 8, 6, 3, 1, 0xff, 0xff, {0, 0} },  // UART控制器(调试打印口)数据信息 tx{ 8, 7, 3, 1, 0xff, 0xff, {0, 0} }      // UART控制器(调试打印口)数据信息 rx},

DDR配置与时序:

/***normal configuration******/552,                 //dram_clk3,                //dram_type0x3bbb,              //dram_zq1,             //dram_odt_en0x10F20200,                //dram_para10x00,               //dram_para2/****timing configuration*****/0x1840,               //dram_mr00x40,             //dram_mr10x8,          //dram_mr20,            //dram_mr30x0048A192,               //dram_tpr00x01B1B18d,              //dram_tpr10x00076052,              //dram_tpr20x0,             //dram_tpr30x0,             //dram_tpr40x0,             //dram_tpr50x0,             //dram_tpr60x0,             //dram_tpr70x0,             //dram_tpr80x0,             //dram_tpr90x0,             //dram_tpr100x0,                //dram_tpr11168,                //dram_tpr120x10900,                //dram_tpr13

使用SDC0启动,同样根据芯片手册,配置其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} },           // 存储设备 GPIO信息},

期间遇到sd卡驱动失败的问题,调试发现mmc->capacity容量是零,经过很长时间的调试,对照sanDisk的Spc,两者通讯正常且sd卡的相关寄存器都读取正常,发现capacity计算方法出现问题:

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

这里需要计算sd卡block的数量,应该是capacity有多少个bl_len,所以正确方法应该如下:

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

一步一步调试之后,直到打印出现sdcard0 init ok说明整个Boot0工作正常,后面对于uboot的操作,由于sd卡中尚未烧录uboot,所以校验失败,后续用移植后的uboot校验,正确跳转并执行,Boot0工作到此结束。


总结

Boot0代码虽然不是那么的复杂,但移植过程中确实遇到不少麻烦,牵扯到方方面面,虽然后期舍弃了Boot0方式,但是对其调试修改的过程确实能收获不少,后续任务是uboot和linux kernel的操作,加油!

基于全志A33开发板linux系统移植学习记录(Boot0)相关推荐

  1. 玩转开发板--Linux系统移植至开发板fl2440实践过程

    一.开发板介绍     CPU:S3C2440(SAMSUNG).ARM920T.400MHz     Pone/mic:耳机和话筒 JTAG:可以通过外部插入直接控制CPU,因此在初始化内存时,起到 ...

  2. iTOP-4418开发板Linux系统移植modbus

    首先确保开发板和虚拟机 Ubuntu 可以 ping 通,如下图所示,作者虚拟机的 IP 为"192.168.2.200" 通过开发板可以 ping 通 Ubuntu. 其次,注意 ...

  3. iTOP-4418开发板Linux系统移植modbus-arm的测试程序

    进入目录/home/minilinux/libmodbus-3.1.4/tests/,查看测试程序 random-testserver.c,如下图所示 已经编译出来了,但是还是需要修改一下源码中的几个 ...

  4. NUC980开发板Linux系统EC20模块 移植 串口 PPP拨号

    NUC980开发板Linux系统EC20模块 移植 串口 PPP拨号 1. EC20模块连接 2. Linux内核配置 3. 交叉编译PPP 4. 拨号脚本 5. 进行拨号 1. EC20模块连接 在 ...

  5. 基于全志T133-s3(Tina Linux)移植wifi(rtl8723d)驱动

    基于全志T133-s3(Tina Linux)移植wifi(rtl8723d)驱动 1.硬件电路 2.软件准备 2.1.驱动代码 2.2.修改脚本 2.3.添加驱动 2.4.设备树适配 3.测试wif ...

  6. 全志A33开发板vstar编译环境搭建

    全志A33开发板vstar编译环境搭建 安装系统 全志提供的vstar的SDK使用内核linux-3.4.39, 在编译过程中,要用到一个文件gen_check_code,位于linux-3.4/ar ...

  7. 全志A33开发板烧录Image到EMMC教程

    全志A33开发板烧录Image到EMMC教程 当前环境: Manjaro Linux 软件: sunxi-livesuite 1. 安装烧录软件 $ yay -S sunix-livesuite-gi ...

  8. 基于全志T133-s3(Tina Linux)移植5寸RGB显示屏驱动

    基于全志T133-s3(Tina Linux)移植5寸RGB显示屏驱动 1.硬件电路 2.LCD实物图 3.LCD 的驱动 4.uboot配置 4.1.配置文件 4.2.uboot设备树 5.kern ...

  9. 基于NNEWN NSR3588开发板Android12系统实现四屏异显

    基于NNEWN NSR3588开发板Android12系统实现四屏异显 RK3588四屏异显功能实现介绍 1.硬件连接 2.内核dts配置 3.Android异显示方案 4.四屏异显测试APK及效果演 ...

最新文章

  1. python中的__str__ __name__ 和__call__方法
  2. Git之submodule使用总结
  3. php curl ajax get请求,PHP的curl的get,post请求-Fun言
  4. 服务器linux启动,Linux 服务器环境启动
  5. 特斯拉推出儿童版电动四轮越野摩托车
  6. Django:应用程序的两种架构:C/S架构,B/S架构,(TCP, URL)HTTP,HTTP request, HTTP response
  7. Java服务器多站点,java客户端web服务器连接到多个web服务器
  8. python分布式任务调度_Python开源任务调度框架介绍
  9. mysql常用字符串操作函数大全,以及实例
  10. nsis使用URLDownloadToFile下载文件
  11. VB6+Mo图层顺序的调整(MoveToTop、MoveTo、MoveToBottom )
  12. 恶意软件清理助手 v2.50 Build 005
  13. hiveql 没有left()right()函数,可用substr()替代
  14. JS+asp.net在线裁剪图片源码
  15. 2019.9.27,SAP成都研究院数字创新空间团队建设,射箭和游泳
  16. 【ChatGPT模板】教学辅助教案篇
  17. 在Azure上建立Ubantu虚拟机
  18. 基于6818粤嵌开发板的2048游戏项目
  19. 电脑系统修复之--Windows系统开机蓝屏 EFI Network 0 for IPv4(XX-XX-XX-XX-XX)boot failed.
  20. 使用SurfaceView实现飘赞动画

热门文章

  1. 【群话题精华】五月集锦—— 机器学习和深度学习中一些值得思考的问题
  2. 网络知识入门,用户如何连接互联网,ADSL调制解调器的妙用,PPP上网的三种方式(十二)
  3. 如何打开tdms文件
  4. 服务器2008 r2开启远程桌面连接不上,windows server 2008 R2怎么开启远程桌面_windows server 2008 R2开启远程桌面的步骤...
  5. java并发编程实战wwj----------------------第二阶段-------不可变对象-------19-20
  6. TransR 论文笔记
  7. php内存不够,php内存不足怎么办
  8. 新字体引用本地运行可以获得,放到服务器上报404
  9. python中用递归求和
  10. 计算机与通信专业英语教学大纲,通信工程专业英语教学大纲英文版.docx