×
嵌入式 > 嵌入式开发 > 详情

基于S3C2410-ARM-Linux静态映射分析

发布时间:2020-08-17 发布时间:
|
s3c2410_gpio_cfgpin(S3C2410_GPB0, S3C2410_GPB0_TOUT0);
我们可以这样控制外设寄存器,想过它怎么实现的吗?
首先分析下structmachine_desc (include/asm-arm/Mach/Arch.h)
这是一个非常重要的结构体,内核通过 machine_desc 来控制体系架构相关部分的初始化,包括map_io,init_irq,init_machine,pthys_io,timer等

structmachine_desc{
/*
* Note! The first five elements are used
* by assembler code in head-armv.S
*/
unsignedintnr;/* architecture number*/
unsignedintphys_ram;/* start of physical ram */
unsignedintphys_io;/* start of physical io*/
unsignedintio_pg_offst;/* byte offset for io
* page tabe entry*/
constchar*name;/* architecture name*/
unsignedlongboot_params;/* tagged list*/
unsignedintvideo_start;/* start of video RAM*/
unsignedintvideo_end;/* end of video RAM*/
unsignedintreserve_lp0:1;/* never has lp0*/
unsignedintreserve_lp1:1;/* never has lp1*/
unsignedintreserve_lp2:1;/* never has lp2*/
unsignedintsoft_reboot:1;/* soft reboot*/
void(*fixup)(structmachine_desc*,
structtag*,char**,
structmeminfo*);
void(*map_io)(void);/* IO mapping function*/
void(*init_irq)(void);
structsys_timer*timer;/* system tick timer*/
void(*init_machine)(void);
};

那我们怎么创建自己的machine_desc呢?
内核给我们提供了一个宏:

#defineMACHINE_START(_type,_name)/
conststructmachine_desc __mach_desc_##_type/
__attribute__((__section__(".arch.info.init")))={/
.nr=MACH_TYPE_##_type,/
.name=_name,
#defineMACHINE_END/
};


这样我们就可以定义自己的machine_desc了

MACHINE_START(SMDK2410,"SMDK2410")/* @TODO: request a new identifier and switch
* to SMDK2410 */
/* Maintainer: Jonas Dietsche */
.phys_ram=S3C2410_SDRAM_PA,
.phys_io=S3C2410_PA_UART,
.io_pg_offst=(((u32)S3C24XX_VA_UART)>>18)&0xfffc,
.boot_params=S3C2410_SDRAM_PA+0x100,
.map_io=smdk2410_map_io,
.init_irq=smdk2410_init_irq,
.init_machine=sdmk2410_init,
.timer=&s3c24xx_timer,
MACHINE_END

这里我们创建了 machine_desc,并给其中一些成员赋了值,这相当于是内核给我们提供的编程接口,这样就可以调用自己的函数了。

这其中map_io 在 setup_arch 中调用调用,我们跟进去会发现:

在smdk2410_map_io-->s3c24xx_init_io(smdk2410_iodesc, ARRAY_SIZE(smdk2410_iodesc))->iotable_init(s3c_iodesc, ARRAY_SIZE(s3c_iodesc)) 看到:

void__init iotable_init(structmap_desc*io_desc,intnr)
{
inti;
for(i=0;icreate_mapping(io_desc+i);
}

就是在这里调用create_mapping()创建的页表,这里的第一个参数,map_desc 定义如下:

structmap_desc{
unsignedlongvirtual;
unsignedlongphysical;
unsignedlonglength;
unsignedinttype;
};

create_mapping()就是通过这个结构体创建的映射表,这样我们可以通过创建 map_desc 然后传给这个函数就可以创建相应的 虚拟地址-->物理地址 映射.

在 inlcude/asm-arch/Arch-s3c2410/Map.h

定义了每一种资源用于 map_desc变量的宏定义,如:

/* MMC controller - available on the S3C2400 */
#defineS3C2400_VA_MMC S3C2400_ADDR(0x00700000)
#defineS3C2400_PA_MMC (0x15A00000)
#defineS3C2400_SZ_MMC SZ_1M

/* UARTs */
#defineS3C24XX_VA_UART S3C2410_ADDR(0x00800000)
#defineS3C2400_PA_UART(0x15000000)
#defineS3C2410_PA_UART(0x50000000)
#defineS3C24XX_SZ_UART SZ_1M

/* Timers */
#defineS3C24XX_VA_TIMER S3C2410_ADDR(0x00900000)
#defineS3C2400_PA_TIMER(0x15100000)
#defineS3C2410_PA_TIMER(0x51000000)
#defineS3C24XX_SZ_TIMER SZ_1M

然后针对具体的某个外设,有具体寄存器的定义,如:

include/asm/arch-s3c2410/regs-timer.h

#ifndef__ASM_ARCH_REGS_TIMER_H
#define__ASM_ARCH_REGS_TIMER_H"$Id: timer.h,v 1.4 2003/05/06 19:30:50 ben Exp $"

#defineS3C2410_TIMERREG(x)(S3C24XX_VA_TIMER+(x))
#defineS3C2410_TIMERREG2(tmr,reg)S3C2410_TIMERREG((reg)+0x0c+((tmr)*0x0c))

#defineS3C2410_TCFG0 S3C2410_TIMERREG(0x00)
#defineS3C2410_TCFG1 S3C2410_TIMERREG(0x04)
#defineS3C2410_TCON S3C2410_TIMERREG(0x08)

#defineS3C2410_TCFG_PRESCALER0_MASK(255<<0)
#defineS3C2410_TCFG_PRESCALER1_MASK(255<<8)
#defineS3C2410_TCFG_PRESCALER1_SHIFT(8)
#defineS3C2410_TCFG_DEADZONE_MASK(255<<16)
#defineS3C2410_TCFG_DEADZONE_SHIFT(16)
.........................




『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
发明专利在疫情影响下的逆势增长