/********************************************************************************************************* * ------------------------------------------------------------------------------------------------------ * 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 #include // 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 }