tl.h


1
#ifndef armv6_m__tl_h
2
#define armv6_m__tl_h
3
4
/*
5
  armv6-m/tl.h 
6
  Copyright 2014 Marc Prager
7
 
8
  This file is part of the c-lpc8 library.
9
  c-lpc8 is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License
10
  as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
11
 
12
  c-lpc8 is published in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
13
  of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
14
 
15
  You should have received a copy of the GNU General Public License along with c-lpc8.
16
  If not see <http://www.gnu.org/licenses/>
17
 */
18
19
/** @file
20
 * @brief Thread loops - a simple context switcher between a thread in a loop and a second context.
21
 *
22
 * This module tl is intended for use in interrupt service routines to synchronized a sequential control flow and the
23
 * interrupt. It's based on cooperative multitasking. Focus is on simplicity.
24
 * tl works with infinite loops only - all threads loops have to continue working indefinitely. Any number of thread
25
 * loops is possible. Scheduling has to be done explicitely. The intended usage is as follows: main() inititializes
26
 * the TlContext structures (stack and nonterminating loop function) and calls tlCreate() for ever thread loop. That
27
 * 'starts' all threads and they run - one after the other - until the first tlYield() in every loop. Upon tlYield()
28
 * control is transferred back to main(). It is then the responsibility of main() (or an ISR!) to wake up the needed
29
 * thread loops by invoking tlCall() for the respective TlContext structure.
30
 * A simple round robin scheduler can be implemented by invoking tlCall() for each thread loop inside the main loop.
31
 */
32
33
/** This data structure is shared between the two contexts an contains all information that is required for context
34
 * switching.
35
 */
36
typedef struct {
37
  void*  spThread;  ///< has to be initialized to a valid (thread) stack pointer.
38
  void*  spCaller;  ///< set/re-set by tlCreate/tlCall.
39
} TlContext;
40
41
// #define NORETURN __attribute__((noreturn,nothrow));
42
#define NORETURN  // line above doesn't work, unfortunately
43
44
/** A thread loop must be of this type. The function MUST NOT return, it has to be a loop.
45
 */
46
typedef void TlLoop (TlContext *ctx) NORETURN;
47
48
/** Creates a new thread loop. This function is typically called from the main thread. Currently it does not return
49
 * until the first tlYield() is executed inside the new thread.
50
 * @param ctx the context switch information storage
51
 * @param loop the thread function (not returning).
52
 */
53
void tlCreate (TlContext *ctx, TlLoop *loop);
54
55
/** This function yields control from the thread to the caller.
56
 * @param ctx the context switch information storage
57
 */
58
void tlYield (TlContext *ctx);
59
60
/** This function continues the thread at the latest yield() call. It will return on the next tlYield() in the thread.
61
 * @param ctx the context switch information storage
62
 */
63
void tlCall (TlContext *ctx);
64
65
#endif