?? arm_00_os_core.c
字號(hào):
/**********************************************************************************************
本程序只供學(xué)習(xí)使用,不得用于其它任何用途,否則后果自負(fù)。
ARM_00_OS_Core.c file
作者:Computer-lov
建立日期:2006-5-1
修改日期:2006-5-15
版本:V1.0
版權(quán)所有,盜版必究。
任何技術(shù)問題可到我的博客上留言: http://computer00.21ic.org
Copyright(C) Computer-lov 2006-2016
All rights reserved
**********************************************************************************************/
#include <ADuC7027.H>
#include "interrupt.h"
#include "LED.H"
#include "ARM_00_OS_TaskSwitch.H"
#include "my_type.h"
#include "ARM_00_OS_Core.H"
#include "UART.H"
#include "KEYS.H"
#include "Task.h"
OSpcb * OSReadyList; //就緒態(tài)任務(wù)表表頭
OSpcb * OSSuspendList; //掛起態(tài)任務(wù)表表頭
OSpcb * OSDelayList; //延時(shí)態(tài)任務(wù)表表頭
OSpcb * OSCurrentPcb; //當(dāng)前運(yùn)行的任務(wù)
OSpcb OSSystemIdlePcb; //系統(tǒng)空閑任務(wù)
OSShortPcb OSSuspendListBottom; //掛起態(tài)列表表底
OSShortPcb OSDelayListBottom; //延時(shí)態(tài)列表表底
OSdevice OSDeviceBottom; //設(shè)備列表的底部
OSdevice * OSDeviceList; //設(shè)備列表
volatile uint32 CopyOfIRQEN; //用來備份IRQEN的狀態(tài)
volatile uint32 CopyOfFIQEN; //用來備份FIQEN的狀態(tài)
volatile uint32 OSEnCrCount; //用來統(tǒng)計(jì)進(jìn)入臨界代碼段次數(shù)
volatile uint32 TaskAmount; //用來統(tǒng)計(jì)共有多少個(gè)任務(wù)
volatile uint32 TimeOfTaskStart; //用來保存一個(gè)任務(wù)剛被切換到運(yùn)行態(tài)的時(shí)刻
#define OSMemoryLack 0x0000000100000000 /*錯(cuò)誤號(hào):內(nèi)存資源不足*/
/**********************************************************************************************
功能:內(nèi)存管理。
入口參數(shù)1:Operation。操作方式。可以設(shè)置為MEMORY_ALLOCATION(分配)、MEMORY_FREE(釋放)、統(tǒng)計(jì)使用量(MEMORY_STATISTIC)
入口參數(shù)2:StartAddr。起始地址,釋放內(nèi)存時(shí)使用。
入口參數(shù)3:Length。申請(qǐng)內(nèi)存或釋放內(nèi)存時(shí)的長度,單位為字節(jié)。但實(shí)際分配時(shí),是按塊分配的,所以分配時(shí),
實(shí)際分配到的數(shù)量可能會(huì)比指定的多,所以分配時(shí),最好按塊的整數(shù)倍大小來指定分配長度。
返回:32無符號(hào)型整數(shù)。
當(dāng)操作為分配內(nèi)存時(shí),返回32位的內(nèi)存首地址,返回0表示無足夠多的可以用內(nèi)存。
當(dāng)操作為釋放內(nèi)存時(shí),返回1表示釋放成功。返回0表示釋放出錯(cuò)。
當(dāng)操作為統(tǒng)計(jì)內(nèi)存使用量時(shí),返回的是內(nèi)存被使用的字節(jié)數(shù)。
當(dāng)操作為獲取緩沖池大小時(shí),返回的是內(nèi)存緩沖池大小。
備注:緩沖池大小由OSSizeOfMemoryPool指定。每塊的大小由OSSizePerBlock指定
**********************************************************************************************/
uint32 OSMemoryManage(uint32 Operation,uint32 StartAddr,uint32 Length)
{
//內(nèi)存分配表
//內(nèi)存分配表是32位整數(shù)的一維數(shù)組。用每一位來表示一塊是否被使用。當(dāng)某位設(shè)置為1時(shí),表示那一塊被使用。
//當(dāng)某位為0時(shí),表示那一塊可用。
static uint32 OSMemoryTable[OSSizeOfMemoryPool/OSSizePerBlock/32];
static uint32 OSMemoryPool[OSSizeOfMemoryPool/4]; //內(nèi)存緩沖池。內(nèi)存緩沖池為一個(gè)大是數(shù)組
uint32 BlankCount; //統(tǒng)計(jì)空塊的計(jì)數(shù)器
uint32 Mask; //分配內(nèi)存時(shí)用的掩碼
volatile uint32 i,j; //循環(huán)用的變量
OSEnterCritical(); //進(jìn)入臨界段
switch(Operation) //根據(jù)操作碼,選擇不同的操作
{
case MEMORY_INIT: //如果是內(nèi)存初始化
{
for(i=0;i<OSSizeOfMemoryPool/OSSizePerBlock/32;i++)
{
OSMemoryTable[i]=0; //則將整張內(nèi)存分配表清0
}
OSExitCritical(); //退出臨界段
return 1; //返回1
}
case MEMORY_ALLOCATION: //如果是內(nèi)存分配,則
{
BlankCount=0; //先將內(nèi)存空塊的數(shù)量清0
for(i=0;i<(OSSizeOfMemoryPool/OSSizePerBlock/32);i++) //掃描整個(gè)內(nèi)存分配表
{
Mask=1; //掩碼被設(shè)置為1,即最低位為1,其它位為0。
if(OSMemoryTable[i]==0xFFFFFFFF) //如果該字中的所以位都為1,表示該字節(jié)對(duì)應(yīng)的所有塊都被占用
{
BlankCount=0; //空塊計(jì)數(shù)器置0
continue; //退出本次循環(huán),查找下一個(gè)字
}
for(j=0;j<32;j++) //掃描一個(gè)字的32個(gè)bit是否有空閑的RAM
{
if((Mask & OSMemoryTable[i])==0) //如果該位為0,表示該塊空閑
{
BlankCount++; //空塊計(jì)數(shù)器加1。
}
else
{
BlankCount=0; //如果遇到非空塊,則空塊計(jì)數(shù)器置0。
}
if((BlankCount*OSSizePerBlock)>=Length) //如果空閑的RAM,大于或者等于需要的長度,那么分配成功
{
//計(jì)算被分配到的內(nèi)存的起始地址,并將其保存在StartAddr中。
StartAddr=((uint32)OSMemoryPool)+(i*32+j+1)*OSSizePerBlock-OSSizePerBlock*BlankCount;
while(1) //設(shè)置被使用的塊為1
{
OSMemoryTable[i] |=Mask; //將已經(jīng)被分配的標(biāo)志為1
Mask>>=1; //調(diào)整掩碼的值
if(j==0) //如果已到最低位
{
Mask=0x80000000; //則掩碼調(diào)整為第31位為1
j=32;
i--; //移到下一位
}
BlankCount--; //空塊計(jì)數(shù)減1
j--; //移到下一個(gè)字
if(BlankCount==0) //如果空塊計(jì)數(shù)器減到0,則標(biāo)志完畢
{
OSExitCritical();
return StartAddr; //將啟始地址StartAddr返回
}
}
}
Mask<<=1; //掩碼調(diào)整,移動(dòng)到下一個(gè)塊
}
}
OSExitCritical();
return 0; //如果沒有足夠大的內(nèi)存塊可用,則返回0,分配失敗
}
case MEMORY_FREE: //如果操作碼是釋放內(nèi)存
{
if(Length==0) //如果要釋放的內(nèi)存長度為0
{
OSExitCritical(); //退出臨界段
return 1; //返回1,釋放成功
}
i=(StartAddr-(uint32)OSMemoryPool)/(32*OSSizePerBlock); //計(jì)算出指定地址內(nèi)存在內(nèi)存分配表中的位置
j=(StartAddr-(uint32)OSMemoryPool-i*32*OSSizePerBlock)/OSSizePerBlock;
Mask=1<<j; //將掩碼調(diào)整到對(duì)應(yīng)的值
while(Length) //直到全部被釋放為止
{
if((OSMemoryTable[i])&(Mask)==0) //如果該內(nèi)存并未被分配,則說明發(fā)生了錯(cuò)誤,
{
OSExitCritical(); //推出臨界段
return 0; //返回0,表示釋放失敗
}
OSMemoryTable[i] &=~Mask; //清除對(duì)應(yīng)的位,即釋放該塊內(nèi)存
j++; //調(diào)整到下一塊
Mask<<=1; //掩碼調(diào)整到下一塊的位置
if(j==32) //如果已經(jīng)到最高位
{
Mask=1; //掩碼設(shè)置為1
j=0; //j回到最低位
i++; //調(diào)整下一個(gè)字
}
if(Length<=OSSizePerBlock) //如果釋放完畢
{
Length=0; //則Length設(shè)置為0,退出循環(huán)
}
else //如果沒釋放完畢
{
Length-=OSSizePerBlock; //則長度減小一個(gè)塊的量
}
}
OSExitCritical(); //退出臨界段
return 1; //返回1,表示釋放成功
}
case MEMORY_STATISTIC: //如果操作碼是統(tǒng)計(jì)內(nèi)存使用量
{
Length=0; //清Length
for(i=0;i<OSSizeOfMemoryPool/OSSizePerBlock/32;i++) //掃描整張內(nèi)存分配表
{
if(OSMemoryTable[i]==0) //如果當(dāng)前字是全0,則該字對(duì)應(yīng)的內(nèi)存都未被分配,
{
continue; //則跳過本次循環(huán)
}
if(OSMemoryTable[i]==0xFFFFFFFF) //如果當(dāng)前字是全1,則該字對(duì)應(yīng)的內(nèi)存全部被分配
{
Length+=32*OSSizePerBlock; //Length累加上32塊的長度
continue; //退出本次循環(huán)
}
Mask=1; //掩碼設(shè)置為1
for(j=0;j<32;j++) //掃描當(dāng)前字的32bit,看是否有內(nèi)存被使用
{
if(OSMemoryTable[i]&Mask) //如果該塊被使用
{
Length+=OSSizePerBlock; //則Length累加一塊的長度
}
Mask<<=1; //調(diào)整掩碼到下一位
}
}
OSExitCritical(); //退出臨界段
return Length; //返回使用的內(nèi)存數(shù)量
}
case GET_MEMORY_POOL_SIZE: //如果是獲取緩沖池大小,
{
OSExitCritical(); //退出臨界段
return OSSizeOfMemoryPool; //返回緩沖池的字節(jié)數(shù)
}
case MEMORY_TEST: //如果是內(nèi)存檢測(cè)
{
j=0xFF; //標(biāo)志j為非0,即初始化成功
prints("Memory testing. ",1); //顯示信息
for(i=0;i<OSSizeOfMemoryPool/4;i++) //檢測(cè)整個(gè)內(nèi)存緩沖池
{
OSMemoryPool[i]=0x55555555; //寫入0x55555555
if(OSMemoryPool[i]!=0x55555555) //如果讀回的不是0x55555555
{
j=0; //則測(cè)試失敗
}
OSMemoryPool[i]=0xAAAAAAAA; //寫入0xAAAAAAAA
if(OSMemoryPool[i]!=0xAAAAAAAA) //如果讀回的不是0xAAAAAAAA
{
j=0; //則測(cè)試失敗
}
OSMemoryPool[i]=0; //寫入0
if(OSMemoryPool[i]!=0) //如果讀回的不是0
{
j=0; //則測(cè)試失敗
}
if(i%(OSSizeOfMemoryPool/4/80)==0) //顯示測(cè)試進(jìn)度。共顯示80個(gè)>
{
prints(">",0);
}
}
prints("",1);
if(j) //如果測(cè)試成功
{
prints("Memory test passed.",1); //顯示成功
}
else //否則,
{
prints("Memroy test failed.",1); //顯示測(cè)試失敗
}
OSExitCritical(); //退出臨界段
return j; //返回是否成功
}
default: OSExitCritical();return 0;
}
}
//////////////////////////////////End of function//////////////////////////////////////////////
/**********************************************************************************************
功能:進(jìn)入臨界段。
入口參數(shù):無。
返回:無。
備注:該函數(shù)使用的是將中斷分配寄存器清0的方法來關(guān)中斷。比起用軟中斷,運(yùn)行速度要快。
如果要開某個(gè)中斷,則應(yīng)該先調(diào)用一次該函數(shù),然后再修改中斷備份變量CopyOfIRQEN跟CopyOfFIQEN
的值,而不能直接修改IRQEN跟FIQEN的值。否則會(huì)出錯(cuò)。
**********************************************************************************************/
void OSEnterCritical(void)
{
if(OSEnCrCount==0) //如果前面未關(guān)中斷
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -