SmartOS/Kernel/Sys.cpp

286 lines
5.6 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 "WatchDog.h"
//#include "Platform\stm32.h"
TSys Sys;
const TTime Time;
#if defined(BOOT) || defined(APP)
//#pragma location = 0x20000000
struct HandlerRemap StrBoot __attribute__((at(0x2000fff0)));
#endif
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
#if !defined(TINY) && defined(STM32F0)
#pragma arm section code = "SectionForSys"
#endif
TSys::TSys()
{
OnInit();
OnSleep = nullptr;
Code = 0x0000;
Ver = 0x0300;
#ifndef TINY
Name = "SmartOS";
Company = "NewLife_Embedded_Team";
//BuildTime = "yyyy-MM-dd HH:mm:ss";
Interrupt.Init();
#endif
Started = false;
}
#pragma arm section code
void ShowTime(void* param)
{
debug_printf("\r");
DateTime::Now().Show();
debug_printf(" ");
}
void TSys::Init(void)
{
InitClock();
// 必须在系统主频率确定以后再初始化时钟
((TTime&)Time).Init();
}
void TSys::ShowInfo() const
{
#if DEBUG
//byte* ver = (byte*)&Version;
debug_printf("%s::%s Code:%04X ", Company.GetBuffer(), Name.GetBuffer(), Code);
//debug_printf("Ver:%x.%x Build:%s\r\n", *ver++, *ver++, BuildTime);
debug_printf("Ver:%s Build:%s\r\n", Ver.ToString().GetBuffer(), Ver.Compile().ToString().GetBuffer());
OnShowInfo();
debug_printf("ChipID:");
ByteArray(ID, ArrayLength(ID)).Show();
// 新的字符串这样用会导致第一个字符被清零
//debug_printf("\t %s", ID);
String str;
str.Copy(0, ID, 12);
str.Show(true);
debug_printf("Time : ");
DateTime::Now().Show(true);
debug_printf("Support: http://www.WsLink.cn\r\n");
debug_printf("\r\n");
#endif
}
#define __TASK__MODULE__ 1
#ifdef __TASK__MODULE__
// 任务
#include "Task.h"
// 创建任务返回任务编号。dueTime首次调度时间msperiod调度间隔ms-1表示仅处理一次
uint TSys::AddTask(Action func, void* param, int dueTime, int period, cstring name) const
{
return Task::Scheduler()->Add(func, param, dueTime, period, name);
}
void TSys::RemoveTask(uint& taskid) const
{
if(taskid) Task::Scheduler()->Remove(taskid);
taskid = 0;
}
#if !defined(TINY) && defined(STM32F0) && defined(DEBUG)
#pragma arm section code = "SectionForSys"
#endif
bool TSys::SetTask(uint taskid, bool enable, int msNextTime) const
{
if(!taskid) return false;
auto task = Task::Get(taskid);
if(!task) return false;
task->Set(enable, msNextTime);
return true;
}
// 改变任务周期
bool TSys::SetTaskPeriod(uint taskid, int period) const
{
if(!taskid) return false;
auto task = Task::Get(taskid);
if(!task) return false;
if(period)
{
task->Period = period;
// 改变任务周期的同时重新计算下一次调度时间NextTime让它立马生效
// 否则有可能系统按照上一次计算好的NextTime再调度一次任务
task->NextTime = Ms() + period;
}
else
task->Enable = false;
return true;
}
void TSys::Start()
{
OnStart();
Started = true;
#if DEBUG
//AddTask(ShowTime, nullptr, 2000000, 2000000);
#endif
Task::Scheduler()->Start();
}
void TimeSleep(uint us)
{
TS("Sys::TimeSleep");
// 在这段时间里面,去处理一下别的任务
if(Sys.Started && us != 0 && us >= 50)
{
auto sc = Task::Scheduler();
// 记录当前正在执行任务
auto task = sc->Current;
TimeCost tc;
// 实际可用时间。100us一般不够调度新任务留给硬件等待
int total = us;
/*int ts = sc->Times;
int tid = 0;
int tms = 0;
if(task)
{
tid = task->ID;
tms = task->Times;
}
debug_printf("Sys::Sleep=> taskid=%d/%d us=%d \r\n", tid, tms, us);*/
// 如果休眠时间足够长,允许多次调度其它任务
while(true)
{
// 统计这次调度的时间,累加作为当前任务的休眠时间
TimeCost tc2;
sc->Execute(total / 1000);
total -= tc2.Elapsed();
if(total <= 0) break;
}
int ct = tc.Elapsed();
//debug_printf("Sys::Sleep<= taskid=%d/%d us=%d total=%d ct=%d Times=%d \r\n", tid, tms, us, total, ct, sc->Times - ts);
if(task)
{
sc->Current = task;
task->SleepTime += ct;
}
if(ct >= us) return;
us -= ct;
}
if(us) Time.Delay(us);
}
// 系统启动后的毫秒数
UInt64 TSys::Ms() const { return Time.Current(); }
// 系统绝对当前时间,秒
uint TSys::Seconds() const { return Time.Seconds + Time.BaseSeconds; }
// 当前时间
DateTime DateTime::Now()
{
DateTime dt(Sys.Seconds());
dt.Ms = Sys.Ms();
return dt;
}
void TSys::Sleep(uint ms) const
{
// 优先使用线程级睡眠
if(OnSleep)
OnSleep(ms);
else
{
#if DEBUG
if(ms > 1000) debug_printf("Sys::Sleep 设计错误,睡眠%dms太长", ms);
#endif
TimeSleep(ms * 1000);
}
}
void TSys::Delay(uint us) const
{
// 如果延迟微秒数太大,则使用线程级睡眠
if(OnSleep && us >= 2000)
OnSleep((us + 500) / 1000);
else
{
#if DEBUG
if(us > 1000000) debug_printf("Sys::Sleep 设计错误,睡眠%dus太长", us);
#endif
if(us < 50)
Time.Delay(us);
else
TimeSleep(us);
}
}
#endif
#pragma arm section code
/****************系统跟踪****************/
//#if DEBUG
#include "Port.h"
static OutputPort* _trace = nullptr;
//#endif
void TSys::InitTrace(void* port) const
{
//#if DEBUG
_trace = (OutputPort*)port;
//#endif
}
void TSys::Trace(int times) const
{
//#if DEBUG
if(_trace)
{
while(times--) *_trace = !*_trace;
}
//#endif
}