2015-02-26 10 views
5

के साथ कचरा फ्लोट प्रिंट करता है मैं एआरएम कॉर्टेक्स-एम 3 (एसटीएम 32 एफ 205) के साथ एक नंगे धातु एम्बेडेड सिस्टम चला रहा हूं। जब मैं नाव की संख्या के साथ snprintf() उपयोग करने के लिए, उदा .:स्नप्रिंटफ() न्यूबिल नैनो

float f; 

f = 1.23; 
snprintf(s, 20, "%5.2f", f); 

कोशिश मैं s में कचरा मिलता है। प्रारूप को सम्मानित किया जा रहा है, यानी कचरा अंक, दशमलव बिंदु, और दो पीछे वाले अंकों के साथ एक अच्छी तरह से बनाई गई स्ट्रिंग है। हालांकि, अगर मैं snprintf दोहराता हूं, तो स्ट्रिंग दो कॉल के बीच बदल सकती है।

चल बिन्दु गणित अन्यथा काम करने के लिए लगता है, और snprintf पूर्णांकों के साथ काम करता है, उदा .:

snprintf(s, 20, "%10d", 1234567); 

मैं -u _printf_float लिंकर स्विच के साथ newlib-nano कार्यान्वयन का उपयोग करें। कंपाइलर arm-none-eabi-gcc है।

मुझे मेमोरी आवंटन समस्याओं का एक मजबूत संदेह है, क्योंकि पूर्णांक बिना किसी हिचकी के मुद्रित होते हैं, लेकिन फ्लोट कार्य करता है जैसे कि वे प्रक्रिया में दूषित हो जाते हैं। printf पारिवारिक फ़ंक्शंस फ्लोट के साथ malloc पर कॉल करता है, पूर्णांक के साथ नहीं।

कोड newlib से संबंधित नहीं मैं इस संदर्भ में उपयोग कर रहा हूँ का केवल कुछ भाग मेरी _sbrk(), जो malloc के लिए आवश्यक है है।

caddr_t _sbrk(int incr) 
{ 
    extern char _Heap_Begin; // Defined by the linker. 
    extern char _Heap_Limit; // Defined by the linker. 

    static char* current_heap_end; 
    char* current_block_address; 

    // first allocation 
    if (current_heap_end == 0) 
     current_heap_end = &_Heap_Begin; 

    current_block_address = current_heap_end; 

    // increment and align to 4-octet border 
    incr = (incr + 3) & (~3); 
    current_heap_end += incr; 

    // Overflow? 
    if (current_heap_end > &_Heap_Limit) 
    { 
    errno = ENOMEM; 
    current_heap_end = current_block_address; 
    return (caddr_t) - 1; 
    } 

    return (caddr_t)current_block_address; 
} 

जहां तक ​​मैं ट्रैक करने में सक्षम हूं, यह काम करना चाहिए। ऐसा लगता है कि कोई भी इसे नकारात्मक वृद्धि के साथ कभी नहीं बुलाता है, लेकिन मुझे लगता है कि यह न्यूलिब malloc के डिजाइन के कारण है। केवल थोड़ी सी अजीब चीज यह है कि _sbrk पर पहली कॉल शून्य वृद्धि है। (लेकिन यह केवल malloc की ढेर के शुरुआती पते के बारे में जिज्ञासा हो सकती है।)

ढेर ढेर के साथ टकरा नहीं होना चाहिए, क्योंकि दोनों के लिए लगभग 60 कीबी रैम है। लिंकर स्क्रिप्ट पागल हो सकती है, लेकिन कम से कम ढेर और ढेर पते सही लगते हैं।

+2

ध्यान दें कि वे 'डबल' हैं, न कि 'फ्लोट' हैं। कोई फर्क नहीं पड़ता कि यह मायने रखता है, तो आप 'फ्लोट' को 'snprintf()' वैसे भी पास नहीं कर सकते हैं। – unwind

+4

[snprintf() '] के लिए प्रोटोटाइप (http://pubs.opengroup.org/onlinepubs/9699919799/functions/snprintf.html) 'int snprintf (char * प्रतिबंधित s, size_t n, const char * प्रतिबंधित प्रारूप है , ...); 'आप प्रोटोटाइप के अनुसार फ़ंक्शन को कॉल नहीं कर रहे हैं। क्या आपने #'** शामिल किया है और सभी चेतावनियों के साथ संकलित ** **? – pmg

+1

निश्चित रूप से आपका सच्चा कोड 'snprintf()' का उपयोग कर रहा है और 'sprintf() 'नहीं है? – chux

उत्तर

9

के माध्यम से जाना चाहते हो सकता है, मैं अपने ही प्रश्न का उत्तर पोस्ट। हालांकि, यह @ नॉटलिकेथ की टिप्पणी थी जिसने सही उत्तर का सुझाव दिया था।

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

मूल लिंकर स्क्रिप्ट की प्रासंगिकता का:

_estack = 0x2000ffff; 

और स्टार्टअप स्क्रिप्ट में अपने समकक्षों:

Reset_Handler: 
    ldr sp, =_estack  /* set stack pointer */ 
... 

g_pfnVectors: 
    .word _estack 
    .word Reset_Handler 
... 

पहले बाधा वेक्टर स्थिति (0 में) हमेशा स्टार्टअप पर ले जाना चाहिए शीर्ष ढेर जब रीसेट बाधित हो जाता है, तो यह स्टैक पॉइंटर भी लोड करता है। (जहां तक ​​मैं कह सकता हूं, बाद वाला एक अनावश्यक है क्योंकि एचडब्ल्यू रीसेट हैंडलर को कॉल करने से पहले 0 वें वेक्टर से एसपी को फिर से लोड करता है।)

कॉर्टेक्स-एम स्टैक पॉइंटर हमेशा स्टैक में अंतिम आइटम को इंगित करना चाहिए। स्टार्टअप में स्टैक में कोई आइटम नहीं है और इस प्रकार पॉइंटर को इस मामले में वास्तविक स्मृति, 0x020010000 से ऊपर के पहले पते पर इंगित करना चाहिए। मूल लिंकर स्क्रिप्ट के साथ स्टैक पॉइंटर 0x0200ffff पर सेट होता है, जो वास्तव में sp = 0x0200fffc (हार्डवेयर बल शब्द-संरेखित स्टैक) में परिणाम देता है। इसके बाद ढेर से 4.

गलत संरेखित है मैं _estack की लगातार परिभाषा को दूर करने और _stacktop द्वारा जगह के रूप में नीचे दिखाया गया है द्वारा लिंकर स्क्रिप्ट बदल दिया है। स्मृति परिभाषाएं पहले थीं। मैंने सिर्फ यह देखने के लिए नाम बदल दिया कि मूल्य कहां उपयोग किया जाता है।

MEMORY 
{ 
FLASH (rx)  : ORIGIN = 0x8000000, LENGTH = 128K 
RAM (xrw)  : ORIGIN = 0x20000000, LENGTH = 64K 
} 

_stacktop = ORIGIN(RAM) + LENGTH(RAM); 

इसके बाद _stacktop का मूल्य 0x20010000 है, और मेरे संख्या खूबसूरती से तैरने लगते हैं ... एक ही समस्या डबल लंबाई पैरामीटर का उपयोग कर किसी भी बाहरी (पुस्तकालय) समारोह के साथ पैदा कर सकता है, के रूप में एआरएम कॉर्टेक्स ABI कहा गया है कि ढेर बाहरी कार्यों को कॉल करते समय 8 ऑक्टेट्स को गठबंधन किया जाना चाहिए।

1

स्नप्रिंटफ दूसरे तर्क के रूप में आकार स्वीकार करता है। यह हो सकता है के रूप में है कि किसी एक ही बग ने काट लिया हो जाता है आप इस उदाहरण http://www.cplusplus.com/reference/cstdio/snprintf/

/* snprintf example */ 
#include <stdio.h> 

int main() 
{ 
    char buffer [100]; 
    int cx; 

    cx = snprintf (buffer, 100, "The half of %d is %d", 60, 60/2); 

    snprintf (buffer+cx, 100-cx, ", and the half of that is %d.", 60/2/2); 

    puts (buffer); 

    return 0; 
} 
+0

अच्छा जवाब, और हाँ, मैं वास्तव में उस गलती को कर सकता था ... लेकिन उस मामले में 'जीसीसी' (एक बार फिर) ने मुझे बताया कि मैं बेवकूफ हूं। इसलिए, इस बार समस्या 'न्यूलिब' में कहीं अधिक गहरी लगती है - या संभवतः लिंकर स्क्रिप्ट में। – DrV

+0

लॉल .... लेकिन आप इसे कम से कम कोशिश कर सकते हैं .... – theadnangondal

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