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

📄 ictrl.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
字号:
/*  ictrl.c * *  This routine installs and handles external interrupt vectors for *  PowerPC 403 CPU built-in external interrupt controller * *  Author: Thomas Doerfler <td@imd.m.isar.de> * *  COPYRIGHT (c) 1998 by IMD, Puchheim, Germany * *  To anyone who acknowledges that this file is provided "AS IS" *  without any express or implied warranty: *      permission to use, copy, modify, and distribute this file *      for any purpose is hereby granted without fee, provided that *      the above copyright notice and this notice appears in all *      copies, and that the name of IMD not be used in *      advertising or publicity pertaining to distribution of the *      software without specific, written prior permission. *      IMD makes no representations about the suitability *      of this software for any purpose. * *  Modifications for PPC405GP by Dennis Ehlin  * */#include "ictrl.h"#include <rtems.h>#include <rtems/libio.h>#include <stdlib.h>                     /* for atexit() *//* *  ISR vector table to dispatch external interrupts */ rtems_isr_entry ictrl_vector_table[PPC_IRQ_EXT_MAX];/*  * *  some utilities to access the EXI* registers * *//*  *  clear bits in EXISR that have a bit set in mask  */#if defined(ppc405)RTEMS_INLINE_ROUTINE void clr_exisr(unsigned32 mask) {    asm volatile ("mtdcr 0xC0,%0"::"r" (mask));/*EXISR*/} /*  *  get value of EXISR  */RTEMS_INLINE_ROUTINE unsigned32 get_exisr(void) {    unsigned32 val;    asm volatile ("mfdcr %0,0xC0":"=r" (val));/*EXISR*/    return val; } /*  *  get value of EXIER  */RTEMS_INLINE_ROUTINE unsigned32 get_exier(void) {    unsigned32 val;    asm volatile ("mfdcr %0,0xC2":"=r" (val));/*EXIER*/    return val; } /*  *  set value of EXIER  */RTEMS_INLINE_ROUTINE void set_exier(unsigned32 val) {    asm volatile ("mtdcr 0xC2,%0"::"r" (val));/*EXIER*/} #else /* not ppc405 */RTEMS_INLINE_ROUTINE void clr_exisr(unsigned32 mask) {    asm volatile ("mtdcr 0x40,%0"::"r" (mask));/*EXISR*/} /*  *  get value of EXISR  */RTEMS_INLINE_ROUTINE unsigned32 get_exisr(void) {    unsigned32 val;    asm volatile ("mfdcr %0,0x40":"=r" (val));/*EXISR*/    return val; } /*  *  get value of EXIER  */RTEMS_INLINE_ROUTINE unsigned32 get_exier(void) {    unsigned32 val;    asm volatile ("mfdcr %0,0x42":"=r" (val));/*EXIER*/    return val; } /*  *  set value of EXIER  */RTEMS_INLINE_ROUTINE void set_exier(unsigned32 val) {    asm volatile ("mtdcr 0x42,%0"::"r" (val));/*EXIER*/} #endif /* ppc405 *//*  *  enable an external interrupt, make this interrupt consistent */RTEMS_INLINE_ROUTINE void enable_ext_irq( unsigned32 mask){    unsigned32 isrlvl;    _CPU_ISR_Disable(isrlvl);    set_exier(get_exier() | ((mask)&PPC_EXI_MASK));    _CPU_ISR_Enable(isrlvl);}/*  *  disable an external interrupt, make this interrupt consistent */RTEMS_INLINE_ROUTINE void disable_ext_irq( unsigned32 mask){    unsigned32 isrlvl;    _CPU_ISR_Disable(isrlvl);    set_exier(get_exier() & ~(mask) & PPC_EXI_MASK);    _CPU_ISR_Enable(isrlvl);}/* * *  this function is called, when a external interrupt is present and  *  enabled but there is no handler installed. It will clear *  the corresponding enable bits and call the spurious handler *  present in the CPU Configuration Table, if any. * */void ictrl_spurious_handler(unsigned32 spurious_mask, 		       CPU_Interrupt_frame *cpu_frame){  int v;    for (v=0; v < PPC_IRQ_EXT_MAX; v++) {    if (VEC_TO_EXMSK(v) & spurious_mask) {      clr_exisr(VEC_TO_EXMSK(v));      disable_ext_irq(VEC_TO_EXMSK(v));#if 0      printf("spurious external interrupt: %d at pc 0x%x; disabling\n",	     vector, cpu_frame->Interrupt.pcoqfront);#endif      if (rtems_cpu_configuration_get_spurious_handler()) {	rtems_cpu_configuration_get_spurious_handler()(v + PPC_IRQ_EXT_BASE,cpu_frame);      }    }  }}/* *  ISR Handler: this is called from the primary exception dispatcher */ voidictrl_isr(rtems_vector_number vector,CPU_Interrupt_frame *cpu_frame){  unsigned32        istat,                    mask,                    global_vec;  int               exvec;  rtems_isr_entry handler;  istat = get_exisr() & get_exier() & PPC_EXI_MASK;  /* FIXME: this may be speeded up using cntlzw instruction */  for (exvec = 0;exvec < PPC_IRQ_EXT_MAX;exvec++) {    mask = VEC_TO_EXMSK(exvec);    if (0 != (istat & mask)) {      /*clr_exisr(mask); too early to ack*/      handler = ictrl_vector_table[exvec];      if (handler) {	istat &= ~mask;	global_vec = exvec + PPC_IRQ_EXT_BASE;	(handler)(global_vec);      }      clr_exisr(mask);/* now we can ack*/    }  }  if (istat != 0) { /* anything left? then we have a spurious interrupt */    ictrl_spurious_handler(istat,cpu_frame);  }}/* * * the following functions form the user interface * *//* * * install a user vector for one of the external interrupt sources  * */ rtems_status_codeictrl_set_vector(rtems_isr_entry   new_handler,		 unsigned32        vector,		 rtems_isr_entry   *old_handler){  /*   *  We put the actual user ISR address in 'ictrl_vector_table'.  This will   *  be used by the _ictrl_isr so the user gets control.   */  /* check for valid vector range */  if ((vector >= PPC_IRQ_EXT_BASE) &&      (vector <  PPC_IRQ_EXT_BASE + PPC_IRQ_EXT_MAX)) {    /* return old handler entry */    *old_handler = ictrl_vector_table[vector - PPC_IRQ_EXT_BASE];    if (new_handler != NULL) {      /* store handler function... */      ictrl_vector_table[vector - PPC_IRQ_EXT_BASE] = new_handler;      /* then enable it in EXIER register */      enable_ext_irq(VEC_TO_EXMSK(vector - PPC_IRQ_EXT_BASE));    }    else { /* new_handler == NULL */      /* then disable it in EXIER register */      disable_ext_irq(VEC_TO_EXMSK(vector - PPC_IRQ_EXT_BASE));      ictrl_vector_table[vector - PPC_IRQ_EXT_BASE] = NULL;    }    return RTEMS_SUCCESSFUL;  }  else {    return RTEMS_INVALID_NUMBER;  }}/* * Called via atexit() * deactivate the interrupt controller  */voidictrl_exit(void){  /* mark them all unused */  disable_ext_irq(~0);  clr_exisr(~0);  }/* * activate the interrupt controller  */rtems_status_code ictrl_init(void){  proc_ptr dummy;  /* mark them all unused */  disable_ext_irq(~0);  clr_exisr(~0);    /* install the external interrupt handler */  _CPU_ISR_install_vector(PPC_IRQ_EXTERNAL,			  ictrl_isr,			  &dummy);  atexit(ictrl_exit);  return RTEMS_SUCCESSFUL;}

⌨️ 快捷键说明

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