USB के माध्यम से FPGA के लिए कॉन्फ़िगरेशन डाउनलोड करें या FTDI MPSSE को इकट्ठा करें



प्रत्येक दराज के जीवन में एक समय आता है जब आप FPGA में कॉन्फ़िगरेशन फ़ाइल के अपने लोडर को लिखना चाहते हैं। मुझे एक तकनीकी विश्वविद्यालय के विभाग के लिए एक प्रशिक्षण स्टैंड के विकास में भाग लेना था। स्टैंड को डिजिटल सिग्नल प्रोसेसिंग का अध्ययन करने के लिए डिज़ाइन किया गया है, हालांकि इस लेख के ढांचे में इसका विशेष महत्व नहीं है। और महत्व यह है कि FPGA (Altera Cyclone IV) स्टैंड के केंद्र में है, जिस पर छात्र स्टैंड के लेखक द्वारा कल्पना के अनुसार सभी प्रकार की डीएसपी योजनाओं को एकत्र करते हैं। स्टैंड यूएसबी के माध्यम से कंप्यूटर से जुड़ा हुआ है। आपको USB से कंप्यूटर से FPGA डाउनलोड करने की आवश्यकता है।

अपने दोहरे चैनल अवतार - FT2232H में FTDI का उपयोग करते हुए एक पीसी से कनेक्ट करने का निर्णय लिया गया था। एक चैनल को FPGA कॉन्फ़िगरेशन के लिए उपयोग किया जाएगा, दूसरे का उपयोग उच्च गति वाले FIFO एक्सचेंज के लिए किया जा सकता है।


FTDI में MORPH-IC-II डिबग बोर्ड होता है, जहां Cyclone II FPGA को USB के माध्यम से फ्लैश किया जाता है। पब्लिक डोमेन में अवधारणाओं। बूटलोडर का स्रोत कोड आंशिक रूप से खुला है: बूटलोडर स्वयं उपलब्ध है, हालांकि, एफटीडीआई के साथ काम करने के सभी तर्क एक निजी पुस्तकालय में ले जाया जाता है और इसे संशोधित नहीं किया जा सकता है। सच में, मैंने मूल रूप से अपने प्रोजेक्ट में इस बूटलोडर का उपयोग करने की योजना बनाई है, या, चरम मामलों में, उनके dll के आधार पर अपना शेल बनाते हैं। फर्मवेयर को FPGA में निष्क्रिय सीरियल मोड (निष्क्रिय धारावाहिक - PS) में लोड किया जाता है, FTDI MPSSE मोड में संचालित होता है। ब्रेडबोर्ड पर, MORPH-IC-II समाधान के प्रदर्शन की पूरी तरह से पुष्टि की गई थी, लेकिन समस्या, जैसा कि अक्सर होता है, जहां से नहीं आया था। यह पता चला है कि dll MORPH-IC-II के संचालन के दौरान, सभी कनेक्ट किए गए FTDI उपकरण अवरुद्ध हैं, और प्रशिक्षण परिसर के हिस्से के रूप में समान कन्वर्टर्स के साथ दो और डिवाइस हैं: एक जनरेटर और एक सिग्नल विश्लेषक। उनके साथ एक साथ काम करना संभव नहीं है। लानत है अजीब और कष्टप्रद।


इसी तरह का एक मामला मार्स रोवर के लोगों द्वारा लागू किया गया था: यूएसबी जेटीजी प्रोग्रामर एमबीएफटीडीआई । FTDI का उपयोग MPSSE मोड में भी किया जाता है, लेकिन MORPH-IC-II के विपरीत, JPGAG मोड में FPGA संचालन किया जाता है। स्रोत स्वतंत्र रूप से उपलब्ध हैं, लेकिन मुझे उनकी स्थिति (लाइसेंस) का स्पष्ट संकेत नहीं मिला। इसलिए, एक वाणिज्यिक परियोजना में उनका उपयोग करने के लिए, मेरा हाथ नहीं बढ़ा।


मैं ऐसी गलती को सुधारूंगा, इस लेख के ढांचे में प्रस्तुत किया जाने वाला सब कुछ बीएसडी लाइसेंस के तहत एक खुले भंडार में पोस्ट किया जाएगा।


FPGA चिप के लिए कॉन्फ़िगरेशन फ़ाइल डाउनलोड करें


सबसे पहले, आपको FPGA बूट मोड से निपटना चाहिए। उन लोगों के लिए जो अभी विषय से परिचित होना शुरू कर रहे हैं, मैं एक छोटा सा भ्रमण दूंगा। हालाँकि मेरे बोर्ड पर चक्रवात IV E परिवार के Altera (Intel) FPGAs स्थापित हैं, लेकिन लोडिंग के तरीके पूरे Cyclone FPGA समूह के लिए समान हैं, और इस बात पर संदेह है कि एक या दूसरे रूप में वे कई अन्य परिवारों के लिए उपयुक्त हैं।


इस प्रकार का FPGA कॉन्फ़िगरेशन डेटा संग्रहीत करने के लिए अस्थिर SRAM का उपयोग करता है। ये कॉन्फ़िगरेशन डेटा परिणामी डिवाइस की कार्यक्षमता निर्धारित करते हैं। पेशेवर शब्दजाल में, इस डेटा को अक्सर "फर्मवेयर" कहा जाता है। इस प्रकार, फर्मवेयर को एक विशेष रैम में संग्रहीत किया जाता है और हर बार जब डिवाइस चालू होता है, तो उसे FPGA चिप में लोड किया जाना चाहिए। कई तरीके (कॉन्फ़िगरेशन योजनाएं) हैं जिनके द्वारा फर्मवेयर को SRAM में लोड किया जा सकता है (सूची चक्रवात IV ई के लिए प्रासंगिक है):


  1. सक्रिय धारावाहिक (एएस)।
  2. सक्रिय समानांतर (एपी)
  3. निष्क्रिय धारावाहिक (PS)
  4. तेजी से निष्क्रिय समानांतर (एफपीपी)।
  5. JTAG।

FPGA (MSEL समूह) के बाहरी टर्मिनलों का उपयोग करके एक विशिष्ट बूट मोड का चुनाव किया जाता है। JTAG मोड हमेशा उपलब्ध है। सक्रिय मोड का अर्थ है कि जब बिजली लागू होती है, तो FPGA स्वतंत्र रूप से बाहरी मेमोरी (सीरियल या समानांतर) से डेटा पढ़ता है। निष्क्रिय मोड में, FPGA एक बाहरी माध्यम के लिए विन्यास डेटा को उसमें स्थानांतरित करने के लिए प्रतीक्षा करता है। ये योजनाएं मास्टर (मास्टर) - दास (दास) की अवधारणा में अच्छी तरह से फिट होती हैं। सक्रिय मोड में, FPGA एक मास्टर के रूप में और एक गुलाम के रूप में निष्क्रिय मोड में कार्य करता है।


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



कॉन्फ़िगरेशन शुरू करने के लिए, बाहरी मास्टर को nCONFIG लाइन पर कम से उच्च संक्रमण उत्पन्न करना चाहिए। जैसे ही FPGA डेटा प्राप्त करने के लिए तैयार होता है, यह nSTATUS लाइन पर एक उच्च स्तर बनाएगा । उसके बाद, मास्टर डेटा लाइन [0] पर डेटा ट्रांसमिट करना शुरू कर सकता है, और DCLK लाइन पर संबंधित क्लॉक दालें। CONF_DONE लाइन (या डेटा समाप्त नहीं होता है) पर एक उच्च स्तर स्थापित होने तक डेटा को लक्ष्य डिवाइस में प्रेषित किया जाना चाहिए, और FPGA प्रारंभिक अवस्था में स्विच हो जाता है। यह ध्यान दिया जाना चाहिए कि CONF_DONE के एक पर सेट होने के बाद, दो और घड़ी दालों को लागू किया जाना चाहिए ताकि FPGA प्रारंभिक शुरुआत हो।


डेटा को कम से कम महत्वपूर्ण बिट ( LSB ) द्वारा प्रेषित किया जाता है, अर्थात, यदि कॉन्फ़िगरेशन फ़ाइल में अनुक्रम 02 1B EE 01 FA (उदाहरण के लिए हैंडबुक से है) को शामिल करें, तो अनुक्रम को डेटा लाइन पर बनाया जाना चाहिए:


0100-0000 1101-1000 0111-0111 1000-0000 0101-1111 

इस प्रकार, केवल पांच लाइनों का उपयोग किया जाता है: सीरियल ट्रांसमिशन के लिए डेटा लाइनें [0] और DCLK , नियंत्रण के लिए nCONFIG , nSTATUS , CONF_DONE लाइनें
इसके मूल में, पीएस मोड अतिरिक्त ध्वज हेरफेर के साथ एसपीआई से ज्यादा कुछ नहीं है।
डेटा ट्रांसफर दर प्रलेखन में इंगित अधिकतम आवृत्ति से कम होनी चाहिए; परियोजना में उपयोग किए जाने वाले चक्रवात IV ई श्रृंखला के लिए, यह 66 मेगाहर्ट्ज है।


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


नीचे दिया गया आंकड़ा सबसे महत्वपूर्ण समय के साथ इंटरफ़ेस का समय आरेख दिखाता है।



धूर्त जानवर MPSSE


MPSSE मोड में FTDI के संचालन पर विचार करें। MPSSE (मल्टी-प्रोटोकॉल सिंक्रोनस सीरियल इंजन) मोड, मेरी राय में, एसपीआई, आई 2 सी, जेटीएजी, 1-वायर और कई जैसे व्यापक डेटा ट्रांसफर प्रोटोकॉल को लागू करने का अवसर देने के लिए, कुछ प्रकार के सीरियल इंटरफ़ेस डिजाइनर बनाने का कम या ज्यादा सफल प्रयास है। दूसरों के आधार पर।


वर्तमान में, मोड microcircuits के लिए उपलब्ध है: FT232H, FT2232D, FT2232H, FT4232H। अपनी परियोजना में मैं FT2232H का उपयोग करता हूं, इसलिए बड़ी हद तक हम इसके बारे में बात कर रहे हैं। एमपीएसएसई मोड के लिए, 16 पैरों को आवंटित किया जाता है, दो बाइट्स में विभाजित किया जाता है: निचला एल और उच्चतम एच। प्रत्येक बाइट को पढ़ा या सेट किया जा सकता है। बाइट एल के चार निचले पैरों में विशेष कार्य हैं - उनके माध्यम से सीरियल डेटा ट्रांसमिशन हो सकता है। प्रत्येक पैर को इनपुट या आउटपुट के रूप में कॉन्फ़िगर किया जा सकता है, आउटपुट के लिए एक डिफ़ॉल्ट मान सेट किया जा सकता है। अनुक्रमिक संचरण के लिए, बिट्स ( MSB / LSB ), प्रेषित शब्द की लंबाई, घड़ी की आवृत्ति, सिंक्रनाइज़ेशन फ्रंट - फ्रंट (राइजिंग) या रियर (फॉलिंग) का क्रम, आप बिना डेटा के केवल घड़ी दालों को प्रसारित करना चुन सकते हैं, या 3-चरण घड़ी चुन सकते हैं (I2C के लिए प्रासंगिक) और भी बहुत कुछ।


प्रोग्रामिंग के लिए निर्बाध रूप से आगे बढ़ें। FTDI चिप्स के साथ सॉफ्टवेयर इंटरैक्शन के दो वैकल्पिक तरीके हैं: पहला, चलो इसे क्लासिक कहते हैं, इस मामले में, जब एक यूएसबी पोर्ट से जुड़ा होता है, तो सिस्टम में चिप को वर्चुअल सीरियल पोर्ट (COM) के रूप में परिभाषित किया जाता है, ऑपरेटिंग सिस्टम वीसीपी ड्राइवर (वर्चुअल कॉम पोर्ट) का उपयोग करता है। सभी अन्य प्रोग्रामिंग क्लासिक COM पोर्ट की प्रोग्रामिंग से अलग नहीं हैं: खोला - प्रेषित / गिना - बंद। और यह विभिन्न ऑपरेटिंग सिस्टम के लिए सही है, जिसमें लिनक्स और मैक ओएस शामिल हैं। हालांकि, इस दृष्टिकोण के साथ, एफटीडीआई नियंत्रक की सभी विशेषताओं का एहसास करना संभव नहीं होगा - चिप यूएसबी-यूएआरटी एडाप्टर के रूप में काम करेगा। दूसरी विधि FTD2XX मालिकाना पुस्तकालय द्वारा प्रदान की जाती है, यह इंटरफ़ेस विशेष कार्य प्रदान करता है जो मानक COM पोर्ट एपीआई में उपलब्ध नहीं हैं, विशेष रूप से, विशेष ऑपरेटिंग मोड, जैसे एमपीएसएसई, 245 एफआईएफओ, बिट-बैंग को कॉन्फ़िगर और उपयोग करना संभव है। FTD2XX एपीआई लाइब्रेरी सॉफ्टवेयर एप्लीकेशन डेवलपमेंट D2XX प्रोग्रामर गाइड द्वारा अच्छी तरह से प्रलेखित है, जिसे व्यापक रूप से संकीर्ण क्षेत्रों में लंबे समय से जाना जाता है। और हां, विभिन्न ऑपरेटिंग सिस्टम के लिए FTD2XX भी उपलब्ध है।


FTDI डेवलपर्स को मौजूदा D2XX सॉफ़्टवेयर इंटरैक्शन मॉडल में अपेक्षाकृत नए MPSSE को एकीकृत करने के कार्य के साथ सामना करना पड़ा। और वे सफल हुए, MPSSE मोड में काम करने के लिए उसी प्रकार के फ़ंक्शन का उपयोग अन्य "शास्त्रीय" मोड के लिए किया जाता है, उसी लाइब्रेरी FTD2XX एपीआई का उपयोग किया जाता है।


संक्षेप में, एमपीएसएसई मोड में संचालन के लिए एल्गोरिथ्म को निम्नानुसार वर्णित किया जा सकता है:


  1. डिवाइस को सिस्टम में ढूंढें और इसे खोलें।
  2. चिप को इनिशियलाइज़ करें और इसे MPSSE मोड में डालें।
  3. MPSEE के ऑपरेशन मोड को सेट करें।
  4. डेटा के साथ प्रत्यक्ष कार्य: GPIO को प्रसारित, प्राप्त करना, प्रबंधित करना - हम लक्ष्य विनिमय प्रोटोकॉल को लागू करते हैं।
  5. डिवाइस को बंद करें।

बूटलोडर लिखना


चलो व्यावहारिक भाग के लिए नीचे उतरो। अपने प्रयोगों में, मैं IDE के रूप में Oxygen.3a रिलीज़ (4.7.3a) के ग्रहण संस्करण और कंपाइलर के रूप में mingw32-gcc (6.3.0) का उपयोग करूंगा। Win7 ऑपरेटिंग सिस्टम।


FTDI वेबसाइट से हम अपने ऑपरेटिंग सिस्टम के लिए ड्राइवर का नवीनतम वर्तमान संस्करण डाउनलोड करते हैं। संग्रह में हम सभी एपीआई कार्यों के विवरण के साथ हेडर फ़ाइल ftd2xx.h को ढूंढते हैं। एपीआई खुद को ftd2xx.dll के रूप में लागू किया गया है, लेकिन हम बाद के लिए गतिशील आयात छोड़ देंगे, और स्थैतिक लिंक का उपयोग करेंगे: हमें लाइब्रेरी फ़ाइल ftd2xx.lib की आवश्यकता है। मेरे मामले के लिए, ftd2xx.lib i386 निर्देशिका में है।


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


एक बिंदु। एक डिवाइस ढूंढें और इसे खोलें


FTD2XX एपीआई आपको इसके बारे में एक या किसी अन्य ज्ञात जानकारी का उपयोग करके चिप को खोलने की अनुमति देता है। यह सिस्टम में इसका सीरियल नंबर हो सकता है: पहले कनेक्टेड FTDI चिप नंबर 0, अगले 1 और इतने पर ले जाएगा। सिस्टम में संख्या को उस क्रम से निर्धारित किया जाता है जिसमें माइक्रोक्रिस्केट जुड़े होते हैं, इसे हल्के ढंग से लगाने के लिए, यह हमेशा सुविधाजनक नहीं होता है। चिप को नंबर से खोलने के लिए, FT_Open फ़ंक्शन का FT_Open । आप इसके सीरियल नंबर ( FT_OPEN_BY_SERIAL_NUMBER ), विवरण ( FT_OPEN_BY_DESCRIPTION ) या स्थान ( FT_OPEN_BY_LOCATION ) द्वारा चिप को खोल सकते हैं, इसके लिए FT_OpenEx फ़ंक्शन का FT_OpenEx । सीरियल नंबर और विवरण चिप की आंतरिक मेमोरी में संग्रहीत होते हैं और डिवाइस के निर्माण के दौरान एफटीडीआई के साथ स्थापित किए जाने के दौरान वहां रिकॉर्ड किए जा सकते हैं। विवरण, एक नियम के रूप में, डिवाइस या परिवार के प्रकार की विशेषता है, और प्रत्येक उत्पाद के लिए सीरियल नंबर अद्वितीय होना चाहिए। इसलिए, विकसित किए जा रहे कार्यक्रम द्वारा समर्थित उपकरणों की पहचान करने का सबसे सुविधाजनक तरीका इसका विवरण है। हम विवरण (डिस्क्रिप्टर) के अनुसार एफटीडीआई चिप खोलेंगे। वास्तव में, अगर हम शुरू में चिप डिस्क्रिप्टर लाइन को जानते थे, तो हमें सिस्टम में डिवाइस देखने की जरूरत नहीं है, हालांकि, एक प्रयोग के रूप में, हम FTDI के साथ कंप्यूटर से जुड़े सभी उपकरणों को प्रदर्शित करेंगे। FT_CreateDeviceInfoList फ़ंक्शन का उपयोग करते FT_CreateDeviceInfoList , FT_CreateDeviceInfoList कनेक्ट किए गए चिप्स की एक विस्तृत सूची बनाएंगे, और FT_GetDeviceInfoList फ़ंक्शन का उपयोग करते FT_GetDeviceInfoList , FT_GetDeviceInfoList पर विचार करेंगे।


जुड़े उपकरणों की सूची। लिस्टिंग:
 ftStatus = FT_CreateDeviceInfoList(&numDevs); if (ftStatus == FT_OK) { printf("Number of devices is %d\n",numDevs); } if (numDevs == 0) return -1; // allocate storage for list based on numDevs devInfo = (FT_DEVICE_LIST_INFO_NODE*)malloc(sizeof(FT_DEVICE_LIST_INFO_NODE)*numDevs); ftStatus = FT_GetDeviceInfoList(devInfo,&numDevs); if (ftStatus == FT_OK) for (int i = 0; i < numDevs; i++) { printf("Dev %d:\n",i); printf(" Flags=0x%x\n",devInfo[i].Flags); printf(" Type=0x%x\n",devInfo[i].Type); printf(" ID=0x%x\n",devInfo[i].ID); printf(" LocId=0x%x\n",devInfo[i].LocId); printf(" SerialNumber=%s\n",devInfo[i].SerialNumber); printf(" Description=%s\n",devInfo[i].Description); } 

आपका स्वागत है मेरा चिड़ियाघर
 D:\workspace\ftdi-mpsse-ps\Debug>ftdi-mpsse-ps.exe Number of devices is 4 Dev 0: Flags = 0x0 Type = 0x5 ID = 0x4036001 LocId = 0x214 SerialNumber = AI043NNV Description = FT232R USB UART Dev 1: Flags = 0x2 Type = 0x6 ID = 0x4036010 LocId = 0x2121 SerialNumber = L731T70OA Description = LESO7 A Dev 2: Flags = 0x2 Type = 0x6 ID = 0x4036010 LocId = 0x2122 SerialNumber = L731T70OB Description = LESO7 B Dev 3: Flags = 0x2 Type = 0x8 ID = 0x4036014 LocId = 0x213 SerialNumber = FTYZ92L6 Description = LESO4.1_ER 

FTDI चिप्स के साथ तीन डिवाइस मेरे पीसी से जुड़े हैं: FT232RL (टाइप 0x5), FT2232H (टाइप 0x6) और FT232H (टेप 0x8)। सिस्टम में FT2232H चिप को दो स्वतंत्र उपकरणों (देव 1 और देव 2) के रूप में प्रदर्शित किया गया था। FPGA PS इंटरफ़ेस देव 2 से जुड़ा है, इसका विवरण "LESO7 B" है। इसे खोलें:


 //Open a device with device description "LESO7 B" ftStatus = FT_OpenEx("LESO7 B", FT_OPEN_BY_DESCRIPTION, &ftHandle); if (ftStatus != FT_OK) { printf ("pen failure\r\n"); return -1; } 

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


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


चिप के साथ काम खत्म करने के बाद, आपको इसे बंद करने की आवश्यकता है। ऐसा करने के लिए, FT_Close फ़ंक्शन का उपयोग करें:


 FT_Close(ftHandle); 

प्वाइंट 2. चिप को इनिशियलाइज़ करें और MPSSE चालू करें


सेटिंग अधिकांश मोड के लिए विशिष्ट है और इसे AN_135 FTDI MPSSE मूल बातें प्रलेखन में अच्छी तरह से वर्णित किया गया है।


  1. हम चिप का एक रीसेट (rezet) करते हैं। FT_ResetDevice फ़ंक्शन।
  2. यदि प्राप्त बफर में कोई कचरा है, तो हम इसे साफ करते हैं। FT_Purge फ़ंक्शन।
  3. पढ़ने और लिखने के लिए बफ़र्स के आकार को समायोजित करें। फ़ंक्शन FT_SetUSBParameters
  4. समता को बंद करें। FT_SetChars
  5. हम पढ़ने और लिखने के लिए समय निर्धारित करते हैं। डिफ़ॉल्ट रूप से, टाइमआउट अक्षम हैं, ट्रांसमिशन टाइमआउट सक्षम करें। FT_SetTimeouts
  6. हम चिप से होस्ट को एक पैकेट भेजने के लिए प्रतीक्षा समय को कॉन्फ़िगर करते हैं। डिफ़ॉल्ट रूप से, 16 एमएस, 1 एमएस में तेजी लाएं। FT_SetLatencyTimer
  7. आने वाले अनुरोधों को सिंक्रनाइज़ करने के लिए प्रवाह नियंत्रण चालू करें। FT_SetFlowControl
  8. MPSSE मोड को सक्रिय करने के लिए सब कुछ तैयार है। MPSSE नियंत्रक रीसेट करें। हम FT_SetBitMode फ़ंक्शन का उपयोग करते हैं, मोड को 0 (मोड = 0, मास्क = 0) पर सेट करते हैं।
  9. MPSSE मोड चालू करें। फंक्शन FT_SetBitMode - मोड = 2, मुखौटा = 0।

हम MPSSE_open फ़ंक्शन में चिप को एकजुट करते हैं और कॉन्फ़िगर करते हैं, एक पैरामीटर के रूप में हम खोले जाने वाले डिवाइस के हैंडल के साथ एक पंक्ति पास करते हैं:


लिस्टिंग MPSSE_open
 static FT_STATUS MPSSE_open (char *description) { FT_STATUS ftStatus; ftStatus = FT_OpenEx(description, FT_OPEN_BY_DESCRIPTION, &ftHandle); if (ftStatus != FT_OK) { printf ("open failure\r\n"); return FT_DEVICE_NOT_OPENED; } printf ("open OK, %d\r\n", ftHandle); printf("\nConfiguring port for MPSSE use...\n"); ftStatus |= FT_ResetDevice(ftHandle); //Purge USB receive buffer first by reading out all old data from FT2232H receive buff: ftStatus |= FT_Purge(ftHandle, FT_PURGE_RX); //Set USB request transfer sizes to 64K: ftStatus |= FT_SetUSBParameters(ftHandle, 65536, 65536); //Disable event and error characters: ftStatus |= FT_SetChars(ftHandle, 0, 0, 0, 0); //Sets the read and write timeouts in milliseconds: ftStatus |= FT_SetTimeouts(ftHandle, 0, 5000); //Set the latency timer to 1mS (default is 16mS): ftStatus |= FT_SetLatencyTimer(ftHandle, 1); //Turn on flow control to synchronize IN requests: ftStatus |= FT_SetFlowControl(ftHandle, FT_FLOW_RTS_CTS, 0x00, 0x00); //Reset controller: ftStatus |= FT_SetBitMode(ftHandle, 0x0, FT_BITMODE_RESET); //Enable MPSSE mode: ftStatus |= FT_SetBitMode(ftHandle, 0x0, FT_BITMODE_MPSSE); if (ftStatus != FT_OK) { printf("Error in initializing the MPSSE %d\n", ftStatus); return FT_OTHER_ERROR; } Sleep(50); // Wait for all the USB stuff to complete and work return FT_OK; } 

मद 3. ऑपरेशन के MPSEE मोड को कॉन्फ़िगर करें


दरअसल, इस स्तर पर MPSSE प्रोसेसर सक्रिय है और कमांड प्राप्त करने के लिए तैयार है। कमांड बाइट सीक्वेंस हैं, जिनमें से पहला बाइट "ऑप-कोड" है, जिसके बाद कमांड पैरामीटर हैं। आदेश में पैरामीटर नहीं हो सकता है और इसमें एक "ऑप-कोड" शामिल हो सकता है। FT_Write फ़ंक्शन का उपयोग करके कमांड प्रसारित किए जाते हैं, MPSSE प्रोसेसर से एक प्रतिक्रिया FT_Read फ़ंक्शन का उपयोग करके प्राप्त की जा सकती है।


प्रत्येक कमांड भेजने के बाद, प्रोसेसर की प्रतिक्रिया को पढ़ना उपयोगी है, क्योंकि गलत कमांड के मामले में, प्रतिक्रिया में त्रुटि संदेश हो सकता है - वर्ण 0xFA। "खराब कमांड - 0xFA प्रतिक्रिया" तंत्र का उपयोग एमपीएसएसई प्रोसेसर के साथ एप्लिकेशन प्रोग्राम को सिंक्रनाइज़ करने के लिए किया जा सकता है। यदि सब कुछ ठीक है, तो चिप 0xFA वर्ण को जानबूझकर गलत आदेश पर वापस कर देगा। MPSSE और MCU होस्ट बस एमुलेशन मोड के लिए कमांड प्रोसेसर में Op-कोड वर्णित हैं।
MPSSE को कॉन्फ़िगर करना I / O लाइनों की डेटा दर, दिशा और प्रारंभिक अवस्थाओं को निर्धारित करने के लिए आता है।
MPSSE प्रोसेसर की डेटा दर निर्धारित करने पर विचार करें। केवल पूर्ण गति मोड (FT2232 D ) के लिए समर्थन के साथ चिप्स के लिए सेटिंग्स और उच्च गति (FT2232 H , FT232H, FT4232H) के साथ चिप्स कुछ अलग हैं। विरासत FT2232D 12MHz घड़ी का उपयोग करता है, जबकि आधुनिक 60MHz का उपयोग करते हैं। इसलिए डेटा अंतरण दर की गणना के लिए सूत्र:


ि= fracfcore(1+) cdot2


जहां एफ कोर एफटीडीआई कोर फ्रिक्वेंसी है, डिविज़र एक दो-बाइट विभक्त है, जो वास्तव में, डेटा क्लॉक फ़्रीक्वेंसी सेट करता है।
नतीजतन, यदि विभक्त शून्य के बराबर है, तो अधिकतम डेटा अंतरण दर 30 एमबीपीएस होगी, और न्यूनतम डेटा अंतरण दर 65535 - 458 बिट / एस पर होगी।
हम प्रीप्रोसेसर को डिवाइडर की गणना सौंपेंगे। मैक्रो डिविज़र लौटाता है:


 #define FCORE 60000000ul #define MPSSE_DATA_SPEED_DIV(data_speed) ((FCORE/(2*data_speed)) -1) 

और ये दो मैक्रोज़ क्रमशः विभक्त के उच्च और निम्न बाइट्स लौटाते हैं:


 #define MPSSE_DATA_SPEED_DIV_H(data_speed) ((MPSSE_DATA_SPEED_DIV(data_speed)) >> 8) #define MPSSE_DATA_SPEED_DIV_L(data_speed) \ (MPSSE_DATA_SPEED_DIV(data_speed) - (MPSSE_DATA_SPEED_DIV_H(data_speed)<< 8)) 

इसके अलावा, यह ध्यान दिया जाना चाहिए कि पुराने FT2232D के साथ संगतता के लिए आधुनिक चिप्स में एक अतिरिक्त 5 विभक्त है, जो 60 मेगाहर्ट्ज को 12 मेगाहर्ट्ज में बदल देता है। यह विभेदक डिफ़ॉल्ट रूप से सक्रिय है, हमारे मामले में इसे बंद कर दिया जाना चाहिए।
हम इसी ऑप-कोड (0x8A) और प्रोसेसर के लिए हेलमेट कमांड पाते हैं:


टीम प्रस्तुत सूची
 BYTE byOutputBuffer[8], byInputBuffer[8]; DWORD dwNumBytesToRead, dwNumBytesSent = 0, dwNumBytesRead = 0; byOutputBuffer[0] = 0x8A; ftStatus = FT_Write(ftHandle, byOutputBuffer, 1, &dwNumBytesSent); Sleep(2); // Wait for data to be transmitted and status ftStatus = FT_GetQueueStatus(ftHandle, &dwNumBytesToRead); ftStatus |= FT_Read(ftHandle, byInputBuffer, dwNumBytesToRead, &dwNumBytesRead); if (ftStatus != FT_OK) { printf("Error\r\n"); return FT_OTHER_ERROR; } else if (dwNumBytesToRead > 0) { printf("dwNumBytesToRead = %d:", dwNumBytesToRead); for ( int i = 0; i < dwNumBytesToRead; i++) printf (" %02Xh", byInputBuffer[i]); printf("\r\n"); return FT_INVALID_PARAMETER; } return FT_OK; 

प्रयोग के रूप में, वास्तविक कमांड 0x8A के बजाय, हम 0xFE मान भेजेंगे, जो किसी भी ऑप-कोड के अनुरूप नहीं है, कंसोल आउटपुट:


 dwNumBytesToRead = 2: FAh FEh 

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



DCLK , DATA [0] , nCONFIG लाइनों को आउटपुट के रूप में कॉन्फ़िगर किया जाना चाहिए, nSTATUS , CONF_DONE लाइनों को इनपुट के रूप में। आरेख का उपयोग करते हुए, हम निर्धारित करते हैं कि लाइनों के पास प्रारंभिक अवस्था क्या होनी चाहिए। स्पष्टता के लिए, सर्किट के पिनआउट को तालिका में संक्षेपित किया गया है:


FPGA पिनपिन नामपिनMPSSEदिशाचूक
DCLKBDBUS038टीसीके / एसकेबाहर0
DATA [0]BDBUS139TDI / डीओबाहर1
nCONFIGBDBUS240TDO / डिबाहर1
nSTATUSBDBUS341टीएमएस / सीएसमें1
CONF_DONEBDBUS443GPIOL0में1

उपयोग की जाने वाली सभी लाइनें MPSSE पोर्ट के निचले बाइट पर स्थित हैं। मान सेट करने के लिए, op-code 0x80 का उपयोग करें। यह कमांड दो तर्कों को मानता है: ऑप-कोड का अनुसरण करने वाली पहली बाइट बिट-बाय-बिट मान है, और दूसरी दिशा है (एक आउटपुट पोर्ट है, शून्य इनपुट पोर्ट है)।
"मैजिक नंबर" के खिलाफ लड़ाई के हिस्से के रूप में, सभी सीरियल लाइन नंबर और उनके डिफ़ॉल्ट मानों को स्थिरांक के रूप में स्वरूपित किया जाएगा:


बंदरगाहों को परिभाषित करें
 #define PORT_DIRECTION (0x07) #define DCLK (0) #define DATA0 (1) #define N_CONFIG (2) #define N_STATUS (3) #define CONF_DONE (4) // initial states of the MPSSE interface #define DCLK_DEF (1) #define DATA0_DEF (0) #define N_CONFIG_DEF (1) #define N_STATUS_DEF (1) #define CONF_DONE_DEF (1) 

यह केवल यह सुनिश्चित करने के लिए बना हुआ है कि TDI - TDO लूप अक्षम है (परीक्षण के लिए सक्रिय किया जा सकता है) और इसे एक अलग फ़ंक्शन में रखा जाए:


MPSSE_setup फ़ंक्शन सूचीबद्ध करना
 static FT_STATUS MPSSE_setup () { DWORD dwNumBytesToSend, dwNumBytesSent, dwNumBytesToRead, dwNumBytesRead; BYTE byOutputBuffer[8], byInputBuffer[8]; FT_STATUS ftStatus; // Multple commands can be sent to the MPSSE with one FT_Write dwNumBytesToSend = 0; // Start with a fresh index byOutputBuffer[dwNumBytesToSend++] = MPSSE_CMD_DISABLE_DIVIDER_5; byOutputBuffer[dwNumBytesToSend++] = MPSSE_CMD_DISABLE_ADAPTIVE_CLK; byOutputBuffer[dwNumBytesToSend++] = MPSSE_CMD_DISABLE_3PHASE_CLOCKING; ftStatus = FT_Write(ftHandle, byOutputBuffer, dwNumBytesToSend, &dwNumBytesSent); dwNumBytesToSend = 0; // Reset output buffer pointer // Set TCK frequency // Command to set clock divisor: byOutputBuffer[dwNumBytesToSend++] = MPSSE_CMD_SET_TCK_DIVISION; // Set ValueL of clock divisor: byOutputBuffer[dwNumBytesToSend++] = MPSSE_DATA_SPEED_DIV_L(DATA_SPEED); // Set 0xValueH of clock divisor: byOutputBuffer[dwNumBytesToSend++] = MPSSE_DATA_SPEED_DIV_H(DATA_SPEED); ftStatus |= FT_Write(ftHandle, byOutputBuffer, dwNumBytesToSend, &dwNumBytesSent); dwNumBytesToSend = 0; // Reset output buffer pointer // Set initial states of the MPSSE interface // - low byte, both pin directions and output values /* | FPGA pin | Pin Name | Pin | MPSSE | Dir | def | | --------- | -------- | --- | ------ | --- | --- | | DCLK | BDBUS0 | 38 | TCK/SK | Out | 0 | | DATA[0] | BDBUS1 | 39 | TDI/DO | Out | 1 | | nCONFIG | BDBUS2 | 40 | TDO/DI | Out | 1 | | nSTATUS | BDBUS3 | 41 | TMS/CS | In | 1 | | CONF_DONE | BDBUS4 | 43 | GPIOL0 | In | 1 | */ // Configure data bits low-byte of MPSSE port: byOutputBuffer[dwNumBytesToSend++] = MPSSE_CMD_SET_DATA_BITS_LOWBYTE; // Initial state config above: byOutputBuffer[dwNumBytesToSend++] = (DCLK_DEF << DCLK) | (DATA0_DEF << DATA0) | (N_CONFIG_DEF << N_CONFIG) | (N_STATUS_DEF << N_STATUS) | (CONF_DONE_DEF << CONF_DONE); // Direction config above: byOutputBuffer[dwNumBytesToSend++] = PORT_DIRECTION; ftStatus |= FT_Write(ftHandle, byOutputBuffer, dwNumBytesToSend, &dwNumBytesSent); // Send off the low GPIO config commands dwNumBytesToSend = 0; // Reset output buffer pointer // Set initial states of the MPSSE interface // - high byte, all input, Initial State -- 0. // Send off the high GPIO config commands: byOutputBuffer[dwNumBytesToSend++] = MPSSE_CMD_SET_DATA_BITS_HIGHBYTE; byOutputBuffer[dwNumBytesToSend++] = 0x00; byOutputBuffer[dwNumBytesToSend++] = 0x00; ftStatus |= FT_Write(ftHandle, byOutputBuffer, dwNumBytesToSend, &dwNumBytesSent); // Disable loopback: byOutputBuffer[dwNumBytesToSend++] = MPSSE_CMD_DISABLE_LOOP_TDI_TDO; ftStatus |= FT_Write(ftHandle, byOutputBuffer, dwNumBytesToSend, &dwNumBytesSent); Sleep(2); // Wait for data to be transmitted and status ftStatus = FT_GetQueueStatus(ftHandle, &dwNumBytesToRead); ftStatus |= FT_Read(ftHandle, byInputBuffer, dwNumBytesToRead, &dwNumBytesRead); if (ftStatus != FT_OK) { printf("Unknown error in initializing the MPSSE\r\n"); return FT_OTHER_ERROR; } else if (dwNumBytesToRead > 0) { printf("Error in initializing the MPSSE, bad code:\r\n"); for ( int i = 0; i < dwNumBytesToRead; i++) printf (" %02Xh", byInputBuffer[i]); printf("\r\n"); return FT_INVALID_PARAMETER; } return FT_OK; } 

बिंदु 4. हम लोडिंग प्रोटोकॉल को लागू करते हैं


व्यावहारिक प्रयोगों के लिए सब कुछ तैयार लगता है। सबसे पहले, जांच लें कि प्रारंभिककरण सही ढंग से किया गया है, कार्यक्रम के मुख्य निकाय में, MPSSE_open() और MPSSE_setup() कॉल करें, और डिवाइस ( FT_Close ) को बंद करने से पहले, हम एक खाली getchar() डालते हैं। प्रोग्राम को चलाएं और ऑसिलोस्कोप का उपयोग करके यह सुनिश्चित करें कि सभी पीएस लाइनें डिफ़ॉल्ट स्तर पर सेट हैं। आरंभीकरण में इन स्तरों के मूल्य को बदलना (FPGA के साथ कुछ भी बुरा नहीं होगा), हम यह सुनिश्चित करते हैं कि MPSSE प्रोसेसर वांछित परिणाम को वैध बनाता है - सब कुछ पर्याप्त रूप से काम करता है और आप डेटा स्थानांतरित करने के लिए आगे बढ़ सकते हैं।
समान ऑप-कोड का उपयोग करके कमांड मोड में अनुक्रमिक भेजने और प्राप्त करने का कार्य किया जाता है। कमांड का पहला बाइट ऑप-कोड है, जो ऑपरेशन के प्रकार को निर्धारित करता है, इसके बाद प्रेषित या प्राप्त अनुक्रम की लंबाई और, अगर यह एक ट्रांसमिशन है, तो वास्तविक डेटा। MPSSE प्रोसेसर डेटा भेज और प्राप्त कर सकता है, वह भी उसी समय कर सकता है। ट्रांसमिशन या तो कम से कम महत्वपूर्ण बिट फॉरवर्ड (एलएसबी) या सबसे महत्वपूर्ण (एमएसबी) हो सकता है। डेटा ट्रांसमिशन या तो घड़ी की दालों के अग्रणी या पीछे के किनारों पर हो सकता है। विकल्पों के प्रत्येक संयोजन का अपना ऑप-कोड होता है, प्रत्येक ऑप-कोड बिट ऑपरेशन मोड का वर्णन करता है:


बिटसमारोह
0फ्रंट-राइट सिंक्रोनाइज़ेशन: 0 - पॉजिटिव, 1 - नेगेटिव
11 - बाइट्स के साथ काम करें, 0 - बिट्स के साथ काम करें
2पढ़ने के लिए सामने का किनारा: 0 - सकारात्मक, 1 - नकारात्मक
3ट्रांसमिशन मोड: 1 - एलएसबी, 0 - एमएसबी पहले
4TDI डेटा संचरण
5एक TDO लाइन से डेटा पढ़ना
6टीएमएस डेटा ट्रांसमिशन
70 होना चाहिए, अन्यथा यह आदेशों का एक और समूह है

पीएस योजना के अनुसार FPGAs को कॉन्फ़िगर करते समय, डेटा LSB मोड में अग्रणी किनारे पर प्रेषित होता है। , , op-code 0001_1000b 0x18 . ( , ), . : . , , 0, 65536, 65535. , . MPSSE_send .


MPSSE_send
 static BYTE byBuffer[65536 + 3]; static FT_STATUS MPSSE_send(BYTE * buff, DWORD dwBytesToWrite) { DWORD dwNumBytesToSend = 0, dwNumBytesSent, bytes; FT_STATUS ftStatus; // Output on rising clock, no input // MSB first, clock a number of bytes out byBuffer[dwNumBytesToSend++] = MPSSE_CMD_LSB_DATA_OUT_BYTES_POS_EDGE; // 0x18 bytes = dwBytesToWrite -1; byBuffer[dwNumBytesToSend++] = (bytes) & 0xFF; // Length L byBuffer[dwNumBytesToSend++] = (bytes >> 8) & 0xFF; // Length H memcpy(&byBuffer[dwNumBytesToSend], buff, dwBytesToWrite); dwNumBytesToSend += dwBytesToWrite; ftStatus = FT_Write(ftHandle, byBuffer, dwNumBytesToSend, &dwNumBytesSent); if (ftStatus != FT_OK ) { printf ("ERROR send data\r\n"); return ftStatus; } else if (dwNumBytesSent != dwNumBytesToSend) { printf ("ERROR send data, %d %d\r\n", dwNumBytesSent, dwNumBytesToSend); } return FT_OK; } 

— 65 , - , op-code . byBuffer , buff , , op-code . , , .
, "" , 25 , , , 1 ( , #define DATA_SPEED 1000000ul ). :


 BYTE byOutputBuffer[] = {0x02, 0x1B, 0xEE, 0x01, 0xFA}; MPSSE_send(byOutputBuffer, sizeof(byOutputBuffer)); 

( ):


DATA[0] , — DCLK . . , , .


, SPI ( ). , PS, . nCONFIG , nSTATUS , CONF_DONE . — , , — , .


MPSSE_get_lbyte , , .


MPSSE_get_lbyte
 static FT_STATUS MPSSE_get_lbyte(BYTE *lbyte) { DWORD dwNumBytesToSend, dwNumBytesSent, dwNumBytesToRead, dwNumBytesRead; BYTE byOutputBuffer[8]; FT_STATUS ftStatus; dwNumBytesToSend = 0; byOutputBuffer[dwNumBytesToSend++] = MPSSE_CMD_GET_DATA_BITS_LOWBYTE; ftStatus = FT_Write(ftHandle, byOutputBuffer, dwNumBytesToSend, &dwNumBytesSent); Sleep(2); // Wait for data to be transmitted and status ftStatus = FT_GetQueueStatus(ftHandle, &dwNumBytesToRead); ftStatus |= FT_Read(ftHandle, lbyte, dwNumBytesToRead, &dwNumBytesRead); if ((ftStatus != FT_OK) & (dwNumBytesToRead != 1)) { printf("Error read Lbyte\r\n"); return FT_OTHER_ERROR; // Exit with error } return FT_OK; } 

, op-code , . , - , , . , . MPSSE_set_lbyte :


MPSSE_set_lbyte
 static FT_STATUS MPSSE_set_lbyte(BYTE lb, BYTE mask) { DWORD dwNumBytesToSend, dwNumBytesSent; BYTE byOutputBuffer[8], lbyte; FT_STATUS ftStatus; ftStatus = MPSSE_get_lbyte(&lbyte); if ( ftStatus != FT_OK) return ftStatus; // Set to zero the bits selected by the mask: lbyte &= ~mask; // Setting zero is not selected by the mask bits: lb &= mask; lbyte |= lb; dwNumBytesToSend = 0; // Set data bits low-byte of MPSSE port: byOutputBuffer[dwNumBytesToSend++] = MPSSE_CMD_SET_DATA_BITS_LOWBYTE; byOutputBuffer[dwNumBytesToSend++] = lbyte; byOutputBuffer[dwNumBytesToSend++] = PORT_DIRECTION; ftStatus = FT_Write(ftHandle, byOutputBuffer, dwNumBytesToSend, &dwNumBytesSent); if ((ftStatus != FT_OK) & (dwNumBytesSent != 1)) { printf("Error set Lbyte\r\n"); return FT_OTHER_ERROR; } return FT_OK; } 

, . : FTDI; MPSSE; rbf- , nCONFIG , N_STATUS ; rbf- ; , , CONF_DONE . , MPSSE FTDI . , nCONFIG "" , , , .


main
 int main(int argc, char *argv[]) { FT_STATUS ftStatus; BYTE lowByte; DWORD numDevs; // create the device information list if ( argv[1] == NULL) { printf ("NO file\r\n"); return -1; } frbf = fopen(argv[1],"rb"); if (frbf == NULL) { printf ("Error open rbf\r\n"); return -1; } ftStatus = FT_CreateDeviceInfoList(&numDevs); if ((numDevs == 0) || (ftStatus != FT_OK)) { printf("Error. FTDI devices not found in the system\r\n"); return -1; } ftStatus = MPSSE_open ("LESO7 B"); if (ftStatus != FT_OK) { printf("Error in MPSSE_open %d\n", ftStatus); EXIT(-1); } MPSSE_setup(); if (ftStatus != FT_OK) { printf("Error in MPSSE_setup %d\n", ftStatus); EXIT(-1); } printf ("nConfig -> 0\r\n"); MPSSE_set_lbyte(0, 1 << N_CONFIG); printf ("nConfig -> 1\r\n"); MPSSE_set_lbyte(1 << N_CONFIG, 1 << N_CONFIG); if (MPSSE_get_lbyte(&lowByte) != FT_OK) { EXIT(-1); } if (((lowByte >> N_STATUS) & 1) == 0) { printf("Error. FPGA is not responding\r\n"); EXIT(-1); } int i = 0; size_t readBytes = 0; // Send the configuration file: do { readBytes = fread(buff, 1, MPSSE_PCK_SEND_SIZE, frbf); if (MPSSE_send(buff, readBytes) != FT_OK) EXIT(-1); putchar('*'); if (!((++i)%16)) printf("\r\n"); } while (readBytes == MPSSE_PCK_SEND_SIZE); printf("\r\n"); memset(buff, 0x00, sizeof(buff)); MPSSE_send(buff, 1); //        ? printf("Load complete\r\n"); // wait CONF_DONE set // A low-to-high transition on the CONF_DONE pin indicates that the configuration is // complete and initialization of the device can begin. i = 0; do { if (MPSSE_get_lbyte(&lowByte) != FT_OK) { printf ("Error read CONF_DONE\r\n"); EXIT(-1); } if (i++ > TIMEOUT_CONF_DONE) { printf ("Error CONF_DONE\r\n"); EXIT(-1); } Sleep(2); } while (((lowByte >> CONF_DONE) & 1) == 0); printf("Configuration complete\r\n"); FT_Close(ftHandle); fclose(frbf); } 

:


 pen "LESO7 B" OK nConfig -> 0 nConfig -> 1 ** Load complete Configuration complete 

rbf- . . 30 / .
, - JTAG.



  1. FTDI-MPSSE-Altera PS . .
  2. . . .
  3. Software Application Development D2XX Programmer's Guide . FTDI. API D2XX.
  4. FTDI MPSSE Basics. Application Note AN_135 . . FTDI MPSSE. .
  5. MPSSE और MCU होस्ट बस इम्यूलेशन मोड्स के लिए कमांड प्रोसेसर। आवेदन नोट AN_108ऑप-कोड के लिए संदर्भ। इसके बिना कोई रास्ता नहीं।
  6. D2XX ड्राइवरFTDI ड्राइवर।

Source: https://habr.com/ru/post/hi426131/


All Articles