init
This commit is contained in:
		@@ -0,0 +1,220 @@
 | 
			
		||||
#ifndef _ARR_DESC_H_
 | 
			
		||||
#define _ARR_DESC_H_
 | 
			
		||||
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
/* Includes */
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <string.h>             /* memset() */
 | 
			
		||||
#include "../util/util.h"       /* CONCAT() */
 | 
			
		||||
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
/* Type Definitions */
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Array-descriptor struct.
 | 
			
		||||
 */
 | 
			
		||||
typedef struct ARR_DESC_struct
 | 
			
		||||
{
 | 
			
		||||
    void *  data_ptr;                /* Pointer to the array contents. */
 | 
			
		||||
    int32_t element_count;           /* Number of current elements. */
 | 
			
		||||
    int32_t element_size;            /* Size of current elements in bytes. */
 | 
			
		||||
    int32_t underlying_size;         /* Size of underlying array in bytes. */
 | 
			
		||||
} ARR_DESC_t;
 | 
			
		||||
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
/* Macros and Defines */
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Prefix of the array variable's name when creating an array and an array
 | 
			
		||||
 *  descriptor at the same time.
 | 
			
		||||
 */
 | 
			
		||||
#define ARR_DESC_ARR_PREFIX ARR_DESC_ARR_
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Evaluate to the array variable's name when creating an array and an array
 | 
			
		||||
 *  descriptor at the same time.
 | 
			
		||||
 */
 | 
			
		||||
#define ARR_DESC_ARR_NAME(name)                 \
 | 
			
		||||
    CONCAT(ARR_DESC_ARR_PREFIX, name)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Define an #ARR_DESC_t by itself.
 | 
			
		||||
 *
 | 
			
		||||
 *  @note The user must supply an array to store the data used by the
 | 
			
		||||
 *  #ARR_DESC_t.
 | 
			
		||||
 */
 | 
			
		||||
#define ARR_DESC_INTERNAL_DEFINE(name, data_ptr,                \
 | 
			
		||||
                                 element_count, element_size)   \
 | 
			
		||||
    ARR_DESC_t name = {                                         \
 | 
			
		||||
        data_ptr,                                               \
 | 
			
		||||
        element_count,                                          \
 | 
			
		||||
        element_size,                                           \
 | 
			
		||||
        element_count * element_size                            \
 | 
			
		||||
    }                                                           \
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Define both an array and an #ARR_DESC_t that describes it.
 | 
			
		||||
 *
 | 
			
		||||
 *  @note Use the #CURLY() macro for the content field; it provides the curly
 | 
			
		||||
 *  braces necessary for an array initialization.
 | 
			
		||||
 */
 | 
			
		||||
#define ARR_DESC_DEFINE(type, name, element_count, content)             \
 | 
			
		||||
    type ARR_DESC_ARR_NAME(name)[element_count] = content;              \
 | 
			
		||||
    ARR_DESC_INTERNAL_DEFINE(name,                                      \
 | 
			
		||||
                             &ARR_DESC_ARR_NAME(name),                  \
 | 
			
		||||
                             element_count,                             \
 | 
			
		||||
                             sizeof(type)) /* Note the lacking semicolon */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Create a #ARR_DESC_t which refers to a subset of the data in another.
 | 
			
		||||
 *
 | 
			
		||||
 *  The new #ARR_DESC_t shares the same underlying array as the aliased
 | 
			
		||||
 *  #ARR_DESC_t, but only describes a subset of the originals values.
 | 
			
		||||
 */
 | 
			
		||||
#define ARR_DESC_DEFINE_SUBSET(name, original, element_cnt)         \
 | 
			
		||||
    ARR_DESC_INTERNAL_DEFINE(name,                                  \
 | 
			
		||||
                             &ARR_DESC_ARR_NAME(original),          \
 | 
			
		||||
                             element_cnt,                           \
 | 
			
		||||
                             sizeof(ARR_DESC_ARR_NAME(original)[0]) \
 | 
			
		||||
        ) /* Note the lacking semicolon */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Creat an #ARR_DESC_t which points to the data in an existing array.
 | 
			
		||||
 *
 | 
			
		||||
 *  @param start_idx Offset in array_ptr of first element.
 | 
			
		||||
 *  @param element_cnt Number of elements to include in the #ARR_DESC_t.
 | 
			
		||||
 *
 | 
			
		||||
 *  @example
 | 
			
		||||
 *
 | 
			
		||||
 *  float my_floats[4] = {0.0f, 1.0f, 2.0f, 3.0f};
 | 
			
		||||
 *
 | 
			
		||||
 *  ARR_DESC_DEFINE_USING_ARR(my_arr_desc, my_floats, 1, 3);
 | 
			
		||||
 *
 | 
			
		||||
 *  printf("Element 0: %f\n", ARR_DESC_ELT(float, 0, &my_arr_desc));
 | 
			
		||||
 *  printf("Element 1: %f\n", ARR_DESC_ELT(float, 1, &my_arr_desc));
 | 
			
		||||
 *
 | 
			
		||||
 *  Outputs:
 | 
			
		||||
 *
 | 
			
		||||
 *  Element 0: 1.000000
 | 
			
		||||
 *  Element 1: 2.000000
 | 
			
		||||
 *
 | 
			
		||||
 *  @warning There are no checks in place to catch invalid start indices; This
 | 
			
		||||
 *  is left to the user.
 | 
			
		||||
 */
 | 
			
		||||
#define ARR_DESC_DEFINE_USING_ARR(type, name, array_ptr, start_idx, element_cnt) \
 | 
			
		||||
    ARR_DESC_INTERNAL_DEFINE(                                           \
 | 
			
		||||
        name,                                                           \
 | 
			
		||||
        (type *) (array_ptr + start_idx),                               \
 | 
			
		||||
        element_cnt,                                                    \
 | 
			
		||||
        sizeof(type)                                                    \
 | 
			
		||||
        ) /* Note the lacking semicolon*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Declare an #ARR_DESC_t object.
 | 
			
		||||
 */
 | 
			
		||||
#define ARR_DESC_DECLARE(name)                              \
 | 
			
		||||
    extern ARR_DESC_t name /* Note the lacking semicolon */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Evaluate to the number of bytes stored in the #ARR_DESC_t.
 | 
			
		||||
 */
 | 
			
		||||
#define ARR_DESC_BYTES(arr_desc_ptr)                                \
 | 
			
		||||
    ((arr_desc_ptr)->element_count * (arr_desc_ptr)->element_size)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Set the contents of #ARR_DESC_t to value.
 | 
			
		||||
 */
 | 
			
		||||
#define ARR_DESC_MEMSET(arr_desc_ptr, value, bytes)     \
 | 
			
		||||
    do                                                  \
 | 
			
		||||
    {                                                   \
 | 
			
		||||
        memset((arr_desc_ptr)->data_ptr,                \
 | 
			
		||||
               value,                                   \
 | 
			
		||||
               BOUND(0,                                 \
 | 
			
		||||
                     (arr_desc_ptr)->underlying_size,   \
 | 
			
		||||
                     bytes)                             \
 | 
			
		||||
            );                                          \
 | 
			
		||||
    } while (0)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Perform a memcpy of 'bytes' bytes from the source #ARR_DESC_t to the
 | 
			
		||||
 *  destination #ARR_DESC_t.
 | 
			
		||||
 */
 | 
			
		||||
#define ARR_DESC_MEMCPY(arr_desc_dest_ptr, arr_desc_src_ptr, bytes) \
 | 
			
		||||
    do                                                              \
 | 
			
		||||
    {                                                               \
 | 
			
		||||
        memcpy((arr_desc_dest_ptr)->data_ptr,                       \
 | 
			
		||||
               (arr_desc_src_ptr)->data_ptr,                        \
 | 
			
		||||
               BOUND(0,                                             \
 | 
			
		||||
                     (arr_desc_dest_ptr)->underlying_size,          \
 | 
			
		||||
                     bytes));                                       \
 | 
			
		||||
    } while (0)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Evaluate to true if the source #ARR_DESC_t contents will fit into the
 | 
			
		||||
 *  destination #ARR_DESC_t and false otherwise.
 | 
			
		||||
 */
 | 
			
		||||
#define ARR_DESC_COPYABLE(arr_desc_dest_ptr, arr_desc_src_ptr)  \
 | 
			
		||||
      (ARR_DESC_BYTES(arr_desc_src_ptr) <=                      \
 | 
			
		||||
       (arr_desc_dest_ptr)->underlying_size)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Copy all the data from the source #ARR_DESC_t to the destination
 | 
			
		||||
 *  #ARR_DESC_t.
 | 
			
		||||
 *
 | 
			
		||||
 *  @note If the destination #ARR_DESC_t is too small to fit the source data the
 | 
			
		||||
 *  copy is aborted and nothing happens.
 | 
			
		||||
 */
 | 
			
		||||
#define ARR_DESC_COPY(arr_desc_dest_ptr, arr_desc_src_ptr)      \
 | 
			
		||||
    do                                                          \
 | 
			
		||||
    {                                                           \
 | 
			
		||||
        if (ARR_DESC_COPYABLE(arr_desc_dest_ptr,                 \
 | 
			
		||||
                             arr_desc_src_ptr))                 \
 | 
			
		||||
        {                                                       \
 | 
			
		||||
            ARR_DESC_MEMCPY(arr_desc_dest_ptr,                  \
 | 
			
		||||
                            arr_desc_src_ptr,                   \
 | 
			
		||||
                            ARR_DESC_BYTES(arr_desc_src_ptr));  \
 | 
			
		||||
            /* Update the properties*/                          \
 | 
			
		||||
            (arr_desc_dest_ptr)->element_count =                \
 | 
			
		||||
                (arr_desc_src_ptr)->element_count;              \
 | 
			
		||||
            (arr_desc_dest_ptr)->element_size =                 \
 | 
			
		||||
                (arr_desc_src_ptr)->element_size;               \
 | 
			
		||||
        }                                                       \
 | 
			
		||||
    } while (0)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Compare the data in two #ARR_DESC_t structs for the specified number of
 | 
			
		||||
 *  bytes.
 | 
			
		||||
 */
 | 
			
		||||
#define ARR_DESC_MEMCMP(arr_desc_ptr_a, arr_desc_ptr_b, bytes)  \
 | 
			
		||||
        memcmp((arr_desc_ptr_a)->data_ptr,                      \
 | 
			
		||||
            (arr_desc_ptr_b)->data_ptr,                         \
 | 
			
		||||
               bytes) /* Note the lacking semicolon */          \
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Zero out the contents of the #ARR_DESC_t.
 | 
			
		||||
 */
 | 
			
		||||
#define ARR_DESC_ZERO(arr_desc_ptr)             \
 | 
			
		||||
        ARR_DESC_MEMSET(arr_desc_ptr,           \
 | 
			
		||||
                        0,                      \
 | 
			
		||||
                        (arr_desc_ptr)->underlying_size)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Evaluate to the data address in #ARR_DESC_t at offset.
 | 
			
		||||
 */
 | 
			
		||||
#define ARR_DESC_DATA_ADDR(type, arr_desc_ptr, offset)  \
 | 
			
		||||
        ((void*)(((type *)                              \
 | 
			
		||||
                  ((arr_desc_ptr)->data_ptr))           \
 | 
			
		||||
                 + offset))
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Evaluate to the element in #ARR_DESC_t with type at idx.
 | 
			
		||||
 */
 | 
			
		||||
#define ARR_DESC_ELT(type, idx, arr_desc_ptr)           \
 | 
			
		||||
        (*((type *) ARR_DESC_DATA_ADDR(type,            \
 | 
			
		||||
                                       arr_desc_ptr,    \
 | 
			
		||||
                                       idx)))
 | 
			
		||||
 | 
			
		||||
#endif /* _ARR_DESC_H_ */
 | 
			
		||||
@@ -0,0 +1,17 @@
 | 
			
		||||
#ifndef _JTEST_H_
 | 
			
		||||
#define _JTEST_H_
 | 
			
		||||
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
/* Includes */
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
#include "jtest_fw.h"
 | 
			
		||||
#include "jtest_test.h"
 | 
			
		||||
#include "jtest_test_define.h"
 | 
			
		||||
#include "jtest_test_call.h"
 | 
			
		||||
#include "jtest_group.h"
 | 
			
		||||
#include "jtest_group_define.h"
 | 
			
		||||
#include "jtest_group_call.h"
 | 
			
		||||
#include "jtest_cycle.h"
 | 
			
		||||
 | 
			
		||||
#endif /* _JTEST_H_ */
 | 
			
		||||
@@ -0,0 +1,65 @@
 | 
			
		||||
#ifndef _JTEST_CYCLE_H_
 | 
			
		||||
#define _JTEST_CYCLE_H_
 | 
			
		||||
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
/* Includes */
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
#include "jtest_fw.h"           /* JTEST_DUMP_STRF() */
 | 
			
		||||
#include "jtest_systick.h"
 | 
			
		||||
#include "jtest_util.h"         /* STR() */
 | 
			
		||||
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
/* Declare Module Variables */
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
extern const char * JTEST_CYCLE_STRF;
 | 
			
		||||
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
/* Macros and Defines */
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Wrap the function call, fn_call, to count execution cycles and display the
 | 
			
		||||
 *  results.
 | 
			
		||||
 */
 | 
			
		||||
/* skipp function name + param
 | 
			
		||||
#define JTEST_COUNT_CYCLES(fn_call)                     \
 | 
			
		||||
    do                                                  \
 | 
			
		||||
    {                                                   \
 | 
			
		||||
        uint32_t __jtest_cycle_end_count;               \
 | 
			
		||||
                                                        \
 | 
			
		||||
        JTEST_SYSTICK_RESET(SysTick);                   \
 | 
			
		||||
        JTEST_SYSTICK_START(SysTick);                   \
 | 
			
		||||
                                                        \
 | 
			
		||||
        fn_call;                                        \
 | 
			
		||||
                                                        \
 | 
			
		||||
        __jtest_cycle_end_count =                       \
 | 
			
		||||
            JTEST_SYSTICK_VALUE(SysTick);               \
 | 
			
		||||
                                                        \
 | 
			
		||||
		JTEST_SYSTICK_RESET(SysTick);                   \
 | 
			
		||||
        JTEST_DUMP_STRF(JTEST_CYCLE_STRF,               \
 | 
			
		||||
                        STR(fn_call),                   \
 | 
			
		||||
                        (JTEST_SYSTICK_INITIAL_VALUE -  \
 | 
			
		||||
                         __jtest_cycle_end_count));     \
 | 
			
		||||
    } while (0)
 | 
			
		||||
*/
 | 
			
		||||
#define JTEST_COUNT_CYCLES(fn_call)                     \
 | 
			
		||||
    do                                                  \
 | 
			
		||||
    {                                                   \
 | 
			
		||||
        uint32_t __jtest_cycle_end_count;               \
 | 
			
		||||
                                                        \
 | 
			
		||||
        JTEST_SYSTICK_RESET(SysTick);                   \
 | 
			
		||||
        JTEST_SYSTICK_START(SysTick);                   \
 | 
			
		||||
                                                        \
 | 
			
		||||
        fn_call;                                        \
 | 
			
		||||
                                                        \
 | 
			
		||||
        __jtest_cycle_end_count =                       \
 | 
			
		||||
            JTEST_SYSTICK_VALUE(SysTick);               \
 | 
			
		||||
                                                        \
 | 
			
		||||
		JTEST_SYSTICK_RESET(SysTick);                   \
 | 
			
		||||
        JTEST_DUMP_STRF(JTEST_CYCLE_STRF,               \
 | 
			
		||||
                        (JTEST_SYSTICK_INITIAL_VALUE -  \
 | 
			
		||||
                         __jtest_cycle_end_count));     \
 | 
			
		||||
    } while (0)
 | 
			
		||||
 | 
			
		||||
#endif /* _JTEST_CYCLE_H_ */
 | 
			
		||||
@@ -0,0 +1,37 @@
 | 
			
		||||
#ifndef _JTEST_DEFINE_H_
 | 
			
		||||
#define _JTEST_DEFINE_H_
 | 
			
		||||
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
/* Macros and Defines */
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Makes a symbol for use as a struct name. Names made this way have two parts;
 | 
			
		||||
 *  the first parts is a prefix common to all structs of that class. The second
 | 
			
		||||
 *  is a specifier which differs for each instance of that struct type.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_STRUCT_NAME(prefix, specifier)    \
 | 
			
		||||
    CONCAT(prefix, specifier)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Define a struct with type with a name generated by #JTEST_STRUCT_NAME().
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_DEFINE_STRUCT(type, struct_name)    \
 | 
			
		||||
    type struct_name
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Declare a struct with type with a name generated by #JTEST_STRUCT_NAME().
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_DECLARE_STRUCT(struct_definition) \
 | 
			
		||||
    extern struct_definition
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Define and initialize a struct (created with JTEST_DEFINE_STRUCT()) and
 | 
			
		||||
 *  initialize it with init_values.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_INIT_STRUCT(struct_definition, init_values)       \
 | 
			
		||||
    struct_definition = {                                       \
 | 
			
		||||
        init_values                                             \
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#endif /* _JTEST_DEFINE_H_ */
 | 
			
		||||
@@ -0,0 +1,253 @@
 | 
			
		||||
#ifndef _JTEST_FW_H_
 | 
			
		||||
#define _JTEST_FW_H_
 | 
			
		||||
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
/* Includes */
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>             /* int32_t */
 | 
			
		||||
#include <string.h>             /* strcpy() */
 | 
			
		||||
#include <stdio.h>              /* sprintf() */
 | 
			
		||||
#include "jtest_pf.h"           /* Extend JTEST_FW_t with Pass/Fail data */
 | 
			
		||||
#include "jtest_group.h"
 | 
			
		||||
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
/* Type Definitions */
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  A struct used to interface with the Keil Debugger.
 | 
			
		||||
 */
 | 
			
		||||
typedef struct JTEST_FW_struct
 | 
			
		||||
{
 | 
			
		||||
    /* Action Triggers: The Keil debugger monitors these values for changes.  In
 | 
			
		||||
     * response to a change, the debugger executes code on the host. */
 | 
			
		||||
    volatile int32_t test_start;
 | 
			
		||||
    volatile int32_t test_end;
 | 
			
		||||
    volatile int32_t group_start;
 | 
			
		||||
    volatile int32_t group_end;
 | 
			
		||||
    volatile int32_t dump_str;
 | 
			
		||||
    volatile int32_t dump_data;
 | 
			
		||||
    volatile int32_t exit_fw;
 | 
			
		||||
 | 
			
		||||
    JTEST_GROUP_t * current_group_ptr;
 | 
			
		||||
 | 
			
		||||
    /* Buffers: The C-code cannot send strings and data directly to the
 | 
			
		||||
     * debugging framework. Instead, the debugger can be told to read 128 byte
 | 
			
		||||
     * (by default) chunks of memory.  Data received in this manner requires
 | 
			
		||||
     * post-processing to be legible.*/
 | 
			
		||||
    char * str_buffer;
 | 
			
		||||
    char * data_buffer;
 | 
			
		||||
 | 
			
		||||
    /* Pass/Fail Data */
 | 
			
		||||
    JTEST_PF_MEMBERS;
 | 
			
		||||
 | 
			
		||||
} JTEST_FW_t;
 | 
			
		||||
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
/* Macros and Defines */
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Default name for the JTEST_FW struct.
 | 
			
		||||
 *
 | 
			
		||||
 *  Define your own if you want the variable containing the #JTEST_FW_t to have
 | 
			
		||||
 *  a different name.
 | 
			
		||||
 */
 | 
			
		||||
#ifndef JTEST_FW
 | 
			
		||||
#define JTEST_FW JTEST_FW
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Default name for the JTEST_FW_STR_BUFFER.
 | 
			
		||||
 *
 | 
			
		||||
 *  Define your own if you want the variable containing the char buffer to have
 | 
			
		||||
 *  a different name.
 | 
			
		||||
 */
 | 
			
		||||
#ifndef JTEST_FW_STR_BUFFER
 | 
			
		||||
#define JTEST_FW_STR_BUFFER JTEST_FW_STR_BUFFER
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Size of the #JTEST_FW_t, output string-buffer.
 | 
			
		||||
 *
 | 
			
		||||
 *  If you change this value, make sure the "dump_str_fn" and "dump_data_fn"
 | 
			
		||||
 *  functions in jtest_fns.ini uses the same size. If you aren't sure, read the
 | 
			
		||||
 *  documentation Keil Debugger Command 'DISPLAY'.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_BUF_SIZE 256
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  The maximum number of bytes output at once using #JTEST_DUMP_STRF().
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_STR_MAX_OUTPUT_SIZE 128
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  The maximum number of block transimissions needed to send a string from a
 | 
			
		||||
 *  buffer with JTEST_BUF_SIZE.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_STR_MAX_OUTPUT_SEGMENTS           \
 | 
			
		||||
    (JTEST_BUF_SIZE / JTEST_STR_MAX_OUTPUT_SIZE)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Initialize the JTEST framework.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_INIT()                                                    \
 | 
			
		||||
    do                                                                  \
 | 
			
		||||
    {                                                                   \
 | 
			
		||||
        JTEST_FW.str_buffer = JTEST_FW_STR_BUFFER;                      \
 | 
			
		||||
    } while (0)
 | 
			
		||||
 | 
			
		||||
/* Debugger Action-triggering Macros */
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Dispatch macro to trigger various actions in the Keil Debugger.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_TRIGGER_ACTION(action_name)       \
 | 
			
		||||
    do                                          \
 | 
			
		||||
    {                                           \
 | 
			
		||||
        action_name();                          \
 | 
			
		||||
    } while (0)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Trigger the "Test Start" action in the Keil Debugger.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_ACT_TEST_START()                  \
 | 
			
		||||
    JTEST_TRIGGER_ACTION(test_start)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Trigger the "Test End" action in the Keil Debugger.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_ACT_TEST_END()                    \
 | 
			
		||||
    JTEST_TRIGGER_ACTION(test_end)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Trigger the "Group Start" action in the Keil Debugger.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_ACT_GROUP_START()                 \
 | 
			
		||||
    JTEST_TRIGGER_ACTION(group_start)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Trigger the "Group End" action in the Keil Debugger.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_ACT_GROUP_END()                   \
 | 
			
		||||
    JTEST_TRIGGER_ACTION(group_end)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Fill the buffer named buf_name with value and dump it to the Keil debugger
 | 
			
		||||
 *  using action.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_ACT_DUMP(action, buf_name, value) \
 | 
			
		||||
    do                                          \
 | 
			
		||||
    {                                           \
 | 
			
		||||
        JTEST_CLEAR_BUFFER(buf_name);           \
 | 
			
		||||
        strcpy(JTEST_FW.buf_name, (value));     \
 | 
			
		||||
        JTEST_TRIGGER_ACTION(action);           \
 | 
			
		||||
    } while (0)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Trigger the "Exit Framework" action in the Keil Debugger.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_ACT_EXIT_FW()                     \
 | 
			
		||||
    do                                          \
 | 
			
		||||
    {                                           \
 | 
			
		||||
        JTEST_TRIGGER_ACTION(exit_fw);          \
 | 
			
		||||
    } while (0)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Buffer Manipulation Macros */
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Clear the JTEST_FW buffer with name buf_name.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_CLEAR_BUFFER(buf_name)                    \
 | 
			
		||||
    do                                                  \
 | 
			
		||||
    {                                                   \
 | 
			
		||||
        memset(JTEST_FW.buf_name, 0, JTEST_BUF_SIZE);   \
 | 
			
		||||
    } while (0)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Clear the memory needed for the JTEST_FW's string buffer.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_CLEAR_STR_BUFFER()                \
 | 
			
		||||
        JTEST_CLEAR_BUFFER(str_buffer)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Clear the memory needed for the JTEST_FW's data buffer.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_CLEAR_DATA_BUFFER()               \
 | 
			
		||||
        JTEST_CLEAR_BUFFER(data_buffer)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Dump the given string to the Keil Debugger.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_DUMP_STR(string)                          \
 | 
			
		||||
        JTEST_ACT_DUMP(dump_str, str_buffer, string)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Dump a formatted string to the Keil Debugger.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_DUMP_STRF(format_str, ... )                               \
 | 
			
		||||
    do                                                                  \
 | 
			
		||||
    {                                                                   \
 | 
			
		||||
        JTEST_CLEAR_STR_BUFFER();                                       \
 | 
			
		||||
        sprintf(JTEST_FW.str_buffer,format_str, __VA_ARGS__);           \
 | 
			
		||||
        jtest_dump_str_segments();                                      \
 | 
			
		||||
    } while (0)
 | 
			
		||||
 | 
			
		||||
/* Pass/Fail Macros */
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Increment the number of passed tests in #JTEST_FW.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_FW_INC_PASSED(amount)             \
 | 
			
		||||
        JTEST_PF_INC_PASSED(&JTEST_FW, amount)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Increment the number of passed tests in #JTEST_FW.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_FW_INC_FAILED(amount)             \
 | 
			
		||||
        JTEST_PF_INC_FAILED(&JTEST_FW, amount)
 | 
			
		||||
 | 
			
		||||
/* Manipulating the Current Group */
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Evaluate to the current_group_ptr in #JTEST_FW.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_CURRENT_GROUP_PTR()               \
 | 
			
		||||
    (JTEST_FW.current_group_ptr)
 | 
			
		||||
 | 
			
		||||
#define JTEST_SET_CURRENT_GROUP(group_ptr)      \
 | 
			
		||||
    do                                          \
 | 
			
		||||
    {                                           \
 | 
			
		||||
        JTEST_CURRENT_GROUP_PTR() = group_ptr;  \
 | 
			
		||||
    } while (0)
 | 
			
		||||
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
/* Declare Global Variables */
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
extern char JTEST_FW_STR_BUFFER[JTEST_BUF_SIZE];
 | 
			
		||||
extern volatile JTEST_FW_t JTEST_FW;
 | 
			
		||||
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
/* Function Prototypes */
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
void jtest_dump_str_segments(void);
 | 
			
		||||
 | 
			
		||||
void test_start  (void);
 | 
			
		||||
void test_end    (void);
 | 
			
		||||
void group_start (void);
 | 
			
		||||
void group_end   (void);
 | 
			
		||||
void dump_str    (void);
 | 
			
		||||
void dump_data   (void);
 | 
			
		||||
void exit_fw     (void);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif /* _JTEST_FW_H_ */
 | 
			
		||||
@@ -0,0 +1,66 @@
 | 
			
		||||
#ifndef _JTEST_GROUP_H_
 | 
			
		||||
#define _JTEST_GROUP_H_
 | 
			
		||||
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
/* Includes */
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
#include "jtest_pf.h"
 | 
			
		||||
#include "jtest_util.h"
 | 
			
		||||
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
/* Type Definitions */
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  A struct which represents a group of #JTEST_TEST_t structs. This struct is
 | 
			
		||||
 *  used to run the group of tests, and report on their outcomes.
 | 
			
		||||
 */
 | 
			
		||||
typedef struct JTEST_GROUP_struct
 | 
			
		||||
{
 | 
			
		||||
    void (* group_fn_ptr) (void); /**< Pointer to the test group */
 | 
			
		||||
    char * name_str;              /**< Name of the group */
 | 
			
		||||
    
 | 
			
		||||
    /* Extend the #JTEST_GROUP_t with Pass/Fail information.*/
 | 
			
		||||
    JTEST_PF_MEMBERS;
 | 
			
		||||
} JTEST_GROUP_t;
 | 
			
		||||
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
/* Macros and Defines */
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Set the name of JTEST_GROUP_t.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_GROUP_SET_NAME(group_ptr, name)     \
 | 
			
		||||
    JTEST_SET_STRUCT_ATTRIBUTE(group_ptr, name_str, name)
 | 
			
		||||
 | 
			
		||||
#define JTEST_GROUP_SET_FN(group_ptr, fn_ptr)     \
 | 
			
		||||
    JTEST_SET_STRUCT_ATTRIBUTE(group_ptr, group_fn_ptr, fn_ptr)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Increment the number of tests passed in the JTEST_GROUP_t pointed to by
 | 
			
		||||
 *  group_ptr.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_GROUP_INC_PASSED(group_ptr, amount) \
 | 
			
		||||
    JTEST_PF_INC_PASSED(group_ptr, amount)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Increment the number of tests failed in the JTEST_GROUP_t pointed to by
 | 
			
		||||
 *  group_ptr.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_GROUP_INC_FAILED(group_ptr, amount) \
 | 
			
		||||
    JTEST_PF_INC_FAILED(group_ptr, amount)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Reset the pass/fail information of the #JTEST_GROUP_t pointed to by
 | 
			
		||||
 *  group_ptr.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_GROUP_RESET_PF(group_ptr)         \
 | 
			
		||||
    do                                          \
 | 
			
		||||
    {                                           \
 | 
			
		||||
        JTEST_PF_RESET_PASSED(group_ptr);       \
 | 
			
		||||
        JTEST_PF_RESET_FAILED(group_ptr);       \
 | 
			
		||||
    } while (0)
 | 
			
		||||
 | 
			
		||||
#endif /* _JTEST_GROUP_H_ */
 | 
			
		||||
@@ -0,0 +1,126 @@
 | 
			
		||||
#ifndef _JTEST_GROUP_CALL_H_
 | 
			
		||||
#define _JTEST_GROUP_CALL_H_
 | 
			
		||||
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
/* Includes */
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
#include "jtest_fw.h"
 | 
			
		||||
#include <inttypes.h>
 | 
			
		||||
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
/* Macros and Defines */
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Execute the test in the #JTEST_GROUP_t struct associated witht he identifier
 | 
			
		||||
 *  group_fn.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_GROUP_RUN(group_fn)                                   \
 | 
			
		||||
    do                                                              \
 | 
			
		||||
    {                                                               \
 | 
			
		||||
        JTEST_DUMP_STR("Group Name:\n");                            \
 | 
			
		||||
        JTEST_DUMP_STR(JTEST_GROUP_STRUCT_NAME(group_fn).name_str); \
 | 
			
		||||
        JTEST_GROUP_STRUCT_NAME(group_fn).group_fn_ptr();           \
 | 
			
		||||
    } while (0)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Update the enclosing #JTEST_GROUP_t's pass/fail information using the
 | 
			
		||||
 *  current #JTEST_GROUP_t's.
 | 
			
		||||
 *
 | 
			
		||||
 *  @param group_ptr Pointer to the current #JTEST_GROUP_t.
 | 
			
		||||
 *  @param parent_ptr Pointer to the enclosing #JTEST_GROUP_t.
 | 
			
		||||
 *
 | 
			
		||||
 *  @warning Only run this if the current #JTEST_GROUP_t is being called within
 | 
			
		||||
 *  the context of another #JTEST_GROUP_t.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_GROUP_UPDATE_PARENT_GROUP_PF(group_ptr, parent_group_ptr) \
 | 
			
		||||
    do                                                                  \
 | 
			
		||||
    {                                                                   \
 | 
			
		||||
        JTEST_GROUP_INC_PASSED(parent_group_ptr,                        \
 | 
			
		||||
                               (group_ptr)->passed);                    \
 | 
			
		||||
        JTEST_GROUP_INC_FAILED(parent_group_ptr,                        \
 | 
			
		||||
                               (group_ptr)->failed);                    \
 | 
			
		||||
    } while (0)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Update the #JTEST_FW's pass/fail information using the current
 | 
			
		||||
 *  #JTEST_GROUP_t's.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_GROUP_UPDATE_FW_PF(group_ptr)                     \
 | 
			
		||||
    do                                                          \
 | 
			
		||||
    {                                                           \
 | 
			
		||||
        JTEST_FW_INC_PASSED((group_ptr)->passed);               \
 | 
			
		||||
        JTEST_FW_INC_FAILED((group_ptr)->failed);               \
 | 
			
		||||
    } while (0)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Update the enclosing context with the current #JTEST_GROUP_t's pass/fail
 | 
			
		||||
 *  information. If this group isn't in an enclosing group, it updates the
 | 
			
		||||
 *  #JTEST_FW's pass/fail info by default.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_GROUP_UPDATE_PARENT_GROUP_OR_FW_PF(group_ptr,         \
 | 
			
		||||
                                                 parent_group_ptr)  \
 | 
			
		||||
    do                                                              \
 | 
			
		||||
    {                                                               \
 | 
			
		||||
        /* Update the pass fail counts in the parent group */       \
 | 
			
		||||
        if (parent_group_ptr /* Null implies Top*/)                 \
 | 
			
		||||
        {                                                           \
 | 
			
		||||
            JTEST_GROUP_UPDATE_PARENT_GROUP_PF(                     \
 | 
			
		||||
                group_ptr,                                          \
 | 
			
		||||
                parent_group_ptr);                                  \
 | 
			
		||||
        } else {                                                    \
 | 
			
		||||
            JTEST_GROUP_UPDATE_FW_PF(                               \
 | 
			
		||||
                group_ptr);                                         \
 | 
			
		||||
        }                                                           \
 | 
			
		||||
    } while (0)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Dump the results of running the #JTEST_GROUP_t to the Keil Debugger.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_GROUP_DUMP_RESULTS(group_ptr)                             \
 | 
			
		||||
        do                                                              \
 | 
			
		||||
        {                                                               \
 | 
			
		||||
            JTEST_DUMP_STRF(                                            \
 | 
			
		||||
                "Tests Run: %" PRIu32 "\n"                              \
 | 
			
		||||
                "----------\n"                                          \
 | 
			
		||||
                "   Passed: %" PRIu32 "\n"                              \
 | 
			
		||||
                "   Failed: %" PRIu32 "\n",                             \
 | 
			
		||||
                (group_ptr)->passed + (group_ptr)->failed,              \
 | 
			
		||||
                (group_ptr)->passed,                                    \
 | 
			
		||||
                (group_ptr)->failed);                                   \
 | 
			
		||||
        } while (0)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Call the #JTEST_GROUP_t associated with the identifier group_fn.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_GROUP_CALL(group_fn)                                      \
 | 
			
		||||
        do                                                              \
 | 
			
		||||
        {   /* Save the current group from JTEST_FW_t before swapping */ \
 | 
			
		||||
            /* it to this group (in order to restore it later )*/       \
 | 
			
		||||
            JTEST_GROUP_t * __jtest_temp_group_ptr =                    \
 | 
			
		||||
                JTEST_CURRENT_GROUP_PTR();                              \
 | 
			
		||||
            JTEST_SET_CURRENT_GROUP(&JTEST_GROUP_STRUCT_NAME(group_fn)); \
 | 
			
		||||
                                                                        \
 | 
			
		||||
            /* Reset this group's pass/fail count. Each group */        \
 | 
			
		||||
            /* should only remember counts for its last execution. */   \
 | 
			
		||||
            JTEST_GROUP_RESET_PF(JTEST_CURRENT_GROUP_PTR());            \
 | 
			
		||||
                                                                        \
 | 
			
		||||
            /* Run the current group */                                 \
 | 
			
		||||
            JTEST_ACT_GROUP_START();                                    \
 | 
			
		||||
            JTEST_GROUP_RUN(group_fn);                                  \
 | 
			
		||||
            JTEST_ACT_GROUP_END();                                      \
 | 
			
		||||
                                                                        \
 | 
			
		||||
            /* Update the pass fail counts in the parent group (or FW) */ \
 | 
			
		||||
            JTEST_GROUP_UPDATE_PARENT_GROUP_OR_FW_PF(                   \
 | 
			
		||||
                JTEST_CURRENT_GROUP_PTR(),                              \
 | 
			
		||||
                __jtest_temp_group_ptr);                                \
 | 
			
		||||
                                                                        \
 | 
			
		||||
            JTEST_GROUP_DUMP_RESULTS(JTEST_CURRENT_GROUP_PTR());        \
 | 
			
		||||
                                                                        \
 | 
			
		||||
            /* Restore the previously current group */                  \
 | 
			
		||||
            JTEST_SET_CURRENT_GROUP(__jtest_temp_group_ptr);            \
 | 
			
		||||
        } while (0)
 | 
			
		||||
 | 
			
		||||
#endif /* _JTEST_GROUP_CALL_H_ */
 | 
			
		||||
@@ -0,0 +1,87 @@
 | 
			
		||||
#ifndef _JTEST_GROUP_DEFINE_H_
 | 
			
		||||
#define _JTEST_GROUP_DEFINE_H_
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
/* Includes */
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
#include "jtest_util.h"
 | 
			
		||||
#include "jtest_define.h"
 | 
			
		||||
#include "jtest_group.h"
 | 
			
		||||
 | 
			
		||||
/* For defining macros with optional arguments */
 | 
			
		||||
#include "opt_arg/opt_arg.h"
 | 
			
		||||
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
/* Macros and Defines */
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Prefix for all #JTEST_GROUP_t structs.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_GROUP_STRUCT_NAME_PREFIX G_JTEST_GROUP_STRUCT_
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Define test template used by #JTEST_GROUP_t tests.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_GROUP_FN_TEMPLATE(group_fn)    \
 | 
			
		||||
    void group_fn(void)
 | 
			
		||||
 | 
			
		||||
#define JTEST_GROUP_FN_PROTOTYPE JTEST_GROUP_FN_TEMPLATE /**< Alias for
 | 
			
		||||
                                                            #JTEST_GROUP_FN_TEMPLATE. */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Evaluate to the name of the #JTEST_GROUP_t struct associated with group_fn.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_GROUP_STRUCT_NAME(group_fn)    \
 | 
			
		||||
    JTEST_STRUCT_NAME(JTEST_GROUP_STRUCT_NAME_PREFIX, group_fn)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Define a #JTEST_GROUP_t struct based on the given group_fn.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_GROUP_DEFINE_STRUCT(group_fn)  \
 | 
			
		||||
    JTEST_DEFINE_STRUCT(JTEST_GROUP_t,       \
 | 
			
		||||
                        JTEST_GROUP_STRUCT_NAME(group_fn))
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Declare a #JTEST_GROUP_t struct based on the given group_fn.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_GROUP_DECLARE_STRUCT(group_fn) \
 | 
			
		||||
    JTEST_DECLARE_STRUCT(JTEST_GROUP_DEFINE_STRUCT(group_fn))
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Contents needed to initialize a JTEST_GROUP_t struct.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_GROUP_STRUCT_INIT(group_fn)    \
 | 
			
		||||
    group_fn,                                \
 | 
			
		||||
        STR_NL(group_fn),                       \
 | 
			
		||||
        JTEST_PF_MEMBER_INIT
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Initialize the contents of a #JTEST_GROUP_t struct.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_GROUP_INIT(group_fn)           \
 | 
			
		||||
    JTEST_GROUP_DEFINE_STRUCT(group_fn) = {  \
 | 
			
		||||
        JTEST_GROUP_STRUCT_INIT(group_fn)    \
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
/* Test Definition Macro */
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Define a #JTEST_GROUP_t object and a test function.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_DEFINE_GROUP(group_fn)         \
 | 
			
		||||
    JTEST_GROUP_FN_PROTOTYPE(group_fn);      \
 | 
			
		||||
    JTEST_GROUP_INIT(group_fn);              \
 | 
			
		||||
    JTEST_GROUP_FN_PROTOTYPE(group_fn) /* Notice the lacking semicolon */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Declare a #JTEST_GROUP_t object and a test function prototype.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_DECLARE_GROUP(group_fn)        \
 | 
			
		||||
    JTEST_GROUP_FN_PROTOTYPE(group_fn);      \
 | 
			
		||||
    JTEST_GROUP_DECLARE_STRUCT(group_fn) /* Note the lacking semicolon */
 | 
			
		||||
 | 
			
		||||
#endif /* _JTEST_GROUP_DEFINE_H_ */
 | 
			
		||||
@@ -0,0 +1,85 @@
 | 
			
		||||
#ifndef _JTEST_PF_H_
 | 
			
		||||
#define _JTEST_PF_H_
 | 
			
		||||
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
/* Purpose */
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
/* jtest_pf.h Contains macros useful for capturing pass/fail data. */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
/* Macros and Defines */
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Members that can be added to other structs to extend them pass/fail data and
 | 
			
		||||
 * corresponding functionality.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_PF_MEMBERS                            \
 | 
			
		||||
    uint32_t passed;                                \
 | 
			
		||||
    uint32_t failed /* Note the lacking semicolon*/ \
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Used for initializing JTEST_PF_MEMBERS in a struct declaration.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_PF_MEMBER_INIT                    \
 | 
			
		||||
    0,                                          \
 | 
			
		||||
    0
 | 
			
		||||
 | 
			
		||||
/* Member-Incrementing Macros */
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Dispatch macro for incrementing #JTEST_PF_MEMBERS.
 | 
			
		||||
 *
 | 
			
		||||
 *  @param xxx Values: 'passed', 'failed'
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_PF_INC_XXX(xxx, struct_pf_ptr, amount)    \
 | 
			
		||||
    do                                                  \
 | 
			
		||||
    {                                                   \
 | 
			
		||||
        ((struct_pf_ptr)->xxx) += (amount);             \
 | 
			
		||||
    } while (0)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Specialization of the #JTEST_PF_INC_XXX macro to increment the passed
 | 
			
		||||
 *  member.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_PF_INC_PASSED(struct_pf_ptr, amount)  \
 | 
			
		||||
    JTEST_PF_INC_XXX(passed, struct_pf_ptr, amount)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Specialization of the #JTEST_PF_INC_XXX macro to increment the failed
 | 
			
		||||
 *  member.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_PF_INC_FAILED(struct_pf_ptr, amount)  \
 | 
			
		||||
    JTEST_PF_INC_XXX(failed, struct_pf_ptr, amount)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Member-Resetting Macros */
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Dispatch macro for setting #JTEST_PF_MEMBERS to zero.
 | 
			
		||||
 *
 | 
			
		||||
 *  @param xxx Values: 'passed', 'failed'
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_PF_RESET_XXX(xxx, struct_pf_ptr)  \
 | 
			
		||||
    do                                          \
 | 
			
		||||
    {                                           \
 | 
			
		||||
        ((struct_pf_ptr)->xxx) = UINT32_C(0);   \
 | 
			
		||||
    } while (0)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Specialization of #JTEST_PF_RESET_XXX for the 'passed' member.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_PF_RESET_PASSED(struct_pf_ptr)    \
 | 
			
		||||
    JTEST_PF_RESET_XXX(passed, struct_pf_ptr)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Specialization of #JTEST_PF_RESET_XXX for the 'failed' member.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_PF_RESET_FAILED(struct_pf_ptr)    \
 | 
			
		||||
    JTEST_PF_RESET_XXX(failed, struct_pf_ptr)
 | 
			
		||||
 | 
			
		||||
#endif /* _JTEST_PF_H_ */
 | 
			
		||||
@@ -0,0 +1,93 @@
 | 
			
		||||
#ifndef _JTEST_SYSTICK_H_
 | 
			
		||||
#define _JTEST_SYSTICK_H_
 | 
			
		||||
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
/* Includes */
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/* Get access to the SysTick structure. */
 | 
			
		||||
#if   defined ARMCM0
 | 
			
		||||
  #include "ARMCM0.h"
 | 
			
		||||
#elif defined ARMCM0P
 | 
			
		||||
  #include "ARMCM0plus.h"
 | 
			
		||||
#elif defined ARMCM3
 | 
			
		||||
  #include "ARMCM3.h"
 | 
			
		||||
#elif defined ARMCM4
 | 
			
		||||
  #include "ARMCM4.h"
 | 
			
		||||
#elif defined ARMCM4_FP
 | 
			
		||||
  #include "ARMCM4_FP.h"
 | 
			
		||||
#elif defined ARMCM7
 | 
			
		||||
  #include "ARMCM7.h" 
 | 
			
		||||
#elif defined ARMCM7_SP
 | 
			
		||||
  #include "ARMCM7_SP.h"
 | 
			
		||||
#elif defined ARMCM7_DP
 | 
			
		||||
  #include "ARMCM7_DP.h"
 | 
			
		||||
#elif defined ARMSC000
 | 
			
		||||
  #include "ARMSC000.h"
 | 
			
		||||
#elif defined ARMSC300
 | 
			
		||||
  #include "ARMSC300.h"
 | 
			
		||||
#elif defined ARMv8MBL
 | 
			
		||||
  #include "ARMv8MBL.h"
 | 
			
		||||
#elif defined ARMv8MML
 | 
			
		||||
  #include "ARMv8MML.h"
 | 
			
		||||
#elif defined ARMv8MML_DSP
 | 
			
		||||
  #include "ARMv8MML_DSP.h"
 | 
			
		||||
#elif defined ARMv8MML_SP
 | 
			
		||||
  #include "ARMv8MML_SP.h"
 | 
			
		||||
#elif defined ARMv8MML_DSP_SP
 | 
			
		||||
  #include "ARMv8MML_DSP_SP.h"
 | 
			
		||||
#elif defined ARMv8MML_DP
 | 
			
		||||
  #include "ARMv8MML_DP.h"
 | 
			
		||||
#elif defined ARMv8MML_DSP_DP
 | 
			
		||||
  #include "ARMv8MML_DSP_DP.h"
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
  #warning "no appropriate header file found!"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
/* Macros and Defines */
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Initial value for the SysTick module.
 | 
			
		||||
 *
 | 
			
		||||
 *  @note This is also the maximum value, important as SysTick is a decrementing
 | 
			
		||||
 *  counter.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_SYSTICK_INITIAL_VALUE 0xFFFFFF
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Reset the SysTick, decrementing timer to it's maximum value and disable it.
 | 
			
		||||
 *
 | 
			
		||||
 *  This macro should leave the SysTick timer in a state that's ready for cycle
 | 
			
		||||
 *  counting.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_SYSTICK_RESET(systick_ptr)                    \
 | 
			
		||||
    do                                                      \
 | 
			
		||||
    {                                                       \
 | 
			
		||||
        (systick_ptr)->LOAD = JTEST_SYSTICK_INITIAL_VALUE;  \
 | 
			
		||||
        (systick_ptr)->VAL = 1;                             \
 | 
			
		||||
                                                            \
 | 
			
		||||
        /* Disable the SysTick module. */                   \
 | 
			
		||||
        (systick_ptr)->CTRL = UINT32_C(0x000000);           \
 | 
			
		||||
    } while (0)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Start the SysTick timer, sourced by the processor clock.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_SYSTICK_START(systick_ptr)                    \
 | 
			
		||||
    do                                                      \
 | 
			
		||||
    {                                                       \
 | 
			
		||||
        (systick_ptr)->CTRL =                               \
 | 
			
		||||
            SysTick_CTRL_ENABLE_Msk |                       \
 | 
			
		||||
            SysTick_CTRL_CLKSOURCE_Msk; /* Internal clk*/   \
 | 
			
		||||
    } while (0)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Evaluate to the current value of the SysTick timer.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_SYSTICK_VALUE(systick_ptr)        \
 | 
			
		||||
    ((systick_ptr)->VAL)
 | 
			
		||||
           
 | 
			
		||||
#endif /* _JTEST_SYSTICK_H_ */
 | 
			
		||||
@@ -0,0 +1,100 @@
 | 
			
		||||
#ifndef _JTEST_TEST_H_
 | 
			
		||||
#define _JTEST_TEST_H_
 | 
			
		||||
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
/* Includes */
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include "jtest_util.h"
 | 
			
		||||
#include "jtest_test_ret.h"
 | 
			
		||||
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
/* Type Definitions */
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  A struct which represents a Test in the JTEST framework.  This struct is
 | 
			
		||||
 *  used to enable, run, and describe the test it represents.
 | 
			
		||||
 */
 | 
			
		||||
typedef struct JTEST_TEST_struct
 | 
			
		||||
{
 | 
			
		||||
    JTEST_TEST_RET_t ( * test_fn_ptr)(void); /**< Pointer to the test function. */
 | 
			
		||||
    char   * test_fn_str;                    /**< Name of the test function */
 | 
			
		||||
    char   * fut_str;           /**< Name of the function under test. */
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     *  Flags that govern how the #JTEST_TEST_t behaves.
 | 
			
		||||
     */
 | 
			
		||||
    union {
 | 
			
		||||
        struct {
 | 
			
		||||
            unsigned enabled : 1;
 | 
			
		||||
            unsigned unused  : 7;
 | 
			
		||||
        } bits;
 | 
			
		||||
        uint8_t byte;           /* Access all flags at once. */
 | 
			
		||||
    } flags;
 | 
			
		||||
    
 | 
			
		||||
} JTEST_TEST_t;
 | 
			
		||||
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
/* Macros and Defines */
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Assign a test function to the #JTEST_TEST_t struct.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_TEST_SET_FN(jtest_test_ptr, fn_ptr)                   \
 | 
			
		||||
    JTEST_SET_STRUCT_ATTRIBUTE(jtest_test_ptr, test_fn_ptr, fn_ptr)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Specify a function under test (FUT) for the #JTEST_TEST_t struct.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_TEST_SET_FUT(jtest_test_ptr, str)                 \
 | 
			
		||||
    JTEST_SET_STRUCT_ATTRIBUTE(jtest_test_ptr, fut_str, str)
 | 
			
		||||
 | 
			
		||||
/* Macros concerning JTEST_TEST_t flags */
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
#define JTEST_TEST_FLAG_SET 1 /**< Value of a set #JTEST_TEST_t flag. */
 | 
			
		||||
#define JTEST_TEST_FLAG_CLR 0 /**< Value of a cleared #JTEST_TEST_t flag. */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Evaluate to the flag in #JTEST_TEST_t having flag_name.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_TEST_FLAG(jtest_test_ptr, flag_name)  \
 | 
			
		||||
    ((jtest_test_ptr)->flags.bits.flag_name)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Dispatch macro for setting and clearing #JTEST_TEST_t flags.
 | 
			
		||||
 *
 | 
			
		||||
 *  @param jtest_test_ptr Pointer to a #JTEST_TEST_t struct.
 | 
			
		||||
 *  @param flag_name      Name of the flag to set in #JTEST_TEST_t.flags.bits
 | 
			
		||||
 *  @param xxx            Vaid values: "SET" or "CLR"
 | 
			
		||||
 *
 | 
			
		||||
 *  @note This function depends on JTEST_TEST_FLAG_SET and JTEST_TEST_FLAG_CLR.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_TEST_XXX_FLAG(jtest_test_ptr, flag_name, xxx)                  \
 | 
			
		||||
    do                                                                       \
 | 
			
		||||
    {                                                                        \
 | 
			
		||||
        JTEST_TEST_FLAG(jtest_test_ptr, flag_name) = JTEST_TEST_FLAG_##xxx ; \
 | 
			
		||||
    } while (0)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Specification of #JTEST_TEST_XXX_FLAG to set #JTEST_TEST_t flags.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_TEST_SET_FLAG(jtest_test_ptr, flag_name)                       \
 | 
			
		||||
    JTEST_TEST_XXX_FLAG(jtest_test_ptr, flag_name, SET)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Specification of #JTEST_TEST_XXX_FLAG to clear #JTEST_TEST_t flags.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_TEST_CLR_FLAG(jtest_test_ptr, flag_name)                       \
 | 
			
		||||
    JTEST_TEST_XXX_FLAG(jtest_test_ptr, flag_name, CLR)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Evaluate to true if the #JTEST_TEST_t is enabled.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_TEST_IS_ENABLED(jtest_test_ptr)                           \
 | 
			
		||||
    (JTEST_TEST_FLAG(jtest_test_ptr, enabled) == JTEST_TEST_FLAG_SET)
 | 
			
		||||
 | 
			
		||||
#endif /* _JTEST_TEST_H_ */
 | 
			
		||||
@@ -0,0 +1,121 @@
 | 
			
		||||
#ifndef _JTEST_TEST_CALL_H_
 | 
			
		||||
#define _JTEST_TEST_CALL_H_
 | 
			
		||||
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
/* Includes */
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
#include "jtest_test.h"
 | 
			
		||||
#include "jtest_test_define.h"
 | 
			
		||||
#include "jtest_fw.h"
 | 
			
		||||
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
/* Macros and Defines */
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Exectute the test in the #JTEST_TEST_t struct associated with the identifier
 | 
			
		||||
 *  test_fn and store the result in retval.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_TEST_RUN(retval, test_fn)                                 \
 | 
			
		||||
    do                                                                  \
 | 
			
		||||
    {                                                                   \
 | 
			
		||||
        JTEST_DUMP_STR("Test Name:\n");                                 \
 | 
			
		||||
        JTEST_DUMP_STR(JTEST_TEST_STRUCT_NAME(test_fn).test_fn_str);    \
 | 
			
		||||
        JTEST_DUMP_STR("Function Under Test:\n");                       \
 | 
			
		||||
        JTEST_DUMP_STR(JTEST_TEST_STRUCT_NAME(test_fn).fut_str);        \
 | 
			
		||||
        retval = JTEST_TEST_STRUCT_NAME(test_fn).test_fn_ptr();         \
 | 
			
		||||
    } while (0)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Update the enclosing #JTEST_GROUP_t's pass/fail information based on
 | 
			
		||||
 *  test_retval.
 | 
			
		||||
 *
 | 
			
		||||
 *  @param test_retval A #JTEST_TEST_RET_enum for the current test.
 | 
			
		||||
 *
 | 
			
		||||
 *  @warning Only use if #JTEST_TEST_t is called in the context of a
 | 
			
		||||
 *  #JTEST_GROUP_t.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_TEST_UPDATE_PARENT_GROUP_PF(test_retval)              \
 | 
			
		||||
    do                                                              \
 | 
			
		||||
    {                                                               \
 | 
			
		||||
        /* Update enclosing JTEST_GROUP_t with pass/fail info */    \
 | 
			
		||||
        if (test_retval == JTEST_TEST_PASSED)                       \
 | 
			
		||||
        {                                                           \
 | 
			
		||||
            JTEST_GROUP_INC_PASSED(JTEST_CURRENT_GROUP_PTR(), 1);   \
 | 
			
		||||
        } else {                                                    \
 | 
			
		||||
            JTEST_GROUP_INC_FAILED(JTEST_CURRENT_GROUP_PTR(), 1);   \
 | 
			
		||||
        }                                                           \
 | 
			
		||||
    } while (0)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Update the #JTEST_FW with pass/fail information based on test_retval.
 | 
			
		||||
 *
 | 
			
		||||
 *  @param test_retval A #JTEST_TEST_RET_enum for the current test.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_TEST_UPDATE_FW_PF(test_retval)                        \
 | 
			
		||||
    do                                                              \
 | 
			
		||||
    {                                                               \
 | 
			
		||||
        /* Update the JTEST_FW with pass/fail info */                \
 | 
			
		||||
        if (test_retval == JTEST_TEST_PASSED)                       \
 | 
			
		||||
        {                                                           \
 | 
			
		||||
            JTEST_FW_INC_PASSED( 1);                                \
 | 
			
		||||
        } else {                                                    \
 | 
			
		||||
            JTEST_FW_INC_FAILED(1);                                 \
 | 
			
		||||
        }                                                           \
 | 
			
		||||
    } while (0)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Update the enclosing JTEST_GROUP_t's pass/fail information, or the
 | 
			
		||||
 *  #JTEST_FW's if this test has no enclosing #JTEST_GROUP_t.
 | 
			
		||||
 *
 | 
			
		||||
 *  @param test_retval A #JTEST_TEST_RET_enum for the current test.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_TEST_UPDATE_PARENT_GROUP_OR_FW_PF(test_retval)            \
 | 
			
		||||
    do                                                                  \
 | 
			
		||||
    {                                                                   \
 | 
			
		||||
        /* Update pass-fail information */                              \
 | 
			
		||||
        if (JTEST_CURRENT_GROUP_PTR() /* Non-null */)                    \
 | 
			
		||||
        {                                                               \
 | 
			
		||||
            JTEST_TEST_UPDATE_PARENT_GROUP_PF(test_retval);             \
 | 
			
		||||
        } else {                                                        \
 | 
			
		||||
            JTEST_TEST_UPDATE_FW_PF(test_retval);                       \
 | 
			
		||||
        }                                                               \
 | 
			
		||||
    } while (0)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Dump the results of the test to the Keil Debugger.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_TEST_DUMP_RESULTS(test_retval)        \
 | 
			
		||||
        do                                          \
 | 
			
		||||
        {                                           \
 | 
			
		||||
            if (test_retval == JTEST_TEST_PASSED)   \
 | 
			
		||||
            {                                       \
 | 
			
		||||
                JTEST_DUMP_STR("Test Passed\n");      \
 | 
			
		||||
            } else {                                \
 | 
			
		||||
                JTEST_DUMP_STR("Test Failed\n");      \
 | 
			
		||||
            }                                       \
 | 
			
		||||
        } while (0)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Call the #JTEST_TEST_t assocaited with the identifier test_fn.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_TEST_CALL(test_fn)                                        \
 | 
			
		||||
    do                                                                  \
 | 
			
		||||
    {                                                                   \
 | 
			
		||||
        if (JTEST_TEST_IS_ENABLED(&JTEST_TEST_STRUCT_NAME(test_fn)))    \
 | 
			
		||||
        {                                                               \
 | 
			
		||||
            /* Default to failure */                                    \
 | 
			
		||||
            JTEST_TEST_RET_t __jtest_test_ret = JTEST_TEST_FAILED;      \
 | 
			
		||||
                                                                        \
 | 
			
		||||
            JTEST_ACT_TEST_START();                                     \
 | 
			
		||||
            JTEST_TEST_RUN(__jtest_test_ret, test_fn);                  \
 | 
			
		||||
                                                                        \
 | 
			
		||||
            /* Update pass-fail information */                          \
 | 
			
		||||
            JTEST_TEST_UPDATE_PARENT_GROUP_OR_FW_PF(__jtest_test_ret);  \
 | 
			
		||||
                                                                        \
 | 
			
		||||
            JTEST_TEST_DUMP_RESULTS(__jtest_test_ret);                  \
 | 
			
		||||
            JTEST_ACT_TEST_END();                                       \
 | 
			
		||||
        }                                                               \
 | 
			
		||||
    } while (0)
 | 
			
		||||
 | 
			
		||||
#endif /* _JTEST_TEST_CALL_H_ */
 | 
			
		||||
@@ -0,0 +1,133 @@
 | 
			
		||||
#ifndef _JTEST_TEST_DEFINE_H_
 | 
			
		||||
#define _JTEST_TEST_DEFINE_H_
 | 
			
		||||
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
/* Includes */
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
#include "jtest_util.h"
 | 
			
		||||
#include "jtest_define.h"
 | 
			
		||||
#include "jtest_test.h"
 | 
			
		||||
 | 
			
		||||
/* For defining macros with optional arguments */
 | 
			
		||||
#include "opt_arg/opt_arg.h"
 | 
			
		||||
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
/* Macros and Defines */
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Prefix for all #JTEST_TEST_t structs.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_TEST_STRUCT_NAME_PREFIX G_JTEST_TEST_STRUCT_
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Define test template used by #JTEST_TEST_t tests.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_TEST_FN_TEMPLATE(test_fn)                         \
 | 
			
		||||
    JTEST_TEST_RET_t test_fn(void)
 | 
			
		||||
 | 
			
		||||
#define JTEST_TEST_FN_PROTOTYPE JTEST_TEST_FN_TEMPLATE /**< Alias for
 | 
			
		||||
                                                        * #JTEST_TEST_FN_TEMPLATE. */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Evaluate to the name of the #JTEST_TEST_t struct associated with test_fn.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_TEST_STRUCT_NAME(test_fn)                         \
 | 
			
		||||
    JTEST_STRUCT_NAME(JTEST_TEST_STRUCT_NAME_PREFIX, test_fn)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Define a #JTEST_TEST_t struct based on the given test_fn.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_TEST_DEFINE_STRUCT(test_fn)                   \
 | 
			
		||||
    JTEST_DEFINE_STRUCT(JTEST_TEST_t,                       \
 | 
			
		||||
                        JTEST_TEST_STRUCT_NAME(test_fn))
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Declare a #JTEST_TEST_t struct based on the given test_fn.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_TEST_DECLARE_STRUCT(test_fn)      \
 | 
			
		||||
    JTEST_DECLARE_STRUCT(JTEST_TEST_DEFINE_STRUCT(test_fn))
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Contents needed to initialize a JTEST_TEST_t struct.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_TEST_STRUCT_INIT(test_fn, fut, enable)    \
 | 
			
		||||
    test_fn,                                            \
 | 
			
		||||
        STR_NL(test_fn),                                   \
 | 
			
		||||
        STR_NL(fut),                                       \
 | 
			
		||||
    {                                                   \
 | 
			
		||||
        {                                               \
 | 
			
		||||
            enable,                                     \
 | 
			
		||||
                0                                       \
 | 
			
		||||
        }                                               \
 | 
			
		||||
    }                                                   \
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Initialize the contents of a #JTEST_TEST_t struct.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_TEST_INIT(test_fn, fut, enable)              \
 | 
			
		||||
    JTEST_TEST_DEFINE_STRUCT(test_fn) = {                  \
 | 
			
		||||
        JTEST_TEST_STRUCT_INIT(test_fn, fut, enable)       \
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
/* Test Definition Macro */
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Define a #JTEST_TEST_t object and a test function.
 | 
			
		||||
 */
 | 
			
		||||
#define _JTEST_DEFINE_TEST(test_fn, fut, enable)           \
 | 
			
		||||
    JTEST_TEST_FN_PROTOTYPE(test_fn);                      \
 | 
			
		||||
    JTEST_TEST_INIT(test_fn, fut, enable);                 \
 | 
			
		||||
    JTEST_TEST_FN_PROTOTYPE(test_fn) /* Notice the lacking semicolon */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Declare a #JTEST_TEST_t object and a test function prototype.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_DECLARE_TEST(test_fn)                                     \
 | 
			
		||||
    JTEST_TEST_FN_PROTOTYPE(test_fn);                                   \
 | 
			
		||||
    JTEST_TEST_DECLARE_STRUCT(test_fn) /* Note the lacking semicolon */
 | 
			
		||||
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
/* Macros with optional arguments */
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/* Top-level Interface */
 | 
			
		||||
#define JTEST_DEFINE_TEST(...)                             \
 | 
			
		||||
    JTEST_DEFINE_TEST_(PP_NARG(__VA_ARGS__), ##__VA_ARGS__)
 | 
			
		||||
 | 
			
		||||
/* Dispatch Macro*/
 | 
			
		||||
#define JTEST_DEFINE_TEST_(N, ...)                         \
 | 
			
		||||
    SPLICE(JTEST_DEFINE_TEST_, N)(__VA_ARGS__)
 | 
			
		||||
 | 
			
		||||
/* Default Arguments */
 | 
			
		||||
#define JTEST_DEFINE_TEST_DEFAULT_FUT /* Blank */
 | 
			
		||||
#define JTEST_DEFINE_TEST_DEFAULT_ENABLE                   \
 | 
			
		||||
    JTEST_TRUE                                 /* Tests enabled by
 | 
			
		||||
                                                * default. */ 
 | 
			
		||||
 | 
			
		||||
/* Dispatch Cases*/
 | 
			
		||||
#define JTEST_DEFINE_TEST_1(_1)                            \
 | 
			
		||||
    _JTEST_DEFINE_TEST(                                    \
 | 
			
		||||
        _1,                                                \
 | 
			
		||||
        JTEST_DEFINE_TEST_DEFAULT_FUT,                     \
 | 
			
		||||
        JTEST_DEFINE_TEST_DEFAULT_ENABLE                   \
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
#define JTEST_DEFINE_TEST_2(_1, _2)                        \
 | 
			
		||||
    _JTEST_DEFINE_TEST(                                    \
 | 
			
		||||
        _1,                                                \
 | 
			
		||||
        _2,                                                \
 | 
			
		||||
        JTEST_DEFINE_TEST_DEFAULT_ENABLE                   \
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
#define JTEST_DEFINE_TEST_3(_1, _2, _3)                    \
 | 
			
		||||
    _JTEST_DEFINE_TEST(                                    \
 | 
			
		||||
        _1,                                                \
 | 
			
		||||
        _2,                                                \
 | 
			
		||||
        _3                                                 \
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
#endif /* _JTEST_TEST_DEFINE_H_ */
 | 
			
		||||
@@ -0,0 +1,17 @@
 | 
			
		||||
#ifndef _JTEST_TEST_RET_H_
 | 
			
		||||
#define _JTEST_TEST_RET_H_
 | 
			
		||||
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
/* Type Definitions */
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Values a #JTEST_TEST_t can return.
 | 
			
		||||
 */
 | 
			
		||||
typedef enum JTEST_TEST_RET_enum
 | 
			
		||||
{
 | 
			
		||||
    JTEST_TEST_PASSED,
 | 
			
		||||
    JTEST_TEST_FAILED
 | 
			
		||||
} JTEST_TEST_RET_t;
 | 
			
		||||
 | 
			
		||||
#endif /* _JTEST_TEST_RET_H_ */
 | 
			
		||||
@@ -0,0 +1,27 @@
 | 
			
		||||
#ifndef _JTEST_UTIL_H_
 | 
			
		||||
#define _JTEST_UTIL_H_
 | 
			
		||||
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
/* Includes */
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
#include "util/util.h"
 | 
			
		||||
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
/* Macros and Defines */
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/* Define boolean values for the framework. */
 | 
			
		||||
#define JTEST_TRUE  1           /**< Value used for TRUE in JTEST. */
 | 
			
		||||
#define JTEST_FALSE 0           /**< Value used for FALSE in JTEST. */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Set the value of the attribute in the struct to by struct_ptr to value.
 | 
			
		||||
 */
 | 
			
		||||
#define JTEST_SET_STRUCT_ATTRIBUTE(struct_ptr, attribute, value)    \
 | 
			
		||||
    do                                                              \
 | 
			
		||||
    {                                                               \
 | 
			
		||||
        (struct_ptr)->attribute = (value);                          \
 | 
			
		||||
    } while (0)
 | 
			
		||||
 | 
			
		||||
#endif /* _JTEST_UTIL_H_ */
 | 
			
		||||
@@ -0,0 +1,15 @@
 | 
			
		||||
#ifndef _OPT_ARG_H_
 | 
			
		||||
#define _OPT_ARG_H_
 | 
			
		||||
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
/* Includes */
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
#include "pp_narg.h"
 | 
			
		||||
#include "splice.h"
 | 
			
		||||
 | 
			
		||||
/* If you are Joseph Jaoudi, you have a snippet which expands into an
 | 
			
		||||
   example. If you are not Joseph, but possess his code, study the examples. If
 | 
			
		||||
   you have no examples, turn back contact Joseph. */
 | 
			
		||||
 | 
			
		||||
#endif /* _OPT_ARG_H_ */
 | 
			
		||||
@@ -0,0 +1,25 @@
 | 
			
		||||
#ifndef _PP_NARG_H_
 | 
			
		||||
#define _PP_NARG_H_
 | 
			
		||||
 | 
			
		||||
#define PP_NARG(...)                                      \
 | 
			
		||||
    PP_NARG_(__VA_ARGS__,PP_RSEQ_N())
 | 
			
		||||
#define PP_NARG_(...)                                     \
 | 
			
		||||
    PP_ARG_N(__VA_ARGS__)
 | 
			
		||||
#define PP_ARG_N(                                         \
 | 
			
		||||
                 _1, _2, _3, _4, _5, _6, _7, _8, _9,_10,  \
 | 
			
		||||
                 _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \
 | 
			
		||||
                 _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \
 | 
			
		||||
                 _31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \
 | 
			
		||||
                 _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \
 | 
			
		||||
                 _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \
 | 
			
		||||
                 _61,_62,_63,N,...) N
 | 
			
		||||
#define PP_RSEQ_N()                                       \
 | 
			
		||||
    63,62,61,60,                                          \
 | 
			
		||||
        59,58,57,56,55,54,53,52,51,50,                    \
 | 
			
		||||
        49,48,47,46,45,44,43,42,41,40,                    \
 | 
			
		||||
        39,38,37,36,35,34,33,32,31,30,                    \
 | 
			
		||||
        29,28,27,26,25,24,23,22,21,20,                    \
 | 
			
		||||
        19,18,17,16,15,14,13,12,11,10,                    \
 | 
			
		||||
        9,8,7,6,5,4,3,2,1,0
 | 
			
		||||
 | 
			
		||||
#endif /* _PP_NARG_H_ */
 | 
			
		||||
@@ -0,0 +1,8 @@
 | 
			
		||||
#ifndef _SPLICE_H_
 | 
			
		||||
#define _SPLICE_H_
 | 
			
		||||
 | 
			
		||||
#define SPLICE(a,b) SPLICE_1(a,b)
 | 
			
		||||
#define SPLICE_1(a,b) SPLICE_2(a,b)
 | 
			
		||||
#define SPLICE_2(a,b) a##b
 | 
			
		||||
 | 
			
		||||
#endif /* _SPLICE_H_ */
 | 
			
		||||
@@ -0,0 +1,52 @@
 | 
			
		||||
#ifndef _UTIL_H_
 | 
			
		||||
#define _UTIL_H_
 | 
			
		||||
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
/* Macros and Defines */
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Convert a symbol to a string and add a 'NewLine'.
 | 
			
		||||
 */
 | 
			
		||||
#define STR_NL(x)  STR1_NL(x)
 | 
			
		||||
#define STR1_NL(x) (STR2_NL(x)"\n")
 | 
			
		||||
#define STR2_NL(x) #x
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Convert a symbol to a string.
 | 
			
		||||
 */
 | 
			
		||||
#define STR(x)  STR1(x)
 | 
			
		||||
#define STR1(x) STR2(x)
 | 
			
		||||
#define STR2(x) #x
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Concatenate two symbols.
 | 
			
		||||
 */
 | 
			
		||||
#define CONCAT(a, b)  CONCAT1(a, b)
 | 
			
		||||
#define CONCAT1(a, b) CONCAT2(a, b)
 | 
			
		||||
#define CONCAT2(a, b) a##b
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Place curly braces around a varaible number of macro arguments.
 | 
			
		||||
 */
 | 
			
		||||
#define CURLY(...) {__VA_ARGS__}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Place parenthesis around a variable number of macro arguments.
 | 
			
		||||
 */
 | 
			
		||||
#define PAREN(...) (__VA_ARGS__)
 | 
			
		||||
 | 
			
		||||
/* Standard min/max macros. */
 | 
			
		||||
#define MIN(x,y) (((x) < (y)) ? (x) : (y) )
 | 
			
		||||
#define MAX(x,y) (((x) > (y)) ? (x) : (y) )
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Bound value using low and high limits.
 | 
			
		||||
 *
 | 
			
		||||
 *  Evaluate to a number in the range, endpoint inclusive.
 | 
			
		||||
 */
 | 
			
		||||
#define BOUND(low, high, value)                 \
 | 
			
		||||
    MAX(MIN(high, value), low)
 | 
			
		||||
 | 
			
		||||
#endif /* _UTIL_H_ */
 | 
			
		||||
@@ -0,0 +1,9 @@
 | 
			
		||||
#include "../inc/jtest_cycle.h"
 | 
			
		||||
#include <inttypes.h>
 | 
			
		||||
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
/* Define Module Variables */
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/* const char * JTEST_CYCLE_STRF = "Running: %s\nCycles: %" PRIu32 "\n"; */
 | 
			
		||||
const char * JTEST_CYCLE_STRF = "Cycles: %" PRIu32 "\n"; /* function name + parameter string skipped */
 | 
			
		||||
@@ -0,0 +1,36 @@
 | 
			
		||||
#include "jtest_fw.h"
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Dump the JTEST_FW.str_buffer the Keil framework in pieces.
 | 
			
		||||
 *
 | 
			
		||||
 *  The JTEST_FW.str_buffer contains more characters than the Keil framework can
 | 
			
		||||
 *  dump at once. This function dumps them in blocks.
 | 
			
		||||
 */
 | 
			
		||||
void jtest_dump_str_segments(void)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t seg_idx      = 0;
 | 
			
		||||
    uint32_t memmove_idx = 0;
 | 
			
		||||
    uint32_t seg_cnt  =
 | 
			
		||||
        (strlen(JTEST_FW.str_buffer) / JTEST_STR_MAX_OUTPUT_SIZE) + 1;
 | 
			
		||||
 | 
			
		||||
    for( seg_idx = 0; seg_idx < seg_cnt; ++seg_idx)
 | 
			
		||||
    {
 | 
			
		||||
        JTEST_TRIGGER_ACTION(dump_str);
 | 
			
		||||
 | 
			
		||||
        if (seg_idx < JTEST_STR_MAX_OUTPUT_SEGMENTS)
 | 
			
		||||
        {
 | 
			
		||||
            memmove_idx = 0;
 | 
			
		||||
            while (memmove_idx < (seg_cnt - seg_idx -1) )
 | 
			
		||||
            {
 | 
			
		||||
                memmove(
 | 
			
		||||
                    JTEST_FW.str_buffer+
 | 
			
		||||
                    (memmove_idx* JTEST_STR_MAX_OUTPUT_SIZE),
 | 
			
		||||
                    JTEST_FW.str_buffer+
 | 
			
		||||
                    ((memmove_idx+1)*JTEST_STR_MAX_OUTPUT_SIZE),
 | 
			
		||||
                    JTEST_BUF_SIZE);
 | 
			
		||||
                ++memmove_idx;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return;
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,9 @@
 | 
			
		||||
#include "../inc/jtest.h"
 | 
			
		||||
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
/* Define Global Variables */
 | 
			
		||||
/*--------------------------------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
char JTEST_FW_STR_BUFFER[JTEST_BUF_SIZE] = {0};
 | 
			
		||||
 | 
			
		||||
volatile JTEST_FW_t JTEST_FW = {0};
 | 
			
		||||
@@ -0,0 +1,37 @@
 | 
			
		||||
 | 
			
		||||
#include "jtest_fw.h"
 | 
			
		||||
 | 
			
		||||
void test_start    (void) {
 | 
			
		||||
//  ;
 | 
			
		||||
  JTEST_FW.test_start++;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void test_end      (void) {
 | 
			
		||||
//  ;
 | 
			
		||||
  JTEST_FW.test_end++;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void group_start   (void) {
 | 
			
		||||
//  ;
 | 
			
		||||
  JTEST_FW.group_start++;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void group_end     (void) {
 | 
			
		||||
//  ;
 | 
			
		||||
  JTEST_FW.group_end++;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void dump_str      (void) {
 | 
			
		||||
//  ;
 | 
			
		||||
  JTEST_FW.dump_str++;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void dump_data     (void) {
 | 
			
		||||
//  ;
 | 
			
		||||
  JTEST_FW.dump_data++;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void exit_fw       (void) {
 | 
			
		||||
//  ;
 | 
			
		||||
  JTEST_FW.exit_fw++;
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user