STM32 पर एंडियन समस्या


11

मैं STM32F4discovery प्रोग्राम करने के लिए आर्म gcc (CooCox) का उपयोग कर रहा हूं, और मैं w / एंडियन समस्या का सामना कर रहा हूं

मैं SPI के माध्यम से 24 बिट ADC के साथ नमूना ले रहा हूं। चूंकि तीन बाइट्स आ रहे हैं, पहले MSB मुझे उन्हें बनाने के लिए एक संघ में लोड करने का विचार था (मुझे उम्मीद है, वैसे भी!) का उपयोग करना थोड़ा आसान है।

typedef union
{
int32_t spilong;
uint8_t spibytes [4];
uint16_t spihalfwords [2];} spidata;
spidata analogin0;

मैं एसआईबी के रूप में [0] - [2] के साथ एमएसबी के रूप में [0] - [2] के साथ स्पाई का उपयोग करके डेटा लोड करता हूं, फिर मैं एक बार में 8 बिट्स पर मेगाबॉट में यूएसएआरटी के माध्यम से उन्हें थूकता हूं। कोई समस्या नहीं।

समस्याएं तब शुरू हुईं जब मैंने 12 बिट डीएसी में डेटा पास करने की कोशिश की। यह SPI DAC 16 बिट शब्द चाहता है, जिसमें MSB से शुरू होने वाले 4 बिट उपसर्ग शामिल हैं, इसके बाद 12 बिट डेटा होता है।

प्रारंभिक प्रयास थे कि एडीसी के पूरक को एडीसी पूरक बाइनरी को ऑफसेट करने के लिए मुझे दिया गया था, xor-ing analogin0.spihalfwords द्वारा [0] 0x8000 के साथ, परिणाम को नीचे 12 बिट्स पर शिफ्ट किया गया, और फिर अंकगणित को अंकगणितीय रूप से जोड़ा गया।

अविश्वसनीय रूप से निराशा होती है, जब तक कि मैं नहीं देखता कि analogin0.spibytes [0] = 0xFF और और analogin0.spibytes के लिए [1] = 0xB5, analogin0.halfwords [0] 0xB5FF के बराबर था और 0xFFB5 !!!!!

इसे नोट करने के बाद, मैंने अंकगणित संचालन और अर्धांश का उपयोग करना बंद कर दिया, और बिटवाइज़ लॉजिक और बाइट्स से चिपक गया

uint16_t temp=0;
.
.
.


// work on top 16 bits
temp= (uint16_t)(analogin0.spibytes[0])<<8|(uint16_t)(analogin0.spibytes[1]);
temp=temp^0x8000; // convert twos complement to offset binary
temp=(temp>>4) | 0x3000; // shift and prepend with bits to send top 12 bits to DAC A


SPI_I2S_SendData(SPI3,temp); //send to DACa (16 bit SPI words)

... और यह ठीक काम किया। जब मैं कोड की पहली पंक्ति, उसके 0xFFB5, और 0xB5FF के बाद टेंप में झांकता हूं, तो सब अच्छा है

तो, सवालों के लिए ...

  • कोर्टेक्स मेरे लिए नया है। मुझे याद नहीं है कि पीआईसी ने कभी भी int16 में स्वैपिंग नहीं की है, भले ही दोनों प्लेटफॉर्म थोड़े ही एंडियन हैं। क्या ये सही है?

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


2
"चूंकि तीन बाइट्स आ रहे हैं, एमएसबी पहले" - यह बड़ा-एंडियन है, जबकि आप सीपीयू छोटे-एंडियन हैं, इसलिए यह आपकी समस्या शुरू होती है। मैं संकलक मैक्रोज़ / मानक पुस्तकालय कार्यों के लिए 16/32-बिट बाइट स्वैपिंग करना चाहता हूं, आमतौर पर वे विशेष रूप से सीपीयू प्लेटफॉर्म के लिए सबसे कुशल तरीके से कार्यान्वित होते हैं। बेशक, बिट-वाइज शिफ्टिंग / एंडिंग / ओरिंग का उपयोग करना भी ठीक है।
लेज़्लो वाल्को

मुझे लगता है कि मैं analogin0.spibytes को किसी भी क्रम में सामान करना चाहता हूं, लेकिन मुझे लगता है कि यह एक धोखा की तरह है, साथ ही मुझे यह याद रखने के लिए इसे अनस्टफ करने का आदेश याद रखना होगा। मुझे लगता है कि 3-बाइट प्रारूप चीजों को थोड़ा गैर-मानक बनाता है। यदि यह सी ++ होता, तो मैं एक वर्ग पर विचार कर सकता था।
स्कॉट सीडमैन

3
CMSIS है __REV()और __REV16()बाइट्स को पलटने के लिए।
टर्बो जे

3
यह बिल्कुल भी धोखा नहीं है - जब आप इस स्तर पर I / O कर रहे हैं, तो आपको बाहरी बाइट ऑर्डर और आंतरिक बाइट ऑर्डर के बीच संबंध के बारे में पता होना चाहिए। मेरी अपनी प्राथमिकता सॉफ्टवेयर पदानुक्रम में सबसे निचले स्तर पर / "मूल" (आंतरिक) अभ्यावेदन को बाह्य रूपांतरित करना है जो समझ में आता है, और सभी उच्च-स्तरीय सॉफ़्टवेयर को केवल मूल स्वरूप के साथ सौदा करते हैं।
डेव ट्वीड

भले ही एआरएम कॉर्प द्वारा डिज़ाइन किया गया कोर या तो एंडियननेस के साथ काम करने में सक्षम है, एसटीएम का एसआरएम 32 एफ 4040 में एआरएम कोर का कार्यान्वयन केवल-एंडियन है। संदर्भ मैनुअल RM0090 पृष्ठ 64 देखें। AIRCR.ENDIANNESS केवल-पढ़ने के लिए है।
लेज़्ज़ो वाल्को

जवाबों:


6

एंबेडेड सिस्टम में हमेशा बड़े-एंडियन / छोटे-एंडियन मुद्दे होंगे। मेरा व्यक्तिगत दृष्टिकोण हमेशा से रहा है कि आंतरिक स्मृति को देशी धीरज के साथ सांकेतिक शब्दों में बदलना और डेटा में प्रवेश या छोड़ते समय कोई स्वैप करना सही है।

मैं एसबीबी के रूप में [0] - [2] - [2] - [2] के साथ, स्पाई का उपयोग करके डेटा को लोड करता हूं

MSB के रूप में [0] लोड करके, आप मान को बड़े-एंडियन के रूप में एन्कोडिंग कर रहे हैं।

analogin0.spibytes [0] = 0xFF और और analogin0.spibytes [1] = 0xB5, analogin0.halfwords [0] 0xB5FF के बराबर था

यह इंगित करता है कि प्रोसेसर थोड़ा-सा एंडियन है।

यदि इसके बजाय, आप पहले मान को [2] में लोड करते हैं और वापस [0] पर काम करते हैं, तो आपने इनकमिंग नंबर को थोड़ा-एंडियन के रूप में एन्कोड किया है, अनिवार्य रूप से स्वैप को नंबर में प्रवेश करते हुए बनाते हैं। एक बार जब आप मूल प्रतिनिधित्व के साथ काम कर रहे होते हैं, तो आप अंकगणितीय संचालन का उपयोग करने के अपने मूल दृष्टिकोण पर लौट सकते हैं। जब आप मूल्य प्रेषित करते हैं तो बस इसे बड़े-एंडियन में वापस फ्लिप करना सुनिश्चित करें।


5

इनाम के बारे में "वास्तव में srm32f4 बड़े एंडियन मोड के बारे में जानना चाहते हैं", इस चिप के लिए कोई बड़ा एंडियन मोड नहीं है। STM32F4 छोटे एंडियन में सभी मेमोरी एक्सेस करता है।

उपयोगकर्ता पुस्तिका http://www.st.com/web/en/resource/technical/document/programming_manual/DM00046982.pdf पृष्ठ 25 पर इसका उल्लेख करता है। लेकिन और भी बहुत कुछ है। पृष्ठ 93 पर आप देख सकते हैं कि एंडियन स्वैपिंग निर्देश हैं। आरईवी और आरईवीबी रिवर्स और रिवर्स बिट के लिए। आरईवी 32 बिट्स के लिए एंडियन बदल देगा और आरईवी 16 इसे 16 बिट डेटा के लिए करेगा।


3

यहाँ एक कोर्टेक्स M4 के लिए एक कोड स्निपेट है, जिसे gcc के साथ संकलित किया गया है

/*
 * asmLib.s
 *
 *  Created on: 13 mai 2016
 */
    .syntax unified
    .cpu cortex-m4
    .thumb
    .align
    .global big2little32
    .global big2little16
    .thumb
    .thumb_func
 big2little32:
    rev r0, r0
    bx  lr
 big2little16:
    rev16   r0, r0
    bx  lr

C से, कॉल हो सकती है:

 extern uint32_t big2little32(uint32_t x);
 extern uint16_t big2little16(uint16_t x);

 myVar32bit = big2little32( myVar32bit );
 myVar16bit = big2little16( myVar16bit );

पता नहीं कैसे यह तेजी से करने के लिए :-)


आप इस कोड को तेज बनाने के लिए मैक्रो या इनलाइन फ़ंक्शन का उपयोग कर सकते हैं
प्रो

24 बिट डेटा के बारे में क्या?
पेन्गेमीज़्ट

1

CooCox STM32F429 के लिए यह ठीक है:

typedef union {
  uint8_t  c[4];
  uint16_t   i[2];
  uint32_t  l[1];
}adc;

adc     adcx[8];

...

// first channel ...
    adcx[0].c[3] = 0;
    adcx[0].c[2] = UB_SPI1_SendByte(0x00);
    adcx[0].c[1] = UB_SPI1_SendByte(0x00);
    adcx[0].c[0] = UB_SPI1_SendByte(0x00);
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.