ErrorLib 1.0.14-master SHA: 787260c7d1
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
39#define MIN_ERR_REACTION_NAME_LENTH 10
41#define MIN_DESCRIPTION_LENTH 10
43#define MIN_HELP_LENTH 20
44
46#define ERROR_STACK_OVERFLOW 0x80000000
47
49#define ERROR_SYSTEM_VERSION 2
50
51extern uint32_t g_u32ErrorPending;
52
56{
61 PLC_RESET = 16,
63 NV_STORED = 64
64};
65
67typedef void (*fpOnErrorX)(void);
68
72typedef struct
73{
75 const char* cName;
76 const uint32_t ui32NameSize;
77 const char* cHelp;
78 const uint32_t ui32HelpSize;
80
83typedef bool (*fpOnErrorResetX)(void);
84
88typedef struct
89{
91 const char* cName;
92 const uint32_t ui32NameSize;
93 const char* cHelp;
94 const uint32_t ui32HelpSize;
96
98typedef struct
99{
100 const uint16_t ui16Id;
101 const uint16_t ui16DataCount;
102 const uint32_t ui32Flags;
103 const char* Description;
104 const uint32_t ui32DescriptionLength;
105 const char* Help;
106 const uint32_t ui32HelpLength;
109}tError;
110
112typedef struct
113{
114 const uint32_t ui32Line;
115 const char* File;
116 const uint32_t ui32FileLength;
118
119
121typedef struct
122{
127 uint32_t ui32ErrorCount;
128 void* Data;
130
132#define ERR_VAR_NAME_SRT(x, y) x ## y
134#define ERR_VAR_NAME(x, y) ERR_VAR_NAME_SRT(x, y)
135
137#define xstr(s) str(s)
139#define str(s) #s
140
142#define ASSERT_REACTION_NAME(NAME) static_assert(sizeof(NAME) > MIN_ERR_REACTION_NAME_LENTH, \
143"Error reaction name to short must be at least "xstr(MIN_ERR_REACTION_NAME_LENTH)" characters long!") \
144
146#define ASSERT_DESCRIPTION(DESCRIPTION) static_assert(sizeof(DESCRIPTION) > MIN_DESCRIPTION_LENTH, \
147"Error description text to short must be at least "xstr(MIN_DESCRIPTION_LENTH)" characters long!") \
148
150#define ASSERT_HELP(HELP) static_assert(sizeof(HELP) > MIN_HELP_LENTH, \
151"Error help text to short must be at least "xstr(MIN_HELP_LENTH)" characters long!") \
152
154#ifdef ERROR_TEXTS_IN_FILE
156typedef struct
157{
158 const uint16_t ui16ErrorID;
159 const uint32_t ui32Length;
160 const char cText[];
161}tErrorHelpText;
162
163#define ERROR_HELP_TEXT_COMBINE(x)
164#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};
165#else
166#define ERROR_HELP_TEXT_COMBINE(x) x
167#define ERROR_HELP_TEXT_SECTION(ERROR_ID, HELP)
168#endif
169
170#ifdef INCLUDE_ENGLISH_HELP
171#define INCLUDE_HELP_EN(HELP) HELP
172#else
173#define INCLUDE_HELP_EN(HELP)
174#endif
175
176#ifdef INCLUDE_GERMAN_HELP
177#define INCLUDE_HELP_DE(HELP) HELP
178#else
179#define INCLUDE_HELP_DE(HELP)
180#endif
181
182
193#define DefineError(ID, PERMISSION, ON_ERROR, ON_ERROR_RESET, DESCRIPTION, HELP_EN, HELP_DE) \
194 ASSERT_DESCRIPTION(DESCRIPTION); \
195 ASSERT_HELP(INCLUDE_HELP_EN(HELP_EN) INCLUDE_HELP_DE(HELP_DE)); \
196 static const char g_s##ID##Description[] __attribute__((section("error_strings"), used)) = DESCRIPTION; \
197 static const char g_s##ID##Help[] __attribute__((section("error_strings"), used)) = \
198 ERROR_HELP_TEXT_COMBINE(INCLUDE_HELP_EN("DOC_E " HELP_EN) INCLUDE_HELP_DE("DOC_D " HELP_DE)); \
199 \
200 const tError g_t##ID __attribute__((section("error_descriptor"), used)) = { \
201 ID, \
202 0, \
203 PERMISSION, \
204 g_s##ID##Description, \
205 sizeof(DESCRIPTION) - 1, \
206 g_s##ID##Help, \
207 sizeof(g_s##ID##Help) - 1, \
208 &g_t##ON_ERROR, \
209 &g_t##ON_ERROR_RESET, \
210 }
211
212
224#define DefineErrorData(ID, PERMISSION, ON_ERROR, ON_ERROR_RESET, DESCRIPTION, HELP_EN, HELP_DE, DATA_COUNT) \
225 ASSERT_DESCRIPTION(DESCRIPTION); \
226 ASSERT_HELP(INCLUDE_HELP_EN(HELP_EN) INCLUDE_HELP_DE(HELP_DE)); \
227 static const char g_s##ID##Description[] __attribute__((section("error_strings"), used)) = DESCRIPTION; \
228 static const char g_s##ID##Help[] __attribute__((section("error_strings"), used)) = \
229 ERROR_HELP_TEXT_COMBINE(INCLUDE_HELP_EN("DOC_E " HELP_EN) INCLUDE_HELP_DE("DOC_D " HELP_DE)); \
230 \
231 const tError g_t##ID __attribute__((section("error_descriptor"), used)) = { \
232 ID, \
233 DATA_COUNT, \
234 PERMISSION, \
235 g_s##ID##Description, \
236 sizeof(g_s##ID##Description) - 1, \
237 g_s##ID##Help, \
238 sizeof(g_s##ID##Help) - 1, \
239 &g_t##ON_ERROR, \
240 &g_t##ON_ERROR_RESET, \
241 }
242
243
248#define DeclareError(ID) const tError g_t##ID
249
250
261#define SetError(ID, PERMISSION, ON_ERROR, ON_ERROR_RESET, DESCRIPTION, HELP_EN, HELP_DE) \
262do \
263{ \
264 ASSERT_DESCRIPTION(DESCRIPTION); \
265 ASSERT_HELP(INCLUDE_HELP_EN(HELP_EN) INCLUDE_HELP_DE(HELP_DE)); \
266 static const char g_s##ID##Description[] __attribute__((section("error_strings"), used)) = DESCRIPTION; \
267 static const char g_s##ID##Help[] __attribute__((section("error_strings"), used)) = \
268 ERROR_HELP_TEXT_COMBINE(INCLUDE_HELP_EN("DOC_E " HELP_EN) INCLUDE_HELP_DE("DOC_D " HELP_DE)); \
269 static const tErrorSource g_t##ID##Source __attribute__((section("error_sources"), used)) = { \
270 __LINE__, \
271 g_sFileName, \
272 sizeof(g_sFileName) - 1 \
273 }; \
274 \
275 static const tError g_t##ID __attribute__((section("error_descriptor"), used)) = { \
276 ID, \
277 0, \
278 PERMISSION, \
279 g_s##ID##Description, \
280 sizeof(DESCRIPTION) - 1, \
281 g_s##ID##Help, \
282 sizeof(g_s##ID##Help) - 1, \
283 &g_t##ON_ERROR, \
284 &g_t##ON_ERROR_RESET, \
285 }; \
286 _SetErrorX(&g_t##ID, &g_t##ID##Source); \
287}while(0)
288
289
301#define SetErrorSource(ID, PERMISSION, ON_ERROR, ON_ERROR_RESET, DESCRIPTION, HELP_EN, HELP_DE, SOURCE) \
302do \
303{ \
304 ASSERT_DESCRIPTION(DESCRIPTION); \
305 ASSERT_HELP(INCLUDE_HELP_EN(HELP_EN) INCLUDE_HELP_DE(HELP_DE)); \
306 static const char g_s##ID##Description[] __attribute__((section("error_strings"), used)) = DESCRIPTION; \
307 static const char g_s##ID##Help[] __attribute__((section("error_strings"), used)) = \
308 ERROR_HELP_TEXT_COMBINE(INCLUDE_HELP_EN("DOC_E " HELP_EN) INCLUDE_HELP_DE("DOC_D " HELP_DE)); \
309 \
310 static const tError g_t##ID __attribute__((section("error_descriptor"), used)) = { \
311 ID, \
312 0, \
313 PERMISSION, \
314 g_s##ID##Description, \
315 sizeof(DESCRIPTION) - 1, \
316 g_s##ID##Help, \
317 sizeof(g_s##ID##Help) - 1, \
318 &g_t##ON_ERROR, \
319 &g_t##ON_ERROR_RESET, \
320 }; \
321 _SetErrorX(&g_t##ID, SOURCE); \
322}while(0)
323
324
336#define SetErrorData1(ID, PERMISSION, ON_ERROR, ON_ERROR_RESET, DESCRIPTION, HELP_EN, HELP_DE, DATA1) \
337do \
338{ \
339 ASSERT_DESCRIPTION(DESCRIPTION); \
340 ASSERT_HELP(INCLUDE_HELP_EN(HELP_EN) INCLUDE_HELP_DE(HELP_DE)); \
341 static const char g_s##ID##Description[] __attribute__((section("error_strings"), used)) = DESCRIPTION; \
342 static const char g_s##ID##Help[] __attribute__((section("error_strings"), used)) = \
343 ERROR_HELP_TEXT_COMBINE(INCLUDE_HELP_EN("DOC_E " HELP_EN) INCLUDE_HELP_DE("DOC_D " HELP_DE)); \
344 static const tErrorSource g_t##ID##Source __attribute__((section("error_sources"), used)) = { \
345 __LINE__, \
346 g_sFileName, \
347 sizeof(g_sFileName) - 1 \
348 }; \
349 \
350 static const tError g_t##ID __attribute__((section("error_descriptor"), used)) = { \
351 ID, \
352 1, \
353 PERMISSION, \
354 g_s##ID##Description, \
355 sizeof(DESCRIPTION) - 1, \
356 g_s##ID##Help, \
357 sizeof(g_s##ID##Help) - 1, \
358 &g_t##ON_ERROR, \
359 &g_t##ON_ERROR_RESET, \
360 }; \
361 if(sizeof(DATA1) < 4) \
362 { \
363 int32_t ERR_VAR_NAME(DataTemp, __LINE__) = DATA1; \
364 _SetErrorX(&g_t##ID, &g_t##ID##Source, ERR_VAR_NAME(DataTemp, __LINE__)); \
365 } \
366 else \
367 { \
368 _SetErrorX(&g_t##ID, &g_t##ID##Source, *(uint32_t*)&DATA1); \
369 } \
370}while(0)
371
372
387#define SetErrorData1Compare(ID, PERMISSION, ON_ERROR, ON_ERROR_RESET, DESCRIPTION, HELP_EN, HELP_DE, DATA1, COMPARE1) \
388do \
389{ \
390 ASSERT_DESCRIPTION(DESCRIPTION); \
391 ASSERT_HELP(INCLUDE_HELP_EN(HELP_EN) INCLUDE_HELP_DE(HELP_DE)); \
392 static const char g_s##ID##Description[] __attribute__((section("error_strings"), used)) = DESCRIPTION; \
393 static const char g_s##ID##Help[] __attribute__((section("error_strings"), used)) = \
394 ERROR_HELP_TEXT_COMBINE(INCLUDE_HELP_EN("DOC_E " HELP_EN) INCLUDE_HELP_DE("DOC_D " HELP_DE)); \
395 static const tErrorSource g_t##ID##Source __attribute__((section("error_sources"), used)) = { \
396 __LINE__, \
397 g_sFileName, \
398 sizeof(g_sFileName) - 1 \
399 }; \
400 \
401 static const tError g_t##ID __attribute__((section("error_descriptor"), used)) = { \
402 ID, \
403 1, \
404 PERMISSION, \
405 g_s##ID##Description, \
406 sizeof(DESCRIPTION) - 1, \
407 g_s##ID##Help, \
408 sizeof(g_s##ID##Help) - 1, \
409 &g_t##ON_ERROR, \
410 &g_t##ON_ERROR_RESET, \
411 }; \
412 \
413 tErrorListItem* ERR_VAR_NAME(ptError, __LINE__); \
414 if(sizeof(DATA1) < 4) \
415 { \
416 int32_t ERR_VAR_NAME(DataTemp, __LINE__) = DATA1; \
417 ERR_VAR_NAME(ptError, __LINE__) = _SetErrorX(&g_t##ID, &g_t##ID##Source, ERR_VAR_NAME(DataTemp, __LINE__)); \
418 } \
419 else \
420 { \
421 ERR_VAR_NAME(ptError, __LINE__) = _SetErrorX(&g_t##ID, &g_t##ID##Source, *(uint32_t*)&DATA1); \
422 } \
423 COMPARE1(ERR_VAR_NAME(ptError, __LINE__)->Data, DATA1); \
424}while(0)
425
426
439#define SetErrorData2(ID, PERMISSION, ON_ERROR, ON_ERROR_RESET, DESCRIPTION, HELP_EN, HELP_DE, DATA1, DATA2) \
440do \
441{ \
442 ASSERT_DESCRIPTION(DESCRIPTION); \
443 ASSERT_HELP(INCLUDE_HELP_EN(HELP_EN) INCLUDE_HELP_DE(HELP_DE)); \
444 static const char g_s##ID##Description[] __attribute__((section("error_strings"), used)) = DESCRIPTION; \
445 static const char g_s##ID##Help[] __attribute__((section("error_strings"), used)) = \
446 ERROR_HELP_TEXT_COMBINE(INCLUDE_HELP_EN("DOC_E " HELP_EN) INCLUDE_HELP_DE("DOC_D " HELP_DE)); \
447 static const tErrorSource g_t##ID##Source __attribute__((section("error_sources"), used)) = { \
448 __LINE__, \
449 g_sFileName, \
450 sizeof(g_sFileName) - 1 \
451 }; \
452 \
453 static const tError g_t##ID __attribute__((section("error_descriptor"), used)) = { \
454 ID, \
455 2, \
456 PERMISSION, \
457 g_s##ID##Description, \
458 sizeof(DESCRIPTION) - 1, \
459 g_s##ID##Help, \
460 sizeof(g_s##ID##Help) - 1, \
461 &g_t##ON_ERROR, \
462 &g_t##ON_ERROR_RESET, \
463 }; \
464 \
465 int32_t* ERR_VAR_NAME(pDataTemp1, __LINE__); \
466 if(sizeof(DATA1) < 4) \
467 { \
468 int32_t ERR_VAR_NAME(DataTemp1, __LINE__) = DATA1; \
469 ERR_VAR_NAME(pDataTemp1, __LINE__) = &ERR_VAR_NAME(DataTemp1, __LINE__); \
470 } \
471 else \
472 { \
473 ERR_VAR_NAME(pDataTemp1, __LINE__) = (int32_t*)&(DATA1); \
474 } \
475 int32_t* ERR_VAR_NAME(pDataTemp2, __LINE__); \
476 if(sizeof(DATA2) < 4) \
477 { \
478 int32_t ERR_VAR_NAME(DataTemp2, __LINE__) = DATA2; \
479 ERR_VAR_NAME(pDataTemp2, __LINE__) = &ERR_VAR_NAME(DataTemp2, __LINE__); \
480 } \
481 else \
482 { \
483 ERR_VAR_NAME(pDataTemp2, __LINE__) = (int32_t*)&(DATA2); \
484 } \
485 _SetErrorX(&g_t##ID, &g_t##ID##Source, *ERR_VAR_NAME(pDataTemp1, __LINE__), *ERR_VAR_NAME(pDataTemp2, __LINE__)); \
486}while(0)
487
488
505#define SetErrorData2Compare(ID, PERMISSION, ON_ERROR, ON_ERROR_RESET, DESCRIPTION, HELP_EN, HELP_DE, DATA1, COMPARE1, DATA2, COMPARE2) \
506do \
507{ \
508 ASSERT_DESCRIPTION(DESCRIPTION); \
509 ASSERT_HELP(INCLUDE_HELP_EN(HELP_EN) INCLUDE_HELP_DE(HELP_DE)); \
510 static const char g_s##ID##Description[] __attribute__((section("error_strings"), used)) = DESCRIPTION; \
511 static const char g_s##ID##Help[] __attribute__((section("error_strings"), used)) = \
512 ERROR_HELP_TEXT_COMBINE(INCLUDE_HELP_EN("DOC_E " HELP_EN) INCLUDE_HELP_DE("DOC_D " HELP_DE)); \
513 static const tErrorSource g_t##ID##Source __attribute__((section("error_sources"), used)) = { \
514 __LINE__, \
515 g_sFileName, \
516 sizeof(g_sFileName) - 1 \
517 }; \
518 \
519 static const tError g_t##ID __attribute__((section("error_descriptor"), used)) = { \
520 ID, \
521 2, \
522 PERMISSION, \
523 g_s##ID##Description, \
524 sizeof(DESCRIPTION) - 1, \
525 g_s##ID##Help, \
526 sizeof(g_s##ID##Help) - 1, \
527 &g_t##ON_ERROR, \
528 &g_t##ON_ERROR_RESET, \
529 }; \
530 \
531 int32_t* ERR_VAR_NAME(pDataTemp1, __LINE__); \
532 if(sizeof(DATA1) < 4) \
533 { \
534 int32_t ERR_VAR_NAME(DataTemp1, __LINE__) = DATA1; \
535 ERR_VAR_NAME(pDataTemp1, __LINE__) = &ERR_VAR_NAME(DataTemp1, __LINE__); \
536 } \
537 else \
538 { \
539 ERR_VAR_NAME(pDataTemp1, __LINE__) = (int32_t*)&(DATA1); \
540 } \
541 int32_t* ERR_VAR_NAME(pDataTemp2, __LINE__); \
542 if(sizeof(DATA2) < 4) \
543 { \
544 int32_t ERR_VAR_NAME(DataTemp2, __LINE__) = DATA2; \
545 ERR_VAR_NAME(pDataTemp2, __LINE__) = &ERR_VAR_NAME(DataTemp2, __LINE__); \
546 } \
547 else \
548 { \
549 ERR_VAR_NAME(pDataTemp2, __LINE__) = (int32_t*)&(DATA2); \
550 } \
551 tErrorListItem* ERR_VAR_NAME(ptError, __LINE__) = _SetErrorX(&g_t##ID, &g_t##ID##Source, *ERR_VAR_NAME(pDataTemp1, __LINE__), \
552 *ERR_VAR_NAME(pDataTemp2, __LINE__)); \
553 if((ERR_VAR_NAME(ptError, __LINE__) != 0) && (ERR_VAR_NAME(ptError, __LINE__)->Data != 0)) \
554 { \
555 COMPARE1(ERR_VAR_NAME(ptError, __LINE__)->Data, DATA1); \
556 COMPARE2(ERR_VAR_NAME(ptError, __LINE__)->Data + 4, DATA2); \
557 } \
558}while(0)
559
560
574#define SetErrorData3(ID, PERMISSION, ON_ERROR, ON_ERROR_RESET, DESCRIPTION, HELP_EN, HELP_DE, DATA1, DATA2, DATA3) \
575do \
576{ \
577 ASSERT_DESCRIPTION(DESCRIPTION); \
578 ASSERT_HELP(INCLUDE_HELP_EN(HELP_EN) INCLUDE_HELP_DE(HELP_DE)); \
579 static const char g_s##ID##Description[] __attribute__((section("error_strings"), used)) = DESCRIPTION; \
580 static const char g_s##ID##Help[] __attribute__((section("error_strings"), used)) = \
581 ERROR_HELP_TEXT_COMBINE(INCLUDE_HELP_EN("DOC_E " HELP_EN) INCLUDE_HELP_DE("DOC_D " HELP_DE)); \
582 static const tErrorSource g_t##ID##Source __attribute__((section("error_sources"), used)) = { \
583 __LINE__, \
584 g_sFileName, \
585 sizeof(g_sFileName) - 1 \
586 }; \
587 \
588 static const tError g_t##ID __attribute__((section("error_descriptor"), used)) = { \
589 ID, \
590 3, \
591 PERMISSION, \
592 g_s##ID##Description, \
593 sizeof(DESCRIPTION) - 1, \
594 g_s##ID##Help, \
595 sizeof(g_s##ID##Help) - 1, \
596 &g_t##ON_ERROR, \
597 &g_t##ON_ERROR_RESET, \
598 }; \
599 \
600 int32_t* ERR_VAR_NAME(pDataTemp1, __LINE__); \
601 if(sizeof(DATA1) < 4) \
602 { \
603 int32_t ERR_VAR_NAME(DataTemp1, __LINE__) = DATA1; \
604 ERR_VAR_NAME(pDataTemp1, __LINE__) = &ERR_VAR_NAME(DataTemp1, __LINE__); \
605 } \
606 else \
607 { \
608 ERR_VAR_NAME(pDataTemp1, __LINE__) = (int32_t*)&(DATA1); \
609 } \
610 int32_t* ERR_VAR_NAME(pDataTemp2, __LINE__); \
611 if(sizeof(DATA2) < 4) \
612 { \
613 int32_t ERR_VAR_NAME(DataTemp2, __LINE__) = DATA2; \
614 ERR_VAR_NAME(pDataTemp2, __LINE__) = &ERR_VAR_NAME(DataTemp2, __LINE__); \
615 } \
616 else \
617 { \
618 ERR_VAR_NAME(pDataTemp2, __LINE__) = (int32_t*)&(DATA2); \
619 } \
620 int32_t* ERR_VAR_NAME(pDataTemp3, __LINE__); \
621 if(sizeof(DATA3) < 4) \
622 { \
623 int32_t ERR_VAR_NAME(DataTemp3, __LINE__) = DATA3; \
624 ERR_VAR_NAME(pDataTemp3, __LINE__) = &ERR_VAR_NAME(DataTemp3, __LINE__); \
625 } \
626 else \
627 { \
628 ERR_VAR_NAME(pDataTemp3, __LINE__) = (int32_t*)&(DATA3); \
629 } \
630 _SetErrorX(&g_t##ID, &g_t##ID##Source, *ERR_VAR_NAME(pDataTemp1, __LINE__), *ERR_VAR_NAME(pDataTemp2, __LINE__), \
631 *ERR_VAR_NAME(pDataTemp3, __LINE__)); \
632}while(0)
633
634
649#define SetErrorData4(ID, PERMISSION, ON_ERROR, ON_ERROR_RESET, DESCRIPTION, HELP_EN, HELP_DE, DATA1, DATA2, DATA3, DATA4) \
650do \
651{ \
652 ASSERT_DESCRIPTION(DESCRIPTION); \
653 ASSERT_HELP(INCLUDE_HELP_EN(HELP_EN) INCLUDE_HELP_DE(HELP_DE)); \
654 static const char g_s##ID##Description[] __attribute__((section("error_strings"), used)) = DESCRIPTION; \
655 static const char g_s##ID##Help[] __attribute__((section("error_strings"), used)) = \
656 ERROR_HELP_TEXT_COMBINE(INCLUDE_HELP_EN("DOC_E " HELP_EN) INCLUDE_HELP_DE("DOC_D " HELP_DE)); \
657 static const tErrorSource g_t##ID##Source __attribute__((section("error_sources"), used)) = { \
658 __LINE__, \
659 g_sFileName, \
660 sizeof(g_sFileName) - 1 \
661 }; \
662 \
663 static const tError g_t##ID __attribute__((section("error_descriptor"), used)) = { \
664 ID, \
665 4, \
666 PERMISSION, \
667 g_s##ID##Description, \
668 sizeof(DESCRIPTION) - 1, \
669 g_s##ID##Help, \
670 sizeof(g_s##ID##Help) - 1, \
671 &g_t##ON_ERROR, \
672 &g_t##ON_ERROR_RESET, \
673 }; \
674 \
675 int32_t* ERR_VAR_NAME(pDataTemp1, __LINE__); \
676 if(sizeof(DATA1) < 4) \
677 { \
678 int32_t ERR_VAR_NAME(DataTemp1, __LINE__) = DATA1; \
679 ERR_VAR_NAME(pDataTemp1, __LINE__) = &ERR_VAR_NAME(DataTemp1, __LINE__); \
680 } \
681 else \
682 { \
683 ERR_VAR_NAME(pDataTemp1, __LINE__) = (int32_t*)&(DATA1); \
684 } \
685 int32_t* ERR_VAR_NAME(pDataTemp2, __LINE__); \
686 if(sizeof(DATA2) < 4) \
687 { \
688 int32_t ERR_VAR_NAME(DataTemp2, __LINE__) = DATA2; \
689 ERR_VAR_NAME(pDataTemp2, __LINE__) = &ERR_VAR_NAME(DataTemp2, __LINE__); \
690 } \
691 else \
692 { \
693 ERR_VAR_NAME(pDataTemp2, __LINE__) = (int32_t*)&(DATA2); \
694 } \
695 int32_t* ERR_VAR_NAME(pDataTemp3, __LINE__); \
696 if(sizeof(DATA3) < 4) \
697 { \
698 int32_t ERR_VAR_NAME(DataTemp3, __LINE__) = DATA3; \
699 ERR_VAR_NAME(pDataTemp3, __LINE__) = &ERR_VAR_NAME(DataTemp3, __LINE__); \
700 } \
701 else \
702 { \
703 ERR_VAR_NAME(pDataTemp3, __LINE__) = (int32_t*)&(DATA3); \
704 } \
705 int32_t* ERR_VAR_NAME(pDataTemp4, __LINE__); \
706 if(sizeof(DATA4) < 4) \
707 { \
708 int32_t ERR_VAR_NAME(DataTemp4, __LINE__) = DATA4; \
709 ERR_VAR_NAME(pDataTemp4, __LINE__) = &ERR_VAR_NAME(DataTemp4, __LINE__); \
710 } \
711 else \
712 { \
713 ERR_VAR_NAME(pDataTemp4, __LINE__) = (int32_t*)&(DATA4); \
714 } \
715 _SetErrorX(&g_t##ID, &g_t##ID##Source, *ERR_VAR_NAME(pDataTemp1, __LINE__), *ERR_VAR_NAME(pDataTemp2, __LINE__), \
716 *ERR_VAR_NAME(pDataTemp3, __LINE__), *ERR_VAR_NAME(pDataTemp4, __LINE__)); \
717}while(0)
718
719
723#define SetErrorId(ID) \
724do \
725{ \
726 static const tErrorSource ERR_VAR_NAME(g_t##ID##Source, __LINE__) __attribute__((section("error_sources"), used)) = { \
727 __LINE__, \
728 g_sFileName, \
729 sizeof(g_sFileName) - 1 \
730 }; \
731 \
732 _SetErrorX(&g_t##ID, &ERR_VAR_NAME(g_t##ID##Source, __LINE__)); \
733}while(0)
734
735
740#define SetErrorIdData1(ID, DATA1) \
741do \
742{ \
743 static const tErrorSource ERR_VAR_NAME(g_t##ID##Source, __LINE__) __attribute__((section("error_sources"), used)) = { \
744 __LINE__, \
745 g_sFileName, \
746 sizeof(g_sFileName) - 1 \
747 }; \
748 \
749 if(sizeof(DATA1) < 4) \
750 { \
751 int32_t ERR_VAR_NAME(DataTemp, __LINE__) = DATA1; \
752 _SetErrorX(&g_t##ID, &ERR_VAR_NAME(g_t##ID##Source, __LINE__), ERR_VAR_NAME(DataTemp, __LINE__)); \
753 } \
754 else \
755 { \
756 _SetErrorX(&g_t##ID, &ERR_VAR_NAME(g_t##ID##Source, __LINE__), DATA1); \
757 } \
758}while(0)
759
760
766#define SetErrorIdData2(ID, DATA1, DATA2) \
767do \
768{ \
769 static const tErrorSource ERR_VAR_NAME(g_t##ID##Source, __LINE__) __attribute__((section("error_sources"), used)) = { \
770 __LINE__, \
771 g_sFileName, \
772 sizeof(g_sFileName) - 1 \
773 }; \
774 \
775 int32_t* ERR_VAR_NAME(pDataTemp1, __LINE__); \
776 if(sizeof(DATA1) < 4) \
777 { \
778 int32_t ERR_VAR_NAME(DataTemp1, __LINE__) = DATA1; \
779 ERR_VAR_NAME(pDataTemp1, __LINE__) = &ERR_VAR_NAME(DataTemp1, __LINE__); \
780 } \
781 else \
782 { \
783 ERR_VAR_NAME(pDataTemp1, __LINE__) = (int32_t*)&(DATA1); \
784 } \
785 int32_t* ERR_VAR_NAME(pDataTemp2, __LINE__); \
786 if(sizeof(DATA2) < 4) \
787 { \
788 int32_t ERR_VAR_NAME(DataTemp2, __LINE__) = DATA2; \
789 ERR_VAR_NAME(pDataTemp2, __LINE__) = &ERR_VAR_NAME(DataTemp2, __LINE__); \
790 } \
791 else \
792 { \
793 ERR_VAR_NAME(pDataTemp2, __LINE__) = (int32_t*)&(DATA2); \
794 } \
795 _SetErrorX(&g_t##ID, &ERR_VAR_NAME(g_t##ID##Source, __LINE__), *ERR_VAR_NAME(pDataTemp1, __LINE__), \
796 *ERR_VAR_NAME(pDataTemp2, __LINE__)); \
797}while(0)
798
799
806#define SetErrorIdData3(ID, DATA1, DATA2, DATA3) \
807do \
808{ \
809 static const tErrorSource ERR_VAR_NAME(g_t##ID##Source, __LINE__) __attribute__((section("error_sources"), used)) = { \
810 __LINE__, \
811 g_sFileName, \
812 sizeof(g_sFileName) - 1 \
813 }; \
814 \
815 int32_t* ERR_VAR_NAME(pDataTemp1, __LINE__); \
816 if(sizeof(DATA1) < 4) \
817 { \
818 int32_t ERR_VAR_NAME(DataTemp1, __LINE__) = DATA1; \
819 ERR_VAR_NAME(pDataTemp1, __LINE__) = &ERR_VAR_NAME(DataTemp1, __LINE__); \
820 } \
821 else \
822 { \
823 ERR_VAR_NAME(pDataTemp1, __LINE__) = (int32_t*)&(DATA1); \
824 } \
825 int32_t* ERR_VAR_NAME(pDataTemp2, __LINE__); \
826 if(sizeof(DATA2) < 4) \
827 { \
828 int32_t ERR_VAR_NAME(DataTemp2, __LINE__) = DATA2; \
829 ERR_VAR_NAME(pDataTemp2, __LINE__) = &ERR_VAR_NAME(DataTemp2, __LINE__); \
830 } \
831 else \
832 { \
833 ERR_VAR_NAME(pDataTemp2, __LINE__) = (int32_t*)&(DATA2); \
834 } \
835 int32_t* ERR_VAR_NAME(pDataTemp3, __LINE__); \
836 if(sizeof(DATA3) < 4) \
837 { \
838 int32_t ERR_VAR_NAME(DataTemp3, __LINE__) = DATA3; \
839 ERR_VAR_NAME(pDataTemp3, __LINE__) = &ERR_VAR_NAME(DataTemp3, __LINE__); \
840 } \
841 else \
842 { \
843 ERR_VAR_NAME(pDataTemp3, __LINE__) = (int32_t*)&(DATA3); \
844 } \
845 _SetErrorX(&g_t##ID, &ERR_VAR_NAME(g_t##ID##Source, __LINE__), *ERR_VAR_NAME(pDataTemp1, __LINE__), \
846 *ERR_VAR_NAME(pDataTemp2, __LINE__), \
847 *ERR_VAR_NAME(pDataTemp3, __LINE__)); \
848}while(0)
849
850
858#define SetErrorIdData4(ID, DATA1, DATA2, DATA3, DATA4) \
859do \
860{ \
861 static const tErrorSource ERR_VAR_NAME(g_t##ID##Source, __LINE__) __attribute__((section("error_sources"), used)) = { \
862 __LINE__, \
863 g_sFileName, \
864 sizeof(g_sFileName) - 1 \
865 }; \
866 \
867 int32_t* ERR_VAR_NAME(pDataTemp1, __LINE__); \
868 if(sizeof(DATA1) < 4) \
869 { \
870 int32_t ERR_VAR_NAME(DataTemp1, __LINE__) = DATA1; \
871 ERR_VAR_NAME(pDataTemp1, __LINE__) = &ERR_VAR_NAME(DataTemp1, __LINE__); \
872 } \
873 else \
874 { \
875 ERR_VAR_NAME(pDataTemp1, __LINE__) = (int32_t*)&(DATA1); \
876 } \
877 int32_t* ERR_VAR_NAME(pDataTemp2, __LINE__); \
878 if(sizeof(DATA2) < 4) \
879 { \
880 int32_t ERR_VAR_NAME(DataTemp2, __LINE__) = DATA2; \
881 ERR_VAR_NAME(pDataTemp2, __LINE__) = &ERR_VAR_NAME(DataTemp2, __LINE__); \
882 } \
883 else \
884 { \
885 ERR_VAR_NAME(pDataTemp2, __LINE__) = (int32_t*)&(DATA2); \
886 } \
887 int32_t* ERR_VAR_NAME(pDataTemp3, __LINE__); \
888 if(sizeof(DATA3) < 4) \
889 { \
890 int32_t ERR_VAR_NAME(DataTemp3, __LINE__) = DATA3; \
891 ERR_VAR_NAME(pDataTemp3, __LINE__) = &ERR_VAR_NAME(DataTemp3, __LINE__); \
892 } \
893 else \
894 { \
895 ERR_VAR_NAME(pDataTemp3, __LINE__) = (int32_t*)&(DATA3); \
896 } \
897 int32_t* ERR_VAR_NAME(pDataTemp4, __LINE__); \
898 if(sizeof(DATA4) < 4) \
899 { \
900 int32_t ERR_VAR_NAME(DataTemp4, __LINE__) = DATA4; \
901 ERR_VAR_NAME(pDataTemp4, __LINE__) = &ERR_VAR_NAME(DataTemp4, __LINE__); \
902 } \
903 else \
904 { \
905 ERR_VAR_NAME(pDataTemp4, __LINE__) = (int32_t*)&(DATA4); \
906 } \
907 _SetErrorX(&g_t##ID, &ERR_VAR_NAME(g_t##ID##Source, __LINE__), *ERR_VAR_NAME(pDataTemp1, __LINE__), \
908 *ERR_VAR_NAME(pDataTemp2, __LINE__), \
909 *ERR_VAR_NAME(pDataTemp3, __LINE__), \
910 *ERR_VAR_NAME(pDataTemp4, __LINE__)); \
911}while(0)
912
913
921#define DefineOnErrorReaction(ERROR_REACTION, NAME, HELP_EN, HELP_DE) \
922ASSERT_REACTION_NAME(NAME); \
923ASSERT_HELP(INCLUDE_HELP_EN(HELP_EN) INCLUDE_HELP_DE(HELP_DE)); \
924static const char ERR_VAR_NAME(g_s##ERROR_REACTION##Name, __LINE__)[] __attribute__((section("error_strings"), used)) = NAME; \
925static const char ERR_VAR_NAME(g_s##ERROR_REACTION##Help, __LINE__)[] __attribute__((section("error_strings"), used)) = \
926ERROR_HELP_TEXT_COMBINE(INCLUDE_HELP_EN("DOC_E " HELP_EN) INCLUDE_HELP_DE("DOC_D " HELP_DE)); \
927const tOnErrorReaction g_t##ERROR_REACTION __attribute__((section("error_reactions"), used)) = { \
928 &ERROR_REACTION, \
929 ERR_VAR_NAME(g_s##ERROR_REACTION##Name, __LINE__), \
930 sizeof(ERR_VAR_NAME(g_s##ERROR_REACTION##Name, __LINE__)) - 1, \
931 ERR_VAR_NAME(g_s##ERROR_REACTION##Help, __LINE__), \
932 sizeof(ERR_VAR_NAME(g_s##ERROR_REACTION##Help, __LINE__)) - 1 \
933};
934
935
940#define DeclareOnErrorReaction(ERROR_REACTION) \
941 const tOnErrorReaction g_t##ERROR_REACTION; \
942 void ERROR_REACTION(void)
943
944
952#define DefineOnErrorResetReaction(ERROR_REACTION, NAME, HELP_EN, HELP_DE) \
953ASSERT_REACTION_NAME(NAME); \
954ASSERT_HELP(INCLUDE_HELP_EN(HELP_EN) INCLUDE_HELP_DE(HELP_DE)); \
955static const char ERR_VAR_NAME(g_s##ERROR_REACTION##Name, __LINE__)[] __attribute__((section("error_strings"), used)) = NAME; \
956static const char ERR_VAR_NAME(g_s##ERROR_REACTION##Help, __LINE__)[] __attribute__((section("error_strings"), used)) = \
957ERROR_HELP_TEXT_COMBINE(INCLUDE_HELP_EN("DOC_E " HELP_EN) INCLUDE_HELP_DE("DOC_D " HELP_DE)); \
958const tOnErrorResetReaction g_t##ERROR_REACTION __attribute__((section("error_reactions"), used)) = { \
959 &ERROR_REACTION, \
960 ERR_VAR_NAME(g_s##ERROR_REACTION##Name, __LINE__), \
961 sizeof(ERR_VAR_NAME(g_s##ERROR_REACTION##Name, __LINE__)) - 1, \
962 ERR_VAR_NAME(g_s##ERROR_REACTION##Help, __LINE__), \
963 sizeof(ERR_VAR_NAME(g_s##ERROR_REACTION##Help, __LINE__)) - 1 \
964};
965
966
971#define DeclareOnErrorResetReaction(ERROR_REACTION) \
972 const tOnErrorResetReaction g_t##ERROR_REACTION; \
973 bool ERROR_REACTION(void)
974
975extern DeclareOnErrorReaction(NoOnErrorReaction);
976extern DeclareOnErrorResetReaction(NoOnErrorResetReaction);
977
978//-----------------------------------------------------------------------------
979// Local data
980//-----------------------------------------------------------------------------
984static const char g_sFileName[] __attribute__((section("error_strings"), used)) = __BASE_FILE__;
985
986//-----------------------------------------------------------------------------
987// global data
988//-----------------------------------------------------------------------------
989extern uint32_t g_u32ErrorPending;
990extern tErrorListItem g_ptErrorList[MAX_NUMBER_OF_ERRORS];
991
992//-----------------------------------------------------------------------------
993// Global function prototypes
994//-----------------------------------------------------------------------------
995void ErrorInit(void);
996tErrorListItem* _SetErrorX(const tError* ptError, const tErrorSource* ptErrorSource, ...);
997void ErrorResetX(uint8_t ui8AccessLevel);
998void ResetErrorIdRange(uint16_t ui16ErrorIdStart, uint16_t ui16ErrorIdEnd, uint8_t ui8AccessLevel);
999void ErrorClear(uint8_t ui8AccessLevel);
1000bool ErrorsPending(void);
1001void MaxFloat(void* DataOld, float DataNew);
1002void MinFloat(void* DataOld, float DataNew);
1003void MaxAbsFloat(void* DataOld, float DataNew);
1004void MaxInt(void* DataOld, int32_t DataNew);
1005void MinInt(void* DataOld, int32_t DataNew);
1006void MaxUInt(void* DataOld, uint32_t DataNew);
1007void MinUInt(void* DataOld, uint32_t DataNew);
1008void NoDataUpdate(void* DataOld, ...);
1009bool IsErrorPending(uint32_t position);
1010bool IsErrorIdPending(uint16_t ui16ErrorId);
1011bool IsErrorIdRangePending(uint16_t ui16ErrorIdStart, uint16_t ui16ErrorIdEnd);
1012uint16_t GetErrorId(uint32_t position);
1013uint32_t PendingErrosSortedByTime(tErrorListItem* pptPendingErrorList[]);
1014
1015#ifdef __cplusplus
1016}
1017#endif
1018#endif //ERROR_h
void(* fpOnErrorX)(void)
Structure used in tError to describe a function to be called on error set.
Definition: Error.h:67
ERROR_FLAGS
Flags used for errors.
Definition: Error.h:56
@ VIEWER_RESET
Can be reset by user with Viewer access level.
Definition: Error.h:57
@ PLC_RESET
Can be reset by the PLC.
Definition: Error.h:61
@ CODE_RESET
Can be reset by the program it-selve e.g. after Init.
Definition: Error.h:62
@ DEVELOPER_RESET
Can be reset by user with Developer access level.
Definition: Error.h:60
@ PROFESSIONAL_RESET
Can be reset by user with Professional access level.
Definition: Error.h:59
@ USER_RESET
Can be reset by user with User access level.
Definition: Error.h:58
@ NV_STORED
Stored in Non-Volatile RAM.
Definition: Error.h:63
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:83
uint16_t void int32_t uint32_t ParameterAccessSource uint8_t ui8AccessLevel
Definition: PARA_Timestamp.c:63
DeclareOnErrorReaction(TestErrorReaction)
Definition of a timestamp type.
Definition: timestamp.h:33
Main error structure.
Definition: Error.h:99
const uint16_t ui16Id
Error-ID.
Definition: Error.h:100
const uint16_t ui16DataCount
Number of attached variables (not byte). See Details on Page Data appended to errors.
Definition: Error.h:101
const uint32_t ui32Flags
Flags from enum ERROR_FLAGS e.g. error reset permissions.
Definition: Error.h:102
const uint32_t ui32HelpLength
Strlen of Help.
Definition: Error.h:106
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:105
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:107
const tOnErrorResetReaction * OnErrorReset
Function to be called on reseting the error. See Page Actions on Error set and reset for details.
Definition: Error.h:108
const uint32_t ui32DescriptionLength
Strlen of Description.
Definition: Error.h:104
const char * Description
Short Description of the error.
Definition: Error.h:103
Structure used in the error stack.
Definition: Error.h:122
Type_Timestamp tTimestampFirst
Time when the error was set the first time.
Definition: Error.h:125
Type_Timestamp tTimestampLast
Time when the error was set the last time.
Definition: Error.h:126
void * Data
Pointer to the attached data the number is stored on ptError. The length is defined in Error-Definiti...
Definition: Error.h:128
const tErrorSource * ptErrorSource
Location of the error in source code.
Definition: Error.h:124
const tError * ptError
Pointer to the error itself.
Definition: Error.h:123
uint32_t ui32ErrorCount
Number of occurrences. Starts with 1 and increments on every occurence.
Definition: Error.h:127
Structure used in tError holding source-code file an line.
Definition: Error.h:113
const uint32_t ui32Line
Source-code line.
Definition: Error.h:114
const char * File
Source-code filename and path.
Definition: Error.h:115
const uint32_t ui32FileLength
Strlen of filename.
Definition: Error.h:116
The error reaction is called on occurence of the error.
Definition: Error.h:73
const uint32_t ui32HelpSize
StrLen of Help.
Definition: Error.h:78
const fpOnErrorX fpErrorReaction
Function to be called.
Definition: Error.h:74
const char * cHelp
Help Text. See Page Help-texts in Errors for details.
Definition: Error.h:77
const char * cName
Name of the Function.
Definition: Error.h:75
const uint32_t ui32NameSize
StrLen of Name.
Definition: Error.h:76
The error reset reaction is called on reset of the error.
Definition: Error.h:89
const fpOnErrorResetX fpErrorReaction
Function to be called.
Definition: Error.h:90
const uint32_t ui32HelpSize
StrLen of Help.
Definition: Error.h:94
const char * cHelp
Help Text. See Page Help-texts in Errors for details.
Definition: Error.h:93
const char * cName
Name of the Function.
Definition: Error.h:91
const uint32_t ui32NameSize
StrLen of Name.
Definition: Error.h:92
Definition of timestamp data-structs.