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

📄 at91_init.c

📁 lwip在ucos上的移植
💻 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 entrys
unsigned long svr[32];
#ifndef NULL
#define NULL (void *)0
#endif

void 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 irqs
void 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 + -