Przeglądaj źródła

update timer

Signed-off-by: FuangCao <cavan.cao@foxmail.com>
FuangCao 5 lat temu
rodzic
commit
3ab99ec875
2 zmienionych plików z 90 dodań i 12 usunięć
  1. 88 12
      Application/libs/shark_task.c
  2. 2 0
      Application/libs/shark_task.h

+ 88 - 12
Application/libs/shark_task.c

@@ -3,6 +3,18 @@
 
 static u64 shark_mseconds;
 
+static u32 shark_timer_task_handler(void);
+
+static shark_timer_t shark_timer_head = {
+	.prev = &shark_timer_head,
+	.next = &shark_timer_head
+};
+
+static shark_task_t shark_task_head = {
+	.next = &shark_task_head,
+	.handler = shark_timer_task_handler
+};
+
 void SysTick_Handler(void)
 {
 	shark_mseconds++;
@@ -13,20 +25,86 @@ u64 shark_get_mseconds(void)
 	return shark_mseconds;
 }
 
-static u32 shark_task_timer(void)
+static inline void shark_timer_sync(void)
 {
-	return 1000;
+	shark_task_head.time = shark_timer_head.next->time;
 }
 
-static shark_task_t shark_task_head = {
-	.next = &shark_task_head,
-	.handler = shark_task_timer
-};
+void shark_timer_post(shark_timer_t *timer, u32 delay)
+{
+	shark_timer_t *node;
+	u64 time;
+
+	__disable_irq();
+
+	time = shark_mseconds + (delay > 0 ? delay : 1);
+
+	if (timer->prev != NULL) {
+		timer->prev->next = timer->next;
+	}
+
+	if (timer->next != NULL) {
+		timer->next->prev = timer->prev;
+	}
+
+	for (node = shark_timer_head.next; node != &shark_timer_head; node = node->next) {
+		if (node->time > time) {
+			break;
+		}
+	}
+
+	timer->prev = node->prev;
+	node->prev->next = timer;
+	node->prev = timer;
+	timer->next = node;
+	timer->time = time;
+	shark_timer_sync();
+
+	__enable_irq();
+}
+
+void shark_timer_cancel(shark_timer_t *timer)
+{
+	__disable_irq();
+
+	timer->prev->next = timer->next;
+	timer->next->prev = timer->prev;
+	timer->next = timer->prev = timer;
+	shark_timer_sync();
+
+	__enable_irq();
+}
+
+static u32 shark_timer_task_handler(void)
+{
+	while (1) {
+		shark_timer_t *timer = shark_timer_head.next;
+
+		if (timer->time > shark_mseconds) {
+			return timer->time - shark_mseconds;
+		}
+
+		if (timer != &shark_timer_head) {
+			shark_timer_cancel(timer);
+			timer->handler();
+		} else {
+			break;
+		}
+
+		fwdgt_counter_reload();
+	}
+
+	return 0xFFFFFFFF;
+}
 
 void shark_task_add(shark_task_t *task)
 {
+	__disable_irq();
+
 	task->next = shark_task_head.next;
 	shark_task_head.next = task;
+
+	__enable_irq();
 }
 
 void shark_task_run(void)
@@ -39,14 +117,12 @@ void shark_task_run(void)
 	NVIC_SetPriority(SysTick_IRQn, 0x00U);
 
 	while (1) {
-		shark_task_t *next = head->next;
-		u64 time = shark_mseconds;
+		fwdgt_counter_reload();
 
-		if (head->time <= time) {
-			head->time = time + head->handler();
+		if (head->time <= shark_mseconds) {
+			head->time = shark_mseconds + head->handler();
 		}
 
-		head = next;
-		fwdgt_counter_reload();
+		head = head->next;
 	}
 }

+ 2 - 0
Application/libs/shark_task.h

@@ -16,5 +16,7 @@ typedef struct shark_timer {
 } shark_timer_t;
 
 u64 shark_get_mseconds(void);
+void shark_timer_post(shark_timer_t *timer, u32 delay);
+void shark_timer_cancel(shark_timer_t *timer);
 void shark_task_add(shark_task_t *task);
 void shark_task_run(void);