• خطا در پردازش وقفه های تودرتو در STM8 (در اشتباه توضیح داده نشده است). مدیریت وقفه، بردارهای وقفه، وقفه های نرم افزاری، IRQ

    وقفه های تو در تو

    این مکانیزم به طور کامل در سیستم عامل QNX Neutrino پشتیبانی می شود. سناریوهای قبلی ساده ترین و رایج ترین وضعیتی را که در آن تنها یک وقفه رخ می دهد، توصیف کرده است. با این حال، برای به دست آوردن حداکثر مقدارتأخیر در غیاب وقفه‌های غیرقابل پوشش باید زمانی در نظر گرفته شود که همه وقفه‌های فعلی را در یک زمان در نظر بگیریم، زیرا یک وقفه غیرقابل پوشش با اولویت بالاتر از وقفه فعلی جلوگیری می‌کند.

    روی انجیر شکل 2-25 رشته A را در حال اجرا نشان می دهد. وقفه IRQx کنترل کننده وقفه Intx را راه اندازی می کند که توسط وقفه IRQy و کنترل کننده وقفه lnty از پیش گرفته می شود. کنترل کننده وقفه Inty رویدادی را برمی گرداند که Thread B را شروع می کند و کنترل کننده وقفه Intx رویدادی را برمی گرداند که Thread C را شروع می کند.

    قطع تماس ها

    API مدیریت وقفه شامل فراخوانی های هسته زیر است.

    از این طریق رابط نرم افزارییک رشته با امتیازات کاربر مناسب می‌تواند تابع InterruptAttach() یا Interrupt Attach Event() را فراخوانی کند و شماره وقفه سخت‌افزاری و آدرس تابع را در فضای آدرس رشته ارسال کند تا هنگام وقوع وقفه فراخوانی شود. QNX Neutrino اجازه می دهد تا چندین کنترل کننده وقفه (ISR) با هر شماره وقفه سخت افزاری مرتبط شود. وقفه‌های غیرقابل پوشش را می‌توان در حالی که کنترل‌کننده‌های وقفه در حال اجرا در حال اجرا هستند، مدیریت کرد.

    در زیر یک نمونه است کد برنامه، که با آن یک کنترل کننده وقفه (ISR) به وقفه سخت افزاری تایمر (که سیستم عامل از آن به عنوان ساعت سیستم نیز استفاده می کند) متصل می شود. کنترل کننده وقفه تایمر در هسته منابع وقفه را خود پاک می کند، بنابراین فقط شمارنده را در فضای داده رشته افزایش می دهد و سپس کنترل را به هسته منتقل می کند.

    در نتیجه، رشته‌های کاربر با امتیازات مناسب می‌توانند به‌طور پویا کنترل‌کننده‌های وقفه را به بردارهای وقفه سخت‌افزاری (از) هنگام اجرا متصل کنند (و جدا کنند). این رشته ها را می توان در سطح منبع با استفاده از ابزارهای اشکال زدایی معمول رفع اشکال کرد و خود کنترل کننده وقفه را می توان با فراخوانی این کنترل کننده در سطح رشته و اجرای گام به گامدر سطح منبع یا با فراخوانی تابع ()InterruptAttachEvent.

    هنگامی که یک وقفه سخت افزاری رخ می دهد، پردازنده redirector وقفه میکروکرنل را فراخوانی می کند. این ماژول زمینه ثبت رشته در حال اجرا را روی پشته در ورودی جدول رشته مناسب فشار می دهد و سپس زمینه را به گونه ای تنظیم می کند که کنترل کننده وقفه به کد و داده های رشته ای که شامل کنترل کننده وقفه است دسترسی داشته باشد. بنابراین، کنترل کننده وقفه می تواند از بافرها و کدهای موجود در رشته کاربر برای تعیین منبع وقفه استفاده کند و در صورتی که موضوع نیاز به کار بیشتری داشته باشد. سطح بالا، یک رویداد برای رشته ایجاد می کند که شامل این کنترل کننده وقفه است، پس از آن این رشته می تواند داده هایی را که کنترل کننده وقفه در بافر خود قرار داده است پردازش کند.

    از آنجایی که کنترل کننده وقفه در زمینه رشته حاوی آن نگاشت می شود، می تواند مستقیماً روی دستگاه های نگاشت شده در فضای آدرس رشته کار کند یا دستورالعمل های I/O را به تنهایی اجرا کند. در نتیجه، نیاز به اتصال درایورهای دستگاه به هسته را از بین می برد.

    ماژول مدیریت وقفه اولیه، که در میکروکرنل موجود است، همه کنترل کننده های مرتبط با یک وقفه سخت افزاری معین را فراخوانی می کند. اگر مقدار بازگشتی نشان دهد که یک رویداد باید به فرآیند ارسال شود، هسته آن رویداد را در صف قرار می دهد. پس از فراخوانی آخرین کنترل کننده وقفه برای پردازش یک بردار وقفه داده شده، کنترل کننده وقفه هسته از کنترل کننده وقفه خارج می شود و "از وقفه برمی گردد".

    این بازگشت وقفه نیازی به ایجاد زمینه موضوع قطع شده ندارد. اگر یک رویداد در صف باعث شود که یک رشته با اولویت بالاتر وارد حالت آماده شود، آنگاه میکروکرنل از وقفه به بافت رشته ای که در حال حاضر فعال است باز می گردد.

    این دوره (به اصطلاح تأخیر پردازش وقفه) بین وقوع وقفه و اجرای اولین دستورالعمل کنترل کننده وقفه و همچنین دوره (به اصطلاح تاخیر زمان بندی) بین آخرین دستورالعملکنترل کننده وقفه و اولین دستورالعمل رشته که توسط کنترل کننده وقفه به حالت آماده می رسد.

    دوره حداکثر تأخیر پردازش وقفه دقیقاً تعریف شده است زیرا سیستم عامل وقفه ها را فقط برای مدت اجرای چندین دستورالعمل در چندین بخش مهم کد برنامه غیرفعال می کند. دوره هایی که در آن وقفه ممنوع است به شدت ادامه دارد زمان مشخصو به داده ها وابسته نیستند.

    کنترل کننده وقفه اولیه میکروکرنل چندین دستورالعمل را قبل از فراخوانی کنترل کننده وقفه اجرا می کند. در نتیجه، فرآیندها با وقفه‌های سخت‌افزاری یا فراخوانی هسته به همان سرعت و از طریق زنجیره‌ای از دستورالعمل‌ها پیشی گرفته می‌شوند.

    در طول عملیات خود، کنترل کننده وقفه دارد دسترسی کاملبه سخت افزار (چون بخشی از یک رشته ممتاز است)، اما نمی تواند هسته های دیگر را فراخوانی کند. کنترل کننده وقفه باید در سریع ترین زمان ممکن به وقفه سخت افزاری پاسخ دهد، حداقل کار را برای سرویس وقفه انجام دهد (خواندن یک بایت از یک فرستنده ناهمزمان جهانی (UART) و غیره) و به صورت اختیاری یک رشته را با مقداری اولویت برنامه ریزی کند. کارهای بیشتر انجام دهید. .

    حداکثر تأخیر وقفه برای یک اولویت سخت افزاری معین را می توان مستقیماً از تأخیر وقفه معرفی شده توسط هسته و حداکثر زمان کنترل کننده وقفه برای هر وقفه ای که اولویت سخت افزاری بالاتری نسبت به کنترل کننده وقفه داده شده دارد محاسبه کرد. از آنجایی که می توان اولویت های وقفه سخت افزاری را دوباره تخصیص داد، می توان به مهم ترین وقفه در سیستم بیشترین اولویت را داد.

    توجه داشته باشید که فراخوانی تابع InterruptAttachEvent () کنترل کننده وقفه را راه اندازی نمی کند. در عوض، یک رویداد تعریف شده توسط کاربر برای هر وقفه ایجاد می شود. به طور معمول، این رویداد باعث می شود تا یک رشته انتظار برنامه ریزی شود تا بتواند کار اصلی را انجام دهد. وقفه به طور خودکار پس از ایجاد رویداد پوشانده می شود و باید به صراحت توسط رشته ای که دستگاه را در زمان مناسب ارائه می کند، پوشش داده شود.

    بنابراین، اولویت کاری انجام شده بر روی وقفه های سخت افزاری را می توان توسط خود سیستم عامل کنترل کرد و نه توسط سخت افزار. منبع وقفه تا زمانی که وقفه فعلی سرویس نشود، وقفه جدیدی ایجاد نمی کند، که به شما امکان می دهد اثر وقفه ها را بر بخش های مهم کد برنامه کنترل کنید و کنترل زمان بندی با دقت بالا را انجام دهید.

    فرآیندهای کاربر و رشته ها می توانند نه تنها وقفه های سخت افزاری، بلکه «رویدادهای» مختلف را در میکروکرنل «به دام بیاندازند». هنگامی که هر یک از این رویدادها رخ می دهد، هسته می تواند تابع خارجی مشخص شده (upcall) در رشته کاربر را برای رسیدگی فراخوانی کند. این رخداد. به عنوان مثال، هر بار که یک رشته بیکار فراخوانی می شود، یک نخ کاربر می تواند به هسته دستور دهد تا یک فراخوانی خارجی برای پیاده سازی حالت های صرفه جویی انرژی سخت افزاری خاص برقرار کند.

    نام پارامتر معنی
    موضوع مقاله: قطع می کند.
    روبریک (دسته موضوعی) برنامه نويسي

    تایمر سگ نگهبان

    اغلب، نویز الکتریکی تولید شده توسط تجهیزات اطراف باعث می شود که میکروکنترلر آدرس اشتباه، پس از آن رفتار آن غیرقابل پیش بینی می شود (میکروکنترلر ʼʼ به overdrive ʼʼ می رود). برای نظارت بر چنین شرایطی، تایمرهای نگهبان اغلب در میکروکنترلر گنجانده می شوند.

    این دستگاه در صورتی که محتویات آن در بازه زمانی معینی (معمولا از ده ها میلی ثانیه تا چند ثانیه) به روز نشود، باعث ریست شدن میکروکنترلر می شود. اگر تغییر محتویات شمارنده برنامه مطابقت نداشته باشد برنامه داده شده، سپس دستور به روز رسانی watchdog اجرا نمی شود. در این حالت، تایمر نگهبان، میکروکنترلر را بازنشانی کرده و آن را به حالت اولیه خود تنظیم می کند.

    بسیاری از توسعه دهندگان از تایمرهای نگهبان در برنامه های خود استفاده نمی کنند زیرا اهمیت حیاتی استفاده از آن ها برای مبارزه با اثرات تداخل الکتریکی را نمی بینند، به عنوان مثال، هنگام قرار دادن یک میکروکنترلر در یک نمایشگر پرتو کاتدی در نزدیکی یک ترانسفورماتور که باعث سرکوب ترانسفورماتور می شود. پرتو به عقب، یا نزدیک کویل های احتراق خودرو. در الکترونیک مدرن، اغتشاشات الکتریکی بعید به نظر می رسد، اگرچه گاهی اوقات در موقعیت هایی مشابه موارد ذکر شده در بالا رخ می دهند.

    استفاده از تایمر داگ برای ماسک کردن توصیه نمی شود مشکلات نرم افزاری. در حالی که این تایمر ممکن است احتمال خطاهای نرم افزاری را کاهش دهد، بعید است که اطمینان حاصل شود که همه دلایل احتمالی خطاها از بین رفته اند. به جای تکیه بر سخت افزار برای جلوگیری از خرابی نرم افزار، بهتر است با دقت بیشتری تست کنید نرم افزاردر موقعیت های مختلف

    بسیاری از کاربران احساس می‌کنند که وقفه‌ها قطعه‌ای از سخت‌افزار هستند که بهتر است به حال خود رها شوند، زیرا استفاده از آن‌ها به دانش برتر پردازنده برای توسعه یک برنامه کنترل کننده وقفه نیاز دارد. در غیر این صورت، هنگامی که یک وقفه رخ می دهد، سیستم ʼʼبه خواب می رودʼʼ یا ʼʼpeddleʼʼ. این احساس معمولاً از تجربه یک توسعه‌دهنده با وقفه‌ها برای رایانه شخصی ناشی می‌شود، که دارای تعدادی ویژگی است که ایجاد یک کنترل کننده وقفه را پیچیده می‌کند. بسیاری از این مشکلات در سخت افزار مبتنی بر میکروکنترلر وجود ندارد. استفاده در این تجهیزاتوقفه ها می توانند توسعه و کاربرد آن را تا حد زیادی ساده کنند.

    اگر هرگز با وقفه‌ها برخورد نکرده‌اید، یک سوال برایتان پیش خواهد آمد - چیست؟ که در سیستم کامپیوتریوقفه اجرای یک برنامه فرعی ویژه است (به نام «کنترل وقفه» یا «روتین سرویس وقفه») که توسط یک سیگنال سخت افزاری فراخوانی می شود. در طول مدت این زیربرنامه، اجرای برنامه فعلی متوقف می شود. اصطلاح "درخواست وقفه" به این دلیل استفاده می شود که گاهی اوقات برنامه از تایید وقفه و اجرای فوری کنترل کننده وقفه امتناع می ورزد (شکل 2.19).

    وقفه در یک سیستم کامپیوتری شبیه به وقفه در زندگی روزمره است. یک مثال کلاسیک از چنین وقفه ای، تماس تلفنی هنگام تماشای یک برنامه تلویزیونی است. وقتی تلفن زنگ می زند، سه گزینه دارید. اولین مورد این است که تماس را نادیده بگیرید. دوم این است که به تماس پاسخ دهید، اما بگویید که بعداً تماس خواهید گرفت. سوم پاسخ به تماس، به تعویق انداختن تمام امور جاری است. سیستم کامپیوتری همچنین دارای سه پاسخ مشابه است که به عنوان پاسخ به درخواست سخت افزار خارجی استفاده می شود.

    اولین پاسخ ممکن - "به یک وقفه پاسخ ندهید تا زمانی که کار فعلی کامل نشده است" - با غیرفعال کردن (پوشاندن) سرویس درخواست وقفه اجرا می شود. پس از تکمیل کار، یکی از دو گزینه ممکن است: تنظیم مجدد ماسک و فعال کردن سرویس، که باعث فراخوانی کنترل کننده وقفه می شود، یا تجزیه و تحلیل مقدار بیت ها (ʼʼpollingʼʼ). نشان دهنده دریافت درخواست های وقفه و اجرای مستقیم برنامه سرویس بدون فراخوانی کنترل کننده وقفه است. این روش رسیدگی به وقفه زمانی استفاده می شود که نیاز به ارائه باشد زمان داده شدهاجرای برنامه اصلی، زیرا هر گونه وقفه می تواند اجرای یک رابط حیاتی را مختل کند.

    برنج. 2.18 - اجرای وقفه.

    پوشاندن وقفه طولانی توصیه نمی شود، زیرا در این مدت ممکن است چندین رویداد وقفه با هم همپوشانی داشته باشند و تنها یکی از آنها شناسایی می شود. مدت زمان مجاز پوشاندن به کاربرد خاص میکروکنترلر، نوع و فرکانس چنین رویدادهایی بستگی دارد. غیرفعال کردن وقفه ها برای بیش از نیمی از حداقل فاصله مورد انتظار برای رویدادهایی که درخواست وقفه دارند، توصیه نمی شود.

    کنترل کننده وقفه همیشه دنباله ای از اقدامات زیر را ارائه می دهد:

    2. کنترل کننده وقفه و سخت افزاری که باعث درخواست شده است را بازنشانی کنید.

    3. داده ها را پردازش کنید.

    4. محتویات رجیسترهای زمینه را بازیابی کنید.

    5. به برنامه قطع شده برگردید.

    ثبات های زمینه، ثبات هایی هستند که وضعیت اجرای فعلی برنامه اصلی را تعیین می کنند. اینها معمولاً شامل شمارنده برنامه، ثبت وضعیت ها و انباشته ها می شوند. سایر رجیسترهای پردازنده، مانند ثبات‌های فهرست، در هنگام پردازش وقفه استفاده می‌شوند و بنابراین محتویات آن‌ها نیز برای ذخیره بسیار مهم است. همه رجیسترهای دیگر مختص یک میکروکنترلر خاص و کاربرد آن هستند.

    پس از تنظیم مجدد به حالت اولیهکنترل کننده وقفه آماده پذیرش درخواست بعدی است و سخت افزار ایجاد کننده وقفه آماده ارسال درخواست در صورت بروز دلایل مناسب است. اگر یک درخواست وقفه جدید وارد شود، رجیستر پوشش دهنده وقفه پردازنده از پردازش وقفه جلوگیری می کند، اما ثبت وضعیت وقفه رفع می شود. درخواست داده شدهکه منتظر خدمتشان خواهند بود. پس از تکمیل پردازش وقفه فعلی، ماسک وقفه بازنشانی می‌شود و درخواست تازه دریافت‌شده پردازش می‌شود.

    اجرای وقفه های تودرتو در برخی از انواع میکروکنترلرها که پشته ندارند، دشوار است. این وقفه ها همچنین می توانند باعث مشکلات سرریز پشته شوند. مشکل سرریز به دلیل مقدار محدود حافظه و پشته داده به میکروکنترلرها مربوط می شود: دنباله ای از وقفه های تودرتو می تواند باعث شود داده های بیشتری از حد مجاز در پشته قرار گیرد.

    در نهایت، وقفه کنترل می شود. مثال دوم تلویزیون نشان می دهد که شما می توانید به سرعت به درخواست وقفه با دریافت داده های لازم پاسخ دهید که پس از حل کار فعلی استفاده می شود. در میکروکنترلرها، این کار با ذخیره داده های دریافتی در یک آرایه حافظه و سپس پردازش آنها پس از اتمام اجرای برنامه اصلی انجام می شود. این نوع سرویس سازش خوبی بین مدیریت وقفه به طور کامل، که می تواند زمان زیادی طول بکشد، و نادیده گرفتن وقفه، که می تواند منجر به از دست رفتن اطلاعات در مورد رویدادی شود که باعث وقفه شده است، می باشد.

    بازیابی رجیسترهای متن و اجرای دستور بازگشت وقفه، پردازنده را به حالتی که قبل از وقوع وقفه در آن بود، برمی‌گرداند.

    در نظر بگیرید که در طول پردازش وقفه چه اتفاقی برای محتویات ثبات های مختلف می افتد. محتویات ثبت وضعیت معمولاً به صورت خودکار همراه با محتویات شمارنده برنامه قبل از رسیدگی به وقفه ذخیره می شود. این امر فوریت نگهداری آن را در حافظه از بین می برد. ابزارهای نرم افزاریبا استفاده از دستورات انتقال، و سپس بازیابی در هنگام بازگشت به برنامه اصلی. در عین حال، چنین ذخیره خودکاردر همه انواع میکروکنترلرها اجرا نمی شود، در ارتباط با این موضوع، سازماندهی پردازش وقفه باید مورد توجه ویژه قرار گیرد.

    اگر محتویات ثبت وضعیت قبل از شروع اجرای کنترل کننده وقفه ذخیره شود، آنگاه به طور خودکار با دستور بازگشت بازیابی می شود.

    اگر محتویات سایر رجیسترهای پردازنده در حین سرویس وقفه تغییر کند، باید قبل از تغییر در حافظه ذخیره شده و قبل از بازگشت به برنامه اصلی بازیابی شوند. ذخیره همه رجیسترهای پردازنده برای جلوگیری از اشکالات غیرقابل پیش بینی که یافتن آنها بسیار دشوار است، معمول است.

    آدرسی که هنگام پرش به کنترل کننده وقفه در شمارنده برنامه بارگذاری می شود، "بردار وقفه" نامیده می شود. چندین نوع بردار وجود دارد. آدرسی که هنگام راه اندازی میکروکنترلر در شمارنده برنامه بارگذاری می شود (بازنشانی) معمولاً "بردار تنظیم مجدد" نامیده می شود. بردارهای وقفه متفاوتی را می توان به بردارهای مختلف اختصاص داد، که برنامه تعمیر و نگهداری را از اهمیت فوق العاده در تعیین علت وقفه رها می کند. استفاده از وقفه های مختلف یک بردار معمولاً مشکلی در عملکرد میکروکنترلرها ایجاد نمی کند، زیرا اغلب میکروکنترلر یک برنامه واحد را اجرا می کند. این میکروکنترلر با یک کامپیوتر شخصی متفاوت است که در حین کار می توان منابع وقفه های مختلفی را اضافه کرد. (اگر تا به حال دو دستگاه را به پورت های COM1 و COM3 متصل کرده اید، می توانید تصور کنید که این در مورد چیست). در یک میکروکنترلر، که سخت افزار آن به خوبی شناخته شده است، نباید هیچ مشکلی وجود داشته باشد اشتراک گذاریبردارهای وقفه

    آخرین چیزی که باید در نظر بگیرید وقفه های نرم افزاری است. دستورالعمل های پردازنده وجود دارد که می توان از آنها برای شبیه سازی وقفه های سخت افزاری استفاده کرد. واضح ترین کاربرد این دستورات فراخوانی زیر روال های سیستمی است که در یک مکان دلخواه در حافظه قرار دارند یا برای دسترسی به آنها نیاز به پرش های بین بخش دارند. این ویژگی در ریزپردازنده های خانواده i86 اینتل پیاده سازی شده و در آن استفاده می شود سیستم پایه I/O BIOS(سیستم ورودی/خروجی پایه) و عملیاتی سیستم DOS کامپیوترهای شخصیبرای فراخوانی روال های سیستم بدون اهمیت فوق العاده تعمیر نقطه ورود. در عوض، بردارهای وقفه مختلفی استفاده می‌شوند و دستوری را انتخاب می‌کنند که باید در هنگام وقوع چنین وقفه‌ای در نرم‌افزار اجرا شود.

    شاید پس از خواندن این فصل، مکانیسم وقفه برای شما قابل درک تر شود یا برعکس. فقط بیشتر گیج خواهید شد. هنگام توصیف هر میکروکنترلر، نشان داده خواهد شد که چگونه استفاده از وقفه ها می تواند کاربرد آن را ساده کند.

    قطع می کند. - مفهوم و انواع طبقه بندی و ویژگی های دسته "وقفه". 2017، 2018.

    3. نمونه هایی از وقفه ها

    3.1. وقفه در تغییر سیگنال در پورت های I/O (مثال در PROTEUS)

    3.2. وقفه خارجی INT (مثال در PROTEUS)

    همه انواع میکروکنترلرهای معماری dsPIC دارای وقفه های یکسان هستند. بنابراین، می توانید با خیال راحت وقفه ها را در برنامه PROTEUS مطالعه کنید. برای مطالعه، از میکروکنترلر موجود در پروتئوس استفاده خواهیم کرد.

    بنابراین، چه نوع وقفه هایی در میکروکنترلر dsPIC33FJ32GP204 وجود دارد؟

    و وقفه های زیادی در میکروکنترلر وجود دارد. و فهرست کردن همه چیز در این سخنرانی معنی ندارد. به هر حال، اولین چیزی که در انتخاب میکروکنترلر به آن توجه می کنیم این است که چه ماژول هایی دارد و تنها پس از آن می بینیم که چه وقفه هایی دارد. به همین ترتیب، ما همه چیز را به همان ترتیب مطالعه خواهیم کرد. همانطور که ما میکروکنترلر را مطالعه می کنیم، وقفه های ماژول های مختلف را تجزیه و تحلیل خواهیم کرد.

    به طور کلی باید بدانید که یک جدول برداری وقفه برای میکروکنترلر وجود دارد که در حافظه برنامه قرار دارد. هر وقفه بردار خاص خود را دارد، یعنی آدرس شروع روال کنترل کننده وقفه خاص (ISR). همچنین یک جدول بردار وقفه جایگزین وجود دارد. با یک بیت ALTINV می توانید مشخص کنید که آدرس روتین وقفه از کدام جدول گرفته شود. یعنی جایگزینی برای جدول اصلی وجود دارد. اما باید به یاد داشته باشید که بیت ALTINV برای کل جدول به طور همزمان استفاده می شود. و اگر یک جدول جایگزین نصب شده باشد، برنامه اصلی کاملاً تمام آدرس‌های روال مدیریت وقفه را از جدول جایگزین می‌گیرد. جدول جایگزین برای حالت اشکال زدایی بسیار مفید است، زیرا به شما این امکان را می دهد که یک بار برنامه ای را در کنترلر بنویسید و مثلاً با استفاده از یک دکمه، بین دو الگوریتم عملیات برنامه را انتخاب کنید.

    dsPIC دامنه اولویت های وقفه را گسترش داد. اگر در PIC18 فقط 2 مورد از آنها وجود داشت، در dsPIC در حال حاضر 8 سطح وجود دارد. و زمانی که من یک ماژول برای ارتباط از طریق یک کانال GPRS توسعه می‌دادم، برای من بسیار مفید بود، زیرا میکروکنترلر تقریباً از تمام تجهیزات جانبی موجود روی برد استفاده می‌کرد و تعداد وقفه‌های پردازش شده حدود بیست بود.

    مهمترین چیزی که باید بدانید این است که تنها 3 بیت اصلی (رجیستر) برای کار با هر وقفه وجود دارد: بیت فعال کننده وقفه، پرچم وقفه و سه بیت انتخاب اولویت وقفه.

    بنابراین، آنچه از یک برنامه نویس برای کار با وقفه ها لازم است:

    1. او باید اجازه وقفه خاصی بدهد.

    2. پس از وقوع رویدادی که باعث وقفه شد، پرچم وقفه مربوطه تنظیم می شود و برنامه به اصطلاح در امتداد بردار وقفه می پرد. و اگر به زبان معمولی بگویید: پس به محض وقوع وقفه، زیربرنامه پردازش یک وقفه خاص بلافاصله فراخوانی می شود.

    3. نکته اصلی این است که فراموش نکنید که پرچم این وقفه را در روال وقفه تنظیم مجدد کنید.

    برای میکروکنترلر dsPIC، کامپایلر C30 قانون زیر را برای توصیف روال‌های وقفه ارائه می‌کند، به عنوان مثال، برای وقفه INT1:

    خالی __ ویژگی های__((__ قطع کردن__)) _ INT1 قطع کنید()

    نکته اصلی که باید به آن توجه کنید پایان متن عنوان زیربرنامه است: _ INT1 قطع کنید() - این تنها پارامتری است که باید برای آن تغییر کرد انواع مختلفقطع می کند. هر وقفه از جدول بردار وقفه، نام خود را دارد پارامتر داده شده. و در اینجا باید فایل راهنما را برای کامپایلر C30 باز کنید، به ویژه بخش (من آن را دارم ...) "dsPIC30F DSCs (SMPS) Interrupt Vectors" و به جدول نگاه کنید که کدام وقفه باید به چه صورت فراخوانی شود. من ارائه این جدول را در این مقاله مناسب نمی دانم، زیرا هر کسی که کامپایلر C30 دارد باید فایل راهنما ضمیمه شده باشد. hlpMPLABC30.chm(شخصاً این چیزی است که من به آن می گویم). و برای کسانی که این کامپایلر را ندارند، پس به جدول J نیازی ندارند.

    به هر حال، اگر عمیق‌تر با اصول توصیف تابع وقفه آشنا شوید، می‌توانید وجود ویژگی auto_psv ویژه را تشخیص دهید. این پارامتر در نظر گرفته شده است که به میکروکنترلر نشان دهد که باید رجیسترهای اصلی را قبل از اقدام به وقفه در پردازش ذخیره کند. من فرض می‌کنم که می‌دانی رجیسترهای کلید برای چه هستند.

    به عنوان مثال، توضیحات وقفه به شکل زیر است:

    خالی__ویژگی__((وقفه، خودکار_psv)) _INT1Interrupt()

    در بالا نمونه ای از هدر تماس زیر روال با استفاده از آدرس جدول اصلی بود. و برای یک میز جایگزین، فقط نیاز دارید پارامتر قابل تغییربعد از زیر خط درج کنید alt، مثلا:

    _ INT1 قطع کنید() -> _ AltINT1 قطع کنید()

    من می خواهم به این واقعیت توجه کنم که اگرچه روال وقفه مانند یک برنامه فرعی به نظر می رسد، اما نیازی به اعلان ندارد و همچنین اصلی ، از آنجایی که قبلاً توسط کامپایلر اعلام شده است، فقط باید هدر روتین وقفه را به درستی بنویسید.

    بیایید با مطالعه وقفه های ابتدایی شروع کنیم و سپس در مطالعه هر ماژول با وقفه های ذاتی آنها آشنا می شویم.

    3.1. وقفه تغییر پورت I/O (CN)

    یکی از ساده ترین وقفه ها برای درک، وقفه CN است. میکروکنترلر dsPIC33FJ32GP204 پر از چنین ورودی هایی است، بنابراین فکر می کنم این عدد هر درخواستی را برآورده کند. مهم نیست که کدام حالت در این کانال ها تغییر می کند ("1" -> "0" یا "0" -> "1")، این تغییر، در صورت فعال بودن، باعث می شود که پرچم "CNIF" تنظیم شود. برای فعال کردن وقفه تغییر سیگنال، باید موارد زیر را انجام دهید:

    1. کانال های CN مورد نیاز را روی ورودی تنظیم کنید (با استفاده از رجیستر TRISx).

    2. کنترل تغییر سیگنال را در ورودی CN مربوطه فعال کنید. برای این، در حال حاضر 2 ثبت CNEN1 و CNEN2 وجود دارد. شما می توانید به طور کامل به هر ثبات برای تنظیم دسترسی داشته باشید یا به بیت های مربوطه دسترسی داشته باشید (به عنوان مثال _CN15IE=1؛ _CN6IE=1;)

    3. در صورت لزوم، مقاومت های کششی را روشن کنید. همچنین دو رجیستر CNPU1 و CNPU2 برای این کار وجود دارد. به طور جداگانه نیز امکان پذیر است، برای مثال _CN15PUE=1; _CN6PUE=1;

    4. وقفه تغییر سیگنال به CN را فعال کنید ( _ CNIE=1 )

    5. اکنون به محض تغییر سیگنال روی پین های CN نظارت شده، پرچم وقفه _CNIF تنظیم می شود. و برنامه وارد تابع مدیریت وقفه می شود. کامپایلر C30 برای وقفه در تغییر سیگنال به CN شرح عملکرد زیر را ارائه می دهد:

    خالی __ ویژگی های __((__ قطع کردن __)) _ CNI قطع شود ()

    اینجاست که پردازش این وقفه اتفاق می افتد (به مثال مراجعه کنید)

    6. در روال وقفه، فراموش نکنید که پرچم وقفه را مجددا تنظیم کنید.

    برای آشنایی با این نوع وقفه به مثال زیر توجه کنید. دارای یک موتور و 4 سنسور. وقتی همه چیز مرتب است، موتور باید در خلاف جهت عقربه های ساعت بچرخد. اما به محض تغییر وضعیت سنسور (حالت اضطراری) - موتور باید بلافاصله شروع به چرخش در سمت معکوس(در جهت عقربه های ساعت). و پس از یک دوره زمانی معین، دوباره شروع به چرخش در خلاف جهت عقربه های ساعت کنید.

    به طور مشابه، یک فلزیاب بر روی ماشین های برداشت اجرا می شود. به عنوان مثال، هنگامی که علف های چمن زنی وارد دستگاه می شود، این حالت عادی کار است. اما به محض اینکه فلزیاب یک جسم فلزی را تشخیص می‌دهد، فوراً معکوس می‌شود و دستگاه، به عنوان مثال، این جسم فلزی را بیرون می‌ریزد تا به مکانیزم آسیب نرساند. و فلز توسط یک سنسور ویژه، متشکل از چندین کانال مستقل، اما در یک کانال، شناسایی می شود دستگاه عمومی. در مثال ما، البته، ما همه چیز را بسیار ساده می کنیم، به جای سنسور حضور فلزی، از دکمه های معمولی استفاده می کنیم.

    مونتاژ مدار در پروتئوس

    و اکنون برنامه ای برای انجام وظیفه می نویسیم.

    # عبارتند از " پ33 fxxxx. ساعت"

    _ FOSCSEL(0 ایکس02);

    _ FOSC(0 xE2);

    کاراکتر حالت; // متغیر جهت چرخش موتور را ذخیره می کند

    // "1" - حالت اضطراری، "0" - حالت عادی

    خالی init (خالی);

    خالی init (خالی)

    { _ CN8 PUE=1; // مقاومت pull-up را به ورودی CN8 (RC0) روشن کنید

    _ CN10 PUE=1; // مقاومت pull-up را به ورودی CN10 (RC2) روشن کنید

    _ CN17 PUE=1; // مقاومت pull-up را به ورودی CN17 (RC7) روشن کنید

    _ CN19 PUE=1; // مقاومت pull-up را به ورودی CN19 (RC9) روشن کنید

    آگهی1 PCFGL=0 xffff;

    PORTC=0; // پورت C را مقداردهی کنید

    LATC=0;

    TRISC=0 xFFFF; // پورت C را به عنوان ورودی تنظیم کنید

    PORTC=0 xFFFF;

    پورتا=0; // پورت A را مقداردهی اولیه کنید

    LATA=0;

    TRISA=0; // همه خروجی ها روی خروجی تنظیم می شوند،

    پورتا=0;

    _ CN8 IE=1; // کنترل تغییر سیگنال را فعال کنید

    _ CN10 IE=1; // پین های مربوطه

    _ CN17 IE=1; // اگر سیگنال روی آنها تغییر کند، پس

    _ CN19 IE=1; // تنظیم پرچم وقفه _CNIF

    _ CNIE=1; // وقفه INT1 را فعال کنید

    خالی __ ویژگی های__((__ قطع کردن__)) _ CNI قطع شود()

    حالت=1; // این یک حالت اضطراری است

    _ CNIF=0; // بازنشانی پرچم وقفه در تغییر سیگنال

    خالی اصلی (خالی)

    { ایستا طولانی بین المللی من;

    init();

    حالت=0; // در نظر بگیرید که حالت کار در هنگام راه اندازی عادی است

    در حالی که(1) // اجرا کن چرخه بی پایان

    { اگر (حالت) // اگر حالت اضطراری، پس

    { _ CNIE=0; // وقفه در تغییر سیگنال را غیرفعال کنید

    _ RA8=0;

    _ RA0=1; // در حالت اضطراری

    برای(من=0; من<210000; من++) // تأخیر ایجاد کند

    حالت=0; // فعال کردن عملکرد عادی موتور

    _ CNIE=1; // وقفه های CN را فعال کنید

    { _ RA8=1; // در حالت عادی

    _ RA0=0; // جهت چرخش موتور را ارائه می دهد

    } // while(1)

    3.2. وقفه خارجیINT

    اگر به میکروکنترلر خود نیاز دارید که فوراً به اقدامات دستگاه های خارجی پاسخ دهد، وقفه INT همان چیزی است که نیاز دارید. میکروکنترلر dsPIC33FJ32GP204 دارای سه کانال INT (INT0، INT1، INT2) است. یعنی شما می توانید وقفه خود را برای هر یک از سه دستگاه خارجی ارائه دهید. این وقفه از این جهت خوب است که می تواند کنترلر را از حالت SLEEP بیدار کند. علاوه بر این، شما نیازی به اسکن مداوم این ورودی ها ندارید، که باعث اشغال منابع میکروکنترلر می شود.

    وقفه INT زمانی رخ می دهد که سیگنال ورودی تغییر می کند، یا "0" -> "1" یا "1" -> "0". بستگی به وضعیت بیت دارد _INT1EP. اگر _INT1EP=1، سپس در لبه انتهایی. اگر _INT1EP= 0، سپس در لبه افزایشی (به عنوان مثال _INT1EP=1 - وقفه INT0 در لبه سقوط رخ می دهد).

    در مورد اولویت، وقفه INT0 بالاترین اولویت را دارد و در جدول وقفه اولین است. در زیر وقفه های INT1 و INT2 وجود دارد.

    در اصل، این همه ویژگی های این وقفه است. همه چیزهای دیگر مانند سایر وقفه ها است، یعنی باید وقفه خارجی مربوطه را فعال کنید. و اگر وقفه ای رخ دهد، پرچم _INTxIF مناسب را تنظیم می کند (به عنوان مثال، _INT1IF). فراموش نکنید که آن را رها کنید. به طور کلی، همه چیز ساده است.

    برویم سراغ یک مثال

    ما یک تماس الکترونیکی را به یک آپارتمان یا خانه ارسال می کنیم. هنگامی که دکمه فشار داده می شود، دستگاه باید صادر شود سیگنال صوتیو با نور چشمک بزنید (برای کسانی که دوست دارند موسیقی را با صدای بلند گوش کنند).

    ما یک مدار در PROTEUS رسم می کنیم، علاوه بر میکروکنترلر، به یک دکمه دیگر، یک زنگ و یک LED نیاز داریم.

    به نظر من تصویر بسیار واضح است. بریم سراغ برنامه.

    #عبارتند از"p33Fxxxx.h"

    // تنظیم بیت های تنظیم نوسان ساز (HS)

    _ FOSCSEL(0 ایکس02);

    _ FOSC(0 xE2);

    کاراکترحالت؛// "1" - تماس را روشن کنید، "0" - تماس را خاموش کنید

    خالیinit(void);//اعلان یک روال اولیه سازی

    // ** مقداردهی اولیه زیر روال **

    خالیآغاز (باطل)

    ( _CN4PUE=1;// مقاومت pull-up را به ورودی CN4 (RB0) روشن کنید

    AD1PCFGL=0xffff;// همه پین ​​ها به عنوان ورودی/خروجی دیجیتال

    PORTB=0x00;// پورت B را مقداردهی اولیه کنید

    LATB=0;

    TRISB=0x0001;// خروجی RB0 روی ورودی تنظیم شده است

    PORTB=0x00;

    // پورت C را مقداردهی کنید.

    PORTC=0;

    LATC=0;

    TRISC=0;//تنظیم تمام پین ها به عنوان خروجی

    PORTC=0;

    RPINR0=0x0000;// سیگنال INT1 پیکربندی شده است تا RP0 (RB0) از خروجی حذف شود (این

    دستور // برای همه dsPIC نیست

    _INT1EP=1;// وقفه INT1 در لبه سقوط رخ می دهد

    _INT1IE=1;// وقفه INT1 را فعال کنید

    // ****** روال وقفه *

    خالی __ ویژگی های__((__ قطع کردن__)) _ INT1 قطع کنید()

    حالت=1; // باید تماس را فعال کنید

    _ INT1 اگر=0; // پرچم وقفه INT1 را بازنشانی کنید

    // **** نقطه ورود برنامه *

    خالی اصلی (خالی)

    { ایستا طولانی بین المللی من; //اعلان یک متغیر برای سازماندهی تاخیر

    init();// روال اولیه سازی تماس

    state=0;// ابتدا تماس باید خاموش شود

    در حالی که (1)// یک حلقه بی نهایت را شروع کنید

    (اگر (حالت)// اگر حالت "1" باشد، پس

    (_RC0=1;// LED را روشن کنید

    _RC2=1;// زنگ را روشن کنید

    برای (i=0;i<160000;i++) // تاخیر، زمان مشخصی را برای بازی فراهم می کند

    state=0;// نشان می دهد که buzzer باید غیرفعال باشد

    دیگر// در غیر این صورت، اگر حالت "0" باشد، پس

    (_RC0=0;// LED را خاموش کنید

    _RC2=0;// توقف بوق

    } // while(1)

    به طور مشابه، با وقفه های INT0 و INT2 کار کنید. در مثال های بعدی، بیش از یک بار از این وقفه ها استفاده خواهیم کرد.

    چنین شرایطی وجود دارد که شما باید کارهای مختلف زیادی را روی یک دستگاه جانبی آویزان کنید، اما این تنها یکی است و باید کاری در مورد آن انجام شود.

    یک مثال ساده یک تایمر و وقفه سرریز آن است.
    ما می توانیم سرعت شاتر و وقفه را برای انجام برخی عملیات تنظیم کنیم. اما اگر در یک نقطه از زمان بخواهیم تایمر وقفه یک عملیات را انجام دهد و سپس عملیات دیگری را انجام دهد، سوم. بله، بسته به شرایط به هر تعداد که دوست دارید. و تنها یک بردار وجود دارد.

    یا مثلا USART. ما ممکن است به راحتی نیاز داشته باشیم که بسته به حالت وقفه، کدهای متفاوتی پس از رسیدن یک بایت اجرا شود. در یک حالت - صدور سلام، در حالت دیگر - ارسال الفاظ ناپسند به حمام. در سومین ضربه به سر. و تنها یک بردار وجود دارد.

    البته می توانید یک ساختار سوئیچ کیس را به کنترل کننده وقفه اضافه کنید و با انتخاب یک حالت، به قسمت مورد نظر کد بروید، اما این کاملاً دست و پا گیر است و مهمتر از همه اینکه بسته به اینکه زمان انتقال متفاوت خواهد بود. ترتیبی که ساختارهای نظرسنجی-مقایسه سوئیچ-مورد پیش خواهد رفت.

    یعنی در یک سوئیچ از فرم:

    1 2 3 4 5 6 7 سوئیچ (x) ( 1 : اقدام 1 2 : اقدام 2 3 : اقدام 3 4 : اقدام 4 )

    switch(x) ( 1: Action 1 2: Action 2 3: Action 3 4: Action 4 )

    یک مقایسه متوالی x ابتدا با 1، سپس با 2، سپس با 3 و به همین ترتیب تا زمانی که همه گزینه ها تمام شوند وجود خواهد داشت. و در این مورد، واکنش به Action 1 سریعتر از واکنش به Action 4 خواهد بود. این امر به ویژه هنگام محاسبه فواصل زمانی دقیق روی تایمر بسیار مهم است.

    اما یک راه حل ساده برای این مشکل وجود دارد - پرش شاخص. کافی است قبل از اینکه منتظر وقفه باشیم تا متغیرها را از قبل بارگذاری کنیم (یا می‌توانید فوراً در ثبت شاخص Z) جهتی را که باید بردار خود را تغییر مسیر دهیم و انتقال شاخص را در کنترل کننده وقفه بچسبانیم. و ویلا! انتقال در جایی خواهد بود که شما به آن نیاز دارید، بدون هیچ مقایسه ای بین گزینه ها.

    در حافظه، متغیرهایی را برای یک بردار شناور ایجاد می کنیم:

    Timer0_Vect_L: .byte 1 ; دو بایت آدرس، High و Low Timer0_Vect_H: .byte 1

    آماده شدن برای انتظار وقفه ساده است، آن را می گیریم و با آدرس مورد نظر در متغیر خود بارگذاری می کنیم

    CLI ; بخش بحرانی وقفه OFF LDI R16,low(Timer_01) ; آدرس را می گیریم و STS Timer0_Vect_L,R16 را ذخیره می کنیم. آن را در یک سلول حافظه LDI R16,High(Timer_01) ; به طور مشابه، اما با بالاترین بردار STS Timer0_Vect_H,R16 SEI. وقفه روشن است

    همه چیز، شما می توانید تایمر را راه اندازی کنید و منتظر وقفه ما باشید. مشابه با موارد دیگر.

    و کنترل کننده به نظر می رسد:

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 ;=============================== ; ورودی وقفه سرریز از Timer0 ;============================ TIMER_0: PUSH ZL ; ذخیره فهرست شاخص برای پشته PUSH ZH. زیرا ما از آن PUSH R2 استفاده می کنیم. R2 را ذخیره کنید، زیرا ما همچنین آن را در R2، SREG خراب می کنیم. ثبت پرچم PUSH R2 را بازیابی و ذخیره کنید. اگر این کار را انجام ندهید، 100٪ با اشکالاتی مواجه می شویم LDS ZL,Timer0_Vect_L ; آدرس بردار جدید LDS ZH,Timer0_Vect_H را بارگیری کنید. هر دو بایت CLR R2 ; پاک کردن R2 یا R2,ZL؛ بردار را برای صفر بررسی می کنیم. در غیر این صورت، آنالوگ OR R2,ZH را می گیریم. reset"a. چک از طریق عملیات OR BREQ Exit_Tm0 می رود؛ با انباشت نتیجه در R2؛ بنابراین محتویات Z را خراب نمی کنیم و مجبور نیستیم؛ دوباره آن را بارگذاری کنید IJMP؛ ما در امتداد جدید ترک می کنیم. بردار؛ از وقفه خارج شوید Exit_Tm0: POP R2؛ ثبت پرچم OUT SREG,R2 POP R2 را دریافت و بازیابی می کنیم؛ R2 POP ZH را بازیابی می کنیم؛ بازیابی Z POP ZL RETI؛ بردار اضافی 1 Timer_01: NOP؛ اینها بردارهای جدید ما هستند NOP؛ اینجا ما می‌توانیم هر کاری را NOP انجام دهیم؛ ترجیحاً نه برای مدت طولانی - در همان وقفه NOP؛ اگر از هر NOP دیگری استفاده کنیم، آن‌ها را در پشته RJMP Exit_Tm0 نیز ذخیره می‌کنیم؛ این یک انتقال برای خروج از وقفه است؛ به‌ویژه از طریق انجام می‌شود. RJMP به منظور؛ بردار اضافی 2؛ ذخیره ده بایت در کد بازگشتی :))) Timer_02: NOP NOP NOP NOP NOP RJMP Exit_Tm0 ;بردار اضافی 3 Timer_03: NOP NOP NOP NOP NOP RJMP Exit_Tm0

    ;=============================== ; ورودی وقفه سرریز از Timer0 ;============================ TIMER_0: PUSH ZL ; ذخیره فهرست شاخص برای پشته PUSH ZH. زیرا ما از آن PUSH R2 استفاده می کنیم. R2 را ذخیره کنید، زیرا ما همچنین آن را در R2، SREG خراب می کنیم. ثبت پرچم PUSH R2 را بازیابی و ذخیره کنید. اگر این کار را انجام ندهید، 100٪ با اشکالاتی مواجه می شویم LDS ZL,Timer0_Vect_L ; آدرس بردار جدید LDS ZH,Timer0_Vect_H را بارگیری کنید. هر دو بایت CLR R2 ; پاک کردن R2 یا R2,ZL؛ بردار را برای صفر بررسی می کنیم. در غیر این صورت، آنالوگ OR R2,ZH را می گیریم. reset"a. چک از طریق عملیات OR BREQ Exit_Tm0 می رود؛ با انباشت نتیجه در R2؛ بنابراین محتویات Z را خراب نمی کنیم و مجبور نیستیم؛ دوباره آن را بارگذاری کنید IJMP؛ ما در امتداد جدید ترک می کنیم. بردار؛ از وقفه خارج شوید Exit_Tm0: POP R2؛ ثبت پرچم OUT SREG,R2 POP R2 را دریافت و بازیابی می کنیم؛ R2 POP ZH را بازیابی می کنیم؛ بازیابی Z POP ZL RETI؛ بردار اضافی 1 Timer_01: NOP؛ اینها بردارهای جدید ما هستند NOP؛ اینجا ما می‌توانیم هر کاری را NOP انجام دهیم؛ ترجیحاً نه برای مدت طولانی - در همان وقفه NOP؛ اگر از هر NOP دیگری استفاده کنیم، آن‌ها را در پشته RJMP Exit_Tm0 نیز ذخیره می‌کنیم؛ این یک انتقال برای خروج از وقفه است؛ به‌ویژه از طریق انجام می‌شود. RJMP به منظور؛ بردار اضافی 2؛ ذخیره ده بایت در کد بازگشتی :))) Timer_02: NOP NOP NOP NOP NOP RJMP Exit_Tm0 ;بردار اضافی 3 Timer_03: NOP NOP NOP NOP NOP RJMP Exit_Tm0

    پیاده سازی برای RTOS
    اما اگر برنامه ای داشته باشیم که به گونه ای ساخته شده باشد که تمام کدها از طریق زنجیره وظیفه از طریق توزیع کننده RTOS بچرخند؟ محاسبه نحوه اجرای این زنجیره ها نسبت به یکدیگر در ذهن بسیار دشوار است. و هر یک از آنها می توانند سعی کنند تایمر را در اختیار بگیرند (البته نه خودسرانه، به پیشنهاد ما، ما در حال نوشتن برنامه هستیم، اما پیگیری اینکه چگونه همه چیز به موقع خواهد بود دشوار خواهد بود).
    در محورهای بزرگ مدرن، مکانیزم Mutual exclusion - mutex برای این مورد وجود دارد. آن ها این یک نوع پرچم شلوغ است. اگر فرآیندی مثلاً با UART ارتباط برقرار کند، آنگاه فرآیند دیگری جرأت نمی‌کند بایتی را در آنجا قرار دهد و با وظیفه‌شناسی منتظر می‌ماند تا اولین فرآیند UART را آزاد کند، که با پرچم نشان داده می‌شود.

    هیچ مکانیسم حذف متقابلی در من وجود ندارد، اما می توان آنها را اجرا کرد. حداقل کمی شباهت داشته باشید. من نمی خواهم اجرای کامل این همه آشغال را انجام دهم، زیرا هدف من حفظ اندازه هسته در 500-800 بایت است.
    ساده ترین راه این است که یک بایت دیگر در حافظه ذخیره کنید - متغیر busy. و هنگامی که یک فرآیند یک منبع را می گیرد، زمان انتشار تقریباً آن را روی این متغیر می نویسد. زمان به تیک تایمر سیستم می رود که من 1 میلی ثانیه دارم.
    اگر هر فرآیند دیگری سعی کند به همان منبع سخت افزاری دسترسی پیدا کند، ابتدا به حالت مشغول بودن آن نگاه می کند، مدت زمانی را که در آن مشغول خواهد بود می شمرد و برای این مدت سیگار می کشد - با تایمر خود را در صف بارگذاری می کند. آنجا او دوباره چک می کند و غیره. این ساده ترین گزینه است.

    مشکل اینجاست که اگر متقاضیان زیادی برای یک بردار وجود داشته باشد، فرآیندها به دور و اطراف انجام می‌شود، مانند کوبیدن جوانان به دور تنها توالت میدان در طول جشن‌های جشن. مثانه کسی نمی تواند آن را تحمل کند - الگوریتم خراب می شود. و چه کسی انجیر را حدس بزنید، زیرا. مدل سازی مشکل خواهد بود

    راه حل مشکل اضافه کردن یک زنجیره معمولی دیگر است، این بار برای دسترسی به منبع. به طوری که او اصلاً بیکار نمی ماند. آن ها یکی بیرون پرید، سپس دومی، سومی و به همین ترتیب تا زمانی که همه فرآیندها کار خود را در نوعی USART انجام دهند.
    نقطه ضعف واضح است - یک صف دیگر حافظه اضافی، کد اضافی، زمان اضافی است. البته می توانید کد توزیع کننده مدار اصلی را در صف به بردار منحرف کرده و تحریک کنید. اما در اینجا باید همه چیز را با دقت اشکال زدایی کنید، زیرا با وقفه فراخوانی می شود! بله، و دست و پا گیر، تنها زمانی لازم است که متقاضیان زیادی داشته باشیم.

    راه حل دوم این است که متغیر busy time را حذف کنید و فقط پرچم "Busy!" باقی بماند. و فرآیندی که سعی می‌کند اعمال شود، به سمت دود کردن فرار نمی‌کند، بلکه چند قدم به عقب بازمی‌گردد - تا انتهای صف کار و بلافاصله برمی‌گردد. افرادی که در اطراف توالت هستند در حال دویدن نیستند، بلکه آرنج های خود را در ورودی فشار می دهند، طبق این اصل که چه کسی ابتدا از آن می خزد.
    یکی دیگر از اشکالات، بار زیاد روی خط لوله اصلی است، تعداد زیادی درخواست برای ایجاد صف برای کل RAM برای مدت طولانی و ملاقات با پشته، و این مملو از یک آخرالزمان جهانی است.

    البته، تایمر در اینجا به عنوان مثال آورده شده است، بسیاری از کارها را می توان با تایمر سیستم RTOS حل کرد، اما اگر به طور ناگهانی به گسستگی کمتر یا سرعت پاسخگویی بالا به یک رویداد نیاز دارید (و نه تا زمانی که خط لوله اصلی آن را بکشد. وظیفه تا اجرا)، سپس مکانیسم وقفه کنترل شده، IMHO، سپس پزشک چه چیزی را تجویز می کند.