-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathuc_ao.c
137 lines (117 loc) · 4.57 KB
/
uc_ao.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#include "uc_ao.h" /* uC/AO interface */
static char const this_module[] = "uc_ao"; /* this module name for Q_ASSERT() */
/*..........................................................................*/
void Active_ctor(Active *const me, DispatchHandler dispatch) {
me->dispatch = dispatch; /* attach the dispatch handler for the "me" AO */
}
/*..........................................................................*/
/* Thread function for all Active Objects (uC/OS-II task signature) */
static void Active_eventLoop(void *pdata) {
Active *me = (Active *)pdata; /* the AO instance "me" */
/* initialize the AO */
static Event const initEvt = {INIT_SIG};
(*me->dispatch)(me, &initEvt);
/* event loop ("message pump") */
while (1) {
Event *e; /* pointer to event object ("message") */
INT8U err; /* uC/OS-II error status */
/* wait for any event and receive it into object 'e' */
e = OSQPend(me->queue, 0U, &err); /* BLOCKING! */
Q_ASSERT(err == 0U);
/* dispatch event to the active object 'me' */
(*me->dispatch)(me, e); /* NO BLOCKING! */
}
}
/*..........................................................................*/
void Active_start(Active *const me,
uint8_t prio, /* priority (1-based) */
Event **queueSto,
uint32_t queueLen,
void *stackSto,
uint32_t stackSize,
uint16_t opt) {
INT8U err;
OS_STK *stk_sto = stackSto;
INT32U stk_depth = (stackSize / sizeof(OS_STK));
/* precondition */
Q_ASSERT(me /* AO instance must be provided (cannot be NULL) */
&& (0 < prio) && (prio < OS_LOWEST_PRIO - 2U));
me->queue = OSQCreate((void **)queueSto, queueLen);
Q_ASSERT(me->queue); /* queue must be created */
me->thread = OS_LOWEST_PRIO - 2U - prio; /* uC/OS-II priority */
err = OSTaskCreateExt(
&Active_eventLoop, /* the thread function */
me, /* the 'pdata' parameter */
#if OS_STK_GROWTH
&stk_sto[stk_depth - 1], /* ptos */
#else
stk_sto, /* ptos */
#endif
me->thread, /* uC/OS-II priority */
prio, /* task ID -- the unique AO priority */
stk_sto, /* pbos */
stk_depth, /* stack depth */
(void *)0, /* pext */
opt); /* task options */
Q_ASSERT(err == 0U); /* thread must be created */
}
/*..........................................................................*/
void Active_post(Active *const me, Event const *const e) {
OSQPost(me->queue, (void *)e);
}
/*--------------------------------------------------------------------------*/
/* Time Event services... */
static TimeEvent *l_tevt[10]; /* all TimeEvents in the application */
static uint_fast8_t l_tevtNum; /* current number of TimeEvents */
/*..........................................................................*/
void TimeEvent_ctor(TimeEvent *const me, Signal sig, Active *act) {
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr;
#endif
/* no critical section because it is presumed that all TimeEvents
* are created *before* multitasking has started.
*/
me->super.sig = sig;
me->act = act;
me->timeout = 0U;
me->interval = 0U;
/* register one more TimeEvent instance */
OS_ENTER_CRITICAL();
Q_ASSERT(l_tevtNum < sizeof(l_tevt) / sizeof(l_tevt[0]));
l_tevt[l_tevtNum] = me;
++l_tevtNum;
OS_EXIT_CRITICAL();
}
/*..........................................................................*/
void TimeEvent_arm(TimeEvent *const me, uint32_t timeout, uint32_t interval) {
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr;
#endif
OS_ENTER_CRITICAL();
me->timeout = timeout;
me->interval = interval;
OS_EXIT_CRITICAL();
}
/*..........................................................................*/
void TimeEvent_disarm(TimeEvent *const me) {
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr;
#endif
OS_ENTER_CRITICAL();
me->timeout = 0U;
OS_EXIT_CRITICAL();
}
/*..........................................................................*/
void TimeEvent_tick(void) {
uint_fast8_t i;
for (i = 0U; i < l_tevtNum; ++i) {
TimeEvent *const t = l_tevt[i];
Q_ASSERT(t); /* TimeEvent instance must be registered */
if (t->timeout > 0U) { /* is this TimeEvent armed? */
if (--t->timeout == 0U) { /* is it expiring now? */
Active_post(t->act, &t->super);
t->timeout = t->interval; /* rearm or disarm (one-shot) */
}
}
}
}