Hooks扩展

embedded/2025/1/19 3:29:03/

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 == 1static 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;						//初始计数值为0tBitmapInit(&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 == 1tHooksTaskSwitch(currentTask, nextTask);
#endiftTaskSwitch();//任务切换函数}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 == 1checkCpuUsage();//检查cpu使用率
#endiftTaskExitCritical(status);#if TINYOS_ENABLE_TIMER == 1tTimerModuleTickNotify();//对定时器模块的tick通知
#endif#if TINYOS_ENABLE_HOOKS == 1tHooksSysTick();
#endiftTaskSched();//调度函数
}#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;//取出计数值给MaxCountidleCount = 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;
}
#endiftTask tTaskIdle;//空闲任务
tTaskStack idleTaskEnv[TINYOS_IDLETASK_STACK_SIZE];	//空闲任务的堆栈/* 空闲任务具体内容 */
void idleTaskEntry(void *param)
{tTaskSchedDisable();//关闭调度锁,防止初始化应用任务切换到任务中运行tInitApp();#if TINYOS_ENABLE_TIMER == 1tTimerInitTask();
#endiftSetSysTickPeriod(TINYOS_SYSTICK_MS);//初始化#if TINYOS_ENABLE_CPUUSAGE_STAT == 1//时钟同步,开始测量是时钟节拍刚开始发生时,而不是两个时钟节拍之间的时间cpuUsageSyncWithSystick();
#endiffor(;;){/* 特殊代码块 */uint32_t status = tTaskEnterCritical();idleCount++;tTaskExitCritical(status);#if TINYOS_ENABLE_HOOKS == 1tHooksCpuIdle();
#endif}
}int main(void)
{tTaskSchedInit();		//初始化调度锁tTaskDelayedInit();	//初始化延时队列#if TINYOS_ENABLE_TIMER == 1tTimerModuleInit();	//初始化定时器模块
#endiftTimerTickInit();		//初始化tickCount#if TINYOS_ENABLE_CPUUSAGE_STAT == 1initCpuUsageStat();	//初始化cpu统计
#endiftTaskInit(&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);									//堆栈空间清0stackTop = 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;										//初始化计数器为0task->prio = prio;											//初始化优先级task->state = TINYOS_TASK_STATE_RDY;		//任务状态初始化为就绪态task->suspendCount = 0;									//任务挂起计数器为0task->clean = (void (*)(void *))0;			//清理函数为空task->cleanParam = (void *)0;						//清理函数参数为空task->requestDeleteFlag = 0;						//删除请求标记为0tNodeInit(&(task->delayNode));				//延时结点初始化tNodeInit(&(task->linkNode));					//链接结点初始化tTaskSchedRdy(task);									//链接结点插入就绪表#if TINYOS_ENABLE_HOOKS == 1tHooksTaskInit(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.ppmy.cn/embedded/155123.html

相关文章

剑指Offer|LCR 031. LRU 缓存

LCR 031. LRU 缓存 运用所掌握的数据结构&#xff0c;设计和实现一个 LRU (Least Recently Used&#xff0c;最近最少使用) 缓存机制 。 实现 LRUCache 类&#xff1a; LRUCache(int capacity) 以正整数作为容量 capacity 初始化 LRU 缓存int get(int key) 如果关键字 key 存…

Redis延迟队列详解

以下是对 Redis 延迟队列的详细解释&#xff1a; 一、什么是 Redis 延迟队列 Redis 延迟队列是一种使用 Redis 实现的消息队列&#xff0c;其中的消息在被消费之前会等待一段时间&#xff0c;这段时间就是延迟时间。延迟队列常用于一些需要延迟处理的任务场景&#xff0c;例如订…

2025年01月17日Github流行趋势

项目名称&#xff1a;MiniCPM-o 项目地址url&#xff1a;https://github.com/OpenBMB/MiniCPM-o 项目语言&#xff1a;Python 历史star数&#xff1a;14181 今日star数&#xff1a;371 项目维护者&#xff1a;yiranyyu, iceflame89, yaoyuanTHU, LDLINGLINGLING, tc-mb 项目简介…

商城系统中的常见 BUG

以下是商城系统中一些常见的 BUG&#xff1a; 功能与操作类 支付问题&#xff1a;如无法成功完成支付&#xff0c;支付过程中出现延迟、错误或订单重复支付等&#xff0c;还可能因网络问题导致支付失败或数据不一致。 登录 / 注册问题&#xff1a;用户在注册或登录时可能遇到…

【MySQL】复合查询+表的内外连接

复合查询表的内外连接 1.基本查询回顾2.多表查询3.自连接4.子查询4.1单列子查询4.2多列子查询 5.在from子句中使用子查询6.合并查询7.表的内连和外连7.1内连接7.2外连接7.2.1左外连接7.2.2右外连接 点赞&#x1f44d;&#x1f44d;收藏&#x1f31f;&#x1f31f;关注&#x1f…

第八章、python的类及其应用(8.1.1-8.2.1.2)------类的常见概念、类的构造器概述、空间化构造方法__new__()

目录 8.1 python类的常见概念 8.1.1面向过程与面向对象编程 8.1.2类、类地址、类实例对象地址、封装、继承、多态的概念 8.2 python类的构成详解及其性质 8.2.1类中的构造方法 8.2.1.1类的构造器概述 8.2.1.2空间化构造方法__new__() 第八章 python的类及其应用 本章主要讲述类…

React 中hooks之useLayoutEffect 用法总结以及与useEffect的区别

React useLayoutEffect 1. useLayoutEffect 基本概念 useLayoutEffect 是 React 的一个 Hook&#xff0c;它的函数签名与 useEffect 完全相同&#xff0c;但它会在所有的 DOM 变更之后同步调用 effect。它可以用来读取 DOM 布局并同步触发重渲染。 2. useLayoutEffect vs us…

设计模式-结构型-装饰器模式

装饰器模式&#xff08;Decorator Pattern&#xff09;是结构型设计模式中的一种&#xff0c;它允许你通过将对象封装在一个新的对象中&#xff0c;来动态地添加新的功能&#xff0c;而无需改变原对象的结构。装饰器模式的核心思想是“将功能附加到对象上”&#xff0c;它是一种…