一:ADS.12的工程建立与配置
① 新建工程类型为 ARM Excuteable Image。用于由 ARM 指令的代码生成一个 ELF 格式的可以执行映象文件。
② 再把lib与inc文件夹拷贝到所建工程的文件夹中,inc文件夹中包含了很多.h文件,其中.c文件在lib中。(后面将对这些文件的作用与含义进行分析)。
③ 把需要用到的函数所在的.c文件添加到工程中,在简单的现在默认工程中我们要添加这三个文件,
2440init.s(是对板子的启动初始化,有内存配置,中断初始化,栈空间的分配,中断时入栈与出栈的方式寄存器的保存——这部分与具体的板子芯片都十分相关也是系统移植时需要关注的),并且要注意在初始化时跳入C语言的入口点BL Main (在后面自己写函数时,一定要写为Main不要写成main,不然将找不到入口)。
2440lib.c文件(里面包含了对芯片的常规初始化,主要是IO的初始化与时钟频率初始化要使用到的函数,有时候会有Uart需要的一些函数,但是没有的时候可以自己在内部加入,因此自己要写一些十分基本和常用的函数时,可以把这些函数写入到这个.c文件中,但是是针对某个特殊芯片的的函数,eg:NAND FLASH,IIS,IIC等的操作,最好要在另外建立他的.c文件,这样文件结构会更加清楚)
2440slib.s文件主要是对CP15这个协处理的配置(内存管理器),配置结束后使内存,cache,CPU协调工作,最开始也对LCD的一些内存区进行了分配等。
④ 建立自己的主函数文件。(文件名字可以是main.c但是里面的函数一定是Main)
⑤ 写好自己的主函数后,再进行Debug setting,主要设置的有五项:
Target settings,其中有 Target Name (当前目标设置)Linker(默认,是表示使用什么连接器),post-Linker是链接后生成什么文件,设置为ARM from ELF(exe load flash)。
ARM Assembler 与ARM C compiler 都把芯片型号配置为ARM920T(即你开发板的型号),
ARM Linker
其中下面编译的内容中可以去掉-map –list list.txt对程序运行没影响,只是出现一些提示信息。
ARM from ELF 中设置输出文件的名字。到此一个完整的工程与配置都已经完成。
二、对一个最简单工程中的头文件与一些函数作用的分析。
在main.c中一般要包含一下几个头文件
(def.h) 定义了一些数据类型,eg:#define U8 char 。目的是增强可移植性。
(option.h) RAM,中断,栈的基地址定义,与系统时钟的定义
(2440addr.h) 定义了各种寄存器的地址。
(2440lib.h) 申明了2440lib.c中使用的函数,与其中用到的宏定义。
(2440slib.h) 申明了2440slib.s中使用到的函数。
函数 Port_Init()中就是对A-J的端口进行了一般的初始化。要修改时可以对照着用户手册进行对应的修改。
下面还包括了四个与系统时钟有关的函数,
- <span style="font-size:18px;">void ChangeMPllValue(int mdiv, int pdiv, int sdiv) //对MPLL这个锁相环进行配置
- {
- Rmpllcon = (mdiv << 12) | (pdiv <<4) | sdiv;
- }
- </span>
- <span style="font-size:18px;">void ChangeClockDivider(int hdivn_val, int pdivn_val),
- {
- int hdivn=2, pdivn=0;
-
- // hdivn_val (FCLK:HCLK)ratio hdivn
- // 11 1:1 (0)
- // 12 1:2 (1)
- // 13 1:3 (3)
- // 14 1:4 (2)
- // pdivn_val (HCLK:PCLK)ratio pdivn
- // 11 1:1 (0)
- // 12 1:2 (1)
- switch(hdivn_val) {
- case 11: hdivn=0; break;
- case 12: hdivn=1; break;
- case 13:
- case 16: hdivn=3; break;
- case 14:
- case 18: hdivn=2; break;
- }
-
- switch(pdivn_val) {
- case 11: pdivn=0; break;
- case 12: pdivn=1; break;
- }
-
- rCLKDIVN = (hdivn<<1) | pdivn;
-
- switch(hdivn_val) {
- case 16: // when 1, HCLK=FCLK/8.
- rCAMDIVN = (rCAMDIVN & ~(3<<8)) | (1<<8);
- break;
- case 18: // when 1, HCLK=FCLK/6.
- rCAMDIVN = (rCAMDIVN & ~(3<<8)) | (1<<9);
- break;
- }
-
- if(hdivn!=0)
- MMU_SetAsyncBusMode();
- else
- MMU_SetFastBusMode();
- }
- </span>
- <span style="font-size:18px;">void ChangeUPllValue(int mdiv, int pdiv, int sdiv) //对UPLL这个锁相环的配置
- {
- rUPLLCON = (mdiv<<12) | (pdiv<<4) | sdiv;
- }
- </span>
- <span style="font-size:18px;">static void cal_cpu_bus_clk(void)
- {
- U32 val;
- U8 m, p, s;
-
- val = rMPLLCON; //MPLL控制寄存器
- m = (val>>12)&0xff; //获得MDIV的值
- p = (val>>4)&0x3f; //获得PDIV的值
- s = val&3; //获得SDIV的值
-
- //(m+8)*FIN*2 不要超出32位数!
- FCLK = ((m+8)*(FIN/100)*2)/((p+2)*(1<<s))*100; //MPLL与FCLK应该等同
-
- val = rCLKDIVN; //时钟分频器控制寄存器
- m = (val>>1)&3; //获取HDIVN的值,控制HCLK与FCLK的关系(FCLK被分频多少)
- p = val&1; //控制PCLK与HCLK之间的关系
- val = rCAMDIVN; //摄像头时钟分频寄存器
- s = val>>8; //与HDIVN共同控制HCLK与FCLK的关系
-
- switch (m) {
- case 0:
- HCLK = FCLK;
- break;
- case 1:
- HCLK = FCLK>>1;
- break;
- case 2:
- if(s&2)
- HCLK = FCLK>>3;//右移3位 == 除以8
- else
- HCLK = FCLK>>2;//右移2位 == 除以4
- break;
- case 3:
- if(s&1)
- HCLK = FCLK/6;
- else
- HCLK = FCLK/3;
- break;
- }
-
- if(p)
- PCLK = HCLK>>1;
- else
- PCLK = HCLK;
-
- if(s&0x10) //取DIVN_UPLL的值,0:FCLK = MPLL clock 1:FCLK = HCLK
- cpu_freq = HCLK;
- else
- cpu_freq = FCLK;
-
- val = rUPLLCON; //UPLL控制寄存器
- m = (val>>12)&0xff; //获取MDIV
- p = (val>>4)&0x3f; //获取PDIV
- s = val&3; //获取SDIV
- UPLL = ((m+8)*FIN)/((p+2)*(1<<s)); //计算出UPLL
- UCLK = (rCLKDIVN&8)?(UPLL>>1):UPLL; //控制UCLK与UPLL的关系
- }
- </span>
对这几个函数使用方式:
- <span style="font-size:18px;">//给出了能产生 200M,300M,400M,440M几种频率的算法,设定好mpll_val与key
- //再通过函数ChangeMPllValue与ChangeClockDivider把他们传递进去
- //最后再进行cal_cpu_bus_clk,()时钟的最后确定
- i = 2 ; //don't use 100M!
- //boot_params.cpu_clk.val = 3;
- switch ( i ) {
- case 0: //200
- key = 12;
- mpll_val = (92<<12)|(4<<4)|(1);
- break;
- case 1: //300
- key = 13;
- mpll_val = (67<<12)|(1<<4)|(1);
- break;
- case 2: //400
- key = 14;
- mpll_val = (92<<12)|(1<<4)|(1);
- break;
- case 3: //440!!!
- key = 14;
- mpll_val = (102<<12)|(1<<4)|(1);
- break;
- default:
- key = 14;
- mpll_val = (92<<12)|(1<<4)|(1);
- break;
- }
-
- //init FCLK=400M, so change MPLL first
- ChangeMPllValue((mpll_val>>12)&0xff, (mpll_val>>4)&0x3f, mpll_val&3);
- ChangeClockDivider(key, 12);
- cal_cpu_bus_clk();
- </span>