当前位置: 首页 > article >正文

Hooks扩展

Hooks钩子函数用于某些内核代码插入一个占位执行位置执行自定义功能代码避免直接修改原始内核代码

内核外部填充函数实现不必修改空闲任务代码

tHooks.c

#include "tinyOS.h"

#if TINYOS_ENABLE_HOOKS == 1

/* 空闲任务钩子函数 */
void tHooksCpuIdle(void)
{
	
}

/* systick发生钩子函数 */
void tHooksSysTick(void)
{
	
}

/* 任务切换钩子函数 */
void tHooksTaskSwitch(tTask *from, tTask *to)
{
	
}

/* 任务初始化钩子函数 */
void tHooksTaskInit(tTask *task)
{
	
}

#endif

tHooks.h

#ifndef __THOOKS_H
#define __THOOKS_H

#include "tTask.h"

void tHooksCpuIdle(void);
void tHooksSysTick(void);
void tHooksTaskSwitch(tTask *from, tTask *to);
void tHooksTaskInit(tTask *task);

#endif

tConfig.h

#ifndef __TCONFIG_H
#define __TCONFIG_H

#define TINYOS_PRO_COUNT							32		//优先级数量
#define TINYOS_SLICE_MAX							10		//任务时间片大小度,最小单元是一个systick周期10ms
#define TINYOS_IDLETASK_STACK_SIZE		1024	//空闲任务堆栈大小

#define TINYOS_TIMERTASK_STACK_SIZE		1024	//定时器任务堆栈大小
#define TINYOS_TIMERTASK_PRIO					1			//定时器任务优先级,不能和空闲任务相同

#define TINYOS_SYSTICK_MS							10		//SYSTICK

/* 控制开关 */
/* 计数信号量 */
#define TINYOS_ENABLE_SEM							0
/* 互斥信号量 */
#define TINYOS_ENABLE_MUTEX						0
/* 事件标志组 */
#define TINYOS_ENABLE_FLAGGROUP				0
/* 邮箱 */
#define TINYOS_ENABLE_MBOX						0
/* 存储块 */
#define TINYOS_ENABLE_MEMBLOCK				0
/* 软定时器 */
#define TINYOS_ENABLE_TIMER						0
/* CPU统计 */
#define TINYOS_ENABLE_CPUUSAGE_STAT		0
/* Hooks函数 */
#define TINYOS_ENABLE_HOOKS						1
#endif

main.c

#include "tinyOS.h"
#include "ARMCM3.h"

tTask *currentTask;			//指示当前运行任务的指针
tTask *nextTask;				//指向下一个任务的指针
tTask *idleTask;				//空闲任务

tBitmap taskPrioBitmap;	//优先级位图
tList taskTable[TINYOS_PRO_COUNT];	//任务数组列表

uint8_t schedLockCount;	//调度锁计数器

tList tTaskDelayedList;	//延时队列

uint32_t tickCount;			//统计时钟节拍发生次数
uint32_t idleCount;			//特殊代码块执行计数器
uint32_t idleMaxCount;	//最大计数值

#if TINYOS_ENABLE_CPUUSAGE_STAT == 1

static void initCpuUsageStat(void);
static void checkCpuUsage(void);
static void cpuUsageSyncWithSystick(void);
#endif

/* 查找优先级位图函数 */
tTask *tTaskHighestReady(void)
{
	uint32_t highestPrio = tBitmaoFirstSet(&taskPrioBitmap);
	tNode *node = tListFirst(&taskTable[highestPrio]);//取出优先级队列第一个结点
	return tNodeParent(node, tTask, linkNode);
}

/* 调度锁初始化函数 */
void tTaskSchedInit(void)
{
	schedLockCount = 0;						//初始计数值为0
	tBitmapInit(&taskPrioBitmap);	//对bitmap初始化
	for(int i = 0; i < TINYOS_PRO_COUNT; i++)	//初始化优先级数组的各个列表项
	{
		tListInit(&taskTable[i]);
	}
}

/* 上锁函数(禁止调度函数) */
void tTaskSchedDisable(void)
{
	uint32_t status = tTaskEnterCritical();
	//schedLockCount是全局变量需要临界区保护
	if(schedLockCount < 255)//schedLockCount是8位的,防止溢出
	{
		schedLockCount++;
	}
	tTaskExitCritical(status);
}

/* 解锁函数(使能调度函数) */
void tTaskSchedEnable(void)
{
	uint32_t status = tTaskEnterCritical();
	if(schedLockCount > 0)
	{
		if(--schedLockCount == 0)
		{
			tTaskSched();//执行调度函数
		}
	}
	tTaskExitCritical(status);
}

/* 任务就绪(插入就绪表) */
void tTaskSchedRdy(tTask *task)
{
	tListAddFirst(&(taskTable[task->prio]), &(task->linkNode));	//将链接结点加入所在优先级队列
	tBitmapSet(&taskPrioBitmap, task->prio);	//对位图置1,就绪表中设置任务就绪
}

/* 任务非就绪(移出就绪表) */
//将任务设置为非就绪状态
void tTaskSchedUnRdy(tTask *task)
{
	tListRemove(&(taskTable[task->prio]), &(task->linkNode));
	if(tListCount(&taskTable[task->prio]) == 0)//判断列表中是否还有其他任务
	{
		tBitmapClear(&taskPrioBitmap, task->prio);	//没有其他任务,位图位清零
	}
}

/* 优先级队列移除任务 */
void tTaskSchedRemove(tTask *task)
{
	tListRemove(&(taskTable[task->prio]), &(task->linkNode));
	if(tListCount(&taskTable[task->prio]) == 0)//判断列表中是否还有其他任务
	{
		tBitmapClear(&taskPrioBitmap, task->prio);	//没有其他任务,位图位清零
	}
}

/* 调度函数 */
//决定CPU在哪两个任务之间运行,采用什么规则,怎么分配
void tTaskSched(void)
{
	tTask *tempTask;
	uint32_t status = tTaskEnterCritical();
	
	//判断调度器是否上锁
	if(schedLockCount > 0)//上锁
	{
		tTaskExitCritical(status);//退出
		return;
	}
	
	tempTask = tTaskHighestReady();//获取最高优先级需要占用CPU运行的任务
	if(tempTask != currentTask)//最高优先级任务与当前任务不同
	{
		nextTask = tempTask;
		
#if TINYOS_ENABLE_HOOKS == 1
	tHooksTaskSwitch(currentTask, nextTask);
#endif
		
		tTaskSwitch();//任务切换函数
	}
	
	tTaskExitCritical(status);
}

/* 延时队列初始化 */
void tTaskDelayedInit()
{
	tListInit(&tTaskDelayedList);//初始化延时链表
}

/* 任务挂起(插入延时队列) */
void tTimeTaskWait(tTask *task, uint32_t ticks)
{
	task->delayTicks = ticks;
	tListAddLast(&tTaskDelayedList, &(task->delayNode));//任务插入队列尾部
	task->state |= TINYOS_TASK_STATE_DELAYED;
}

/* 任务唤醒(移出延时队列) */
void tTimeTaskWakeUp(tTask *task)
{
	tListRemove(&tTaskDelayedList, &(task->delayNode));
	task->state &= ~TINYOS_TASK_STATE_DELAYED;//清除延时标志位
}

/* 延时队列移除任务 */
void tTimeTaskRemove(tTask *task)
{
	tListRemove(&tTaskDelayedList, &(task->delayNode));
}

/* tickCount初始化函数 */
void tTimerTickInit(void)
{
	tickCount = 0;
}

/* 时钟节拍处理函数 */
void tTaskSystemTickHandler(void)
{
	tNode *node;
	uint32_t status = tTaskEnterCritical();
	//扫描延时队列
	for(node = tTaskDelayedList.headNode.nextNode; node != &(tTaskDelayedList.headNode); node = node->nextNode)
	{
		tTask *task = tNodeParent(node, tTask, delayNode);//获取任务结构
		if(--task->delayTicks == 0)//判断任务有没有延时到
		{
			
			if(task->waitEvent)//判断任务是否在等待事件
			{
				tEventRemoveTask(task, (void *)0, tErrorTimeout);//从事件控制块中移除
			}
			
			tTimeTaskWakeUp(task);//从延时队列中移除
			
			tTaskSchedRdy(task);//插入就绪表
		}
	}
	if(--currentTask->slice == 0)//当前任务时间片是否已用完
	{
		if(tListCount(&taskTable[currentTask->prio]) > 0)//还有其他任务
		{
			//切换轮转
			tListRemoveFirst(&taskTable[currentTask->prio]);
			tListAddLast(&taskTable[currentTask->prio], &(currentTask->linkNode));
			
			currentTask->slice = TINYOS_SLICE_MAX;//时间片重新赋值
		}
	}
	
	tickCount++;
	
#if TINYOS_ENABLE_CPUUSAGE_STAT == 1
	checkCpuUsage();//检查cpu使用率
#endif
	
	tTaskExitCritical(status);
	
#if TINYOS_ENABLE_TIMER == 1
	tTimerModuleTickNotify();//对定时器模块的tick通知
#endif
	
#if TINYOS_ENABLE_HOOKS == 1
	tHooksSysTick();
#endif

	tTaskSched();//调度函数
}

#if TINYOS_ENABLE_CPUUSAGE_STAT == 1
static float cpuUsage;
static uint32_t enableCpuUsageState;

/* 初始化cpu统计函数 */
static void initCpuUsageStat(void)
{
	idleCount = 0;
	idleMaxCount = 0;
	cpuUsage = 0.0f;
	enableCpuUsageState = 0;
}

/* 检查cpu使用率函数 */
static void checkCpuUsage(void)
{
	//判断是否同步
	if(enableCpuUsageState == 0)
	{
		enableCpuUsageState = 1;
		tickCount = 0;
		return;
	}
	if(tickCount == TICKS_PER_SEC)//恰好运行到一秒
	{
		idleMaxCount = idleCount;//取出计数值给MaxCount
		idleCount = 0;
		
		tTaskSchedEnable();
	}
	else if(tickCount % TICKS_PER_SEC == 0)//每隔一秒检查CPU利用率
	{
		cpuUsage = 100 - (idleCount * 100.0 / idleMaxCount);
		idleCount = 0;
	}
}


/* 检查cpu使用率与系统时钟节拍同步辅助函数 */
static void cpuUsageSyncWithSystick(void)
{
	//不断对标志位进行检查,等待与系统时钟节拍同步
	while(enableCpuUsageState == 0)
	{
		;;
	}
}

/* cpu获取函数 */
float tCpuUsageGet(void)
{
	float usage = 0;
	
	uint32_t status = tTaskEnterCritical();
	usage = cpuUsage;
	tTaskExitCritical(status);
	
	return usage;
}
#endif

tTask tTaskIdle;//空闲任务
tTaskStack idleTaskEnv[TINYOS_IDLETASK_STACK_SIZE];	//空闲任务的堆栈

/* 空闲任务具体内容 */
void idleTaskEntry(void *param)
{
	tTaskSchedDisable();//关闭调度锁,防止初始化应用任务切换到任务中运行
	
	tInitApp();
	
#if TINYOS_ENABLE_TIMER == 1
	tTimerInitTask();
#endif
	
	tSetSysTickPeriod(TINYOS_SYSTICK_MS);//初始化
	
#if TINYOS_ENABLE_CPUUSAGE_STAT == 1
	//时钟同步,开始测量是时钟节拍刚开始发生时,而不是两个时钟节拍之间的时间
	cpuUsageSyncWithSystick();
#endif
	
	for(;;)
	{
		/* 特殊代码块 */
		uint32_t status = tTaskEnterCritical();
		idleCount++;
		tTaskExitCritical(status);
		
#if TINYOS_ENABLE_HOOKS == 1
	tHooksCpuIdle();
#endif
	}
}

int main(void)
{
	tTaskSchedInit();		//初始化调度锁
	
	tTaskDelayedInit();	//初始化延时队列

#if TINYOS_ENABLE_TIMER == 1
	tTimerModuleInit();	//初始化定时器模块
#endif
	
	tTimerTickInit();		//初始化tickCount
	
#if TINYOS_ENABLE_CPUUSAGE_STAT == 1
	initCpuUsageStat();	//初始化cpu统计
#endif
	
	tTaskInit(&tTaskIdle, idleTaskEntry, (void *)0, TINYOS_PRO_COUNT - 1, idleTaskEnv, TINYOS_IDLETASK_STACK_SIZE);//创建空闲任务
	idleTask = &tTaskIdle;//空闲任务赋值
	
	nextTask = tTaskHighestReady();//初始运行任务指向就绪表中优先级最高的任务
	
	tTaskRunFirst();//切换到第0个任务运行
	
	return 0;
	//执行tTaskRunFirst函数后,CPU的控制权切换到任务里运行
	//任务里是for循环会一直在任务里运行
	//切换到另一个函数里面也是for循环
	//永远不会返回
}

tTask.c

#include "tinyOS.h"

/* 任务初始化函数 */
//参数:tTask结构的指针,任务入口函数的地址,传递给任务的参数地址,优先级,堆栈起始地址,堆栈大小
//任务初始运行时,会把栈里的内容依次弹出来,恢复到内核寄存器中。
void tTaskInit(tTask *task, void(*entry)(void *), void *param, uint32_t prio, tTaskStack *stack, uint32_t size)
{
	uint32_t *stackTop;//指向堆栈末端
	
	task->stackBase = stack;								//堆栈起始位置
	task->stackSize = size;									//堆栈大小
	memset(stack, 0, size);									//堆栈空间清0
	
	stackTop = stack + size / sizeof(tTaskStack);//堆栈起始位置+堆栈大小(除堆栈单元的大小)
	
	//初始化具体的堆栈内容
	//传递堆栈的末端地址,内核本身的堆栈增长方式是满递减方式增长的,先进行递减操作
	*(--stackTop) = (unsigned long)(1 << 24);	//xPSR,设置T标志位
	*(--stackTop) = (unsigned long)entry;			//R15(PC),程序入口函数
	*(--stackTop) = (unsigned long)0x14;				//R14(LR),未用
	*(--stackTop) = (unsigned long)0x12;				//R12,未用
	*(--stackTop) = (unsigned long)0x3;				//R3,未用
	*(--stackTop) = (unsigned long)0x2;				//R2,未用
	*(--stackTop) = (unsigned long)0x1;				//R1,未用
	*(--stackTop) = (unsigned long)param;			//R0,程序的入口参数,函数第一个参数存入R0
	*(--stackTop) = (unsigned long)0x11;				//R11,未用
	*(--stackTop) = (unsigned long)0x10;				//R10,未用
	*(--stackTop) = (unsigned long)0x9;				//R9,未用
	*(--stackTop) = (unsigned long)0x8;				//R8,未用
	*(--stackTop) = (unsigned long)0x7;				//R7,未用
	*(--stackTop) = (unsigned long)0x6;				//R6,未用
	*(--stackTop) = (unsigned long)0x5;				//R5,未用
	*(--stackTop) = (unsigned long)0x4;				//R4,未用
	
	
	task->slice = TINYOS_SLICE_MAX; 				//时间片初始值是最大值
	task->stack = stackTop;									//保存最终的值
	task->delayTicks = 0;										//初始化计数器为0
	task->prio = prio;											//初始化优先级
	task->state = TINYOS_TASK_STATE_RDY;		//任务状态初始化为就绪态
	task->suspendCount = 0;									//任务挂起计数器为0
	task->clean = (void (*)(void *))0;			//清理函数为空
	task->cleanParam = (void *)0;						//清理函数参数为空
	task->requestDeleteFlag = 0;						//删除请求标记为0
	
	tNodeInit(&(task->delayNode));				//延时结点初始化
	tNodeInit(&(task->linkNode));					//链接结点初始化
	
	tTaskSchedRdy(task);									//链接结点插入就绪表
	
#if TINYOS_ENABLE_HOOKS == 1
	tHooksTaskInit(task);
#endif

}

/* 任务挂起函数 */
void tTaskSuspend(tTask *task)
{
	uint32_t status = tTaskEnterCritical();
		
	if(!(task->state & TINYOS_TASK_STATE_DELAYED))//任务不在延时状态
	{
		if(++task->suspendCount <= 1)//对挂起计数器++后,挂起计数器是第一次挂起
		{
			task->state |= TINYOS_TASK_SYATE_SUSPEND;//任务为挂起态
			tTaskSchedUnRdy(task);//将任务从挂起就绪列表中移除
			if(task == currentTask)//判断任务是否是当前任务
			{
				tTaskSched();
			}
		}
	}
	
	tTaskExitCritical(status);
}

/* 任务恢复函数 */
void tTaskWakeUp(tTask *task)
{
	uint32_t status = tTaskEnterCritical();
	
	if(task->state & TINYOS_TASK_SYATE_SUSPEND)//任务在挂起状态
	{
		if(--task->suspendCount == 0)
		{
			task->state &= ~TINYOS_TASK_SYATE_SUSPEND;//清除挂起态
			tTaskSchedRdy(task);//将任务插入就绪列表
			tTaskSched();
		}
	}
	
	tTaskExitCritical(status);
}

/* 资源清理回调函数 */
void tTaskSetCleanCallFunc(tTask *task, void (*clean)(void *param), void *param)
{
	task->clean = clean;
	task->cleanParam = param;
}
	
/* 强制删除函数 */
void tTaskForceDelete(tTask *task)
{
	uint32_t status = tTaskEnterCritical();
	
	if(task->state & TINYOS_TASK_STATE_DELAYED)//任务处于延时状态
	{
		tTimeTaskRemove(task);
	}
	else if(!(task->state & TINYOS_TASK_SYATE_SUSPEND))//任务不处于挂起状态
	{
		//任务在运行或就绪态
		tTaskSchedRemove(task);
	}
	if(task->clean)
	{
		task->clean(task->cleanParam);
	}
	if(currentTask == task)//任务是当前任务
	{
		tTaskSched();
	}
	
	tTaskExitCritical(status);
}

/* 请求删除函数 */
void tTaskRequestDelete(tTask *task)
{
	uint32_t status = tTaskEnterCritical();
	
	task->requestDeleteFlag = 1;
	
	tTaskExitCritical(status);
}

/* 检查删除请求函数 */
uint8_t tTaskIsRequestedDelete(void)
{
	uint8_t delete;
	uint32_t states = tTaskEnterCritical();
	
	delete = currentTask->requestDeleteFlag;
		
	tTaskExitCritical(states);
	
	return delete;
}

/* 删除任务自己函数 */
void tTaskDeleteSelf(void)
{
	uint32_t states = tTaskEnterCritical();
	
	//任务处于运行态
	tTaskSchedRemove(currentTask);
	
	if(currentTask->clean)
	{
		currentTask->clean(currentTask->cleanParam);
	}
	tTaskSched();
	
	tTaskExitCritical(states);
}

/* 任务状态查询函数 */
void tTaskGetInfo(tTask *task, tTaskInfo *info)
{
	uint32_t *stackEnd;//堆栈末端指针
	uint32_t states = tTaskEnterCritical();
	
	info->delayTicks = task->delayTicks;
	info->prio = task->prio;
	info->slice = task->slice;
	info->state = task->state;
	info->suspendCount = task->suspendCount;
	info->stackSize = task->stackSize;
	
	info->stackFree = 0;
	stackEnd = task->stackBase;//堆栈向下生长,stackBase处于堆栈空间的低地址
	while((*stackEnd++ == 0) && (stackEnd <= task->stackBase + task->stackSize / sizeof(tTaskStack)))//再判断一下这个位置有没有超出堆栈空间
	{
		info->stackFree++;
	}
	info->stackFree *= sizeof(tTaskStack);//单元数转为字节数
	
	tTaskExitCritical(states);
}


http://www.kler.cn/a/506975.html

相关文章:

  • sparkSQL练习
  • Ondo SIP Server
  • 如何在 Rocky Linux 上安装极狐GitLab?
  • ORB-SLAM2源码学习: Frame.cc: cv::Mat Frame::UnprojectStereo将某个特征点反投影到三维世界坐标系中
  • docker 部署 MantisBT
  • 传统摄像头普通形态的系统连接方式
  • 【刷题笔记】滑动窗口单调队列题目
  • 大疆最新款无人机发布,可照亮百米之外目标
  • Redis超详细入门教程(基础篇)
  • Spring Boot自动装配原理与Stater开发及使用场景
  • JAVA EE与Spring的关系
  • DP读书:江苏省政府境外奖学金申请指南——A2悉尼大学现代工业设计【2024学习指南、笔记总结】+ 苏教国际 + 悉尼大学短期交流攻略 Blog 版
  • 小程序组件 —— 31 事件系统 - 事件绑定和事件对象
  • 《零基础Go语言算法实战》【题目 2-30】并发安全问题
  • 项目太大导致 git clone 失败
  • 前端小知识 鼠标穿透 pointer-events: none;
  • Vue快速开发之环境搭建nodejs与运行第一个Vue项目
  • docker的数据卷与dockerfile自定义镜像
  • Golang—— error 和 panic
  • [私用学习笔记·突击面试]Collection和迭代器
  • 图论的起点——七桥问题
  • 软件测试入门—测试流程之需求分析
  • Pycharm报错:DeprecationWarning: sipPyTypeDict() is deprecated
  • react 与 vue 的比较,以及如何选择?
  • 使用 spring boot 2.5.6 版本时缺少 jvm 配置项
  • 持续集成 02|Jenkins介绍与安装、Postman集成Jenkins、代码集成Jenkins