MINI2440 QEMU 的 eCos 启动分析

2023-10-06 22:08
文章标签 分析 启动 ecos mini2440 qemu

本文主要是介绍MINI2440 QEMU 的 eCos 启动分析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1.总览一下eCos的启动方式

 

(原创文章,欢迎转载,请注明出处,谢谢。)


eCos目前默认的启动方式有三种,RAM,ROM,ROMRAM。

RAM启动的意思就是直接在RAM中运行,这种方式一般用于调试,不做必要的硬件初始化。

ROM启动方式的意思是在ROM中直接运行,当然一定要支持XIP的NORFLASH才可以。

ROMRAM的启动方式的意思是,ROM中开始运行然后把所有的代码复制到RAM中继续运行。

 

2.Mini2440 QEMU的启动方式的选择

 

MINI2440中目前还没有实现NOR和NAND Flash,(虽然NAND的代码加了,但是里面注名工作不是很正常,我姑且认为不能用吧)

所以,我们必须在RAM中运行eCos,并且还要完成硬件的初始化任务,这也就有了接下来的一大串的问题。

 

3.MINI2440 QEMU的启动方式分析

 

我加点注视来解释下面的ROMRAM启动代码:

 

 

// Create MMU tables

        RAW_LED_MACRO 3

        bl      hal_mmu_init

上面的语句会创建MMU页表,会把0x30000000映射到0地址,0地址映射到0x80000000

        RAW_LED_MACRO 4

 

        // Enable MMU

        ldr     r2,=10f

#ifdef CYG_HAL_STARTUP_ROMRAM

        ldr     r1,=__exception_handlers

        ldr r9,=0x80000000

        sub     r1,r2,r1

        add     r2,r9,r1        // r9 has ROM offset

这里比较重要,首先我们必须知道我们目前还运行在ROM中,经过这两条语句,我们可以确定r2里面存放的是10这个标号相对于

0x80000000的地址。

#endif        

        ldr        r1,=MMU_Control_Init|MMU_Control_M

        mcr        MMU_CP,0,r1,MMU_Control,c0

        mov        pc,r2    /* Change address spaces */

在这里我们看到,MMU被映射后我们把NOR的地址从0映射到了0x80000000,所以我们跳到R2时,就是MMU映射以后在NOR中

的运行效果。

        nop

        nop

        nop

10:

        RAW_LED_MACRO 5

 

#ifdef CYG_HAL_STARTUP_ROMRAM

        mov     r0,r9                     // Relocate FLASH/ROM to RAM

        ldr     r1,=__exception_handlers  // ram base & length

        ldr     r2,=__rom_data_end

20:     ldr     r3,[r0],#4

        str     r3,[r1],#4

        cmp     r1,r2

        bne     20b

        ldr     r0,=30f

        mov     pc,r0

这部分代码就比较简单,把ROM中的代码复制到RAM中,然后跳过去。

        nop

        nop

        nop

        nop

30:             

#endif

 

 

4. vector的问题

现在来看我们的QEMU的启动,ecos的一个特点是运行位置只是相对于启动位置,所以无论怎样我们的代码第一条是可以在RAM中跑的。

所以我们让ROMRAM代码直接跑在RAM中可以做硬件的初始化。

 

接下来的一个问题是,如何保证中断向量工作正常,我们再看两段ARM平台初始化的代码吧,(虽然比较枯燥)

 

这部分叫fix_vectors

 

.section ".fixed_vectors"

        // Interrupt/exception VSR pointers

        .globl  hal_vsr_table

hal_vsr_table:

        .rept   8               

        .long   0

        .endr

 

        .globl  hal_dram_size

hal_dram_size:  

        .long   0

// what, if anything, hal_dram_type means is up to the platform

        .globl  hal_dram_type

hal_dram_type:  

        .long   0

 

 

 

这部分是vectors复制

 

// Reset software interrupt pointer

        ldr     r0,=CYGHWR_HAL_VECTOR_TABLE_BASE           // move vectors

        ldr     r1,.__exception_handlers

#if defined(CYG_HAL_STARTUP_RAM) && /

    !defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS)

        cmp     r7,#CPSR_SUPERVISOR_MODE

        beq     10f

#endif

        ldr     r2,[r1,#HAL_ARM_SWI_VECTOR_ADDR]   // software interrupt

        str     r2,[r0,#HAL_ARM_SWI_VECTOR_ADDR]

10:

        ldr     r2,[r1,#HAL_ARM_IRQ_VECTOR]   // IRQ

        str     r2,[r0,#HAL_ARM_IRQ_VECTOR]

        ldr     r2,[r1,#HAL_ARM_IRQ_VECTOR_ADDR]

        str     r2,[r0,#HAL_ARM_IRQ_VECTOR_ADDR]

        ldr     r2,[r1,#HAL_ARM_FIQ_VECTOR]   // FIQ

        str     r2,[r0,#HAL_ARM_FIQ_VECTOR]

        ldr     r2,[r1,#HAL_ARM_FIQ_VECTOR_ADDR]

        str     r2,[r0,#HAL_ARM_FIQ_VECTOR_ADDR]

        ldr     r2,[r1,#HAL_ARM_PREFETCH_VECTOR]   // abort (prefetch)

        str     r2,[r0,#HAL_ARM_PREFETCH_VECTOR]

        ldr     r2,[r1,#HAL_ARM_PREFETCH_VECTOR_ADDR]   

        str     r2,[r0,#HAL_ARM_PREFETCH_VECTOR_ADDR]

        ldr     r2,[r1,#HAL_ARM_ABORT_VECTOR]   // abort (data)

        str     r2,[r0,#HAL_ARM_ABORT_VECTOR]

        ldr     r2,[r1,#HAL_ARM_ABORT_VECTOR_ADDR]

        str     r2,[r0,#HAL_ARM_ABORT_VECTOR_ADDR]

 

这个是link文件

 

#include <cyg/infra/cyg_type.inc>

 

MEMORY

{

    ram  : ORIGIN = 0, LENGTH = 0x8000000

    sram : ORIGIN = 0x40000000, LENGTH = 0x1000

}

 

SECTIONS

{

    SECTIONS_BEGIN

    SECTION_fixed_vectors (ram, 0x20, LMA_EQ_VMA)

    SECTION_rom_vectors (ram, 0x8000, LMA_EQ_VMA)

    SECTION_RELOCS (ram, ALIGN (0x1), LMA_EQ_VMA)

    SECTION_text (ram, ALIGN (0x4), LMA_EQ_VMA)

    SECTION_fini (ram, ALIGN (0x4), LMA_EQ_VMA)

    SECTION_rodata (ram, ALIGN (0x4), LMA_EQ_VMA)

    SECTION_rodata1 (ram, ALIGN (0x4), LMA_EQ_VMA)

    SECTION_got (ram, ALIGN (0x4), LMA_EQ_VMA)

    SECTION_fixup (ram, ALIGN (0x4), LMA_EQ_VMA)

    SECTION_gcc_except_table (ram, ALIGN (0x4), LMA_EQ_VMA)

    SECTION_data (ram, ALIGN (0x4), LMA_EQ_VMA)

    SECTION_bss (ram, ALIGN (0x4), LMA_EQ_VMA)

    CYG_LABEL_DEFN(__heap1) = ALIGN (0x8);

    SECTIONS_END

}

 

 

看到了吧,在我们的RAM中留了一块空地叫fix_vector,我们在启动的时候可以把vector复制过去,然后mmu_init以后

这部分刚好满足ARM920T的中断向量地址。庆幸吧,没修改这里就能用了

 

 

5.代码复制的问题

最后一个问题是,既然我们本来就在RAM中,我们就不用在做代码复制和NOR重新映射了,我们只要定义新的QEMU启动方式就可以旁路掉

这两部分代码了。

 

最后只要QEMU运行的时候加载elf格式的文件到0x30000000就可以正常的运行代码了。

这篇关于MINI2440 QEMU 的 eCos 启动分析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/154171

相关文章

SpringBoot通过main方法启动web项目实践

《SpringBoot通过main方法启动web项目实践》SpringBoot通过SpringApplication.run()启动Web项目,自动推断应用类型,加载初始化器与监听器,配置Spring... 目录1. 启动入口:SpringApplication.run()2. SpringApplicat

解决Nginx启动报错Job for nginx.service failed because the control process exited with error code问题

《解决Nginx启动报错Jobfornginx.servicefailedbecausethecontrolprocessexitedwitherrorcode问题》Nginx启... 目录一、报错如下二、解决原因三、解决方式总结一、报错如下Job for nginx.service failed bec

Spring Boot项目如何使用外部application.yml配置文件启动JAR包

《SpringBoot项目如何使用外部application.yml配置文件启动JAR包》文章介绍了SpringBoot项目通过指定外部application.yml配置文件启动JAR包的方法,包括... 目录Spring Boot项目中使用外部application.yml配置文件启动JAR包一、基本原理

Android 缓存日志Logcat导出与分析最佳实践

《Android缓存日志Logcat导出与分析最佳实践》本文全面介绍AndroidLogcat缓存日志的导出与分析方法,涵盖按进程、缓冲区类型及日志级别过滤,自动化工具使用,常见问题解决方案和最佳实... 目录android 缓存日志(Logcat)导出与分析全攻略为什么要导出缓存日志?按需过滤导出1. 按

解决若依微服务框架启动报错的问题

《解决若依微服务框架启动报错的问题》Invalidboundstatement错误通常由MyBatis映射文件未正确加载或Nacos配置未读取导致,需检查XML的namespace与方法ID是否匹配,... 目录ruoyi-system模块报错报错详情nacos文件目录总结ruoyi-systnGLNYpe

Linux中的HTTPS协议原理分析

《Linux中的HTTPS协议原理分析》文章解释了HTTPS的必要性:HTTP明文传输易被篡改和劫持,HTTPS通过非对称加密协商对称密钥、CA证书认证和混合加密机制,有效防范中间人攻击,保障通信安全... 目录一、什么是加密和解密?二、为什么需要加密?三、常见的加密方式3.1 对称加密3.2非对称加密四、

MySQL中读写分离方案对比分析与选型建议

《MySQL中读写分离方案对比分析与选型建议》MySQL读写分离是提升数据库可用性和性能的常见手段,本文将围绕现实生产环境中常见的几种读写分离模式进行系统对比,希望对大家有所帮助... 目录一、问题背景介绍二、多种解决方案对比2.1 原生mysql主从复制2.2 Proxy层中间件:ProxySQL2.3

解决hive启动时java.net.ConnectException:拒绝连接的问题

《解决hive启动时java.net.ConnectException:拒绝连接的问题》Hadoop集群连接被拒,需检查集群是否启动、关闭防火墙/SELinux、确认安全模式退出,若问题仍存,查看日志... 目录错误发生原因解决方式1.关闭防火墙2.关闭selinux3.启动集群4.检查集群是否正常启动5.

python使用Akshare与Streamlit实现股票估值分析教程(图文代码)

《python使用Akshare与Streamlit实现股票估值分析教程(图文代码)》入职测试中的一道题,要求:从Akshare下载某一个股票近十年的财务报表包括,资产负债表,利润表,现金流量表,保存... 目录一、前言二、核心知识点梳理1、Akshare数据获取2、Pandas数据处理3、Matplotl

python panda库从基础到高级操作分析

《pythonpanda库从基础到高级操作分析》本文介绍了Pandas库的核心功能,包括处理结构化数据的Series和DataFrame数据结构,数据读取、清洗、分组聚合、合并、时间序列分析及大数据... 目录1. Pandas 概述2. 基本操作:数据读取与查看3. 索引操作:精准定位数据4. Group