博文

目前显示的是 五月, 2010的博文

从外到内,看中断处理

仍旧以s3c2410来看。中断来了以后,找到一个表项,假如找到了vector_irq。 /home/sda3/linux-2.6.21.1/arch/arm/kernel/entry-armv.S .globl __vectors_start __vectors_start: swi SYS_ERROR0 b vector_und + stubs_offset ldr pc, .LCvswi + stubs_offset b vector_pabt + stubs_offset b vector_dabt + stubs_offset b vector_addrexcptn + stubs_offset b vector_irq + stubs_offset b vector_fiq + stubs_offset .globl __vectors_end __vectors_end: 即,执行了b vector_irq + sbus_offset vector_irq是什么东东呢? 我们在该文件中,可以看到一个宏: .macro vector_stub, name, mode, correction=0 .align 5 vector_\name: .if \correction sub lr, lr, #\correction .endif @ @ Save r0, lr_ (parent PC) and spsr_ @ (parent CPSR) @ stmia sp, {r0, lr} @ save r0, lr mrs lr, spsr str lr, [sp, #8] @ save spsr @ @ Prepare for SVC32 mode. IRQs remain disabled. @ mrs r0, cpsr eor r0, r0, #(\mode ^ SVC_MODE) msr spsr_cxsf, r0 @ @ the branch ta

从下到上分析中断处理

S3C2410中断的定义的中断向量是从16~47.然后外部中断从48~69.70~80.一共有66(80-16)个中断其中70~78 UART是用来与PC进行通信的。 25 #define S3C2410_CPUIRQ_OFFSET (16) 26 27 #define S3C2410_IRQ(x) ((x) + S3C2410_CPUIRQ_OFFSET) 28 29 /* main cpu interrupts */ 30 #define IRQ_EINT0 S3C2410_IRQ(0) /* 16 */ 31 #define IRQ_EINT1 S3C2410_IRQ(1) 32 #define IRQ_EINT2 S3C2410_IRQ(2) 33 #define IRQ_EINT3 S3C2410_IRQ(3) 34 #define IRQ_EINT4t7 S3C2410_IRQ(4) /* 20 */ 35 #define IRQ_EINT8t23 S3C2410_IRQ(5) 36 #define IRQ_RESERVED6 S3C2410_IRQ(6) /* for s3c2410 */ 37 #define IRQ_CAM S3C2410_IRQ(6) /* for s3c2440,s3c2443 */ 38 #define IRQ_BATT_FLT S3C2410_IRQ(7) 39 #define IRQ_TICK S3C2410_IRQ(8) /* 24 */ 40 #define IRQ_WDT S3C2410_IRQ(9) /* WDT/AC97 for s3c2443 */ 41 #define IRQ_TIMER0 S3C2410_IRQ(10) 42 #define IRQ_TIMER1 S3C2410_IRQ(11) 43 #define IRQ_TIMER2 S3C2410_IRQ(12) 44 #define IRQ_TIMER3 S3C2410_IRQ(13) 45 #define

S3C2410中断处理器模块寄存器详解

图片
      S3C2410的中断异常处理模块有以下寄存器构成: SRCPND, INTMODE, INTMSK, PRIORITY, INTPND, INTOFFSET, SUBSRCPND, INTSUBMSK。 下面具体介绍各个寄存器的功能:        SRCPND(Source Pending Register)寄存器有效位32位,可读写,每一位涉及到一个中断源,SRCPND是主中断源引脚寄存器,某个位被置1表示相应的中断被触发,但我们知道在同一时刻内系统可以触发若干个中断,只要中断被触发了,SRCPND的相应位便被置1,也就是说SRCPND 在 同一时刻可以有若干位同时被置1 ,另外,此寄存器不受中断控制器的优先权逻辑的影响。如果此中断没有被INTMSK寄存器屏蔽或者是快中断(FIQ) 的话,它将被进一步处理。通过写数据到这个寄存器能清除SPCPND相应的位。       INTMODE(Interrupt Mode Register)寄存器有效位为32位,可读写,每一位与SRCPND中各位相对应,它的 作用是指定该位相应的中断源处理模式 (IRQ还是FIQ)。若某位为0,则该位相对应的中断按IRQ模式处理,为1则以FIQ模式进行处理,该寄存器初始化值为0x00000000,即所有中断皆以IRQ模式进行处理。此中断控制器中只有一个中断源能用FIQ mode(在紧急中断下使用FIQ mode),因此INTMODE仅有一位能置1。      INTMSK(Interrupt Mask Register)寄存器有效位为32位,可读写,INTMSK为主中断屏蔽寄存器与SRCPND寄存器对应,它的作用是决定该位相应的中断请求是否被处理。若某位被设置为1,则该位相对应的中断产生后将被忽略(CPU不处理该中断请求),设置为0则CPU对其进行处理。该寄存器初始化值为 0xFFFFFFFF,既默认情况下所有的中断都是被屏蔽的。       PRIORITY(IRQ PRIORITY Control Register)寄存器有32位,有效位[20:0],可读写,此寄存器的作用是如果有几个中断源同时触发,按照下图的流向,假如这几个中断源都没被屏蔽,并且都是IRQ模式,因此就要判定哪个中断

arm-linux注册中断

图片
二 注册中断 这部分我们仍以3sc2410下 的watchdog的中断为例来讲解中断的注册及调用过程。 drivers/char/watchdog/s3c2410_wdt.c: static int s3c2410wdt_probe(struct platform_device *pdev) { struct resource *res; int started = 0; int ret; int size; DBG("%s: probe=%p\n", __FUNCTION__, pdev); /* get the memory region for the watchdog timer */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (res == NULL) { printk(KERN_INFO PFX "failed to get memory region resouce\n"); return -ENOENT; } size = (res->end-res->start)+1; wdt_mem = request_mem_region(res->start, size, pdev->name); if (wdt_mem == NULL) { printk(KERN_INFO PFX "failed to get memory region\n"); ret = -ENOENT; goto err_req; } wdt_base = ioremap(res->start, size); if (wdt_base == 0) { printk(KERN_INFO PFX &qu

arm-linux中断初始化分析

图片
这篇文档准备简要的分析下arm平台上linux下的中断是如何运行的,本文将先分析初始化时的中断是如何建立的,然后以一个例子来注册一个中断,并详细分析中断触发到调用我们自己的中断例程的整个流程。 本文linux2.6.18的源码和s3c2410的CPU及smdk2410的板子为例来分析代码。 一 中断初始化: 大家都知道arm下规定,在0x00000000或0xffff0000的地址处必须存放一张跳转表, 其格式如下: 上面的这个表我们称之为”异常中断向量表”,表中的IRQ和FIQ位置就是用来存放处理中断函数的地址。至于具体选择在哪一个地址处存放该表, 可由 CPU的协处理器完成 。如s3c2410下由CP15中寄存器1的位13来决定,我们可以通过设置该位来告诉系统我们的向量表在哪。 include/arch/asm-arm/proc-armv/system.h #if __LINUX_ARM_ARCH__ >= 4 //at91rm9200是ARMV4结构 #define vectors_base() ((cr_alignment & CR_V) ? 0xffff0000 : 0) #else #define vectors_base() (0) #endif 可以看到ARMv4以下的版本,该地址固定为0;ARMv4及以上版本,ARM中断向量表的地址由CP15协处理器c1寄存器中V位 (bit[13])控制,V和中断向量表的对应关系如下: V=0    ~    0x00000000~0x0000001C V=1    ~    0xffff0000~0xffff001C 因此,在中断初始化的时候我们要做的就是在IRQ和FIQ的位置处放置我们的中断处理函数地址或跳转语句跳转到我们的中断处理函数。这个过程是在trap_init中完成的,而它由start_kernel()调用。 arch/arm/kernel/traps.c void __init trap_init(void) { unsigned long vectors = CONFIG_VECTORS_BASE;/*跳转表的存放位置(即上面那表的存放位置)*/ /*这些都在entry-armv.S下定义 *stub vector kuser_helper具体指什

ARM中断原理—ARM9 2410

几天前一个学生问我ARM中断嵌套的问题,我才发现原在我心中理所当然的事对学生来说理解实属不易。      ARM有七种模式,我们这里只讨论SVC、IRQ和FIQ模式。      我们可以假设ARM核心有两根中断引脚(实际上是看不见的),一根叫 irq pin, 一根叫fiq pin.      在ARM的cpsr中,有一个I位和一个F位,分别用来禁止IRQ和FIQ的。      先不说中断控制器,只说ARM核心。正常情况下,ARM核都只是机械地随着pc的指示去做事情,当CPSR中的I和F位为1的时候,IRQ和FIQ全部处 于禁止状态。无论你在irq pin和fiq pin上面发什么样的中断信号,ARM是不会理你的,你根本不能打断他,因为他耳聋了,眼也瞎了。      在I位和F位为0的时候,当irq pin上有中断信号过来的时候,就会打断arm的当前工作,并且切换到IRQ模式下,并且跳到相应的异常向量表(vector)位置去执行代码。这个过程 是自动的,但是返回到被中断打断的地方就得您亲自动手了。当你跳到异常向量表,处于IRQ的模式的时候,这个时候如果irq pin上面又来中断信号了,这个时候ARM不会理你的,irq pin就跟秘书一样,ARM核心就像老板,老板本来在做事,结果来了一个客户,秘书打断它,让客户进去了。而这个时候再来一个客户,要么秘书不断去敲门 问,要么客户走人。老板第一个客户没有会见完,是不会理你的。      但是有一种情况例外,当ARM处在IRQ模式,这个时候fiq pin来了一个中断信号,fiq pin是什么?是快速中断呀,比如是公安局的来查刑事案件,那才不管你老板是不是在会见客户,直接打断,进入到fiq模式下,并且跳到相应的fiq的异常 向量表处去执行代码。那如果当ARM处理FIQ模式,fiq pin又来中断信号,又就是又一批公安来了,那没戏,都是执法人员,你打不断我。那如果这个时候irq pin来了呢?来了也不理呀,正在办案,还敢来妨碍公务。     所以得出一个结论: IRQ模式只能被FIQ模式打断,FIQ模式下谁也打不断。    在打不断的情况下,irq pin 或 fiq pin随便你怎么发中断信号,都是白发。    所以除了fiq能打断irq以外,根本没有

Linux源码点滴--asmlinkage

asmlinkage是个宏,使用它是为了保持参数在stack中。因为从汇编语言到C语言代码参数的传递是通过stack的,它也可能从 stack中得到一些不需要的参数。Asmlinkage将要解析那些参数。 "asmlinkage" is defined, for example, in the header file "include/asm-i386/linkage.h" as __attribute__((regparm(0))) that tells compiler put all function parameters in the stack (i.e. disables call optimization). Definition of "__init" is placed in the header "include/linux/init.h". (Paths to headers are valid for version 2.6.9) 看一下/usr/include/asm /linkage.h里面的定义: #define asmlinkage CPP_ASMLINKAGE __attribute__((regparm(0))) __attribute__是关键字,是gcc的C语言扩展,regparm(0)表示不从寄存器传递参数 asmlinkage存在的必要性: 这个asmlinkage大都用在系统调用中,系统调用需要在entry.s文件中用汇编语言调用,所以必须要保证它符合C语言的参数传递规则,才能用汇编语言正确调用它。 补充一: __attribute__机制是GNU C的一大特色,它可以设置函数属性、变量属性和类型属性等。可以通过它们向编译器提供更多数据,帮助编译器执行优化等。 __attribute__((regparm(0))):告诉gcc编译器该函数不需要通过任何寄存器来传递参数,参数只是通过堆栈来传递。 __attribute__((regparm(3))):告诉gcc编译器这个函数可以通过寄存器传递多达3个的参数,这3个寄存器依次为EAX、 EDX 和 ECX。更多的参数才通过堆栈传递。这样可以减少一些入栈出栈操作,因此调用比较快。 补充二: 关于C

ubuntu 9.10 network-server configure

删除网桥: ip link set br0 down brctl delbr br0 tftp服务器 sudo vi /etc/inetd.conf tftp dgram udp wait nobody /usr/sbin/tcpd /usr/sbin/in.tftpd /tftpboot   重新启动服务: sudo /etc/init.d/openbsd-inetd restart 测试: 在/tftpboot 文件夹下新建立一个文件 cd /tftpboot touch test 进入另外一个文件夹 tftp 192.168.227.101 tftp> get test   NFS服务器: 1、进行NFS服务器端与客户端的安装: sudo apt-get install nfs-kernel-server  nfs-common  portmap 安装客户端的作用是可以在本机进行NFS服务的测试。 2、配置portmap 两种方法任选一种就可以: (1):sudo emacs /etc/default/portmap 去掉 -i 127.0.0.1 (2)sudo dpkg-reconfigure portmap 运行后选择“否” 3、配置挂载目录和权限 vim /etc/exports 配置如下: /home/nfsboot *(rw,sync) 解释一下: /home/nfsboot是NFS的共享目录,*表示任何IP都可以共享这个目录,你可以改为受限的IP,rw表示的是权限,sync是默认的。 4、更新exports文件 只要你更改了/etc/exports, 你不可以通过sudo exportfs -r 来更新 这个文件 5、重启NFS服务 sudo /etc/init.d/nfs-kernel-server restart 重启nfs服务 6、进行测试 尝试一下挂载本地磁盘(我的linux系统IP为202.198.137.18,将

CentOS5.4安装xen

终于把xen编译好了,只有DOM0,安装的时候,出了很多错误,说实话都没有解决。于是,采用了最简单的方法: 下载: xen3.4.2: http://bits.xensource.com/oss-xen/release/3.4.2/xen-3.4.2.tar.gz linux 2.6.18.8打过xen补丁的: http://bits.xensource.com/oss-xen/release/3.4.2/linux-2.6.18-xen-3.4.2.tar.gz 安装方法: step 1: 分别解压后,将linux-2.6.18.8解压后的内核拷入xen-3.4.2目录内,并重命名为 xen-2.6.18-xen.hg。 为了不再进行同步linux,修改xen-3.4.2/buildconfigs/src.hg-clone文件,将其中的某些行删除,删除后的内容为: # Mercurial HG ?= hg LINUX_SRCDIR ?= linux-$(LINUX_VER)-xen.hg # Repository to clone. XEN_LINUX_HGREPO ?= $$(sh buildconfigs/select-repository $(LINUX_SRCDIR) $(LINUX_SRC_PATH)) # Set XEN_LINUX_HGREV to update to a particlar revision. XEN_LINUX_HGREV  ?= tip $(LINUX_SRCDIR)/.valid-src: $(__XEN_LINUX_UPDATE) set -e ; \ touch $@ step 2: 安装xen的时候,需要依赖一些库文件,因此,要预先检查一下 进入xen-3.4.2/tools/check目录 分别运行 ./chk build 和 ./chk install 都提示OK,则可,否则,安装之。 step3: 准备xen-3.4.2/studom目录内的相关文件: grub-0.97.tar.gz   newlib-1.16.0.tar.gz    pciutils-2.2.9.tar.gz lwip-1.

pts与tty

在使用ubuntu的时候,如果输入ps –e ,会出现: 2358 pts/0    00:00:00 su 2368 pts/0    00:00:00 bash 2789 tty1     00:00:00 bash 2837 ?        00:00:00 gnome-terminal 2838 ?        00:00:00 gnome-pty-helpe 2839 pts/1    00:00:00 bash 2873 pts/2    00:00:00 bash 2905 pts/0    00:00:00 ps 之类的信息,其中tty1和pts/0是何东东? 在计算机的发展史上,关于人机接口,有2个主要概念,一个是终端;另一个是控制台 终端分为 字符哑终端 和 图形终端 控制台 是另外一个人机接口,不通过终端与主机相连, 而是通过显示卡-显示器和键盘接口分别与主机相连。 在PC机上,没有终端的概念,仅有控制台,而且是1个。 我们所看到的这些tty1-7和pts/0实际上都是虚拟的终端,由getty来虚拟的。而tty7是由Xorg来管理的,如下: 892 tty7     00:00:10 Xorg 894 ?        00:00:00 hald-addon-acpi 895 ?        00:00:00 hald-addon-inpu 944 tty4     00:00:00 getty 946 tty5     00:00:00 getty 956 tty2     00:00:00 getty 957 tty3     00:00:00 getty 961 tty6     00:00:00 getty 另外,扩展一下: 在UNIX系统中,计算机显示器通常被称为控制台终端(Console),关于/dev/console  应该来说更像一个缓冲结果。实现对内核的打印,比如说内核把要打印的内容装入缓冲区,然后由console来决定打印到哪里吧(比如是tty0还是串口等)。 在kernel中,console这个结构中有个device。 如果

git备忘

git diff :比较 索引 和 本地 之间的区别,当本地提交到索引(使用了add命令),则输出为空 而 git diff -cached 应该是比较 仓库 和 索引 之间的区别,当索引提交到仓库(使用了commit命令),则输出为空 git-merge后,是会产生双父母的,这种情况如果要查看父母信息,: $git show HEAD^1 //查看HEAD的第一个父母,合并之前的主分支 $git show HEAD^2 //查看HEAD的第二个父母,合并之前的被合并分支 git cat-file –t  … 查看文件类型 git cat-file 类型 id 查看文件内容 git ls-tree id 查看树 Changes to be committed表示在index和commit的区别状况。 而Changed but not updated表示当前目录和index的区别状况。 git commit之后要输入commit信息,加个 –s 不用输入信息