




已阅读5页,还剩19页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
2410中断分析本文基于S3C2410开发板源代码和datasheet,分析了2410的中断机制,包括原理、初始化、中断处理过程和中断程序设计,希望能够对初学者有所帮助,若有错误,还请指出,非常感谢。目录2410中断分析1一、BOOTLOADER2二、内核3三、2410中断分析51.硬件机制52.对应于硬件机制的软件中断处理7四、中断处理过程121.全局数据结构:122.汇编部分133.通用处理过程15五、中断初始化17六、驱动设计21一、 BOOTLOADER摘自基于ARM嵌入式系统的通用bootloader的设计与实现简单地说,bootloader就是在操作系统内核运行前运行地一段小程序。通过这段小程序,我们可以初始化必要的硬件设备,创建内核需要的一些信息并将这些信息通过相关机制传递给内核,从而将系统的软硬件环境带到一个合适的状态,最终调用操作系统内核,真正起到引导和加载内核的作用。bootloader是依赖于硬件而实现的,特别是在嵌入式系统中。不同的体系结构需求的bootloader是不同的;除了体系结构,bootloader还依赖于具体的嵌入式板级设备的配置。也就是说,对于两块不同的嵌入式板而言,即使它们基于相同的CPU构建,运行在其中一块电路板上的bootloader,未必能够运行在另一块电路开发板上。对于一个ARM系统来说,本质上,bootloader作为引导与加载内核镜像的“工具”,在实现上,必须提供以下几个功能,更确切地说,必须做到以下几点 1(DOCARMBOOTING):(1) 初始化RAM(必需):bootloader必须能够初始化RAM,因为将来系统要通过它保存一些Volatile数据,但具体地实现要依赖与具体的CPU以及硬件系统。(2) 初始化串口(可选,推荐):bootloader应该要初始化以及使能至少一个串口,通过它与控制台联系进行一些debug的工作;甚至与PC通信。(3) 创建内核参数列表(针对linux操作系统,推荐)。(4) 启动内核镜像(必需):根据内核镜像保存的存储介质不同,可以有两种启动方式:FALSH启动以及RAM启动;但是无论是哪种启动方式,下面的系统状态必须得到满足:l CPU寄存器的设置:R00; R1机器类型;R2启动参数标记列表在RAM中的起始地址; 这三个寄存器的设置是在最后启动内核时通过启动参数来传递完成的。linux/arch/arm/kernel/head-armv.S/* * Kernel startup entry point.* The rules are: * r0 - should be 0 * r1 - unique architecture number * MMU - off * I-cache - on or off * D-cache - off* See linux/arch/arm/tools/mach-types for the complete list of numbers * for r1. */Bootloader启动内核镜像的方法是通过跳转语句直接跳转至内核镜像的第一句指令语句。二、 内核Documentation/Arm/readmeMachine/Platform support The ARM tree contains support for a lot of different machine types. To continue supporting these differences, it has become necessary to split machine-specific parts by directory. For this, the machine category is used to select which directories and files get included (we will use $(MACHINE) to refer to the category) To this end, we now have arch/arm/mach-$(MACHINE) directories which are designed to house the non-driver files for a particular machine (eg, PCI, memory management, architecture definitions etc). For all future machines, there should be a corresponding include/asm-arm/arch-$(MACHINE) directory.即除了标准的arm通用处理(kernel、mm,支持不同的体系结构,arm7、9等),还用MACHINE(机器类型)来代表不同的板子和体系结构,在mach-$(MACHINE)中仅包含非driver的特定机器内容。Kernel entry (head-armv.S) The initial entry into the kernel made via head-armv.S uses architecture independent code. The architecture is selected by the value of r1 on entry, which must be kept unique. You can register a new architecture by mailing the following details to .uk在arch/arm config.in中,用于make menuconfig配置mainmenu_option next_commentcomment System Typechoice ARM system type AnakinCONFIG_ARCH_ANAKIN S3C2400-based CONFIG_ARCH_S3C2400 S3C2410-based CONFIG_ARCH_S3C2410 支持smdkif $CONFIG_ARCH_S3C2410 = y ; thencomment S3C2410 Implementationdep_bool SMDK (MERI TECH BOARD) CONFIG_S3C2410_SMDK $CONFIG_ARCH_S3C2410dep_bool change AIJI CONFIG_SMDK_AIJIdep_tristate S3C2410 USB function support CONFIG_S3C2410_USB $CONFIG_ARCH_S3C2100dep_tristate Support for S3C2410 USB character device emulation CONFIG_S3C2410_USB_CHAR $CONFIG_S3C2410_USBfi# /* CONFIG_ARCH_S3C2410 */在arch/arm/Makefile中,指定machineifeq ($(CONFIG_ARCH_S3C2410),y)TEXTADDR = 0xC0008000MACHINE = s3c2410Endif# If we have a machine-specific directory, then include it in the build.MACHDIR:= arch/arm/mach-$(MACHINE)ifeq ($(MACHDIR),$(wildcard $(MACHDIR)SUBDIRS+= $(MACHDIR)CORE_FILES:= $(MACHDIR)/$(MACHINE).o $(CORE_FILES)Endif在mach-s3c2410目录下的Makefile中,选择了对应的文件,因此,经过编译,内核中的MACHINE_START宏起作用,生成了const struct machine_desc结构,然后再由bootloader传递的机器类型号nr就可以选择对应的描述结构,链接到对应的处理,这样,系统初始化过程中,就可以调用相应于板子的初始化程序,这里,就是S3C2410对应的程序。USE_STANDARD_AS_RULE := trueO_TARGET:= s3c2410.oobj-y :=obj-m := obj-n :=obj- :=export-objs := smdk.o irq.o generic.o cpu.o dma.o pcibuf.o pcipool.o usb_ctl.o usb_ep0.o usb-char.o usb_recv.o usb_send.o pm_drv.o pm.o# Common support (must be linked before board specific support)obj-y += generic.o irq.o cpu.o dma.o# Specific board supportobj-$(CONFIG_S3C2410_SMDK) += smdk.oobj-$(CONFIG_USB_OHCI_S3C2410) += pcibuf.o pcipool.o三、 2410中断分析1. 硬件机制如上图:根据2410 datasheet,在硬件上,将中断分成3种不同的类型:normal(常规中断)、外部扩展中断(EINT4_7, EINT_8_23)、子中断(INT_ADC, INT_UARTn),不同的中断处理过程不尽相同,过程如下:srcpnd-intpnd-cpsr(I, F bit)subsrcpnd-srcpnd-intpnd-cpsr(I, F bit)eintpnd-srcpnd-intpnd-cpsr(I, F bit) 使用的寄存器:SRCPND, INTPND, INTMASK(缺省全1,禁用所有中断), INTMOD(缺省全0,irq,仅有一个能成为fiq),PRIORITYSUBSRCPND,11个中断源,串口3*3,ADC, TC(触摸屏两个),INTSUBMSKEXTINTn ,EINTFLTn, EINTMASK, EINTPNDn,有中断源请求时,SRCPND(不受优先级仲裁和mask影响)某位置1,经过优先级判定(如果有多个),INTPND中的唯一一位置位(仅在该位MASK为0时),如果cpsr中的I、F位没有置位,中断处理程序开始执行(具体分析见后)执行完中断后(或者在中断程序中)需要写1到SRCPND,然后到INTPND,以清除对应的中断,使得后续中断可以继续进行。(否则认为又有中断发生了)EINT8_23表示这么多个中断合用该中断源(SRCPND),所以外部8_23中的任意一个中断源产生中断,只要EINTMASK没有屏蔽,EINT8_23都会触发,同理,INT_UARTn中的任意一个子中断源(RXD, TXD, ERR)产生中断,只要INTSUBMSK中没有屏蔽,都会使得UARTn中断产生,在do_irq中断处理过程中,再通过SUBSRCPND和INTSUBMSK继续查找真正的处理程序进行分派。优先级分配如下图,两级仲裁,每个仲裁器中0(最高)、5固定,其他的优先级可以任意指定,或者轮转。(通过对应的寄存器进行设置)2. 对应于硬件机制的软件中断处理3种类型的irq在linux/include/asm-arm/arch-s3c2410/irqs.h中,分别分配了不同的irq号码,从062,这样,在do_irq函数中,就可以根据实际的号码调用特定的用户中断处理程序。在以下的处理中,涉及到一些irq号码的转换,其目的是从分配的irq号码中获得数据,便于操作对应的硬件寄存器。常规中断处理arch/arm/mach-s3c2410/irq.c直接使用写1的方式进行清中断操作#defineClearPending(x) SRCPND = (1 (x); INTPND = (1 (x);禁用中断并清中断源static void s3c2410_mask_ack_irq(unsigned int irq)INTMSK |= (1 irq);SRCPND = (1 irq);INTPND = (1 irq);禁用中断(在do_irq中,用于禁止同一个中断的产生)static void s3c2410_mask_irq(unsigned int irq)INTMSK |= (1 irq);使能中断(在do_irq中,用于禁止同一个中断的产生,重新使能中断)static void s3c2410_unmask_irq(unsigned int irq)INTMSK &= (1 irq);子中断处理也就是说,带子中断处理的,需要清除子mask和pend,同时,还需要根据不同情况,清除INTMASK和INTPND中的对应位static void SUB_mask_ack_irq(unsigned int irq)INTSUBMSK |= (1 SUBIRQ_OFFSET(irq);SUBSRCPND = (1 SUBIRQ_OFFSET(irq);if (irq = IRQ_ERR0) /清除INTPND和INTMASK中的对应位 ClearPending(SHIFT_UART0); else if (irq = IRQ_ERR1) ClearPending(SHIFT_UART1); else if (irq = IRQ_ERR2) ClearPending(SHIFT_UART2); else /* if ( irq = IRQ_ADC_DONE ) */ ClearPending(SHIFT_ADCTC);static void SUB_mask_irq(unsigned int irq)INTSUBMSK |= (1 SUBIRQ_OFFSET(irq);static void SUB_unmask_irq(unsigned int irq)INTSUBMSK &= (1 SUBIRQ_OFFSET(irq);if (irq = IRQ_ERR0) INTMSK &= (1 SHIFT_UART0); else if (irq = IRQ_ERR1) INTMSK &= (1 SHIFT_UART1); else if (irq = IRQ_ERR2) INTMSK &= (1 SHIFT_UART2); else /* if ( irq = IRQ_ADC_DONE ) */INTMSK &= (1 SHIFT_ADCTC); /* * fixup_irq() for do_IRQ() in kernel/irq.c,从而经过转换获得可以访问中断处理函数的irq号码(0-62) */inline unsigned int get_subIRQ(int irq, int begin, int end, int fail_irq) int i;for(i=begin; i = end; i+) if (irq & (1 irq_no, EXT_BOTH_EDGES, GPIO_PULLUP_DIS);EXTINTn ,0-23寄存器用于定义外部中断的触发方式(高低电平、上升下降边沿)EINTFLTn决定16-23外部中断的过滤时钟(PCLK,外部clk,om决定)EINTMASK决定掩码,4-23EINTPNDn,4-23*static void inline设置外部中断0-23的模式(由于使用gpio,复用,故需要指定为irq,且上拉电阻无效,好像一般中断设置时无效,端口时有效,matrix5-leds.c中用于端口,故set_gpio_ctrl (led_tablei | GPIO_PULLUP_EN | GPIO_MODE_OUT);set_gpios(int irq, int pullup)int shift;if (irq 8) shift = 2*irq;GPFCON &= (0x3 shift);GPFCON |= (0x2 shift);GPFUP &= (GRAB_PULLUP(pullup) irq);GPFUP |= (GRAB_PULLUP(pullup) irq); else shift = 2*(irq - 8);GPGCON &= (0x3 shift);GPGCON |= (0x2 shift);GPGUP &= (GRAB_PULLUP(pullup) (irq - 8);GPGUP |= (GRAB_PULLUP(pullup) (irq - 8); /* for EINT? */其实原理和子中断相似,只不过这里使用的是gpio的寄存器static void EINT4_23mask_ack_irq(unsigned int irq)irq = EINT_OFFSET(irq);/判断在子寄存器中的位置EINTMASK |= (1 irq);EINTPEND = (1 irq);if (irq EINT_OFFSET(IRQ_EINT8) / INTMSK |= (1 SHIFT_EINT4_7); ClearPending(SHIFT_EINT4_7); else / INTMSK |= (1 SHIFT_EINT8_23); ClearPending(SHIFT_EINT8_23);static void EINT4_23mask_irq(unsigned int irq)irq = EINT_OFFSET(irq);EINTMASK |= (1 irq);static void EINT4_23unmask_irq(unsigned int irq)EINTMASK &= (1 EINT_OFFSET(irq);if (irq IRQ_EINT8) INTMSK &= (1 SHIFT_EINT4_7); else INTMSK &= (1 SHIFT_EINT8_23);/* * fixup_irq() for do_IRQ() in kernel/irq.c,从而经过转换获得可以访问中断处理函数的irq号码(0-62) */inline unsigned int get_extIRQ(int irq, int begin, int end, int fail_irq) int i;for(i=begin; i = end; i+) if (irq & (1 i) return (NORMAL_IRQ_OFFSET - 4 + i);return fail_irq;设置外部中断,由于系统初始化时,s3c2410_init_irq中,没有对外部中断置为有效,实际上也不可能置为有效,需要在用户驱动程序中设置。int set_external_irq(int irq, int edge, int pullup)unsigned long flags;int real_irq, reg_ofs, shift;取得外部中断寄存器地址volatile u32 *extint = (volatile u32 *)io_p2v(0x56000088);if (irq IRQ_EINT23) | (irq IRQ_EINT3) & (irq IRQ_EINT4)return -EINVAL;获得irq号码(在extint中使用)real_irq = fixup_irq_num(irq);仅仅用于外部中断static int inlinefixup_irq_num(int irq)if (irq IRQ_EINT4) return irq;else return (irq + 4) - NORMAL_IRQ_OFFSET);如果normal irq,返回其值,eint4_23,返回4-23设置端口为中断方式set_gpios(real_irq, pullup);保存中断状态local_irq_save(flags);计算操作的寄存器reg_ofs = (real_irq / 8);shift = 4 * (real_irq - 8 * reg_ofs);extint += reg_ofs;*extint &= (EXTINT_MASK shift);*extint |= (edge shift);if (irq 4) SRCPND |= (1 real_irq);INTPND |= (1 real_irq); else EINTPEND |= (1 schedule()bnerescheduleteqr2, #0 sigpending = do_signal()blne_do_signalrestore_user_regs_do_signal:movr0, #0 NULL oldsetmovr1, sp regsmovr2, why syscallbSYMBOL_NAME(do_signal) note the bl above sets lr本来就在SVC模式下的处理和用户模式不同.align5_irq_svc:subsp, sp, #S_FRAME_SIZEstmiasp, r0 - r12 save r0 - r12ldrr7, .LCirqaddr5, sp, #S_FRAME_SIZEldmiar7, r7 - r9addr4, sp, #S_SPmovr6, lrstmiar4, r5, r6, r7, r8, r9 save sp_SVC, lr_SVC, pc, cpsr, old_ro1:get_irqnr_and_base r0, r6, r5, lrmovner1, sp routine called with r0 = irq number, r1 = struct pt_regs *adrsvcne, lr, 1bbnedo_IRQldrr0, sp, #S_PSR irqs are already disabledmsrspsr, r0直接返回内核,而不是用户态进程ldmiasp, r0 - pc load r0 - pc, cpsr3. 通用处理过程asmlinkage void do_IRQ(int irq, struct pt_regs * regs)struct irqdesc * desc;struct irqaction * action;int cpu;获得irq号码(从0到NR_IRQS1,即0-62),此时传入的irq(0-31),需要进一步处理,原理是判断irq类型,然后再通过get_subIRQ或者get_extIRQ来进一步处理irq = fixup_irq(irq);/* * Some hardware gives randomly wrong interrupts. Rather * than crashing, do something sensible. */if (irq = NR_IRQS)goto bad_irq;desc = irq_desc + irq;spin_lock(&irq_controller_lock);禁止同一个中断发生desc-mask_ack(irq);spin_unlock(&irq_controller_lock);以上先禁止同一中断再次发生cpu = smp_processor_id();内核计数,irq嵌套数目irq_enter(cpu, irq);kstat.irqscpuirq+;desc-triggered = 1;/* Return with this interrupt masked if no action */action = desc-action;if (action) int status = 0;如果在用户中断程序中不需要mask中断,就直接unmask,否则,处理完用户中断后再unmaskif (desc-nomask) spin_lock(&irq_controller_lock);desc-unmask(irq);spin_unlock(&irq_controller_lock);if (!(action-flags & SA_INTERRUPT)_sti();如果中断共享,依次执行do status |= action-flags;action-handler(irq, action-dev_id, regs);action = action-next; while (action);if (status & SA_SAMPLE_RANDOM)add_interrupt_randomness(irq);_cli();if (!desc-nomask & desc-enabled) spin_lock(&irq_controller_lock);desc-unmask(irq);spin_unlock(&irq_controller_lock);/* * Debug measure - hopefully we can continue if an * IRQ lockup problem occurs. */check_irq_lock(desc, irq, regs);irq_exit(cpu, irq);如果有软中断需要处理,执行之if (softirq_pending(cpu)do_softirq();return;bad_irq:irq_err_count += 1;printk(KERN_ERR IRQ: spurious interrupt %dn, irq);return;五、 中断初始化建立机器类型描述结构const struct machine_desc,通过该结构将系统通用处理过程与特定与板子的过程连接起来/* * Set of macros to define architecture features. This is built into * a table by the linker. */linux/arch/arm/mach-s3c2410/smdk.cMACHINE_START(SMDK2410, Samsung-SMDK2410)BOOT_MEM(0x30000000, 0x48000000, 0xe8000000)BOOT_PARAMS(0x30000100)FIXUP(fixup_smdk)MAPIO(smdk_map_io)INITIRQ(s3c2410_init_irq)MACHINE_ENDlinux/init/main.casmlinkage void _init start_kernel(void)setup_arch(&command_line) mdesc = setup_machine(machine_arch_type);for (list = &_arch_info_begin; list nr = nr)break;判断机器类型的号码(bootloader准备好),唯一,故,可以得到对应的struct machine_desc *,即上述_mach_desc_SMDK2410,然后:setup_archif (mdesc-fixup)mdesc-fixup(mdesc, (struct param_struct *)tags, &from, &meminfo);这里面可以修改关于体系结构的一些特殊东西,比如ramdisk位置等、内存起始地址等。./* Set up various architecture-specific pointers*/设置了体系结构的irq初始化函数,即下面的s3c2410_init_irq从而可以在init_irq中进行调用,init_arch_irq = mdesc-init_irq;start_kernelvoid _init init_IRQ(void)extern void init_dma(void);int irq;先全部设置为无效,函数为空,然后调用板级初始化,注,这些初始化并没有初始化handler,仅仅初始化了标准的mask、unmask、mask_ack等操作,对于外部中断和除了系统必须(已经添加的中断外),驱动程序必须自行加入对应的中断处理程序,并在request_irq加入函数链表,系统中已有的也是这样加入:例如:在串口操作中,对某个串口增加了3个中断处理程序,分别对应于串口中断的3个子中断s3c2410uart_startup ret = request_irq(RX_IRQ(port), s3c2410uart_rx_interrupt, SA_INTERRUPT, serial_s3c2410_rx, info); if (ret) goto rx_failed; ret = request_irq(TX_IRQ(port), s3c2410uart_tx_interrupt, SA_INTERRUPT, serial_s3c2410_tx, info); if (ret) goto tx_failed;#ifdef CONFIG_USE_ERR_IRQ ret = request_irq(ERR_IRQ(port), s3c2410ua
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 陶粒隔热层施工方案
- 建筑金属斗拱销售方案设计
- 工程地质调查员专业技能考核试卷及答案
- 优化咨询流程方案模板
- 企业人力资源管理师岗位操作规程考核试卷及答案
- 成都工厂管理咨询方案
- 城市防洪气象保障体系报告
- 专业互联网营销活动方案
- 复合型风管施工方案
- 四月营销执行方案策划
- 酷家乐教学课件下载
- 自动化生产线安装、调试和维护技术 第2版 教案全套 模块1-7 认识柔性自动化生产线-全线运行控制方案设计与调试
- 浙江名校协作体(G12)2025年9月2026届高三返校联考政治(含答案)
- 2025至2030年中国鹿茸药品行业市场发展现状及投资方向研究报告
- Unit 1 This is me!第5课时 Integration 说课稿- 2024-2025学年译林版(2024)七年级上册英语
- 2025-2026学年苏教版小学数学四年级上册(全册)教学设计(附目录P197)
- 《中华人民共和国学前教育法》试题库及答案
- 2025年住院医师规范化培训考试(超声诊断科)试题及答案
- 江苏省南通市启东市2024-2025学年七年级上学期期中语文试卷含答案
- 市场监督局知识培训课件
- 手术部(室)医院感染控制标准WST855-2025解读课件
评论
0/150
提交评论