- /*
- @hehung
- 2023-6-30
- email: 1398660197@qq.com
- wechat: hehung95
- reproduced and please indicate the source @hehung
- */
- // This is a simple OS, and base a timer
- #include "app_scheduler.h"
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include "ac780x_timer.h"
- #define Timer_CLK (APB_BUS_FREQ) /*!定时器时钟为APB时钟 */
- #define TimeoutS(n) (Timer_CLK*n - 1) /*!n 秒超时值 */
- #define Timeout1ms (Timer_CLK/1000-1) /*!1ms超时值 */
- #define Timeout500ms (Timer_CLK/2-1) /*!500ms超时值 */
- static uint32_t time_escape = 1U;
- static schr_task_func_t *task_2ms_list;
- static uint8_t task_2ms_cnt = 0;
- static schr_task_func_t *task_5ms_list;
- static uint8_t task_5ms_cnt = 0;
- static schr_task_func_t *task_10ms_list;
- static uint8_t task_10ms_cnt = 0;
- static schr_task_func_t *task_100ms_list;
- static uint8_t task_100ms_cnt = 0;
- static schr_task_func_t *task_500ms_list;
- static uint8_t task_500ms_cnt = 0;
- static schr_task_func_t *task_1000ms_list;
- static uint8_t task_1000ms_cnt = 0;
- static void Schr_SchedulerRunning(void);
- // === User function declaration
- static void Schr_TimerInit(void);
- static void TIMER_CH0_Callback(void *device, uint32_t wpara, uint32_t lpara);
- // === End user function declaration
- // Scheduler Initialization
- void Schr_Init(void)
- {
- // === User Code
-
- // === End user code
- }
- static void Schr_SchedulerRunning(void)
- {
- uint8_t task_cnt;
- #if (SCHR_PERIOD_2MS != 0U)
- if ((time_escape % SCHR_PERIOD_2MS) == 0U)
- {
- for (task_cnt = 0; task_cnt < task_2ms_cnt; task_cnt++)
- {
- task_2ms_list[task_cnt]();
- }
- }
- #endif
- #if (SCHR_PERIOD_5MS != 0U)
- if ((time_escape % SCHR_PERIOD_5MS) == 0U)
- {
- for (task_cnt = 0; task_cnt < task_5ms_cnt; task_cnt++)
- {
- task_5ms_list[task_cnt]();
- }
- }
- #endif
- #if (SCHR_PERIOD_10MS != 0U)
- if ((time_escape % SCHR_PERIOD_10MS) == 0U)
- {
- for (task_cnt = 0; task_cnt < task_10ms_cnt; task_cnt++)
- {
- task_10ms_list[task_cnt]();
- }
- }
- #endif
- #if (SCHR_PERIOD_100MS != 0U)
- if ((time_escape % SCHR_PERIOD_100MS) == 0U)
- {
- for (task_cnt = 0; task_cnt < task_100ms_cnt; task_cnt++)
- {
- task_100ms_list[task_cnt]();
- }
- }
- #endif
- #if (SCHR_PERIOD_500MS != 0U)
- if ((time_escape % SCHR_PERIOD_500MS) == 0U)
- {
- for (task_cnt = 0; task_cnt < task_500ms_cnt; task_cnt++)
- {
- task_500ms_list[task_cnt]();
- }
- }
- #endif
- #if (SCHR_PERIOD_1000MS != 0U)
- if ((time_escape % SCHR_PERIOD_1000MS) == 0U)
- {
- for (task_cnt = 0; task_cnt < task_1000ms_cnt; task_cnt++)
- {
- task_1000ms_list[task_cnt]();
- }
- }
- #endif
- time_escape ++;
- if (time_escape > SCHR_PERIOD_1000MS)
- {
- time_escape = 1;
- }
- }
- // Start timer to shceduler
- void Schr_StartScheduler(void)
- {
- Schr_TimerInit();
- }
- void Schr_CreateTask(const schr_task_func_t task_func, uint32_t task_period)
- {
- switch (task_period)
- {
- case SCHR_PERIOD_2MS:
- {
- task_2ms_cnt++;
- task_2ms_list = (schr_task_func_t*)realloc(task_2ms_list, task_2ms_cnt * sizeof(schr_task_func_t));
- task_2ms_list[task_2ms_cnt-1] = task_func;
- break;
- }
- case SCHR_PERIOD_5MS:
- {
- task_5ms_cnt++;
- task_5ms_list = (schr_task_func_t*)realloc(task_5ms_list, task_5ms_cnt * sizeof(schr_task_func_t));
- task_5ms_list[task_5ms_cnt-1] = task_func;
- break;
- }
- case SCHR_PERIOD_10MS:
- {
- task_10ms_cnt++;
- task_10ms_list = (schr_task_func_t*)realloc(task_10ms_list, task_10ms_cnt * sizeof(schr_task_func_t));
- task_10ms_list[task_10ms_cnt-1] = task_func;
- break;
- }
- case SCHR_PERIOD_100MS:
- {
- task_100ms_cnt++;
- task_100ms_list = (schr_task_func_t*)realloc(task_100ms_list, task_100ms_cnt * sizeof(schr_task_func_t));
- task_100ms_list[task_100ms_cnt-1] = task_func;
- break;
- }
- case SCHR_PERIOD_500MS:
- {
- task_500ms_cnt++;
- task_500ms_list = (schr_task_func_t*)realloc(task_500ms_list, task_500ms_cnt * sizeof(schr_task_func_t));
- task_500ms_list[task_500ms_cnt-1] = task_func;
- break;
- }
- case SCHR_PERIOD_1000MS:
- {
- task_1000ms_cnt++;
- task_1000ms_list = (schr_task_func_t*)realloc(task_1000ms_list, task_1000ms_cnt * sizeof(schr_task_func_t));
- task_1000ms_list[task_1000ms_cnt-1] = task_func;
- break;
- }
- default:
- {
- break;
- }
- }
- }
- ```
- 2.2 定时器0初始化
- 初始化代码如下,设置超时时间为1s,在定时器0的中断服务函数中进行时间累计。
- ```c
- static void Schr_TimerInit(void)
- {
- TIMER_ConfigType timerConfig;
- memset(&timerConfig, 0, sizeof(timerConfig));
- /*!配置定时器.*/
- timerConfig.periodValue = Timeout1ms; /*! 定义超时值为1ms */
- timerConfig.linkModeEn = DISABLE; /*! 禁能链接模式 */
- timerConfig.interruptEn = ENABLE; /*! 使能定时器中断 */
- timerConfig.timerEn = ENABLE; /*! 打开定时器 */
- timerConfig.callBack = TIMER_CH0_Callback; /*! 中断回调函数 */
- TIMER_Init(TIMER_CHANNEL0, &timerConfig); /*! TIMER初始化函数生效 */
- }
- static void TIMER_CH0_Callback(void *device, uint32_t wpara, uint32_t lpara)
- {
- Schr_SchedulerRunning();
- }
2.3 主函数实现
主函数中,用于创建任务以及启动调度器。
- Print_Running()为新建的任务
- Schr_CreateTask()动态注册任务
- Schr_StartScheduler()启动调度器
- void Print_Running(void)
- {
- static uint32_t timer = 0;
- printf ("Timer escape for %ds\r\n", timer);
- timer++;
- }
- int main(void)
- {
- InitDelay();
-
- UART_Cfg_Init(); /*! 串口1初始化 */
- Schr_CreateTask(Print_Running, SCHR_PERIOD_1000MS);
- Schr_StartScheduler();
- while(1)
- {
- }
- }
3 试验效果
如下图所示,可以看到,与串口助手自带的时间戳上的时间进行对比,调度器还是十分准确的,记了10秒钟,算是比较精确。