mirror of
https://gitee.com/Lamdonn/varch.git
synced 2025-12-07 01:06:41 +08:00
Add performance class module, update make
This commit is contained in:
parent
81db585502
commit
ca9bdaad24
79
makefile
79
makefile
@ -1,8 +1,9 @@
|
|||||||
##################################################################################
|
##################################################################################
|
||||||
### config
|
### config
|
||||||
##################################################################################
|
##################################################################################
|
||||||
CC = gcc
|
CC := gcc
|
||||||
AR = ar
|
AR := ar
|
||||||
|
CSTD := c11
|
||||||
BUILT_DIR = built
|
BUILT_DIR = built
|
||||||
TARGET = app
|
TARGET = app
|
||||||
LIB = varch
|
LIB = varch
|
||||||
@ -18,18 +19,18 @@ VSTD_PATH = $(WORKSPACE)/02_vstd
|
|||||||
CONTAINER_PATH = $(WORKSPACE)/03_container
|
CONTAINER_PATH = $(WORKSPACE)/03_container
|
||||||
ALGORITHM_PATH = $(WORKSPACE)/04_algorithm
|
ALGORITHM_PATH = $(WORKSPACE)/04_algorithm
|
||||||
PARSER_PATH = $(WORKSPACE)/05_parser
|
PARSER_PATH = $(WORKSPACE)/05_parser
|
||||||
|
PERFORMANCE_PATH = $(WORKSPACE)/06_performance
|
||||||
|
|
||||||
##################################################################################
|
##################################################################################
|
||||||
### sources and head path
|
### sources, libaries and head path
|
||||||
##################################################################################
|
##################################################################################
|
||||||
include $(TESTSPACE)/test.mk
|
|
||||||
|
|
||||||
INCLUDE += $(APPLICATION_PATH)
|
INCLUDE += $(APPLICATION_PATH)
|
||||||
INCLUDE += $(GENDATA_PATH)
|
INCLUDE += $(GENDATA_PATH)
|
||||||
INCLUDE += $(VSTD_PATH)
|
INCLUDE += $(VSTD_PATH)
|
||||||
INCLUDE += $(CONTAINER_PATH)
|
INCLUDE += $(CONTAINER_PATH)
|
||||||
INCLUDE += $(ALGORITHM_PATH)
|
INCLUDE += $(ALGORITHM_PATH)
|
||||||
INCLUDE += $(PARSER_PATH)
|
INCLUDE += $(PARSER_PATH)
|
||||||
|
INCLUDE += $(PERFORMANCE_PATH)
|
||||||
|
|
||||||
LIBSRCS += $(APPLICATION_PATH)/init.c
|
LIBSRCS += $(APPLICATION_PATH)/init.c
|
||||||
LIBSRCS += $(wildcard $(APPLICATION_PATH)/console/*.c)
|
LIBSRCS += $(wildcard $(APPLICATION_PATH)/console/*.c)
|
||||||
@ -38,14 +39,30 @@ LIBSRCS += $(wildcard $(VSTD_PATH)/*.c)
|
|||||||
LIBSRCS += $(wildcard $(CONTAINER_PATH)/*.c)
|
LIBSRCS += $(wildcard $(CONTAINER_PATH)/*.c)
|
||||||
LIBSRCS += $(wildcard $(ALGORITHM_PATH)/*.c)
|
LIBSRCS += $(wildcard $(ALGORITHM_PATH)/*.c)
|
||||||
LIBSRCS += $(wildcard $(PARSER_PATH)/*.c)
|
LIBSRCS += $(wildcard $(PARSER_PATH)/*.c)
|
||||||
|
LIBSRCS += $(wildcard $(PERFORMANCE_PATH)/*.c)
|
||||||
|
|
||||||
|
LIBLIST += m
|
||||||
|
LIBLIST += pthread
|
||||||
|
# LIBLIST += X11
|
||||||
|
|
||||||
|
CFLAG += -std=$(CSTD)
|
||||||
|
# CFLAG += -Wall
|
||||||
|
# CFLAG += -Werror
|
||||||
|
|
||||||
|
##################################################################################
|
||||||
|
### test source
|
||||||
|
##################################################################################
|
||||||
|
|
||||||
|
include $(TESTSPACE)/test.mk
|
||||||
|
|
||||||
TESTSRC += $(APPLICATION_PATH)/main.c
|
TESTSRC += $(APPLICATION_PATH)/main.c
|
||||||
TESTSRC += $(TEST_SRC)
|
TESTSRC += $(TEST_SRC)
|
||||||
|
|
||||||
##################################################################################
|
##################################################################################
|
||||||
### targets and recipes
|
### recipes
|
||||||
##################################################################################
|
##################################################################################
|
||||||
INCS = $(addprefix -I,$(INCLUDE))
|
INCS = $(addprefix -I,$(INCLUDE))
|
||||||
|
LIBS = $(addprefix -l,$(LIBLIST))
|
||||||
OBJP = $(BUILT_DIR)/obj
|
OBJP = $(BUILT_DIR)/obj
|
||||||
BINP = $(BUILT_DIR)/bin
|
BINP = $(BUILT_DIR)/bin
|
||||||
LIBO = $(patsubst %.c, $(OBJP)/%.o, $(LIBSRCS))
|
LIBO = $(patsubst %.c, $(OBJP)/%.o, $(LIBSRCS))
|
||||||
@ -56,11 +73,14 @@ LIBN = lib$(LIB)
|
|||||||
LIBA = $(BUILT_DIR)/$(LIBN).a
|
LIBA = $(BUILT_DIR)/$(LIBN).a
|
||||||
LIBP ?= /usr
|
LIBP ?= /usr
|
||||||
|
|
||||||
|
##################################################################################
|
||||||
|
### make targets
|
||||||
|
##################################################################################
|
||||||
|
|
||||||
# link
|
# link
|
||||||
${TARP}:$(OBJS)
|
${TARP}:$(OBJS)
|
||||||
mkdir -p $(dir $@)
|
mkdir -p $(dir $@)
|
||||||
# @ $(CC) $(OBJS) -o $(TARP) -lm -lX11 -lpthread
|
@ $(CC) $(CFLAG) $(OBJS) -o $(TARP) $(LIBS)
|
||||||
@ $(CC) $(CFLAG) $(OBJS) -o $(TARP) -lm -lpthread
|
|
||||||
|
|
||||||
# compile
|
# compile
|
||||||
$(OBJP)/%.o:%.c
|
$(OBJP)/%.o:%.c
|
||||||
@ -68,15 +88,54 @@ $(OBJP)/%.o:%.c
|
|||||||
@ echo "compiling $(notdir $<)"
|
@ echo "compiling $(notdir $<)"
|
||||||
@ $(CC) $(CFLAG) $(INCS) -c $< -o $@
|
@ $(CC) $(CFLAG) $(INCS) -c $< -o $@
|
||||||
|
|
||||||
|
app:${TARP}
|
||||||
|
|
||||||
|
# lib
|
||||||
|
lib:$(LIBO)
|
||||||
|
@ $(AR) -crv $(LIBA) $(LIBO)
|
||||||
|
|
||||||
|
.PHONY:help
|
||||||
|
help:
|
||||||
|
@echo "Makefile Help"
|
||||||
|
@echo "Usage: make [target] [options]"
|
||||||
|
@echo ""
|
||||||
|
@echo "Available targets:"
|
||||||
|
@echo ""
|
||||||
|
@echo " app - Build the project (default target $(TARP))"
|
||||||
|
@echo " [CC] - Specify the compiler (default is $(CC))"
|
||||||
|
@echo " [AR] - Specify the archiver (default is $(AR))"
|
||||||
|
@echo " [CSTD] - Specify the C std version (c89, c99, c11, c18, default is $(CSTD))"
|
||||||
|
@echo ""
|
||||||
|
@echo " lib - Build the library ($(LIB))"
|
||||||
|
@echo ""
|
||||||
|
@echo " run - Execute the default application"
|
||||||
|
@echo ""
|
||||||
|
@echo " install - Install the library"
|
||||||
|
@echo " [LIBP] - Specify the lib installation path (default is $(LIBP))"
|
||||||
|
@echo " example: linux - make install"
|
||||||
|
@echo " MinGW - make install LIBP=D:/MinGW"
|
||||||
|
@echo ""
|
||||||
|
@echo " uninstall - Uninstall the library"
|
||||||
|
@echo " [LIBP] - Same as install"
|
||||||
|
@echo ""
|
||||||
|
@echo " clean - Remove build artifacts"
|
||||||
|
@echo ""
|
||||||
|
@echo " help - Show this help message"
|
||||||
|
|
||||||
|
|
||||||
.PHONY:clean
|
.PHONY:clean
|
||||||
clean:
|
clean:
|
||||||
@echo "remove app and objs files ..."
|
@echo "remove app and objs files ..."
|
||||||
@ rm $(BUILT_DIR)/$(WORKSPACE) -rf
|
@ rm $(BUILT_DIR)/$(WORKSPACE) -rf
|
||||||
@ rm $(BUILT_DIR)/* -rf
|
@ rm $(BUILT_DIR)/* -rf
|
||||||
|
|
||||||
|
.PHONY:run
|
||||||
|
run:app
|
||||||
|
@ echo "executing..."
|
||||||
|
./$(BUILT_DIR)/bin/$(TARGET)
|
||||||
|
|
||||||
.PHONY:install
|
.PHONY:install
|
||||||
install:$(LIBO)
|
install:lib
|
||||||
@ $(AR) -crv $(LIBA) $(LIBO)
|
|
||||||
@ mkdir -p $(LIBP)/include/$(LIB)
|
@ mkdir -p $(LIBP)/include/$(LIB)
|
||||||
@ find $(INCLUDE) -name "*.h" -exec cp {} $(LIBP)/include/$(LIB) \;
|
@ find $(INCLUDE) -name "*.h" -exec cp {} $(LIBP)/include/$(LIB) \;
|
||||||
@ mv -f $(LIBA) $(LIBP)/lib \
|
@ mv -f $(LIBA) $(LIBP)/lib \
|
||||||
|
|||||||
389
source/06_performance/ramt.c
Normal file
389
source/06_performance/ramt.c
Normal file
@ -0,0 +1,389 @@
|
|||||||
|
/*********************************************************************************************************
|
||||||
|
* ------------------------------------------------------------------------------------------------------
|
||||||
|
* file description
|
||||||
|
* ------------------------------------------------------------------------------------------------------
|
||||||
|
* \file ramt.c
|
||||||
|
* \unit ramt
|
||||||
|
* \brief This is a simple ram test module for C language
|
||||||
|
* \author Lamdonn
|
||||||
|
* \version v0.1.0
|
||||||
|
* \license GPL-2.0
|
||||||
|
* \copyright Copyright (C) 2023 Lamdonn.
|
||||||
|
********************************************************************************************************/
|
||||||
|
#include "ramt.h"
|
||||||
|
|
||||||
|
#define PRIVATE_INDEX_RESULT_HISTORY 0
|
||||||
|
#define PRIVATE_INDEX_RESULT_LATEST 1
|
||||||
|
#define PRIVATE_INDEX_DURATION 2
|
||||||
|
#define PRIVATE_INDEX_TEST_MODE 3
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Performs a normal read/write test on the RAM
|
||||||
|
* \param[in] ramt: pointer to the RAMT structure
|
||||||
|
* \return 1 if the test passes, 0 if it fails
|
||||||
|
*/
|
||||||
|
static uint8_t test_normal(RAMT *ramt)
|
||||||
|
{
|
||||||
|
uint8_t *base = (uint8_t *)(ramt->base); // Cast the base pointer to a uint8_t pointer
|
||||||
|
uint32_t i = 0;
|
||||||
|
|
||||||
|
// Write data: set each byte to its index value modulo 256
|
||||||
|
for (i = 0; i < ramt->size; i++)
|
||||||
|
{
|
||||||
|
base[i] = (uint8_t)(i % 256); // Write data
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read and verify data
|
||||||
|
for (i = 0; i < ramt->size; i++)
|
||||||
|
{
|
||||||
|
// If the read value does not match the expected value, return 0
|
||||||
|
if (base[i] != (uint8_t)(i % 256))
|
||||||
|
{
|
||||||
|
return 0; // Test failed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1; // Test passed
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Test RAM boundary conditions
|
||||||
|
* \param[in] ramt: Pointer to the RAMT structure
|
||||||
|
* \return 1 if the boundary write test passes, 0 if it fails
|
||||||
|
*/
|
||||||
|
static uint8_t test_boundary(RAMT *ramt)
|
||||||
|
{
|
||||||
|
uint8_t *base = (uint8_t *)(ramt->base); // Cast the base pointer to a uint8_t pointer
|
||||||
|
|
||||||
|
// Test writing at the boundaries
|
||||||
|
base[0] = 0xAA; // Write to the start address
|
||||||
|
base[ramt->size - 1] = 0xBB; // Write to the end address
|
||||||
|
|
||||||
|
// Check boundary writes
|
||||||
|
if (base[0] != 0xAA || base[ramt->size - 1] != 0xBB)
|
||||||
|
{
|
||||||
|
return 0; // Boundary write failed
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1; // Boundary write succeeded
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Test RAM random writes and reads
|
||||||
|
* \param[in] ramt: Pointer to the RAMT structure
|
||||||
|
* \param[in] iterations: Number of random write/read iterations
|
||||||
|
* \return 1 if the random write/read test passes, 0 if it fails
|
||||||
|
*/
|
||||||
|
static uint8_t test_random(RAMT *ramt, uint32_t iterations)
|
||||||
|
{
|
||||||
|
uint8_t *base = (uint8_t *)(ramt->base); // Cast the base pointer to a uint8_t pointer
|
||||||
|
uint8_t data;
|
||||||
|
uint32_t i = 0;
|
||||||
|
uint32_t addr = 0;
|
||||||
|
|
||||||
|
// srand((unsigned int)time(NULL)); // Set random seed (uncomment to enable randomness)
|
||||||
|
for (i = 0; i < iterations; i++)
|
||||||
|
{
|
||||||
|
// Generate random address and data
|
||||||
|
addr = rand() % (ramt->size); // Generate a random address within the RAM size
|
||||||
|
data = (uint8_t)(rand() % 256); // Generate random data
|
||||||
|
|
||||||
|
base[addr] = data; // Write random data to the RAM
|
||||||
|
|
||||||
|
// Read and verify the data
|
||||||
|
if (base[addr] != data)
|
||||||
|
{
|
||||||
|
return 0; // Data mismatch
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1; // Random write/read test succeeded
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Test RAM data pattern
|
||||||
|
* \param[in] ramt: Pointer to the RAMT structure
|
||||||
|
* \param[in] pattern: The data pattern to write to the RAM
|
||||||
|
* \return 1 if the data pattern test passes, 0 if it fails
|
||||||
|
*/
|
||||||
|
static uint8_t test_data_pattern(RAMT *ramt, uint8_t pattern)
|
||||||
|
{
|
||||||
|
uint8_t *base = (uint8_t *)(ramt->base); // Cast the base pointer to a uint8_t pointer
|
||||||
|
uint32_t i = 0;
|
||||||
|
|
||||||
|
// Write the specified pattern data to the RAM
|
||||||
|
for (i = 0; i < ramt->size; i++)
|
||||||
|
{
|
||||||
|
base[i] = pattern; // Write pattern data
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the pattern data
|
||||||
|
for (i = 0; i < ramt->size; i++)
|
||||||
|
{
|
||||||
|
if (base[i] != pattern)
|
||||||
|
{
|
||||||
|
return 0; // If data doesn't match, return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1; // Data pattern test passed
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Test RAM inversion
|
||||||
|
* \param[in] ramt: Pointer to the RAMT structure
|
||||||
|
* \return 1 if the inversion test passes, 0 if it fails
|
||||||
|
*/
|
||||||
|
static uint8_t test_inversion(RAMT *ramt)
|
||||||
|
{
|
||||||
|
uint8_t *base = (uint8_t *)(ramt->base); // Cast the base pointer to a uint8_t pointer
|
||||||
|
uint32_t i = 0;
|
||||||
|
uint8_t temp;
|
||||||
|
|
||||||
|
// Initialize data
|
||||||
|
for (i = 0; i < ramt->size; i++)
|
||||||
|
{
|
||||||
|
base[i] = (uint8_t)(i % 256); // Fill RAM with initial data
|
||||||
|
}
|
||||||
|
|
||||||
|
// Invert RAM data
|
||||||
|
for (i = 0; i < ramt->size / 2; i++)
|
||||||
|
{
|
||||||
|
temp = base[i]; // Temporarily store the value
|
||||||
|
base[i] = base[ramt->size - 1 - i]; // Swap values
|
||||||
|
base[ramt->size - 1 - i] = temp; // Complete the swap
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if inversion is correct
|
||||||
|
for (i = 0; i < ramt->size; i++)
|
||||||
|
{
|
||||||
|
if (base[i] != (uint8_t)((ramt->size - 1 - i) % 256))
|
||||||
|
{
|
||||||
|
return 0; // If data does not match, return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1; // Inversion test passed
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Test RAM clearing
|
||||||
|
* \param[in] ramt: Pointer to the RAMT structure
|
||||||
|
* \return 1 if the clearing test passes, 0 if it fails
|
||||||
|
*/
|
||||||
|
static uint8_t test_clearing(RAMT *ramt)
|
||||||
|
{
|
||||||
|
uint8_t *base = (uint8_t *)(ramt->base); // Cast the base pointer to a uint8_t pointer
|
||||||
|
uint32_t i = 0;
|
||||||
|
|
||||||
|
// Clear RAM
|
||||||
|
for (i = 0; i < ramt->size; i++)
|
||||||
|
{
|
||||||
|
base[i] = 0; // Set all data to 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if clearing was successful
|
||||||
|
for (i = 0; i < ramt->size; i++)
|
||||||
|
{
|
||||||
|
if (base[i] != 0)
|
||||||
|
{
|
||||||
|
return 0; // If any data is not 0, return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1; // Clearing test passed
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Test specific data writing and reading in RAM
|
||||||
|
* \param[in] ramt: Pointer to the RAMT structure
|
||||||
|
* \param[in] data: The specific data to write to the RAM
|
||||||
|
* \return 1 if the specific data test passes, 0 if it fails
|
||||||
|
*/
|
||||||
|
static uint8_t test_specific_data(RAMT *ramt, uint8_t data)
|
||||||
|
{
|
||||||
|
uint8_t *base = (uint8_t *)(ramt->base); // Cast the base pointer to a uint8_t pointer
|
||||||
|
uint32_t i = 0;
|
||||||
|
|
||||||
|
// Write specific data to RAM
|
||||||
|
for (i = 0; i < ramt->size; i++)
|
||||||
|
{
|
||||||
|
base[i] = data; // Write the specified data to each location in RAM
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the specific data
|
||||||
|
for (i = 0; i < ramt->size; i++)
|
||||||
|
{
|
||||||
|
if (base[i] != data)
|
||||||
|
{
|
||||||
|
return 0; // If any data does not match, return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1; // Specific data test passed
|
||||||
|
}
|
||||||
|
|
||||||
|
int ramt_init(RAMT *ramt)
|
||||||
|
{
|
||||||
|
// Check if the ramt pointer is valid
|
||||||
|
if (!ramt) return 0;
|
||||||
|
|
||||||
|
// Check if the base pointer within the ramt structure is valid
|
||||||
|
if (!ramt->base) return 0;
|
||||||
|
|
||||||
|
// Check if the size of RAM is greater than 0
|
||||||
|
if (ramt->size == 0) return 0;
|
||||||
|
|
||||||
|
// Initialize the private data to zero
|
||||||
|
memset(ramt->private, 0, sizeof(ramt->private));
|
||||||
|
|
||||||
|
return 1; // Initialization successful
|
||||||
|
}
|
||||||
|
|
||||||
|
int ramt_start(RAMT *ramt, uint32_t mode, uint32_t duration)
|
||||||
|
{
|
||||||
|
// Check if the ramt pointer is valid
|
||||||
|
if (!ramt) return 0;
|
||||||
|
|
||||||
|
// Check if the base pointer within the ramt structure is valid
|
||||||
|
if (!ramt->base) return 0;
|
||||||
|
|
||||||
|
// Check if the size of RAM is greater than 0
|
||||||
|
if (ramt->size == 0) return 0;
|
||||||
|
|
||||||
|
// Check if mode and duration are valid
|
||||||
|
if (mode == 0 || duration == 0) return 0;
|
||||||
|
|
||||||
|
// Set the test mode and duration in the private data
|
||||||
|
ramt->private[PRIVATE_INDEX_TEST_MODE] = mode;
|
||||||
|
ramt->private[PRIVATE_INDEX_DURATION] = duration;
|
||||||
|
|
||||||
|
return 1; // Operation successful
|
||||||
|
}
|
||||||
|
|
||||||
|
int ramt_stop(RAMT *ramt)
|
||||||
|
{
|
||||||
|
// Check if the ramt pointer is valid
|
||||||
|
if (!ramt) return 0;
|
||||||
|
|
||||||
|
// Check if the base pointer within the ramt structure is valid
|
||||||
|
if (!ramt->base) return 0;
|
||||||
|
|
||||||
|
// Check if the size of RAM is greater than 0
|
||||||
|
if (ramt->size == 0) return 0;
|
||||||
|
|
||||||
|
// Reset the test mode and duration in the private data
|
||||||
|
ramt->private[PRIVATE_INDEX_TEST_MODE] = 0;
|
||||||
|
ramt->private[PRIVATE_INDEX_DURATION] = 0;
|
||||||
|
|
||||||
|
return 1; // Operation successful
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ramt_result(RAMT *ramt)
|
||||||
|
{
|
||||||
|
// Check if the ramt pointer is valid
|
||||||
|
if (!ramt) return 0xFFFFFFFF;
|
||||||
|
|
||||||
|
// Check if the base pointer within the ramt structure is valid
|
||||||
|
if (!ramt->base) return 0xFFFFFFFF;
|
||||||
|
|
||||||
|
// Check if the size of RAM is greater than 0
|
||||||
|
if (ramt->size == 0) return 0xFFFFFFFF;
|
||||||
|
|
||||||
|
// Return the historical result from the private data
|
||||||
|
return ramt->private[PRIVATE_INDEX_RESULT_HISTORY];
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ramt_result_latest(RAMT *ramt)
|
||||||
|
{
|
||||||
|
// Check if the ramt pointer is valid
|
||||||
|
if (!ramt) return 0xFFFFFFFF;
|
||||||
|
|
||||||
|
// Check if the base pointer within the ramt structure is valid
|
||||||
|
if (!ramt->base) return 0xFFFFFFFF;
|
||||||
|
|
||||||
|
// Check if the size of RAM is greater than 0
|
||||||
|
if (ramt->size == 0) return 0xFFFFFFFF;
|
||||||
|
|
||||||
|
// Return the latest result from the private data
|
||||||
|
return ramt->private[PRIVATE_INDEX_RESULT_LATEST];
|
||||||
|
}
|
||||||
|
|
||||||
|
void ramt_task(RAMT *ramt)
|
||||||
|
{
|
||||||
|
uint32_t result = 0; // Variable to store the results of the tests
|
||||||
|
uint32_t mode = 0; // Variable to store the current testing mode
|
||||||
|
|
||||||
|
// Check if the ramt pointer is not NULL
|
||||||
|
if (ramt != NULL)
|
||||||
|
{
|
||||||
|
// Check if the duration is set to a special value or decrements it
|
||||||
|
if (ramt->private[PRIVATE_INDEX_DURATION] == 0xFFFFFFFF ||
|
||||||
|
(ramt->private[PRIVATE_INDEX_DURATION] > 0 && (ramt->private[PRIVATE_INDEX_DURATION])--))
|
||||||
|
{
|
||||||
|
// Get the current testing mode
|
||||||
|
mode = ramt->private[PRIVATE_INDEX_TEST_MODE];
|
||||||
|
|
||||||
|
// Execute tests based on the current mode
|
||||||
|
if (mode & RAMT_MODE_NORMAL)
|
||||||
|
{
|
||||||
|
if (!test_normal(ramt))
|
||||||
|
{
|
||||||
|
result |= RAMT_MODE_NORMAL; // Mark failure for normal test
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode & RAMT_MODE_BOUNDARY)
|
||||||
|
{
|
||||||
|
if (!test_boundary(ramt))
|
||||||
|
{
|
||||||
|
result |= RAMT_MODE_BOUNDARY; // Mark failure for boundary test
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode & RAMT_MODE_PATTERN)
|
||||||
|
{
|
||||||
|
if (!test_data_pattern(ramt, 0x55))
|
||||||
|
{
|
||||||
|
result |= RAMT_MODE_PATTERN; // Mark failure for data pattern test
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode & RAMT_MODE_RANDOM)
|
||||||
|
{
|
||||||
|
if (!test_random(ramt, 0x55))
|
||||||
|
{
|
||||||
|
result |= RAMT_MODE_RANDOM; // Mark failure for random test
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode & RAMT_MODE_INVERSION)
|
||||||
|
{
|
||||||
|
if (!test_inversion(ramt))
|
||||||
|
{
|
||||||
|
result |= RAMT_MODE_INVERSION; // Mark failure for inversion test
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode & RAMT_MODE_CLEARING)
|
||||||
|
{
|
||||||
|
if (!test_clearing(ramt))
|
||||||
|
{
|
||||||
|
result |= RAMT_MODE_CLEARING; // Mark failure for clearing test
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode & RAMT_MODE_SPECIFIC)
|
||||||
|
{
|
||||||
|
if (!test_specific_data(ramt, 0x55))
|
||||||
|
{
|
||||||
|
result |= RAMT_MODE_SPECIFIC; // Mark failure for specific data test
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the latest result and accumulate the historical result
|
||||||
|
ramt->private[PRIVATE_INDEX_RESULT_LATEST] = result;
|
||||||
|
ramt->private[PRIVATE_INDEX_RESULT_HISTORY] |= result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
87
source/06_performance/ramt.h
Normal file
87
source/06_performance/ramt.h
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
/*********************************************************************************************************
|
||||||
|
* ------------------------------------------------------------------------------------------------------
|
||||||
|
* file description
|
||||||
|
* ------------------------------------------------------------------------------------------------------
|
||||||
|
* \file ramt.h
|
||||||
|
* \unit ramt
|
||||||
|
* \brief This is a simple ram test module for C language
|
||||||
|
* \author Lamdonn
|
||||||
|
* \version v0.1.0
|
||||||
|
* \license GPL-2.0
|
||||||
|
* \copyright Copyright (C) 2023 Lamdonn.
|
||||||
|
********************************************************************************************************/
|
||||||
|
#ifndef __ramt_H
|
||||||
|
#define __ramt_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
/* Version infomation */
|
||||||
|
#define RAMT_V_MAJOR 0
|
||||||
|
#define RAMT_V_MINOR 1
|
||||||
|
#define RAMT_V_REVISE 0
|
||||||
|
|
||||||
|
// Define different RAM test modes
|
||||||
|
#define RAMT_MODE_NORMAL ((uint32_t)0x00000001) // Normal read/write test
|
||||||
|
#define RAMT_MODE_BOUNDARY ((uint32_t)0x00000002) // Boundary test
|
||||||
|
#define RAMT_MODE_PATTERN ((uint32_t)0x00000004) // Data pattern test
|
||||||
|
#define RAMT_MODE_RANDOM ((uint32_t)0x00000008) // Random access test
|
||||||
|
#define RAMT_MODE_INVERSION ((uint32_t)0x00000010) // Inversion test
|
||||||
|
#define RAMT_MODE_CLEARING ((uint32_t)0x00000020) // Clearing test
|
||||||
|
#define RAMT_MODE_SPECIFIC ((uint32_t)0x00000040) // Specific data test
|
||||||
|
|
||||||
|
// RAM structure definition
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
void *base; // Pointer to the simulated RAM
|
||||||
|
uint32_t size; // Size of the RAM
|
||||||
|
uint32_t private[4]; // Private data, modification not allowed
|
||||||
|
} RAMT;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Initialize RAMT structure
|
||||||
|
* \param[in] ramt: Pointer to the RAMT structure to be initialized
|
||||||
|
* \return 1 if initialization is successful, 0 if it fails
|
||||||
|
*/
|
||||||
|
int ramt_init(RAMT *ramt);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Start the RAM testing with specified mode and duration
|
||||||
|
* \param[in] ramt: Pointer to the RAMT structure
|
||||||
|
* \param[in] mode: The mode of the RAM test, see RAMT_MODE_XXX define
|
||||||
|
* \param[in] duration: The duration for which the RAM test should run, 0xFFFFFFFF continuous running
|
||||||
|
* \return 1 if the operation is successful, 0 if it fails
|
||||||
|
*/
|
||||||
|
int ramt_start(RAMT *ramt, uint32_t mode, uint32_t duration);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Stop the RAM testing
|
||||||
|
* \param[in] ramt: Pointer to the RAMT structure
|
||||||
|
* \return 1 if the operation is successful, 0 if it fails
|
||||||
|
*/
|
||||||
|
int ramt_stop(RAMT *ramt);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Retrieve the historical result of the RAM test
|
||||||
|
* \param[in] ramt: Pointer to the RAMT structure
|
||||||
|
* \return The result history if successful, 0xFFFFFFFF if it invalid, fail mask see RAMT_MODE_XXX define
|
||||||
|
*/
|
||||||
|
uint32_t ramt_result(RAMT *ramt);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Retrieve the latest result of the RAM test
|
||||||
|
* \param[in] ramt: Pointer to the RAMT structure
|
||||||
|
* \return The latest result if successful, 0xFFFFFFFF if it invalid, fail mask see RAMT_MODE_XXX define
|
||||||
|
*/
|
||||||
|
uint32_t ramt_result_latest(RAMT *ramt);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Periodically execute RAM testing tasks based on the mode and duration
|
||||||
|
* \param[in] ramt: Pointer to the RAMT structure
|
||||||
|
*/
|
||||||
|
void ramt_task(RAMT *ramt);
|
||||||
|
|
||||||
|
#endif
|
||||||
469
source/06_performance/romt.c
Normal file
469
source/06_performance/romt.c
Normal file
@ -0,0 +1,469 @@
|
|||||||
|
/*********************************************************************************************************
|
||||||
|
* ------------------------------------------------------------------------------------------------------
|
||||||
|
* file description
|
||||||
|
* ------------------------------------------------------------------------------------------------------
|
||||||
|
* \file romt.c
|
||||||
|
* \unit romt
|
||||||
|
* \brief This is a simple rom test module for C language
|
||||||
|
* \author Lamdonn
|
||||||
|
* \version v0.1.0
|
||||||
|
* \license GPL-2.0
|
||||||
|
* \copyright Copyright (C) 2023 Lamdonn.
|
||||||
|
********************************************************************************************************/
|
||||||
|
#include "romt.h"
|
||||||
|
|
||||||
|
#define PRIVATE_INDEX_RESULT_HISTORY 0
|
||||||
|
#define PRIVATE_INDEX_RESULT_LATEST 1
|
||||||
|
#define PRIVATE_INDEX_DURATION 2
|
||||||
|
#define PRIVATE_INDEX_TEST_MODE 3
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Test the read functionality of the ROMT structure.
|
||||||
|
*
|
||||||
|
* This function reads data from the ROMT structure in units of UNIT_SIZE
|
||||||
|
* until the entire ROM is read. It verifies that the number of bytes read
|
||||||
|
* matches the expected number for each read operation.
|
||||||
|
*
|
||||||
|
* \param[in] romt: Pointer to the ROMT structure to be tested.
|
||||||
|
* \return Returns 1 if the read test is successful; otherwise, returns 0.
|
||||||
|
*/
|
||||||
|
static uint8_t test_read(ROMT *romt)
|
||||||
|
{
|
||||||
|
uint32_t base = romt->base; ///< Current address in the ROM
|
||||||
|
uint32_t size = 0; ///< Total bytes read
|
||||||
|
uint8_t buffer[UNIT_SIZE]; ///< Buffer to hold read data
|
||||||
|
uint16_t num; ///< Number of bytes to read in current iteration
|
||||||
|
|
||||||
|
while (size < romt->size) ///< Loop until the entire ROM is read
|
||||||
|
{
|
||||||
|
if (romt->size - size > UNIT_SIZE) num = UNIT_SIZE; ///< Determine number of bytes to read
|
||||||
|
else num = romt->size - size;
|
||||||
|
|
||||||
|
// Perform the read operation and check if the number of bytes read is correct
|
||||||
|
if (num != (uint8_t)(romt->read)(base, buffer, num))
|
||||||
|
{
|
||||||
|
return 0; ///< Return 0 if read operation fails
|
||||||
|
}
|
||||||
|
|
||||||
|
base += num; ///< Update the base address
|
||||||
|
size += num; ///< Update the total bytes read
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1; ///< Return 1 if the read test is successful
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Test the write functionality of the ROMT structure.
|
||||||
|
*
|
||||||
|
* This function writes data to the ROMT structure in units of UNIT_SIZE
|
||||||
|
* until the entire ROM is written. It verifies that the number of bytes
|
||||||
|
* written matches the expected number for each write operation.
|
||||||
|
*
|
||||||
|
* \param[in] romt: Pointer to the ROMT structure to be tested.
|
||||||
|
* \return Returns 1 if the write test is successful; otherwise, returns 0.
|
||||||
|
*/
|
||||||
|
static uint8_t test_write(ROMT *romt)
|
||||||
|
{
|
||||||
|
uint32_t base = romt->base; ///< Current address in the ROM
|
||||||
|
uint32_t size = 0; ///< Total bytes written
|
||||||
|
uint8_t buffer[UNIT_SIZE] = {0}; ///< Buffer initialized to zeros for writing
|
||||||
|
uint16_t num; ///< Number of bytes to write in current iteration
|
||||||
|
|
||||||
|
while (size < romt->size) ///< Loop until the entire ROM is written
|
||||||
|
{
|
||||||
|
if (romt->size - size > UNIT_SIZE) num = UNIT_SIZE; ///< Determine number of bytes to write
|
||||||
|
else num = romt->size - size;
|
||||||
|
|
||||||
|
// Perform the write operation and check if the number of bytes written is correct
|
||||||
|
if (num != (uint8_t)(romt->write)(base, buffer, num))
|
||||||
|
{
|
||||||
|
return 0; ///< Return 0 if write operation fails
|
||||||
|
}
|
||||||
|
|
||||||
|
base += num; ///< Update the base address
|
||||||
|
size += num; ///< Update the total bytes written
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1; ///< Return 1 if the write test is successful
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Test the normal functionality of the ROMT structure.
|
||||||
|
*
|
||||||
|
* This function writes a pattern to the ROMT structure and then reads it back.
|
||||||
|
* It verifies that the data read matches the pattern that was written.
|
||||||
|
* The pattern consists of values from 0 to 255, repeating as necessary.
|
||||||
|
*
|
||||||
|
* \param[in] romt: Pointer to the ROMT structure to be tested.
|
||||||
|
* \return Returns 1 if the normal test is successful; otherwise, returns 0.
|
||||||
|
*/
|
||||||
|
static uint8_t test_normal(ROMT *romt)
|
||||||
|
{
|
||||||
|
uint32_t base = romt->base; ///< Current address in the ROM
|
||||||
|
uint32_t size = 0; ///< Total bytes processed
|
||||||
|
uint8_t buffer[UNIT_SIZE]; ///< Buffer for reading and writing data
|
||||||
|
uint16_t i, num; ///< Loop index and number of bytes for current iteration
|
||||||
|
|
||||||
|
while (size < romt->size) ///< Loop until the entire ROM is processed
|
||||||
|
{
|
||||||
|
// Determine number of bytes to write in the current iteration
|
||||||
|
if (romt->size - size > UNIT_SIZE)
|
||||||
|
num = UNIT_SIZE;
|
||||||
|
else
|
||||||
|
num = romt->size - size;
|
||||||
|
|
||||||
|
// Fill the buffer with a pattern (0, 1, 2, ..., 255)
|
||||||
|
for (i = 0; i < UNIT_SIZE; i++)
|
||||||
|
{
|
||||||
|
buffer[i] = (uint8_t)(i % 256);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform the write operation and check if the number of bytes written is correct
|
||||||
|
if (num != (uint8_t)(romt->write)(base, buffer, num))
|
||||||
|
{
|
||||||
|
return 0; ///< Return 0 if write operation fails
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear the buffer before reading
|
||||||
|
memset(buffer, 0, sizeof(buffer));
|
||||||
|
|
||||||
|
// Perform the read operation and check if the number of bytes read is correct
|
||||||
|
if (num != (uint8_t)(romt->read)(base, buffer, num))
|
||||||
|
{
|
||||||
|
return 0; ///< Return 0 if read operation fails
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that the read data matches the expected pattern
|
||||||
|
for (i = 0; i < UNIT_SIZE; i++)
|
||||||
|
{
|
||||||
|
if (buffer[i] != (uint8_t)(i % 256))
|
||||||
|
{
|
||||||
|
return 0; ///< Return 0 if the read data does not match the expected pattern
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
base += num; ///< Update the base address for the next iteration
|
||||||
|
size += num; ///< Update the total bytes processed
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1; ///< Return 1 if the normal test is successful
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Test the boundary write and read functionality of the ROMT structure.
|
||||||
|
*
|
||||||
|
* This function writes data to the first and last byte of the ROMT structure
|
||||||
|
* and then reads it back to verify that the data was written correctly.
|
||||||
|
*
|
||||||
|
* \param[in] romt: Pointer to the ROMT structure to be tested.
|
||||||
|
* \return Returns 1 if the boundary test is successful; otherwise, returns 0.
|
||||||
|
*/
|
||||||
|
static uint8_t test_boundary(ROMT *romt)
|
||||||
|
{
|
||||||
|
uint8_t data = 0; ///< Variable for data to be written and read
|
||||||
|
|
||||||
|
// Write a value to the beginning of the ROM
|
||||||
|
data = 0xAA;
|
||||||
|
if ((romt->write)(romt->base, &data, 1) != 1)
|
||||||
|
{
|
||||||
|
return 0; ///< Return 0 if the write operation at the start fails
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write a value to the end of the ROM
|
||||||
|
data = 0xBB;
|
||||||
|
if ((romt->write)(romt->base + romt->size - 1, &data, 1) != 1)
|
||||||
|
{
|
||||||
|
return 0; ///< Return 0 if the write operation at the end fails
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read back the value from the beginning of the ROM and check if it matches
|
||||||
|
if ((romt->read)(romt->base, &data, 1) != 1 || data != 0xAA)
|
||||||
|
{
|
||||||
|
return 0; ///< Return 0 if the read operation at the start fails or if the data does not match
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read back the value from the end of the ROM and check if it matches
|
||||||
|
if ((romt->read)(romt->base + romt->size - 1, &data, 1) != 1 || data != 0xBB)
|
||||||
|
{
|
||||||
|
return 0; ///< Return 0 if the read operation at the end fails or if the data does not match
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1; ///< Return 1 if the boundary write and read tests are successful
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Test the random write and read functionality of the ROMT structure.
|
||||||
|
*
|
||||||
|
* This function randomly generates addresses and data to write to the ROMT structure
|
||||||
|
* and then reads back the data to verify that it matches what was written.
|
||||||
|
*
|
||||||
|
* \param[in] romt: Pointer to the ROMT structure to be tested.
|
||||||
|
* \param[in] iterations: Number of random write/read operations to perform.
|
||||||
|
* \return Returns 1 if the random test is successful; otherwise, returns 0.
|
||||||
|
*/
|
||||||
|
static uint8_t test_random(ROMT *romt, uint32_t iterations)
|
||||||
|
{
|
||||||
|
uint8_t data, temp; ///< Variables for data to write and read back
|
||||||
|
uint32_t i = 0; ///< Loop index
|
||||||
|
uint32_t addr; ///< Random address for writing and reading
|
||||||
|
|
||||||
|
// srand((unsigned int)time(NULL)); // Set random seed (uncomment to enable randomness)
|
||||||
|
for (i = 0; i < iterations; i++)
|
||||||
|
{
|
||||||
|
// Generate random address and data
|
||||||
|
addr = (rand() % (romt->size)) + romt->base; // Generate a random address within the ROM size
|
||||||
|
data = (uint8_t)(rand() % 256); // Generate random data (0 to 255)
|
||||||
|
|
||||||
|
// Write data to the randomly generated address
|
||||||
|
if ((romt->write)(addr, &data, 1) != 1)
|
||||||
|
{
|
||||||
|
return 0; // Return 0 if the write operation fails
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read data back from the same address
|
||||||
|
if ((romt->read)(addr, &temp, 1) != 1 || temp != data)
|
||||||
|
{
|
||||||
|
return 0; // Return 0 if the read operation fails or if the data does not match
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1; // Return 1 if the random write/read test succeeded
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Test the pattern write and read functionality of the ROMT structure.
|
||||||
|
*
|
||||||
|
* This function writes a specified pattern to the ROMT structure and then reads it back
|
||||||
|
* to verify that the data matches the expected pattern.
|
||||||
|
*
|
||||||
|
* \param[in] romt: Pointer to the ROMT structure to be tested.
|
||||||
|
* \param[in] pattern: Byte value to write repeatedly to the ROM.
|
||||||
|
* \return Returns 1 if the pattern test is successful; otherwise, returns 0.
|
||||||
|
*/
|
||||||
|
static uint8_t test_pattern(ROMT *romt, uint8_t pattern)
|
||||||
|
{
|
||||||
|
uint32_t base = romt->base; ///< Current base address in the ROM
|
||||||
|
uint32_t size = 0; ///< Total bytes processed
|
||||||
|
uint8_t buffer[UNIT_SIZE], temp[UNIT_SIZE]; ///< Buffers for writing and reading data
|
||||||
|
uint16_t i, num; ///< Loop index and number of bytes for current iteration
|
||||||
|
|
||||||
|
// Fill the buffer with the specified pattern
|
||||||
|
for (i = 0; i < UNIT_SIZE; i++)
|
||||||
|
{
|
||||||
|
buffer[i] = pattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (size < romt->size) ///< Loop until the entire ROM is processed
|
||||||
|
{
|
||||||
|
// Determine number of bytes to write in the current iteration
|
||||||
|
if (romt->size - size > UNIT_SIZE)
|
||||||
|
num = UNIT_SIZE;
|
||||||
|
else
|
||||||
|
num = romt->size - size;
|
||||||
|
|
||||||
|
// Write the pattern to the ROM
|
||||||
|
if (num != (uint8_t)(romt->write)(base, buffer, num))
|
||||||
|
{
|
||||||
|
return 0; // Return 0 if the write operation fails
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(temp, 0, sizeof(temp)); // Clear the temporary buffer before reading
|
||||||
|
|
||||||
|
// Read back the data from the ROM
|
||||||
|
if (num != (uint8_t)(romt->read)(base, temp, num))
|
||||||
|
{
|
||||||
|
return 0; // Return 0 if the read operation fails
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that the read data matches the expected pattern
|
||||||
|
for (i = 0; i < UNIT_SIZE; i++)
|
||||||
|
{
|
||||||
|
if (temp[i] != pattern)
|
||||||
|
{
|
||||||
|
return 0; // Return 0 if the read data does not match the expected pattern
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
base += num; ///< Update the base address for the next iteration
|
||||||
|
size += num; ///< Update the total bytes processed
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1; ///< Return 1 if the pattern write/read test succeeded
|
||||||
|
}
|
||||||
|
|
||||||
|
int romt_init(ROMT *romt)
|
||||||
|
{
|
||||||
|
// Check if the provided ROMT pointer is NULL
|
||||||
|
if (!romt) return 0;
|
||||||
|
|
||||||
|
// Check if the size of the ROM is zero
|
||||||
|
if (romt->size == 0) return 0;
|
||||||
|
|
||||||
|
// Check if the read function pointer is NULL
|
||||||
|
if (!romt->read) return 0;
|
||||||
|
|
||||||
|
// Check if the write function pointer is NULL
|
||||||
|
if (!romt->write) return 0;
|
||||||
|
|
||||||
|
// Initialize the private data to zero
|
||||||
|
memset(romt->private, 0, sizeof(romt->private));
|
||||||
|
|
||||||
|
return 1; // Initialization successful
|
||||||
|
}
|
||||||
|
|
||||||
|
int romt_start(ROMT *romt, uint32_t mode, uint32_t duration)
|
||||||
|
{
|
||||||
|
// Check if the romt pointer is valid
|
||||||
|
if (!romt) return 0;
|
||||||
|
|
||||||
|
// Check if the size of ROM is greater than 0
|
||||||
|
if (romt->size == 0) return 0;
|
||||||
|
|
||||||
|
// Check if the read function pointer is valid
|
||||||
|
if (!romt->read) return 0;
|
||||||
|
|
||||||
|
// Check if the write function pointer is valid
|
||||||
|
if (!romt->write) return 0;
|
||||||
|
|
||||||
|
// Check if mode and duration are valid
|
||||||
|
if (mode == 0 || duration == 0) return 0;
|
||||||
|
|
||||||
|
// Set the test mode and duration in the private data
|
||||||
|
romt->private[PRIVATE_INDEX_TEST_MODE] = mode;
|
||||||
|
romt->private[PRIVATE_INDEX_DURATION] = duration;
|
||||||
|
|
||||||
|
return 1; // Operation successful
|
||||||
|
}
|
||||||
|
|
||||||
|
int romt_stop(ROMT *romt)
|
||||||
|
{
|
||||||
|
// Check if the romt pointer is valid
|
||||||
|
if (!romt) return 0;
|
||||||
|
|
||||||
|
// Check if the size of ROM is greater than 0
|
||||||
|
if (romt->size == 0) return 0;
|
||||||
|
|
||||||
|
// Check if the read function pointer is valid
|
||||||
|
if (!romt->read) return 0;
|
||||||
|
|
||||||
|
// Check if the write function pointer is valid
|
||||||
|
if (!romt->write) return 0;
|
||||||
|
|
||||||
|
// Reset the test mode and duration in the private data
|
||||||
|
romt->private[PRIVATE_INDEX_TEST_MODE] = 0;
|
||||||
|
romt->private[PRIVATE_INDEX_DURATION] = 0;
|
||||||
|
|
||||||
|
return 1; // Operation successful
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t romt_result(ROMT *romt)
|
||||||
|
{
|
||||||
|
// Check if the romt pointer is valid
|
||||||
|
if (!romt) return 0xFFFFFFFF;
|
||||||
|
|
||||||
|
// Check if the size of ROM is greater than 0
|
||||||
|
if (romt->size == 0) return 0xFFFFFFFF;
|
||||||
|
|
||||||
|
// Check if the read function pointer is valid
|
||||||
|
if (!romt->read) return 0xFFFFFFFF;
|
||||||
|
|
||||||
|
// Check if the write function pointer is valid
|
||||||
|
if (!romt->write) return 0xFFFFFFFF;
|
||||||
|
|
||||||
|
// Return the historical result from the private data
|
||||||
|
return romt->private[PRIVATE_INDEX_RESULT_HISTORY];
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t romt_result_latest(ROMT *romt)
|
||||||
|
{
|
||||||
|
// Check if the romt pointer is valid
|
||||||
|
if (!romt) return 0xFFFFFFFF;
|
||||||
|
|
||||||
|
// Check if the size of ROM is greater than 0
|
||||||
|
if (romt->size == 0) return 0xFFFFFFFF;
|
||||||
|
|
||||||
|
// Check if the read function pointer is valid
|
||||||
|
if (!romt->read) return 0xFFFFFFFF;
|
||||||
|
|
||||||
|
// Check if the write function pointer is valid
|
||||||
|
if (!romt->write) return 0xFFFFFFFF;
|
||||||
|
|
||||||
|
// Return the latest result from the private data
|
||||||
|
return romt->private[PRIVATE_INDEX_RESULT_LATEST];
|
||||||
|
}
|
||||||
|
|
||||||
|
void romt_task(ROMT *romt)
|
||||||
|
{
|
||||||
|
uint32_t result = 0; // Variable to store the results of the tests
|
||||||
|
uint32_t mode = 0; // Variable to store the current testing mode
|
||||||
|
|
||||||
|
// Check if the romt pointer is not NULL
|
||||||
|
if (romt != NULL)
|
||||||
|
{
|
||||||
|
// Check if the duration is set to a special value or decrements it
|
||||||
|
if (romt->private[PRIVATE_INDEX_DURATION] == 0xFFFFFFFF ||
|
||||||
|
(romt->private[PRIVATE_INDEX_DURATION] > 0 && (romt->private[PRIVATE_INDEX_DURATION])--))
|
||||||
|
{
|
||||||
|
// Get the current testing mode
|
||||||
|
mode = romt->private[PRIVATE_INDEX_TEST_MODE];
|
||||||
|
|
||||||
|
// Perform read test if the read mode is enabled
|
||||||
|
if (mode & ROMT_MODE_READ)
|
||||||
|
{
|
||||||
|
if (!test_read(romt))
|
||||||
|
{
|
||||||
|
result |= ROMT_MODE_READ; // Mark failure for read test
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform write test if the write mode is enabled
|
||||||
|
if (mode & ROMT_MODE_WRITE)
|
||||||
|
{
|
||||||
|
if (!test_write(romt))
|
||||||
|
{
|
||||||
|
result |= ROMT_MODE_WRITE; // Mark failure for write test
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform normal test if the normal mode is enabled
|
||||||
|
if (mode & ROMT_MODE_NORMAL)
|
||||||
|
{
|
||||||
|
if (!test_normal(romt))
|
||||||
|
{
|
||||||
|
result |= ROMT_MODE_NORMAL; // Mark failure for normal test
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform boundary test if the boundary mode is enabled
|
||||||
|
if (mode & ROMT_MODE_BOUNDARY)
|
||||||
|
{
|
||||||
|
if (!test_boundary(romt))
|
||||||
|
{
|
||||||
|
result |= ROMT_MODE_BOUNDARY; // Mark failure for boundary test
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform random test if the random mode is enabled
|
||||||
|
if (mode & ROMT_MODE_RANDOM)
|
||||||
|
{
|
||||||
|
if (!test_random(romt, 0x55))
|
||||||
|
{
|
||||||
|
result |= ROMT_MODE_RANDOM; // Mark failure for random test
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform pattern test if the pattern mode is enabled
|
||||||
|
if (mode & ROMT_MODE_PATTERN)
|
||||||
|
{
|
||||||
|
if (!test_pattern(romt, 0x55))
|
||||||
|
{
|
||||||
|
result |= ROMT_MODE_PATTERN; // Mark failure for pattern test
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the latest result and accumulate the historical result
|
||||||
|
romt->private[PRIVATE_INDEX_RESULT_LATEST] = result;
|
||||||
|
romt->private[PRIVATE_INDEX_RESULT_HISTORY] |= result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
135
source/06_performance/romt.h
Normal file
135
source/06_performance/romt.h
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
/*********************************************************************************************************
|
||||||
|
* ------------------------------------------------------------------------------------------------------
|
||||||
|
* file description
|
||||||
|
* ------------------------------------------------------------------------------------------------------
|
||||||
|
* \file romt.h
|
||||||
|
* \unit romt
|
||||||
|
* \brief This is a simple rom test module for C language
|
||||||
|
* \author Lamdonn
|
||||||
|
* \version v0.1.0
|
||||||
|
* \license GPL-2.0
|
||||||
|
* \copyright Copyright (C) 2023 Lamdonn.
|
||||||
|
********************************************************************************************************/
|
||||||
|
#ifndef __romt_H
|
||||||
|
#define __romt_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/* Version infomation */
|
||||||
|
#define ROMT_V_MAJOR 0
|
||||||
|
#define ROMT_V_MINOR 1
|
||||||
|
#define ROMT_V_REVISE 0
|
||||||
|
|
||||||
|
#define ROMT_MODE_READ ((uint32_t)0x00000001) ///< Mode for reading from ROM
|
||||||
|
#define ROMT_MODE_WRITE ((uint32_t)0x00000002) ///< Mode for writing to ROM
|
||||||
|
#define ROMT_MODE_NORMAL ((uint32_t)0x00000004) ///< Normal operation mode
|
||||||
|
#define ROMT_MODE_BOUNDARY ((uint32_t)0x00000008) ///< Boundary condition mode
|
||||||
|
#define ROMT_MODE_RANDOM ((uint32_t)0x00000010) ///< Random access mode
|
||||||
|
#define ROMT_MODE_PATTERN ((uint32_t)0x00000020) ///< Pattern generation mode
|
||||||
|
|
||||||
|
#define UNIT_SIZE ((uint16_t)256) ///< Size of a unit data block
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Type definition for read callback function.
|
||||||
|
* \param[in] address: Address from which to read data.
|
||||||
|
* \param[in] data: Pointer to the buffer where data will be stored.
|
||||||
|
* \param[in] length: Number of bytes to read.
|
||||||
|
* \return Returns the number of bytes read on success; otherwise, an error code.
|
||||||
|
*/
|
||||||
|
typedef int (*romt_read_t)(uint32_t address, const uint8_t *data, uint32_t length);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Type definition for write callback function.
|
||||||
|
* \param[in] address: Address at which to write data.
|
||||||
|
* \param[in] data: Pointer to the buffer containing data to be written.
|
||||||
|
* \param[in] length: Number of bytes to write.
|
||||||
|
* \return Returns the number of bytes written on success; otherwise, an error code.
|
||||||
|
*/
|
||||||
|
typedef int (*romt_write_t)(uint32_t address, const uint8_t *data, uint32_t length);
|
||||||
|
|
||||||
|
// ROM structure definition
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint32_t base; ///< Pointer to the simulated ROM
|
||||||
|
uint32_t size; ///< Size of the ROM
|
||||||
|
romt_read_t read; ///< Read function pointer
|
||||||
|
romt_write_t write; ///< Write function pointer
|
||||||
|
uint32_t private[4]; ///< Private data, modification not allowed
|
||||||
|
} ROMT;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Initialize the ROMT structure.
|
||||||
|
*
|
||||||
|
* This function checks the validity of the provided ROMT structure and its parameters,
|
||||||
|
* and initializes the private data field to zero. It ensures that the size, read, and
|
||||||
|
* write function pointers are valid before proceeding with the initialization.
|
||||||
|
*
|
||||||
|
* \param[in] romt: Pointer to the ROMT structure to be initialized.
|
||||||
|
* \return Returns 1 if initialization is successful; otherwise, returns 0.
|
||||||
|
*/
|
||||||
|
int romt_init(ROMT *romt);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Start the ROMT operations with specified mode and duration.
|
||||||
|
*
|
||||||
|
* This function initializes the ROMT structure for operation by setting the test mode
|
||||||
|
* and duration. It checks the validity of the input parameters and ensures that the ROM
|
||||||
|
* is properly initialized before starting the operation.
|
||||||
|
*
|
||||||
|
* \param[in] romt: Pointer to the ROMT structure to be started.
|
||||||
|
* \param[in] mode: The mode of operation for the ROMT.
|
||||||
|
* \param[in] duration: The duration for which the operation should run.
|
||||||
|
* \return Returns 1 if the operation is successful; otherwise, returns 0.
|
||||||
|
*/
|
||||||
|
int romt_start(ROMT *romt, uint32_t mode, uint32_t duration);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Stop the ROMT operations and reset its configuration.
|
||||||
|
*
|
||||||
|
* This function halts the operation of the ROMT structure and resets the test mode
|
||||||
|
* and duration to zero. It ensures that the ROM is properly initialized before stopping
|
||||||
|
* the operation.
|
||||||
|
*
|
||||||
|
* \param[in] romt: Pointer to the ROMT structure to be stopped.
|
||||||
|
* \return Returns 1 if the operation is successful; otherwise, returns 0.
|
||||||
|
*/
|
||||||
|
int romt_stop(ROMT *romt);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Retrieve the historical result from the ROMT structure.
|
||||||
|
*
|
||||||
|
* This function checks the validity of the ROMT structure and returns the historical
|
||||||
|
* result stored in the private data. If any checks fail, it returns 0xFFFFFFFF
|
||||||
|
* to indicate an error.
|
||||||
|
*
|
||||||
|
* \param[in] romt: Pointer to the ROMT structure from which to retrieve the result.
|
||||||
|
* \return Returns the historical result if successful; otherwise, returns 0xFFFFFFFF.
|
||||||
|
*/
|
||||||
|
uint32_t romt_result(ROMT *romt);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Retrieve the latest result from the ROMT structure.
|
||||||
|
*
|
||||||
|
* This function checks the validity of the ROMT structure and returns the latest
|
||||||
|
* result stored in the private data. If any checks fail, it returns 0xFFFFFFFF
|
||||||
|
* to indicate an error.
|
||||||
|
*
|
||||||
|
* \param[in] romt: Pointer to the ROMT structure from which to retrieve the result.
|
||||||
|
* \return Returns the latest result if successful; otherwise, returns 0xFFFFFFFF.
|
||||||
|
*/
|
||||||
|
uint32_t romt_result_latest(ROMT *romt);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Execute the ROMT test tasks based on the configured test mode.
|
||||||
|
*
|
||||||
|
* This function checks the current test mode and performs the respective tests (read, write,
|
||||||
|
* normal, boundary, random, pattern) on the ROMT structure if the duration allows for it.
|
||||||
|
* It updates the latest result and accumulates the historical result in the private data.
|
||||||
|
*
|
||||||
|
* \param[in] romt: Pointer to the ROMT structure to be tested.
|
||||||
|
*/
|
||||||
|
void romt_task(ROMT *romt);
|
||||||
|
|
||||||
|
#endif
|
||||||
Loading…
x
Reference in New Issue
Block a user