📄 linux设备驱动程序学习(9)-与硬件通信 - linux设备驱动程序 - tekkaman ninja.htm
字号:
style="COLOR: #0000ff">void</SPAN> smp_mb<SPAN
style="COLOR: #0000cc">(</SPAN><SPAN
style="COLOR: #0000ff">void</SPAN><SPAN
style="COLOR: #0000cc">)</SPAN><SPAN
style="COLOR: #0000cc">;</SPAN> <BR><SPAN
style="COLOR: #ff9900">/*仅当内核为 SMP 系统编译时插入硬件屏障;
否则,
它们都扩展为一个简单的屏障调用。*/</SPAN></SPAN></CODE></P></TD></TR></TBODY></TABLE>
<P>典型的应用:</P>
<TABLE style="BORDER-COLLAPSE: collapse"
borderColor=#999999 cellSpacing=0 cellPadding=0
width="95%" bgColor=#f1f1f1 border=1>
<TBODY>
<TR>
<TD>
<P
style="MARGIN: 5px; LINE-HEIGHT: 150%"><CODE><SPAN
style="COLOR: #000000">writel<SPAN
style="COLOR: #0000cc">(</SPAN>dev<SPAN
style="COLOR: #0000cc">-</SPAN><SPAN
style="COLOR: #0000cc">></SPAN>registers<SPAN
style="COLOR: #0000cc">.</SPAN>addr<SPAN
style="COLOR: #0000cc">,</SPAN>
io_destination_address<SPAN
style="COLOR: #0000cc">)</SPAN><SPAN
style="COLOR: #0000cc">;</SPAN><BR>writel<SPAN
style="COLOR: #0000cc">(</SPAN>dev<SPAN
style="COLOR: #0000cc">-</SPAN><SPAN
style="COLOR: #0000cc">></SPAN>registers<SPAN
style="COLOR: #0000cc">.</SPAN>size<SPAN
style="COLOR: #0000cc">,</SPAN> io_size<SPAN
style="COLOR: #0000cc">)</SPAN><SPAN
style="COLOR: #0000cc">;</SPAN><BR>writel<SPAN
style="COLOR: #0000cc">(</SPAN>dev<SPAN
style="COLOR: #0000cc">-</SPAN><SPAN
style="COLOR: #0000cc">></SPAN>registers<SPAN
style="COLOR: #0000cc">.</SPAN>operation<SPAN
style="COLOR: #0000cc">,</SPAN> DEV_READ<SPAN
style="COLOR: #0000cc">)</SPAN><SPAN
style="COLOR: #0000cc">;</SPAN><BR>wmb<SPAN
style="COLOR: #0000cc">(</SPAN><SPAN
style="COLOR: #0000cc">)</SPAN><SPAN
style="COLOR: #0000cc">;</SPAN><SPAN
style="COLOR: #ff9900">/*类似一条分界线,上面的写操作必然会在下面的写操作前完成,但是上面的三个写操作的排序无法保证*/</SPAN><BR>writel<SPAN
style="COLOR: #0000cc">(</SPAN>dev<SPAN
style="COLOR: #0000cc">-</SPAN><SPAN
style="COLOR: #0000cc">></SPAN>registers<SPAN
style="COLOR: #0000cc">.</SPAN>control<SPAN
style="COLOR: #0000cc">,</SPAN> DEV_GO<SPAN
style="COLOR: #0000cc">)</SPAN><SPAN
style="COLOR: #0000cc">;</SPAN></SPAN></CODE></P></TD></TR></TBODY></TABLE>
<P>内存屏障影响性能,所以应当只在确实需要它们的地方使用。不同的类型对性能的影响也不同,因此要尽可能地使用需要的特定类型。值得注意的是大部分处理同步的内核原语,例如自旋锁和atomic_t,也可作为内存屏障使用。</P>
<P>某些体系允许赋值和内存屏障组合,以提高效率。它们定义如下:
<TABLE style="BORDER-COLLAPSE: collapse"
borderColor=#999999 cellSpacing=0 cellPadding=0
width="95%" bgColor=#f1f1f1 border=1>
<TBODY>
<TR>
<TD>
<P
style="MARGIN: 5px; LINE-HEIGHT: 150%"><CODE><SPAN
style="COLOR: #000000"><FONT face=新宋体><SPAN
style="COLOR: #0000cc">#</SPAN><SPAN
style="COLOR: #ff0000">define</SPAN> set_mb<SPAN
style="COLOR: #0000cc">(</SPAN>var<SPAN
style="COLOR: #0000cc">,</SPAN> value<SPAN
style="COLOR: #0000cc">)</SPAN> <SPAN
style="COLOR: #0000ff">do</SPAN> <SPAN
style="COLOR: #0000cc">{</SPAN>var <SPAN
style="COLOR: #0000cc">=</SPAN> value<SPAN
style="COLOR: #0000cc">;</SPAN> mb<SPAN
style="COLOR: #0000cc">(</SPAN><SPAN
style="COLOR: #0000cc">)</SPAN><SPAN
style="COLOR: #0000cc">;</SPAN><SPAN
style="COLOR: #0000cc">}</SPAN> <SPAN
style="COLOR: #0000ff">while</SPAN> 0<BR><SPAN
style="COLOR: #ff9900">/*以下宏定义在ARM体系中不存在*/</SPAN><BR><SPAN
style="COLOR: #0000cc">#</SPAN><SPAN
style="COLOR: #ff0000">define</SPAN>
set_wmb<SPAN
style="COLOR: #0000cc">(</SPAN>var<SPAN
style="COLOR: #0000cc">,</SPAN> value<SPAN
style="COLOR: #0000cc">)</SPAN> <SPAN
style="COLOR: #0000ff">do</SPAN> <SPAN
style="COLOR: #0000cc">{</SPAN>var <SPAN
style="COLOR: #0000cc">=</SPAN> value<SPAN
style="COLOR: #0000cc">;</SPAN> wmb<SPAN
style="COLOR: #0000cc">(</SPAN><SPAN
style="COLOR: #0000cc">)</SPAN><SPAN
style="COLOR: #0000cc">;</SPAN><SPAN
style="COLOR: #0000cc">}</SPAN> <SPAN
style="COLOR: #0000ff">while</SPAN> 0<BR><SPAN
style="COLOR: #0000cc">#</SPAN><SPAN
style="COLOR: #ff0000">define</SPAN>
set_rmb<SPAN
style="COLOR: #0000cc">(</SPAN>var<SPAN
style="COLOR: #0000cc">,</SPAN> value<SPAN
style="COLOR: #0000cc">)</SPAN> <SPAN
style="COLOR: #0000ff">do</SPAN> <SPAN
style="COLOR: #0000cc">{</SPAN>var <SPAN
style="COLOR: #0000cc">=</SPAN> value<SPAN
style="COLOR: #0000cc">;</SPAN> rmb<SPAN
style="COLOR: #0000cc">(</SPAN><SPAN
style="COLOR: #0000cc">)</SPAN><SPAN
style="COLOR: #0000cc">;</SPAN><SPAN
style="COLOR: #0000cc">}</SPAN> <SPAN
style="COLOR: #0000ff">while</SPAN>
0</FONT></SPAN></CODE></P></TD></TR></TBODY></TABLE></P>
<P><FONT color=#ff0000 size=3>使用do...while
结构来构造宏是标准 C 的惯用方法,它保证了扩展后的宏可在所有上下文环境中被作为一个正常的 C
语句执行。
<HR id=null>
</FONT>
<P></P>
<P><FONT color=#0000ff size=4><STRONG>使用 I/O
端口</STRONG></FONT></P>
<DIV>I/O 端口是驱动用来和许多设备之间的通讯方式。</DIV>
<DIV><FONT color=#0000ff size=3><STRONG>I/O
端口分配</STRONG></FONT></DIV><DIV在< FONT>
<DIV><FONT color=#0000ff
size=2>在尚未取得端口的独占访问前,不应对端口进行操作。<FONT color=#000000
size=1>内核提供了一个注册用的接口,允许驱动程序声明它需要的端口:</FONT></FONT></DIV>
<TABLE style="BORDER-COLLAPSE: collapse"
borderColor=#999999 cellSpacing=0 cellPadding=0
width="95%" bgColor=#f1f1f1 border=1>
<TBODY>
<TR>
<TD>
<P
style="MARGIN: 5px; LINE-HEIGHT: 150%"><CODE><SPAN
style="COLOR: #000000"><SPAN
style="COLOR: #0000cc">#</SPAN><SPAN
style="COLOR: #ff0000">include</SPAN> <SPAN
style="COLOR: #0000cc"><</SPAN>linux<SPAN
style="COLOR: #0000cc">/</SPAN>ioport<SPAN
style="COLOR: #0000cc">.</SPAN>h<SPAN
style="COLOR: #0000cc">></SPAN><BR><SPAN
style="COLOR: #0000ff">struct</SPAN> resource
<SPAN
style="COLOR: #0000cc">*</SPAN>request_region<SPAN
style="COLOR: #0000cc">(</SPAN><SPAN
style="COLOR: #0000ff">unsigned</SPAN> <SPAN
style="COLOR: #0000ff">long</SPAN> first<SPAN
style="COLOR: #0000cc">,</SPAN> <SPAN
style="COLOR: #0000ff">unsigned</SPAN> <SPAN
style="COLOR: #0000ff">long</SPAN> n<SPAN
style="COLOR: #0000cc">,</SPAN> <SPAN
style="COLOR: #0000ff">const</SPAN> <SPAN
style="COLOR: #0000ff">char</SPAN> <SPAN
style="COLOR: #0000cc">*</SPAN>name<SPAN
style="COLOR: #0000cc">)</SPAN><SPAN
style="COLOR: #0000cc">;</SPAN><SPAN
style="COLOR: #ff9900">/*告诉内核:要使用从 first 开始的 n
个端口,name 参数为设备名。若分配成功返回非
NULL,否则将无法使用需要的端口。*/</SPAN> <BR><SPAN
style="COLOR: #ff9900">/*所有的的端口分配显示在
/proc/ioports
中。若不能分配到需要的端口,则可以到这里看看谁先用了。*/</SPAN><BR><BR><SPAN
style="COLOR: #ff9900">/*当用完 I/O 端口集(可能在模块卸载时),
应当将它们返回给系统*/</SPAN><BR><SPAN
style="COLOR: #0000ff">void</SPAN>
release_region<SPAN
style="COLOR: #0000cc">(</SPAN><SPAN
style="COLOR: #0000ff">unsigned</SPAN> <SPAN
style="COLOR: #0000ff">long</SPAN> start<SPAN
style="COLOR: #0000cc">,</SPAN> <SPAN
style="COLOR: #0000ff">unsigned</SPAN> <SPAN
style="COLOR: #0000ff">long</SPAN> n<SPAN
style="COLOR: #0000cc">)</SPAN><SPAN
style="COLOR: #0000cc">;</SPAN> <BR><BR><SPAN
style="COLOR: #0000ff">int</SPAN>
check_region<SPAN
style="COLOR: #0000cc">(</SPAN><SPAN
style="COLOR: #0000ff">unsigned</SPAN> <SPAN
style="COLOR: #0000ff">long</SPAN> first<SPAN
style="COLOR: #0000cc">,</SPAN> <SPAN
style="COLOR: #0000ff">unsigned</SPAN> <SPAN
style="COLOR: #0000ff">long</SPAN> n<SPAN
style="COLOR: #0000cc">)</SPAN><SPAN
style="COLOR: #0000cc">;</SPAN> <BR><SPAN
style="COLOR: #ff9900">/*检查一个给定的 I/O
端口集是否可用,若不可用,
返回值是一个负错误码。不推荐使用*/</SPAN></SPAN></CODE></P></TD></TR></TBODY></TABLE>
<P><FONT color=#0000ff size=3><STRONG>操作 I/O
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -