ErrorLib 1.0.12-master SHA: f73ac03fda
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
153
154
164#define DefineError(ID, PERMISSION, ON_ERROR, ON_ERROR_RESET, DESCRIPTION, HELP) \
165 ASSERT_DESCRIPTION(DESCRIPTION); \
166 ASSERT_HELP(HELP); \
167 static const char g_s##ID##Description[] __attribute__((section("error_strings"), used)) = DESCRIPTION; \
168 static const char g_s##ID##Help[] __attribute__((section("error_strings"), used)) = HELP; \
169 \
170 const tError g_t##ID __attribute__((section("error_descriptor"), used)) = { \
171 ID, \
172 0, \
173 PERMISSION, \
174 g_s##ID##Description, \
175 sizeof(DESCRIPTION) - 1, \
176 g_s##ID##Help, \
177 sizeof(HELP) - 1, \
178 &g_t##ON_ERROR, \
179 &g_t##ON_ERROR_RESET, \
180 }
181
182
193#define DefineErrorData(ID, PERMISSION, ON_ERROR, ON_ERROR_RESET, DESCRIPTION, HELP, DATA_COUNT) \
194 ASSERT_DESCRIPTION(DESCRIPTION); \
195 ASSERT_HELP(HELP); \
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)) = HELP; \
198 \
199 const tError g_t##ID __attribute__((section("error_descriptor"), used)) = { \
200 ID, \
201 DATA_COUNT, \
202 PERMISSION, \
203 g_s##ID##Description, \
204 sizeof(DESCRIPTION) - 1, \
205 g_s##ID##Help, \
206 sizeof(HELP) - 1, \
207 &g_t##ON_ERROR, \
208 &g_t##ON_ERROR_RESET, \
209 }
210
211
216#define DeclareError(ID) const tError g_t##ID
217
218
228#define SetError(ID, PERMISSION, ON_ERROR, ON_ERROR_RESET, DESCRIPTION, HELP) \
229do \
230{ \
231 ASSERT_DESCRIPTION(DESCRIPTION); \
232 ASSERT_HELP(HELP); \
233 static const char g_s##ID##Description[] __attribute__((section("error_strings"), used)) = DESCRIPTION; \
234 static const char g_s##ID##Help[] __attribute__((section("error_strings"), used)) = HELP; \
235 static const tErrorSource g_t##ID##Source __attribute__((section("error_sources"), used)) = { \
236 __LINE__, \
237 g_sFileName, \
238 sizeof(g_sFileName) - 1 \
239 }; \
240 \
241 static const tError g_t##ID __attribute__((section("error_descriptor"), used)) = { \
242 ID, \
243 0, \
244 PERMISSION, \
245 g_s##ID##Description, \
246 sizeof(DESCRIPTION) - 1, \
247 g_s##ID##Help, \
248 sizeof(HELP) - 1, \
249 &g_t##ON_ERROR, \
250 &g_t##ON_ERROR_RESET, \
251 }; \
252 _SetErrorX(&g_t##ID, &g_t##ID##Source); \
253}while(0)
254
255
266#define SetErrorSource(ID, PERMISSION, ON_ERROR, ON_ERROR_RESET, DESCRIPTION, HELP, SOURCE) \
267do \
268{ \
269 ASSERT_DESCRIPTION(DESCRIPTION); \
270 ASSERT_HELP(HELP); \
271 static const char g_s##ID##Description[] __attribute__((section("error_strings"), used)) = DESCRIPTION; \
272 static const char g_s##ID##Help[] __attribute__((section("error_strings"), used)) = HELP; \
273 \
274 static const tError g_t##ID __attribute__((section("error_descriptor"), used)) = { \
275 ID, \
276 0, \
277 PERMISSION, \
278 g_s##ID##Description, \
279 sizeof(DESCRIPTION) - 1, \
280 g_s##ID##Help, \
281 sizeof(HELP) - 1, \
282 &g_t##ON_ERROR, \
283 &g_t##ON_ERROR_RESET, \
284 }; \
285 _SetErrorX(&g_t##ID, SOURCE); \
286}while(0)
287
288
299#define SetErrorData1(ID, PERMISSION, ON_ERROR, ON_ERROR_RESET, DESCRIPTION, HELP, DATA1) \
300do \
301{ \
302 ASSERT_DESCRIPTION(DESCRIPTION); \
303 ASSERT_HELP(HELP); \
304 static const char g_s##ID##Description[] __attribute__((section("error_strings"), used)) = DESCRIPTION; \
305 static const char g_s##ID##Help[] __attribute__((section("error_strings"), used)) = HELP; \
306 static const tErrorSource g_t##ID##Source __attribute__((section("error_sources"), used)) = { \
307 __LINE__, \
308 g_sFileName, \
309 sizeof(g_sFileName) - 1 \
310 }; \
311 \
312 static const tError g_t##ID __attribute__((section("error_descriptor"), used)) = { \
313 ID, \
314 1, \
315 PERMISSION, \
316 g_s##ID##Description, \
317 sizeof(DESCRIPTION) - 1, \
318 g_s##ID##Help, \
319 sizeof(HELP) - 1, \
320 &g_t##ON_ERROR, \
321 &g_t##ON_ERROR_RESET, \
322 }; \
323 if(sizeof(DATA1) < 4) \
324 { \
325 int32_t ERR_VAR_NAME(DataTemp, __LINE__) = DATA1; \
326 _SetErrorX(&g_t##ID, &g_t##ID##Source, ERR_VAR_NAME(DataTemp, __LINE__)); \
327 } \
328 else \
329 { \
330 _SetErrorX(&g_t##ID, &g_t##ID##Source, *(uint32_t*)&DATA1); \
331 } \
332}while(0)
333
334
348#define SetErrorData1Compare(ID, PERMISSION, ON_ERROR, ON_ERROR_RESET, DESCRIPTION, HELP, DATA1, COMPARE1) \
349do \
350{ \
351 ASSERT_DESCRIPTION(DESCRIPTION); \
352 ASSERT_HELP(HELP); \
353 static const char g_s##ID##Description[] __attribute__((section("error_strings"), used)) = DESCRIPTION; \
354 static const char g_s##ID##Help[] __attribute__((section("error_strings"), used)) = HELP; \
355 static const tErrorSource g_t##ID##Source __attribute__((section("error_sources"), used)) = { \
356 __LINE__, \
357 g_sFileName, \
358 sizeof(g_sFileName) - 1 \
359 }; \
360 \
361 static const tError g_t##ID __attribute__((section("error_descriptor"), used)) = { \
362 ID, \
363 1, \
364 PERMISSION, \
365 g_s##ID##Description, \
366 sizeof(DESCRIPTION) - 1, \
367 g_s##ID##Help, \
368 sizeof(HELP) - 1, \
369 &g_t##ON_ERROR, \
370 &g_t##ON_ERROR_RESET, \
371 }; \
372 \
373 tErrorListItem* ERR_VAR_NAME(ptError, __LINE__); \
374 if(sizeof(DATA1) < 4) \
375 { \
376 int32_t ERR_VAR_NAME(DataTemp, __LINE__) = DATA1; \
377 ERR_VAR_NAME(ptError, __LINE__) = _SetErrorX(&g_t##ID, &g_t##ID##Source, ERR_VAR_NAME(DataTemp, __LINE__)); \
378 } \
379 else \
380 { \
381 ERR_VAR_NAME(ptError, __LINE__) = _SetErrorX(&g_t##ID, &g_t##ID##Source, *(uint32_t*)&DATA1); \
382 } \
383 COMPARE1(ERR_VAR_NAME(ptError, __LINE__)->Data, DATA1); \
384}while(0)
385
386
398#define SetErrorData2(ID, PERMISSION, ON_ERROR, ON_ERROR_RESET, DESCRIPTION, HELP, DATA1, DATA2) \
399do \
400{ \
401 ASSERT_DESCRIPTION(DESCRIPTION); \
402 ASSERT_HELP(HELP); \
403 static const char g_s##ID##Description[] __attribute__((section("error_strings"), used)) = DESCRIPTION; \
404 static const char g_s##ID##Help[] __attribute__((section("error_strings"), used)) = HELP; \
405 static const tErrorSource g_t##ID##Source __attribute__((section("error_sources"), used)) = { \
406 __LINE__, \
407 g_sFileName, \
408 sizeof(g_sFileName) - 1 \
409 }; \
410 \
411 static const tError g_t##ID __attribute__((section("error_descriptor"), used)) = { \
412 ID, \
413 2, \
414 PERMISSION, \
415 g_s##ID##Description, \
416 sizeof(DESCRIPTION) - 1, \
417 g_s##ID##Help, \
418 sizeof(HELP) - 1, \
419 &g_t##ON_ERROR, \
420 &g_t##ON_ERROR_RESET, \
421 }; \
422 \
423 int32_t* ERR_VAR_NAME(pDataTemp1, __LINE__); \
424 if(sizeof(DATA1) < 4) \
425 { \
426 int32_t ERR_VAR_NAME(DataTemp1, __LINE__) = DATA1; \
427 ERR_VAR_NAME(pDataTemp1, __LINE__) = &ERR_VAR_NAME(DataTemp1, __LINE__); \
428 } \
429 else \
430 { \
431 ERR_VAR_NAME(pDataTemp1, __LINE__) = (int32_t*)&(DATA1); \
432 } \
433 int32_t* ERR_VAR_NAME(pDataTemp2, __LINE__); \
434 if(sizeof(DATA2) < 4) \
435 { \
436 int32_t ERR_VAR_NAME(DataTemp2, __LINE__) = DATA2; \
437 ERR_VAR_NAME(pDataTemp2, __LINE__) = &ERR_VAR_NAME(DataTemp2, __LINE__); \
438 } \
439 else \
440 { \
441 ERR_VAR_NAME(pDataTemp2, __LINE__) = (int32_t*)&(DATA2); \
442 } \
443 _SetErrorX(&g_t##ID, &g_t##ID##Source, *ERR_VAR_NAME(pDataTemp1, __LINE__), *ERR_VAR_NAME(pDataTemp2, __LINE__)); \
444}while(0)
445
446
462#define SetErrorData2Compare(ID, PERMISSION, ON_ERROR, ON_ERROR_RESET, DESCRIPTION, HELP, DATA1, COMPARE1, DATA2, COMPARE2) \
463do \
464{ \
465 ASSERT_DESCRIPTION(DESCRIPTION); \
466 ASSERT_HELP(HELP); \
467 static const char g_s##ID##Description[] __attribute__((section("error_strings"), used)) = DESCRIPTION; \
468 static const char g_s##ID##Help[] __attribute__((section("error_strings"), used)) = HELP; \
469 static const tErrorSource g_t##ID##Source __attribute__((section("error_sources"), used)) = { \
470 __LINE__, \
471 g_sFileName, \
472 sizeof(g_sFileName) - 1 \
473 }; \
474 \
475 static const tError g_t##ID __attribute__((section("error_descriptor"), used)) = { \
476 ID, \
477 2, \
478 PERMISSION, \
479 g_s##ID##Description, \
480 sizeof(DESCRIPTION) - 1, \
481 g_s##ID##Help, \
482 sizeof(HELP) - 1, \
483 &g_t##ON_ERROR, \
484 &g_t##ON_ERROR_RESET, \
485 }; \
486 \
487 int32_t* ERR_VAR_NAME(pDataTemp1, __LINE__); \
488 if(sizeof(DATA1) < 4) \
489 { \
490 int32_t ERR_VAR_NAME(DataTemp1, __LINE__) = DATA1; \
491 ERR_VAR_NAME(pDataTemp1, __LINE__) = &ERR_VAR_NAME(DataTemp1, __LINE__); \
492 } \
493 else \
494 { \
495 ERR_VAR_NAME(pDataTemp1, __LINE__) = (int32_t*)&(DATA1); \
496 } \
497 int32_t* ERR_VAR_NAME(pDataTemp2, __LINE__); \
498 if(sizeof(DATA2) < 4) \
499 { \
500 int32_t ERR_VAR_NAME(DataTemp2, __LINE__) = DATA2; \
501 ERR_VAR_NAME(pDataTemp2, __LINE__) = &ERR_VAR_NAME(DataTemp2, __LINE__); \
502 } \
503 else \
504 { \
505 ERR_VAR_NAME(pDataTemp2, __LINE__) = (int32_t*)&(DATA2); \
506 } \
507 tErrorListItem* ERR_VAR_NAME(ptError, __LINE__) = _SetErrorX(&g_t##ID, &g_t##ID##Source, *ERR_VAR_NAME(pDataTemp1, __LINE__), \
508 *ERR_VAR_NAME(pDataTemp2, __LINE__)); \
509 if((ERR_VAR_NAME(ptError, __LINE__) != 0) && (ERR_VAR_NAME(ptError, __LINE__)->Data != 0)) \
510 { \
511 COMPARE1(ERR_VAR_NAME(ptError, __LINE__)->Data, DATA1); \
512 COMPARE2(ERR_VAR_NAME(ptError, __LINE__)->Data + 4, DATA2); \
513 } \
514}while(0)
515
516
529#define SetErrorData3(ID, PERMISSION, ON_ERROR, ON_ERROR_RESET, DESCRIPTION, HELP, DATA1, DATA2, DATA3) \
530do \
531{ \
532 ASSERT_DESCRIPTION(DESCRIPTION); \
533 ASSERT_HELP(HELP); \
534 static const char g_s##ID##Description[] __attribute__((section("error_strings"), used)) = DESCRIPTION; \
535 static const char g_s##ID##Help[] __attribute__((section("error_strings"), used)) = HELP; \
536 static const tErrorSource g_t##ID##Source __attribute__((section("error_sources"), used)) = { \
537 __LINE__, \
538 g_sFileName, \
539 sizeof(g_sFileName) - 1 \
540 }; \
541 \
542 static const tError g_t##ID __attribute__((section("error_descriptor"), used)) = { \
543 ID, \
544 3, \
545 PERMISSION, \
546 g_s##ID##Description, \
547 sizeof(DESCRIPTION) - 1, \
548 g_s##ID##Help, \
549 sizeof(HELP) - 1, \
550 &g_t##ON_ERROR, \
551 &g_t##ON_ERROR_RESET, \
552 }; \
553 \
554 int32_t* ERR_VAR_NAME(pDataTemp1, __LINE__); \
555 if(sizeof(DATA1) < 4) \
556 { \
557 int32_t ERR_VAR_NAME(DataTemp1, __LINE__) = DATA1; \
558 ERR_VAR_NAME(pDataTemp1, __LINE__) = &ERR_VAR_NAME(DataTemp1, __LINE__); \
559 } \
560 else \
561 { \
562 ERR_VAR_NAME(pDataTemp1, __LINE__) = (int32_t*)&(DATA1); \
563 } \
564 int32_t* ERR_VAR_NAME(pDataTemp2, __LINE__); \
565 if(sizeof(DATA2) < 4) \
566 { \
567 int32_t ERR_VAR_NAME(DataTemp2, __LINE__) = DATA2; \
568 ERR_VAR_NAME(pDataTemp2, __LINE__) = &ERR_VAR_NAME(DataTemp2, __LINE__); \
569 } \
570 else \
571 { \
572 ERR_VAR_NAME(pDataTemp2, __LINE__) = (int32_t*)&(DATA2); \
573 } \
574 int32_t* ERR_VAR_NAME(pDataTemp3, __LINE__); \
575 if(sizeof(DATA3) < 4) \
576 { \
577 int32_t ERR_VAR_NAME(DataTemp3, __LINE__) = DATA3; \
578 ERR_VAR_NAME(pDataTemp3, __LINE__) = &ERR_VAR_NAME(DataTemp3, __LINE__); \
579 } \
580 else \
581 { \
582 ERR_VAR_NAME(pDataTemp3, __LINE__) = (int32_t*)&(DATA3); \
583 } \
584 _SetErrorX(&g_t##ID, &g_t##ID##Source, *ERR_VAR_NAME(pDataTemp1, __LINE__), *ERR_VAR_NAME(pDataTemp2, __LINE__), \
585 *ERR_VAR_NAME(pDataTemp3, __LINE__)); \
586}while(0)
587
588
602#define SetErrorData4(ID, PERMISSION, ON_ERROR, ON_ERROR_RESET, DESCRIPTION, HELP, DATA1, DATA2, DATA3, DATA4) \
603do \
604{ \
605 ASSERT_DESCRIPTION(DESCRIPTION); \
606 ASSERT_HELP(HELP); \
607 static const char g_s##ID##Description[] __attribute__((section("error_strings"), used)) = DESCRIPTION; \
608 static const char g_s##ID##Help[] __attribute__((section("error_strings"), used)) = HELP; \
609 static const tErrorSource g_t##ID##Source __attribute__((section("error_sources"), used)) = { \
610 __LINE__, \
611 g_sFileName, \
612 sizeof(g_sFileName) - 1 \
613 }; \
614 \
615 static const tError g_t##ID __attribute__((section("error_descriptor"), used)) = { \
616 ID, \
617 4, \
618 PERMISSION, \
619 g_s##ID##Description, \
620 sizeof(DESCRIPTION) - 1, \
621 g_s##ID##Help, \
622 sizeof(HELP) - 1, \
623 &g_t##ON_ERROR, \
624 &g_t##ON_ERROR_RESET, \
625 }; \
626 \
627 int32_t* ERR_VAR_NAME(pDataTemp1, __LINE__); \
628 if(sizeof(DATA1) < 4) \
629 { \
630 int32_t ERR_VAR_NAME(DataTemp1, __LINE__) = DATA1; \
631 ERR_VAR_NAME(pDataTemp1, __LINE__) = &ERR_VAR_NAME(DataTemp1, __LINE__); \
632 } \
633 else \
634 { \
635 ERR_VAR_NAME(pDataTemp1, __LINE__) = (int32_t*)&(DATA1); \
636 } \
637 int32_t* ERR_VAR_NAME(pDataTemp2, __LINE__); \
638 if(sizeof(DATA2) < 4) \
639 { \
640 int32_t ERR_VAR_NAME(DataTemp2, __LINE__) = DATA2; \
641 ERR_VAR_NAME(pDataTemp2, __LINE__) = &ERR_VAR_NAME(DataTemp2, __LINE__); \
642 } \
643 else \
644 { \
645 ERR_VAR_NAME(pDataTemp2, __LINE__) = (int32_t*)&(DATA2); \
646 } \
647 int32_t* ERR_VAR_NAME(pDataTemp3, __LINE__); \
648 if(sizeof(DATA3) < 4) \
649 { \
650 int32_t ERR_VAR_NAME(DataTemp3, __LINE__) = DATA3; \
651 ERR_VAR_NAME(pDataTemp3, __LINE__) = &ERR_VAR_NAME(DataTemp3, __LINE__); \
652 } \
653 else \
654 { \
655 ERR_VAR_NAME(pDataTemp3, __LINE__) = (int32_t*)&(DATA3); \
656 } \
657 int32_t* ERR_VAR_NAME(pDataTemp4, __LINE__); \
658 if(sizeof(DATA4) < 4) \
659 { \
660 int32_t ERR_VAR_NAME(DataTemp4, __LINE__) = DATA4; \
661 ERR_VAR_NAME(pDataTemp4, __LINE__) = &ERR_VAR_NAME(DataTemp4, __LINE__); \
662 } \
663 else \
664 { \
665 ERR_VAR_NAME(pDataTemp4, __LINE__) = (int32_t*)&(DATA4); \
666 } \
667 _SetErrorX(&g_t##ID, &g_t##ID##Source, *ERR_VAR_NAME(pDataTemp1, __LINE__), *ERR_VAR_NAME(pDataTemp2, __LINE__), \
668 *ERR_VAR_NAME(pDataTemp3, __LINE__), *ERR_VAR_NAME(pDataTemp4, __LINE__)); \
669}while(0)
670
671
675#define SetErrorId(ID) \
676do \
677{ \
678 static const tErrorSource ERR_VAR_NAME(g_t##ID##Source, __LINE__) __attribute__((section("error_sources"), used)) = { \
679 __LINE__, \
680 g_sFileName, \
681 sizeof(g_sFileName) - 1 \
682 }; \
683 \
684 _SetErrorX(&g_t##ID, &ERR_VAR_NAME(g_t##ID##Source, __LINE__)); \
685}while(0)
686
687
692#define SetErrorIdData1(ID, DATA1) \
693do \
694{ \
695 static const tErrorSource ERR_VAR_NAME(g_t##ID##Source, __LINE__) __attribute__((section("error_sources"), used)) = { \
696 __LINE__, \
697 g_sFileName, \
698 sizeof(g_sFileName) - 1 \
699 }; \
700 \
701 if(sizeof(DATA1) < 4) \
702 { \
703 int32_t ERR_VAR_NAME(DataTemp, __LINE__) = DATA1; \
704 _SetErrorX(&g_t##ID, &ERR_VAR_NAME(g_t##ID##Source, __LINE__), ERR_VAR_NAME(DataTemp, __LINE__)); \
705 } \
706 else \
707 { \
708 _SetErrorX(&g_t##ID, &ERR_VAR_NAME(g_t##ID##Source, __LINE__), DATA1); \
709 } \
710}while(0)
711
712
718#define SetErrorIdData2(ID, DATA1, DATA2) \
719do \
720{ \
721 static const tErrorSource ERR_VAR_NAME(g_t##ID##Source, __LINE__) __attribute__((section("error_sources"), used)) = { \
722 __LINE__, \
723 g_sFileName, \
724 sizeof(g_sFileName) - 1 \
725 }; \
726 \
727 int32_t* ERR_VAR_NAME(pDataTemp1, __LINE__); \
728 if(sizeof(DATA1) < 4) \
729 { \
730 int32_t ERR_VAR_NAME(DataTemp1, __LINE__) = DATA1; \
731 ERR_VAR_NAME(pDataTemp1, __LINE__) = &ERR_VAR_NAME(DataTemp1, __LINE__); \
732 } \
733 else \
734 { \
735 ERR_VAR_NAME(pDataTemp1, __LINE__) = (int32_t*)&(DATA1); \
736 } \
737 int32_t* ERR_VAR_NAME(pDataTemp2, __LINE__); \
738 if(sizeof(DATA2) < 4) \
739 { \
740 int32_t ERR_VAR_NAME(DataTemp2, __LINE__) = DATA2; \
741 ERR_VAR_NAME(pDataTemp2, __LINE__) = &ERR_VAR_NAME(DataTemp2, __LINE__); \
742 } \
743 else \
744 { \
745 ERR_VAR_NAME(pDataTemp2, __LINE__) = (int32_t*)&(DATA2); \
746 } \
747 _SetErrorX(&g_t##ID, &ERR_VAR_NAME(g_t##ID##Source, __LINE__), *ERR_VAR_NAME(pDataTemp1, __LINE__), \
748 *ERR_VAR_NAME(pDataTemp2, __LINE__)); \
749}while(0)
750
751
758#define SetErrorIdData3(ID, DATA1, DATA2, DATA3) \
759do \
760{ \
761 static const tErrorSource ERR_VAR_NAME(g_t##ID##Source, __LINE__) __attribute__((section("error_sources"), used)) = { \
762 __LINE__, \
763 g_sFileName, \
764 sizeof(g_sFileName) - 1 \
765 }; \
766 \
767 int32_t* ERR_VAR_NAME(pDataTemp1, __LINE__); \
768 if(sizeof(DATA1) < 4) \
769 { \
770 int32_t ERR_VAR_NAME(DataTemp1, __LINE__) = DATA1; \
771 ERR_VAR_NAME(pDataTemp1, __LINE__) = &ERR_VAR_NAME(DataTemp1, __LINE__); \
772 } \
773 else \
774 { \
775 ERR_VAR_NAME(pDataTemp1, __LINE__) = (int32_t*)&(DATA1); \
776 } \
777 int32_t* ERR_VAR_NAME(pDataTemp2, __LINE__); \
778 if(sizeof(DATA2) < 4) \
779 { \
780 int32_t ERR_VAR_NAME(DataTemp2, __LINE__) = DATA2; \
781 ERR_VAR_NAME(pDataTemp2, __LINE__) = &ERR_VAR_NAME(DataTemp2, __LINE__); \
782 } \
783 else \
784 { \
785 ERR_VAR_NAME(pDataTemp2, __LINE__) = (int32_t*)&(DATA2); \
786 } \
787 int32_t* ERR_VAR_NAME(pDataTemp3, __LINE__); \
788 if(sizeof(DATA3) < 4) \
789 { \
790 int32_t ERR_VAR_NAME(DataTemp3, __LINE__) = DATA3; \
791 ERR_VAR_NAME(pDataTemp3, __LINE__) = &ERR_VAR_NAME(DataTemp3, __LINE__); \
792 } \
793 else \
794 { \
795 ERR_VAR_NAME(pDataTemp3, __LINE__) = (int32_t*)&(DATA3); \
796 } \
797 _SetErrorX(&g_t##ID, &ERR_VAR_NAME(g_t##ID##Source, __LINE__), *ERR_VAR_NAME(pDataTemp1, __LINE__), \
798 *ERR_VAR_NAME(pDataTemp2, __LINE__), \
799 *ERR_VAR_NAME(pDataTemp3, __LINE__)); \
800}while(0)
801
802
810#define SetErrorIdData4(ID, DATA1, DATA2, DATA3, DATA4) \
811do \
812{ \
813 static const tErrorSource ERR_VAR_NAME(g_t##ID##Source, __LINE__) __attribute__((section("error_sources"), used)) = { \
814 __LINE__, \
815 g_sFileName, \
816 sizeof(g_sFileName) - 1 \
817 }; \
818 \
819 int32_t* ERR_VAR_NAME(pDataTemp1, __LINE__); \
820 if(sizeof(DATA1) < 4) \
821 { \
822 int32_t ERR_VAR_NAME(DataTemp1, __LINE__) = DATA1; \
823 ERR_VAR_NAME(pDataTemp1, __LINE__) = &ERR_VAR_NAME(DataTemp1, __LINE__); \
824 } \
825 else \
826 { \
827 ERR_VAR_NAME(pDataTemp1, __LINE__) = (int32_t*)&(DATA1); \
828 } \
829 int32_t* ERR_VAR_NAME(pDataTemp2, __LINE__); \
830 if(sizeof(DATA2) < 4) \
831 { \
832 int32_t ERR_VAR_NAME(DataTemp2, __LINE__) = DATA2; \
833 ERR_VAR_NAME(pDataTemp2, __LINE__) = &ERR_VAR_NAME(DataTemp2, __LINE__); \
834 } \
835 else \
836 { \
837 ERR_VAR_NAME(pDataTemp2, __LINE__) = (int32_t*)&(DATA2); \
838 } \
839 int32_t* ERR_VAR_NAME(pDataTemp3, __LINE__); \
840 if(sizeof(DATA3) < 4) \
841 { \
842 int32_t ERR_VAR_NAME(DataTemp3, __LINE__) = DATA3; \
843 ERR_VAR_NAME(pDataTemp3, __LINE__) = &ERR_VAR_NAME(DataTemp3, __LINE__); \
844 } \
845 else \
846 { \
847 ERR_VAR_NAME(pDataTemp3, __LINE__) = (int32_t*)&(DATA3); \
848 } \
849 int32_t* ERR_VAR_NAME(pDataTemp4, __LINE__); \
850 if(sizeof(DATA4) < 4) \
851 { \
852 int32_t ERR_VAR_NAME(DataTemp4, __LINE__) = DATA4; \
853 ERR_VAR_NAME(pDataTemp4, __LINE__) = &ERR_VAR_NAME(DataTemp4, __LINE__); \
854 } \
855 else \
856 { \
857 ERR_VAR_NAME(pDataTemp4, __LINE__) = (int32_t*)&(DATA4); \
858 } \
859 _SetErrorX(&g_t##ID, &ERR_VAR_NAME(g_t##ID##Source, __LINE__), *ERR_VAR_NAME(pDataTemp1, __LINE__), \
860 *ERR_VAR_NAME(pDataTemp2, __LINE__), \
861 *ERR_VAR_NAME(pDataTemp3, __LINE__), \
862 *ERR_VAR_NAME(pDataTemp4, __LINE__)); \
863}while(0)
864
865
872#define DefineOnErrorReaction(ERROR_REACTION, NAME, HELP) \
873ASSERT_REACTION_NAME(NAME); \
874ASSERT_HELP(HELP); \
875static const char ERR_VAR_NAME(g_s##ERROR_REACTION##Name, __LINE__)[] __attribute__((section("error_strings"), used)) = NAME; \
876static const char ERR_VAR_NAME(g_s##ERROR_REACTION##Help, __LINE__)[] __attribute__((section("error_strings"), used)) = HELP; \
877const tOnErrorReaction g_t##ERROR_REACTION __attribute__((section("error_reactions"), used)) = { \
878 &ERROR_REACTION, \
879 ERR_VAR_NAME(g_s##ERROR_REACTION##Name, __LINE__), \
880 sizeof(ERR_VAR_NAME(g_s##ERROR_REACTION##Name, __LINE__)) - 1, \
881 ERR_VAR_NAME(g_s##ERROR_REACTION##Help, __LINE__), \
882 sizeof(ERR_VAR_NAME(g_s##ERROR_REACTION##Help, __LINE__)) - 1 \
883};
884
885
890#define DeclareOnErrorReaction(ERROR_REACTION) \
891 const tOnErrorReaction g_t##ERROR_REACTION; \
892 void ERROR_REACTION(void)
893
894
901#define DefineOnErrorResetReaction(ERROR_REACTION, NAME, HELP) \
902ASSERT_REACTION_NAME(NAME); \
903ASSERT_HELP(HELP); \
904static const char ERR_VAR_NAME(g_s##ERROR_REACTION##Name, __LINE__)[] __attribute__((section("error_strings"), used)) = NAME; \
905static const char ERR_VAR_NAME(g_s##ERROR_REACTION##Help, __LINE__)[] __attribute__((section("error_strings"), used)) = HELP; \
906const tOnErrorResetReaction g_t##ERROR_REACTION __attribute__((section("error_reactions"), used)) = { \
907 &ERROR_REACTION, \
908 ERR_VAR_NAME(g_s##ERROR_REACTION##Name, __LINE__), \
909 sizeof(ERR_VAR_NAME(g_s##ERROR_REACTION##Name, __LINE__)) - 1, \
910 ERR_VAR_NAME(g_s##ERROR_REACTION##Help, __LINE__), \
911 sizeof(ERR_VAR_NAME(g_s##ERROR_REACTION##Help, __LINE__)) - 1 \
912};
913
914
919#define DeclareOnErrorResetReaction(ERROR_REACTION) \
920 const tOnErrorResetReaction g_t##ERROR_REACTION; \
921 bool ERROR_REACTION(void)
922
925
926//-----------------------------------------------------------------------------
927// Local data
928//-----------------------------------------------------------------------------
932static const char g_sFileName[] __attribute__((section("error_strings"), used)) = __BASE_FILE__;
933
934//-----------------------------------------------------------------------------
935// global data
936//-----------------------------------------------------------------------------
937extern uint32_t g_u32ErrorPending;
939
940//-----------------------------------------------------------------------------
941// Global function prototypes
942//-----------------------------------------------------------------------------
943void ErrorInit(void);
944tErrorListItem* _SetErrorX(const tError* ptError, const tErrorSource* ptErrorSource, ...);
945void ErrorResetX(uint8_t ui8AccessLevel);
946void ResetErrorIdRange(uint16_t ui16ErrorIdStart, uint16_t ui16ErrorIdEnd, uint8_t ui8AccessLevel);
947void ErrorClear(uint8_t ui8AccessLevel);
948bool ErrorsPending(void);
949void MaxFloat(void* DataOld, float DataNew);
950void MinFloat(void* DataOld, float DataNew);
951void MaxAbsFloat(void* DataOld, float DataNew);
952void MaxInt(void* DataOld, int32_t DataNew);
953void MinInt(void* DataOld, int32_t DataNew);
954void MaxUInt(void* DataOld, uint32_t DataNew);
955void MinUInt(void* DataOld, uint32_t DataNew);
956void NoDataUpdate(void* DataOld, ...);
957bool IsErrorPending(uint32_t position);
958bool IsErrorIdPending(uint16_t ui16ErrorId);
959bool IsErrorIdRangePending(uint16_t ui16ErrorIdStart, uint16_t ui16ErrorIdEnd);
960uint16_t GetErrorId(uint32_t position);
961uint32_t PendingErrosSortedByTime(tErrorListItem* pptPendingErrorList[]);
962
963#ifdef __cplusplus
964}
965#endif
966#endif //ERROR_h
uint32_t PendingErrosSortedByTime(tErrorListItem *pptPendingErrorList[])
Get an array of the pending Errors sorted by tTimestampFirst.
Definition: Error.c:865
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:932
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
bool IsErrorIdPending(uint16_t ui16ErrorId)
Check if a Error-ID is pending.
Definition: Error.c:790
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:838
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: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
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
bool IsErrorIdRangePending(uint16_t ui16ErrorIdStart, uint16_t ui16ErrorIdEnd)
Check if a Error in the range is pending.
Definition: Error.c:815
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:937
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:36
#define DeclareOnErrorReaction(ERROR_REACTION)
Use to declare an ErrorReaction as external.
Definition: Error.h:890
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:83
#define DeclareOnErrorResetReaction(ERROR_REACTION)
Use to declare an ErrorResetReaction as external.
Definition: Error.h:919
uint16_t void int32_t uint32_t ParameterAccessSource uint8_t ui8AccessLevel
Definition: PARA_Timestamp.c:63
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.