الهندسة العكسية الصناعية

قصة عملية الاقتراض في تطوير الالكترونيات على مثال جيد.



تسجيل سجل المصعد من الشم محلية الصنع


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


الجهاز نفسه هو زر استدعاء المصعد في الصورة على اليسار. للتجارب ، أعطوني نسختين ، واحدة منها يمكن تفكيكها بالكامل.


بدا خطة العمل الشاملة مثل هذا:


  1. دراسة لوحات الدارات الكهربائية
  2. دراسة قاعدة عنصر المجلس نفسه ؛
  3. رسم دائرتها الكهربائية ؛
  4. محاولة قراءة ملف البرنامج الثابت من متحكم ؛
  5. تفكيك البرامج الثابتة ؛
  6. استخراج خوارزمية العملية ؛
  7. تطوير مجلس إدارة جديد
  8. كتابة البرامج الثابتة الجديدة.

إذا فشلت الفقرة 4 ، فستكون الخطة الإضافية أكثر تعقيدًا ، لكنني كنت محظوظًا.


نحن ندرس التجريبية



متحكم رئيسي



قطعة من الدائرة الكهربائية للمصعد ، حيث تكون لوحاتنا محاطة بدائرة باللون الأحمر


تم تجميع اللوحة على متحكم 1997 ، AT89C2051 ، الذي يعتمد على بنية Intel MCS-51 . في عام 2020 ، احتفلت بعيدها الأربعين في سوق الأنظمة المدمجة.


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


نحن تفكيك لوحة الدوائر

سيساعد رسم مخطط الدائرة الأصلي للوحة في المستقبل على معرفة الغرض من دبابيس المتحكم الدقيق ، وهو أمر ضروري لتحليل رمز البرنامج الثابت.


تم تطوير الجهاز الأصلي من قِبل شركة صينية ، وبالتالي فإن الدائرة لها مشوشة للغاية ومع العديد من المكونات غير الضرورية. على سبيل المثال ، تم تشغيل التتابع من خلال سلسلة ثلاثية من الترانزستور ثنائي القطب ، optocoupler والتحكم الميداني (في هذا الترتيب).


أخبرني أحد معارفي الذين يعملون مع المصنعين الصينيين أن الصينيين منخرطون في مضاعفات مماثلة لخطط لزيادة تكلفة التطوير والإنتاج ، إذا قام بذلك شخص واحد فقط. بعد ذلك ، أميل إلى تصديقه:



نفس المكان على اللوحة الصينية ثنائية الطبقات على كلا الجانبين. ثلاثة مقاومات ضخمة غير مرتبطة بأي شيء. أنا أشرق حتى المجلس مع مصباح يدوي قوي للتأكد.


يتم نسخ المخطط ، على غرار الأماكن الغامضة في multisim ، ونحن نأخذ البرامج الثابتة.


تحاول قراءة البرامج الثابتة


كنت محظوظًا جدًا لأن حماية القراءة لم يتم تمكينها على كلتا اللوحتين في وحدات التحكم ، لذلك قمت بدمج خياري البرنامج الثابت مع المواد الإباحية المماثلة بنجاح:



صورة من المدونة الشخصية لعشاق أمريكي


تفكيك البرامج الثابتة


الخطوة التالية التي نحتاجها لتحويل كود الآلة هذا إلى شيء أكثر قابلية للقراءة:



نحن نأخذ أداة IDA Pro المعروفة ، والتي لديها بالفعل جهاز التحكم لدينا مع جميع السجلات الطرفية ، وفتح ملف البرنامج الثابت HEX:



معالجة البيانات التي تلقاها المجلس بلغة التجميع


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


تم العثور على معالجات المقاطعة أنفسهم في عناوين جدول متجه المقاطعة ؛ حيث قدمت الإدخالات في السجلات الطرفية معلومات حول تكوين واجهة الاتصال. خطوة بخطوة ، تحول رمز المجمّع غير المعروف إلى شيء يمكن قراءته.


استخراج خوارزمية العمل


نظرًا لأنني كنت بحاجة إلى تطوير جهاز جديد على قاعدة عناصر مختلفة ، كان من الضروري استخراج خوارزمية من الشفرة. بعد مرور بعض الوقت ، وُلد مثل هذا الرمز الزائف:


void UartISR (void) { counter500ms = 0; //ClearFlag(isrFlags, ISR_FLAG_3); ProcessUart(recievedByte); } void ProcessUart(uint8_t recievedData) { static uint8_t uartPacketsToRxLeft, uartRecievedCmd, uartCurrPacketCRC; static uint8_t i, carryFlag; static uint16_t uartIsrPointer; static uint8_t uartBuffer1[8], uartBuffer2[6]; static uint8_t uartBuffer1Pos, uartBuffer2Pos; // 0 - // 1 - // 2 - // 3 - led state, 0x0F // 4 - // 5 - // 6 - // 7 - // 8 - buttons time static uint8_t dataRegisters[9]; // RAM:0050 uint8_t tmpVal, i; uint8_t dataToSend; if (GetFlag(UartISRFlags, UART_RECIEVED_FLAG)) { ClearFlag(UartISRFlags, UART_RECIEVED_FLAG); if (recieved9thBit) { switch (recievedData) { case 0xC1: uartPacketsToRxLeft = 8; uartRecievedCmd = 1; uartBuffer1Pos = 0; uartBuffer1[uartBuffer1Pos] = recievedData; //uartIsrPointer = 0x0037; //tmpVal_0037 = recievedData; uartCurrPacketCRC = recievedData; UartRxOn(); return; break; case 0xC2: uartPacketsToRxLeft = 3; uartRecievedCmd = 2; 

نفس معالجة البيانات المستلمة في C


من يهتم ببروتوكول النقل:


تتصل محطة التحكم في المصعد بلوحات زر الاتصال عبر واجهة مزدوجة الاتجاه بجهد 24 فولت. في الوضع العادي ، استمعت بطاقات الزر إلى السطر ، في انتظار حزمة بيانات 9 بت. إذا كان عنوان لوحتنا يأتي في هذه الحزمة (تم ضبطها بواسطة مفتاح DIP الموجود على اللوحة) ، فتبديل اللوحة إلى وضع الاستقبال 8 بت ، وتم تجاهل جميع الحزم اللاحقة من قبل بقية اللوحات في الأجهزة.

الأول بعد العنوان كان حزمة مع رمز أمر تحكم. على وجه التحديد ، استغرق هذا المنتدى 3 فرق فقط:
  1. الكتابة إلى سجلات البيانات. على سبيل المثال ، تردد ومدة زر الوميض على مكالمة ؛
  2. زر الإضاءة الخلفية
  3. الاستعلام عن حالة الأزرار (مضغوطة أم لا).


البايت الأخير كان المجموع الاختباري ، وهو XOR بسيط لجميع البايتات بعد العنوان.
بعد اختباري ، ذهب المجلس مرة أخرى إلى وضع الاستعداد لعنوانه.

تطوير مجلس إدارة جديد


بالنسبة لمرحلة تطوير رسم تخطيطي جديد للأسلاك ولوحة دوائر مطبوعة ، ليس لدي صور ، لكن كان الأمر كما يلي:


تم الأسلاك والأسلاك في Altium Designer . تم طلب تصنيع لوحات الدارات المطبوعة في Zelenograd " Resonite ".


كتابة البرامج الثابتة الجديدة


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

قطعة من الدوائر الارسال التي تعادل كهربائيا الأصلي. المتلقي هو مجرد optocoupler.


 //UART1 initialize // desired baud rate:19200 // actual baud rate:19231 (0,2%) // char size: 9 bit // parity: Disabled void uart1_init(void) { UCSR1B = 0x00; //disable while setting baud rate UCSR1A = 0x00; UCSR1C = 0x06; UBRR1L = 0x33; //set baud rate lo UBRR1H = 0x00; //set baud rate hi UCSR1B = 0x94; } #pragma interrupt_handler uart1_rx_isr:iv_USART1_RXC void uart1_rx_isr(void) { unsigned char tmp; unsigned int rcv = 0; if (UCSR1B & 0x02) { rcv = 0x100; } rcv |= UDR1; tmp = (rcv >> 4) & 0x0F; if (rcv & 0x100) { tmp |= 0xC0; } else { tmp |= 0x80; } txBuf12 = (rcv & 0x0F); txBuf11 = tmp; txState1 = 0; TX_ON(); msCounter0 = 5000; } 

الحديث عن الشم لدينا في المحكمة الجنائية الدولية AVR


بعد ذلك ، كان من الضروري التصرف بحذر شديد حتى لا تحترق أي شيء في المصعد وتمنعه ​​من التوقف.



نحن يصعد إلى زر الاتصال. الأسلاك الصفراء السميكة - واجهة الطاقة ونقل الحركة. أبيض على الموصل المكون من 4 أسنان - توصيل الزر والإضاءة الخلفية.


نتحقق من أن كل شيء يعمل كما ينبغي ، وإصلاح أعناق وكتابة برنامج ثابت جديد لجهازنا:


 //ICC-AVR application builder : 11.02.2015 12:25:51 // Target : M328p // Crystal: 16.000Mhz #include <macros.h> #include <iccioavr.h> #include <avrdef.h> #include "types.h" #include "gpio.h" #define TX_OFF() UCSR0B &= 0b11011111; #define TX_ON() UCSR0B |= 0b00100000; #define TX_STATE() (UCSR0B & 0b00100000) #define MAX_TIMEOUT 3000 //#define SNIFFER_MODE 1 //#define MASTER_MODE 1 // #pragma avr_fuse (fuses0, fuses1, fuses2, fuses3, fuses4, fuses5) #pragma avr_fuse (0xFF, 0xD1, 0xFC) #pragma avr_lockbits (0xFC) // AVR signature is always three bytes. Signature0 is always the Atmel // manufacturer code of 0x1E. The other two bytes are device dependent. #pragma avr_signature (0x1E, 0x95, 0x0F) // atmega32 static GPIOx errorLed, rcvLed, butUp, butDn, ledUp, ledDn, butLedUp, butLedDn, ledButUp, ledButDn; static uint8_t msFlag = 0; static uint8_t ledState = 0, buttonsState = 0; static uint16_t rcvLedLitTime = 0, butMaskCalcTime = 0, timeoutTimer = 0; typedef struct { uint16_t buffer[10]; uint8_t dataLength; } UartPacket; static UartPacket txPacket, rxPacket; #ifdef SNIFFER_MODE static uint8_t txBuffer[64], txBufferLength = 0, bufferMutex = 0; #endif static uint8_t GetPacketCRC(UartPacket* packet); static void SendLedState(void); uint8_t GetAddress(void) { return (PINC & 0x3F); } 

رمز C للوحة الجديدة استنادًا إلى متحكم AVR ATmega328P


يمكن تقدير بساطة الجهاز والبرامج الثابتة بمقدار الكود ، فهو يحتوي فقط على حوالي 600 سطر بلغة C.


بدا بناء عملية مثل هذا:



الرسوم مختلفة ، ولكن المبدأ هو نفسه


لا يمكنني إرفاق صورة للجهاز النهائي ، فقط أعتقد أنه لا يزال يتم إنتاجه وبيعه.


الاستنتاج الغنائي


فيما يتعلق بأزرار المصاعد "أعلى" و "أسفل" على الأرض. لقد لاحظت أن الكثير من الناس لا يفهمون هدفهم تمامًا ويهزوهما مرة واحدة.



من هنا


يحتوي المصعد على مجموعتين من الأزرار: يوجد في الكابينة لوحة ترتيب ، وفي الطابق توجد لوحة اتصال. يمكنك بالفعل أن تخمن من أن لوحة الترتيب لها أولوية تحكم أعلى.


تعمل جميع المصاعد المزودة بألواح الاتصال مع أزرار لأعلى ولأسفل مع نوع من خوارزمية تحسين السفر ، والغرض منها هو نقل أكبر عدد ممكن من الركاب في أقل وقت وشرط منفصل لأقصى وقت انتظار على الأرض (منظم وفقًا لمعايير الولاية).


عادةً ما تتضمن هذه الخوارزمية اختيار الركاب على الأرضيات إذا كانوا يسافرون في نفس الاتجاه كما هو موضح بالضغط على زر الاتصال "لأعلى" أو "لأسفل".


تخيل الموقف الذي يسير فيه المصعد مع الركاب ويتلقى مكالمة "من الأسفل" من طابق أدناه. سيتوقف المصعد لالتقاط الراكب (نعم ، لا يزال هناك حساب لتحميل المقصورة بواسطة مستشعر الوزن ، لكننا سنخفضه).


يمتد المصعد ويستقبل مكالمة "أعلى" من الطابق أدناه. من المنطقي أن المصعد لن يتوقف لالتقاط الراكب ، لأنه لن يغير اتجاه السفر (هذا ينظمه أيضًا المعيار) ، ويلتقط راكبًا للنزول ثم - استهلاكًا غير مجدي للطاقة والفضاء في المصعد.


يستمر المصعد ويستقبل مكالمتين "صعودا وهبوطا" من الطابق أدناه ، والتي تم الضغط عليها من قبل بعض الركاب بفارغ الصبر الذي يحتاج إلى الصعود. من المنطقي أن يتوقف المصعد في هذا الطابق ، لكن الراكب لن يدخله ، لكن الأمر سيستغرق وقتًا من الناس في المقصورة لإبطاء المصعد وإيقافه ، وفتح الأبواب ، والانتظار ، وإغلاق الأبواب ، والتعجيل بالسرعة المحددة.


إذا كان المصعد به زر واحد فقط على الأرض ، فإنه في 99٪ من الحالات يعمل وفقًا لخوارزمية "الهبوط الجماعي" ، وإذا كانت هناك أوامر في المقصورة ، فإنه يتوقف فقط عند التحرك لأسفل.


إذا كانت لديك مهارات برمجة في JS ، فيمكنك محاولة تنفيذ خوارزمية تحكم مماثلة في لعبة Elevator Saga على الإنترنت. إنه يحتوي على جميع جوانب تحسين الرحلات دون التعمق في العمق مثل تشغيل دوائر أمان المصاعد.



في قناة التلغراف الخاصة بي ، أقوم بنشر مواد مماثلة. الآن يمكنك متابعة تطوير الجهاز التالي.

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


All Articles