初始化硬时钟.

    搜索 @note_pic 可查看绘制的全部字符图
    搜索 @note_why 是尚未看明白的地方,有看明白的,请Pull Request完善
    搜索 @note_thinking 是一些的思考和建议
    搜索 @note_#if0 是由第三方项目提供不在内核源码中定义的极为重要结构体,为方便理解而添加的。
    搜索 @note_good 是给源码点赞的地方
上级 f9551571
......@@ -8,7 +8,7 @@
[![star](https://gitee.com/weharmony/kernel_liteos_a_note/badge/star.svg?theme=dark)](https://gitee.com/weharmony/kernel_liteos_a_note)[![fork](https://gitee.com/weharmony/kernel_liteos_a_note/badge/fork.svg?theme=dark)](https://gitee.com/weharmony/kernel_liteos_a_note)
每个码农,学职生涯,都应精读一遍内核源码.精读内核源码最大的好处是:将孤立知识点织成一张高浓度,高密度底层网,是对计算机底层体系化理解形成永久记忆
每个码农,学职生涯,都应精读一遍内核源码.是浇筑计算机知识大厦的地基工程,地基纵深坚固程度,决定了大厦能盖多高。为何一定要精读?因为内核代码本身并不太多,都是浓缩的精华,精读就是让各个知识点高频出现,闪爆大脑,短时间内容易结成一张高浓度,高密度的底层网,形成永久大脑记忆。跟骑单车一样,一旦学会,即便多年不骑,照样跨上就走,游刃有余。
## **做了些什么呢?**
......@@ -61,17 +61,15 @@
第二: **专业概念抽象级** 对抽象的专业逻辑概念具体化认知, 比如虚拟内存,老百姓是听不懂的,学过计算机的人都懂,具体怎么实现的很多人又都不懂了,但这并不妨碍成为一个优秀的上层应用程序员,因为虚拟内存已经被抽象出来,目的是要屏蔽上层对它的现实认知.试图用 **[鸿蒙源码分析系列篇 【 CSDN](https://blog.csdn.net/kuangyufei/article/details/108727970) [| OSCHINA](https://my.oschina.net/u/3751245/blog/4626852) [| WIKI 】](https://gitee.com/weharmony/kernel_liteos_a_note/wikis/pages)** 去拆解那些已经被抽象出来的专业概念, 希望能卷入更多对内核感兴趣的应用软件人才流入基础软件生态, 应用软件咱们是无敌宇宙,但基础软件却很薄弱.
第三: **具体微观代码级** 这一级是具体到每一行代码的实现,到了用代码指令级的地步,这段代码是什么意思?为什么要这么设计? **[kernel\_liteos\_a_note:鸿蒙内核源码注释中文版](https://gitee.com/weharmony/kernel_liteos_a_note)** 试图从细微处去解释代码实现层,英文真的是天生适合设计成编程语言的人类语言,计算机的01码映射到人类世界的26个字母,诞生了太多的伟大奇迹.但我们的母语注定了很大部分人存在着自然语言层级的理解映射,希望注释中文版能让更多爱好者快速的理解内核,共同进步.
- ### **鸿蒙内核500问,你知道多少?**
抛出的500个内核知识问题,可前往 **[鸿蒙内核源码分析(源码结构篇) | 内核500问 【 CSDN ](https://blog.csdn.net/kuangyufei/article/details/111938348) [| OSCHINA 】](https://my.oschina.net/u/3751245/blog/4869137)** 查看.
- ### **系列博客更新到哪里了?**
把研究过程心得写成鸿蒙源码分析系列篇,如此源码中文注释+系列篇文章,将加速理解鸿蒙内核实现过程,因时间有限,博文更新较慢,会反复修正.
把研究过程心得写成鸿蒙源码分析系列篇,如此源码中文注释+系列篇文章,将加速理解鸿蒙内核实现过程.
- **[鸿蒙源码分析系列(总目录) | 持续更新中... 【 CSDN ](https://blog.csdn.net/kuangyufei/article/details/108727970) [| OSCHINA 】](https://my.oschina.net/u/3751245/blog/4626852)**
* **[|- 鸿蒙内核源码分析(位图管理篇) | 为何进程和线程都是32个优先级? 【 CSDN ](https://blog.csdn.net/kuangyufei/article/details/112394982) [| OSCHINA 】](https://my.oschina.net/u/3751245/blog/4888467)**
* **[|- 鸿蒙内核源码分析(源码结构篇) | 内核500问你能答对多少? 【 CSDN ](https://blog.csdn.net/kuangyufei/article/details/111938348) [| OSCHINA 】](https://my.oschina.net/u/3751245/blog/4869137)**
* **[|- 鸿蒙内核源码分析(物理内存篇) | 伙伴算法是在卖标准猪肉块吗?【 CSDN ](https://blog.csdn.net/kuangyufei/article/details/111765600) [| OSCHINA 】](https://my.oschina.net/u/3751245/blog/4842408)**
......@@ -117,12 +115,10 @@
2. [新建 Issue](https://gitee.com/weharmony/kernel_liteos_a_note/issues)
- ### **鸿蒙内核源码分析 官方公众号**
- ### **喜欢关注官方公众号**
![在这里插入图片描述](./zzz/pic/other/wxcode.png)
感谢关注,您的支持是注者最大的动力.
作者邮箱:weharmony@126.com
---
......
......@@ -125,7 +125,7 @@ LITE_OS_SEC_TEXT_INIT VOID OsTaskSchedQueueEnqueue(LosTaskCB *taskCB, UINT16 sta
LOS_ASSERT(!(taskCB->taskStatus & OS_TASK_STATUS_READY));// 只有非就绪状态任务才能入队
processCB = OS_PCB_FROM_PID(taskCB->processID);// 通过一个任务得到这个任务所在的进程
if (!(processCB->processStatus & OS_PROCESS_STATUS_READY)) {//task状态为就绪状态
if (!(processCB->processStatus & OS_PROCESS_STATUS_READY)) {//task状态没有就绪状态标签
if (((processCB->policy == LOS_SCHED_RR) && (processCB->timeSlice != 0)) ||//调度方式为抢断且时间片没用完
((processCB->processStatus & OS_PROCESS_STATUS_RUNNING) && (processCB->policy == LOS_SCHED_FIFO))) {//或处于运行的FIFO调度方式的task
OS_PROCESS_PRI_QUEUE_ENQUEUE_HEAD(processCB);//进程入g_priQueueList就绪队列头部
......@@ -139,7 +139,7 @@ LITE_OS_SEC_TEXT_INIT VOID OsTaskSchedQueueEnqueue(LosTaskCB *taskCB, UINT16 sta
LOS_ASSERT((UINTPTR)processCB->pendList.pstNext);
if ((processCB->timeSlice == 0) && (processCB->policy == LOS_SCHED_RR)) {//没有时间片且采用抢占式调度算法的情况
OS_PROCESS_PRI_QUEUE_DEQUEUE(processCB);//进程先出队列
OS_PROCESS_PRI_QUEUE_ENQUEUE(processCB);//进程再入队列,区别是排到了最后.这可是队列前面还有很多人等着被调度呢.
OS_PROCESS_PRI_QUEUE_ENQUEUE(processCB);//进程再入队列,区别是排到了最后.队列前面还有很多进程在等着被调度.
}
}
......@@ -362,29 +362,29 @@ STATIC VOID OsWaitCheckAndWakeParentProcess(LosProcessCB *parentCB, const LosPro
return;
}
//回收指定进程的资源
LITE_OS_SEC_TEXT VOID OsProcessResourcesToFree(LosProcessCB *processCB)
{
if (!(processCB->processStatus & (OS_PROCESS_STATUS_INIT | OS_PROCESS_STATUS_RUNNING))) {
PRINT_ERR("The process(%d) has no permission to release process(%d) resources!\n",
if (!(processCB->processStatus & (OS_PROCESS_STATUS_INIT | OS_PROCESS_STATUS_RUNNING))) {//1.初始化阶段并没有使用到资源,所以不用回收
PRINT_ERR("The process(%d) has no permission to release process(%d) resources!\n",//2.正在运行的进程不能回收
OsCurrProcessGet()->processID, processCB->processID);
}
#ifdef LOSCFG_FS_VFS
if (OsProcessIsUserMode(processCB)) {//用户模式下
delete_files(processCB, processCB->files);//删除文件
if (OsProcessIsUserMode(processCB)) {//用户进程
delete_files(processCB, processCB->files);//删除与用户进程相关的文件
}
processCB->files = NULL;
#endif
#ifdef LOSCFG_SECURITY_CAPABILITY
#ifdef LOSCFG_SECURITY_CAPABILITY //安全开关
if (processCB->user != NULL) {
(VOID)LOS_MemFree(m_aucSysMem1, processCB->user);
(VOID)LOS_MemFree(m_aucSysMem1, processCB->user);//删除用户
processCB->user = NULL;
}
#endif
OsSwtmrRecycle(processCB->processID);//软件定时器回收
OsSwtmrRecycle(processCB->processID);//回收进程使用的定时器
processCB->timerID = (timer_t)(UINTPTR)MAX_INVALID_TIMER_VID;
#ifdef LOSCFG_SECURITY_VID
......@@ -395,13 +395,13 @@ LITE_OS_SEC_TEXT VOID OsProcessResourcesToFree(LosProcessCB *processCB)
#endif
#if (LOSCFG_KERNEL_LITEIPC == YES)
if (OsProcessIsUserMode(processCB)) {//用户模式下
LiteIpcPoolDelete(&(processCB->ipcInfo));//删除进程IPC
if (OsProcessIsUserMode(processCB)) {//用户进程
LiteIpcPoolDelete(&(processCB->ipcInfo));//删除进程对lite IPC的开销
(VOID)memset_s(&(processCB->ipcInfo), sizeof(ProcIpcInfo), 0, sizeof(ProcIpcInfo));
}
#endif
}
//回收僵死状态进程流程
//回收僵死状态进程的资源
LITE_OS_SEC_TEXT STATIC VOID OsRecycleZombiesProcess(LosProcessCB *childCB, ProcessGroup **group)
{
OsExitProcessGroup(childCB, group);//退出进程组
......@@ -420,7 +420,7 @@ LITE_OS_SEC_TEXT STATIC VOID OsRecycleZombiesProcess(LosProcessCB *childCB, Proc
OsInsertPCBToFreeList(childCB);//直接插到freeList中去,可用于重新分配了。
}
}
//当一个进程自然退出的时候,它的孩子进程要怎么处理
STATIC VOID OsDealAliveChildProcess(LosProcessCB *processCB)
{
UINT32 parentID;
......@@ -429,13 +429,13 @@ STATIC VOID OsDealAliveChildProcess(LosProcessCB *processCB)
LOS_DL_LIST *nextList = NULL;
LOS_DL_LIST *childHead = NULL;
if (!LOS_ListEmpty(&processCB->childrenList)) {
if (!LOS_ListEmpty(&processCB->childrenList)) {//如果存在孩子进程
childHead = processCB->childrenList.pstNext;
LOS_ListDelete(&(processCB->childrenList));
if (OsProcessIsUserMode(processCB)) {
parentID = g_userInitProcess;
if (OsProcessIsUserMode(processCB)) {//是用户模式吗?
parentID = g_userInitProcess;//指定1号进程父ID
} else {
parentID = g_kernelInitProcess;
parentID = g_kernelInitProcess;//指定2号进程为父ID
}
for (nextList = childHead; ;) {
......@@ -474,9 +474,9 @@ STATIC VOID OsProcessNaturalExit(LosTaskCB *runTask, UINT32 status)
LOS_ASSERT(!(processCB->threadScheduleMap != 0));//断言没有任务需要调度了,当前task是最后一个了
LOS_ASSERT(processCB->processStatus & OS_PROCESS_STATUS_RUNNING);//断言必须为正在运行的进程
OsChildProcessResourcesFree(processCB);//
OsChildProcessResourcesFree(processCB);//释放孩子进程的资源
#ifdef LOSCFG_KERNEL_CPUP
#ifdef LOSCFG_KERNEL_CPUP
OsCpupClean(processCB->processID);
#endif
......@@ -495,7 +495,7 @@ STATIC VOID OsProcessNaturalExit(LosTaskCB *runTask, UINT32 status)
OsDealAliveChildProcess(processCB);
processCB->processStatus |= OS_PROCESS_STATUS_ZOMBIES;
processCB->processStatus |= OS_PROCESS_STATUS_ZOMBIES;//贴上僵死进程的标签
(VOID)OsKill(processCB->parentProcessID, SIGCHLD, OS_KERNEL_KILL_PERMISSION);
LOS_ListHeadInsert(&g_processRecyleList, &processCB->pendList);
......@@ -526,10 +526,10 @@ LITE_OS_SEC_TEXT_INIT UINT32 OsProcessInit(VOID)
for (index = 0; index < g_processMaxNum; index++) {//进程池循环创建
g_processCBArray[index].processID = index;//进程ID[0-g_processMaxNum]赋值
g_processCBArray[index].processStatus = OS_PROCESS_FLAG_UNUSED;// 默认都是白纸一张,臣妾干净着呢
g_processCBArray[index].processStatus = OS_PROCESS_FLAG_UNUSED;// 默认都是白纸一张,贴上未使用标签
LOS_ListTailInsert(&g_freeProcess, &g_processCBArray[index].pendList);//注意g_freeProcess挂的是pendList节点,所以使用要通过OS_PCB_FROM_PENDLIST找到进程实体.
}
// ????? 为啥用户模式的根进程 选1 ,内核模式的根进程选2
g_userInitProcess = 1; /* 1: The root process ID of the user-mode process is fixed at 1 *///用户模式的根进程
LOS_ListDelete(&g_processCBArray[g_userInitProcess].pendList);// 清空g_userInitProcess pend链表
......
......@@ -47,16 +47,16 @@ extern "C" {
#endif /* __cplusplus */
LITE_OS_SEC_BSS volatile UINT64 g_tickCount[LOSCFG_KERNEL_CORE_NUM] = {0};//tick计数器,系统一旦启动,一直在++, 为防止溢出,这是一个 UINT64 的变量
LITE_OS_SEC_DATA_INIT UINT32 g_sysClock;//系统时钟
LITE_OS_SEC_DATA_INIT UINT32 g_sysClock;//系统时钟,是绝大部分部件工作的时钟源,也是其他所有外设的时钟的来源
LITE_OS_SEC_DATA_INIT UINT32 g_tickPerSecond;//每秒Tick数,鸿蒙默认是每秒100次,即:10ms
LITE_OS_SEC_BSS DOUBLE g_cycle2NsScale;
LITE_OS_SEC_BSS DOUBLE g_cycle2NsScale; //周期转纳秒级
/* spinlock for task module */
LITE_OS_SEC_BSS SPIN_LOCK_INIT(g_tickSpin); //节拍器自旋锁
/*
* Description : Tick interruption handler
*///系统时钟中断处理函数 ,鸿蒙是 10ms触发一次
*///节拍中断处理函数 ,鸿蒙默认10ms触发一次
LITE_OS_SEC_TEXT VOID OsTickHandler(VOID)
{
UINT32 intSave;
......
......@@ -314,9 +314,9 @@ STATIC INLINE BOOL OsProcessIsDead(const LosProcessCB *processCB)//查下进程
#define OS_USER_TASK_SYSCALL_SATCK_SIZE 0x3000 //用户通过系统调用的栈大小 12K ,这时是运行在内核模式下
#define OS_USER_TASK_STACK_SIZE 0x100000 //用户任务运行在用户空间的栈大小 1M
#define OS_KERNEL_MODE 0x0U //内核模式
#define OS_USER_MODE 0x1U //用户模式
STATIC INLINE BOOL OsProcessIsUserMode(const LosProcessCB *processCB)//进程处于用户态?
#define OS_KERNEL_MODE 0x0U //内核模式
#define OS_USER_MODE 0x1U //用户模式
STATIC INLINE BOOL OsProcessIsUserMode(const LosProcessCB *processCB)//用户模式进程
{
return (processCB->processMode == OS_USER_MODE);
}
......
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "los_hw_pri.h"
#include "los_tick_pri.h"
#include "los_sys_pri.h"
#include "gic_common.h"
#define STRING_COMB(x, y, z) x ## y ## z
#ifdef LOSCFG_ARCH_SECURE_MONITOR_MODE
#define TIMER_REG(reg) STRING_COMB(TIMER_REG_, CNTPS, reg)
#else
#define TIMER_REG(reg) STRING_COMB(TIMER_REG_, CNTP, reg)
#endif
#define TIMER_REG_CTL TIMER_REG(_CTL) /* 32 bits */
#define TIMER_REG_TVAL TIMER_REG(_TVAL) /* 32 bits */
#define TIMER_REG_CVAL TIMER_REG(_CVAL) /* 64 bits */
#define TIMER_REG_CT TIMER_REG(CT) /* 64 bits */
#ifdef __LP64__
#define TIMER_REG_CNTFRQ cntfrq_el0
/* CNTP AArch64 registers */
#define TIMER_REG_CNTP_CTL cntp_ctl_el0
#define TIMER_REG_CNTP_TVAL cntp_tval_el0
#define TIMER_REG_CNTP_CVAL cntp_cval_el0
#define TIMER_REG_CNTPCT cntpct_el0
/* CNTPS AArch64 registers */
#define TIMER_REG_CNTPS_CTL cntps_ctl_el1
#define TIMER_REG_CNTPS_TVAL cntps_tval_el1
#define TIMER_REG_CNTPS_CVAL cntps_cval_el1
#define TIMER_REG_CNTPSCT cntpct_el0
#define READ_TIMER_REG32(reg) AARCH64_SYSREG_READ(reg)
#define READ_TIMER_REG64(reg) AARCH64_SYSREG_READ(reg)
#define WRITE_TIMER_REG32(reg, val) AARCH64_SYSREG_WRITE(reg, (UINT64)(val))
#define WRITE_TIMER_REG64(reg, val) AARCH64_SYSREG_WRITE(reg, val)
#else /* Aarch32 */
#define TIMER_REG_CNTFRQ CP15_REG(c14, 0, c0, 0)
/* CNTP AArch32 registers */
#define TIMER_REG_CNTP_CTL CP15_REG(c14, 0, c2, 1)
#define TIMER_REG_CNTP_TVAL CP15_REG(c14, 0, c2, 0)
#define TIMER_REG_CNTP_CVAL CP15_REG64(c14, 2)
#define TIMER_REG_CNTPCT CP15_REG64(c14, 0)
/* CNTPS AArch32 registers are banked and accessed though CNTP */
#define CNTPS CNTP
#define READ_TIMER_REG32(reg) ARM_SYSREG_READ(reg)
#define READ_TIMER_REG64(reg) ARM_SYSREG64_READ(reg)
#define WRITE_TIMER_REG32(reg, val) ARM_SYSREG_WRITE(reg, val)
#define WRITE_TIMER_REG64(reg, val) ARM_SYSREG64_WRITE(reg, val)
#endif
#define OS_CYCLE_PER_TICK (g_sysClock / LOSCFG_BASE_CORE_TICK_PER_SECOND) //每个tick多少周期
UINT32 HalClockFreqRead(VOID)
{
return READ_TIMER_REG32(TIMER_REG_CNTFRQ);
}
VOID HalClockFreqWrite(UINT32 freq)
{
WRITE_TIMER_REG32(TIMER_REG_CNTFRQ, freq);
}
STATIC_INLINE VOID TimerCtlWrite(UINT32 cntpCtl)
{
WRITE_TIMER_REG32(TIMER_REG_CTL, cntpCtl);
}
STATIC_INLINE UINT64 TimerCvalRead(VOID)
{
return READ_TIMER_REG64(TIMER_REG_CVAL);
}
STATIC_INLINE VOID TimerCvalWrite(UINT64 cval)
{
WRITE_TIMER_REG64(TIMER_REG_CVAL, cval);
}
STATIC_INLINE VOID TimerTvalWrite(UINT32 tval)
{
WRITE_TIMER_REG32(TIMER_REG_TVAL, tval);
}
UINT64 HalClockGetCycles(VOID)
{
UINT64 cntpct;
cntpct = READ_TIMER_REG64(TIMER_REG_CT);
return cntpct;
}
//节拍回调函数
LITE_OS_SEC_TEXT VOID OsTickEntry(VOID)
{
TimerCtlWrite(0);
OsTickHandler();//节拍处理主体函数
/* //使用最近的 cval生成下一个tick的计时是绝对和准确的。
* use last cval to generate the next tick's timing is
* absolute and accurate. DO NOT use tval to drive the
* generic time in which case tick will be slower.
*///不要使用tval来产生时间,在这种情况下,滴答声会变慢
TimerCvalWrite(TimerCvalRead() + OS_CYCLE_PER_TICK);
TimerCtlWrite(1);
}
LITE_OS_SEC_TEXT_INIT VOID HalClockInit(VOID)
{
UINT32 ret;
g_sysClock = HalClockFreqRead();//读时间
ret = LOS_HwiCreate(OS_TICK_INT_NUM, MIN_INTERRUPT_PRIORITY, 0, OsTickEntry, 0);
if (ret != LOS_OK) {
PRINT_ERR("%s, %d create tick irq failed, ret:0x%x\n", __FUNCTION__, __LINE__, ret);
}
}
LITE_OS_SEC_TEXT_INIT VOID HalClockStart(VOID)
{
HalIrqUnmask(OS_TICK_INT_NUM);
/* triggle the first tick */
TimerCtlWrite(0);
TimerTvalWrite(OS_CYCLE_PER_TICK);
TimerCtlWrite(1);
}
VOID HalDelayUs(UINT32 usecs)
{
UINT64 cycles = (UINT64)usecs * HalClockFreqRead() / OS_SYS_US_PER_SECOND;
UINT64 deadline = HalClockGetCycles() + cycles;
while (HalClockGetCycles() < deadline) {
__asm__ volatile ("nop");
}
}
UINT64 hi_sched_clock(VOID)
{
return LOS_CurrNanosec();
}
UINT32 HalClockGetTickTimerCycles(VOID)
{
UINT64 cval = TimerCvalRead();
UINT64 cycles = HalClockGetCycles();
return (UINT32)((cval > cycles) ? (cval - cycles) : 0);
}
VOID HalClockTickTimerReload(UINT32 cycles)
{
HalIrqMask(OS_TICK_INT_NUM);
HalIrqClear(OS_TICK_INT_NUM);
TimerCtlWrite(0);
TimerCvalWrite(HalClockGetCycles() + cycles);
TimerCtlWrite(1);
HalIrqUnmask(OS_TICK_INT_NUM);
}
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "los_hw_pri.h"
#include "los_tick_pri.h"
#include "los_sys_pri.h"
#include "gic_common.h"
#define STRING_COMB(x, y, z) x ## y ## z
#ifdef LOSCFG_ARCH_SECURE_MONITOR_MODE
#define TIMER_REG(reg) STRING_COMB(TIMER_REG_, CNTPS, reg)
#else
#define TIMER_REG(reg) STRING_COMB(TIMER_REG_, CNTP, reg)
#endif
#define TIMER_REG_CTL TIMER_REG(_CTL) /* 32 bits */
#define TIMER_REG_TVAL TIMER_REG(_TVAL) /* 32 bits */
#define TIMER_REG_CVAL TIMER_REG(_CVAL) /* 64 bits */
#define TIMER_REG_CT TIMER_REG(CT) /* 64 bits */
#ifdef __LP64__
#define TIMER_REG_CNTFRQ cntfrq_el0
/* CNTP AArch64 registers */
#define TIMER_REG_CNTP_CTL cntp_ctl_el0
#define TIMER_REG_CNTP_TVAL cntp_tval_el0
#define TIMER_REG_CNTP_CVAL cntp_cval_el0
#define TIMER_REG_CNTPCT cntpct_el0
/* CNTPS AArch64 registers */
#define TIMER_REG_CNTPS_CTL cntps_ctl_el1
#define TIMER_REG_CNTPS_TVAL cntps_tval_el1
#define TIMER_REG_CNTPS_CVAL cntps_cval_el1
#define TIMER_REG_CNTPSCT cntpct_el0
#define READ_TIMER_REG32(reg) AARCH64_SYSREG_READ(reg)
#define READ_TIMER_REG64(reg) AARCH64_SYSREG_READ(reg)
#define WRITE_TIMER_REG32(reg, val) AARCH64_SYSREG_WRITE(reg, (UINT64)(val))
#define WRITE_TIMER_REG64(reg, val) AARCH64_SYSREG_WRITE(reg, val)
#else /* Aarch32 */
#define TIMER_REG_CNTFRQ CP15_REG(c14, 0, c0, 0)
/* CNTP AArch32 registers */
#define TIMER_REG_CNTP_CTL CP15_REG(c14, 0, c2, 1)
#define TIMER_REG_CNTP_TVAL CP15_REG(c14, 0, c2, 0)
#define TIMER_REG_CNTP_CVAL CP15_REG64(c14, 2)
#define TIMER_REG_CNTPCT CP15_REG64(c14, 0)
/* CNTPS AArch32 registers are banked and accessed though CNTP */
#define CNTPS CNTP
#define READ_TIMER_REG32(reg) ARM_SYSREG_READ(reg)
#define READ_TIMER_REG64(reg) ARM_SYSREG64_READ(reg)
#define WRITE_TIMER_REG32(reg, val) ARM_SYSREG_WRITE(reg, val)
#define WRITE_TIMER_REG64(reg, val) ARM_SYSREG64_WRITE(reg, val)
#endif
#define OS_CYCLE_PER_TICK (g_sysClock / LOSCFG_BASE_CORE_TICK_PER_SECOND) //每个tick多少周期
UINT32 HalClockFreqRead(VOID)
{
return READ_TIMER_REG32(TIMER_REG_CNTFRQ);
}
VOID HalClockFreqWrite(UINT32 freq)
{
WRITE_TIMER_REG32(TIMER_REG_CNTFRQ, freq);
}
//写时间控制寄存器
STATIC_INLINE VOID TimerCtlWrite(UINT32 cntpCtl)
{
WRITE_TIMER_REG32(TIMER_REG_CTL, cntpCtl);
}
STATIC_INLINE UINT64 TimerCvalRead(VOID)
{
return READ_TIMER_REG64(TIMER_REG_CVAL);
}
STATIC_INLINE VOID TimerCvalWrite(UINT64 cval)
{
WRITE_TIMER_REG64(TIMER_REG_CVAL, cval);
}
STATIC_INLINE VOID TimerTvalWrite(UINT32 tval)
{
WRITE_TIMER_REG32(TIMER_REG_TVAL, tval);
}
UINT64 HalClockGetCycles(VOID)
{
UINT64 cntpct;
cntpct = READ_TIMER_REG64(TIMER_REG_CT);
return cntpct;
}
//节拍回调函数
LITE_OS_SEC_TEXT VOID OsTickEntry(VOID)
{
TimerCtlWrite(0);
OsTickHandler();//节拍处理主体函数
/* //使用最近的 cval生成下一个tick的计时是绝对和准确的。
* use last cval to generate the next tick's timing is
* absolute and accurate. DO NOT use tval to drive the
* generic time in which case tick will be slower.
*///不要使用tval来产生时间,在这种情况下,滴答声会变慢
TimerCvalWrite(TimerCvalRead() + OS_CYCLE_PER_TICK);
TimerCtlWrite(1);
}
LITE_OS_SEC_TEXT_INIT VOID HalClockInit(VOID)
{
UINT32 ret;
g_sysClock = HalClockFreqRead();//读硬时钟频率
ret = LOS_HwiCreate(OS_TICK_INT_NUM, MIN_INTERRUPT_PRIORITY, 0, OsTickEntry, 0);//创建硬时钟中断
if (ret != LOS_OK) {//29号中断,暂时使用安全物理计时器
PRINT_ERR("%s, %d create tick irq failed, ret:0x%x\n", __FUNCTION__, __LINE__, ret);
}
}
LITE_OS_SEC_TEXT_INIT VOID HalClockStart(VOID)
{
HalIrqUnmask(OS_TICK_INT_NUM);//取消屏蔽29号中断
/* triggle the first tick */
TimerCtlWrite(0);//
TimerTvalWrite(OS_CYCLE_PER_TICK);//设置节拍周期
TimerCtlWrite(1);
}
VOID HalDelayUs(UINT32 usecs)
{
UINT64 cycles = (UINT64)usecs * HalClockFreqRead() / OS_SYS_US_PER_SECOND;
UINT64 deadline = HalClockGetCycles() + cycles;
while (HalClockGetCycles() < deadline) {
__asm__ volatile ("nop");
}
}
UINT64 hi_sched_clock(VOID)
{
return LOS_CurrNanosec();
}
UINT32 HalClockGetTickTimerCycles(VOID)
{
UINT64 cval = TimerCvalRead();
UINT64 cycles = HalClockGetCycles();
return (UINT32)((cval > cycles) ? (cval - cycles) : 0);
}
VOID HalClockTickTimerReload(UINT32 cycles)
{
HalIrqMask(OS_TICK_INT_NUM);//先屏蔽时钟中断
HalIrqClear(OS_TICK_INT_NUM);//清除中断位
TimerCtlWrite(0);
TimerCvalWrite(HalClockGetCycles() + cycles);
TimerCtlWrite(1);
HalIrqUnmask(OS_TICK_INT_NUM);//取消屏蔽时钟中断
}
......@@ -33,19 +33,19 @@
#include "los_hwi.h"
#include "los_tick_pri.h"
#define OS_CYCLE_PER_TICK (TIMER_FREQ / LOSCFG_BASE_CORE_TICK_PER_SECOND)
#define OS_CYCLE_PER_TICK (TIMER_FREQ / LOSCFG_BASE_CORE_TICK_PER_SECOND)
typedef struct {
UINT32 load; /* Private Timer Load Register */
UINT32 count; /* Private Timer Counter Register */
UINT32 control; /* Private Timer Control Register */
UINT32 intStatus; /* Private Timer Interrupt Status Register */
UINT32 load; /* Private Timer Load Register */ //专用定时器加载寄存器
UINT32 count; /* Private Timer Counter Register */ //专用定时器计数寄存器
UINT32 control; /* Private Timer Control Register */ //专用定时器控制寄存器
UINT32 intStatus; /* Private Timer Interrupt Status Register */ //专用定时器中断状态寄存器
} PrivateTimer;
typedef struct {
UINT32 low; /* Global Timer Counter Registers, low bits */
typedef struct {//全局计数器
UINT32 low; /* Global Timer Counter Registers, low bits */ //需用64位来表示,所以需要高低位
UINT32 high; /* Global Timer Counter Registers, high bits */
UINT32 control; /* Global Timer Control Register */
UINT32 control; /* Global Timer Control Register */
UINT32 intStatus; /* Global Timer Interrupt Status Register */
UINT32 compareLow; /* Comparator Value Registers, low bits */
UINT32 compareHigh; /* Comparator Value Registers, high bits */
......
此差异已折叠。
git add -A
git commit -m '内核哪种任务的优先级是最高的 ?.
git commit -m '初始化硬时钟.
搜索 @note_pic 可查看绘制的全部字符图
搜索 @note_why 是尚未看明白的地方,有看明白的,请Pull Request完善
搜索 @note_thinking 是一些的思考和建议
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册