mirror of
https://gitee.com/Lamdonn/varch.git
synced 2025-12-06 08:46:42 +08:00
469 lines
17 KiB
C
469 lines
17 KiB
C
/*********************************************************************************************************
|
|
* ------------------------------------------------------------------------------------------------------
|
|
* 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 ROMT_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[ROMT_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 > ROMT_UNIT_SIZE) num = ROMT_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 != (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 ROMT_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[ROMT_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 > ROMT_UNIT_SIZE) num = ROMT_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 != (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[ROMT_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 > ROMT_UNIT_SIZE)
|
|
num = ROMT_UNIT_SIZE;
|
|
else
|
|
num = romt->size - size;
|
|
|
|
// Fill the buffer with a pattern (0, 1, 2, ..., 255)
|
|
for (i = 0; i < ROMT_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 != (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 != (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 < ROMT_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[ROMT_UNIT_SIZE], temp[ROMT_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 < ROMT_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 > ROMT_UNIT_SIZE)
|
|
num = ROMT_UNIT_SIZE;
|
|
else
|
|
num = romt->size - size;
|
|
|
|
// Write the pattern to the ROM
|
|
if (num != (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 != (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 < ROMT_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;
|
|
}
|
|
}
|
|
} |