• TinyThread源码分析之中断


    转载请注明来源:cuixiaolei的技术博客


    https://github.com/xhawk18/TinyThread

    TinyThread 是基于Cortex-M0的小型的OS.


    知识储备:

      IPSR(中断程序状态寄存器),IPSR包含了当前正在执行的中断服务程序编号,用于识别当前中断。

      Cortex-M0处理器内置中断控制器,并且支持最多32个中断请求(IRQ)和一个不可屏蔽中断(NMI).

      PRIMASK置位(写1),开启屏蔽,屏蔽除了NMI和硬件错误(hardfault)外的所有中断。清除此位,关闭屏蔽。

      


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

    TinyThread中断控制函数API主要有以下两个,它们分别是打开IPSR和关闭IPSR寄存器(中断屏蔽特殊寄存器).

    • 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.h

    #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
    ");
    #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.

  • 相关阅读:
    用JSP实现的商城购物车模块
    PHP Filesystem 函数(文件系统函数)(每日一课的内容可以从php参考手册上面来)
    PHP unlink() 函数(删除文件)
    $_SERVER['DOCUMENT_ROOT']
    thinkphp模型事件(钩子函数:模型中在增删改等操作前后自动执行的事件)
    php实现字符串替换
    js私有变量
    js模仿块级作用域(js没有块级作用域私有作用域)
    unity 3d开发的大型网络游戏
    thinkphp5项目--企业单车网站(八)(文章板块要点)(删除图片)
  • 原文地址:https://www.cnblogs.com/xiaolei-kaiyuan/p/6099042.html
Copyright © 2020-2023  润新知