臨界段
代碼的臨界段也稱為臨界區,一旦這部分代碼開始執行,則不允許任何中斷打斷。為確保臨界段代碼的執行不被中斷,在進入臨界段之前須關中斷,而臨界段代碼執行完畢后,要立即開中斷。
由於Cortex-M3/M4的RTX內核庫中沒有關閉中斷的操作,也就是說RTX的源碼中不存在臨界段。
中斷鎖
中斷鎖就是RTOS提供的開關中斷函數,因為Cortex-M3/M4的RTX源碼中沒有關閉中斷的操作,所以也就沒有提供開關中斷函數。 由於RTX沒有提供開關中斷函數,如果用戶自己的應用代碼需要開關中斷的話怎么辦呢?
裸機時如何開關中斷的,在使用了RTX后仍然使用以前的開關中斷函數即可
任務鎖
為了防止當前任務的執行被其它高優先級的任務打斷而提供的鎖機制就是任務鎖。實現任務鎖可以通過給調度器加鎖或者直接關閉RTOS內核定時器(就是前面一直說的系統滴答定時器)來實現。
1.通過給調度器加鎖實現 給調度器加鎖的話,就無法實現任務切換,高優先級任務也就無法搶占低優先級任務的執行,同時高優先級任務也是無法向低優先級任務切換的。像uCOS-II和uCOS-III是采用的這種方法實現任務鎖。特別注意,這種方式只是禁止了調度器工作,並沒有關閉任何中斷。
2.
通過關閉RTOS內核定時器實現 關閉了RTOS內核定時器的話,也就關閉了通過RTOS內核定時器中斷實現任務切換的功能,因為在退出定時器中斷時需要檢測當前需要執行的最高優先級任務,如果有高優先級任務就緒的話需要做任務切換。
RTX操作系統是采用的這種方式實現任務鎖的。
os_resume
#include <rtl.h>
void os_resume (
U32 sleep_time ); /* Number of ticks the system was in sleep mode. */
說明:
該函數喚醒操作系統調度器. 客戶在調用了os_suspend之后必須調用該方法來重新使能調度器.
sleep_time參數標識系統將在休眠或者掉電模式下呆多久. 以系統周期作為測量依據.
返回值:
無
注意要點:
該函數只能在系統空閑任務下調用.
單系統處於power_down模式下,tick定時器將不再運行.
例程:
The wake-up timer, when expired, generates the interrupt and wakes-up the system. Hence, it must run also in power-down mode. The system resumes operation and needs to call the function os_resume(). This function restores the RTX and re-enables the OS task scheduler
/* After Wake-up */
sleep = (tc - LPC_WWDT->TV) / 250;
}
os_resume(sleep);
os_suspend
#include <rtl.h>
U32 os_suspend (void);
說明:
該函數掛起操作系統調度器. 該函數將測量需要多久進入掉電模式並關閉操作系統調度器.當函數返回的時候,操作系統調度器就被掛起了
對於RTX,當調用了
os_suspend之后,就必須調用
os_resume
來恢復系統調度
.
返回值:
無
注意要點:
只能在空閑任務中調用該函數
.
操作系統進入power_down模式.系統tick定時器被禁止.
例程:
#include <rtl.h>
__task void os_idle_demon (void) {
uint32_t sleep;
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; /* Configure Cortex-M3 for deep sleep */
PWR->CR &= ~PWR_CR_PDDS; /* Enter Stop mode when in deepsleep */
PWR->CR |= PWR_CR_LPDS; /* Voltage regulator in low-power */
/* Enable LSI clock and wait until ready */
RCC->CSR |= RCC_CSR_LSION;
while ((RCC->CSR & RCC_CSR_LSIRDY) == 0);
/* Enable power interface clock */
RCC->APB1ENR |= RCC_APB1ENR_PWREN;
/* Disable backup domain write protection */
PWR->CR |= PWR_CR_DBP;
/* Select LSI as clock source for RTC and enable RTC */
RCC->BDCR &= ~RCC_BDCR_RTCSEL;
RCC->BDCR |= RCC_BDCR_RTCSEL_1;
RCC->BDCR |= RCC_BDCR_RTCEN;
/* Disable the write protection for RTC registers */
RTC->WPR = 0xCA;
RTC->WPR = 0x53;
/* Configure RTC auto-wakeup mode */
RTC->ISR &= ~RTC_ISR_WUTF; /* Clear wakeup timer flag */
RTC->CR &= ~RTC_CR_WUCKSEL; /* Set RTC clock to 2kHz */
RTC->CR |= RTC_CR_WUTIE; /* Enable RTC wakeup timer interrupt */
/* Configure EXTI line 22 for wakeup on rising edge */
EXTI->EMR |= (1 << 22); /* Event request is not masked */
EXTI->RTSR |= (1 << 22); /* Rising trigger enabled */
NVIC_EnableIRQ (RTC_WKUP_IRQn); /* Enable RTC WakeUp IRQ */
for (;;) {
/* HERE: include optional user code to be executed when no task runs. */
sleep = os_suspend (); /* OS Suspend */
if (sleep) {
RTC->ISR &= ~RTC_ISR_WUTF; /* Clear timer wakeup flag */
RTC->CR &= ~RTC_CR_WUTE; /* Disable wakeup timer */
while ((RTC->ISR & RTC_ISR_WUTWF) == 0);
/* RTC clock is @2kHz, set wakeup time for OS_TICK >= 1ms */
RTC->WUTR = (sleep * (OS_TICK / 1000) * 2);
RTC->CR |= RTC_CR_WUTE; /* Enable wakeup timer */
__WFE (); /* Enter STOP mode */
/* After Wake-up */
if ((RTC->ISR & RTC_ISR_WUTF) == 0) {
sleep = 0; /* We didn't enter Stop mode */
}
}
os_resume (sleep); /* OS Resume */
}
}
tsk_lock
#include <rtl.h>
void tsk_lock (void);
說明:
該函數禁止RTX內核時間中斷,也就自然禁止了操作系統調度器.
返回值:
無
注意要點:
不能在中斷向量中調用該函數
.
不能在中斷處理程序中調用該函數
.
當禁用了內核時間中斷,操作系統時間中斷和時間片輪轉中斷被禁止,超時功能不在工作. 因此,強烈建議關RTX內核定時器中斷的時間越短越好.
例程:
#include <rtl.h>
void protect_critical_op () {
tsk_lock ();
do_critical_op ();
tsk_unlock ();
}
tsk_unlock
#include <rtl.h>
void tsk_unlock (void);
說明:
函數tsk_unlock用於使能RTX內核定時器中斷,因此也就重新開啟任務切換。注意tsk_unlock一定要跟tsk_lock配套使用
.
返回值:
無
注意要點:
函數tsk_lock不支持嵌套調用
.
不允許在中斷服務程序中調用tsk_lock.
例程:
#include <rtl.h>
void protect_critical_op () {
tsk_lock ();
do_critical_op ();
tsk_unlock ();
}
