
arm原理与c程序设计-第四章课件.ppt
144页单击此处编辑母版标题样式,第四章,,ARM存储系统及其配置,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,*,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,*,*,第四章 ARM存储系统系统其配置,,4.1 RealView MDK仿真环境建设,4.2 Nand Flash启动配置,4.3 SDRAM配置,4.4 CP15协处理器,4.5 MMU配置,本章小结,第四章 ARM存储系统系统其配置4.1 RealVie,4.1 RealView MDK仿真环境建设,本书采用的软件为RealView MDK-ARM Version 3.24(即安装软件),集成开发环境为Keil mVision3 v3.63,MDK内部使用的编译连接器为RVDS v3.1版本安装完成后的开发环境界面如图4-1所示,后续的交叉开发工作均基于该集成开发环境4.1 RealView MDK仿真环境,图4-1 RealView MDK工作环境,图4-1 RealView MDK工作环境,4.1.1 开发平台建设,将UP-NETARM2410实验箱的JP1(位于实验箱的左上方)跳线跳至2-3脚,即使2-3脚相连接,工作在ARM-ICE状态下。
然后,将ULINK2连接到实验箱的J1接口(位于实验箱的左上方,20针),ULINK2仿真器的另一端与计算机的USB口相连接(支持热插拔)打开实验箱电源开关,打开计算机,进入图4-1所示界面由于ULINK2仿真器基于USB口,可以使用不带并口的笔记本电脑作为研发计算机,十分方便4.1.1 开发平台建设 将UP-NETARM24,当需要测试数字信号或输出信号的时序和波形时,读者还要具备示波器、逻辑分析仪等;需要接外部设备时,读者甚至需要做一些专用接口板卡,特别是针对技创SBC2440实验板但是本书的学习,不需要这些贵重的仪表本书主要讲解UP-NETARM2410实验箱自身硬件能够实现的功能,第七章中还要讲述串口通信程序设计,读者需要用到一根串口线当需要测试数字信号或输出信号的时序和波形时,读者还要具备,4.1.2 第一个MDK工程,,在图4-1中点击菜单“Project | New mVision Project”,在弹出的“Create New Project”对话框中选择保存工程文件的目录,在文件名框中输入ex4_1,如图4-2所示,点击对话框右下角的“保存”按钮(工程文件完整目录为E:\ARM9BOOK\ex4_1\ex4_1.uv2),之后如图4-3所示。
4.1.2 第一个MDK工程 在图4-1中点击菜单“,图4-2 创建新工程对话框,图4-2 创建新工程对话框,图4-3 选择ARM芯片对话框,图4-3 选择ARM芯片对话框,在图4-3中选择S3C2410A,点击“OK”按钮这里选择S3C2410A是由于UP-NETARM2410实验箱上使用了S3C2410A如果读者的ARM实验箱上不是该芯片,则要选择相应的芯片;如果没有找到相应的芯片(这是有可能的),说明MDK芯片数据库中还没有包括该芯片,这时读者可任选一个,但是需要自己编写初始化文件这种情况下,使用MDK和使用RVDS的编程工作量差不多,MDK的优点在于对其芯片数据库中的ARM芯片可图形化地配置芯片存储器和外设,这一点对初学者尤其是那些只懂C语言的读者十分方便在图4-3中选择S3C2410A,点击“OK”按钮这里,需要指出的是,在基于ARM芯片级程序设计中需要做这些初始化工作;如果读者直接使用了商业化的操作系统,例如Windows CE等,则无需理会这些初始化工作,操作系统供应商为用户考虑了初始化工作 点击图4-3的“OK”按钮后,弹出如图4-4所示的对话框,对话框标题中有乱码,这是因为使用特殊字符“μ”的缘故。
图4-4询问“将Samsung S3C2410A启动代码文件拷贝到工程文件夹中并将该文件添加到工程中吗?”,回答“是(Y)”,进入图4-5所示窗口需要指出的是,在基于ARM芯片级程序设计中需要做这些初始,图4-4 添加初始化代码对话框,图4-4 添加初始化代码对话框,图4-5 添加了初始化文件S3C2410A.s的ex4_1工程窗口,图4-5 添加了初始化文件S3C2410A.s的ex4,双击图4-5左边的工程工作区(Project Workspace)中的S3C2410A.s,如图4-6所示S3C2410A.s文件具有两种编辑和显示方式:即Text Editor文本编辑和显示方式以及Configuration Wizard图形配置智能向导方式 在图4-6中显示了文本形式的S3C2410A.s文件的开始几行,这几行均为注释,这部分注释的含义为“该文件(指S3C2410A.s)是mVision/ARM开发工具的一部分,所有版权归Keil公司该软件(指MDK)仅供具有Keil授权的合法有效的最终用户使用双击图4-5左边的工程工作区(Project Works,由此可见Keil公司对该文件的重视程度。
图4-6中也解释了Startup Code的含义,即Executed After Reset(复位后执行的代码)这段代码的含义和使用方法将在本章和第五章中逐步介绍(笔者也将编写一个启动代码)同时,笔者强调,所有MDK软件及启动代码的版权归Keil公司,笔者使用了评估版本,并且,遵守了Keil公司相关的协议,仅用于教学评估由此可见Keil公司对该文件的重视程度图4-6中也解释,图4-6 S3C2410A.s文件,图4-6 S3C2410A.s文件,聪明的读者可能会问及能不能自己写启动代码,答案是肯定的对比一下MDK软件的启动代码及我们自己写的启动代码,一定会从中学到不少东西尽管如此,笔者建议高级的ARM程序员自己编写启动代码 在图4-6中点击菜单“File | New”,并输入如下的代码: 1 #define Seg7_1_addr (*(volatile unsigned char*) 0x08000110) 2 #define Seg7_2_addr (*(volatile unsigned char*) 0x08000112) 3 4 #define uchar unsigned char,聪明的读者可能会问及能不能自己写启动代码,答案是肯定的,5 6 uchar seg7table[16] = 7 { 8 0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80, 0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E 9 // 0 1 2 3 4 5 6 7 8 9 A B C D E F 10 }; 11 12 int main() 13 { 14 Seg7_1_addr = seg7table[2];,5 6 uchar seg7table[1,15 Seg7_2_addr = seg7table[9]; 16 while(1) 17 { 18 19 } 20 } 这些代码将在第七章中解释,将上述代码保存为文件ex4_1.c,并添加到工程中(在图4-6中,右键点击Source Group 1,在弹出菜单中选择“Add Files to Group(Source Group 1)”,在弹出的添加文件对话框中选择刚创建的文件ex4_1.c)。
目前工程文件窗口如图4-7所示15 Seg7_2_addr = seg7t,图4-7 ex4_1工程文件窗口,图4-7 ex4_1工程文件窗口,图4-7右下角的状态栏“Simulation”表示当前工程工作在软件仿真模式下(常被称作模拟模式)如果工程中还包括其他的文件,通过鼠标右键菜单添加文件的方式将那些文件添加到工程中,这样一个工程文件即创建成功此处,ex4_1.uv2工程仅包括两个文件,即启动代码S3C2410A.s和C程序ex4_1.c查看一下ex4_1.uv2工程所在的目录,还可以看到扩展名为 .opt、.plg和 .dep的三个MDK软件后台自动创建的文件,这些文件均为ASCII格式,可以用记事本或UltraEdit等软件打开查看,它们是与编译连接相关的文件图4-7右下角的状态栏“Simulation”表示当前工,4.1.3 硬仿真环境设置,在图4-7中,选择菜单“Project | Options for Target’Target 1’”,或右键点击窗口左侧的“Project Workspace”中的“Target 1”,在弹出菜单中选择“Options for Target' Target 1'”,进入图4-8所示窗口,选中“Debug”页签。
4.1.3 硬仿真环境设置 在图4-7中,选择菜单,图4-8 Debug调试设置选项,图4-8 Debug调试设置选项,图4-9 ULINK仿真设置,点选图4-8中的“Use”,从组合框中选择“ULINK ARM Debugger”,如图4-9所示图4-9 ULINK仿真设置 点选图4-8中的“Use,图4-10 ARM目标仿真驱动配置,点击图4-9右上角的“Settings”,弹出如图4-10所示窗口图4-10 ARM目标仿真驱动配置 点击图4-9右上角,在图4-10中选中“Automatic Detection”,将自动检测到ARM核点击“OK”按钮回到图4-9点击图4-9中的“OK”按钮,回到图4-7,此时图4-7右下角的状态栏将由“Simulation”变为“ULINK ARM Debugger”,表示此时集成开发环境处于硬仿真工作状态,简称仿真状态在图4-10中选中“Automatic Detectio,4.1.4 编译配置,在主界面下选择菜单“Project | Options for Target‘ Target 1’”,在弹出的目标选项窗口中选择“Target”页签,并设置其内容,如图4-11。
图4-11中,根据硬件中使用的时钟频率设置Xtal的值为12.0,将片外SDRAM的16 MB配置为只读存储区,48 MB配置为读写存储区,同时片上有4 KB的RAM区 在图4-11中,点击Debug页签,添加初始化文件S3C2410SDRAM.ini,如图4-12所示4.1.4 编译配置 在主界面下选择菜单“Proj,图4-11 “Target”选项页仿真设置,图4-11 “Target”选项页仿真设置,图4-12 添加初始化文件,图4-12 添加初始化文件,其中,S3C2410SDRAM.ini的内容如下:/***************************************//*,S3C2410SDRAM.INI: External RAM (SDRAM) Initialization File,*//*********************************************/// >> // /*********************************************//* This file is part of the uVision/ARM development tools. *//* Copyright (c) 2005-2006 Keil Software. All rights reserved. */,其中,S3C2410SDRAM.ini的内容如下:/***,/* This software may only be used under the terms of a valid, current, *//* end user licence from KEIL for a compatible version of KEIL software *//* development tools. Nothing else gives you the right to use this software. *//*************************************/FUNC void Setup (void){ _WDWORD(0x53000000, 0x00000000); // watch _WDWORD(0x4A000008, 0xFFFFFFFF); // intmsk1,/* This software may only be u,_WDWORD(0x4A00001C, 0x000007FF); // intsub _WDWORD(0x4C000014, 0x00000003); // CLKDIVN _WDWORD(0x4C000004, 0x0005C042); // MPLLCON _WDWORD(0x56000070, 0x00280000); // GPHCON _WDWORD(0x56000078, 0x00000000); // GPHUP _WDWORD(0x48000000, 0x22111110); // BWSCON _WDWORD(0x48000004, 0x00000700); // BANKCON0 _WDWORD(0x48000008, 0x00000700); // BANKCON1 _WDWORD(0x4800000C, 0x00000700); // BANKCON2 _WDWORD(0x48000010, 0x00000700); // BANKCON3,_WDWORD(0x4A00001C, 0x000007F,_WDWORD(0x48000014, 0x00000700); // BANKCON4 _WDWORD(0x48000018, 0x00000700); // BANKCON5 _WDWORD(0x4800001C, 0x00018009); // BANKCON6 _WDWORD(0x48000020, 0x00018009); // BANKCON7 _WDWORD(0x48000024, 0x00AC0459); // REFRESH _WDWORD(0x48000028, 0x000000B1); // BANKSIZE _WDWORD(0x4800002C, 0x00000020); // MRSRB6 _WDWORD(0x48000030, 0x00000020); // MRSRB7 _WDWORD(0x56000014, 0x00000001); // GPBDAT _WDWORD(0x56000020, 0xAAAA55AA); // GPCCON _WDWORD(0x56000028, 0x0000FFFF); // GPCUP,_WDWORD(0x48000014, 0x0000070,_WDWORD(0x56000024, 0x00000000); // GPCDAT } Setup(); // Setup for Init LOAD ex4_1.axf INCREMENTAL// Download PC = 0x30000000; // Program Entry Point g, main // Run to main function 上述代码为调试脚本,使用过AXD Debugger软件调试ARM程序的读者对此一定不陌生。
调试脚本由命令和函数组成,例如_WDWORD(address, ulong val)表示向address地址写入一个32位的(配置)字这段代码的主要功能为配置外部SDRAMWDWORD(0x56000024, 0x000000,4.1.5 仿真,在主界面下点击菜单“Project | Rebuild all target files”或点击工具栏上的快捷编译按钮,编译ex4_1工程,如图4-13所示图4-13 编译工程文件,4.1.5 仿真 在主界面下点击菜单“P,点击图4-13中菜单“Debug | Start/Stop Debug Session Ctrl+F5”或点击工具栏上的快捷调试图标,如图4-14所示 图4-14中可以查看寄存器的值、存储空间和反汇编及程序执行位置等信息,按F11键可单步执行程序,执行到死循环后,UP-NETARM2410实验箱上的两个七段数码管会显示“29”字样程序中定义的字节型数组seg7table包含16个元素,为RW型数据,根据图4-11的存储区配置,该数组应位于地址0x31000000处,如图4-14右侧的Memory区所示。
点击图4-13中菜单“Debug | Start/Sto,图4-14 调试窗口,,图4-14 调试窗口,4.2 Nand Flash启动配置,本节介绍UP-NETARM2410上电后如何从Nand Flash启动以及如何借助ULNK2向Nand Flash写入启动程序对Nand Flash访问的程序设计可参考MDK软件自带的写Flash算法,如下文的图4-18 在工程文件主界面上,点击菜单“Project | Options for Target' Target 1'”,选择“Target”页签,设置该页如图4-15所示4.2 Nand,图4-15 Target页签设置情况,图4-15 Target页签设置情况,图4-16 Utilities页签设置情况,点击图4-15上的Debug页签,设置如图4-9所示,即去掉,配置初始化文件然后点击图4-15上的Utilities页签,设置如图4-16所示图4-16 Utilities页签设置情况 点击图4-,图4-17 Flash下载配置对话框,点击图4-16上的“Settings”,弹出如图4-17所示的“Flash Download Setup”对话框,配置内容如图4-17所示。
图4-17 Flash下载配置对话框 点击图4-16上,图4-18 选择Flash编程算法,图4-17中,点击“Add”按钮,在弹出的对话框中选择K9F1208,如图4-18所示图4-18 选择Flash编程算法 图4-17中,点击,图4-18中的“K9F1208”Flash编程算法(Programming Algorithm),是将C:\Keil\ARM\Flash\ S3C2410_NAND_SP\FlashDev.c中的struct FlashDevice const FlashDevice结构体常量修改如下: struct FlashDevice const FlashDevice = { FLASH_DRV_VERS, // Driver Version, do not modify!,“K9F1208”, //“S3C2410 NAND Flash SP”,,// Device Name EXT8BIT, // Device Type 0x00000000, // Device Start Address,图4-18中的“K9F1208”Flash编程算法(Pr,512, // Programming Page Size 0, // Reserved, must be 0 0xFF, // Initial Content of Erased Memory 200, //Program Page Timeout 200 mSec 3000, // Erase Sector Timeout 3000 mSec // Specify Size and Address of Sectors 0x4000, 0x000000, // Sector Size 16 KB SECTOR_END };,512, // Progr,即把设备名(Device Name)修改为“K9F1208”,把存储容量(Device Size in Bytes)改为“0x04000000”。
同时,把FlashHW.c中的函数InitFlashController_HW的寻址时钟周期“*adr_cycles = 3;”修改为“*adr_cycles = 4;”然后重新编译工程文件 点击图4-18中的“Add”按钮,得到图4-19即把设备名(Device Name)修改为“K9F1208”,图4-19 配置好的Flash下载设置对话框,图4-19 配置好的Flash下载设置对话框,点击图4-19中的“OK”按钮回到如图4-16所示窗口,点击图上的“OK”按钮回到主工作窗口必须重新编译一下工程ex4_1,然后点击主工作窗口的菜单“Flash | Download”,将当前工程生成的ex4_1.axf下载到UP-NETARM2410实验箱的Nand型Flash芯片K9F1208中,如图4-20所示这一操作将把K9F1208芯片出厂时的程序和数据全部或部分删除掉点击图4-19中的“OK”按钮回到如图4-16所示窗口,,图4-20 Flash编程完成,图4-20 Flash编程完成,如图4-20,在Flash编程完成后,UP-NETARM2410实验箱上的两个七段数码管将显示“29”字样。
此时,可以关闭UP-NETARM2410实验箱电源,取下ULINK2仿真器,然后打开实验箱电源,七段数码管将会显示“29”,说明程序是从K9F1208启动的如果读者手上有UP-NETARM2410实验箱,可以看一下焊有S3C2410A的核心板上靠近12 MHz晶体的一侧有一个ROM101,注明了如果1-2焊接,则OM[1:0]=00b,从Nand Flash引导;而2-3焊接,OM[1:0]=01,从Nor Flash引导核心板上可以清楚地看到1-2脚上焊了0 W的电阻如图4-20,在Flash编程完成后,UP-NETARM,至此,读者对RealView MDK软件的使用及Nand Flash引导都应比较熟悉了读者在输入ex4_1.c这个短小的程序时,可能会和笔者一样,对MDK的编辑器十分不满意当然,MDK是个优秀的软件,尽管如此,笔者对它的调试也有一些不满意的地方,而这一两点不足在RVDS上均不存在至此,读者对RealView MDK软件的使用及Nand,,4.3 SDRAM配置,,ARM芯片S3C2410A上电复位后,将首先完成对芯片的初始化工作,即初始化存储器和需要用到的片上外设等,然后开始执行主程序。
外部SDRAM配置属于初始化工作的一部分下面的4.3.1小节将介绍MDK启动代码S3C2410A.s是如何配置SDRAM的,接着在4.3.2小节给出笔者编写出的相应代码4.3 S,4.3.1 MDK启动代码配置SDRAM,前面的2.4.5小节和附录2.1是本节的硬件基础,这里配置SDRAM相关的寄存器均需参考这些内容 承图4-20,当前的工作主窗口如图4-21所示图中的E:\ARM9BOOK\ex4_1\S3C2410A.s窗口是本节讨论的重点,该窗口的下面有两个页签,即Text Editor和Configuration Wizard,表示启动代码S3C2410A.s的配置和显示方式4.3.1 MDK启动代码配置SDRAM,图4-21 工作主窗口,图4-21 工作主窗口,由附录2.1知,0x48000000至0x48000030为存储器配置寄存器,共13个通过图4-22中的Memory Controller可以图形化地配置这13个寄存器的值,其中的Bank 0~Bank 7分别表示8个区块的配置情况,Refresh表示SDRAM的刷新情况由附录2.1知,0x48000000至0x4800003,图4-22 启动代码S3C2410A.s图形配置窗口,图4-22 启动代码S3C2410A.s图形配置窗口,由前面2.4.5小节可知,此外,仅需要配置Bank 6即可,因为只有区块6映射了64 MB的物理SDRAM芯片,其他区块没有映射到实际的物理存储空间上;虽然区块0配置了64 MB的启动Nand型Flash,但并不需要存储器映射寄存器配置它。
区块6的配置如图4-23所示(区块7的配置与区块6完全相同)图4-22中Refresh的配置如图4-24所示区块0的配置保持默认值,区块1的配置如图4-25所示(区块2~5的配置与区块1完全相同)由前面2.4.5小节可知,此外,仅需要配置Bank 6即,图4-23 区块6配置情况,图4-23 区块6配置情况,图4-24 SDRAM刷新配置,图4-24 SDRAM刷新配置,图4-25 区块1配置情况,图4-25 区块1配置情况,进行上述配置后,启动代码S3C2410A.s中第470~482行的值将随之自动变更为如图4-26所示的值 在此把区块6之外的所有存储区块进行了配置,这是因为这样配置后的存储器寄存器值与4.1.4小节中的S3C2410SDRAM.ini文件中相应的存储器寄存器值相同当然,对于UP-NETARM2410实验箱,读者完全可以只配置区块6和SDRAM刷新寄存器,而不用理会其他的存储区块进行上述配置后,启动代码S3C2410A.s中第470~,图4-26 存储器寄存器配置结果,图4-26 存储器寄存器配置结果,需要说明的是,当仅配置图4-22中的Memory Controller时,只有图4-26中第470~482行的值会随之变动,而S3C2410A.s中的其他代码将保持不变。
当配置图4-22中其他外设时,S3C2410A.s中将有相应的寄存器值随之变动这种图形化配置ARM芯片的方法十分方便一般地,初始化代码是用汇编语言写的,MDK这一做法可以让不懂汇编语言的人也可以进行系统初始化设计这种图形化初始化芯片寄存器的方法,很早被用于CCS软件的DSP/BIOS中需要说明的是,当仅配置图4-22中的Memory Con,启动代码S3C2410A.s有1000多行,当然大部分为注释,作者将在以后的章节中逐步剖析这个程序,本小节只就存储器配置,特别是SDRAM配置进行讲解下面,把S3C2410A.s中与存储器寄存器相关的初始化代码提取出来逐一解释这些相关的代码如表4-1所示(行号是在不编辑S3C2410A.s的情况下的行号,如果读者编辑了S3C2410A.s,行号可能与书上列出的行号不统一)启动代码S3C2410A.s有1000多行,当然大部分为,表4-1 S3C2410A.s中存储器配置相关的代码,序号,行号,注 释 或 语 句,1,0183,; Memory Controller definitions,2,0184,MC_BASE EQU 0x48000000 ; Memory Controller Base Address,3,0186,;// Memory Controller,4,0187,MC_SETUP EQU 1,5,0189,~,0469,注释,为附录2.1存储器配置寄存器的解释,6,0470,BANKCON0_Val EQU 0x00000700,7,0471,BANKCON1_Val EQU 0x00000700,8,0472,BANKCON2_Val EQU 0x00000700,9,0473,BANKCON3_Val EQU 0x00000700,10,0474,BANKCON4_Val EQU 0x00000700,11,0475,BANKCON5_Val EQU 0x00000700,12,0476,BANKCON6_Val EQU 0x00018009,13,0477,BANKCON7_Val EQU 0x00018009,14,0478,BWSCON_Val EQU 0x22111110,表4-1 S3C2410A.s中存储器配置相关的代码序号,15,0479,REFRESH_Val EQU 0x00AC0459,16,0480,BANKSIZE_Val EQU 0x000000B1,17,0481,MRSRB6_Val EQU 0x00000020,18,0482,MRSRB7_Val EQU 0x00000020,19,0484,;// End of MC,20,0890,; Memory Controller Configuration,21,0891,IF MC_SETUP 0,22,0892,MC_CFG,23,0893,DCD BWSCON_Val,24,0894,DCD BANKCON0_Val,25,0895,DCD BANKCON1_Val,26,0896,DCD BANKCON2_Val,27,0897,DCD BANKCON3_Val,28,0898,DCD BANKCON4_Val,150479REFRESH_Val EQU,序号,行号,注 释 或 语 句,29,0899,DCD BANKCON5_Val,30,0900,DCD BANKCON6_Val,31,0901,DCD BANKCON7_Val,32,0902,DCD REFRESH_Val,33,0903,DCD BANKSIZE_Val,34,0904,DCD MRSRB6_Val,35,0905,DCD MRSRB7_Val,36,0906,ENDIF,37,0970,IF MC_SETUP 0,38,0971,ADR R14, MC_CFG,39,0972,LDMIA R14, {R0-R12},40,0973,LDR R14, =MC_BASE,41,0974,STMIA R14, {R0-R12},42,0975,ENDIF,序号行号注 释 或 语 句290899DCD BAN,表4-1中,第3列中以“;”号开头的单元格为注释,顶格写的单元格语句在程序中也是顶格写的。
顶格写的一般为标号,而前面有空格的单元格语句在程序中也是前面有空格的EQU伪指令表示相等赋值,DCD伪指令表示分配一个32位的字空间,并使用其后的值初始化该空间,IF和ENDIF伪指令与C语言相似,当IF后面的表达式为真时执行IF和ENDIF间的语句块符号“”表示不等于表4-1中,第3列中以“;”号开头的单元格为注释,顶格,表4-1解释如下: 序号2:定义标号MC_BASE,其值为0x48000000,表示存储器映射寄存器地址的基地址由附录一附表1-1可知,在MC_BASE基地址上偏移0得到寄存器BWSCON的地址,偏移4得到寄存器BANKCON0的地址,偏移8得到寄存器BANKCON1的地址,依次类推,偏移0x30得到寄存器MRSRB7的地址 序号4:图4-22中的Memory Controller被勾选后,MC_SETUP为1,此时后面的IF语句块均将被执行(严格意义上讲是被预编译);如果没有勾选,则MC_SETUP为0,此时后面的IF语句块均不被执行表4-1解释如下: 序号2:定义标号MC_BASE,序号6~18:前文提到的图形化配置Memory Controller的值均被反映在此处。
这些标号的值即为需要写到相应寄存器中的值,例如BANKCON0_Val表示要写到寄存器BANKCON0中的值这个值即为配置字,其含义可参考附录二的附2.1序号3和序号19均为注释,这两个注释是一对,序号3表示存储器控制器配置开始,序号19表示存储器控制器配置结束 序号21~36:如果MC_SETUP不等于0,则为标号MC_CFG分配13个连续的字空间,依次初始化为BWSCON_Val、BANKCON0_Val等,排列顺序与附表1-1中寄存器地址的排列顺序相同序号6~18:前文提到的图形化配置Memory Con,序号37~42:当UP-NETARM2410实验箱上电复位后,将会跳转到Reset_Handler标号处执行,在初始化看门狗和时钟后,将执行本段代码(参见S3C2410A.s第0945行)由于MC_SETUP为1,故IF语句块中的四条语句均被执行(参见3.3.4节和3.4.10节理解这四条语句)语句“ADR R14, MC_CFG”将MC_CFG标号的值赋给R14,此时,R14即为13个存储器寄存器配置字空间的首地址,参见序号22;语句“LDMIA R14, {R0-R12}”将序号23~35的值装入R0~R12中;伪指令语句“LDR R14, =MC_BASE”执行后,R14的值为存储器寄存器的基地址0x48000000。
序号37~42:当UP-NETARM2410实验箱上电,语句“STMIA R14, {R0-R12}”执行后,将把R0~R12中的值写入到存储器寄存器中,完成存储器控制器的初始化工作 至此,应该能感受到MDK软件在初始化存储器控制器(甚至外设)方面的高明之处了下一小节我们将把这些代码从启动代码文件S3C2410A.s中分离出来,形成自定义的SDRAM配置代码语句“STMIA R14, {R0-R12}”执行后,4.3.2 自定义SDRAM配置代码,新建一个工程ex4_2,位于E:\ARM9BOOK\ex4_2\ex4_2.uv2,将工程ex4_1的文件ex4_1.c和S3C2410A.s拷贝到目录E:\ARM9BOOK\ex4_2\下,并把ex4_1.c改名为ex4_2.c,设置工程选项如图4-9、图4-10、图4-15和图4-16所示工作主窗口如图4-27所示 此时可以编译连接运行工程ex4_2,执行结果和工程ex4_1相同设置工程选项图4-28中的“Create HEX File”,编译连接后,将在当前工程目录下生成ex4_2.hex文件4.3.2 自定义SDRAM配置代码 新建一,图4-27 工作主窗口,图4-27 工作主窗口,图4-28 工程选项“Output”页签,图4-28 工程选项“Output”页签,如图4-29所示,将Memory Controller的勾选取消。
此时S3C2410A.s中的“MC_SETUP EQU 0”,即MC_SETUP为0,启动代码文件S3C2410A.s将不对存储器控制器进行初始化图4-29 启动代码图形化配置向导,如图4-29所示,将Memory Controller的,编写一个新汇编文件initmemcon.s,并把该文件添加到工程ex4_2中,initmemcon.s的内容罗列如下,工程ex4_2的工作界面如图4-30所示图4-30 工程ex4_2工作主界面,编写一个新汇编文件initmemcon.s,并把该文件添,文件initmemcon.s的内容如下: 1 AREA INITMEM, CODE, READONLY 2 EXPORT InitMemCon 3 Mem_Addr_Base EQU 0x48000000 4 InitMemCon 5 ADR R8, Mem_Val_Conf 6 LDR R9, =Mem_Addr_Base 7 LDMIA R8!, {R0-R7} 8 STMIA R9!, {R0-R7} 9 LDMIA R8, {R0-R4} 10 STMIA R9, {R0-R4},文件initmemcon.s的内容如下: 1,11 ; MOV PC, LR ; Subroutine Return but not recommended in MDK 12 BX LR 13 Mem_Val_Conf ; The Configuration Value of Memory Controller 14 DCD 0x22111110, 0x700, 0x700, 0x700, 0x700, 0x700, 0x700 15 ;BWSCON, BANKCON0,BANKCON1,BANKCON2,BANKCON3,BANKCON4,BANKCON5 16 DCD 0x18009, 0x18009, 0x0AC0459, 0xB1, 0x20, 0x20 17 ;BANKCON6, BANKCON7, REFRESH, BANKSIZE, MRSRB6, MRSRB7 18 END,11 ; MOV PC, LR ;,同时,修改启动代码文件S3C2410A.s,添加三行代码,如图4-31所示,后面跟着注释“Added by ZY”的三行语句为添加的语句。
在图4-30所示工作界面上编译连接工程ex4_2,然后点击菜单“Flash | Download”,随后,点击菜单“Debug | Start/Stop Debug Session”或直接按“Ctrl + F5”组合键,进入调试状态,可以通过查看Memory了解initmemcon.s的工作情况如图4-32所示同时,修改启动代码文件S3C2410A.s,添加三行代码,图4-31 添加三行代码的S3C2410A.s,图4-31 添加三行代码的S3C2410A.s,图4-32 工程ex4_2调试情况,图4-32 工程ex4_2调试情况,图4-32窗口右侧Memory区可以同时查看四个区段,图中显示了从地址0x48000000开始的存储器控制寄存器区,当PC指针执行到如图4-32所示情况时,Memory #2中的地址0x48000000至0x48000030间的值即为Mem_Val_Conf的值图4-32窗口右侧Memory区可以同时查看四个区段,图,现在回顾一下添加的程序及语句的含义,相信在第三章的帮助下读者能够完全读懂这个程序图4-31中第0945行添加的“IMPORT InitMemCon”表示引用不在本程序文件中定义的标号InitMemCon,这个标号在initmemcom.s中定义了;第0976行和第0977行添加的语句“ELSE”和“BL InitMemCon”,结合上下文,表示当MC_SETUP为0时,将跳转到标号InitMemCon,同时把下一条要执行的语句地址赋给LR(即R14)寄存器。
现在回顾一下添加的程序及语句的含义,相信在第三章的帮助下,initmemcon.s文件按语句的先后顺序依次解释如下: 定义只读代码段,段名为INITMEM; 定义外部文件可引用的标号InitMemCon; 标号Mem_Addr_Base赋值为0x48000000,表示存储器控制寄存器组的基地址; 标号InitMemCon; R8赋值为标号Mem_Val_Conf,即存储寄存器配置字的空间首地址; R9赋值为0x48000000; 以R8的值为地址,将其后的8个字地址的值装入R0~R7中,R8=R8+0x20; 将R0~R7的值存储到以R9的值为地址的字存储空间处,R9=R9+0x20;,initmemcon.s文件按语句的先后顺序依次解释如下,以R8的值为地址,将其后的5个字地址的值装入R0~R4中; 将R0~R4的值存储到以R9的值为地址的字存储空间处; 上述四条语句把Mem_Val_Conf指向的13个寄存器配置字赋给0x48000000~0x48000030处的存储器控制寄存器 语句“BX LR”实现子程序的跳转 对比一下工程ex4_1和工程ex4_2,可以看到MDK软件的启动代码S3C2410A.s的功能也可以自己编写。
显然,MDK软件实现的启动代码具有配置直观、不用编写汇编程序等优点,自己编写的初始化代码需要使用汇编语言,针对性和专用性稍强一些以R8的值为地址,将其后的5个字地址的值装入R0~R4中,4.3.3 堆和栈,ARM程序运行时,总会用到栈,尤其在中断和子程序调用情况下,所以程序中需要开辟一定大小的可读写存储空间给栈,并把栈指针SP (即R13)指向栈顶栈是先进后出的存储空间,一般地,压栈后,栈顶向地址减少的方向变化,即栈底地址小于栈顶地址由于ARM系统有用户、管理等七种工作模式,每种工作模式都需要有各自独立的栈空间(用户模式和系统模式下的寄存器相同,其栈区也是共用的),当切换到指定工作模式时,首先要把SP指针初始化栈空间分配过小,导致栈数据压破栈底,可能会导致整个程序致命性的错误;栈空间分配过大,会严重浪费存储空间,但是只要存储空间够大,对程序运行没有任何影响故栈空间分配上就大不就小4.3.3 堆和栈 ARM程序运行时,总会用到栈,尤其,栈有时也被称为堆栈,但是堆本身是与栈完全不同的概念在高级语言中,定义了引用(或指针)数据类型,指针的地址保存在栈中,而指针指向的数据集保存在堆中因此,堆是比栈容量更大的存储空间。
在ARM存储系统中,可读写的空间均可视为堆,所以,无需为堆开辟空间(在使用C++编程时有特殊情况) 新建一个工程ex4_3,包括文件ex4_3.c、S3C2410A.s和initmemcon.s,其中,initmemcon.s与工程ex4_2中的完全相同,S3C2410A.s中不使能看门狗复位系统功能(当然,这个功能是看门狗的主要用途之一),设置如图4-33所示,图中也展示了堆和栈的设置情况栈有时也被称为堆栈,但是堆本身是与栈完全不同的概念在高,图4-33 启动代码S3C2410A.s配置向导,图4-33 启动代码S3C2410A.s配置向导,C语言程序ex4_3.c的代码如下所示: 1 #define Seg7_1_addr (*(volatile unsigned char*) 0x08000110) 2 #define Seg7_2_addr (*(volatile unsigned char*) 0x08000112) 3 4 #define uchar unsigned char 5 6 uchar seg7table[16] = 7 { 8 0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80, 0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E,C语言程序ex4_3.c的代码如下所示: 1,9 // 0 1 2 3 4 5 6 7 8 9 A B C D E F 10 }; 11 12 void Delay(int lcnt) // Delay subroutine 13 { 14 int i,j; 15 for(i=0;i
需要强调指出的是,该工程与4.3.2小节介绍的工程ex4_2的工程选项(Options for Target“Target 1”)设置相同,以后所有工程文件都不再给出工程选项设置工程选项有10个页签,其中的某些页签设置比较简单,本书中没有提及31 iSeat++; 32,由图4-33可见,六种工作模式的栈空间共占有0 + 0x8 + 0 + 0 + 0x80 + 0x400 = 0x488 = 1160d使用记事本或UltraEdit软件打开E:\ARM9BOOK\ex4_3\ex4_3.map文件,该文件。
