TinyThread源碼分析之中斷

轉載請註明來源:cuixiaolei的技術博客


 

https://github.com/xhawk18/TinyThreadgit

TinyThread 是基於Cortex-M0的小型的OS.github

 


 

 

知識儲備:函數

  IPSR(中斷程序狀態寄存器),IPSR包含了當前正在執行的中斷服務程序編號,用於識別當前中斷。ui

  Cortex-M0處理器內置中斷控制器,而且支持最多32箇中斷請求(IRQ)和一個不可屏蔽中斷(NMI).spa

  PRIMASK置位(寫1),開啓屏蔽,屏蔽除了NMI和硬件錯誤(hardfault)外的全部中斷。清除此位,關閉屏蔽。code

  


 

 

TinyThread中斷控制涉及到的文件主要有:tt_sys.h、tt_sys.cblog

TinyThread中斷控制函數API主要有如下兩個,它們分別是打開IPSR和關閉IPSR寄存器(中斷屏蔽特殊寄存器).ip

  • void tt_enable_irq (void)            // 打開中斷,PRIMASK清零
  • void tt_disable_irq (void)            // 關閉中斷,PRIMASK置位

 

tt_sys.c開發

1 #include "../Inc/tt_thread.h"
2 
3 volatile int g_iIRQ_disable_count = 0;
4 volatile bool g_bIRQ_real_disable = 0;

 

tt_sys.hget

#ifndef INC_TT_SYS_H__
#define INC_TT_SYS_H__

#ifdef __cplusplus
extern "C" {
#endif


extern volatile int    g_iIRQ_disable_count;
extern volatile bool    g_bIRQ_real_disable;

//#define TT_SYS_NO_PRINTF


/* Implement in tt_syscall.s */
#if defined __CC_ARM
#    if __CM0_CMSIS_VERSION < 0x00020000
TT_INLINE bool tt_is_in_irq (void)                              //__get_IPSR()獲得當前 中斷程序狀態寄存器 的值,此函數用來判斷當前是否處在中斷狀態。
{
    register uint32_t __regIPSR          __asm("ipsr");
    return(__regIPSR);
}    
#    else
TT_INLINE bool tt_is_in_irq (void)
{
    return __get_IPSR ();
}
#endif
#elif defined __GNUC__
__attribute__((always_inline )) TT_INLINE bool tt_is_in_irq (void)
{
    uint32_t result;
    __asm__ volatile ("MRS %0, ipsr" : "=r" (result) );
    return(result);
}
#elif defined __ICCARM__
#    pragma diag_suppress=Pe940
TT_INLINE bool tt_is_in_irq (void)
{
    __asm("    MRS R0, IPSR    ");
}
#endif


TT_INLINE bool tt_is_irq_disabled (void)                            //查看 中斷屏蔽特殊寄存器的值  中斷被屏蔽返回true,中斷可用返回false
{
    int primask = __get_PRIMASK ();
    if ((primask & 1) == 0)                            //中斷程序狀態寄存器第0位置1,表示中斷被屏蔽
        return false;
    else
        return true;
}


TT_INLINE void tt_enable_irq (void)
{
    if (!tt_is_irq_disabled ())     //若是中斷可使用
    {
        __set_PRIMASK(1);                              //PRIMASK寫1,屏蔽中斷
#if !defined TT_SYS_NO_PRINTF
        printf ("Not call tt_disable_irq before tt_enable_irq\n");
#endif
        while (1);                    //錯誤處理,用死循環提示,我我的認爲做者這麼處理的緣由是程序死掉,開發人員會追到這裏,就知道緣由了(沒有先執行tt_disable_irq函數).
    }

    g_iIRQ_disable_count--;           
    if (g_iIRQ_disable_count == 0)
    {
        if (g_bIRQ_real_disable)
        {
            __set_PRIMASK(0);
        }
    }
}


TT_INLINE void tt_disable_irq (void)
{
    if (tt_is_irq_disabled ())                        //已經disbale過了
    {
        if (g_iIRQ_disable_count == 0)
            g_bIRQ_real_disable = false;
    }
    else
    {
        __set_PRIMASK(1);
        if (g_iIRQ_disable_count == 0)
            g_bIRQ_real_disable = true;
    }    
    g_iIRQ_disable_count++;
}

在 void tt_enable_irq (void) 函數中,咱們能夠知道,在沒有先disable irq的狀況下,不容許執行此函數. 若是連續執行此函數,報錯。

在 void tt_disable_irq (void) 函數中,咱們能夠知道,雖然能夠連續執行tt_disable_irq函數,可是當連續執行此函數後, g_bIRQ_real_disable 的值爲 false, 那麼當enable irq時是沒有其做用的。

因此使用這對函數,必定要成對出現,並且要先disable,而後enable.

相關文章
相關標籤/搜索