Morpheus / mbed-hal

Dependencies:   target-freescale

Committer:
screamer
Date:
Wed Mar 23 21:36:09 2016 +0000
Revision:
0:9c59db1fbc9e
Initial revision

Who changed what in which revision?

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