SmartOS/Kernel/Sys.cpp

318 lines
6.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 "Kernel\Sys.h"
#include "Interrupt.h"
#include "TTime.h"
TSys Sys;
const TTime Time;
// 系统配置
const SystemConfig g_Config = {
//SystemConfig g_Config = {
// 操作系统 v3.2.x
(0x03020000 | __BUILD_DATE__),
"SmartOS_CPU",
// 硬件
(0x0 | __BUILD_DATE__),
// 应用软件
(0x0 | __BUILD_DATE__),
(0x0 | __BUILD_DATE__),
__BUILD_USER__,
__BUILD_SDATE__,
};
#if defined(BOOT) || defined(APP)
struct HandlerRemap StrBoot __attribute__((at(0x2000fff0)));
#endif
// 关键性代码,放到开头
INROOT TSys::TSys()
{
auto& cfg = g_Config;
Config = &g_Config;
OnInit();
OnSleep = nullptr;
Code = cfg.Code;
Ver = cfg.Ver;
HardVer = cfg.HardVer;
AppVer = cfg.AppVer;
#ifndef TINY
Name = cfg.Name;
Company = cfg.Company;
Product = cfg.Product;
Interrupt.Init();
#endif
StartTimes = 1;
HotStart = 1;
Started = false;
}
void TSys::Init(void)
{
InitClock();
// 必须在系统主频率确定以后再初始化时钟
((TTime&)Time).Init();
}
void TSys::ShowInfo() const
{
#if DEBUG
debug_printf("%s::%s Code:%04X %s \r\n", Company, Name, Code, Product);
debug_printf("Build:%s %s\r\n", __BUILD_USER__, __BUILD_STIME__);
Version v1(AppVer);
Version v2(HardVer);
Version v3(Ver);
debug_printf("AppVer:%s HardVer:%s CoreVer:%s\r\n", v1.ToString().GetBuffer(), v2.ToString().GetBuffer(), v3.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(false);
debug_printf(" Start: %d/%d \r\n", HotStart, StartTimes);
//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;
}
// 关键性代码,放到开头
INROOT 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;
}
// 改变任务周期
INROOT 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;
Task::Scheduler()->Start();
}
// 延迟异步重启
void TSys::Reboot(int msDelay) const
{
if (msDelay <= 0)Reset();
auto func = &TSys::Reset;
AddTask(*(Action*)&func, (void*)this, msDelay, -1, "延迟重启");
}
// 系统启动后的毫秒数
INROOT UInt64 TSys::Ms() const { return Time.Current(); }
// 系统绝对当前时间,秒
INROOT uint TSys::Seconds() const { return Time.Seconds + Time.BaseSeconds; }
INROOT void TSys::Sleep(int ms) const
{
// 优先使用线程级睡眠
if(OnSleep)
OnSleep(ms);
else
{
#if DEBUG
if(ms > 1000) debug_printf("Sys::Sleep 设计错误,睡眠%dms太长", ms);
#endif
// 在这段时间里面,去处理一下别的任务
if(Sys.Started && ms != 0)
{
bool cancel = false;
int ct = Task::Scheduler()->ExecuteForWait(ms, cancel);
if(ct >= ms) return;
ms -= ct;
}
if(ms) Time.Sleep(ms);
}
}
INROOT void TSys::Delay(int us) const
{
// 如果延迟微秒数太大,则使用线程级睡眠
if(OnSleep && us >= 2000)
OnSleep((us + 500) / 1000);
else
{
#if DEBUG
if(us > 1000000) debug_printf("Sys::Sleep 设计错误,睡眠%dus太长", us);
#endif
// 在这段时间里面,去处理一下别的任务
if(Sys.Started && us != 0 && us >= 1000)
{
bool cancel = false;
int ct = Task::Scheduler()->ExecuteForWait(us / 1000, cancel);
ct *= 1000;
if(ct >= us) return;
us -= ct;
}
if(us) Time.Delay(us);
}
}
#endif
/****************系统日志****************/
#include <stdarg.h>
// 打印日志
extern int SmartOS_Log(const String& msg);
extern "C"
{
// 是否新行结尾
static bool newline = false;
WEAK int SmartOS_printf(const char* format, ...)
{
if(Sys.Clock == 0 || Sys.MessagePort == COM_NONE) return 0;
char cs[512];
int tab = 0;
// 先根据子任务打印缩进级别
if(Sys.Started)
{
int deepth = Task::Scheduler()->Deepth - 1;
if(newline && deepth > 0 && (format[0] != '\0' || format[1] != '\0' || format[2] != '\0'))
{
String fm = format;
if(fm.Length() == 1)
{
tab = 0;
}
for(int i=0; i<deepth; i++)
cs[tab++] = '\t';
tab += snprintf(&cs[tab], sizeof(cs) - tab, "%d=>", Task::Current().ID);
}
}
va_list ap;
va_start(ap, format);
int rs = vsnprintf(&cs[tab], sizeof(cs) - tab, format, ap);
va_end(ap);
// 如果格式化得到为空,则不做输出
if(rs == 0) return rs;
newline = cs[tab + rs - 1] == '\r' || cs[tab + rs - 1] == '\n';
// 必须转为cstring否则会当作缓冲区并把最后一个字符清零。当作缓冲区长度加一也可以
rs += SmartOS_Log(String((cstring)cs, tab + rs));
return rs;
}
#ifndef _MSC_VER
/* 重载fputc可以让用户程序使用printf函数 */
int fputc(int ch, FILE *f)
{
#if DEBUG
if(Sys.Clock == 0) return ch;
int idx = Sys.MessagePort;
if(idx == COM_NONE) return ch;
byte b = ch;
SmartOS_Log(String((cstring)&b, 1));
#endif
return ch;
}
#endif
}
/****************系统跟踪****************/
//#if DEBUG
#include "Device\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
}