การระบุที่อยู่ I / O ของหน่วยความจำทำงานอย่างไร


29

การระบุที่อยู่ I / O ของหน่วยความจำทำงานอย่างไร

ฉันกำลังพยายามที่จะเข้าใจตัวอย่างที่ให้มาI2S: ทุกคนทำงานได้หรือไม่ .

การกำหนดค่านาฬิกา:

#define BCM2708_PERI_BASE        0x20000000
#define CLOCK_BASE               (BCM2708_PERI_BASE + 0x101000) /* Clocks */

ก่อนจะจับคู่รหัสอย่างนั้น ...

clk_map = (unsigned char *)mmap(
      (caddr_t)clk_mem,
      MAP_BLOCK_SIZE,
      PROT_READ|PROT_WRITE,
      MAP_SHARED|MAP_FIXED,
      mem_fd,
      CLOCK_BASE
   );

ถ้าอย่างนั้นมันก็ทำอะไร ...

 // Always use volatile pointer!
   clk = (volatile unsigned *)clk_map;

และเมื่อมีการอ้างอิงจะมีส่วนเพิ่มเติมแปลก ๆ ของ 0x26 & 0x27 นั่นคืออะไร?

 printf("Disabling I2S clock\n");
 *(clk+0x26) = 0x5A000000;
 *(clk+0x27) = 0x5A000000;

 usleep(10);

 printf("Confiure I2S clock\n");
 *(clk+0x26) = 0x5A000001;
 *(clk+0x27) = 0x5A000000 | 3<<12 | 1<<9; // divider: 3.125==0b11.001

 usleep(10);
 printf("Enabling I2S clock\n");
 *(clk+0x26) = 0x5A000011;

ดูที่แผ่นข้อมูลฉันสามารถดูว่าพวกเขาได้รับค่าเหล่านี้เช่นที่อยู่พื้นฐาน แต่ฉันพยายามที่จะเข้าใจคนอื่น ๆ มันถูกCLOCK_BASEกำหนดแล้วและเกิดอะไรขึ้น?


1
นี่อาจเหมาะที่สุดสำหรับ StackOverflow แม้ว่ามันจะเกี่ยวข้องกับ RPi คุณจะมีแนวโน้มที่จะได้คำตอบสำหรับคำถามการเขียนโปรแกรมที่นั่น
Jivings

4
อาจ แต่ฉันรู้สึกว่ามันเป็นคำถามทั่วไปที่เกี่ยวกับการเขียนโปรแกรม Pi รวมการตีความแผ่นข้อมูลและฮาร์ดแวร์ Pi ลองดูว่ามันได้รับข้อมูลที่ดีบ้างไหม
หูสุนัข

ถูก มาดูกันว่ามันจะเป็นอย่างไร :)
Jivings

1
ฉันไม่คิดว่าสิ่งนี้จะทำได้ดีเกินไปกับ Stack Overflow - เป็นผู้เชี่ยวชาญที่น่ารักและมีแนวโน้มว่าจะได้รับความสนใจจากผู้เชี่ยวชาญมากขึ้นที่นี่
เฟล็กโซ

คำตอบ:


18

ในคอมพิวเตอร์คุณเขียนไปยัง 'ที่อยู่หน่วยความจำ' ที่ระบุ ที่อยู่นี้ได้รับการยอมรับจากระบบว่าเป็นที่อยู่ของฮาร์ดแวร์และฮาร์ดแวร์ที่เหมาะสมได้รับหรือส่งค่าที่เหมาะสม

ระบบฮาร์ดแวร์ส่วนใหญ่มีรีจิสเตอร์ต่าง ๆ มากมายที่สามารถตั้งค่าหรืออ่านได้ บางคนอาจมีบางคนอาจมีบางคน การลงทะเบียนเหล่านี้จะถูกจัดกลุ่มเป็นช่วงต่อเนื่อง ตัวชี้พื้นฐานชี้ไปที่จุดแรกในช่วงและคุณเขียนถึงเช่นพอร์ตที่สองที่มี base_pointer + 1 คุณไม่จำเป็นต้องเขียนโดยตรงไปยังตัวชี้ แต่การใช้ออฟเซ็ตจะทำให้การทำงานง่ายขึ้น

Raspberry Pi ตระหนักถึงการลงทะเบียนฮาร์ดแวร์ที่หลากหลายตามที่อยู่ 0x20000000 ช่วงของการลงทะเบียนที่ระบบควบคุมนาฬิกาเข้าถึงได้จาก BCM2708_PERI_BASE + 0x101000 รีจิสเตอร์ที่ควบคุมนาฬิกา I2S คือการลงทะเบียน 38 และ 39 ในบล็อกนั้นซึ่งเขียนขึ้นโดยใช้ BCM2708_PERI_BASE + 0x101000 + 0x26 และ 0x27

คุณไม่สามารถเปลี่ยนค่านาฬิกาได้เพียงปิดการใช้งานนาฬิกาเปลี่ยนค่าและเริ่มใหม่

หากคำตอบนี้ธรรมดาเกินไปฉันขอโทษ ในกรณีนี้คำถามของคุณไม่ยอมใครง่ายๆโชคดีจริงๆ คุณอาจพบว่าลิงค์นี้มีประโยชน์

อัปเดต: เหตุใดจึงใช้ mmap และไม่เขียนลงในหน่วยความจำโดยตรง

เมื่อโปรแกรมทำงานที่อยู่หน่วยความจำที่โปรแกรมคิดว่าไม่ใช่ที่อยู่จริงโปรแกรมเหล่านั้นจะถูกแมปไปยังที่อยู่จริงโดยผู้จัดการหน่วยความจำ สิ่งนี้จะหยุดโปรแกรมหนึ่งไม่ให้ส่งผลกระทบต่อโปรแกรมอื่น สองกระบวนการสามารถอ่านและเขียนไปยังที่อยู่ของตนเอง 1234 อย่างมีความสุขอย่างสมบูรณ์และผู้จัดการหน่วยความจำจะแยกสองตำแหน่งอย่างสมบูรณ์

พอร์ตฮาร์ดแวร์อย่างไรก็ตามเป็นที่อยู่ทางกายภาพที่แน่นอน แต่คุณไม่สามารถเขียนถึงพวกเขาโดยตรงเพราะผู้จัดการหน่วยความจำจะนำที่อยู่ของคุณและแมปไปยังพื้นที่หน่วยความจำส่วนตัวของคุณ

บน Linux / dev / mem เป็น ' ไฟล์อุปกรณ์ตัวอักษรที่เป็นรูปภาพของหน่วยความจำหลักของคอมพิวเตอร์ '

ถ้าคุณเปิดไฟล์แบบนี้คุณจะสามารถอ่านและเขียนมันได้เหมือนไฟล์ ในตัวอย่าง mem_fd ที่ให้มาเป็นตัวจัดการไฟล์ที่เป็นผลมาจากการเปิด / dev / mem

อีกระบบที่สามารถทำให้ชีวิตง่ายขึ้นมากคือความสามารถในการแมปไฟล์ไปยังหน่วยความจำและเขียนลงในหน่วยความจำ ดังนั้นหากคุณมีไฟล์ที่คุณต้องการอ่านหรือเขียนบิตเฉพาะที่แตกต่างกันแล้วแทนที่จะย้ายตัวชี้ไฟล์ไปข้างหน้าหรือข้างหลังคุณสามารถแมปไฟล์นั้นไปยังตำแหน่งในหน่วยความจำแล้วเขียนลงโดยตรงราวกับว่ามันเป็นหน่วยความจำ

ดังนั้นในตัวอย่างนี้รหัสกำลังสร้างตัวจัดการหน่วยความจำกายภาพราวกับว่ามันเป็นไฟล์บนดิสก์แล้วขอให้ระบบรักษามันราวกับว่ามันเป็นหน่วยความจำ ค่อนข้างซับซ้อน แต่จำเป็นเพื่อให้รอบตัวจัดการหน่วยความจำเสมือนและเขียนไปยังที่อยู่ทางกายภาพจริง มูลค่า 0x20000000 ดูเหมือนว่าเป็นปลาเฮอริ่งแดง รหัสกำลังเสนอที่อยู่นี้ว่าเป็นคำใบ้ระบบไม่จำเป็นต้องแมป / dev / mem ที่นี่แม้ว่าอาจเป็นไปได้ โดยปกติแล้วค่า null จะถูกส่งผ่านและระบบจะแม็พหมายเลขอ้างอิงไฟล์กับที่อยู่ใด ๆ ที่คิดว่าดีที่สุด

ตอนนี้หน่วยความจำกายภาพถูกแมปกับกระบวนการหน่วยความจำเสมือนจริงและอ่านและเขียนตามที่คุณคาดหวัง

อ้างอิง:

http://www.kernel.org/doc/man-pages/online/pages/man2/mmap.2.html

http://www.raspberrypi.org/phpBB3/viewtopic.php?f=44&t=8496&p=104359

https://superuser.com/questions/71389/what-is-dev-mem


ฉันยังมีคำถามสองสามข้อ: ทำไมพวกเขาถึง mmap ทำไมไม่เพียงแค่เข้าถึงหน่วยความจำโดยตรง
อเล็กซ์แชมเบอร์เลน

@AlexChamberlain เนื่องจากโค้ดทำงานบน linux ดังนั้นคุณจึงไม่สามารถเข้าถึงหน่วยความจำได้โดยตรงเนื่องจากแต่ละกระบวนการได้รับพื้นที่หน่วยความจำเสมือนของตัวเอง อย่างไรก็ตามหนึ่งสามารถเปิดและ mmap / dev / ข่าวจะได้รับการเข้าถึงโดยตรงไปยังหน่วยความจำกายภาพ
Nos

1

@AlexChamberlain นี่เป็นเพราะโครงสร้างระบบปฏิบัติการ คุณสามารถไปได้โดยไม่ต้องmmapมีการประกาศการเพจดังนั้นจึงไม่มีการเข้าถึงโดยตรง ในโหมดเคอร์เนลคุณสามารถไปได้โดยไม่ต้องโดยยกตัวอย่างเช่นการใส่ขับรถของคุณเป็นเคอร์เนลโมดูลที่มีความจำเป็นในการmmap mmapนอกจากนี้ในกรณีที่ง่ายที่สุดของระบบปฏิบัติการที่ไม่มีหน่วยความจำตารางเพจที่คุณสามารถเข้าถึงได้โดยไม่ต้องใช้mmapทั้ง การเข้าถึงที่อยู่ทางกายภาพโดยตรง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.