ErrorLib 1.0.19-master SHA: 1ee11e80f5
Error.h
Go to the documentation of this file.
1
14#ifndef ERROR_h
15#define ERROR_h
16
17//-----------------------------------------------------------------------------
18// Includes
19//-----------------------------------------------------------------------------
20#include <stdint.h>
21#include "timestamp.h"
22
23#ifdef __cplusplus
24extern "C" {
25#endif
26//-----------------------------------------------------------------------------
27// Defines
28//-----------------------------------------------------------------------------
29#if __STDC_VERSION__ >= 201112L && ! defined __cplusplus
30 #include <assert.h>
31#else
32 #define static_assert _Static_assert
33#endif
34
36#define MAX_NUMBER_OF_ERRORS 30
37
38
40#define ERROR_STACK_OVERFLOW 0x80000000
41
43#define ERROR_SYSTEM_VERSION 2
44
45extern uint32_t g_u32ErrorPending;
46
50{
55 PLC_RESET = 16,
57 NV_STORED = 64
58};
59
61typedef void (*fpOnErrorX)(void);
62
66typedef struct
67{
69 const char* cName;
70 const uint32_t ui32NameSize;
71 const char* cHelp;
72 const uint32_t ui32HelpSize;
74
77typedef bool (*fpOnErrorResetX)(void);
78
82typedef struct
83{
85 const char* cName;
86 const uint32_t ui32NameSize;
87 const char* cHelp;
88 const uint32_t ui32HelpSize;
90
92typedef struct
93{
94 const uint16_t ui16Id;
95 const uint16_t ui16DataCount;
96 const uint32_t ui32Flags;
97 const char* Description;
98 const uint32_t ui32DescriptionLength;
99 const char* Help;
100 const uint32_t ui32HelpLength;
103}tError;
104
106typedef struct
107{
108 const uint32_t ui32Line;
109 const char* File;
110 const uint32_t ui32FileLength;
112
113
115typedef struct
116{
121 uint32_t ui32ErrorCount;
122 void* Data;
124
126#define ERR_VAR_NAME_SRT(x, y) x ## y
128#define ERR_VAR_NAME(x, y) ERR_VAR_NAME_SRT(x, y)
129
131#define xstr(s) str(s)
133#define str(s) #s
134
136#define ASSERT_REACTION_NAME(NAME) static_assert(sizeof(NAME) > MIN_ERR_REACTION_NAME_LENTH, \
137"Error reaction name to short must be at least "xstr(MIN_ERR_REACTION_NAME_LENTH)" characters long!") \
138
140#define ASSERT_DESCRIPTION(DESCRIPTION) static_assert(sizeof(DESCRIPTION) > MIN_ERR_DESCRIPTION_LENTH, \
141"Error description text to short must be at least "xstr(MIN_ERR_DESCRIPTION_LENTH)" characters long!") \
142
144#define ASSERT_HELP(HELP) static_assert(sizeof(HELP) > MIN_ERR_HELP_LENTH, \
145"Error help text to short must be at least "xstr(MIN_ERR_HELP_LENTH)" characters long!") \
146
148#ifdef ERROR_TEXTS_IN_FILE
150typedef struct
151{
152 const uint16_t ui16ErrorID;
153 const uint32_t ui32Length;
154 const char cText[];
155}tErrorHelpText;
156
157#define ERROR_HELP_TEXT_COMBINE(x)
158#define ERROR_HELP_TEXT_SECTION(ERROR_ID, HELP) static const tErrorHelpText g_tErrorHelpText##PARA_ID __attribute__((section("para_help_strings"), used)) = {ERROR_ID, sizeof(HELP) - 1, HELP};
159#else
160#define ERROR_HELP_TEXT_COMBINE(x) x
161#define ERROR_HELP_TEXT_SECTION(ERROR_ID, HELP)
162#endif
163
164#ifdef INCLUDE_ENGLISH_HELP
165#define INCLUDE_HELP_EN(HELP) HELP
166#else
167#define INCLUDE_HELP_EN(HELP) ""
168#endif
169
170#ifdef INCLUDE_GERMAN_HELP
171#define INCLUDE_HELP_DE(HELP) HELP
172#else
173#define INCLUDE_HELP_DE(HELP) ""
174#endif
175
176
187#define DefineError(ID, PERMISSION, ON_ERROR, ON_ERROR_RESET, DESCRIPTION, HELP_EN, HELP_DE) \
188 ASSERT_DESCRIPTION(DESCRIPTION); \
189 ASSERT_HELP(INCLUDE_HELP_EN(HELP_EN) INCLUDE_HELP_DE(HELP_DE)); \
190 static const char g_s##ID##Description[] __attribute__((section("error_strings"), used)) = DESCRIPTION; \
191 static const char g_s##ID##Help[] __attribute__((section("error_strings"), used)) = \
192 ERROR_HELP_TEXT_COMBINE(INCLUDE_HELP_EN("DOC_E " HELP_EN) INCLUDE_HELP_DE("DOC_D " HELP_DE)); \
193 \
194 const tError g_t##ID __attribute__((section("error_descriptor"), used)) = { \
195 ID, \
196 0, \
197 PERMISSION, \
198 g_s##ID##Description, \
199 sizeof(DESCRIPTION) - 1, \
200 g_s##ID##Help, \
201 sizeof(g_s##ID##Help) - 1, \
202 &g_t##ON_ERROR, \
203 &g_t##ON_ERROR_RESET, \
204 }
205
206
218#define DefineErrorData(ID, PERMISSION, ON_ERROR, ON_ERROR_RESET, DESCRIPTION, HELP_EN, HELP_DE, DATA_COUNT) \
219 ASSERT_DESCRIPTION(DESCRIPTION); \
220 ASSERT_HELP(INCLUDE_HELP_EN(HELP_EN) INCLUDE_HELP_DE(HELP_DE)); \
221 static const char g_s##ID##Description[] __attribute__((section("error_strings"), used)) = DESCRIPTION; \
222 static const char g_s##ID##Help[] __attribute__((section("error_strings"), used)) = \
223 ERROR_HELP_TEXT_COMBINE(INCLUDE_HELP_EN("DOC_E " HELP_EN) INCLUDE_HELP_DE("DOC_D " HELP_DE)); \
224 \
225 const tError g_t##ID __attribute__((section("error_descriptor"), used)) = { \
226 ID, \
227 DATA_COUNT, \
228 PERMISSION, \
229 g_s##ID##Description, \
230 sizeof(g_s##ID##Description) - 1, \
231 g_s##ID##Help, \
232 sizeof(g_s##ID##Help) - 1, \
233 &g_t##ON_ERROR, \
234 &g_t##ON_ERROR_RESET, \
235 }
236
237
242#define DeclareError(ID) const tError g_t##ID
243
244
255#define SetError(ID, PERMISSION, ON_ERROR, ON_ERROR_RESET, DESCRIPTION, HELP_EN, HELP_DE) \
256do \
257{ \
258 ASSERT_DESCRIPTION(DESCRIPTION); \
259 ASSERT_HELP(INCLUDE_HELP_EN(HELP_EN) INCLUDE_HELP_DE(HELP_DE)); \
260 static const char g_s##ID##Description[] __attribute__((section("error_strings"), used)) = DESCRIPTION; \
261 static const char g_s##ID##Help[] __attribute__((section("error_strings"), used)) = \
262 ERROR_HELP_TEXT_COMBINE(INCLUDE_HELP_EN("DOC_E " HELP_EN) INCLUDE_HELP_DE("DOC_D " HELP_DE)); \
263 static const tErrorSource g_t##ID##Source __attribute__((section("error_sources"), used)) = { \
264 __LINE__, \
265 g_sFileName, \
266 sizeof(g_sFileName) - 1 \
267 }; \
268 \
269 static const tError g_t##ID __attribute__((section("error_descriptor"), used)) = { \
270 ID, \
271 0, \
272 PERMISSION, \
273 g_s##ID##Description, \
274 sizeof(DESCRIPTION) - 1, \
275 g_s##ID##Help, \
276 sizeof(g_s##ID##Help) - 1, \
277 &g_t##ON_ERROR, \
278 &g_t##ON_ERROR_RESET, \
279 }; \
280 _SetErrorX(&g_t##ID, &g_t##ID##Source); \
281}while(0)
282
283
295#define SetErrorSource(ID, PERMISSION, ON_ERROR, ON_ERROR_RESET, DESCRIPTION, HELP_EN, HELP_DE, SOURCE) \
296do \
297{ \
298 ASSERT_DESCRIPTION(DESCRIPTION); \
299 ASSERT_HELP(INCLUDE_HELP_EN(HELP_EN) INCLUDE_HELP_DE(HELP_DE)); \
300 static const char g_s##ID##Description[] __attribute__((section("error_strings"), used)) = DESCRIPTION; \
301 static const char g_s##ID##Help[] __attribute__((section("error_strings"), used)) = \
302 ERROR_HELP_TEXT_COMBINE(INCLUDE_HELP_EN("DOC_E " HELP_EN) INCLUDE_HELP_DE("DOC_D " HELP_DE)); \
303 \
304 static const tError g_t##ID __attribute__((section("error_descriptor"), used)) = { \
305 ID, \
306 0, \
307 PERMISSION, \
308 g_s##ID##Description, \
309 sizeof(DESCRIPTION) - 1, \
310 g_s##ID##Help, \
311 sizeof(g_s##ID##Help) - 1, \
312 &g_t##ON_ERROR, \
313 &g_t##ON_ERROR_RESET, \
314 }; \
315 _SetErrorX(&g_t##ID, SOURCE); \
316}while(0)
317
318
330#define SetErrorData1(ID, PERMISSION, ON_ERROR, ON_ERROR_RESET, DESCRIPTION, HELP_EN, HELP_DE, DATA1) \
331do \
332{ \
333 ASSERT_DESCRIPTION(DESCRIPTION); \
334 ASSERT_HELP(INCLUDE_HELP_EN(HELP_EN) INCLUDE_HELP_DE(HELP_DE)); \
335 static const char g_s##ID##Description[] __attribute__((section("error_strings"), used)) = DESCRIPTION; \
336 static const char g_s##ID##Help[] __attribute__((section("error_strings"), used)) = \
337 ERROR_HELP_TEXT_COMBINE(INCLUDE_HELP_EN("DOC_E " HELP_EN) INCLUDE_HELP_DE("DOC_D " HELP_DE)); \
338 static const tErrorSource g_t##ID##Source __attribute__((section("error_sources"), used)) = { \
339 __LINE__, \
340 g_sFileName, \
341 sizeof(g_sFileName) - 1 \
342 }; \
343 \
344 static const tError g_t##ID __attribute__((section("error_descriptor"), used)) = { \
345 ID, \
346 1, \
347 PERMISSION, \
348 g_s##ID##Description, \
349 sizeof(DESCRIPTION) - 1, \
350 g_s##ID##Help, \
351 sizeof(g_s##ID##Help) - 1, \
352 &g_t##ON_ERROR, \
353 &g_t##ON_ERROR_RESET, \
354 }; \
355 if(sizeof(DATA1) < 4) \
356 { \
357 int32_t ERR_VAR_NAME(DataTemp, __LINE__) = DATA1; \
358 _SetErrorX(&g_t##ID, &g_t##ID##Source, ERR_VAR_NAME(DataTemp, __LINE__)); \
359 } \
360 else \
361 { \
362 _SetErrorX(&g_t##ID, &g_t##ID##Source, *(uint32_t*)&DATA1); \
363 } \
364}while(0)
365
366
381#define SetErrorData1Compare(ID, PERMISSION, ON_ERROR, ON_ERROR_RESET, DESCRIPTION, HELP_EN, HELP_DE, DATA1, COMPARE1) \
382do \
383{ \
384 ASSERT_DESCRIPTION(DESCRIPTION); \
385 ASSERT_HELP(INCLUDE_HELP_EN(HELP_EN) INCLUDE_HELP_DE(HELP_DE)); \
386 static const char g_s##ID##Description[] __attribute__((section("error_strings"), used)) = DESCRIPTION; \
387 static const char g_s##ID##Help[] __attribute__((section("error_strings"), used)) = \
388 ERROR_HELP_TEXT_COMBINE(INCLUDE_HELP_EN("DOC_E " HELP_EN) INCLUDE_HELP_DE("DOC_D " HELP_DE)); \
389 static const tErrorSource g_t##ID##Source __attribute__((section("error_sources"), used)) = { \
390 __LINE__, \
391 g_sFileName, \
392 sizeof(g_sFileName) - 1 \
393 }; \
394 \
395 static const tError g_t##ID __attribute__((section("error_descriptor"), used)) = { \
396 ID, \
397 1, \
398 PERMISSION, \
399 g_s##ID##Description, \
400 sizeof(DESCRIPTION) - 1, \
401 g_s##ID##Help, \
402 sizeof(g_s##ID##Help) - 1, \
403 &g_t##ON_ERROR, \
404 &g_t##ON_ERROR_RESET, \
405 }; \
406 \
407 tErrorListItem* ERR_VAR_NAME(ptError, __LINE__); \
408 if(sizeof(DATA1) < 4) \
409 { \
410 int32_t ERR_VAR_NAME(DataTemp, __LINE__) = DATA1; \
411 ERR_VAR_NAME(ptError, __LINE__) = _SetErrorX(&g_t##ID, &g_t##ID##Source, ERR_VAR_NAME(DataTemp, __LINE__)); \
412 } \
413 else \
414 { \
415 ERR_VAR_NAME(ptError, __LINE__) = _SetErrorX(&g_t##ID, &g_t##ID##Source, *(uint32_t*)&DATA1); \
416 } \
417 COMPARE1(ERR_VAR_NAME(ptError, __LINE__)->Data, DATA1); \
418}while(0)
419
420
433#define SetErrorData2(ID, PERMISSION, ON_ERROR, ON_ERROR_RESET, DESCRIPTION, HELP_EN, HELP_DE, DATA1, DATA2) \
434do \
435{ \
436 ASSERT_DESCRIPTION(DESCRIPTION); \
437 ASSERT_HELP(INCLUDE_HELP_EN(HELP_EN) INCLUDE_HELP_DE(HELP_DE)); \
438 static const char g_s##ID##Description[] __attribute__((section("error_strings"), used)) = DESCRIPTION; \
439 static const char g_s##ID##Help[] __attribute__((section("error_strings"), used)) = \
440 ERROR_HELP_TEXT_COMBINE(INCLUDE_HELP_EN("DOC_E " HELP_EN) INCLUDE_HELP_DE("DOC_D " HELP_DE)); \
441 static const tErrorSource g_t##ID##Source __attribute__((section("error_sources"), used)) = { \
442 __LINE__, \
443 g_sFileName, \
444 sizeof(g_sFileName) - 1 \
445 }; \
446 \
447 static const tError g_t##ID __attribute__((section("error_descriptor"), used)) = { \
448 ID, \
449 2, \
450 PERMISSION, \
451 g_s##ID##Description, \
452 sizeof(DESCRIPTION) - 1, \
453 g_s##ID##Help, \
454 sizeof(g_s##ID##Help) - 1, \
455 &g_t##ON_ERROR, \
456 &g_t##ON_ERROR_RESET, \
457 }; \
458 \
459 int32_t* ERR_VAR_NAME(pDataTemp1, __LINE__); \
460 if(sizeof(DATA1) < 4) \
461 { \
462 int32_t ERR_VAR_NAME(DataTemp1, __LINE__) = DATA1; \
463 ERR_VAR_NAME(pDataTemp1, __LINE__) = &ERR_VAR_NAME(DataTemp1, __LINE__); \
464 } \
465 else \
466 { \
467 ERR_VAR_NAME(pDataTemp1, __LINE__) = (int32_t*)&(DATA1); \
468 } \
469 int32_t* ERR_VAR_NAME(pDataTemp2, __LINE__); \
470 if(sizeof(DATA2) < 4) \
471 { \
472 int32_t ERR_VAR_NAME(DataTemp2, __LINE__) = DATA2; \
473 ERR_VAR_NAME(pDataTemp2, __LINE__) = &ERR_VAR_NAME(DataTemp2, __LINE__); \
474 } \
475 else \
476 { \
477 ERR_VAR_NAME(pDataTemp2, __LINE__) = (int32_t*)&(DATA2); \
478 } \
479 _SetErrorX(&g_t##ID, &g_t##ID##Source, *ERR_VAR_NAME(pDataTemp1, __LINE__), *ERR_VAR_NAME(pDataTemp2, __LINE__)); \
480}while(0)
481
482
499#define SetErrorData2Compare(ID, PERMISSION, ON_ERROR, ON_ERROR_RESET, DESCRIPTION, HELP_EN, HELP_DE, DATA1, COMPARE1, DATA2, COMPARE2) \
500do \
501{ \
502 ASSERT_DESCRIPTION(DESCRIPTION); \
503 ASSERT_HELP(INCLUDE_HELP_EN(HELP_EN) INCLUDE_HELP_DE(HELP_DE)); \
504 static const char g_s##ID##Description[] __attribute__((section("error_strings"), used)) = DESCRIPTION; \
505 static const char g_s##ID##Help[] __attribute__((section("error_strings"), used)) = \
506 ERROR_HELP_TEXT_COMBINE(INCLUDE_HELP_EN("DOC_E " HELP_EN) INCLUDE_HELP_DE("DOC_D " HELP_DE)); \
507 static const tErrorSource g_t##ID##Source __attribute__((section("error_sources"), used)) = { \
508 __LINE__, \
509 g_sFileName, \
510 sizeof(g_sFileName) - 1 \
511 }; \
512 \
513 static const tError g_t##ID __attribute__((section("error_descriptor"), used)) = { \
514 ID, \
515 2, \
516 PERMISSION, \
517 g_s##ID##Description, \
518 sizeof(DESCRIPTION) - 1, \
519 g_s##ID##Help, \
520 sizeof(g_s##ID##Help) - 1, \
521 &g_t##ON_ERROR, \
522 &g_t##ON_ERROR_RESET, \
523 }; \
524 \
525 int32_t* ERR_VAR_NAME(pDataTemp1, __LINE__); \
526 if(sizeof(DATA1) < 4) \
527 { \
528 int32_t ERR_VAR_NAME(DataTemp1, __LINE__) = DATA1; \
529 ERR_VAR_NAME(pDataTemp1, __LINE__) = &ERR_VAR_NAME(DataTemp1, __LINE__); \
530 } \
531 else \
532 { \
533 ERR_VAR_NAME(pDataTemp1, __LINE__) = (int32_t*)&(DATA1); \
534 } \
535 int32_t* ERR_VAR_NAME(pDataTemp2, __LINE__); \
536 if(sizeof(DATA2) < 4) \
537 { \
538 int32_t ERR_VAR_NAME(DataTemp2, __LINE__) = DATA2; \
539 ERR_VAR_NAME(pDataTemp2, __LINE__) = &ERR_VAR_NAME(DataTemp2, __LINE__); \
540 } \
541 else \
542 { \
543 ERR_VAR_NAME(pDataTemp2, __LINE__) = (int32_t*)&(DATA2); \
544 } \
545 tErrorListItem* ERR_VAR_NAME(ptError, __LINE__) = _SetErrorX(&g_t##ID, &g_t##ID##Source, *ERR_VAR_NAME(pDataTemp1, __LINE__), \
546 *ERR_VAR_NAME(pDataTemp2, __LINE__)); \
547 if((ERR_VAR_NAME(ptError, __LINE__) != 0) && (ERR_VAR_NAME(ptError, __LINE__)->Data != 0)) \
548 { \
549 COMPARE1(ERR_VAR_NAME(ptError, __LINE__)->Data, DATA1); \
550 COMPARE2(ERR_VAR_NAME(ptError, __LINE__)->Data + 4, DATA2); \
551 } \
552}while(0)
553
554
568#define SetErrorData3(ID, PERMISSION, ON_ERROR, ON_ERROR_RESET, DESCRIPTION, HELP_EN, HELP_DE, DATA1, DATA2, DATA3) \
569do \
570{ \
571 ASSERT_DESCRIPTION(DESCRIPTION); \
572 ASSERT_HELP(INCLUDE_HELP_EN(HELP_EN) INCLUDE_HELP_DE(HELP_DE)); \
573 static const char g_s##ID##Description[] __attribute__((section("error_strings"), used)) = DESCRIPTION; \
574 static const char g_s##ID##Help[] __attribute__((section("error_strings"), used)) = \
575 ERROR_HELP_TEXT_COMBINE(INCLUDE_HELP_EN("DOC_E " HELP_EN) INCLUDE_HELP_DE("DOC_D " HELP_DE)); \
576 static const tErrorSource g_t##ID##Source __attribute__((section("error_sources"), used)) = { \
577 __LINE__, \
578 g_sFileName, \
579 sizeof(g_sFileName) - 1 \
580 }; \
581 \
582 static const tError g_t##ID __attribute__((section("error_descriptor"), used)) = { \
583 ID, \
584 3, \
585 PERMISSION, \
586 g_s##ID##Description, \
587 sizeof(DESCRIPTION) - 1, \
588 g_s##ID##Help, \
589 sizeof(g_s##ID##Help) - 1, \
590 &g_t##ON_ERROR, \
591 &g_t##ON_ERROR_RESET, \
592 }; \
593 \
594 int32_t* ERR_VAR_NAME(pDataTemp1, __LINE__); \
595 if(sizeof(DATA1) < 4) \
596 { \
597 int32_t ERR_VAR_NAME(DataTemp1, __LINE__) = DATA1; \
598 ERR_VAR_NAME(pDataTemp1, __LINE__) = &ERR_VAR_NAME(DataTemp1, __LINE__); \
599 } \
600 else \
601 { \
602 ERR_VAR_NAME(pDataTemp1, __LINE__) = (int32_t*)&(DATA1); \
603 } \
604 int32_t* ERR_VAR_NAME(pDataTemp2, __LINE__); \
605 if(sizeof(DATA2) < 4) \
606 { \
607 int32_t ERR_VAR_NAME(DataTemp2, __LINE__) = DATA2; \
608 ERR_VAR_NAME(pDataTemp2, __LINE__) = &ERR_VAR_NAME(DataTemp2, __LINE__); \
609 } \
610 else \
611 { \
612 ERR_VAR_NAME(pDataTemp2, __LINE__) = (int32_t*)&(DATA2); \
613 } \
614 int32_t* ERR_VAR_NAME(pDataTemp3, __LINE__); \
615 if(sizeof(DATA3) < 4) \
616 { \
617 int32_t ERR_VAR_NAME(DataTemp3, __LINE__) = DATA3; \
618 ERR_VAR_NAME(pDataTemp3, __LINE__) = &ERR_VAR_NAME(DataTemp3, __LINE__); \
619 } \
620 else \
621 { \
622 ERR_VAR_NAME(pDataTemp3, __LINE__) = (int32_t*)&(DATA3); \
623 } \
624 _SetErrorX(&g_t##ID, &g_t##ID##Source, *ERR_VAR_NAME(pDataTemp1, __LINE__), *ERR_VAR_NAME(pDataTemp2, __LINE__), \
625 *ERR_VAR_NAME(pDataTemp3, __LINE__)); \
626}while(0)
627
628
643#define SetErrorData4(ID, PERMISSION, ON_ERROR, ON_ERROR_RESET, DESCRIPTION, HELP_EN, HELP_DE, DATA1, DATA2, DATA3, DATA4) \
644do \
645{ \
646 ASSERT_DESCRIPTION(DESCRIPTION); \
647 ASSERT_HELP(INCLUDE_HELP_EN(HELP_EN) INCLUDE_HELP_DE(HELP_DE)); \
648 static const char g_s##ID##Description[] __attribute__((section("error_strings"), used)) = DESCRIPTION; \
649 static const char g_s##ID##Help[] __attribute__((section("error_strings"), used)) = \
650 ERROR_HELP_TEXT_COMBINE(INCLUDE_HELP_EN("DOC_E " HELP_EN) INCLUDE_HELP_DE("DOC_D " HELP_DE)); \
651 static const tErrorSource g_t##ID##Source __attribute__((section("error_sources"), used)) = { \
652 __LINE__, \
653 g_sFileName, \
654 sizeof(g_sFileName) - 1 \
655 }; \
656 \
657 static const tError g_t##ID __attribute__((section("error_descriptor"), used)) = { \
658 ID, \
659 4, \
660 PERMISSION, \
661 g_s##ID##Description, \
662 sizeof(DESCRIPTION) - 1, \
663 g_s##ID##Help, \
664 sizeof(g_s##ID##Help) - 1, \
665 &g_t##ON_ERROR, \
666 &g_t##ON_ERROR_RESET, \
667 }; \
668 \
669 int32_t* ERR_VAR_NAME(pDataTemp1, __LINE__); \
670 if(sizeof(DATA1) < 4) \
671 { \
672 int32_t ERR_VAR_NAME(DataTemp1, __LINE__) = DATA1; \
673 ERR_VAR_NAME(pDataTemp1, __LINE__) = &ERR_VAR_NAME(DataTemp1, __LINE__); \
674 } \
675 else \
676 { \
677 ERR_VAR_NAME(pDataTemp1, __LINE__) = (int32_t*)&(DATA1); \
678 } \
679 int32_t* ERR_VAR_NAME(pDataTemp2, __LINE__); \
680 if(sizeof(DATA2) < 4) \
681 { \
682 int32_t ERR_VAR_NAME(DataTemp2, __LINE__) = DATA2; \
683 ERR_VAR_NAME(pDataTemp2, __LINE__) = &ERR_VAR_NAME(DataTemp2, __LINE__); \
684 } \
685 else \
686 { \
687 ERR_VAR_NAME(pDataTemp2, __LINE__) = (int32_t*)&(DATA2); \
688 } \
689 int32_t* ERR_VAR_NAME(pDataTemp3, __LINE__); \
690 if(sizeof(DATA3) < 4) \
691 { \
692 int32_t ERR_VAR_NAME(DataTemp3, __LINE__) = DATA3; \
693 ERR_VAR_NAME(pDataTemp3, __LINE__) = &ERR_VAR_NAME(DataTemp3, __LINE__); \
694 } \
695 else \
696 { \
697 ERR_VAR_NAME(pDataTemp3, __LINE__) = (int32_t*)&(DATA3); \
698 } \
699 int32_t* ERR_VAR_NAME(pDataTemp4, __LINE__); \
700 if(sizeof(DATA4) < 4) \
701 { \
702 int32_t ERR_VAR_NAME(DataTemp4, __LINE__) = DATA4; \
703 ERR_VAR_NAME(pDataTemp4, __LINE__) = &ERR_VAR_NAME(DataTemp4, __LINE__); \
704 } \
705 else \
706 { \
707 ERR_VAR_NAME(pDataTemp4, __LINE__) = (int32_t*)&(DATA4); \
708 } \
709 _SetErrorX(&g_t##ID, &g_t##ID##Source, *ERR_VAR_NAME(pDataTemp1, __LINE__), *ERR_VAR_NAME(pDataTemp2, __LINE__), \
710 *ERR_VAR_NAME(pDataTemp3, __LINE__), *ERR_VAR_NAME(pDataTemp4, __LINE__)); \
711}while(0)
712
713
717#define SetErrorId(ID) \
718do \
719{ \
720 static const tErrorSource ERR_VAR_NAME(g_t##ID##Source, __LINE__) __attribute__((section("error_sources"), used)) = { \
721 __LINE__, \
722 g_sFileName, \
723 sizeof(g_sFileName) - 1 \
724 }; \
725 \
726 _SetErrorX(&g_t##ID, &ERR_VAR_NAME(g_t##ID##Source, __LINE__)); \
727}while(0)
728
729
734#define SetErrorIdData1(ID, DATA1) \
735do \
736{ \
737 static const tErrorSource ERR_VAR_NAME(g_t##ID##Source, __LINE__) __attribute__((section("error_sources"), used)) = { \
738 __LINE__, \
739 g_sFileName, \
740 sizeof(g_sFileName) - 1 \
741 }; \
742 \
743 if(sizeof(DATA1) < 4) \
744 { \
745 int32_t ERR_VAR_NAME(DataTemp, __LINE__) = DATA1; \
746 _SetErrorX(&g_t##ID, &ERR_VAR_NAME(g_t##ID##Source, __LINE__), ERR_VAR_NAME(DataTemp, __LINE__)); \
747 } \
748 else \
749 { \
750 _SetErrorX(&g_t##ID, &ERR_VAR_NAME(g_t##ID##Source, __LINE__), DATA1); \
751 } \
752}while(0)
753
754
760#define SetErrorIdData2(ID, DATA1, DATA2) \
761do \
762{ \
763 static const tErrorSource ERR_VAR_NAME(g_t##ID##Source, __LINE__) __attribute__((section("error_sources"), used)) = { \
764 __LINE__, \
765 g_sFileName, \
766 sizeof(g_sFileName) - 1 \
767 }; \
768 \
769 int32_t* ERR_VAR_NAME(pDataTemp1, __LINE__); \
770 if(sizeof(DATA1) < 4) \
771 { \
772 int32_t ERR_VAR_NAME(DataTemp1, __LINE__) = DATA1; \
773 ERR_VAR_NAME(pDataTemp1, __LINE__) = &ERR_VAR_NAME(DataTemp1, __LINE__); \
774 } \
775 else \
776 { \
777 ERR_VAR_NAME(pDataTemp1, __LINE__) = (int32_t*)&(DATA1); \
778 } \
779 int32_t* ERR_VAR_NAME(pDataTemp2, __LINE__); \
780 if(sizeof(DATA2) < 4) \
781 { \
782 int32_t ERR_VAR_NAME(DataTemp2, __LINE__) = DATA2; \
783 ERR_VAR_NAME(pDataTemp2, __LINE__) = &ERR_VAR_NAME(DataTemp2, __LINE__); \
784 } \
785 else \
786 { \
787 ERR_VAR_NAME(pDataTemp2, __LINE__) = (int32_t*)&(DATA2); \
788 } \
789 _SetErrorX(&g_t##ID, &ERR_VAR_NAME(g_t##ID##Source, __LINE__), *ERR_VAR_NAME(pDataTemp1, __LINE__), \
790 *ERR_VAR_NAME(pDataTemp2, __LINE__)); \
791}while(0)
792
793
800#define SetErrorIdData3(ID, DATA1, DATA2, DATA3) \
801do \
802{ \
803 static const tErrorSource ERR_VAR_NAME(g_t##ID##Source, __LINE__) __attribute__((section("error_sources"), used)) = { \
804 __LINE__, \
805 g_sFileName, \
806 sizeof(g_sFileName) - 1 \
807 }; \
808 \
809 int32_t* ERR_VAR_NAME(pDataTemp1, __LINE__); \
810 if(sizeof(DATA1) < 4) \
811 { \
812 int32_t ERR_VAR_NAME(DataTemp1, __LINE__) = DATA1; \
813 ERR_VAR_NAME(pDataTemp1, __LINE__) = &ERR_VAR_NAME(DataTemp1, __LINE__); \
814 } \
815 else \
816 { \
817 ERR_VAR_NAME(pDataTemp1, __LINE__) = (int32_t*)&(DATA1); \
818 } \
819 int32_t* ERR_VAR_NAME(pDataTemp2, __LINE__); \
820 if(sizeof(DATA2) < 4) \
821 { \
822 int32_t ERR_VAR_NAME(DataTemp2, __LINE__) = DATA2; \
823 ERR_VAR_NAME(pDataTemp2, __LINE__) = &ERR_VAR_NAME(DataTemp2, __LINE__); \
824 } \
825 else \
826 { \
827 ERR_VAR_NAME(pDataTemp2, __LINE__) = (int32_t*)&(DATA2); \
828 } \
829 int32_t* ERR_VAR_NAME(pDataTemp3, __LINE__); \
830 if(sizeof(DATA3) < 4) \
831 { \
832 int32_t ERR_VAR_NAME(DataTemp3, __LINE__) = DATA3; \
833 ERR_VAR_NAME(pDataTemp3, __LINE__) = &ERR_VAR_NAME(DataTemp3, __LINE__); \
834 } \
835 else \
836 { \
837 ERR_VAR_NAME(pDataTemp3, __LINE__) = (int32_t*)&(DATA3); \
838 } \
839 _SetErrorX(&g_t##ID, &ERR_VAR_NAME(g_t##ID##Source, __LINE__), *ERR_VAR_NAME(pDataTemp1, __LINE__), \
840 *ERR_VAR_NAME(pDataTemp2, __LINE__), \
841 *ERR_VAR_NAME(pDataTemp3, __LINE__)); \
842}while(0)
843
844
852#define SetErrorIdData4(ID, DATA1, DATA2, DATA3, DATA4) \
853do \
854{ \
855 static const tErrorSource ERR_VAR_NAME(g_t##ID##Source, __LINE__) __attribute__((section("error_sources"), used)) = { \
856 __LINE__, \
857 g_sFileName, \
858 sizeof(g_sFileName) - 1 \
859 }; \
860 \
861 int32_t* ERR_VAR_NAME(pDataTemp1, __LINE__); \
862 if(sizeof(DATA1) < 4) \
863 { \
864 int32_t ERR_VAR_NAME(DataTemp1, __LINE__) = DATA1; \
865 ERR_VAR_NAME(pDataTemp1, __LINE__) = &ERR_VAR_NAME(DataTemp1, __LINE__); \
866 } \
867 else \
868 { \
869 ERR_VAR_NAME(pDataTemp1, __LINE__) = (int32_t*)&(DATA1); \
870 } \
871 int32_t* ERR_VAR_NAME(pDataTemp2, __LINE__); \
872 if(sizeof(DATA2) < 4) \
873 { \
874 int32_t ERR_VAR_NAME(DataTemp2, __LINE__) = DATA2; \
875 ERR_VAR_NAME(pDataTemp2, __LINE__) = &ERR_VAR_NAME(DataTemp2, __LINE__); \
876 } \
877 else \
878 { \
879 ERR_VAR_NAME(pDataTemp2, __LINE__) = (int32_t*)&(DATA2); \
880 } \
881 int32_t* ERR_VAR_NAME(pDataTemp3, __LINE__); \
882 if(sizeof(DATA3) < 4) \
883 { \
884 int32_t ERR_VAR_NAME(DataTemp3, __LINE__) = DATA3; \
885 ERR_VAR_NAME(pDataTemp3, __LINE__) = &ERR_VAR_NAME(DataTemp3, __LINE__); \
886 } \
887 else \
888 { \
889 ERR_VAR_NAME(pDataTemp3, __LINE__) = (int32_t*)&(DATA3); \
890 } \
891 int32_t* ERR_VAR_NAME(pDataTemp4, __LINE__); \
892 if(sizeof(DATA4) < 4) \
893 { \
894 int32_t ERR_VAR_NAME(DataTemp4, __LINE__) = DATA4; \
895 ERR_VAR_NAME(pDataTemp4, __LINE__) = &ERR_VAR_NAME(DataTemp4, __LINE__); \
896 } \
897 else \
898 { \
899 ERR_VAR_NAME(pDataTemp4, __LINE__) = (int32_t*)&(DATA4); \
900 } \
901 _SetErrorX(&g_t##ID, &ERR_VAR_NAME(g_t##ID##Source, __LINE__), *ERR_VAR_NAME(pDataTemp1, __LINE__), \
902 *ERR_VAR_NAME(pDataTemp2, __LINE__), \
903 *ERR_VAR_NAME(pDataTemp3, __LINE__), \
904 *ERR_VAR_NAME(pDataTemp4, __LINE__)); \
905}while(0)
906
907
915#define DefineOnErrorReaction(ERROR_REACTION, NAME, HELP_EN, HELP_DE) \
916ASSERT_REACTION_NAME(NAME); \
917ASSERT_HELP(INCLUDE_HELP_EN(HELP_EN) INCLUDE_HELP_DE(HELP_DE)); \
918static const char ERR_VAR_NAME(g_s##ERROR_REACTION##Name, __LINE__)[] __attribute__((section("error_strings"), used)) = NAME; \
919static const char ERR_VAR_NAME(g_s##ERROR_REACTION##Help, __LINE__)[] __attribute__((section("error_strings"), used)) = \
920ERROR_HELP_TEXT_COMBINE(INCLUDE_HELP_EN("DOC_E " HELP_EN) INCLUDE_HELP_DE("DOC_D " HELP_DE)); \
921const tOnErrorReaction g_t##ERROR_REACTION __attribute__((section("error_reactions"), used)) = { \
922 &ERROR_REACTION, \
923 ERR_VAR_NAME(g_s##ERROR_REACTION##Name, __LINE__), \
924 sizeof(ERR_VAR_NAME(g_s##ERROR_REACTION##Name, __LINE__)) - 1, \
925 ERR_VAR_NAME(g_s##ERROR_REACTION##Help, __LINE__), \
926 sizeof(ERR_VAR_NAME(g_s##ERROR_REACTION##Help, __LINE__)) - 1 \
927};
928
929
934#define DeclareOnErrorReaction(ERROR_REACTION) \
935 const tOnErrorReaction g_t##ERROR_REACTION; \
936 void ERROR_REACTION(void)
937
938
946#define DefineOnErrorResetReaction(ERROR_REACTION, NAME, HELP_EN, HELP_DE) \
947ASSERT_REACTION_NAME(NAME); \
948ASSERT_HELP(INCLUDE_HELP_EN(HELP_EN) INCLUDE_HELP_DE(HELP_DE)); \
949static const char ERR_VAR_NAME(g_s##ERROR_REACTION##Name, __LINE__)[] __attribute__((section("error_strings"), used)) = NAME; \
950static const char ERR_VAR_NAME(g_s##ERROR_REACTION##Help, __LINE__)[] __attribute__((section("error_strings"), used)) = \
951ERROR_HELP_TEXT_COMBINE(INCLUDE_HELP_EN("DOC_E " HELP_EN) INCLUDE_HELP_DE("DOC_D " HELP_DE)); \
952const tOnErrorResetReaction g_t##ERROR_REACTION __attribute__((section("error_reactions"), used)) = { \
953 &ERROR_REACTION, \
954 ERR_VAR_NAME(g_s##ERROR_REACTION##Name, __LINE__), \
955 sizeof(ERR_VAR_NAME(g_s##ERROR_REACTION##Name, __LINE__)) - 1, \
956 ERR_VAR_NAME(g_s##ERROR_REACTION##Help, __LINE__), \
957 sizeof(ERR_VAR_NAME(g_s##ERROR_REACTION##Help, __LINE__)) - 1 \
958};
959
960
965#define DeclareOnErrorResetReaction(ERROR_REACTION) \
966 const tOnErrorResetReaction g_t##ERROR_REACTION; \
967 bool ERROR_REACTION(void)
968
969extern DeclareOnErrorReaction(NoOnErrorReaction);
970extern DeclareOnErrorResetReaction(NoOnErrorResetReaction);
971
972//-----------------------------------------------------------------------------
973// Local data
974//-----------------------------------------------------------------------------
978static const char g_sFileName[] __attribute__((section("error_strings"), used)) = __BASE_FILE__;
979
980//-----------------------------------------------------------------------------
981// global data
982//-----------------------------------------------------------------------------
983extern uint32_t g_u32ErrorPending;
984extern tErrorListItem g_ptErrorList[MAX_NUMBER_OF_ERRORS];
985
986//-----------------------------------------------------------------------------
987// Global function prototypes
988//-----------------------------------------------------------------------------
989void ErrorInit(void);
990tErrorListItem* _SetErrorX(const tError* ptError, const tErrorSource* ptErrorSource, ...);
991void ErrorResetX(uint8_t ui8AccessLevel);
992void ResetErrorIdRange(uint16_t ui16ErrorIdStart, uint16_t ui16ErrorIdEnd, uint8_t ui8AccessLevel);
993void ErrorClear(uint8_t ui8AccessLevel);
994bool ErrorsPending(void);
995void MaxFloat(void* DataOld, float DataNew);
996void MinFloat(void* DataOld, float DataNew);
997void MaxAbsFloat(void* DataOld, float DataNew);
998void MaxInt(void* DataOld, int32_t DataNew);
999void MinInt(void* DataOld, int32_t DataNew);
1000void MaxUInt(void* DataOld, uint32_t DataNew);
1001void MinUInt(void* DataOld, uint32_t DataNew);
1002void NoDataUpdate(void* DataOld, ...);
1003bool IsErrorPending(uint32_t position);
1004bool IsErrorIdPending(uint16_t ui16ErrorId);
1005bool IsErrorIdRangePending(uint16_t ui16ErrorIdStart, uint16_t ui16ErrorIdEnd);
1006uint16_t GetErrorId(uint32_t position);
1007uint32_t PendingErrosSortedByTime(tErrorListItem* pptPendingErrorList[]);
1008
1009#ifdef __cplusplus
1010}
1011#endif
1012#endif //ERROR_h
void(* fpOnErrorX)(void)
Structure used in tError to describe a function to be called on error set.
Definition: Error.h:61
ERROR_FLAGS
Flags used for errors.
Definition: Error.h:50
@ VIEWER_RESET
Can be reset by user with Viewer access level.
Definition: Error.h:51
@ PLC_RESET
Can be reset by the PLC.
Definition: Error.h:55
@ CODE_RESET
Can be reset by the program it-selve e.g. after Init.
Definition: Error.h:56
@ DEVELOPER_RESET
Can be reset by user with Developer access level.
Definition: Error.h:54
@ PROFESSIONAL_RESET
Can be reset by user with Professional access level.
Definition: Error.h:53
@ USER_RESET
Can be reset by user with User access level.
Definition: Error.h:52
@ NV_STORED
Stored in Non-Volatile RAM.
Definition: Error.h:57
uint32_t g_u32ErrorPending
#define MAX_NUMBER_OF_ERRORS
Size of the error stack.
Definition: Error.h:36
bool(* fpOnErrorResetX)(void)
Structure used in tError to describe a function to be called on error reset.
Definition: Error.h:77
DeclareOnErrorReaction(TestErrorReaction)
Definition of a timestamp type.
Definition: timestamp.h:33
Main error structure.
Definition: Error.h:93
const uint16_t ui16Id
Error-ID.
Definition: Error.h:94
const uint16_t ui16DataCount
Number of attached variables (not byte). See Details on Page Data appended to errors.
Definition: Error.h:95
const uint32_t ui32Flags
Flags from enum ERROR_FLAGS e.g. error reset permissions.
Definition: Error.h:96
const uint32_t ui32HelpLength
Strlen of Help.
Definition: Error.h:100
const char * Help
Long help text explaining the cause and maybe how to solve the error. See Page Help-texts in Errors f...
Definition: Error.h:99
const tOnErrorReaction * OnError
Function to be called on first time setting the error. See Page Actions on Error set and reset for de...
Definition: Error.h:101
const tOnErrorResetReaction * OnErrorReset
Function to be called on reseting the error. See Page Actions on Error set and reset for details.
Definition: Error.h:102
const uint32_t ui32DescriptionLength
Strlen of Description.
Definition: Error.h:98
const char * Description
Short Description of the error.
Definition: Error.h:97
Structure used in the error stack.
Definition: Error.h:116
Type_Timestamp tTimestampFirst
Time when the error was set the first time.
Definition: Error.h:119
Type_Timestamp tTimestampLast
Time when the error was set the last time.
Definition: Error.h:120
void * Data
Pointer to the attached data the number is stored on ptError. The length is defined in Error-Definiti...
Definition: Error.h:122
const tErrorSource * ptErrorSource
Location of the error in source code.
Definition: Error.h:118
const tError * ptError
Pointer to the error itself.
Definition: Error.h:117
uint32_t ui32ErrorCount
Number of occurrences. Starts with 1 and increments on every occurence.
Definition: Error.h:121
Structure used in tError holding source-code file an line.
Definition: Error.h:107
const uint32_t ui32Line
Source-code line.
Definition: Error.h:108
const char * File
Source-code filename and path.
Definition: Error.h:109
const uint32_t ui32FileLength
Strlen of filename.
Definition: Error.h:110
The error reaction is called on occurence of the error.
Definition: Error.h:67
const uint32_t ui32HelpSize
StrLen of Help.
Definition: Error.h:72
const fpOnErrorX fpErrorReaction
Function to be called.
Definition: Error.h:68
const char * cHelp
Help Text. See Page Help-texts in Errors for details.
Definition: Error.h:71
const char * cName
Name of the Function.
Definition: Error.h:69
const uint32_t ui32NameSize
StrLen of Name.
Definition: Error.h:70
The error reset reaction is called on reset of the error.
Definition: Error.h:83
const fpOnErrorResetX fpErrorReaction
Function to be called.
Definition: Error.h:84
const uint32_t ui32HelpSize
StrLen of Help.
Definition: Error.h:88
const char * cHelp
Help Text. See Page Help-texts in Errors for details.
Definition: Error.h:87
const char * cName
Name of the Function.
Definition: Error.h:85
const uint32_t ui32NameSize
StrLen of Name.
Definition: Error.h:86
Definition of timestamp data-structs.