task_.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. #include "libs/task.h"
  2. #include "bsp/bsp.h"
  3. static u64 task_mseconds;
  4. static task_t _task_handler[MAX_TASK];
  5. static u32 timer_task_handler(void);
  6. static timer_t timer_head = {
  7. .prev = &timer_head,
  8. .next = &timer_head
  9. };
  10. static task_t task_head = {
  11. .next = &task_head,
  12. .handler = timer_task_handler
  13. };
  14. void system_tick_handler(void)
  15. {
  16. task_mseconds++;
  17. }
  18. u64 get_mseconds(void)
  19. {
  20. return task_mseconds;
  21. }
  22. u32 get_seconds(void){
  23. return task_mseconds/1000;
  24. }
  25. void task_ticks_enable(void)
  26. {
  27. CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
  28. DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
  29. }
  30. u32 task_ticks_abs(void)
  31. {
  32. return DWT->CYCCNT;
  33. }
  34. u32 task_ticks_rel(u32 start)
  35. {
  36. u32 ticks = DWT->CYCCNT;
  37. if (ticks >= start) {
  38. return ticks - start;
  39. }
  40. return 0xFFFFFFFF - start + ticks + 1;
  41. }
  42. void task_ticks_delay(u32 ticks)
  43. {
  44. u32 start;
  45. start = task_ticks_abs();
  46. while (task_ticks_rel(start) < ticks);
  47. }
  48. void task_udelay(u32 delay)
  49. {
  50. task_ticks_delay(delay * (SystemCoreClock / 1000000));
  51. }
  52. static inline void timer_sync(void)
  53. {
  54. task_head.time = timer_head.next->time;
  55. }
  56. void timer_post(timer_t *timer, u32 delay)
  57. {
  58. timer_t *node;
  59. u64 time;
  60. __disable_irq();
  61. time = task_mseconds + (delay > 0 ? delay : 1);
  62. if (timer->prev != NULL) {
  63. timer->prev->next = timer->next;
  64. }
  65. if (timer->next != NULL) {
  66. timer->next->prev = timer->prev;
  67. }
  68. for (node = timer_head.next; node != &timer_head; node = node->next) {
  69. if (node->time > time) {
  70. break;
  71. }
  72. }
  73. timer->prev = node->prev;
  74. node->prev->next = timer;
  75. node->prev = timer;
  76. timer->next = node;
  77. timer->time = time;
  78. timer_sync();
  79. __enable_irq();
  80. }
  81. void timer_cancel(timer_t *timer)
  82. {
  83. __disable_irq();
  84. if (timer->prev != NULL && timer->next != NULL) {
  85. timer->prev->next = timer->next;
  86. timer->next->prev = timer->prev;
  87. }
  88. timer->next = timer->prev = timer;
  89. timer_sync();
  90. __enable_irq();
  91. }
  92. static u32 timer_task_handler(void)
  93. {
  94. while (1) {
  95. timer_t *timer = timer_head.next;
  96. if (timer->time > task_mseconds) {
  97. return timer->time - task_mseconds;
  98. }
  99. if (timer != &timer_head) {
  100. timer_cancel(timer);
  101. timer->handler(timer);
  102. } else {
  103. break;
  104. }
  105. wdog_reload();
  106. }
  107. return 0xFFFFFFFF;
  108. }
  109. void task_add(task_t *task)
  110. {
  111. __disable_irq();
  112. task->next = task_head.next;
  113. task_head.next = task;
  114. __enable_irq();
  115. }
  116. task_t* task_start(task_func func, u32 delay){
  117. task_t *task = NULL;
  118. for (int i = 0; i < MAX_TASK; i++) {
  119. __disable_irq();
  120. if (_task_handler[i].handler == NULL) {
  121. task = _task_handler + i;
  122. task->handler = func;
  123. task->time = delay;
  124. task->next = task_head.next;
  125. task_head.next = task;
  126. __enable_irq();
  127. return task;
  128. }
  129. __enable_irq();
  130. }
  131. return NULL;
  132. }
  133. void task_run(void)
  134. {
  135. task_t *head = &task_head;
  136. while (1) {
  137. wdog_reload();
  138. if (head->time <= task_mseconds) {
  139. head->time = task_mseconds + head->handler();
  140. }
  141. head = head->next;
  142. }
  143. }