Skip to content

Commit ac8cf72

Browse files
nattgrishefloryd
authored andcommitted
Allow EMCY callback to enable the error behavior
Change-Id: I4a78ba7b4a521f64fb271d528df6c56953b04bad
1 parent f07091e commit ac8cf72

File tree

6 files changed

+42
-24
lines changed

6 files changed

+42
-24
lines changed

include/co_api.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ extern "C" {
2626
#endif
2727

2828
#include <stdint.h>
29+
#include <stdbool.h>
2930
#include <stddef.h>
3031

3132
#include "co_export.h"
@@ -303,8 +304,8 @@ typedef struct co_cfg
303304
/** SYNC callback */
304305
void (*cb_sync) (void * arg);
305306

306-
/** EMCY callback */
307-
void (*cb_emcy) (
307+
/** EMCY callback, return true to enable error behavior */
308+
bool (*cb_emcy) (
308309
void * arg,
309310
uint8_t node,
310311
uint16_t code,
@@ -480,7 +481,7 @@ CO_EXPORT int co_sdo_write (
480481
* Calling this function adds an error to the error history object
481482
* (1003h). It also signals an error to the NMT state-machine which
482483
* may change state according to the setting of the error behavior
483-
* object (1029h).
484+
* object (1029h) and the return value of the EMCY callback.
484485
*
485486
* The application will be notified via the EMCY callback. The node id
486487
* will be the active node id for this node.

src/co_emcy.c

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,24 @@ static uint32_t co_emcy_error_set (co_net_t * net, uint8_t subindex, uint32_t *
6060
return 0;
6161
}
6262

63+
static void co_trigger_error_behavior (co_net_t * net)
64+
{
65+
/* Transition state according to error behavior setting */
66+
switch (net->error_behavior)
67+
{
68+
case 0:
69+
if (net->state == STATE_OP)
70+
co_nmt_event (net, EVENT_PREOP);
71+
break;
72+
case 2:
73+
co_nmt_event (net, EVENT_STOP);
74+
break;
75+
default:
76+
/* Do nothing */
77+
break;
78+
}
79+
}
80+
6381
uint32_t co_od1001_fn (
6482
co_net_t * net,
6583
od_event_t event,
@@ -214,6 +232,7 @@ int co_emcy_tx (co_net_t * net, uint16_t code, uint16_t info, uint8_t msef[5])
214232
uint8_t * p = msg;
215233
uint8_t reg;
216234
uint32_t now;
235+
bool error_behavior = false;
217236

218237
if (net->number_of_errors < MAX_ERRORS)
219238
net->number_of_errors++;
@@ -254,26 +273,13 @@ int co_emcy_tx (co_net_t * net, uint16_t code, uint16_t info, uint8_t msef[5])
254273
/* Call user callback */
255274
if (net->cb_emcy)
256275
{
257-
net->cb_emcy (net->cb_arg, net->node, code, reg, msef);
276+
error_behavior = net->cb_emcy (net->cb_arg, net->node, code, reg, msef);
258277
}
259278

260-
if (code != 0x8140 && code != 0x8130) {
261-
return 0;
262-
}
263-
264-
/* Transition state according to error behavior setting */
265-
switch (net->error_behavior)
266-
{
267-
case 0:
268-
if (net->state == STATE_OP)
269-
co_nmt_event (net, EVENT_PREOP);
270-
break;
271-
case 2:
272-
co_nmt_event (net, EVENT_STOP);
273-
break;
274-
default:
275-
/* Do nothing */
276-
break;
279+
/* Always trigger error behavior on the mandatory events,
280+
* otherwise, follow the callback return value. */
281+
if (code == 0x8130 || code == 0x8140 || error_behavior) {
282+
co_trigger_error_behavior (net);
277283
}
278284

279285
return 0;

src/co_main.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ struct co_net
267267
void (*cb_sync) (void * arg);
268268

269269
/** EMCY callback */
270-
void (*cb_emcy) (
270+
bool (*cb_emcy) (
271271
void * arg,
272272
uint8_t node,
273273
uint16_t code,

test/mocks.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,14 +149,16 @@ uint8_t cb_emcy_node;
149149
uint16_t cb_emcy_code;
150150
uint8_t cb_emcy_reg;
151151
uint8_t cb_emcy_msef[5];
152-
void cb_emcy (void * arg, uint8_t node, uint16_t code, uint8_t reg, uint8_t msef[5])
152+
bool cb_emcy_result;
153+
bool cb_emcy (void * arg, uint8_t node, uint16_t code, uint8_t reg, uint8_t msef[5])
153154
{
154155
cb_emcy_calls++;
155156
cb_emcy_node = node;
156157
cb_emcy_code = code;
157158
cb_emcy_reg = reg;
158159
if (msef != NULL)
159160
memcpy (cb_emcy_msef, msef, sizeof (cb_emcy_msef));
161+
return cb_emcy_result;
160162
}
161163

162164
unsigned int cb_sync_calls;

test/mocks.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,8 @@ extern uint8_t cb_emcy_node;
9696
extern uint16_t cb_emcy_code;
9797
extern uint8_t cb_emcy_reg;
9898
extern uint8_t cb_emcy_msef[5];
99-
void cb_emcy (void * arg, uint8_t node, uint16_t code, uint8_t reg, uint8_t msef[5]);
99+
extern bool cb_emcy_result;
100+
bool cb_emcy (void * arg, uint8_t node, uint16_t code, uint8_t reg, uint8_t msef[5]);
100101

101102
extern unsigned int cb_sync_calls;
102103
void cb_sync (void * arg);

test/test_emcy.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ class EmcyTest : public TestBase
2626
{
2727
TestBase::SetUp();
2828
net.emcy.cobid = 0x81;
29+
cb_emcy_result = false;
2930
}
3031

3132
uint8_t msef[5] = {5, 4, 3, 2, 1};
@@ -283,8 +284,15 @@ TEST_F (EmcyTest, NMTErrorBehavior)
283284
EXPECT_EQ (STATE_STOP, net.state);
284285

285286
net.state = STATE_OP;
287+
cb_emcy_result = false;
286288
co_emcy_tx (&net, 1, 0x1234, msef);
287289
EXPECT_EQ (STATE_OP, net.state);
290+
291+
net.state = STATE_OP;
292+
cb_emcy_result = true;
293+
co_emcy_tx (&net, 1, 0x1234, msef);
294+
EXPECT_EQ (STATE_STOP, net.state);
295+
288296
}
289297

290298
TEST_F (EmcyTest, EmcyOverrun)

0 commit comments

Comments
 (0)