S3C6410之uboot回炉再造(7)C环境的入口

发布时间:2024-09-02  

  上一部分讲到 uboot 跳转到 start_armboot 处执行(中间插了一篇 异常中断处理)。


  这次主要是记录 start_armboot 的实现。


  文件为 /lib_arm/board.c


  1、参数声明


  1 void start_armboot (void)

  2 {

  3     init_fnc_t **init_fnc_ptr;        //这里实际上是创建数组指针

           //指向的数组为 start_armboot 之前的 init_sequence 数组

  4     char *s;

  5 #if defined(CONFIG_VFD) || defined(CONFIG_LCD)

  6     unsigned long addr;

  7 #endif


  2、两个结构体与内存屏障


  8 

  9     /* Pointer is writable since we allocated a register for it */

 10     gd = (gd_t*)(_armboot_start - CONFIG_SYS_MALLOC_LEN - sizeof(gd_t));

 11     /* compiler optimization barrier needed for GCC >= 3.4 */

 12     __asm__ __volatile__('': : :'memory');

  这里有两个结构体要展开


  1)uboot所调用的配置信息,文件为/include/asm-arm/Global_data.h


typedef    struct    global_data {

    bd_t        *bd;      

    unsigned long    flags;

    unsigned long    baudrate;

    unsigned long    have_console;    /* serial_init() was called */

    unsigned long    env_addr;    /* Address  of Environment struct */

    unsigned long    env_valid;    /* Checksum of Environment valid? */

    unsigned long    fb_base;    /* base address of frame buffer */

#ifdef CONFIG_VFD

    unsigned char    vfd_type;    /* display type */

#endif

#ifdef CONFIG_FSL_ESDHC

    unsigned long    sdhc_clk;

#endif

#if 0

    unsigned long    cpu_clk;    /* CPU clock in Hz!        */

    unsigned long    bus_clk;

    phys_size_t    ram_size;    /* RAM size */

    unsigned long    reset_status;    /* reset status register at boot */

#endif

    void        **jt;        /* jump table */

} gd_t;


  2)板子所调用的板级配置信息,文件为/include/asm-arm/U-boot.h


typedef struct bd_info {

    int            bi_baudrate;    /* serial console baudrate */

    unsigned long    bi_ip_addr;    /* IP Address */

    struct environment_s           *bi_env;

    ulong            bi_arch_number;    /* unique id for this board */

    ulong            bi_boot_params;    /* where this board expects params */

    struct                /* RAM configuration */

    {

    ulong start;

    ulong size;

    }            bi_dram[CONFIG_NR_DRAM_BANKS];

} bd_t;


  这里的 gd 实际指向了一个地址,地址位置可以看下图


  注意,这里为小端模式


  _bss_start    

     |

  TEXT/DATA       

        |        // = 0x100000 + 0x4000

CONFIG_SYS_MALLOC_LEN 

        |        // = sizeof(gd_t)

      gd_t            // gd 实际指向的地址

        |        // = sizeof(bd_t)

    bd_t       // gd_t 的第一部分就是 bd_t

     |

_armboot_start     // 定义在 start.S 中

     |

    STACK      // IRQ_STACK_START FIQ_STACK_START


  然后是内存屏障


 12     __asm__ __volatile__('': : :'memory');

  简单理解起来就是:禁止编译器优化此处的汇编代码。


  这样做,可以有效防止 编译器将当前的寄存器的值 直接替换在代码中。


  这行代码大量地使用在内存屏障函数中,例如 mb()函数组。


  更详细的介绍可以参详


http://blog.sina.com.cn/s/blog_7e741b830100wz1f.html

 

  3、分配空间


 13 

 14     memset ((void*)gd, 0, sizeof (gd_t));      //清空 gd 的对应空间

 15     gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));   //设置 bd 指向地址

 16     memset (gd->bd, 0, sizeof (bd_t));        //清空 bd 的对应空间

 17 

 18     gd->flags |= GD_FLG_RELOC;  

      // #define GD_FLG_RELOC 0x00001 /* Code was relocated to RAM*/

 19 

 20     monitor_flash_len = _bss_start - _armboot_start;


  4、初始化


 21 

 22     for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {

 23         if ((*init_fnc_ptr)() != 0) {

 24             hang ();

 25         }

 26     }


  这里的 hang 其实是死循环,函数如下


void hang (void)

{

    puts ('### ERROR ### Please RESET the board ###n');

    for (;;);

}

  意味着如果有初始化函数不存在,或者初始化失败(返回不为0),则出错。


  5、清空 code 区


 27 

 28     /* armboot_start is defined in the board-specific linker script */

 29     mem_malloc_init (_armboot_start - CONFIG_SYS_MALLOC_LEN,

 30             CONFIG_SYS_MALLOC_LEN);

  此处有


void mem_malloc_init(ulong start, ulong size)

{

    mem_malloc_start = start;

    mem_malloc_end = start + size;

    mem_malloc_brk = start;


    memset((void *)mem_malloc_start, 0, size);

}


  6、之后有大量的可配置项,这些可配置项的内部实现都很简单清晰,所以仅列出标题了


 32 #ifndef CONFIG_SYS_NO_FLASH

 37 #ifdef CONFIG_VFD

 50 #ifdef CONFIG_LCD

 75 #ifdef CONFIG_HAS_DATAFLASH

 

  7、变量搬移


 79 

 80     /* initialize environment */

 81     env_relocate ();

  具体实现在 /common/Env_common.c 中


  8、可配置项


 83 #ifdef CONFIG_VFD

 88 #ifdef CONFIG_SERIAL_MULTI

 

  9、这一段代码量较长、不继续深入


  主要功能看代码自注


复制代码

 91 

 92     /* IP Address */

 93     gd->bd->bi_ip_addr = getenv_IPaddr ('ipaddr');

 94 

 95     stdio_init ();    /* get the devices list going. */

 96 

 97     jumptable_init ();


  10、可配置项


 99 #if defined(CONFIG_API)

 


  11、控制台初始化


104     console_init_r ();    /* fully init console as a device */

 


  12、可配置项


106 #if defined(CONFIG_ARCH_MISC_INIT)

110 #if defined(CONFIG_MISC_INIT_R)

 

  13、使能中断


114 

115     /* enable exceptions */

116     enable_interrupts ();

 

  14、可配置项


119 #ifdef CONFIG_DRIVER_TI_EMAC

129 #if defined(CONFIG_DRIVER_SMC91111) || defined (CONFIG_DRIVER_LAN91C96)

 

  16、


137 

138     /* Initialize from environment */

139     if ((s = getenv ('loadaddr')) != NULL) {

140         load_addr = simple_strtoul (s, NULL, 16);

141     }

 

  17、可配置项


142 #if defined(CONFIG_CMD_NET)

148 #ifdef BOARD_LATE_INIT

152 #ifdef CONFIG_GENERIC_MMC

157 #ifdef CONFIG_BITBANGMII

160 #if defined(CONFIG_CMD_NET)

161 #if defined(CONFIG_NET_MULTI)


  18、网卡设置


164     eth_initialize(gd->bd);

 

  19、可配置项


165 #if defined(CONFIG_RESET_PHY_R)

 


  20、进入主循环


170     /* main_loop() can return to retry autoboot, if so just run it again. */

171     for (;;) {

172         main_loop ();

173     }

174 

175     /* NOTREACHED - no way out of command loop except booting */


  文件路径为 /common/Main.c


文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

相关文章

    都有多个功能,包括GPIO、UART、SPI、PWM等。正确配置PWM功能的引脚是实现PWM输出的第一步。首先,检查引脚是否使用了正确的模式和功能。其次,确认引脚的时钟使能是否正确。通过使用寄存器操作来确保引脚的正确配置......
    会导致串口接收中断无法触发。请确保正确配置了中断优先级,并确保串口接收中断的优先级高于其他中断。 3. 接收缓冲区溢出:如果接收缓冲区溢出,可能会导致串口接收中断无法触发。确保......
    问宽度和PSIZE所选并行位数类型不一致时,硬件置1;还有一种是编程并齐错误,对FLASH进行跨越128位行界限的数据编程操作时,将由硬件置位该标志位;第三种是擦除顺序错误,如果代码在控制寄存器未正确配置......
    、开关等输入设备的连接和状态,以确保PLC能够正确感知和响应输入信号。(4)检查程序和逻辑:检查PLC程序和逻辑是否正确。验证程序中的逻辑条件、定时器和计数器是否正确配置和运行。使用......
    始触摸动作转换为具体的触摸事件,并转发给当前活动的 UI 元素。 3.触摸功能实现步骤 要实现触摸功能,首先需通过 STM32CubeMX 正确配置触摸控制器和 MCU,并添加相应驱动代码,保证 MCU 通过 I2C 或其......
    = GPIO_Mode_Out_PP; //通用推挽输出 GPIO_Init(GPIOA, &GPIO_InitStructure); 正确配置: /* Configure SPI1 pins: SCK......
    问题:   PLC系统中的通信问题可能导致数据传输错误、延迟或丢失。为了减少通信问题,确保正确配置和设置通信模块、使用可靠的通信协议,并进行适当的通信测试和监控。   (3)时序问题:   PLC系统......
    器控制位,即使进入低功耗模式,还是可以进行一定程度的调试。 在保证DGBMCU控制位正确配置前提下,还需注意SWD调试脚没有被配置为【analog state】模拟输入状态。我们......
    后就没问题了。 问题5:时钟检测不过,测试时,发现工程为F030,但实际芯片是F042,二者存在时钟配置上的差异,主要是SystemInit和SystemCoreClockUpdate函数中的差异。 方法:按照实际芯片正确配置......
    件开发工具和库函数,这些工具和库函数是专门为GD32开发的,可保证与GD32硬件的正确配合。总结来看,GD32和STM32虽然都是基于ARM Cortex-M内核的微控制器,但具......

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>