1 /* mbed Microcontroller Library
2 * Copyright (c) 2006-2013 ARM Limited
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #include <stddef.h>
17 #include "us_ticker_api.h"
18 #include "cmsis.h"
19
20 static ticker_event_handler event_handler;
21 static ticker_event_t *head = NULL;
22
us_ticker_set_handler(ticker_event_handler handler)23 void us_ticker_set_handler(ticker_event_handler handler)
24 {
25 us_ticker_init();
26
27 event_handler = handler;
28 }
29
us_ticker_irq_handler(void)30 void us_ticker_irq_handler(void)
31 {
32 us_ticker_clear_interrupt();
33
34 /* Go through all the pending TimerEvents */
35 while (1) {
36 if (head == NULL) {
37 /* There are no more TimerEvents left, so disable matches. */
38 us_ticker_disable_interrupt();
39 return;
40 }
41
42 if ((int)(head->timestamp - us_ticker_read()) <= 0) {
43 /* This event was in the past: point to the following one and execute its handler */
44 ticker_event_t *p = head;
45 head = head->next;
46 if (event_handler != NULL) {
47 event_handler(p->id); // NOTE: the handler can set new events
48 }
49 /* Note: We continue back to examining the head because calling the */
50 /* event handler may have altered the chain of pending events. */
51 } else {
52 /* This event and the following ones in the list are in the future: set it as next interrupt and return */
53 us_ticker_set_interrupt(head->timestamp);
54 return;
55 }
56 }
57 }
58
us_ticker_insert_event(ticker_event_t * obj,timestamp_t timestamp,uint32_t id)59 void us_ticker_insert_event(ticker_event_t *obj, timestamp_t timestamp, uint32_t id)
60 {
61 /* disable interrupts for the duration of the function */
62 __disable_irq();
63
64 /* initialise our data */
65 obj->timestamp = timestamp;
66 obj->id = id;
67
68 /* Go through the list until we either reach the end, or find */
69 /* an element this should come before (which is possibly the head). */
70 ticker_event_t *prev = NULL, *p = head;
71 while (p != NULL) {
72 /* check if we come before p */
73 if ((int)(timestamp - p->timestamp) <= 0) {
74 break;
75 }
76 /* go to the next element */
77 prev = p;
78 p = p->next;
79 }
80 /* if prev is NULL we're at the head */
81 if (prev == NULL) {
82 head = obj;
83 us_ticker_set_interrupt(timestamp);
84 } else {
85 prev->next = obj;
86 }
87 /* if we're at the end p will be NULL, which is correct */
88 obj->next = p;
89
90 __enable_irq();
91 }
92
us_ticker_remove_event(ticker_event_t * obj)93 void us_ticker_remove_event(ticker_event_t *obj)
94 {
95 __disable_irq();
96
97 /* remove this object from the list */
98 if (head == obj) {
99 /* first in the list, so just drop me */
100 head = obj->next;
101 if (head == NULL) {
102 us_ticker_disable_interrupt();
103 } else {
104 us_ticker_set_interrupt(head->timestamp);
105 }
106 } else {
107 /* find the object before me, then drop me */
108 ticker_event_t* p = head;
109 while (p != NULL) {
110 if (p->next == obj) {
111 p->next = obj->next;
112 break;
113 }
114 p = p->next;
115 }
116 }
117
118 __enable_irq();
119 }
120