আমি যখন ওয়াচডগ টাইমার বন্ধ করার চেষ্টা করতে wdt_disable () কল করি তখন কেন আমার AVR রিসেট হয়?


34

আমার একটি সমস্যা হচ্ছে যেখানে কোনও AVR এটিটিনি 84A এ অক্ষম ওয়াচডগ সিকোয়েন্সটি কার্যকর করা আসলে চিপটি পুনরায় সেট করে দিচ্ছে যদিও টাইমারটিতে প্রচুর সময় থাকতে হবে। এটি অনেকগুলি শারীরিক অংশে একই কোড চালিত হওয়ার সাথে সাথে বেমানান হয়; কিছু প্রতিবার রিসেট, কিছু কখনও কখনও রিসেট, এবং কিছু কখনও না।

সমস্যাটি দেখানোর জন্য, আমি একটি সাধারণ প্রোগ্রাম লিখেছি যা ...

  1. 1 দ্বিতীয় সময়সীমা সহ ওয়াচডগ সক্ষম করে
  2. নজরদারি পুনরায় সেট করুন
  3. 0.1 সেকেন্ডের জন্য সাদা এলইডি ফ্ল্যাশ করে
  4. 0.1 সেকেন্ডের জন্য সাদা এলইডি বন্ধ ফ্ল্যাশ করে
  5. নজরদারি অক্ষম করে

নজরদারি সক্ষম এবং অক্ষম করার মধ্যে মোট সময়টি 0.3 সেকেন্ডেরও কম হয়, তবুও কখনও কখনও অক্ষম অনুক্রমটি কার্যকর করা হলে একটি ওয়াচডগ পুনরায় সেট করা হয়।

কোডটি এখানে:

#define F_CPU 1000000                   // Name used by delay.h. We are running 1Mhz (default fuses)

#include <avr/io.h>
#include <util/delay.h>
#include <avr/wdt.h>


// White LED connected to pin 8 - PA5

#define WHITE_LED_PORT PORTA
#define WHITE_LED_DDR DDRA
#define WHITE_LED_BIT 5


// Red LED connected to pin 7 - PA6

#define RED_LED_PORT PORTA
#define RED_LED_DDR DDRA
#define RED_LED_BIT 6


int main(void)
{
    // Set LED pins to output mode

    RED_LED_DDR |= _BV(RED_LED_BIT);
    WHITE_LED_DDR |= _BV(WHITE_LED_BIT);


    // Are we coming out of a watchdog reset?
    //        WDRF: Watchdog Reset Flag
    //        This bit is set if a watchdog reset occurs. The bit is reset by a Power-on Reset, or by writing a
    //        logic zero to the flag

    if (MCUSR & _BV(WDRF) ) {

        // We should never get here!


        // Light the RED led to show it happened
        RED_LED_PORT |= _BV(RED_LED_BIT);

        MCUCR = 0;        // Clear the flag for next time
    }

    while(1)
    {
        // Enable a 1 second watchdog
        wdt_enable( WDTO_1S );

        wdt_reset();          // Not necessary since the enable macro does it, but just to be 100% sure

        // Flash white LED for 0.1 second just so we know it is running
        WHITE_LED_PORT |= _BV(WHITE_LED_BIT);
        _delay_ms(100);
        WHITE_LED_PORT &= ~_BV(WHITE_LED_BIT);
        _delay_ms(100);

        // Ok, when we get here, it has only been about 0.2 seconds since we reset the watchdog.

        wdt_disable();        // Turn off the watchdog with plenty of time to spare.

    }
}

প্রারম্ভকালে, প্রোগ্রামটি পরীক্ষা করে দেখুন যে পূর্ববর্তী রিসেটটি কোনও ওয়াচডগের সময়সীমা শেষ হওয়ার কারণে হয়েছিল এবং যদি তাই হয় তবে এটি লাল এলইডি জ্বলিয়ে দেয় এবং একটি নজরদারি রিসেট ঘটেছে তা বোঝাতে ওয়াচডগ রিসেট পতাকা সাফ করে। আমি বিশ্বাস করি যে এই কোডটি কখনই কার্যকর করা উচিত নয় এবং লাল এলইডি কখনও চলবে না, তবুও এটি প্রায়শই ঘটে।

এখানে কি হচ্ছে?


7
এই সমস্যাটি সম্পর্কে যদি আপনি এখানে নিজের প্রশ্নোত্তর লিখে রাখার সিদ্ধান্ত নিয়েছেন তবে এটি আবিষ্কার করার জন্য যে ব্যথা এবং যন্ত্রণার প্রয়োজন হয়েছিল তা আমি কল্পনা করতে পারি।
ভ্লাদিমির ক্র্যাভারো

3
আপনি বাজি! এই বাগে 12 ঘন্টা কিছুক্ষণের জন্য, বাগটি কেবল সাইটটি বন্ধ হয়ে যায়। আমি যদি বোর্ডগুলি আমার ডেস্কটপে নিয়ে এসেছি তবে ত্বকটি চলে যাবে, সম্ভবত তাপমাত্রার প্রভাবের কারণে (আমার জায়গাটি শীতল কারণ এটি ওয়াচডোগ দোলনদ্বয়টি সিস্টেমের ঘড়ির তুলনায় কিছুটা ধীর গতিতে চালিত করে)। এটিকে পুনরুত্পাদন করতে এবং ভিডিওতে অভিনয় করতে এটি 30+ ট্রায়াল নিয়েছিল
বিগজোশ

আমি প্রায় ব্যথা অনুভব করতে পারি। আমি কোনও পুরানো এবং নেভিগেট করা EE নই তবে মাঝে মাঝে নিজেকে এই জাতীয় পরিস্থিতিতে পেয়েছি। দুর্দান্ত ধরুন, একটি বিয়ার রাখুন এবং সমস্যাগুলি সমাধান করুন;)
ভ্লাদিমির ক্র্যাভারো

উত্তর:


41

Wdt_reset () লাইব্রেরি রুটিনে একটি বাগ রয়েছে।

এখানে কোডটি ...

__asm__ __volatile__ ( \
   "in __tmp_reg__, __SREG__" "\n\t" \
   "cli" "\n\t" \
   "out %0, %1" "\n\t" \
   "out %0, __zero_reg__" "\n\t" \
   "out __SREG__,__tmp_reg__" "\n\t" \
   : /* no outputs */ \
   : "I" (_SFR_IO_ADDR(_WD_CONTROL_REG)), \
   "r" ((uint8_t)(_BV(_WD_CHANGE_BIT) | _BV(WDE))) \
   : "r0" \
)

চতুর্থ লাইনটি প্রসারিত করে ...

out _WD_CONTROL_REG, _BV(_WD_CHANGE_BIT) | _BV(WDE)

এই লাইনের উদ্দেশ্য হ'ল WD_CHANGE_BIT- তে একটি 1 লিখুন যা নীচের লাইনটিকে ওয়াচডগ সক্ষম বিট (ডাব্লুডিই) তে 0 লিখতে সক্ষম করবে। ডাটাশিট থেকে:

একটি সক্ষম ওয়াচডগ টাইমার অক্ষম করতে, নিম্নলিখিত পদ্ধতিটি অনুসরণ করা আবশ্যক: 1. একই ক্রিয়ায়, ডাব্লুডিসিই এবং ডাব্লুডিইতে একটি যুক্তি লিখুন write ডাব্লুডিই বিটের পূর্ববর্তী মান নির্বিশেষে একটি যুক্তি একটি ডাব্লুডিইতে লিখতে হবে। ২. পরবর্তী চারটি ঘড়ির চক্রের মধ্যে, একই ক্রিয়াকলাপে, ডাব্লুডিই এবং ডাব্লুডিপি বিটগুলি পছন্দমতো লিখুন, তবে ডাব্লুডিসিই বিট সাফ করে দিয়ে।

দুর্ভাগ্যক্রমে, এই কার্যভারটি ওয়াচডগ কন্ট্রোল রেজিস্টার (ডাব্লুডিসিই) এর নীচে 3 বিটগুলি 0-এ সেট করারও পার্শ্ব প্রতিক্রিয়া রয়েছে । এটি অবিলম্বে প্রেসক্যালারকে তার স্বল্পতম মানতে সেট করে। এই নির্দেশটি কার্যকর করার মুহূর্তে যদি নতুন প্রেসক্যালার ইতিমধ্যে বরখাস্ত করা হয়, তবে প্রসেসরটি পুনরায় সেট করা হবে।

যেহেতু নজরদারি টাইমার শারীরিকভাবে স্বাধীন 128 কেএইচজেড অসিলেটরটি চালাচ্ছে, তাই চলমান প্রোগ্রামের সাথে নতুন প্রেসক্যালারের অবস্থা কী হবে তা অনুমান করা শক্ত। এটি পরিলক্ষিত আচরণের বিস্তৃত পরিসরের জন্য অ্যাকাউন্ট যেখানে সরবরাহের ভোল্টেজ, তাপমাত্রা এবং উত্পাদন ব্যাচের সাথে বাগটি সম্পর্কযুক্ত করা যেতে পারে যেহেতু এই সমস্ত জিনিস ওয়াচডগ দোলকের গতি এবং সিস্টেম ঘড়িকে অসামান্যভাবে প্রভাবিত করতে পারে। এটি খুঁজে পাওয়া খুব হার্ড বাগ ছিল!

এখানে আপডেট হওয়া কোড যা এই সমস্যাটি এড়ায় ...

__asm__ __volatile__ ( \
   "in __tmp_reg__, __SREG__" "\n\t" \
   "cli" "\n\t" \
   "wdr" "\n\t" \
   "out %0, %1" "\n\t" \
   "out %0, __zero_reg__" "\n\t" \
   "out __SREG__,__tmp_reg__" "\n\t" \
   : /* no outputs */ \
   : "I" (_SFR_IO_ADDR(_WD_CONTROL_REG)), \
   "r" ((uint8_t)(_BV(_WD_CHANGE_BIT) | _BV(WDE))) \
   : "r0" \
)

অতিরিক্ত wdrনির্দেশিকা ওয়াচডগ টাইমারকে পুনরায় সেট করে, সুতরাং যখন নিম্নলিখিত লাইনটি সম্ভাব্যভাবে কোনও পৃথক উপস্থাপককে পরিবর্তন করে, তখনও সময় শেষ না হওয়ার গ্যারান্টিযুক্ত।

ডেটাশিটগুলির পরামর্শ অনুসারে ডাব্লুডি_সিএন্টআরএল বিজিটি এবং ডাব্লুডিই বিটগুলিতে ওআরিং করেও এটি ঠিক করা যেতে পারে ...

; Write logical one to WDCE and WDE
; Keep old prescaler setting to prevent unintentional Watchdog Reset
in r16, WDTCR
ori r16, (1<<WDCE)|(1<<WDE)
out WDTCR, r16

... তবে এর জন্য আরও কোড এবং একটি অতিরিক্ত স্ক্র্যাচ নিবন্ধক প্রয়োজন। যেহেতু যে কোনও উপায়ে অক্ষম করা হলে ওয়াচডগ কাউন্টারটি পুনরায় সেট করা হয়, অতিরিক্ত রিসেট কোনও কিছুই ক্লোবার করে না এবং অনিচ্ছাকৃত কোনও পার্শ্ব প্রতিক্রিয়া নেই has


7
আমি আপনাকে প্রপসগুলিও দিতে চাই কারণ যখন আমি এভ্রির-লিবিসি ইস্যু তালিকাটি পরীক্ষা করতে গিয়েছিলাম, মনে হয় আপনি (সম্ভবত আপনি) এটি ইতিমধ্যে জমা দিয়েছেন savannah.nongnu.org/bugs/?44140
ভ্যাক্যাটাকু

1
PS "জোশ ডট কম" আসল ... চিত্তাকর্ষক
ভ্যাক্যাটাকু
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.