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

📄 kernel-interrupts.html

📁 encos_rtos一款精致小巧的实时嵌入式操作系统 +CODEWORR 教程
💻 HTML
📖 第 1 页 / 共 2 页
字号:
          </P
><P
>The return value of an ISR is normally one of
<TT
CLASS="LITERAL"
>CYG_ISR_CALL_DSR</TT
> or
<TT
CLASS="LITERAL"
>CYG_ISR_HANDLED</TT
>. The former indicates that further
processing is required at DSR level, and the interrupt handler's DSR
will be run as soon as possible. The latter indicates that the
interrupt has been fully handled and no further effort is required.
          </P
><P
>An ISR is allowed to make very few kernel calls. It can manipulate the
interrupt mask, and on SMP systems it can use spinlocks. However an
ISR must not make higher-level kernel calls such as posting to a
semaphore, instead any such calls must be made from the DSR. This
avoids having to disable interrupts throughout the kernel and thus
improves interrupt latency.
          </P
></DD
><DT
>cyg_DSR_t <TT
CLASS="PARAMETER"
><I
>dsr</I
></TT
></DT
><DD
><P
>If an interrupt has occurred and the ISR has returned a value
<TT
CLASS="LITERAL"
>CYG_ISR_CALL_DSR</TT
>, the system will call the
deferred service routine or DSR associated with this interrupt
handler. If the scheduler is not currently locked then the DSR will
run immediately. However if the interrupted thread was in the middle
of a kernel call and had locked the scheduler, then the DSR will be
deferred until the scheduler is again unlocked. This allows the
DSR to make certain kernel calls safely, for example posting to a
semaphore or signalling a condition variable. A DSR is a C function
which takes the following form:
          </P
><TABLE
BORDER="5"
BGCOLOR="#E0E0F0"
WIDTH="70%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>void
dsr_function(cyg_vector_t vector,
             cyg_ucount32 count,
             cyg_addrword_t data)
{
}
          </PRE
></TD
></TR
></TABLE
><P
>The first argument identifies the specific interrupt that has caused
the DSR to run. The second argument indicates the number of these
interrupts that have occurred and for which the ISR requested a DSR.
Usually this will be <TT
CLASS="LITERAL"
>1</TT
>, unless the system is
suffering from a very heavy load. The third argument is the
<TT
CLASS="PARAMETER"
><I
>data</I
></TT
> field passed to
<TT
CLASS="FUNCTION"
>cyg_interrupt_create</TT
>. 
          </P
></DD
><DT
>cyg_handle_t* <TT
CLASS="PARAMETER"
><I
>handle</I
></TT
></DT
><DD
><P
>The kernel will return a handle to the newly created interrupt handler
via this argument. Subsequent operations on the interrupt handler such
as attaching it to the interrupt source will use this handle.
          </P
></DD
><DT
>cyg_interrupt* <TT
CLASS="PARAMETER"
><I
>intr</I
></TT
></DT
><DD
><P
>This provides the kernel with an area of memory for holding this
interrupt handler and associated data.
          </P
></DD
></DL
></DIV
><P
>The call to <TT
CLASS="FUNCTION"
>cyg_interrupt_create</TT
> simply fills in
a kernel data structure. A typical next step is to call
<TT
CLASS="FUNCTION"
>cyg_interrupt_attach</TT
> using the handle returned by
the create operation. This makes it possible to have several different
interrupt handlers for a given vector, attaching whichever one is
currently appropriate. Replacing an interrupt handler requires a call
to <TT
CLASS="FUNCTION"
>cyg_interrupt_detach</TT
>, followed by another call
to <TT
CLASS="FUNCTION"
>cyg_interrupt_attach</TT
> for the replacement
handler. <TT
CLASS="FUNCTION"
>cyg_interrupt_delete</TT
> can be used if an
interrupt handler is no longer required.
      </P
><P
>Some hardware may allow for further control over specific interrupts,
for example whether an interrupt is level or edge triggered. Any such
hardware functionality can be accessed using
<TT
CLASS="FUNCTION"
>cyg_interrupt_configure</TT
>: the
<TT
CLASS="PARAMETER"
><I
>level</I
></TT
> argument selects between level versus
edge triggered; the <TT
CLASS="PARAMETER"
><I
>up</I
></TT
> argument selects between
high and low level, or between rising and falling edges.
      </P
><P
>Usually interrupt handlers are created, attached and configured during
system initialization, while global interrupts are still disabled. On
most hardware it will also be necessary to call
<TT
CLASS="FUNCTION"
>cyg_interrupt_unmask</TT
>, since the sensible default
for interrupt masking is to ignore any interrupts for which no handler
is installed.
      </P
></DIV
><DIV
CLASS="REFSECT1"
><A
NAME="KERNEL-INTERRUPTS-ENABLE"
></A
><H2
>Controlling Interrupts</H2
><P
>eCos provides two ways of controlling whether or not interrupts
happen. It is possible to disable and reenable all interrupts
globally, using <TT
CLASS="FUNCTION"
>cyg_interrupt_disable</TT
> and
<TT
CLASS="FUNCTION"
>cyg_interrupt_enable</TT
>. Typically this works by
manipulating state inside the cpu itself, for example setting a flag
in a status register or executing special instructions. Alternatively
it may be possible to mask a specific interrupt source by writing to
one or to several interrupt mask registers. Hardware-specific
documentation should be consulted for the exact details of how
interrupt masking works, because a full implementation is not possible
on all hardware.
      </P
><P
>The primary use for these functions is to allow data to be shared
between ISRs and other code such as DSRs or threads. If both a thread
and an ISR need to manipulate either a data structure or the hardware
itself, there is a possible conflict if an interrupt happens just when
the thread is doing such manipulation. Problems can be avoided by the
thread either disabling or masking interrupts during the critical
region. If this critical region requires only a few instructions then
usually it is more efficient to disable interrupts. For larger
critical regions it may be more appropriate to use interrupt masking,
allowing other interrupts to occur. There are other uses for interrupt
masking. For example if a device is not currently being used by the
application then it may be desirable to mask all interrupts generated
by that device.
      </P
><P
>There are two functions for masking a specific interrupt source,
<TT
CLASS="FUNCTION"
>cyg_interrupt_mask</TT
> and
<TT
CLASS="FUNCTION"
>cyg_interrupt_mask_intunsafe</TT
>. On typical hardware
masking an interrupt is not an atomic operation, so if two threads
were to perform interrupt masking operations at the same time there
could be problems. <TT
CLASS="FUNCTION"
>cyg_interrupt_mask</TT
> disables
all interrupts while it manipulates the interrupt mask. In situations
where interrupts are already know to be disabled,
<TT
CLASS="FUNCTION"
>cyg_interrupt_mask_intunsafe</TT
> can be used
instead. There are matching functions
<TT
CLASS="FUNCTION"
>cyg_interrupt_unmask</TT
> and
<TT
CLASS="FUNCTION"
>cyg_interrupt_unmask_intsafe</TT
>.
      </P
></DIV
><DIV
CLASS="REFSECT1"
><A
NAME="KERNEL-INTERRUPTS-SMP"
></A
><H2
>SMP Support</H2
><P
>On SMP systems the kernel provides an additional two functions related
to interrupt handling. <TT
CLASS="FUNCTION"
>cyg_interrupt_set_cpu</TT
>
specifies that a particular hardware interrupt should always be
handled on one specific processor in the system. In other words when
the interrupt triggers it is only that processor which detects it, and
it is only on that processor that the VSR and ISR will run. If a DSR
is requested then it will also run on the same CPU. The
function <TT
CLASS="FUNCTION"
>cyg_interrupt_get_cpu</TT
> can be used to
find out which interrupts are handled on which processor. 
      </P
></DIV
><DIV
CLASS="REFSECT1"
><A
NAME="KERNEL-INTERRUPTS-VSR"
></A
><H2
>VSR Support</H2
><P
>When an interrupt occurs the hardware will transfer control to a piece
of code known as the VSR, or Vector Service Routine. By default this
code is provided by eCos. Usually it is written in assembler, but on
some architectures it may be possible to implement VSRs in C by
specifying an interrupt attribute. Compiler documentation should be
consulted for more information on this. The default eCos VSR will work
out which ISR function should process the interrupt, and set up a C
environment suitable for this ISR.
      </P
><P
>For some applications it may be desirable to replace the default eCos
VSR and handle some interrupts directly. This minimizes interrupt
latency, but it requires application developers to program at a lower
level. Usually the best way to write a custom VSR is to copy the
existing one supplied by eCos and then make appropriate modifications.
The function <TT
CLASS="FUNCTION"
>cyg_interrupt_get_vsr</TT
> can be used to
get hold of the current VSR for a given interrupt vector, allowing it
to be restored if the custom VSR is no longer required.
<TT
CLASS="FUNCTION"
>cyg_interrupt_set_vsr</TT
> can be used to install a
replacement VSR. Usually the <TT
CLASS="PARAMETER"
><I
>vsr</I
></TT
> argument will
correspond to an exported label in an assembler source file.
      </P
></DIV
><DIV
CLASS="REFSECT1"
><A
NAME="KERNEL-INTERRUPTS-CONTEXT"
></A
><H2
>Valid contexts</H2
><P
>In a typical configuration interrupt handlers are created and attached
during system initialization, and never detached or deleted. However
it is possible to perform these operations at thread level, if
desired. Similarly <TT
CLASS="FUNCTION"
>cyg_interrupt_configure</TT
>,
<TT
CLASS="FUNCTION"
>cyg_interrupt_set_vsr</TT
>, and
<TT
CLASS="FUNCTION"
>cyg_interrupt_set_cpu</TT
> are usually called only
during system initialization, but on typical hardware may be called at
any time. <TT
CLASS="FUNCTION"
>cyg_interrupt_get_vsr</TT
> and
<TT
CLASS="FUNCTION"
>cyg_interrupt_get_cpu</TT
> may be called at any time.
      </P
><P
>The functions for enabling, disabling, masking and unmasking
interrupts can be called in any context, when appropriate. It is the
responsibility of application developers to determine when the use of
these functions is appropriate.
      </P
></DIV
><DIV
CLASS="NAVFOOTER"
><HR
ALIGN="LEFT"
WIDTH="100%"><TABLE
SUMMARY="Footer navigation table"
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
><A
HREF="kernel-schedcontrol.html"
ACCESSKEY="P"
>Prev</A
></TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="ecos-ref.html"
ACCESSKEY="H"
>Home</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
><A
HREF="kernel-characterization.html"
ACCESSKEY="N"
>Next</A
></TD
></TR
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
>Scheduler Control</TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="kernel.html"
ACCESSKEY="U"
>Up</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
>Kernel Real-time Characterization</TD
></TR
></TABLE
></DIV
></BODY
></HTML
>

⌨️ 快捷键说明

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