نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr...

61
اﺻﻔﻬﺎن داﻧﺸﮕﺎه ﻣﻬﻨﺪﺳﯽ و ﻓﻨﯽ داﻧﺸﮑﺪة درس: ﺳﯿﺴﺘﻤ ﭘﯿﺸﺮﻓﺘﻪ ﺑﻼدرﻧﮓ ﻬﺎي ﻣﻮﺿﻮع: ﭘﯿﺎده ﺳﺎ ﺳﯿﺴﺘﻢ ﯾﮏ زي ﻋﺎﻣﻞ ﺑﻼدرﻧﮓ ﺑﺮاي ﻣﯿﮑﺮوﮐﻨﺘﺮﻟﺮﻫﺎ درس اﺳﺘﺎد: دﮐﺘﺮ ﺟﻤﺸﯿﺪي ﮐﻤﺎل ﻋﻠﯽ ﺑﻬﻠﻮﻟﯽ ﻓﺮوردﯾﻦ ﻣﺎ ه1386

Transcript of نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr...

Page 1: نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr يﺎﻬﺗﺎﺒﺛ ﮥﺸﻘﻧ :1 ﻞﮑﺷ AVR يﺎﻬﺗﺎﺒﺛ و هداد ﻪﻈﻓﺎﺣ

دانشگاه اصفهان

دانشکدة فنی و مهندسی هاي بالدرنگ پیشرفتهسیستم: درس

:موضوعبراي بالدرنگ عامل زي یک سیستمسا پیاده

میکروکنترلرها

:استاد درس کمال جمشیدي دکتر

بهلولیعلی

1386 همافروردین

Page 2: نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr يﺎﻬﺗﺎﺒﺛ ﮥﺸﻘﻧ :1 ﻞﮑﺷ AVR يﺎﻬﺗﺎﺒﺛ و هداد ﻪﻈﻓﺎﺣ

2

فهرست مطالب 4......................................................................................................................دهی چک1

5....................................................................................................................... مقدمه2

AVR..................................................................................................7 يکروکنترلرهای م3

AVR......................................................................................................7 ي ثباتها3-1

AVR.....................................................................................8 ي حافظه داده و ثباتها3-2

AVR.................................................................................9 محصوالتي خانواده ها3-3

3-3-1 Tiny AVR.................................................................................................9

3-3-2 Mega AVR...............................................................................................9

3-3-3 LCD AVR..............................................................................................10

10...................................................................................................................افزار نرم4

11..........................................................................................................يشنهادی طرح پ5

11........................................................................................عامل بالدرنگ ستمی سي کدها6

12................................................................................................ی عموميرهای متغ6-1

6-1-1 os_central_table.......................................................................................12

13........................................................................................................ ثابتها6-1-2

14............................................................................... شدهفی تعريها نوع داده6-1-3

6-2 Tasks14..........................................................................................................ها

14....................................................................................................... مقدمه6-2-1

Task) TCB(.............................................................................14 بلوك کنترل 6-2-2

task.................................................................................................16 جادی ا6-2-3

17...................................................................................................... استک6-2-4

6-2-5 Null task.................................................................................................17

17.......................................................................................... نمونه برنامهکی 6-2-6

19.................................................................................................هاtask ي زمانبند6-3

6-3-1 Scheduler................................................................................................19

6-3-2 Dispatcher...............................................................................................19

Page 3: نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr يﺎﻬﺗﺎﺒﺛ ﮥﺸﻘﻧ :1 ﻞﮑﺷ AVR يﺎﻬﺗﺎﺒﺛ و هداد ﻪﻈﻓﺎﺣ

3

19................................................................................................هاtask نی ارتباط ب6-4

19................................................................................................... سمافورها6-4-1

6-4-2 Mailboxes...............................................................................................21

23......................................................................................................... صفرمری تا6-5

24..................................................................................................ها سورس برنامه6-6

6-6-1 rtos.h......................................................................................................24

6-6-2 rtos_core.c..............................................................................................26

6-6-3 user_task.c..............................................................................................35

6-6-4 Rtos_semaphore.c....................................................................................39

6-6-5 rtos_mbox.c............................................................................................41

6-6-6 user_task.c..............................................................................................42

6-6-7 user_task.h..............................................................................................46

6-6-8 rtos_uart.c...............................................................................................46

49..........................................................................................عامل ستمی روش استفاده از س7

Atmega32(..................................................................................50مشخصات (1 مۀی ضم8

52......................................................................................) و اجرالینحوة کامپا (2 مۀی ضم9

rtos.c..............................................................................................56 لی سورس فا9-1

60.....................................................................افزار سختيعامل رو ستمی سيساز ادهی پ9-2

61................................................................................................................... مراجع10

Page 4: نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr يﺎﻬﺗﺎﺒﺛ ﮥﺸﻘﻧ :1 ﻞﮑﺷ AVR يﺎﻬﺗﺎﺒﺛ و هداد ﻪﻈﻓﺎﺣ

4

چکیده 1 است که براي عملیات بالدرنگ در نظر گرفته multi taskعامل در واقع یک سیستمسیستم عامل بالدرنگ

. هاي زمانی مورد نیاز را برآورده کند اند که محدودیت اي تنظیم شده شده است و پارامترهاي آن به گونهدن پیاده هاي بالدرنگ باعث سادگی و سریع ش سازي سیستم عامل بالدرنگ براي پیاده استفاده از یک سیستم

. گردد نویس در گیر جزئیات نمی باشد چون عمال بستري براي پیاده سازي ایجاد شده است و برنامه سازي میاز طرفی دیگر میکروکنترلرهاي جدید با داشتن امکانات زیاد و سادگی طراحی مدارهاي سخت افزاري مبتنی

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

در این گزارش به معرفی . افزار با استفاده از میکروکنترلرها بسیار سریع و اقتصادي خواهد بود افزار و نرم سختتوان از نوشته شد و با اندکی تغییر میAVRشود که براي میکروکنترلرهاي ه میعامل بالدرنگی پرداخت سیستم

.آن براي سایر میکروکنترلرها نیز استفاده کرد

Page 5: نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr يﺎﻬﺗﺎﺒﺛ ﮥﺸﻘﻧ :1 ﻞﮑﺷ AVR يﺎﻬﺗﺎﺒﺛ و هداد ﻪﻈﻓﺎﺣ

5

مقدمه 2حافظه، پردازنده، نرم افزاري است که مسئول کنترل و بکار گیري منابع سخت افزاري مانند سیستم عاملها و چهار چوبی را براي اجراي برنامهسیستم عامل .ستسازي دیسک و تجهیزات جانبی ا فضاي ذخیره Single Taskهاي در حال اجرا به دو دستۀ عاملها از لحاظ تعداد برنامه سیستم. کند ها فراهم می ارتباط بین آن

، چندین برنامۀ آمادة اجرا در حافظه وجود multi taskهاي عامل در سیستم. شوند تقسیم میmulti taskو قسمتی از سیستم عامل که زمان پردازنده را بین . کند عامل زمان پردازنده را بین آنها تقسیم می که سیستمدارند

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

. شود به این برنامۀ انتخاب شده منتقل می Dispatcherعامل به عنوان NonPreemptive و Preemptiveشود به دو دستۀ استفاده میSchedulerالگوریتمهاي زمانبندي که توسط

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

تواند کنترل را از یک برنامۀ در حال اجرا بگیرد و به برنامۀ عامل می سیستمPreemptiveروش زمانبندي امل قادر است کنترل اجراي برنامه را موقتا قطع و برنامۀ دیگري را اجرا ع این روش چون سیستم. دیگر دهد

.سازي کند را پیاده round robinتواند الگوریتمهاي زمانبندي الویت دار و میSchedulerکند بنابراین تبادل داده انجام ها بتوانند با یکدیگر ها فراهم کند تا برنامه سیستم عامل باید محیطی را براي ارتباط بین برنامه

همچنین همزمانی مورد نیاز بین آنها را . گیرد انجام میMailBox یا PIPEدهند این کار معموال با استفاده از .کند ها و سمافورها فراهم می با استفاده از سیگنال

زمانی هاي تعیین شده در بازة عاملی است که قادر به اجراي برنامه سیستم) RTOS1(سیستم عامل بالدرنگمشخصی باشد و در صورتی که این بازة زمانی رعایت نشود، سیستم عامل در انجام وظیفۀ خود شکست

باشد Preemptive باشد، ثانیا multi taskعامل بالدرنگ اوال باید با توجه به نکتۀ فوق سیستم. خورده است نوع سیستمها برآورده کردن هدف اصلی در این. سازي کند تا بتواند مکانیزم اولویت بندي را پیاده

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

هاي بالدرنگ به قسمت مدیریت حافظه نیازي ندارند، چون عامل خیلی از سیستم. باشند نمایشگر ساده می

1 Real Time Operating System

Page 6: نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr يﺎﻬﺗﺎﺒﺛ ﮥﺸﻘﻧ :1 ﻞﮑﺷ AVR يﺎﻬﺗﺎﺒﺛ و هداد ﻪﻈﻓﺎﺣ

6

Taskدر . هاي مورد نیاز براي اجرا از همان ابتدا مشخص هستند و نیازي به پیاده سازي این قسمت ندارند .اند تعدادي از سیستم عامل هاي بالدرنگ متن باز و اختصاصی ارائه شده1جدول

بالدرنگعاملهاي لیستی از سیستم: 1جدول

OpenSorces RTOS Proprietary RTOS ECos Windows CE µCOS Ardence RTX EROS ChorusOS CapROS DMERT Coyotos DNIX Fiasco (L4clone) Symbian OS FreeRTOS embOS (Segger) C Executive HP-1000/RTE scmRTOS Intime MenuetOS ITRON Nut/OS LynxOS Phoenix-RTOS MERT Prex MicroC/OS-II RTAI µnOS RTEMS MQX RTOS RTLinux Nucleus Solaris OSE SHaRK OSEK/VDX TRON Project OSEKtime TUD:OS Phar Lap ETS Xenomai PikeOS Marte OS QNX

این . شود عامل بالدرنگ براي میکروکنترلرها پرداخته می این گزارش به نحوة پیاده سازي یک سیستمدر

CodeVisionAvr 1.23.8C standardافزار شده است و براي کمپایل آن از نرم نوشته Cعامل به زبان سیستم .استفاده شده است

شود معرفی میAVRهاي ترتیب، ابتدا تراشههاي بعدي به روند گزارش به این صورت است که در قسمتسپس با توجه به خصوصیات آنها و نیازهاي مورد نیاز به ارائۀ طرح پیشنهادي براي سیستم عامل مزبور پرداخته

این گزارش داراي دو . شود ها به همراه توضیحات در مورد آنها آورده می شده و در نهایت لیست برنامهعامل افزار سیستم که به عنوان سختAtmega32، مشخصات میکرو کنترلر 1مۀ باشد که در ضمی ضمیمه می

Page 7: نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr يﺎﻬﺗﺎﺒﺛ ﮥﺸﻘﻧ :1 ﻞﮑﺷ AVR يﺎﻬﺗﺎﺒﺛ و هداد ﻪﻈﻓﺎﺣ

7

نحوة کامپایل و پراگرام کردن برد آزمایشی به همراه 2شود و در ضمیمۀ در نظر گرفته شده است آورده می .گردد ارائه گردیده است اجرا میPC نوشته شده که در کامپیوتر Cتصاویري از آن و همچنین کد برنامۀ

AVRمیکروکنترلرهاي 3ارائه شد و بعد از آن جزء تولیدات Atmel توسط شرکت1997سال براي اولین بار در AVR يژتکنولو

همراه با تعداد زیادي ثبات RISC مزیت اصلی این تکنولوژي داشتن هسته .گرفت محبوب این شرکت قرارزیادي ریز تند و توسط آنها می توان تعدادمرتبط هس ALU این ثباتها به.است Working Register کاري یا

هر دستورالعمل یک پالس دستورالعمل را در مدت زمان یک پالس ساعت اجرا کرد به عبارتی دیگر اجرايمیکروکنترلرهاي دیگر در تعداد زیادتري از ساعت الزم دارد در حالیکه اجراي این ریز دستورالعملها در

می توانند بسیار سریعتر عمل کنند و همچنین کدهاي با حجم ها AVR نپالس ساعت اجرا می شوند بنابرایکار می کند با کارایی 4MHzکه با سرعت AVR عنوان مثال کارایی یک به.باالیی را اجرا کنند

.برابر است 48MHz با سرعت 8051 کنترلرو همچنین میکرو 16MHz با سرعت PIC کنترلرمیکرو

AVR ثباتهاي 3-1 .باشند می . r31 تا r0 به نامهاي بیتی همه منظوره هشتثبات 32داراي AVR بیتیشتهمیکروکنترلرهاي

ثبات 32دو ثبات از همان که هر کدام از این سه ثبات Z و Y و X ثبات آدرس شانزده بیتی با نام مستعار سه . (X(r27:r26), Y(r29:r28), Z(r31:r30) بیتی هستند یعنی8

0x3d(SPL)و 0x3e(SPH):خروجی/گر پشته که در آدرسهاي ورودي ر اشارهبیتی به منظو 16 یک ثبات .اند قرارگرفته

که بیتهاي آن به صورت . SREG بیتی به منظور سنجش وضعیت یا همان ثبات پرچم با نام8ثبات یکITHSVNZCباشد شرح این بیت ها به صورت زیر می. اند نامگذاري شده:

: I عمومی وقفه فعال ساز و غیرفعال ساز SREG7 یا Global Interrupt Enable/Disable Flag

: Tبیت انتقالی مورد استفاده دستورالعملهاي BLD وBST با نام SREG6 H: Half Carry Flag, SRE5 G

: Sبیت عالمت یا Signed tests Instruction Set, SREG4

: Vسرریزنما براي مکمل دو یا Two's Complement Overflow Indicator, SREG3

: Nبیت منفی یا Negative Flag, SREG2

: Zبیت صفر یا Zero Flag, SREG1 Carry Flag, SREG0 : C

Page 8: نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr يﺎﻬﺗﺎﺒﺛ ﮥﺸﻘﻧ :1 ﻞﮑﺷ AVR يﺎﻬﺗﺎﺒﺛ و هداد ﻪﻈﻓﺎﺣ

8

. نمایش داده شده استAVR، نقشۀ ثباتهاي 1در شکل

AVRنقشۀ ثباتهاي : 1شکل

AVR حافظه داده و ثباتهاي 3-2 MCU البته در برخی .هستند r31 تا r0 علق به ثباتهايمت) 0x001fتا x0000(آدرس اول حافظه یعنی 32

(Master Controller Unit) شود داده استفاده می ي ها براي ثباتها از فضاي حافظ.

خروجی است/دسترس آدرسهاي ورودي ي داده در از حافظه) x005fتاx0020 (آدرسهاي

.یک است بعد فقط شامل حافظه استاتداده به ي حافظه x0060 آدرس از

. ارائه شده استAVR نقشۀ حافظه میکروکنترلر 2در شکل

Page 9: نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr يﺎﻬﺗﺎﺒﺛ ﮥﺸﻘﻧ :1 ﻞﮑﺷ AVR يﺎﻬﺗﺎﺒﺛ و هداد ﻪﻈﻓﺎﺣ

9

AVRنقشۀ حافظۀ میکروکنتررهاي : 2شکل

AVR خانواده هاي محصوالت 3-3

3-3-1 Tiny AVR کوچک به منظور انجام یک عملیات ساده بهینه سازي شده و در ساخت وسایلی که به میکروهاي این مدل

.عظیم آنها براي ارزش و بهاي وسایل موثر است ییکارا .احتیاج است کاربرد فراوان دارند

3-3-2 Mega AVR :باشند این مدل از میکروکنترلر ها داراي امکانات زیر می

مگاهرتز16فرکانس کاري

داخلیRAMحافظۀ

داخلیEEPROMحافظۀ

فلشحافظه آنالوگ به دیجیتال هاي مبدل

USART و SPI و TWIلس بر طبق واسطه هاي سریا IEEE 1149.1 بر طبق JTAG واسطه ي

TWI: Two Wire Interface is a byte oriented interface USART: Universal Serial Asynchronous Receiver/Transmitter SPI: Serial Peripheral Interface

Page 10: نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr يﺎﻬﺗﺎﺒﺛ ﮥﺸﻘﻧ :1 ﻞﮑﺷ AVR يﺎﻬﺗﺎﺒﺛ و هداد ﻪﻈﻓﺎﺣ

10

JTAG available only on devices with 16KB Flash and up . کیلوبایت حافظه فلش موجود است16ش از فقط در میکروهاي با بیJTAGواسط

را برحسب ) حافظۀ برنامه( مقدار حافظۀ فلش xxباشد که میATMEGAxxنامگذاري این مدل به صورت باشند و تفاوت آنها در حجم و ها داراي امکانات فوق می هر کدام از این تراشه. کند مگابایت مشخص می

. شرح داده شده استATMEGA32یات تراشۀ ، خصوص1در پیوست . باشد تعداد آنها می

3-3-3 LCD AVR و کنترلر LCD و با داشتن درایورستپذیري ممکن طراحی شده ا با باالترین یکپارچگی و انعطافاین مدل

،بهترین واسطه را با انسان دارند و داراي توان مصرفی پایین و کارایی باالیی اتوماتیک وضوح تصویر

به منظور ارتباط به صورت SPI و UART سگمنت داشت و داراي یک100اده اولین عضو این خانو.هستند .بود سریال

افزار نرم 4افزارهاي خاص خود را براي شوند که هر کدام نرم به سه زبان زیر برنامه نویسی میAVRي میکروکنترلرها

:امر برنامه نویسی و کامپایل کردن نیاز دارند برنامه نویسی اسمبلی زبان -1 c زبان برنامه نویسی -2 برنامه نویسی بیسیک زبان -3

نیاز به خواندن کتاب یا جزوه خاصی زبان برنامه نویسی اسمبلی زبان اصلی بوده و براي یادگیري آن در AVR افزاري خانواده میکروکنترلرهاي ساختار سخت نویسی و تمامی دستورالعملهاي برنامه.یستن

DATA SHEET شرکتهاي آماده شده توسط ATMEL همچنین با مراجعه به سایتهاي .آورده شده است :شد میتوان با مثالهاي این زبان برنامه نویسی آشناذیل

www.avr-asm-tutorial.net/avr_en www.avrfreaks.net www.cygan.com/avr

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

برنامه نویسان میتوانند براي اجزاء سخت افزاري مختلف قابل اتصال به .است ویسی کامال باز گذاشتهکدنبراي .است CodevisionAVR نرم افزار محبوب مورد استفاده براي این برنامه نویسی .میکرو کدنویسی کنند

افزار فوق استفاده شده است رم و براي کمپایل آن از نCنوشتن سیستم عامل بالدرنگ مورد بحث نیز از زبان

Page 11: نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr يﺎﻬﺗﺎﺒﺛ ﮥﺸﻘﻧ :1 ﻞﮑﺷ AVR يﺎﻬﺗﺎﺒﺛ و هداد ﻪﻈﻓﺎﺣ

11

است اما قابلیتهاي زبانهاي AVR براي یادگیري برنامه نویسی زبان برنامه نویسی بیسیک که ساده ترین راه

BASCOM نویسی استفاده براي این نوع برنامه افزار محبوب مورد نرم .و اسمبلی را ندارد C برنامه نویسی

.است

طرح پیشنهادي 5باشند که پس از اتصال اند به این صورت می هاي بالدرنگی که تا کنون پیاده سازي شده عامل اکثر سیستم

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

یا هر نوع میکرو کنترلر دیگر محدودیت حافظه موجود است و AVRتوجه به اینکه در میکروکنترلرهاي به صورت دینامیک Taskباشند و نیازي به فراهم آوردن محیطی براي ایجاد ها از ابتدا معلوم میTaskمعموال

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

در طرح پیشنهادي هدف این . شوند یل میاها از یکدیگر جدا هستند و جداگانه کامپ عامل و برنامه ها سیستمدر این روش با توجه به . یل شوندها و سیستم عامل بالدرنگ تحت عنوان یک برنامه کامپاtaskاست که

هاي مورد نیاز و اولویت Taskگردد و تعداد سیستمی که قرار است به صورت بالدرنگ کار کند بررسی میها در Taskگردند و سپس این شود و برنامه نویسی می آنها و زمانهاي مورد نیاز براي آنها استخراج می

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

افزار را کند که تمام سخت تصور میTaskشود و هر ها نوشته میTask مستقل از بقیۀ Taskآورد که هر می رجیستر را در 32 تمام Taskار دارد، نیازي به هماهنگی در نحوة استفاده از رجیسترها نیست و هر در اختی

گردند بدون اینکه کاربر نیازي به نوشتن کدي داشته ها به صورت همزمان اجرا میTask همچنین .اختیار دارد . تغییر دهد را نیزSchedulingتواند الگوریتم با توجه به نوع سیستم کاربر می.باشد

عامل بالدرنگ کدهاي سیستم 6 پردازیم عامل مزبور می در این قسمت به شرح کدهاي سیستم

Page 12: نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr يﺎﻬﺗﺎﺒﺛ ﮥﺸﻘﻧ :1 ﻞﮑﺷ AVR يﺎﻬﺗﺎﺒﺛ و هداد ﻪﻈﻓﺎﺣ

12

متغیرهاي عمومی 6-1

6-1-1 os_central_table os_central_table کند، هاي اصلی مورد نیاز سیستم عامل را نگهداري می داده استراکچري است که

:فیلدهاي این استراکچر به صورت زیر است

typedef struct os_central_table { ULONG os_systime; // Timer ticks since last boot ULONG os_dispcntr;//dispatch counter

ULONG os_idlecntr;// Counter for processor idle time UBYTE os_version; // OS version UBYTE os_running; // OS running flag UBYTE os_schedrun;//scheduler flag os_tcb *tcb_used_list; // Pointer to used TCBs os_tcb *tcb_free_list; // Pointer to TCB freelist os_tcb *tcb_current; // Pointer to current running task TCB os_tcb *tcb_runq;//Pointer to highest priority runnable task TCB os_scb *scb_used_list; // Pointer to used semaphores os_scb *scb_free_list; // Pointer to semaphores freelist os_mcb *mcb_used_list; // Pointer to used message mailboxes os_mcb *mcb_free_list; // Pointer to mailbox freelist

} os_cent_tbl;

نمایش داده شده است2 استراکچر در جدول اینفیلدهايشرح

os_central_table فیلدهاي استراکچر: 2جدول

توضیحات نوع نام فیلدos_systime 32-bit unsigned

integer کند تعداد تیکهاي ساعت را شمارش می. os_dispcntr 32-bit unsigned

integer دهد تعداد دفعاتی که تعویض متن انجام شده را نشان می aos_idlecntr 32-bit unsigned

integer تعداد دفعاتی کهNULL-taskاحضار شده است aos_version 8-bit unsigned

integer نشان دهندة نسخۀ سیستم عامل است os_running 8-bit unsigned

integer عامل در حال اجرا دهد آیا سیستم فلگی است که نشان می باشد یا خیر می

os_schedrun 8-bit unsigned integer دهد فلگی است که نشان میschedulerفعال است یا خیر

tcb_used_list TCB pointer استفاده شده Taskاشاره گر به اولین tcb_free_list TCB pointer آزادTaskاشاره گر به اولین

Page 13: نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr يﺎﻬﺗﺎﺒﺛ ﮥﺸﻘﻧ :1 ﻞﮑﺷ AVR يﺎﻬﺗﺎﺒﺛ و هداد ﻪﻈﻓﺎﺣ

13

tcb_current TCB pointer اشاره گر بهTCB مربوط به Taskال اجرا در ح tcb_runq TCB pointer اشاره گر بهTCB مربوط به Task ي که باالترین اولویت را

باشد دارد و قابل اجرا میscb_used_list SCB pointer استفاده شدهروسمافگر به اولین اشاره scb_free_list SCB pointer آزادسمافوراشاره گر به اولین . mcb_used_list MCB pointer گر به اولین اشارهMailBox شدهادهتفاس mcb_free_list MCB pointer گر به اولین اشارهMailBox آزاد

ثابتها 6-1-2باشد که قبل از کامپایل کردن آن باید با مقدار صحیح مقدار دهی میconstantسیستم عامل داراي تعدادي

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

هایی که توسط کاربر باید مقدار دهی constantتمام . باشد احتصاص فضاي حافظه به صورت استاتیک می :ها عبارتند ازconstantاین . د قرار دارنrtos.hشود در فایل

OS_TASK_MAX, Taskماکزیمم تعداد ها

OS_SEM_MAX, ماکزیمم سمافورهاي مورد نیاز

OS_MBOX_MAX, هاي مورد نیازMail Box ماکزیمم

OS_TASK_HSTK_SIZE, افزاري اندازة استک سخت

OS_TASK_DSTK_SIZE, افزاري اندازة استک نرم

تواند با مقدار دهی این باشد و کاربر می یز توسط کاربر قابل مقدار دهی می نOS_TICK_TIMEمقدار ثابت عامل از این ثابت براي مقدار سیستم. ها انتخاب کندTask را براي Slice timeثابت قبل از کامپایل مدت هر

16 تا 1اند بین تو کند و می مقدار این ثابت زمان را بر حسب میلی ثانیه مشخص می. کند دهی تایمر استفاده میثانیه باشد، در صورتی که کاربر زمانهاي کوتاهتر یا طوالنی تري نیاز داشته باشد، باید مود تایمر در میلی

و کالك تایمر تایمر صفر استفاده شده است CTCدر پیاده سازي فعلی از مود . عوض شودMainقسمت . )1024کالك اصلی تقسیم بر .(کیلو هرتز انتخاب شده است15,624

OCR0کند تا به مقدار تعیین شده در رجیستر هشت بیتی تایمر از صفر شروع به شمارش میCTCمود در به مقدار فاصلۀ زمانی بین دو وقفه . کند دهد و شمارش را از صفر شروع می برسد، در این حالت تایمر وقفه می

Page 14: نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr يﺎﻬﺗﺎﺒﺛ ﮥﺸﻘﻧ :1 ﻞﮑﺷ AVR يﺎﻬﺗﺎﺒﺛ و هداد ﻪﻈﻓﺎﺣ

14

OCR016)( میکروکالك تایمر از تقسیم کالك اصلی. و کالك تایمر بستگی داردMhz بر مقدار تعیین ثابت در نظر گرفته TCCR0در پیاده سازي کنونی مقدار رجیستر . شود تعیین میTCCR0شده در رجیستر

.پذیرد انجام میOS_TICK_TIME با توجه به ثابت OCR0شده است و مقدار دهی رجیستر TCCR0یمر صفر را با مقدار دهی رجیستر صورتی که به رزولوشن بیشتري نیاز داشته باشید باید کالك تادر

. که کالك تایمر سریعتر باشدقرار دهیددر حالتی

هاي تعریف شده نوع داده 6-1-3 . تعریف شده استrtos.h نوع هاي زیر را در فایل

typedef unsigned char UBYTE; typedef unsigned int UWORD; typedef unsigned long int UDWORD; typedef unsigned long int ULONG;

6-2 Tasksها

مقدمه 6-2-1Taskشودکه محیط کاري مربوط به خودش را دارد و داراي یک به یک زیر برنامه یا تابع ساده گفته می

Contextعامل همیشه هنگام وقوع وقفۀ تایمر، سیستم. باشد میtask آماده به اجرایی را براي اجرا انتخاب .شته باشدکند که باالترین اولویت را دا می

ها از یک فضاي آدرس Taskدهد و همۀ عامل پیاده سازي شده عمل محافظتی از حافظه انجام نمی سیستم همچنین تمام متغیرهاي عمومی از جمله متغیرهاي مربوط به سیستم عامل توسط کنند مشترك استفاده می

Taskنامهبنابراین کاربران باید هنگام نوشتن بر. باشد ها قابل دسترسی می)Taskبه این نکته دقت کنند)ها.

)Task) TCBبلوك کنترل 6-2-2 Taskهاي مهم مربوط به کنترل تمام دادهTCBدر . باشد میTCBعامل داراي یک در سیستمTaskهر

ها توسط سیستم عامل به هم پیوند Taskهاي مربوط به TCBتمام . شود عامل نگهداري می توسط سیستم کنند دي یک طرفه ایجاد میخورند و یک لیست پیون می

:به صورت زیر تعریف شده استTCBفیلدهاي typedef struct os_task_control_block { void *hwstk; // Pointer to task's hardware stack void *datastk; // Pointer to task's data stack

UBYTE status; // Status of task UBYTE prio; // Priority of task UWORD delay; // Nbr of ticks to keep task sleeping ULONG ttime; //for keep track task time void *hstktop ; //for keep track stack use

Page 15: نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr يﺎﻬﺗﺎﺒﺛ ﮥﺸﻘﻧ :1 ﻞﮑﺷ AVR يﺎﻬﺗﺎﺒﺛ و هداد ﻪﻈﻓﺎﺣ

15

void *dstktop ; //for keep track stack use struct os_task_control_block *next_tcb;//Pointer to next task's TCB void *tcb_sem_q; // Next task on semaphore waiting list

} os_tcb;

: توضیحات فیلدهاي این استراکچر شرح داده شده است3در جدول os_task_control_block فیلدهاي استراکچر: 3جدول

توضیحات نوع نام فیلدhwstk Pointer گر به استک سخت افزاري اشاره datastk Pointer افزاري اشاره گر به استک نرم status 8-bit unsigned

integer عیتنشان دهندة وض Taskتواند یکی از که می RUNNABLE, DELAYD RUNNINGحاالت

WAITING باشد . prio 8-bit unsigned

integer الویتTaskعددي بین صفر . کند را مشخص می پایین ترین 255صفر باالترین اولویت و . 255تا

باشد اولویت میdelay 16-bit unsigned

integer مدت زمانی است کهTASK توسط . نباید اجرا شوداین زمان برحسب تیک . کاربر تاخیر خورده است

مشخص شده rtos.hباشد که در فایل ساعت می .است

ttime مدت زمانی که پردازنده به اینTask اختصاص . داده است

hstktop براي دنبال کردن استک استفاده دارد. dstktop براي دنبال کردن استک استفاده دارد.

Page 16: نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr يﺎﻬﺗﺎﺒﺛ ﮥﺸﻘﻧ :1 ﻞﮑﺷ AVR يﺎﻬﺗﺎﺒﺛ و هداد ﻪﻈﻓﺎﺣ

16

next_tcb TCB pointer گر به اشارهTCBبعدي در لیست tcb_sem_q TCB pointer گر به اشارهTCBبعدي که منتظر سمافور است

task ایجاد 6-2-3باشد، ایجاد عامل پیاده سازي شده می که جزئی از هستۀ سیستم()os_task_createها توسط تابع taskتمامی

شود تا در فراخوانی میNULL-taskعامل براي ایجاد خلی توسط سیستماین تابع به صورت دا. گردند می Taskسیستم عامل اولویت این . عامل مشکلی رخ ندهد ي تعریف نکند، براي سیستمTaskصورتی که کاربر

. هیچگاه اجرا نگرددtaskکاربر، این Taskدهد تا در صورت وجود را کمترین مقدار ممکن قرار می، اشاره گر به Taskاشاره گر به کد این : که عبارتند از باشد داراي چهار پارامتر می()os_task_createتابع

فضاي اختصاص داده شده براي استک سخت افزاري، اشاره گر به فضاي اختصاص داده شده براي استک .Taskنرم افزاري و نهایتا اولویت

این استک باید طبق فرمت خاصی باشد و با ساختاري که . شود افزاري تولید می در این تابع ابتدا استک سخت در آن Task انتظار دارد مطابقت داشته باشد به همین دلیل آدرس برگشت به CodevisionAVRافزار نرم

گیرددر این استک روي آن قرار میR29 و R28شود سپس تمام رجیسترهاي عمومی بجز قرار داده می .شود اینتراپت در آن فعال شده است روي استک قرار داده می که بیت مربوط به SREGرجیستر

Page 17: نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr يﺎﻬﺗﺎﺒﺛ ﮥﺸﻘﻧ :1 ﻞﮑﺷ AVR يﺎﻬﺗﺎﺒﺛ و هداد ﻪﻈﻓﺎﺣ

17

استک 6-2-4 به زبان اسمبلی از دو استک استفاده Cهاي نوشته شده از زبان براي تبدیل برنامهCodevisionAVRبرنامۀ افزاري توسط مکانیزم استک سخت. اند افزاري نامیده افزاري و نرم کند که اصطالحاً آنها را استک سخت میهنگامی که از دستورات . شود ها براي نگهداري آدرس برگشت استفاده می ینتراپت و صدا زدن زیر برنامها

Push یا Popافزاري براي ارسال پارامترها از استک نرم. شود شود در واقع از این استک استفاده می استفاده میافزاري براي ذخیره کردن متغیرهاي نرماز استک . شود و دریافت مقدار برگشتی از زیر برنامه استفاده می

باید داراي این دو استک مخصوص Task هر .شود اند نیز استفاده می ها استفاده شده محلی که در زیر برنامه . تعیین شده استrtos.hباشند که در فایل این استکها داراي اندازة ثابت می. به خودش باشد

6-2-5 Null task Null-task نیز مشابه Taskباشد ولی داراي چند خصوصیت متفاوت تعریف شده توسط کاربر میهاي

این دو .باشد میRunnableباشد و وضعیت آن همیشه داراي کمترین الویت میtaskاوال این . باشد می براي اجرا taskهاي کاربر در وضعیت اجرا نباشند، این Taskشود که اگر هیچ کدام از خصوصیت باعث می

taskاز این . قرار داشته باشدidleشود که سیستم در حالت در واقع زمانی اجرا میtaskن ای. انتخاب شودشود میزان بودن سیستم را نشان استفاده کرد که روشنایی آن باعث میLEDتوان براي روشن کردن یک می .دهد

یک نمونه برنامه 6-2-6عامل پیاده سازي شد، معرفی این سیستمدر این قسمت به عنوان مثال یک نمونه سیستم که با استفاده از

در نظر گرفته شد و برنامۀ task1, task2, task3 and task4 به نامهاي task چهار مثالدر این . کنیم می rtos_core.c که در فایل main توسط برنامۀ Task1. نوشته شدuser_tasks.cها در فایل taskمربوط به این

.شوند تولید شده، ایجاد میtaskها توسط این taskیۀ شود و بق قرار دارد ایجاد میTask شامل یک حلقۀ بینهایت هستند که باعث روشن و خاموش شدن 4 و3و2هاي ،Led متناظر خود روي استفاده ()os_sleepها از تابع Ledها براي ایجاد تاخیر بین روشن و خاموش شدن Task این .شوند برد می

.کند شود، غیر فعال می ا براي مدت معینی که در پارامتر آن ذکر می رtaskاین تابع . کنند میTask1کند و منتظر دریافت کاراکتري از طرف کامپیوتر پورت سریال میکرو را مقدار دهی میPCشود می .

با توجه به کاراکتر ارسال شده . کند میToggle متناظر خودش را Led نیز با دریافت هر کاراکتر taskاین

Page 18: نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr يﺎﻬﺗﺎﺒﺛ ﮥﺸﻘﻧ :1 ﻞﮑﺷ AVR يﺎﻬﺗﺎﺒﺛ و هداد ﻪﻈﻓﺎﺣ

18

همچنین این . دهد باشد انجام می ها میTask فرمان مربوطه را که فعال یا غیر فعال کردن یک از PCسط تو . ارسال کند تا کاربر از وضعیت آنها با خبر شودPCها را براي taskتواند اطالعات زمانی در مورد برنامه می

Page 19: نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr يﺎﻬﺗﺎﺒﺛ ﮥﺸﻘﻧ :1 ﻞﮑﺷ AVR يﺎﻬﺗﺎﺒﺛ و هداد ﻪﻈﻓﺎﺣ

19

هاtaskزمانبندي 6-3 .شود انجام میDispatcher و Schedulerها توسط زمانبندي و سوئیچ بین برنامه

6-3-1 Scheduler باشد که در تیک زمانی بعدي باید اجرا ي میtask ، انتخاب و تصمیم گیري در مورد schedulerوظیفۀ نام دارد و در ()os_schedule_این تابع . ها بستگی دارد Taskتصمیم گیري به وضعیت و اولویت ، . گردد که در ابتداي نام این تابع استفاده شده است براي مشخص کردن این _ت عالم. قرار داردrtos_core.cفایل

.شود و مخصوص خود سیستم عامل است هاي کاربر صدا زده نمیTaskاست که این تابع توسط این زمانبندي این امکان را . باشد میPre-emptiveعامل پیاده سازي شده از نوع الگوریتم زمانبندي سیستم

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

برنامۀ Context برنامۀ جاري و بار کردنContext انجام شود که شامل ذخیره کردن ()os_dispatch_تابع .باشد جدید می

6-3-2 Dispatcher تعویض متن . شود باشد که اصطاحا تعویض متن نامیده می ها میtask، سوئیچ واقعی بین dispatcherوظیفۀ

:باشد شامل سه مرحلۀ زیر می TCBگر استک در افزاري و ذخیره کردن اشاره قبلی در استک سختtaskذخیره کردن رجیسترهاي -1 جدید و بارکردن مقدار رجیسترها از استک task مربوط به TCBدن مقدار اشاره گر استک از بارکر-2

جدیدtaskافزاري سخت جدیدtaskرفتن به -3

که در ابتداي نام این تابع _عالمت . قرار داردrtos_core.c نام دارد و در فایل ()os_dispatch_این تابع شود و هاي کاربر صدا زده نمیTaskن است که این تابع توسط استفاده شده است براي مشخص کردن ای

.مخصوص خود سیستم عامل است

هاtaskارتباط بین 6-4

سمافورها 6-4-1 مقدمه

Page 20: نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr يﺎﻬﺗﺎﺒﺛ ﮥﺸﻘﻧ :1 ﻞﮑﺷ AVR يﺎﻬﺗﺎﺒﺛ و هداد ﻪﻈﻓﺎﺣ

20

سازي ناحیۀ بحرانی نیز استفاده و براي پیاده. شود ها استفاده میtaskسمافورها براي ایجاد هماهنگی بین تا 0تواند متغیر عمومی است که مقدار اولیه آن میتوان گفت سمافور یک در حالت کلی می. گردد می

. باشد 65535 بلوك کنترلی سمافور

هاي این بلوك کنترلی، حاوي تمام داده. شود تخصیص داده میSCB یک بلوك کنترلی به نام به هر سمافوراند و یک لیست این بلوکهاي کنترلی به هم دیگر پیوند خورده. باشد مورد نیاز سمافور مربوط به خودش می

.شود فیلدهاي بلوك کنترل سمافور به صورت زیر تعریف می. پیوندي را تشکیل داده اند typedef struct os_sema { UWORD count; // Semaphore value os_tcb *scb_sem_q; // Semaphore queue struct os_sema *next_scb;// Pointer next semaphore's SCB } os_scb;

os_sema فیلدهاي استراکچر: 4جدول

توضیحات نوع فیلدcount 16-bit unsigned

integer مقدار سمافور scb_sem_q TCB pointer گر به اولین اشارهTCB که منتظر این سمافور

.باشد میnext_scb SCB pointer اشاره گر بهSCBاستفاده شدة بعدي

ایجاد سمافور

،آزاد را از لیست SCBاین تابع اولین . گردد ایجاد می()os_sem_createاده از تابع سیستمی با استفسمافور فراخوانی کنندة Task را براي SCBگر به آن کند و اشاره کند و فیلدهاي آن را مقدار دهی می انتخاب می

SCBدر صورتی که . شود می به ان سمافور استفاده Handleگر به عنوان از این اشاره. گرداند این تابع برمی .گرداند آزاد موجود نباشد، این تابع مقدار تهی را برمی

نحوة عملکرد سمافور

مقدار سمافور ()os_waitتابع . گیرد مورد استفاده قرار می()os_signal و ()os_waitسمافور توسط دو تابع ي که این Taskکند و سپس اجراي میکند، اگر مقدار آن مثبت باشد آنگاه یک واحد از آن کم را چک می

Page 21: نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr يﺎﻬﺗﺎﺒﺛ ﮥﺸﻘﻧ :1 ﻞﮑﺷ AVR يﺎﻬﺗﺎﺒﺛ و هداد ﻪﻈﻓﺎﺣ

21

شود و فراخوانی کننده معلق میtaskاگر مقدار سمافور صفر باشد، آنگاه . یابد تابع را صدا زده است ادامه می . دیگري فراخوانی شودtask توسط ()os_signalشود تا اینکه تابع در صف انتظار سمافور قرار داده می

ي در صف انتظار وجود داشته باشد taskکند، اگر ظار سمافور را چک میابتدا صف انت()os_signalتابع اگر صف انتظار خالی باشد آنگاه مقدار . شود کند و زمانبند صدا زده می را از صف خارج میtaskاولین

.یابد فراخوانی کننده ادامه میtaskشود و سمافور یک واحد اضافه میبا غیر فعال کردن . ع اجرا شوند بنابراین باید در ناحیۀ بحرانی انجام شوندچون توابع سمافور باید بدون انقطا

. ها این کار به اسانی قابل انجام است وقفه

6-4-2 Mailboxes مقدمه

Mailbox براي ارسال پیام بین مکانیزمیtaskباشد ها می .Mailbox مکانی از حافظه است که حاوي باشد گري به آن پیام می اشاره

Mailboxل بلوك کنترهاي مورد نیاز باشد که براي نگهداري داده میMCB داراي یک بلوك کنترلی به نام Mailboxهر

Mailboxهمۀ . باشد میMailboxفیلدهاي . اند اند و یک لیست پیوندي ایجاد کرده ها به هم پیوند خورده : به صورت زیر استMailboxبلوك کنترل

typedef struct os_mail_box { os_scb *msend; // Semaphore for sending to mailbox os_scb *mrecv; // Semaphore for receiving from mailbox void *mmsg; // Pointer to message struct os_mail_box *next_mcb; // Pointer to next mailbox } os_mcb;

os_mail_box فیلدهاي استراکچر: 5جدول

توضیحات نوع فیلدmsend SCB pointer گر به سمافوري که براي ارسال استفاده اشاره

شود میmrecv SCB pointer گر به سمافوري که براي دریافت استفاده اشاره

شود میmmsg Pointer گر به پیام اشاره next_mcb MCB pointer گر به بلوك کنترل اشارهmailboxبعدي

Page 22: نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr يﺎﻬﺗﺎﺒﺛ ﮥﺸﻘﻧ :1 ﻞﮑﺷ AVR يﺎﻬﺗﺎﺒﺛ و هداد ﻪﻈﻓﺎﺣ

22

mailboxایجاد mailbox با استفاده از تابع سیستمی os_ mbox _create()این تابع اولین . گردد ایجاد میMCB آزاد را از،

فراخوانی Task را براي SCBگر به آن کند و اشاره کند و فیلدهاي آن را مقدار دهی می لیست انتخاب میدر صورتی که . شود استفاده میmailboxن به اHandleگر به عنوان از این اشاره. گرداند کنندة این تابع برمی

MCBگرداند آزاد موجود نباشد، این تابع مقدار تهی را برمی .Task ي که باmailboxکند باید کار می .ها باشد خودش مواظب اندازة پیام

mailboxنحوة عملکرد Mailbox توسط دو تابع os_mbox_send() و os_mbox_ recv ()تابع . دباشن قابل دسترسی می

os_mbox_send()اگر پیامی در ، mailbox نباشد آن را به mailboxاگر . کند ارسال میmailbox در حال تابع . خالی شودmailboxرود تا اینکه فراخوان کنندة این تابع به حالت تعلیق میtaskاستفاده باشد،

os_mbox_ recv () پیام را از mailboxکند و به دریافت میtask اگر . گرداند فراخوانی کننده برمیmailbox خالی باشد آنگاه Taskشود تا اینکه پیامی دریافت شود فراخوانی کننده به حالت تعلیق برده می.

Page 23: نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr يﺎﻬﺗﺎﺒﺛ ﮥﺸﻘﻧ :1 ﻞﮑﺷ AVR يﺎﻬﺗﺎﺒﺛ و هداد ﻪﻈﻓﺎﺣ

23

تایمر صفر 6-5 این تایمر با توجه به مقداري که در ثابت .کند تایمر صفر در سیستم عامل پیدا سازي شده نقش مهمی ایفا می

OS_TICK_TIMEایل در فrtos.hسرویس روتین این وقفه . دهد تعیین شده است وقفه میtask هایی را که خارج و آنها را فعال delayed فعال از حالت اند در موقع مناسب غیر فعال شده()os_sleepبا استفاده تابع

بزرگتر از delayکند و اگر فیلد فرایندها را چک میTCBسرویس روتین از طریق لیست پیوندي . کند می تغییر وضعیت runnableکند و اگر به صفر رسید آنگاه فرایند را به حالت صفر بود از آن یکی کم می

.دهد را افزایش میuptime سرویس روتین همچنین مقدار .کند را فراخوانی میschedulerدهد و می

Page 24: نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr يﺎﻬﺗﺎﺒﺛ ﮥﺸﻘﻧ :1 ﻞﮑﺷ AVR يﺎﻬﺗﺎﺒﺛ و هداد ﻪﻈﻓﺎﺣ

24

ها سورس برنامه 6-6

6-6-1 rtos.h

//define macro and data structure and constants #define OS_ENTER_CRITICAL { \ #asm("cli") \

os_crit_count++; \ }

#define OS_EXIT_CRITICAL { \ --os_crit_count; \

if(!os_crit_count){ \ #asm("sei") \

} \ }

int os_crit_count;

#define OS_TASK_RUNNABLE 0b00000000 #define OS_TASK_RUNNING 0b00000001 #define OS_TASK_WAITING 0b00000010 #define OS_TASK_DELAYD 0b00000100

#define OS_TASK_SUSPENDED 0b00001000 #define OS_TASK_SUSPENDED_WAIT 0b00010000

#define OS_TASK_SUSPENDED_DELA 0b00100000 // start of User configurable Constants: #define OS_TICK_TIME 1 //mSec (maximum value is 16ms)

#define OS_SEM_MAX 5 #define OS_TASK_MAX 5 #define OS_MBOX_MAX 2

#define OS_TASK_HSTK_SIZE 100 #define OS_TASK_DSTK_SIZE 200

//Scheduler task time acculumulator //When OS_CHCK==1 the scheduler uses timer1!

#define OS_CHCK 1 //sched time enable // end of User configurable Constants:

#define OS_GLOBAL_VAR #pragma regalloc- #define OS_GLOBAL_END #pragma regalloc+

typedef unsigned char UBYTE; typedef unsigned int UWORD; typedef unsigned long int UDWORD; typedef unsigned long int ULONG;

Page 25: نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr يﺎﻬﺗﺎﺒﺛ ﮥﺸﻘﻧ :1 ﻞﮑﺷ AVR يﺎﻬﺗﺎﺒﺛ و هداد ﻪﻈﻓﺎﺣ

25

typedef struct os_task_control_block { void *hwstk; // Pointer to task's hardware stack void *datastk; // Pointer to task's data stack UBYTE status; // Status of task UBYTE prio; // Priority of task UWORD delay; // Nbr of ticks to keep task sleeping ULONG ttime; //for keep track task time void *hstktop ; //for keep track stack use void *dstktop ; //for keep track stack use struct os_task_control_block *next_tcb; // Pointer to next task's TCB void *tcb_sem_q; // Next task on semaphore waiting list } os_tcb;

typedef struct os_sema { UWORD count; // Semaphore value os_tcb *scb_sem_q; // Semaphore queue struct os_sema *next_scb;// Pointer next semaphore's SCB } os_scb;

typedef struct os_mail_box { os_scb *msend; // Semaphore for sending to mailbox os_scb *mrecv; // Semaphore for receiving from mailbox void *mmsg; // Pointer to message

struct os_mail_box *next_mcb; // Pointer to next mailbox } os_mcb;

typedef struct os_central_table { ULONG os_systime; // Timer ticks since last boot

ULONG os_dispcntr; //dispatch counter ULONG os_idlecntr; // Counter for processor idle time UBYTE os_version; // OS version UBYTE os_running; // OS running flag UBYTE os_schedrun; //scheduler flag os_tcb *tcb_used_list; // Pointer to used TCBs os_tcb *tcb_free_list; // Pointer to TCB freelist os_tcb *tcb_current; // Pointer to current running task TCB os_tcb *tcb_runq; // Pointer to highest priority runnable task TCB os_scb *scb_used_list; // Pointer to used semaphores os_scb *scb_free_list; // Pointer to semaphores freelist os_mcb *mcb_used_list; // Pointer to used message mailboxes

os_mcb *mcb_free_list; // Pointer to mailbox freelist } os_cent_tbl;

// Kernel services and data-types that are visible to user tasks typedef os_scb os_semaphore;

Page 26: نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr يﺎﻬﺗﺎﺒﺛ ﮥﺸﻘﻧ :1 ﻞﮑﺷ AVR يﺎﻬﺗﺎﺒﺛ و هداد ﻪﻈﻓﺎﺣ

26

typedef os_mcb os_mailbox; typedef os_tcb os_task; extern os_tcb *os_task_create( void (*task)(void), UBYTE *hstack, UBYTE *dstack, UBYTE p ); extern void os_sleep( UWORD ticks ); extern ULONG os_uptime( void ); extern os_scb *os_sem_create( UWORD ival ); extern void os_wait( os_scb *semaphore ); extern void os_signal( os_scb *semaphore ); extern os_mcb *os_mbox_create( void ); extern void os_mbox_send( os_mcb *mbox, void *msg ); extern void *os_mbox_recv( os_mcb *mbox );

6-6-2 rtos_core.c

//Core of operating system( _os_schedule timer interrupt _init_free_list os_start //os_sleep os_uptime NULLTASK main) are in this file //Main function is in this file

os_cent_tbl os_ctbl; // Central table os_tcb all_tcb[OS_TASK_MAX]; // Pointers to Task Control Blocks

os_scb all_scb[OS_SEM_MAX]; // Pointers to Semaphore Control Blocks

os_mcb all_mcb[OS_MBOX_MAX]; // Pointers to Message Queue Control Blocks

os_tcb *NULL_TASK; // Straight pointer to null-process' PCB // Stacks for NULL task UBYTE DNULL[OS_TASK_DSTK_SIZE], HWNULL[OS_TASK_HSTK_SIZE];

// Low level function which makes actual context switch void _os_dispatch( void ) { UBYTE *dstk_highrdy, *hstk_highrdy; os_tcb *curr_tcb; OS_ENTER_CRITICAL;

os_ctbl.os_dispcntr++; //dispatch counter

curr_tcb = os_ctbl.tcb_current; // Get address to current TCB dstk_highrdy = os_ctbl.tcb_runq->datastk; // Get highest priority ready tasks data stack hstk_highrdy = os_ctbl.tcb_runq->hwstk; // Get highest priority ready task's hw stack os_ctbl.tcb_current = os_ctbl.tcb_runq; // Make first in run-queue current os_ctbl.tcb_current->status = OS_TASK_RUNNING;

/* Context switch.

Page 27: نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr يﺎﻬﺗﺎﺒﺛ ﮥﺸﻘﻧ :1 ﻞﮑﺷ AVR يﺎﻬﺗﺎﺒﺛ و هداد ﻪﻈﻓﺎﺣ

27

; *dstk_highrdy -> Y+4 ; *hstk_highrdy -> Y+2

; *curr_tcb -> Y+0

1. Save HW SP and data SP to current task's PCB 2. Load SP from highest priority task's TCB 3. Restore context and return to new task

*/ #asm ; Save all registers except SW stack pointer

PUSH R0 PUSH R1 PUSH R2 PUSH R3 PUSH R4 PUSH R5 PUSH R6 PUSH R7 PUSH R8 PUSH R9 PUSH R10 PUSH R11 PUSH R12 PUSH R13 PUSH R14 PUSH R15 PUSH R16 PUSH R17 PUSH R18 PUSH R19 PUSH R20 PUSH R21 PUSH R22 PUSH R23 PUSH R24 PUSH R25 PUSH R26 PUSH R27 PUSH R30 PUSH R31 IN R0,SREG PUSH R0

; Save current HW stack pointer, low first LDD R26,Y+0 ; hstk_current -> X

LDD R27,Y+1

IN R30,SPL ; *hstk_current = SP; ST X+,R30 IN R30,SPH

Page 28: نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr يﺎﻬﺗﺎﺒﺛ ﮥﺸﻘﻧ :1 ﻞﮑﺷ AVR يﺎﻬﺗﺎﺒﺛ و هداد ﻪﻈﻓﺎﺣ

28

ST X+,R30

; Save current SW stack pointer, low first MOV R30,R28 ; LOW(Y) -> R30 ADIW R30,6 ; Restore Y value (3 pointers * 2 bytes each) ST X+,R30 ; *dstk_current = Y; ST X,R29

; Load new HW stack pointer, low first LDD R30,Y+2

OUT SPL,R30 LDD R30,Y+3 OUT SPH,R30

; Load new SW stack pointer, low first LDD R30,Y+4 LDD R31,Y+5 MOV R28,R30 MOV R29,R31

; Pop all registers except SW stack pointer

POP R0 OUT SREG,R0 POP R31 POP R30 POP R27 POP R26 POP R25 POP R24 POP R23 POP R22 POP R21 POP R20 POP R19 POP R18 POP R17 POP R16 POP R15 POP R14 POP R13 POP R12 POP R11 POP R10 POP R9 POP R8 POP R7 POP R6 POP R5 POP R4 POP R3 POP R2 POP R1

Page 29: نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr يﺎﻬﺗﺎﺒﺛ ﮥﺸﻘﻧ :1 ﻞﮑﺷ AVR يﺎﻬﺗﺎﺒﺛ و هداد ﻪﻈﻓﺎﺣ

29

POP R0

RETI #endasm }

void _os_schedule( void ) { os_tcb *tptr, *highest_tcb; UBYTE highest;

//don't do anything if scheduler is off

if (!(os_ctbl.os_schedrun)) return;

OS_ENTER_CRITICAL; if (OS_CHCK) //Uses TIMER1!!!! { TCCR1B=0; os_ctbl.tcb_current->ttime++;//=(unsigned long)TCNT1 ; //Increment current task time } highest = 255;

// NULL-task's priority NULL_TASK->status = OS_TASK_RUNNABLE; // NULL-task is always runnable

if( os_ctbl.tcb_current->status & OS_TASK_RUNNING ) // If current

task is running here os_ctbl.tcb_current->status = OS_TASK_RUNNABLE; // it is still runnable

tptr = (os_tcb *)os_ctbl.tcb_used_list; // Go through all

runnable tasks do { // and get the one having highest priority if( OS_TASK_RUNNABLE==tptr->status ) { // Is task runnable? runnable=0

if( tptr->prio <= highest ) { // Yes, is it's priority higher than highest allready? highest = tptr->prio; // Yes, save it highest_tcb = (os_tcb *)tptr; } } tptr = (os_tcb *)tptr->next_tcb; } while( tptr ); // Was it last one?

os_ctbl.tcb_runq = (os_tcb *)highest_tcb; // Put highest priority task in run-queue

Page 30: نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr يﺎﻬﺗﺎﺒﺛ ﮥﺸﻘﻧ :1 ﻞﮑﺷ AVR يﺎﻬﺗﺎﺒﺛ و هداد ﻪﻈﻓﺎﺣ

30

if( os_ctbl.tcb_current != os_ctbl.tcb_runq ) // If next in

run-queue is different task _os_dispatch(); // we have to dispatch if (OS_CHCK) //USES timer 1!!! {

TCNT1=0; TCCR1B=5; }

OS_EXIT_CRITICAL; }

//#pragma savereg-

// Timer 0 output compare interrupt service routine // Timer tick ISR interrupt [TIM0_COMP] void timer0_comp_isr(void) { volatile os_tcb *tptr; volatile UBYTE sched_n_disp;

OS_ENTER_CRITICAL; if( os_ctbl.os_running ) { // Is multitasking on? sched_n_disp = 0; // Flag of need for scheduling and dispatching

tptr = (os_tcb *)os_ctbl.tcb_used_list; // Point to first TCB do { // Go through all PCBs if(tptr->status==OS_TASK_DELAYD){ //Is the task sleeping? if(tptr->delay>0) //Still some time left? tptr->delay--; // Yes, decrement else { //no, make it runnable tptr->status = OS_TASK_RUNNABLE; //make the task runnable again sched_n_disp = 1; //re-schedule

} } tptr = (os_tcb *)tptr->next_tcb;// Get next TCB } while( tptr ); // Last in PCB chain?

os_ctbl.os_systime++; // Increment system uptime

Page 31: نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr يﺎﻬﺗﺎﺒﺛ ﮥﺸﻘﻧ :1 ﻞﮑﺷ AVR يﺎﻬﺗﺎﺒﺛ و هداد ﻪﻈﻓﺎﺣ

31

if( sched_n_disp ) { // If some task became runnable _os_schedule(); // we have to re-schedule } }

OS_EXIT_CRITICAL; }

//#pragma savereg+

void _init_free_list( void ) { UBYTE i; os_tcb *tcb_this, *tcb_next; os_scb *scb_this, *scb_next; os_mcb *mcb_this, *mcb_next;

OS_ENTER_CRITICAL; // Process PCBs for(i=0;i<OS_TASK_MAX-1;i++) { // Link all

PCBs in free list tcb_this = (os_tcb *)&all_tcb[i]; tcb_next = (os_tcb *)&all_tcb[i+1]; tcb_this->next_tcb = (os_tcb *)tcb_next; } all_tcb[OS_TASK_MAX].next_tcb = (os_tcb *)0; // Last PCB in chain

// Process SCBs for(i=0;i<OS_SEM_MAX-1;i++) { // Link all SCBs in

free list scb_this = (os_scb *)&all_scb[i]; scb_next = (os_scb *)&all_scb[i+1]; scb_this->next_scb = (os_scb *)scb_next; } all_scb[OS_SEM_MAX].next_scb = (os_scb *)0; // Last SCB

in chain

// Process MCBs for(i=0;i<OS_MBOX_MAX-1;i++) { // Link all MCBs in free list

mcb_this = (os_mcb *)&all_mcb[i]; mcb_next = (os_mcb *)&all_mcb[i+1]; mcb_this->next_mcb = (os_mcb *)mcb_next; } all_mcb[OS_MBOX_MAX].next_mcb = (os_mcb *)0; // Last SCB in chain

OS_EXIT_CRITICAL;

}

Page 32: نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr يﺎﻬﺗﺎﺒﺛ ﮥﺸﻘﻧ :1 ﻞﮑﺷ AVR يﺎﻬﺗﺎﺒﺛ و هداد ﻪﻈﻓﺎﺣ

32

void os_start( void ) { if( os_ctbl.tcb_used_list ) { // Is there tasks created? os_ctbl.os_running = 1; // Start multi-tasking } }

void os_sleep( UWORD ticks ) { OS_ENTER_CRITICAL;

os_ctbl.tcb_current->delay = ticks; // Put task to sleep for 'ticks' time. os_ctbl.tcb_current->status = OS_TASK_DELAYD; _os_schedule(); OS_EXIT_CRITICAL; }

ULONG os_uptime( void ) { return( os_ctbl.os_systime ); }

void NULLTASK( void ) { while( 1 );

}

void main(void) {

UBYTE *nt_dstk, *nt_hstk; // NULL-task's stacks

///************************************ //Application dependent setup //most of this should be moved to task definitions //(EXECPT for timer 0 setup

// Timer/Counter 0 initialization // Clock source: System Clock // Clock value: 16 MHz // Mode: Output Compare //OC0 output: Disconnected // Timer/Counter 0 is cleared on compare match

Page 33: نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr يﺎﻬﺗﺎﺒﺛ ﮥﺸﻘﻧ :1 ﻞﮑﺷ AVR يﺎﻬﺗﺎﺒﺛ و هداد ﻪﻈﻓﺎﺣ

33

//TCCR0=0b00001101; devide source clk by 1024 and timr to CTC mode //ASSR=0x00; TCNT0=0x00; //The following sets the task-switch rate!!! //internal clock (16Mhz) divided by 1024 so each tick is 64 microseconds

OCR0=15.6 * OS_TICK_TIME; //64 usec x 15.6 = 1mSec //OCR0=78 ; //5 ms //OCR0=39 ; //2.5 ms //OCR0=20 ; //1.25 ms //OCR0=0 ; //960 usec //BUT don't start clock until OS is started // Timer(s)/Counter(s) Interrupt(s) initialization TIMSK=0x02; //timer 0 compare match

// Initialize PCB & SCB freelist _init_free_list();

// Set up OS central table

os_ctbl.os_running = 0; // Not running os_ctbl.os_schedrun = 1; //enable scheduler

os_ctbl.tcb_used_list = (os_tcb *)0; // No created processes yet os_ctbl.tcb_free_list = (os_tcb *)&all_tcb[0]; // First TCB in free list

os_ctbl.scb_used_list = (os_scb *)0; // No created semaphores yet os_ctbl.scb_free_list = (os_scb *)&all_scb[0]; // First SCB in free list

os_ctbl.mcb_used_list = (os_mcb *)0; // No created mailboxes yet os_ctbl.mcb_free_list = (os_mcb *)&all_mcb[0]; // First MCB in free list

// Allways create NULL task which is allways runnable // and which has the lowest priority NULL_TASK = os_task_create( NULLTASK, HWNULL, DNULL, 255 );

// Use NULL-task's stacks prior to first context switch nt_dstk = (UBYTE *)NULL_TASK->datastk; nt_hstk = (UBYTE *)NULL_TASK->hwstk; #asm ; Load new HW stack pointer, low first LDD R30,Y+0 OUT SPL,R30 LDD R30,Y+1

OUT SPH,R30

; Load new data stack pointer, low first? LDD R30,Y+2 LDD R31,Y+3 MOV R28,R30 MOV R29,R31 #endasm

Page 34: نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr يﺎﻬﺗﺎﺒﺛ ﮥﺸﻘﻧ :1 ﻞﮑﺷ AVR يﺎﻬﺗﺎﺒﺛ و هداد ﻪﻈﻓﺎﺣ

34

os_ctbl.tcb_current = (os_tcb *)NULL_TASK;

///************************************************** // Create at least one user task //Modify for task and stack names if nescessary //os_task_create( task1, hw_stack1, data_stack1, 50 ); os_task_create(OS_FIRST_TASK_NAME, OS_FIRST_TASK_HSTACK_NAME ,OS_FIRST_TASK_DSTACK_NAME, OS_FIRST_TASK_PRIO); ///**************************************************

// Start multitasking os_start(); TCNT0=0; TCCR0=0b00001101; //devide source clk by 1024 and timr to CTC mode _os_schedule();

// This causes program to jump actual NULL process #asm POP R0 OUT SREG,R0 POP R31

POP R30 POP R27 POP R26 POP R25 POP R24 POP R23 POP R22 POP R21 POP R20 POP R19 POP R18 POP R17 POP R16 POP R15 POP R14 POP R13 POP R12 POP R11 POP R10 POP R9 POP R8 POP R7 POP R6 POP R5 POP R4 POP R3 POP R2 POP R1 POP R0

Page 35: نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr يﺎﻬﺗﺎﺒﺛ ﮥﺸﻘﻧ :1 ﻞﮑﺷ AVR يﺎﻬﺗﺎﺒﺛ و هداد ﻪﻈﻓﺎﺣ

35

RETI #endasm while (1) { // We won't never, ever reach this point #asm("nop"); }; }

6-6-3 user_task.c os_tcb *os_task_create( void (*task)(void), UBYTE *hstack, UBYTE *dstack, UBYTE p ) { UBYTE *stk, *dstk, *hstk; UBYTE i; os_tcb *tcb_new;

OS_ENTER_CRITICAL; tcb_new = (os_tcb *)os_ctbl.tcb_free_list;// Get next free TCB if( tcb_new ) { // TCBs left? // Set up the hardware stack

hstk = (UBYTE *)hstack + (OS_TASK_HSTK_SIZE - 1);// Stack begins in the end of array stk = hstk; *stk-- = (UBYTE)(task); // Low part of task's address *stk-- = (UBYTE)(task >> 8); // High part of task's address for(i=0;i<30;i++) // Clear all other registers *stk-- = 0; *stk-- = 0x80; // SREG with interrupts enabled

// Set up data stack dstk = (UBYTE *)dstack + (OS_TASK_DSTK_SIZE - 1);// Stack

begins in the end of array

os_ctbl.tcb_free_list = (os_tcb *)tcb_new->next_tcb;// Release TCB from freelist tcb_new->next_tcb = (os_tcb *)os_ctbl.tcb_used_list;// Link new TCB into TCB used list os_ctbl.tcb_used_list = (os_tcb *)tcb_new;

tcb_new->datastk = (UBYTE *)dstk; // Load data stack pointer to TCB tcb_new->hwstk = (UBYTE *)stk; // Load hw stack pointer to TCB tcb_new->hstktop = (UBYTE *)hstk; //for keep track stk tcb_new->dstktop = (UBYTE *)dstk; //for keep track stk tcb_new->status = OS_TASK_RUNNABLE; // Make task runnable tcb_new->prio = (UBYTE)p; // Set task's priority

Page 36: نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr يﺎﻬﺗﺎﺒﺛ ﮥﺸﻘﻧ :1 ﻞﮑﺷ AVR يﺎﻬﺗﺎﺒﺛ و هداد ﻪﻈﻓﺎﺣ

36

tcb_new->delay = (UWORD)0; // No initial delay tcb_new->tcb_sem_q = (os_tcb *)0; // Initialize semaphore

queue }

OS_EXIT_CRITICAL; return( tcb_new ); }

///******************************************************* //utility which allows one task to sleep another //no call to the scheduler is needed here since the //task is not the current task. // USE os_sleep if you are sleeping the current task!!

void os_sleep_task(os_tcb *task, UWORD ticks) {

OS_ENTER_CRITICAL; task->delay = ticks; task->status = OS_TASK_DELAYD; OS_EXIT_CRITICAL; }

///****************************************************** //utility which allows one task to UN-sleep another //if the task is dalayed. Task will restart on next tick.

void os_unsleep_task(os_tcb *task) { OS_ENTER_CRITICAL; if (task->status == OS_TASK_DELAYD) task->delay = 0; OS_EXIT_CRITICAL; }

///******************************************************* //utility to allow tasks to suspend each other //need to schedule if the current task suspends itself void os_suspend_task(os_tcb *task) { OS_ENTER_CRITICAL; if (task->status<2) //running or runnable task->status = OS_TASK_SUSPENDED; else if (task->status==OS_TASK_WAITING) task->status = OS_TASK_SUSPENDED_WAIT; else if (task->status==OS_TASK_DELAYD) task->status = OS_TASK_SUSPENDED_DELA;

if (os_ctbl.tcb_current==task) _os_schedule(); OS_EXIT_CRITICAL; }

Page 37: نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr يﺎﻬﺗﺎﺒﺛ ﮥﺸﻘﻧ :1 ﻞﮑﺷ AVR يﺎﻬﺗﺎﺒﺛ و هداد ﻪﻈﻓﺎﺣ

37

///******************************************************* //utility to allow tasks to resume another task //need to reschedule IF the task has priority void os_resume_task(os_tcb *task) { char change ;

OS_ENTER_CRITICAL; change=0; if (task->status == OS_TASK_SUSPENDED){ change=1; task->status = OS_TASK_RUNNABLE;

} else if (task->status == OS_TASK_SUSPENDED_WAIT){

change=1; task->status = OS_TASK_WAITING;

} else if (task->status == OS_TASK_SUSPENDED_DELA){

change=1; task->status = OS_TASK_DELAYD;

} //reschedule if reactivated task has priority

if (change==1 && task->prio < os_ctbl.tcb_current->prio) _os_schedule(); OS_EXIT_CRITICAL;

} ///******************************************************* //Find the high point of a task //hardware stack use int os_task_hstk_chck(os_tcb *task) { char *hbottom ;

int free ; OS_ENTER_CRITICAL; hbottom = (char *)task->hstktop - OS_TASK_HSTK_SIZE + 1 ; while (*hbottom++ == 0) free++; return free; OS_EXIT_CRITICAL;

} ///******************************************************* //Find the high point of a task //hardware stack use int os_task_dstk_chck(os_tcb *task) { char *dbottom ; int free ;

OS_ENTER_CRITICAL; dbottom = (char *)task->dstktop - OS_TASK_DSTK_SIZE + 1 ; while (*dbottom++ == 0) free++; return free; OS_EXIT_CRITICAL; }

Page 38: نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr يﺎﻬﺗﺎﺒﺛ ﮥﺸﻘﻧ :1 ﻞﮑﺷ AVR يﺎﻬﺗﺎﺒﺛ و هداد ﻪﻈﻓﺎﺣ

38

///******************************************************* //get the task time long os_task_gettime(os_tcb *task) { OS_ENTER_CRITICAL;

return task->ttime ; OS_EXIT_CRITICAL; }

///******************************************************* //set the task time void os_task_settime(os_tcb *task, ULONG time) { OS_ENTER_CRITICAL; task->ttime = time ; OS_EXIT_CRITICAL; }

///******************************************************* //get the dispatch counter long os_getdispatch() { OS_ENTER_CRITICAL;

return os_ctbl.os_dispcntr ; OS_EXIT_CRITICAL; }

///******************************************************* //set the dispatch counter void os_setdispatch(ULONG count) { OS_ENTER_CRITICAL; os_ctbl.os_dispcntr = count ; OS_EXIT_CRITICAL; }

///******************************************************* //get a task's status UBYTE os_task_getstatus(os_tcb *task) { OS_ENTER_CRITICAL;

return task->status ; OS_EXIT_CRITICAL; }

///******************************************************* //lock scheduler void os_sched_lock(){ OS_ENTER_CRITICAL; os_ctbl.os_schedrun = 0 ; OS_EXIT_CRITICAL; }

Page 39: نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr يﺎﻬﺗﺎﺒﺛ ﮥﺸﻘﻧ :1 ﻞﮑﺷ AVR يﺎﻬﺗﺎﺒﺛ و هداد ﻪﻈﻓﺎﺣ

39

///******************************************************* //UNlock scheduler void os_sched_unlock(){ OS_ENTER_CRITICAL; os_ctbl.os_schedrun = 1 ; OS_EXIT_CRITICAL;}

6-6-4 Rtos_semaphore.c

os_scb *os_sem_create( UWORD init_val ) { os_scb *scb_new;

OS_ENTER_CRITICAL; scb_new = (os_scb *)os_ctbl.scb_free_list; // Get next

free SCB if( scb_new ) { // SCBs left? os_ctbl.scb_free_list = (os_scb *)scb_new->next_scb;//

Release SCB from freelist scb_new->next_scb = (os_scb *)os_ctbl.scb_used_list;// Link new SCB into SCB used list

os_ctbl.scb_used_list = (os_scb *)scb_new; scb_new->count = init_val; // Set semaphore's initial value scb_new->scb_sem_q = (os_tcb *)0; // No task pending on semaphore } OS_EXIT_CRITICAL; return( scb_new ); }

/* About wait(), signal() and HW locking:

Since we are in uniprocessor environment, indivisibility is achieved by simply disabling interrupts. After that there is no way for task to loose the processor. Otherwise somekind of hardware locking would be needed. In multi-processor

environments possibilities are 'test-and-set'-instruction or instruction to

interchange two memory locations. */ //================================================================

Page 40: نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr يﺎﻬﺗﺎﺒﺛ ﮥﺸﻘﻧ :1 ﻞﮑﺷ AVR يﺎﻬﺗﺎﺒﺛ و هداد ﻪﻈﻓﺎﺣ

40

void os_wait( os_scb *sem ) { os_tcb *ptcb;

OS_ENTER_CRITICAL; if( sem->count ) { // Semaphore value >0 ? sem->count--; // Yes, decrement the value } else { // No, we have to wait ptcb = (os_tcb *)sem->scb_sem_q; if( ptcb ) { // Any tasks in queue?

while( ptcb->tcb_sem_q ) {// Yes, find queue's end because ptcb = (os_tcb *)ptcb->tcb_sem_q;// this is a FIFO, not a stack. }

ptcb->tcb_sem_q = (os_tcb *)os_ctbl.tcb_current;// Link current process to wait queue } else { sem->scb_sem_q = (os_tcb *)os_ctbl.tcb_current; // No, this is the first one } os_ctbl.tcb_current->tcb_sem_q = (os_tcb *)0; // Terminate queue properly os_ctbl.tcb_current->status = OS_TASK_WAITING;// Now we're waiting _os_schedule(); // Re-schedule run-queue } OS_EXIT_CRITICAL; }

//============================================================ void os_signal( os_scb *sem ) {

os_tcb *ptcb;

OS_ENTER_CRITICAL; ptcb = (os_tcb *)sem->scb_sem_q; if( ptcb ) { // Is there pending wait()s?

sem->scb_sem_q = (os_tcb *)ptcb->tcb_sem_q; // Yes, dequeue the first one ptcb->status = OS_TASK_RUNNABLE; // Make task runnable _os_schedule(); // Re-schedule run-queue } else { // No, just increment the semaphore

sem->count++; } OS_EXIT_CRITICAL;

Page 41: نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr يﺎﻬﺗﺎﺒﺛ ﮥﺸﻘﻧ :1 ﻞﮑﺷ AVR يﺎﻬﺗﺎﺒﺛ و هداد ﻪﻈﻓﺎﺣ

41

} //=============================================================== //semaphore accept UWORD os_sem_accept( os_scb *sem ) { UWORD temp; OS_ENTER_CRITICAL; temp = sem->count; if (temp>0) sem->count--; return temp; OS_EXIT_CRITICAL; }

6-6-5 rtos_mbox.c

os_mcb *os_mbox_create( void ) { os_mcb *mcb_new;

mcb_new = 0; OS_ENTER_CRITICAL; mcb_new = (os_mcb *)os_ctbl.mcb_free_list;// Save pointer to next

free mcb if( mcb_new ) { // mcbs left? mcb_new->mmsg = NULL; //initilize mailbox os_ctbl.mcb_free_list = (os_mcb *)mcb_new->next_mcb; // Yes, release mcb from freelist mcb_new->next_mcb = (os_mcb *)os_ctbl.mcb_used_list; // Link new mcb into mcb used list os_ctbl.mcb_used_list = (os_mcb *)mcb_new;

mcb_new->mrecv = (os_scb *)os_sem_create( 0 ); // Semaphore for receiving messages

mcb_new->msend = (os_scb *)os_sem_create( 1 ); // Semaphore for sending messages mcb_new->mmsg = (void *)0; // Clear message pointer }

OS_EXIT_CRITICAL; return( mcb_new ); }

//=================================================================== // Send a message to mailbox void os_mbox_send( os_mcb *mcb, void *msg ) { os_wait( (os_scb *)mcb->msend ); // Is there room in the mailbox mcb->mmsg = msg; // Put message in the mailbox

os_signal( (os_scb *)mcb->mrecv ); // Signal the queue's receive semaphore }

Page 42: نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr يﺎﻬﺗﺎﺒﺛ ﮥﺸﻘﻧ :1 ﻞﮑﺷ AVR يﺎﻬﺗﺎﺒﺛ و هداد ﻪﻈﻓﺎﺣ

42

//=================================================================== // Receive a message from mailbox void *os_mbox_recv( os_mcb *mcb ) { void *msg;

os_wait( (os_scb *)mcb->mrecv );// Wait for a message msg = mcb->mmsg; // Get the message from mailbox mcb->mmsg = NULL; //and wipe the old message os_signal( (os_scb *)mcb->msend ); // Signal the queue's sending

semaphore

return( msg ); }

//=================================================================== //receive a message without waiting //You MUST check the retrun value to see if it is NULL void *os_mbox_accept( os_mcb *mcb ) { void *msg; OS_ENTER_CRITICAL; msg = mcb->mmsg; // Get the message from mailbox

if (msg!=NULL) { //if there is a message mcb->mmsg = NULL ; //clear the mailbox

os_signal( (os_scb *)mcb->msend ); // Signal the sending semaphore } return msg; OS_EXIT_CRITICAL; }

6-6-6 user_task.c

//definition of task are in this file #include <mega32.h> #include <stdio.h>

#include "rtos.h" #include "user_tasks.h" #include "rtos_core.c" #include "rtos_task.c"

#include "rtos_semaphore.c" //for impelement semaphores #include "rtos_mbox.c" //for impelement mailboxes

#include "rtos_uart.c" //for impelement UART //global variables for all tasks

OS_GLOBAL_VAR //force the data to be in RAM using pragma

Page 43: نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr يﺎﻬﺗﺎﺒﺛ ﮥﺸﻘﻧ :1 ﻞﮑﺷ AVR يﺎﻬﺗﺎﺒﺛ و هداد ﻪﻈﻓﺎﺣ

43

os_mailbox *task23_pipe ; //string from task2 to task3 os_mailbox *task11_pipe ; //string from task1 to itself //shared memory task 1, 3, 4 UWORD sleep_time=10 ; //memory lock semaphore os_semaphore *sem_memory; //task control block pointer os_tcb *t1, *t2, *t3, *t4 ; //allow register vars again OS_GLOBAL_END bit flag=1; bit key_flag=1; //******************************************************** void task1( void ) { char t1str[32];

char t1astr[20]; // char*msg ;

char msg[5]="Ali" ; //get the current task control block t1 = os_ctbl.tcb_current;

//start 3 tasks and retrun control block pointers t2=os_task_create( task2, hw_stack2, data_stack2, 100 ); t3=os_task_create( task3, hw_stack3, data_stack3, 150 ); t4=os_task_create( task4, hw_stack4, data_stack4, 200 );

//allocate UART structures, turn on UART

//parameter is baud rate given as an integer //This routine uses the clock value set in the

//Project...Config dialog!! os_init_uart(9600);

//init portA to output DDRA = 0xff ; PORTA = 0xff;

//init portD to input DDRD.6 =0; PORTD.6 =1;

while(1) {

PORTA.0 ^= 1; os_sleep(1);

if (PIND.6==0 && key_flag==1){ sprintf(t1astr,"Uptime: %d\r\n",os_uptime()) ; os_puts(t1astr);

flag=!flag; key_flag=0; }

if (PIND.6==1 && key_flag==0)

Page 44: نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr يﺎﻬﺗﺎﺒﺛ ﮥﺸﻘﻧ :1 ﻞﮑﺷ AVR يﺎﻬﺗﺎﺒﺛ و هداد ﻪﻈﻓﺎﺣ

44

key_flag=1; msg[0]=getchar();

if(msg[0]=='2') { PORTA.2=0; os_suspend_task(t2); } if(msg[0]=='3') { PORTA.4=0;

os_suspend_task(t3); } if(msg[0]=='4') { PORTA.6=0; os_suspend_task(t4); }

if(msg[0]=='6') os_resume_task(t2); if(msg[0]=='7') os_resume_task(t3);

if(msg[0]=='8') os_resume_task(t4); if(msg[0]=='9')

{ sprintf(t1astr,"\r\nUptime:%d\r\n",os_uptime()%65000) ; os_puts(t1astr);

sprintf(t1astr,"Task1

time:%d\r\n",os_task_gettime(t1)%65000) ; os_puts(t1astr);

sprintf(t1astr,"Task2

time:%d\r\n",os_task_gettime(t2)%65000) ; os_puts(t1astr);

sprintf(t1astr,"Task3

time:%d\r\n",os_task_gettime(t3)%65000) ; os_puts(t1astr);

sprintf(t1astr,"Task4

time:%d\r\n",os_task_gettime(t4)%65000) ; os_puts(t1astr);

Page 45: نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr يﺎﻬﺗﺎﺒﺛ ﮥﺸﻘﻧ :1 ﻞﮑﺷ AVR يﺎﻬﺗﺎﺒﺛ و هداد ﻪﻈﻓﺎﺣ

45

} msg[0]='p'; } }

//******************************************************** void task2( void ) { while(1) {

//toggle the led PORTA.2 ^= 1; os_sleep( sleep_time ); } }

//******************************************************** void task3( void ) { while(1) { //toggle the led PORTA.4 ^= 1; os_sleep( 2*sleep_time ); } }

//******************************************************** void task4( void ) { while(1) {

//toggle the led PORTA.6 ^= 1; os_sleep( 3*sleep_time );

} }

//********************************************************

Page 46: نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr يﺎﻬﺗﺎﺒﺛ ﮥﺸﻘﻧ :1 ﻞﮑﺷ AVR يﺎﻬﺗﺎﺒﺛ و هداد ﻪﻈﻓﺎﺣ

46

6-6-7 user_task.h //Portotype of user task are in this file //Code of user tasks are in user_task.c file //Need this to identify the first task to os_core.c #define OS_FIRST_TASK_NAME task1 #define OS_FIRST_TASK_DSTACK_NAME data_stack1 #define OS_FIRST_TASK_HSTACK_NAME hw_stack1 #define OS_FIRST_TASK_PRIO 240 //priority

//user defined names for tasks //The task names will be used during calls //to os_task_create //NOTE that the creation of task1 is done in os_core.c void task1(void); void task2(void); void task3(void); void task4(void);

//stack definitions for eaxh task //The stack names will be used during calls //to os_task_create UBYTE data_stack1[OS_TASK_DSTK_SIZE], hw_stack1[OS_TASK_HSTK_SIZE];// Stacks for task1 UBYTE data_stack2[OS_TASK_DSTK_SIZE], hw_stack2[OS_TASK_HSTK_SIZE];// Stacks for task2 UBYTE data_stack3[OS_TASK_DSTK_SIZE], hw_stack3[OS_TASK_HSTK_SIZE];// Stacks for task3 UBYTE data_stack4[OS_TASK_DSTK_SIZE], hw_stack4[OS_TASK_HSTK_SIZE];// Stacks for task4

6-6-8 rtos_uart.c

// UART communication code #pragma regalloc- //need this to ensure no reg variables char uart_recv_index ; char uart_send_index ; char* uart_send_ptr ; char* uart_recv_ptr ;

os_semaphore *sem_uart_xmit; // Semaphore for writing UART os_semaphore *sem_uart_recv; // Semaphore for reading UART

#pragma regalloc+ //******************************************************** //macros to package up semaphores and hide interrupts #define os_puts(str) \\ do{ \\ os_wait(sem_uart_xmit); \\ uart_send_index = 0; \\

uart_send_ptr = &str[0]; \\

Page 47: نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr يﺎﻬﺗﺎﺒﺛ ﮥﺸﻘﻧ :1 ﻞﮑﺷ AVR يﺎﻬﺗﺎﺒﺛ و هداد ﻪﻈﻓﺎﺣ

47

if (str[0]>0) \\ { \\

putchar(str[0]); \\ UCSRB.5=1; \\

os_wait(sem_uart_xmit); \\ } ; \\

os_signal(sem_uart_xmit); \\ }while(0) #define os_gets(str) \\

do{ \\ os_wait(sem_uart_recv);\\ uart_recv_index=0; UCSRB.7=1;\\ uart_recv_ptr = str; \\ os_wait(sem_uart_recv);\\ os_signal(sem_uart_recv);\\

}while(0) //******************************************************** //define the structures and turn on the UART void os_init_uart(long baud) { sem_uart_xmit = (os_semaphore *)os_sem_create( 1 ); sem_uart_recv = (os_semaphore *)os_sem_create( 1 );

UCSRB=0x18; // activate UART //uses the clock freq set in the config dialog box

UBRRL=0x19;// _MCU_CLOCK_FREQUENCY_ /(baud*16L) - 1L; }

//receive ISR ///********************************************************* //UART character-ready ISR interrupt [USART_RXC] void uart_rec(void) { char r_char; r_char=UDR; //get a char

//build the input string if ((r_char!='\r') && (r_char!='\n')) uart_recv_ptr[uart_recv_index++] = r_char; else { // putchar('\n'); //use putchar to aoid overwrite uart_recv_ptr[uart_recv_index] = 0x00 ; //zero terminate UCSRB.7=0; //stop ISR after <CR> os_signal(sem_uart_recv); }

} //******************************************************** //UART xmit-empty ISR interrupt [USART_DRE] void uart_send(void) { char t_char;

Page 48: نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr يﺎﻬﺗﺎﺒﺛ ﮥﺸﻘﻧ :1 ﻞﮑﺷ AVR يﺎﻬﺗﺎﺒﺛ و هداد ﻪﻈﻓﺎﺣ

48

t_char = uart_send_ptr[++uart_send_index]; if (t_char == 0) { UCSRB.5=0; //kill isr os_signal(sem_uart_xmit); }

else { putchar(t_char); //send the char

} } //********************************************************

Page 49: نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr يﺎﻬﺗﺎﺒﺛ ﮥﺸﻘﻧ :1 ﻞﮑﺷ AVR يﺎﻬﺗﺎﺒﺛ و هداد ﻪﻈﻓﺎﺣ

49

عامل روش استفاده از سیستم 7، یک پروژه 2عامل بالدرنگ ارائه شده کافی است مطابق روش ذکر شده در ضمیمۀ براي استفاده از سیستم

عامل ربر بخواهد سیستماگر کا. ایجاد گردد و تنظیمات ذکر شده انجام پذیردCodevisionAVRافزار در نرمرا مطابق منظور user_tasks.c وuser_tasks.h استفاده کند کافی است، دو فایل MEGA32فوق را براي

user_tasks.cشود و در فایل ها انجام میtask تعریف کلی user_tasks.hدر فایل . خودش بازنویسی کند user_tasks.h در فایل taskزة استک مورد نیاز براي هر همچنین اندا. شود ها نوشته میtaskکد مربوط به آن . باید مشخص گردد استفاده کنید فقط وقفۀ مربوط به تایمر و AVRعامل را براي تراشۀ دیگري از خانوادة اگر بخواهید سیستم

بتوان در در صورتی که تایمر صفر آن تراشه را . تنظیمات آن باید مطابق با تراشۀ انتخاب شده پیکربندي شودباشد و فقط در فایلها به ریزي کرد، نیازي به تغییر وقفه نیز نمی برنامهCTC و compre mach IRQحالت . کردinclude را megaxx.h باید فایل mega32.h کردن فایل includeجاي

ز فایل استفاده کنید، قسمتهایی اAVRعامل را براي میکرو کنترلرهاي دیگري بجز اگر بخواهید سیستمrtos_core.cریزي وقفۀ تایمر نیز را که به زبان اسمبلی نوشته شده است باید عوض شوند و همچنین برنامه

.کند البته سرویس روتین وقفه تغییري نمی. مطابق با آن میکروکنترلر انجام شود

Page 50: نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr يﺎﻬﺗﺎﺒﺛ ﮥﺸﻘﻧ :1 ﻞﮑﺷ AVR يﺎﻬﺗﺎﺒﺛ و هداد ﻪﻈﻓﺎﺣ

50

)Atmega32مشخصات (1ضمیمۀ 8 :امکانات کلی این تراشه به صورت زیر است

افظۀ فلش براي ذخیره سازي برنامه مگابایت ح32 EEPROMیک کیلو بایت حافظۀ

SRAMدو کیلو بایت حافظۀ ها امکانات امنیتی براي حفظ برنامه

Jtagپشتیبانی از استاندارد دو تایمر هشت بیتی

یک تایمر شانزده بیتی PWMچهار کانال

بیتی10هشت مبدل آنالوگ به دیجیتال ، TWI ،USART ،SPIامکانات سریال

Watch dogشمارندة مقایسه کنندة آنالوگ

Power on resetامکان کریستال داخلی

براي راه اندازي این تراشه نیازي به هیچ قطعۀ جانبی . هاي این تراشه نمایش داده شده است پایه3 در شکل .کند هاي تغذیه کفایت می نیست و اتصال پایه

Page 51: نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr يﺎﻬﺗﺎﺒﺛ ﮥﺸﻘﻧ :1 ﻞﮑﺷ AVR يﺎﻬﺗﺎﺒﺛ و هداد ﻪﻈﻓﺎﺣ

51

Atmega32هاي تراشۀ پایه: 3شکل

Page 52: نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr يﺎﻬﺗﺎﺒﺛ ﮥﺸﻘﻧ :1 ﻞﮑﺷ AVR يﺎﻬﺗﺎﺒﺛ و هداد ﻪﻈﻓﺎﺣ

52

)نحوة کامپایل و اجرا (2ضمیمۀ 9براي . یک پروژه ایجاد کردCodeVisionAVRعامل باید ابتدا توسط نرم افزار براي کامپایل کردن سیستم

را انتخاب Project را انتخاب کرد سپس در پنجرة ظاهر شده گزینۀ Newاینکار باید از منوي فایل گزینۀ .)4شکل (کنید

AVRیکروکنتررهاي نقشۀ حافظۀ م: 4شکل

.)5شکل ( انتخاب شودNoشود که باید گزینۀ بعد از انتخاب این گزینۀ پنجرة زیر ظاهر می

AVRنقشۀ حافظۀ میکروکنتررهاي : 5شکل

در مرحلۀ بعدي نام پروژه را تایپ کنید، دقت شود که پروژه در فولدري ذخیره شود که سورس فایلهاي )6شکل (سیستم عامل قرار دارند

AVRنقشۀ حافظۀ میکروکنتررهاي : 6شکل

Page 53: نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr يﺎﻬﺗﺎﺒﺛ ﮥﺸﻘﻧ :1 ﻞﮑﺷ AVR يﺎﻬﺗﺎﺒﺛ و هداد ﻪﻈﻓﺎﺣ

53

user_tasks.c ، فایل Add با زدن دکمۀ Filesدر قسمت . شود بعد از ذخیره شدن پروژه پنجرة زیر ظاهر می .)7شکل (دقت شود که بقیۀ فایلها نباید اضافه شوند. را انتخاب کنید

AVRنقشۀ حافظۀ میکروکنتررهاي : 7شکل

هایی که گزینه. تنظیمات شکل زیر را وارد کنید را انتخاب کنید و سپس C Compilerت در پنجرة قبلی قسم Data انتخاب شود و در قسمت Clock ،16. انتخاب شودATmega32نام چیپ، : باید تغییر کنند عبارتند از

Stack size 8شکل ( وارد کنید300 عدد(.

Page 54: نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr يﺎﻬﺗﺎﺒﺛ ﮥﺸﻘﻧ :1 ﻞﮑﺷ AVR يﺎﻬﺗﺎﺒﺛ و هداد ﻪﻈﻓﺎﺣ

54

AVRنقشۀ حافظۀ میکروکنتررهاي : 8شکل

را make گزینۀ Projectنجام تنظیمات فوق باید برنامه را کامپایل کرد، براي این منظور باید از منوي بعد از اشود در این پنجره باید اي به صورت زیر ظاهر می در صورتی که اشکالی در برنامه نباشد پنجره. انتخاب کنید

No Error9شکل ( نوشته شده باشد(.

Page 55: نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr يﺎﻬﺗﺎﺒﺛ ﮥﺸﻘﻧ :1 ﻞﮑﺷ AVR يﺎﻬﺗﺎﺒﺛ و هداد ﻪﻈﻓﺎﺣ

55

AVRهاي نقشۀ حافظۀ میکروکنترر: 9شکل

ظاهر پنجرة را انتخاب کنید و سپس درProgrammer گزینۀ settingبراي پراگرام کردن باید ابتدا در منوي .شده، نوع پراگرامر را انتخاب کنید

.)10شکل ( را انتخاب کنید تا پنجرة زیر ظاهر شودChip programmer گزینۀ toolsسپس از منوي

Page 56: نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr يﺎﻬﺗﺎﺒﺛ ﮥﺸﻘﻧ :1 ﻞﮑﺷ AVR يﺎﻬﺗﺎﺒﺛ و هداد ﻪﻈﻓﺎﺣ

56

AVRرهاي نقشۀ حافظۀ میکروکنتر: 10شکل

چیپ را انتخاب کنید تا حافظۀ میکرو را پاك کند، بعد Erase گزینۀ Programدر پنجرة ظاهر شده از منوي . را انتخاب کنید تا میکرو پراگرام شودFlashاز اینکار از همان منو گزینۀ

نوشته Cامه به زبان در طرف کامپیوتر یک برن. میکروکنترلر با استفاد از لینک سریال به کامپیوتر متصل است شده است سورس این فایل در ادامه آورده شده است

rtos.cسورس فایل 9-1ام دهد که عبارتند از معلق ج کار متفاوت ان3این برنامه قادر است . شودمیاین فایل روي کامپیوتر اجرا

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

. شود می

Page 57: نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr يﺎﻬﺗﺎﺒﺛ ﮥﺸﻘﻧ :1 ﻞﮑﺷ AVR يﺎﻬﺗﺎﺒﺛ و هداد ﻪﻈﻓﺎﺣ

57

#include <dos.h> #include <stdio.h> #include <stdlib.h> #include <conio.h> #define PORT1 0x3F8 /* Port Address Goes Here */ #define INTVECT 0x0C /* Com Port's IRQ here (Must also change PIC setting) */ /* Defines Serial Ports Base Address */ /* COM1 0x3F8 */

/* COM2 0x2F8 */ /* COM3 0x3E8 */ /* COM4 0x2E8 */

int bufferin = 0; int bufferout = 0; char ch; char buffer[1025]; void InitPort(void); void ClosePort(void); void ClosePort(void); void GetData(void); void interrupt PORT1INT(void); void interrupt (*oldport1isr)();

void main(void) { int c; int i; int ch; // printf("\n Press ESC to quit \n"); InitPort(); c=1; do { GetData(); if(c!=0) { clrscr(); window(1,10,80,25); cprintf("1.Suspend process\r\n"); cprintf("2.Resume process\r\n"); cprintf("3.Get process Information \r\n"); cprintf("Enter your choice=>"); } c=0; if (kbhit()) c = getch(); switch(c-'0'){ case 1 : cprintf("\r\n\r\nEnter Process Number(2 or 3 or 4)=>"); ch=getch();

ch=((ch-1)%4)+1; outportb(PORT1,'0'+ch); break;

Page 58: نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr يﺎﻬﺗﺎﺒﺛ ﮥﺸﻘﻧ :1 ﻞﮑﺷ AVR يﺎﻬﺗﺎﺒﺛ و هداد ﻪﻈﻓﺎﺣ

58

case 2 : cprintf("\r\n\r\nEnter Process Number(2 or 3 or 4)=>"); ch=getch(); ch=((ch-1)%4)+5; outportb(PORT1,'0'+ch); break;

case 3 : // clrscr();

// while(!kbhit()) // { outportb(PORT1,'9');

// for(i=0;i<=10000;++i) GetData(); // delay(700);

// getch(); // } break;

} // outportb(PORT1, c);} // if (kbhit()){c = getch();

// outportb(PORT1, c);} } while (c !=27);

ClosePort();

}

void GetData(void) { // cprintf("A "); if (bufferin != bufferout){ch = buffer[bufferout]; bufferout++; if (bufferout == 1024) {bufferout = 0;} cprintf("%c",ch); /* if(ch=='\n')

{ buffer[bufferin+2] = 0; bufferin = 0; cprintf("%s",buffer); bufferout = 0; ch=0;

} */

} }

Page 59: نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr يﺎﻬﺗﺎﺒﺛ ﮥﺸﻘﻧ :1 ﻞﮑﺷ AVR يﺎﻬﺗﺎﺒﺛ و هداد ﻪﻈﻓﺎﺣ

59

void ClosePort() { outportb(PORT1 + 1 , 0); /* Turn off interrupts - Port1 */ outportb(0x21,(inportb(0x21) | 0x10)); /* MASK IRQ using PIC */ /* COM1 (IRQ4) - 0x10 */ /* COM2 (IRQ3) - 0x08 */

/* COM3 (IRQ4) - 0x10 */ /* COM4 (IRQ3) - 0x08 */ setvect(INTVECT, oldport1isr); /* Restore old interrupt vector */ } void InitPort() { outportb(PORT1 + 1 , 0); /* Turn off interrupts - Port1 */ oldport1isr = getvect(INTVECT); /* Save old Interrupt Vector of later recovery */ setvect(INTVECT, PORT1INT); /* Set Interrupt Vector Entry */

/* COM1 - 0x0C */ /* COM2 - 0x0B */ /* COM3 - 0x0C */ /* COM4 - 0x0B */ /* PORT 1 - Communication Settings */ outportb(PORT1 + 3 , 0x80); /* SET DLAB ON */ outportb(PORT1 + 0 , 0x30); /* Set Baud rate - Divisor Latch Low Byte */ /* Default 0x03 = 38,400 BPS */

/* 0x01 = 115,200 BPS */ /* 0x02 = 57,600 BPS */ /* 0x06 = 19,200 BPS */ /* 0x0C = 9,600 BPS */ /* 0x18 = 4,800 BPS */ /* 0x30 = 2,400 BPS */

outportb(PORT1 + 1 , 0x00); /* Set Baud rate - Divisor Latch High Byte */ outportb(PORT1 + 3 , 0x03); /* 8 Bits, No Parity, 1 Stop Bit */ outportb(PORT1 + 2 , 0xC7); /* FIFO Control Register */

outportb(PORT1 + 4 , 0x0B ); /* Turn on DTR, RTS, and OUT2 */ outportb(0x21,(inportb(0x21) & 0xEF)); /* Set Programmable Interrupt Controller */ /* COM1 (IRQ4) - 0xEF */ /* COM2 (IRQ3) - 0xF7 */ /* COM3 (IRQ4) - 0xEF */ /* COM4 (IRQ3) - 0xF7 */ outportb(PORT1 + 1 , 0x01); /* Interrupt when data received */ } void interrupt PORT1INT() /* Interrupt Service Routine (ISR) for PORT1 */ { int c; do { c = inportb(PORT1 + 5); if (c & 1) {buffer[bufferin] = inportb(PORT1);

bufferin++; if (bufferin == 1024) {bufferin = 0;}} }while (c & 1); outportb(0x20,0x20); }

Page 60: نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr يﺎﻬﺗﺎﺒﺛ ﮥﺸﻘﻧ :1 ﻞﮑﺷ AVR يﺎﻬﺗﺎﺒﺛ و هداد ﻪﻈﻓﺎﺣ

60

افزار سختعامل روي سازي سیستم هپیاد 9-2 ISP استفاده شد، این تراشه با استفاده از کابلATMEGA32عامل از یک تراشۀ براي پیاده سازي سیستم

براي LEDباشند که چهار میtaskهایی که براي این نمونه در نظر گرفته شد، چهار taskدر . شود پراگرام میشده است که نحوة روشن و خاموش شدن آنها در قسمت قبل آورده شده ها در نظر گرفته taskهریک از این

با استفاده از یک ATMEGA32عامل فراهم شود،تراشۀ براي اینکه یک محیط براي تست سیستم. است در شکل . به پورت سریال کامپیوتر متصل شده است تا بتواند با کامپیوتر داده تبادل نمایدMAX232تراشۀ

. مدار نمایش داده شده است، شماتیک این11

شماتیک سخت افزار مورد نیاز براي تست سیستم عامل: 11شکل

که روي برد بورد بسته شده است و براي آزمایش استفاده گردید 11، تصویري از مدار شکل 12در شکل .نمایش داده شده است

Page 61: نﺎﻬﻔﺻا هﺎﮕﺸﻧاد ﯽﺳﺪﻨﻬﻣ و ﯽﻨﻓ ةﺪﮑﺸﻧاد · avr يﺎﻬﺗﺎﺒﺛ ﮥﺸﻘﻧ :1 ﻞﮑﺷ AVR يﺎﻬﺗﺎﺒﺛ و هداد ﻪﻈﻓﺎﺣ

61

ATmega32عامل روي تراشۀ سازي سیستم تصویري از پیاده: 12شکل

مراجع 10

[1]Labrosse, Jean J., (1992), uC/OS The Real-Time Kernel [2]Tanenbaum, Andrew S.,Operating Systems: Design and Implementation