rtthread

3 篇文章 0 订阅

链表

初始化双向链表

rt_inline void rt_list_init(rt_list_t *l)
{
    l->next = l->prev = l;
}

插入

rt_inline void rt_list_insert_after(rt_list_t *l, rt_list_t *n)
{
    l->next->prev = n;
    n->next = l->next;

    l->next = n;
    n->prev = l;
}

在这里插入图片描述
NODE1后面插入节点n,可以理解为:NODE3的前一个结点为n,n的后一个节点为NODE3,NODE3l->next

删除

rt_inline void rt_list_remove(rt_list_t *n)
{
    n->next->prev = n->prev;
    n->prev->next = n->next;

    n->next = n->prev = n;
}

在这里插入图片描述

就绪列表

就是一个rt_list_t类型的数组。

/* 线程就绪列表 */
rt_list_t rt_thread_priority_table[RT_THREAD_PRIORITY_MAX];

每个线程控制块都有一个成员tlist,类型为rt_list_t.我们将线程插入到就绪列表里面,就是通过将线程控制块的 tlist 这个节点插入到就绪列表中来实现的。

/* 初始化线程 */
rt_thread_init( &rt_flag1_thread,                 /* 线程控制块 */
                flag1_thread_entry,               /* 线程入口地址 */
                RT_NULL,                          /* 线程形参 */
                &rt_flag1_thread_stack[0],        /* 线程栈起始地址 */
                sizeof(rt_flag1_thread_stack) );  /* 线程栈大小,单位为字节 */
/* 将线程插入到就绪列表 */
rt_list_insert_before( &(rt_thread_priority_table[0]),&(rt_flag1_thread.tlist) );

系统调度初始化

/**
 * @ingroup SystemInit
 * This function will initialize the system scheduler
 */
void rt_system_scheduler_init(void)
{
    register rt_base_t offset;
	/* 线程就绪列表初始化 */
    for (offset = 0; offset < RT_THREAD_PRIORITY_MAX; offset ++)
    {
        rt_list_init(&rt_thread_priority_table[offset]);
    }
	/* 初始化当前线程控制块指针 */
    rt_current_thread = RT_NULL;
}

此时的链表为空
在这里插入图片描述

启动调度器

/**
 * @ingroup SystemInit
 * This function will startup scheduler. It will select one thread
 * with the highest priority level, then switch to it.
 */
void rt_system_scheduler_start(void)
{
    register struct rt_thread *to_thread;
    register rt_ubase_t highest_ready_priority;

#if RT_THREAD_PRIORITY_MAX > 32
    register rt_ubase_t number;

    number = __rt_ffs(rt_thread_ready_priority_group) - 1;
    highest_ready_priority = (number << 3) + __rt_ffs(rt_thread_ready_table[number]) - 1;
#else
    highest_ready_priority = __rt_ffs(rt_thread_ready_priority_group) - 1;
#endif

    /* get switch to thread */
    to_thread = rt_list_entry(rt_thread_priority_table[highest_ready_priority].next,
                              struct rt_thread,
                              tlist);

    rt_current_thread = to_thread;

    /* switch to new thread */
    rt_hw_context_switch_to((rt_uint32_t)&to_thread->sp);

    /* never come back */
}

临界段保护

PRIMASK寄存器

这个寄存器只有一个位,置1后,将关闭所有可屏蔽中断的异常,只剩NMI和硬fault,默认值为0

;/*
; * rt_base_t rt_hw_interrupt_disable();
; */
rt_hw_interrupt_disable    PROC
    EXPORT  rt_hw_interrupt_disable
    MRS     r0, PRIMASK
    CPSID   I
    BX      LR
    ENDP

;/*
; * void rt_hw_interrupt_enable(rt_base_t level);
; */
rt_hw_interrupt_enable    PROC
    EXPORT  rt_hw_interrupt_enable
    MSR     PRIMASK, r0
    BX      LR
    ENDP

为什么不直接这样写?

;/*
; * void rt_hw_interrupt_disable();
; */
rt_hw_interrupt_disable PROC
EXPORT rt_hw_interrupt_disable
CPSID I
BX LR
ENDP

;/*
; * void rt_hw_interrupt_enable(void);
; */
rt_hw_interrupt_enable PROC
EXPORT rt_hw_interrupt_enable
CPSIE I
BX LR
ENDP

避免在嵌套的临界段失效,如下所示

/* 临界段代码 */
{
	/* 临界段 1 开始 */
	rt_hw_interrupt_disable(); /* 关中断,PRIMASK = 1 */
	{
		/* 临界段 2 */
		rt_hw_interrupt_disable(); /* 关中断,PRIMASK = 1 */
		{
		
		}
		rt_hw_interrupt_enable(); /* 开中断,PRIMASK = 0 */ //(注意)
	}
	/* 这里已经开启了中断,而临界段1还未结束 */
	/* 临界段 1 结束 */
	rt_hw_interrupt_enable(); /* 开中断,PRIMASK = 0 */
}

正确做法如下:

PRIMASK = 0; /* PRIMASK 初始值为 0,表示没有关中断 */ 
rt_base_t level1;
rt_base_t level2;

/* 临界段代码 */
{
	/* 临界段 1 开始 */
	level1 = rt_hw_interrupt_disable(); /* 关中断,level1=0,PRIMASK=1 */
	{
		/* 临界段 2 */
		level2 = rt_hw_interrupt_disable(); /* 关中断,level2=1,PRIMASK=1 */ 
		{
		
		}
		rt_hw_interrupt_enable(level2); /* 开中断,level2=1,PRIMASK=1 */
	}
	/* 临界段 1 结束 */
	rt_hw_interrupt_enable(level1); /* 开中断,level1=0,PRIMASK=0 */ 
}

对象

软件定时器




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值