Ejemplo n.º 1
0
// Function Specification
//
// Name: amec_update_channel_sensor
//
// Description: Updates the APSS channel sensors only.  Used to calculate power based
//              on raw data obtained from APSS
//
// End Function Specification
void amec_update_channel_sensor(const uint8_t i_channel)
{
    if (i_channel < MAX_APSS_ADC_CHANNELS)
    {
        if(AMECSENSOR_PTR(PWRAPSSCH0 + i_channel)->ipmi_sid != 0)
        {
            uint32_t l_bulk_voltage = ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.sense_12v);

            uint32_t l_temp32 = ADC_CONVERTED_VALUE(i_channel);
            l_temp32  = ((l_temp32  * l_bulk_voltage)+ADCMULT_ROUND)/ADCMULT_TO_UNITS;
            sensor_update(AMECSENSOR_PTR(PWRAPSSCH0 + i_channel), (uint16_t) l_temp32);
        }
    }
}
Ejemplo n.º 2
0
// Function Specification
//
// Name: amec_update_apss_sensors
//
// Description: Calculates sensor from raw ADC value
//
// Thread: RealTime Loop
//
// End Function Specification
void amec_update_apss_sensors(void)
{
    /*
     * Removed fake apss config data, do not reuse, the old hardcoded
     * values will not work with the new code used in processing APSS channel
     * data.
     * Code is in place to receive command code 0x21 SET CONFIG DATA
     * which should popluate the ADC and GPIO maps as well as the APSS
     * calibration data for all 16 ADC channels.
     */

    // ------------------------------------------------------
    // APSS Data Collection & Sensorization
    // ------------------------------------------------------

    // Need to check to make sure APSS data has been received
    // via slave inbox first
    if(G_slv_inbox_received)
    {
        uint8_t l_proc  = G_pob_id.module_id;
        uint32_t temp32 = 0;
        uint8_t  l_idx   = 0;
        uint32_t l_bulk_current_sum = 0;

        // ----------------------------------------------------
        // Convert all ADC Channels immediately
        // ----------------------------------------------------
        for(l_idx=0; l_idx < MAX_APSS_ADC_CHANNELS; l_idx++)
        {
            // These values returned are gain adjusted. The APSS readings for
            // the remote ground and 12V sense are returned in mVs, all other
            // readings are treated as mAs.
            G_lastValidAdcValue[l_idx] = amec_value_from_apss_adc(l_idx);

            // Add up all channels now, we will subtract ones later that don't
            // count towards the system power
            l_bulk_current_sum += G_lastValidAdcValue[l_idx];
        }

        // --------------------------------------------------------------
        // Convert 12Vsense into interim value - this has to happen first
        // --------------------------------------------------------------
        uint32_t l_bulk_voltage = ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.sense_12v);

        // ----------------------------------------------------------
        // Convert Raw Vdd/Vcs/Vio/Vpcie Power from APSS into sensors
        // ----------------------------------------------------------
        // Some sensor values are in Watts so after getting the mA readings we
        // multiply by the bulk voltage (mVs) which requires us to then divide
        // by 1000000 to get W (A.V), ie.
        //  divide by    1000 to get it back to milliUnits (0.001)
        //  divide by   10000 to get it to centiUnits      (0.01)
        //  divide by  100000 to get it to deciUnits       (0.1)
        //  divide by 1000000 to get it to Units           (1)
        #define ADCMULT_TO_UNITS 1000000
        #define ADCMULT_ROUND ADCMULT_TO_UNITS/2
        uint32_t l_vdd = ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.vdd[l_proc]);
        uint32_t l_vcs_vio_vpcie = ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.vcs_vio_vpcie[l_proc]);
        temp32 = ((l_vcs_vio_vpcie + l_vdd) * l_bulk_voltage)/ADCMULT_TO_UNITS;
        sensor_update(AMECSENSOR_PTR(PWR250USP0), (uint16_t) temp32);
        // Save off the combined power from all modules
        for (l_idx=0; l_idx < MAX_NUM_CHIP_MODULES; l_idx++)
        {
            uint32_t l_vd = ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.vdd[l_idx]);
            uint32_t l_vpcie = ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.vcs_vio_vpcie[l_idx]);
            g_amec->proc_snr_pwr[l_idx] =  ((l_vpcie + l_vd) * l_bulk_voltage)/ADCMULT_TO_UNITS;
        }

        // All readings from APSS come back as milliUnits, so if we want
        // to convert one, we need to
        //  divide by    1 to get it back to milliUnits (0.001)
        //  divide by   10 to get it to centiUnits      (0.01)
        //  divide by  100 to get it to deciUnits       (0.1)
        //  divide by 1000 to get it to Units           (1)
        #define ADCSINGLE_TO_CENTIUNITS 100
        // Vdd has both a power and a current sensor, we convert the Vdd power
        // to Watts and the current to centiAmps
        temp32 = ((l_vdd * l_bulk_voltage)+ADCMULT_ROUND)/ADCMULT_TO_UNITS;
        sensor_update( AMECSENSOR_PTR(PWR250USVDD0), (uint16_t)temp32);
        temp32 = (l_vdd)/ADCSINGLE_TO_CENTIUNITS; // Current is in 0.01 Amps,
        sensor_update( AMECSENSOR_PTR(CUR250USVDD0), l_vdd);
        temp32 = ((l_vcs_vio_vpcie * l_bulk_voltage)+ADCMULT_ROUND)/ADCMULT_TO_UNITS;
        sensor_update( AMECSENSOR_PTR(PWR250USVCS0), (uint16_t)temp32);

        // ----------------------------------------------------
        // Convert Other Raw Misc Power from APSS into sensors
        // ----------------------------------------------------

        // Fans
        temp32  = ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.fans[0]);
        temp32 += ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.fans[1]);
        temp32  = ((temp32  * l_bulk_voltage)+ADCMULT_ROUND)/ADCMULT_TO_UNITS;
        sensor_update( AMECSENSOR_PTR(PWR250USFAN), (uint16_t)temp32);

        // I/O
        temp32  = ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.io[0]);
        temp32 += ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.io[1]);
        temp32 += ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.io[2]);
        temp32 = ((temp32  * l_bulk_voltage)+ADCMULT_ROUND)/ADCMULT_TO_UNITS;
        sensor_update( AMECSENSOR_PTR(PWR250USIO), (uint16_t)temp32);

        // Memory
        temp32 = ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.memory[l_proc]);
        temp32 = ((temp32  * l_bulk_voltage)+ADCMULT_ROUND)/ADCMULT_TO_UNITS;
        sensor_update( AMECSENSOR_PTR(PWR250USMEM0), (uint16_t)temp32);
        // Save off the combined power from all memory
        for (l_idx=0; l_idx < MAX_NUM_CHIP_MODULES; l_idx++)
        {
            uint32_t l_temp = ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.memory[l_idx]);
            g_amec->mem_snr_pwr[l_idx] = ((l_temp  * l_bulk_voltage)+ADCMULT_ROUND)/ADCMULT_TO_UNITS;
        }

        // Storage/Media
        temp32  = ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.storage_media[0]);
        temp32 += ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.storage_media[1]);
        temp32  = ((temp32  * l_bulk_voltage)+ADCMULT_ROUND)/ADCMULT_TO_UNITS;
        sensor_update( AMECSENSOR_PTR(PWR250USSTORE), (uint16_t)temp32);

        // GPU adapter
        temp32 = ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.gpu);
        temp32 = ((temp32 * l_bulk_voltage)+ADCMULT_ROUND)/ADCMULT_TO_UNITS;
        sensor_update( AMECSENSOR_PTR(PWR250USGPU), (uint16_t)temp32);

        // ----------------------------------------------------
        // Convert Raw Bulk Power from APSS into sensors
        // ----------------------------------------------------
        // We don't get this adc channel in some systems, we have to add it manually.
        // With valid sysconfig data the code here should automatically use what
        // is provided by the APSS if it is available, or manually sum it up if not.
        temp32 = ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.total_current_12v);
        temp32 = ((temp32 * l_bulk_voltage)+ADCMULT_ROUND)/ADCMULT_TO_UNITS;

        // To calculated the total 12V current based on a sum of all ADC channels,
        // Subract adc channels that don't measure power
        l_bulk_current_sum -= ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.sense_12v);
        l_bulk_current_sum -= ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.remote_gnd);

        // If we don't have a ADC channel that measures the bulk 12v power, use
        // the ADC sum instead
        if(0 == temp32)
        {
            temp32 = ((l_bulk_current_sum * l_bulk_voltage)+ADCMULT_ROUND)/ADCMULT_TO_UNITS;
        }
        sensor_update(AMECSENSOR_PTR(PWR250US), (uint16_t)temp32);

        // Calculate average frequency of all OCCs.
        uint32_t    l_allOccAvgFreqOver250us = 0;
        uint8_t     l_presentOCCs = 0;
        uint8_t     l_occCount = 0;

        // Add up the average freq from all OCCs.
        for (l_occCount = 0; l_occCount < MAX_OCCS; l_occCount++)
        {
            if (G_sysConfigData.is_occ_present & (1<< l_occCount))
            {
                l_allOccAvgFreqOver250us += G_dcom_slv_outbox_rx[l_occCount].freqa2msp0;
                l_presentOCCs++;
            }
        }
        //Calculate average of all the OCCs.
        l_allOccAvgFreqOver250us /= l_presentOCCs;

        // Save the max and min pwr250us sensors and keep an accumulator of the
        // average frequency over 30 seconds.
        if (g_pwr250us_over30sec.count == 0)
        {
            //The counter has been reset, therefore initialize the stored values.
            g_pwr250us_over30sec.max = (uint16_t) temp32;
            g_pwr250us_over30sec.min = (uint16_t) temp32;
            g_pwr250us_over30sec.freqaAccum = l_allOccAvgFreqOver250us;
        }
        else
        {
            //Check for max.
            if (temp32 > g_pwr250us_over30sec.max)
            {
                g_pwr250us_over30sec.max = (uint16_t) temp32;
            }
            //Check for min.
            if (temp32 < g_pwr250us_over30sec.min)
            {
                g_pwr250us_over30sec.min = (uint16_t) temp32;
            }
            //Average frequency accumulator.
            g_pwr250us_over30sec.freqaAccum += l_allOccAvgFreqOver250us;
        }

        //Count of number of updates.
        g_pwr250us_over30sec.count++;

        // ----------------------------------------------------
        // Clear Flag to indicate that AMEC has received the data.
        // ----------------------------------------------------
        G_slv_inbox_received = FALSE;
    }
    else
    {
        // Skip it...AMEC Health Monitor will figure out we didn't
        // update this sensor.
    }
}