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

📄 synth_intr.c

📁 eCos操作系统源码
💻 C
📖 第 1 页 / 共 4 页
字号:
voidhal_vsr_set(cyg_vector_t vec, void (*new_vsr)(void), void (**old_vsrp)(void)){    cyg_bool_t  old;    CYG_ASSERT( (CYGNUM_HAL_VSR_MIN <= vec) && (vec <= CYGNUM_HAL_VSR_MAX), "Can only get valid VSR vectors");    CYG_CHECK_FUNC_PTR( new_vsr, "A valid VSR must be supplied");    // There is a theoretical possibility of two hal_vsr_set calls at    // the same time. The old and new VSRs must be kept in synch.    HAL_DISABLE_INTERRUPTS(old);    if (0 != old_vsrp) {        *old_vsrp = synth_VSR;    }    synth_VSR = new_vsr;    HAL_RESTORE_INTERRUPTS(old);}voidhal_interrupt_mask(cyg_vector_t which){    CYG_PRECONDITION( !hal_interrupts_enabled, "Interrupts should be disabled on entry to hal_interrupt_mask");    CYG_ASSERT((CYGNUM_HAL_ISR_MIN <= which) && (which <= CYGNUM_HAL_ISR_MAX), "A valid ISR vector must be supplied");    synth_masked_isrs |= (0x01 << which);}voidhal_interrupt_unmask(cyg_vector_t which){    CYG_PRECONDITION( !hal_interrupts_enabled, "Interrupts should be disabled on entry to hal_interrupt_unmask");    CYG_ASSERT((CYGNUM_HAL_ISR_MIN <= which) && (which <= CYGNUM_HAL_ISR_MAX), "A valid ISR vector must be supplied");    synth_masked_isrs &= ~(0x01 << which);}voidhal_interrupt_acknowledge(cyg_vector_t which){    cyg_bool_t old;    CYG_ASSERT((CYGNUM_HAL_ISR_MIN <= which) && (which <= CYGNUM_HAL_ISR_MAX), "A valid ISR vector must be supplied");    // Acknowledging an interrupt means clearing the bit in the    // interrupt pending "register".    // NOTE: does the auxiliary need to keep track of this? Probably    // not, the auxiliary can just raise SIGIO whenever a device wants    // attention. There may be a trade off here between additional    // communication and unnecessary SIGIOs.    HAL_DISABLE_INTERRUPTS(old);    synth_pending_isrs &= ~(0x01 << which);    HAL_RESTORE_INTERRUPTS(old);}voidhal_interrupt_configure(cyg_vector_t which, cyg_bool_t level, cyg_bool_t up){    CYG_ASSERT((CYGNUM_HAL_ISR_MIN <= which) && (which <= CYGNUM_HAL_ISR_MAX), "A valid ISR vector must be supplied");    // The synthetic target does not currently distinguish between    // level and edge interrupts. Possibly this information will have    // to be passed on to the auxiliary in future.    CYG_UNUSED_PARAM(cyg_vector_t, which);    CYG_UNUSED_PARAM(cyg_bool_t, level);    CYG_UNUSED_PARAM(cyg_bool_t, up);}voidhal_interrupt_set_level(cyg_vector_t which, cyg_priority_t level){    CYG_ASSERT((CYGNUM_HAL_ISR_MIN <= which) && (which <= CYGNUM_HAL_ISR_MAX), "A valid ISR vector must be supplied");    // The legal values for priorities are not defined at this time.    // Manipulating the interrupt priority level currently has no    // effect. The information is stored anyway, for future use.    synth_isr_handlers[which].pri = level;}// ----------------------------------------------------------------------------// Exception handling. Typically this involves calling into the kernel,// translating the POSIX signal number into a HAL exception number. In// practice these signals will generally be caught in the debugger and// will not have to be handled by eCos itself.static voidsynth_exception_sighandler(int sig){    CYG_WORD    ecos_exception_number = 0;    cyg_bool_t  old;    // There is no need to save state, that will have been done by the    // system as part of the signal delivery process.        // Disable interrupts. Performing e.g. an interaction with the    // auxiliary after a SIGSEGV is dubious.    HAL_DISABLE_INTERRUPTS(old);    // Now decode the signal and turn it into an eCos exception.    switch(sig) {      case CYG_HAL_SYS_SIGILL:        ecos_exception_number = CYGNUM_HAL_EXCEPTION_ILLEGAL_INSTRUCTION;        break;      case CYG_HAL_SYS_SIGBUS:      case CYG_HAL_SYS_SIGSEGV:        ecos_exception_number = CYGNUM_HAL_EXCEPTION_DATA_ACCESS;        break;      case CYG_HAL_SYS_SIGFPE:        ecos_exception_number = CYGNUM_HAL_EXCEPTION_FPU;        break;      default:        CYG_FAIL("Unknown signal");        break;    }#ifdef CYGPKG_KERNEL_EXCEPTIONS    // Deliver the signal, usually to the kernel, possibly to the    // common HAL. The second argument should be the current    // savestate, but that is not readily accessible.    cyg_hal_deliver_exception(ecos_exception_number, (CYG_ADDRWORD) 0);    // It is now necessary to restore the machine state, including    // interrupts. In theory higher level code may have manipulated    // the machine state to prevent any recurrence of the exception.    // In practice the machine state is not readily accessible.    HAL_RESTORE_INTERRUPTS(old);#else    CYG_FAIL("Exception!!!");    for (;;);#endif    }// ----------------------------------------------------------------------------// The clock support. This can be implemented using the setitimer()// and getitimer() calls. The kernel will install a suitable interrupt// handler for CYGNUM_HAL_INTERRUPT_RTC, but it depends on the HAL// for low-level manipulation of the clock hardware.//// There is a problem with HAL_CLOCK_READ(). The obvious// implementation would use getitimer(), but that has the wrong// behaviour: it is intended for fairly coarse intervals and works in// terms of system clock ticks, as opposed to a fine-grained// implementation that actually examines the system clock. Instead use// gettimeofday().static struct cyg_hal_sys_timeval synth_clock   = { 0, 0 };voidhal_clock_initialize(cyg_uint32 period){    struct cyg_hal_sys_itimerval    timer;    // Needed for hal_clock_read(), if HAL_CLOCK_READ() is used before    // the first clock interrupt.    cyg_hal_sys_gettimeofday(&synth_clock, (struct cyg_hal_sys_timezone*) 0);        // The synthetic target clock resolution is in microseconds. A typical    // value for the period will be 10000, corresponding to one timer    // interrupt every 10ms. Set up a timer to interrupt in period us,    // and again every period us after that.    CYG_ASSERT( period < 1000000, "Clock interrupts should happen at least once per second");    timer.hal_it_interval.hal_tv_sec    = 0;    timer.hal_it_interval.hal_tv_usec   = period;    timer.hal_it_value.hal_tv_sec       = 0;    timer.hal_it_value.hal_tv_usec      = period;        if (0 != cyg_hal_sys_setitimer(CYG_HAL_SYS_ITIMER_REAL, &timer, (struct cyg_hal_sys_itimerval*) 0)) {        CYG_FAIL("Failed to initialize the clock itimer");    }}static voidsynth_alrm_sighandler(int sig){    CYG_PRECONDITION((CYG_HAL_SYS_SIGALRM == sig), "Only SIGALRM should be handled here");        if (!hal_interrupts_enabled) {        synth_sigalrm_pending = true;        return;    }    // Interrupts were enabled, but must be blocked before any further processing.    hal_interrupts_enabled = false;    // Update the cached value of the clock for hal_clock_read()    cyg_hal_sys_gettimeofday(&synth_clock, (struct cyg_hal_sys_timezone*) 0);    // Update the interrupt status "register" to match pending interrupts    // A timer signal means that IRQ 0 needs attention.    synth_pending_isrs |= 0x01;    // If any of the pending interrupts are not masked, invoke the    // VSR. That will reenable interrupts.    if (0 != (synth_pending_isrs & ~synth_masked_isrs)) {        (*synth_VSR)();    } else {        hal_interrupts_enabled = true;    }    // The VSR will have invoked interrupt_end() with interrupts    // enabled, and they should still be enabled.    CYG_ASSERT( hal_interrupts_enabled, "Interrupts should still be enabled on return from the VSR");}// Implementing hal_clock_read(). gettimeofday() in conjunction with// synth_clock gives the time since the last clock tick in// microseconds, the correct unit for the synthetic target.cyg_uint32hal_clock_read(void){    int elapsed;    struct cyg_hal_sys_timeval  now;    cyg_hal_sys_gettimeofday(&now, (struct cyg_hal_sys_timezone*) 0);    elapsed = (1000000 * (now.hal_tv_sec - synth_clock.hal_tv_sec)) + (now.hal_tv_usec - synth_clock.hal_tv_usec);    return elapsed;}// ----------------------------------------------------------------------------// The signal handler for SIGIO. This can also be invoked by// hal_enable_interrupts() to catch up with any signals that arrived// while interrupts were disabled. SIGIO is raised by the auxiliary// when it requires attention, i.e. when one or more of the devices// want to raise an interrupt. Finding out exactly which interrupt(s)// are currently pending in the auxiliary requires communication with// the auxiliary.//// If interrupts are currently disabled then the signal cannot be// handled immediately. In particular SIGIO cannot be handled because// there may already be ongoing communication with the auxiliary.// Instead some volatile flags are used to keep track of which signals// were raised while interrupts were disabled. //// It might be better to perform the interaction with the auxiliary// as soon as possible, i.e. either in the SIGIO handler or when the// current communication completes. That way the mask of pending// interrupts would remain up to date even when interrupts are// disabled, thus allowing applications to run in polled mode.// A little utility called when the auxiliary has been asked to exit,// implicitly affecting this application as well. The sole purpose// of this function is to put a suitably-named function on the stack// to make it more obvious from inside gdb what is happening.static voidsynth_io_handle_shutdown_request_from_auxiliary(void){    cyg_hal_sys_exit(0);}static voidsynth_io_sighandler(int sig){    CYG_PRECONDITION((CYG_HAL_SYS_SIGIO == sig), "Only SIGIO should be handled here");        if (!hal_interrupts_enabled) {        synth_sigio_pending = true;        return;    }        // Interrupts were enabled, but must be blocked before any further processing.    hal_interrupts_enabled = false;    // Update the interrupt status "register" to match pending interrupts    // Contact the auxiliary to find out what interrupts are currently pending there.    // If there is no auxiliary at present, e.g. because it has just terminated    // and things are generally somewhat messy, ignore it.    //    // This code also deals with the case where the user has requested program    // termination. It would be wrong for the auxiliary to just exit, since the    // application could not distinguish that case from a crash. Instead the    // auxiliary can optionally return an additional byte of data, and if that    // byte actually gets sent then that indicates pending termination.    if (synth_auxiliary_running) {        int             result;        int             actual_len;        unsigned char   dummy[1];        synth_auxiliary_xchgmsg(SYNTH_DEV_AUXILIARY, SYNTH_AUXREQ_GET_IRQPENDING, 0, 0,                                (const unsigned char*) 0, 0,        // The auxiliary does not need any additional data                                &result, dummy, &actual_len, 1);        synth_pending_isrs |= result;        if (actual_len) {            // The auxiliary has been asked to terminate by the user. This            // request has now been passed on to the eCos application.            synth_io_handle_shutdown_request_from_auxiliary();        }    }    // If any of the pending interrupts are not masked, invoke the VSR    if (0 != (synth_pending_isrs & ~synth_masked_isrs)) {        (*synth_VSR)();    } else {        hal_interrupts_enabled = true;    }    // The VSR will have invoked interrupt_end() with interrupts    // enabled, and they should still be enabled.    CYG_ASSERT( hal_interrupts_enabled, "Interrupts should still be enabled on return from the VSR");}// ----------------------------------------------------------------------------// Here we define an action to do in the idle thread. For the// synthetic target it makes no sense to spin eating processor time// that other processes could make use of. Instead we call select. The// itimer will still go off and kick the scheduler back into life,// giving us an escape path from the select. There is one problem: in// some configurations, e.g. when preemption is disabled, the idle// thread must yield continuously rather than blocking.voidhal_idle_thread_action(cyg_uint32 loop_count){#ifndef CYGIMP_HAL_IDLE_THREAD_SPIN    cyg_hal_sys__newselect(0,                           (struct cyg_hal_sys_fd_set*) 0,                           (struct cyg_hal_sys_fd_set*) 0,                           (struct cyg_hal_sys_fd_set*) 0,                           (struct cyg_hal_sys_timeval*) 0);#endif    CYG_UNUSED_PARAM(cyg_uint32, loop_count);}// ----------------------------------------------------------------------------// The I/O auxiliary.//// I/O happens via an auxiliary process. During startup this code attempts// to locate and execute a program ecosynth which should be installed in// ../libexec/ecosynth relative to some directory on the search path.// Subsequent I/O operations involve interacting with this auxiliary.#define MAKESTRING1(a) #a#define MAKESTRING2(a) MAKESTRING1(a)#define AUXILIARY       "../libexec/ecos/hal/synth/arch/" MAKESTRING2(CYGPKG_HAL_SYNTH) "/ecosynth"// Is the auxiliary up and running?cyg_bool    synth_auxiliary_running   = false;// The pipes to and from the auxiliary.static int  to_aux      = -1;static int  from_aux    = -1;// Attempt to start up the auxiliary. Note that this happens early on// during system initialization so it is "known" that the world is// still simple, e.g. that no other files have been opened.static voidsynth_start_auxiliary(void){#define BUFSIZE 256

⌨️ 快捷键说明

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