মাইক্রোকন্ট্রোলার স্লিপ রেস শর্ত


11

একটি মাইক্রোকন্ট্রোলার দেওয়া যা নিম্নলিখিত কোডটি চালাচ্ছে:

volatile bool has_flag = false;

void interrupt(void) //called when an interrupt is received
{
    clear_interrupt_flag(); //clear interrupt flag
    has_flag = true; //signal that we have an interrupt to process
}

int main()
{
    while(1)
    {
        if(has_flag) //if we had an interrupt
        {
            has_flag = false; //clear the interrupt flag
            process(); //process the interrupt
        }
        else
            sleep(); //place the micro to sleep
    }
}

ধরুন if(has_flag)শর্তটি মিথ্যা হিসাবে মূল্যায়ন করে এবং আমরা ঘুমের নির্দেশ কার্যকর করতে চলেছি। রাইট আগে আমরা ঘুম নির্দেশ চালানো, আমরা একটি বিঘ্ন পাবেন। আমরা বাধা ছাড়ার পরে, আমরা ঘুমের নির্দেশ কার্যকর করি।

এই মৃত্যুদন্ডের ক্রমটি কাম্য নয় কারণ:

  • মাইক্রোকন্ট্রোলার ঘুম থেকে ওঠার পরিবর্তে ঘুম থেকে যায় process()
  • এরপরে কোনও বাধা না পেলে মাইক্রোকন্ট্রোলার কখনই জাগতে পারে না।
  • কলটি process()পরবর্তী বাধা না দেওয়া পর্যন্ত স্থগিত করা হয়েছে।

এই রেসের শর্তটি যাতে না ঘটে সে জন্য কোডটি কীভাবে লেখা যেতে পারে?

সম্পাদন করা

এটিএমতেগায় কিছু মাইক্রোকন্ট্রোলারদের একটি স্লিপ সক্ষম বিট থাকে যা এই অবস্থার সৃষ্টি হতে বাধা দেয় (এটি নির্দেশ করার জন্য আপনাকে কেভেগোরোকে ধন্যবাদ)। জে রবার্টস একটি উদাহরণ প্রয়োগের প্রস্তাব করে যা এই আচরণটির উদাহরণ দেয়।

অন্যান্য মাইক্রো, যেমন পিআইসি 18 তে রয়েছে, এই বিটটি নেই, এবং সমস্যাটি এখনও ঘটে। যাইহোক, এই মাইক্রোগুলি এমনভাবে তৈরি করা হয়েছে যে গ্লোবাল ইন্টারপ্যান্ট সক্ষম বিট সেট হয়েছে কিনা তা বিবেচনা না করেই বাধা এখনও জেগে উঠতে পারে (এটি নির্দেশ করার জন্য আপনাকে সুপারক্যাটকে ধন্যবাদ)। এই জাতীয় স্থাপত্যগুলির জন্য সমাধান হ'ল ঘুমানোর আগে বৈশ্বিক বাধা নিষ্ক্রিয় করা। ঘুমের নির্দেশ কার্যকর করার আগে যদি কোনও বিঘ্ন ঘটে তবে বাধা হ্যান্ডলার কার্যকর হবে না, মূলটি জেগে উঠবে এবং একবার বিশ্বব্যাপী বাধা পুনরায় সক্ষম হয়ে গেলে, বাধা হ্যান্ডলারটি কার্যকর করা হবে। সিউডো-কোডে, বাস্তবায়নটি দেখতে এরকম হবে:

int main()
{
    while(1)
    {
        //clear global interrupt enable bit.
        //if the flag tested below is not set, then we enter
        //sleep with the global interrupt bit cleared, which is
        //the intended behavior.
        disable_global_interrupts();

        if(has_flag) //if we had an interrupt
        {
            has_flag = false; //clear the interrupt flag
            enable_global_interrupts();  //set global interrupt enable bit.

            process(); //process the interrupt
        }
        else
            sleep(); //place the micro to sleep
    }
}

এটি কি ব্যবহারিক বা তাত্ত্বিক প্রশ্ন?
আন্দ্রেজাকো

তত্ত্ব অনুসারে আপনি এমন একটি টাইমার ব্যবহার করেন যা আপনাকে একবারে জাগিয়ে তোলে (গ্রহণযোগ্য মান লিখুন) এবং কিছু করার প্রয়োজন না হলে ঘুমাতে ফিরে যান।
গ্রেডি প্লেয়ার

1
আমি এটি interrupt_flagহিসাবে করব intএবং প্রতিবার বাধাগ্রস্থ হওয়ার সাথে সাথে এটি বাড়িয়ে তুলব । তারপর পরিবর্তন if(has_flag)করার জন্য while (interrupts_count)এবং তারপর ঘুম। তবুও, আপনি যখন লুপটি প্রস্থান করেছেন তখন বাধা সৃষ্টি হতে পারে। যদি এটি কোনও সমস্যা হয়, তবে প্রক্রিয়াটি নিজেই বাধা হয়ে যায়?
অ্যাঞ্জেল্যাটলজ

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

1
@ ট্রাইজেটস: পিআইসি 18x এ, আমি আমার উত্তরে যে পদ্ধতিটি বর্ণনা করেছি তা ঠিক কাজ করে (এই অংশটি ব্যবহার করার সময় এটি আমার সাধারণ নকশা)।
সুপারক্যাট

উত্তর:


9

এই ক্ষেত্রে সাধারণত কোনও ধরণের হার্ডওয়্যার সমর্থন থাকে। উদাহরণস্বরূপ, seiনিম্নলিখিত নির্দেশনা সম্পূর্ণ না হওয়া পর্যন্ত বাধা সক্ষম করার জন্য AVR- এর নির্দেশনা সক্ষম করে। এটির সাহায্যে কেউ এটি করতে পারে:

forever,
   interrupts off;
   if has_flag,
      interrupts on;
      process interrupt;
   else,
      interrupts-on-and-sleep;    # won't be interrupted
   end
end

উদাহরণস্বরূপ যে বিঘ্নটি মিস করা হত প্রসেসরটির ঘুমের ক্রমটি শেষ না করা পর্যন্ত এই ক্ষেত্রে বন্ধ রাখা হবে।


দুর্দান্ত উত্তর! আপনি যে অ্যালগরিদম সরবরাহ করেছেন এটি একটি AVR তে সত্যই ভাল কাজ করে। পরামর্শের জন্য ধন্যবাদ.
TRISABS

3

অনেকগুলি মাইক্রোকন্ট্রোলারগুলিতে, নির্দিষ্ট বাধা কারণগুলি (সাধারণত একটি বিঘ্নিত নিয়ামক মডিউলের মধ্যে) সক্ষম বা অক্ষম করতে সক্ষম হওয়া ছাড়াও, সিপিইউ কোরের মধ্যে একটি মাস্টার ফ্ল্যাগ থাকে যা নির্ধারণ করে যে বিঘ্নিত অনুরোধ গ্রহণ করা হবে কিনা। অনেকগুলি মাইক্রোকন্ট্রোলাররা ঘুমের মোডে প্রস্থান করবে যদি কোনও বাধা অনুরোধ কোরটিতে পৌঁছায় তবে কোরটি এটি গ্রহণ করতে ইচ্ছুক কিনা।

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

এই দৃশ্যের অধীনে, প্রধান লুপ ব্যবস্থাগুলি নিষ্ক্রিয় করার আগে একটি বাধাগুলি চূড়ান্ত পরীক্ষার আগে পতাকা সেট করে। একটি বাধা যা ঘুমের নির্দেশের আগে সার্ভিস করতে খুব দেরিতে মুলতুবি হয়ে যায় প্রসেসরটিকে ঘুমাতে যেতে বাধা দেয়। উভয় পরিস্থিতি ঠিক আছে।

স্লিপ অন-প্রস্থান কখনও কখনও ব্যবহারের জন্য একটি ভাল মডেল, তবে সমস্ত অ্যাপ্লিকেশনগুলি এটি "ফিট" করে না। উদাহরণস্বরূপ, একটি শক্তি-দক্ষ এলসিডি সহ একটি ডিভাইস কোডগুলির সাথে সাদাসিধে প্রোগ্রামিং করা যেতে পারে যা দেখে মনে হচ্ছে:

void select_view_user(int default_user)
{
  int current_user;
  int ch;
  current_user = default_user;
  do
  {
    lcd_printf(0, "User %d");
    lcd_printf(1, ...whatever... );
    get_key();
    if (key_hit(KEY_UP)) {current_user = (current_user + 1) % MAX_USERS};
    if (key_hit(KEY_DOWN)) {current_user = (current_user + MAX_USERS-1) % MAX_USERS};
    if (key_hit(KEY_ENTER)) view_user(current_user);
  } while(!key_hit(KEY_EXIT | KEY_TIMEOUT));
}

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


দুর্দান্ত উত্তরের জন্য ধন্যবাদ সুপারক্যাট। বাধা নিষ্ক্রিয় করা এবং তারপরে ঘুমাতে যাওয়া একটি দুর্দান্ত সমাধান, তবে বিশ্বব্যাপী বাধা বিট সেট / স্পষ্ট কিনা তা নির্বিশেষে মূল কোনও বিঘ্নিত উত্স থেকে মূল জেগে উঠবে। আমি PIC18 বিঘ্নিত হার্ডওয়্যার স্কিমেটিকটি একবার দেখেছি এবং এই সমাধানটি কার্যকর হবে।
TRISABS

1

মাইক্রোকে বাধা দেওয়ার জন্য জাগ্রত করতে প্রোগ্রাম করুন।

আপনি যে মাইক্রোটি ব্যবহার করছেন তার উপর নির্ভর করে নির্দিষ্ট বিশদগুলি পৃথক হবে vary

তারপরে মূল () রুটিনটি পরিবর্তন করুন:

int main()
{
    while(1)
    {
        sleep();
        process(); //process the interrupt
    }
}

1
প্রশ্নে ওয়েক-অন-বিঘ্নিত আর্কিটেকচারটি ধরে নেওয়া হয়েছে। আমি মনে করি না আপনার উত্তরটি প্রশ্ন / সমস্যা সমাধান করে।
এঞ্জেল্যাটলজ

@ অ্যাঞ্জেল্যাটলার্জ পয়েন্ট গৃহীত হয়েছে। আমি একটি কোড উদাহরণ যুক্ত করেছি যা আমি মনে করি সহায়তা করে।
jwygralak67

@ jwygralak67: এই পরামর্শের জন্য ধন্যবাদ, তবে আপনি যে কোডটি সরবরাহ করেছেন তা সমস্যাটিকে কেবল প্রক্রিয়া () রুটিনে নিয়ে যায়, যা এখন পরীক্ষা করতে হবে যে প্রক্রিয়াটি () বডি কার্যকর করার আগে বাধা ঘটেছে কিনা।
TRISABS

2
বাধা যদি না ঘটে থাকে তবে আমরা জাগ্রত কেন?
জে রবার্ট

1
@ জারউবার্ট: আমরা পূর্ববর্তী বাধা থেকে জেগে থাকতে পারি, প্রক্রিয়াটি () রুটিনটি সম্পূর্ণ করতে পারি এবং ঘুমের ঠিক আগে যদি আমরা (has_flag) পরীক্ষা শেষ করি তখন আমরা আবার একটি বাধা পাই, যার কারণে আমি বর্ণিত ইস্যুটির কারণ হয় প্রশ্ন।
TRISABS
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.