📄 at91_init.c
字号:
/* * at91_init.h * this file defines init process on AT91X40 * for Atmel AT91 initialization, includes AIC, TC, USART ... * * Bugs report: li ming ( lmcs00@mails.tsinghua.edu.cn ) * Last modified: 2003-02-02 * */ #include "at91_init.h"#include "skyeye_stdio.h"//yangye 2003-2-14//add svr[32] to save ISR entrysunsigned long svr[32];#ifndef NULL#define NULL (void *)0#endifvoid do_irq( void );void at91_mask_irq(unsigned int irq){ unsigned long mask = 1 << (irq); __arch_putl(mask, AIC_IDCR); // AIC Interrupt Disable Command Register} void at91_unmask_irq(unsigned int irq){ unsigned long mask = 1 << (irq); __arch_putl(mask, AIC_IECR); // AIC Interrupt Enable Command Register}void at91_mask_ack_irq(unsigned int irq){ at91_mask_irq(irq); __arch_putl(0, AIC_EOICR); /* value=don't care */}void at91_init(){ // here Must put at91_init_usart() at the very beginning of init ! at91_init_usart(); at91_init_aic(); at91_init_timer();}//yangye//use this function to install your OSISR as the IRQ mode handler//and your OSISR must call do_irq to deal with different irqsvoid install_irqhandler(void * isr){ /* ARM irq exception vector addr is 0x00000018 */ unsigned int * irq_vec_addr = ( unsigned int * ) 0x18; /* this is isr entry address, could be another address like 0x3c, 0x58... */ unsigned int * isr_entry_addr = ( unsigned int * ) 0x38; unsigned int instruction; /* set the ISR entry at 0x38 */ *isr_entry_addr = (unsigned int)isr; /* make an instruction: it is machine-code for "ldr pc, [pc, #(38-18-8)]" */ instruction = ((unsigned int) isr_entry_addr - (unsigned int)irq_vec_addr - 0x08) | 0xe59ff000; /* set this instruction at 0x18 */ *irq_vec_addr = instruction; }void do_irq(void){ int irq_num; void (*isr)(void); //chy 2003-02-16 : IVR could have some irqs at the same time, so should check it untile IVR=0 //irqnum is the highest irq number label_again: irq_num = __arch_getl(AIC_IVR); if(irq_num!=0){ //close this interrupt at91_mask_irq(irq_num); isr = (void *)svr[irq_num]; if( isr != 0 ) isr(); if(irq_num == KERNEL_TIMER_IRQ_NUM){ //do some extra work for skyeye timer interrupt register volatile struct at91_timers* tt = (struct at91_timers*) (AT91_TC_BASE); register volatile struct at91_timer_channel* tc = &tt->chans[KERNEL_TIMER].ch; /* clear TC Status Register to continue interrupt */ unsigned long tmp = tc->sr; // only read status register, must do! tmp = tmp; // just use it to avoid compiler warnings! } //reenable this interrupt at91_unmask_irq(irq_num); /* clear AIC : indicate the end of interrupts */ __arch_putl(irq_num,AIC_EOICR); // only write AIC_EOICR //chy 2003-02-16 : IVR could have some irqs at the same time, so should check it untile IVR=0 goto label_again; }}int request_irq(int irq_num, void * usr_isr){ if(irq_num>0 && irq_num < 32){ svr[irq_num] = (unsigned long)usr_isr; return 1; }else{ //wrong irq_num return -1; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -