Lancaster University's (short term!) clone of mbed-src for micro:bit. This is a copy of the github branch https://github.com/lancaster-university/mbed-classic

Fork of mbed-src by mbed official

Committer:
LancasterUniversity
Date:
Wed Jul 13 12:52:54 2016 +0100
Revision:
641:be9b2017785a
Parent:
525:c320967f86b9
Synchronized with git rev 1fb8ab4c
Author: James Devine
mbed-classic: BUGFIX for timer when using wait_ms from interrupt context

Previously if a user used wait[_ms,_us] in interrupt context the device would
hang indefinitely. This was due to incrementing overflowCount from
interrupt context only.

This meant that if a user used wait[_ms,_us] in an ISR with
the same or greater interrupt priority, it would result in an infinite
loop as the overflowCount variable would never be incremented, and
wait[_ms,_us] would never return.

This patch simply applies a better solution for the race condition
mentioned in the previous commit. It instead disables the timer1
interrupt and increments the overflowCount variable, preventing
the race condition whilst supporting wait[_ms,_us] in interrupt
context.

Who changed what in which revision?

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