ErrorLib 1.0.8-master SHA: 810228da25
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//-----------------------------------------------------------------------------
24// Defines
25//-----------------------------------------------------------------------------
26#if __STDC_VERSION__ >= 201112L && ! defined __cplusplus
27 #include <assert.h>
28#else
29 #define static_assert _Static_assert
30#endif
31
33#define MAX_NUMBER_OF_ERRORS 30
34
36#define MIN_ERR_REACTION_NAME_LENTH 10
38#define MIN_DESCRIPTION_LENTH 10
40#define MIN_HELP_LENTH 20
41
43#define ERROR_STACK_OVERFLOW 0x80000000
44
46#define ERROR_SYSTEM_VERSION 2
47
48extern uint32_t g_u32ErrorPending;
49
53{
58 PLC_RESET = 16,
60 NV_STORED = 64
61};
62
64typedef void (*fpOnErrorX)(void);
65
69typedef struct
70{
72 const char* cName;
73 const uint32_t ui32NameSize;
74 const char* cHelp;
75 const uint32_t ui32HelpSize;
77
80typedef bool (*fpOnErrorResetX)(void);
81
85typedef struct
86{
88 const char* cName;
89 const uint32_t ui32NameSize;
90 const char* cHelp;
91 const uint32_t ui32HelpSize;
93
95typedef struct
96{
97 const uint16_t ui16Id;
98 const uint16_t ui16DataCount;
99 const uint32_t ui32Flags;
100 const char* Description;
101 const uint32_t ui32DescriptionLength;
102 const char* Help;
103 const uint32_t ui32HelpLength;
106}tError;
107
109typedef struct
110{
111 const uint32_t ui32Line;
112 const char* File;
113 const uint32_t ui32FileLength;
115
116
118typedef struct
119{
124 uint32_t ui32ErrorCount;
125 void* Data;
127
129#define ERR_VAR_NAME_SRT(x, y) x ## y
131#define ERR_VAR_NAME(x, y) ERR_VAR_NAME_SRT(x, y)
132
134#define xstr(s) str(s)
136#define str(s) #s
137
139#define ASSERT_REACTION_NAME(NAME) static_assert(sizeof(NAME) > MIN_ERR_REACTION_NAME_LENTH, \
140"Error reaction name to short must be at least "xstr(MIN_ERR_REACTION_NAME_LENTH)" characters long!") \
141
143#define ASSERT_DESCRIPTION(DESCRIPTION) static_assert(sizeof(DESCRIPTION) > MIN_DESCRIPTION_LENTH, \
144"Error description text to short must be at least "xstr(MIN_DESCRIPTION_LENTH)" characters long!") \
145
147#define ASSERT_HELP(HELP) static_assert(sizeof(HELP) > MIN_HELP_LENTH, \
148"Error help text to short must be at least "xstr(MIN_HELP_LENTH)" characters long!") \
149
150
151
161#define DefineError(ID, PERMISSION, ON_ERROR, ON_ERROR_RESET, DESCRIPTION, HELP) \
162 ASSERT_DESCRIPTION(DESCRIPTION); \
163 ASSERT_HELP(HELP); \
164 static const char g_s##ID##Description[] __attribute__((section("error_strings"), used)) = DESCRIPTION; \
165 static const char g_s##ID##Help[] __attribute__((section("error_strings"), used)) = HELP; \
166 \
167 const tError g_t##ID __attribute__((section("error_descriptor"), used)) = { \
168 ID, \
169 0, \
170 PERMISSION, \
171 g_s##ID##Description, \
172 sizeof(DESCRIPTION) - 1, \
173 g_s##ID##Help, \
174 sizeof(HELP) - 1, \
175 &g_t##ON_ERROR, \
176 &g_t##ON_ERROR_RESET, \
177 }
178
179
190#define DefineErrorData(ID, PERMISSION, ON_ERROR, ON_ERROR_RESET, DESCRIPTION, HELP, DATA_COUNT) \
191 ASSERT_DESCRIPTION(DESCRIPTION); \
192 ASSERT_HELP(HELP); \
193 static const char g_s##ID##Description[] __attribute__((section("error_strings"), used)) = DESCRIPTION; \
194 static const char g_s##ID##Help[] __attribute__((section("error_strings"), used)) = HELP; \
195 \
196 const tError g_t##ID __attribute__((section("error_descriptor"), used)) = { \
197 ID, \
198 DATA_COUNT, \
199 PERMISSION, \
200 g_s##ID##Description, \
201 sizeof(DESCRIPTION) - 1, \
202 g_s##ID##Help, \
203 sizeof(HELP) - 1, \
204 &g_t##ON_ERROR, \
205 &g_t##ON_ERROR_RESET, \
206 }
207
208
213#define DeclareError(ID) const tError g_t##ID
214
215
225#define SetError(ID, PERMISSION, ON_ERROR, ON_ERROR_RESET, DESCRIPTION, HELP) \
226do \
227{ \
228 ASSERT_DESCRIPTION(DESCRIPTION); \
229 ASSERT_HELP(HELP); \
230 static const char g_s##ID##Description[] __attribute__((section("error_strings"), used)) = DESCRIPTION; \
231 static const char g_s##ID##Help[] __attribute__((section("error_strings"), used)) = HELP; \
232 static const tErrorSource g_t##ID##Source __attribute__((section("error_sources"), used)) = { \
233 __LINE__, \
234 g_sFileName, \
235 sizeof(g_sFileName) - 1 \
236 }; \
237 \
238 static const tError g_t##ID __attribute__((section("error_descriptor"), used)) = { \
239 ID, \
240 0, \
241 PERMISSION, \
242 g_s##ID##Description, \
243 sizeof(DESCRIPTION) - 1, \
244 g_s##ID##Help, \
245 sizeof(HELP) - 1, \
246 &g_t##ON_ERROR, \
247 &g_t##ON_ERROR_RESET, \
248 }; \
249 _SetErrorX(&g_t##ID, &g_t##ID##Source); \
250}while(0)
251
252
263#define SetErrorSource(ID, PERMISSION, ON_ERROR, ON_ERROR_RESET, DESCRIPTION, HELP, SOURCE) \
264do \
265{ \
266 ASSERT_DESCRIPTION(DESCRIPTION); \
267 ASSERT_HELP(HELP); \
268 static const char g_s##ID##Description[] __attribute__((section("error_strings"), used)) = DESCRIPTION; \
269 static const char g_s##ID##Help[] __attribute__((section("error_strings"), used)) = HELP; \
270 \
271 static const tError g_t##ID __attribute__((section("error_descriptor"), used)) = { \
272 ID, \
273 0, \
274 PERMISSION, \
275 g_s##ID##Description, \
276 sizeof(DESCRIPTION) - 1, \
277 g_s##ID##Help, \
278 sizeof(HELP) - 1, \
279 &g_t##ON_ERROR, \
280 &g_t##ON_ERROR_RESET, \
281 }; \
282 _SetErrorX(&g_t##ID, SOURCE); \
283}while(0)
284
285
296#define SetErrorData1(ID, PERMISSION, ON_ERROR, ON_ERROR_RESET, DESCRIPTION, HELP, DATA1) \
297do \
298{ \
299 ASSERT_DESCRIPTION(DESCRIPTION); \
300 ASSERT_HELP(HELP); \
301 static const char g_s##ID##Description[] __attribute__((section("error_strings"), used)) = DESCRIPTION; \
302 static const char g_s##ID##Help[] __attribute__((section("error_strings"), used)) = HELP; \
303 static const tErrorSource g_t##ID##Source __attribute__((section("error_sources"), used)) = { \
304 __LINE__, \
305 g_sFileName, \
306 sizeof(g_sFileName) - 1 \
307 }; \
308 \
309 static const tError g_t##ID __attribute__((section("error_descriptor"), used)) = { \
310 ID, \
311 1, \
312 PERMISSION, \
313 g_s##ID##Description, \
314 sizeof(DESCRIPTION) - 1, \
315 g_s##ID##Help, \
316 sizeof(HELP) - 1, \
317 &g_t##ON_ERROR, \
318 &g_t##ON_ERROR_RESET, \
319 }; \
320 if(sizeof(DATA1) < 4) \
321 { \
322 int32_t ERR_VAR_NAME(DataTemp, __LINE__) = DATA1; \
323 _SetErrorX(&g_t##ID, &g_t##ID##Source, ERR_VAR_NAME(DataTemp, __LINE__)); \
324 } \
325 else \
326 { \
327 _SetErrorX(&g_t##ID, &g_t##ID##Source, *(uint32_t*)&DATA1); \
328 } \
329}while(0)
330
331
345#define SetErrorData1Compare(ID, PERMISSION, ON_ERROR, ON_ERROR_RESET, DESCRIPTION, HELP, DATA1, COMPARE1) \
346do \
347{ \
348 ASSERT_DESCRIPTION(DESCRIPTION); \
349 ASSERT_HELP(HELP); \
350 static const char g_s##ID##Description[] __attribute__((section("error_strings"), used)) = DESCRIPTION; \
351 static const char g_s##ID##Help[] __attribute__((section("error_strings"), used)) = HELP; \
352 static const tErrorSource g_t##ID##Source __attribute__((section("error_sources"), used)) = { \
353 __LINE__, \
354 g_sFileName, \
355 sizeof(g_sFileName) - 1 \
356 }; \
357 \
358 static const tError g_t##ID __attribute__((section("error_descriptor"), used)) = { \
359 ID, \
360 1, \
361 PERMISSION, \
362 g_s##ID##Description, \
363 sizeof(DESCRIPTION) - 1, \
364 g_s##ID##Help, \
365 sizeof(HELP) - 1, \
366 &g_t##ON_ERROR, \
367 &g_t##ON_ERROR_RESET, \
368 }; \
369 \
370 tErrorListItem* ERR_VAR_NAME(ptError, __LINE__); \
371 if(sizeof(DATA1) < 4) \
372 { \
373 int32_t ERR_VAR_NAME(DataTemp, __LINE__) = DATA1; \
374 ERR_VAR_NAME(ptError, __LINE__) = _SetErrorX(&g_t##ID, &g_t##ID##Source, ERR_VAR_NAME(DataTemp, __LINE__)); \
375 } \
376 else \
377 { \
378 ERR_VAR_NAME(ptError, __LINE__) = _SetErrorX(&g_t##ID, &g_t##ID##Source, *(uint32_t*)&DATA1); \
379 } \
380 COMPARE1(ERR_VAR_NAME(ptError, __LINE__)->Data, DATA1); \
381}while(0)
382
383
395#define SetErrorData2(ID, PERMISSION, ON_ERROR, ON_ERROR_RESET, DESCRIPTION, HELP, DATA1, DATA2) \
396do \
397{ \
398 ASSERT_DESCRIPTION(DESCRIPTION); \
399 ASSERT_HELP(HELP); \
400 static const char g_s##ID##Description[] __attribute__((section("error_strings"), used)) = DESCRIPTION; \
401 static const char g_s##ID##Help[] __attribute__((section("error_strings"), used)) = HELP; \
402 static const tErrorSource g_t##ID##Source __attribute__((section("error_sources"), used)) = { \
403 __LINE__, \
404 g_sFileName, \
405 sizeof(g_sFileName) - 1 \
406 }; \
407 \
408 static const tError g_t##ID __attribute__((section("error_descriptor"), used)) = { \
409 ID, \
410 2, \
411 PERMISSION, \
412 g_s##ID##Description, \
413 sizeof(DESCRIPTION) - 1, \
414 g_s##ID##Help, \
415 sizeof(HELP) - 1, \
416 &g_t##ON_ERROR, \
417 &g_t##ON_ERROR_RESET, \
418 }; \
419 \
420 int32_t* ERR_VAR_NAME(pDataTemp1, __LINE__); \
421 if(sizeof(DATA1) < 4) \
422 { \
423 int32_t ERR_VAR_NAME(DataTemp1, __LINE__) = DATA1; \
424 ERR_VAR_NAME(pDataTemp1, __LINE__) = &ERR_VAR_NAME(DataTemp1, __LINE__); \
425 } \
426 else \
427 { \
428 ERR_VAR_NAME(pDataTemp1, __LINE__) = (int32_t*)&(DATA1); \
429 } \
430 int32_t* ERR_VAR_NAME(pDataTemp2, __LINE__); \
431 if(sizeof(DATA2) < 4) \
432 { \
433 int32_t ERR_VAR_NAME(DataTemp2, __LINE__) = DATA2; \
434 ERR_VAR_NAME(pDataTemp2, __LINE__) = &ERR_VAR_NAME(DataTemp2, __LINE__); \
435 } \
436 else \
437 { \
438 ERR_VAR_NAME(pDataTemp2, __LINE__) = (int32_t*)&(DATA2); \
439 } \
440 _SetErrorX(&g_t##ID, &g_t##ID##Source, *ERR_VAR_NAME(pDataTemp1, __LINE__), *ERR_VAR_NAME(pDataTemp2, __LINE__)); \
441}while(0)
442
443
459#define SetErrorData2Compare(ID, PERMISSION, ON_ERROR, ON_ERROR_RESET, DESCRIPTION, HELP, DATA1, COMPARE1, DATA2, COMPARE2) \
460do \
461{ \
462 ASSERT_DESCRIPTION(DESCRIPTION); \
463 ASSERT_HELP(HELP); \
464 static const char g_s##ID##Description[] __attribute__((section("error_strings"), used)) = DESCRIPTION; \
465 static const char g_s##ID##Help[] __attribute__((section("error_strings"), used)) = HELP; \
466 static const tErrorSource g_t##ID##Source __attribute__((section("error_sources"), used)) = { \
467 __LINE__, \
468 g_sFileName, \
469 sizeof(g_sFileName) - 1 \
470 }; \
471 \
472 static const tError g_t##ID __attribute__((section("error_descriptor"), used)) = { \
473 ID, \
474 2, \
475 PERMISSION, \
476 g_s##ID##Description, \
477 sizeof(DESCRIPTION) - 1, \
478 g_s##ID##Help, \
479 sizeof(HELP) - 1, \
480 &g_t##ON_ERROR, \
481 &g_t##ON_ERROR_RESET, \
482 }; \
483 \
484 int32_t* ERR_VAR_NAME(pDataTemp1, __LINE__); \
485 if(sizeof(DATA1) < 4) \
486 { \
487 int32_t ERR_VAR_NAME(DataTemp1, __LINE__) = DATA1; \
488 ERR_VAR_NAME(pDataTemp1, __LINE__) = &ERR_VAR_NAME(DataTemp1, __LINE__); \
489 } \
490 else \
491 { \
492 ERR_VAR_NAME(pDataTemp1, __LINE__) = (int32_t*)&(DATA1); \
493 } \
494 int32_t* ERR_VAR_NAME(pDataTemp2, __LINE__); \
495 if(sizeof(DATA2) < 4) \
496 { \
497 int32_t ERR_VAR_NAME(DataTemp2, __LINE__) = DATA2; \
498 ERR_VAR_NAME(pDataTemp2, __LINE__) = &ERR_VAR_NAME(DataTemp2, __LINE__); \
499 } \
500 else \
501 { \
502 ERR_VAR_NAME(pDataTemp2, __LINE__) = (int32_t*)&(DATA2); \
503 } \
504 tErrorListItem* ERR_VAR_NAME(ptError, __LINE__) = _SetErrorX(&g_t##ID, &g_t##ID##Source, *ERR_VAR_NAME(pDataTemp1, __LINE__), \
505 *ERR_VAR_NAME(pDataTemp2, __LINE__)); \
506 if((ERR_VAR_NAME(ptError, __LINE__) != 0) && (ERR_VAR_NAME(ptError, __LINE__)->Data != 0)) \
507 { \
508 COMPARE1(ERR_VAR_NAME(ptError, __LINE__)->Data, DATA1); \
509 COMPARE2(ERR_VAR_NAME(ptError, __LINE__)->Data + 4, DATA2); \
510 } \
511}while(0)
512
513
526#define SetErrorData3(ID, PERMISSION, ON_ERROR, ON_ERROR_RESET, DESCRIPTION, HELP, DATA1, DATA2, DATA3) \
527do \
528{ \
529 ASSERT_DESCRIPTION(DESCRIPTION); \
530 ASSERT_HELP(HELP); \
531 static const char g_s##ID##Description[] __attribute__((section("error_strings"), used)) = DESCRIPTION; \
532 static const char g_s##ID##Help[] __attribute__((section("error_strings"), used)) = HELP; \
533 static const tErrorSource g_t##ID##Source __attribute__((section("error_sources"), used)) = { \
534 __LINE__, \
535 g_sFileName, \
536 sizeof(g_sFileName) - 1 \
537 }; \
538 \
539 static const tError g_t##ID __attribute__((section("error_descriptor"), used)) = { \
540 ID, \
541 3, \
542 PERMISSION, \
543 g_s##ID##Description, \
544 sizeof(DESCRIPTION) - 1, \
545 g_s##ID##Help, \
546 sizeof(HELP) - 1, \
547 &g_t##ON_ERROR, \
548 &g_t##ON_ERROR_RESET, \
549 }; \
550 \
551 int32_t* ERR_VAR_NAME(pDataTemp1, __LINE__); \
552 if(sizeof(DATA1) < 4) \
553 { \
554 int32_t ERR_VAR_NAME(DataTemp1, __LINE__) = DATA1; \
555 ERR_VAR_NAME(pDataTemp1, __LINE__) = &ERR_VAR_NAME(DataTemp1, __LINE__); \
556 } \
557 else \
558 { \
559 ERR_VAR_NAME(pDataTemp1, __LINE__) = (int32_t*)&(DATA1); \
560 } \
561 int32_t* ERR_VAR_NAME(pDataTemp2, __LINE__); \
562 if(sizeof(DATA2) < 4) \
563 { \
564 int32_t ERR_VAR_NAME(DataTemp2, __LINE__) = DATA2; \
565 ERR_VAR_NAME(pDataTemp2, __LINE__) = &ERR_VAR_NAME(DataTemp2, __LINE__); \
566 } \
567 else \
568 { \
569 ERR_VAR_NAME(pDataTemp2, __LINE__) = (int32_t*)&(DATA2); \
570 } \
571 int32_t* ERR_VAR_NAME(pDataTemp3, __LINE__); \
572 if(sizeof(DATA3) < 4) \
573 { \
574 int32_t ERR_VAR_NAME(DataTemp3, __LINE__) = DATA3; \
575 ERR_VAR_NAME(pDataTemp3, __LINE__) = &ERR_VAR_NAME(DataTemp3, __LINE__); \
576 } \
577 else \
578 { \
579 ERR_VAR_NAME(pDataTemp3, __LINE__) = (int32_t*)&(DATA3); \
580 } \
581 _SetErrorX(&g_t##ID, &g_t##ID##Source, *ERR_VAR_NAME(pDataTemp1, __LINE__), *ERR_VAR_NAME(pDataTemp2, __LINE__), \
582 *ERR_VAR_NAME(pDataTemp3, __LINE__)); \
583}while(0)
584
585
599#define SetErrorData4(ID, PERMISSION, ON_ERROR, ON_ERROR_RESET, DESCRIPTION, HELP, DATA1, DATA2, DATA3, DATA4) \
600do \
601{ \
602 ASSERT_DESCRIPTION(DESCRIPTION); \
603 ASSERT_HELP(HELP); \
604 static const char g_s##ID##Description[] __attribute__((section("error_strings"), used)) = DESCRIPTION; \
605 static const char g_s##ID##Help[] __attribute__((section("error_strings"), used)) = HELP; \
606 static const tErrorSource g_t##ID##Source __attribute__((section("error_sources"), used)) = { \
607 __LINE__, \
608 g_sFileName, \
609 sizeof(g_sFileName) - 1 \
610 }; \
611 \
612 static const tError g_t##ID __attribute__((section("error_descriptor"), used)) = { \
613 ID, \
614 4, \
615 PERMISSION, \
616 g_s##ID##Description, \
617 sizeof(DESCRIPTION) - 1, \
618 g_s##ID##Help, \
619 sizeof(HELP) - 1, \
620 &g_t##ON_ERROR, \
621 &g_t##ON_ERROR_RESET, \
622 }; \
623 \
624 int32_t* ERR_VAR_NAME(pDataTemp1, __LINE__); \
625 if(sizeof(DATA1) < 4) \
626 { \
627 int32_t ERR_VAR_NAME(DataTemp1, __LINE__) = DATA1; \
628 ERR_VAR_NAME(pDataTemp1, __LINE__) = &ERR_VAR_NAME(DataTemp1, __LINE__); \
629 } \
630 else \
631 { \
632 ERR_VAR_NAME(pDataTemp1, __LINE__) = (int32_t*)&(DATA1); \
633 } \
634 int32_t* ERR_VAR_NAME(pDataTemp2, __LINE__); \
635 if(sizeof(DATA2) < 4) \
636 { \
637 int32_t ERR_VAR_NAME(DataTemp2, __LINE__) = DATA2; \
638 ERR_VAR_NAME(pDataTemp2, __LINE__) = &ERR_VAR_NAME(DataTemp2, __LINE__); \
639 } \
640 else \
641 { \
642 ERR_VAR_NAME(pDataTemp2, __LINE__) = (int32_t*)&(DATA2); \
643 } \
644 int32_t* ERR_VAR_NAME(pDataTemp3, __LINE__); \
645 if(sizeof(DATA3) < 4) \
646 { \
647 int32_t ERR_VAR_NAME(DataTemp3, __LINE__) = DATA3; \
648 ERR_VAR_NAME(pDataTemp3, __LINE__) = &ERR_VAR_NAME(DataTemp3, __LINE__); \
649 } \
650 else \
651 { \
652 ERR_VAR_NAME(pDataTemp3, __LINE__) = (int32_t*)&(DATA3); \
653 } \
654 int32_t* ERR_VAR_NAME(pDataTemp4, __LINE__); \
655 if(sizeof(DATA4) < 4) \
656 { \
657 int32_t ERR_VAR_NAME(DataTemp4, __LINE__) = DATA4; \
658 ERR_VAR_NAME(pDataTemp4, __LINE__) = &ERR_VAR_NAME(DataTemp4, __LINE__); \
659 } \
660 else \
661 { \
662 ERR_VAR_NAME(pDataTemp4, __LINE__) = (int32_t*)&(DATA4); \
663 } \
664 _SetErrorX(&g_t##ID, &g_t##ID##Source, *ERR_VAR_NAME(pDataTemp1, __LINE__), *ERR_VAR_NAME(pDataTemp2, __LINE__), \
665 *ERR_VAR_NAME(pDataTemp3, __LINE__), *ERR_VAR_NAME(pDataTemp4, __LINE__)); \
666}while(0)
667
668
672#define SetErrorId(ID) \
673do \
674{ \
675 static const tErrorSource ERR_VAR_NAME(g_t##ID##Source, __LINE__) __attribute__((section("error_sources"), used)) = { \
676 __LINE__, \
677 g_sFileName, \
678 sizeof(g_sFileName) - 1 \
679 }; \
680 \
681 _SetErrorX(&g_t##ID, &ERR_VAR_NAME(g_t##ID##Source, __LINE__)); \
682}while(0)
683
684
689#define SetErrorIdData1(ID, DATA1) \
690do \
691{ \
692 static const tErrorSource ERR_VAR_NAME(g_t##ID##Source, __LINE__) __attribute__((section("error_sources"), used)) = { \
693 __LINE__, \
694 g_sFileName, \
695 sizeof(g_sFileName) - 1 \
696 }; \
697 \
698 if(sizeof(DATA1) < 4) \
699 { \
700 int32_t ERR_VAR_NAME(DataTemp, __LINE__) = DATA1; \
701 _SetErrorX(&g_t##ID, &ERR_VAR_NAME(g_t##ID##Source, __LINE__), ERR_VAR_NAME(DataTemp, __LINE__)); \
702 } \
703 else \
704 { \
705 _SetErrorX(&g_t##ID, &ERR_VAR_NAME(g_t##ID##Source, __LINE__), DATA1); \
706 } \
707}while(0)
708
709
715#define SetErrorIdData2(ID, DATA1, DATA2) \
716do \
717{ \
718 static const tErrorSource ERR_VAR_NAME(g_t##ID##Source, __LINE__) __attribute__((section("error_sources"), used)) = { \
719 __LINE__, \
720 g_sFileName, \
721 sizeof(g_sFileName) - 1 \
722 }; \
723 \
724 int32_t* ERR_VAR_NAME(pDataTemp1, __LINE__); \
725 if(sizeof(DATA1) < 4) \
726 { \
727 int32_t ERR_VAR_NAME(DataTemp1, __LINE__) = DATA1; \
728 ERR_VAR_NAME(pDataTemp1, __LINE__) = &ERR_VAR_NAME(DataTemp1, __LINE__); \
729 } \
730 else \
731 { \
732 ERR_VAR_NAME(pDataTemp1, __LINE__) = (int32_t*)&(DATA1); \
733 } \
734 int32_t* ERR_VAR_NAME(pDataTemp2, __LINE__); \
735 if(sizeof(DATA2) < 4) \
736 { \
737 int32_t ERR_VAR_NAME(DataTemp2, __LINE__) = DATA2; \
738 ERR_VAR_NAME(pDataTemp2, __LINE__) = &ERR_VAR_NAME(DataTemp2, __LINE__); \
739 } \
740 else \
741 { \
742 ERR_VAR_NAME(pDataTemp2, __LINE__) = (int32_t*)&(DATA2); \
743 } \
744 _SetErrorX(&g_t##ID, &ERR_VAR_NAME(g_t##ID##Source, __LINE__), *ERR_VAR_NAME(pDataTemp1, __LINE__), \
745 *ERR_VAR_NAME(pDataTemp2, __LINE__)); \
746}while(0)
747
748
755#define SetErrorIdData3(ID, DATA1, DATA2, DATA3) \
756do \
757{ \
758 static const tErrorSource ERR_VAR_NAME(g_t##ID##Source, __LINE__) __attribute__((section("error_sources"), used)) = { \
759 __LINE__, \
760 g_sFileName, \
761 sizeof(g_sFileName) - 1 \
762 }; \
763 \
764 int32_t* ERR_VAR_NAME(pDataTemp1, __LINE__); \
765 if(sizeof(DATA1) < 4) \
766 { \
767 int32_t ERR_VAR_NAME(DataTemp1, __LINE__) = DATA1; \
768 ERR_VAR_NAME(pDataTemp1, __LINE__) = &ERR_VAR_NAME(DataTemp1, __LINE__); \
769 } \
770 else \
771 { \
772 ERR_VAR_NAME(pDataTemp1, __LINE__) = (int32_t*)&(DATA1); \
773 } \
774 int32_t* ERR_VAR_NAME(pDataTemp2, __LINE__); \
775 if(sizeof(DATA2) < 4) \
776 { \
777 int32_t ERR_VAR_NAME(DataTemp2, __LINE__) = DATA2; \
778 ERR_VAR_NAME(pDataTemp2, __LINE__) = &ERR_VAR_NAME(DataTemp2, __LINE__); \
779 } \
780 else \
781 { \
782 ERR_VAR_NAME(pDataTemp2, __LINE__) = (int32_t*)&(DATA2); \
783 } \
784 int32_t* ERR_VAR_NAME(pDataTemp3, __LINE__); \
785 if(sizeof(DATA3) < 4) \
786 { \
787 int32_t ERR_VAR_NAME(DataTemp3, __LINE__) = DATA3; \
788 ERR_VAR_NAME(pDataTemp3, __LINE__) = &ERR_VAR_NAME(DataTemp3, __LINE__); \
789 } \
790 else \
791 { \
792 ERR_VAR_NAME(pDataTemp3, __LINE__) = (int32_t*)&(DATA3); \
793 } \
794 _SetErrorX(&g_t##ID, &ERR_VAR_NAME(g_t##ID##Source, __LINE__), *ERR_VAR_NAME(pDataTemp1, __LINE__), \
795 *ERR_VAR_NAME(pDataTemp2, __LINE__), \
796 *ERR_VAR_NAME(pDataTemp3, __LINE__)); \
797}while(0)
798
799
807#define SetErrorIdData4(ID, DATA1, DATA2, DATA3, DATA4) \
808do \
809{ \
810 static const tErrorSource ERR_VAR_NAME(g_t##ID##Source, __LINE__) __attribute__((section("error_sources"), used)) = { \
811 __LINE__, \
812 g_sFileName, \
813 sizeof(g_sFileName) - 1 \
814 }; \
815 \
816 int32_t* ERR_VAR_NAME(pDataTemp1, __LINE__); \
817 if(sizeof(DATA1) < 4) \
818 { \
819 int32_t ERR_VAR_NAME(DataTemp1, __LINE__) = DATA1; \
820 ERR_VAR_NAME(pDataTemp1, __LINE__) = &ERR_VAR_NAME(DataTemp1, __LINE__); \
821 } \
822 else \
823 { \
824 ERR_VAR_NAME(pDataTemp1, __LINE__) = (int32_t*)&(DATA1); \
825 } \
826 int32_t* ERR_VAR_NAME(pDataTemp2, __LINE__); \
827 if(sizeof(DATA2) < 4) \
828 { \
829 int32_t ERR_VAR_NAME(DataTemp2, __LINE__) = DATA2; \
830 ERR_VAR_NAME(pDataTemp2, __LINE__) = &ERR_VAR_NAME(DataTemp2, __LINE__); \
831 } \
832 else \
833 { \
834 ERR_VAR_NAME(pDataTemp2, __LINE__) = (int32_t*)&(DATA2); \
835 } \
836 int32_t* ERR_VAR_NAME(pDataTemp3, __LINE__); \
837 if(sizeof(DATA3) < 4) \
838 { \
839 int32_t ERR_VAR_NAME(DataTemp3, __LINE__) = DATA3; \
840 ERR_VAR_NAME(pDataTemp3, __LINE__) = &ERR_VAR_NAME(DataTemp3, __LINE__); \
841 } \
842 else \
843 { \
844 ERR_VAR_NAME(pDataTemp3, __LINE__) = (int32_t*)&(DATA3); \
845 } \
846 int32_t* ERR_VAR_NAME(pDataTemp4, __LINE__); \
847 if(sizeof(DATA4) < 4) \
848 { \
849 int32_t ERR_VAR_NAME(DataTemp4, __LINE__) = DATA4; \
850 ERR_VAR_NAME(pDataTemp4, __LINE__) = &ERR_VAR_NAME(DataTemp4, __LINE__); \
851 } \
852 else \
853 { \
854 ERR_VAR_NAME(pDataTemp4, __LINE__) = (int32_t*)&(DATA4); \
855 } \
856 _SetErrorX(&g_t##ID, &ERR_VAR_NAME(g_t##ID##Source, __LINE__), *ERR_VAR_NAME(pDataTemp1, __LINE__), \
857 *ERR_VAR_NAME(pDataTemp2, __LINE__), \
858 *ERR_VAR_NAME(pDataTemp3, __LINE__), \
859 *ERR_VAR_NAME(pDataTemp4, __LINE__)); \
860}while(0)
861
862
869#define DefineOnErrorReaction(ERROR_REACTION, NAME, HELP) \
870ASSERT_REACTION_NAME(NAME); \
871ASSERT_HELP(HELP); \
872static const char ERR_VAR_NAME(g_s##ERROR_REACTION##Name, __LINE__)[] __attribute__((section("error_strings"), used)) = NAME; \
873static const char ERR_VAR_NAME(g_s##ERROR_REACTION##Help, __LINE__)[] __attribute__((section("error_strings"), used)) = HELP; \
874const tOnErrorReaction g_t##ERROR_REACTION __attribute__((section("error_reactions"), used)) = { \
875 &ERROR_REACTION, \
876 ERR_VAR_NAME(g_s##ERROR_REACTION##Name, __LINE__), \
877 sizeof(ERR_VAR_NAME(g_s##ERROR_REACTION##Name, __LINE__)) - 1, \
878 ERR_VAR_NAME(g_s##ERROR_REACTION##Help, __LINE__), \
879 sizeof(ERR_VAR_NAME(g_s##ERROR_REACTION##Help, __LINE__)) - 1 \
880};
881
882
887#define DeclareOnErrorReaction(ERROR_REACTION) \
888 const tOnErrorReaction g_t##ERROR_REACTION; \
889 void ERROR_REACTION(void)
890
891
898#define DefineOnErrorResetReaction(ERROR_REACTION, NAME, HELP) \
899ASSERT_REACTION_NAME(NAME); \
900ASSERT_HELP(HELP); \
901static const char ERR_VAR_NAME(g_s##ERROR_REACTION##Name, __LINE__)[] __attribute__((section("error_strings"), used)) = NAME; \
902static const char ERR_VAR_NAME(g_s##ERROR_REACTION##Help, __LINE__)[] __attribute__((section("error_strings"), used)) = HELP; \
903const tOnErrorResetReaction g_t##ERROR_REACTION __attribute__((section("error_reactions"), used)) = { \
904 &ERROR_REACTION, \
905 ERR_VAR_NAME(g_s##ERROR_REACTION##Name, __LINE__), \
906 sizeof(ERR_VAR_NAME(g_s##ERROR_REACTION##Name, __LINE__)) - 1, \
907 ERR_VAR_NAME(g_s##ERROR_REACTION##Help, __LINE__), \
908 sizeof(ERR_VAR_NAME(g_s##ERROR_REACTION##Help, __LINE__)) - 1 \
909};
910
911
916#define DeclareOnErrorResetReaction(ERROR_REACTION) \
917 const tOnErrorResetReaction g_t##ERROR_REACTION; \
918 bool ERROR_REACTION(void)
919
922
923//-----------------------------------------------------------------------------
924// Local data
925//-----------------------------------------------------------------------------
929static const char g_sFileName[] __attribute__((section("error_strings"), used)) = __BASE_FILE__;
930
931//-----------------------------------------------------------------------------
932// global data
933//-----------------------------------------------------------------------------
934extern uint32_t g_u32ErrorPending;
936
937//-----------------------------------------------------------------------------
938// Global function prototypes
939//-----------------------------------------------------------------------------
940void ErrorInit(void);
941tErrorListItem* _SetErrorX(const tError* ptError, const tErrorSource* ptErrorSource, ...);
942void ErrorResetX(uint8_t ui8AccessLevel);
943void ResetErrorIdRange(uint16_t ui16ErrorIdStart, uint16_t ui16ErrorIdEnd, uint8_t ui8AccessLevel);
944void ErrorClear(uint8_t ui8AccessLevel);
945bool ErrorsPending(void);
946void MaxFloat(void* DataOld, float DataNew);
947void MinFloat(void* DataOld, float DataNew);
948void MaxAbsFloat(void* DataOld, float DataNew);
949void MaxInt(void* DataOld, int32_t DataNew);
950void MinInt(void* DataOld, int32_t DataNew);
951void MaxUInt(void* DataOld, uint32_t DataNew);
952void MinUInt(void* DataOld, uint32_t DataNew);
953void NoDataUpdate(void* DataOld, ...);
954bool IsErrorPending(uint32_t position);
955uint16_t GetErrorId(uint32_t position);
956uint32_t PendingErrosSortedByTime(tErrorListItem* pptPendingErrorList[]);
957
958#endif //ERROR_h
uint32_t PendingErrosSortedByTime(tErrorListItem *pptPendingErrorList[])
Get an array of the pending Errors sorted by tTimestampFirst.
Definition: Error.c:816
void MaxInt(void *DataOld, int32_t DataNew)
Update the atatched data if new value is higher.
Definition: Error.c:701
void ErrorInit(void)
Inits the Error Stack with 0.
Definition: Error.c:763
void MaxUInt(void *DataOld, uint32_t DataNew)
Update the atatched data if new value is higher.
Definition: Error.c:723
static const char g_sFileName[]
The filename for all Errors within a module.
Definition: Error.h:929
tErrorListItem g_ptErrorList[30]
This array contains the error stack.
Definition: Error.c:283
void MinUInt(void *DataOld, uint32_t DataNew)
Update the atatched data if new value is lower.
Definition: Error.c:734
void MaxAbsFloat(void *DataOld, float DataNew)
Update the atatched data if new value abs is higher.
Definition: Error.c:690
void MinInt(void *DataOld, int32_t DataNew)
Update the atatched data if new value is lower.
Definition: Error.c:712
void MaxFloat(void *DataOld, float DataNew)
Update the atached data if new value is higher.
Definition: Error.c:668
uint16_t GetErrorId(uint32_t position)
Get Error ID of the Error on a specified Position.
Definition: Error.c:789
void MinFloat(void *DataOld, float DataNew)
Update the atatched data if new value is lower.
Definition: Error.c:679
void ErrorResetX(uint8_t ui8AccessLevel)
Resets all pending errors if access level is sufficient.
Definition: Error.c:513
bool ErrorsPending(void)
Check if errors are pending.
Definition: Error.c:752
void(* fpOnErrorX)(void)
Structure used in tError to describe a function to be called on error set.
Definition: Error.h:64
ERROR_FLAGS
Flags used for errors.
Definition: Error.h:53
@ VIEWER_RESET
Can be reset by user with Viewer access level.
Definition: Error.h:54
@ PLC_RESET
Can be reset by the PLC.
Definition: Error.h:58
@ CODE_RESET
Can be reset by the program it-selve e.g. after Init.
Definition: Error.h:59
@ DEVELOPER_RESET
Can be reset by user with Developer access level.
Definition: Error.h:57
@ PROFESSIONAL_RESET
Can be reset by user with Professional access level.
Definition: Error.h:56
@ USER_RESET
Can be reset by user with User access level.
Definition: Error.h:55
@ NV_STORED
Stored in Non-Volatile RAM.
Definition: Error.h:60
void ErrorClear(uint8_t ui8AccessLevel)
Removes all errors from stack if access level is sufficient, might be called after Init.
Definition: Error.c:614
void NoOnErrorReaction(void)
This function is called if no Reaction is required after an error.
Definition: Error.c:332
bool NoOnErrorResetReaction(void)
This function is called if no Reaction is required after an error reset.
Definition: Error.c:341
void NoDataUpdate(void *DataOld,...)
Dummy Function for no Data-updates.
Definition: Error.c:744
void ResetErrorIdRange(uint16_t ui16ErrorIdStart, uint16_t ui16ErrorIdEnd, uint8_t ui8AccessLevel)
Resets all pending errors in a range of error IDs if access level is sufficient.
Definition: Error.c:567
uint32_t g_u32ErrorPending
An error that has not been reset is marked with a high bit, bit 0 corresponds to g_ptErrorList[0] etc...
Definition: Error.h:934
tErrorListItem * _SetErrorX(const tError *ptError, const tErrorSource *ptErrorSource,...)
This function adds a error to the stack.
Definition: Error.c:352
#define MAX_NUMBER_OF_ERRORS
Size of the error stack.
Definition: Error.h:33
#define DeclareOnErrorReaction(ERROR_REACTION)
Use to declare an ErrorReaction as external.
Definition: Error.h:887
bool IsErrorPending(uint32_t position)
Check if the requestes Error-Position is pending.
Definition: Error.c:780
bool(* fpOnErrorResetX)(void)
Structure used in tError to describe a function to be called on error reset.
Definition: Error.h:80
#define DeclareOnErrorResetReaction(ERROR_REACTION)
Use to declare an ErrorResetReaction as external.
Definition: Error.h:916
uint16_t void int32_t uint32_t ParameterAccessSource uint8_t ui8AccessLevel
Definition: PARA_Timestamp.c:63
Definition of a timestamp type.
Definition: timestamp.h:30
Main error structure.
Definition: Error.h:96
const uint16_t ui16Id
Error-ID.
Definition: Error.h:97
const uint16_t ui16DataCount
Number of attached variables (not byte). See Details on Page Data appended to errors.
Definition: Error.h:98
const uint32_t ui32Flags
Flags from enum ERROR_FLAGS e.g. error reset permissions.
Definition: Error.h:99
const uint32_t ui32HelpLength
Strlen of Help.
Definition: Error.h:103
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:102
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:104
const tOnErrorResetReaction * OnErrorReset
Function to be called on reseting the error. See Page Actions on Error set and reset for details.
Definition: Error.h:105
const uint32_t ui32DescriptionLength
Strlen of Description.
Definition: Error.h:101
const char * Description
Short Description of the error.
Definition: Error.h:100
Structure used in the error stack.
Definition: Error.h:119
Type_Timestamp tTimestampFirst
Time when the error was set the first time.
Definition: Error.h:122
Type_Timestamp tTimestampLast
Time when the error was set the last time.
Definition: Error.h:123
void * Data
Pointer to the attached data the number is stored on ptError. The length is defined in Error-Definiti...
Definition: Error.h:125
const tErrorSource * ptErrorSource
Location of the error in source code.
Definition: Error.h:121
const tError * ptError
Pointer to the error itself.
Definition: Error.h:120
uint32_t ui32ErrorCount
Number of occurrences. Starts with 1 and increments on every occurence.
Definition: Error.h:124
Structure used in tError holding source-code file an line.
Definition: Error.h:110
const uint32_t ui32Line
Source-code line.
Definition: Error.h:111
const char * File
Source-code filename and path.
Definition: Error.h:112
const uint32_t ui32FileLength
Strlen of filename.
Definition: Error.h:113
The error reaction is called on occurence of the error.
Definition: Error.h:70
const uint32_t ui32HelpSize
StrLen of Help.
Definition: Error.h:75
const fpOnErrorX fpErrorReaction
Function to be called.
Definition: Error.h:71
const char * cHelp
Help Text. See Page Help-texts in Errors for details.
Definition: Error.h:74
const char * cName
Name of the Function.
Definition: Error.h:72
const uint32_t ui32NameSize
StrLen of Name.
Definition: Error.h:73
The error reset reaction is called on reset of the error.
Definition: Error.h:86
const fpOnErrorResetX fpErrorReaction
Function to be called.
Definition: Error.h:87
const uint32_t ui32HelpSize
StrLen of Help.
Definition: Error.h:91
const char * cHelp
Help Text. See Page Help-texts in Errors for details.
Definition: Error.h:90
const char * cName
Name of the Function.
Definition: Error.h:88
const uint32_t ui32NameSize
StrLen of Name.
Definition: Error.h:89
Definition of timestamp data-structs.