嵌入式技术论坛
直播中

ss

7年用户 8762经验值
擅长:电源/新能源 制造/封装 RF/无线
私信 关注
[经验]

如何将RT-Thread中的timer改成裸机程序呢

  前言
  RTOS使用多了,是不是认为一切皆RTOS,其实小的设备,反而使用裸机程序也是可以完成的
  本篇把RT-Thread中的timer,通过【魔改】的方式,改成裸机程序
  裸机程序,虽然没有OS,也需要设计一些软件架构,让开发更高效
  移植方法
  移除操作系统的依赖
  修复编译
  API重命名
  验证平台
  STM32L476平台,理论上稍微调整,可以用于多个平台
  timer部分尽量保证平台无关
  由于没有充分的测试验证,不清楚是否有BUG
  由于基于systick,默认1ms的硬件定时器,所以定时器回调中,执行时间不能过长
  实现代码
  timer.h : 定义timer使用的数据类型与结构,timer的API
  #ifndef __TIMER_H__
  #define __TIMER_H__
  #include 《stdint.h》
  #define TIMER_FLAG_DEACTIVATED 0x00
  #define TIMER_FLAG_ACTIVATED 0x01
  #define TIMER_FLAG_ONE_SHOT 0x00
  #define TIMER_FLAG_PERIODIC 0x02
  #define TIMER_CTRL_GET_TIME 0x01
  #define TIMER_CTRL_SET_TIME 0x02
  #define TIMER_CTRL_SET_ONESHOT 0x04
  #define TIMER_CTRL_SET_PERIODIC 0x08
  #define TIMER_CTRL_GET_STATE 0x10
  #define TIM_NULL 0
  #define TIM_EOK 0
  #define TIM_ERROR 1
  #define TIM_TICK_MAX 0xffffffff
  #define TIM_ASSERT(ex)
  if (!(ex))
  {
  while (1);
  }
  struct list_head
  {
  struct list_head *next;
  struct list_head *prev;
  };
  static inline void INIT_LIST_HEAD(struct list_head *list)
  {
  list-》next = list;
  list-》prev = list;
  }
  #define container_of(ptr, type, member)
  ((type *)((char *)(ptr) - (unsigned long)(&((type *)0)-》member)))
  #define list_entry(ptr, type, member)
  container_of(ptr, type, member)
  static inline void __list_add(struct list_head *new,
  struct list_head *prev,
  struct list_head *next)
  {
  next-》prev = new;
  new-》next = next;
  new-》prev = prev;
  prev-》next = new;
  }
  static inline void list_add(struct list_head *new, struct list_head *head)
  {
  __list_add(new, head, head-》next);
  }
  static inline void list_add_tail(struct list_head *new, struct list_head *head)
  {
  __list_add(new, head-》prev, head);
  }
  static inline void __list_del(struct list_head *prev, struct list_head *next)
  {
  next-》prev = prev;
  prev-》next = next;
  }
  static inline void list_del_init(struct list_head *entry)
  {
  __list_del(entry-》prev, entry-》next);
  INIT_LIST_HEAD(entry);
  }
  static inline int list_empty(const struct list_head *head)
  {
  return head-》next == head;
  }
  typedef struct list_head dl_list_t;
  struct sys_time
  {
  uint32_t flag;
  dl_list_t list;
  void (*timeout_func)(void *arg);
  void *arg;
  uint32_t init_tick;
  uint32_t timeout_tick;
  };
  typedef struct sys_timer sys_timer_t;
  uint32_t isr_enable(void);
  void isr_disable(uint32_t level);
  uint32_t tick_get(void);
  void tick_set(uint32_t tick);
  void tick_increase(void);
  void timer_init(sys_timer_t *timer,
  void (*timeout_func)(void *param),
  void *param,
  uint32_t ticks,
  uint32_t flag);
  int32_t timer_detach(sys_timer_t *timer);
  int32_t timer_start(sys_timer_t *timer);
  int32_t timer_stop(sys_timer_t *timer);
  void system_timer_init(void);
  int32_t timer_control(sys_timer_t *timer, int cmd, void *arg);
  void timer_check(void);
  #endif
  timer.c 的实现:
  #include 《timer.h》
  static uint32_t tim_tick = 0;
  /* systick : system timer list */
  static struct list_head system_timer_list;
  uint32_t isr_enable(void)
  {
  return 1;
  }
  void isr_disable(uint32_t level)
  {
  }
  uint32_t tick_get(void)
  {
  return tim_tick;
  }
  void tick_set(uint32_t tick)
  {
  uint32_t level;
  level = isr_enable();
  tim_tick = tick;
  isr_disable(level);
  }
  void tick_increase(void)
  {
  uint32_t irq_lock;
  irq_lock = isr_enable();
  tim_tick++;
  isr_disable(irq_lock);
  timer_check();
  }
  dl_list_t * get_system_timer_list(void)
  {
  return &system_timer_list;
  }
  static void _timer_init(sys_timer_t *timer,
  void (*timeout_func)(void *arg),
  void *arg,
  uint32_t ticks,
  uint32_t flag)
  {
  timer-》flag = flag;
  timer-》flag &= ~TIMER_FLAG_ACTIVATED;
  timer-》timeout_func = timeout_func;
  timer-》arg = arg;
  timer-》timeout_tick = 0;
  timer-》init_tick = ticks;
  INIT_LIST_HEAD(&(timer-》list));
  }
  void timer_init(sys_timer_t *timer,
  void (*timeout_func)(void *arg),
  void *arg,
  uint32_t ticks,
  uint32_t flag)
  {
  TIM_ASSERT(timer != TIM_NULL);
  _timer_init(timer, timeout_func, arg, ticks, flag);
  }
  int32_t timer_detach(sys_timer_t *timer)
  {
  uint32_t irq_lock
  TIM_ASSERT(timer != TIM_NULL);
  irq_lock = isr_enable();
  list_del_init(&timer-》list);
  timer-》flag &= ~TIMER_FLAG_ACTIVATED;
  isr_disable(irq_lock);
  return TIM_EOK;
  }
  int32_t timer_start(sys_timer_t *timer)
  {
  uint32_t irq_lock;
  dl_list_t *timer_list = TIM_NULL;
  dl_list_t *list = TIM_NULL;
  sys_timer_t *tm = TIM_NULL;
  TIM_ASSERT(timer != TIM_NULL);
  TIM_ASSERT(timer-》init_tick 《 TIM_TICK_MAX / 2);
  irq_lock = isr_enable();
  /* step1 : stop timer */
  list_del_init(&timer-》list);
  timer-》flag &= ~TIMER_FLAG_ACTIVATED;
  timer-》timeout_tick = tick_get() + timer-》init_tick;
  timer_list = &system_timer_list;
  for (list = timer_list; list != timer_list-》prev; list = list-》next)
  {
  tm = list_entry(list-》next, sys_timer_t, list);
  if (tm-》timeout_tick - timer-》timeout_tick == 0)
  {
  continue;
  }
  else if ((tm-》timeout_tick - timer-》timeout_tick) 《 TIM_TICK_MAX / 2)
  {
  break;
  }
  }
  list_add(&timer-》list, list); /* add to tail */
  timer-》flag |= TIMER_FLAG_ACTIVATED; /* set activated flag */
  isr_disable(irq_lock);
  return TIM_EOK;
  }
  int32_t timer_stop(sys_timer_t *timer)
  {
  uint32_t irq_lock;
  TIM_ASSERT(timer != TIM_NULL);
  if (!(timer-》flag & TIMER_FLAG_ACTIVATED))
  {
  return TIM_ERROR;
  }
  irq_lock = isr_enable();
  list_del_init(&timer-》list);
  timer-》flag &= ~TIMER_FLAG_ACTIVATED;
  isr_disable(irq_lock);
  return TIM_EOK;
  }
  void system_timer_init(void)
  {
  INIT_LIST_HEAD(&system_timer_list);
  }
  int32_t timer_control(sys_timer_t *timer, int cmd, void *arg)
  {
  uint32_t irq_lock;
  TIM_ASSERT(timer != TIM_NULL);
  irq_lock = isr_enable();
  switch (cmd)
  {
  case TIMER_CTRL_GET_TIME:
  *(uint32_t *)arg = timer-》init_tick;
  break;
  case TIMER_CTRL_SET_TIME:
  timer-》init_tick = *(uint32_t *)arg;
  break;
  case TIMER_CTRL_SET_ONESHOT:
  timer-》flag &= ~TIMER_FLAG_PERIODIC;
  break;
  case TIMER_CTRL_SET_PERIODIC:
  timer-》flag |= TIMER_FLAG_PERIODIC;
  break;
  case TIMER_CTRL_GET_STATE:
  if (timer-》flag & TIMER_FLAG_ACTIVATED)
  {
  *(uint32_t *)arg = TIMER_FLAG_ACTIVATED;
  }
  else
  {
  *(uint32_t *)arg = TIMER_FLAG_DEACTIVATED;
  }
  break;
  default:
  break;
  }
  isr_disable(irq_lock);
  return TIM_EOK;
  }
  void timer_check(void)
  {
  uint32_t irq_lock;
  sys_timer_t *tm;
  uint32_t cur_tick;
  dl_list_t temp_list;
  INIT_LIST_HEAD(&temp_list);
  cur_tick = tick_get();
  irq_lock = isr_enable();
  while (!list_empty(&system_timer_list))
  {
  tm = list_entry(system_timer_list.next, sys_timer_t, list);
  if ((cur_tick - tm-》timeout_tick) 《 TIM_TICK_MAX / 2)
  {
  list_del_init(&tm-》list);
  if (!(tm-》flag & TIMER_FLAG_PERIODIC))
  {
  tm-》flag &= ~TIMER_FLAG_ACTIVATED;
  }
  list_add(&(tm-》list), &temp_list); /* insert temp list */
  tm-》timeout_func(tm-》arg);
  cur_tick = tick_get();
  /* check timer object is detached or started again */
  if (list_empty(&temp_list))
  {
  continue;
  }
  list_del_init(&tm-》list);
  if ((tm-》flag & TIMER_FLAG_PERIODIC) &&
  (tm-》flag & TIMER_FLAG_ACTIVATED))
  {
  tm-》flag &= ~TIMER_FLAG_ACTIVATED;
  timer_start(tm);
  }
  }
  else
  {
  break;
  }
  }
  isr_disable(irq_lock);
  }
  测试 timer_test.c
  #include 《timer_test.h》
  #include 《board.h》
  static sys_timer_t timer_test1;
  static sys_timer_t timer_test2;
  static sys_timer_t timer_test3;
  void timer_test1_timeout_func(void *param)
  {
  printk(“tim1 func, tick=%drn”, tick_get());
  }
  void timer_test1_init(void)
  {
  timer_init(&timer_test1,
  timer_test1_timeout_func,
  TIM_NULL,
  1000,
  TIMER_FLAG_ONE_SHOT);
  }
  void timer_test1_start(void)
  {
  timer_start(&timer_test1);
  }
  void timer_test1_stop(void)
  {
  timer_stop(&timer_test1);
  }
  void timer_test2_timeout_func(void *param)
  {
  printk(“tim2 func, tick=%drn”, tick_get());
  //os_timer_start(&timer_test2);
  }
  void timer_test2_init(void)
  {
  timer_init(&timer_test2,
  timer_test2_timeout_func,
  TIM_NULL,
  2000,
  TIMER_FLAG_PERIODIC);
  }
  void timer_test2_start(void)
  {
  timer_start(&timer_test2);
  }
  void timer_test2_stop(void)
  {
  timer_stop(&timer_test2);
  }
  void timer_test3_timeout_func(void *param)
  {
  printk(“tim3 func, tick=%drn”, tick_get());
  }
  void timer_test3_init(void)
  {
  timer_init(&timer_test3,
  timer_test3_timeout_func,
  TIM_NULL,
  5000,
  TIMER_FLAG_PERIODIC);
  }
  void timer_test3_start(void)
  {
  timer_start(&timer_test3);
  }
  void timer_test3_stop(void)
  {
  timer_stop(&timer_test3);
  }
  int timer_test_handler(void)
  {
  system_timer_init();
  timer_test1_init();
  timer_test2_init();
  timer_test3_init();
  timer_test1_start();
  timer_test2_start();
  timer_test3_start();
  return 0;
  }
  test_timer.h
  #ifndef __TIMER_TEST_H__
  #define __TIMER_TEST_H__
  #include “timer.h”
  int os_timer_run_test(void);
  #endif
  main 函数:
  /*
  * 裸机工程:用于功能验证
  * 硬件平台:STM32L476RG : NUCLEO-L476RG
  * 2022-01-15
  */
  #include “board.h”
  #include “timer_test.h”
  #define USART2_BAUDRATE 115200
  /**
  * @Brief The application entry point.
  * @retval int
  */
  int main(void)
  {
  HAL_Init();
  SystemClock_Config();
  bsp_systick_init();
  MX_GPIO_Init();
  usart2_init(USART2_BAUDRATE);
  LEDG_GPIO_Init();
  printk(“hello, NUCLEO-L476RGrn”);
  os_timer_run_test();
  while (1)
  {
  LEDG_power_ctrl(1);
  HAL_Delay(1000);
  LEDG_power_ctrl(0);
  HAL_Delay(1000);
  }
  }
  systick.c : 这里使用systick实现1ms计数
  #include 《board.h》
  /**
  * @brief This function handles System tick timer.
  */
  void SysTick_Handler(void)
  {
  HAL_IncTick();
  tick_increase();
  }
  HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
  return HAL_OK;
  }
  void bsp_systick_init(void)
  {
  HAL_SYSTICK_Config(SystemCoreClock / 1000);
  NVIC_SetPriority(SysTick_IRQn, 0xFF);
  }
  验证效果
  这里使用uart串口打印,类似于printf
  hello, NUCLEO-L476RG
  tim1 func, tick=1002
  tim2 func, tick=2002
  tim2 func, tick=4002
  tim3 func, tick=5002
  tim2 func, tick=6002
  tim2 func, tick=8002
  tim3 func, tick=10002
  tim2 func, tick=10002
  tim2 func, tick=12002
  tim2 func, tick=14002
  tim3 func, tick=15002
  tim2 func, tick=16002
  tim2 func, tick=18002
  tim3 func, tick=20002
  tim2 func, tick=20002
  验证效果初步符合预期
  小结
  基本实现的定时器的初始化、开启、停止等功能
  占用资源不算太多,主要可以方便实现多个定时器应用。

更多回帖

发帖
×
20
完善资料,
赚取积分