2012-02-21 38 views
5

मैं रैम के केवल कुछ बाइट्स के साथ एक छोटे 8-बिट माइक्रोकंट्रोलर के लिए कोड लिख रहा हूं। इसमें एक साधारण काम है जो 7 16-बिट शब्दों को प्रेषित करना है, फिर उन शब्दों का सीआरसी। शब्दों के मान संकलन समय पर चुने जाते हैं। सीआरसी विशेष रूप से " शब्द 0 के शब्द का शेष है, जो शब्द 6 को बहुपद x^8 + x² + x + 1 (प्रारंभिक मान 0xFF) द्वारा विभाजित हस्ताक्षरित संख्या के रूप में है।"सी प्रीप्रोसेसर के साथ 8-बिट सीआरसी की गणना करना?

सी प्रीप्रोसेसर का उपयोग करके संकलन समय पर उन बाइट्स के सीआरसी की गणना करना संभव है?

#define CALC_CRC(a,b,c,d,e,f,g) /* what goes here? */ 

#define W0 0x6301 
#define W1 0x12AF 
#define W2 0x7753 
#define W3 0x0007 
#define W4 0x0007 
#define W5 0x5621 
#define W6 0x5422 
#define CRC CALC_CRC(W0, W1, W2, W3, W4, W5, W6) 
+2

http://codegolf.stackexchange.com/questions/3268/compute-the-crc32-table-at-compile-time – Xophmeister

+0

यदि गैर-अस्थिर स्मृति (फ़्लैश) की तुलना में गति आपके लिए अधिक महत्वपूर्ण है, तो आप सभी परिणाम पूर्व-गणना और निरंतर लुकअप तालिका में संग्रहीत हो सकते हैं। आपके द्वारा वर्णित सीआरसी बहुपद को "सीआरसी -8-सीसीआईटीटी" के रूप में जाना जाता है। मैं उस के लिए इष्टतम एल्गोरिदम नहीं जानता, मैं वेब पर खोज करने का सुझाव दूंगा। – Lundin

उत्तर

1

सरल checksum एल्गोरिथ्म तथाकथित अनुदैर्ध्य समता जांच, जो बिट्स की एक निश्चित संख्या n के साथ "शब्दों" में डेटा टूट जाता है, और फिर विशेष या उन सभी शब्दों की गणना करता है। परिणाम एक अतिरिक्त शब्द के रूप में संदेश में जोड़ा गया है।

किसी संदेश की अखंडता की जांच करने के लिए, रिसीवर चेकसम सहित विशेष या उसके सभी शब्दों की गणना करता है; यदि परिणाम एन शून्य के साथ एक शब्द नहीं है, तो रिसीवर जानता है कि एक संचरण त्रुटि हुई।

(souce: विकि)

अपने उदाहरण में:

#define CALC_CRC(a,b,c,d,e,f) ((a)^(b)^(c)^(d)^(e)^(f)) 
+0

यह एक चक्रीय रिडंडेंसी जांच नहीं है, यह बहुपद के बिना सिर्फ एक पार्टी की जांच है। सिंगल बिट त्रुटियों का पता लगाने में विफल होने पर 50% की संभावना है। – Lundin

+0

मैं सहमत हूं, लेकिन यह सबसे सरल है, जैसा कि मैंने कहा था। इस चेकसम के साथ, किसी भी ट्रांसमिशन त्रुटि जो संदेश के एक बिट को फ़्लिप करती है, या बिट्स की विषम संख्या को गलत चेकसम के रूप में पहचाना जाएगा। हालांकि, दो बिट्स को प्रभावित करने वाली त्रुटि का पता नहीं लगाया जाएगा यदि उन बिट्स एक ही स्थिति में दो अलग-अलग शब्दों में हैं। यदि प्रभावित बिट्स को यादृच्छिक रूप से स्वतंत्र रूप से चुना जाता है, तो दो-बिट त्रुटि की संभावना को अनदेखा किया जा सकता है 1/n है। – vulkanino

+0

मुझे यह उल्लेख करना चाहिए था कि यह सिर्फ कोई चेकसम नहीं है, मुझे एक विशिष्ट आवश्यकता है। – Rocketmagnet

0

अस्वीकरण: इस नहीं वास्तव में एक सीधा जवाब है, बल्कि सवाल और सुझाव है कि एक टिप्पणी के लिए बहुत लंबा है की एक श्रृंखला है।

पहला प्रश्न: क्या आपके पास प्रोटोकॉल के दोनों सिरों पर नियंत्रण है, उदा। क्या आप स्वयं के माध्यम से चेकसम एल्गोरिदम चुन सकते हैं या दूसरे सिरे पर कोड को नियंत्रित करने वाले एक सहकर्मी?

हाँ सवाल करने के लिए, तो # 1:

आप का मूल्यांकन करने के कारण है कि आप चेकसम की जरूरत की जरूरत है, क्या चेकसम उचित है, और एक वैध चेकसम (जो दोनों में कारकों के साथ एक भ्रष्ट संदेश प्राप्त होने के परिणाम क्या & क्यों)।

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

खराब संदेश के परिणाम हमेशा सबसे महत्वपूर्ण सवाल है। तो यदि आप डिजिटल रूम थर्मामीटर के लिए नियंत्रक लिख रहे हैं और एक प्रदर्शन को 10x प्रदर्शित करने के लिए एक संदेश भेज रहे हैं, तो किसी भी वास्तविक हानि के कारण कभी भी 1000 संदेशों में बहुत कम मूल्य होता है। कोई चेकसम या कमजोर चेकसम ठीक नहीं होना चाहिए।

यदि इन 6 बाइट्स मिसाइल को आग लगाते हैं, रोबोटिक स्केलपेल की स्थिति निर्धारित करते हैं, या पैसे के हस्तांतरण का कारण बनते हैं, तो आप बेहतर सुनिश्चित करते हैं कि आपके पास सही चेकसम है, और यहां तक ​​कि एक क्रिप्टोग्राफिक हैश (जो भी एक क्रिप्टोग्राफिक हैश (आपके पास अधिक रैम की आवश्यकता हो सकती है)।

सामान के बीच में, उत्पाद के साथ प्रदर्शन/संतुष्टि के लिए ध्यान देने योग्य नुकसान के साथ, लेकिन कोई वास्तविक नुकसान नहीं, यह आपकी कॉल है।उदाहरण के लिए, एक टीवी जो कभी-कभी चैनल के बजाए वॉल्यूम को बदलता है, ग्राहकों से बाहर निकल सकता है - अगर कोई अच्छा सीआरसी किसी त्रुटि का पता लगाता है तो कमांड छोड़ने से कहीं ज्यादा, लेकिन यदि आप सस्ते/नॉक-ऑफ टीवी जो ठीक हो सकते हैं यदि यह तेजी से बाजार में उत्पाद प्राप्त करता है।

तो आपको किस चेकसम की आवश्यकता है?

यदि दोनों या दोनों सिरों में परिधीय (उदाहरण के लिए एसपीआई में काफी आम) में बनाए गए चेकसम के लिए एचडब्ल्यू समर्थन है, तो यह एक बुद्धिमान विकल्प हो सकता है। फिर यह गणना करने के लिए कम या ज्यादा मुक्त हो जाता है।

वल्कनिनो के उत्तर द्वारा सुझाए गए एक एलआरसी, सबसे सरल एल्गोरिदम है।

विकिपीडिया कैसे/क्यों एक बहुपद का चयन करने पर कुछ सभ्य जानकारी है यदि आप वास्तव में एक सीआरसी की जरूरत है: http://en.wikipedia.org/wiki/Cyclic_redundancy_check

कोई सवाल ही नहीं है तो # 1:

क्या सीआरसी एल्गोरिथ्म/बहुपद करता है दूसरी छोर की आवश्यकता है? यही वह है जिसे आप फंस गए हैं, लेकिन हमें बताएं कि आपको एक बेहतर/अधिक पूरा उत्तर मिल सकता है। कार्यान्वयन पर

विचार:

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

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

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

+0

कोई प्रश्न नहीं 1. मैंने अपने प्रश्न के बहुपद को जोड़ा है। – Rocketmagnet

+0

मुझे पता है कि सभी बाइट संकलन समय पर जाना जाना चाहिए। यही कारण है कि मेरे उदाहरण कोड ने उन्हें सभी परिभाषित किया था। – Rocketmagnet

+0

@ रॉकेटमैग्नेट: मैं सबसे पहले देखता हूं कि क्या आप बिटवर्क ऑपरेशंस के लिए शॉर्टकट के रूप में एक लुक-टेबल के साथ एक वर्किंग एल्गोरिदम के साथ आ सकते हैं। एक पीसी प्रोग्राम के साथ लुकअप टेबल की गणना करें और इसे प्रीप्रोसेसर वैरिएबल (यानी मैक्रो) में स्टोर करें। फिर 'बाहरी' लूप को अनलोल करें जो प्रत्येक शब्द पर लुकअप जैसा कुछ इस तरह दिखता है: '# परिभाषित करें CALC_CRC (ए, बी, सी) LUT [सी^LUT [बी^LUT [ए^एफएफ]]]' –

2

एक मैक्रो तैयार करना संभव है जो संकलन समय पर सीआरसी गणना करेगा।

 
// Choosing names to be short and hopefully unique. 
#define cZX((n),b,v) (((n) & (1 << b)) ? v : 0) 
#define cZY((n),b, w,x,y,z) (cZX((n),b,w)^CzX((n),b+1,x)^CzX((n),b+2,y)^cZX((n),b+3,z)) 
#define CRC(n) (cZY((n),0,cZ0,cZ1,cZ2,cZ3)^cZY((n),4,cZ4,cZ5,cZ6,cZ7)) 
जैसे कुछ काम करना चाहिए, और (n) को संकलित-समय निरंतर के रूप में मूल्यांकन किया जा सकता है; यह केवल स्थिरता का मूल्यांकन करेगा। दूसरी ओर, यदि n एक अभिव्यक्ति है, तो अभिव्यक्ति आठ बार पुनः संयोजित हो जाएगी। भले ही n एक साधारण चर है, परिणामी कोड इसे लिखने के सबसे तेज़ गैर-टेबल-आधारित तरीके से काफी बड़ा होगा, और इसे लिखने के सबसे कॉम्पैक्ट तरीके से धीमा हो सकता है।

बीटीडब्लू, एक चीज जो मैं वास्तव में सी और सी ++ मानक में देखना चाहूंगा, ओवरलोड को निर्दिष्ट करने का एक माध्यम होगा जो केवल इनलाइन घोषित फ़ंक्शंस के लिए उपयोग किया जाएगा यदि विशिष्ट पैरामीटर का संकलन-समय स्थिरांक के रूप में मूल्यांकन किया जा सके।अर्थशास्त्र इस तरह होगा कि कोई 'गारंटी' नहीं होगी कि ऐसे किसी भी अधिभार का उपयोग हर मामले में किया जाएगा जहां एक कंपाइलर मूल्य निर्धारित करने में सक्षम हो सकता है, लेकिन गारंटी होगी कि (1) इस तरह के अधिभार का उपयोग नहीं किया जाएगा किसी भी मामले में जहां "कंपाइल-टाइम-कॉन्स्ट" पैरामीटर को रनटाइम पर मूल्यांकन किया जाना चाहिए, और (2) किसी भी पैरामीटर जिसे एक ऐसे ओवरलोड में स्थिर माना जाता है उसे किसी भी फ़ंक्शन में निरंतर माना जाएगा। ऐसे कई मामले हैं जहां एक पैरामीटर स्थिरता के मूल्यांकन के लिए एक फ़ंक्शन लिखा जा सकता है यदि उसका पैरामीटर स्थिर है, लेकिन जहां रन-टाइम मूल्यांकन बिल्कुल भयानक होगा। उदाहरण के लिए:

 
#define bit_reverse_byte(n) ((((n) & 128)>>7)|(((n) & 64)>>5)|(((n) & 32)>>3)|(((n) & 16)>>1)| 
    (((n) & 8)<<1)|(((n) & 4)<<3)|(((n) & 2)<<5)|(((n) & 1)<<7)) 
#define bit_reverse_word(n) (bit_reverse_byte((n) >> 8) | (bit_reverse_byte(n) << 8)) 

पीआईसी पर सी में एक गैर फंस एकल-बाइट बिट रिवर्स समारोह का एक सरल प्रतिपादन 17-19 के बारे में एकल चक्र निर्देश होगा, एक शब्द बिट-रिवर्स 34 होगा, या लगभग 10 प्लस बाइट-रिवर्स फ़ंक्शन (जो दो बार निष्पादित होगा)। इष्टतम असेंबली कोड बाइट रिवर्स के लिए लगभग 15 एकल-चक्र निर्देश या शब्द-रिवर्स के लिए 17 होगा। कुछ बाइट वेरिएबल b के लिए कंप्यूटिंग bit_reverse_byte(b) कई दर्जनों चक्रों के कुल दर्जनों निर्देशों को ले जाएगा। कंप्यूटिंग bit_reverse_word( डब्ल्यू ) for some 16-bit word डब्ल्यू शायद सैकड़ों या हजारों चक्रों को निष्पादित करने के लिए सैकड़ों निर्देश लेगा। यह वास्तव में अच्छा होगा अगर कोई परिदृश्य में उपर्युक्त फॉर्मूलेशन जैसे कुछ का उपयोग करके इनलाइन का विस्तार करने के लिए फ़ंक्शन को चिह्नित कर सकता है, जहां यह कुल चार निर्देशों (मूल रूप से केवल परिणाम लोड कर रहा है) तक विस्तारित होगा, लेकिन इनलाइन परिदृश्यों में फ़ंक्शन कॉल का उपयोग करें विस्तार जघन्य होगा।

+0

+1 चालाक। हालांकि, मुझे लगता है कि कोड को समझना आसान होगा (शायद सामान्य सी या पायथन में लिखा गया है) जो मेरे डेस्कटॉप कंप्यूटर पर चलता है और ".h" स्रोत फ़ाइल में "पूर्व-गणना तालिका" प्रिंट करता है जिसे बाद में # शामिल किया गया है सी कोड जो microcontroller पर चलाएगा। कुछ ऐसा है ["पाइथन का उपयोग सी उत्पन्न करने के लिए"] (http://stackoverflow.com/questions/4000678/using-python-to-generate-ac-string-literal-of-json) या ["pycrc"] (http : //programmers.stackexchange.com/questions/96211/what-is-a-faster-alternative-to-a-crc/96374#96374) –