Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of gr-peach-opencv-project-sd-card by
mbed_ticker_api.c
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2015 ARM Limited 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 #include <stdio.h> 00017 #include <stddef.h> 00018 #include "hal/ticker_api.h" 00019 #include "platform/mbed_critical.h" 00020 00021 static void schedule_interrupt(const ticker_data_t *const ticker); 00022 static void update_present_time(const ticker_data_t *const ticker); 00023 00024 /* 00025 * Initialize a ticker instance. 00026 */ 00027 static void initialize(const ticker_data_t *ticker) 00028 { 00029 // return if the queue has already been initialized, in that case the 00030 // interface used by the queue is already initialized. 00031 if (ticker->queue->initialized) { 00032 return; 00033 } 00034 00035 ticker->interface->init(); 00036 00037 ticker->queue->event_handler = NULL; 00038 ticker->queue->head = NULL; 00039 ticker->queue->present_time = 0; 00040 ticker->queue->initialized = true; 00041 00042 update_present_time(ticker); 00043 schedule_interrupt(ticker); 00044 } 00045 00046 /** 00047 * Set the event handler function of a ticker instance. 00048 */ 00049 static void set_handler(const ticker_data_t *const ticker, ticker_event_handler handler) 00050 { 00051 ticker->queue->event_handler = handler; 00052 } 00053 00054 /* 00055 * Convert a 32 bit timestamp into a 64 bit timestamp. 00056 * 00057 * A 64 bit timestamp is used as the point of time of reference while the 00058 * timestamp to convert is relative to this point of time. 00059 * 00060 * The lower 32 bits of the timestamp returned will be equal to the timestamp to 00061 * convert. 00062 * 00063 * If the timestamp to convert is less than the lower 32 bits of the time 00064 * reference then the timestamp to convert is seen as an overflowed value and 00065 * the upper 32 bit of the timestamp returned will be equal to the upper 32 bit 00066 * of the reference point + 1. 00067 * Otherwise, the upper 32 bit returned will be equal to the upper 32 bit of the 00068 * reference point. 00069 * 00070 * @param ref: The 64 bit timestamp of reference. 00071 * @param timestamp: The timestamp to convert. 00072 */ 00073 static us_timestamp_t convert_timestamp(us_timestamp_t ref, timestamp_t timestamp) 00074 { 00075 bool overflow = timestamp < ((timestamp_t) ref) ? true : false; 00076 00077 us_timestamp_t result = (ref & ~((us_timestamp_t)UINT32_MAX)) | timestamp; 00078 if (overflow) { 00079 result += (1ULL<<32); 00080 } 00081 00082 return result; 00083 } 00084 00085 /** 00086 * Update the present timestamp value of a ticker. 00087 */ 00088 static void update_present_time(const ticker_data_t *const ticker) 00089 { 00090 ticker->queue->present_time = convert_timestamp( 00091 ticker->queue->present_time, 00092 ticker->interface->read() 00093 ); 00094 } 00095 00096 /** 00097 * Compute the time when the interrupt has to be triggered and schedule it. 00098 * 00099 * If there is no event in the queue or the next event to execute is in more 00100 * than MBED_TICKER_INTERRUPT_TIMESTAMP_MAX_DELTA us from now then the ticker 00101 * irq will be scheduled in MBED_TICKER_INTERRUPT_TIMESTAMP_MAX_DELTA us. 00102 * Otherwise the irq will be scheduled to happen when the running counter reach 00103 * the timestamp of the first event in the queue. 00104 * 00105 * @note If there is no event in the queue then the interrupt is scheduled to 00106 * in MBED_TICKER_INTERRUPT_TIMESTAMP_MAX_DELTA. This is necessary to keep track 00107 * of the timer overflow. 00108 */ 00109 static void schedule_interrupt(const ticker_data_t *const ticker) 00110 { 00111 update_present_time(ticker); 00112 uint32_t relative_timeout = MBED_TICKER_INTERRUPT_TIMESTAMP_MAX_DELTA; 00113 00114 if (ticker->queue->head) { 00115 us_timestamp_t present = ticker->queue->present_time; 00116 us_timestamp_t next_event_timestamp = ticker->queue->head->timestamp; 00117 00118 // if the event at the head of the queue is in the past then schedule 00119 // it immediately. 00120 if (next_event_timestamp < present) { 00121 relative_timeout = 0; 00122 } else if ((next_event_timestamp - present) < MBED_TICKER_INTERRUPT_TIMESTAMP_MAX_DELTA) { 00123 relative_timeout = next_event_timestamp - present; 00124 } 00125 } 00126 00127 ticker->interface->set_interrupt(ticker->queue->present_time + relative_timeout); 00128 } 00129 00130 void ticker_set_handler(const ticker_data_t *const ticker, ticker_event_handler handler) 00131 { 00132 initialize(ticker); 00133 set_handler(ticker, handler); 00134 } 00135 00136 void ticker_irq_handler(const ticker_data_t *const ticker) 00137 { 00138 ticker->interface->clear_interrupt(); 00139 00140 /* Go through all the pending TimerEvents */ 00141 while (1) { 00142 if (ticker->queue->head == NULL) { 00143 break; 00144 } 00145 00146 // update the current timestamp used by the queue 00147 update_present_time(ticker); 00148 00149 if (ticker->queue->head->timestamp <= ticker->queue->present_time) { 00150 // This event was in the past: 00151 // point to the following one and execute its handler 00152 ticker_event_t *p = ticker->queue->head; 00153 ticker->queue->head = ticker->queue->head->next; 00154 if (ticker->queue->event_handler != NULL) { 00155 (*ticker->queue->event_handler)(p->id); // NOTE: the handler can set new events 00156 } 00157 /* Note: We continue back to examining the head because calling the 00158 * event handler may have altered the chain of pending events. */ 00159 } else { 00160 break; 00161 } 00162 } 00163 00164 schedule_interrupt(ticker); 00165 } 00166 00167 void ticker_insert_event(const ticker_data_t *const ticker, ticker_event_t *obj, timestamp_t timestamp, uint32_t id) 00168 { 00169 core_util_critical_section_enter(); 00170 00171 // update the current timestamp 00172 update_present_time(ticker); 00173 us_timestamp_t absolute_timestamp = convert_timestamp( 00174 ticker->queue->present_time, 00175 timestamp 00176 ); 00177 core_util_critical_section_exit(); 00178 00179 // defer to ticker_insert_event_us 00180 ticker_insert_event_us( 00181 ticker, 00182 obj, absolute_timestamp, id 00183 ); 00184 } 00185 00186 void ticker_insert_event_us(const ticker_data_t *const ticker, ticker_event_t *obj, us_timestamp_t timestamp, uint32_t id) 00187 { 00188 core_util_critical_section_enter(); 00189 00190 // update the current timestamp 00191 update_present_time(ticker); 00192 00193 // initialise our data 00194 obj->timestamp = timestamp; 00195 obj->id = id; 00196 00197 /* Go through the list until we either reach the end, or find 00198 an element this should come before (which is possibly the 00199 head). */ 00200 ticker_event_t *prev = NULL, *p = ticker->queue->head; 00201 while (p != NULL) { 00202 /* check if we come before p */ 00203 if (timestamp < p->timestamp) { 00204 break; 00205 } 00206 /* go to the next element */ 00207 prev = p; 00208 p = p->next; 00209 } 00210 00211 /* if we're at the end p will be NULL, which is correct */ 00212 obj->next = p; 00213 00214 /* if prev is NULL we're at the head */ 00215 if (prev == NULL) { 00216 ticker->queue->head = obj; 00217 } else { 00218 prev->next = obj; 00219 } 00220 00221 schedule_interrupt(ticker); 00222 00223 core_util_critical_section_exit(); 00224 } 00225 00226 void ticker_remove_event(const ticker_data_t *const ticker, ticker_event_t *obj) 00227 { 00228 core_util_critical_section_enter(); 00229 00230 // remove this object from the list 00231 if (ticker->queue->head == obj) { 00232 // first in the list, so just drop me 00233 ticker->queue->head = obj->next; 00234 schedule_interrupt(ticker); 00235 } else { 00236 // find the object before me, then drop me 00237 ticker_event_t* p = ticker->queue->head; 00238 while (p != NULL) { 00239 if (p->next == obj) { 00240 p->next = obj->next; 00241 break; 00242 } 00243 p = p->next; 00244 } 00245 } 00246 00247 core_util_critical_section_exit(); 00248 } 00249 00250 timestamp_t ticker_read(const ticker_data_t *const ticker) 00251 { 00252 return ticker_read_us(ticker); 00253 } 00254 00255 us_timestamp_t ticker_read_us(const ticker_data_t *const ticker) 00256 { 00257 update_present_time(ticker); 00258 return ticker->queue->present_time; 00259 } 00260 00261 int ticker_get_next_timestamp(const ticker_data_t *const data, timestamp_t *timestamp) 00262 { 00263 int ret = 0; 00264 00265 /* if head is NULL, there are no pending events */ 00266 core_util_critical_section_enter(); 00267 if (data->queue->head != NULL) { 00268 *timestamp = data->queue->head->timestamp; 00269 ret = 1; 00270 } 00271 core_util_critical_section_exit(); 00272 00273 return ret; 00274 } 00275
Generated on Tue Jul 12 2022 14:47:26 by
