2016-08-14 8 views
6

पर संरचना तत्व को कैसे सेट करें हार्डवेयर को वर्णित करते समय एम्बेडेड प्रोग्रामिंग में अक्सर एचडब्ल्यू इंजीनियर द्वारा डिजाइन किए जाने वाले ज्ञात पूर्वनिर्धारित स्थितियों पर संरचना तत्वों को रखने की आवश्यकता होती है। उदाहरण के लिए, एक संरचना FPGA है, जो निम्नलिखित सरल उदाहरण में के रूप में कुछ 100 रजिस्टरों/क्षेत्र हैं निर्दिष्ट कर सकते हैं:वांछित ऑफसेट

struct __attribute__ ((__packed__)) sFPGA { 
    uchar Spare1[0x24]; 
    ushort DiscreteInput; 
    uchar Spare2[0x7A]; 
//CPLD_Version is required to be at offset 0xA0, so 0xA0-0x24-2=0x7A 
    ushort CPLD_Version; 
}; 

अब, मैं निराश और मैनुअल गणना और में एक परिवर्तन के मामले में संभव त्रुटियों की नाराज़ हूँ संरचना। क्या यह और अधिक मजबूत/सुविधाजनक करने का कोई तरीका है? मैं इसे इस तरह से लिखने का प्रयास किया:

uchar Spare2[0xA0 - offsetof(sFPGA, Spare2)]; 

लेकिन यह अधूरी struct ... नोट के बारे में शिकायत है कि मेरे उदाहरण सरलीकृत है संकलन नहीं है। हकीकत में कुछ 20-30 ऐसे अतिरिक्त क्षेत्र हैं जिन्हें परिभाषित किया जाना चाहिए - संरचना बहुत बड़ी है।

+2

साइड नोट: अतिरिक्त फ़ील्ड्स को आम तौर पर 'आरक्षित 1', 'आरक्षित 2' आदि के रूप में संदर्भित किया जाता है (कम से कम यह वह सम्मेलन है जिसे मैंने हमेशा प्रदर्शित करने के लिए संरचना का उपयोग करते समय कोड में देखा है मेमोरी मैप किए गए रजिस्टर्स)। –

+0

https://en.wikipedia.org/wiki/Data_structure_alignment – fstamour

उत्तर

1

खैर, यह मिस यूनिवर्स पुरस्कार को जीतने नहीं है, लेकिन मैं इसे आप क्या चाहते हैं करता है लगता है:

#include <boost/preprocessor/cat.hpp> 
typedef unsigned char uchar; 
typedef unsigned short ushort; 
#define PAD_FIELDS(i_,f_, n_) \ 
    typedef struct __attribute__((packed)) {f_}    ftype##i_; \ 
    typedef struct __attribute__((packed)) {f_ uchar t_;} ttype##i_; \ 
    f_ uchar BOOST_PP_CAT(padding,i_)[n_ - sizeof (BOOST_PP_CAT(ftype,i_)) * (sizeof (BOOST_PP_CAT(ftype,i_)) != sizeof (BOOST_PP_CAT(ttype,i_)))]; 

struct sFPGA { 
    PAD_FIELDS(1, 
    PAD_FIELDS(2, 
    uchar Spare1[0x24]; 
    ushort DiscreteInput; 
    //CPLD_Version is required to be at offset 0xA0 
    , 0xA0)  // First padding 
    ushort CPLD_Version; 
    uchar more_stuff[0x50]; 
    ushort even_more[4]; 
    //NID_Version is required to be at offset 0x10A2 
    , 0x10A2)  // Second padding 
    ushort NID_Version; 
} __attribute__((packed)); 

int main() { 
    printf("CPLD_Version offset %x\n", offsetof(sFPGA,CPLD_Version)); 
    printf("NID_Version offset %x\n", offsetof(sFPGA,NID_Version)); 
} 

मान लीजिए कि आप चाहते हैं एन = 20 चलो पैडिंग फ़ील्ड आपको अपनी संरचना की शुरुआत में उन PAD_FIELDS(i, में से एन को जोड़ना होगा, जहां i उदाहरण के लिए 1 से 20 (मेरे उदाहरण में) या 0 से 1 9 तक या जो भी आपको खुश करता है, के लिए चलता है। फिर, जब आपको पैडिंग की आवश्यकता होती है तो उदाहरण के लिए , 0x80) जिसका अर्थ है कि अगला फ़ील्ड संरचना की शुरुआत से ऑफसेट 0x80 पर स्थित होगा।

इस कोड चलाने पर, यह निम्न पाठ आउटपुट:

CPLD_Version offset a0 
NID_Version offset 10a2 

तरह से इस मैक्रो काम करता है यह अपने क्षेत्रों के साथ एक संरचना को परिभाषित करता है, यह तो अपने क्षेत्रों को शामिल किया गया है, और गद्दी के अनुसार गणना की कहते हैं संरचना।

#include <boost/preprocessor/cat.hpp> 
#include <boost/preprocessor/comma.hpp> 
#include <boost/preprocessor/repetition/repeat.hpp> 
#include <boost/preprocessor/punctuation/paren.hpp> 
typedef unsigned char uchar; 
typedef unsigned short ushort; 
#define PAD_FIELDS(i_,f_, n_) \ 
    typedef struct __attribute__((packed)) {f_}    BOOST_PP_CAT(ftype,i_); \ 
    typedef struct __attribute__((packed)) {f_ uchar t_;} BOOST_PP_CAT(ttype,i_); \ 
    f_ uchar BOOST_PP_CAT(padding,i_)[n_ - sizeof (BOOST_PP_CAT(ftype,i_)) * (sizeof (BOOST_PP_CAT(ftype,i_)) != sizeof (BOOST_PP_CAT(ttype,i_)))]; 
#define PADMAC(z,n,s) PAD_FIELDS BOOST_PP_LPAREN() n BOOST_PP_COMMA() 
#define PADREP(n) BOOST_PP_REPEAT(n, PADMAC, junk) 
#define FORCE_EVAL(...) __VA_ARGS__ 
#define CONTAINS_PADDING(n) FORCE_EVAL(PADREP(n) 
#define SET_OFFSET(o) BOOST_PP_COMMA() o BOOST_PP_RPAREN() 

struct sFPGA { 
    CONTAINS_PADDING(2); 
    uchar Spare1[0x24]; 
    ushort DiscreteInput; 
    //CPLD_Version is required to be at offset 0xA0 
    SET_OFFSET(0xA0); 
    ushort CPLD_Version; 
    uchar more_stuff[0x50]; 
    ushort even_more[4]; 
    //NID_Version is required to be at offset 0x10A2 
    SET_OFFSET(0x10A2); 
    ushort NID_Version; 
    ) 
} __attribute__((packed)); 

सूचना क्या उपयोग में बदल दिया है::

  1. आप कुछ बढ़ावा :: पूर्वप्रक्रमक जादू कोई आपत्ति नहीं है, यहाँ एक तरह से आप पूरी PAD_FIELDS(1,PAD_FIELDS(2,PAD_FIELDS(3,PAD_FIELDS(4,... शुरुआत में स्वचालित कर सकते हैं है संरचना की शुरुआत में आप CONTAINS_PADDING(n) लिखते हैं जहां n वांछित पैडिंग तत्वों की संख्या है।

  2. संरचना के अंत से ठीक पहले आपको ")" जोड़ना होगा।
  3. ,0x0A) के बजाय SET_OFFSET(0x0A); (; वैकल्पिक) लिखने के लिए पैडिंग निर्दिष्ट करने के लिए।
+0

वाह !!! यह सचमुच काम करता है!!! महान!! बहुत धन्यवाद!! – leonp

0

क्या इस बारे में:

struct sFPGA { 
    struct Internal_S { 
    uchar Spare1[0x24]; 
    ushort DiscreteInput; 
    } s; 
    uchar Spare2[0xA0 - sizeof (struct Internal_S)]; 
    ushort CPLD_Version; 
}; 
+0

पर एक नज़र डालें यह निश्चित रूप से काम करेगा। समस्या यह है कि मेरा उदाहरण सरलीकृत है। हकीकत में कुछ 20-30 ऐसे स्पेयर फ़ील्ड हैं जिन्हें परिभाषित किया जाना चाहिए - संरचना बहुत बड़ी है ... :-( – leonp

+1

@leonp: इस मामले में आप एक कोड जेनरेटर लिखना चाहेंगे, जो स्रोत को ' प्रत्येक संकलन चलाने की तैयारी में प्रश्न में संरचना ' – alk

+0

_ @alk: हम्म ... आपके मतलब का कोई संकेत/अंक/लिंक? कुछ और विस्तृत स्पष्टीकरण? :-) – leonp

1

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

बेशक

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

यदि आपको विशिष्ट ऑफसेट पर डेटा को पूरी तरह से एक्सेस करना होगा, तो आप या तो गैर मानक __attribute__(packed) जीसीसी एक्सटेंशन (लेकिन this देखें) का प्रयास कर सकते हैं; या सी प्रोग्रामिंग स्तर पर आसान पहुंच के लिए struct के अंदर/बाहर के रूप में डेटा को डी/क्रमबद्ध करने के लिए कस्टम I/O मार्ग लिखें।

+0

पॉल: हाँ, आप बिल्कुल सही हैं। मैं सिर्फ उदाहरण को सरल बनाना चाहता था और पैक किए गए गुण को छोड़ देता हूं जिसे मैं लगातार ऐसे मामलों में उपयोग करता हूं। – leonp

+0

@leonp यह जानकारी छोड़ने का एक महत्वपूर्ण हिस्सा है! –

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