2013-05-08 9 views
10

मैं एक हाथ माइक्रोप्रोसेसर पर प्रोग्रामिंग कर रहा हूं और यूएआरटी के माध्यम से प्रिंट स्टेटमेंट का उपयोग करके डीबग करने की कोशिश कर रहा हूं। मैं सिर्फ डीबगिंग के लिए stdlibs जोड़ना नहीं चाहता हूं। stdio.h/iostream.h के बिना कंसोल पर प्रिंट करने का कोई तरीका है? क्या मेरे लिए अपना खुद का printf() लिखना संभव है?क्या यह संभव है बिना stdlibs के कंसोल को लिखना? सी/सी ++

वैकल्पिक रूप से मैं इसे डीएमए नियंत्रक का उपयोग करके और सीधे यूएआरटी पर लिख सकता हूं। हालांकि मैं इससे बचना चाहता हूं कि यह संभव है। अंतर्निहित टेस्ट फ़ंक्शन "इको" या "रिमोट लूप-बैक" का उपयोग करके मुझे पता है कि मेरे पास UART ठीक से कॉन्फ़िगर किया गया है।

+2

हाँ, यह संभव है - आप अपने स्वयं के उत्पादन दिनचर्या लिखना एक छोटे से स्टैंड-अलोन आंशिक printf() कार्यान्वयन मिल जाए, या एक minimimal एम्बेडेड libc से इन कार्यों को सक्षम करने के लिए आवश्यक बैक-एंड समर्थन लिख सकते हैं (संभवतः आपके टूलचेन के साथ शामिल) अपने प्लेटफॉर्म पर चलाने के लिए। –

+0

धन्यवाद। मैंने सुना है कि एक एम्बेडेड libc के रूप में newlib ठीक काम करता है। हालांकि मैं पहले आंशिक printf() की तलाश करूंगा। – Sam

+0

@ChrisStratton: यह ओएस पर प्रभावी ढंग से निर्भर करता है। यह संभव है कि मूल ओएस दिनरेखा मानक पुस्तकालय _are_। –

उत्तर

9

संक्षिप्त उत्तर: हां, यह आपके दोनों समाधानों को पूरी तरह से संभव है।

यदि आप सभी डेटा प्रकारों और प्रारूपों का समर्थन करना चाहते हैं तो printf फ़ंक्शन काफी जटिल है। लेकिन ऐसा कुछ लिखना मुश्किल नहीं है जो कुछ अलग-अलग अड्डों में एक स्ट्रिंग या एक पूर्णांक को आउटपुट कर सके (अधिकांश लोगों को केवल दशमलव और हेक्स की आवश्यकता होती है, लेकिन ऑक्टेटल संभवतः दशमलव और हेक्स होने पर कोड की एक और 3-4 पंक्तियों को जोड़ता है)।

आमतौर पर, printf इस तरह लिखा है:

int printf(const char *fmt, ...) 
{ 
    int ret; 
    va_list args; 

    va_start(args, fmt) 
    ret = do_xprintf(outputfunc, NULL, fmt, args); 
    va_end(args); 
    return ret; 
} 

और फिर do_xprintf() करता है सभी कड़ी मेहनत के सभी संस्करणों (printf, sprintf, fprintf, आदि)

int do_xprintf(void (*outputfunc)(void *extra, char c), void *extra, const char *fmt, va_list args) 
{ 
    char *ptr = fmt; 
    while(1) 
    { 
     char c = *ptr++; 

     if (c == '%') 
     { 
      c = *ptr++; // Get next character from format string. 
      switch(c) 
      { 
       case 's': 
        char *str = va_arg(args, const char *); 
        while(*str) 
        { 
         count++; 
         outputfunc(extra, *str); 
         str++; 
        } 
        break; 
       case 'x': 
        base = 16; 
        goto output_number; 

       case 'd': 
        base = 10; 
     output_number: 
        int i = va_arg(args, int); 
        // magical code to output 'i' in 'base'. 
        break; 

       default: 
        count++; 
        outputfunc(extra, c); 
        break; 
     } 
     else 
      count++; 
      outputfunc(extra, c); 
    } 
    return count; 
}     

के लिए अब, सभी आपको उपर्युक्त कोड के कुछ बिट्स भरना होगा और outputfunc() लिखना होगा जो आपके सीरियल पोर्ट पर आउटपुट करता है।

ध्यान दें कि यह किसी न किसी प्रकार का स्केच है, और मुझे यकीन है कि कोड में कुछ बग हैं - और यदि आप फ़्लोटिंग पॉइंट या "चौड़ाई" का समर्थन करना चाहते हैं, तो आपको थोड़ा और काम करना होगा ...

(अतिरिक्त पैरामीटर पर ध्यान दें - एक FILE * के उत्पादन के लिए है कि filepointer होगा, sprintf के लिए, आप बफर और स्थिति बफर में, या कुछ इस तरह के लिए एक ढांचा पारित कर सकते हैं)

+0

बहुत बहुत धन्यवाद। मैं उन कुछ लोगों में से एक हूं जिन्हें केवल दशमलव/हेक्स की आवश्यकता है। मैं निश्चित बिंदु नोटेशन का उपयोग कर रहा हूं और अपने परिणामों को सत्यापित करना चाहता हूं। यह चीजों को आसान बना देगा। तुम्हारी सहायता सराहनीय है! – Sam

+0

किसी भी कारण से क्यों 'output_number' एक सादे फ़ंक्शन के बजाय केस स्टेटमेंट के अंदर एक लेबल है? – Lundin

+0

@ लंदन: केवल यह कि टाइप करने के लिए छोटा है। यह छोटा कोड उत्पन्न करने की भी संभावना है जब तक कि संकलक वास्तव में चालाक न हो और यह महसूस हो कि दो फ़ंक्शन कॉल के बीच एकमात्र अंतर इनपुट पैरामीटर है। –

2

अवधारणा आपके द्वारा उपयोग किए जा रहे विशिष्ट सिस्टम के संदर्भ के बाहर "कंसोल" का अधिक अर्थ नहीं है। आम तौर पर एम्बेडेड प्रोग्राम में कंसोल की कोई वास्तविक अवधारणा नहीं होती है।

जो आप खोज रहे हैं वह आपके सिस्टम से डेटा प्राप्त करने का एक तरीका है। यदि आप यूएआरटी का उपयोग करना चाहते हैं, और आप जीएनयू/लिनक्स जैसे उच्च स्तरीय ओएस का उपयोग नहीं कर रहे हैं, तो आपको अपना खुद का I/O ड्राइवर लिखना होगा। आम तौर पर इसका मतलब है कि पंजीकरण लिखने के माध्यम से वांछित बटरेट/समानता/प्रवाह नियंत्रण के लिए यूएआर को पहले कॉन्फ़िगर करना। किसी भी प्रकार के मजबूत आईओ के लिए आप इसे बाधित करने के लिए चाहते हैं, इसलिए आपको टीएसएक्स और आरएक्स के लिए आईएसआर लिखना होगा जो सर्कुलर बफर का उपयोग करते हैं।

ऐसा करने के बाद, आप अपने स्वयं के प्रिंटफ लिख सकते हैं जैसे मैट संकेतित।

+0

धन्यवाद! मुझे यह एहसास हुआ। मैं मूल रूप से यह पता लगाने की कोशिश कर रहा था कि इस बारे में कैसे जाना है क्योंकि मुझे समस्याएं थीं। लेकिन मुझे पता चला कि मेरे प्रोसेसर के साथ मुझे टीएक्स बफर को प्रत्येक लिखने के बाद स्टेटस रजिस्टर तक पहुंचना होगा। अगर मैं इसे स्टाल नहीं करता हूं। अब मैं बाउड रेट के मुद्दों से निपट रहा हूं लेकिन जैसे ही मैं कंकों को काम करता हूं, मैं निश्चित रूप से मैट सामान का उपयोग करूंगा। आपकी सहायता के लिए धन्यवाद – Sam

1

मुझे बैकग्राउंड डिबगिंग के लिए मिला है, जो एक गोलाकार बफर में पात्रों को घेर रहा है जिसे यूआर्ट ट्रांसमिट रजिस्टर पर एक मतदान दिनचर्या द्वारा निकाला जाता है, मेरी पसंद का तरीका है।

प्रक्षेपित दिनचर्या एक चरित्र, स्ट्रिंग और परिवर्तनीय आकार (या तो हेक्स या निश्चित चौड़ाई दशमलव) के आसपास आधारित होती है। और एक डीलक्स बफर दिनचर्या एक आरक्षित चरित्र के साथ एक अतिप्रवाह इंगित कर सकता है।

दृष्टिकोण लक्ष्य ऑपरेशन पर सबसे कम ओवरहेड/प्रभाव है, इंटरप्ट रूटीन में (देखभाल के साथ) का उपयोग किया जा सकता है और विचार आसानी से हस्तांतरणीय है, इसलिए मैंने उपयोग की गई सभी प्रणालियों पर डीबगर को अनदेखा कर दिया है।

1

एक एम्बेडेड सिस्टम में एक सीरियल पोर्ट के माध्यम से जानकारी प्रिंट करने के बाद से मुख्य कार्यक्रम के समय को संशोधित करता है, मुझे मिला है कि सबसे अच्छा समाधान 2 बाइट्स (कभी-कभी 1 बाइट काम ठीक है) में एन्कोड किया गया एक छोटा संदेश भेजना है, और फिर उपयोग करना पीसी में एक कार्यक्रम उन संदेशों को डीकोड करने और आवश्यक जानकारी प्रदान करने के लिए, जिसमें आंकड़े और आपको जो कुछ भी चाहिए, शामिल कर सकते हैं। इस तरह, मैं मुख्य कार्यक्रम में थोड़ा सा ओवरहेड जोड़ रहा हूं, और पीसी को संदेशों को संसाधित करने के लिए कड़ी मेहनत कर रहा हूं। हो सकता है कि कुछ इस तरह:

  • 1 बाइट संदेश: बिट्स 7: 4 = मॉड्यूल आईडी, बिट्स 3: 0 = डिबग जानकारी।

  • 2 बाइट्स संदेश: बिट्स 15:12 = मॉड्यूल आईडी, बिट्स 11: 8 = डीबग जानकारी, बिट्स 7: 0 = डेटा।

फिर, पीसी सॉफ्टवेयर में, आप संदेश है कि किसी भी मॉड्यूल आईडी/डिबग जानकारी जोड़ी के लिए नक्शे के साथ एक मेज ऐलान करते हैं और उपयोग करने के लिए उन्हें स्क्रीन पर मुद्रित करने के लिए किया है।

शायद यह छद्म-प्रिंटफ फ़ंक्शन के रूप में लचीला नहीं है, क्योंकि आपको पीसी में डीकोड करने के लिए संदेशों के एक निश्चित सेट की आवश्यकता होती है, लेकिन इससे पहले मैंने उल्लेख किया है कि यह बहुत अधिक ओवरहेड नहीं जोड़ता है।

उम्मीद है कि यह मदद करता है।

फर्नांडो

संबंधित मुद्दे