كيفية التوقف عن كتابة البرامج الثابتة للميكروكونترولر. بدأنا نعيش ...


ومرة أخرى ، نكتشف كيف لا نكتب البرامج الثابتة للميكروكونترولر. أثارت المقالة السابقة الكثير من المشاعر لدى الناس ، ويبدو لي أن القليل من الناس فهموا ، وربما تم شرحه بشكل سيء لي لماذا بدأ كل هذا.


لذلك ، قمت بإعداد مثال .


على الرغم من أن هذه مجرد عينة من قرص DMA_Polling من مكتبة الأجهزة الطرفية القياسية.


ولكن هذه هي ميزة هذا النهج ، حيث يمكنك استخدام جميع التطورات من التعليمات البرمجية المنفذة على متحكم ، بما في ذلك المكتبات من الشركة المصنعة MK مثل HAL أو Standard Peripherals Library. وهذا يجب أن يكون عادلاً لأي وحدة تحكم تدعم openOCD - على الأقل STM32 و Atmel و PIC32 وغيرها على القائمة . في الوقت نفسه ، يمكننا استخدام جميع مكتبات الكمبيوتر المضيف ، وكذلك استخدام معايير لغة C ++ الجديدة. وإذا كتبت أغلفة ، فيمكنك عمومًا استخدام أي لغة. لكنني لم تعقّد الكثير هنا. لقد قررت فقط إظهار الوظائف والميزات الأساسية.


في المثال ، بالطبع ، سوف نرمش LED. وكذلك إرسال البيانات على UART وعلى UART آخر لاستقبالهم باستخدام DMA. باستخدام DMA يعطي مكافأة ضخمة. غالبًا ما يكون من الممكن التخلص من المقاطعات التي لا يمكننا استخدامها هنا ، والاقتراع ، الذي يكون بسبب مصحح الأخطاء الخاص بي بطيئًا جدًا ، ولكنه لا يزال أقل وقتًا لالتقاط البيانات على الواجهات. وأيضا توليد بسرعة. لذلك ، من السهل جدًا إنشاء مولد إشارة قابل للبرمجة ومتشمم للواجهات المختلفة.


تبقى المعدات التي سنختبرها من وقت المقالة الأولى


الصورة
هنا قمت بتوصيل الأسلاك البيضاء UART1 (PA9 pin) مع Rx UART2 (PA3 pin).


إذا نظرت إلى الكود
const char * message = "AddressIntercept PinTool UART DMA example"; int main() { sizeMemoryTranslate_t s = 0; memoryTranslate *p = getMemoryMap(&s); pAddrPERIPH = p[0].start_addr; pAddrSRAM = p[1].start_addr; init(); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); GPIO_InitTypeDef gpio; gpio.GPIO_Pin = GPIO_Pin_13; gpio.GPIO_Speed = GPIO_Speed_50MHz; gpio.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOC, &gpio); const size_t _SIZE_MESSAGE = strlen(message); printf("sending message "); for (int i = 0; i < _SIZE_MESSAGE; i++) { /* Send one byte from USARTy to USARTz */ USART_SendData(USARTy, message[i]); GPIO_SetBits(GPIOC, GPIO_Pin_13); /* Loop until USARTy DR register is empty */ while (USART_GetFlagStatus(USARTy, USART_FLAG_TXE) == RESET); printf("."); fflush(stdout); GPIO_ResetBits(GPIOC, GPIO_Pin_13); } printf("\n"); printf("qty of sent bytes %d\n", strlen(message)); const uint16_t rec = DMA_GetCurrDataCounter(USARTz_Rx_DMA_Channel); printf("qty of received byte using DMA : %d\n", sizeDMAbuf - rec); printf("read message from buffer DMA : "); const uint8_t *pM = (uint8_t *)pAddrSRAM; for (int r = 0; r < _SIZE_MESSAGE; r++) { printf("%c", pM[r]); fflush(stdout); } printf("\n"); assert(strncmp(message, (const char *)pM, _SIZE_MESSAGE) == 0); printf("Received and sent bytes are equal!\n"); return 0; } 

يمكنك أن ترى أنه باستثناء وظيفتنا المتمثلة في تحويل العناوين والوظائف من المكتبة القياسية ، فإن كل شيء آخر مأخوذ من SPL من ST ، من حيث المبدأ ، كان من الممكن استخدامه من وظيفة HAL. لكنني أكثر دراية بالحركة الشعبية القديمة الجيدة.


كيفية تجميع وتشغيل كل شيء


هذا مثال للكمبيوتر الشخصي مع Ubuntu 16.04 64 بت:


تحتاج أولاً إلى تنزيل Pintool v3.7


عملية فك الارتباط مريحة ، ثم يمكنك تحديد المتغير PIN_ROOT لإنشاء عميل PinTool أو ببساطة تحديد موقع عميلنا في


 pin-3.7-97619-g0d0c92f4f-gcc-linux/source/tools/ 

أفعل الطريقة الثانية


 cd pin-3.7-97619-g0d0c92f4f-gcc-linux/source/tools/ git clone git@github.com:ser-mk/AddressIntercept.git cd AddressIntercept 

بعد ذلك ، تحتاج إلى إنشاء عميل 32 بت


 make TARGET=ia32 

سوف يكون هنا ثنائي obj-ia32 / addrIntercept.so. مطلوب 32 بت ، لأنه في ARM ortex مثل حجم العنوان.


الآن يمكنك جمع المثال نفسه. أنا نسخها مباشرة إلى المجلد إلى عميل pintool


 cd pin-3.7-97619-g0d0c92f4f-gcc-linux/source/tools/AddressIntercept Git clone https://github.com/ser-mk/addrIntercept-example-UART-DMA Cd addrIntercept-example-UART-DMA Make 

ونحن نحصل على ثنائي في الدليل test.elf. علاوة على بساطة التجربة ، سأضع الملف في دليل عميل Pintool AddressIntercept الخاص بنا


قبل البدء في كل شيء ، نحتاج إلى إنشاء FIFOs مسمى للتواصل مع عميل OpenOCD


 cd pin-3.7-97619-g0d0c92f4f-gcc-linux/source/tools/AddressIntercept mkfifo in.fifo out.fifo 

in.fifo out.fifo - الأسماء الافتراضية لعملائنا ، يمكنك إعطاء أسماء أخرى ، ولكن بعد ذلك سيتعين تحديدها بشكل صريح عند بدء العملاء.


دعنا نبدأ عميل openOCD ، في حالتي أحتاج لتمرير خادم ip openOCD إليه ، سيكون 192.168.0.111 ، سيترك المنفذ 6666 القياسي ، لذلك أنا لا أحدده.


لذلك ، ركض بالترتيب


 cd pin-3.7-97619-g0d0c92f4f-gcc-linux/source/tools/AddressIntercept python3.5m OCDclient.py -ip 192.168.0.111 & ../../../pin -t obj-ia32/addrIntercept.so -- addrIntercept-example-UART-DMA/test.elf 

والنتيجة يجب أن تكون مثل هذا:


الصورة


آمل مثال توضيحي. بالفعل دليل على المفهوم الذي يمكن استخدامه.


علاوة على ذلك ، يجب أن يعمل كل شيء ، بما في ذلك على MacOS و Windows (هنا ، قد تضطر إلى تعديل العمل باستخدام fifo المسمى أو استبداله بما هو موجود في "windows").


علاوة على ذلك ، في المقالات التالية ، إذا كان الأمر ممتعًا ، يمكنك التحدث عن REPL كما في GIF من المقالة السابقة وطرق أخرى لاعتراض العناوين ، دون تقييد نظام Intel الأساسي.

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


All Articles