显示标签为“linux-arch-arm”的博文。显示所有博文
显示标签为“linux-arch-arm”的博文。显示所有博文

2009年2月20日星期五

EP93xx GPIO interface

名词

AMBA是EP93xx采用的内部总线结构,他包含一个高速总线(AHB)和一个低速总线(APB)。

AHB (Advanced High-Performance Bus),包含一个高速内部总线时钟,用来同步协处理 器、MMU、cache、DMA控制器和其他内存模块。

APB (Advanced Peripheral Bus),此总线就来连接一些低速并行设备,比如UART和GPIO。 AHB 和 APB 使用 AMBA 架构中的 AHB/APB 总线连接,

GPIO (General Purpose I/O),GPIO在EP93xx中是APB的一个子模块,他提供简单的LED控制, 可实现非常基础的调试功能(相当于printk?)。

GPIO

GPIO 包含两种类型和8个接口。

  • 标准GPIO (port C, D, E, G, H)。每个端口包含两组寄存器
    1. data reg x1
    2. data direction reg x1
  • 增强型的GPIO(EGPIO, port A, B, F),包含三种寄存器
    1. data reg x1
    2. data direction reg x1
    3. intr reg and status regs x?

标准GPIO的每个端口都包含一个8位数据寄存器(data regs)和另外的8位数据方向寄存器 (datadirection regs)。而EGPIO还会多包含一组8位中断控制寄存器。

ABF端口还包括了七个多余的寄存器。

  1. GPIO Interrupt Enable registers (GPIOAIntEn, GPIOBIntEn, GPIOFIntEn)
  2. GPIO Interrupt Type 1 registers (GPIOAIntType1, GPIOBIntType1, GPIOFIntType1)
  3. GPIO Interrupt Type 2 registers (GPIOAIntType2, GPIOBIntType2, GPIOFIntType2)
  4. GPIO End-Of-Interrupt registers (GPIOAEOI, GPIOBEOI, GPIOFEOI)
  5. GPIO Debounce registers (GPIOADB, GPIOBDB, GPIOFDB)
  6. Interrupt Status registers (IntStsA, IntStsB, IntStsF)
  7. Raw Interrupt Status registers (RawIntStsA, RawIntStsB, RawIntStsF)

GPIO 初始化

系统复位的时候,GPIO 会执行初始化。

  • 所有端口的 data reg 和 data direction reg 都将清零,设置为 input 方式
  • Port E[1:0] 用来表示 RDLED 和 GRLED,他们将会被置高,也就是 0x11
  • Port G[3:2] 用来表示 SLA[1:0] 输出,他们被置低。
  • Port G[1:0] 用来表示 EEDAT 和 EECLK,设置为 input 方式
  • 所有的中断控制寄存器和祛抖动寄存器都被清零

GPIO端口和针脚映射

EP93xx的阵脚情况不一样,后继版本的板子总是多了点,下面只是列出EP9301/EP9302的针 脚映射:

主板针脚名称 位于GPIO模块上的端口
EGPIO[7:0] Port A
EGPIO[15:8] Port B
GRLED1 Port E0
RDLED2 Port E1
EECLK3 Port G0
EEDAT4 Port G1

GPIO 寄存器映射

鉴于GPIO寄存器很多,我也就不列出来了。

只是说几个要点。

  1. PADR ― PHDR,数据寄存器
    • 读取这些寄存器将会返回GPIO模块输入端口的值(由PXDDR控制),默认情况是缺省端 口映射下的端口状态信息。
  2. PEDR,他的bit[1:0]提供了LED 驱动方法,默认是0x11
  3. RAWSTATUSx,共三个寄存器。显示了无关针脚的读取状态

寄存器索引

略

引用

  1. EP9302 User's Guide

2008年12月25日星期四

ARM Linux 启动过程 (1)

此系列记录了ARM Linux从Bootloader部分到Linux初始化,然后进入C环境的一段坎坷历程 。作为第一部分,我将从RedBoot开开始。RedBoot是嵌入式中应用广泛的Bootloader,他将作为此系列的序章。

RedBoot (bootloader)

  • 概述
  • RedBoot所作的工作

概述

(本示例讲解基于ARM9的Cirrus EP9302) Bootloader 在 ARM 中依然是加电后的第一道程序,其作用简单,相当于 PC 机器上的 BIOS 固件程序。Bootloader 负责完成系统初始化,它将非易失性储存器中的 Linux 内核 拷贝到 RAM 中去,然后跳转到内核的第一道指令,将控制权交给内核。从这个意义上讲, 嵌入式 Bootloader 要做的事情比 x86 等机器多很多。

一般ARM Linux的第一条指令地址是0x0000_0000,而通常嵌入式系统会将FLASH等存储寄存 器映射到这个地址,而Bootloader就位于该存储器顶端,这保证了Bootloader的顺利执行。

以 RedBoot for EP93xx 为例,EP93xx 采用 NAND Flash 作为存储介质,在 RedBoot 中可 以罗列存储器的根目录如下:

RedBoot> fis init
Name FLASH addr Mem addr Length Entry point
RedBoot 0x60000000 0x60000000 0x00040000 0x00000000
RedBoot config 0x60FC0000 0x60FC0000 0x00001000 0x00000000
FIS directory 0x60FE0000 0x60FE0000 0x00020000 0x00000000
zImage 0x60040000 0x00080000 0x00120000 0x00080000
ramdisk 0x60140000 0x00800000 0x00800000 0x00800000

这里可以看出在 Flash 文件系统中存储了他的系统文件 RedBoot(内核)、RedBoot config(设置信息)、FIS directory(系统目录),另外就是 Linux 的内核 zImage 和内 存盘 ramdisk.gz。

RedBoot做的工作

  1. SDRAM初始化,没有内存,啥东西也玩不转 (cyg/hal/hal_platform_setup.h)
  2. 初始化串口 (hal/arch/ARCH/src/hal_diag.c)
  3. 检测处理器类型 (宏指定,cdl/hal_ARCH_MACHINE.cdl)
  4. 设置Linux启动参数 (hal/ARCH/arch/src/redboot_linux_exec.c)
  5. 将Linux内核装载到内存中,跳转执行

启动内核

启动内核函数do_exec的这段代码在 hal/ARCH/arch/src/redboot_linux_exec.c,最重要的 就是末尾处的内联汇编语句:

    asm volatile (
CYGARC_HAL_MMU_OFF(%5)
"__tramp_start__:\n"
" cmp %1,%4;\n" // Default kernel load address. Relocate
" beq 2f;\n" // kernel image there if necessary, and
" cmp %2,#0;\n" // if size is non-zero
" beq 2f;\n"
"1:\n"
" ldr r0,[%1],#4;\n"
" str r0,[%4],#4;\n"
" subs %2,%2,#4;\n"
" bne 1b;\n"
"2:\n"
" mov r0,#0;\n" // Set board type
" mov r1,%3;\n" // Machine type
" mov r2,%6;\n" // Kernel parameters
" mov pc,%0;\n" // Jump to kernel
"__tramp_end__:\n"
: :
"r"(entry),
"r"(CYGARC_PHYSICAL_ADDRESS(base_addr)),
"r"(length),
"r"(CYGHWR_REDBOOT_ARM_MACHINE_TYPE),
#ifdef CYGHWR_HAL_ARM_EDB93XX_VARIANT
"r"((CYGHWR_REDBOOT_ARM_LINUX_EXEC_ADDRESS & 0x3ffffff) +
ConfigInfo[3]),
#else
"r"(CYGHWR_REDBOOT_ARM_LINUX_EXEC_ADDRESS),
#endif
"r"(CYGARC_PHYSICAL_ADDRESS(CYGHWR_REDBOOT_ARM_TRAMPOLINE_ADDRESS)),
"r"(CYGARC_PHYSICAL_ADDRESS(CYGHWR_REDBOOT_ARM_LINUX_TAGS_ADDRESS))
: "r0", "r1"
);
首先关闭MMU,保证代码跳转位置是绝对的物理地址,然后重置内核(如果需要)到entry处, 执行跳转,跳转前保证了:r0置0,r1装载机器类型,r2装载struct tag数组地址。

这样RedBoot结束了其短暂而又伟大的一生,我们进入Linux的世界。

2008年11月25日星期二

Cirrus EP9302: 从RedBoot到Linux

Cirrus EP9302

Cirrus Logic是美国德州的一家半导体制造商,早在1989年就进入NASDAQ,股票代码是CRUS。
EP93xx是基于ARM920T的主板系列,在官方上你可以看到详尽的EP9302资料。

http://www.cirrus.com/en/products/pro/detail/P1066.html

EP9302和EP9301最大的区别就在于,CPU核心加入了一个浮点运算部件MaverickCrunch。

我在开始的时候曾经说过,eCos支持非常多的架构,包括ARM, CalmRISC, FR-V, H8,
IA32, M68K, Matsushita AM3x, MIPS, NEC V8xx, PowerPC, SPARC, SuperH。这是eCos非
常值得骄傲的一点,也充分发挥了开源的长处。但是毕竟世界上的主板千千万,从汽车到蓝
牙,无线设备等等等等,eCos开发小组也无法支持所有的主板。如果厂商新推出一个主板,
那多半需要自己拓展eCos来支持自己的新板,我所使用的Cirrus Logic就是一个例子。

你可以在官方网站上找到这些工具:

搭建工作环境

(此工作环境是在Red Hat Linux 9.0下配置完成,嵌入式开发普遍需要串口支持。)

  1. 解压arm-elf-gcc-3.2.1-full.tar.bz2得到两个目录,按照目录指引放置文件
  2. 在/etc/profile或者~/.bashrc中添加系统环境变量。比如 /etc/profile
    if [ `id -u` = 0]; then
    pathmunge /sbin
    pathmunge /usr/sbin
    pathmunge /usr/local/sbin
    #newly added for arm-3.4
    pathmunge /usr/local/arm/3.4/bin
    fi

配置安装redboot

这步会非常简单。Cirrus几乎把一切工作都做好了,解压cirrus-arm-linux-2.0.8.tar.bz2
进入目录 cirrus-arm-linux-2.0.8/edb9302,直接编译

cd /path/to/cirrus-arm-linux-2.0.8/edb9302
make redboot

然后得到cirrus-arm-linux-2.0.8/edb9302/images/redboot.bin,这就是一个redboot内核,
他使用了ecos的redboot模板,创建针对EP9302主板的ecos内核。安装也是比较方便,这使
用到了cirrus给的download工具(如果没有,你还需要编译):

../download/download -p 1 images/redboot.bin

通常情况下,我们的主板都是不允许FLASH被任意擦写的,这个规定在硬件上被强制实现:
用短路块连接EP9302的JP14的2、3脚。相反接到1、2脚,这个时候Flash会根据写入的协议
向外发布数据,待download侦测到数据时候会进行握手和数据传递。

然后关闭主板,进入EP9302,则可以进入Redboot命令行。

编译烧录linux

# busybox config
cd /path/to/cirrus-arm-linux-2.0.8
tar jxf tarballs/busybox-1.1.3.tar.bz2
cd busybox
make menuconfig

# compile ramdisk.gz
cd /path/to/cirrus-arm-linux-2.0.8/edb9302
make ramdisk

# compile linux zImage
make linuxconfig
make linux
这样就在/path/to/cirrus-arm-linux-2.0.8/edb9302/images中生成两个文件:
ramdisk.gz和zImage。

其中busybox和linux都需要对自己需求的理解来进行配置,在这里不再赘述。这里将一下
linux拷贝方法。将Linux内核传递给EP9302,是使用到了tftp(Trival FTP),首先需要配置
Red Hat 9.0主机的tftp客户端(/etc/xinetd.d/tftp),tftp常常用于无盘工作站。在这
里作为RH和EP9302的通讯协议。

然后进入EP9302 redboot配置主板(主要是网络)。

# ---- 主板配置部分 ----
# Local IP address是EP9302 IP地址
# Default server IP address是RH9 IP地址
RedBoot> fcon -i
Initialize non-volatile configuration - continue(y/n)
Run script at boot: true
Boot script:
Enter script, terminate with empty line
>> fis load ramdisk
>> fis load zImage
>> exec -r 0x800000 -s 0x800000
>>
Boot script(1000ms resolution): 1
Use BOOTP for network configuration: false
Gateway IP address: 192.168.16.1
Local IP address: 192.168.16.93
Local IP address mask: 255.255.255.0
Default server IP address: 192.168.16.91
DNS server IP address:
Network hardware address[MAC]:0x78:0x56:0x34:0x12:0x64:0x30
GDB connection port: 9000
Force console for special debug messages: false
Network debug at boot time: false
Update RedBoot non-volatile configuration - continue(y/n)? y

# ---- 拷贝文件部分 ----
RedBoot> fis init -f
RedBoot> load -v -r -b 0x800000 ramdisk.gz -h 192.168.16.91
RedBoot> fis create -b 0x800000 -l 0x800000 ramdisk
RedBoot> load -v -r -b 0x80000 zImage -h 192.168.16.91
RedBoot> fis create -b 0x80000 -l 0x120000 zImage

# ---- 重启 ----
RedBoot> re

重启EP9302之后,主板开机加载RedBoot,然后执行默认的启动脚本,加载ramdisk和zImage。
就这样我们进入Linux,第一次进入嵌入式Linux的感觉,是不是很奇妙?