2024-11-15 00:31:10 +08:00

212 lines
7.1 KiB
C

/*********************************************************************************************************
* ------------------------------------------------------------------------------------------------------
* file description
* ------------------------------------------------------------------------------------------------------
* \file cpul.c
* \unit cpul
* \brief This is a simple cpuload module for C language
* \author Lamdonn
* \version v1.0.0
* \license GPL-2.0
* \copyright Copyright (C) 2023 Lamdonn.
********************************************************************************************************/
#include "cpul.h"
#include <stdlib.h>
#include <string.h>
// Buffer for CRC calculation, initialized with some values
uint8_t calbuffer[CPUL_GEN_BSIZE] = {'A', 'B', 0};
/**
* \brief Adjust the refined load based on current and target loads.
*
* This function controls the refined load adjustment by comparing
* the current load with the target load and modifying the refined
* load accordingly.
*
* \param[in] cpul: Pointer to the CPUL instance.
* \return Returns the adjusted refined load value.
*/
static uint32_t controller(CPUL *cpul)
{
// If the current load is less than the target load
if (cpul->ctrl.cload < cpul->ctrl.tload)
{
// If adding resolution to refined load does not exceed its current value
if (cpul->ctrl.refine + cpul->resolution > cpul->ctrl.refine)
{
// Increase the refined load by the resolution value
cpul->ctrl.refine += cpul->resolution;
}
}
// If the current load is greater than target load + 1
else if (cpul->ctrl.cload > (cpul->ctrl.tload + 1))
{
// If the refined load is greater than or equal to the resolution
if (cpul->ctrl.refine >= cpul->resolution)
{
// Decrease the refined load by the resolution value
cpul->ctrl.refine -= cpul->resolution;
}
}
return cpul->ctrl.refine; // Return the adjusted refined load
}
/**
* \brief Calculate CRC8 checksum.
*
* This function computes the CRC8 checksum for a given data buffer.
* It iterates through each byte of data and processes it to generate
* the CRC value.
*
* \param[in] data: Pointer to the data buffer.
* \param[in] len: Length of the data buffer.
* \return Returns the calculated CRC8 value.
*/
static uint8_t crc8(uint8_t *data, uint32_t len)
{
uint8_t i; // Loop index for bit processing
uint8_t crc = 0; // Initialize CRC value to 0
while (len--) // Process each byte in the data buffer
{
crc ^= *data++; // XOR the current byte with the CRC value
for (i = 0; i < 8; i++) // Process each bit of the byte
{
if (crc & 0x80) // If the highest bit of CRC is set
crc = (crc << 1) ^ 0x07; // Shift left and XOR with the polynomial
else
crc <<= 1; // Just shift left if the highest bit is not set
}
}
return crc; // Return the calculated CRC8 value
}
/**
* \brief Update the granularity of the load control.
*
* This function updates the calbuffer values based on the refined load
* using CRC8 checksum for each iteration specified by the input parameter.
*
* \param[in] input: Number of iterations to update the buffer.
* \return none.
*/
static void granularity(uint32_t input)
{
// Loop through the specified number of iterations
for (uint32_t i = 0; i < input; i++)
{
// Update calbuffer with a CRC8 value calculated from the current buffer
calbuffer[calbuffer[0] % sizeof(calbuffer)] = crc8(calbuffer, sizeof(calbuffer));
}
}
/**
* \brief Initialize the CPUL instance.
*
* This function initializes the CPUL structure to default values
* and checks for valid pointers.
*
* \param[in] cpul: Pointer to the CPUL instance.
* \return Returns CPUL_E_OK on success, otherwise an error code.
*/
int cpul_init(CPUL *cpul)
{
// Check if the cpul pointer is valid
if (!cpul) return CPUL_E_INVALID;
// Check if the raw function pointer is valid
if (!cpul->raw) return CPUL_E_RAW;
cpul->ctrl.cload = 0xFFFF; // Set current load to untested value
cpul->ctrl.tload = 0; // Default target load to zero (no load increase)
cpul->ctrl.refine = 0; // Initialize refined load
return CPUL_E_OK; // Initialization successful
}
/**
* \brief Get the current CPU load.
*
* This function retrieves the current load from the CPUL instance
* and checks for validity of parameters and state.
*
* \param[in] cpul: Pointer to the CPUL instance.
* \param[out] load: Pointer to store the current load value.
* \return Returns CPUL_E_OK on success, otherwise an error code.
*/
int cpul_get(CPUL *cpul, uint16_t *load)
{
// Check if the cpul pointer is valid
if (!cpul) return CPUL_E_INVALID;
// Check if the raw function pointer is valid
if (!cpul->raw) return CPUL_E_RAW;
// Check if the load parameter is valid
if (!load) return CPUL_E_PARA;
// If current load is still untested, return an error
if (cpul->ctrl.cload == 0xFFFF) return CPUL_E_NTEST;
// Check if the current load exceeds the maximum allowed value
if (cpul->ctrl.cload > 10000) return CPUL_E_OVER;
*load = cpul->ctrl.cload; // Retrieve the current load value
return CPUL_E_OK; // Success
}
/**
* \brief Set the target CPU load.
*
* This function sets the target load for the CPUL instance and checks for valid parameters.
*
* \param[in] cpul: Pointer to the CPUL instance.
* \param[in] load: Target load value to set.
* \return Returns CPUL_E_OK on success, otherwise an error code.
*/
int cpul_set(CPUL *cpul, uint16_t load)
{
// Check if the cpul pointer is valid
if (!cpul) return CPUL_E_INVALID;
// Check if the raw function pointer is valid
if (!cpul->raw) return CPUL_E_RAW;
// Check if the load parameter is zero
if (!load) return CPUL_E_PARA;
// Check if the load exceeds the maximum allowed value
if (load > 10000) return CPUL_E_OVER;
cpul->ctrl.tload = load; // Set the target load
return CPUL_E_OK; // Success
}
/**
* \brief Execute a CPUL management task.
*
* This function executes a task to manage the CPU load based on
* the current and target load values.
*
* \param[in] cpul: Pointer to the CPUL instance.
* \return Returns CPUL_E_OK on success, otherwise an error code.
*/
int cpul_task(CPUL *cpul)
{
// Check if the cpul pointer is valid
if (!cpul) return CPUL_E_INVALID;
// Check if the raw function pointer is valid
if (!cpul->raw) return CPUL_E_RAW;
// Call the raw function to get the current load value
cpul->ctrl.cload = cpul->raw(cpul->coreid);
// If the target load is not zero, perform load management
if (cpul->ctrl.tload != 0)
{
// Adjust the refined load based on current and target load
cpul->ctrl.refine = controller(cpul);
// Update granularity based on the refined load
granularity(cpul->ctrl.refine);
}
return CPUL_E_OK; // Success
}