Ch9 Communicating with Hardware

Slides:



Advertisements
Similar presentations
现代电子技术实验 ——综合实验之单片机部分
Advertisements

什么是SOPC: SOPC是英文System On a Programmable Chip的缩写,称为片上可编程系统。SOPC将传统的EDA技术、计算机系统、嵌入式系统、数字信号处理等融为一体,综合了各自的优势,且在结构上形成一块芯片。 为什么用SOPC:SOPC是现代电子技术和电子系统设计的发展趋势,建立了电子系统设计的新模式。用户利用SOPC开发平台,自行设计高速、高性能的DSP处理器、特定功能的CPU及其外围接口电路,创建结构最为简洁的电子系统。
C语言程序设计 主讲教师 :张群燕 电话:
第一章 C语言概述 计算机公共教学部.
第一章 计算机基础知识 计算机的发展简史 1 计算机软件系统 6 计算机的定义和分类 2 微型计算机的组成 7 计算机的特点和用途 3
计算机组成原理 北京理工大学计算机科学工程系 赵清杰 北京理工大学计算机科学工程系.
编译原理上机实习
基于ARM和linux的开发 华中科技大学 武汉创维特 2017/3/20.
第四章 存储体系.
Chapter 6 時序.
计算机与信息技术应用基础 徐东雨 计算机中心
第一章 引论 1.1操作系统的概念 计算机系统: 计算机硬件 计算机软件 计算机硬件:运算器、控制器、存储器、输入设备和 输出设备
第一章 计算机基础知识 第一节 计算机概述 一、计算机的基本组成和工作原理 二、有关术语 三、计算机发展简史 四、微型计算机概述
Hardware Chen Ching-Jung
CH.2 Introduction to Microprocessor-Based Control
Xen基础架构安全性分析 云朋
資策會 南區資訊處 教育訓練中心 吳建興 個人電腦組裝 PC DIY 資策會 南區資訊處 教育訓練中心 吳建興
主讲教师:唐大仕 第5讲 计算机硬件 主讲教师:唐大仕
2.1 基本資料型別 2.2 變數 2.3 運算式與運算子 2.4 輸出與輸入資料 2.5 資料型別轉換 2.6 實例
Operating System Concepts 作業系統原理 Chapter 3 行程觀念 (Process Concept)
第 13 章 DNS 著作權所有 © 旗標出版股份有限公司.
第一章 C语言概述.
CH2 開發環境介紹 最簡單的互動設計 – Arduino一試就上手 孫駿榮、吳明展、盧聰勇.
第二章 C# 基础知识.
99(1)義守大學工讀職場技能精進訓練班 資訊工程系 林義隆 老師
补充内容 结构体 概述 定义结构体类型和定义结构体变量 结构体变量的引用 结构体变量的初始化 指针与结构体 用typedef定义类型的别名.
编译原理与技术 类型检查 2018/11/21 《编译原理与技术》-类型检查.
单片机原理与应用 C/C++在现代数字计算机上的实现.
5 Computer Organization (計算機組織).
第十一章 文件 文件概述 文件操作 文件操作实例 本章小结 作业: 练习:
SWITCH&7-SEG元件控制 嵌入式作業系統實作 11/17.
授课老师:龚涛 信息科学与技术学院 2018年3月 教材: 《Visual C++程序员成长攻略》 《C++ Builder程序员成长攻略》
第三章 C++中的C 面向对象程序设计(C++).
CH.8 硬體管理.
在專用的嵌入式板子運行 GNU/Linux 系統已經變得越來越流行。一個嵌入式 Linux 系統從軟體的角度看通常可以分為四個層次:
中国科学技术大学计算机系 陈香兰(0512- ) Autumn 2009
嵌入式系统的Boot Loader技术 陈文智 浙江大学计算机学院 2009年5月.
重點 資料結構之選定會影響演算法 選擇對的資料結構讓您上天堂 程式.
K60基础课程 02 首都师范大学物理系 王甜.
1.3 微型计算机的结构和工作原理.
第五章 C/C++及汇编语言的混合编程 5.1 ARM C/C++编译器 5.2 在C/C++程序中内嵌汇编指令
组员:吴迪&王柳杨&金虎&陈武荣&谭金柏
編譯程式設計 期末專題說明 V1.1 May 2004.
第1章 概述 本章要点: C语言程序结构和特点 C语言程序的基本符号与关键字 C语言程序的编辑及运行 学习方法建议:
Author:BobZhang Copy Right 2007
合泰半导体股份有限公司 技术讲座 - Holtek V3 C Compiler介绍 主讲人:王幼端 2017/06/15.
任务一:初识计算机 任务二:学习计算机中的信息表示 P /4/7.
Holtek C Compiler V3--advanced
(第2版).
8051單晶片 蘇恆生 老師.
微机原理与接口技术 西安邮电大学计算机学院 王忠民.
Chapter 7 掌控記憶體.
计算机系统结构(2012年春) ----存储层次: Cache基本概念
单片机原理与应用 主讲人:张荣刚 福建师范大学福清分校.
<编程达人入门课程> 本节内容 为什么要使用变量? 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ:
第二章 Java语法基础.
Chapter 7 掌控記憶體.
第六章 記憶體.
4-12 外部中斷 HT66F70A.
实验2 中断模拟实验.
第二章 类型、对象、运算符和表达式.
第二章 基本数据类型 ——数据的表示.
#include <iostream.h>
第二章 Java基本语法 讲师:复凡.
4-14 類比中斷 HT66F70A.
实验二:添加Linux系统调用及熟悉常见系统调用
第十二章 位运算.
Ch9 Communicating with Hardware
變數、資料型態、運算子.
Presentation transcript:

Ch9 Communicating with Hardware Linux Device Driver Ch9 Communicating with Hardware

Content I/O 埠 與 I/O 記憶體 使用 I/O 埠 使用數位 I/O 埠 I/O 暫存器與傳統記憶體 字串操作 暫停 I/O 平台相依性 使用數位 I/O 埠 並列埠的基本概念 short驅動程式

Content -cont. 使用 I/O 記憶體 直接映射記憶體 使用short 測試 I/O 記憶體 軟體映射的 I/O 記憶體 位於1MB以下的 ISA記憶體 isa_readb()與相關函式

I/O 埠 與 I/O 記憶體 幾乎每一種周邊裝置的控制,都是藉由 register 來達 成的,這些暫存器,可能在記憶體空間,也可能在 I/O 空間。 目前流行的周邊匯流排是以PC架構為模型;因此,即 使沒將 I/O 位址空間獨立出來的處理器,在存取這些 週邊裝置時,也必須”假裝”讀寫 I/O 埠。因此, Linux 虛構一組 I/O 埠存取架構。 一般認為,I/O 記憶區是比較適當的形式,他有下列 優點: 不需要用到特殊用途的 CPU 指令。 CPU core 對記憶體的存取效率相對於專用 I/O 指令而言較高。 在暫存器的分配及定址模式上,由編輯器產生存取記憶體的 程式碼有較自由的選擇。

I/O 埠 與 I/O 記憶體 直接映射記憶體 I/O 暫存器和RAM最大的差異,在於 I/O 操作有”副作用”: 存取記憶體只是改變目標的儲存值。 存取 I/O,目的不在於儲存值,許多控制是藉由”讀取”和“寫入”的 動作來改變裝置的狀態。 將原本施加於記憶體最佳化技術施(cache)加於 I/O 暫存器身上, 則無法產生 I/O 暫存器操作想要的“副作用”。 解決方法:在必須以原貌出現在硬體上的程式之間,加上記憶屏 障(memory barrier)。

I/O 埠 與 I/O 記憶體 memory barrier #include <linux/kernel.h> void barrier(void) 要求編譯器編譯出來的程式碼,被修改存在CPU暫存器的值,會確 實寫回記憶體: #include <asm/system.h> void rmb(void); void read_barrier_depends(void); void wmb(void); void mb(void); rmb()保證出現在barrier之前的讀取動作,都會在後續的任何讀取 動作之前如實完成。 wmb()保證寫出動作會被依序徹底完成。 mb() 保證 讀、寫動作都會落實執行。

I/O 埠 與 I/O 記憶體 void smp_rmb(void); void smp_read_barrier_depends(void); void smp_wmb(void); void smp_mb(void); 同前述函式,但只在支援SMP的system有作用 使用barrier的例子: writel(dev->registers.addr, io_destination_address); writel(dev->registers.size, io_size); writel(dev->registers.operation, DEV_READ); wmb( ); writel(dev->registers.control, DEV_GO); 前面三個writel都完成後,才會進行writel(dev-> …….)的動作。

I/O 埠 與 I/O 記憶體 某些平台容許「一次設值(atomic_t)」和「一個記憶體屏障」組成比較有 效率的執行單位,提供以下巨集: #define set_mb(var, value) do {var = value; mb( );} while 0 #define set_wmb(var, value) do {var = value; wmb( );} while 0 #define set_rmb(var, value) do {var = value; rmb( );} while 0

使用 I/O 埠 #include <linux/ioport.h> int check_region(unsigned long first, unsigned long n); struct resource *request_region(unsigned long first, unsigned long n,const char *name); void release_region(unsigned long start, unsigned long n); 大部分的硬體會區分 8-bit 16-bit 32-bit埠,因此不能像平常存許系統記憶 體那樣混用。

使用 I/O 埠 Linux核心中的<asm/io.h>定義以下用來存取I/O埠的內插函式: unsigned inb(unsigned port); void outb(unsigned char byte, unsigned port); 讀寫1-byte埠,某些平台上port定義成unsigned long,回傳值也因平台 而易。 unsigned inw(unsigned port); void outw(unsigned short word, unsigned port); 存取16-bits埠,在只支援byte I/O的平台不存在。 unsigned inl(unsigned port); void outl(unsigned longword, unsigned port); 存取32-bits埠,longword有可能被宣告成unsigned long或是unsigned int 64-bits port I/O 並不存在。

使用 I/O 埠 前述 I/O 函式也可以在user space使用,GUN定義在<sys/io.h>,但 必須遵守以下條件: 必須先使用ioperm() 或iopl()取得目標I/O埠的存取權,這兩個函式只能 用在Intel系統上。 程式本身要以root的身分呼叫ioerm()或iopl(),或是他的父行程之一必 須已經用root取得I/O埠的存取權。 範例程式:misc-progs/inp.c、misc-progs/outp.c

使用 I/O 埠 字串操作(string intructions):某些處理器提供特殊指令能 夠將依連串同等大小的bytes、word、longs讀入、寫出到一個 I/O埠。 字串操作的巨集原型: void insb(unsigned port, void *addr, unsigned long count); void outsb(unsigned port, void *addr, unsigned long count); 前者從port讀取count個位元組存入addr位址上的記憶體,後 者將addr位址上的count個位元組寫入port void insw(unsigned port, void *addr, unsigned long count); void outsw(unsigned port, void *addr, unsigned long count); 同上面的函式,以16-bits word為單位。 void insl(unsigned port, void *addr, unsigned long count); void outsl(unsigned port, void *addr, unsigned long count); 同上面的函式,以32-bits long word為單位。

使用 I/O 埠 暫停 I/O:當處理器與匯流排之間的傳輸率過快,導致裝置漏失一 些資料。 改採一些會暫停的函式來代替正常函式,其作用和用法與之前那些 正常I/O相同,只在名稱末端多了 _p字樣(e.g. inb_p() 、outb_p())

使用 I/O 埠 平台相依性 I/O 指令天生和處理器之間有著高度的相依性,因為他們控制著資 料如何進出處理器的細節;因此,程式中涉及I/O埠的部份,幾乎 都必須針對特定平台來設計,而沒有一體性的寫法。 各平台差異請詳見課本 p.243 ~ p.244

使用數位 I/O 埠 數位I/O埠最平常的具體形式,是一個單位元組寬的I/O位置,該位址 可能映射到記憶空間,但也可能有專屬的I/O空間。 並列埠的基本概念 依照PC標準規格每台可以配置兩個並列埠介面,第一個介面起始位置是 0x378,第二個是0x278。並列埠的基本模式是由三個8-bit埠構成;第一個 埠是雙向的資料暫存器,直接連到實體街頭的pin2 ~ pin9;第二埠是一個 唯讀的暫存器;第三埠是控制暫存器(能寫不能讀)。

使用數位 I/O 埠 並列埠各個位元的規格

使用數位 I/O 埠 short(Simple Hardware Operations and Raw Tests)驅動程式 short只能讀、寫在載入期指定的少數幾個 8-bits埠。 short驅動程式不會做任何有用的事情,只讓我們將I/O指令作用到指 定的埠。 不能用short存取已被其他驅動程式佔用的裝置。 short宗旨:在任何Linux平台測試任何可透過outb()和inb()來存取數 位I/O介面。

使用數位 I/O 埠 short本身操作- /dev/short0 是 I/O的基底位址8-bits管道,能 夠一次寫出或讀入8-bits資料。/dev/short1對應到base + 1, 以此類推到short7。 輸出動作 while (count--) { outb(*(ptr++), port); wmb( ); } #echo –n “any string” > /dev/short0 點亮LED燈,只有最後一個字元能夠被看到,因此加上-n選項,在 字串末端加上‘\n’。 讀入動作 outb()換成inb()。 讀出port 0x378的值: #dd if=/dev/short0 bs=1 count=1 | od –t x1 Memory barrier 確保動作不會被最佳化處理掉

使用數位 I/O 埠 short三種變形 /dev/short0 用前述的緊密迴圈 /dev/short0p使用outb_p() 和 inb_p() /dev/short0s使用字串函式

使用 I/O 記憶體 I/O 記憶體是性質類似於RAM的特殊區域,處理器可直接從其 匯流排存取特定的硬體裝置,意即,讀寫這些區域會產生“副 作用”。 本章只討論如何存取PCI和ISA記憶體。 基於8.1.1強調的額外顧慮,應避免使用直接指向I/O記憶體的指 標 裝置記憶體需要先配置才能使用(linux/ioport.h): struct resource *request_mem_region(unsigned long start, unsigned long len,char *name); 配置的記憶體列表於 /proc/iomem. void release_mem_region(unsigned long start, unsigned long len); int check_mem_region(unsigned long start, unsigned long len);

使用 I/O 記憶體 直接映射記憶體 保留部位記憶位址空間給I/O專用,這些I/O專區不受記憶體管理系統的 管制,也沒有任何虛擬位址會落在I/O專區的範圍內。 存取直接映射的I/O記憶區:用指標存取 unsigned int ioread8(void *addr); unsigned int ioread16(void *addr); unsigned int ioread32(void *addr); void iowrite8(u8 value, void *addr); void iowrite16(u16 value, void *addr); void iowrite32(u32 value, void *addr); 如果要存取一序列的資料(repeat): void ioread8_rep(void *addr, void *buf, unsigned long count); void ioread16_rep(void *addr, void *buf, unsigned long count); void ioread32_rep(void *addr, void *buf, unsigned long count); void iowrite8_rep(void *addr, const void *buf, unsigned long count); void iowrite16_rep(void *addr, const void *buf, unsigned long count); void iowrite32_rep(void *addr, const void *buf, unsigned long count);

使用 I/O 記憶體 讀寫一個block,用: unsigned readb(address); unsigned readw(address); unsigned readl(address); 這些巨集分別從I/O記憶體擷取8-bits、16-bits、32-bits資料值。 void writeb(unsigned value, address); void writew(unsigned value, address); void writel(unsigned value, address); 用於寫出8-bits、16-bits、32-bits資料值。 void memset_io(void *addr, u8 value, unsigned int count); void memcpy_fromio(void *dest, void *source, unsigned int count); void memcpy_toio(void *dest, void *source, unsigned int count); 這些函式將資料塊搬出、搬入I/O記憶體,類似C函式庫中的memcpy() 一樣。

使用 I/O 記憶體 使用short 測試 I/O 記憶體 Ports as I/O Memory 於載入期告訴它使用I/O記憶體,並將I/O region的起始位置告 訴它。 對short,存取I/O埠和I/O記憶體一樣,不過I/O記憶體沒有字 串操作;因此/dev/short0p /dev/short0s和/dev/short0操作是 一樣的。 Ports as I/O Memory 有些裝置使用I/O port,有些使用I/O Memory;兩者access的 方法不同,2.6版本提供: void *ioport_map(unsigned long port, unsigned int count); void ioport_unmap(void *addr); 使得作法更為簡便。

使用 I/O 記憶體 軟體映射的 I/O 記憶體 對於要存取I/O記憶體的軟體,必須要有一種辦法將虛 擬位址指向裝置:ioremap() #include <asm/io.h> void *ioremap(unsigned long phys_addr, unsigned long size); void *ioremap_nocache(unsigned long phys_addr, unsigned long size); 大多數平台上,其實做和ioremap()完全一樣。 void iounmap(void * addr); 如果使用的是完全映射的I/O位址,則ioremap()沒有作 用。

使用 I/O 記憶體 位於1MB以下的 ISA記憶體 指位於640KB ~ 1024KB範圍的的記憶體位址。 Silly模組(Simple Tool for Unloading and Printing ISA Data)。 Silly的任務是存取ISA記憶體,他必須把ISA的實體位址映射到核心 的虛擬位址(使用ioremap() )。 #define ISA_BASE 0xA0000 #define ISA_MAX 0x100000 /* for general memory access */ /* this line appears in silly_init */ io_base = ioremap(ISA_BASE, ISA_MAX - ISA_BASE);

使用 I/O 記憶體 Silly的作業方法: 存取/dev/sillyb (8-bits存取模式) case M_8: while (count) { *ptr = ioread8(add); add++; count--; ptr++; } break;

使用 I/O 記憶體 最後使用iounmap(io_base)恢復原狀。 存取/dev/sillyw和/dev/sillyl case M_32: while (count >= 4) { iowrite8(*(u32 *)ptr, add); add += 4; count -= 4; ptr += 4; } break; 存取/dev/sillycp,使用memcpy_*io() case M_memcpy: memcpy_fromio(ptr, add, count); 最後使用iounmap(io_base)恢復原狀。

使用 I/O 記憶體 isa_readb()與相關函式 先前介紹的每個函式,都有各自對等的isa_*()函式,讓我們可以存取ISA 記憶體而不必是先呼叫ioremap()。 不過這些函式將來可能會消失,盡量避免不用。

THE END~ Any question?