Linux io内存存在的意义~
今天是母親節,首先祝各位讀者的母親節日快樂,祝你們的母親年輕健康。母親節是一個亙古的話題,我本來想寫個文章,但是想起來這周就一個周末,要花點時間陪下家人,昨天我們老大開會,特別說了,有時間多陪陪家人,我腦子一轉,今天就一直陪著楠哥各種玩。
晚上回來看看筆記,寫了這個技術文章,ioremap是一個屬于被遺忘的技術知識點,可能我做Android 驅動沒用上,也就疏忽了,像內核通知鏈一些冷門的技術,還偶爾用一下。
內存管理是一個經久不衰的話題,從段式管理到頁式管理已經過去很久了,頁式管理也已經有了好長好長時間了,使用Linux內核的操作系統已經從更新了很多不同的版本。
不同的CPU體系對外設IO端口物理地址的編址方式也不同,分為I/O映射方式(I/O-mapped)和內存映射方式(Memory-mapped)。
以X86為例:X86為外設專門實現有單獨的地址空間,可以稱為「I/O地址空間」或「I/O端口空間」,這個是獨立與CPU和RAM物理地址空間,所有外設的IO端口均在這一空間。CPU通過設立專門的IN和OUT指令來訪問這一空間中的地址單元(即I/O端口),這就是所謂的“I/O映射方式”(I/O-mapped)。和RAM物理地址空間相比,I/O地址空間通常都比較小,如x86 CPU的I/O空間就只有64KB(0-0xffff)。這是「I/O映射方式」的一個主要缺點,你可以通過cat /proc/ioports去查看,IO port空間的地址資源分配情況是以樹狀結構顯示。這個源于x86平臺的設計思想,目前基本不用了,獲取這些資源的函數接口如request_region和ioremap。
像用戶空間一樣,內核也是通過頁表訪問內存,很多人對頁表理解不是很透徹,你要是說他復雜也是非常復雜,但是你說要是簡單也很簡單,可以理解成一個圖書的目錄,有了這個目錄,就可以知道什么內存地址存放了什么東西,以后要是想存新的東西進去,就在原來的目錄表里面進行更新。
但是我們使用的外設,比如是一個光感傳感器,我們需要控制這個光感傳感器,那就需要讀寫這個光感傳感器的I2C寄存器,如果內核代碼需要像訪問內存一樣來訪問這個光感設備呢?我們這時候就需要首先設置一個適當的內核頁表映射。
這時候我們就需要使用 ioremap()這個函數,經過這個函數還衍生了其他很多變種函數,我不知道為什么要用變種這個詞,如果有其他詞語可以留言一起討論下,畢竟一次好的詞語可以加深我們的印象。
具體可以看代碼arch/arm/mm/ioremap.c 里面有很多相近似的函數。函數參數含義
//?功能:將物理地址映射為虛擬地址 //?參數1:需要映射的物理地址 //?參數2:需要映射的地址長度 //?返回值:該函數返回映射后的內核虛擬地址(3G-4G). 接著便可以通過讀寫該返回的內核虛擬地址去訪問之這段I/O內存資源。簡單的實例代碼
void?led_on(void) {void?*reg_base;unsigned?int?temp;?reg_base?=?ioremap(0x1212,?4);temp?=?__raw_readl(reg_base);?temp?&=?~(0xff<<12);temp?|=?(0x11<<12);__raw_writel(temp,?reg_base); }#但是內核沒幾個地方用這個函數
我在內核里面搜了下,這個函數在內核里面并沒有幾個地方用到的。特別是我們最近做MTK方案和RK方案,里面的觸摸屏驅動下面沒使用到。但是音頻platform部分卻還有使用的地方。
用了一個新的轉換方式
?/*?ioremap?to?BT?HW?register?base?address?*/BTSYS_PKV_BASE_ADDRESS?=?(void?*)btsys_pkv_physical_base;BTSYS_SRAM_BANK2_BASE_ADDRESS?=?(void?*)btsys_sram_bank2_physical_base;bt_hw_REG_PACKET_R?=?BTSYS_PKV_BASE_ADDRESS?+?cvsd_mcu_read_offset;bt_hw_REG_PACKET_W?=?BTSYS_PKV_BASE_ADDRESS?+?cvsd_mcu_write_offset;bt_hw_REG_CONTROL?=?BTSYS_PKV_BASE_ADDRESS?+?cvsd_packet_indicator;pr_debug("[BTCVSD?probe]?BTSYS_PKV_BASE_ADDRESS?=?%p?BTSYS_SRAM_BANK2_BASE_ADDRESS?=?%p\n",BTSYS_PKV_BASE_ADDRESS,?BTSYS_SRAM_BANK2_BASE_ADDRESS);return?snd_soc_register_platform(&pdev->dev,?&mtk_btcvsd_rx_soc_platform);/*使用*/kal_int32?i;kal_uint16?pv;kal_uint8?*pSrc;kal_uint8?*pPacketBuf;unsigned?long?flags;unsigned?long?connsys_addr_rx,?ap_addr_rx;LOGBT("%s(+)?btsco.pRX->iPacket_w=%d\n",?__func__,?btsco.pRX->iPacket_w);connsys_addr_rx?=?*bt_hw_REG_PACKET_R;ap_addr_rx?=?(unsigned?long)BTSYS_SRAM_BANK2_BASE_ADDRESS?+?(connsys_addr_rx?&?0xFFFF);LOGBT("%s?connsys_addr_rx=0x%lx,ap_addr_rx=0x%lx\n",__func__,?connsys_addr_rx,?ap_addr_rx);pSrc?=?(kal_uint8?*)ap_addr_rx;LOGBT("%s?uPacketLength=%d,uPacketNumber=%d,?btsco.uRXState=%d\n",__func__,?uPacketLength,?uPacketNumber,?btsco.uRXState);AudDrv_BTCVSD_DataTransfer(BT_SCO_DIRECT_BT2ARM,?pSrc,?btsco.pRX->TempPacketBuf,uPacketLength,?uPacketNumber,?btsco.uRXState);LOGBT("%s?AudDrv_BTCVSD_DataTransfer?DONE!!!,uControl=0x%x,uLen=%d\n",?__func__,?uControl,?uLen);#查看系統當前的內存映射
/proc/iomem這個文件記錄的是物理地址的分配情況,記得要查看需要使用root權限。這些地址范圍是通過 requset_mem_region 函數申請得到的。
weiqifa0@weiqifa-System-Product-Name:~$?sudo?cat?/proc/iomem [sudo]?password?for?weiqifa0: 00000000-00000fff?:?Reserved 00001000-00057fff?:?System?RAM 00058000-00058fff?:?Reserved 00059000-0009efff?:?System?RAM 0009f000-000fffff?:?Reserved000a0000-000bffff?:?PCI?Bus?0000:00000c0000-000cffff?:?Video?ROM000f0000-000fffff?:?System?ROM 00100000-b77eefff?:?System?RAM b77ef000-b7828fff?:?ACPI?Tables b7829000-b7bc9fff?:?System?RAM b7bca000-b7bcafff?:?ACPI?Non-volatile?Storage b7bcb000-b7bcbfff?:?Reserved b7bcc000-c492efff?:?System?RAM c492f000-c61b9fff?:?Reserved c61ba000-c61cefff?:?ACPI?Tables c61cf000-c62ccfff?:?System?RAM c62cd000-c65f4fff?:?ACPI?Non-volatile?Storage c65f5000-c7795fff?:?Reserved c7796000-c77fefff?:?Unknown?E820?type c77ff000-c77fffff?:?System?RAM c7800000-c7ffffff?:?Reserved c8000000-f7ffffff?:?PCI?Bus?0000:00c8000000-c81fffff?:?PCI?Bus?0000:05c8200000-c83fffff?:?PCI?Bus?0000:05e0000000-efffffff?:?PCI?Bus?0000:01e0000000-efffffff?:?0000:01:00.0ioports主要顯示IO端口的地址范圍,使用request_region( )分配I/O端口地址范圍會顯示在這里。
weiqifa0@weiqifa-System-Product-Name:~$?sudo?cat?/proc/ioports 0000-0cf7?:?PCI?Bus?0000:000000-001f?:?dma10020-0021?:?pic10040-0043?:?timer00050-0053?:?timer10060-0060?:?keyboard0064-0064?:?keyboard0070-0077?:?rtc00080-008f?:?dma?page?reg00a0-00a1?:?pic200c0-00df?:?dma200f0-00ff?:?fpu00f0-00f0?:?PNP0C04:000290-029f?:?pnp?00:0003f8-03ff?:?serial0680-069f?:?pnp?00:020800-087f?:?pnp?00:03 0cf8-0cff?:?PCI?conf1 0d00-ffff?:?PCI?Bus?0000:00164e-164f?:?pnp?00:021800-18fe?:?pnp?00:021800-1803?:?ACPI?PM1a_EVT_BLK1804-1805?:?ACPI?PM1a_CNT_BLK1808-180b?:?ACPI?PM_TMR1850-1850?:?ACPI?PM2_CNT_BLK1854-1857?:?pnp?00:051880-189f?:?ACPI?GPE0_BLK2000-2fff?:?PCI?Bus?0000:05d000-dfff?:?PCI?Bus?0000:04d000-d0ff?:?0000:04:00.0e000-efff?:?PCI?Bus?0000:01e000-e0ff?:?0000:01:00.0f000-f01f?:?0000:00:1f.4f020-f03f?:?0000:00:17.0f020-f03f?:?ahcif040-f043?:?0000:00:17.0f040-f043?:?ahcif050-f057?:?0000:00:17.0f050-f057?:?ahcife00-fefe?:?pnp?00:08ffff-ffff?:?pnp?00:02ffff-ffff?:?pnp?00:02ffff-ffff?:?pnp?00:02 weiqifa0@weiqifa-System-Product-Name:~$#總結
ioremap 這些曾經用起來很不錯,或者說是設計者設計的時候,覺得很不錯的東西,現在突然被遺忘,我認為很大程度是因為設計的時候允許的地址范圍太小,也就是因為太小,要加新的東西總是畏首畏尾。
? 回復「?籃球的大肚子」進入技術群聊
回復「1024」獲取1000G學習資料
PS:想加入技術群的同學,加了我好友后,就給我發「籃球的大肚子」這句話,有可能機器人打瞌睡,可以多發幾次,不要發與技術無關的消息或者推廣。
總結
以上是生活随笔為你收集整理的Linux io内存存在的意义~的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ubuntu下载linux源码
- 下一篇: Linux 僵尸进程可以被杀死吗?