DIY:给单片机写个实时操作系统内核!
//SP指针指向该任务的栈顶
SP = (uint16_t)OS_CurrentThread->ThreadStackTop ;
//使用出栈操作
POP_REG();
//调用RET,调用之后开始执行任务,不会再返回到这里
_asm("RET");
}
怎样实现时间片?答案是用定时器定时,每次定时器产生中断的时候就转换一次任务,时基可以自己确定,一般来说时基越小的话会让CPU花很多时间在切换任务上,降低了效率,时基大的话又使时间粒度变粗,会使一些程序得不到及时的执行。我设定了每10MS中断一次,就是说每一轮中每个线程都有10MS的执行时间。具体算法不再赘述。
内存管理策略
接下来要考虑怎样管理内存了!在PC里面编程的时候,如果需要开辟一个内存空间,我们可以很容易地调用malloc()和free()来完成,但是在单片机里面却行不通,因为要实现这两个函数背后需要完成很多算法支持,从速度和空间上单片机都做不到。
在单片机里面如果你需要开辟内存空间,你只有在编译的时候就先定义好变量,无法动态申请,但是我们可以设计一个简单的内存管理策略来实现这种动态申请!原理就是在编译的时候先向编译器要一块足够大的内存并且声明为静态,然后把这块空间交给内存管理模块来调用,内存管理模块负责分配这块内存,当有任务要向它申请内存的时候它就从里面拿出一块交给任务,而任务要释放的时候就把该内存空间交给内存管理模块来实现。
关于内存管理也有很多种策略,在这里就不一一述说了,我在源代码里面使用了一种简单的随机分配的方法,即有线程申请的时候就从当前内存块的可用空间里拿出一块来,然后在内存头加上一个专用的结构体,把每个内存块都链接起来,这样便于管理。当线程释放内存的时候,就把内存返回到内存空间并跟其他空间的内存块合并起来等待线程再次调用。
/**
* @名称 : 内存块申请函数
* @版本 : V 0.0
* @输入参数 : 1. OS_DataType_MemorySize MemorySize
需要申请内存块的大小
* @输出参数 : 1. void *
若申请成功,则返回可使用内存块首地址,否则返回NULL
* @描述 :
* @建立时间 : 2011-11-16
* @最近修改时间: 2011-11-16
*/
#if OS_MEMORY_EN
void *OS_MemoryMalloc(OS_DataType_MemorySize MemorySize)
{
pOS_MCB pmcb = OS_MCB_Head ;
pOS_MCB pmcb2 ;
MemorySize+=OS_MEMORY_BLOCK_SIZE ;
//进入内存搜索算法
while(1)
{
//检测该内存块是否存在
if(pmcb==NULL)
{
return NULL ;
}
//如果存在则检测该内存块的使用状态
else if( (pmcb->Status==OS_MEMORY_STATUS_IDLE) && (pmcb->Size >= MemorySize) )
{
//如果可用内存块大小刚好等于需要申请的大小
//则立即分配
if(pmcb->Size == MemorySize)
{
pmcb->Status=OS_MEMORY_STATUS_USING ;
OS_MemoryIdleCount -= MemorySize ;
return (OS_DataType_Memory *)pmcb + OS_MEMORY_SIZE ;
}
//若可用内存块大小大于需要申请的大小
//则进行分割操作
else
{
pmcb2=(pOS_MCB)( (OS_DataType_Memory *)pmcb + MemorySize );
pmcb2->Front=pmcb ;
pmcb2->Next=pmcb->Next ;
pmcb2->Status=OS_MEMORY_STATUS_IDLE ;
pmcb2->Size = pmcb->Size - MemorySize ;
pmcb->Status = OS_MEMORY_STATUS_USING ;
pmcb->Size = MemorySize ;
pmcb->Next=pmcb2;
OS_MemoryIdleCount -= MemorySize ;
return (OS_DataType_Memory *)pmcb+OS_MEMORY_BLOCK_SIZE ;
}
}
else
{
pmcb=pmcb->Next;
}
}
}
#endif
内存释放函数:
/**
* @名称 : 内存块释放函数
* @版本 : V 0.0
* @输入参数 : 1. OS_DataType_MemorySize MemorySize
需要申请内存块的大小
* @输出参数 : 1. void *
若申请成功,则返回可使用内存块首地址,否则返回NULL
* @描述 :
* @建立时间 : 2011-11-16
* @最近修改时间: 2011-11-16
*/
#if OS_MEMORY_EN
void OS_MemoryFree(void *MCB)
{
pOS_MCB pmcb = (pOS_MCB)( (OS_DataType_Memory *)MCB - OS_MEMORY_BLOCK_SIZE );
//将当前内存块设置为空闲状态
pmcb->Status=OS_MEMORY_STATUS_IDLE ;
OS_MemoryIdleCount += pmcb->Size ;
//如果存在上一块内存块,则进入判断
if(pmcb->Front!=NULL)
{
//如果上一块内存块处于空闲状态,则进行合并操作
if(pmcb->Front->Status == OS_MEMORY_STATUS_IDLE)
{
pmcb->Front->Size += pmcb->Size ;
pmcb->Front->Next = pmcb->Next ;
pmcb=pmcb->Front ;
OS_MemoryIdleCount += pmcb->Size ;
}
}
//如果存在下一块内存块,则进入判断
if(pmcb->Next!=NULL)
{
//
DIY单片机实时操作系统内 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)