2013-03-14 10 views
7

सारांशजीसीसी 4.7.2 अनुकूलन समस्याओं

मैं Sourcery CodeBench लाइट toolchain का नवीनतम संस्करण (जीसीसी हाथ-नन-EABI 4.7.2) का उपयोग कर अनुसूचित जनजाति के USB OTG लाइब्रेरी पोर्टिंग कर रहा हूँ एक कस्टम STM32F4 बोर्ड के लिए।

जब मैं -00 के साथ कोड संकलित करता हूं, तो प्रोग्राम ठीक चलता है। जब मैं -O1 या -O2 के साथ संकलित करता हूं तो यह विफल हो जाता है। जब मैं असफल कहता हूं, तो यह बंद हो जाता है। कोई कठोर गलती नहीं, कुछ भी नहीं (ठीक है, जाहिर है कि यह कुछ कर रहा है लेकिन मेरे पास डीबग करने और पता लगाने के लिए उपयोग करने के लिए एक एमुलेटर नहीं है, मुझे खेद है। मेरी हार्ड गलती हैंडलर को नहीं कहा जा रहा है)।

विवरण

मैं निम्नलिखित कार्य करने के लिए कॉल करने के लिए कोशिश कर रहा हूँ ...

void USBD_Init(USB_OTG_CORE_HANDLE *pdev, 
      USB_OTG_CORE_ID_TypeDef coreID, 
      USBD_DEVICE *pDevice,     
      USBD_Class_cb_TypeDef *class_cb, 
      USBD_Usr_cb_TypeDef *usr_cb); 

... लेकिन यह यह समारोह शरीर में बनाने के लिए प्रतीत नहीं होता। (इस "स्टैक-स्मैश" का एक लक्षण है?)

संरचनाओं इस समारोह के लिए पारित निम्नलिखित परिभाषा है:

typedef struct USB_OTG_handle 
{ 
    USB_OTG_CORE_CFGS cfg; 
    USB_OTG_CORE_REGS regs; 
    DCD_DEV  dev; 
} 
USB_OTG_CORE_HANDLE , *PUSB_OTG_CORE_HANDLE; 

typedef enum 
{ 
    USB_OTG_HS_CORE_ID = 0, 
    USB_OTG_FS_CORE_ID = 1 
}USB_OTG_CORE_ID_TypeDef; 

typedef struct _Device_TypeDef 
{ 
    uint8_t *(*GetDeviceDescriptor)(uint8_t speed , uint16_t *length); 
    uint8_t *(*GetLangIDStrDescriptor)(uint8_t speed , uint16_t *length); 
    uint8_t *(*GetManufacturerStrDescriptor)(uint8_t speed , uint16_t *length); 
    uint8_t *(*GetProductStrDescriptor)(uint8_t speed , uint16_t *length); 
    uint8_t *(*GetSerialStrDescriptor)(uint8_t speed , uint16_t *length); 
    uint8_t *(*GetConfigurationStrDescriptor)(uint8_t speed , uint16_t *length); 
    uint8_t *(*GetInterfaceStrDescriptor)(uint8_t speed , uint16_t *length); 
} USBD_DEVICE, *pUSBD_DEVICE; 

typedef struct _Device_cb 
{ 
    uint8_t (*Init)   (void *pdev , uint8_t cfgidx); 
    uint8_t (*DeInit)  (void *pdev , uint8_t cfgidx); 
/* Control Endpoints*/ 
    uint8_t (*Setup)  (void *pdev , USB_SETUP_REQ *req); 
    uint8_t (*EP0_TxSent) (void *pdev);  
    uint8_t (*EP0_RxReady) (void *pdev); 
    /* Class Specific Endpoints*/ 
    uint8_t (*DataIn)  (void *pdev , uint8_t epnum); 
    uint8_t (*DataOut)  (void *pdev , uint8_t epnum); 
    uint8_t (*SOF)   (void *pdev); 
    uint8_t (*IsoINIncomplete) (void *pdev); 
    uint8_t (*IsoOUTIncomplete) (void *pdev); 
    uint8_t *(*GetConfigDescriptor)(uint8_t speed , uint16_t *length); 
    uint8_t *(*GetUsrStrDescriptor)(uint8_t speed ,uint8_t index, uint16_t *length); 

} USBD_Class_cb_TypeDef; 

typedef struct _USBD_USR_PROP 
{ 
    void (*Init)(void); 
    void (*DeviceReset)(uint8_t speed); 
    void (*DeviceConfigured)(void); 
    void (*DeviceSuspended)(void); 
    void (*DeviceResumed)(void); 

    void (*DeviceConnected)(void); 
    void (*DeviceDisconnected)(void);  

} 
USBD_Usr_cb_TypeDef; 

मैं सभी स्रोत इस समस्या के लिए प्रासंगिक कोड को शामिल करने की कोशिश की है। आप पूरे स्रोत कोड देखना चाहते हैं तो आप इसे यहां से डाउनलोड कर सकते हैं: http://www.st.com/st-web-ui/static/active/en/st_prod_software_internet/resource/technical/software/firmware/stm32_f105-07_f2_f4_usb-host-device_lib.zip

समाधान का प्रयास किया गया

मैं volatile रूप #pragma GCC optimize ("O0"), __attribute__((optimize("O0"))) के साथ खेल, और घोषणा की कुछ परिभाषाओं की कोशिश की, लेकिन कुछ भी काम किया। मैं वैसे भी अनुकूलक के साथ अच्छी तरह से खेलने के लिए कोड को संशोधित करना चाहता हूं।

प्रश्न

मैं इसे जीसीसी के अनुकूलक के साथ अच्छा खेलने बनाने के लिए इस कोड को कैसे संशोधित कर सकते हैं?

+2

शायद यह मामला है कि ऑप्टिमाइज़ेशन चालू करना आपके कोड में यूबी को उजागर कर रहा है। यानी, आपका कोड शायद ऑप्टिमाइज़ेशन अक्षम होने के साथ भी गलत है, आपको बस कोई लक्षण नहीं दिख रहा है। – ildjarn

+11

यह एक 3.7 एमबी ज़िप फ़ाइल है, मुझे कोई बात नहीं है कि कोई भी आपके लिए मुफ्त में डीबग करेगा। पोस्ट किया गया कोड केवल कुछ घोषणाएं है और हमें कुछ भी नहीं बताती है। आपको अपना कोड पूर्ण न्यूनतम संभव से कम करना चाहिए, और इसे डीबग करने का प्रयास करें। इसके अलावा, क्या आपने सभी चेतावनियां चालू की हैं, और उन पर ध्यान दिया है? – nos

+1

क्यों कोई एमुलेटर नहीं? आप एक एसटीएम 32 एफ 4 डिस्कोवर बोर्ड में $ 15 निवेश करना चाहते हैं जिसमें ऑन-बोर्ड जेएफई है। मैंने एक का उपयोग नहीं किया है, और मुझे नहीं पता कि सोर्सरी कोडबेन्च लाइट टूलचेन आसानी से काम करेगा या नहीं, लेकिन आपको एसटी यूएसबी ओटीजी लाइब्रेरी को कुछ टूलचैन के साथ बनाया और चलाना चाहिए (अगर सोर्सरी टूलचेन नहीं है) और देखें कि क्या आपके कोड में इंटरफेसिंग के साथ आपको कोई समस्या है या नहीं। –

उत्तर

1

आपके द्वारा दिखाए गए कोड के साथ कुछ भी गलत नहीं लगता है, इसलिए यह उत्तर अधिक सामान्य होगा।

"हार्डवेयर के नजदीक" कोड के साथ सामान्य त्रुटियां क्या हैं जो उचित रूप से अपरिवर्तित काम करती हैं और उच्च अनुकूलन स्तरों में विफल होती हैं?

-O0 और -O1/-O2 के बीच मतभेद के बारे में सोचो: अनुकूलन रणनीतियों रहे हैं - दूसरों के बीच - पाश unrolling (खतरनाक हो प्रतीत नहीं होता है), जब तक संभव, मृत कोड उन्मूलन और शिक्षा पुनर्व्यवस्था के रूप में रजिस्टर में मूल्यों धारण करने के लिए प्रयास करते हैं।

बेहतर पंजीकरण उपयोग आमतौर पर उच्च अनुकूलन स्तरों के साथ समस्याओं का कारण बनता है यदि हार्डवेयर रजिस्ट्रार जो किसी भी समय बदल सकते हैं volatile ठीक से घोषित नहीं किया गया है (ऊपर पॉकीब्रेन की टिप्पणी देखें)। अनुकूलित कोड रजिस्टरों में यथासंभव मूल्यों को रखने की कोशिश करेगा, जिसके परिणामस्वरूप आपका प्रोग्राम हार्डवेयर पक्ष में बदलावों को नोटिस करने में विफल रहा है। हार्डवेयर घोषित करने के लिए सुनिश्चित करें कि पंजीकृत करता volatile ठीक से

मृत कोड उन्मूलन की संभावना समस्याओं को जन्म दे यदि आप एक हार्डवेयर रजिस्टर पढ़ने के लिए जो कुछ भी संकलक के लिए नहीं जाना हार्डवेयर पर प्रभाव उत्पन्न करने की जरूरत है और साथ कुछ भी नहीं करते होंगे मूल्य जो आपने अभी पढ़ा है।यदि आप पढ़ने के लिए void ठीक से उपयोग करने के लिए उपयोग किए गए चर घोषित नहीं करते हैं, तो इन हार्डवेयर एक्सेस को ऑप्टिमाइज़ किया जा सकता है (हालांकि कंपाइलर को चेतावनी जारी करनी चाहिए)। कास्ट करने के लिए डमी पढ़ता (void)

के लिए अनुदेश को पुन: क्रम सुनिश्चित करें: आप इच्छित परिणाम प्राप्त होने की एक निश्चित क्रम में विभिन्न हार्डवेयर रजिस्टरों का उपयोग करने की जरूरत है और आप करते हैं कि अगर किसी भी प्रकार से संबंधित नहीं संकेत के माध्यम से, संकलक परिणामी निर्देशों को पुन: व्यवस्थित करने के लिए स्वतंत्र है क्योंकि यह उपयुक्त दिखता है (यदि हार्डवेयर रजिस्ट्रार ठीक से volatile घोषित किया गया है)। आवश्यक पहुंच अनुक्रम (__asm__ __volatile__(::: "memory");) को लागू करने के लिए आपको अपने कोड में मेमोरी बाधाओं को भटकने की आवश्यकता होगी। जहां आवश्यक हो वहां मेमोरी बाधाएं जोड़ना सुनिश्चित करें।

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

यदि यह सब मदद नहीं करता है, तो आप कभी-कभी जेनरेट किए गए असेंबलर कोड में खोदने से बच नहीं सकते हैं ताकि यह सुनिश्चित किया जा सके कि यह क्या करना है।

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