Statistics
| Branch: | Revision:

urtware / src / urt_core.c @ 33aa05c5

History | View | Annotate | Download (8.949 KB)

1 1fb06240 skenneweg
/*
2
µRtWare is a lightweight publish/subscribe middleware for real-time
3
applications. It was developed as part of the software habitat for the
4
Autonomous Mini Robot [1] (AMiRo) but can be used for other purposes as well.
5

6
Copyright (C) 2018..2020  Thomas Schöpping et al.
7

8
This program is free software: you can redistribute it and/or modify
9
it under the terms of the GNU General Public License as published by
10
the Free Software Foundation, either version 3 of the License, or
11
(at your option) any later version.
12

13
This program is distributed in the hope that it will be useful,
14
but WITHOUT ANY WARRANTY; without even the implied warranty of
15
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
GNU General Public License for more details.
17

18
You should have received a copy of the GNU General Public License
19
along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
*/
21
22 7d9678db skenneweg
#include <urtware.h>
23
24 1fb06240 skenneweg
/******************************************************************************/
25
/* LOCAL DEFINITIONS                                                          */
26
/******************************************************************************/
27
28
/******************************************************************************/
29
/* EXPORTED VARIABLES                                                         */
30
/******************************************************************************/
31
32
/******************************************************************************/
33
/* LOCAL TYPES                                                                */
34
/******************************************************************************/
35
36 408a606c skenneweg
/**
37
 * @brief  core
38
 */
39
typedef struct urt_core
40
{
41
  urt_node_t* _nodes;
42 792f6c74 skenneweg
  urt_osEventSource_t _evtSource;
43 408a606c skenneweg
  urt_osMutex_t _lock;
44
  urt_status_t _status;
45
  #if (URT_CFG_PUBSUB_ENABLED)
46
    urt_topic_t* _topics;
47
  #endif /* URT_CFG_PUBSUB_ENABLED */
48
  #if (URT_CFG_RPC_ENABLED)
49
    urt_service_t* _services;
50
  #endif /* URT_CFG_RPC_ENABLED */
51
}urt_core_t;
52
53
static urt_core_t core;
54
55 1fb06240 skenneweg
/******************************************************************************/
56
/* LOCAL VARIABLES                                                            */
57
/******************************************************************************/
58
59
/******************************************************************************/
60
/* LOCAL FUNCTIONS                                                            */
61
/******************************************************************************/
62
63
/******************************************************************************/
64
/* EXPORTED FUNCTIONS                                                         */
65
/******************************************************************************/
66 7d9678db skenneweg
67
/**
68
 * @brief   Initialize the Core.
69
 */
70 1f7ffcff skenneweg
void urtCoreInit(void)
71
{
72 64fde4ba skenneweg
  core._nodes = NULL;
73
  core._status = URT_STATUS_OK;
74 792f6c74 skenneweg
  urtEventSourceInit(&core._evtSource);
75 64fde4ba skenneweg
  urtMutexInit(&core._lock);
76 37cd5dc2 Svenja
# if (URT_CFG_PUBSUB_ENABLED)
77 64fde4ba skenneweg
    core._topics = NULL;
78 37cd5dc2 Svenja
# endif /* URT_CFG_PUBSUB_ENABLED */
79
# if (URT_CFG_RPC_ENABLED)
80 64fde4ba skenneweg
    core.urt_service_t = NULL;
81 37cd5dc2 Svenja
# endif /* URT_CFG_RPC_ENABLED */
82 1f7ffcff skenneweg
  return;
83
}
84 7d9678db skenneweg
85
/**
86
 * @brief   Get Core status.
87
 *
88 5198dfae skenneweg
 * @return  Current system status.
89 7d9678db skenneweg
 */
90 64fde4ba skenneweg
urt_status_t urtCoreGetStatus(void)
91
{
92
  return core._status;
93
}
94 7d9678db skenneweg
95 cd0cba58 skenneweg
urt_osEventMask_t urtCoreGetEventMask(void)
96
{
97 792f6c74 skenneweg
    return URT_EVENTMASK_MAXPRIO;
98 cd0cba58 skenneweg
}
99
100 7d9678db skenneweg
/**
101 408a606c skenneweg
 * @brief   Get Core mutex.
102
 *
103
 * @return  Current system mutex.
104
 */
105 792f6c74 skenneweg
urt_osMutex_t* urtCoreGetMutex(void)
106 408a606c skenneweg
{
107 792f6c74 skenneweg
    return &core._lock;
108 408a606c skenneweg
}
109
110
/**
111
 * @brief   Get Core event source.
112
 *
113
 * @return  Current system event source.
114
 */
115
urt_osEventSource_t* urtCoreGetEvtSource(void)
116
{
117 792f6c74 skenneweg
    return &core._evtSource;
118 408a606c skenneweg
}
119
120
/**
121 5198dfae skenneweg
 * @brief   Start threads of all nodes of the Core.
122 7d9678db skenneweg
 */
123 64fde4ba skenneweg
void urtCoreStartNodes(void)
124
{
125 e566c39e skenneweg
  urtMutexLock(&core._lock);
126 64fde4ba skenneweg
  urt_node_t* node = core._nodes;
127
  while (node)
128
  {
129
    urtThreadStart(node->thread);
130
    node = node->next;
131
  }
132 e566c39e skenneweg
  urtMutexUnlock(&core._lock);
133 64fde4ba skenneweg
  return;
134
}
135 7d9678db skenneweg
136
/**
137 5198dfae skenneweg
 * @brief   Synchronize all nodes of the core.
138 7d9678db skenneweg
 *
139 5198dfae skenneweg
 * @param[in] node  Pointer to a node to synchronize. Must not be NULL.
140 7d9678db skenneweg
 *
141 5198dfae skenneweg
 * @return  Returns URT_STATUS_OK if all nodes are synchronized and proceed.
142
 *          Returns URT_STATUS_SYNC_ERROR if an exception occurred (faulty stage value detected).
143
 *          Returns URT_STATUS_SYNC_PENDING if there are nodes left to synchronize.
144
 *          In the latter case, the node thread must still wait for the control event (proceed) to synchronize.
145 7d9678db skenneweg
 */
146 e566c39e skenneweg
urt_status_t urtCoreSynchronizeNodes(urt_node_t* node)
147 64fde4ba skenneweg
{
148 17d978fe skenneweg
  urtDebugAssert(node != NULL);
149
150 e566c39e skenneweg
  urtMutexLock(&core._lock);
151 e360ce71 skenneweg
  node->stage++;
152 64fde4ba skenneweg
  urt_node_t* nodeFromCore = core._nodes;
153 e566c39e skenneweg
  while (nodeFromCore && nodeFromCore->stage == node->stage)
154 64fde4ba skenneweg
  {
155
    nodeFromCore = nodeFromCore->next;
156
  }
157 e360ce71 skenneweg
158
  if (!nodeFromCore)
159 64fde4ba skenneweg
  {
160 03ed5026 skenneweg
    urt_osEventFlags_t flag = URT_EVENTFLAG_PROCEED;
161 792f6c74 skenneweg
    urtEventSourceBroadcast(&core._evtSource, flag);
162 e566c39e skenneweg
    urtMutexUnlock(&core._lock);
163 64fde4ba skenneweg
    return URT_STATUS_OK;
164
  }
165 e566c39e skenneweg
  else if (nodeFromCore->stage == (node->stage - 1))
166 64fde4ba skenneweg
  {
167 e566c39e skenneweg
    urtMutexUnlock(&core._lock);
168 64fde4ba skenneweg
    return URT_STATUS_SYNC_PENDING;
169
  }
170
  else
171
  {
172
      urtCoreStopNodes(URT_STATUS_SYNC_ERROR);
173 e566c39e skenneweg
      urtMutexUnlock(&core._lock);
174 64fde4ba skenneweg
      return URT_STATUS_SYNC_ERROR;
175
  }
176
}
177 7d9678db skenneweg
178
/**
179 5198dfae skenneweg
 * @brief   Stop threads of all nodes of the Core.
180 7d9678db skenneweg
 *
181 5198dfae skenneweg
 * @param[in] reason  The reason why the function was called. For normal shutdown URT_STATUS_OK should be used.
182 7d9678db skenneweg
 *
183 5198dfae skenneweg
 * @return  Returns URT_STATUS_OK if there was no call with another reason than URT_STATUS_OK before.
184
 *          If the function has been called before with a different reason, that reason is returned.
185 7d9678db skenneweg
 */
186 64fde4ba skenneweg
urt_status_t urtCoreStopNodes(urt_status_t reason)
187
{
188 e566c39e skenneweg
  urtMutexLock(&core._lock);
189
  bool priorityBoosted = false;
190
  urt_osThreadPrio_t oldPrio;
191
192 64fde4ba skenneweg
  if (core._status == URT_STATUS_OK)
193
  {
194
    if (core._nodes->thread->prio < URT_THREAD_PRIO_HIGH_MAX)
195
    {
196 e566c39e skenneweg
      oldPrio = core._nodes->thread->prio;
197
      priorityBoosted = true;
198 64fde4ba skenneweg
      core._nodes->thread->prio = URT_THREAD_PRIO_HIGH_MAX;
199
    }
200 e566c39e skenneweg
    core._status = reason;
201
    urt_node_t* node = core._nodes;
202
    while (node)
203 64fde4ba skenneweg
    {
204 e566c39e skenneweg
      urtThreadTerminate(node->thread, URT_THREAD_TERMINATE_REQUEST);
205
      node = node->next;
206 64fde4ba skenneweg
    }
207 03ed5026 skenneweg
    urt_osEventFlags_t flag = URT_EVENTFLAG_TERMINATE;
208 792f6c74 skenneweg
    urtEventSourceBroadcast(&core._evtSource, flag);
209 e566c39e skenneweg
    urtMutexUnlock(&core._lock);
210 33aa05c5 Svenja
    if (priorityBoosted) {
211 e566c39e skenneweg
      core._nodes->thread->prio = oldPrio;
212 33aa05c5 Svenja
    }
213 e566c39e skenneweg
    return URT_STATUS_OK;
214 64fde4ba skenneweg
  }
215
  else
216
  {
217 e566c39e skenneweg
    urtMutexUnlock(&core._lock);
218
    return core._status;
219 64fde4ba skenneweg
  }
220
}
221 7d9678db skenneweg
222
/**
223 37cd5dc2 Svenja
 * @brief   Get Core nodes.
224
 *
225
 * @return  Nodes registered to the core.
226
 */
227
urt_node_t* urtCoreGetNodes(void)
228
{
229
  return core._nodes;
230
}
231
232
233
/**
234
 * @brief   Prepend node to core's list of nodes.
235
 *
236
 * @param[in] node The node to prepend. Must not be NULL.
237 e7056e1b skenneweg
 *
238
 * @return URT_STATUS_OK on success.
239 37cd5dc2 Svenja
 */
240 e7056e1b skenneweg
urt_status_t urtCoreAddNode(urt_node_t* node)
241 37cd5dc2 Svenja
{
242
  urtDebugAssert(node);
243
244 e7056e1b skenneweg
  urtMutexLock(&core._lock);
245 37cd5dc2 Svenja
  node->next = core._nodes;
246
  core._nodes = node;
247 e7056e1b skenneweg
  urtMutexUnlock(&core._lock);
248
  return URT_STATUS_OK;
249 37cd5dc2 Svenja
}
250
251
252
/**
253 7d9678db skenneweg
 * @brief   Get the topic of the Core.
254
 *
255 5198dfae skenneweg
 * @param[in] id  Identifier of the topic to retrieve.
256 7d9678db skenneweg
 *
257 5198dfae skenneweg
 * @return  Returns a pointer to the requested service. Returns NULL if no service matches the given ID.
258 7d9678db skenneweg
 */
259 33aa05c5 Svenja
#if (URT_CFG_PUBSUB_ENABLED == true)
260 37cd5dc2 Svenja
261
/**
262
 * @brief   Append topic to core's list of topics.
263
 *
264 e7056e1b skenneweg
 * @param[in] node The topic to append. Must not be NULL.
265 37cd5dc2 Svenja
 */
266 e7056e1b skenneweg
urt_status_t urtCoreAddTopic(urt_topic_t* topic)
267 37cd5dc2 Svenja
{
268 e7056e1b skenneweg
  urtDebugAssert(topic);
269
270
  urtMutexLock(&core._lock);
271 37cd5dc2 Svenja
  urt_topic_t* lastTopic = core._topics;
272
  while (lastTopic->next != NULL)
273 5c6cb22f skenneweg
  {
274 37cd5dc2 Svenja
    lastTopic = lastTopic->next;
275 5c6cb22f skenneweg
  }
276 37cd5dc2 Svenja
  lastTopic->next = topic;
277 e7056e1b skenneweg
  urtMutexUnlock(&core._lock);
278
  return URT_STATUS_OK;
279 37cd5dc2 Svenja
}
280
281
/**
282
 * @brief   Get core's list of topics.
283
 *
284
 * @return  The first topic of the core.
285
 */
286
urt_topic_t* urtCoreGetTopic(urt_topicid_t id)
287
{
288
  urtMutexLock(&core._lock);
289
  urt_topic_t* topic = core._topics;
290
  while (topic != NULL && topic->id < id)
291
      topic = topic->next;
292
  urtMutexUnlock(&core._lock);
293
  if (topic != NULL && topic->id == id)
294
      return topic;
295
  else
296
    return NULL;
297
}
298 33aa05c5 Svenja
#endif /* URT_CFG_PUBSUB_ENABLED */
299 64fde4ba skenneweg
300 7d9678db skenneweg
301 37cd5dc2 Svenja
# if (URT_CFG_RPC_ENABLED)
302 7d9678db skenneweg
/**
303 e7056e1b skenneweg
 * @brief   Prepend service to core's list of services.
304
 *
305
 * @param[in] service The service to prepend. Must not be NULL.
306
 *
307
 * @return URT_STATUS_OK on success.
308
 */
309
urt_status_t urtCoreAddService(urt_service_t* service)
310
{
311
  urtDebugAssert(service);
312
313
  urtMutexLock(&core._lock);
314
  service->next = core._services;
315
  core._services = service;
316
  urtMutexUnlock(&core._lock);
317
  return URT_STATUS_OK;
318
}
319
320
/**
321 7d9678db skenneweg
 * @brief   Get the service of the Core.
322
 *
323 5198dfae skenneweg
 * @param[in] id  Identifier of the service to retrieve.
324 7d9678db skenneweg
 *
325 5198dfae skenneweg
 * @return Returns a pointer to the requested service. Returns NULL if no service matches the given ID.
326 37cd5dc2 Svenja
 */
327 e7056e1b skenneweg
urt_service_t* urtCoreGetService(urt_serviceid_t id) {return urt_service_t;}
328 37cd5dc2 Svenja
# endif /* URT_CFG_RPC_ENABLED */
329 64fde4ba skenneweg
330 33aa05c5 Svenja
#if (URT_CFG_PUBSUB_QOS_DEADLINECHECKS == true)
331 e7056e1b skenneweg
urt_osTimerCallback_t urtCoreCallbackDefault(void* params)
332
{
333
  urtMutexLock(&core._lock);
334
  while (params) {
335
    urtPrintf("Danger");
336
    urtThreadSleep(1);
337
  }
338
  urtMutexUnlock(&core._lock);
339
  return
340
}
341
#endif /* URT_CFG_PUBSUB_QOS_DEADLINECHECKS */
342