AM335x裸机<二>:StartWare的分析

这篇接着上一篇,来分析上一篇程序里面的MLO和app文件启动过程,基本涵盖到整个am335x的大部分操作,包括:时钟初始化、代码搬移、中断向量的重定位、中断的处理等。要分析程序,首先分析makefile和连接脚本lds文件,然后顺藤摸瓜,当同名函数太多时,可以考虑反汇编elf文件,进行对比判断。

0.添加Source Insight工程

创建新工程,添加所有文件,注意Source Insight添加对asm和makefile文件支持,更有利于分析

1.bootloader分析

查看build/armv7a/gcc/am335x/sbc8600/bootloader目录makefile和lds文件可知(*bl_init.o),第一个文件为bootloader/src/armv7a/gcc/bl_init.S

#bootloader/src/armv7a/gcc/bl_init.S
Entry:
    bl_start
        #bootloader/src/bl_main.c
        /* 各种初始化 */
        DeviceConfig()
            #bootloader/src/bl_am335x.c
            // 关看门狗
            HWREG(SOC_WDT_1_REGS + WDT_WSPR) = 0xAAAAu;
            while(HWREG(SOC_WDT_1_REGS + WDT_WWPS) != 0x00);
            HWREG(SOC_WDT_1_REGS + WDT_WSPR) = 0x5555u;
            while(HWREG(SOC_WDT_1_REGS + WDT_WWPS) != 0x00);
            // 初始化时钟
            PLLInit();                
            // 使能控制模块
            HWREG(SOC_CM_WKUP_REGS + CM_WKUP_CONTROL_CLKCTRL) =
                    CM_WKUP_CONTROL_CLKCTRL_MODULEMODE_ENABLE;
            // 初始化内存
            EMIFInit();
            DDR3Init();
            // 初始化串口
            UARTSetup();
        /* 打印启动信息 */
        UARTPuts("StarterWare ", -1);    
        /* 将app从mmc复制到ram */
        ImageCopy();
            #bootloader/src/bl_copy.c
            MMCSDBootCopy();
                #bootloader/src/bl_hsmmcsd.c
                // 初始化控制器
                HSMMCSDInit();
                // 复制mmc内容到ram
                HSMMCSDImageCopy();
                    // 设置app入口地址
                    entryPoint = imageHdr.load_addr;
        /* 跳转到app执行 */
        appEntry = (void (*)(void)) entryPoint;
        UARTPuts("Jumping to StarterWare Application...

", -1);
        (*appEntry)( );

2.app分析

查看build/armv7a/gcc/am335x/sbc8600/bootloader目录makefile和lds文件可知(*init.o),第一个文件为system_config/armv7a/gcc/init.S

#system_config/armv7a/gcc/init.S
Entry:
    start_boot                
        #system_config/armv7a/am335x/startup.c
        /* 中断向量重定位 */
        CopyVectorTable();
            CP15VectorBaseAddrSet(AM335X_VECTOR_BASE);
                #system_config/armv7a/gcc/cp15.S
                CP15VectorBaseAddrSet:
            dest[count] = src[count];
                static unsigned int const vecTbl[14]=
                    (unsigned int)IRQHandler,
                        #system_config/armv7a/am335x/gcc/exceptionhandler.S
                        IRQHandler:
                            /* 保存现场 */
                            ...
                            /* 处理中断 */
                            LDR      r0, =fnRAMVectors
                            /* 恢复现场 */
                            ...
        /* 调用main函数 */
        main();
            #examples/sbc8600/uart/uartEcho.c
            /* 打开时钟 */
            UART0ModuleClkConfig();
            /* 串口初始化 */
            UartFIFOConfigure();
            ......
            /* 配置中断 */
            UartInterruptEnable();
                UART0AINTCConfigure();
                    IntRegister(SYS_INT_UART0INT, UARTIsr);
                        #system_config/armv7a/am335x/interrupt.c
                        void IntRegister(unsigned int intrNum, void (*fnHandler)(void))
                            fnRAMVectors[intrNum] = fnHandler;
                                void (*fnRAMVectors[NUM_INTERRUPTS])(void);
        /* 死循环 */
        while(1);

整个uart裸机程序分为两部分:MLO、app,其中MLO用于完成基本初始化,然后跳转到app入口,app负责完成中断向量(interrupt vector)重定位,并负责实现中断的处理,当uart发生收发中断时,会暂时停止当前工作,跳转到异常入口中断,进行对数据的处理,当处理完中断后,返回前面位置继续运行。

最后总结一下,分析要点:

makefile、lds、反汇编

原文地址:https://www.cnblogs.com/Ethan-Gao/p/7498875.html