移植linux到龙芯3210笔记3
来源:互联网 发布:2006年nba总决赛数据 编辑:程序博客网 时间:2024/06/05 22:54
根据笔记2对Makefile的配置,接下来就应该加入这些平台相关的代码到相应的目录下。
所以这次的主要任务是:增加代碼或修改代碼
把平台相关的代碼,加入内核工程中:
(1)将soc3210-board目录拷贝到arch/mips目录下,这里拷贝到arch/mips/mips-boards/。
这个目录将在arch/mips/kernel/Makefile中添加进去,这样集成到内核里。
(2)将mach-longmeng目录拷贝到include/asm-mips/目录下,这部分代码也将在arch/mips/kernel/Makefile中添加进去,作为头文件路径。这部分代码是loongmeng平台的特殊性,对SOC32101不知道相不相关。
(3)PCI操作相关的两个文件:fixup-soc-soc.c和ops-soc-soc.c拷贝到./arch/mips/pci/下。
(4)把平台相关的头文件目录soc-soc/加入到./include/asm-mips/下面,其中soc_soc.h保存了外设资源的地址。
在内核工程中的代碼上添加或修改平台相关的代碼:
我们开始看代码,汇编部分不用作修改,直接看main.c文件,汇编head.S执行完之后直接跳转到main.c中的start_kernel函数。
在start_kernel函数中,看与平台相关的函数setup_arch。
(1)cpu_probe() 从函数名中看,这是一个探测CPU信息的函数,所以这肯定是一个需要修改的部分。
进入cpu_probe,可以看到这个函数实际上就是读协处理器C0的PRId寄存器值。查看《See Mips Run》关于这部分的内容:
31-----------------------24-23-------------------16-15-------------8-7----------------0
| Company Options | Company ID | CPU ID | Revision |
------------------------------------------------------------------------------------------------
Company ID字段是新近定义的,因此,以前的CPU都把其设为0。
所以:
struct cpuinfo_mips *c = ¤t_cpu_data; c->processor_id = PRID_IMP_UNKNOWN; c->fpu_id = FPIR_IMP_NONE; c->cputype = CPU_UNKNOWN; c->processor_id = read_c0_prid(); switch (c->processor_id & 0xff0000) { ... ... }
c->processor_id & 0xff0000为0
执行:cpu_probe_legacy(c);
switch (c->processor_id & 0xff00) { ... ...}
实际上开始判断CPU ID,然后根据CPU ID来填写cpuinfo_mips。
在include/asm-mips/cpu.h中添加:
#definePRID_IMP_SOC32101 0x4200#define CPU_SOC32101 65 #defineCPU_LAST 66
在cpu_probe_legacy里增加PRID_IMP_SOC32101的操作:
switch (c->processor_id & 0xff00) { case ... ... ... ... case PRID_IMP_SOC32101: c->cputype = CPU_SOC32101; c->isa_level = MIPS_CPU_ISA_II; c->options = R4K_OPTS | /* MIPS_CPU_FPU | */ MIPS_CPU_LLSC; c->tlbsize = 48; break;}
对于上面定义的宏CPU_SOC32101,这个只是在本内核中的一个代号而已,没有特殊意义的。
(2)在./arch/mips/kernel/proc.c中,在cpu_name数组下多加一个元素:
static const char *cpu_name[] = {... ...[CPU_SOC32101] = "SOC32101",}
此时CPU_SOC32101就是刚才在cpu.h中定义的一个宏,而这个宏的具体值就是按这个数组的第几个元素,或者说是下标,则在本内核中所支持的CPU编号。当然了宏CPU_LAST的值就是最后的一个CPU编号,要大于或者等于最后一个,我们的最后一个是CPU_SOC32101。
在show_cpuinfo()中可以看到打印这些信息的操作。相应地,在文件系统/proc下有一个cpuinfo的文件,cat cpuinfo就可以看到这些信息了。
(3)关于mips_machgroup和mips_machtype这两个变量
执行完cpu_probe之后就是prom_init()了。prom_init函数定义在./arch/mips/mips-boards/soc32101-boards/soc-soc/prom.c里面。这个文件是平台相关的,在笔记2里说的被拷贝到内核源码的平台相关代码。在prom_init函数一开始就对这两个变量进行赋值:
mips_machgroup = MACH_GROUP_ICT; mips_machtype = MACH_SOC3210EV2E;
所以MACH_GROUP_ICT和MACH_SOC3210EV2E这两个宏要定义了。
关于组和类型的定义,一般在文件./include/asm-mips/bootinfo.h里定义的,所以在该文件里添加两个宏:
#defineMACH_GROUP_ICT 23 #define MACH_SOC3210EV2E 5
这两个宏的值不是特殊的值,只要不跟之前的重复了就行了。根据字面意思,大概这两个宏的意义是CPU组和该CPU在该组内的ID。这两个变量在代码中的具体的作用不太明确。因为之前已经存在一些CPU相关的宏定义了。当然用这两个变量也可以作一些与该CPU相关的特殊的操作。
(4)在./include/asm-mips/modules.h里定义MODULE_PROC_FAMILY
可以在看到这个文件里已经为各种支持的CPU都定义这个宏了,所以在后面加上:
#elifdefined CONFIG_CPU_SOC32101 #defineMODULE_PROC_FAMILY "SOC32101"
这个宏的实际意义不太清楚,搜索了一遍代码,没有发现代码中用到这个宏来作任何操作,但是如果不定义这个宏的话,编译会报错,因为:
#else#error MODULE_PROC_FAMILY undefined for your processor configuration#endif
(5)修改MM部分,主要是Cache和TLB
编译通过之后,下载到开发板运行了一下,結果打印一些信息就停止了。后来跟踪代码发现进入trap_init之后,就不出来了。打开./arch/mips/kernel/traps.c查看trap_init函数,发现这个函数的主要功能是设置异常处理,不过在最后调用了两个函数:
flush_icache_range(ebase, ebase + 0x400); flush_tlb_handlers();从函数的名字上可以看到这两个函数是操作cache和tlb的,程序就停在这里。
在./include/asm-mips/cacheops.h中,
修改:
#define Hit_Invalidate_I 0x10
为:
#ifdefined(CONFIG_CPU_SOC32101)#defineHit_Invalidate_I 0x00#else#defineHit_Invalidate_I 0x10#endif
如果编译报错找不到CONFIG_CPU_SOC32101这个宏,那么添加头文件#include <linux/config.h>。
在./arch/mips/mm/c-r4k.c的函数probe_pcache里添加:
switch (c->cputype) { case ... ... ...... break; caseCPU_SOC32101: icache_size= 1 << (12 + ((config & CONF_IC) >> 9)); c->icache.linesz= 16 << ((config & CONF_IB) >> 5); if(prid & 0x3) { c->icache.ways = 4; }else { c->icache.ways = 2; } c->icache.waybit=0; dcache_size= 1 << (12 + ((config & CONF_DC) >> 6)); c->dcache.linesz= 16 << ((config & CONF_DB) >> 4); if(prid & 0x3) { c->dcache.ways = 4; }else { c->dcache.ways = 2; } c->dcache.waybit= 0; break;}
在./arch/mips/mm/tlb-r4k.c去掉宏定义BARRIER的意义:
#ifdefined(CONFIG_CPU_SOC32101)#defineBARRIER#else….....#endif
在./arch/mips/mm/tlbex.c中加入操作码insn_dsrl32
在opcode枚举中加多一个成员:
insn_dsrl32
在insn_table加多一个成员:
{insn_dsrl32, M(spec_op,0,0,0,0,dsrl32_op), RT | RD | RE },
在build_get_pmde64函数中:
修改:
i_dsrl(p,tmp, tmp, PGDIR_SHIFT-3);
为:
if(PGDIR_SHIFT - 3 >= 32) { i_dsrl32(p,tmp, tmp, PGDIR_SHIFT-3 - 32); /* get pgd offset in bytes */ }else{ i_dsrl(p,tmp, tmp, PGDIR_SHIFT-3); /* get pgd offset in bytes */ }
这个函数从字面上看,是64位的操作,不太清楚这段的应用。
在函数build_adjust_context中对shift变量操作加入:
#ifdefCONFIG_PAGE_SIZE_16KB shift+=2;#endif
这个是针对页面大小为16K的情况,页面大小可在内核配置里设置,一般都是4K
按上面的记录修改后,内核跑过trap_init这个函数里,但是还是继续跑了一段就停止了,继续调试,找到原因。
PS:这部分的修改非常重要,主要是根据实际的平台作相应的修改,特别是关于CPU的Cache和TLB部分,由于不太清楚,现在只是通过对比以前的内核来确定这些修改,而这些修改对移植到一个新的CPU是至关重要的,所以这部分要继续深入。
--龙芯嵌入式系列开发板更多信息请关注 http://shop107479358.taobao.com
--龙芯1B开发板: http://item.taobao.com/item.htm?spm=a1z10.1.w4004-4678790104.8.WBYZuT&id=36562593290
- 移植linux到龙芯3210笔记3
- 移植linux到龙芯3210笔记1
- 移植linux到龙芯3210笔记2
- 移植linux到龙芯3210笔记4
- LINUX移植笔记----S3C2410
- linux驱动移植笔记
- linux移植笔记
- Linux vsftpd移植笔记
- Linux kernel移植笔记
- linux内核移植笔记
- Linux系统移植笔记
- Zedboard Linux移植笔记
- linux内核移植-DM9000C移植笔记
- linux 2.6.35移植笔记
- 给linux移植Ethercat笔记
- Linux学习内核移植相关笔记第3部分
- AT91RM9200Linux移植笔记(三)-移植Linux kernel 2.6.17
- QT6410移植linux-2.6.39 笔记(四)-dm9k驱动移植
- 如何解决在快速向jtable添加数据的时候报AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException:异常
- 【Oracle补丁集下载大全】Oracle 9i、10g、11g补丁集下载大全patchset
- Oracle Statspack报告中各项指标含义详解!
- routeapi.com_v2:时间表
- http://download.csdn.net/source/2534289
- 移植linux到龙芯3210笔记3
- c++ - 数组形参的退化/自动转换
- 做一个WAP网站
- VC项目配置详解
- Properties操作例子类
- Android 中 Log分析教程及例子(KeyDispatchingTimeout)
- VB.net中的sender和e
- cat more less 等命令的区别与使用—管道
- jsp用commons-uploadfiles1.2.1实现文件上传