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.
Revision 0:906c21fbf97c, committed 2010-09-27
- Comitter:
- kasturir
- Date:
- Mon Sep 27 22:51:19 2010 +0000
- Commit message:
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp Mon Sep 27 22:51:19 2010 +0000
@@ -0,0 +1,58 @@
+// Author: kasturir@ucla.edu (Kasturi Rangan Raghavan)
+// \file
+// QRSDet library ported to OOP
+// Allows easy adjustment of sampling rates
+
+#include <mbed.h>
+#include <scmRTOS.h>
+#include <qrsdet/qrsdet2-inl.h>
+
+AnalogIn ecg_in(p20);
+DigitalOut led1(LED1);
+DigitalOut led2(LED2);
+PwmOut led3(LED3);
+DigitalOut led4(LED4);
+
+
+typedef OS::process<OS::pr0, 200> TEcgSampler;
+
+TEcgSampler EcgSampler;
+
+OS::TEventFlag ecg_sampler_ef;
+
+int main() {
+ OS::Run();
+}
+
+template<> OS_PROCESS void TEcgSampler::Exec() {
+ float float_val;
+ int int_val;
+ qrsdet::QRSFilterParams qrs_filter_params(8.0);
+ qrsdet::QRSDet2 *qrs_filter =
+ new qrsdet::QRSDet2(qrs_filter_params);
+ qrsdet::DelayFilter *delay_filter = new qrsdet::DelayFilter(45);
+ for(;;) {
+ ecg_sampler_ef.Wait();
+ led2 = !led2;
+ float_val = ecg_in.read();
+ int_val = float_val * 128;
+ int qrs_val = qrs_filter->Process(int_val);
+ int delay_val = delay_filter->Process(int_val);
+ led3 = delay_val/128.0;
+ if (qrs_val > 0) led4 = !led4;
+
+ }
+}
+
+void OS::SystemTimerUserHook() {
+ static int cnt=0;
+ if (++cnt == 8) {
+ cnt = 0;
+ led1 = !led1;
+ ecg_sampler_ef.Signal();
+ }
+}
+
+void OS::IdleProcessUserHook() {
+ __WFI();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Mon Sep 27 22:51:19 2010 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/e2ac27c8e93e
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/qrsdet/qrsdet2-inl.h Mon Sep 27 22:51:19 2010 +0000
@@ -0,0 +1,320 @@
+#ifndef ECG_THIRD_EPLIMITED_QRSDET2_INL_H_
+#define ECG_THIRD_EPLIMITED_QRSDET2_INL_H_
+// Modified to OOP class sturcture
+// Author: Kasturi Rangan Raghavan
+/*****************************************************************************
+FILE: qrsdet2.cpp
+AUTHOR: Patrick S. Hamilton
+REVISED: 7/08/2002
+ ___________________________________________________________________________
+
+qrsdet2.cpp: A QRS detector.
+Copywrite (C) 2002 Patrick S. Hamilton
+
+This file is free software; you can redistribute it and/or modify it under
+the terms of the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your option) any
+later version.
+
+This software is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+PARTICULAR PURPOSE. See the GNU Library General Public License for more
+details.
+
+You should have received a copy of the GNU Library General Public License along
+with this library; if not, write to the Free Software Foundation, Inc., 59
+Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+You may contact the author by e-mail (pat@eplimited.edu) or postal mail
+(Patrick Hamilton, E.P. Limited, 35 Medford St., Suite 204 Somerville,
+MA 02143 USA). For updates to this software, please visit our website
+(http://www.eplimited.com).
+ __________________________________________________________________________
+
+This file contains functions for detecting QRS complexes in an ECG. The
+QRS detector requires filter functions in qrsfilt.cpp and parameter
+definitions in qrsdet.h. QRSDet is the only function that needs to be
+visable outside of these files.
+
+Syntax:
+ int QRSDet(int ecgSample, int init) ;
+
+Description:
+ QRSDet() implements a modified version of the QRS detection
+ algorithm described in:
+
+ Hamilton, Tompkins, W. J., "Quantitative investigation of QRS
+ detection rules using the MIT/BIH arrhythmia database",
+ IEEE Trans. Biomed. Eng., BME-33, pp. 1158-1165, 1987.
+
+ Consecutive ECG samples are passed to QRSDet. QRSDet was
+ designed for a 200 Hz sample rate. QRSDet contains a number
+ of static variables that it uses to adapt to different ECG
+ signals. These variables can be reset by passing any value
+ not equal to 0 in init.
+
+ Note: QRSDet() requires filters in QRSFilt.cpp
+
+Returns:
+ When a QRS complex is detected QRSDet returns the detection delay.
+
+****************************************************************/
+
+/* For memmove. */
+#ifdef __STDC__
+#include <string.h>
+#else
+#include <mem.h>
+#endif
+
+#include "qrsfilt-inl.h"
+
+
+namespace qrsdet {
+
+int mean(int *array, int datnum);
+
+int detection_thresh(int qmean, int nmean);
+
+
+// TODO(krr) : Where to put this?
+const int MEMMOVELEN = 7*sizeof(int);
+
+
+class QRSDet2 {
+ public:
+ QRSDet2(const QRSFilterParams& params)
+ : qrs_filter(params),
+ peak_detector(params),
+ first_derivative_filter(params.get_d_length()),
+ bls_check_buffer(params) {
+ rsetCount = 0;
+ sbcount = params.get_ms(1500);
+ ms_preblank_ = params.get_ms(200);
+ ms_360_ = params.get_ms(360);
+ ms_1000_ = params.get_ms(1000);
+ ms_1650_ = params.get_ms(1650);
+ ms_window_length_ = params.get_window_length();
+ ms_filter_delay_ = params.get_filter_delay();
+
+ for (int i = 0; i < 8; i++) {
+ noise[i] = 0; /* Initialize noise buffer */
+ rrbuf[i] = ms_1000_;/* and R-to-R interval buffer. */
+ }
+ qpkcnt = maxder = lastmax = count = sbpeak = 0 ;
+ initBlank = initMax = preBlankCnt = 0 ;
+ }
+
+ int Process(int datum) {
+ int fdatum, QrsDelay = 0;
+ int newPeak, aPeak;
+ fdatum = qrs_filter.Process(datum);
+ /* Wait until normal detector is ready before calling early detections. */
+ aPeak = peak_detector.Process(fdatum);
+ if (aPeak < QRSDet2::MIN_PEAK_AMP)
+ aPeak = 0;
+
+ // Hold any peak that is detected for 200 ms
+ // in case a bigger one comes along. There
+ // can only be one QRS complex in any 200 ms window.
+
+ newPeak = 0;
+ if (aPeak && !preBlankCnt) {
+ // If there has been no peak for 200 ms
+ // save this one and start counting.
+ tempPeak = aPeak;
+ preBlankCnt = ms_preblank_;
+ } else if (!aPeak && preBlankCnt) {
+ // If we have held onto a peak for
+ // 200 ms pass it on for evaluation.
+ if (--preBlankCnt == 0)
+ newPeak = tempPeak ;
+ } else if (aPeak) {
+ // If we were holding a peak, but
+ // this ones bigger, save it and
+ if (aPeak > tempPeak) {
+ // start counting to 200 ms again.
+ tempPeak = aPeak ;
+ preBlankCnt = ms_preblank_;
+ } else if (--preBlankCnt == 0) {
+ newPeak = tempPeak ;
+ }
+ }
+
+ // Save derivative of raw signal for T-wave and baseline
+ // shift discrimination.
+ int deriv_datum = first_derivative_filter.Process(datum);
+ bls_check_buffer.Process(deriv_datum);
+
+ // Initialize the qrs peak buffer with the first eight
+ // local maximum peaks detected.
+ if (qpkcnt < 8) {
+ ++count;
+ if (newPeak > 0)
+ count = ms_window_length_;
+ if (++initBlank == ms_1000_) {
+ initBlank = 0;
+ qrsbuf[qpkcnt] = initMax;
+ initMax = 0;
+ ++qpkcnt;
+ if (qpkcnt == 8) {
+ qmean = mean(qrsbuf, 8) ;
+ nmean = 0 ;
+ rrmean = ms_1000_ ;
+ sbcount = ms_1650_ ;
+ det_thresh = detection_thresh(qmean,nmean) ;
+ }
+ }
+ if (newPeak > initMax)
+ initMax = newPeak ;
+ }
+
+ else /* Else test for a qrs. */
+ {
+ ++count ;
+ if(newPeak > 0)
+ {
+
+
+ /* Check for maximum derivative and matching minima and maxima
+ for T-wave and baseline shift rejection. Only consider this
+ peak if it doesn't seem to be a base line shift. */
+
+ if(!bls_check_buffer.BLSCheck(&maxder))
+ {
+
+
+ // Classify the beat as a QRS complex
+ // if the peak is larger than the detection threshold.
+
+ if(newPeak > det_thresh)
+ {
+ memmove(&qrsbuf[1], qrsbuf, MEMMOVELEN) ;
+ qrsbuf[0] = newPeak ;
+ qmean = mean(qrsbuf,8) ;
+ det_thresh = detection_thresh(qmean,nmean) ;
+ memmove(&rrbuf[1], rrbuf, MEMMOVELEN) ;
+ rrbuf[0] = count - ms_window_length_ ;
+ rrmean = mean(rrbuf,8) ;
+ sbcount = rrmean + (rrmean >> 1) + ms_window_length_ ;
+ count = ms_window_length_ ;
+
+ sbpeak = 0 ;
+
+ lastmax = maxder ;
+ maxder = 0 ;
+ QrsDelay = ms_window_length_ + ms_filter_delay_ ;
+ initBlank = initMax = rsetCount = 0 ;
+ }
+
+ // If a peak isn't a QRS update noise buffer and estimate.
+ // Store the peak for possible search back.
+
+
+ else
+ {
+ memmove(&noise[1],noise,MEMMOVELEN) ;
+ noise[0] = newPeak ;
+ nmean = mean(noise,8) ;
+ det_thresh = detection_thresh(qmean,nmean) ;
+
+ // Don't include early peaks (which might be T-waves)
+ // in the search back process. A T-wave can mask
+ // a small following QRS.
+
+ if((newPeak > sbpeak) && ((count-ms_window_length_) >= ms_360_))
+ {
+ sbpeak = newPeak ;
+ sbloc = count - ms_window_length_ ;
+ }
+ }
+ }
+ }
+
+ /* Test for search back condition. If a QRS is found in */
+ /* search back update the QRS buffer and det_thresh. */
+
+ if((count > sbcount) && (sbpeak > (det_thresh >> 1)))
+ {
+ memmove(&qrsbuf[1],qrsbuf,MEMMOVELEN) ;
+ qrsbuf[0] = sbpeak ;
+ qmean = mean(qrsbuf,8) ;
+ det_thresh = detection_thresh(qmean,nmean) ;
+ memmove(&rrbuf[1],rrbuf,MEMMOVELEN) ;
+ rrbuf[0] = sbloc ;
+ rrmean = mean(rrbuf,8) ;
+ sbcount = rrmean + (rrmean >> 1) + ms_window_length_ ;
+ QrsDelay = count = count - sbloc ;
+ QrsDelay += ms_filter_delay_;
+ sbpeak = 0 ;
+ lastmax = maxder ;
+ maxder = 0 ;
+
+ initBlank = initMax = rsetCount = 0 ;
+ }
+ }
+
+ // In the background estimate threshold to replace adaptive threshold
+ // if eight seconds elapses without a QRS detection.
+
+ if( qpkcnt == 8 )
+ {
+ if(++initBlank == ms_1000_)
+ {
+ initBlank = 0 ;
+ rsetBuff[rsetCount] = initMax ;
+ initMax = 0 ;
+ ++rsetCount ;
+
+ // Reset threshold if it has been 8 seconds without
+ // a detection.
+
+ if(rsetCount == 8)
+ {
+ for(int i = 0; i < 8; ++i)
+ {
+ qrsbuf[i] = rsetBuff[i] ;
+ noise[i] = 0 ;
+ }
+ qmean = mean( rsetBuff, 8 ) ;
+ nmean = 0 ;
+ rrmean = ms_1000_;
+ sbcount = ms_1650_;
+ det_thresh = detection_thresh(qmean,nmean) ;
+ initBlank = initMax = rsetCount = 0 ;
+ }
+ }
+ if( newPeak > initMax )
+ initMax = newPeak ;
+ }
+
+ return(QrsDelay);
+ }
+ private:
+ int det_thresh, qpkcnt;
+ int qrsbuf[8], noise[8], rrbuf[8];
+ int rsetBuff[8], rsetCount;
+ int nmean, qmean, rrmean;
+ int count, sbpeak, sbloc, sbcount;
+ int maxder, lastmax;
+ int initBlank, initMax;
+ int preBlankCnt, tempPeak;
+ QRSFilter qrs_filter;
+ PeakDetector peak_detector;
+ DerivFilter first_derivative_filter;
+ BLSCheckBuffer bls_check_buffer;
+ size_t ms_preblank_;
+ size_t ms_360_;
+ size_t ms_1000_;
+ size_t ms_1650_;
+ size_t ms_window_length_;
+ size_t ms_filter_delay_;
+
+ // Prevents detections of peaks smaller than 150 uV.
+ static const int MIN_PEAK_AMP = 7;
+};
+
+
+} // namespace qrsdet
+
+#endif // ECG_THIRD_EPLIMITED_QRSDET2_INL_H_
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/qrsdet/qrsfilt-inl.h Mon Sep 27 22:51:19 2010 +0000
@@ -0,0 +1,427 @@
+#ifndef ECG_THIRD_EPLIMITED_QRSFILT_INL_H_
+#define ECG_THIRD_EPLIMITED_QRSFILT_INL_H_
+// Modified to OOP class sturcture
+// Author: Kasturi Rangan Raghavan
+/*****************************************************************************
+FILE: qrsfilt.cpp
+AUTHOR: Patrick S. Hamilton
+REVISED: 5/13/2002
+ ___________________________________________________________________________
+
+qrsfilt.cpp filter functions to aid beat detecton in electrocardiograms.
+Copywrite (C) 2000 Patrick S. Hamilton
+
+This file is free software; you can redistribute it and/or modify it under
+the terms of the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your option) any
+later version.
+
+This software is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+PARTICULAR PURPOSE. See the GNU Library General Public License for more
+details.
+
+You should have received a copy of the GNU Library General Public License along
+with this library; if not, write to the Free Software Foundation, Inc., 59
+Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+You may contact the author by e-mail (pat@eplimited.edu) or postal mail
+(Patrick Hamilton, E.P. Limited, 35 Medford St., Suite 204 Somerville,
+MA 02143 USA). For updates to this software, please visit our website
+(http://www.eplimited.com).
+ __________________________________________________________________________
+
+ This file includes QRSFilt() and associated filtering files used for QRS
+ detection. Only QRSFilt() and deriv1() are called by the QRS detector
+ other functions can be hidden.
+ Revisions:
+ 5/13: Filter implementations have been modified to allow simplified
+ modification for different sample rates.
+*******************************************************************************/
+#include <cstdlib>
+
+namespace qrsdet {
+
+/******************************************************************************
+* Syntax:
+* int QRSFilter(int datum, int init) ;
+* Description:
+* QRSFilter() takes samples of an ECG signal as input and returns a sample of
+* a signal that is an estimate of the local energy in the QRS bandwidth. In
+* other words, the signal has a lump in it whenever a QRS complex, or QRS
+* complex like artifact occurs. The filters were originally designed for data
+* sampled at 200 samples per second, but they work nearly as well at sample
+* frequencies from 150 to 250 samples per second.
+*
+* The filter buffers and static variables are reset if a value other than
+* 0 is passed to QRSFilter through init.
+*******************************************************************************/
+
+class RingBuffer {
+ public:
+ RingBuffer(size_t buf_size) {
+ this->buf_size = buf_size;
+ data = new int[buf_size];
+ for (ptr = 0; ptr < buf_size; ptr++)
+ data[ptr] = 0;
+ ptr = 0;
+ }
+
+ ~RingBuffer() {
+ delete[] data;
+ }
+
+ int* GetRange(int begin, int end, int* n) {
+ *n = end - begin;
+ int* mem = new int[*n];
+ for (int p = begin, i = 0; p < end; p++, i++) {
+ mem[i] = GetValue(p);
+ }
+ return mem;
+ }
+
+ void SetValue(int value, int offset = 0) {
+ int set_ptr = ptr + offset;
+ if (set_ptr < 0)
+ set_ptr += static_cast<int>(buf_size);
+ set_ptr %= buf_size;
+ data[set_ptr] = value;
+ }
+
+ int GetValue(int offset = 0) {
+ int get_ptr = ptr + offset;
+ if (get_ptr < 0)
+ get_ptr += static_cast<int>(buf_size);
+ get_ptr %= buf_size;
+ return data[get_ptr];
+ }
+
+ void Increment() {
+ if (++ptr == buf_size)
+ ptr = 0;
+ }
+
+ protected:
+ size_t buf_size;
+ int* data;
+ int ptr;
+};
+
+class DelayFilter : public RingBuffer {
+ public:
+ explicit DelayFilter(size_t buf_size) : RingBuffer(buf_size) {}
+ int Process(int datum) {
+ int output = GetValue();
+ SetValue(datum);
+ Increment();
+ return output;
+ }
+};
+
+/*************************************************************************
+* lpfilt() implements the digital filter represented by the difference
+* equation:
+*
+* y[n] = 2*y[n-1] - y[n-2] + x[n] - 2*x[t-24 ms] + x[t-48 ms]
+*
+* Note that the filter delay is (LPBUFFER_LGTH/2)-1
+*
+**************************************************************************/
+class LowPassFilter : public RingBuffer {
+ public:
+ LowPassFilter(size_t buf_size) : RingBuffer(buf_size) {
+ y1 = 0;
+ y2 = 0;
+ }
+
+ int Process(int datum) {
+ int length = static_cast<int>(buf_size);
+ long y0;
+ int output, halfPtr;
+ halfPtr = ptr - length / 2;
+ if (halfPtr < 0) // to x[n-6].
+ halfPtr += length;
+ y0 = (y1 << 1) - y2 + datum - (data[halfPtr] << 1) + data[ptr];
+ y2 = y1;
+ y1 = y0;
+ output = y0 / ((length * length) / 4);
+ data[ptr] = datum;
+ Increment();
+ return output;
+ }
+
+ private:
+ long y1, y2;
+};
+
+
+/******************************************************************************
+* hpfilt() implements the high pass filter represented by the following
+* difference equation:
+*
+* y[n] = y[n-1] + x[n] - x[n-128 ms]
+* z[n] = x[n-64 ms] - y[n] ;
+*
+* Filter delay is (buf_size-1)/2
+******************************************************************************/
+class HighPassFilter : public RingBuffer {
+ public:
+ HighPassFilter(size_t buf_size) : RingBuffer(buf_size) {
+ y = 0;
+ }
+
+ int Process(int datum) {
+ int output, halfPtr;
+ int length = static_cast<int>(buf_size);
+ y += datum - data[ptr];
+ halfPtr = ptr - (length / 2);
+ if (halfPtr < 0)
+ halfPtr += length;
+ output = data[halfPtr] - (y / length);
+ data[ptr] = datum;
+ Increment();
+ return output;
+ }
+
+ private:
+ long y;
+};
+
+
+/*****************************************************************************
+* deriv1 and deriv2 implement derivative approximations represented by
+* the difference equation:
+*
+* y[n] = x[n] - x[n - 10ms]
+*
+* Filter delay is DERIV_LENGTH/2
+*****************************************************************************/
+class DerivFilter : public RingBuffer {
+ public:
+ DerivFilter(size_t buf_size) : RingBuffer(buf_size) {}
+
+ int Process(int datum) {
+ int y;
+ y = datum - data[ptr];
+ data[ptr] = datum;
+ Increment();
+ return y;
+ }
+};
+
+
+/*****************************************************************************
+* mvwint() implements a moving window integrator. Actually, mvwint() averages
+* the signal values over the last WINDOW_WIDTH samples.
+*****************************************************************************/
+class MovingWindowAverager : public RingBuffer {
+ public:
+ MovingWindowAverager(size_t buf_size) : RingBuffer(buf_size) {
+ sum = 0;
+ }
+
+ int Process(int datum) {
+ int output;
+ int length = static_cast<int>(buf_size);
+ sum += datum;
+ sum -= data[ptr];
+ data[ptr] = datum;
+ Increment();
+ if((sum / length) > 32000)
+ output = 32000 ;
+ else
+ output = sum / length;
+ return output;
+ }
+ private:
+ long sum;
+};
+
+struct QRSFilterParams {
+ QRSFilterParams(double ts) {
+ this->ts = ts;
+ }
+
+ size_t get_ms(size_t t) const { return static_cast<double>(t) / ts + 0.5; }
+
+ double get_ts() const { return ts; }
+
+ size_t get_lp_length() const { return get_ms(50); }
+
+ size_t get_hp_length() const { return get_ms(125); }
+
+ size_t get_d_length() const { return get_ms(10); }
+
+ size_t get_window_length() const { return get_ms(80); }
+
+ size_t get_preblank() const { return get_ms(200); }
+
+ size_t get_filter_delay() const {
+ return get_d_length() / 2.0 +
+ get_lp_length() / 2.0 - 1.0 +
+ (get_hp_length() - 1.0) / 2.0 +
+ get_preblank();
+ }
+
+ size_t get_der_delay() const {
+ return get_filter_delay() + get_window_length() + get_ms(100);
+ }
+
+ private:
+ double ts;
+};
+
+class QRSFilter {
+ public:
+ QRSFilter(QRSFilterParams params) :
+ lp_filter(params.get_lp_length()),
+ hp_filter(params.get_hp_length()),
+ d_filter(params.get_d_length()),
+ mwa_filter(params.get_window_length()) {}
+
+ int Process(int datum) {
+ datum = lp_filter.Process(datum);
+ datum = hp_filter.Process(datum);
+ datum = d_filter.Process(datum);
+ datum = abs(datum);
+ datum = mwa_filter.Process(datum);
+ return datum;
+ }
+
+ private:
+ LowPassFilter lp_filter;
+ HighPassFilter hp_filter;
+ DerivFilter d_filter;
+ MovingWindowAverager mwa_filter;
+};
+
+/**************************************************************
+* peak() takes a datum as input and returns a peak height
+* when the signal returns to half its peak height, or
+**************************************************************/
+class PeakDetector {
+ public:
+ PeakDetector(const QRSFilterParams& params) {
+ max = 0;
+ timeSinceMax = 0;
+ lastDatum = 0;
+ ms_95_ = params.get_ms(95);
+ }
+
+ // what is Dly used for?
+ int Process(int datum) {
+ int pk = 0;
+ if(timeSinceMax > 0)
+ ++timeSinceMax ;
+
+ if((datum > lastDatum) && (datum > max)) {
+ max = datum;
+ if(max > 2)
+ timeSinceMax = 1;
+ } else if(datum < (max >> 1)) {
+ pk = max ;
+ max = 0 ;
+ timeSinceMax = 0 ;
+ Dly = 0 ;
+ } else if(timeSinceMax > ms_95_) {
+ pk = max;
+ max = 0;
+ timeSinceMax = 0;
+ Dly = 3;
+ }
+ lastDatum = datum ;
+ return pk;
+ }
+ private:
+ size_t ms_95_;
+ int Dly; // unused?
+ int max;
+ int timeSinceMax;
+ int lastDatum;
+};
+
+/********************************************************************
+mean returns the mean of an array of integers. It uses a slow
+sort algorithm, but these arrays are small, so it hardly matters.
+********************************************************************/
+int mean(int *array, int n)
+ {
+ long sum = 0;
+ for(int i = 0; i < n; ++i)
+ sum += array[i];
+ sum /= n;
+ return sum;
+ }
+
+/****************************************************************************
+ thresh() calculates the detection threshold from the qrs mean and noise
+ mean estimates.
+****************************************************************************/
+int detection_thresh(int qmean, int nmean) {
+ static const float TH = .3125;
+ int thrsh, dmed;
+ float temp;
+ dmed = qmean - nmean;
+ temp = dmed;
+ temp *= TH;
+ dmed = temp;
+ thrsh = nmean + dmed;
+ return thrsh;
+}
+
+/***********************************************************************
+ BLSCheck() reviews data to see if a baseline shift has occurred.
+ This is done by looking for both positive and negative slopes of
+ roughly the same magnitude in a 220 ms window.
+***********************************************************************/
+class BLSCheckBuffer : RingBuffer {
+ public:
+ BLSCheckBuffer(const QRSFilterParams& params)
+ : RingBuffer(params.get_der_delay()) {
+ ms150_ = params.get_ms(150);
+ ms220_ = params.get_ms(220);
+ }
+
+ int Process(int datum) {
+ data[ptr] = datum;
+ Increment();
+ return datum;
+ }
+
+ int BLSCheck(int *maxder) {
+ int max = 0, min = 0;
+ int maxt, mint;
+ int saved_ptr = ptr;
+ for(int t = 0; t < ms220_; t++) {
+
+ int x = data[ptr];
+ if(x > max) {
+ maxt = t;
+ max = x;
+ } else if(x < min) {
+ mint = t;
+ min = x;
+ }
+ Increment();
+ }
+ ptr = saved_ptr;
+ *maxder = max;
+ min = -min;
+
+ /* Possible beat if a maximum and minimum pair are found
+ where the interval between them is less than 150 ms. */
+
+ if((max > (min >> 3)) && (min > (max >> 3)) &&
+ (abs(maxt - mint) < ms150_))
+ return 0;
+ else
+ return 1;
+ }
+ private:
+ size_t ms150_, ms220_;
+};
+
+
+} // namespace qrsdet
+
+#endif // ECG_THIRD_EPLIMITED_QRSFILT_INL_H_
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/scmRTOS/Common/OS_Kernel.cpp Mon Sep 27 22:51:19 2010 +0000
@@ -0,0 +1,115 @@
+//******************************************************************************
+//*
+//* FULLNAME: Single-Chip Microcontroller Real-Time Operating System
+//*
+//* NICKNAME: scmRTOS
+//*
+//* PURPOSE: OS Kernel Source
+//*
+//* Version: 3.10
+//*
+//* $Revision: 256 $
+//* $Date:: 2010-01-22 #$
+//*
+//* Copyright (c) 2003-2010, Harry E. Zhurov
+//*
+//* Permission is hereby granted, free of charge, to any person
+//* obtaining a copy of this software and associated documentation
+//* files (the "Software"), to deal in the Software without restriction,
+//* including without limitation the rights to use, copy, modify, merge,
+//* publish, distribute, sublicense, and/or sell copies of the Software,
+//* and to permit persons to whom the Software is furnished to do so,
+//* subject to the following conditions:
+//*
+//* The above copyright notice and this permission notice shall be included
+//* in all copies or substantial portions of the Software.
+//*
+//* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+//* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+//* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+//* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+//* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+//* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
+//* THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//*
+//* =================================================================
+//* See http://scmrtos.sourceforge.net for documentation, latest
+//* information, license and contact details.
+//* =================================================================
+//*
+//******************************************************************************
+
+#include "scmRTOS.h"
+
+using namespace OS;
+//------------------------------------------------------------------------------
+OS::TKernel OS::Kernel;
+
+//------------------------------------------------------------------------------
+#if scmRTOS_CONTEXT_SWITCH_SCHEME == 0
+void TKernel::Sched()
+{
+ byte NextPrty = GetHighPriority(ReadyProcessMap);
+ if(NextPrty != CurProcPriority)
+ {
+ TStackItem* Next_SP = ProcessTable[NextPrty]->StackPointer;
+ TStackItem** Curr_SP_addr = &(ProcessTable[CurProcPriority]->StackPointer);
+ CurProcPriority = NextPrty;
+ OS_ContextSwitcher(Curr_SP_addr, Next_SP);
+ }
+}
+#else
+//------------------------------------------------------------------------------
+void TKernel::Sched()
+{
+ byte NextPrty = GetHighPriority(ReadyProcessMap);
+ if(NextPrty != CurProcPriority)
+ {
+ SchedProcPriority = NextPrty;
+
+ RaiseContextSwitch();
+ do
+ {
+ EnableContextSwitch();
+ DUMMY_INSTR();
+ DisableContextSwitch();
+ }
+ while(!IsContextSwitchDone());
+ }
+}
+//------------------------------------------------------------------------------
+TStackItem* OS_ContextSwitchHook(TStackItem* sp) { return OS::Kernel.ContextSwitchHook(sp); }
+//------------------------------------------------------------------------------
+#endif // scmRTOS_CONTEXT_SWITCH_SCHEME
+//------------------------------------------------------------------------------
+void TBaseProcess::Sleep(TTimeout timeout)
+{
+ TCritSect cs;
+
+ Kernel.ProcessTable[Kernel.CurProcPriority]->Timeout = timeout;
+ Kernel.SetProcessUnready(Kernel.CurProcPriority);
+ Kernel.Scheduler();
+}
+//------------------------------------------------------------------------------
+void OS::WakeUpProcess(TBaseProcess& p)
+{
+ TCritSect cs;
+
+ if(p.Timeout)
+ {
+ p.Timeout = 0;
+ Kernel.SetProcessReady(p.Priority);
+ Kernel.Scheduler();
+ }
+}
+//------------------------------------------------------------------------------
+void OS::ForceWakeUpProcess(TBaseProcess& p)
+{
+ TCritSect cs;
+
+ p.Timeout = 0;
+ Kernel.SetProcessReady(p.Priority);
+ Kernel.Scheduler();
+}
+//------------------------------------------------------------------------------
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/scmRTOS/Common/OS_Kernel.h Mon Sep 27 22:51:19 2010 +0000
@@ -0,0 +1,426 @@
+//******************************************************************************
+//*
+//* FULLNAME: Single-Chip Microcontroller Real-Time Operating System
+//*
+//* NICKNAME: scmRTOS
+//*
+//* PURPOSE: OS Kernel Header. Declarations And Definitions
+//*
+//* Version: 3.10
+//*
+//* $Revision: 256 $
+//* $Date:: 2010-01-22 #$
+//*
+//* Copyright (c) 2003-2010, Harry E. Zhurov
+//*
+//* Permission is hereby granted, free of charge, to any person
+//* obtaining a copy of this software and associated documentation
+//* files (the "Software"), to deal in the Software without restriction,
+//* including without limitation the rights to use, copy, modify, merge,
+//* publish, distribute, sublicense, and/or sell copies of the Software,
+//* and to permit persons to whom the Software is furnished to do so,
+//* subject to the following conditions:
+//*
+//* The above copyright notice and this permission notice shall be included
+//* in all copies or substantial portions of the Software.
+//*
+//* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+//* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+//* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+//* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+//* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+//* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
+//* THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//*
+//* =================================================================
+//* See http://scmrtos.sourceforge.net for documentation, latest
+//* information, license and contact details.
+//* =================================================================
+//*
+//*****************************************************************************
+
+#ifndef OS_KERNEL_H
+#define OS_KERNEL_H
+
+#include <stddef.h>
+#include <commdefs.h>
+#include <usrlib.h>
+
+//------------------------------------------------------------------------------
+
+//==============================================================================
+extern "C" void OS_Start(TStackItem* sp);
+
+#if scmRTOS_CONTEXT_SWITCH_SCHEME == 0
+ extern "C" void OS_ContextSwitcher(TStackItem** Curr_SP, TStackItem* Next_SP);
+#else
+ extern "C" TStackItem* OS_ContextSwitchHook(TStackItem* sp);
+#endif
+
+//==============================================================================
+
+//------------------------------------------------------------------------------
+//
+//
+// NAME : OS
+//
+// PURPOSE : Namespace for all OS stuff
+//
+// DESCRIPTION: Includes: Kernel,
+// Processes,
+// Mutexes,
+// Event Flags,
+// Byte-wide Channels,
+// Arbitrary-type Channels,
+// Messages
+//
+namespace OS
+{
+ class TBaseProcess;
+
+ INLINE inline void SetPrioTag(TProcessMap& pm, const TProcessMap PrioTag) { pm |= PrioTag; }
+ INLINE inline void ClrPrioTag(TProcessMap& pm, const TProcessMap PrioTag) { pm &= ~PrioTag; }
+
+ //--------------------------------------------------------------------------
+ //
+ // NAME : TKernel
+ //
+ /// Implements kernel-level operations such as
+ /// process management, process-level scheduling,
+ /// ISR-level scheduling, system timing.
+ //
+ // DESCRIPTION:
+ //
+ //
+ class TKernel
+ {
+ //-----------------------------------------------------------
+ //
+ // Declarations
+ //
+
+
+ friend class TISRW;
+ friend class TISRW_SS;
+ friend class TBaseProcess;
+ friend class TMutex;
+ friend class TEventFlag;
+ friend class TChannel;
+ friend class TBaseMessage;
+
+ template<typename T, word size, class S> friend class channel;
+ template<typename T> friend class message;
+
+ friend void Run();
+ friend void WakeUpProcess(TBaseProcess& p);
+ friend void ForceWakeUpProcess(TBaseProcess& p);
+ friend inline bool IsProcessSleeping(const TBaseProcess& p);
+ friend inline bool IsProcessSuspended(const TBaseProcess& p);
+ friend inline dword GetTickCount();
+
+ //-----------------------------------------------------------
+ //
+ // Data
+ //
+ private:
+ byte CurProcPriority;
+ TProcessMap ReadyProcessMap;
+ TBaseProcess* ProcessTable[scmRTOS_PROCESS_COUNT+1];
+ volatile byte ISR_NestCount;
+
+ #if scmRTOS_CONTEXT_SWITCH_SCHEME == 1
+ byte SchedProcPriority;
+ #endif
+
+ #if scmRTOS_SYSTEM_TICKS_ENABLE == 1
+ volatile dword SysTickCount;
+ #endif
+
+ //-----------------------------------------------------------
+ //
+ // Functions
+ //
+ public:
+ INLINE TKernel()
+ : CurProcPriority(pr0)
+ , ReadyProcessMap( (1 << (scmRTOS_PROCESS_COUNT + 1)) - 1) // set all processes ready
+ , ISR_NestCount(0)
+ {
+ }
+
+ private:
+ INLINE inline void RegisterProcess(TBaseProcess* const p);
+
+ void Sched();
+ INLINE void Scheduler() { if(ISR_NestCount) return; else Sched(); }
+ INLINE inline void SchedISR();
+
+ #if scmRTOS_CONTEXT_SWITCH_SCHEME == 1
+ INLINE inline bool IsContextSwitchDone() const volatile;
+ #endif
+ INLINE void SetProcessReady (const byte pr) { TProcessMap PrioTag = GetPrioTag(pr); SetPrioTag( ReadyProcessMap, PrioTag); }
+ INLINE void SetProcessUnready(const byte pr) { TProcessMap PrioTag = GetPrioTag(pr); ClrPrioTag( ReadyProcessMap, PrioTag); }
+
+ public:
+ INLINE inline void SystemTimer();
+ #if scmRTOS_CONTEXT_SWITCH_SCHEME == 1
+ INLINE inline TStackItem* ContextSwitchHook(TStackItem* sp);
+ #endif
+
+ }; // End of TKernel class definition
+ //--------------------------------------------------------------------------
+ extern TKernel Kernel;
+
+ //--------------------------------------------------------------------------
+ //
+ /// BaseProcess
+ ///
+ /// Implements base class-type for application processes
+ //
+ // DESCRIPTION:
+ //
+ //
+ class TBaseProcess
+ {
+ friend class TKernel;
+ friend class TISRW;
+ friend class TISRW_SS;
+ friend class TEventFlag;
+ friend class TMutex;
+ friend class TBaseMessage;
+
+ template<typename T, word size, class S> friend class channel;
+ template<typename T> friend class message;
+
+
+ friend void Run();
+ friend void WakeUpProcess(TBaseProcess& p);
+ friend void ForceWakeUpProcess(TBaseProcess& p);
+ friend bool IsProcessSleeping(const TBaseProcess& p);
+ friend bool IsProcessSuspended(const TBaseProcess& p);
+
+ public:
+ #if SEPARATE_RETURN_STACK == 0
+ TBaseProcess( TStackItem* Stack, TPriority pr, void (*exec)() );
+ #else
+ TBaseProcess( TStackItem* Stack, TStackItem* RStack, TPriority pr, void (*exec)() );
+ #endif
+
+ static void Sleep(TTimeout timeout = 0);
+
+ protected:
+ TStackItem* StackPointer;
+ TTimeout Timeout;
+ TPriority Priority;
+ };
+ //--------------------------------------------------------------------------
+
+ //--------------------------------------------------------------------------
+ //
+ /// process
+ ///
+ /// Implements template for application processes instantiation
+ //
+ // DESCRIPTION:
+ //
+ //
+ #if SEPARATE_RETURN_STACK == 0
+
+ template<TPriority pr, word stack_size>
+ class process : public TBaseProcess
+ {
+ public:
+ INLINE_PROCESS_CTOR process();
+
+ OS_PROCESS static void Exec();
+
+ private:
+ TStackItem Stack[stack_size/sizeof(TStackItem)];
+ };
+
+ template<TPriority pr, word stack_size>
+ OS::process<pr, stack_size>::process() : TBaseProcess( &Stack[stack_size/sizeof(TStackItem)]
+ , pr
+ , reinterpret_cast<void (*)()>(Exec) )
+ {
+ }
+
+ #else
+
+ template<TPriority pr, word stack_size, word rstack_size>
+ class process : public TBaseProcess
+ {
+ public:
+ INLINE_PROCESS_CTOR process();
+
+ OS_PROCESS static void Exec();
+
+ private:
+ TStackItem Stack [stack_size/sizeof(TStackItem)];
+ TStackItem RStack[rstack_size/sizeof(TStackItem)];
+ };
+
+ template<TPriority pr, word stack_size, word rstack_size>
+ process<pr, stack_size, rstack_size>::process() : TBaseProcess( &Stack[stack_size/sizeof(TStackItem)]
+ , &RStack[rstack_size/sizeof(TStackItem)]
+ , pr
+ , reinterpret_cast<void (*)()>(Exec))
+ {
+ }
+
+ #endif
+ //--------------------------------------------------------------------------
+
+ //--------------------------------------------------------------------------
+ //
+ // Miscellaneous
+ //
+ //
+ INLINE inline void Run();
+ INLINE inline void LockSystemTimer() { TCritSect cs; LOCK_SYSTEM_TIMER(); }
+ INLINE inline void UnlockSystemTimer() { TCritSect cs; UNLOCK_SYSTEM_TIMER(); }
+ void WakeUpProcess(TBaseProcess& p);
+ void ForceWakeUpProcess(TBaseProcess& p);
+ INLINE inline void Sleep(TTimeout t = 0) { TBaseProcess::Sleep(t); }
+
+ INLINE inline bool IsProcessSleeping(const TBaseProcess& p)
+ {
+ TCritSect cs;
+ if(p.Timeout)
+ return true;
+ else
+ return false;
+ }
+
+ INLINE inline bool IsProcessSuspended(const TBaseProcess& p)
+ {
+ TCritSect cs;
+ if(Kernel.ReadyProcessMap & GetPrioTag(p.Priority))
+ return false;
+ else
+ return true;
+ }
+ //--------------------------------------------------------------------------
+
+#if scmRTOS_SYSTEM_TICKS_ENABLE == 1
+ INLINE inline dword GetTickCount() { TCritSect cs; return Kernel.SysTickCount; }
+#endif
+
+#if scmRTOS_SYSTIMER_HOOK_ENABLE == 1
+ INLINE_SYS_TIMER_HOOK void SystemTimerUserHook();
+#endif
+
+#if scmRTOS_CONTEXT_SWITCH_USER_HOOK_ENABLE == 1
+ INLINE_CONTEXT_SWITCH_HOOK void ContextSwitchUserHook();
+#endif
+
+}
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+//
+/// Register Process
+///
+/// Places pointer to process in kernel's process table
+//
+void OS::TKernel::RegisterProcess(OS::TBaseProcess* const p)
+{
+ ProcessTable[p->Priority] = p;
+}
+//------------------------------------------------------------------------------
+//
+/// System Timer Implementation
+///
+/// Performs process's timeouts checking and
+/// moving processes to ready-to-run state
+//
+void OS::TKernel::SystemTimer()
+{
+ SYS_TIMER_CRIT_SECT();
+#if scmRTOS_SYSTEM_TICKS_ENABLE == 1
+ SysTickCount++;
+#endif
+
+#if scmRTOS_PRIORITY_ORDER == 0
+ const byte BaseIndex = 0;
+#else
+ const byte BaseIndex = 1;
+#endif
+
+ for(byte i = BaseIndex; i < (scmRTOS_PROCESS_COUNT + BaseIndex); i++)
+ {
+ TBaseProcess* p = ProcessTable[i];
+
+ if(p->Timeout > 0)
+ {
+ if(--p->Timeout == 0)
+ {
+ SetProcessReady(p->Priority);
+ }
+ }
+ }
+}
+//------------------------------------------------------------------------------
+//
+/// ISR optimized scheduler
+///
+/// !!! IMPORTANT: This function must be call from ISR services only !!!
+//
+//
+#if scmRTOS_CONTEXT_SWITCH_SCHEME == 0
+void OS::TKernel::SchedISR()
+{
+ byte NextPrty = GetHighPriority(ReadyProcessMap);
+ if(NextPrty != CurProcPriority)
+ {
+ TStackItem* Next_SP = ProcessTable[NextPrty]->StackPointer;
+ TStackItem** Curr_SP_addr = &(ProcessTable[CurProcPriority]->StackPointer);
+ CurProcPriority = NextPrty;
+ OS_ContextSwitcher(Curr_SP_addr, Next_SP);
+ }
+}
+#else
+void OS::TKernel::SchedISR()
+{
+ byte NextPrty = GetHighPriority(ReadyProcessMap);
+ if(NextPrty != CurProcPriority)
+ {
+ SchedProcPriority = NextPrty;
+ RaiseContextSwitch();
+ }
+}
+//------------------------------------------------------------------------------
+bool OS::TKernel::IsContextSwitchDone() const volatile
+{
+ byte cur = CurProcPriority; ///< reading to temporary vars is performed due to
+ byte sched = SchedProcPriority; ///< suppress warning about order of volatile access
+ return cur == sched;
+}
+//------------------------------------------------------------------------------
+TStackItem* OS::TKernel::ContextSwitchHook(TStackItem* sp)
+{
+ ProcessTable[CurProcPriority]->StackPointer = sp;
+ sp = ProcessTable[SchedProcPriority]->StackPointer;
+
+#if scmRTOS_CONTEXT_SWITCH_USER_HOOK_ENABLE == 1
+ ContextSwitchUserHook();
+#endif
+
+ CurProcPriority = SchedProcPriority;
+ return sp;
+}
+//------------------------------------------------------------------------------
+#endif // scmRTOS_CONTEXT_SWITCH_SCHEME
+
+//-----------------------------------------------------------------------------
+/// Start Operation
+INLINE inline void OS::Run()
+{
+ TStackItem* sp = Kernel.ProcessTable[pr0]->StackPointer;
+ OS_Start(sp);
+}
+
+#include <OS_Services.h>
+
+#endif // OS_KERNEL_H
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/scmRTOS/Common/OS_Services.cpp Mon Sep 27 22:51:19 2010 +0000
@@ -0,0 +1,298 @@
+//******************************************************************************
+//*
+//* FULLNAME: Single-Chip Microcontroller Real-Time Operating System
+//*
+//* NICKNAME: scmRTOS
+//*
+//* PURPOSE: OS Services Source
+//*
+//* Version: 3.10
+//*
+//* $Revision: 256 $
+//* $Date:: 2010-01-22 #$
+//*
+//* Copyright (c) 2003-2010, Harry E. Zhurov
+//*
+//* Permission is hereby granted, free of charge, to any person
+//* obtaining a copy of this software and associated documentation
+//* files (the "Software"), to deal in the Software without restriction,
+//* including without limitation the rights to use, copy, modify, merge,
+//* publish, distribute, sublicense, and/or sell copies of the Software,
+//* and to permit persons to whom the Software is furnished to do so,
+//* subject to the following conditions:
+//*
+//* The above copyright notice and this permission notice shall be included
+//* in all copies or substantial portions of the Software.
+//*
+//* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+//* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+//* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+//* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+//* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+//* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
+//* THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//*
+//* =================================================================
+//* See http://scmrtos.sourceforge.net for documentation, latest
+//* information, license and contact details.
+//* =================================================================
+//*
+//******************************************************************************
+
+#include "scmRTOS.h"
+
+using namespace OS;
+
+//------------------------------------------------------------------------------
+//
+//
+// TEventFlag
+//
+//
+bool OS::TEventFlag::Wait(TTimeout timeout)
+{
+ TCritSect cs;
+
+ if(Value) // if flag already signaled
+ {
+ Value = efOff; // clear flag
+ return true;
+ }
+ else
+ {
+ TBaseProcess* p = Kernel.ProcessTable[Kernel.CurProcPriority];
+ p->Timeout = timeout;
+ TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority);
+
+ SetPrioTag(ProcessMap, PrioTag); // put current process to the wait map
+ ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map
+
+ Kernel.Scheduler();
+
+ p->Timeout = 0;
+
+ if( !(ProcessMap & PrioTag) ) // if waked up by signal() or signal_ISR()
+ return true;
+
+ ClrPrioTag(ProcessMap, PrioTag); // otherwise waked up by timeout or by
+ return false; // OS::ForceWakeUpProcess(), remove process from the wait map
+ }
+}
+//------------------------------------------------------------------------------
+void OS::TEventFlag::Signal()
+{
+ TCritSect cs;
+ if(ProcessMap) // if any process waits for event
+ {
+ TProcessMap Timeouted = Kernel.ReadyProcessMap; // Process has its tag set in ReadyProcessMap if timeout expired
+ // or it was waked up by OS::ForceWakeUpProcess()
+
+ if( ProcessMap & ~Timeouted ) // if any process has to be waked up
+ {
+ SetPrioTag(Kernel.ReadyProcessMap, ProcessMap); // place all waiting processes to the ready map
+ ClrPrioTag(ProcessMap, ~Timeouted); // remove all non-timeouted processes from the waiting map.
+ // Used to check that process waked up by signal() or signalISR()
+ // and not by timeout or OS::ForceWakeUpProcess()
+ Kernel.Scheduler();
+ return;
+ }
+ }
+ Value = efOn;
+}
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+//
+//
+// TMutex
+//
+//
+void OS::TMutex::Lock()
+{
+ TCritSect cs;
+
+ TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority);
+ while(ValueTag)
+ {
+ SetPrioTag(ProcessMap, PrioTag); // mutex already locked by another process, put current process to the wait map
+ ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map
+
+ Kernel.Scheduler();
+ }
+ ValueTag = PrioTag; // mutex has been successfully locked
+}
+//------------------------------------------------------------------------------
+void OS::TMutex::Unlock()
+{
+ TCritSect cs;
+
+ TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority);
+ if(ValueTag != PrioTag) return; // the only process that had locked mutex can unlock the mutex
+ ValueTag = 0;
+ if(ProcessMap)
+ {
+ byte pr = GetHighPriority(ProcessMap);
+ PrioTag = GetPrioTag(pr);
+ ClrPrioTag(ProcessMap, PrioTag); // remove next ready process from the wait map
+ SetPrioTag(Kernel.ReadyProcessMap, PrioTag); // place next process to the ready map
+ Kernel.Scheduler();
+ }
+}
+//------------------------------------------------------------------------------
+void OS::TMutex::UnlockISR()
+{
+ TCritSect cs;
+
+ ValueTag = 0;
+ if(ProcessMap)
+ {
+ byte pr = GetHighPriority(ProcessMap);
+ TProcessMap PrioTag = GetPrioTag(pr);
+ ClrPrioTag(ProcessMap, PrioTag); // remove next ready process from the wait map
+ SetPrioTag(Kernel.ReadyProcessMap, PrioTag); // place next process to the ready map
+ }
+}
+//------------------------------------------------------------------------------
+
+
+//------------------------------------------------------------------------------
+//
+//
+// TChannel
+//
+//
+void OS::TChannel::CheckWaiters(TProcessMap& pm)
+{
+ if(pm)
+ {
+ byte pr = GetHighPriority(pm);
+ TProcessMap PrioTag = GetPrioTag(pr);
+ ClrPrioTag(pm, PrioTag); // remove next ready process from the wait map
+ SetPrioTag(Kernel.ReadyProcessMap, PrioTag); // place next process to the ready map
+ Kernel.Scheduler();
+ }
+}
+//------------------------------------------------------------------------------
+void OS::TChannel::Push(byte x)
+{
+ TCritSect cs;
+
+ while (!Cbuf.get_free_size())
+ {
+ TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority);
+ SetPrioTag (ProducersProcessMap, PrioTag); // channel is full, put current process to the wait map
+ ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map
+ Kernel.Scheduler(); // wait until waked-up by Pop() or Read()
+ }
+
+ Cbuf.put(x);
+ CheckWaiters(ConsumersProcessMap);
+}
+//------------------------------------------------------------------------------
+byte OS::TChannel::Pop()
+{
+ TCritSect cs;
+ byte x;
+
+ while(!Cbuf.get_count())
+ {
+ TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority);
+ SetPrioTag(ConsumersProcessMap, PrioTag); // channel is empty, put current process to the wait map
+ ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map
+ Kernel.Scheduler(); // wait until waked up by Push() or Write()
+ }
+ x = Cbuf.get();
+ CheckWaiters(ProducersProcessMap);
+ return x;
+}
+//------------------------------------------------------------------------------
+void OS::TChannel::Write(const byte* data, const byte count)
+{
+ TCritSect cs;
+
+ while(Cbuf.get_free_size() < count)
+ {
+ TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority);
+ SetPrioTag(ProducersProcessMap, PrioTag); // channel has not enough space, put current process to the wait map
+ ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map
+ Kernel.Scheduler(); // wait until waked up by Read() or Pop()
+ }
+
+ Cbuf.write(data, count);
+ CheckWaiters(ConsumersProcessMap);
+}
+//------------------------------------------------------------------------------
+void OS::TChannel::Read(byte* const data, const byte count)
+{
+ TCritSect cs;
+
+ while(Cbuf.get_count() < count)
+ {
+ TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority);
+ SetPrioTag(ConsumersProcessMap, PrioTag); // channel doesn't contain enough data, put current process to the wait map
+ ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map
+ Kernel.Scheduler(); // wait until waked up by Write() or Push()
+ }
+
+ Cbuf.read(data, count);
+ CheckWaiters(ProducersProcessMap);
+}
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+//
+// OS::message template
+//
+// Function-members implementation
+//
+//
+//------------------------------------------------------------------------------
+bool OS::TBaseMessage::wait(TTimeout timeout)
+{
+ TCritSect cs;
+
+ if(NonEmpty) // message alredy send
+ {
+ NonEmpty = false;
+ return true;
+ }
+ else
+ {
+ TBaseProcess* p = Kernel.ProcessTable[Kernel.CurProcPriority];
+ p->Timeout = timeout;
+ TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority);
+
+ SetPrioTag(ProcessMap, PrioTag); // put current process to the wait map
+ ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map
+ Kernel.Scheduler(); // wait until wake up
+
+ p->Timeout = 0;
+ if( !(ProcessMap & PrioTag) ) // if waked up by send() or sendISR()
+ return true;
+
+ ClrPrioTag(ProcessMap, PrioTag); // otherwise waked up by timeout or by
+ return false; // OS::ForceWakeUpProcess(), remove process from wait map
+ }
+}
+//------------------------------------------------------------------------------
+void OS::TBaseMessage::send()
+{
+ TCritSect cs;
+
+ if(ProcessMap)
+ {
+ TProcessMap Timeouted = Kernel.ReadyProcessMap; // Process has its tag set in ReadyProcessMap if timeout expired,
+ // or it was waked up by OS::ForceWakeUpProcess()
+ if( ProcessMap & ~Timeouted ) // if any process has to be waked up
+ {
+ SetPrioTag(Kernel.ReadyProcessMap, ProcessMap); // place all waiting processes to the ready map
+ ClrPrioTag(ProcessMap, ~Timeouted); // remove all non-timeouted processes from the waiting map.
+ Kernel.Scheduler();
+ return;
+ }
+ }
+
+ NonEmpty = true;
+}
+//------------------------------------------------------------------------------
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/scmRTOS/Common/OS_Services.h Mon Sep 27 22:51:19 2010 +0000
@@ -0,0 +1,467 @@
+//******************************************************************************
+//*
+//* FULLNAME: Single-Chip Microcontroller Real-Time Operating System
+//*
+//* NICKNAME: scmRTOS
+//*
+//* PURPOSE: OS Services Header. Declarations And Definitions
+//*
+//* Version: 3.10
+//*
+//* $Revision: 256 $
+//* $Date:: 2010-01-22 #$
+//*
+//* Copyright (c) 2003-2010, Harry E. Zhurov
+//*
+//* Permission is hereby granted, free of charge, to any person
+//* obtaining a copy of this software and associated documentation
+//* files (the "Software"), to deal in the Software without restriction,
+//* including without limitation the rights to use, copy, modify, merge,
+//* publish, distribute, sublicense, and/or sell copies of the Software,
+//* and to permit persons to whom the Software is furnished to do so,
+//* subject to the following conditions:
+//*
+//* The above copyright notice and this permission notice shall be included
+//* in all copies or substantial portions of the Software.
+//*
+//* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+//* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+//* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+//* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+//* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+//* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
+//* THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//*
+//* =================================================================
+//* See http://scmrtos.sourceforge.net for documentation, latest
+//* information, license and contact details.
+//* =================================================================
+//*
+//******************************************************************************
+
+#ifndef OS_SERVICES_H
+#define OS_SERVICES_H
+
+namespace OS
+{
+ //--------------------------------------------------------------------------
+ //
+ // NAME : Mutex
+ //
+ /// Binary semaphore for support of mutual exclusion
+ //
+ // DESCRIPTION:
+ //
+ //
+ class TMutex
+ {
+ public:
+ INLINE TMutex() : ProcessMap(0), ValueTag(0) { }
+ void Lock();
+ void Unlock();
+ void UnlockISR();
+
+ INLINE bool LockSoftly() { TCritSect cs; if(ValueTag) return false; else Lock(); return true; }
+ INLINE bool IsLocked() const { TCritSect cs; if(ValueTag) return true; else return false; }
+
+ private:
+ TProcessMap ProcessMap;
+ TProcessMap ValueTag;
+
+ };
+ //--------------------------------------------------------------------------
+
+ //--------------------------------------------------------------------------
+ //
+ /// Event Flag
+ ///
+ /// Intended for processes synchronization and
+ /// event notification one (or more) process by another
+ //
+ // DESCRIPTION:
+ //
+ //
+ class TEventFlag
+ {
+ public:
+ enum TValue { efOn = 1, efOff= 0 }; // prefix 'ef' means: "Event Flag"
+
+ public:
+ INLINE TEventFlag(TValue init_val = efOff) : ProcessMap(0), Value(init_val) { }
+
+ bool Wait(TTimeout timeout = 0);
+ void Signal();
+ INLINE void Clear() { TCritSect cs; Value = efOff; }
+ INLINE inline void SignalISR();
+ INLINE bool IsSignaled() { TCritSect cs; if(Value == efOn) return true; else return false; }
+
+ private:
+ TProcessMap ProcessMap;
+ TValue Value;
+ };
+ //--------------------------------------------------------------------------
+
+ //--------------------------------------------------------------------------
+ //
+ /// TChannel
+ ///
+ /// Byte-wide data channel for transferring "raw" data
+ //
+ // DESCRIPTION:
+ //
+ //
+ class TChannel
+ {
+ public:
+ INLINE TChannel(byte* buf, byte size) : Cbuf(buf, size) { }
+ void Push(byte x);
+ byte Pop();
+ void Write(const byte* data, const byte count);
+ void Read(byte* const data, const byte count);
+
+ INLINE byte GetCount() const { TCritSect cs; return Cbuf.get_count(); }
+
+ private:
+ TProcessMap ProducersProcessMap;
+ TProcessMap ConsumersProcessMap;
+ usr::TCbuf Cbuf;
+
+ private:
+ void CheckWaiters(TProcessMap& pm);
+ };
+ //--------------------------------------------------------------------------
+
+
+ //--------------------------------------------------------------------------
+ //
+ // NAME : channel
+ //
+ // PURPOSE : Data channel for transferring data
+ // objects of arbitrary type
+ //
+ // DESCRIPTION:
+ //
+ //
+ template<typename T, word Size, typename S = byte>
+ /// channel
+ ///
+ /// Data channel for transferring data objects of arbitrary type
+ class channel
+ {
+ public:
+ INLINE channel() : ProducersProcessMap(0)
+ , ConsumersProcessMap(0)
+ , pool()
+ {
+ }
+
+ //----------------------------------------------------------------
+ //
+ // Data transfer functions
+ //
+ void write(const T* data, const S cnt);
+ bool read (T* const data, const S cnt, TTimeout timeout = 0);
+
+ void push (const T& item);
+ void push_front(const T& item);
+
+ bool pop (T& item, TTimeout timeout = 0);
+ bool pop_back(T& item, TTimeout timeout = 0);
+
+
+ //----------------------------------------------------------------
+ //
+ // Service functions
+ //
+ INLINE S get_count() const { TCritSect cs; return pool.get_count(); }
+ INLINE S get_free_size() const { TCritSect cs; return pool.get_free_size(); }
+ void flush();
+ //const T& operator[](const S index) { TCritSect cs; return pool[index]; }
+
+
+ private:
+ TProcessMap ProducersProcessMap;
+ TProcessMap ConsumersProcessMap;
+ usr::ring_buffer<T, Size, S> pool;
+
+ private:
+ void CheckWaiters(TProcessMap& pm);
+ };
+
+ //--------------------------------------------------------------------------
+
+ //--------------------------------------------------------------------------
+ //
+ /// message
+ ///
+ /// Template for messages
+ //
+ // DESCRIPTION:
+ //
+ //
+ class TBaseMessage
+ {
+ public:
+ INLINE TBaseMessage() : ProcessMap(0), NonEmpty(false) { }
+
+ bool wait (TTimeout timeout = 0);
+ void send();
+ INLINE inline void sendISR();
+ INLINE bool is_non_empty() const { TCritSect cs; return NonEmpty; }
+ INLINE void reset () { TCritSect cs; NonEmpty = false; }
+
+ private:
+ TProcessMap ProcessMap;
+ bool NonEmpty;
+ };
+ //--------------------------------------------------------------------------
+ template<typename T>
+ class message : public TBaseMessage
+ {
+ public:
+ INLINE message() : TBaseMessage() { }
+ INLINE const T& operator=(const T& msg) { TCritSect cs; Msg = msg; return Msg; }
+ INLINE operator T() const { TCritSect cs; return Msg; }
+
+ private:
+ T Msg;
+ };
+ //--------------------------------------------------------------------------
+}
+//------------------------------------------------------------------------------
+//
+// Function-members implementation
+//
+//------------------------------------------------------------------------------
+void OS::TEventFlag::SignalISR()
+{
+ TCritSect cs;
+ if(ProcessMap) // if any process waits for event
+ {
+ TProcessMap Timeouted = Kernel.ReadyProcessMap; // Process has its tag set in ReadyProcessMap if timeout
+ // expired, or it was waked up by OS::ForceWakeUpProcess()
+ if( ProcessMap & ~Timeouted ) // if any process has to be waked up
+ {
+ SetPrioTag(Kernel.ReadyProcessMap, ProcessMap); // place all waiting processes to the ready map
+ ClrPrioTag(ProcessMap, ~Timeouted); // remove all non-timeouted processes from the waiting map.
+ return;
+ }
+ }
+ Value = efOn;
+}
+//------------------------------------------------------------------------------
+template<typename T, word Size, typename S>
+void OS::channel<T, Size, S>::CheckWaiters(TProcessMap& pm)
+{
+ if(pm)
+ {
+ TProcessMap Timeouted = Kernel.ReadyProcessMap;
+
+ SetPrioTag(Kernel.ReadyProcessMap, pm); // place all waiting processes to the ready map
+ ClrPrioTag(pm, ~Timeouted); // remove waiting processes from the wait map
+ Kernel.Scheduler();
+ }
+}
+//------------------------------------------------------------------------------
+template<typename T, word Size, typename S>
+void OS::channel<T, Size, S>::push(const T& item)
+{
+ TCritSect cs;
+
+ while(!pool.get_free_size())
+ {
+ TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority);
+ SetPrioTag(ProducersProcessMap, PrioTag); // channel is full, put current process to the wait map
+ ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map
+ Kernel.Scheduler();
+ }
+
+ pool.push_back(item);
+ CheckWaiters(ConsumersProcessMap);
+}
+//------------------------------------------------------------------------------
+template<typename T, word Size, typename S>
+void OS::channel<T, Size, S>::push_front(const T& item)
+{
+ TCritSect cs;
+
+ while(!pool.get_free_size())
+ {
+ TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority);
+ SetPrioTag(ProducersProcessMap, PrioTag); // channel is full, put current process to the wait map
+ ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map
+ Kernel.Scheduler();
+ }
+
+ pool.push_front(item);
+ CheckWaiters(ConsumersProcessMap);
+}
+//------------------------------------------------------------------------------
+template<typename T, word Size, typename S>
+bool OS::channel<T, Size, S>::pop(T& item, TTimeout timeout)
+{
+ TCritSect cs;
+
+ if(pool.get_count())
+ {
+ item = pool.pop();
+ CheckWaiters(ProducersProcessMap);
+ return true;
+ }
+ else
+ {
+ TBaseProcess* p = Kernel.ProcessTable[Kernel.CurProcPriority];
+ p->Timeout = timeout;
+
+ TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority);
+ for(;;)
+ {
+ SetPrioTag(ConsumersProcessMap, PrioTag); // channel is empty, put current process to the wait map
+ ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map
+ Kernel.Scheduler();
+
+ if(pool.get_count())
+ {
+ p->Timeout = 0;
+ item = pool.pop();
+ CheckWaiters(ProducersProcessMap);
+ return true;
+ }
+
+ if(ConsumersProcessMap & PrioTag) // waked up by timer when timeout expired
+ { // or by OS::ForceWakeUpProcess()
+
+ p->Timeout = 0; // non-zero if waked up by ForceWakeUpProcess()
+ ClrPrioTag(ConsumersProcessMap, PrioTag); // remove current process from the wait map
+ return false;
+ }
+ }
+ }
+}
+//------------------------------------------------------------------------------
+template<typename T, word Size, typename S>
+bool OS::channel<T, Size, S>::pop_back(T& item, TTimeout timeout)
+{
+ TCritSect cs;
+
+ if(pool.get_count())
+ {
+ item = pool.pop_back();
+ CheckWaiters(ProducersProcessMap);
+ return true;
+ }
+ else
+ {
+ TBaseProcess* p = Kernel.ProcessTable[Kernel.CurProcPriority];
+ p->Timeout = timeout;
+
+ TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority);
+ for(;;)
+ {
+ SetPrioTag(ConsumersProcessMap, PrioTag); // channel is empty, put current process to the wait map
+ ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map
+ Kernel.Scheduler();
+
+ if(pool.get_count())
+ {
+ p->Timeout = 0;
+ item = pool.pop_back();
+ CheckWaiters(ProducersProcessMap);
+ return true;
+ }
+
+ if(ConsumersProcessMap & PrioTag) // waked up by timer when timeout expired
+ { // or by OS::ForceWakeUpProcess()
+
+ p->Timeout = 0; // non-zero if waked up by ForceWakeUpProcess()
+ ClrPrioTag(ConsumersProcessMap, PrioTag); // remove current process from the wait map
+ return false;
+ }
+ }
+ }
+}
+//------------------------------------------------------------------------------
+template<typename T, word Size, typename S>
+void OS::channel<T, Size, S>::flush()
+{
+ TCritSect cs;
+ pool.flush();
+ CheckWaiters(ProducersProcessMap);
+}
+//------------------------------------------------------------------------------
+template<typename T, word Size, typename S>
+void OS::channel<T, Size, S>::write(const T* data, const S count)
+{
+ TCritSect cs;
+
+ while(pool.get_free_size() < count)
+ {
+ TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority);
+ SetPrioTag(ProducersProcessMap, PrioTag); // channel does not have enough space, put current process to the wait map
+ ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map
+ Kernel.Scheduler();
+ }
+
+ pool.write(data, count);
+ CheckWaiters(ConsumersProcessMap);
+}
+//------------------------------------------------------------------------------
+template<typename T, word Size, typename S>
+bool OS::channel<T, Size, S>::read(T* const data, const S count, TTimeout timeout)
+{
+ TCritSect cs;
+
+ TBaseProcess* p = Kernel.ProcessTable[Kernel.CurProcPriority];
+ p->Timeout = timeout;
+
+ TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority);
+ while(pool.get_count() < count)
+ {
+ SetPrioTag(ConsumersProcessMap, PrioTag); // channel doesn't contain enough data, put current process to the wait map
+ ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map
+ Kernel.Scheduler();
+
+ if(ConsumersProcessMap & PrioTag) // waked up by timer when timeout expired
+ { // or by OS::ForceWakeUpProcess()
+
+ p->Timeout = 0; // non-zero if waked up by ForceWakeUpProcess()
+ ClrPrioTag(ConsumersProcessMap, PrioTag); // remove current process from the wait map
+ return false;
+ }
+ }
+
+ p->Timeout = 0;
+ pool.read(data, count);
+ CheckWaiters(ProducersProcessMap);
+
+ return true;
+}
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+//
+// OS::message template
+//
+// Function-members implementation
+//
+//
+//------------------------------------------------------------------------------
+void OS::TBaseMessage::sendISR()
+{
+ TCritSect cs;
+
+ if(ProcessMap)
+ {
+ TProcessMap Timeouted = OS::Kernel.ReadyProcessMap; // Process has it's tag set in ReadyProcessMap if timeout
+ // expired, or it was waked up by OS::ForceWakeUpProcess()
+ if( ProcessMap & ~Timeouted ) // if any process has to be waked up
+ {
+ SetPrioTag(Kernel.ReadyProcessMap, ProcessMap); // place all waiting processes to the ready map
+ ClrPrioTag(ProcessMap, ~Timeouted); // remove all non-timeouted processes from the waiting map.
+ return;
+ }
+ }
+ NonEmpty = true;
+}
+//------------------------------------------------------------------------------
+#endif // OS_SERVICES_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scmRTOS/Common/scmRTOS.h Mon Sep 27 22:51:19 2010 +0000 @@ -0,0 +1,58 @@ +//****************************************************************************** +//* +//* FULLNAME: Single-Chip Microcontroller Real-Time Operating System +//* +//* NICKNAME: scmRTOS +//* +//* PURPOSE: Main RTOS header file +//* +//* Version: 3.10 +//* +//* $Revision: 256 $ +//* $Date:: 2010-01-22 #$ +//* +//* Copyright (c) 2003-2010, Harry E. Zhurov +//* +//* Permission is hereby granted, free of charge, to any person +//* obtaining a copy of this software and associated documentation +//* files (the "Software"), to deal in the Software without restriction, +//* including without limitation the rights to use, copy, modify, merge, +//* publish, distribute, sublicense, and/or sell copies of the Software, +//* and to permit persons to whom the Software is furnished to do so, +//* subject to the following conditions: +//* +//* The above copyright notice and this permission notice shall be included +//* in all copies or substantial portions of the Software. +//* +//* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +//* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +//* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +//* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +//* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +//* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH +//* THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +//* +//* ================================================================= +//* See http://scmrtos.sourceforge.net for documentation, latest +//* information, license and contact details. +//* ================================================================= +//* +//****************************************************************************** + +#ifndef scmRTOS_H +#define scmRTOS_H + +//----------------------------------------------------------------------------- +// +// !!! The order of includes is important !!! +// +#include <stddef.h> +#include <commdefs.h> +#include <usrlib.h> +#include <OS_Target.h> + +//------------------------------------------------------------------------------ + + +#endif // scmRTOS_H +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/scmRTOS/Common/scmRTOS_defs.h Mon Sep 27 22:51:19 2010 +0000
@@ -0,0 +1,374 @@
+//******************************************************************************
+//*
+//* FULLNAME: Single-Chip Microcontroller Real-Time Operating System
+//*
+//* NICKNAME: scmRTOS
+//*
+//* PURPOSE: Macros And Common Definitions
+//*
+//* Version: 3.10
+//*
+//* $Revision: 256 $
+//* $Date:: 2010-01-22 #$
+//*
+//* Copyright (c) 2003-2010, Harry E. Zhurov
+//*
+//* Permission is hereby granted, free of charge, to any person
+//* obtaining a copy of this software and associated documentation
+//* files (the "Software"), to deal in the Software without restriction,
+//* including without limitation the rights to use, copy, modify, merge,
+//* publish, distribute, sublicense, and/or sell copies of the Software,
+//* and to permit persons to whom the Software is furnished to do so,
+//* subject to the following conditions:
+//*
+//* The above copyright notice and this permission notice shall be included
+//* in all copies or substantial portions of the Software.
+//*
+//* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+//* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+//* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+//* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+//* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+//* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
+//* THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//*
+//* =================================================================
+//* See http://scmrtos.sourceforge.net for documentation, latest
+//* information, license and contact details.
+//* =================================================================
+//*
+//******************************************************************************
+
+#ifndef scmRTOS_DEFS_H
+#define scmRTOS_DEFS_H
+
+#include <commdefs.h>
+
+//------------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+//
+//
+/// Macro for Channel Type definition
+//
+//
+#define DefineChannel(Name, Capacity) \
+class Name : public OS::TChannel \
+{ \
+public: \
+ Name() : OS::TChannel(buf, sizeof(buf)) { } \
+ \
+private: \
+ byte buf[Capacity]; \
+ \
+}
+//-----------------------------------------------------------------------------
+//
+// Check CONFIG Macro Definitions
+//
+//
+
+//----------------- scmRTOS_SYSTIMER_NEST_INTS_ENABLE -------------------------
+#ifndef scmRTOS_SYSTIMER_NEST_INTS_ENABLE
+#error "Error: Config macro scmRTOS_SYSTIMER_NEST_INTS_ENABLE must be defined!"
+#endif
+
+#if (scmRTOS_SYSTIMER_NEST_INTS_ENABLE < 0) || (scmRTOS_SYSTIMER_NEST_INTS_ENABLE > 1)
+#error "Error: scmRTOS_SYSTIMER_NEST_INTS_ENABLE must have values 0 or 1 only!"
+#endif
+
+//----------------- scmRTOS_SYSTEM_TICKS_ENABLE -------------------------------
+#ifndef scmRTOS_SYSTEM_TICKS_ENABLE
+#error "Error: Config macro scmRTOS_SYSTEM_TICKS_ENABLE must be defined!"
+#endif
+
+#if (scmRTOS_SYSTEM_TICKS_ENABLE < 0) || (scmRTOS_SYSTEM_TICKS_ENABLE > 1)
+#error "Error: scmRTOS_SYSTEM_TICKS_ENABLE must have values 0 or 1 only!"
+#endif
+
+
+//----------------- scmRTOS_SYSTIMER_HOOK_ENABLE ------------------------------
+#ifndef scmRTOS_SYSTIMER_HOOK_ENABLE
+#error "Error: Config macro scmRTOS_SYSTIMER_HOOK_ENABLE must be defined!"
+#endif
+
+#if (scmRTOS_SYSTIMER_HOOK_ENABLE < 0) || (scmRTOS_SYSTIMER_HOOK_ENABLE > 1)
+#error "Error: scmRTOS_SYSTIMER_HOOK_ENABLE must have values 0 or 1 only!"
+#endif
+
+//-------------- scmRTOS_CONTEXT_SWITCH_USER_HOOK_ENABLE ----------------------
+#ifndef scmRTOS_CONTEXT_SWITCH_USER_HOOK_ENABLE
+#error "Error: Config macro scmRTOS_CONTEXT_SWITCH_USER_HOOK_ENABLE must be defined!"
+#endif
+
+#if (scmRTOS_CONTEXT_SWITCH_USER_HOOK_ENABLE < 0) || (scmRTOS_CONTEXT_SWITCH_USER_HOOK_ENABLE > 1)
+#error "Error: scmRTOS_CONTEXT_SWITCH_USER_HOOK_ENABLE must have values 0 or 1 only!"
+#endif
+
+//----------------- scmRTOS_IDLE_HOOK_ENABLE ----------------------------------
+#ifndef scmRTOS_IDLE_HOOK_ENABLE
+#error "Error: Config macro scmRTOS_IDLE_HOOK_ENABLE must be defined!"
+#endif
+
+#if (scmRTOS_IDLE_HOOK_ENABLE < 0) || (scmRTOS_IDLE_HOOK_ENABLE > 1)
+#error "Error: scmRTOS_IDLE_HOOK_ENABLE must have values 0 or 1 only!"
+#endif
+
+//----------------- scmRTOS_CONTEXT_SWITCH_SCHEME -----------------------------
+#ifndef scmRTOS_CONTEXT_SWITCH_SCHEME
+#error "Error: Config macro scmRTOS_CONTEXT_SWITCH_SCHEME must be defined!"
+#endif
+
+#if (scmRTOS_CONTEXT_SWITCH_SCHEME < 0) || (scmRTOS_CONTEXT_SWITCH_SCHEME > 1)
+#error "Error: scmRTOS_CONTEXT_SWITCH_SCHEME must have values 0 or 1 only!"
+#endif
+
+
+//----------------- scmRTOS_PRIORITY_ORDER ------------------------------------
+#ifndef scmRTOS_PRIORITY_ORDER
+#error "Error: Config macro scmRTOS_PRIORITY_ORDER must be defined!"
+#endif
+
+#if (scmRTOS_PRIORITY_ORDER < 0) || (scmRTOS_PRIORITY_ORDER > 1)
+#error "Error: scmRTOS_PRIORITY_ORDER must have values 0 or 1 only!"
+#endif
+
+//----------------- User Hooks inlining ------------------------------------
+#ifndef INLINE_SYS_TIMER_HOOK
+#define INLINE_SYS_TIMER_HOOK
+#endif
+
+#ifndef INLINE_CONTEXT_SWITCH_HOOK
+#define INLINE_CONTEXT_SWITCH_HOOK
+#endif
+
+
+//-----------------------------------------------------------------------------
+//
+/// Priority and process map type definitions
+//
+//
+namespace OS
+{
+ #if scmRTOS_PROCESS_COUNT < 8
+ typedef byte TProcessMap;
+ #elif scmRTOS_PROCESS_COUNT < 16
+ typedef word TProcessMap;
+ #else
+ typedef dword TProcessMap;
+ #endif
+ //------------------------------------------------------
+#if scmRTOS_PRIORITY_ORDER == 0
+ enum TPriority {
+ #if scmRTOS_PROCESS_COUNT > 0
+ pr0,
+ #endif
+ #if scmRTOS_PROCESS_COUNT > 1
+ pr1,
+ #endif
+ #if scmRTOS_PROCESS_COUNT > 2
+ pr2,
+ #endif
+ #if scmRTOS_PROCESS_COUNT > 3
+ pr3,
+ #endif
+ #if scmRTOS_PROCESS_COUNT > 4
+ pr4,
+ #endif
+ #if scmRTOS_PROCESS_COUNT > 5
+ pr5,
+ #endif
+ #if scmRTOS_PROCESS_COUNT > 6
+ pr6,
+ #endif
+ #if scmRTOS_PROCESS_COUNT > 7
+ pr7,
+ #endif
+ #if scmRTOS_PROCESS_COUNT > 8
+ pr8,
+ #endif
+ #if scmRTOS_PROCESS_COUNT > 9
+ pr9,
+ #endif
+ #if scmRTOS_PROCESS_COUNT > 10
+ pr10,
+ #endif
+ #if scmRTOS_PROCESS_COUNT > 11
+ pr11,
+ #endif
+ #if scmRTOS_PROCESS_COUNT > 12
+ pr12,
+ #endif
+ #if scmRTOS_PROCESS_COUNT > 13
+ pr13,
+ #endif
+ #if scmRTOS_PROCESS_COUNT > 14
+ pr14,
+ #endif
+ #if scmRTOS_PROCESS_COUNT > 15
+ pr15,
+ #endif
+ #if scmRTOS_PROCESS_COUNT > 16
+ pr16,
+ #endif
+ #if scmRTOS_PROCESS_COUNT > 17
+ pr17,
+ #endif
+ #if scmRTOS_PROCESS_COUNT > 18
+ pr18,
+ #endif
+ #if scmRTOS_PROCESS_COUNT > 19
+ pr19,
+ #endif
+ #if scmRTOS_PROCESS_COUNT > 20
+ pr20,
+ #endif
+ #if scmRTOS_PROCESS_COUNT > 21
+ pr21,
+ #endif
+ #if scmRTOS_PROCESS_COUNT > 22
+ pr22,
+ #endif
+ #if scmRTOS_PROCESS_COUNT > 23
+ pr23,
+ #endif
+ #if scmRTOS_PROCESS_COUNT > 24
+ pr24,
+ #endif
+ #if scmRTOS_PROCESS_COUNT > 25
+ pr25,
+ #endif
+ #if scmRTOS_PROCESS_COUNT > 26
+ pr26,
+ #endif
+ #if scmRTOS_PROCESS_COUNT > 27
+ pr27,
+ #endif
+ #if scmRTOS_PROCESS_COUNT > 28
+ pr28,
+ #endif
+ #if scmRTOS_PROCESS_COUNT > 29
+ pr29,
+ #endif
+ #if scmRTOS_PROCESS_COUNT > 30
+ pr30,
+ #endif
+ #if (scmRTOS_PROCESS_COUNT > 31) || (scmRTOS_PROCESS_COUNT < 1)
+ #error "Invalid Process Count specification! Must be from 1 to 31."
+ #endif
+ prIDLE
+ };
+#else // scmRTOS_PRIORITY_ORDER == 1
+ enum TPriority {
+ prIDLE,
+ #if scmRTOS_PROCESS_COUNT > 30
+ pr30,
+ #endif
+ #if scmRTOS_PROCESS_COUNT > 29
+ pr29,
+ #endif
+ #if scmRTOS_PROCESS_COUNT > 28
+ pr28,
+ #endif
+ #if scmRTOS_PROCESS_COUNT > 27
+ pr27,
+ #endif
+ #if scmRTOS_PROCESS_COUNT > 26
+ pr26,
+ #endif
+ #if scmRTOS_PROCESS_COUNT > 25
+ pr25,
+ #endif
+ #if scmRTOS_PROCESS_COUNT > 24
+ pr24,
+ #endif
+ #if scmRTOS_PROCESS_COUNT > 23
+ pr23,
+ #endif
+ #if scmRTOS_PROCESS_COUNT > 22
+ pr22,
+ #endif
+ #if scmRTOS_PROCESS_COUNT > 21
+ pr21,
+ #endif
+ #if scmRTOS_PROCESS_COUNT > 20
+ pr20,
+ #endif
+ #if scmRTOS_PROCESS_COUNT > 19
+ pr19,
+ #endif
+ #if scmRTOS_PROCESS_COUNT > 18
+ pr18,
+ #endif
+ #if scmRTOS_PROCESS_COUNT > 17
+ pr17,
+ #endif
+ #if scmRTOS_PROCESS_COUNT > 16
+ pr16,
+ #endif
+ #if scmRTOS_PROCESS_COUNT > 15
+ pr15,
+ #endif
+ #if scmRTOS_PROCESS_COUNT > 14
+ pr14,
+ #endif
+ #if scmRTOS_PROCESS_COUNT > 13
+ pr13,
+ #endif
+ #if scmRTOS_PROCESS_COUNT > 12
+ pr12,
+ #endif
+ #if scmRTOS_PROCESS_COUNT > 11
+ pr11,
+ #endif
+ #if scmRTOS_PROCESS_COUNT > 10
+ pr10,
+ #endif
+ #if scmRTOS_PROCESS_COUNT > 9
+ pr9,
+ #endif
+ #if scmRTOS_PROCESS_COUNT > 8
+ pr8,
+ #endif
+ #if scmRTOS_PROCESS_COUNT > 7
+ pr7,
+ #endif
+ #if scmRTOS_PROCESS_COUNT > 6
+ pr6,
+ #endif
+ #if scmRTOS_PROCESS_COUNT > 5
+ pr5,
+ #endif
+ #if scmRTOS_PROCESS_COUNT > 4
+ pr4,
+ #endif
+ #if scmRTOS_PROCESS_COUNT > 3
+ pr3,
+ #endif
+ #if scmRTOS_PROCESS_COUNT > 2
+ pr2,
+ #endif
+ #if scmRTOS_PROCESS_COUNT > 1
+ pr1,
+ #endif
+ #if scmRTOS_PROCESS_COUNT > 0
+ pr0
+ #endif
+ #if (scmRTOS_PROCESS_COUNT > 31) || (scmRTOS_PROCESS_COUNT < 1)
+ #error "Invalid Process Count specification! Must be from 1 to 31."
+ #endif
+ };
+#endif //scmRTOS_PRIORITY_ORDER
+}
+//-----------------------------------------------------------------------------
+//
+// Process's constructor inlining control: default behaviour
+//
+#ifndef INLINE_PROCESS_CTOR
+#define INLINE_PROCESS_CTOR
+#endif
+
+
+//-----------------------------------------------------------------------------
+
+#endif // scmRTOS_DEFS_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/scmRTOS/Common/usrlib.cpp Mon Sep 27 22:51:19 2010 +0000
@@ -0,0 +1,140 @@
+//******************************************************************************
+//*
+//* FULLNAME: Single-Chip Microcontroller Real-Time Operating System
+//*
+//* NICKNAME: scmRTOS
+//*
+//* PURPOSE: User Suport Library Source
+//*
+//* Version: 3.10
+//*
+//* $Revision: 256 $
+//* $Date:: 2010-01-22 #$
+//*
+//* Copyright (c) 2003-2010, Harry E. Zhurov
+//*
+//* Permission is hereby granted, free of charge, to any person
+//* obtaining a copy of this software and associated documentation
+//* files (the "Software"), to deal in the Software without restriction,
+//* including without limitation the rights to use, copy, modify, merge,
+//* publish, distribute, sublicense, and/or sell copies of the Software,
+//* and to permit persons to whom the Software is furnished to do so,
+//* subject to the following conditions:
+//*
+//* The above copyright notice and this permission notice shall be included
+//* in all copies or substantial portions of the Software.
+//*
+//* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+//* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+//* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+//* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+//* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+//* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
+//* THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//*
+//* =================================================================
+//* See http://scmrtos.sourceforge.net for documentation, latest
+//* information, license and contact details.
+//* =================================================================
+//*
+//******************************************************************************
+
+#include <usrlib.h>
+#include <commdefs.h>
+
+using namespace usr;
+
+//------------------------------------------------------------------------------
+//
+/// Circular buffer function-member description
+//
+//
+//
+TCbuf::TCbuf(byte* const Address, const byte Size) :
+ buf(Address),
+ size(Size),
+ count(0),
+ first(0),
+ last(0)
+{
+}
+//------------------------------------------------------------------------------
+bool TCbuf::write(const byte* data, const byte Count)
+{
+ if( Count > (size - count) )
+ return false;
+
+ for(byte i = 0; i < Count; i++)
+ push(*(data++));
+
+ return true;
+}
+//------------------------------------------------------------------------------
+void TCbuf::read(byte* data, const byte Count)
+{
+ byte N = Count <= count ? Count : count;
+
+ for(byte i = 0; i < N; i++)
+ data[i] = pop();
+}
+//------------------------------------------------------------------------------
+byte TCbuf::get_byte(const byte index) const
+{
+ byte x = first + index;
+
+ if(x < size)
+ return buf[x];
+ else
+ return buf[x - size];
+}
+
+//------------------------------------------------------------------------------
+bool TCbuf::put(const byte item)
+{
+ if(count == size)
+ return false;
+
+ push(item);
+ return true;
+}
+//------------------------------------------------------------------------------
+byte TCbuf::get()
+{
+ if(count)
+ return pop();
+ else
+ return 0;
+}
+//------------------------------------------------------------------------------
+//
+/// \note
+/// For internal purposes.
+/// Use this function with care - it doesn't perform free size check.
+//
+void TCbuf::push(const byte item)
+{
+ buf[last] = item;
+ last++;
+ count++;
+
+ if(last == size)
+ last = 0;
+}
+//------------------------------------------------------------------------------
+//
+/// \note
+/// For internal purposes.
+/// Use this function with care - it doesn't perform free size check.
+//
+byte TCbuf::pop()
+{
+ byte item = buf[first];
+
+ count--;
+ first++;
+ if(first == size)
+ first = 0;
+
+ return item;
+}
+//------------------------------------------------------------------------------
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/scmRTOS/Common/usrlib.h Mon Sep 27 22:51:19 2010 +0000
@@ -0,0 +1,298 @@
+//******************************************************************************
+//*
+//* FULLNAME: Single-Chip Microcontroller Real-Time Operating System
+//*
+//* NICKNAME: scmRTOS
+//*
+//* PURPOSE: User Suport Library Header
+//*
+//* Version: 3.10
+//*
+//* $Revision: 256 $
+//* $Date:: 2010-01-22 #$
+//*
+//* Copyright (c) 2003-2010, Harry E. Zhurov
+//*
+//* Permission is hereby granted, free of charge, to any person
+//* obtaining a copy of this software and associated documentation
+//* files (the "Software"), to deal in the Software without restriction,
+//* including without limitation the rights to use, copy, modify, merge,
+//* publish, distribute, sublicense, and/or sell copies of the Software,
+//* and to permit persons to whom the Software is furnished to do so,
+//* subject to the following conditions:
+//*
+//* The above copyright notice and this permission notice shall be included
+//* in all copies or substantial portions of the Software.
+//*
+//* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+//* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+//* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+//* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+//* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+//* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
+//* THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//*
+//* =================================================================
+//* See http://scmrtos.sourceforge.net for documentation, latest
+//* information, license and contact details.
+//* =================================================================
+//*
+//******************************************************************************
+
+#ifndef USRLIB_H
+#define USRLIB_H
+
+#include <commdefs.h>
+
+//------------------------------------------------------------------------------
+//
+// DESCRIPTON: user namespace for some useful types and functions
+//
+//
+namespace usr
+{
+ //------------------------------------------------------------------------------
+ //
+ /// The Circular Buffer
+ //
+ /// Byte-wide FIFO.
+ //
+ /// Allows to:
+ /// add byte,
+ /// get byte,
+ /// write bytes from array,
+ /// read bytes to array,
+ /// and some other service actions.
+ //
+ class TCbuf
+ {
+ public:
+ TCbuf(byte* const Address, const byte Size);
+ bool write(const byte* data, const byte Count);
+ void read(byte* const data, const byte Count);
+ byte get_count() const { return count; }
+ byte get_free_size() const { return size - count; }
+ byte get_byte(const byte index) const;
+ void clear() { count = 0; last = first; }
+ bool put(const byte item);
+ byte get();
+
+ private:
+ //------------------------------------------------------------------------------
+ //
+ // DESCRIPTON: For internal purposes
+ //
+ void push(const byte item); ///< Use this function with care - it doesn't perform free size check
+ byte pop(); ///< Use this function with care - it doesn't perform count check
+ //------------------------------------------------------------------------------
+
+ private:
+ byte* buf;
+ byte size;
+ volatile byte count;
+ byte first;
+ byte last;
+ };
+ //------------------------------------------------------------------------------
+
+
+
+ //-----------------------------------------------------------------------
+ //
+ /// The Ring Buffer Template
+ ///
+ /// Carries out FIFO functionality for
+ /// arbitrary data types
+ ///
+ /// Allows to:
+ /// add item to back (default),
+ /// add item to front,
+ /// get item at front (default),
+ /// get item from back,
+ /// write items from array,
+ /// read items to array and some other actions
+ //
+ //
+ //
+ template<typename T, word Size, typename S = byte>
+ class ring_buffer
+ {
+ public:
+ ring_buffer() : Count(0), First(0), Last(0) { }
+
+ //----------------------------------------------------------------
+ //
+ // Data transfer functions
+ //
+ bool write(const T* data, const S cnt);
+ void read(T* const data, const S cnt);
+
+ bool push_back(const T item);
+ bool push_front(const T item);
+
+ T pop_front();
+ T pop_back();
+
+ bool push(const T item) { return push_back(item); }
+ T pop() { return pop_front(); }
+
+ //----------------------------------------------------------------
+ //
+ // Service functions
+ //
+ S get_count() const { return Count; }
+ S get_free_size() const { return Size - Count; }
+ T& operator[](const S index);
+ void flush() { Count = 0; Last = First; }
+
+ private:
+ //--------------------------------------------------------------
+ // DESCRIPTON: For internal purposes
+ // Use this functions with care: it don't perform
+ // free size and count check
+ //
+ void push_item(const T item);
+ void push_item_front(const T item);
+ T pop_item();
+ T pop_item_back();
+ //--------------------------------------------------------------
+
+ private:
+ S Count;
+ S First;
+ S Last;
+ T Buf[Size];
+ };
+ //------------------------------------------------------------------
+}
+//---------------------------------------------------------------------------
+
+
+//------------------------------------------------------------------------------
+//
+// The ring buffer function-member definitions
+//
+//
+//
+template<typename T, word Size, typename S>
+bool usr::ring_buffer<T, Size, S>::write(const T* data, const S cnt)
+{
+ if( cnt > (Size - Count) )
+ return false;
+
+ for(S i = 0; i < cnt; i++)
+ push_item(*(data++));
+
+ return true;
+}
+//------------------------------------------------------------------------------
+template<typename T, word Size, typename S>
+void usr::ring_buffer<T, Size, S>::read(T* data, const S cnt)
+{
+ S nItems = cnt <= Count ? cnt : Count;
+
+ for(S i = 0; i < nItems; i++)
+ data[i] = pop_item();
+}
+//------------------------------------------------------------------------------
+template<typename T, word Size, typename S>
+T& usr::ring_buffer<T, Size, S>::operator[](const S index)
+{
+ S x = First + index;
+
+ if(x < Size)
+ return Buf[x];
+ else
+ return Buf[x - Size];
+}
+
+//------------------------------------------------------------------------------
+template<typename T, word Size, typename S>
+bool usr::ring_buffer<T, Size, S>::push_back(const T item)
+{
+ if(Count == Size)
+ return false;
+
+ push_item(item);
+ return true;
+}
+//------------------------------------------------------------------------------
+template<typename T, word Size, typename S>
+bool usr::ring_buffer<T, Size, S>::push_front(const T item)
+{
+ if(Count == Size)
+ return false;
+
+ push_item_front(item);
+ return true;
+}
+//------------------------------------------------------------------------------
+template<typename T, word Size, typename S>
+T usr::ring_buffer<T, Size, S>::pop_front()
+{
+ if(Count)
+ return pop_item();
+ else
+ return Buf[First];
+}
+//------------------------------------------------------------------------------
+template<typename T, word Size, typename S>
+T usr::ring_buffer<T, Size, S>::pop_back()
+{
+ if(Count)
+ return pop_item_back();
+ else
+ return Buf[First];
+}
+//------------------------------------------------------------------------------
+template<typename T, word Size, typename S>
+void usr::ring_buffer<T, Size, S>::push_item(const T item)
+{
+ Buf[Last] = item;
+ Last++;
+ Count++;
+
+ if(Last == Size)
+ Last = 0;
+}
+//------------------------------------------------------------------------------
+template<typename T, word Size, typename S>
+void usr::ring_buffer<T, Size, S>::push_item_front(const T item)
+{
+ if(First == 0)
+ First = Size - 1;
+ else
+ --First;
+ Buf[First] = item;
+ Count++;
+}
+//------------------------------------------------------------------------------
+template<typename T, word Size, typename S>
+T usr::ring_buffer<T, Size, S>::pop_item()
+{
+ T item = Buf[First];
+
+ Count--;
+ First++;
+ if(First == Size)
+ First = 0;
+
+ return item;
+}
+//------------------------------------------------------------------------------
+template<typename T, word Size, typename S>
+T usr::ring_buffer<T, Size, S>::pop_item_back()
+{
+
+ if(Last == 0)
+ Last = Size - 1;
+ else
+ --Last;
+
+ Count--;
+ return Buf[Last];;
+}
+//------------------------------------------------------------------------------
+
+
+#endif // USRLIB_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/scmRTOS/CortexM3/OS_Target.h Mon Sep 27 22:51:19 2010 +0000
@@ -0,0 +1,236 @@
+//******************************************************************************
+//*
+//* FULLNAME: Single-Chip Microcontroller Real-Time Operating System
+//*
+//* NICKNAME: scmRTOS
+//*
+//* PROCESSOR: ARM Cortex-M3
+//*
+//* TOOLKIT: RVCT (ARM)
+//*
+//* PURPOSE: Target Dependent Stuff Header. Declarations And Definitions
+//*
+//* Version: 3.10
+//*
+//* $Revision: 195 $
+//* $Date:: 2008-06-19 #$
+//*
+//* Copyright (c) 2003-2010, Harry E. Zhurov
+//*
+//* Permission is hereby granted, free of charge, to any person
+//* obtaining a copy of this software and associated documentation
+//* files (the "Software"), to deal in the Software without restriction,
+//* including without limitation the rights to use, copy, modify, merge,
+//* publish, distribute, sublicense, and/or sell copies of the Software,
+//* and to permit persons to whom the Software is furnished to do so,
+//* subject to the following conditions:
+//*
+//* The above copyright notice and this permission notice shall be included
+//* in all copies or substantial portions of the Software.
+//*
+//* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+//* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+//* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+//* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+//* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+//* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
+//* THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//*
+//* =================================================================
+//* See http://scmrtos.sourceforge.net for documentation, latest
+//* information, license and contact details.
+//* =================================================================
+//*
+//******************************************************************************
+//* Ported by Andrey Chuikin, Copyright (c) 2008-2010
+
+#ifndef scmRTOS_CORTEXM3_H
+#define scmRTOS_CORTEXM3_H
+
+#include <commdefs.h>
+
+//------------------------------------------------------------------------------
+//
+// Compiler and Target checks
+//
+//
+#ifndef __ARMCC_VERSION
+#error "This file should only be compiled with ARM RVCT Compiler"
+#endif // __ARMCC_VERSION
+
+#if __TARGET_ARCH_ARM != 0 || __TARGET_ARCH_THUMB != 4
+#error "This file must be compiled for ARMv7-M (Cortex-M3) processor only."
+#endif
+
+//------------------------------------------------------------------------------
+//
+// Target specific types
+//
+//
+typedef dword TStackItem;
+typedef dword TStatusReg;
+
+//-----------------------------------------------------------------------------
+//
+// Configuration macros
+//
+//
+#define OS_PROCESS __attribute__((__noreturn__))
+#define OS_INTERRUPT
+#define DUMMY_INSTR() __NOP()
+#define INLINE_PROCESS_CTOR INLINE inline
+
+//-----------------------------------------------------------------------------
+//
+// Uncomment macro value below for SystemTimer() run in critical section
+//
+// This is useful (and necessary) when target processor has hardware
+// enabled nested interrups. Cortex-M3 have such interrupts.
+//
+#define SYS_TIMER_CRIT_SECT() TCritSect cs
+
+//-----------------------------------------------------------------------------
+// Separate return stack not required
+#define SEPARATE_RETURN_STACK 0
+
+//-----------------------------------------------------------------------------
+// Software interrupt stack switching not supported in Cortex-M3 port
+// because processor implements hardware stack switching.
+// So, system timer isr wrapper can't be choosen at project level
+//
+#define scmRTOS_ISRW_TYPE TISRW
+
+//-----------------------------------------------------------------------------
+//
+// scmRTOS Context Switch Scheme
+//
+// The macro defines a context switch manner. Value 0 sets direct context
+// switch in the scheduler and in the OS ISRs. This is the primary method.
+// Value 1 sets the second way to switch context - by using of software
+// interrupt. See documentation fo details.
+// Cortex-M3 port supports software interrupt switch method only.
+//
+#define scmRTOS_CONTEXT_SWITCH_SCHEME 1
+
+//-----------------------------------------------------------------------------
+//
+// Include project-level configurations
+// !!! The order of includes is important !!!
+//
+#include "../../scmRTOS_config.h"
+#include "../scmRTOS_TARGET_CFG.h"
+#include <scmRTOS_defs.h>
+#include <LPC17xx.h>
+
+//-----------------------------------------------------------------------------
+//
+// The Critital Section Wrapper
+//
+//
+#define __enable_interrupt() __enable_irq()
+#define __disable_interrupt() __disable_irq()
+
+#define __set_interrupt_state(status) __set_PRIMASK(status)
+#define __get_interrupt_state() __get_PRIMASK()
+
+class TCritSect
+{
+public:
+ TCritSect () : StatusReg(__get_interrupt_state()) { __disable_interrupt(); }
+ ~TCritSect() { __set_interrupt_state(StatusReg); }
+
+private:
+ TStatusReg StatusReg;
+};
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+//
+// Priority stuff
+//
+//
+namespace OS
+{
+INLINE inline OS::TProcessMap GetPrioTag(const byte pr) { return static_cast<OS::TProcessMap> (1 << pr); }
+
+#if scmRTOS_PRIORITY_ORDER == 0
+ INLINE inline byte GetHighPriority(TProcessMap pm)
+ {
+ byte pr = 0;
+
+ while( !(pm & 0x0001) )
+ {
+ pr++;
+ pm >>= 1;
+ }
+ return pr;
+ }
+#else
+ INLINE inline byte GetHighPriority(TProcessMap pm) { return (31 - __clz(pm)); }
+#endif // scmRTOS_PRIORITY_ORDER
+}
+
+//-----------------------------------------------------------------------------
+//
+// Interrupt and Interrupt Service Routines support
+//
+INLINE inline TStatusReg GetInterruptState( ) { return __get_interrupt_state(); }
+INLINE inline void SetInterruptState(TStatusReg sr) { __set_interrupt_state(sr); }
+
+INLINE inline void EnableInterrupts() { __enable_interrupt(); }
+INLINE inline void DisableInterrupts() { __disable_interrupt(); }
+
+
+namespace OS
+{
+ INLINE inline void EnableContextSwitch() { EnableInterrupts(); }
+ INLINE inline void DisableContextSwitch() { DisableInterrupts(); }
+}
+
+#include <OS_Kernel.h>
+
+namespace OS
+{
+ //--------------------------------------------------------------------------
+ //
+ // NAME : OS ISR support
+ //
+ // PURPOSE : Implements common actions on interrupt enter and exit
+ // under the OS
+ //
+ // DESCRIPTION:
+ //
+ //
+ class TISRW
+ {
+ public:
+ INLINE TISRW() { ISR_Enter(); }
+ INLINE ~TISRW() { ISR_Exit(); }
+
+ private:
+ //-----------------------------------------------------
+ INLINE void ISR_Enter()
+ {
+ TCritSect cs;
+ Kernel.ISR_NestCount++;
+ }
+ //-----------------------------------------------------
+ INLINE void ISR_Exit()
+ {
+ TCritSect cs;
+ if(--Kernel.ISR_NestCount) return;
+ Kernel.SchedISR();
+ }
+ //-----------------------------------------------------
+ };
+
+ // No software interrupt stack switching provided,
+ // TISRW_SS declared to be the same as TISRW for porting compability
+ #define TISRW_SS TISRW
+
+} // ns OS
+//-----------------------------------------------------------------------------
+
+#endif // scmRTOS_CORTEXM3_H
+//-----------------------------------------------------------------------------
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/scmRTOS/CortexM3/OS_Target_asm.s Mon Sep 27 22:51:19 2010 +0000
@@ -0,0 +1,178 @@
+; ******************************************************************************
+; *
+; * FULLNAME: Single-Chip Microcontroller Real-Time Operating System
+; *
+; * NICKNAME: scmRTOS
+; *
+; * PROCESSOR: ARM Cortex-M3
+; *
+; * TOOLKIT: EWARM (IAR Systems)
+; *
+; * PURPOSE: Target Dependent Low-Level Stuff
+; *
+; * Version: 3.10
+; *
+; * $Revision: 195 $
+; * $Date:: 2008-06-19 #$
+; *
+; * Copyright (c) 2003-2010, Harry E. Zhurov
+; *
+; * Permission is hereby granted, free of charge, to any person
+; * obtaining a copy of this software and associated documentation
+; * files (the "Software"), to deal in the Software without restriction,
+; * including without limitation the rights to use, copy, modify, merge,
+; * publish, distribute, sublicense, and/or sell copies of the Software,
+; * and to permit persons to whom the Software is furnished to do so,
+; * subject to the following conditions:
+; *
+; * The above copyright notice and this permission notice shall be included
+; * in all copies or substantial portions of the Software.
+; *
+; * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+; * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+; * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+; * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+; * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+; * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
+; * THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+; *
+; * =================================================================
+; * See http://scmrtos.sourceforge.net for documentation, latest
+; * information, license and contact details.
+; * =================================================================
+; *
+; ******************************************************************************
+; * Ported by Andrey Chuikin, Copyright (c) 2008-2010
+
+; #include "scmRTOS_TARGET_CFG.h"
+
+; -----------------------------------------------------------------------------
+; PUBLIC FUNCTIONS
+;
+ EXTERN OS_ContextSwitchHook
+
+ EXPORT OS_Start
+ EXPORT PendSV_Handler
+
+; -----------------------------------------------------------------------------
+; EQUATES
+;
+NVIC_INT_CTRL EQU 0xE000ED04 ; Interrupt control state register.
+NVIC_PENDSVSET EQU 0x10000000 ; Value to trigger PendSV exception.
+
+NVIC_SYSPRI14 EQU 0xE000ED22 ; System priority register (priority 14).
+NVIC_PENDSV_PRI EQU 0xFF ; PendSV priority value (lowest).
+NVIC_SYSPRI15 EQU 0xE000ED23 ; System priority register (priority 15).
+NVIC_ST_PRI EQU 0xFF ; SysTick priority value (lowest).
+
+NVIC_ST_CTRL EQU 0xE000E010 ; SysTick Ctrl & Status Reg.
+NVIC_ST_RELOAD EQU 0xE000E014 ; SysTick Reload Value Reg.
+NVIC_ST_CTRL_CLK_SRC EQU 0x00000004 ; Clock Source.
+NVIC_ST_CTRL_INTEN EQU 0x00000002 ; Interrupt enable.
+NVIC_ST_CTRL_ENABLE EQU 0x00000001 ; Counter mode.
+
+; should be the same as in scmRTOS_TARGET_CFG.h
+SYSTICKFREQ EQU 100000000
+SYSTICKINTRATE EQU 1000
+
+; -----------------------------------------------------------------------------
+; CODE GENERATION DIRECTIVES
+;
+ AREA TEXT, CODE, READONLY
+ THUMB
+
+; -----------------------------------------------------------------------------
+; HANDLE PendSV EXCEPTION
+; void PendSV_Handler(void)
+;
+; Note(s) : 1) PendSV is used to cause a context switch. This is a recommended method for performing
+; context switches with Cortex-M3. This is because the Cortex-M3 auto-saves half of the
+; processor context on any exception, and restores same on return from exception. So only
+; saving of R4-R11 is required and fixing up the stack pointers. Using the PendSV exception
+; this way means that context saving and restoring is identical whether it is initiated from
+; a thread or occurs due to an interrupt or exception.
+;
+; 2) Pseudo-code is:
+; a) Get the process SP, if 0 then skip (goto f) the saving part (first context switch);
+; b) Save remaining regs r4-r11 on process stack;
+; c) Call OS_ContextSwitchHook for save current task SP and get new task SP;
+; d) Restore R4-R11 from new process stack;
+; e) Perform exception return which will restore remaining context.
+; f) Get SP for the first context switch (R2 hold it);
+; run SysTick; goto d);
+;
+; 3) On entry into PendSV handler:
+; a) The following have been saved on the process stack (by processor):
+; xPSR, PC, LR, R12, R0-R3
+; b) Processor mode is switched to Handler mode (from Thread mode)
+; c) Stack is Main stack (switched from Process stack)
+;
+; 4) Since PendSV is set to lowest priority in the system (by OS_Start() below), we
+; know that it will only be run when no other exception or interrupt is active, and
+; therefore safe to assume that context being switched out was using the process stack (PSP).
+;
+PendSV_Handler
+ CPSID I ; Prevent interruption during context switch
+ MRS R0, PSP ; PSP is process stack pointer
+ CBZ R0, nosave ; Skip register save the first time
+
+ STMDB R0!, {R4-R11} ; Save remaining regs r4-11 on process stack
+ ; At this point, entire context of process has been saved
+
+ PUSH {R14} ; Save LR exc_return value
+ LDR R1, =OS_ContextSwitchHook ; OS_ContextSwitchHook();
+ BLX R1
+ POP {R14}
+
+ContextRestore
+ ; R0 is new process SP;
+ LDMIA R0!, {R4-R11} ; Restore r4-11 from new process stack
+ MSR PSP, R0 ; Load PSP with new process SP
+ ORR LR, LR, #0x04 ; Ensure exception return uses process stack
+ CPSIE I
+ BX LR ; Exception return will restore remaining context
+nosave
+ MOV R0, R2 ; R2 hold the first task SP
+
+ LDR R1, =NVIC_ST_CTRL ; Enable and run SysTick
+ LDR R2, =(NVIC_ST_CTRL_CLK_SRC | NVIC_ST_CTRL_INTEN | NVIC_ST_CTRL_ENABLE)
+ STR R2, [R1]
+
+ B ContextRestore
+
+
+; -----------------------------------------------------------------------------
+; START MULTITASKING
+; void OS_Start(TStackItem* sp)
+;
+; Note(s) : 1) OS_Start() MUST:
+; a) Setup PendSV and SysTick exception priority to lowest;
+; b) Setup SysTick (reload value);
+; c) Enable interrupts (tasks will run with interrupts enabled).
+;
+OS_Start
+ LDR R1, =NVIC_SYSPRI14 ; Set the PendSV exception priority (lowest)
+ LDR R2, =NVIC_PENDSV_PRI
+ STRB R2, [R1]
+ LDR R1, =NVIC_SYSPRI15 ; Set the SysTick exception priority (lowest)
+ LDR R2, =NVIC_ST_PRI
+ STRB R2, [R1]
+
+ LDR R1, =NVIC_ST_RELOAD ; Setup SysTick
+ LDR R2, =(SYSTICKFREQ/SYSTICKINTRATE-1)
+ STR R2, [R1]
+
+ MOV R2, R0 ; Save the first task stack
+ MOVS R0, #0 ; Set the PSP to 0 for initial context switch call
+ MSR PSP, R0
+
+ LDR R0, =NVIC_INT_CTRL ; Trigger the PendSV exception (causes context switch)
+ LDR R1, =NVIC_PENDSVSET
+ STR R1, [R0]
+
+ CPSIE I ; Enable interrupts at processor level
+loop
+ B loop ; Should never get here
+
+
+ END
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/scmRTOS/CortexM3/OS_Target_cpp.cpp Mon Sep 27 22:51:19 2010 +0000
@@ -0,0 +1,131 @@
+//******************************************************************************
+//*
+//* FULLNAME: Single-Chip Microcontroller Real-Time Operating System
+//*
+//* NICKNAME: scmRTOS
+//*
+//* PROCESSOR: ARM Cortex-M3
+//*
+//* TOOLKIT: EWARM (IAR Systems)
+//*
+//* PURPOSE: Target Dependent Stuff Source
+//*
+//* Version: 3.10
+//*
+//* $Revision: 195 $
+//* $Date:: 2008-06-19 #$
+//*
+//* Copyright (c) 2003-2010, Harry E. Zhurov
+//*
+//* Permission is hereby granted, free of charge, to any person
+//* obtaining a copy of this software and associated documentation
+//* files (the "Software"), to deal in the Software without restriction,
+//* including without limitation the rights to use, copy, modify, merge,
+//* publish, distribute, sublicense, and/or sell copies of the Software,
+//* and to permit persons to whom the Software is furnished to do so,
+//* subject to the following conditions:
+//*
+//* The above copyright notice and this permission notice shall be included
+//* in all copies or substantial portions of the Software.
+//*
+//* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+//* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+//* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+//* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+//* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+//* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
+//* THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//*
+//* =================================================================
+//* See http://scmrtos.sourceforge.net for documentation, latest
+//* information, license and contact details.
+//* =================================================================
+//*
+//******************************************************************************
+//* Ported by Andrey Chuikin, Copyright (c) 2008-2010
+
+
+#include <scmRTOS.h>
+
+using namespace OS;
+
+//------------------------------------------------------------------------------
+//
+// OS Process's constructor
+//
+// Performs:
+// * initializing process data;
+// * registering of the process in kernel;
+// * preparing stack frame;
+//
+//
+TBaseProcess::TBaseProcess(TStackItem* Stack, TPriority pr, void (*exec)())
+ : StackPointer(Stack)
+ , Timeout(0)
+ , Priority(pr)
+{
+ Kernel.RegisterProcess(this);
+
+ //---------------------------------------------------------------
+ //
+ // Prepare Process Stack Frame
+ //
+ *(--StackPointer) = 0x01000000L; // xPSR
+ *(--StackPointer) = reinterpret_cast<dword>(exec); // Entry Point
+ StackPointer -= 14; // emulate "push R14,R12,R3,R2,R1,R0,R11-R4"
+
+ // The code below can be used for debug purpose. In this case comment
+ // line above and uncomment block below.
+/*
+ *(--StackPointer) = 0xFFFFFFFEL; // R14 (LR) (init value will cause fault if ever used)
+ *(--StackPointer) = 0x12121212L; // R12
+ *(--StackPointer) = 0x03030303L; // R3
+ *(--StackPointer) = 0x02020202L; // R2
+ *(--StackPointer) = 0x01010101L; // R1
+ *(--StackPointer) = 0x00000000L; // R0
+
+ // Remaining registers saved on process stack
+ *(--StackPointer) = 0x11111111L; // R11
+ *(--StackPointer) = 0x10101010L; // R10
+ *(--StackPointer) = 0x09090909L; // R9
+ *(--StackPointer) = 0x08080808L; // R8
+ *(--StackPointer) = 0x07070707L; // R7
+ *(--StackPointer) = 0x06060606L; // R6
+ *(--StackPointer) = 0x05050505L; // R5
+ *(--StackPointer) = 0x04040404L; // R4
+*/
+}
+//------------------------------------------------------------------------------
+//
+// Idle Process
+//
+typedef process<prIDLE, scmRTOS_IDLE_PROCESS_STACK_SIZE> TIdleProcess;
+
+TIdleProcess IdleProcess;
+
+template<> OS_PROCESS void TIdleProcess::Exec()
+{
+ for(;;)
+ {
+ #if scmRTOS_IDLE_HOOK_ENABLE == 1
+ IdleProcessUserHook();
+ #endif
+ }
+}
+//------------------------------------------------------------------------------
+OS_INTERRUPT void OS::SysTick_Handler()
+{
+ scmRTOS_ISRW_TYPE ISR;
+
+ Kernel.SystemTimer();
+
+#if scmRTOS_SYSTIMER_NEST_INTS_ENABLE == 0
+ DISABLE_NESTED_INTERRUPTS();
+#endif
+
+#if scmRTOS_SYSTIMER_HOOK_ENABLE == 1
+ SystemTimerUserHook();
+#endif
+}
+//------------------------------------------------------------------------------
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/scmRTOS/CortexM3/commdefs.h Mon Sep 27 22:51:19 2010 +0000
@@ -0,0 +1,71 @@
+//******************************************************************************
+//*
+//* FULLNAME: Single-Chip Microcontroller Real-Time Operating System
+//*
+//* NICKNAME: scmRTOS
+//*
+//* PROCESSOR: ARM Cortex-M3
+//*
+//* TOOLKIT: EWARM (IAR Systems)
+//*
+//* PURPOSE: Common Type Definitions
+//*
+//* Version: 3.10
+//*
+//* $Revision: 195 $
+//* $Date:: 2008-06-19 #$
+//*
+//* Copyright (c) 2003-2010, Harry E. Zhurov
+//*
+//* Permission is hereby granted, free of charge, to any person
+//* obtaining a copy of this software and associated documentation
+//* files (the "Software"), to deal in the Software without restriction,
+//* including without limitation the rights to use, copy, modify, merge,
+//* publish, distribute, sublicense, and/or sell copies of the Software,
+//* and to permit persons to whom the Software is furnished to do so,
+//* subject to the following conditions:
+//*
+//* The above copyright notice and this permission notice shall be included
+//* in all copies or substantial portions of the Software.
+//*
+//* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+//* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+//* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+//* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+//* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+//* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
+//* THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//*
+//* =================================================================
+//* See http://scmrtos.sourceforge.net for documentation, latest
+//* information, license and contact details.
+//* =================================================================
+//*
+//******************************************************************************
+//* Ported by Andrey Chuikin, Copyright (c) 2008-2010
+
+
+#ifndef COMMONDEFS_H
+#define COMMONDEFS_H
+
+#ifndef __IAR_SYSTEMS_ASM__
+
+typedef unsigned char byte;
+typedef signed char sbyte;
+typedef unsigned short word;
+typedef unsigned long dword;
+
+typedef volatile byte sfr_byte;
+typedef volatile word sfr_word;
+typedef volatile dword sfr_dword;
+
+#define INLINE _Pragma("inline=forced")
+
+#endif // __IAR_SYSTEMS_ASM__
+
+#endif // COMMONDEFS_H
+
+//-----------------------------------------------------------------------------
+
+/*============================================================================*/
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scmRTOS/CortexM3/device.h Mon Sep 27 22:51:19 2010 +0000 @@ -0,0 +1,60 @@ +//****************************************************************************** +//* +//* FULLNAME: Single-Chip Microcontroller Real-Time Operating System +//* +//* NICKNAME: scmRTOS +//* +//* PROCESSOR: ARM Cortex-M3 +//* +//* TOOLKIT: EWARM (IAR Systems) +//* +//* PURPOSE: Device Definitions +//* +//* Version: 3.10 +//* +//* $Revision: 196 $ +//* $Date:: 2008-06-19 #$ +//* +//* Copyright (c) 2003-2010, Harry E. Zhurov +//* +//* Permission is hereby granted, free of charge, to any person +//* obtaining a copy of this software and associated documentation +//* files (the "Software"), to deal in the Software without restriction, +//* including without limitation the rights to use, copy, modify, merge, +//* publish, distribute, sublicense, and/or sell copies of the Software, +//* and to permit persons to whom the Software is furnished to do so, +//* subject to the following conditions: +//* +//* The above copyright notice and this permission notice shall be included +//* in all copies or substantial portions of the Software. +//* +//* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +//* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +//* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +//* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +//* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +//* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH +//* THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +//* +//* ================================================================= +//* See http://scmrtos.sourceforge.net for documentation, latest +//* information, license and contact details. +//* ================================================================= +//* +//****************************************************************************** +//* Ported by Andrey Chuikin, Copyright (c) 2008-2010 + +#ifndef DEVICE_H +#define DEVICE_H + +#include <commdefs.h> + +//------------------------------------------------------------------------------ +// Definitions for some processor registers in order to not include specific +// header file for various Cortex-M3 processor derivatives. +#define CPU_ICSR ( ( sfr_dword *) 0xE000ED04 ) // Interrupt Control State Register +#define CPU_SYSTICKCSR ( ( sfr_dword *) 0xE000E010 ) // SysTick Control and Status Register +#define CPU_SYSTICKCSR_EINT 0x02 // Bit for enable/disable SysTick interrupt + + +#endif /* DEVICE_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/scmRTOS/scmRTOS_TARGET_CFG.h Mon Sep 27 22:51:19 2010 +0000
@@ -0,0 +1,102 @@
+//******************************************************************************
+//*
+//* FULLNAME: Single-Chip Microcontroller Real-Time Operating System
+//*
+//* NICKNAME: scmRTOS
+//*
+//* PROCESSOR: ARM Cortex-M3
+//*
+//* TOOLKIT: EWARM (IAR Systems)
+//*
+//* PURPOSE: Project Level Target Extensions Config
+//*
+//* Version: 3.10
+//*
+//* $Revision: 196 $
+//* $Date:: 2008-06-19 #$
+//*
+//* Copyright (c) 2003-2010, Harry E. Zhurov
+//*
+//* Permission is hereby granted, free of charge, to any person
+//* obtaining a copy of this software and associated documentation
+//* files (the "Software"), to deal in the Software without restriction,
+//* including without limitation the rights to use, copy, modify, merge,
+//* publish, distribute, sublicense, and/or sell copies of the Software,
+//* and to permit persons to whom the Software is furnished to do so,
+//* subject to the following conditions:
+//*
+//* The above copyright notice and this permission notice shall be included
+//* in all copies or substantial portions of the Software.
+//*
+//* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+//* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+//* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+//* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+//* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+//* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
+//* THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//*
+//* =================================================================
+//* See http://scmrtos.sourceforge.net for documentation, latest
+//* information, license and contact details.
+//* =================================================================
+//*
+//******************************************************************************
+//* mbed port by Igor Skochinsky
+
+#ifndef scmRTOS_TARGET_CFG_H
+#define scmRTOS_TARGET_CFG_H
+
+#include "device.h"
+
+// Define SysTick clock frequency and its interrupt rate in Hz.
+#define SYSTICKFREQ 100000000
+#define SYSTICKINTRATE 1000
+
+//------------------------------------------------------------------------------
+//
+// System Timer stuff
+//
+//
+namespace OS
+{
+extern "C" void SysTick_Handler();
+}
+
+#define LOCK_SYSTEM_TIMER() ( *CPU_SYSTICKCSR &= ~CPU_SYSTICKCSR_EINT )
+#define UNLOCK_SYSTEM_TIMER() ( *CPU_SYSTICKCSR |= CPU_SYSTICKCSR_EINT )
+
+//------------------------------------------------------------------------------
+//
+// Context Switch ISR stuff
+//
+//
+namespace OS
+{
+#if scmRTOS_IDLE_HOOK_ENABLE == 1
+ void IdleProcessUserHook();
+#endif
+
+#if scmRTOS_CONTEXT_SWITCH_SCHEME == 1
+
+ INLINE inline void RaiseContextSwitch() { *CPU_ICSR |= 0x10000000; }
+
+ #define ENABLE_NESTED_INTERRUPTS()
+
+ #if scmRTOS_SYSTIMER_NEST_INTS_ENABLE == 0
+ #define DISABLE_NESTED_INTERRUPTS() TCritSect cs
+ #else
+ #define DISABLE_NESTED_INTERRUPTS()
+ #endif
+
+#else
+ #error "Cortex-M3 port supports software interrupt switch method only!"
+
+#endif // scmRTOS_CONTEXT_SWITCH_SCHEME
+
+}
+//-----------------------------------------------------------------------------
+
+#endif // scmRTOS_TARGET_CFG_H
+//-----------------------------------------------------------------------------
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scmRTOS_config.h Mon Sep 27 22:51:19 2010 +0000 @@ -0,0 +1,132 @@ +//****************************************************************************** +//* +//* FULLNAME: Single-Chip Microcontroller Real-Time Operating System +//* +//* NICKNAME: scmRTOS +//* +//* PROCESSOR: ARM Cortex-M3 +//* +//* TOOLKIT: EWARM (IAR Systems) +//* +//* PURPOSE: Project Level Configuration +//* +//* Version: 3.10 +//* +//* $Revision: 196 $ +//* $Date:: 2008-06-19 #$ +//* +//* Copyright (c) 2003-2010, Harry E. Zhurov +//* +//* Permission is hereby granted, free of charge, to any person +//* obtaining a copy of this software and associated documentation +//* files (the "Software"), to deal in the Software without restriction, +//* including without limitation the rights to use, copy, modify, merge, +//* publish, distribute, sublicense, and/or sell copies of the Software, +//* and to permit persons to whom the Software is furnished to do so, +//* subject to the following conditions: +//* +//* The above copyright notice and this permission notice shall be included +//* in all copies or substantial portions of the Software. +//* +//* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +//* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +//* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +//* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +//* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +//* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH +//* THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +//* +//* ================================================================= +//* See http://scmrtos.sourceforge.net for documentation, latest +//* information, license and contact details. +//* ================================================================= +//* +//****************************************************************************** +//* Ported by Andrey Chuikin, Copyright (c) 2008-2010 + +#ifndef scmRTOS_CONFIG_H +#define scmRTOS_CONFIG_H + +#ifndef __IAR_SYSTEMS_ASM__ +#include <commdefs.h> + +typedef word TTimeout; + +#endif // __IAR_SYSTEMS_ASM__ + +#include "device.h" +//------------------------------------------------------------------------------ +// +// Specify scmRTOS Process Count. Must be less than 31 +// +// +#define scmRTOS_PROCESS_COUNT 1 + +//----------------------------------------------------------------------------- +// +// scmRTOS System Timer +// +// Nested Interrupts enable macro. Value 1 means that interrupts are +// globally enabled within System Timer ISR (this is default for Cortex-M3). +// +// +#define scmRTOS_SYSTIMER_NEST_INTS_ENABLE 1 + +//----------------------------------------------------------------------------- +// +// scmRTOS System Timer Tick Counter Enable +// +// +#define scmRTOS_SYSTEM_TICKS_ENABLE 1 + + +//----------------------------------------------------------------------------- +// +// scmRTOS System Timer Hook +// +// +#define scmRTOS_SYSTIMER_HOOK_ENABLE 1 + +//----------------------------------------------------------------------------- +// +// scmRTOS Idle Process Hook +// +// +#define scmRTOS_IDLE_HOOK_ENABLE 1 + +//----------------------------------------------------------------------------- +// +// scmRTOS Idle Process Stack size (in bytes) +// (20 * sizeof(TStackItem)) - it's a minimum allowed value. +// +#define scmRTOS_IDLE_PROCESS_STACK_SIZE (20 * sizeof(TStackItem)) + +//----------------------------------------------------------------------------- +// +// scmRTOS Priority Order +// +// This macro defines the order of the process's priorities. Default, +// the ascending order is used. Alternatively, the descending priority +// order can be used. On some platforms the descending order is preferred +// because of performance. +// +// Default (corresponding to ascending order) value of macro is 0. +// Alternative (corresponding to descending order) value of macro is 1. +// +// On Cortex-M3 the descending order is preferred for performance reason. +// +#define scmRTOS_PRIORITY_ORDER 1 + +//----------------------------------------------------------------------------- +// +// scmRTOS Context Switch User Hook enable +// +// The macro enables/disables user defined hook called from system +// Context Switch Hook function. +// +// +#define scmRTOS_CONTEXT_SWITCH_USER_HOOK_ENABLE 0 + + +#endif // scmRTOS_CONFIG_H +//-----------------------------------------------------------------------------