1、今天拿到了周立功的 EasyARM1138 开发板,又要准备大干一场了!晒晒:我准备分以下几个方面开始学习:1.了解 LM3s1138 内部结构,包括存储器,ADC,GPIO,等等。其中我认为最重要的是对各个寄存器地址的掌握。因为个人认为写驱动程序就是对各种寄存器的读写,只要把各个寄存器的地址弄清楚了(个人愚见),那么很多问题也就迎刃而解了。2.熟悉软件开发平台 IAR。这一点我就不想多啰唆了,反正每个处理器都有一个自己的软件开发平台,所以我就烦感:又得花时间去熟悉。那么多家大公司能不能合伙一起开发一个软件平台呢,这样给用户带来好多的方便。3.软件硬件结合开发。这就要好多东西了!有的搞的,呵呵
2、。下面结合实例程序谈谈对这个板子的理解。这是一个简单的 LED 程序:第一行是添加到系统的头文件,我们找到这个头文件:在这个头文件里面,又包含了很多的头文件,还有一些宏定义,不要怕麻烦,在看看这些子头文件里面到底是什么:我们打开第一个头文件 hw_types.h,字面意思应该是硬件类型的定义。打开看看就知道了:果然如此,第一句就说这是 Stellaris 外设驱动程序库 3223 的一部分;第二句蓝色字体就是说定义了一个 Boolean 类型,它的值是 true 表示 1,false 表示 0。我们接着往下看:同样,这里也无非就是些#define,咋一看有点复杂。不怕,我们看看蓝体字:意思是宏
3、硬件访问,不管是直接访问还是通过 bit-band 区域访问。这里我对 bit-band 就不了解了,没关系,现在就去了解它。查看 lm3s1138 的 datasheet。这里说的很清楚。具体是这样的:Stellaris 器件内部的 SRAM 的地址是 0x2000.0000,为了减少读修改写(RMW)操作的时间,ARM 在 Cortex-M3 处理器中引入了 bit-banding 技术。在 bit-banding 使能的处理器中,存储器映射的特定区域(SRAM 和外设空间)能够使用地址别名,在单个原子操作中访问各个位。使用下面的公式来计算 bit-band 别名:bit-band 别名
4、= bit-band 基址 + (字节偏移量 * 32) + (位编号 * 4)例如,如果要修改地址 0x2000.1000 的位 3,则 bit-band 别名计算如下:0x2200.0000 + (0x1000 * 32) + (3 * 4) = 0x2202.000C通过计算得出的别名地址,对地址 0x2202.000C 执行读/写操作的指令仅允许直接访问地址 0x2000.1000 处字节的位 3。其中 0x2200.0000 是 bit-band 基址的起始地址,0x1000 是偏移地址,3 是位编号。好,这里先告一段落,我们继续看前面的宏:#define HWREG(x) (* (
5、 (volatile unsigned long * ) (x) ) 这一句后面的 (*(volatile unsigned long *)(x) 是什么意思呢?我也不知道了,那么百度一下吧。搜到这样的文章:#define A (* (volatile unsigned long *) 详解2008/08/03 09:00 A.M.#define A (* (volatile unsigned long *) 0x48000000 )对于不同的计算机体系结构,设备可能是端口映射,也可能是内存映射的。如果系统结构支持独立的 IO 地址空间,并且是端口映射,就必须使用汇编语言完成实际对设备的控制,
6、因为 C 语言并没有提供真正的 “端口”的概念。如果是内存映射,那就方便的多了。举个例子,比如像寄存器 A(地址假定为 0x48000000)写入数据 0x01,那么就可以这样设置了。#define A (*(volatile unsigned long *) 0x48000000 ).A = 0x01;.这实际上就是内存映射机制的方便性了。其中 volatile 关键字是嵌入式系统开发的一个重要特点。volatile(可变的)这个关键字说明这变量可能会被意想不到地改变,这样编译器就不会去假设这个变量的值了。这种“意想不到地改变” ,不是由程序去改变,而是由硬件去改变。volatile 限定编
7、译器不对这个指针的指向的存储单元进行优化, 即不用通用寄存器暂时代替这个指针的指向的存储单元,而是每次取值都直接到指针的指向的存储单元取值 .volatile 主要用于变量会异步改变的情况下,主要有三个方面:1.cpu 外设寄存器 2.中断和主循环都会用到的全局变量 3.操作系统中的线程间都会用到的公共变量.上述表达式拆开来分析,首先(volatile unsigned long *) 0x48000000 的意思是把 0x48000000 强制转换成volatile unsigned long 类型的指针,即对指针的操作的范围是从 0x48000000 开始的 4 个字节(long 型).暂
8、记为 p,那么就是#define A *p,即 A 为 P 指针指向位置的内容了。这里就是通过内存寻址访问到寄存器 A,可以读/写操作!仔细看看这位兄台的文章,说的很清楚了。那么我们的那句:#define HWREG(x) (* ( (volatile unsigned long * ) (x) ) 就是等于 #define HWREG(x) (x),这里的( x)就是你想设置的存储器地址了。例如 HWREG(0x22000000)=0x12 就是把 0x12 这个数存储在地址 0x22000000 里面。呵呵 A=“HWREG“(0x22000000)就是把存储空间 0x22000000 里
9、面的数据读出来。OK ,这里搞定!接下来看下面这个宏:#define HWREGBITW(x, b) HWREG(unsigned long)(x) & 0xF0000000) | 0x02000000 | (unsigned long)(x) & 0x000FFFFF) :/*/ interrupt.h - Prototypes for the NVIC Interrupt Controller Driver./ Copyright (c) 2005-2008 Luminary Micro, Inc. All rights reserved./ / Software License Agreement#ifndef _INTERRUPT_H_#define _INTERRUPT_H_/*/ If building with a C+ compiler, make all of the definitions in this header/ have a C binding./*#ifdef _cplusplus