Statistics
| Branch: | Revision:

urtware / src / urt_core.c @ 408a606c

History | View | Annotate | Download (6.995 KB)

1
/*
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
#include <urtware.h>
23

    
24
/******************************************************************************/
25
/* LOCAL DEFINITIONS                                                          */
26
/******************************************************************************/
27

    
28
/******************************************************************************/
29
/* EXPORTED VARIABLES                                                         */
30
/******************************************************************************/
31

    
32
/******************************************************************************/
33
/* LOCAL TYPES                                                                */
34
/******************************************************************************/
35

    
36
/**
37
 * @brief  core
38
 */
39
typedef struct urt_core
40
{
41
  urt_node_t* _nodes;
42
  urt_osEventSource_t* _evtSource;
43
  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
/******************************************************************************/
56
/* LOCAL VARIABLES                                                            */
57
/******************************************************************************/
58

    
59
/******************************************************************************/
60
/* LOCAL FUNCTIONS                                                            */
61
/******************************************************************************/
62

    
63
/******************************************************************************/
64
/* EXPORTED FUNCTIONS                                                         */
65
/******************************************************************************/
66

    
67
/**
68
 * @brief   Initialize the Core.
69
 */
70
void urtCoreInit(void)
71
{
72
  core._nodes = NULL;
73
  core._status = URT_STATUS_OK;
74
  urtEventSourceInit(core._evtSource);
75
  urtMutexInit(&core._lock);
76
  #if (URT_CFG_PUBSUB_ENABLED)
77
    core._topics = NULL;
78
  #endif /* URT_CFG_PUBSUB_ENABLED */
79
  #if (URT_CFG_RPC_ENABLED)
80
    core.urt_service_t = NULL;
81
  #endif /* URT_CFG_RPC_ENABLED */
82
  return;
83
}
84

    
85
/**
86
 * @brief   Get Core status.
87
 *
88
 * @return  Current system status.
89
 */
90
urt_status_t urtCoreGetStatus(void)
91
{
92
  return core._status;
93
}
94

    
95
/**
96
 * @brief   Get Core mutex.
97
 *
98
 * @return  Current system mutex.
99
 */
100
urt_osMutex_t urtCoreGetMutex(void)
101
{
102
    return core._lock;
103
}
104

    
105
/**
106
 * @brief   Get Core event source.
107
 *
108
 * @return  Current system event source.
109
 */
110
urt_osEventSource_t* urtCoreGetEvtSource(void)
111
{
112
    return core._evtSource;
113
}
114

    
115
urt_node_t* urtCoreGetNodes(void)
116
{
117
    return core._nodes;
118
}
119

    
120
/**
121
 * @brief   Start threads of all nodes of the Core.
122
 */
123
void urtCoreStartNodes(void)
124
{
125
  urtMutexLock(&core._lock);
126
  urt_node_t* node = core._nodes;
127
  while (node)
128
  {
129
    urtThreadStart(node->thread);
130
    node = node->next;
131
  }
132
  urtMutexUnlock(&core._lock);
133
  return;
134
}
135

    
136
/**
137
 * @brief   Synchronize all nodes of the core.
138
 *
139
 * @param[in] node  Pointer to a node to synchronize. Must not be NULL.
140
 *
141
 * @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
 */
146
urt_status_t urtCoreSynchronizeNodes(urt_node_t* node)
147
{
148
  urtDebugAssert(node != NULL);
149

    
150
  urtMutexLock(&core._lock);
151
  node->stage -= 1;
152
  urt_node_t* nodeFromCore = core._nodes;
153
  while (nodeFromCore && nodeFromCore->stage == node->stage)
154
  {
155
    nodeFromCore = nodeFromCore->next;
156
  }
157
  if (nodeFromCore)
158
  {
159
    urt_osEventFlags_t flag = URT_EVENTFLAG_PROCEED;
160
    urtEventSourceBroadcast(core._evtSource, flag);
161
    urtMutexUnlock(&core._lock);
162
    return URT_STATUS_OK;
163
  }
164
  else if (nodeFromCore->stage == (node->stage - 1))
165
  {
166
    urtMutexUnlock(&core._lock);
167
    return URT_STATUS_SYNC_PENDING;
168
  }
169
  else
170
  {
171
      urtCoreStopNodes(URT_STATUS_SYNC_ERROR);
172
      urtMutexUnlock(&core._lock);
173
      return URT_STATUS_SYNC_ERROR;
174
  }
175
}
176

    
177
/**
178
 * @brief   Stop threads of all nodes of the Core.
179
 *
180
 * @param[in] reason  The reason why the function was called. For normal shutdown URT_STATUS_OK should be used.
181
 *
182
 * @return  Returns URT_STATUS_OK if there was no call with another reason than URT_STATUS_OK before.
183
 *          If the function has been called before with a different reason, that reason is returned.
184
 */
185
urt_status_t urtCoreStopNodes(urt_status_t reason)
186
{
187
  urtMutexLock(&core._lock);
188
  bool priorityBoosted = false;
189
  urt_osThreadPrio_t oldPrio;
190

    
191
  if (core._status == URT_STATUS_OK)
192
  {
193
    if (core._nodes->thread->prio < URT_THREAD_PRIO_HIGH_MAX)
194
    {
195
      oldPrio = core._nodes->thread->prio;
196
      priorityBoosted = true;
197
      core._nodes->thread->prio = URT_THREAD_PRIO_HIGH_MAX;
198
    }
199
    core._status = reason;
200
    urt_node_t* node = core._nodes;
201
    while (node)
202
    {
203
      urtThreadTerminate(node->thread, URT_THREAD_TERMINATE_REQUEST);
204
      node = node->next;
205
    }
206
    urt_osEventFlags_t flag = URT_EVENTFLAG_TERMINATE;
207
    urtEventSourceBroadcast(core._evtSource, flag);
208
    urtMutexUnlock(&core._lock);
209
    if (priorityBoosted)
210
      core._nodes->thread->prio = oldPrio;
211
    return URT_STATUS_OK;
212
  }
213
  else
214
  {
215
    urtMutexUnlock(&core._lock);
216
    return core._status;
217
  }
218
}
219

    
220
/**
221
 * @brief   Get the topic of the Core.
222
 *
223
 * @param[in] id  Identifier of the topic to retrieve.
224
 *
225
 * @return  Returns a pointer to the requested service. Returns NULL if no service matches the given ID.
226
 */
227
#if (URT_CFG_PUBSUB_ENABLED)
228
  urt_topic_t* urtCoreGetTopic(urt_topicid_t id) {return urt_topic_t;}
229
#endif /* URT_CFG_PUBSUB_ENABLED */
230

    
231

    
232
/**
233
 * @brief   Get the service of the Core.
234
 *
235
 * @param[in] id  Identifier of the service to retrieve.
236
 *
237
 * @return Returns a pointer to the requested service. Returns NULL if no service matches the given ID.
238
 */  
239
#if (URT_CFG_RPC_ENABLED)
240
  urt_service_t urtCoreGetService(urt_serviceid_t id) {return urt_service_t;}
241
#endif /* URT_CFG_RPC_ENABLED */
242

    
243