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

📄 c-iosys9.html

📁 this about vxworks operations systems
💻 HTML
📖 第 1 页 / 共 5 页
字号:
<p class="listspace"><ul class="Bullet" type="disc"><li><a name="85699"> </a>The tasks want to specify a timeout to wait for I/O from the device. For example, a task might want to time out on a UDP socket if the packet never arrives.</li></ul></p><p class="listspace"><ul class="Bullet" type="disc"><li><a name="85700"> </a>The driver supports multiple devices, and the tasks want to wait simultaneously for any number of them. For example, multiple pipes might be used for different data priorities.</li></ul></p><p class="listspace"><ul class="Bullet" type="disc"><li><a name="85701"> </a>The tasks want to wait for I/O from the device while also waiting for I/O from another device. For example, a server task might use both pipes and sockets.</li></ul></p></dl><dl class="margin"><dd><p class="Body"><a name="85702"> </a>To implement <b class="routine"><i class="routine">select</i></b><b>(</b>&nbsp;<b>)</b>, the driver must keep a list of tasks waiting for device activity. When the device becomes ready, the driver unblocks all the tasks waiting on the device. </p><dd><p class="Body"><a name="85703"> </a>For a device driver to support <b class="routine"><i class="routine">select</i></b><b>(</b>&nbsp;<b>)</b>, it must declare a <b class="symbol_UC">SEL_WAKEUP_LIST</b> structure (typically declared as part of the device descriptor structure) and initialize it by calling <b class="routine"><i class="routine">selWakeupListInit</i></b><b>(</b>&nbsp;<b>)</b>. This is done in the driver's <i class="textVariable">xx</i><b class="routine"><i class="routine">DevCreate</i></b><b>(</b>&nbsp;<b>)</b> routine. When a task calls <b class="routine"><i class="routine">select</i></b><b>(</b>&nbsp;<b>)</b>, <b class="library">selectLib</b> calls the driver's <b class="routine"><i class="routine">ioctl</i></b><b>(</b>&nbsp;<b>)</b> routine with the function <b class="symbol_UC">FIOSELECT</b> or <b class="symbol_UC">FIOUNSELECT</b>. If <b class="routine"><i class="routine">ioctl</i></b><b>(</b>&nbsp;<b>)</b> is called with <b class="symbol_UC">FIOSELECT,</b> the driver must do the following:</p></dl><dl class="margin"><p><ol class="List"><li value="1."><a name="85708"> </a>Add the<b class="symbol_UC"> SEL_WAKEUP_NODE</b> (provided as the third argument of <b class="routine"><i class="routine">ioctl</i></b><b>(</b>&nbsp;<b>)</b>) to the <b class="symbol_UC">SEL_WAKEUP_LIST</b> by calling <b class="routine"><i class="routine">selNodeAdd</i></b><b>(</b>&nbsp;<b>)</b>.</li></ol></p><p><ol class="List"><li value="2."><a name="85712"> </a>Use the routine <b class="routine"><i class="routine">selWakeupType</i></b><b>(</b>&nbsp;<b>)</b> to check whether the task is waiting for data to read from the device (<b class="symbol_UC">SELREAD</b>) or if the device is ready to be written (<b class="symbol_UC">SELWRITE</b>). </li></ol></p><p><ol class="List"><li value="3."><a name="85713"> </a>If the device is ready (for reading or writing as determined by <b class="routine"><i class="routine">selWakeupType</i></b><b>(</b>&nbsp;<b>)</b>), the driver calls the routine <b class="routine"><i class="routine">selWakeup</i></b><b>(</b>&nbsp;<b>)</b> to make sure that the <b class="routine"><i class="routine">select</i></b><b>(</b>&nbsp;<b>)</b> call in the task does not pend. This avoids the situation where the task is blocked but the device is ready.</li></ol></p></dl><dl class="margin"><dd><p class="Body"><a name="85716"> </a>If <b class="routine"><i class="routine">ioctl</i></b><b>(</b>&nbsp;<b>)</b> is called with <b class="symbol_UC">FIOUNSELECT</b>, the driver calls <b class="routine"><i class="routine">selNodeDelete</i></b><b>(</b>&nbsp;<b>)</b> to remove the provided <b class="symbol_UC">SEL_WAKEUP_NODE</b> from the wakeup list.</p><dd><p class="Body"><a name="85718"> </a>When the device becomes available, <b class="routine"><i class="routine">selWakeupAll</i></b><b>(</b>&nbsp;<b>)</b> is used to unblock all the tasks waiting on this device. Although this typically occurs in the driver's ISR, it can also occur elsewhere. For example, a pipe driver might call <b class="routine"><i class="routine">selWakeupAll</i></b><b>(</b>&nbsp;<b>)</b> from its<b class="routine"><i class="routine"> </i></b><i class="textVariable">xx</i><b class="routine"><i class="routine">Read</i></b><b>(</b>&nbsp;<b>)</b> routine to unblock all the tasks waiting to write, now that there is room in the pipe to store the data. Similarly the pipe's <i class="textVariable">xx</i><b class="routine"><i class="routine">Write</i></b><b>(</b>&nbsp;<b>)</b> routine might call<b class="routine"><i class="routine"> selWakeupAll</i></b><b>(</b>&nbsp;<b>)</b> to unblock all the tasks waiting to read, now that there is data in the pipe.</p></dl></dl><h4 class="EntityTitle"><a name="85720"><font face="Helvetica, sans-serif" size="-1" class="sans">Example 3-10:&nbsp;&nbsp;Driver Code Using the Select Facility</font></a></h4><dl class="margin"><dl class="margin"><dd><pre class="Code"><b><a name="85721">/* This code fragment shows how a driver might support select(). In this   * example, the driver unblocks tasks waiting for the device to become ready   * in its interrupt service routine.  */</a></b><dd> <b><a name="85723">/* myDrvLib.h - header file for driver */</a></b><dd> <b><a name="85725">typedef struct     /* MY_DEV */     {     DEV_HDR     devHdr;      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* device header */     BOOL       myDrvDataAvailable; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* data is available to read */     BOOL       myDrvRdyForWriting; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* device is ready to write */     SEL_WAKEUP_LIST selWakeupList;  &nbsp;&nbsp;&nbsp;&nbsp;/* list of tasks pended in select */     } MY_DEV;</a></b></pre></dl><dl class="margin"><dd><hr class="Line"></dl><dl class="margin"><dd><pre class="Code"><b><a name="97661">/* myDrv.c - code fragments for supporting select() in a driver */</a></b><dd> <b><a name="85735">#include "vxWorks.h" #include "selectLib.h"</a></b><dd> <b><a name="93728">/* First create and initialize the device */  STATUS myDrvDevCreate     (     char *  name,  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* name of device to create */     )     {     MY_DEV * pMyDrvDev; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* pointer to device descriptor*/     ... <i class="i">additional driver code</i> ...      /* allocate memory for MY_DEV */     pMyDrvDev = (MY_DEV *) malloc (sizeof MY_DEV);     ... <i class="i">additional driver code</i> ...</a></b><dd> <b><a name="96536">    /* initialize MY_DEV */     pMyDrvDev-&gt;myDrvDataAvailable=FALSE     pMyDrvDev-&gt;myDrvRdyForWriting=FALSE</a></b><dd> <b><a name="85753">    /* initialize wakeup list */     selWakeupListInit (&amp;pMyDrvDev-&gt;selWakeupList);     ... <i class="i">additional driver code</i> ...     }</a></b><dd> <b><a name="97446">/* ioctl function to request reading or writing */  STATUS myDrvIoctl     (     MY_DEV * pMyDrvDev,   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* pointer to device descriptor */     int    &nbsp;&nbsp;request,   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* ioctl function */     int &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;arg     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* where to send answer */     )     {     ... <i class="i">additional driver code</i> ...</a></b><dd> <b><a name="85769">    switch (request)         {         ... <i class="i">additional driver code</i> ...</a></b><dd> <b><a name="85774">        case FIOSELECT:</a></b><dd> <b><a name="85775">            /* add node to wakeup list */</a></b><dd> <b><a name="85776">            selNodeAdd (&amp;pMyDrvDev-&gt;selWakeupList, (SEL_WAKEUP_NODE *) arg);</a></b><dd> <b><a name="85778">            if (selWakeupType ((SEL_WAKEUP_NODE *) arg) == SELREAD                  &amp;&amp; pMyDrvDev-&gt;myDrvDataAvailable)                 {                 /* data available, make sure task does not pend */                 selWakeup ((SEL_WAKEUP_NODE *) arg);                 }             if (selWakeupType ((SEL_WAKEUP_NODE *) arg) == SELWRITE                  &amp;&amp; pMyDrvDev-&gt;myDrvRdyForWriting)                 {                 /* device ready for writing, make sure task does not pend */                 selWakeup ((SEL_WAKEUP_NODE *) arg);                 }             break;</a></b><dd> <b><a name="85788">        case FIOUNSELECT:</a></b><dd> <b><a name="85789">            /* delete node from wakeup list */             selNodeDelete (&amp;pMyDrvDev-&gt;selWakeupList, (SEL_WAKEUP_NODE *) arg);             break;</a></b><dd> <b><a name="85792">            ... <i class="i">additional driver code</i> ...         }     }</a></b><dd> <b><a name="85796">/* code that actually uses the select() function to read or write */  void myDrvIsr     (     MY_DEV * pMyDrvDev;     )     {     ... <i class="i">additional driver code</i> ...</a></b><dd> <b><a name="85803">    /* if there is data available to read, wake up all pending tasks */</a></b><dd> <b><a name="96082">    if (pMyDrvDev-&gt;myDrvDataAvailable)         selWakeupAll (&amp;pMyDrvDev-&gt;selWakeupList, SELREAD);</a></b><dd> <b><a name="85807">    /* if the device is ready to write, wake up all pending tasks */</a></b><dd> <b><a name="93887">    if (pMyDrvDev-&gt;myDrvRdyForWriting)         selWakeupAll (&amp;pMyDrvDev-&gt;selWakeupList, SELWRITE);     }</a></b></pre></dl></dl><font face="Helvetica, sans-serif" class="sans"><h4 class="H4"><i><a name="85815">Cache Coherency</a></i></h4></font><dl class="margin"><dl class="margin"><dd><p class="Body"><a name="85817"> </a>Drivers written for boards with caches must guarantee <i class="term">cache coherency</i>. Cache coherency means data in the cache must be in sync, or coherent, with data in RAM. The data cache and RAM can get out of sync any time there is asynchronous access to RAM (for example, DMA device access or VMEbus access). Data caches are used to increase performance by reducing the number of memory accesses. <a href="c-iosys9.html#85847">Figure&nbsp;3-7</a> shows the relationships between the CPU, data cache, RAM, and a DMA device.</p><dd><p class="Body"><a name="85823"> </a>Data caches can operate in one of two modes: <i class="term">writethrough</i> and <i class="term">copyback</i>. Write-through mode writes data to both the cache and RAM; this guarantees cache coherency on output but not input. Copyback mode writes the data only to the cache; this makes cache coherency an issue for both input and output of data. <div class="frame"><h4 class="EntityTitle"><a name="85847"><font face="Helvetica, sans-serif" size="-1" class="sans">Figure 3-7:&nbsp;&nbsp;Cache Coherency</font></a></h4><dl class="margin"><div class="CellBody"><a name="85844"> </a><img class="figure" border="0" src="images/c-iosysa7.gif">&nbsp;</div></dl></div></p><dd><p class="Body"><a name="85848"> </a>If a CPU writes data to RAM that is destined for a DMA device, the data can first be written to the data cache. When the DMA device transfers the data from RAM, there is no guarantee that the data in RAM was updated with the data in the cache. Thus, the data output to the device may not be the most recent--the new data may still be sitting in the cache. This data incoherency can be solved by making sure the data cache is flushed to RAM before the data is transferred to the DMA device.</p><dd><p class="Body"><a name="85849"> </a>If a CPU reads data from RAM that originated from a DMA device, the data read can be from the cache buffer (if the cache buffer for this data is not marked invalid) and not the data just transferred from the device to RAM. The solution to this data incoherency is to make sure that the cache buffer is marked invalid so that the data is read from RAM and not from the cache.</p><dd><p class="Body"><a name="85850"> </a>Drivers can solve the cache coherency problem either by allocating cache-safe buffers (buffers that are marked non-cacheable) or flushing and invalidating cache entries any time the data is written to or read from the device. Allocating cache-safe buffers is useful for static buffers; however, this typically requires MMU support. Non-cacheable buffers that are allocated and freed frequently (dynamic buffers) can result in large amounts of memory being marked non-cacheable. An alternative to using non-cacheable buffers is to flush and invalidate cache entries manually; this allows dynamic buffers to be kept coherent.</p><dd><p class="Body"><a name="85851"> </a>The routines <b class="routine"><i class="routine">cacheFlush</i></b><b>(</b>&nbsp;<b>)</b> and <b class="routine"><i class="routine">cacheInvalidate</i></b><b>(</b>&nbsp;<b>)</b> are used to manually flush and invalidate cache buffers. Before a device reads the data, flush the data from the cache to RAM using <b class="routine"><i class="routine">cacheFlush</i></b><b>(</b>&nbsp;<b>)</b> to ensure the device reads current data. After the device has written the data into RAM, invalidate the cache entry with <b class="routine"><i class="routine">cacheInvalidate</i></b><b>(</b>&nbsp;<b>)</b>. This guarantees that when the data is read by the CPU, the cache is updated with the new data in RAM.</p></dl></dl><h4 class="EntityTitle"><a name="85857"><font face="Helvetica, sans-serif" size="-1" class="sans">Example 3-11:&nbsp;&nbsp;DMA Transfer Routine </font></a></h4><dl class="margin"><dl class="margin"><dd><pre class="Code"><b><a name="85858">/* This a sample DMA transfer routine. Before programming the device to   * output the data to the device, it flushes the cache by calling   * cacheFlush(). On a read, after the device has transferred the data, the   * cache entry must be invalidated using cacheInvalidate().  */</a></b><dd> <b><a name="85860">#include "vxWorks.h" #include "cacheLib.h" #include "fcntl.h" #include "example.h" void exampleDmaTransfer   /* 1 = READ, 0 = WRITE */     (     UINT8 *pExampleBuf,     int exampleBufLen, 

⌨️ 快捷键说明

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