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

📄 sample_gpio_driver.html

📁 ADI 公司blackfin系列的用户使用文挡。
💻 HTML
📖 第 1 页 / 共 3 页
字号:
<span class="br0">&#125;</span>&nbsp;</pre></div><!-- SECTION [2850-3645] --><h3><a name="write_function" id="write_function">Write Function</a></h3><div class="level3"><p> The write function allows the user code to set or clear the output leds</p><pre class="code c">&nbsp;<span class="kw4">static</span> ssize_tpflags_write <span class="br0">&#40;</span><span class="kw4">struct</span> file *filp, <span class="kw4">const</span> <span class="kw4">char</span> *buf, size_t size, loff_t * offp<span class="br0">&#41;</span><span class="br0">&#123;</span>&nbsp;  <span class="kw4">int</span> minor = check_minor <span class="br0">&#40;</span>filp-&gt;f_dentry-&gt;d_inode<span class="br0">&#41;</span>;&nbsp;  <span class="kw4">volatile</span> <span class="kw4">unsigned</span> <span class="kw4">short</span> *set_or_clear;&nbsp;  DPRINTK <span class="br0">&#40;</span><span class="st0">"pfbits driver for bf53x minor = %d<span class="es0">\n</span>"</span>, minor<span class="br0">&#41;</span>;&nbsp;  <span class="kw1">if</span> <span class="br0">&#40;</span>minor &lt; <span class="nu0">0</span><span class="br0">&#41;</span>    <span class="kw1">return</span> -ENODEV;&nbsp;  <span class="kw1">if</span> <span class="br0">&#40;</span>size &lt; <span class="nu0">2</span><span class="br0">&#41;</span>    <span class="kw1">return</span> -EMSGSIZE;&nbsp;  <span class="kw1">if</span> <span class="br0">&#40;</span>!buf<span class="br0">&#41;</span>    <span class="kw1">return</span> -EFAULT;&nbsp;  <span class="co1">// clear if '0' set if '1'</span>  set_or_clear =   <span class="br0">&#40;</span>buf<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span> == <span class="st0">'0'</span><span class="br0">&#41;</span> ?        <span class="br0">&#40;</span><span class="br0">&#40;</span><span class="kw4">volatile</span> <span class="kw4">unsigned</span> <span class="kw4">short</span> *<span class="br0">&#41;</span> FIO_FLAG_C<span class="br0">&#41;</span> :        <span class="br0">&#40;</span><span class="br0">&#40;</span><span class="kw4">volatile</span> <span class="kw4">unsigned</span> <span class="kw4">short</span> *<span class="br0">&#41;</span> FIO_FLAG_S<span class="br0">&#41;</span>;&nbsp;  *set_or_clear = <span class="br0">&#40;</span><span class="nu0">1</span> &lt;&lt; minor<span class="br0">&#41;</span>;&nbsp;  <span class="kw1">return</span> size;&nbsp;<span class="br0">&#125;</span>&nbsp;</pre></div><!-- SECTION [3646-4347] --><h3><a name="interrupt_handler" id="interrupt_handler">Interrupt Handler</a></h3><div class="level3"><p> This will clear the interrupt and input the flags state and detect a change.</p><p>(Note It should possibly only mask the pins of interest )</p><p>The interrupt handler will wake up the <strong>pflags_in_waitq</strong> wait queue.</p><pre class="code c">&nbsp;<span class="kw4">static</span> irqreturn_t pflags_irq_handler <span class="br0">&#40;</span> <span class="kw4">int</span> irq, <span class="kw4">void</span> *dev_id, <span class="kw4">struct</span> pt_regs *regs <span class="br0">&#41;</span><span class="br0">&#123;</span>&nbsp;  <span class="kw4">short</span> pflags_nextstate = *pFIO_FLAG_D;&nbsp;  <span class="coMULTI">/* FIXME: Clear only status of flag pin that caused the interrupt */</span>  *pFIO_FLAG_C = 0xFFFF; <span class="coMULTI">/* clear irq status on interrupt lines */</span>&nbsp;  printk<span class="br0">&#40;</span><span class="st0">"pflags_irq_handler <span class="es0">\n</span>"</span><span class="br0">&#41;</span>;&nbsp;  pflags_statechanged   = pflags_laststate ^ pflags_nextstate;  pflags_laststate      = pflags_nextstate;&nbsp;  wake_up<span class="br0">&#40;</span> &amp;pflags_in_waitq <span class="br0">&#41;</span>;&nbsp;  <span class="kw1">return</span> IRQ_HANDLED;&nbsp;<span class="br0">&#125;</span>&nbsp;</pre></div><!-- SECTION [4348-5076] --><h3><a name="poll_function" id="poll_function">Poll Function</a></h3><div class="level3"><p> The Poll function is optional. It will indicate that the state of the input pins has changed.</p><pre class="code c"><span class="kw4">static</span> <span class="kw4">unsigned</span> <span class="kw4">int</span> pflags_poll<span class="br0">&#40;</span><span class="kw4">struct</span> file *filp, <span class="kw4">struct</span> poll_table_struct *wait<span class="br0">&#41;</span><span class="br0">&#123;</span>&nbsp;  <span class="kw4">int</span> minor = check_minor<span class="br0">&#40;</span> filp-&gt;f_dentry-&gt;d_inode <span class="br0">&#41;</span>;  <span class="kw4">int</span> changed=<span class="nu0">0</span>;  <span class="kw4">unsigned</span> <span class="kw4">int</span> mask = <span class="nu0">0</span>;&nbsp;  <span class="kw1">if</span><span class="br0">&#40;</span> minor &lt; <span class="nu0">0</span> <span class="br0">&#41;</span> <span class="kw1">return</span> -ENODEV;&nbsp;<span class="co1">//    *pFIO_MASKA_C |= (1 &lt;&lt; minor);</span>  *pFIO_MASKA_S |= <span class="br0">&#40;</span><span class="nu0">1</span> &lt;&lt; minor<span class="br0">&#41;</span>;  *pFIO_INEN    |= <span class="br0">&#40;</span><span class="nu0">1</span> &lt;&lt; minor<span class="br0">&#41;</span>;&nbsp;  <span class="kw1">if</span> <span class="br0">&#40;</span>filp-&gt;f_mode &amp; FMODE_READ<span class="br0">&#41;</span><span class="br0">&#123;</span>      <span class="coMULTI">/* attention! this wakes up when /any/ of the flags changes */</span>      poll_wait<span class="br0">&#40;</span>filp, &amp;pflags_in_waitq, wait<span class="br0">&#41;</span>;&nbsp;      changed = pflags_statechanged &amp; <span class="br0">&#40;</span><span class="nu0">1</span>&lt;&lt;minor<span class="br0">&#41;</span>;      <span class="kw1">if</span> <span class="br0">&#40;</span> changed <span class="br0">&#41;</span> mask |= POLLIN | POLLRDNORM;  <span class="br0">&#125;</span>&nbsp;  <span class="coMULTI">/* we can always write */</span>  <span class="kw1">if</span> <span class="br0">&#40;</span>filp-&gt;f_mode &amp; FMODE_WRITE<span class="br0">&#41;</span>      mask |= POLLOUT | POLLWRNORM;&nbsp;  <span class="kw1">return</span> mask;<span class="br0">&#125;</span>&nbsp;</pre></div><!-- SECTION [5077-5909] --><h3><a name="exit_function" id="exit_function">Exit Function</a></h3><div class="level3"><p>A simple exit function removes the proc interface </p><pre class="code"> (NOTE the Poll Irq is not removed !! )</pre><pre class="code c"><span class="kw4">void</span> __exitblackfin_plags_exit <span class="br0">&#40;</span><span class="kw4">void</span><span class="br0">&#41;</span><span class="br0">&#123;</span>&nbsp;  remove_proc_entry <span class="br0">&#40;</span><span class="st0">"driver/pflags"</span>, <span class="kw2">NULL</span><span class="br0">&#41;</span>;&nbsp;<span class="br0">&#125;</span>&nbsp;module_exit <span class="br0">&#40;</span>blackfin_plags_exit<span class="br0">&#41;</span>;&nbsp;</pre></div><!-- SECTION [5910-6172] --><h3><a name="ioctl_code" id="ioctl_code">IOCTL Code</a></h3><div class="level3"><pre class="code c"><span class="kw4">static</span> <span class="kw4">int</span>pflags_ioctl <span class="br0">&#40;</span><span class="kw4">struct</span> inode *inode, <span class="kw4">struct</span> file *filp, uint cmd,              <span class="kw4">unsigned</span> <span class="kw4">long</span> arg<span class="br0">&#41;</span><span class="br0">&#123;</span>&nbsp;    <span class="kw4">int</span> minor = check_minor <span class="br0">&#40;</span>filp-&gt;f_dentry-&gt;d_inode<span class="br0">&#41;</span>;&nbsp;&nbsp;    <span class="kw1">if</span> <span class="br0">&#40;</span>minor &lt; <span class="nu0">0</span><span class="br0">&#41;</span>        <span class="kw1">return</span> -ENODEV;&nbsp;    DPRINTK <span class="br0">&#40;</span><span class="st0">"pfbits driver for bf53x minor = %d<span class="es0">\n</span>"</span>, minor<span class="br0">&#41;</span>;&nbsp;    <span class="kw1">switch</span> <span class="br0">&#40;</span>cmd<span class="br0">&#41;</span> <span class="br0">&#123;</span>        <span class="kw1">case</span> SET_FIO_DIR:            DPRINTK <span class="br0">&#40;</span><span class="st0">"pflags_ioctl: SET_FIO_DIR <span class="es0">\n</span>"</span><span class="br0">&#41;</span>;            <span class="kw1">if</span> <span class="br0">&#40;</span>arg<span class="br0">&#41;</span> <span class="br0">&#123;</span>                <span class="co1">// OUTPUT</span>                *pFIO_DIR |= <span class="br0">&#40;</span><span class="nu0">1</span> &lt;&lt; minor<span class="br0">&#41;</span>;            <span class="br0">&#125;</span> <span class="kw1">else</span> <span class="br0">&#123;</span>                   <span class="co1">// INPUT</span>                *pFIO_DIR &amp;= ~<span class="br0">&#40;</span><span class="nu0">1</span> &lt;&lt; minor<span class="br0">&#41;</span>;            <span class="br0">&#125;</span>            <span class="kw2">break</span>;&nbsp;        <span class="kw1">case</span> SET_FIO_POLAR:            DPRINTK <span class="br0">&#40;</span><span class="st0">"pflags_ioctl: SET_FIO_POLAR <span class="es0">\n</span>"</span>, arg<span class="br0">&#41;</span>;            <span class="kw1">if</span> <span class="br0">&#40;</span>arg<span class="br0">&#41;</span> <span class="br0">&#123;</span>                <span class="co1">// ACTIVELOW_FALLINGEDGE</span>                *pFIO_POLAR |= <span class="br0">&#40;</span><span class="nu0">1</span> &lt;&lt; minor<span class="br0">&#41;</span>;            <span class="br0">&#125;</span>  <span class="kw1">else</span> <span class="br0">&#123;</span>            <span class="co1">// ACTIVEHIGH_RISINGEDGE</span>                     *pFIO_POLAR &amp;= ~<span class="br0">&#40;</span><span class="nu0">1</span> &lt;&lt; minor<span class="br0">&#41;</span>;            <span class="br0">&#125;</span>            <span class="kw2">break</span>;&nbsp;       <span class="kw1">case</span> SET_FIO_EDGE:            DPRINTK <span class="br0">&#40;</span><span class="st0">"pflags_ioctl: SET_FIO_EDGE <span class="es0">\n</span>"</span><span class="br0">&#41;</span>;&nbsp;           <span class="kw1">if</span> <span class="br0">&#40;</span>arg<span class="br0">&#41;</span> <span class="br0">&#123;</span>                <span class="co1">// EDGE</span>               *pFIO_EDGE |= <span class="br0">&#40;</span><span class="nu0">1</span> &lt;&lt; minor<span class="br0">&#41;</span>;            <span class="br0">&#125;</span> <span class="kw1">else</span>  <span class="br0">&#123;</span>                   <span class="co1">// LEVEL</span>               *pFIO_EDGE &amp;= ~<span class="br0">&#40;</span><span class="nu0">1</span> &lt;&lt; minor<span class="br0">&#41;</span>;            <span class="br0">&#125;</span>            <span class="kw2">break</span>;&nbsp;       <span class="kw1">case</span> SET_FIO_BOTH:           DPRINTK <span class="br0">&#40;</span><span class="st0">"pflags_ioctl: SET_FIO_BOTH <span class="es0">\n</span>"</span><span class="br0">&#41;</span>;&nbsp;           <span class="kw1">if</span> <span class="br0">&#40;</span>arg<span class="br0">&#41;</span> <span class="br0">&#123;</span>                <span class="co1">// BOTHEDGES</span>              *pFIO_BOTH |= <span class="br0">&#40;</span><span class="nu0">1</span> &lt;&lt; minor<span class="br0">&#41;</span>;          <span class="br0">&#125;</span> <span class="kw1">else</span> <span class="br0">&#123;</span>                   <span class="co1">// SINGLEEDGE</span>              *pFIO_BOTH &amp;= ~<span class="br0">&#40;</span><span class="nu0">1</span> &lt;&lt; minor<span class="br0">&#41;</span>;          <span class="br0">&#125;</span>          <span class="kw2">break</span>;        <span class="kw1">case</span> SET_FIO_INEN:           DPRINTK <span class="br0">&#40;</span><span class="st0">"pflags_ioctl: SET_FIO_INEN <span class="es0">\n</span>"</span><span class="br0">&#41;</span>;           <span class="kw1">if</span> <span class="br0">&#40;</span>arg<span class="br0">&#41;</span> <span class="br0">&#123;</span>                <span class="co1">// OUTPUT_ENABLE</span>              *pFIO_INEN |= <span class="br0">&#40;</span><span class="nu0">1</span> &lt;&lt; minor<span class="br0">&#41;</span>;           <span class="br0">&#125;</span> <span class="kw1">else</span> <span class="br0">&#123;</span>                   <span class="co1">// INPUT_DISABLE</span>              *pFIO_INEN &amp;= ~<span class="br0">&#40;</span><span class="nu0">1</span> &lt;&lt; minor<span class="br0">&#41;</span>;           <span class="br0">&#125;</span>           <span class="kw2">break</span>;&nbsp;       <span class="kw1">default</span>:           <span class="kw1">return</span> -EINVAL;    <span class="br0">&#125;</span>  <span class="co1">// end switch</span>    <span class="kw1">return</span> <span class="nu0">0</span>;<span class="br0">&#125;</span>&nbsp;</pre></div><!-- SECTION [6173-8124] --><h3><a name="proc_interface" id="proc_interface">Proc Interface</a></h3><div class="level3"><p> This driver has an example proc interface This uses a small function to populate a string buffer (<strong>page</strong>)  with data to be returned to the user.</p><p>This code has some additional complexity in that is handles part of the multi  page capibility of the proc interface.</p><p>In this case this ios not needed. A simpler </p><pre class="code c">&nbsp;<span class="co1">// from the source example </span><span class="kw4">static</span> <span class="kw4">int</span>pflags_read_proc <span class="br0">&#40;</span><span class="kw4">char</span> *page, <span class="kw4">char</span> **start, off_t off,                  <span class="kw4">int</span> count, <span class="kw4">int</span> *eof, <span class="kw4">void</span> *data<span class="br0">&#41;</span><span class="br0">&#123;</span>  <span class="kw4">int</span> len = <span class="nu0">0</span>;

⌨️ 快捷键说明

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