?? 00000000.htm
字號:
ide_ops = &std_ide_ops; <br />#endif <br />#ifdef CONFIG_VT <br />#if defined(CONFIG_DUMMY_CONSOLE) <br /> conswitchp = &dummy_con; <br />#endif <br />#endif <br />/* <br />* just set rtc_ops && pci_ops; forget the rest <br />*/ <br />rtc_ops = &myplatform_rtc_ops; <br />pci_ops = &myplatform_pci_ops; <br />} <br />myplatform_pcibios_fixup() <br />myplatform_pcibios_read_config_byte() <br />myplatform_pcibios_read_config_word() <br />myplatform_pcibios_read_config_dword() <br />myplatform_pcibios_write_config_byte() <br />myplatform_pcibios_write_config_word() <br />myplatform_pcibios_write_config_dword() <br />Interrupt handling <br />The trap_init() function copies the top-level exception handlers to the KSEG <br />0 vector location based on the CPU type. The interrupt handling code is cont <br />ained in $(TOPDIR)/arch/MY_ARCH/MY_PLATFORM/irq.c and int-handler.S. Most sy <br />stems use a dedicated interrupt controller to handle the interrupts in the s <br />ystem. The interrupt controller is hooked to one of the external interrupt l <br />ines in the processor. The architecture-dependent code has to be modified to <br /> fit the interrupt controller into the kernel interrupt handling. <br />Listing 7 shows the platform-specific interrupt initialization code. The top <br />most interrupt handler has to be installed using set_except_vector(). The in <br />terrupt controller that is used in the platform has to be initialized next. <br />If remote debugging is enabled, a call to set_debug_traps() has to be made t <br />o allow any breakpoints or error conditions to be properly intercepted and r <br />eported to the debugger. In addition, a breakpoint needs to be generated to <br />begin communication with the debugger running on the host. <br />Listing 7: Platform-specific interrupt initialization <br />static void __init myplatform_irq_setup (void) <br />{ <br />set_except_vector (0, myplatform_handle_int); <br />// Initialize InterruptController <br />InterruptController_Init(IsrTable); <br />#ifdef CONFIG_REMOTE_DEBUG <br />printk (*Setting debug traps - <br />please connect the remote debugger.\n*); <br />set_debug_traps (); <br />breakpoint (); <br />#endif <br />} <br />The top-level interrupt handler (Listing 8) first saves all the registers an <br />d then disables further interrupts. The CAUSE register is examined to find t <br />he source of the interrupt. If it is a timer interrupt, the corresponding IS <br />R is called. In case it is not a timer interrupt, it checks whether an inter <br />rupt has occurred on the line connected to the interrupt controller. The int <br />errupt handler for the interrupt controller (Listing 9) has to get the pendi <br />ng interrupt vector that caused the interrupt and then execute the handler f <br />or the particular interrupt source. <br />Listing 8: Top-level interrupt handler <br />NESTED(myplatform_handle_int, PT_SIZE, ra) <br /> .set noat <br /> SAVE_ALL <br /> CLI <br /> .set at <br /> mfc0 s0, CP0_CAUSE # get irq mask <br /> /* First, we check for counter/timer IRQ. */ <br /> andi a0, s0, CAUSEF_IP5 <br /> beq a0, zero, 1f <br /> andi a0, s0, CAUSEF_IP2 <br /> # delay slot, check hw0 interrupt <br /> /* Wheee, a timer interrupt. */ <br /> move a0, sp <br /> jal timer_interrupt <br /> nop # delay slot <br /> j ret_from_irq <br /> nop # delay slot <br />1: <br /> beq a0, zero, 1f <br /> nop <br /> /* Wheee, combined hardware <br /> level zero interrupt. */ <br /> jal InterruptController_InterruptHandler <br /> move a0, sp # delay slot <br /> j ret_from_irq <br /> nop # delay slot <br />1: <br /> /* Here by mistake? This is possible, <br /> *what can happen is that by the time we <br /> *take the exception the IRQ pin goes low, so <br /> *just leave if this is the case. <br /> */ <br /> j ret_from_irq <br /> nop <br /> END(myplatform_handle_int) <br />Listing 9: Interrupt handler for the interrupt controller <br />void <br />InterruptController_InterruptHandler ( <br />struct pt_regs *regs <br />) <br />{ <br />IntVector intvector; <br />struct irqaction *action; <br />int irq, cpu = smp_processor_id(); <br />InterruptControllerGetPendingIntVector(&intvector); <br />InterruptControllerGetPendingIntSrc((&irq); <br />action = (struct irqaction *)intvector; <br />if ( action == NULL ) { <br /> printk(*No handler for hw0 irq: %i\n*, irq); <br />return; <br />} <br />hardirq_enter(cpu); <br />action->handler(irq, action->dev_id, regs); <br />kstat.irqs[0][irq]++; <br />hardirq_exit(cpu); <br />} // InterruptController_InterruptHandler () <br />The functions request_irq(), free_irq(), enable_irq() and disable_irq() have <br /> to be implemented for your target platform. request_irq() is used to instal <br />l an interrupt handler for a given interrupt source. free_irq() needs to fre <br />e the memory allocated for the given interrupt. enable_irq() needs to make a <br /> call to the interrupt controller function that enables the given interrupt <br />line and disable_irq() needs to disable the given interrupt line. <br />Timer interrupt <br />File $(TOPDIR)/arch/MY_ARCH/MY_PLATFORM/time.c contains the platform-depende <br />nt timer code. The Linux kernel on MIPS requires a 100Hz timer interrupt. In <br /> the MIPS, one of the timers in coprocessor 0 is programmed to generate 100H <br />z interrupts. The count register and the compare register together make up t <br />he timer. When active, the count register contains a free running counter. O <br />n each processor clock-tick, the value in the register increments by one. Th <br />e register is reset and an external hardware interrupt is generated when the <br /> values in the count register and compare register match. After the count re <br />gister is reset, it restarts to count on the next processor clock-tick. The <br />timer interrupt service routine (ISR) needs to call the do_timer() routine. <br />Performing a write to the compare register clears the timer interrupt. <br />Serial console driver <br />The console runs on top of a serial driver. A polled serial driver can be us <br />ed for printk() (kernel debug message) functionality. The minimum functions <br />that this driver needs to provide are the following: <br />serial_console_init()-for registering the console printing procedure for ker <br />nel printk() functionality, before the console driver is properly initialize <br />d <br />serial_console_setup()-for initializing the serial port <br />serial_console_write(struct console *console, const char *string, int count) <br />-for writing "count" characters <br />Hook up the serial port on your development board to your host development p <br />latform, then start up a serial communication program on your host developme <br />nt platform to communicate with your target. <br />tty driver <br />An interrupt driven serial driver can be used to create a terminal device. A <br /> terminal device can be created by registering the serial driver with tty. A <br /> variety of serial drivers are available in the $(TOPDIR)/drivers/char direc <br />tory. The driver that matches closest to the serial port hardware being used <br /> should be picked up and modified. The interfaces to an interrupt-driven cha <br />racter driver under Linux have been explained in Linux Device Drivers by Rub <br />ini (see References). <br />CONFIG_SERIAL (serial support) has to be defined as Y in "make config." To t <br />
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -