Example #1
0
File: dimm.c Project: ploetzma/occ
// Scan all of the DIMM temps and keep track of the hottest
void update_hottest_dimm()
{
    // Find/save the hottest DIMM temperature for the last set of readings
    uint8_t hottest = 0, hottest_loc = 0;
    int pIndex, dIndex;
    for (pIndex = 0; pIndex < G_maxDimmPorts; ++pIndex)
    {
        for (dIndex = 0; dIndex < NUM_DIMMS_PER_CENTAUR; ++dIndex)
        {
            if (g_amec->proc[0].memctl[pIndex].centaur.dimm_temps[dIndex].cur_temp > hottest)
            {
                hottest = g_amec->proc[0].memctl[pIndex].centaur.dimm_temps[dIndex].cur_temp;
                hottest_loc = (pIndex*8) + dIndex;
            }
        }
    }

    DIMM_DBG("update_hottest_dimm: hottest DIMM temp for this sample: %dC (loc=%d)", hottest, hottest_loc);
    if(hottest > g_amec->proc[0].memctl[0].centaur.tempdimmax.sample_max)
    {
        // Save hottest DIMM location ever sampled
        DIMM_DBG("update_hottest_dimm: Hottest DIMM ever sampled was DIMM%d %dC (prior %dC)",
                 hottest_loc, hottest,  g_amec->proc[0].memctl[0].centaur.tempdimmax.sample_max);
        sensor_update(&g_amec->proc[0].memctl[0].centaur.locdimmax, hottest_loc);
    }
    // Nimbus has no Centaurs, but store hottest temp in memctl[0]
    sensor_update(&g_amec->proc[0].memctl[0].centaur.tempdimmax, hottest);
}
Example #2
0
// Function Specification
//
// Name: amec_update_external_voltage
//
// Description: Measure actual external voltage
//
// Thread: RealTime Loop
//
// End Function Specification
void amec_update_external_voltage()
{
    /*------------------------------------------------------------------------*/
    /*  Local Variables                                                       */
    /*------------------------------------------------------------------------*/
    uint32_t                    l_data = 0;
    uint16_t                    l_temp = 0;
    uint16_t                    l_vdd = 0;
    uint16_t                    l_vcs = 0;

    /*------------------------------------------------------------------------*/
    /*  Code                                                                  */
    /*------------------------------------------------------------------------*/
    // Collect the external voltage data
    l_data = in32(PMC_GLOBAL_ACTUAL_VOLTAGE_REG);

    // Extract the Vdd vid code and convert to voltage
    l_temp = (l_data & 0xFF000000) >>24;
    l_vdd = 16125 - ((uint32_t)l_temp * 625)/10;

    // Extract the Vcs vid code and convert to voltage
    l_temp = (l_data & 0x00FF0000) >>16;
    l_vcs = 16125 - ((uint32_t)l_temp * 625)/10;

    sensor_update( AMECSENSOR_PTR(VOLT250USP0V0), (uint16_t) l_vdd);
    sensor_update( AMECSENSOR_PTR(VOLT250USP0V1), (uint16_t) l_vcs);
}
Example #3
0
void state_normal_init(){
    reset_fsm();
    sensor_update();
    post_timeout_end = set_timeout(millis() + POST_PERIOD_MS);
    post_res = NOT_POSTING;
    needs_to_post_room_changed = 0;
    returned_led_state = 1;
	#ifdef UPSIDE_DOWN
    util_timer_set_accel(1);
	#endif
}
Example #4
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);
        }
    }
}
Example #5
0
// Function Specification
//
// Name: amec_dps_partition_update_sensors
//
// Description: Update utilization sensors for a core group.
//
// End Function Specification
void amec_dps_partition_update_sensors(const uint16_t i_part_id)
{
    /*------------------------------------------------------------------------*/
    /*  Local Variables                                                       */
    /*------------------------------------------------------------------------*/
    amec_core_perf_counter_t*   l_perf = NULL;
    uint16_t                    l_core_index = 0;
    uint8_t                     l_idx = 0;
    uint32_t                    l_cg_active_accumulator = 0;
    uint32_t                    l_cg_slack_accumulator = 0;
    uint16_t                    l_cg_util_slack_perc = 0;
    uint32_t                    l_divide32[2] = {0, 0};

    /*------------------------------------------------------------------------*/
    /*  Code                                                                  */
    /*------------------------------------------------------------------------*/
    for (l_idx=0; l_idx<g_amec->part_config.part_list[i_part_id].ncores; l_idx++)
    {
        l_core_index = g_amec->part_config.part_list[i_part_id].core_list[l_idx];
        l_perf = &g_amec->proc[0].core[l_core_index % MAX_NUM_CORES].core_perf;

        // Sum accumulators for core group
        l_cg_active_accumulator += l_perf->util_active_accumulator;
        l_cg_slack_accumulator += l_perf->util_slack_accumulator;
    }

    if (l_cg_active_accumulator == 0)
    {
        // Check for divide by zero
        l_cg_util_slack_perc=16384;  // if no active cores, set slack=100%
    }
    else
    {
        l_divide32[1]=(uint32_t)l_cg_active_accumulator;
        l_divide32[0]=(uint32_t)l_cg_slack_accumulator<<14;  // *16384 because 16384=1.0
        l_divide32[0] /= l_divide32[1];
        l_cg_util_slack_perc=(uint16_t)(l_divide32[0]);
    }

    // Update the sensor of the utilization slack
    sensor_update(&g_amec->part_config.part_list[i_part_id].util2msslack, l_cg_util_slack_perc);
}
Example #6
0
// Function Specification
//
// Name: amec_update_current_sensor
//
// Description: Estimates Vdd output current based on input power and Vdd voltage setting.
//   Compute CUR250USVDD0 (current out of Vdd regulator)
//
// Flow:
//
// Thread: RealTime Loop
//
// Changedby:
//
// Task Flags:
//
// End Function Specification
void amec_update_current_sensor(void)
{
    uint32_t result32; //temporary result
    uint16_t l_pow_reg_input_dW = AMECSENSOR_PTR(PWR250USVDD0)->sample * 10; // convert to dW by *10.
    uint16_t l_vdd_reg = AMECSENSOR_PTR(VOLT250USP0V0)->sample;
    uint32_t l_pow_reg_output_mW;
    uint32_t l_curr_output;


    /* Step 1 */

    // 1. Get PWR250USVDD0  (the input power to regulator)
    // 2. Look up efficiency using PWR250USVDD0 as index (and interpolate)
    // 3. Calculate output power = PWR250USVDD0 * efficiency
    // 4. Calculate output current = output power / Vdd set point

    /* Determine regulator efficiency */
    // use 85% efficiency all the time
    result32 = 8500;

    // Compute regulator output power.  out = in * efficiency
    //    in: min=0W max=300W = 3000dW
    //    eff: min=0 max=10000=100% (.01% units)
    //    p_out: max=3000dW * 10000 = 30,000,000 (dW*0.0001) < 2^25, fits in 25 bits
    l_pow_reg_output_mW = (uint32_t)l_pow_reg_input_dW * (uint32_t)result32;
    // Scale up p_out by 10x to give better resolution for the following division step
    //    p_out: max=30M (dW*0.0001) in 25 bits
    //    * 10    = 300M (dW*0.00001) in 29 bits
    l_pow_reg_output_mW *= 10;
    // Compute current out of regulator.  curr_out = power_out (*10 scaling factor) / voltage_out
    //    p_out: max=300M (dW*0.00001) in 29 bits
    //    v_out: min=5000 (0.0001 V)  max=16000(0.0001 V) in 14 bits
    //    i_out: max = 300M/5000 = 60000 (dW*0.00001/(0.0001V)= 0.01A), in 16 bits.
    // VOLT250USP0V0 in units of 0.0001 V = 0.1 mV. (multiply by 0.1 to get mV)
    l_curr_output = l_pow_reg_output_mW / l_vdd_reg;
    sensor_update(AMECSENSOR_PTR(CUR250USVDD0), l_curr_output);

}
Example #7
0
void int_cmt_cmt1(void)
{
    cmt1_counter++;

    //各処理系///////////////////////////////////////////////////////////////////
//	map_update();						//ジャイロと2つのエンコーダを用いてマップの更新(coordinate_omni)
//	gyro_map();							//ジャイロMAP状態の更新

    sensor_update();//センサーの状態を確認(アームの状態等の取得)

    //プレステコンからの受信/////////////////////////////////////////////////////
    recieve_data_input();				//受信割り込みから受け取った値を格納(中でdutyも計算している)


    input_register_ctrl();						//dutyをレジスタに格納

    ////////////////////////////////////////////////////////////////////////////

    //自動制御//////////////////////////////////////////////////////////////////
//	if(left_arm_auto_flag==1)
//	left_arm_ctrl();						//アーム自動制御

    cmt1_counter=0;
}
Example #8
0
// Function Specification
//
// Name: amec_update_vrm_sensors
//
// Description: Updates sensors that use data from the VRMs
// (e.g., VR_FAN, FANS_FULL_SPEED, VR_HOT).
//
// Thread: RealTime Loop
//
// End Function Specification
void amec_update_vrm_sensors(void)
{
    /*------------------------------------------------------------------------*/
    /*  Local Variables                                                       */
    /*------------------------------------------------------------------------*/
    int                         l_rc = 0;
    int                         l_vrfan = 0;
    int                         l_softoc = 0;
    int                         l_minus_np1_regmode = 0;
    int                         l_minus_n_regmode = 0;
    static uint8_t              L_error_count = 0;
    uint8_t                     l_pin = 0;
    uint8_t                     l_pin_value = 1; // active low, so set default to high
    uint8_t                     l_vrhot_count = 0;
    errlHndl_t                  l_err = NULL;

    /*------------------------------------------------------------------------*/
    /*  Code                                                                  */
    /*------------------------------------------------------------------------*/

    // Check if we have access to SPIVID. In DCMs only Master OCC has access to
    // the SPIVID.
    if (G_dcm_occ_role == OCC_DCM_MASTER)
    {
        // VR_FAN and SOFT_OC come from SPIVID
        l_rc = vrm_read_state(SPIVRM_PORT(0),
                            &l_minus_np1_regmode,
                            &l_minus_n_regmode,
                            &l_vrfan,
                            &l_softoc);

        if (l_rc == 0)
        {
            // Update the VR_FAN sensor
            sensor_update( AMECSENSOR_PTR(VRFAN250USPROC), (uint16_t)l_vrfan );

            // Clear our error count and the 'read failure' flag (since we can
            // read VR_FAN signal)
            L_error_count = 0;
            G_thrm_fru_data[DATA_FRU_VRM].read_failure = 0;

            // Obtain the 'fan_full_speed' GPIO from APSS
            l_pin = G_sysConfigData.apss_gpio_map.fans_full_speed;

            // No longer reading gpio from APSS in GA1 due to instability in
            // APSS composite mode
            //apss_gpio_get(l_pin, &l_pin_value);

            // VR_HOT sensor is a counter of number of times the VRHOT signal
            // has been asserted
            l_vrhot_count = AMECSENSOR_PTR(VRHOT250USPROC)->sample;

            // Check if VR_FAN is asserted AND if 'fans_full_speed' GPIO is ON.
            // Note that this GPIO is active low.
            if (AMECSENSOR_PTR(VRFAN250USPROC)->sample && !(l_pin_value))
            {
                // VR_FAN is asserted and 'fans_full_speed' GPIO is ON,
                // then increment our VR_HOT counter
                if (l_vrhot_count < g_amec->vrhotproc.setpoint)
                {
                    l_vrhot_count++;
                }
            }
            else
            {
                // Reset our VR_HOT counter
                l_vrhot_count = 0;
            }
            sensor_update(AMECSENSOR_PTR(VRHOT250USPROC), l_vrhot_count);
        }
        else
        {
            // Increment our error count
            L_error_count++;

            // Don't allow the error count to wrap
            if (L_error_count == 0)
            {
                L_error_count = 0xFF;
            }

            // Log an error if we exceeded our number of fail-to-read sensor
            if ((L_error_count == g_amec->proc[0].vrfan_error_count) &&
                (g_amec->proc[0].vrfan_error_count != 0xFF))
            {
                TRAC_ERR("amec_update_vrm_sensors: Failed to read VR_FAN for %u consecutive times!",
                         L_error_count);

                // Also, inform the thermal thread to send a cooling request
                G_thrm_fru_data[DATA_FRU_VRM].read_failure = 1;

                /* @
                 * @errortype
                 * @moduleid    AMEC_HEALTH_CHECK_VRFAN_TIMEOUT
                 * @reasoncode  VRM_VRFAN_TIMEOUT
                 * @userdata1   timeout value
                 * @userdata2   0
                 * @userdata4   OCC_NO_EXTENDED_RC
                 * @devdesc     Failed to read VR_FAN signal from regulator.
                 *
                 */
                l_err = createErrl(AMEC_HEALTH_CHECK_VRFAN_TIMEOUT,  //modId
                                   VRM_VRFAN_TIMEOUT,                //reasoncode
                                   OCC_NO_EXTENDED_RC,               //Extended reason code
                                   ERRL_SEV_PREDICTIVE,              //Severity
                                   NULL,                             //Trace Buf
                                   DEFAULT_TRACE_SIZE,               //Trace Size
                                   g_amec->thermaldimm.temp_timeout, //userdata1
                                   0);                               //userdata2

                // Callout backplane for this VRM error
                addCalloutToErrl(l_err,
                                 ERRL_CALLOUT_TYPE_HUID,
                                 G_sysConfigData.backplane_huid,
                                 ERRL_CALLOUT_PRIORITY_MED);

                // Commit the error
                commitErrl(&l_err);
            }
        }
    }

    if( 1 )
    {
        sensor_update( AMECSENSOR_PTR(VRFAN250USMEM), 0 );
        sensor_update( AMECSENSOR_PTR(VRHOT250USMEM), 0 );
    }
}
Example #9
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.
    }
}
Example #10
0
void state_normal_play(){
   // HACK do not allow all of these during posting until a clean way of aborting the FSM is coded.
    if (post_res == NOT_POSTING && usb_serial_get_nb_received() > 0){
		uint8_t res;
		char t[32];
        uint8_t c = usb_serial_get_byte();
        switch(c){
            case 'w':
#ifdef WIFI
                state_set_next(&main_fsm, &state_config);
#endif
                return;
                break;
            case 'e':
				DCALIB_PRINTF("HUM calib : %u\r\n", sensor_calib_HUM_is_done());
				DCALIB_PRINTF("TEMP calib : %u\r\n", sensor_calib_TEMP_is_done());
				DCALIB_PRINTF("PM calib : %u\r\n", sensor_calib_PM_is_done());
				DCALIB_PRINTF("k_HUM	: %u\r\n", eeprom_read_byte(calib_eeprom_k_hum_addr));
				DCALIB_PRINTF("b_HUM	: %li\r\n", (uint32_t)  round(eeprom_read_float(calib_eeprom_b_hum_addr)*100));
				DCALIB_PRINTF("k_TEMP : %u\r\n", eeprom_read_byte(calib_eeprom_k_temp_addr));
				DCALIB_PRINTF("b_TEMP : %li\r\n", (int32_t) round(eeprom_read_float(calib_eeprom_b_temp_addr)*100));
				DCALIB_PRINTF("k_PM	: %u\r\n", eeprom_read_byte(calib_eeprom_k_pm_addr));
				DCALIB_PRINTF("b_PM	: %li\r\n", (int32_t) round(eeprom_read_float(calib_eeprom_b_pm_addr)*100));
                break;
            case 'm':
                fprintf(&USBSerialStream, "MAC: %s\r\n", get_mac_str());
                break;
			case 'g':
#ifdef CALIBRATION
				sensor_calib_erase_calibration_k();
#endif
				break;
			case 'c':
				#ifdef CALIBRATION
				state_set_next(&main_fsm,&state_calibration);
				#endif
				break;
            case '-':
                println("Mem clear");
                wifi_config_mem_clear();
                error_set_post(POST_ERROR_WIFI_NO_CONFIG);
            default:
                break;
        }
    }


    if (error_post() != POST_ERROR_WIFI_NO_CONFIG){
        util_timer_enable_interrupt();
        

        // TODO update motor
        motor_set(180);// TEMP
        prev_post_res = post_res;
        // TODO integrate needs_to_post_room_changed to the flow to tell the backend that the room has changed...
        post_res = post_fsm(); // this runs the fsm until it stops then doesn't do anything until it's reset.
        
        uint32_t now = millis();

        if (prev_post_res == POSTING && post_res == NOT_POSTING){ // just finished posting
            if (post_fsm_error()){
                error_set_post(POST_ERROR_WIFI_NO_POST);
            } else {
                error_set_post(POST_ERROR_NO_ERROR);
            }
            DSENSOR_INFO_PRINTF("%lu, VOC, VOC_RAW, CO2, VZ87_VOC, VZ87_CO2, VZ87_RAW, SENSOR_1, SENSOR_2, PM*100, PM_Cal*100, TMP*100,PMP_Cal*100, HUM*100, HUM_Cal*100\r\n", now);
            sensor_update();
            update_timeout_end = set_timeout(now + SENSOR_UPDATE_PERIOD_MS);

            needs_to_post_room_changed = 0;
        }
        
        // when a change of room is detected, the timer before next post is put to at least
        // 1 min to avoid posting old data to the new room.
#ifdef UPSIDE_DOWN
        if ((post_res == NOT_POSTING) && upsidedown_detected ){ // posting must not be happening right now and an upside down condition must have been detected
            upsidedown_detected = 0;
            post_timeout_end = MAX(post_timeout_end, set_timeout(now + 60000));
            needs_to_post_room_changed = 1;
        }
#endif
#ifdef DOUBLE_TAP_ENABLED
		if ((post_res == NOT_POSTING) && double_tap_detected){
			reset_fsm();
		}
#endif
        if ( now > post_timeout_end && (post_res == NOT_POSTING)){ 
            reset_fsm();
            post_timeout_end = set_timeout(now + POST_PERIOD_MS);
        } else if (now > update_timeout_end && (post_res == NOT_POSTING)){
            sensor_update();
            update_timeout_end = set_timeout(now + SENSOR_UPDATE_PERIOD_MS);
        }
		

    } else {
        // The wifi has not been configured. This case is special since it makes it impossible to do anything interesting,
        // aside from configuring it.
        
        util_timer_disable_interrupt();

        led_set(0, 0, 100);
    }

}
Example #11
0
// Function Specification
//
// Name: amec_update_proc_core_sensors
//
// Description: Update all the sensors for a given proc
//
// Thread: RealTime Loop
//
// End Function Specification
void amec_update_proc_core_sensors(uint8_t i_core)
{
  gpe_bulk_core_data_t * l_core_data_ptr;
  int i;
  uint16_t               l_temp16 = 0;
  uint32_t               l_temp32 = 0;

  // Make sure the core is present, and that it has updated data.
  if(CORE_PRESENT(i_core) && CORE_UPDATED(i_core))
  {
    // Clear flag indicating core was updated by proc task
    CLEAR_CORE_UPDATED(i_core);

    // Get pointer to core data
    l_core_data_ptr = proc_get_bulk_core_data_ptr(i_core);

    //-------------------------------------------------------
    // Thermal Sensors & Calc
    //-------------------------------------------------------
    amec_calc_dts_sensors(l_core_data_ptr, i_core);

    //-------------------------------------------------------
    //CPM - Commented out as requested by Malcolm
    // ------------------------------------------------------
    // amec_calc_cpm_sensors(l_core_data_ptr, i_core);

    //-------------------------------------------------------
    // Util / Freq
    //-------------------------------------------------------
    // Skip this update if there was an empath collection error
    if (!CORE_EMPATH_ERROR(i_core))
    {
        amec_calc_freq_and_util_sensors(l_core_data_ptr,i_core);
    }

    //-------------------------------------------------------
    // Performance counter - This function should be called
    // after amec_calc_freq_and_util_sensors().
    //-------------------------------------------------------
    amec_calc_dps_util_counters(i_core);

    //-------------------------------------------------------
    // IPS
    //-------------------------------------------------------
    // Skip this update if there was an empath collection error
    if (!CORE_EMPATH_ERROR(i_core))
    {
        amec_calc_ips_sensors(l_core_data_ptr,i_core);
    }

    //-------------------------------------------------------
    // SPURR
    //-------------------------------------------------------
    amec_calc_spurr(i_core);

    // ------------------------------------------------------
    // Update PREVIOUS values for next time
    // ------------------------------------------------------
    g_amec->proc[0].core[i_core].prev_PC_RAW_Th_CYCLES = l_core_data_ptr->per_thread[0].raw_cycles;

    // Skip empath updates if there was an empath collection error on this core
    if (!CORE_EMPATH_ERROR(i_core))
    {
        g_amec->proc[0].core[i_core].prev_PC_RAW_CYCLES    = l_core_data_ptr->empath.raw_cycles;
        g_amec->proc[0].core[i_core].prev_PC_RUN_CYCLES    = l_core_data_ptr->empath.run_cycles;
        g_amec->proc[0].core[i_core].prev_PC_COMPLETED     = l_core_data_ptr->empath.completion;
        g_amec->proc[0].core[i_core].prev_PC_DISPATCH      = l_core_data_ptr->empath.dispatch;
        g_amec->proc[0].core[i_core].prev_tod_2mhz         = l_core_data_ptr->empath.tod_2mhz;
        g_amec->proc[0].core[i_core].prev_FREQ_SENS_BUSY   = l_core_data_ptr->empath.freq_sens_busy;
        g_amec->proc[0].core[i_core].prev_FREQ_SENS_FINISH = l_core_data_ptr->empath.freq_sens_finish;
    }

    for(i=0; i<MAX_THREADS_PER_CORE; i++)
    {
      g_amec->proc[0].core[i_core].thread[i].prev_PC_RUN_Th_CYCLES = l_core_data_ptr->per_thread[i].run_cycles;
    }

    // Final step is to update TOD sensors
    // Extract 32 bits with 16usec resolution
    l_temp32 = (uint32_t)(G_dcom_slv_inbox_doorbell_rx.tod>>13);
    l_temp16 = (uint16_t)(l_temp32);
    // low 16 bits is 16usec resolution with 512MHz TOD clock
    sensor_update( AMECSENSOR_PTR(TODclock0), l_temp16);
    l_temp16 = (uint16_t)(l_temp32>>16);
    // mid 16 bits is 1.05sec resolution with 512MHz TOD clock
    sensor_update( AMECSENSOR_PTR(TODclock1), l_temp16);
    l_temp16 = (uint16_t)(G_dcom_slv_inbox_doorbell_rx.tod>>45);
    // hi 3 bits in 0.796 day resolution with 512MHz TOD clock
    sensor_update( AMECSENSOR_PTR(TODclock2), l_temp16);
  }
Example #12
0
// Function Specification
//
// Name: amec_slv_voting_box
//
// Description: Slave OCC's voting box that decides the frequency request.
//              This function will run every tick.
//
// Thread: RealTime Loop
//
// Task Flags:
//
// End Function Specification
void amec_slv_voting_box(void)
{
    /*------------------------------------------------------------------------*/
    /*  Local Variables                                                       */
    /*------------------------------------------------------------------------*/
    uint16_t                        k = 0;
    uint16_t                        l_chip_fmax = g_amec->sys.fmax;
    uint16_t                        l_core_freq = 0;
    uint32_t                        l_chip_reason = 0;
    uint32_t                        l_core_reason = 0;
    uint8_t                         l_kvm_throt_reason = NO_THROTTLE;
    amec_part_t                     *l_part = NULL;
    bool                            l_freq_req_changed = FALSE;

    /*------------------------------------------------------------------------*/
    /*  Code                                                                  */
    /*------------------------------------------------------------------------*/

    // Voting Box for CPU speed.
    // This function implements the voting box to decide which input gets the right
    // to actuate the system.

    //Reset the maximum core frequency requested prior to recalculation.
    g_amec->proc[0].core_max_freq = 0;

    // PPB_FMAX
    if(g_amec->proc[0].pwr_votes.ppb_fmax < l_chip_fmax)
    {
        l_chip_fmax = g_amec->proc[0].pwr_votes.ppb_fmax;
        l_chip_reason = AMEC_VOTING_REASON_PPB;
        l_kvm_throt_reason = POWERCAP;
    }

    // PMAX_CLIP_FREQ
    if(g_amec->proc[0].pwr_votes.pmax_clip_freq < l_chip_fmax)
    {
        l_chip_fmax = g_amec->proc[0].pwr_votes.pmax_clip_freq;
        l_chip_reason = AMEC_VOTING_REASON_PMAX;
        l_kvm_throt_reason = POWER_SUPPLY_FAILURE;
    }

    // Pmax_clip frequency request if there is an APSS failure
    if(g_amec->proc[0].pwr_votes.apss_pmax_clip_freq < l_chip_fmax)
    {
        l_chip_fmax = g_amec->proc[0].pwr_votes.apss_pmax_clip_freq;
        l_chip_reason = AMEC_VOTING_REASON_APSS_PMAX;
        l_kvm_throt_reason = POWER_SUPPLY_FAILURE;
    }

    //THERMALPROC.FREQ_REQUEST
    //Thermal controller input based on processor temperature
    if(g_amec->thermalproc.freq_request < l_chip_fmax)
    {
        l_chip_fmax = g_amec->thermalproc.freq_request;
        l_chip_reason = AMEC_VOTING_REASON_PROC_THRM;
        l_kvm_throt_reason = CPU_OVERTEMP;
    }

    // Controller request based on VRHOT signal from processor regulator
    if(g_amec->vrhotproc.freq_request < l_chip_fmax)
    {
        l_chip_fmax = g_amec->vrhotproc.freq_request;
        l_chip_reason = AMEC_VOTING_REASON_VRHOT_THRM;
        l_kvm_throt_reason = CPU_OVERTEMP;
    }

    // CONN_OC_VOTE
    if(g_amec->proc[0].pwr_votes.conn_oc_vote < l_chip_fmax)
    {
        l_chip_fmax = g_amec->proc[0].pwr_votes.conn_oc_vote;
        l_chip_reason = AMEC_VOTING_REASON_CONN_OC;
        l_kvm_throt_reason = OVERCURRENT;
    }

    for (k=0; k<MAX_NUM_CORES; k++)
    {
        if(CORE_PRESENT(k))
        {
            l_core_freq = l_chip_fmax;
            l_core_reason = l_chip_reason;

            // Disable DPS in KVM
            if(!G_sysConfigData.system_type.kvm)
            {
                l_part = amec_part_find_by_core(&g_amec->part_config, k);

                // Check frequency request generated by DPS algorithms
                if(g_amec->proc[0].core[k].core_perf.dps_freq_request < l_core_freq)
                {
                    l_core_freq = g_amec->proc[0].core[k].core_perf.dps_freq_request;
                    l_core_reason = AMEC_VOTING_REASON_UTIL;
                }

                // Adjust frequency based on soft frequency boundaries
                if(l_part != NULL)
                {
                    if(l_core_freq < l_part->soft_fmin)
                    {
                        // Before enforcing a soft Fmin, make sure we don't
                        // have a thermal or power emergency
                        if(!(l_chip_reason & (AMEC_VOTING_REASON_PROC_THRM |
                                              AMEC_VOTING_REASON_VRHOT_THRM |
                                              AMEC_VOTING_REASON_PPB |
                                              AMEC_VOTING_REASON_PMAX |
                                              AMEC_VOTING_REASON_CONN_OC)))
                        {
                            l_core_freq = l_part->soft_fmin;
                            l_core_reason = AMEC_VOTING_REASON_SOFT_MIN;
                        }
                    }
                    else if(l_core_freq > l_part->soft_fmax)
                    {
                        l_core_freq = l_part->soft_fmax;
                        l_core_reason = AMEC_VOTING_REASON_SOFT_MAX;
                    }
                }
            }

            if(CURRENT_MODE() == OCC_MODE_NOMINAL)
            {
                // PROC_PCAP_NOM_VOTE
                if(g_amec->proc[0].pwr_votes.proc_pcap_nom_vote < l_core_freq)
                {
                    l_core_freq = g_amec->proc[0].pwr_votes.proc_pcap_nom_vote;
                    l_core_reason = AMEC_VOTING_REASON_PWR;
                    l_kvm_throt_reason = POWERCAP;
                }
            }
            else
            {
                // PROC_PCAP_VOTE
                if(g_amec->proc[0].pwr_votes.proc_pcap_vote < l_core_freq)
                {
                    l_core_freq = g_amec->proc[0].pwr_votes.proc_pcap_vote;
                    l_core_reason = AMEC_VOTING_REASON_PWR;
                    l_kvm_throt_reason = POWERCAP;
                }
            }

            // Check IPS frequency request sent by Master OCC
            if(g_amec->slv_ips_freq_request != 0)
            {
                if(g_amec->slv_ips_freq_request < l_core_freq)
                {
                    l_core_freq = g_amec->slv_ips_freq_request;
                    l_core_reason = AMEC_VOTING_REASON_IPS;
                }
            }

            // Override frequency with request from Master OCC
            if(g_amec->foverride_enable)
            {
                if(g_amec->foverride != 0)
                {
                    // Override the frequency on all cores if Master OCC sends
                    // a non-zero request
                    l_core_freq = g_amec->foverride;
                    l_core_reason = AMEC_VOTING_REASON_OVERRIDE;
                }
            }

            if(g_amec->pstate_foverride_enable)
            {
                if(g_amec->pstate_foverride != 0)
                {
                    // Override the frequency on all cores if the Global Pstate
                    // table has been modified
                    l_core_freq = g_amec->pstate_foverride;
                    l_core_reason = AMEC_VOTING_REASON_OVERRIDE;
                }
            }

            //Make sure the frequency is not less then the system min
            if(l_core_freq < g_amec->sys.fmin)
            {
                l_core_freq = g_amec->sys.fmin;
            }

            // Override frequency via Amester parameter interface
            if (g_amec->proc[0].parm_f_override_enable &&
                g_amec->proc[0].parm_f_override[k] > 0)
            {
                l_core_freq = g_amec->proc[0].parm_f_override[k];
                l_core_reason = AMEC_VOTING_REASON_OVERRIDE_CORE;
            }

            // If frequency has changed, set the flag
            if ( (l_core_freq != g_amec->proc[0].core[k].f_request) ||
                    (l_core_freq != g_amec->sys.fmax))
            {
                l_freq_req_changed = TRUE;
            }

            //STORE core frequency and reason
            g_amec->proc[0].core[k].f_request = l_core_freq;
            g_amec->proc[0].core[k].f_reason = l_core_reason;

            // Update the Amester parameter telling us the reason. Needed for
            // parameter array.
            g_amec->proc[0].parm_f_reason[k] = l_core_reason;

            //CURRENT_MODE() may be OCC_MODE_NOCHANGE because STATE change is processed
            //before MODE change
            if ((CURRENT_MODE() != OCC_MODE_DYN_POWER_SAVE) &&
                (CURRENT_MODE() != OCC_MODE_DYN_POWER_SAVE_FP) &&
                (CURRENT_MODE() != OCC_MODE_NOCHANGE) &&
                (l_core_reason & NON_DPS_POWER_LIMITED))
            {
                G_non_dps_power_limited = TRUE;
            }
            else
            {
                G_non_dps_power_limited = FALSE;
            }

            // Update the sensor telling us what the requested frequency is
            sensor_update( AMECSENSOR_ARRAY_PTR(FREQ250USP0C0,k),
                    (uint16_t) g_amec->proc[0].core[k].f_request);

#if 0
            /// TODO: This can be deleted if deemed useless
            /// This trace that can be used to debug the voting
            /// box an control loops.  It will trace the reason why a
            /// controller is lowering the freq, but will only do it once in a
            /// row for the specific freq it wants to control to.  It assumes
            /// that all cores will be controlled to same freq.
            if(l_chip_fmax != g_amec->sys.fmax){
                static uint16_t L_trace = 0;
                if(l_chip_fmax != L_trace){
                    L_trace = l_chip_fmax;
                    TRAC_INFO("Core: %d, Freq: %d, Reason: %d",k,l_core_freq,l_core_reason);
                }
            }
#endif

            if(l_core_freq > g_amec->proc[0].core_max_freq)
            {
                g_amec->proc[0].core_max_freq = l_core_freq;
            }
        }
        else
        {
            l_core_freq = 0;
            l_core_reason = 0;
        }
    }//End of for loop

    // Check if the frequency is going to be changing
    if( l_freq_req_changed == TRUE )
    {
        G_time_until_freq_check = FREQ_CHG_CHECK_TIME;
    }
    else if (G_time_until_freq_check != 0)
    {
        G_time_until_freq_check--;
    }

    //convert POWERCAP reason to POWER_SUPPLY_FAILURE if ovs/failsafe is asserted
    if((l_kvm_throt_reason == POWERCAP) &&
        (AMEC_INTF_GET_FAILSAFE() || AMEC_INTF_GET_OVERSUBSCRIPTION()))
    {
        l_kvm_throt_reason = POWER_SUPPLY_FAILURE;
    }

    //check if we need to update the throttle reason in homer
    if(G_sysConfigData.system_type.kvm &&
       (l_kvm_throt_reason != G_amec_kvm_throt_reason))
    {
        //Notify dcom thread to update the table
        G_amec_kvm_throt_reason = l_kvm_throt_reason;
        ssx_semaphore_post(&G_dcomThreadWakeupSem);
    }
}
Example #13
0
void state_calibration_play(){
	uint8_t c;
	char t[6];
	uint32_t now;
	value_sensor value_sensor_d;
	switch(calibration_fsm_state)
	{
			case CALFSM_STATE_CHOICE_DELAY:
				DCALIB_PRINT("\r\nPlease enter the delay between readings (in ms) : \r\n");	
				calibration_fsm_state=CALFSM_STATE_READING_DELAY;
				break;
			case CALFSM_STATE_READING_DELAY:
				c=usb_serial_get_byte();
				if (c>=48 && c<=57)
				{
					fprintf(&USBSerialStream,"%c",c);
					Value_T[fillpos++]=c;
				}
				else if (c=='\r')
				{
					Value_T[fillpos++]=c;
					delay_between_readings=char_to_int(Value_T,0,fillpos-1);
					fillpos=0;
					calibration_fsm_state=CALFSM_STATE_INITIALIZING;
				}
				break;
			case CALFSM_STATE_INITIALIZING:
				DCALIB_PRINT("\r\nPlease chose the calibration type (1 for PM, 2 for temperature, 3 for Humidity) \r\n");
				calibration_fsm_state=CALFSM_STATE_CHOICE_CALIB;
				break;
			case CALFSM_STATE_CHOICE_CALIB:
				c=usb_serial_get_byte();
				if (c>48 && c<=51)
				{
					type_of_calib=c-'0';
					calibration_fsm_state=CALFSM_STATE_READING_SENSOR;
				}				
				break;
			case CALFSM_STATE_READING_SENSOR:
				sensor_update();
				switch(type_of_calib)
				{
					case 1:
						Sensor_t[number_of_reading-1] = (int32_t) (sensors_acc.pm_instant*100);
						break;
					case 2:
						Sensor_t[number_of_reading-1]	=	(uint32_t) (sensors_acc.tmp_instant*100.0);
						break;
					case 3:
						Sensor_t[number_of_reading-1]	=	(uint32_t) (sensors_acc.hum_instant*100.0);
						break;
				}
				if (number_of_reading==1 || number_of_reading ==2)
				{
					number_of_reading++;
					now=millis();
					waiting_end=set_timeout(now+delay_between_readings);
					calibration_fsm_state=CALFSM_STATE_WAITING;
				}
				else 
				{
					DCALIB_PRINTF("T_0 : %lu, T_5 : %lu, T_10 : %lu \r\n", Sensor_t[0], Sensor_t[1], Sensor_t[2]);
					DCALIB_PRINT("Enter the reference values (ref_0;ref_5;ref_10) : \r\n");
					number_of_reading=1;
					calibration_fsm_state=CALFSM_STATE_READING_VALUE_T;
				}
				break;
			case CALFSM_STATE_WAITING:
				//DCALIB_PRINTF("\r\n %li", (int32_t) (millis()-waiting_end));
				if (millis()>waiting_end)
				{
						calibration_fsm_state=CALFSM_STATE_READING_SENSOR;
				}
				break;
			case CALFSM_STATE_READING_VALUE_T:
				c=usb_serial_get_byte();
				if (c>=48 && c<=57 || c==';')
				{
					fprintf(&USBSerialStream,"%c",c);
					Value_T[fillpos++]=c;
				}
				else if (c=='\r')
				{
					Value_T[fillpos++]=c;
					value_sensor_d=parse_ref_value(Value_T,fillpos);
					Sensor_Ref_0=char_to_int(Value_T,0,value_sensor_d.length_S_0);
					Sensor_Ref_5=char_to_int(Value_T,value_sensor_d.length_S_0+1,value_sensor_d.length_S_5);
					Sensor_Ref_10=char_to_int(Value_T,value_sensor_d.length_S_5+1,value_sensor_d.length_S_10);
					//DCALIB_PRINTF("T_0 : %lu, T_5 : %lu, T_10 %lu\r\n",Sensor_Ref_0, Sensor_Ref_5 ,Sensor_Ref_10);
					fillpos=0;
					calibration_fsm_state=CALFSM_STATE_CALCULATE_K;	
				}
				break;
			case CALFSM_STATE_CALCULATE_K:
				coef=calculate_k(Sensor_Ref_0, Sensor_t[0], Sensor_Ref_10, Sensor_t[2]);
				coef1=calculate_k(Sensor_Ref_0, Sensor_t[0], Sensor_Ref_5, Sensor_t[1]);
				coef2=calculate_k(Sensor_Ref_5, Sensor_t[1], Sensor_Ref_10, Sensor_t[2]);
				fprintf(&USBSerialStream,"\n\r 0-10	a	: %u ,	b : %li	, Calibrated_t_5	 : %lu ",coef.a, coef.b, (uint32_t) round(((double)(Sensor_t[1]*coef.a+coef.b)/100)));
				fprintf(&USBSerialStream,"\n\r 0-5	a	: %u ,	b : %li	, Calibrated_t_10	 : %lu  ",coef1.a, coef1.b, (uint32_t) round(((double)(Sensor_t[2]*coef1.a+coef1.b)/100)));
				fprintf(&USBSerialStream,"\n\r 5-10	a	: %u ,	b : %li	, Calibrated_t_0	 : %lu  \r\n",coef2.a, coef2.b, (uint32_t) round(((double)(Sensor_t[0]*coef2.a+coef2.b)/100)) );
				DCALIB_PRINT("Press 1, 2, 3 to save the corresponding coefficient. Press 0 to skip saving.\r\n");
				calibration_fsm_state=CALFSM_STATE_CHOICE_SAVE;
				break;	
			case CALFSM_STATE_CHOICE_SAVE:
				c=usb_serial_get_byte();
				switch (c)
				{
					case '0':
						calibration_fsm_state=CALFSM_STATE_END;
						break;
					case '1':
							sensor_calib_set_k(coef.a,coef.b,SIGNIFICATIVE_DIGITS_K,type_of_calib);
						calibration_fsm_state=CALFSM_STATE_SAVE;
						break;
					case '2':
						sensor_calib_set_k(coef1.a,coef1.b,SIGNIFICATIVE_DIGITS_K,type_of_calib);
						calibration_fsm_state=CALFSM_STATE_SAVE;
						break;
					case '3':
						sensor_calib_set_k(coef2.a,coef2.b,SIGNIFICATIVE_DIGITS_K,type_of_calib);
						calibration_fsm_state=CALFSM_STATE_SAVE;
						break;
					case '-':
						DCALIB_PRINT("Enter the reference values (ref_0;ref_5;ref_10) : \r\n");
						calibration_fsm_state=CALFSM_STATE_READING_VALUE_T;
						break;
					default :
						calibration_fsm_state=CALFSM_STATE_CHOICE_SAVE;
						break;
				}
				break;				
			case CALFSM_STATE_SAVE:	
				sensor_calib_save_k(type_of_calib);
				DCALIB_PRINT("Coefficients saved\r\n");
				calibration_fsm_state=CALFSM_STATE_END;
				break;
			case CALFSM_STATE_END:
				state_set_next(&main_fsm, &state_normal);
				break;
			default:
				state_set_next(&main_fsm, &state_normal);
				break;		
		}
}
Example #14
0
// Function Specification
//
// Name: amec_slv_proc_voting_box
//
// Description: Slave OCC's voting box that decides the frequency request.
//              This function will run every tick.
//
// Thread: RealTime Loop
//
// Task Flags:
//
// End Function Specification
void amec_slv_proc_voting_box(void)
{
    /*------------------------------------------------------------------------*/
    /*  Local Variables                                                       */
    /*------------------------------------------------------------------------*/
    uint16_t                        k = 0;
    uint16_t                        l_chip_fmax = g_amec->sys.fmax;
    uint16_t                        l_core_freq = 0;
    uint16_t                        l_core_freq_max = 0;  // max freq across all cores
    uint16_t                        l_core_freq_min = g_amec->sys.fmax;  // min freq across all cores
    uint32_t                        l_current_reason = 0;  // used for debug purposes
    static uint32_t                 L_last_reason = 0;     // used for debug purposes
    uint32_t                        l_chip_reason = 0;
    uint32_t                        l_core_reason = 0;
    amec_proc_voting_reason_t       l_kvm_throt_reason = NO_THROTTLE;
    amec_part_t                     *l_part = NULL;

    // frequency threshold for reporting throttling
    uint16_t l_report_throttle_freq = G_sysConfigData.system_type.report_dvfs_nom ?  G_sysConfigData.sys_mode_freq.table[OCC_MODE_NOMINAL] : G_sysConfigData.sys_mode_freq.table[OCC_MODE_TURBO];

    /*------------------------------------------------------------------------*/
    /*  Code                                                                  */
    /*------------------------------------------------------------------------*/
    if (!G_allowPstates)
    {
        // Don't allow pstates to be sent until after initial mode has been set
        if ( (CURRENT_MODE()) || (G_sysConfigData.system_type.kvm) )
        {
            G_allowPstates = TRUE;
        }
    }

    // Voting Box for CPU speed.
    // This function implements the voting box to decide which input gets the right
    // to actuate the system.

    // check for oversubscription if redundant ps policy (oversubscription) is being enforced
    if (G_sysConfigData.system_type.non_redund_ps == false)
    {
        // If in oversubscription and there is a defined (non 0) OVERSUB frequency less than max then use it
        if( (AMEC_INTF_GET_OVERSUBSCRIPTION()) &&
            (G_sysConfigData.sys_mode_freq.table[OCC_MODE_OVERSUB]) &&
            (G_sysConfigData.sys_mode_freq.table[OCC_MODE_OVERSUB] < l_chip_fmax) )
        {
            l_chip_fmax = G_sysConfigData.sys_mode_freq.table[OCC_MODE_OVERSUB];
            l_chip_reason = AMEC_VOTING_REASON_OVERSUB;
        }
    }

    // If there is an active VRM fault and a defined (non 0) VRM N frequency less than max use it
    if( (g_amec->sys.vrm_fault_status) &&
        (G_sysConfigData.sys_mode_freq.table[OCC_MODE_VRM_N]) &&
        (G_sysConfigData.sys_mode_freq.table[OCC_MODE_VRM_N] < l_chip_fmax) )
    {
        l_chip_fmax = G_sysConfigData.sys_mode_freq.table[OCC_MODE_VRM_N];
        l_chip_reason = AMEC_VOTING_REASON_VRM_N;
    }

    // PPB_FMAX
    if(g_amec->proc[0].pwr_votes.ppb_fmax < l_chip_fmax)
    {
        l_chip_fmax = g_amec->proc[0].pwr_votes.ppb_fmax;
        l_chip_reason = AMEC_VOTING_REASON_PPB;

        if(l_report_throttle_freq <= l_chip_fmax)
        {
            l_kvm_throt_reason = PCAP_EXCEED_REPORT;
        }
        else
        {
            l_kvm_throt_reason = POWERCAP;
        }
    }

    // PMAX_CLIP_FREQ
    if(g_amec->proc[0].pwr_votes.pmax_clip_freq < l_chip_fmax)
    {
        l_chip_fmax = g_amec->proc[0].pwr_votes.pmax_clip_freq;
        l_chip_reason = AMEC_VOTING_REASON_PMAX;
        l_kvm_throt_reason = POWER_SUPPLY_FAILURE;
    }

    // Pmax_clip frequency request if there is an APSS failure
    if(g_amec->proc[0].pwr_votes.apss_pmax_clip_freq < l_chip_fmax)
    {
        l_chip_fmax = g_amec->proc[0].pwr_votes.apss_pmax_clip_freq;
        l_chip_reason = AMEC_VOTING_REASON_APSS_PMAX;
        l_kvm_throt_reason = POWER_SUPPLY_FAILURE;
    }

    //THERMALPROC.FREQ_REQUEST
    //Thermal controller input based on processor temperature
    if(g_amec->thermalproc.freq_request < l_chip_fmax)
    {
        l_chip_fmax = g_amec->thermalproc.freq_request;
        l_chip_reason = AMEC_VOTING_REASON_PROC_THRM;

        if( l_report_throttle_freq <= l_chip_fmax)
        {
            l_kvm_throt_reason = PROC_OVERTEMP_EXCEED_REPORT;
        }
        else
        {
            l_kvm_throt_reason = CPU_OVERTEMP;
        }
    }

    //Thermal controller input based on VRM Vdd temperature
    if(g_amec->thermalvdd.freq_request < l_chip_fmax)
    {
        l_chip_fmax = g_amec->thermalvdd.freq_request;
        l_chip_reason = AMEC_VOTING_REASON_VDD_THRM;

        if( l_report_throttle_freq <= l_chip_fmax)
        {
            l_kvm_throt_reason = VDD_OVERTEMP_EXCEED_REPORT;
        }
        else
        {
            l_kvm_throt_reason = VDD_OVERTEMP;
        }
    }

    for (k=0; k<MAX_NUM_CORES; k++)
    {
        if( CORE_PRESENT(k) && !CORE_OFFLINE(k) )
        {
            l_core_freq = l_chip_fmax;
            l_core_reason = l_chip_reason;

            // Disable DPS in KVM
            if(!G_sysConfigData.system_type.kvm)
            {
                l_part = amec_part_find_by_core(&g_amec->part_config, k);

                // Check frequency request generated by DPS algorithms
                if(g_amec->proc[0].core[k].core_perf.dps_freq_request < l_core_freq)
                {
                    l_core_freq = g_amec->proc[0].core[k].core_perf.dps_freq_request;
                    l_core_reason = AMEC_VOTING_REASON_UTIL;
                }

                // Adjust frequency based on soft frequency boundaries
                if(l_part != NULL)
                {
                    if(l_core_freq < l_part->soft_fmin)
                    {
                        // Before enforcing a soft Fmin, make sure we don't
                        // have a thermal or power emergency
                        if(!(l_chip_reason & (AMEC_VOTING_REASON_PROC_THRM |
                                              AMEC_VOTING_REASON_VDD_THRM |
                                              AMEC_VOTING_REASON_PPB |
                                              AMEC_VOTING_REASON_PMAX |
                                              AMEC_VOTING_REASON_CONN_OC)))
                        {
                            l_core_freq = l_part->soft_fmin;
                            l_core_reason = AMEC_VOTING_REASON_SOFT_MIN;
                        }
                    }
                    else if(l_core_freq > l_part->soft_fmax)
                    {
                        l_core_freq = l_part->soft_fmax;
                        l_core_reason = AMEC_VOTING_REASON_SOFT_MAX;
                    }
                }
            }

            if(CURRENT_MODE() == OCC_MODE_NOMINAL)
            {
                // PROC_PCAP_NOM_VOTE
                if(g_amec->proc[0].pwr_votes.proc_pcap_nom_vote < l_core_freq)
                {
                    l_core_freq = g_amec->proc[0].pwr_votes.proc_pcap_nom_vote;
                    l_core_reason = AMEC_VOTING_REASON_PWR;
                    l_kvm_throt_reason = POWERCAP;
                }
            }
            else
            {
                // PROC_PCAP_VOTE
                if(g_amec->proc[0].pwr_votes.proc_pcap_vote < l_core_freq)
                {
                    l_core_freq = g_amec->proc[0].pwr_votes.proc_pcap_vote;
                    l_core_reason = AMEC_VOTING_REASON_PWR;

                    if(l_report_throttle_freq <= l_core_freq)
                    {
                        l_kvm_throt_reason = PCAP_EXCEED_REPORT;
                    }
                    else
                    {
                        l_kvm_throt_reason = POWERCAP;
                    }
                }
            }

            // Check IPS frequency request sent by Master OCC
            if(g_amec->slv_ips_freq_request != 0)
            {
                if(g_amec->slv_ips_freq_request < l_core_freq)
                {
                    l_core_freq = g_amec->slv_ips_freq_request;
                    l_core_reason = AMEC_VOTING_REASON_IPS;
                }
            }

            // Override frequency with request from Master OCC
            if(g_amec->foverride_enable)
            {
                if(g_amec->foverride != 0)
                {
                    // Override the frequency on all cores if Master OCC sends
                    // a non-zero request
                    l_core_freq = g_amec->foverride;
                    l_core_reason = AMEC_VOTING_REASON_OVERRIDE;
                }

                l_kvm_throt_reason = MANUFACTURING_OVERRIDE;
            }

            if(g_amec->pstate_foverride_enable)
            {
                if(g_amec->pstate_foverride != 0)
                {
                    // Override the frequency on all cores if the Global Pstate
                    // table has been modified
                    l_core_freq = g_amec->pstate_foverride;
                    l_core_reason = AMEC_VOTING_REASON_OVERRIDE;
                }
            }

            //Make sure the frequency is not less then the system min
            if(l_core_freq < g_amec->sys.fmin)
            {
                l_core_freq = g_amec->sys.fmin;
            }

            // Override frequency via Amester parameter interface
            if (g_amec->proc[0].parm_f_override_enable &&
                g_amec->proc[0].parm_f_override[k] > 0)
            {
                l_core_freq = g_amec->proc[0].parm_f_override[k];
                l_core_reason = AMEC_VOTING_REASON_OVERRIDE_CORE;
            }

            //STORE core frequency and reason
            g_amec->proc[0].core[k].f_request = l_core_freq;
            g_amec->proc[0].core[k].f_reason = l_core_reason;
            if(l_core_freq < l_core_freq_min)
            {
                // store the new lowest frequency and reason to be used after all cores checked
                l_core_freq_min = l_core_freq;
                l_current_reason = l_core_reason;
            }

            // Update the Amester parameter telling us the reason. Needed for
            // parameter array.
            g_amec->proc[0].parm_f_reason[k] = l_core_reason;

            //CURRENT_MODE() may be OCC_MODE_NOCHANGE because STATE change is processed
            //before MODE change
            if ((CURRENT_MODE() != OCC_MODE_DYN_POWER_SAVE)    &&
                (CURRENT_MODE() != OCC_MODE_DYN_POWER_SAVE_FP) &&
                (CURRENT_MODE() != OCC_MODE_NOM_PERFORMANCE)   &&
                (CURRENT_MODE() != OCC_MODE_MAX_PERFORMANCE)   &&
                (CURRENT_MODE() != OCC_MODE_FMF)               &&
                (CURRENT_MODE() != OCC_MODE_NOCHANGE)          &&
                (l_core_reason & NON_DPS_POWER_LIMITED))
            {
                G_non_dps_power_limited = TRUE;
            }
            else
            {
                G_non_dps_power_limited = FALSE;
            }

            // Update the sensor telling us what the requested frequency is
            sensor_update( AMECSENSOR_ARRAY_PTR(FREQREQC0,k),
                    (uint16_t) g_amec->proc[0].core[k].f_request);

#if DEBUG_PROC_VOTING_BOX
            /// This trace that can be used to debug the voting
            /// box and control loops.  It will trace the reason why a
            /// controller is lowering the freq, but will only do it once in a
            /// row for the specific freq it wants to control to.  It assumes
            /// that all cores will be controlled to same freq.
            if(l_chip_fmax != g_amec->sys.fmax){
                static uint16_t L_trace = 0;
                if(l_chip_fmax != L_trace){
                    L_trace = l_chip_fmax;
                    TRAC_INFO("Core: %d, Freq: %d, Reason: %d",k,l_core_freq,l_core_reason);
                }
            }
#endif

            if(l_core_freq > l_core_freq_max)
            {
                l_core_freq_max = l_core_freq;
            }
        } // if core present and not offline
        else
        {
            //Set f_request to 0 so this core is ignored in amec_slv_freq_smh()
            g_amec->proc[0].core[k].f_request = 0;
            g_amec->proc[0].core[k].f_reason = 0;
        }
    }//End of for loop

    // update max core frequency if not 0 i.e. all cores offline (stop 2 or greater)
    // this is used by power capping alg, updating to 0 will cause power throttling when not needed
    if(l_core_freq_max)
    {
        g_amec->proc[0].core_max_freq = l_core_freq_max;
        // update the overall reason driving frequency across all cores
        g_amec->proc[0].f_reason = l_current_reason;
    }

    //check if there was a throttle reason change
    if(l_kvm_throt_reason != G_amec_opal_proc_throt_reason)
    {
        //Always update G_amec_opal_proc_throt_reason, this is used to set poll rsp bits for all system types
        G_amec_opal_proc_throt_reason = l_kvm_throt_reason;

        // Only if running OPAL need to notify dcom thread to update the table in HOMER for OPAL
        if(G_sysConfigData.system_type.kvm)
        {
            ssx_semaphore_post(&G_dcomThreadWakeupSem);
        }
    }
    // For debug... if lower than max update vars returned in poll response to give clipping reason
    g_amec->proc[0].core_min_freq = l_core_freq_min;
    if(l_core_freq_min < g_amec->sys.fmax)
    {
        if(l_current_reason == L_last_reason)
        {
            // same reason INC counter
            if(g_amec->proc[0].current_clip_count != 0xFF)
            {
                 g_amec->proc[0].current_clip_count++;
            }
        }
        else
        {
            // new reason update history and set counter to 1
            L_last_reason = l_current_reason;
            g_amec->proc[0].current_clip_count = 1;
            if( (g_amec->proc[0].chip_f_reason_history & l_current_reason) == 0)
            {
                g_amec->proc[0].chip_f_reason_history |= l_current_reason;
                TRAC_IMP("First time throttling for reason[0x%08X] History[0x%08X] freq = %d",
                          l_current_reason, g_amec->proc[0].chip_f_reason_history, l_core_freq_min);
            }
        }
    }
    else // no active clipping
    {
        L_last_reason = 0;
        g_amec->proc[0].current_clip_count = 0;
    }
}
Example #15
0
int main(void)
{
	system_init();
	clock_init();
	led_init();	led_set(0x01); //show life
	UART_Init(BAUD); UART_Write("\nInit"); //Show UART life
	motor_init();
	adc_init();
	
	
	//Enable Analog pins
	adc_enable(CHANNEL_SENSOR_LEFT); 
    adc_enable(CHANNEL_SENSOR_RIGHT);	
    adc_enable(CHANNEL_SENSOR_FRONT);

	
	//Sensor value variables
	uint16_t sensor_left_value = 0; uint16_t sensor_right_value  = 0; uint16_t sensor_front_value  = 0;

	//Analog inputSignal conditioning arrays
	circBuf_t left_buffer; circBuf_t right_buffer; 	circBuf_t front_buffer;

    //Initialise sensor averaging buffers
	initCircBuf(&left_buffer, ROLLING_AVERAGE_LENGTH);
	initCircBuf(&right_buffer, ROLLING_AVERAGE_LENGTH);
	initCircBuf(&front_buffer, ROLLING_AVERAGE_LENGTH);

		
	//UART output buffer
	char buffer[UART_BUFF_SIZE] = {0};

	//=====Application specific variables=====								//TODO: initialise circbuff
	circBuf_t sweep_times;
	initCircBuf(&sweep_times, SWEEP_TIME_MEMORY_LENGTH);
	short sweep_del_t_last = 0;
	short sweep_end_t_last = 0;
	
	//time when front sensor begins to see grey.
	uint32_t grey_time_start = 0;


	bool sweep_ended = FALSE;
	//set high if the front sensor crosses the line
	bool front_crossed_black = FALSE; 
	//set high if front finds finish line
	bool front_crossed_grey = FALSE;

	bool sensor_update_serviced = TRUE;
	
	action current_action = IDLE;
	
	int16_t forward_speed = DEFAULT_FORWARD_SPEED;
	int16_t turn_speed = DEFAULT_SPEED;
	
	//Scheduler variables
	uint32_t t = 0;	

	//Loop control time variables
	uint32_t maze_logic_t_last = 0;
	uint32_t sample_t_last = 0;
	uint32_t UART_t_last = 0;


	clock_set_ms(0);
	sei(); // Enable all interrupts
	UART_Write("ialized\n");

	//wait for start command
	DDRD &= ~BIT(7);
	PORTD |= BIT(7);
	
	
	//motor_set(128, 128);
	while((PIND & BIT(7)))
	{
		continue;
	}
	

	
	while(1)
	{
		                                                                                                                         
		t = clock_get_ms();
		
		//check if a sensor update has occured
		if ((sensor_update_serviced == FALSE) && 
			(t%MAZE_LOGIC_PERIOD == 0) && (t != maze_logic_t_last))
		{
			sensor_update_serviced = TRUE;


			// finishing condition is a grey read for a set period
			if(is_grey(sensor_front_value) && front_crossed_grey == FALSE)
			{
				front_crossed_grey = TRUE;
				grey_time_start = t;	                                   //TODO: adjust so that finishing condition is a 1/2 whole sweeps on grey line
			}
			else if (is_grey(sensor_front_value) && front_crossed_grey == TRUE)
			{
				//
				if ((grey_time_start + GREY_TIME) <= t )
				{
					// Finish line found. Stop robot.
					maze_completed(); // wait for button push
					front_crossed_grey = FALSE;
				}

			}
			else
			{
				front_crossed_grey = FALSE;
			}
			
			//see if the front sensor crosses the line in case we run into a gap
			if(is_black(sensor_front_value)&&front_crossed_black == FALSE)
			{
				front_crossed_black = TRUE;
				//check for false finish line
				if(front_crossed_grey)
					front_crossed_grey = FALSE; //false alarm
			}	
			
			// when both rear sensors go black, this indicates an intersection (turns included).
			// try turning left
			if(is_black(sensor_left_value) && is_black(sensor_right_value))
			{
				sweep_ended = TRUE;
				motor_set(0, 255);									
				PORTB |= BIT(3);
				PORTB |= BIT(4);
			}
			
			//when both sensors are completely white this indicates a dead end or a tape-gap
			else if (is_white(sensor_left_value) && is_white(sensor_right_value))
			{
				sweep_ended = TRUE;
				PORTB &= ~BIT(3);
				PORTB &= ~BIT(4);
				//current_action = ON_WHITE;
				//Check if the front sensor is on black, or has been during the last sweep.
				if(is_black(sensor_front_value) | front_crossed_black)
					motor_set(255, 255);
				else if (is_white(sensor_front_value))
					motor_set(-255, 255);
			}				
			
			//sweep to the side that reads the darkest value			
			else if (sensor_left_value + SENSOR_TOLLERANCE < sensor_right_value)
			{
				PORTB &= ~BIT(3);
				PORTB |= BIT(4);
				if (current_action == SWEEP_LEFT)
					sweep_ended = TRUE;
				current_action = SWEEP_RIGHT;
				motor_set(forward_speed + turn_speed, forward_speed);
			}
			else if(sensor_right_value + SENSOR_TOLLERANCE< sensor_left_value)
			{
				PORTB |= BIT(3);
				PORTB &= ~BIT(4);			
				if (current_action == SWEEP_RIGHT)
					sweep_ended = TRUE;
				current_action = SWEEP_LEFT;
				motor_set(forward_speed, forward_speed+ turn_speed);
			}

            //If a new sweep started this cycle, find how long it took
            if (sweep_ended)
            {
            	//reset front black crossing detection variable
				sweep_ended = FALSE;
				
				if (front_crossed_black)
					front_crossed_black = FALSE;

				//Calculate sweep time
				sweep_del_t_last = t - sweep_end_t_last;
				sweep_end_t_last = t;
				writeCircBuf(&sweep_times, sweep_del_t_last);
				
				//adjust turn_speed for battery level.
				if (sweep_del_t_last > IDEAL_SWEEP_TIME)
				{
					turn_speed += 5;
				}					
				if (sweep_del_t_last < IDEAL_SWEEP_TIME)
				{
					turn_speed -= 5;
				}					
					
				turn_speed = regulate_within(turn_speed, MIN_TURN_SPEED, MAX_TURN_SPEED);
				
			}
		}
		
		//Sensor value update
 		if((t%SAMPLE_PERIOD == 0) & (t!=sample_t_last))
		{
            sample_t_last = t;
            //read in analog values
            sensor_update(CHANNEL_SENSOR_LEFT, &left_buffer, &sensor_left_value );
            sensor_update(CHANNEL_SENSOR_RIGHT, &right_buffer, &sensor_right_value );
            sensor_update(CHANNEL_SENSOR_FRONT, &front_buffer, &sensor_front_value );
			sensor_update_serviced = FALSE;

		}
		
		//display debug information		
		if((t%UART_PERIOD == 0) & (t != UART_t_last) & UART_ENABLED)
		{
			UART_t_last = t;
			
			sprintf(buffer, "sweep_time: %u \n", sweep_del_t_last);
			UART_Write(buffer);

			sprintf(buffer, "L: %u F: %u R: %u", sensor_left_value, sensor_front_value, sensor_right_value);
			UART_Write(buffer);
			UART_Write("\n");
		}
	}
}
Example #16
0
void amec_update_fw_sensors(void)
{
    errlHndl_t l_err                = NULL;
    int rc                          = 0;
    int rc2                         = 0;
    static bool l_first_call        = TRUE;
    bool l_gpe0_idle, l_gpe1_idle;
    static int L_consec_trace_count = 0;

    // ------------------------------------------------------
    // Update OCC Firmware Sensors from last tick
    // ------------------------------------------------------
    int l_last_state = G_fw_timing.amess_state;
    // RTLtickdur    = duration of last tick's RTL ISR (max = 250us)
    sensor_update( AMECSENSOR_PTR(RTLtickdur), G_fw_timing.rtl_dur);
    // AMEintdur     = duration of last tick's AMEC portion of RTL ISR
    sensor_update( AMECSENSOR_PTR(AMEintdur), G_fw_timing.ameint_dur);
    // AMESSdurX     = duration of last tick's AMEC state
    if(l_last_state >= NUM_AMEC_SMH_STATES)
    {
        // Sanity check.  Trace this out, even though it should never happen.
        TRAC_INFO("AMEC State Invalid, Sensor Not Updated");
    }
    else
    {
        // AMESSdurX = duration of last tick's AMEC state
        sensor_update( AMECSENSOR_ARRAY_PTR(AMESSdur0, l_last_state),  G_fw_timing.amess_dur);
    }

    // ------------------------------------------------------
    // Kick off GPE programs to track WorstCase time in GPE
    // and update the sensors.
    // ------------------------------------------------------
    if( (NULL != G_fw_timing.gpe0_timing_request)
        && (NULL != G_fw_timing.gpe1_timing_request) )
    {
        //Check if both GPE engines were able to complete the last GPE job on
        //the queue within 1 tick.
        l_gpe0_idle = async_request_is_idle(&G_fw_timing.gpe0_timing_request->request);
        l_gpe1_idle = async_request_is_idle(&G_fw_timing.gpe1_timing_request->request);
        if(l_gpe0_idle && l_gpe1_idle)
        {
            //reset the consecutive trace count
            L_consec_trace_count = 0;

            //Both GPE engines finished on time. Now check if they were
            //successful too.
            if( async_request_completed(&(G_fw_timing.gpe0_timing_request->request))
                && async_request_completed(&(G_fw_timing.gpe1_timing_request->request)) )
            {
                // GPEtickdur0 = duration of last tick's PORE-GPE0 duration
                sensor_update( AMECSENSOR_PTR(GPEtickdur0), G_fw_timing.gpe_dur[0]);
                // GPEtickdur1 = duration of last tick's PORE-GPE1 duration
                sensor_update( AMECSENSOR_PTR(GPEtickdur1), G_fw_timing.gpe_dur[1]);
            }
            else
            {
                //This case is expected on the first call of the function.
                //After that, this should not happen.
                if(!l_first_call)
                {
                    //Note: FFDC for this case is gathered by each task
                    //responsible for a GPE job.
                    TRAC_INFO("GPE task idle but GPE task did not complete");
                }
                l_first_call = FALSE;
            }

            // Update Time used to measure GPE duration.
            G_fw_timing.rtl_start_gpe = G_fw_timing.rtl_start;

            // Schedule the GPE Routines that will run and update the worst
            // case timings (via callback) after they complete.  These GPE
            // routines are the last GPE routines added to the queue
            // during the RTL tick.
            rc  = pore_flex_schedule(G_fw_timing.gpe0_timing_request);
            rc2 = pore_flex_schedule(G_fw_timing.gpe1_timing_request);

            if(rc || rc2)
            {
                /* @
                 * @errortype
                 * @moduleid    AMEC_UPDATE_FW_SENSORS
                 * @reasoncode  SSX_GENERIC_FAILURE
                 * @userdata1   return code - gpe0
                 * @userdata2   return code - gpe1
                 * @userdata4   OCC_NO_EXTENDED_RC
                 * @devdesc     Failure to schedule PORE-GPE poreFlex object for FW timing
                 *              analysis.
                 */
                l_err = createErrl(
                    AMEC_UPDATE_FW_SENSORS,             //modId
                    SSX_GENERIC_FAILURE,                //reasoncode
                    OCC_NO_EXTENDED_RC,                 //Extended reason code
                    ERRL_SEV_INFORMATIONAL,             //Severity
                    NULL,                               //Trace Buf
                    DEFAULT_TRACE_SIZE,                 //Trace Size
                    rc,                                 //userdata1
                    rc2);                               //userdata2

                // commit error log
                commitErrl( &l_err );
            }
        }
        else if(L_consec_trace_count < MAX_CONSEC_TRACE)
        {
            uint64_t l_dbg1;

            // Reset will eventually be requested due to not having power measurement
            // data after X ticks, but add some additional FFDC to the trace that
            // will tell us what GPE job is currently executing.
            if(!l_gpe0_idle)
            {
                l_dbg1 = in64(PORE_GPE0_DBG1);
                TRAC_ERR("GPE0 programs did not complete within one tick. DBG1[0x%08x%08x]",
                          l_dbg1 >> 32,
                          l_dbg1 & 0x00000000ffffffffull);
            }