http://mcuos.com/redirect.php?tid=2651&goto=lastpost(原文)
关于ecos内核移植的部分内容:
一、
根据硬件平台修改代码
我们要针对740的芯片和板子情况来具体修改一些代码,主要文件放置位置及其功能如下:
1、修改平台的io宏定义
******************************************************************************
include / plf_io.h
——w90n740芯片的主要寄存器的宏定义。相当于linux里面的hardward.h,修改平台的io宏定义。在include/plt_io.h文件中完成对平台的各种IO宏定义,包括各种CPU的系统配置寄存器、内存配置寄存器、串口配置寄存器、LCD配置寄存器、以太网配置寄存器等的I/O地址。
2、修改平台的Cache代码
******************************************************************************
include /hal_cache.h
——w90n740的cache相关操作处理。修改平台的Cache代码。在include/hal_cache.h文件中修改有关Cache的宏定义。在开发初期,最好先将Cache关闭,等移植稳定后再打开。
3、实现简单的串口驱动程序。
******************************************************************************
src/ hal_diag.c:
-----硬件抽象层诊断输出函数,包含ECOS系统中printf打印的硬件设备驱动程序。实现简单的串口程序。
函数:
cyg_hal_plf_serial_init_channel()
完成对740串口的具体初始化工作。
cyg_hal_plf_serial_putc()
cyg_hal_plf_serial_getc()
从串口发送一个字符和从串口接受一个字符。通过调用cyg_hal_plf_serial_getc_nonblock()来poling接受寄存器满(有数据可读)。
cyg_hal_plf_serial_write()
cyg_hal_plf_serial_read()
从串口写一串字符和读一串字符。
cyg_hal_plf_serial_getc_nonblock()
以无阻塞的方式接收一个字符,即缓冲区中无数据时立即返回。
cyg_hal_plf_serial_isr()
串口中断服务程序;
cyg_hal_plf_serial_init()
调用cyg_hal_plf_serial_init_channel()函数初始化各串口,并向内核注册串口中断服务程序、串口的读写例程和配置例程。
cyg_hal_plf_serial_getc_timeout()
从串口接受一个字符,如果时间溢出则返回。
4、修改或增加平台初始化程序
*******************************************************************************
include / hal_platform_ints.h
——w90n740的专用中断处理,定义各个中断向量号。完成系统的中断宏定义。在不同的平台中设备数量和类型不同,中断的译码方式也不一致,需要根据具体情况作出调整。
include/ hal_platform_setup.h
—— 平台启动代码。本文件主要用ARM汇编指令编写,实现平台上电后程序的启动和执行。主要完成系统硬件的初步配置,这里一般要在看门狗和中断关闭后,配置系统时钟频率、ROM和RAM的初始化参数。
src/ w90n740_misc.c:
—— HAL的底层标准函数,包括时钟平台初始化、时钟延时函数、中断使能、中断屏蔽、中断响应等。文件完成目标板的进一步初始化、中断处理、延时例程和操作系统时钟设置。
函数:
hal_IRQ_handler()--
用AIC_IPER寄存器属于硬件自行侦测优先级中断,当前处于活动且未挂起且处于最高优先级别的中断号为:AIC_IPER。
hal_interrupt_mask()
hal_interrupt_unmask()
中断掩码函数:屏蔽和打开相应中断
hal_interrupt_acknowledge()
中断响应函数,包括清除timer的清中断寄存器。
hal_hardware_init()
关中断、关cache
hal_clock_initialize()
porting uclinux的时候的timer初始化。参考740
hal_clock_reset()
hal_clock_read()
hal_clock_reset获取装入的记数初值,hal_clock_read用初值减去当前的剩余值,得到已经记数的值。
hal_delay_us()
延时微妙级。
hal_reset()
clock选择寄存器,置1为reset
*******************************************************************************
misc/ redboot_primary_ ram.ecm —— 基于RAM启动方式的redboot最小配置文件。
misc/redboot_primary_ rom.ecm —— 基于ROM启动方式的redboot最小配置文件。
硬件启动过程
编写硬件启动的初始化过程是HAL移植的一个难点。当硬件重新上电后,系统的程序指针会自动指向地址0(通常地址0存放着bootloader代码段)。在ECOS操作系统中,程序首先会运行vectors.S文件(该文件存在于hal/arm/arch/src/目录下),它定义了reset_vector、start等各种启动标号。
接着调用740平台层的hal_platform_ setup.h文件中的宏platform_setup1和arm9变体层arm9_misc.c文件中的函数hal_hardware_init。
hal_platform_setup.h定义了宏platform_setup1以供vectors.S调用。该宏定义了目标板上SDRAM和FLASH的初始化启动,其中包括了它们的取数方式和内存大小。然后根据不同的启动方式执行程序。
对于RAM启动方式,无需进行程序段与数据段的搬移,系统已认为SDRAM的起始地址即为程序的起始地址;对于ROM启动方式,需要搬移数据段,而程序段无需搬移;对于ROMRAM启动方式,程序段与数据段都需要进行搬移,然后再把程序起始地址映射为SDRAM的起始地址。
在程序搬移完成后,系统会进行其他硬件的初始化过程,包括系统时钟、系统CACHE、监控串口等基本硬件设备。
二、
内存布局文件的编写:(以ram启动方式为例)
平台的内存布局文件在include/pkgconf目录下。通常,每个平台包括了RAM、ROM和ROMRAM 3种不同启动方式的内存布局文件集。每种启动方式的内存布局文件集都由3个类型的描述文件组成:.h文件包含内存域的C宏定义;.ldi文件定义内存域和内存段位置的链接脚本文件;.mlt文件包括由MLT工具产生的对内存布局的描述。当需要手动修改内存布局时,只有.h和.ldi文件可以被修改,.mlt文件只能由MLT工具生成。
下面以740ram启动方式内存布局为例,主要说明.h和.ldi的程序结构。
.h文件内容索引:
#define CYGMEM_REGION_ram (0)//740只有一个8M的内存,那么我在这里的内存区域只有一个,基地址是从0x0000000开始。(boot映射好之后的事情)
#define CYGMEM_REGION_ram_SIZE (0x0700000)//8M大小的内存,要预留1M给文件系统。
#define CYGMEM_REGION_ram_ATTR (CYGMEM_REGION_ATTR_R | CYGMEM_REGION_ATTR_W)
//设置内存区域的属性是可读可写的。
#ifndef __ASSEMBLER__
extern char CYG_LABEL_NAME (__heap1) [];
#endif
#define CYGMEM_SECTION_heap1 (CYG_LABEL_NAME (__heap1))
#define CYGMEM_SECTION_heap1_SIZE (0x00700000 - (size_t) CYG_LABEL_NAME (__heap1))
.ldi文件内容索引:
1.
MEMORY
2.
{
3.
ram : ORIGIN = 0x000000, LENGTH = 0x00800000
4.
}
//MEMORY部分,它定义了在RAM启动方式下所需要的内存域,以及该内存域的起始地址和长度。MEMORY部分的内容必须与 .h中定义的宏一致。
5.
SECTIONS
6.
{
7.
SECTIONS_BEGIN
8.
SECTION_fixed_vectors (ram, 0x200, LMA_EQ_VMA) //将RAM mode中断向量表放在内存中的0x200处。
9.
SECTION_rom_vectors (ram, 0x0008000, LMA_EQ_VMA)//将RAM mode内核映像在内存中的加载位置放置在0x0008000
10.
SECTION_text (ram, ALIGN (0x4), LMA_EQ_VMA)
11.
SECTION_fini (ram, ALIGN (0x4), LMA_EQ_VMA)
12.
SECTION_rodata (ram, ALIGN (0x4), LMA_EQ_VMA)
13.
SECTION_rodata1 (ram, ALIGN (0x4), LMA_EQ_VMA)
14.
SECTION_fixup (ram, ALIGN (0x4), LMA_EQ_VMA)
15.
SECTION_gcc_except_table (ram, ALIGN (0x4), LMA_EQ_VMA)
16.
SECTION_data (ram, ALIGN (0x4), LMA_EQ_VMA)
17.
SECTION_bss (ram, ALIGN (0x4), LMA_EQ_VMA)
18.
CYG_LABEL_DEFN(__heap1) = ALIGN (0x8);
//各个段的对齐方式都是4
19.
SECTIONS_END
20.
}
//SECTIONS部分,它定义了RAM启动方式下所规定的内存段,这些内存段的定义与系统内存管理功能有关。在SECTION_XXX后带有相应的参数,这些参数包括了内存段所属的内存域、起始地址(或者是对齐方式)、虚拟内存地址(VMA)和加载内存地址(LMA)。以ram方式启动的形式,所有段数据都在内存里面运行,以rom方式则数据部分要搬到ram里面。
关于串口驱动的编写部分内容: