SylixOS BSP tick驱动流程
1. 开发环境
- 操作系统:SylixOS
- 编程环境:RealEvo-IDE3.1
- 硬件平台:IMX6Q实验箱
2.技术实现
时钟节拍(clock tick)是特定的周期性中断。这个中断可以看做是系统心脏的脉动。时钟的节拍式中断使得内核可以将任务延时若干个整数时钟节拍,同时当任务等待事件发生时,提供等待超时的依据。
2.1 Tick的频率设置
Tick的频率需要根据具体的硬件性能来设置。频率越快,系统的额外开销也会越大。SylixOS中频率通 过bspInit.c文件中的halPrimaryCpuMain函数设置,如程序清单 2-1 所示。
程序清单 2-1 tick频率设置
/********************************************************************************************************* ** 函数名称: halPrimaryCpuMain ** 功能描述: Primary CPU C 入口 ** 输 入 : NONE ** 输 出 : 0 ** 全局变量: ** 调用模块: *********************************************************************************************************/ INT halPrimaryCpuMain (VOID) { /* * 系统内核堆与系统堆 */ externUCHAR __heap_start, __heap_end; bspOpenocdInit(); /* 初始化 openocd */ halModeInit(); /* 初始化硬件 */ /* * 这里的调试端口是脱离操作系统的, 所以它应该不依赖于操作系统而存在. * 当系统出现错误时, 这个端口显得尤为关键. (项目成熟后可以通过配置关掉) * (!!当前串口已经由bootloader初始化了, 这里无需处理.) */ /* * 这里使用 bsp设置启动参数, 如果 bootloader支持, 可使用 bootloader设置. * 为了兼容以前的项目, 这里 kfpu=yes 允许内核中(包括中断)使用 FPU. */ #if (BOARD_MARSBOARD == 1) API_KernelStartParam("ncpus=2 kdlog=no kderror=yes kfpu=no heapchk=yes hz=1000 hhz=1000"); #else API_KernelStartParam("ncpus=4 kdlog=no kderror=yes kfpu=no heapchk=yes hz=1000 hhz=1000"); #endif /* 操作系统启动参数设置 */ API_KernelStart(usrStartup, (PVOID)&__heap_start, (size_t)&__heap_end - (size_t)&__heap_start, LW_NULL, 0); /* 启动内核 */ return (0); /* 不会执行到这里 */ }
在代码中,调用了API_KernelStartParam函数,函数参数是字符串类型,字符串里的“hz”参数选项后面的数值是需要设置的频率,调用API_KernelStartParam之后,系统的宏LW_TICK_HZ也会被设置为对应的频率,这里的代码运行后LW_TICK_HZ被设置为1000。
2.2 tick初始化
一般选用硬件定时器来实现系统tick功能,因此tick的初始化其实就是IMX6Q实验箱定时器的初始化。
SylixOS中通过bsplib.c文件里的bspTickInit函数实现tick的初始化。
Imx6Q实验箱的tick初始化代码如程序清单 2 2 所示,流程见代码中的注释。
程序清单 2-2 tick 初始化
/********************************************************************************************************* ** 函数名称: bspTickInit ** 功能描述: 初始化 tick 时钟 ** 输 入 : NONE ** 输 出 : NONE ** 全局变量: ** 调用模块: *********************************************************************************************************/ VOID bspTickInit (VOID) { REGISTERUINT32 uiIncrementValue, uiPrescaler; #if TICK_IN_THREAD > 0 LW_CLASS_THREADATTR threakattr; API_ThreadAttrBuild(&threakattr, (8 * LW_CFG_KB_SIZE), LW_PRIO_T_TICK, LW_OPTION_THREAD_STK_CHK | LW_OPTION_THREAD_UNSELECT | LW_OPTION_OBJECT_GLOBAL | LW_OPTION_THREAD_SAFE, LW_NULL); htKernelTicks = API_ThreadCreate("t_tick", (PTHREAD_START_ROUTINE)__tickThread, &threakattr, LW_NULL); #endif /* TICK_IN_THREAD > 0 */ /* * (PRESCALER_value+1) x (Load_value+1) x 2 * The timer interval = --------------------------------------------- * PERIPHCLK */ uiIncrementValue = ((imx6qMainClkGet(CPU_CLK) / 2) / LW_TICK_HZ); uiPrescaler = 0; /* * 1.设置定时器分频系数,根据LW_TICK_HZ和分频系数计算出定时器的比较数值; */ _G_uiFullCnt = uiIncrementValue; _G_ui64NSecPerCnt7 = ((1000 * 1000 * 1000 / LW_TICK_HZ) << 7) / _G_uiFullCnt; /* * 2.初始化硬件定时器,设置为对应的计数模式; */ armGlobalTimerInit(LW_TRUE, uiIncrementValue, uiPrescaler, LW_TRUE); /* * 3.将定时器当前的计数值,和比较值写入对应的寄存器; */ armGlobalTimerCounterSet(0); armGlobalTimerComparatorSet(uiIncrementValue); _G_ui64ComparatorCur = 0; /* * 4.绑定定时器的中断服务函数(__tickTimerIsr),设置中断优先级; */ API_InterVectorConnect(ARM_TICK_INT_VECTOR, (PINT_SVR_ROUTINE)__tickTimerIsr, LW_NULL, "tick_isr"); API_InterVectorEnable(ARM_TICK_INT_VECTOR); armGicIrqPrioritySet(ARM_TICK_INT_VECTOR, ARM_TICK_INT_PRIORITY); /* * 5.使能定时器,开始计数。 */ armGlobalTimerStart(); }
2.3 tick中断服务函数
SylixOS里tick中断服务函数为__tickTimerIsr,在2.2节的tick初始化过程中已经绑定,对于bsp开发,只需要在__tickTimerIsr函数内,清除tick使用的定时器的中断位。其余的不需要修改。如程序清单 2-3 所示。
程序清单 2-3 tick 中断服务函数
/********************************************************************************************************* ** 函数名称: __tickTimerIsr ** 功能描述: tick 定时器中断服务例程 ** 输 入 : NONE ** 输 出 : 中断返回值 ** 全局变量: ** 调用模块: *********************************************************************************************************/ staticirqreturn_t __tickTimerIsr (VOID) { armGlobalTimerIntClear(); /* 清除中断 */ API_KernelTicksContext(); /* 保存被时钟中断的线程控制块 */ #if TICK_IN_THREAD > 0 API_ThreadResume(htKernelTicks); #else API_KernelTicks(); /* 内核 TICKS 通知 */ API_TimerHTicks(); /* 高速 TIMER TICKS 通知 */ #endif /* TICK_IN_THREAD > 0 */ return (LW_IRQ_HANDLED); }
3.参考资料
时间: 2024-10-16 16:12:31