diff --git a/.gitignore b/.gitignore index 2fbce262..5a0dda69 100644 --- a/.gitignore +++ b/.gitignore @@ -2,5 +2,13 @@ .vscode pkg_build build -.clang-format -**/__pycache__/ \ No newline at end of file +**/__pycache__/ + +# Code-check reports +clang-tidy-report.txt + +scan-build-reports/ + +cppcheck_reports/ +cppcheck.checkers +err.xml \ No newline at end of file diff --git a/IFX_CONTRIBUTING.md b/IFX_CONTRIBUTING.md new file mode 100644 index 00000000..70b6fc96 --- /dev/null +++ b/IFX_CONTRIBUTING.md @@ -0,0 +1,26 @@ +# Develop Environment + +## Develop on Windows +Clone the repository in arduino folder: +- Open Arduino and install any Infineon XMC library (e.g. 2.2.0) +- Open the library location in Arduino program folder +`C:\Users\"USERNAME"\AppData\Local\Arduino15\packages\Infineon\hardware\xmc` +- Open git bash, type command: +`git clone "HTTP_SSH_REPOSITORY" "LIBRARY_VERSION (e.g. 2.2.0)"` + +This is a workaround for current local compilation/testing. + +## Develop on WSL +To be able to use some tools (make, clang, gcc...) easier on Linux, WSL is needed. +Since now we still compile the code with arduino-cli.exe on windows, in order to useLinux commands/ build tools, a symbolic link is created to eunsure the changes are immediately reflected in the other. +In WSL, you can create a symbolic link pointing to your windows project folder: + +`ln -s /mnt/c/Users//AppData/Local/Arduino15/packages/Infineon/hardware/xmc /home//project` + +# Code checks +Refer to libraries\CAN\Makefile.codecheck + +# Example and Unity tests +Refer to libraries\CAN\Makefile.test + +XMC4700 Receiver has some issue. \ No newline at end of file diff --git a/config/clang-format/.clang-format b/config/clang-format/.clang-format new file mode 100644 index 00000000..f4ca94c0 --- /dev/null +++ b/config/clang-format/.clang-format @@ -0,0 +1,26 @@ +--- +# We'll use defaults from the LLVM style, but with 4 columns indentation. +#BasedOnStyle: GNU +BasedOnStyle: LLVM +#BasedOnStyle: Google +#BasedOnStyle: Mozilla +#BasedOnStyle: Chromium +IndentWidth: 4 +--- +Language: Cpp +# BasedOnStyle: Google +AccessModifierOffset: -4 +Standard: c++17 +TabWidth: 2 +UseTab: Never +ColumnLimit: 100 +AlignAfterOpenBracket: Align +BinPackParameters: false +AlignEscapedNewlines: Left +AlwaysBreakTemplateDeclarations: Yes +PackConstructorInitializers: Never +BreakConstructorInitializersBeforeComma: false +IndentPPDirectives: BeforeHash +SortIncludes: Never +SeparateDefinitionBlocks: Always +... diff --git a/config/clang-tidy/.clang-tidy b/config/clang-tidy/.clang-tidy new file mode 100644 index 00000000..db69638c --- /dev/null +++ b/config/clang-tidy/.clang-tidy @@ -0,0 +1,54 @@ +Checks: 'cppcoreguidelines-*, +performance-*, +modernize-*, +google-*, +misc-* +cert-*, +readability-*, +clang-analyzer-*, +-performance-unnecessary-value-param, +-modernize-use-trailing-return-type, +-google-runtime-references, +-misc-non-private-member-variables-in-classes, +-readability-braces-around-statements, +-google-readability-braces-around-statements, +-cppcoreguidelines-avoid-magic-numbers, +-readability-magic-numbers, +-readability-magic-numbers, +-cppcoreguidelines-pro-type-vararg, +-cppcoreguidelines-pro-bounds-pointer-arithmetic, +-cppcoreguidelines-avoid-c-arrays, +-modernize-avoid-c-arrays, +-cppcoreguidelines-pro-bounds-array-to-pointer-decay, +-readability-named-parameter, +-cert-env33-c +' + + +WarningsAsErrors: '' +HeaderFilterRegex: '.*' +#HeaderFilterRegex: '*spdlog/[^f].*' +#AnalyzeTemporaryDtors: false +FormatStyle: none + +CheckOptions: + - key: google-readability-braces-around-statements.ShortStatementLines + value: '1' + - key: google-readability-function-size.StatementThreshold + value: '800' + - key: google-readability-namespace-comments.ShortNamespaceLines + value: '10' + - key: google-readability-namespace-comments.SpacesBeforeComments + value: '2' + - key: modernize-loop-convert.MaxCopySize + value: '16' + - key: modernize-loop-convert.MinConfidence + value: reasonable + - key: modernize-loop-convert.NamingStyle + value: CamelCase + - key: modernize-pass-by-value.IncludeStyle + value: llvm + - key: modernize-replace-auto-ptr.IncludeStyle + value: llvm + - key: modernize-use-nullptr.NullMacros + value: 'NULL' diff --git a/config/cppcheck/misra.json b/config/cppcheck/misra.json new file mode 100644 index 00000000..ef34b5d7 --- /dev/null +++ b/config/cppcheck/misra.json @@ -0,0 +1,4 @@ +{ + "script": "misra.py", + "args": [ "--rule-texts=config/cppcheck/misra.txt" ] +} \ No newline at end of file diff --git a/config/cppcheck/misra.txt b/config/cppcheck/misra.txt new file mode 100644 index 00000000..f98f6dd7 --- /dev/null +++ b/config/cppcheck/misra.txt @@ -0,0 +1,647 @@ +Appendix A Summary of guidelines + +Rule 1.1 Required +The program shall contain no violations of the standard C syntax and constraints, and shall not exceed the implementation’s translation limits + +Rule 1.2 Advisory +Language extensions should not be used + +Rule 1.3 Required +There shall be no occurrence of undefined or critical unspecified behaviour + +Rule 1.4 Required +Emergent language features shall not be used + +Rule 1.5 Required +Obsolescent language features shall not be used + +Rule 2.1 Required +A project shall not contain unreachable code + +Rule 2.2 Required +There shall be no dead code + +Rule 2.3 Advisory +A project should not contain unused type declarations + +Rule 2.4 Advisory +A project should not contain unused tag declarations + +Rule 2.5 Advisory +A project should not contain unused macro declarations + +Rule 2.6 Advisory +A function should not contain unused label declarations + +Rule 2.7 Advisory +There should be no unused parameters in functions + +Rule 2.8 Advisory +A project should not contain unused object definitions + +Rule 3.1 Required +The character sequences /* and // shall not be used within a comment + +Rule 3.2 Required +Line-splicing shall not be used in // comments + +Rule 4.1 Required +Octal and hexadecimal escape sequences shall be terminated + +Rule 4.2 Advisory +Trigraphs should not be used + +Dir 4.3 Required +Assembly language shall be encapsulated and isolated + +Dir 4.4 Advisory +Sections of code should not be "commented out" + +Dir 4.5 Advisory +Identifiers in the same name space with overlapping visibility should be typographically unambiguous + +Dir 4.6 Advisory +typedefs that indicate size and signedness should be used in place of the basic numerical types + +Dir 4.7 Required +If a function returns error information, then that error information shall be tested + +Dir 4.8 Advisory +If a pointer to a structure or union is never dereferenced within a translation unit, then the implementation of the object should be hidden + +Dir 4.9 Advisory +A function should be used in preference to a function-like macro where they are interchangeable + +Dir 4.10 Required +Precautions shall be taken in order to prevent the contents of a header file being included more than once + +Dir 4.11 Required +The validity of values passed to library functions shall be checked + +Dir 4.12 Required +Dynamic memory allocation shall not be used + +Dir 4.13 Advisory +Functions which are designed to provide operations on a resource should be called in an appropriate sequence + +Dir 4.15 Required +Evaluation of floating-point expressions shall not lead to the undetected generation of infinities and NaNs + +Dir 5.1 Required +There shall be no data races between threads + +Dir 5.2 Required +There shall be no deadlocks between threads + +Dir 5.3 Required +There shall be no dynamic thread creation + +Rule 5.1 Required +External identifiers shall be distinct + +Rule 5.2 Required +Identifiers declared in the same scope and name space shall be distinct + +Rule 5.3 Required +An identifier declared in an inner scope shall not hide an identifier declared in an outer scope + +Rule 5.4 Required +Macro identifiers shall be distinct + +Rule 5.5 Required +Identifiers shall be distinct from macro names + +Rule 5.6 Required +A typedef name shall be a unique identifier + +Rule 5.7 Required +A tag name shall be a unique identifier + +Rule 5.8 Required +Identifiers that define objects or functions with external linkage shall be unique + +Rule 5.9 Advisory +Identifiers that define objects or functions with internal linkage should be unique + +Rule 6.1 Required +Bit-fields shall only be declared with an appropriate type + +Rule 6.2 Required +Single-bit named bit fields shall not be of a signed type + +Rule 6.3 Required +A bit field shall not be declared as a member of a union + +Rule 7.1 Required +Octal constants shall not be used + +Rule 7.2 Required +A "u" or "U" suffix shall be applied to all integer constants that are represented in an unsigned type + +Rule 7.3 Required +The lowercase character "l" shall not be used in a literal suffix + +Rule 7.4 Required +A string literal shall not be assigned to an object unless the object’s type is "pointer to const-qualified char" + +Rule 7.5 Mandatory +The argument of an integer constant macro shall have an appropriate form + +Rule 7.6 Required +The small integer variants of the minimum-width integer constant macros shall not be used + +Rule 8.1 Required +Types shall be explicitly specified + +Rule 8.2 Required +Function types shall be in prototype form with named parameters + +Rule 8.3 Required +All declarations of an object or function shall use the same names and type qualifiers + +Rule 8.4 Required +A compatible declaration shall be visible when an object or function with external linkage is defined + +Rule 8.5 Required +An external object or function shall be declared once in one and only one file + +Rule 8.6 Required +An identifier with external linkage shall have exactly one external definition + +Rule 8.7 Advisory +Functions and objects should not be defined with external linkage if they are referenced in only one translation unit + +Rule 8.8 Required +The static storage class specifier shall be used in all declarations of objects and functions that have internal linkage + +Rule 8.9 Advisory +An object should be defined at block scope if its identifier only appears in a single function + +Rule 8.10 Required +An inline function shall be declared with the static storage class + +Rule 8.11 Advisory +When an array with external linkage is declared, its size should be explicitly specified + +Rule 8.12 Required +Enumeration member "name" have a not unique implicitly-specified value + +Rule 8.13 Advisory +A pointer should point to a const-qualified type whenever possible + +Rule 8.14 Required +The restrict type qualifier shall not be used + +Rule 8.15 Required +All declarations of an object with an explicit alignment specification shall specify the same alignment + +Rule 8.16 Advisory +The alignment specification of zero should not appear in an object declaration + +Rule 8.17 Advisory +At most one explicit alignment specifier should appear in an object declaration + +Rule 9.1 Mandatory +The value of an object with automatic storage duration shall not be read before it has been set + +Rule 9.2 Required +The initializer for an aggregate or union shall be enclosed in braces + +Rule 9.3 Required +Arrays shall not be partially initialized + +Rule 9.4 Required +An element of an object shall not be initialized more than once + +Rule 9.5 Required +Where designated initializers are used to initialize an array object the size of the array shall be specified explicitly + +Rule 9.6 Required +An initializer using chained designators shall not contain initializers without designators + +Rule 9.7 Mandatory +Atomic objects shall be appropriately initialized before being accessed + +Rule 10.1 Required +Operands shall not be of an inappropriate essential type + +Rule 10.2 Required +Expressions of essentially character type shall not be used inappropriately in addition and subtraction operations + +Rule 10.3 Required +The value of an expression shall not be assigned to an object with a narrower essential type or of a different essential type category + +Rule 10.4 Required +Both operands of an operator in which the usual arithmetic conversions are performed shall have the same essential type category + +Rule 10.5 Advisory +The value of an expression should not be cast to an inappropriate essential type + +Rule 10.6 Required +The value of a composite expression shall not be assigned to an object with wider essential type + +Rule 10.7 Required +If a composite expression is used as one operand of an operator in which the usual arithmetic conversions are performed then the other operand shall not have wider essential type + +Rule 10.8 Required +The value of a composite expression shall not be cast to a different essential type category or a wider essential type + +Rule 11.1 Required +Conversions shall not be performed between a pointer to a function and any other type + +Rule 11.2 Required +Conversions shall not be performed between a pointer to an incomplete type and any other type + +Rule 11.3 Required +A cast shall not be performed between a pointer to object type and a pointer to a different object type + +Rule 11.4 Advisory +A conversion should not be performed between a pointer to object and an integer type + +Rule 11.5 Advisory +A conversion should not be performed from pointer to void into pointer to object + +Rule 11.6 Required +A cast shall not be performed between pointer to void and an arithmetic type + +Rule 11.7 Required +A cast shall not be performed between pointer to object and a noninteger arithmetic type + +Rule 11.8 Required +A cast shall not remove any const or volatile qualification from the type pointed to by a pointer + +Rule 11.9 Required +The macro NULL shall be the only permitted form of integer null pointer constant + +Rule 11.10 Required +The _Atomic qualifier shall not be applied to the incomplete type void + +Rule 12.1 Advisory +The precedence of operators within expressions should be made explicit + +Rule 12.2 Required +The right hand operand of a shift operator shall lie in the range zero to one less than the width in bits of the essential type of the left hand operand + +Rule 12.3 Advisory +The comma operator should not be used + +Rule 12.4 Advisory +Evaluation of constant expressions should not lead to unsigned integer wrap-around + +Rule 12.5 Mandatory +The sizeof operator shall not have an operand which is a function parameter declared as “array of type” + +Rule 12.6 Required +Structure and union members of atomic objects shall not be directly accessed + +Rule 13.1 Required +Initializer lists shall not contain persistent side effects + +Rule 13.2 Required +The value of an expression and its persistent side effects shall be the same under all permitted evaluation orders + +Rule 13.3 Advisory +A full expression containing an increment (++) or decrement (--) operator should have no other potential side effects other than that caused by the increment or decrement operator + +Rule 13.4 Advisory +The result of an assignment operator should not be used + +Rule 13.5 Required +The right hand operand of a logical && or || operator shall not contain persistent side effects + +Rule 13.6 Mandatory +The operand of the sizeof operator shall not contain any expression which has potential side effects + +Rule 14.1 Required +A loop counter shall not have essentially floating type + +Rule 14.2 Required +A for loop shall be well-formed + +Rule 14.3 Required +Controlling expressions shall not be invariant + +Rule 14.4 Required +The controlling expression of an if statement and the controlling expression of an iteration-statement shall have essentially Boolean type + +Rule 15.1 Advisory +The goto statement should not be used + +Rule 15.2 Required +The goto statement shall jump to a label declared later in the same function + +Rule 15.3 Required +Any label referenced by a goto statement shall be declared in the same block, or in any block enclosing the goto statement + +Rule 15.4 Advisory +There should be no more than one break or goto statement used to terminate any iteration statement + +Rule 15.5 Advisory +A function should have a single point of exit at the end + +Rule 15.6 Required +The body of an iteration-statement or a selection-statement shall be a compound-statement + +Rule 15.7 Required +All if … else if constructs shall be terminated with an else statement + +Rule 16.1 Required +All switch statements shall be well-formed + +Rule 16.2 Required +A switch label shall only be used when the most closely-enclosing compound statement is the body of a switch statement + +Rule 16.3 Required +An unconditional break statement shall terminate every switch-clause + +Rule 16.4 Required +Every switch statement shall have a default label + +Rule 16.5 Required +A default label shall appear as either the first or the last switch label of a switch statement + +Rule 16.6 Required +Every switch statement shall have at least two switch-clauses + +Rule 16.7 Required +A switch-expression shall not have essentially Boolean type + +Rule 17.1 Required +The features of "stdarg.h" shall not be used + +Rule 17.2 Required +Functions shall not call themselves, either directly or indirectly + +Rule 17.3 Mandatory +A function shall not be declared implicitly + +Rule 17.4 Mandatory +All exit paths from a function with non-void return type shall have an explicit return statement with an expression + +Rule 17.5 Advisory +The function argument corresponding to a parameter declared to have an array type shall have an appropriate number of elements + +Rule 17.6 Mandatory +The declaration of an array parameter shall not contain the static keyword between the [ ] + +Rule 17.7 Required +The value returned by a function having non-void return type shall be used + +Rule 17.8 Advisory +A function parameter should not be modified + +Rule 17.9 Mandatory +A function declared with a _Noreturn function specifier shall not return to its caller + +Rule 17.10 Required +A function declared with a _Noreturn function specifier shall have void return type + +Rule 17.11 Advisory +A function that never returns should be declared with a _Noreturn function specifier + +Rule 17.12 Advisory +A function identifier should only be used with either a preceding &, or with a parenthesized parameter list + +Rule 17.13 Required +A function type shall not be type qualified + +Rule 18.1 Required +A pointer resulting from arithmetic on a pointer operand shall address an element of the same array as that pointer operand + +Rule 18.2 Required +Subtraction between pointers shall only be applied to pointers that address elements of the same array + +Rule 18.3 Required +The relational operators >, >=, < and <= shall not be applied to objects of pointer type except where they point into the same object + +Rule 18.4 Advisory +The +, -, += and -= operators should not be applied to an expression of pointer type + +Rule 18.5 Advisory +Declarations should contain no more than two levels of pointer nesting + +Rule 18.6 Required +The address of an object with automatic storage shall not be copied to another object that persists after the first object has ceased to exist + +Rule 18.7 Required +Flexible array members shall not be declared + +Rule 18.8 Required +Variable-length array types shall not be used + +Rule 18.9 Required +An object with temporary lifetime shall not undergo array-to-pointer conversion + +Rule 18.10 Mandatory +Pointers to variably-modified array types shall not be used + +Rule 19.1 Mandatory +An object shall not be assigned or copied to an overlapping object + +Rule 19.2 Advisory +The union keyword should not be used + +Rule 20.1 Advisory +#include directives should only be preceded by preprocessor directives or comments + +Rule 20.2 Required +The ', " or \ characters and the /* or // character sequences shall not occur in a header file name + +Rule 20.3 Required +The #include directive shall be followed by either a "filename" or "filename" sequence + +Rule 20.4 Required +A macro shall not be defined with the same name as a keyword + +Rule 20.5 Advisory +#undef should not be used + +Rule 20.6 Required +A C macro should only be expanded to a constant, a braced initialiser, a parenthesised expression, a storage class keyword, a type qualifier, or a do-while-zero block + +Rule 20.7 Required +Expressions resulting from the expansion of macro parameters shall be enclosed in parentheses + +Rule 20.8 Required +The controlling expression of a #if or #elif preprocessing directive shall evaluate to 0 or 1 + +Rule 20.9 Required +All identifiers used in the controlling expression of #if or #elif preprocessing directives shall be #define’d before evaluation + +Rule 20.10 Advisory +The # and ## preprocessor operators should not be used + +Rule 20.11 Required +A macro parameter immediately following a # operator shall not immediately be followed by a ## operator + +Rule 20.12 Required +A macro parameter used as an operand to the # or ## operators, which is itself subject to further macro replacement, shall only be used as an operand to these operators + +Rule 20.13 Required +A line whose first token is # shall be a valid preprocessing directive + +Rule 20.14 Required +All #else, #elif and #endif preprocessor directives shall reside in the same file as the #if, #ifdef or #ifndef directive to which they are related + +Rule 21.1 Required +#define and #undef shall not be used on a reserved identifier or reserved macro name + +Rule 21.2 Required +A reserved identifier or macro name shall not be declared + +Rule 21.3 Required +The memory allocation and deallocation functions of "stdlib.h" shall not be used + +Rule 21.4 Required +The standard header file "setjmp.h" shall not be used + +Rule 21.5 Required +The standard header file "signal.h" shall not be used + +Rule 21.6 Required +The Standard Library input/output functions shall not be used + +Rule 21.7 Required +The atof, atoi, atol and atoll functions of "stdlib.h" shall not be used + +Rule 21.8 Required +The Standard Library termination functions of "stdlib.h" shall not be used + +Rule 21.9 Required +The library functions bsearch and qsort of "stdlib.h" shall not be used + +Rule 21.10 Required +The Standard Library time and date functions shall not be used + +Rule 21.11 Required +The standard header file "tgmath.h" shall not be used + +Rule 21.12 Advisory +The exception handling features of "fenv.h" should not be used + +Rule 21.13 Mandatory +Any value passed to a function in "ctype.h" shall be representable as an unsigned char or be the value EOF + +Rule 21.14 Required +The Standard Library function memcmp shall not be used to compare null terminated strings + +Rule 21.15 Required +The pointer arguments to the Standard Library functions memcpy, memmove and memcmp shall be pointers to qualified or unqualified versions of compatible types + +Rule 21.16 Required +The pointer arguments to the Standard Library function memcmp shall point to either a pointer type, an essentially signed type, an essentially unsigned type, an essentially Boolean type or an essentially enum type + +Rule 21.17 Mandatory +Use of the string handling functions from "string.h" shall not result in accesses beyond the bounds of the objects referenced by their pointer parameters + +Rule 21.18 Mandatory +The size_t argument passed to any function in "string.h" shall have an appropriate value + +Rule 21.19 Mandatory +The pointers returned by the Standard Library functions localeconv, getenv, setlocale or, strerror shall only be used as if they have pointer to const-qualified type + +Rule 21.20 Mandatory +The pointer returned by the Standard Library functions asctime, ctime, gmtime, localtime, localeconv, getenv, setlocale or strerror shall not be used following a subsequent call to the same function + +Rule 21.21 Required +The Standard Library function system of "stdlib.h" shall not be used + +Rule 21.22 Mandatory +All operand arguments to any type-generic macros declared in "tgmath.h" shall have an appropriate essential type + +Rule 21.23 Required +All operand arguments to any multi-argument type-generic macros declared in "tgmath.h" shall have the same standard type + +Rule 21.24 Required +The random number generator functions of "stdlib.h" shall not be used + +Rule 21.25 Required +All memory synchronization operations shall be executed in sequentially consistent order + +Rule 21.26 Required +The Standard Library function mtx_timedlock() shall only be invoked on mutex objects of appropriate mutex type + +Rule 22.1 Required +All resources obtained dynamically by means of Standard Library functions shall be explicitly released + +Rule 22.2 Mandatory +A block of memory shall only be freed if it was allocated by means of a Standard Library function + +Rule 22.3 Required +The same file shall not be open for read and write access at the same time on different streams + +Rule 22.4 Mandatory +There shall be no attempt to write to a stream which has been opened as read-only + +Rule 22.5 Mandatory +A pointer to a FILE object shall not be dereferenced + +Rule 22.6 Mandatory +The value of a pointer to a FILE shall not be used after the associated stream has been closed + +Rule 22.7 Required +The macro EOF shall only be compared with the unmodified return value from any Standard Library function capable of returning EOF + +Rule 22.8 Required +The value of errno shall be set to zero prior to a call to an errno-setting-function + +Rule 22.9 Required +The value of errno shall be tested against zero after calling an errno-setting-function + +Rule 22.10 Required +The value of errno shall only be tested when the last function to be called was an errno-setting-function + +Rule 22.11 Required +A thread that was previously either joined or detached shall not be subsequently joined nor detached + +Rule 22.12 Mandatory +Thread objects, thread synchronization objects, and thread-specific storage pointers shall only be accessed by the appropriate Standard Library functions + +Rule 22.13 Required +Thread objects, thread synchronization objects and thread-specific storage pointers shall have appropriate storage duration + +Rule 22.14 Mandatory +Thread synchronization objects shall be initialized before being accessed + +Rule 22.15 Required +Thread synchronization objects and thread-specific storage pointers shall not be destroyed until after all threads accessing them have terminated + +Rule 22.16 Required +All mutex objects locked by a thread shall be explicitly unlocked by the same thread + +Rule 22.17 Required +No thread shall unlock a mutex or call cnd_wait() or cnd_timedwait() for a mutex it has not locked before + +Rule 22.18 Required +Non-recursive mutexes shall not be recursively locked + +Rule 22.19 Required +A condition variable shall be associated with at most one mutex object + +Rule 22.20 Mandatory +Thread-specific storage pointers shall be created before being accessed + +Rule 23.1 Advisory +A generic selection should only be expanded from a macro + +Rule 23.2 Required +A generic selection that is not expanded from a macro shall not contain potential side effects in the controlling expression + +Rule 23.3 Advisory +A generic selection should contain at least one non-default association + +Rule 23.4 Required +A generic association shall list an appropriate type + +Rule 23.5 Advisory +A generic selection should not depend on implicit pointer type conversion + +Rule 23.6 Required +The controlling expression of a generic selection shall have an essential type that matches its standard type + +Rule 23.7 Advisory +A generic selection that is expanded from a macro should evaluate its argument only once + +Rule 23.8 Required +A default association shall appear as either the first or the last association of a generic selection + diff --git a/libraries/CAN/Makefile b/libraries/CAN/Makefile index 87f800fa..47afeaa9 100644 --- a/libraries/CAN/Makefile +++ b/libraries/CAN/Makefile @@ -1,20 +1,23 @@ FQBN ?= PORT ?= TESTS ?= +UNITY_PATH ?= +BAUD_RATE ?= 115200 $(info FQBN : $(FQBN)) $(info PORT : $(PORT)) +$(info UNITY_PATH : $(UNITY_PATH)) +$(info BAUD_RATE : $(BAUD_RATE)) -TESTS_CONNECTED=-DTEST_CAN_CONNECTED - +TESTS_CONNECTED=-DTEST_CAN_CONNECTED TESTS_NOT_CONNECTED=-DTEST_CAN - -CAN_connected: TESTS=-DTEST_CAN -DTEST_CAN_CONNECTED CAN: TESTS=-DTEST_CAN - -CAN_connected CAN: unity flash +CAN_connected: TESTS=-DTEST_CAN -DTEST_CAN_CONNECTED +CAN_connected_node1: TESTS=-DTEST_CAN_CONNECTED_NODE1 +CAN_connected_node2: TESTS=-DTEST_CAN_CONNECTED_NODE2 +CAN_connected CAN CAN_connected_node1 CAN_connected_node2: unity_corelibs flash test_all: TESTS=$(TESTS_CONNECTED) $(TESTS_NOT_CONNECTED) test_connected: TESTS=$(TESTS_CONNECTED) @@ -22,25 +25,22 @@ test: TESTS=$(TESTS_NOT_CONNECTED) test_all \ test_connected \ -test: unity flash +test: unity_corelibs flash -EXAMPLES = CANReceiver CANReceiverCallback CANSender - +EXAMPLES= CANReceiver CANReceiverCallback CANSender CANLoopBack clean: -rm -rf build/* - arduino: clean mkdir -p build -# copy library file -# cp -r libraries/CAN/* build -# find src -name '*.[hc]*' -a \( \! -name 'main*' \) -print -exec cp {} build \; - - +# copy library files (not needed for bundled libraries) +# cp -r src/* build +# find src -name '*.[hc]*' -a \( \! -name '*mtb*' \) -print -exec cp {} build \; +.PHONY: CANReceiver CANReceiverCallback CANSender CANLoopBack CANReceiver: arduino - cp examples/CANReceiver/CANReceiver.ino build/build.ino + cp examples/CANReceiver/CANReceiver.ino build/build.ino CANReceiverCallback: arduino cp examples/CANReceiverCallback/CANReceiverCallback.ino build/build.ino @@ -48,20 +48,20 @@ CANReceiverCallback: arduino CANSender: arduino cp examples/CANSender/CANSender.ino build/build.ino -# master1: -# ... +CANLoopBack: arduino + cp examples/CANLoopBack/CANLoopBack.ino build/build.ino -# slave1: -# ... +# install Unity from https://www.throwtheswitch.org/unity or git +unity_corelibs: arduino +ifeq ($(UNITY_PATH),) + $(error "Must set variable UNITY_PATH in order to be able to compile Arduino unit tests !") +else + find $(UNITY_PATH) -name '*.[hc]' \( -path '*extras*' -a -path '*src*' -or -path '*src*' -a \! -path '*example*' \) -exec \cp {} build \; + find test/unit -name '*.[hc]*' -a \! -path '*mtb*' -a \! -path '*applibs*' -exec \cp {} build \; + cp test/unit/src/framework/arduino/corelibs/Test_main.ino build/build.ino +endif -# old unity setup part. -# TODO: Add unit test -#unity: arduino -# cp -r test/unit/Unity/*.[hc] build -# cp test/unit/src/framework/arduino/Test_*.[hc]* build -# cp test/unit/src/framework/arduino/unity_ifx.cpp build -# cp test/unit/src/framework/arduino/Test_main.ino build/build.ino # For WSL and Windows : @@ -72,23 +72,35 @@ ifeq ($(FQBN),) else # CAUTION : only use '=' when assigning values to vars, not '+=' arduino-cli.exe compile --clean --log --warnings all --fqbn $(FQBN) --build-property "compiler.c.extra_flags=\"-DUNITY_INCLUDE_CONFIG_H=1\"" \ - --build-property compiler.cpp.extra_flags="$(TESTS)" \ - --build-property compiler.ar.cmd=arm-none-eabi-gcc-ar \ - --build-property compiler.libraries.ldflags=-lstdc++ \ - --build-property compiler.arm.cmsis.path="-isystem{compiler.xmclib_include.path}/XMCLib_CAN_v4_3_0/inc -isystem{compiler.xmclib_include.path}/XMCLib/inc -isystem{compiler.dsp_include.path} -isystem{compiler.nn_include.path} -isystem{compiler.cmsis_include.path} -isystem{compiler.xmclib_include.path}/LIBS -isystem{build.variant.path} -isystem{build.variant.config_path}" \ - --build-property compiler.usb.path="-isystem{runtime.platform.path}/cores/usblib -isystem{runtime.platform.path}/cores/usblib/Common -isystem{runtime.platform.path}/cores/usblib/Class -isystem{runtime.platform.path}/cores/usblib/Class/Common -isystem{runtime.platform.path}/cores/usblib/Class/Device -isystem{runtime.platform.path}/cores/usblib/Core -isystem{runtime.platform.path}/cores/usblib/Core/XMC4000" \ - build + --build-property compiler.cpp.extra_flags="$(TESTS)" build endif -upload: +compileLTO: +ifeq ($(FQBN),) + $(error "Must set variable FQBN in order to be able to compile Arduino sketches !") +else +# compiler.c.extra_flags : switch to -std=c23 whenever XMCLib is conforming; currently neither c99 nor c11 work ! +# CAUTION : only use '=' when assigning values to vars, not '+=' + arduino-cli.exe compile --clean --log --warnings all --fqbn $(FQBN) \ + --build-property compiler.c.extra_flags="\"-DUNITY_INCLUDE_CONFIG_H=1\" -DNDEBUG -flto -fno-fat-lto-objects -Wextra -Wall -Wfloat-equal -Wconversion -Wredundant-decls -Wswitch-default -Wdouble-promotion -Wpedantic -Wunreachable-code -fanalyzer -std=c20 " \ + --build-property compiler.cpp.extra_flags="$(TESTS) -DNDEBUG -flto -fno-fat-lto-objects -Wextra -Wall -Wfloat-equal -Wconversion -Wredundant-decls -Wswitch-default -Wdouble-promotion -Wpedantic -Wunreachable-code -fanalyzer -std=c++20 " \ + --build-property compiler.ar.cmd=arm-none-eabi-gcc-ar \ + --build-property compiler.libraries.ldflags=-lstdc++ \ + --build-property compiler.arm.cmsis.path="-isystem{compiler.xmclib_include.path}/XMCLib/inc -isystem{compiler.dsp_include.path} -isystem{compiler.nn_include.path} -isystem{compiler.cmsis_include.path} -isystem{compiler.xmclib_include.path}/LIBS -isystem{build.variant.path} -isystem{build.variant.config_path}" \ + --build-property compiler.usb.path="-isystem{runtime.platform.path}/cores/usblib -isystem{runtime.platform.path}/cores/usblib/Common -isystem{runtime.platform.path}/cores/usblib/Class -isystem{runtime.platform.path}/cores/usblib/Class/Common -isystem{runtime.platform.path}/cores/usblib/Class/Device -isystem{runtime.platform.path}/cores/usblib/Core -isystem{runtime.platform.path}/cores/usblib/Core/XMC4000" \ + build +endif + + +upload: compile ifeq ($(PORT),) $(error "Must set variable PORT (Windows port naming convention, ie COM16) in order to be able to flash Arduino sketches !") endif ifeq ($(FQBN),) $(error "Must set variable FQBN in order to be able to flash Arduino sketches !") else - arduino-cli.exe upload -p $(PORT) --fqbn $(FQBN) build + arduino-cli.exe upload -p $(PORT) --fqbn $(FQBN) --verbose build endif @@ -102,5 +114,6 @@ endif ifeq ($(FQBN),) $(error "Must set variable FQBN in order to be able to flash Arduino sketches !") else - arduino-cli.exe monitor -c baudrate=9600 -p $(PORT) --fqbn $(FQBN) + arduino-cli.exe monitor -c baudrate=$(BAUD_RATE) -p $(PORT) --fqbn $(FQBN) endif + diff --git a/libraries/CAN/Makefile.codecheck b/libraries/CAN/Makefile.codecheck new file mode 100644 index 00000000..5dee7388 --- /dev/null +++ b/libraries/CAN/Makefile.codecheck @@ -0,0 +1,12 @@ +#Run Clang-format for c/c++ code. +make -f Makefile.codechecks.mk clang-format + +#Run Clang-tidy +make -f Makefile.codechecks.mk clang-tidy-src + +make -f Makefile.codechecks.mk clang-tidy-test + +#Run cppcheck +make -f Makefile.codechecks.mk cppcheck + + diff --git a/libraries/CAN/Makefile.codechecks.mk b/libraries/CAN/Makefile.codechecks.mk new file mode 100644 index 00000000..6c13ae28 --- /dev/null +++ b/libraries/CAN/Makefile.codechecks.mk @@ -0,0 +1,61 @@ + +WIN_USER ?= +CONFIG_DIR := ../../config +CORE_LIB_DIR := ../../cores + + +CLANG_FORMAT_DIR := $(CONFIG_DIR)/clang-format +CLANG_TIDY_DIR := $(CONFIG_DIR)/clang-tidy + + +#################################### clang-format code formatter +### Need to install clang-tidy + +clang-format: + + clang-format -i -style=file:$(CLANG_FORMAT_DIR)/.clang-format $(shell find src -name \*.[hc]\*) + + + +##TODO: add compilation database for builtin libraries! +#################################### clang-tidy static code checker + +clang-tidy-test: C_CPP_SOURCES = $(shell find test -name \*.[hc]\*) +clang-tidy-src: C_CPP_SOURCES = $(shell find src -name \*.[hc]\*) + +clang-tidy-test clang-tidy-src : clang-tidy + +clang-tidy: + $(info $(C_CPP_SOURCES)) + clang-tidy $(C_CPP_SOURCES) --config-file=$(CLANG_TIDY_DIR)/.clang-tidy -header-filter='' -- -Isrc/framework/arduino -Itest/unit/src/framework/arduino/corelibs -I$(CORE_LIB_DIR) > clang-tidy-report.txt + + + +#################################### scan-build static code checker #TODO: still using foo example +### After executing the scan-build target run the command scan-view as printed in the scan-build output last line. +### Or use firefox directly. +scan-build: + scan-build -o scan-build-reports make -f Makefile.codechecks.mk foo + firefox scan-build-reports/ + +foo: + $(CC) -c -Wextra -Wall -Wfloat-equal -Wconversion -Wredundant-decls -Wswitch-default -Wdouble-promotion -Wpedantic -Wunreachable-code -std=c++20 $(CONFIG_DIR)/sca/foo.cpp -o foo.o + + + +#################################### cppcheck static code checker +### Requirement : install cppcheck from https://github.com/danmar/cppcheck +cppcheck: C_CPP_SOURCES = ./src + +CPPCHECK_PATH = ~/cppcheck/cppcheck + +cppcheck: + export RULE_TEXTS=$(CONFIG_DIR)/cppcheck/misra.txt + $(CPPCHECK_PATH)/build/bin/cppcheck -i build -i examples -i test \ + -I$(C_CPP_SOURCES) \ + --check-level=exhaustive --enable=all --inconclusive \ + --addon=config/cppcheck/misra.json --addon=misc --std=c++20 \ + --checkers-report=cppcheck.checkers --xml --max-configs=50 2> ./err.xml + $(CPPCHECK_PATH)/htmlreport/cppcheck-htmlreport --file=err.xml --title=TestCPPCheck --report-dir=cppcheck-reports --source-dir=. + firefox cppcheck-reports/index.html + diff --git a/libraries/CAN/Makefile.test b/libraries/CAN/Makefile.test index 44e22ff2..55d033f4 100644 --- a/libraries/CAN/Makefile.test +++ b/libraries/CAN/Makefile.test @@ -3,25 +3,31 @@ ### Example program ## XMC4700_Relax_Kit -make FQBN=Infineon:xmc:XMC4700_Relax_Kit PORT=COM20 CANReceiver flash monitor +make FQBN=Infineon:xmc:XMC4700_Relax_Kit PORT=COM20 CANReceiver flash monitor # CAN Receive has some problem for XMC4700. -make FQBN=Infineon:xmc:XMC4700_Relax_Kit PORT=COM20 CANReceiverCallback flash monitor +make FQBN=Infineon:xmc:XMC4700_Relax_Kit PORT=COM20 CANReceiverCallback flash monitor # CAN Receive has some problem for XMC4700. -make FQBN=Infineon:xmc:XMC4700_Relax_Kit PORT=COM24 CANSender flash monitor +make FQBN=Infineon:xmc:XMC4700_Relax_Kit PORT=COM24 CANSender flash monitor make FQBN=Infineon:xmc:XMC4700_Relax_Kit PORT=COM24 CANLoopBack flash monitor ## XMC1400_XMC2GO -make FQBN=Infineon:xmc:XMC1400_XMC2GO PORT=COM41 CANReceiver flash monitor +make FQBN=Infineon:xmc:XMC1400_XMC2GO BAUD_RATE=9600 PORT=COM41 CANReceiver flash monitor -make FQBN=Infineon:xmc:XMC1400_XMC2GO PORT=COM41 CANReceiverCallback flash monitor +make FQBN=Infineon:xmc:XMC1400_XMC2GO BAUD_RATE=9600 PORT=COM41 CANReceiverCallback flash monitor -make FQBN=Infineon:xmc:XMC1400_XMC2GO PORT=COM42 CANSender flash monitor +make FQBN=Infineon:xmc:XMC1400_XMC2GO BAUD_RATE=9600 PORT=COM42 CANSender flash monitor -make FQBN=Infineon:xmc:XMC1400_XMC2GO PORT=COM42 CANLoopBack flash monitor +make FQBN=Infineon:xmc:XMC1400_XMC2GO BAUD_RATE=9600 PORT=COM42 CANLoopBack flash monitor ### Unit tests -make FQBN=Infineon:xmc:XMC4700_Relax_Kit PORT=COM20 CAN monitor +make FQBN=Infineon:xmc:XMC1400_XMC2GO PORT=COM42 UNITY_PATH=/home/zhanglinjing/repo/Unity CAN test-monitor -make FQBN=Infineon:xmc:XMC1100_XMC2GO PORT=COM21 CAN_connected monitor +make FQBN=Infineon:xmc:XMC1400_XMC2GO PORT=COM42 UNITY_PATH=/home/zhanglinjing/repo/Unity CAN_connected_node2 monitor + +make FQBN=Infineon:xmc:XMC1400_XMC2GO PORT=COM41 UNITY_PATH=/home/zhanglinjing/repo/Unity CAN_connected_node1 monitor + +make FQBN=Infineon:xmc:XMC1400_XMC2GO PORT=COM42 UNITY_PATH=/home/zhanglinjing/repo/Unity CAN_connected monitor + +make FQBN=Infineon:xmc:XMC4700_Relax_Kit PORT=COM20 UNITY_PATH=/home/zhanglinjing/repo/Unity CAN test-monitor \ No newline at end of file diff --git a/libraries/CAN/src/CANController.cpp b/libraries/CAN/src/CANController.cpp index df4bb3f9..f341435b 100644 --- a/libraries/CAN/src/CANController.cpp +++ b/libraries/CAN/src/CANController.cpp @@ -1,6 +1,6 @@ // Copyright (c) Sandeep Mistry. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license -// information. +// Licensed under the MIT license. See LICENSE file in the project root for full +// license information. #include "CANController.h" CANControllerClass::CANControllerClass() diff --git a/libraries/CAN/src/CANController.h b/libraries/CAN/src/CANController.h index 6d914279..b89e1872 100644 --- a/libraries/CAN/src/CANController.h +++ b/libraries/CAN/src/CANController.h @@ -56,9 +56,9 @@ class CANControllerClass : public Stream { bool _packetBegun; long _txId; bool _txExtended; - bool _txRtr; - int _txDlc; - int _txLength; + bool _txRtr; // if it Remote Transmission Request + int _txDlc; // DLC: Data Length Code specifies number of bytes in the data field + int _txLength; // index of txData uint8_t _txData[8]; long _rxId; diff --git a/libraries/CAN/src/CANXMC.cpp b/libraries/CAN/src/CANXMC.cpp index 69ef539f..91ab1ff5 100644 --- a/libraries/CAN/src/CANXMC.cpp +++ b/libraries/CAN/src/CANXMC.cpp @@ -1,55 +1,73 @@ #include "CANXMC.h" #include -/* CAN Receive Message Object definition, can also be used for transmit remote - * frame*/ -XMC_CAN_MO_t CAN_msg_rx = { - .can_mo_ptr = (CAN_MO_TypeDef *)CAN_MO0, - {0xFF, XMC_CAN_FRAME_TYPE_STANDARD_11BITS, // {can_identifier, can_id_mode - XMC_CAN_ARBITRATION_MODE_ORDER_BASED_PRIO_1}, // can_priority} - {0x000, 1U}, // {can_id_mask, can_ide_mask} - .can_data_length = 0U, - .can_mo_type = XMC_CAN_MO_TYPE_RECMSGOBJ, -}; - -/* CAN Transmit Message Object definition */ -XMC_CAN_MO_t CAN_msg_tx = { - .can_mo_ptr = (CAN_MO_TypeDef *)CAN_MO1, - {0xFF, XMC_CAN_FRAME_TYPE_STANDARD_11BITS, // {can_identifier, can_id_mode - XMC_CAN_ARBITRATION_MODE_ORDER_BASED_PRIO_1}, // can_priority} - {0x7FFU, 1U}, // {can_id_mask, can_ide_mask} - .can_data_length = 0U, - .can_mo_type = XMC_CAN_MO_TYPE_TRANSMSGOBJ, -}; - /* Flag for receive interrupt*/ static volatile bool can_frame_received = false; /* construct with configuration of different target */ -CANXMC::CANXMC(XMC_ARD_CAN_t *conf) { _XMC_CAN_config = conf; } +CANXMC::CANXMC(XMC_ARD_CAN_t *conf) : _XMC_CAN_config(conf) { + memset(&CAN_msg_rx, 0, sizeof(CAN_msg_rx)); + memset(&CAN_msg_tx, 0, sizeof(CAN_msg_tx)); + + /* CAN Transmit Message Object definition */ + + CAN_msg_tx.can_mo_ptr = (CAN_MO_TypeDef *)CAN_MO1; + CAN_msg_tx.can_identifier = 0xFFFU; + CAN_msg_tx.can_id_mode = XMC_CAN_FRAME_TYPE_STANDARD_11BITS; // Extended ID mode + CAN_msg_tx.can_priority = XMC_CAN_ARBITRATION_MODE_ORDER_BASED_PRIO_1; // Priority level 1 + CAN_msg_tx.can_id_mask = 0x00000000U; // Identifier mask + CAN_msg_tx.can_ide_mask = 0U; // Identifier extension mask + CAN_msg_tx.can_data_length = 0U; // Data length of 0 + CAN_msg_tx.can_mo_type = XMC_CAN_MO_TYPE_TRANSMSGOBJ; // Message Object type + + + /* CAN Receive Message Object definition, can also be used for transmit remote + * frame*/ + CAN_msg_rx.can_mo_ptr = (CAN_MO_TypeDef *)CAN_MO0; + CAN_msg_rx.can_identifier = 0xFFFU; + CAN_msg_rx.can_id_mode = XMC_CAN_FRAME_TYPE_STANDARD_11BITS; + CAN_msg_rx.can_priority = XMC_CAN_ARBITRATION_MODE_ORDER_BASED_PRIO_1; + CAN_msg_rx.can_id_mask = 0x00000000U; + CAN_msg_rx.can_ide_mask = 0U; + CAN_msg_rx.can_data_length = 0U; + CAN_msg_rx.can_mo_type = XMC_CAN_MO_TYPE_RECMSGOBJ; +} + + +CANXMC::~CANXMC() { end(); } -CANXMC::~CANXMC() {} +/* Getter function for CAN_msg_tx */ +XMC_CAN_MO_t *CANXMC::getTxMessage() { return &CAN_msg_tx; } +/* Getter function for CAN_msg_rx */ +XMC_CAN_MO_t *CANXMC::getRxMessage() { return &CAN_msg_rx; } + +/* int CANXMC::setIdentifier(long id) { // TODO: delete in the future! // figure out filtering problem for xmc4700 XMC_CAN_MO_SetIdentifier(&CAN_msg_rx, id); return 0; }; +*/ /** * @brief Initializes the CAN interface with the specified baudrate. * - * This function configures the CAN bit time, enables the CAN node, and sets up the necessary pin - * configurations. + * This function configures the CAN bit time, enables the CAN node, and sets up + * the necessary pin configurations. * - * @param baudrate The desired baudrate for the CAN interface. The default value is 500,000 bps. + * @param baudRate The desired baudrate for the CAN interface. The default value + * is 500,000 bps. * @return Returns 1 if the initialization is successful, 0 otherwise. */ -int CANXMC::begin(long baudrate /*= 500e3*/) { +int CANXMC::begin(long baudRate /*= 500e3*/) { + /* reset CAN nodes*/ + XMC_CAN_Disable(CAN_xmc); + /* CAN bit time configuration*/ XMC_CAN_NODE_NOMINAL_BIT_TIME_CONFIG_t CAN_NODE_bit_time_config = { .can_frequency = _XMC_CAN_config->can_frequency, - .baudrate = (uint32_t)baudrate, + .baudrate = (uint32_t)baudRate, .sample_point = (uint16_t)(80 * 100), .sjw = (uint16_t)1, }; @@ -106,8 +124,9 @@ int CANXMC::begin(long baudrate /*= 500e3*/) { /** * @brief Disables the CAN module and ends the CANXMC object. * - * This function disables the CAN module and ends the CANXMC object. It disables the receive event - * for the CAN message object and disables the CAN module using the XMC_CAN_Disable function. + * This function disables the CAN module and ends the CANXMC object. It disables + * the receive event for the CAN message object and disables the CAN module + * using the XMC_CAN_Disable function. */ void CANXMC::end() { XMC_CAN_MO_DisableEvent(&CAN_msg_rx, XMC_CAN_MO_EVENT_RECEIVE); @@ -174,14 +193,14 @@ int CANXMC::endPacket() { /** * @brief Parses a CAN packet received by the XMC_CAN module. * - * This function waits until a new CAN packet is available in the receive buffer, - * then retrieves the packet information such as the identifier, frame type, remote - * transmission request (RTR), data length code (DLC), and data payload. If the packet - * is an extended frame, the `_rxExtended` flag is set to true. If the packet is an RTR - * frame, the `_rxRtr` flag is set to true and the `_rxLength` is set to 0. Otherwise, - * the `_rxLength` is set to the DLC and the data payload is copied to the `_rxData` - * buffer. Finally, the function resets the receive flag and returns the length of the - * received packet. + * This function waits until a new CAN packet is available in the receive + * buffer, then retrieves the packet information such as the identifier, frame + * type, remote transmission request (RTR), data length code (DLC), and data + * payload. If the packet is an extended frame, the `_rxExtended` flag is set to + * true. If the packet is an RTR frame, the `_rxRtr` flag is set to true and the + * `_rxLength` is set to 0. Otherwise, the `_rxLength` is set to the DLC and the + * data payload is copied to the `_rxData` buffer. Finally, the function resets + * the receive flag and returns the length of the received packet. * * @return The length of the received packet. */ @@ -220,9 +239,9 @@ int CANXMC::parsePacket() { /** * Sets the callback function to be called when a CAN message is received. * - * @param callback A pointer to the function to be called when a CAN message is received. - * The function should take an integer parameter. - * Pass nullptr to disable the callback. + * @param callback A pointer to the function to be called when a CAN message is + * received. The function should take an integer parameter. Pass nullptr to + * disable the callback. */ void CANXMC::onReceive(void (*callback)(int)) { CANControllerClass::onReceive(callback); @@ -269,9 +288,15 @@ int CANXMC::observe() { return 0; }; +/** + * Puts the CAN module into loopback mode. + * This function puts the CAN module into loopback mode by enabling the loopback + * mode for both CAN nodes. It also initializes the CAN message objects for + * loopback mode. + * @return true if the CAN module is successfully put into loopback mode, false + * otherwise. + */ int CANXMC::loopback() { - // TODO: LJ: It is actually only some application level... it is not - // library... /* reset CAN nodes*/ XMC_CAN_Disable(CAN_xmc); @@ -327,31 +352,34 @@ int CANXMC::loopback() { } }; - /** * Puts the CAN module into sleep mode. - * This function disables the CAN module by setting the EDIS bit in the CLC register. - * @return true if the CAN module is successfully put into sleep mode, false otherwise. + * This function disables the CAN module by setting the EDIS bit in the CLC + * register. + * @return 1 if the CAN module is successfully put into sleep mode, 0 + * otherwise. */ -int CANXMC::sleep() { - CAN_xmc -> CLC |= CAN_CLC_EDIS_Msk; - return CAN_xmc -> CLC & CAN_CLC_EDIS_Msk != 0; +int CANXMC::sleep() { + CAN_xmc->CLC |= CAN_CLC_EDIS_Msk; + return CAN_xmc->CLC & CAN_CLC_EDIS_Msk != 0 ? 1 : 0; }; /** * @brief Wakes up the CAN module. - * This function is used to wake up the CAN module by clearing the EDIS bit in the CLC register. - * @return true if the CAN module is successfully woken up, false otherwise. + * This function is used to wake up the CAN module by clearing the EDIS bit in + * the CLC register. + * @return 1 if the CAN module is successfully woken up, 0 otherwise. */ -int CANXMC::wakeup() { - CAN_xmc -> CLC &= CAN_CLC_EDIS_Msk; - return CAN_xmc -> CLC & CAN_CLC_EDIS_Msk == 0; +int CANXMC::wakeup() { + CAN_xmc->CLC &= ~CAN_CLC_EDIS_Msk; + return CAN_xmc->CLC & CAN_CLC_EDIS_Msk == 0 ? 1 : 0; }; /** - * @brief This function is called when an interrupt is triggered for the CANXMC module. - * It checks if a CAN frame has been received and if so, it parses the packet and - * calls the _onReceive() function with the number of available frames. + * @brief This function is called when an interrupt is triggered for the CANXMC + * module. It checks if a CAN frame has been received and if so, it parses the + * packet and calls the _onReceive() function with the number of available + * frames. */ void CANXMC::onInterrupt() { if (can_frame_received == true) { @@ -362,13 +390,15 @@ void CANXMC::onInterrupt() { /* Interrupt Handler */ /** - * @brief Interrupt handler for CAN0_7_IRQHandler (XMC4 series) or CAN0_3_IRQHandler (XMC1 series). + * @brief Interrupt handler for CAN0_7_IRQHandler (XMC4 series) or + * CAN0_3_IRQHandler (XMC1 series). * - * This function is called when a CAN frame is received. It sets the can_frame_received flag to true - * and calls the onInterrupt() function of the CAN object. + * This function is called when a CAN frame is received. It sets the + * can_frame_received flag to true and calls the onInterrupt() function of the + * CAN object. * - * @note This function is intended to be used as an interrupt handler and should not be called - * directly. + * @note This function is intended to be used as an interrupt handler and should + * not be called directly. */ extern "C" { #if (UC_FAMILY == XMC4) diff --git a/libraries/CAN/src/CANXMC.h b/libraries/CAN/src/CANXMC.h index 9e63e43c..26125512 100644 --- a/libraries/CAN/src/CANXMC.h +++ b/libraries/CAN/src/CANXMC.h @@ -28,8 +28,14 @@ class CANXMC : public CANControllerClass { int setIdentifier(long); static void onInterrupt(); + // Getter functions for CAN_msg_rx and CAN_msg_tx + XMC_CAN_MO_t *getRxMessage(); + XMC_CAN_MO_t *getTxMessage(); + private: XMC_ARD_CAN_t *_XMC_CAN_config; + XMC_CAN_MO_t CAN_msg_rx; + XMC_CAN_MO_t CAN_msg_tx; }; extern CANXMC CAN; \ No newline at end of file diff --git a/libraries/CAN/test/unit/src/Test_common_includes.h b/libraries/CAN/test/unit/src/Test_common_includes.h new file mode 100644 index 00000000..e806fba5 --- /dev/null +++ b/libraries/CAN/test/unit/src/Test_common_includes.h @@ -0,0 +1,21 @@ +#ifndef TEST_COMMON_INCLUDES_H +#define TEST_COMMON_INCLUDES_H + + +// std includes +#include + + +// project c includes + + +// test includes +// Unity c includes +#include "unity.h" +#include "unity_fixture.h" + +// IFX Unity addons +#include "unity_ifx.h" + + +#endif // TEST_COMMON_INCLUDES_H diff --git a/libraries/CAN/test/unit/src/features/Test_CAN.hpp b/libraries/CAN/test/unit/src/features/Test_CAN.hpp new file mode 100644 index 00000000..1b6d0808 --- /dev/null +++ b/libraries/CAN/test/unit/src/features/Test_CAN.hpp @@ -0,0 +1,173 @@ +// std includes + +// test includes +#include "Test_includes.hpp" + +// project includes + + +void CAN_suiteSetUp(void); +void CAN_suiteTearDown(void); + + +// variables used in the tests below that have to be accessed in the setup and tear down methods +extern CANXMC CAN; + +// test includes that may require dut + + +// define test group name +TEST_GROUP(CAN); +TEST_GROUP(CAN_internal); + + +// Setup method called before every individual test defined for this test group +static TEST_SETUP(CAN_internal) +{ +} + + +// Tear down method called before every individual test defined for this test group +static TEST_TEAR_DOWN(CAN_internal) +{ +} + + +// Functionality not - yet - supported +TEST_IFX(CAN_internal, checkUnsupportedFunctionality) +{ + TEST_ASSERT_FALSE(CAN.observe() ); + // TEST_ASSERT_TRUE(CAN.packetRtr() ); Remote frame not tested +} + + +TEST_IFX(CAN_internal, checkSupportedFunctionality) +{ + /*TODO: How to test this? + TEST_ASSERT_TRUE(CAN.begin() ); + // TEST_ASSERT_TRUE(CAN.end() ); + // TEST_ASSERT_TRUE(CAN.endPacket() ); // need to configure + // TEST_ASSERT_TRUE(CAN.parsePacket() ); // return value + // TEST_ASSERT_TRUE(CAN.onReceive(0) ); // void + TEST_ASSERT_TRUE(CAN.filter(0x12, 0x7FF) ); + TEST_ASSERT_TRUE(CAN.filterExtended(0x12345678, 0x1FFFFFFF) ); + + TEST_ASSERT_TRUE(CAN.loopback() ); + + // TEST_ASSERT_TRUE(CAN.setIdentifier(0x123) ); // need to be deleted in the future + TEST_ASSERT_TRUE(CAN.beginPacket(0x12, 8, false) ); + TEST_ASSERT_TRUE(CAN.beginExtendedPacket(0xFFF, 8, false) ); + + TEST_ASSERT_TRUE(CAN.available() ); + TEST_ASSERT_TRUE(CAN.read() ); + TEST_ASSERT_TRUE(CAN.peek() ); + // TEST_ASSERT_TRUE(CAN.flush() ); // void + TEST_ASSERT_TRUE(CAN.write(0x12) ); + TEST_ASSERT_TRUE(CAN.write((uint8_t*)0x12, 1) ); + + TEST_ASSERT_TRUE(CAN.sleep() ); + + // TEST_ASSERT_TRUE(CAN.onInterrupt() ); // void + // TEST_ASSERT_TRUE(CAN.packetDlc() ); + // TEST_ASSERT_TRUE(CAN.packetExtended() ); + // TEST_ASSERT_TRUE(CAN.packetId() ); + */ +} + +// Test case for CAN_msg_tx initialization +void test_CAN_msg_tx_initialization(void) +{ + // Get the Tx message object + XMC_CAN_MO_t* txMessage = CAN.getTxMessage(); + + // Verify that the Tx message object is correctly initialized + TEST_ASSERT_NOT_NULL(txMessage); + TEST_ASSERT_EQUAL_UINT32(XMC_CAN_FRAME_TYPE_STANDARD_11BITS, txMessage->can_id_mode); // Standard 11-bit identifier + TEST_ASSERT_EQUAL_UINT32(XMC_CAN_ARBITRATION_MODE_ORDER_BASED_PRIO_1, txMessage->can_priority); + TEST_ASSERT_EQUAL_UINT32(0x1FFFFFFFU, txMessage->can_id_mask); + TEST_ASSERT_EQUAL_UINT32(0U, txMessage->can_ide_mask); // send both standard and extended frames + TEST_ASSERT_EQUAL_UINT32(XMC_CAN_MO_TYPE_TRANSMSGOBJ, txMessage->can_mo_type); +} + +// Test case for CAN_msg_rx initialization +void test_CAN_msg_rx_initialization(void) +{ + // Get the Rx message object + XMC_CAN_MO_t* rxMessage = CAN.getRxMessage(); + + // Verify that the Rx message object is correctly initialized + TEST_ASSERT_NOT_NULL(rxMessage); + TEST_ASSERT_EQUAL_UINT32(XMC_CAN_FRAME_TYPE_STANDARD_11BITS, rxMessage->can_id_mode); // Standard 11-bit identifier + TEST_ASSERT_EQUAL_UINT32(XMC_CAN_ARBITRATION_MODE_ORDER_BASED_PRIO_1, rxMessage->can_priority); + TEST_ASSERT_EQUAL_UINT32(0x000, rxMessage->can_id_mask); + TEST_ASSERT_EQUAL_UINT32(0U, rxMessage->can_ide_mask); // receive both standard and extended frames + TEST_ASSERT_EQUAL_UINT32(XMC_CAN_MO_TYPE_RECMSGOBJ, rxMessage->can_mo_type); + +} + +// Test case for CAN begin function with different baud rates +void test_CAN_initialization_with_baudrate_125k(void) { + int result = CAN.begin(125000); + TEST_ASSERT_EQUAL(1, result); +} + +void test_CAN_initialization_with_baudrate_250k(void) { + int result = CAN.begin(250000); + TEST_ASSERT_EQUAL(1, result); +} + +void test_CAN_initialization_with_baudrate_500k(void) { + int result = CAN.begin(500000); + TEST_ASSERT_EQUAL(1, result); +} + +void test_CAN_initialization_with_baudrate_1M(void) { + int result = CAN.begin(1000000); + TEST_ASSERT_EQUAL(1, result); +} + + +void test_CAN_beginPacket(void) { + int result = CAN.beginPacket(0x123); // Assuming 0x123 is the identifier + TEST_ASSERT_EQUAL(1, result); +} + +void test_CAN_write(void) { + uint8_t data[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}; + size_t result = CAN.write(data, sizeof(data)); + TEST_ASSERT_EQUAL(sizeof(data), result); +} + +void test_CAN_endPacket(void) { + int result = CAN.endPacket(); + TEST_ASSERT_EQUAL(1, result); +} + + + +// Bundle all tests to be executed for this test group +static TEST_GROUP_RUNNER(CAN_internal) +{ + RUN_TEST_CASE(CAN_internal, checkUnsupportedFunctionality); + RUN_TEST_CASE(CAN_internal, checkSupportedFunctionality); + RUN_TEST(test_CAN_msg_tx_initialization); + RUN_TEST(test_CAN_msg_rx_initialization); + RUN_TEST(test_CAN_initialization_with_baudrate_125k); + RUN_TEST(test_CAN_initialization_with_baudrate_250k); + RUN_TEST(test_CAN_initialization_with_baudrate_1M); + RUN_TEST(test_CAN_initialization_with_baudrate_500k); + RUN_TEST(test_CAN_beginPacket); + RUN_TEST(test_CAN_write); + RUN_TEST(test_CAN_endPacket); +} + + +// Bundle all tests to be executed for this test group +TEST_GROUP_RUNNER(CAN) +{ + CAN_suiteSetUp(); + + RUN_TEST_GROUP(CAN_internal); + + CAN_suiteTearDown(); +} diff --git a/libraries/CAN/test/unit/src/features/Test_CAN_connected.hpp b/libraries/CAN/test/unit/src/features/Test_CAN_connected.hpp new file mode 100644 index 00000000..c004011a --- /dev/null +++ b/libraries/CAN/test/unit/src/features/Test_CAN_connected.hpp @@ -0,0 +1,78 @@ +// std includes + +// test includes +#include "Test_includes.hpp" + +// project includes + + +void CAN_connected_suiteSetup(void); +void CAN_connected_suiteTearDown(void); + + +// variables used in the tests below that have to be accessed in the setup and tear down methods +static CANXMC dut = CAN; + + +// test includes that may require dut + + +// define test group name +TEST_GROUP(CAN_connected); +TEST_GROUP(CAN_connectedInternal); + + +// Setup method called by Unity before every individual test defined for this test group. +static TEST_SETUP(CAN_connectedInternal) +{ +} + + +// Tear down method called by Unity after every individual test defined for this test group. +static TEST_TEAR_DOWN(CAN_connectedInternal) +{ +} + + +// Define tests for unsupported functionality. These should return false to indicate this. +TEST_IFX(CAN_connectedInternal, checkUnsupportedFunctionality) +{ +} + + +// Define tests for supported common functionality. These should return true to indicate this. +TEST_IFX(CAN_connectedInternal, checkSupportedFunctionality) +{ + // TEST_ASSERT_TRUE( dut.method_connected() ); +} + + +TEST_IFX(CAN_connectedInternal, checkWhatever) +{ + // Useful macros, but many more available - check cheat sheet. + // TEST_ASSERT_TRUE( ); + // TEST_ASSERT_FLOAT_WITHIN( ); + // TEST_ASSERT_EQUAL_INT16( ); + // TEST_ASSERT_EQUAL_FLOAT( ); + // TEST_ASSERT_EQUAL_STRING( "ERROR : Unknown sensorType !", ); +} + + +static TEST_GROUP_RUNNER(CAN_connectedInternal) +{ + RUN_TEST_CASE(CAN_connectedInternal, checkUnsupportedFunctionality); + RUN_TEST_CASE(CAN_connectedInternal, checkSupportedFunctionality); + + RUN_TEST_CASE(CAN_connectedInternal, checkWhatever); +} + + +// Bundle all tests to be executed for this test group +TEST_GROUP_RUNNER(CAN_connected) +{ + CAN_connected_suiteSetup(); + + RUN_TEST_GROUP(CAN_connectedInternal); + + CAN_connected_suiteTearDown(); +} diff --git a/libraries/CAN/test/unit/src/features/Test_CAN_connected_node1.hpp b/libraries/CAN/test/unit/src/features/Test_CAN_connected_node1.hpp new file mode 100644 index 00000000..ae3353f3 --- /dev/null +++ b/libraries/CAN/test/unit/src/features/Test_CAN_connected_node1.hpp @@ -0,0 +1,86 @@ +// std includes + +// test includes +#include "Test_includes.hpp" + +// project includes + + +void CAN_connected_node1_suiteSetup(void); +void CAN_connected_node1_suiteTearDown(void); + + +// variables used in the tests below that have to be accessed in the setup and tear down methods + + +// test includes that may require dut + + +// define test group name +TEST_GROUP(CAN_connected_node1); +TEST_GROUP(CAN_connected_node1Internal); + + +// Setup method called by Unity before every individual test defined for this test group. +static TEST_SETUP(CAN_connected_node1Internal) +{ + memset(node1Data, 0, sizeof(node1Data)); + memset(receivedData, 0, sizeof(receivedData)); +} + +// Tear down method called by Unity after every individual test defined for this test group. +static TEST_TEAR_DOWN(CAN_connected_node1Internal) +{ +} + +void testSendReceive(uint8_t dataLength, uint8_t iterations) +{ + canDataLength = dataLength; + + for(uint8_t loop = 0; loop < iterations; ++loop) { + TEST_ASSERT_TRUE(CAN.beginPacket(CAN_ID_1)); + TEST_ASSERT_EQUAL_UINT8(canDataLength, CAN.write(node1Data, canDataLength)); + TEST_ASSERT_EQUAL(1, CAN.endPacket()); + + while (!newDataReceivedNode1) { + } + + if (newDataReceivedNode1) { + for (uint8_t i = 0; i < canDataLength; ++i) { + TEST_ASSERT_EQUAL_UINT8(node1Data[i] + node2Increment, receivedData[i]); + } + newDataReceivedNode1 = false; + + #ifdef TRACE_OUTPUT + printArray("\nSent Data", node1Data, canDataLength); + printArray("Received Data", receivedData, canDataLength); + #endif + for(uint8_t i = 0; i < canDataLength; ++i) { + node1Data[i] = receivedData[i] + node1Increment; + } + } + } +} + + +TEST_IFX(CAN_connected_node1Internal, checkPingPong) +{ + testSendReceive(3,5); +} + + +static TEST_GROUP_RUNNER(CAN_connected_node1Internal) +{ + RUN_TEST_CASE(CAN_connected_node1Internal, checkPingPong); +} + + +// Bundle all tests to be executed for this test group +TEST_GROUP_RUNNER(CAN_connected_node1) +{ + CAN_connected_node1_suiteSetup(); + + RUN_TEST_GROUP(CAN_connected_node1Internal); + + CAN_connected_node1_suiteTearDown(); +} diff --git a/libraries/CAN/test/unit/src/features/Test_CAN_connected_node2.hpp b/libraries/CAN/test/unit/src/features/Test_CAN_connected_node2.hpp new file mode 100644 index 00000000..955ccf20 --- /dev/null +++ b/libraries/CAN/test/unit/src/features/Test_CAN_connected_node2.hpp @@ -0,0 +1,79 @@ +// std includes + +// test includes +#include "Test_includes.hpp" + +// project includes + + +void CAN_connected_node2_suiteSetup(void); +void CAN_connected_node2_suiteTearDown(void); + + +// variables used in the tests below that have to be accessed in the setup and tear down methods + + +// test includes that may require dut + + +// define test group name +TEST_GROUP(CAN_connected_node2); +TEST_GROUP(CAN_connected_node2Internal); + +void processReceivedMessagesNode2() +{ + if (newDataReceivedNode2) { + // Process the received data + for (uint8_t i = 0; i < canDataLength; ++i) { + node2Data[i] = receivedData[i] + node2Increment; + } + + // Send processed data back to Node1 + TEST_ASSERT_TRUE(CAN.beginPacket(CAN_ID_2)); + for (uint8_t i = 0; i < canDataLength; ++i) { + TEST_ASSERT_EQUAL(1, CAN.write(node2Data[i])); + } + TEST_ASSERT_EQUAL(1, CAN.endPacket()); + + // Clear flag + newDataReceivedNode2 = false; + +#ifdef TRACE_OUTPUT + printArray("\nReceived Data", receivedData, canDataLength); + printArray("Sent Data", node2Data, canDataLength); +#endif + } +} +// Setup method called by Unity before every individual test defined for this test group. +static TEST_SETUP(CAN_connected_node2Internal) +{ +} + + +// Tear down method called by Unity after every individual test defined for this test group. +static TEST_TEAR_DOWN(CAN_connected_node2Internal) +{ +} + +TEST_IFX(CAN_connected_node2Internal, checkPingPong) +{ + processReceivedMessagesNode2(); +} + + +static TEST_GROUP_RUNNER(CAN_connected_node2Internal) +{ + RUN_TEST_CASE(CAN_connected_node2Internal, checkPingPong); + +} + + +// Bundle all tests to be executed for this test group +TEST_GROUP_RUNNER(CAN_connected_node2) +{ + CAN_connected_node2_suiteSetup(); + + RUN_TEST_GROUP(CAN_connected_node2Internal); + + CAN_connected_node2_suiteTearDown(); +} diff --git a/libraries/CAN/test/unit/src/framework/arduino/Utilities.cpp b/libraries/CAN/test/unit/src/framework/arduino/Utilities.cpp new file mode 100644 index 00000000..d03bf694 --- /dev/null +++ b/libraries/CAN/test/unit/src/framework/arduino/Utilities.cpp @@ -0,0 +1,24 @@ + +// std includes +#include + + +// Arduino includes +#include + + +// project cpp includes + + +void printArray(const char *title, volatile uint8_t *data, uint8_t quantity) { + Serial.print(title); + Serial.print(" : ["); + + for(uint8_t i = 0; i < quantity; ++i) { + Serial.print(data[i]); + Serial.print(", "); + } + + Serial.println("]"); + Serial.flush(); +} diff --git a/libraries/CAN/test/unit/src/framework/arduino/Utilities.hpp b/libraries/CAN/test/unit/src/framework/arduino/Utilities.hpp new file mode 100644 index 00000000..4e3226b3 --- /dev/null +++ b/libraries/CAN/test/unit/src/framework/arduino/Utilities.hpp @@ -0,0 +1,15 @@ +#ifndef UTILITIES_HPP +#define UTILITIES_HPP + + +// std includes +#include + + +// project cpp includes + + +void printArray(const char *title, volatile uint8_t *data, uint8_t quantity); + + +#endif // UTILITIES_HPP diff --git a/libraries/CAN/test/unit/src/framework/arduino/corelibs/Test_CAN.cpp b/libraries/CAN/test/unit/src/framework/arduino/corelibs/Test_CAN.cpp new file mode 100644 index 00000000..05e99fdc --- /dev/null +++ b/libraries/CAN/test/unit/src/framework/arduino/corelibs/Test_CAN.cpp @@ -0,0 +1,27 @@ +// std includes + +// test includes +#include "Test_includes.hpp" + +// project includes + + +// defines +#define TRACE_OUTPUT + + +// variables + + +// test feature includes requiring the above defined variables +#include "Test_CAN.hpp" + + +// Method invoked by Unity before a test suite is run +void CAN_suiteSetUp() { +} + + +// Method invoked by Unity after a test suite is run +void CAN_suiteTearDown() { +} diff --git a/libraries/CAN/test/unit/src/framework/arduino/corelibs/Test_CAN_connected.cpp b/libraries/CAN/test/unit/src/framework/arduino/corelibs/Test_CAN_connected.cpp new file mode 100644 index 00000000..9eae8b55 --- /dev/null +++ b/libraries/CAN/test/unit/src/framework/arduino/corelibs/Test_CAN_connected.cpp @@ -0,0 +1,27 @@ +// std includes + +// test includes +#include "Test_includes.hpp" + +// project includes + + +// defines +#define TRACE_OUTPUT + + +// variables + + +// test feature includes requiring the above defined variables +#include "Test_CAN_connected.hpp" + + +// Method invoked before a test suite is run. +void CAN_connected_suiteSetup() { +} + + +// Method invoked after a test suite is run. +void CAN_connected_suiteTearDown() { +} diff --git a/libraries/CAN/test/unit/src/framework/arduino/corelibs/Test_CAN_connected_node1.cpp b/libraries/CAN/test/unit/src/framework/arduino/corelibs/Test_CAN_connected_node1.cpp new file mode 100644 index 00000000..1f19686e --- /dev/null +++ b/libraries/CAN/test/unit/src/framework/arduino/corelibs/Test_CAN_connected_node1.cpp @@ -0,0 +1,50 @@ +// std includes + +// test includes +#include "Test_includes.hpp" + +// project includes + + +// defines +#define TRACE_OUTPUT +#define CAN_ID_1 0x123 +#define CAN_ID_2 0x321 + +// variables + + +const static uint8_t node1Increment = 10; +const static uint8_t node2Increment = 1; +const static uint8_t canDataLengthMax = 8; + +static uint8_t node1Data[canDataLengthMax]; +static uint8_t receivedData[canDataLengthMax]; +static uint8_t canDataLength = canDataLengthMax; + +volatile bool newDataReceivedNode1 = false; + + +// test feature includes requiring the above defined variables +#include "Test_CAN_connected_node1.hpp" +extern CANXMC CAN; + +void receiveEventNode1(int packetSize) { + uint8_t count = 0; + while (CAN.available() && count < 8) { + receivedData[count++] = CAN.read(); + } + newDataReceivedNode1 = true; +} +// Method invoked before a test suite is run. +void CAN_connected_node1_suiteSetup() { + CAN.begin(); + CAN.filter(CAN_ID_2, 0x7FF); // Set filter to receive messages with CAN_ID_2 + CAN.onReceive(receiveEventNode1); +} + + +// Method invoked after a test suite is run. +void CAN_connected_node1_suiteTearDown() { + CAN.end(); +} diff --git a/libraries/CAN/test/unit/src/framework/arduino/corelibs/Test_CAN_connected_node2.cpp b/libraries/CAN/test/unit/src/framework/arduino/corelibs/Test_CAN_connected_node2.cpp new file mode 100644 index 00000000..21b8f476 --- /dev/null +++ b/libraries/CAN/test/unit/src/framework/arduino/corelibs/Test_CAN_connected_node2.cpp @@ -0,0 +1,55 @@ +// std includes + +// test includes +#include "Test_includes.hpp" + +// project includes + + +// defines +#define TRACE_OUTPUT +#define CAN_ID_1 0x123 +#define CAN_ID_2 0x321 + +// variables + +const static uint8_t node1Increment = 10; +const static uint8_t node2Increment = 1; +const static uint8_t canDataLengthMax = 8; + +static uint8_t canDataLength = canDataLengthMax; +static uint8_t node2Data[canDataLengthMax] = {0}; +static uint8_t receivedData[canDataLengthMax] = {0}; + +volatile bool newDataReceivedNode2 = false; + + +// test feature includes requiring the above defined variables +#include "Test_CAN_connected_node2.hpp" +extern CANXMC CAN; + +void receiveEventNode2(int packetSize) +{ + uint8_t count = 0; + while (CAN.available()) { + receivedData[count++] = CAN.read(); + } + newDataReceivedNode2 = true; + canDataLength = packetSize; +} + +// Method invoked before a test suite is run. +void CAN_connected_node2_suiteSetup() +{ + CAN.begin(); + CAN.filter(CAN_ID_1, 0x7FF); // Set filter to receive messages with CAN_ID_1 + CAN.onReceive(receiveEventNode2); +} + + +// Method invoked after a test suite is run. +void CAN_connected_node2_suiteTearDown() +{ + CAN.end(); +} + diff --git a/libraries/CAN/test/unit/src/framework/arduino/corelibs/Test_includes.hpp b/libraries/CAN/test/unit/src/framework/arduino/corelibs/Test_includes.hpp new file mode 100644 index 00000000..c896f722 --- /dev/null +++ b/libraries/CAN/test/unit/src/framework/arduino/corelibs/Test_includes.hpp @@ -0,0 +1,18 @@ +#ifndef TEST_INCLUDES_HPP +#define TEST_INCLUDES_HPP + + +// Arduino includes +#include + + +// project cpp includes +#include "Utilities.hpp" +#include "CAN.h" + + +// test includes +#include "Test_common_includes.h" + + +#endif // TEST_INCLUDES_HPP diff --git a/libraries/CAN/test/unit/src/framework/arduino/corelibs/Test_main.ino b/libraries/CAN/test/unit/src/framework/arduino/corelibs/Test_main.ino new file mode 100644 index 00000000..fd2e9223 --- /dev/null +++ b/libraries/CAN/test/unit/src/framework/arduino/corelibs/Test_main.ino @@ -0,0 +1,62 @@ +// test includes +#include "Test_includes.hpp" + + +/*** + * Uses flags / defines to determine which groups of tests should be added to this test such that multiple tests CAN be executed in a single run. + * Use the '--build-property option of the 'arduino_compile' target to add the flags by defining the respective targets in the makefile. + * makefile : --build-property "compiler.cpp.extra_flags=\"-D=1\"" build +*/ +void RunAllTests(void) +{ + + +// CAN +#ifdef TEST_CAN + + RUN_TEST_GROUP(CAN); + +#endif + + +// CAN with connections +#ifdef TEST_CAN_CONNECTED + + RUN_TEST_GROUP(CAN_connected); + +#endif + +#ifdef TEST_CAN_CONNECTED_NODE1 + + RUN_TEST_GROUP(CAN_connected_node1); + +#endif + +#ifdef TEST_CAN_CONNECTED_NODE2 + + RUN_TEST_GROUP(CAN_connected_node2); + +#endif + + +} + + +// +void setup() { + Serial.begin(115200); + + Serial.println("setup done."); +} + + +// +void loop() { + Serial.println("\n"); + + const int argc = 2; + const char *argv[argc] = { "", "-v" }; + + (void) UnityMain(argc, argv, RunAllTests); + delay(3000); +} \ No newline at end of file diff --git a/libraries/CAN/test/unit/src/framework/arduino/unity_ifx.cpp b/libraries/CAN/test/unit/src/framework/arduino/unity_ifx.cpp new file mode 100644 index 00000000..c8c5de67 --- /dev/null +++ b/libraries/CAN/test/unit/src/framework/arduino/unity_ifx.cpp @@ -0,0 +1,22 @@ +// std includes + +// Arduino includes +#include + + +// test includes +#include "unity_ifx.h" + + +extern "C" { + // Method used by Unity to output a single character + void putCharacter(char c) { + Serial.print(c); + Serial.flush(); + } + + // Method used by Unity to flush the output + void flushCharacter() { + Serial.flush(); + } +} diff --git a/libraries/CAN/test/unit/unity_config.h b/libraries/CAN/test/unit/unity_config.h new file mode 100644 index 00000000..eef0f529 --- /dev/null +++ b/libraries/CAN/test/unit/unity_config.h @@ -0,0 +1,250 @@ +/* Unity Configuration + * As of May 11th, 2016 at ThrowTheSwitch/Unity commit 837c529 + * Update: December 29th, 2016 + * See Also: Unity/docs/UnityConfigurationGuide.pdf + * + * Unity is designed to run on almost anything that is targeted by a C compiler. + * It would be awesome if this could be done with zero configuration. While + * there are some targets that come close to this dream, it is sadly not + * universal. It is likely that you are going to need at least a couple of the + * configuration options described in this document. + * + * All of Unity's configuration options are `#defines`. Most of these are simple + * definitions. A couple are macros with arguments. They live inside the + * unity_internals.h header file. We don't necessarily recommend opening that + * file unless you really need to. That file is proof that a cross-platform + * library is challenging to build. From a more positive perspective, it is also + * proof that a great deal of complexity can be centralized primarily to one + * place in order to provide a more consistent and simple experience elsewhere. + * + * Using These Options + * It doesn't matter if you're using a target-specific compiler and a simulator + * or a native compiler. In either case, you've got a couple choices for + * configuring these options: + * + * 1. Because these options are specified via C defines, you can pass most of + * these options to your compiler through command line compiler flags. Even + * if you're using an embedded target that forces you to use their + * overbearing IDE for all configuration, there will be a place somewhere in + * your project to configure defines for your compiler. + * 2. You can create a custom `unity_config.h` configuration file (present in + * your toolchain's search paths). In this file, you will list definitions + * and macros specific to your target. All you must do is define + * `UNITY_INCLUDE_CONFIG_H` and Unity will rely on `unity_config.h` for any + * further definitions it may need. + */ + +#ifndef UNITY_CONFIG_H +#define UNITY_CONFIG_H + +/* ************************* AUTOMATIC INTEGER TYPES *************************** + * C's concept of an integer varies from target to target. The C Standard has + * rules about the `int` matching the register size of the target + * microprocessor. It has rules about the `int` and how its size relates to + * other integer types. An `int` on one target might be 16 bits while on another + * target it might be 64. There are more specific types in compilers compliant + * with C99 or later, but that's certainly not every compiler you are likely to + * encounter. Therefore, Unity has a number of features for helping to adjust + * itself to match your required integer sizes. It starts off by trying to do it + * automatically. + **************************************************************************** */ + +/* The first attempt to guess your types is to check `limits.h`. Some compilers + * that don't support `stdint.h` could include `limits.h`. If you don't + * want Unity to check this file, define this to make it skip the inclusion. + * Unity looks at UINT_MAX & ULONG_MAX, which were available since C89. + */ +/* #define UNITY_EXCLUDE_LIMITS_H */ + +/* The second thing that Unity does to guess your types is check `stdint.h`. + * This file defines `UINTPTR_MAX`, since C99, that Unity can make use of to + * learn about your system. It's possible you don't want it to do this or it's + * possible that your system doesn't support `stdint.h`. If that's the case, + * you're going to want to define this. That way, Unity will know to skip the + * inclusion of this file and you won't be left with a compiler error. + */ +/* #define UNITY_EXCLUDE_STDINT_H */ + +/* ********************** MANUAL INTEGER TYPE DEFINITION *********************** + * If you've disabled all of the automatic options above, you're going to have + * to do the configuration yourself. There are just a handful of defines that + * you are going to specify if you don't like the defaults. + **************************************************************************** */ + + /* Define this to be the number of bits an `int` takes up on your system. The + * default, if not auto-detected, is 32 bits. + * + * Example: + */ +/* #define UNITY_INT_WIDTH 16 */ + +/* Define this to be the number of bits a `long` takes up on your system. The + * default, if not autodetected, is 32 bits. This is used to figure out what + * kind of 64-bit support your system can handle. Does it need to specify a + * `long` or a `long long` to get a 64-bit value. On 16-bit systems, this option + * is going to be ignored. + * + * Example: + */ +/* #define UNITY_LONG_WIDTH 16 */ + +/* Define this to be the number of bits a pointer takes up on your system. The + * default, if not autodetected, is 32-bits. If you're getting ugly compiler + * warnings about casting from pointers, this is the one to look at. + * + * Example: + */ +/* #define UNITY_POINTER_WIDTH 64 */ + +/* Unity will automatically include 64-bit support if it auto-detects it, or if + * your `int`, `long`, or pointer widths are greater than 32-bits. Define this + * to enable 64-bit support if none of the other options already did it for you. + * There can be a significant size and speed impact to enabling 64-bit support + * on small targets, so don't define it if you don't need it. + */ +/* #define UNITY_INCLUDE_64 */ + + +/* *************************** FLOATING POINT TYPES **************************** + * In the embedded world, it's not uncommon for targets to have no support for + * floating point operations at all or to have support that is limited to only + * single precision. We are able to guess integer sizes on the fly because + * integers are always available in at least one size. Floating point, on the + * other hand, is sometimes not available at all. Trying to include `float.h` on + * these platforms would result in an error. This leaves manual configuration as + * the only option. + **************************************************************************** */ + + /* By default, Unity guesses that you will want single precision floating point + * support, but not double precision. It's easy to change either of these using + * the include and exclude options here. You may include neither, just float, + * or both, as suits your needs. + */ +/* #define UNITY_EXCLUDE_FLOAT */ +/* #define UNITY_INCLUDE_DOUBLE */ +/* #define UNITY_EXCLUDE_DOUBLE */ + +/* For features that are enabled, the following floating point options also + * become available. + */ + +/* Unity aims for as small of a footprint as possible and avoids most standard + * library calls (some embedded platforms don't have a standard library!). + * Because of this, its routines for printing integer values are minimalist and + * hand-coded. To keep Unity universal, though, we eventually chose to develop + * our own floating point print routines. Still, the display of floating point + * values during a failure are optional. By default, Unity will print the + * actual results of floating point assertion failures. So a failed assertion + * will produce a message like "Expected 4.0 Was 4.25". If you would like less + * verbose failure messages for floating point assertions, use this option to + * give a failure message `"Values Not Within Delta"` and trim the binary size. + */ +/* #define UNITY_EXCLUDE_FLOAT_PRINT */ + +/* If enabled, Unity assumes you want your `FLOAT` asserts to compare standard C + * floats. If your compiler supports a specialty floating point type, you can + * always override this behavior by using this definition. + * + * Example: + */ +/* #define UNITY_FLOAT_TYPE float16_t */ + +/* If enabled, Unity assumes you want your `DOUBLE` asserts to compare standard + * C doubles. If you would like to change this, you can specify something else + * by using this option. For example, defining `UNITY_DOUBLE_TYPE` to `long + * double` could enable gargantuan floating point types on your 64-bit processor + * instead of the standard `double`. + * + * Example: + */ +/* #define UNITY_DOUBLE_TYPE long double */ + +/* If you look up `UNITY_ASSERT_EQUAL_FLOAT` and `UNITY_ASSERT_EQUAL_DOUBLE` as + * documented in the Unity Assertion Guide, you will learn that they are not + * really asserting that two values are equal but rather that two values are + * "close enough" to equal. "Close enough" is controlled by these precision + * configuration options. If you are working with 32-bit floats and/or 64-bit + * doubles (the normal on most processors), you should have no need to change + * these options. They are both set to give you approximately 1 significant bit + * in either direction. The float precision is 0.00001 while the double is + * 10^-12. For further details on how this works, see the appendix of the Unity + * Assertion Guide. + * + * Example: + */ +/* #define UNITY_FLOAT_PRECISION 0.001f */ +/* #define UNITY_DOUBLE_PRECISION 0.001f */ + + +/* *************************** MISCELLANEOUS *********************************** + * Miscellaneous configuration options for Unity + **************************************************************************** */ + +/* Unity uses the stddef.h header included in the C standard library for the + * "NULL" macro. Define this in order to disable the include of stddef.h. If you + * do this, you have to make sure to provide your own "NULL" definition. + */ +/* #define UNITY_EXCLUDE_STDDEF_H */ + +/* Define this to enable the unity formatted print macro: + * "TEST_PRINTF" + */ +/* #define UNITY_INCLUDE_PRINT_FORMATTED */ + + +/* *************************** TOOLSET CUSTOMIZATION *************************** + * In addition to the options listed above, there are a number of other options + * which will come in handy to customize Unity's behavior for your specific + * toolchain. It is possible that you may not need to touch any of these but + * certain platforms, particularly those running in simulators, may need to jump + * through extra hoops to operate properly. These macros will help in those + * situations. + **************************************************************************** */ + +/* By default, Unity prints its results to `stdout` as it runs. This works + * perfectly fine in most situations where you are using a native compiler for + * testing. It works on some simulators as well so long as they have `stdout` + * routed back to the command line. There are times, however, where the + * simulator will lack support for dumping results or you will want to route + * results elsewhere for other reasons. In these cases, you should define the + * `UNITY_OUTPUT_CHAR` macro. This macro accepts a single character at a time + * (as an `int`, since this is the parameter type of the standard C `putchar` + * function most commonly used). You may replace this with whatever function + * call you like. + * + * Example: + * Say you are forced to run your test suite on an embedded processor with no + * `stdout` option. You decide to route your test result output to a custom + * serial `RS232_putc()` function you wrote like thus: + */ + +#define UNITY_OUTPUT_CHAR(a) putCharacter(a) +#define UNITY_OUTPUT_CHAR_HEADER_DECLARATION putCharacter(char c) +#define UNITY_OUTPUT_FLUSH() flushCharacter() +#define UNITY_OUTPUT_FLUSH_HEADER_DECLARATION flushCharacter() + +/* #define UNITY_OUTPUT_CHAR(a) RS232_putc(a) */ +/* #define UNITY_OUTPUT_CHAR_HEADER_DECLARATION RS232_putc(int) */ +/* #define UNITY_OUTPUT_FLUSH() RS232_flush() */ +/* #define UNITY_OUTPUT_FLUSH_HEADER_DECLARATION RS232_flush(void) */ +/* #define UNITY_OUTPUT_START() RS232_config(115200,1,8,0) */ +/* #define UNITY_OUTPUT_COMPLETE() RS232_close() */ + +/* Some compilers require a custom attribute to be assigned to pointers, like + * `near` or `far`. In these cases, you can give Unity a safe default for these + * by defining this option with the attribute you would like. + * + * Example: + */ +/* #define UNITY_PTR_ATTRIBUTE __attribute__((far)) */ +/* #define UNITY_PTR_ATTRIBUTE near */ + +/* Print execution time of each test when executed in verbose mode + * + * Example: + * + * TEST - PASS (10 ms) + */ +#define UNITY_INCLUDE_EXEC_TIME (1) + +#endif /* UNITY_CONFIG_H */ diff --git a/libraries/CAN/test/unit/unity_ifx.h b/libraries/CAN/test/unit/unity_ifx.h new file mode 100644 index 00000000..4689ae5b --- /dev/null +++ b/libraries/CAN/test/unit/unity_ifx.h @@ -0,0 +1,27 @@ + +#ifndef UNITY_IFX_H +#define UNITY_IFX_H + + +#define TEST_IFX(group, name) static void TEST_##group##_##name##_(void); static void TEST_##group##_##name##_run(void); void TEST_##group##_##name##_run(void) { UnityTestRunner(TEST_##group##_SETUP, TEST_##group##_##name##_, TEST_##group##_TEAR_DOWN, "TEST(" #group ", " #name ")", TEST_GROUP_##group, #name, __FILE__, __LINE__); } void TEST_##group##_##name##_(void) + + +#ifdef __cplusplus + +extern "C" { + +#endif + + +void putCharacter(char c); +void flushCharacter(); + + +#ifdef __cplusplus + +} + +#endif + + +#endif // UNITY_IFX_H