SmartOS/Sys.cpp

685 lines
19 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "Sys.h"
#include "Time.h"
#include "SerialPort.h"
TSys Sys;
TTime Time;
extern uint __heap_base;
extern uint __heap_limit;
extern uint __initial_sp;
extern uint __microlib_freelist;
extern uint __microlib_freelist_initialised;
#ifndef BIT
#define BIT(x) (1 << (x))
#endif
#ifdef STM32F1
char MemNames[] = "468BCDEFGIK";
uint MemSizes[] = { 16, 32, 64, 128, 256, 384, 512, 768, 1024, 2048, 3072 };
uint RamSizes[] = { 6, 10, 20, 20, 48, 48, 64, 96, 96, 96, 96 };
#elif defined(STM32F0)
char MemNames[] = "468B";
uint MemSizes[] = { 16, 32, 64, 128 };
//uint RamSizes[] = { 4, 6, 8, 16 }; // 150x6有6kRAM
uint RamSizes[] = { 4, 4, 8, 16 };
#elif defined(STM32F4)
char MemNames[] = "468BCDEFGIK";
uint MemSizes[] = { 16, 32, 64, 128, 256, 384, 512, 768, 1024, 2048, 3072 };
uint RamSizes[] = { 6, 10, 20, 20, 48, 48, 128, 192, 128, 192, 192 };
#endif
void TSys::Reset() { NVIC_SystemReset(); }
#pragma arm section code
_force_inline void InitHeapStack(uint ramSize)
{
uint* p = (uint*)__get_MSP();
// 直接使用RAM最后需要减去一点因为TSys构造函数有压栈待会需要把压栈数据也拷贝过来
uint top = SRAM_BASE + (ramSize << 10);
uint size = (uint)&__initial_sp - (uint)p;
uint msp = top - size;
// 拷贝一部分栈内容到新栈
memset((void*)msp, 0, size);
memcpy((void*)msp, (void*)p, size);
// 必须先拷贝完成栈,再修改栈指针
__set_MSP(msp); // 左移10位就是乘以1024
// 这个时候还没有初始化堆我们来设置堆到内存最大值让堆栈共用RAM剩下全部
//__microlib_freelist
p = &__heap_base + 1;
if(!__microlib_freelist_initialised)
{
//*(uint*)&__heap_limit = top;
// 堆顶地址__heap_limit被编译固化到malloc函数附近无法修改。只能这里负责初始化整个堆
__microlib_freelist = (uint)p; // 空闲链表指针
// 设置堆大小,直达天花板
*p = (top - (uint)p) & 0xFFFFFFF8; // 空闲链表剩余大小
*(p + 1) = 0;
__microlib_freelist_initialised = 1;
}
else
{
//// 如果已经初始化堆,则直接增加大小即可
//*p += (top - (uint)&__heap_limit) & 0xFFFFFFF8; // 空闲链表剩余大小
// 需要找到最后一个空闲节点,然后把大小加上去
uint* p = (uint*)__microlib_freelist;
// 每一个节点由4字节大小以及4字节下一节点的指针组成
while(*(p + 1)) p = (uint*)*(p + 1);
// 给最后一个空闲节点增加大小
*p += (top - (uint)p) & 0xFFFFFFF8; // 空闲链表剩余大小
}
}
bool TSys::CheckMemory()
{
#if DEBUG
uint msp = __get_MSP();
//if(__microlib_freelist >= msp) return false;
assert_param2(__microlib_freelist + 0x40 < msp, "堆栈相互穿透,内存已用完!可能是堆分配或野指针带来了内存泄漏!");
// 如果堆只剩下64字节则报告失败要求用户扩大堆空间以免不测
//uint end = SRAM_BASE + (RAMSize << 10);
//if(__microlib_freelist + 0x40 >= end) return false;
assert_param2(__microlib_freelist + 0x40 < SRAM_BASE + (RAMSize << 10), "堆栈相互穿透,内存已用完!一定是堆分配带来了内存泄漏!");
#endif
return true;
}
// 获取JTAG编号ST是0x041GD是0x7A3
uint16_t Get_JTAG_ID()
{
if( *( uint8_t *)( 0xE00FFFE8 ) & 0x08 )
{
return ((*(uint8_t *)(0xE00FFFD0) & 0x0F ) << 8 ) |
((*(uint8_t *)(0xE00FFFE4) & 0xFF ) >> 3 ) |
((*(uint8_t *)(0xE00FFFE8) & 0x07 ) << 5 ) + 1 ;
}
return 0;
}
bool SysError(uint code)
{
debug_printf("系统错误0x%02x\r\n", code);
#if DEBUG
ShowFault(code);
SerialPort* sp = SerialPort::GetMessagePort();
if(sp) sp->Flush();
#endif
return true;
}
void SysStop()
{
debug_printf("系统停止!\r\n");
while(true);
}
TSys::TSys()
{
Inited = false;
Started = false;
#ifdef STM32F0
Clock = 48000000;
#elif defined(STM32F1)
Clock = 72000000;
#elif defined(STM32F4)
Clock = 168000000;
#endif
//CystalClock = 8000000; // 晶振时钟
CystalClock = HSE_VALUE; // 晶振时钟
MessagePort = COM1; // COM1;
IsGD = Get_JTAG_ID() == 0x7A3;
#ifdef STM32F0
void* p = (void*)0x1FFFF7AC; // 手册里搜索UID优先英文手册
#elif defined(STM32F1)
void* p = (void*)0x1FFFF7E8;
#elif defined(STM32F4)
void* p = (void*)0x1FFF7A10;
#endif
memcpy(ID, p, ArrayLength(ID));
CPUID = SCB->CPUID;
uint mcuid = DBGMCU->IDCODE; // MCU编码。低字设备版本高字子版本
if(mcuid == 0 && IsGD) mcuid = *(uint*)0xE0042000; // 用GD32F103的位置
RevID = mcuid >> 16;
DevID = mcuid & 0x0FFF;
// GD32F103 默认使用120M
if(IsGD && (DevID == 0x0430 || DevID == 0x0414)) Clock = 120000000;
_Index = 0;
#ifndef TINY
#ifdef STM32F0
if(IsGD)
FlashSize = *(__IO ushort *)(0x1FFFF7E0); // 容量
else
FlashSize = *(__IO ushort *)(0x1FFFF7CC); // 容量。手册里搜索FLASH_SIZE优先英文手册
#elif defined(STM32F1)
FlashSize = *(__IO ushort *)(0x1FFFF7E0); // 容量
#elif defined(STM32F4)
FlashSize = *(__IO ushort *)(0x1FFF7A22); // 容量
#endif
if(FlashSize != 0xFFFF)
{
RAMSize = FlashSize >> 3; // 通过Flash大小和MCUID识别型号后得知内存大小
for(int i=0; i<ArrayLength(MemSizes); i++)
{
if(MemSizes[i] == Sys.FlashSize)
{
_Index = i;
break;
}
}
RAMSize = RamSizes[_Index];
}
InitHeapStack(RAMSize);
#endif
StartTime = 0;
OnTick = NULL;
OnSleep = NULL;
#if DEBUG
OnError = SysError;
OnStop = SysStop;
#else
OnError = 0;
OnStop = 0;
#endif
#ifdef STM32F10X
// 关闭JTAG仿真接口只打开SW仿真。
RCC->APB2ENR |= RCC_APB2ENR_AFIOEN; // 打开时钟
AFIO->MAPR |= AFIO_MAPR_SWJ_CFG_JTAGDISABLE; //关闭JTAG仿真接口只打开SW仿真。
#endif
Code = 0x0000;
Version = 0x0300;
#ifndef TINY
Name = "SmartOS";
Company = "NewLife_Embedded_Team";
BuildTime = "yyyy-MM-dd HH:mm:ss";
Interrupt.Init();
#endif
OnStart = NULL;
}
/*TSys::~TSys()
{
if(OnStop) OnStop();
}*/
void ShowTime(void* param)
{
debug_printf("\r");
Time.Now().Show();
debug_printf(" ");
}
void TSys::InitClock()
{
// 获取当前频率
uint clock = RCC_GetSysClock();
// 如果当前频率不等于配置,则重新配置时钟
if(Clock != clock || CystalClock != HSE_VALUE)
{
SetSysClock(Clock, CystalClock);
#ifdef STM32F4
HSE_VALUE = CystalClock;
#endif
Clock = RCC_GetSysClock();
SystemCoreClock = Clock;
}
Inited = true;
}
void TSys::Init(void)
{
InitClock();
// 必须在系统主频率确定以后再初始化时钟
Time.Init();
}
#if DEBUG
typedef struct
{
byte Revision:4; // The p value in the Rnpn product revision identifier, indicates patch release.0x0: patch 0
ushort PartNo:12; // Part number of the processor. 0xC20: Cortex-M0
byte Constant:4; // Constant that defines the architecture of the processor. 0xC: ARMv6-M architecture
byte Variant:4; // Variant number: The r value in the Rnpn product revision identifier. 0x0: revision 0
byte Implementer; // Implementer code. 0x41 ARM
}ST_CPUID;
#endif
void TSys::ShowInfo()
{
#if DEBUG
// 刚刚初始化完成的时间
ulong initedTime = Time.Current();
byte* ver = (byte*)&Version;
debug_printf("%s::%s Code:%04X ", Company, Name, Code);
debug_printf("Ver:%x.%x Build:%s\r\n", *ver++, *ver++, BuildTime);
debug_printf("SmartOS::");
if(IsGD)
debug_printf("GD32");
else
debug_printf("STM32");
ST_CPUID* cpu = (ST_CPUID*)&CPUID;
if(DevID > 0)
{
if(DevID == 0x410)
{
if(IsGD && RevID == 0x1303)
{
if(Clock == 48000000)
debug_printf("F130");
else
debug_printf("F150");
}
#ifdef STM32F1
else
debug_printf("F103");
#endif
}
#ifdef STM32F1
else if(DevID == 0x412 || DevID == 0x414 || DevID == 0x430)
debug_printf("F103");
else if(DevID == 0x418)
debug_printf("F107");
else if(DevID == 0x412)
debug_printf("F130");
#endif
#ifdef STM32F4
else if(DevID == 0x413)
debug_printf("F407");
#endif
else if(DevID == 0x440 || DevID == 0x444) // F030x4/F030x6=0x444 F030x8=0x440
debug_printf("F030/F051");
else
debug_printf("F%03x", DevID);
}
else if(CPUID > 0)
{
if(Clock == 48000000)
debug_printf("F130/F150");
#ifdef STM32F1
else
debug_printf("F103");
#endif
}
// 暂时不知道怎么计算引脚一般F4/F6/C8CB/RB/VC/VE
if(_Index < 2)
debug_printf("F");
else if(_Index < 4)
debug_printf("C");
else if(_Index < 6)
debug_printf("R");
else
debug_printf("V");
debug_printf("%c", MemNames[_Index]);
//debug_printf("\r\n");
// 系统信息
//debug_printf(" %dMHz Flash:%dk RAM:%dk\r\n", Clock/1000000, FlashSize, RAMSize);
// 获取当前频率
debug_printf(" %dMHz Flash:%dk RAM:%dk\r\n", RCC_GetSysClock()/1000000, FlashSize, RAMSize);
//debug_printf("\r\n");
debug_printf("DevID:0x%04X RevID:0x%04X \r\n", DevID, RevID);
debug_printf("CPUID:0x%08X", CPUID);
if(cpu->Implementer == 0x41) debug_printf(" ARM:");
if(cpu->Constant == 0x0C)
debug_printf(" ARMv6-M");
else if(cpu->Constant == 0x0F)
debug_printf(" ARMv7-M");
if((cpu->PartNo & 0x0FF0) == 0x0C20) debug_printf(" Cortex-M%d:", cpu->PartNo & 0x0F);
debug_printf(" R%dp%d", cpu->Revision, cpu->Variant);
debug_printf("\r\n");
debug_printf("ChipID:");
ShowHex(ID, ArrayLength(ID), '-');
debug_printf("\t");
ShowString(ID, 12, false);
debug_printf("\r\n");
// 输出堆信息
uint start = (uint)&__heap_base;
// F4有64k的CCM内存
#if defined(STM32F4)
if(start < 0x20000000) start = 0x20000000;
#endif
uint end = SRAM_BASE + (RAMSize << 10);
debug_printf("Heap :(0x%08x, 0x%08x) = 0x%x (%dk)\r\n", start, end, end - start, (end - start) / 1024);
start = (uint)&__heap_limit;
#if defined(STM32F4)
if(start < 0x20000000) start = 0x20000000;
#endif
//end = 0x20000000 + (RAMSize << 10);
debug_printf("Stack:(0x%08x, 0x%08x) = 0x%x (%dk)\r\n", start, end, end - start, (end - start) / 1024);
debug_printf("Time : ");
Time.Now().Show(true);
// 系统启动时间
debug_printf("Start: %dus (Inited: %dus)\r\n", (uint)(Time.Current() - StartTime), (uint)(initedTime - StartTime));
debug_printf("技术支持: http://www.NewLifeX.com\r\n");
debug_printf("\r\n");
#endif
}
#define __CRC__MODULE__ 1
#ifdef __CRC__MODULE__
//
// CRC 32 table for use under ZModem protocol, IEEE 802
// G(x) = x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1
//
static const uint c_CRCTable[ 256 ] =
{
0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9, 0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005,
0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61, 0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD,
0x4C11DB70, 0x48D0C6C7, 0x4593E01E, 0x4152FDA9, 0x5F15ADAC, 0x5BD4B01B, 0x569796C2, 0x52568B75,
0x6A1936C8, 0x6ED82B7F, 0x639B0DA6, 0x675A1011, 0x791D4014, 0x7DDC5DA3, 0x709F7B7A, 0x745E66CD,
0x9823B6E0, 0x9CE2AB57, 0x91A18D8E, 0x95609039, 0x8B27C03C, 0x8FE6DD8B, 0x82A5FB52, 0x8664E6E5,
0xBE2B5B58, 0xBAEA46EF, 0xB7A96036, 0xB3687D81, 0xAD2F2D84, 0xA9EE3033, 0xA4AD16EA, 0xA06C0B5D,
0xD4326D90, 0xD0F37027, 0xDDB056FE, 0xD9714B49, 0xC7361B4C, 0xC3F706FB, 0xCEB42022, 0xCA753D95,
0xF23A8028, 0xF6FB9D9F, 0xFBB8BB46, 0xFF79A6F1, 0xE13EF6F4, 0xE5FFEB43, 0xE8BCCD9A, 0xEC7DD02D,
0x34867077, 0x30476DC0, 0x3D044B19, 0x39C556AE, 0x278206AB, 0x23431B1C, 0x2E003DC5, 0x2AC12072,
0x128E9DCF, 0x164F8078, 0x1B0CA6A1, 0x1FCDBB16, 0x018AEB13, 0x054BF6A4, 0x0808D07D, 0x0CC9CDCA,
0x7897AB07, 0x7C56B6B0, 0x71159069, 0x75D48DDE, 0x6B93DDDB, 0x6F52C06C, 0x6211E6B5, 0x66D0FB02,
0x5E9F46BF, 0x5A5E5B08, 0x571D7DD1, 0x53DC6066, 0x4D9B3063, 0x495A2DD4, 0x44190B0D, 0x40D816BA,
0xACA5C697, 0xA864DB20, 0xA527FDF9, 0xA1E6E04E, 0xBFA1B04B, 0xBB60ADFC, 0xB6238B25, 0xB2E29692,
0x8AAD2B2F, 0x8E6C3698, 0x832F1041, 0x87EE0DF6, 0x99A95DF3, 0x9D684044, 0x902B669D, 0x94EA7B2A,
0xE0B41DE7, 0xE4750050, 0xE9362689, 0xEDF73B3E, 0xF3B06B3B, 0xF771768C, 0xFA325055, 0xFEF34DE2,
0xC6BCF05F, 0xC27DEDE8, 0xCF3ECB31, 0xCBFFD686, 0xD5B88683, 0xD1799B34, 0xDC3ABDED, 0xD8FBA05A,
0x690CE0EE, 0x6DCDFD59, 0x608EDB80, 0x644FC637, 0x7A089632, 0x7EC98B85, 0x738AAD5C, 0x774BB0EB,
0x4F040D56, 0x4BC510E1, 0x46863638, 0x42472B8F, 0x5C007B8A, 0x58C1663D, 0x558240E4, 0x51435D53,
0x251D3B9E, 0x21DC2629, 0x2C9F00F0, 0x285E1D47, 0x36194D42, 0x32D850F5, 0x3F9B762C, 0x3B5A6B9B,
0x0315D626, 0x07D4CB91, 0x0A97ED48, 0x0E56F0FF, 0x1011A0FA, 0x14D0BD4D, 0x19939B94, 0x1D528623,
0xF12F560E, 0xF5EE4BB9, 0xF8AD6D60, 0xFC6C70D7, 0xE22B20D2, 0xE6EA3D65, 0xEBA91BBC, 0xEF68060B,
0xD727BBB6, 0xD3E6A601, 0xDEA580D8, 0xDA649D6F, 0xC423CD6A, 0xC0E2D0DD, 0xCDA1F604, 0xC960EBB3,
0xBD3E8D7E, 0xB9FF90C9, 0xB4BCB610, 0xB07DABA7, 0xAE3AFBA2, 0xAAFBE615, 0xA7B8C0CC, 0xA379DD7B,
0x9B3660C6, 0x9FF77D71, 0x92B45BA8, 0x9675461F, 0x8832161A, 0x8CF30BAD, 0x81B02D74, 0x857130C3,
0x5D8A9099, 0x594B8D2E, 0x5408ABF7, 0x50C9B640, 0x4E8EE645, 0x4A4FFBF2, 0x470CDD2B, 0x43CDC09C,
0x7B827D21, 0x7F436096, 0x7200464F, 0x76C15BF8, 0x68860BFD, 0x6C47164A, 0x61043093, 0x65C52D24,
0x119B4BE9, 0x155A565E, 0x18197087, 0x1CD86D30, 0x029F3D35, 0x065E2082, 0x0B1D065B, 0x0FDC1BEC,
0x3793A651, 0x3352BBE6, 0x3E119D3F, 0x3AD08088, 0x2497D08D, 0x2056CD3A, 0x2D15EBE3, 0x29D4F654,
0xC5A92679, 0xC1683BCE, 0xCC2B1D17, 0xC8EA00A0, 0xD6AD50A5, 0xD26C4D12, 0xDF2F6BCB, 0xDBEE767C,
0xE3A1CBC1, 0xE760D676, 0xEA23F0AF, 0xEEE2ED18, 0xF0A5BD1D, 0xF464A0AA, 0xF9278673, 0xFDE69BC4,
0x89B8FD09, 0x8D79E0BE, 0x803AC667, 0x84FBDBD0, 0x9ABC8BD5, 0x9E7D9662, 0x933EB0BB, 0x97FFAD0C,
0xAFB010B1, 0xAB710D06, 0xA6322BDF, 0xA2F33668, 0xBCB4666D, 0xB8757BDA, 0xB5365D03, 0xB1F740B4
};
uint TSys::Crc(const void* buf, uint len, uint crc)
{
byte* ptr = (byte*)buf;
while(len-- > 0)
{
crc = c_CRCTable[ ((crc >> 24) ^ (*ptr++)) & 0xFF ] ^ (crc << 8);
}
return crc;
}
// 硬件实现的Crc
/*uint TSys::Crc(const void* buf, uint len)
{
#ifdef STM32F4
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_CRC, ENABLE);
#else
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_CRC, ENABLE);
#endif
CRC_ResetDR();
// STM32的初值是0xFFFFFFFF而软Crc初值是0。必须设置初值否则结果不一样。
uint crc = 0;
CRC->DR = __REV(crc ^ 0xFFFFFFFF);
//CRC->DR = 0xFFFFFFFF;
uint* ptr = (uint*)buf;
len >>= 2;
while(len-- > 0)
{
CRC->DR =__REV(*ptr++); // 字节顺序倒过来,注意不是位序,不是用__RBIT指令
}
crc = CRC->DR;
#ifdef STM32F4
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_CRC, DISABLE);
#else
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_CRC, DISABLE);
#endif
return crc;
}*/
static const ushort c_CRC16Table[] =
{
0x0000, 0xCC01, 0xD801, 0x1400, 0xF001, 0x3C00, 0x2800, 0xE401,
0xA001, 0x6C00, 0x7800, 0xB401, 0x5000, 0x9C01, 0x8801, 0x4400,
};
ushort TSys::Crc16(const void* buf, uint len, ushort crc)
{
if (!buf || !len) return 0;
for (int i = 0; i < len; i++)
{
byte b = ((byte*)buf)[i];
crc = (ushort)(c_CRC16Table[(b ^ crc) & 0x0F] ^ (crc >> 4));
crc = (ushort)(c_CRC16Table[((b >> 4) ^ crc) & 0x0F] ^ (crc >> 4));
}
return crc;
}
#endif
#define __HELP__MODULE__ 1
#ifdef __HELP__MODULE__
// 显示十六进制数据,指定分隔字符
void TSys::ShowHex(byte* buf, uint len, char sep)
{
for(int i=0; i < len; i++)
{
debug_printf("%02X", *buf++);
if(i < len - 1 && sep != '\0') debug_printf("%c", sep);
//if(((i + 1) & 0xF) == 0) debug_printf("\r\n");
}
//debug_printf("\r\n");
}
// 显示字符串,不指定长度时自动找\0
void TSys::ShowString(byte* buf, uint len, bool autoEnd)
{
if(len == 0) len = 1000;
for(int i=0; i<len; i++)
{
if(buf[i] == 0 && autoEnd) return;
if(buf[i] >= 32 && buf[i] <= 126 || buf[i] == 0x0A || buf[i] == 0x0D || buf[i] == 0x09)
debug_printf("%c", buf[i]);
else
debug_printf("%02X", buf[i]);
}
}
// 源数据src转为十六进制字符编码再放入目标字符buf比如0xA8在目标放两个字节0x41(A) 0x38(8)
void TSys::ToHex(byte* buf, byte* src, uint len)
{
for(int i=0; i < len; i++, src++)
{
byte n = *src >> 4;
if(n < 10)
n += '0';
else
n += 'A' - 10;
*buf++ = n;
n = *src & 0x0F;
if(n < 10)
n += '0';
else
n += 'A' - 10;
*buf++ = n;
}
}
#endif
#define __TASK__MODULE__ 1
#ifdef __TASK__MODULE__
// 任务
#include "Task.h"
// 创建任务返回任务编号。priority优先级dueTime首次调度时间usperiod调度间隔us-1表示仅处理一次
uint TSys::AddTask(Action func, void* param, Int64 dueTime, Int64 period, string name)
{
return Task::Scheduler()->Add(func, param, dueTime, period, name);
}
void TSys::RemoveTask(uint& taskid)
{
if(taskid) Task::Scheduler()->Remove(taskid);
taskid = 0;
}
bool TSys::SetTask(uint taskid, bool enable, int usNextTime)
{
if(!taskid) return false;
Task* task = Task::Get(taskid);
if(!task) return false;
task->Enable = enable;
// 可以安排最近一次执行的时间比如0表示马上调度执行
if(usNextTime >= 0) task->NextTime = Time.Current() + usNextTime;
// 如果系统调度器处于Sleep让它立马退出
if(enable) Task::Scheduler()->Sleeping = false;
return true;
}
// 改变任务周期
bool TSys::SetTaskPeriod(uint taskid, Int64 period)
{
if(!taskid) return false;
Task* task = Task::Get(taskid);
if(!task) return false;
task->Period = period;
return true;
}
void TSys::Start()
{
#if DEBUG
//AddTask(ShowTime, NULL, 2000000, 2000000);
#endif
Started = true;
if(OnStart)
{
// 设置重载值让其每1ms重载一次
Time.SetMax(1000);
OnStart();
}
else
Task::Scheduler()->Start();
}
void TimeSleep(uint us)
{
// 在这段时间里面,去处理一下别的任务
if(Sys.Started && (!us || us >= 1000))
{
TaskScheduler* sc = Task::Scheduler();
// 记录当前正在执行任务
Task* task = sc->Current;
TimeCost tc;
// 实际可用时间。100us一般不够调度新任务留给硬件等待
int total = us - 100;
// 如果休眠时间足够长,允许多次调度其它任务
while(true)
{
// 统计这次调度的时间,累加作为当前任务的休眠时间
TimeCost tc2;
sc->Execute(total);
total -= tc2.Elapsed();
if(total <= 0) break;
}
int cost = tc.Elapsed();
if(task)
{
sc->Current = task;
task->SleepTime += cost;
}
if(cost >= us) return;
us -= cost;
}
if(us) Time.Sleep(us);
}
void TSys::Sleep(uint ms)
{
// 优先使用线程级睡眠
if(OnSleep)
OnSleep(ms);
else
{
#if DEBUG
if(ms > 1000) debug_printf("Sys::Sleep 设计错误,睡眠%dms太长超过1000ms建议使用多线程Thread", ms);
#endif
TimeSleep(ms * 1000);
}
}
void TSys::Delay(uint us)
{
// 如果延迟微秒数太大,则使用线程级睡眠
if(OnSleep && us >= 2000)
OnSleep((us + 500) / 1000);
else
{
#if DEBUG
if(us > 1000000) debug_printf("Sys::Sleep 设计错误,睡眠%dus太长超过1000ms建议使用多线程Thread", us);
#endif
TimeSleep(us);
}
}
#endif