เขียนระบบปฏิบัติการสำหรับ Raspberry Pi ใน C


19

ฉันพบบทเรียนการทำขนมอบแต่พวกเขาใช้ภาษาแอสเซมบลีเท่านั้น ฉันติดตามบทเรียนแรก แต่ฉันก็สงสัยว่าจะใช้ C แทนได้อย่างไร ฉันหมายความว่ามีเหตุผลที่พวกเขาคิดค้นภาษาระดับสูงกว่า ฉันพยายามรวบรวมรหัส C กับ.oไฟล์object ( ) โดยรวบรวม

.section .init
.globl _start
_start:

bl main

loop$:
b loop$

ไปยังไฟล์อ็อบเจ็กต์อื่นและเชื่อมโยงเข้าด้วยกันและเพื่อให้ได้kernel.imgมา จากนั้นฉันก็เปลี่ยนเคอร์เนลที่มีอยู่แล้วด้วยตัวเอง แต่มันไม่ได้รันโค้ด C รหัส C ที่ฉันเขียนควรเปิด OK LED แล้วกลับมา (จากนั้นมาloop$: b loop$) แต่ไฟ LED ตกลงจะกะพริบแบบสุ่มสองสามครั้งจากนั้นก็ปิดอยู่ นี่คือรหัส C ของฉัน:

int main(int argc, char ** argv) {
    volatile unsigned *gpioAddr = (volatile unsigned *)0x20200000;
    *(gpioAddr + 4) = 1 << 18;
    *(gpioAddr + 40) = 1 << 16;
    return 0;
}

ฉันจะใช้ C สำหรับการพัฒนาระบบปฏิบัติการบน Raspberry Pi ได้อย่างไร

ฉันสงสัยว่ามันเป็นข้อผิดพลาดในรหัส (แม้ว่าฉันจะเป็นแค่มือสมัครเล่น) ฉันรู้ว่าการตั้งค่า C อาจซับซ้อน แต่ฉันไม่ใช่คนแรกที่ทำสิ่งนี้ AFAIK ระบบปฏิบัติการที่โดดเด่นในปัจจุบันส่วนใหญ่ทั้งหมดเขียนด้วยภาษา C ดังนั้นจะต้องมีบทความอธิบายกระบวนการ ฉันจะมีความสุขมากกับรายการของขั้นตอนด้วยดังนั้นฉันสามารถ google สำหรับขั้นตอนเหล่านั้นและอาจถามคำถามที่กว้างกว่าเล็กน้อย

หมายเหตุ: แอสเซมบลี ARM เทียบเท่าของรหัส C ข้างต้นทำงานได้ดี มันเปิดไฟ LED (หลังจากกะพริบเล็กน้อย) ฉันคิดว่า (หวังว่า) ที่บ่งบอกว่า Raspberry Pi ของฉันดี


C ถูกออกแบบมาให้เป็นภาษาแอสเซมบลีแบบพกพาสำหรับ Unix ลีนุกซ์เขียนด้วยภาษา C, คุณสามารถประหยัดเวลาได้เล็กน้อยโดยดูที่วิธีการทำงาน
Thorbjørn Ravn Andersen

1
@ ThorbjørnRavnAndersenฉันคิดว่าฉันไม่ได้อ่านซอร์สของ Linux ลินุกซ์นั้นซับซ้อนกว่าสิ่งที่ฉันอยากรู้ดังนั้นการปิดบังส่วนที่น่าสนใจสำหรับฉัน
11684

1
อืม 'ติดสาย' LED สองสามดวง
11684

1
ขอบคุณ แต่ฉันต้องการทำสิ่งส่วนใหญ่ด้วยตัวเอง มันเป็นโครงการเรียนรู้
11684

1
ฉันต้องยอมรับว่าฉันไม่เคยเห็นคำถามเกี่ยวกับวิธีการเขียนระบบปฏิบัติการมาก่อน และมีคำตอบที่น่าสนใจ มันบ้าไปแล้ว ...
Piotr Kula

คำตอบ:


14

ฉันเขียนเคอร์เนลอย่างง่ายเมื่อหลายปีก่อนและรันบน 386 ฉันยังไม่ได้เขียนโปรแกรมโลหะเปลือยในปี แต่ในแง่กว้างคุณต้องเขียนรหัสประกอบที่จะ:

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

การตั้งค่าสแต็กเป็นเรื่องง่าย - ค้นหาหน่วยความจำบางส่วนที่ไม่ได้ใช้งานและโหลดที่อยู่ที่เคยลงทะเบียนใช้เป็นตัวชี้สแต็ก

ในรหัส C ของคุณคุณต้องเริ่มโครงสร้างข้อมูล OS เช่นพูลหน่วยความจำและตารางเธรด คุณจะไม่สามารถใช้ฟังก์ชันไลบรารี C - คุณจะต้องเขียนสิ่งนั้นเอง

หากคุณต้องการเขียนระบบมัลติทาสก์แบบง่ายคุณจะต้องเขียนชุดคำสั่งแอสเซมเบลอร์เพื่อบันทึกการลงทะเบียน CPU บนสแต็กและโหลดชุดค่าการลงทะเบียนที่แตกต่างจากสแต็กของเธรดอื่น และคุณจะต้องเขียน API เพื่อสร้างกระทู้ที่แตกต่างกัน


1
ยากที่จะเลือกระหว่างคำตอบนี้กับของ Georges Dupéron ฉันยอมรับอันนี้และมอบการโหวตให้กับอีกคนหนึ่ง
11684

13

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

  • _startสัญลักษณ์ย่อมเป็นหนึ่งที่ใช้เมื่อรวบรวมและเชื่อมโยงไฟล์ประกอบของคุณและไฟล์ของคุณ C (และที่main()ไม่ได้ถูกใช้แทน)
  • เมื่อโทรmain()คุณต้องใช้การประชุม C:
    • กดที่อยู่ของคำแนะนำหลังจากการโทรของคุณ (ที่อยู่ผู้ส่งซึ่งจะถูกใช้โดยreturnคำสั่งใน C)
    • ผลักดันข้อโต้แย้งสำหรับฟังก์ชั่น ในกรณีของคุณคุณสามารถกดสองค่า 32- บิต (ทั้งหมด 8 ไบต์), แต่เพื่อทำให้สิ่งต่าง ๆ ง่ายขึ้นคุณสามารถลบอาร์กิวเมนต์และมีint main() { ... }
    • อาจจองพื้นที่บนสแต็กสำหรับค่าส่งคืน
    • ฉันจำไม่ได้ว่าสิ่งใดที่ควรผลักดันสิ่งเหล่านี้
    • หากต้องการทราบว่าฟังก์ชั่น C คาดหวังอะไรอย่างแน่นอนให้ถอดแยกชิ้นส่วน ( objdump -S main.o) และดูว่ามันทำงานอย่างไรกับสแต็ก
  • หากคุณไม่เคารพการประชุมที่เรียกดังนั้นรหัสแอสเซมบลีที่สร้างโดยคอมไพเลอร์ C อาจยุ่งเกี่ยวกับที่อยู่ผู้ส่งคืนบนสแต็กและในกรณีของคุณคุณไม่ได้กดที่อยู่ผู้ส่งด้วยซ้ำ loop$สุ่มแทนที่จะไป

วิกิพีเดีย OSDevจะเป็นประโยชน์อย่างมาก Ressource - มันเกี่ยวข้องส่วนใหญ่กับการพัฒนา x86 แต่ข้อมูลส่วนใหญ่ยังคงใช้บังคับกับปี่ราสเบอร์รี่

ทรัพยากรเฉพาะของ raspberry-pi osdev เพิ่มเติม:

  • http://elinux.org/RaspberryPi_Osdev
  • https://github.com/hermanhermitage/videocoreivข้อมูลเกี่ยวกับชุดคำสั่งของ GPU ซึ่งกำลังดำเนินการลำดับการบู๊ตก่อนที่คุณจะkernel.imgเริ่มเล่น
  • https://github.com/christinaa/rpi-open-firmwareโครงการนี้มีวัตถุประสงค์เพื่อแทนที่ Blob ที่เป็นกรรมสิทธิ์ซึ่งใช้ในการบูต pi ก่อนที่คุณkernel.imgจะถูกดำเนินการ

ยากที่จะเลือกระหว่างคำตอบนี้กับสตีฟ ฉันให้คุณ upvote และยอมรับอีกคนหนึ่ง ฉันเสียใจที่ 5 ตัวแทนแตกต่างกัน
11684

OSDev วิกิพีเดียเป็นสิ่งที่ดี - และยังมีบางส่วนที่เฉพาะเจาะจงRasPiสิ่ง
เก่ง

2

ปัญหาหลักที่คุณอาจพบคือไลบรารี C และโค้ดอารัมภบท มันเริ่มต้นก่อนที่โค้ดของคุณจะเริ่มทำงานและตั้งค่าสแต็กฮีปและทำสิ่งอื่น ๆ ที่เป็นประโยชน์มากมาย อย่างไรก็ตามเมื่อคุณพยายามโปรแกรมหาโลหะเปลือยคุณไม่มี OS ที่ทำงานอยู่ด้านล่างและคุณควรหลีกเลี่ยงการเรียกใช้ฟังก์ชันเหล่านี้ ในการที่จะทำเช่นนั้นคุณจำเป็นต้องมีไลบรารี่ C เวอร์ชั่นดัดแปลงและ / หรือสัญลักษณ์สากลบางอันที่กำหนดหรือแทนที่ด้วยตัวคุณเอง กระบวนการนี้เกี่ยวข้องกับเรื่องเล็กน้อยนั่นเป็นเหตุผลว่าทำไมคน 'Baking Pi' จึงเลือกใช้ชุดประกอบสำหรับการสอน


ขอบคุณที่ตอบคำถามของฉัน (และขออภัยที่ตอบช้า) แต่ (แปลกใจ!) ฉันซื้อ pi ของฉันเพื่อเรียนรู้เกี่ยวกับสิ่งนั้น, บิตที่เกี่ยวข้องกับกระบวนการระดับต่ำ (ฉันไม่ควรทำเช่นนั้นบนเดสก์ท็อปราคาแพงที่มีความเสี่ยงที่จะทำลายไฟล์ส่วนบุคคล / อีเมล / ภาพถ่าย) คุณช่วยเพิ่มวิธีการตั้งค่ากองซ้อนหรือบทความ / บทช่วยสอน / ทรัพยากรบางอย่างอธิบายได้อย่างไร (และอะไรอีกที่ฉันอาจต้องใช้ C)
11684

2

ลองใช้สิ่งนี้แทน:

http://www.valvers.com/open-software/raspberry-pi/step01-bare-metal-programming-in-cpt1/

นอกจากนี้ประสบการณ์ x86 นั้นแตกต่างกันเล็กน้อย อาจใช้กับการเขียนโปรแกรม OS โลหะเปลือย ARM ทั่วไป แต่สำหรับ Pi ขออภัยมันคือ gpu ที่เริ่มต้นก่อนและติดตั้งก่อนบิตรหัส OS ของคุณ (?)


1
รายละเอียดเพิ่มเติมเล็กน้อยจะดีมากจะเกิดอะไรขึ้นถ้าลิงก์ในคำตอบของคุณแตก?
Darth Vader

มันยังมี แต่ฉันคิดว่าสำหรับผู้ที่มาที่นี่อาจ google "valves โลหะเปลือย" และดีกว่าลองชุด OSDEV (ที่จะได้รับข้าม dev หนึ่งที่ฉันพยายามอ่านฟอรั่มฉันโพสต์หนึ่งคุณสามารถลอง google "OSDEV ฟอรัมหกเดือนข้าม ")
Dennis Ng

ฉันรู้ว่านี่เป็นคำตอบเก่าสำหรับคำถามที่เก่ากว่านี้ แต่หน้านี้อยู่บน web.archive.orgในกรณีที่เกิดปัญหา
anonymoose

1

s-matyukevich/raspberry-pi-os

https://github.com/s-matyukevich/raspberry-pi-os

repo ที่ยอดเยี่ยมนี้ทำทั้งการบู๊ต C และเข้าสู่หัวข้อที่ซับซ้อน

นอกจากนี้ยังตรวจสอบว่าเคอร์เนล Linux ทำสิ่งต่างๆอย่างไรและใส่คำอธิบายประกอบรหัสเคอร์เนล Linux

ดูบทช่วยสอนแรกสำหรับการตั้งค่าแบบเรียบง่าย: https://github.com/s-matyukevich/raspberry-pi-os/tree/43f682d406c8fc08736ca3edd08a1c8e477c72b0/src/lesson01/src/lesson01

ฉันขอแนะนำอย่างยิ่ง

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