临界区(Critical Section)
- 保证在某一时刻只有一个线程能访问数据的简便办法。在任意时刻只允许一个线程对共享资源进行访问。
- RT-Thread 对临界段的保护就处理的很干脆,直接把中断全部关了, NMI FAULT 和硬 FAULT 除外。
- Cortex M3权威指南 中对异常掩蔽寄存器的说明。
- 当临界段嵌套时,如果简单的开关总中断,内部临界段释放时总中断被打开,而外部临界段并没有结束,不应该开启。
context_rvds.s
中定义了临界段开关函数。开启时先保存当前的PRIMASK
。关闭时恢复先前值。
;
rt_hw_interrupt_disable PROC
EXPORT rt_hw_interrupt_disable
MRS r0, PRIMASK
CPSID I
BX LR
ENDP
;
rt_hw_interrupt_enable PROC
EXPORT rt_hw_interrupt_enable
MSR PRIMASK, r0
BX LR
ENDP
对象容器
- 对象,RT-Thread中所有数据结构都称之为对象。在整个系统中,对象的名字必须是唯一的。
- 结构体在
rtdef.h
中定义。
struct rt_object
{
char name[RT_NAME_MAX];
rt_uint8_t type;
rt_uint8_t flag;
rt_list_t list;
};
typedef struct rt_object *rt_object_t;
enum rt_object_class_type
{
RT_Object_Class_Thread = 0,
RT_Object_Class_Semaphore,
RT_Object_Class_Mutex,
RT_Object_Class_Event,
RT_Object_Class_MailBox,
RT_Object_Class_MessageQueue,
RT_Object_Class_MemHeap,
RT_Object_Class_MemPool,
RT_Object_Class_Device,
RT_Object_Class_Timer,
RT_Object_Class_Module,
RT_Object_Class_Unknown,
RT_Object_Class_Static = 0x80
};
struct rt_object_information
{
enum rt_object_class_type type;
rt_list_t object_list;
rt_size_t object_size;
};
- 每个对象都会有对应的一个结构体, 这个结构体叫做该对象的控制
块。 如线程会有一个线程控制块,定时器会有一个定时器控制块,信号量会有信号量控制块等。如下面的线程对象,其它内核对象的都是直接在其开头使用 struct rt_object 直接定义一个内核对象变量。
struct rt_thread
{
char name[RT_NAME_MAX];
rt_uint8_t type;
rt_uint8_t flags;
rt_list_t list;
void *sp;
void *entry;
void *parameter;
void *stack_addr;
rt_uint32_t stack_size;
rt_list_t tlist;
};
- 容器,在RT-Thread中,用户每创建一个对象,就会将这个对象放到一个叫容器的地方,目的是为了方便管理。从代码上看,容器就是一个数组,是一个全局变量,数据类型是
struct rt_object_information
。 - 在
object.c
中定义。
enum rt_object_info_type
{
RT_Object_Info_Thread = 0,
#ifdef RT_USING_SEMAPHORE
RT_Object_Info_Semaphore,
#endif
#ifdef RT_USING_MUTEX
RT_Object_Info_Mutex,
#endif
#ifdef RT_USING_EVENT
RT_Object_Info_Event,
#endif
#ifdef RT_USING_MAILBOX
RT_Object_Info_MailBox,
#endif
#ifdef RT_USING_MESSAGEQUEUE
RT_Object_Info_MessageQueue,
#endif
#ifdef RT_USING_MEMHEAP
RT_Object_Info_MemHeap,
#endif
#ifdef RT_USING_MEMPOOL
RT_Object_Info_MemPool,
#endif
#ifdef RT_USING_DEVICE
RT_Object_Info_Device,
#endif
RT_Object_Info_Timer,
#ifdef RT_USING_MODULE
RT_Object_Info_Module,
#endif
RT_Object_Info_Unknown,
};
#define _OBJ_CONTAINER_LIST_INIT(c) \
{&(rt_object_container[c].object_list), &(rt_object_container[c].object_list)}
static struct rt_object_information rt_object_container[RT_Object_Info_Unknown] =
{
{
RT_Object_Class_Thread,
_OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Thread),
sizeof(struct rt_thread)
},
#ifdef RT_USING_SEMAPHORE
{
RT_Object_Class_Semaphore,
_OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Semaphore),
sizeof(struct rt_semaphore)
},
#endif
#ifdef RT_USING_MUTEX
{
RT_Object_Class_Mutex,
_OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Mutex),
sizeof(struct rt_mutex)
},
#endif
#ifdef RT_USING_EVENT
{
RT_Object_Class_Event,
_OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Event),
sizeof(struct rt_event)
},
#endif
#ifdef RT_USING_MAILBOX
{
RT_Object_Class_MailBox,
_OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MailBox),
sizeof(struct rt_mailbox)
},
#endif
#ifdef RT_USING_MESSAGEQUEUE
{
RT_Object_Class_MessageQueue,
_OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MessageQueue),
sizeof(struct rt_messagequeue)
},
#endif
#ifdef RT_USING_MEMHEAP
{
RT_Object_Class_MemHeap,
_OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MemHeap),
sizeof(struct rt_memheap)
},
#endif
#ifdef RT_USING_MEMPOOL
{
RT_Object_Class_MemPool,
_OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MemPool),
sizeof(struct rt_mempool)
},
#endif
#ifdef RT_USING_DEVICE
{
RT_Object_Class_Device,
_OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Device), sizeof(struct rt_device)},
#endif
#ifdef RT_USING_MODULE
{
RT_Object_Class_Module,
_OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Module),
sizeof(struct rt_module)
},
#endif
};
- 容 器 的 大 小 由
RT_Object_Info_Unknown
决 定。 - 对象初始化,将对象挂到对象容器中,双向链表。
void rt_object_init(struct rt_object *object,
enum rt_object_class_type type,
const char *name)
{
register rt_base_t temp;
struct rt_object_information *information;
information = rt_object_get_information(type);
object->type = type | RT_Object_Class_Static;
rt_strncpy(object->name, name, RT_NAME_MAX);
temp = rt_hw_interrupt_disable();
rt_list_insert_after(&(information->object_list), &(object->list));
rt_hw_interrupt_enable(temp);
}
void rt_object_detach(rt_object_t object)
{
register rt_base_t temp;
temp = rt_hw_interrupt_disable();
rt_list_remove(&(object->list));
rt_hw_interrupt_enable(temp);
}
rt_bool_t rt_object_is_systemobject(rt_object_t object)
{
if (object->type & RT_Object_Class_Static)
return RT_TRUE;
return RT_FALSE;
}
- 比如创建了两个线程, 他们在容器列表中的示意图如下。
- 线程初始化函数也要做相应修改。
rt_err_t rt_thread_init(struct rt_thread *thread,
const char *name,
void (*entry)(void *parameter),
void *parameter,
void *stack_start,
rt_uint32_t stack_size)
{
rt_object_init((rt_object_t)thread, RT_Object_Class_Thread, name);
rt_list_init(&(thread->tlist));
thread->entry = (void *)entry;
thread->parameter = parameter;
thread->stack_addr = stack_start;
thread->stack_size = stack_size;
thread->sp = (void *)rt_hw_stack_init( thread->entry,
thread->parameter,
(void *)((char *)thread->stack_addr + thread->stack_size - 4) );
return RT_EOK;
}
rt_thread_init( &rt_flag1_thread,
"rt_flag1_thread",
flag1_thread_entry,
RT_NULL,
&rt_flag1_thread_stack[0],
sizeof(rt_flag1_thread_stack) );