در قسمت دهم آموزش میکروکنترلر STM32F4 به سیستم عامل زمان واقعی (RTOS) و مبحث Thread پرداختیم. در این قسمت از آموزش میکروکنترلر STM32F4 به ادامه RTOS و مباحث سمافور و موتکس میپردازیم. با سیسوگ همراه باشید.
سمافور
یکی از ساده ترین مفاهیم سیستم عامل سمافور (Semaphore) است. ممکن است شما منابعی داشته باشید که چند قسمت از سیستم شما تمایل به استفاده از آنها در یک زمان را داشته باشند. برای مثال، ممکن است چند بخش از برنامه شما بخواهند دادهای را از رم بخوانند یا در آن بنویسند. یک راه این است که محدودیتی نداشته باشید و به همه اجازه بدهید که هر بار میخواهند از رم استفاده کنند. ولی اگر برنامه شما دارای تابعهای زیادی باشد و تعداد دسترسیها به رم بیش از اندازه شود به احتمال زیاد باس داده و آدرس که به رم متصل هستند نمیتوانند به همه این درخواستها برسند. در اینجا میتوانید برای حل مشکل و جلوگیری از قفل شدن سیستم یا کند شدن آن، محدودیتی روی تعداد درخواستهایی که رم میتواند بپذیرد قرار دهید. این مقدار در واقع توسط سمافور تعیین میشود.
با یک سمافور دسترسی به یک گروه از وسایل جانبی مشابه، مدیریت میشود. تعداد منابع موجود، در پارامتر تابع osSemaphoreCreate بیان میشود. هر بار با تابع osSemaphoreWait یک token میگیرید و از شماره سمافور، یک عدد کم میشود. وقتی شماره سمافور، به صفر رسید، دیگر token نمی توان گرفت. برای آزاد کردن سمافور هم، از تابع osSemaphoreRelease استفاده میشود. این تابع شماره سمافور را یک عدد افزایش میدهد. در نهایت تابع osSemaphoreDelete نیز آن را پاک میکند.
تابعهای تعریف شده
ماکروهای تعریف شده
برنامه نمونه زیر طرز کار این سمافور را نشان میدهد. دو ریسمان در رقابت برای کسب token هستند. سمافور تک token است (تابع osSemaphoreCreate یک token برای سمافور ساخته است.) Thread اول هر سه میلی ثانیه بررسی میکند که آیا سمافور token دارد یا خیر. به مدت 1 میلی ثانیه نیز منتظر میماند تا token را بگیرد. ولی Thread دوم که اولویت زیادی ندارد، همواره منتظر میماند تا هر وقت که بلیتی در دسترس بود آن را بگیرد.
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 | #include "cmsis_os.h" oSThreadId tid_thread1; // ID for thread 1 oSThreadId tid_thread2; // ID for thread 2 osSemaphoreId semaphore; // Semaphore ID osSemaphoreDef(semaphore); // Semaphore definition /* Thread 1 - High Priority - Active every 3ms */ void thread1 (void conST *argument) { int32_t value; while (1) { osDelay(3); // Pass control to other tasks for 3ms val = osSemaphoreWait (semaphore, 1); // Wait 1ms for the free semaphore if (val > 0) { // If there was no time-out the semaphore was acquired : // OK, the interface is free now, use it. osSemaphoreRelease (semaphore); // Return a token back to a semaphore } } } /* Thread 2 - Normal Priority - looks for a free semaphore and uses the resource whenever it is available */ void thread2 (void conST *argument) { while (1) { osSemaphoreWait (semaphore, osWaitForever); // Wait indefinitely for a free semaphore // OK, the interface is free now, use it. : osSemaphoreRelease (semaphore); // Return a token back to a semaphore. } } /* Thread definitions */ oSThreadDef(thread1, osPriorityHigh, 1, 0); oSThreadDef(thread2, osPriorityNormal, 1, 0); void STartApplication (void) { semaphore = osSemaphoreCreate(osSemaphore(semaphore), 1); tid_thread1 = oSThreadCreate(oSThread(thread1), NULL); tid_thread2 = oSThreadCreate(oSThread(thread2), NULL); : } |
موتکس
موتکس (Mutex) برای هم آهنگی اجرای Thread ها به کار می رود. گاهی یک منبع، فقط باید هر بار، توسط یک Thread دستکاری شود. برای نمونه قسمتی از حافظه که به LCD نگاشته میشود. به نوعی، موتکس یک سمافور با تنها یک token است.
تابعهای تعریف شده
ماکروهای تعریف شده
در برنامه نمونه زیر نحوه کار با موتکس نشان داده شده است.
1 2 3 4 5 6 7 8 9 10 | #include "cmsis_os.h" osMutexDef (MutexIsr); // Mutex name definition void CreateMutex (void) { osMutexId mutex_id; mutex_id = osMutexCreate (osMutex (MutexIsr)); if (mutex_id != NULL) { // Mutex object created } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 | #include "cmsis_os.h" osMutexDef (MutexIsr); // Mutex name definition osMutexId mutex_id; // Mutex id populated by the function CreateMutex() osMutexId CreateMutex (void); // function prototype that creates the Mutex void DeleteMutex (osMutexId mutex_id) { osSTatus STatus; if (mutex_id != NULL) { STatus = osMutexDelete(mutex_id); if (STatus != osOK) { // handle failure code } } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 | #include "cmsis_os.h" osMutexDef (MutexIsr); // Mutex name definition osMutexId mutex_id; // Mutex id populated by the function CreateMutex() osMutexId CreateMutex (void); // function prototype that creates the Mutex void ReleaseMutex (osMutexId mutex_id) { osSTatus STatus; if (mutex_id != NULL) { STatus = osMutexRelease(mutex_id); if (STatus != osOK) { // handle failure code } } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 | #include "cmsis_os.h" osMutexDef (MutexIsr); void WaitMutex (void) { osMutexId mutex_id; osSTatus STatus; mutex_id = osMutexCreate (osMutex (MutexIsr)); if (mutex_id != NULL) { STatus = osMutexWait (mutex_id, 0); if (STatus != osOK) { // handle failure code } } } |
در قسمت دوازدهم آموزش میکروکنترلر STM32F4 به ابزارهای ارتباطی بین Thread ها خواهیم پرداخت. با سیسوگ همراه باشید.
سلام و عرض ادب
ممنون از اين همه مهرباني ..
مي خواستم بدونم چرا در تابع
void WaitMutex (void)
از osMutexCreate به جاي osMutexWait استفاده كرده است؟
خيلي ممنون