⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 199.htm

📁 pcb设计资料初学者难得的入门资料包含工厂制作过程
💻 HTM
📖 第 1 页 / 共 3 页
字号:
} <br>

Starting the kernel <br>

Listing 4 contains the first few interesting lines of the start_kernel() fun <br>

ction, located in $(TOPDIR)/init/main.c. <br>

Listing 4: The beginning of the start_kernel function <br>

asmlinkage void __init start_kernel(void) <br>

{ <br>

{ <br>

char * command_line; <br>

/* <br>

* Interrupts are still disabled. Do necessary setups, then <br>

* enable them <br>

*/ <br>

lock_kernel(); <br>

printk(linux_banner); <br>

setup_arch(&command_line, &memory_start, &memory_end); <br>

memory_start = paging_init(memory_start, memory_end); <br>

trap_init(); <br>

init_IRQ(); <br>

sched_init(); <br>

time_init(); <br>

parse_options(command_line); <br>

. <br>

. <br>

. <br>

Listing 5 shows the setup_arch() function in $(TOPDIR)/arch/MY_ARCH/kernel/s <br>

etup.c. The board-specific setup function is called from here. The command l <br>

ine string and memory start and memory end are passed over to the caller of <br>

this function. The start and end addresses for the linked-in ramdisk image a <br>

re also updated here. <br>



Listing 5: Architecture setup function <br>

__initfunc(void setup_arch(char **cmdline_p, <br>

unsigned long * memory_start_p, <br>

unsigned long * memory_end_p)) <br>

{ <br>

#ifdef CONFIG_BLK_DEV_INITRD <br>

#if CONFIG_BLK_DEV_INITRD_OFILE <br>

extern void *__rd_start, *__rd_end; <br>

#endif <br>

#endif <br>

myplatform_setup(); <br>

strncpy(command_line, arcs_cmdline, CL_SIZE); <br>

*cmdline_p = command_line; <br>

*memory_start_p = (unsigned_long) &_end; <br>

*memory_end_p = mips_memory_upper; <br>

#ifdef CONFIG_BLK_DEV_INITRD <br>

#if CONFIG_BLK_DEV_INITRD_OFILE <br>

// Use the linked-in ramdisk <br>

// image located at __rd_start. <br>

initrd_start = (unsigned long)&__rd_start; <br>

initrd_end = (unsigned long)&__rd_end; <br>

initrd_below_start_ok = 1; <br>



if (initrd_end > memory_end) <br>

{ <br>

printk(*initrd extends beyond end of memory * <br>

*(0x%08lx > 0x%08lx)\ndisabling initrd\n*, <br>

initrd_end, memory_end); <br>

initrd_start = 0; <br>

} <br>

#endif <br>

#endif <br>

} <br>

$(TOPDIR)/arch/MY_ARCH/MY_PLATFORM/setup.c contains the platform-specific in <br>

itialization code (Listing 6). Here, the various base addresses and the plat <br>

form-specific RTC and PCI operations are set up. For PCI, the following seve <br>

n functions need to be implemented for the given platform: <br>

Listing 6: Platform-specific initialization code <br>

__initfunc(void myplatform_setup(void)) <br>

{ <br>

irq_setup = myplatform_irq_setup; <br>

/* <br>

* mips_io_port_base is the beginning <br>

*of the address space to which x86 <br>

* style I/O ports are mapped. <br>



*/ <br>

mips_io_port_base = 0xa0000000; <br>

/* <br>

* platform_io_mem_base is the <br>

*beginning of I/O bus memory space as <br>

* seen from the physical address bus. <br>

*This may or may not be ident- <br>

* ical to mips_io_port_base, e.g. the <br>

*former could point to the beginning of PCI <br>

*memory space while the latter might <br>

*indicate PCI I/O  space.  The two values are <br>

*used in different sets of macros.  This <br>

* must be set to a correct value by the <br>

*platform setup code. <br>

*/ <br>

platform_io_mem_base=0x10000000; <br>

/* <br>

* platform_mem_iobus_base is the <br>

*beginning of main memory as seen <br>

* from the I/O bus, and must be set <br>

*by the platform setup code. <br>

*/ <br>

*/ <br>

platform_mem_iobus_base=0x0; <br>

#ifdef CONFIG_REMOTE_DEBUG <br>

/* <br>

* Do the minimum necessary to set up debugging <br>

*/ <br>

myplatform_kgdb_hook(0); <br>

remote_debug = 1; <br>

#endif <br>

#ifdef CONFIG_BLK_DEV_IDE <br>

 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>

} <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>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -