C में रास्पबेरी पाई के लिए OS लिखें


19

मुझे पहले से ही बेकिंग पाई ट्यूटोरियल मिल गए , लेकिन वे केवल असेंबली भाषा का उपयोग करते हैं । मैंने पहले पाठों का पालन किया, लेकिन मैं पहले से ही सोच रहा हूं कि इसके बजाय सी का उपयोग कैसे किया जाए। मेरा मतलब है, एक कारण है कि उन्होंने उच्च-स्तरीय भाषाओं का आविष्कार किया है। मैं सिर्फ एक वस्तु ( .o) फ़ाइल के लिए सी कोड संकलन की कोशिश की , संकलन

.section .init
.globl _start
_start:

bl main

loop$:
b loop$

किसी अन्य ऑब्जेक्ट फ़ाइल और उन्हें एक साथ जोड़ने और इसलिए प्राप्त करना kernel.img। मैंने फिर पहले से मौजूद कर्नेल को अपने साथ बदल दिया, लेकिन यह सी कोड को निष्पादित नहीं करता है। मेरे द्वारा लिखा गया सी कोड ओके एलईडी को चालू करना चाहिए और फिर वापस (फिर आता है loop$: b loop$)। लेकिन ओके एलईडी कुछ समय के लिए बेतरतीब ढंग से चमकती है और फिर बंद हो जाती है। यहाँ मेरा C कोड है:

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

मैं रास्पबेरी पाई पर ऑपरेटिंग सिस्टम के विकास के लिए C का उपयोग कैसे करूं?

मुझे संदेह है कि यह कोड में एक त्रुटि है (हालांकि मैं सिर्फ एक शौक़ीन हूं)। मुझे पता है कि सी स्थापित करना जटिल हो सकता है, लेकिन मैं ऐसा करने वाला पहला नहीं हूं। AFAIK, वर्तमान में सभी प्रमुख OS मुख्य रूप से C में लिखे गए हैं, इसलिए इस प्रक्रिया को समझाने वाला एक लेख होना चाहिए। मैं चरणों की एक सूची के साथ भी बहुत खुश होऊंगा, इसलिए मैं उन चरणों के लिए Google कर सकता हूं और शायद एक सवाल थोड़ा कम व्यापक पूछूं।

नोट: उपरोक्त C कोड के बराबर ARM असेंबली ठीक काम करती है। यह एलईडी (थोड़ी सी पलक के बाद) को चालू करता है। मुझे लगता है (आशा) जो इंगित करता है कि मेरा रास्पबेरी पाई ठीक है।


C को यूनिक्स के लिए पोर्टेबल असेंबली लैंग्वेज के लिए डिज़ाइन किया गया था। लिनक्स सी में लिखा है, आप यह देखकर बहुत समय बचा सकते हैं कि यह कैसे किया जाता है।
थोर्बोजर्न रेवन एंडरसन

1
@ ThorbjørnRavnAndersen मुझे लगता है कि मैं लिनक्स के स्रोत को पढ़ने के लिए नहीं हूं। लिनक्स जितना मैं जानना चाहता हूं उससे कहीं अधिक जटिल है, इस प्रकार मेरे लिए दिलचस्प टुकड़े को अस्पष्ट करना।
15:68 पर 11684

1
उम, कुछ एलईडी का 'वायर अप'।
11684

1
धन्यवाद, लेकिन मैं ज्यादातर चीजें खुद करना चाहता हूं। यह एक सीखने की परियोजना है।
11684

1
मुझे स्वीकार करना चाहिए कि मैंने ओएस लिखने के तरीके पर पहले कभी कोई सवाल नहीं देखा। और कुछ दिलचस्प जवाब हैं। यह बस दीवाना है ...
Piotr Kula

जवाबों:


14

मैंने वर्षों पहले एक बहुत ही सरल कर्नेल लिखा था, और इसे 386 पर चलाया था। मैंने वर्षों में नंगे धातु की प्रोग्रामिंग नहीं की है, लेकिन व्यापक शब्दों में आपको कुछ कोडांतरक कोड लिखने की आवश्यकता होगी:

  • बूट प्रक्रिया के दौरान निष्क्रिय व्यवधान
  • यदि Pi में मेमोरी कंट्रोलर है, तो आपको उसे सेट करना होगा
  • टाइमर टिक सेट करें
  • बाधा नियंत्रक कॉन्फ़िगर करें
  • एक स्टैक सेट करें ताकि आप सी कोड निष्पादित कर सकें

स्टैक सेट करना आसान है - ऐसी कुछ मेमोरी ढूंढें जो उपयोग नहीं की जा रही है, और उस पते को लोड करें जिसमें कभी रजिस्टर का उपयोग स्टैक पॉइंटर के रूप में किया जाता है।

अपने सी कोड में आपको ओएस डेटा संरचनाओं को मेमोरी पूल और थ्रेड टेबल की तरह इनिट करने की आवश्यकता है। आप सी लाइब्रेरी फ़ंक्शंस का उपयोग करने में सक्षम नहीं होंगे - आपको स्वयं उस सामान को लिखना होगा।

यदि आप एक साधारण मल्टीटास्किंग ओएस लिखना चाहते हैं, तो आपको स्टैक पर सीपीयू रजिस्टर को बचाने के लिए कुछ असेंबलर रूटीन लिखने होंगे, और दूसरे थ्रेड के स्टैक से रजिस्टर वैल्यू के एक अलग सेट को लोड करना होगा। और आपको अलग-अलग थ्रेड बनाने के लिए एपीआई लिखना होगा।


1
इस उत्तर और जॉर्जेस ड्यूप्रेन के बीच चयन करना मुश्किल है। मैंने इस एक को स्वीकार किया और दूसरे को उभार दिया।
11684

13

मैंने आपके कोड को गहराई से नहीं देखा है, लेकिन ऐसा लगता है कि आप सही रास्ते पर हैं। निश्चित करें कि:

  • _startप्रतीक वास्तव में जब संकलन और अपने विधानसभा फ़ाइल और अपने सी फ़ाइल को जोड़ने के लिए इस्तेमाल किया जाता है (और है कि main()बजाय इस्तेमाल नहीं किया है)
  • कॉल करते समय main(), आपको C कॉलिंग कन्वेंशन का उपयोग करने की आवश्यकता है:
    • अपने कॉल के बाद अनुदेश के पते को स्टैक पर रखें (वापसी पता, जिसका उपयोग returnसी में बयान द्वारा किया जाएगा )
    • फ़ंक्शन के लिए तर्क पुश करें। आपके मामले में आप दो 32-बिट मान (कुल 8 बाइट्स) को धक्का दे सकते हैं, लेकिन चीजों को सरल बनाने के लिए आप तर्कों को भी हटा सकते हैं और बसint main() { ... }
    • हो सकता है कि वापसी मूल्य के लिए स्टैक पर कुछ स्थान आरक्षित करें
    • मुझे याद नहीं है कि इन चीजों को किस क्रम में धकेला जाए
    • यह जानने के लिए कि सी फ़ंक्शन वास्तव में क्या उम्मीद करता है, इसे अलग कर दें ( objdump -S main.o) और देखें कि यह स्टैक में हेरफेर कैसे करता है।
  • यदि आप कॉलिंग कन्वेंशन का सम्मान नहीं करते हैं, तो सी कंपाइलर द्वारा उत्पन्न असेंबली कोड स्टैक पर रिटर्न एड्रेस के साथ छेड़छाड़ कर सकता है, और आपके मामले में आपने रिटर्न एड्रेस को धक्का भी नहीं दिया है, इसलिए रिटर्न निर्देश कहीं कूद जाएगा यादृच्छिक, के बजाय जाने के लिए loop$

OSDev विकि एक बहुत ही उपयोगी ressource होगा - यह मुख्य रूप से 86 विकास के साथ संबंध है, लेकिन सबसे अधिक जानकारी अभी भी रास्पबेरी पाई के लिए लागू है।

कुछ और रास्पबेरी-पी ओसदेव विशिष्ट संसाधन:

  • http://elinux.org/RaspberryPi_Osdev
  • जीपीयू के निर्देश सेट के बारे में https://github.com/hermanhermitage/videocoreiv जानकारी, जो आपके kernel.imgkicks के सामने बूट अनुक्रम का प्रदर्शन कर रहा है।
  • https://github.com/christinaa/rpi-open-firmware इस प्रोजेक्ट का उद्देश्य आपके kernel.imgनिष्पादित होने से पहले पीआई को बूटस्ट्रैप करने के लिए उपयोग की जाने वाली मालिकाना बूँद को बदलना है।

इस जवाब और स्टीव के बीच चयन करना मुश्किल है। मैंने तुम्हें एक वर दिया और दूसरे को स्वीकार किया। मुझे 5 प्रतिनिधि अंतर पर पछतावा है।
11684

OSDev विकी अच्छा है - और यहां तक कि कुछ विशिष्ट है RasPi सामान
वैली

2

आपके द्वारा सामना की जाने वाली मुख्य समस्या सी लाइब्रेरी और प्रस्तावना कोड है। अपने कोड को निष्पादित करने और स्टैक, ढेर को सेट करने और अन्य सहायक चीजों को करने से पहले यह शुरू हो जाता है। हालाँकि, जब आप नंगे धातु के लिए प्रोग्राम करने की कोशिश कर रहे हैं, तो आपके पास नीचे कोई ओएस नहीं है और आप इन कार्यों को करने से बचने के लिए बेहतर होगा। यह करने के लिए कि आपको C पुस्तकालयों और / या कुछ वैश्विक प्रतीकों के संशोधित संस्करणों की आवश्यकता है या उन्हें अपने स्वयं के साथ परिभाषित किया गया है। यह प्रक्रिया थोड़ी सी शामिल है, इसीलिए 'बेकिंग पाई' लोगों ने अपने ट्यूटोरियल के लिए असेंबली का उपयोग करने के लिए चुना।


मेरे सवाल का जवाब देने के लिए धन्यवाद (और इतनी देर से जवाब देने के लिए खेद है)। लेकिन (आश्चर्य!) मैंने अपने पीआई को बस उस बारे में जानने के लिए खरीदा, जिसमें निम्न स्तर की प्रक्रियाएं शामिल हैं (मैं ऐसा व्यक्तिगत डेस्कटॉप / मेल / फोटो को नष्ट करने के जोखिम वाले महंगे डेस्कटॉप पर नहीं करता हूं)। क्या आप कृपया जोड़ सकते हैं कि मैंने कैसे स्टैक सेट किया है, या एक लेख / ट्यूटोरियल / कुछ संसाधन जो यह समझा रहे हैं? (और मुझे सी चलाने के लिए और क्या चाहिए)।
11684

2

इसके बजाय यह प्रयास करें:

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

साथ ही, x86 का अनुभव थोड़ा अलग है। यह सामान्य एआरएम नंगे धातु ओएस प्रोग्रामिंग के लिए लागू हो सकता है। लेकिन पाई के लिए, खेद है कि यह पहली बार शुरू होने वाला जीपीयू है और आपके ओएस (?) कोड से पहले काफी सेट है।


1
थोड़ा और विस्तार बहुत अच्छा होगा, अगर आपके उत्तर की लिंक टूट जाए तो क्या होगा?
डार्थ वादेर

यह अभी भी वहाँ है, लेकिन मैं उन लोगों के लिए सोचता हूं जो यहां आते हैं, Google "वाल्व नंगे धातु" और बेहतर कोशिश कर सकते हैं OSDEV श्रृंखला (पार करने के लिए एक के रूप में मैं संघर्ष किया, मंच पढ़ा, मैं एक पोस्ट आप Google "OSDEV की कोशिश कर सकते हैं" मंच छह महीने पार ")
डेनिस एनजी

मुझे पता है कि यह एक पुराने प्रश्न का भी पुराना उत्तर है, लेकिन पेज web.archive.org पर है , यदि यह नीचे जाता है।
अनाम

1

s-matyukevich/raspberry-pi-os

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

यह भयानक रेपो दोनों सी बूटस्ट्रैपिंग करता है, और बहुत जटिल विषयों में जाता है।

इसके अलावा, यह देखता है कि लिनक्स कर्नेल कैसे काम करता है, और लिनक्स कर्नेल कोड को एनोटेट करता है।

न्यूनतावादी सेटअप के लिए पहले ट्यूटोरियल पर एक नज़र डालें: https://github.com/s-matyukevich/raspberry-pi-os/tree/43f682d406c8fc08736ca3edd0a1c8e477c72b0/src/lesson01/src

मैं इसकी पुरजोर सलाह देता हूँ।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.