This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

UCD3138: Questions of PMBus

Part Number: UCD3138

Hi TI experts,

I  used UCD3138OL64EVM to test PMBus write command with 100khz trans speed to  microchip pickit serial analyzer,but I found that ACK's clock is not matched that I set 100khz trans speed,

please see the waveform as below , 

ex: Write data [B6h][48h][D0h][39h][4Dh][2Eh][53h][41h][30h][35h] , did I miss something ? thanks.

       

  • First of all, what is the configuration? Is the UCD3138064 the master? If so, what is the slave? It looks like the slave, whatever it is, is stretching the clock before the ACK? It would be useful if you could put a small resistor in between the master and slave, equal to say 10% of the pull up, so that we can see which is pulling the lines down. Actually, it looks like the slave is pulling down before the ACK, because the clock there is going lower than at the other points.

    Does this clock stretch/short ACK happen for every byte, or just with every 4th byte, or what? Perhaps the clock stretch and the short ACK are related.

    Can you please share the code you are using for the write, so that we can verify the issue and see if there are any changes we will suggest to the code?

    Please include all initialization of the interface.

    also, can you tell me which interface you are using, the I2C, or the PMBus?
  • Han Lee, have you resolved this issue on your own? I'm willing to work on this with you, but there are many options in how you could program this, and I want to start with exactly what you are doing, not just try various programs to see if I can duplicate it.
  • Hi Ian,

    Thank you for supporting us ,I'm still debugging with customer now , attach information,
    Device : UCD3138064 64 Pin
    Master/Slave : slave
    This condition only happened at every 4 byte(Not including address)

    #include "include.h"
    
    
    
    
    void init_pmbus(void)
    {
    //	int32 pmbus_address = 0x58;
    
    	if((MiscAnalogRegs.GLBIOREAD.bit.SCI_TX1_IO_READ == 0) && (MiscAnalogRegs.GLBIOREAD.bit.SCI_RX1_IO_READ == 0))
    	{
    		pmbus_address = 0x58;
    	}
    	else if((MiscAnalogRegs.GLBIOREAD.bit.SCI_TX1_IO_READ == 1) && (MiscAnalogRegs.GLBIOREAD.bit.SCI_RX1_IO_READ == 0))
    	{
    		pmbus_address = 0x59;
    	}
    	else if((MiscAnalogRegs.GLBIOREAD.bit.SCI_TX1_IO_READ == 0) && (MiscAnalogRegs.GLBIOREAD.bit.SCI_RX1_IO_READ == 1))
    	{
    		pmbus_address = 0x5A;
    	}
    	else if((MiscAnalogRegs.GLBIOREAD.bit.SCI_TX1_IO_READ == 1) && (MiscAnalogRegs.GLBIOREAD.bit.SCI_RX1_IO_READ == 1))
    	{
    		pmbus_address = 0x5B;	// This is module setup.
    	}
    	else
    	{
    		pmbus_address = 0x58;
    	}
    	//pmbus initialization code.  Much of this is unnecessary after a reset, but is put
    	//in for completeness, and in case code is entered after some other program uses
    	//PMBus interface
    
    	PMBusRegs.PMBINTM.all = 0x1FF; //disable all PMBus interrupts
    	PMBusRegs.PMBCTRL2.all = PMBCTRL2_HALF0_PEC_ENA 
    							 + pmbus_address 
    							 + PMBCTRL2_HALF0_SLAVE_ADDRESS_MASK_AXBX
    							 + PMBCTRL2_ALL_RX_BYTE_ACK_CNT; 
    	pmbus_state = PMBUS_STATE_IDLE;  //initialize state to no message in progress 
    }
    
    void init_timer_interrupt(void)
    {
    	TimerRegs.T16PWM0CMP0DAT.all = 1587;  //approx 10KHz. by spec
    	TimerRegs.T16PWM0CMP1DAT.all = 0xffff;
    	TimerRegs.T16PWM0CMPCTRL.all = 2;
    	TimerRegs.T16PWM0CNTCTRL.all = 0x00c;
    
    	disable_fast_interrupt(); //make sure fast interrupt is disabled
    	disable_interrupt();
    	write_firqpr (0x0A000000); //make them all irqs except FAULT_INT, DPWM2  
    	write_reqmask(0x0A020000); //enable FAULT_INT and PWM0_INT, DPWM2
    	temp = FaultMuxRegs.FAULTMUXINTSTAT.all; 		//read to clear the interrupt flag
    //	FaultMuxRegs.ACOMPCTRL0.bit.ACOMP_B_INT_EN = 1;	//enable ACOMP-B interruptt 
    	enable_interrupt();
    	enable_fast_interrupt(); //make sure fast interrupt is enabled, enabled in Idle state
    }
    
    void init_light_load_configuration(void)
    {
    //	#if (LIGHT_LOAD_ENABLE == 1)
    	Dpwm0Regs.DPWMCTRL1.bit.BURST_EN = 1; //Burst (Light Load) Mode Detection Enable
    	Dpwm1Regs.DPWMCTRL1.bit.BURST_EN = 1;
    	Dpwm2Regs.DPWMCTRL1.bit.BURST_EN = 1;
    	Dpwm3Regs.DPWMCTRL1.bit.BURST_EN = 1;
    	//  ShadowDpwmRegs.DPWMCTRL1.bit.BURST_EN = 1;
    	LoopMuxRegs.LLCTRL.bit.CYCLE_CNT_EN = 0; //Enables Switching Cycle Counter for enabling constant pulse widths 
    	// when configured in Light Load operation
    	LoopMuxRegs.LLCTRL.bit.DPWM_ON_TIME = 0; // default, I guess this is irelevant, we don't use this in kilimanjaro approach
    	LoopMuxRegs.LLCTRL.bit.LL_EN = 0;//disable burst mode for now        
    	LoopMuxRegs.LLCTRL.bit.LL_FILTER_SEL = 0; // Configures source of filter data for Light Load comparisons 
    	LoopMuxRegs.LLENTHRESH.bit.CYCLE_CNT_THRESH = 0; // Don't care// Disabled// Switching Cycle threshold where constant width DPWM pulses 
    	// are enabled when number of switching cycles without pulses exceeds threshold
    	LoopMuxRegs.LLENTHRESH.bit.TURN_ON_THRESH = pmbus_dcdc_config[0].ll_turn_on_thresh;
    	// Filter data threshold where constant width DPWM pulses enabled when filter data exceeds threshold
    	LoopMuxRegs.LLDISTHRESH.bit.TURN_OFF_THRESH = pmbus_dcdc_config[0].ll_turn_off_thresh;  
    	// Filter data threshold where constant width DPWM pulses are disabled when filter data falls below threshold
    //	LoopMuxRegs.FECTRL0MUX.bit.DPWM0_FRAME_SYNC_EN = 1;  
    
    //	#endif
    }
    
    
    void init_gpio(void)
    {
    	// Set outputs to 0.
    	MiscAnalogRegs.GLBIOVAL.all = 0;
    
    	// 1 - GPIO, 0 - other functions
    	MiscAnalogRegs.GLBIOEN.all = MASK_PWOK | MASK_ON_OFF | MASK_AC_FAIL_IN | MASK_AC_FAIL_OUT 
    								| MASK_ENASR | MASK_SMART_ON_GRA | MASK_SMART_ON_GRG | MASK_SMART_ON_READ 
    								| MASK_VBULK_OK | MASK_GREEN | MASK_SBSW | LED_RED | LED_BLUE | MASK_PSON 
    								| A0 | A1 | SMBALERT;
    
    	// 1 - Output, 0 - Input
    	MiscAnalogRegs.GLBIOOE.all = MASK_PWOK | MASK_AC_FAIL_OUT | MASK_ON_OFF | LED_RED | LED_BLUE | MASK_SBSW 
    								| MASK_SMART_ON_GRA | MASK_SMART_ON_GRG | SMBALERT;
    	
    	MiscAnalogRegs.GLBIOVAL.all = MASK_PWOK | MASK_SMART_ON_GRG | SMBALERT | MASK_AC_FAIL_OUT;	// | ~MASK_ON_OFF & ~MASK_SBSW;
    }
    
    void init_miscellaneous(void)
    {
    	enable_turn_on = 1;
    
    	pmbus_status_word = 0;
    	pmbus_status_vout = 0;
    	pmbus_status_iout = 0;
    	pmbus_status_input = 0;
    	pmbus_status_temperature = 0;
    	pmbus_status_cml = 0;
    	psoff_clear_status_flag = 0;
    
    	mr.ein_accumulator = 0;
    	mr.ein_sample_count = 0;
    	mr.ein_rollover_count = 0;
    	real_values.eout_accumulator = 0;
    	real_values.eout_sample_count = 0;
    	real_values.eout_rollover_count = 0;
    
    	ishare_threshold = 1;
    	ishare_center_threshold = 5000;
    
    	master_state = 1;
    	master_time_limit = 10;
    	master_time_count = 0;
    
    	ishare_threshold_ms = 1;
    	ishare_center_threshold_ms = 2;
    	ishare_threshold_master_enable = -60;
    	ishare_threshold_slave_enable = 10;
    
    	current_share_kp = 8000;
    	current_share_ki = 5;
    
    	error_zero = 0;
    
    	light_load_enable = DISABLE;
    	pfc_phase_2_enable = ENABLE;
    	pfc_zvs_enable = DISABLE;
    	pfc_os_enable = ENABLE;
    
    	debug_buffer[0]=1;
    	debug_buffer[1]=2;
    	debug_buffer[2]=3;
    	debug_buffer[3]=4;
    	debug_buffer[4]=5;
    	debug_buffer[5]=6;
    	debug_buffer[6]=7;
    	debug_buffer[7]=8;
    
        PSON = 0;	
    	TURN_ON_COUNT = 0;
    	//BULK_OK = 0;
    
    	supply_state = STATE_IDLE;
    
    	transmit_data = FWID;
    
    	load_condition = heavy_load;
    
    	pfc_bootloader_rdy = 0;
    
    	led_state = LEDSTATE_INIT;
    
    	smart_standby_to_active_step = 600;
    
    	fan_control.rpm_duty = 0;
    
    	sw_en = 0;
    	hw_en = 1;
    
    	smart_on_hightolow_flag = 0;
    
    	eeprom_mfr_erase_write_flag = 0;
    
    	blackbox_erase_write_flag = 0;
    
    	fault_over_current_close = 0;
    
    	regulated_12v = 0;
    
    	sec_boot_loader_rdy = 0;
    
    	PSU_ON_time_count = 0;
    
    	PSU_ON_time_min = 0;
    
    	AC_PSON_power_cycles_flag = 0;
    
    	high_low_line_flag = 0;
    
    	mfr_write_ram_flag = 0;
    
    	led_warning_flag = 0;   //for LED TASK
    
    	pmbus_address_freeze = 0;
    
    	blackbox_erase_write_flag = 0;
    
    	led_fault = 0;
    
    	SBSW_turn_on_count = 0;
    
    	init_count = 0;
    
    	pmbus_write_input_flag = 0;
    	
    	clear_blackbox_for_mfr_system_flag = 0;
    
    	crc16_value = 0x0000;
    
    	crc16_address = 0x2000;
    
    	blackbox_warn_fault_type_temp = 0x8000;
    }
    
    void init_ucd3138_module(void)
    {
    	MiscAnalogRegs.PWRDISCTRL.bit.CPCC_CLK_EN = 0;
    	MiscAnalogRegs.PWRDISCTRL.bit.FE_CTRL1_CLK_EN = 0;
    	MiscAnalogRegs.PWRDISCTRL.bit.FILTER1_CLK_EN = 0;
    	MiscAnalogRegs.PWRDISCTRL.bit.FILTER2_CLK_EN = 0;
    }
    
    void define_pmbus_address(void)
    {
    	if((MiscAnalogRegs.GLBIOREAD.bit.SCI_TX1_IO_READ == 0) && (MiscAnalogRegs.GLBIOREAD.bit.SCI_RX1_IO_READ == 0))
    	{
    		pmbus_address = 0x58;
    	}
    	else if((MiscAnalogRegs.GLBIOREAD.bit.SCI_TX1_IO_READ == 1) && (MiscAnalogRegs.GLBIOREAD.bit.SCI_RX1_IO_READ == 0))
    	{
    		pmbus_address = 0x59;
    	}
    	else if((MiscAnalogRegs.GLBIOREAD.bit.SCI_TX1_IO_READ == 0) && (MiscAnalogRegs.GLBIOREAD.bit.SCI_RX1_IO_READ == 1))
    	{
    		pmbus_address = 0x5A;
    	}
    	else if((MiscAnalogRegs.GLBIOREAD.bit.SCI_TX1_IO_READ == 1) && (MiscAnalogRegs.GLBIOREAD.bit.SCI_RX1_IO_READ == 1))
    	{
    		pmbus_address = 0x5B;	// This is module setup.
    	}
    	else
    	{
    		pmbus_address = 0x58;
    	}
    
    	PMBusRegs.PMBCTRL2.all = PMBCTRL2_HALF0_PEC_ENA 
    							 + pmbus_address 
    							 + PMBCTRL2_HALF0_SLAVE_ADDRESS_MASK_AXBX
    							 + PMBCTRL2_ALL_RX_BYTE_ACK_CNT;
    }
    
    
    
    
    
    

    pmbus.h

    #include "include.h"
    
    void pmbus_idle_handler(void);
    void pmbus_read_block_handler(void);
    //void pmbus_write_block_handler(void);
    void pmbus_read_wait_for_eom_handler(void);
    void pmbus_block_write_or_process_call(void);
    void pmbus_read_wait_for_data_request_handler(void);
    void pmbus_read_process_wait_for_data_request_handler(void);
    
    
    void pmbus_handler(void)
    {
    	this_address = PMBusRegs.PMBHSA.bit.SLAVE_ADDR;
    
    	if(pmbus_watchdog_timer >= 1000) //if watchdog barks
    	{
    		pmbus_start_flag = 0;
    		GioRegs.FAULTOUT.bit.FLT1_OUT = !GioRegs.FAULTOUT.bit.FLT1_OUT ; //signal reset
    
    		PMBusRegs.PMBCTRL3.bit.RESET = 1;
    		PMBusRegs.PMBCTRL3.bit.SLAVE_EN = 0;
    		PMBusRegs.PMBCTRL3.bit.SLAVE_EN = 1;
    		PMBusRegs.PMBCTRL3.bit.RESET = 0;
    		pmbus_watchdog_timer = 0;
    		pmbus_state = PMBUS_STATE_IDLE;
    	}
    
    	switch(pmbus_state)
    	{
    		case PMBUS_STATE_IDLE:
    		{
    			if(pmbus_address_freeze == 0)
    			{
    				define_pmbus_address();
    			}
    			pmbus_idle_handler();
    			break;
    		}
    //		case PMBUS_STATE_WRITE_BLOCK:
    //		{
    //			pmbus_write_block_handler();
    //			break;
    //		}
    		case PMBUS_STATE_READ_BLOCK:
    		{
    			pmbus_read_block_handler();
    			break;
    		}
    		case PMBUS_STATE_READ_WAIT_FOR_EOM:
    		{
    			pmbus_read_wait_for_eom_handler();
    			break;
    		}
    		case PMBUS_STATE_BLOCK_WRITE_OR_PROCESS_CALL:
    		{
    			Dpwm0Regs.DPWMCTRL1.bit.GPIO_A_VAL = 0;
    			Dpwm0Regs.DPWMCTRL1.bit.GPIO_B_VAL = 0;
    			Dpwm1Regs.DPWMCTRL1.bit.GPIO_A_VAL = 1;
    			pmbus_block_write_or_process_call();
    			break;
    		}
    		case PMBUS_STATE_READ_WAIT_FOR_DATA_REQUEST:
    		{
    			pmbus_read_wait_for_data_request_handler();
    			break;
    		}
    		case PMBUS_STATE_READ_PROCESS_WAIT_FOR_DATA_REQUEST:
    		{
    			pmbus_read_process_wait_for_data_request_handler();
    			break;
    		}
    		default:
    		{
    			pmbus_state = PMBUS_STATE_IDLE;
    			pmbus_idle_handler();
    			break;
    		}	
    	}
    }
    
    //	oCR_H = FALSE; //SPIRegs.SPIGPOUT.bit.SCK use this as bit zero for pmubus state output
    //	oCR_L = FALSE; //MiscAnalogRegs.GLBIOVAL.bit.FAULT3_IO_VALUE use this as bit one for pmbus state output
    //	oLED_Amber_ON = 0; //GioRegs.FAULTOUT.bit.GIO_C_OUT use this as bit 2 for pmbus state output
    /*
    void pmbus_state_out(void)
    {
    	if((pmbus_state & 1) == 0)
    	{
    		oCR_H = FALSE;
    	}
    	else
    	{
    		oCR_H = TRUE;
    	}
    	if((pmbus_state & 2) == 0)
    	{
    		oCR_L = FALSE;
    	}
    	else
    	{
    		oCR_L = TRUE;
    	}
    	if((pmbus_state & 4) == 0)
    	{
    		oLED_Amber_ON = FALSE;
    	}
    	else
    	{
    		oLED_Amber_ON = TRUE;
    	}
    }
    */
    
    void read_message_with_ack(void)
    {
    	int32 i; //loop counter
    
    	union
    	{
    		Uint32 pmbus_transmit_load;
    		Uint8 pmbus_transmit_bytes[4];
    	}
    	 u;
    
    	if(pmbus_number_of_bytes == 0) //0 shows its not a valid command, so
    	{
    		PMBusRegs.PMBCTRL2.byte.BYTE2 = 4/* + PMBCTRL2_BYTE2_TX_PEC*/
    										+ PMBCTRL2_BYTE2_RX_BYTE_ACK_CNT;
    		PMBusRegs.PMBTXBUF.all = 0xFFFFFFFF;
    		PMBusRegs.PMBACK.byte.BYTE0 = 1;  //ack command;
    
    		pmbus_state = PMBUS_STATE_READ_WAIT_FOR_EOM; //pmbus_state_out();
    		return;
    	}
    
    	else if(pmbus_number_of_bytes < 5) //here if it all fits in one rxbuf
    	{
    	//			PMBusRegs.PMBACK.byte.BYTE0 = 1;  //ack command;
    
    		PMBusRegs.PMBCTRL2.byte.BYTE2 = pmbus_number_of_bytes/* + PMBCTRL2_BYTE2_TX_PEC*/
    										+ PMBCTRL2_BYTE2_RX_BYTE_ACK_CNT;
    		//transmit with pec, desired number of bytes.
    
    		for(i = 0;i < pmbus_number_of_bytes;i++)
    		{
    			u.pmbus_transmit_bytes[3-i] = pmbus_buffer[i]; //big endian stuff - great fun
    		}
    
    		PMBusRegs.PMBTXBUF.all = u.pmbus_transmit_load; //this sends message
    
    		PMBusRegs.PMBACK.byte.BYTE0 = 1;  //ack command;
    
    		pmbus_watchdog_timer = 0; //something has happened, so pmbus is not locked up
    
    		pmbus_state = PMBUS_STATE_READ_WAIT_FOR_EOM; //pmbus_state_out();
    
    		return ;
    	}
    	else //here if we have to do multiple rxbuf loads - do first one, set up for more
    	{
    	//			PMBusRegs.PMBACK.byte.BYTE0 = 1;  //ack command;
    
    		PMBusRegs.PMBCTRL2.byte.BYTE2 =  4 + PMBCTRL2_BYTE2_RX_BYTE_ACK_CNT; //4 is number of bytes
    		//transmit with desired number of bytes.
    
    		for(i = 0;i < 4;i++)
    		{
    			u.pmbus_transmit_bytes[3-i] = pmbus_buffer[i]; //big endian stuff - great fun
    		}
    
    		PMBusRegs.PMBTXBUF.all = u.pmbus_transmit_load; //this sends message
    
    		PMBusRegs.PMBACK.byte.BYTE0 = 1;  //ack command;
    
    		pmbus_buffer_position = 4;
    
    		pmbus_watchdog_timer = 0; //something has happened, so pmbus is not locked up
    
    		pmbus_state = PMBUS_STATE_READ_BLOCK; //pmbus_state_out();
    
    		return ;
    	}
    }
    
    void read_message_without_ack(void)
    {
    	int32 i; //loop counter
    
    	union
    	{
    		Uint32 pmbus_transmit_load;
    		Uint8 pmbus_transmit_bytes[4];
    	}
    	 u;
    
    	if(pmbus_number_of_bytes == 0) //0 shows its not a valid command, so
    	{
    		PMBusRegs.PMBCTRL2.byte.BYTE2 = 4/* + PMBCTRL2_BYTE2_TX_PEC*/
    										+ PMBCTRL2_BYTE2_RX_BYTE_ACK_CNT;
    		PMBusRegs.PMBTXBUF.all = 0xFFFFFFFF;
    
    		pmbus_state = PMBUS_STATE_READ_WAIT_FOR_EOM; //pmbus_state_out();
    		return;
    	}
    
    	else if(pmbus_number_of_bytes < 5) //here if it all fits in one rxbuf
    	{
    	//			PMBusRegs.PMBACK.byte.BYTE0 = 1;  //ack command;
    
    		PMBusRegs.PMBCTRL2.byte.BYTE2 = pmbus_number_of_bytes/* + PMBCTRL2_BYTE2_TX_PEC*/
    										+ PMBCTRL2_BYTE2_RX_BYTE_ACK_CNT;
    		//transmit with pec, desired number of bytes.
    
    		for(i = 0;i < pmbus_number_of_bytes;i++)
    		{
    			u.pmbus_transmit_bytes[3-i] = pmbus_buffer[i]; //big endian stuff - great fun
    		}
    
    		PMBusRegs.PMBTXBUF.all = u.pmbus_transmit_load; //this sends message
    
    		pmbus_state = PMBUS_STATE_READ_WAIT_FOR_EOM; //pmbus_state_out();
    
    		return ;
    	}
    	else //here if we have to do multiple rxbuf loads - do first one, set up for more
    	{
    	//			PMBusRegs.PMBACK.byte.BYTE0 = 1;  //ack command;
    
    		PMBusRegs.PMBCTRL2.byte.BYTE2 =  4 + PMBCTRL2_BYTE2_RX_BYTE_ACK_CNT; //4 is number of bytes
    		//transmit with desired number of bytes.
    
    		for(i = 0;i < 4;i++)
    		{
    			u.pmbus_transmit_bytes[3-i] = pmbus_buffer[i]; //big endian stuff - great fun
    		}
    
    		PMBusRegs.PMBTXBUF.all = u.pmbus_transmit_load; //this sends message
    
    		pmbus_buffer_position = 4;
    
    		pmbus_state = PMBUS_STATE_READ_BLOCK; //pmbus_state_out();
    
    		return ;
    	}
    }
    
    void pmbus_block_write_or_process_call(void)
    {
    	pmbus_status_half_word_0_value = PMBusRegs.PMBST.half.HALF0 ; //assign to temporary value
    	pmbus_status_half_word_0_value_ored = pmbus_status_half_word_0_value_ored | pmbus_status_half_word_0_value;	
    
    	if((pmbus_status_half_word_0_value & (PMBST_HALF0_CHECK_BITS + PMBST_BYTE0_RD_BYTE_COUNT)) == 0) 
    	{
    		return; //if nothing has happened, just return;
    	}
    	else if((pmbus_status_half_word_0_value & (PMBST_HALF0_CHECK_BITS )) ==
    			(PMBST_BYTE0_EOM + PMBST_BYTE0_DATA_READY))
    			//end of message, good data ready must be 2 to 4 bytes
    	{
    		//copy all 4 over just to make sure
    		pmbus_buffer[pmbus_number_of_bytes] = PMBusRegs.PMBRXBUF.byte.BYTE0;
    		pmbus_buffer[pmbus_number_of_bytes + 1] = PMBusRegs.PMBRXBUF.byte.BYTE1;
    		pmbus_buffer[pmbus_number_of_bytes + 2] = PMBusRegs.PMBRXBUF.byte.BYTE2;
    		pmbus_buffer[pmbus_number_of_bytes + 3] = PMBusRegs.PMBRXBUF.byte.BYTE3;
    		pmbus_number_of_bytes = pmbus_number_of_bytes +
    								(pmbus_status_half_word_0_value & PMBST_BYTE0_RD_BYTE_COUNT);
    		
    		if((pmbus_status_half_word_0_value & PMBST_BYTE0_PEC_VALID) != 0)
    		//if pec_valid bit set
    		{
    			pmbus_pec_valid = 1;
    		}
    		else
    		{
    			pmbus_pec_valid = 0;
    		}
    
    		pmbus_watchdog_timer = 0; //something has happened, so pmbus is not locked up
    
    		if(this_address == pmbus_address)
    		{
    			pmbus_write_message();
    		}
    		else if(this_address == pmbus_address - 8)
    		{
    			fru_write();
    		}
    		PMBusRegs.PMBACK.byte.BYTE0 = 1;  //ack these 4 bytes;
    		pmbus_state = PMBUS_STATE_IDLE; //pmbus_state_out();
    		return;
    	}
    	else if((pmbus_status_half_word_0_value & (PMBST_HALF0_CHECK_BITS + PMBST_BYTE0_RD_BYTE_COUNT)) ==
    			(4 //4 is read byte count 
    			 + PMBST_BYTE0_DATA_READY))
    			//no end of message, good data ready, 4 bytes of data - must be a send block 
    	{
    		//copy data into buffer, set up to recieve more.
    		pmbus_buffer[pmbus_number_of_bytes++] = PMBusRegs.PMBRXBUF.byte.BYTE0;
    		pmbus_buffer[pmbus_number_of_bytes++] = PMBusRegs.PMBRXBUF.byte.BYTE1;
    		pmbus_buffer[pmbus_number_of_bytes++] = PMBusRegs.PMBRXBUF.byte.BYTE2;
    		pmbus_buffer[pmbus_number_of_bytes++] = PMBusRegs.PMBRXBUF.byte.BYTE3;
    
    		pmbus_watchdog_timer = 0; //something has happened, so pmbus is not locked up
    
    		if(pmbus_number_of_bytes >= PMBUS_BUFFER_SIZE) //if it's too big 
    		//assumes pmbus buffer size is multiple of 4
    		{
    			PMBusRegs.PMBACK.byte.BYTE0 = 1;  //NACK it;
    			pmbus_state = PMBUS_STATE_IDLE; //pmbus_state_out();
    			return;
    		}
    			
    		PMBusRegs.PMBACK.byte.BYTE0 = 1;  //ack these 4 bytes;
    		return;
    	}
    	else if((pmbus_status_half_word_0_value & (PMBST_HALF0_CHECK_BITS )) ==
    		(PMBST_BYTE0_EOM))
    		//end of message, no new data ready, pec valid; was exact multiple of 4 bytes, already acked last time
    	{
    		if((pmbus_status_half_word_0_value & PMBST_BYTE0_PEC_VALID) != 0)
    		//if pec_valid bit set
    		{
    			pmbus_pec_valid = 1;
    		}
    		else
    		{
    			pmbus_pec_valid = 0;
    		}
    
    		pmbus_watchdog_timer = 0; //something has happened, so pmbus is not locked up
    
    		if(this_address == pmbus_address)
    		{
    			pmbus_write_message();
    		}
    		else if(this_address == pmbus_address - 8)
    		{
    			fru_write();
    		}
    
    		PMBusRegs.PMBACK.byte.BYTE0 = 1;  //ack the message;
    		pmbus_state = PMBUS_STATE_IDLE; //pmbus_state_out();
    		return;
    	}
    	else if	((pmbus_status_half_word_0_value & (PMBST_HALF0_CHECK_BITS )) == PMBST_BYTE0_DATA_READY)
    	{
    		pmbus_number_of_bytes = 4 + (pmbus_status_half_word_0_value & PMBST_BYTE0_RD_BYTE_COUNT);
    		//add number of bytes from byte count to total number of bytes
    
    		//copy data into buffer, regardless of number of bytes actually there.
    		pmbus_buffer[4] = PMBusRegs.PMBRXBUF.byte.BYTE0;
    		pmbus_buffer[5] = PMBusRegs.PMBRXBUF.byte.BYTE1;
    		pmbus_buffer[6] = PMBusRegs.PMBRXBUF.byte.BYTE2;
    		pmbus_buffer[7] = PMBusRegs.PMBRXBUF.byte.BYTE3;
    		PMBusRegs.PMBACK.byte.BYTE0 = 1;  //ack these 4 bytes;
    
    		if((pmbus_status_half_word_0_value & PMBST_BYTE0_RD_BYTE_COUNT) < 4) //if we have less than 4 bytes and a data ready, it means a repeated start
    		{
    			pmbus_state = PMBUS_STATE_READ_PROCESS_WAIT_FOR_DATA_REQUEST; //wait for data request.
    		}
    	}
    
    	else if(((pmbus_status_half_word_0_value & (PMBST_HALF0_CHECK_BITS )) == PMBST_BYTE0_DATA_REQUEST)  || //this one for repeated start right after previous read from rxbuf
    			((pmbus_status_half_word_0_value & (PMBST_HALF0_CHECK_BITS )) ==  //this one for more bytes coming in, and data request already happened.
     			(PMBST_BYTE0_DATA_REQUEST + PMBST_BYTE0_DATA_READY)))
    			//here if it is a block read process call with 4 to 7 total bytes, meaning 2 to 5 bytes in write block
    			//4 bytes will just have data request, others will have data ready and might have data request.  8 total bytes may
    			// or may not have a data request, so it would have to handled differently.
    	{
    		pmbus_number_of_bytes = pmbus_number_of_bytes + (pmbus_status_half_word_0_value & PMBST_BYTE0_RD_BYTE_COUNT);
    		//add number of bytes from byte count to total number of bytes
    
    		//copy data into buffer, regardless of number of bytes actually there.
    		pmbus_buffer[4] = PMBusRegs.PMBRXBUF.byte.BYTE0;
    		pmbus_buffer[5] = PMBusRegs.PMBRXBUF.byte.BYTE1;
    		pmbus_buffer[6] = PMBusRegs.PMBRXBUF.byte.BYTE2;
    		pmbus_buffer[7] = PMBusRegs.PMBRXBUF.byte.BYTE3;
    
    		pmbus_watchdog_timer = 0; //something has happened, so pmbus is not locked up
    
    		pmbus_read_message_block_process();
    
    		read_message_with_ack();
    	}
    
    
    	else //here if something has happened on bus, not covered by anything above
    	{
    		PMBusRegs.PMBACK.byte.BYTE0 = 1;  //nack them
    		pmbus_state = PMBUS_STATE_IDLE; //pmbus_state_out();
    		return;
    	}
    }		
    #if 0//disable, since had included in pmbus_block_write_or_process_call().
    void pmbus_write_block_handler(void)
    {
    //	Uint16 pmbus_status_half_word_0_value; //save pmbus status, since cleared on read.
    
    	pmbus_status_half_word_0_value = PMBusRegs.PMBST.half.HALF0 ; //assign to temporary value
    	pmbus_status_half_word_0_value_ored = pmbus_status_half_word_0_value_ored | pmbus_status_half_word_0_value;	
    
    	if((pmbus_status_half_word_0_value & (PMBST_HALF0_CHECK_BITS + PMBST_BYTE0_RD_BYTE_COUNT)) == 0) 
    	{
    		return; //if nothing has happened, just return;
    	}
    	else if((pmbus_status_half_word_0_value & (PMBST_HALF0_CHECK_BITS_Write)) ==
    			(PMBST_BYTE0_EOM + PMBST_BYTE0_DATA_READY))
    			//end of message, good data ready, pec valid, must be 2 to 4 bytes
    	{
    		//copy all 4 over just to make sure
    		pmbus_buffer[pmbus_number_of_bytes] = PMBusRegs.PMBRXBUF.byte.BYTE0;
    		pmbus_buffer[pmbus_number_of_bytes + 1] = PMBusRegs.PMBRXBUF.byte.BYTE1;
    		pmbus_buffer[pmbus_number_of_bytes + 2] = PMBusRegs.PMBRXBUF.byte.BYTE2;
    		pmbus_buffer[pmbus_number_of_bytes + 3] = PMBusRegs.PMBRXBUF.byte.BYTE3;
    		pmbus_number_of_bytes = pmbus_number_of_bytes +
    								(pmbus_status_half_word_0_value & PMBST_BYTE0_RD_BYTE_COUNT);
    		if(this_address == pmbus_address)
    		{
    			pmbus_write_message();
    		}
    		else if(this_address == pmbus_address - 8)
    		{
    			fru_write();
    		}
    		PMBusRegs.PMBACK.byte.BYTE0 = 1;  //ack these 4 bytes;
    		pmbus_state = PMBUS_STATE_IDLE;
    		return;
    	}
    	else if((pmbus_status_half_word_0_value & (PMBST_HALF0_CHECK_BITS + PMBST_BYTE0_RD_BYTE_COUNT)) ==
    			(4 //4 is read byte count
    			 + PMBST_BYTE0_DATA_READY))
    			//no end of message, good data ready, 4 bytes of data - must be a send block 
    	{
    		//copy data into buffer, set up to recieve more.
    		pmbus_buffer[pmbus_number_of_bytes++] = PMBusRegs.PMBRXBUF.byte.BYTE0;
    		pmbus_buffer[pmbus_number_of_bytes++] = PMBusRegs.PMBRXBUF.byte.BYTE1;
    		pmbus_buffer[pmbus_number_of_bytes++] = PMBusRegs.PMBRXBUF.byte.BYTE2;
    		pmbus_buffer[pmbus_number_of_bytes++] = PMBusRegs.PMBRXBUF.byte.BYTE3;
    
    		if(pmbus_number_of_bytes >= PMBUS_BUFFER_SIZE) //if it's too big 
    		//assumes pmbus buffer size is multiple of 4
    		{
    			PMBusRegs.PMBACK.byte.BYTE0 = 1;  //NACK it;
    			pmbus_state = PMBUS_STATE_IDLE;
    			return;
    		}
    			
    		PMBusRegs.PMBACK.byte.BYTE0 = 1;  //ack these 4 bytes;
    		return;
    	}
    	else if((pmbus_status_half_word_0_value & (PMBST_HALF0_CHECK_BITS_Write)) ==
    		(PMBST_BYTE0_EOM))
    		//end of message, no new data ready, pec valid; was exact multiple of 4 bytes, already acked last time
    	{
    		if(this_address == pmbus_address)
    		{
    			pmbus_write_message();
    		}
    		else if(this_address == pmbus_address - 8)
    		{
    			fru_write();
    		}
    
    		PMBusRegs.PMBACK.byte.BYTE0 = 1;  //ack the message;
    		pmbus_state = PMBUS_STATE_IDLE;
    		return;
    	}
    	else //here if something has happened on bus, not covered by anything above
    	{
    		PMBusRegs.PMBACK.byte.BYTE0 = 1;  //nack them
    		pmbus_state = PMBUS_STATE_IDLE;
    		return;
    	}
    }		
    #endif
    
    void pmbus_read_wait_for_data_request_handler(void)
    {
    	int32 pmbus_status = PMBusRegs.PMBST.all;
    
    	pmbus_status_half_word_0_value = pmbus_status & 0xFFFF ; //assign to temporary value
    	pmbus_status_half_word_0_value_ored = pmbus_status_half_word_0_value_ored | pmbus_status_half_word_0_value;
    
    	if((pmbus_status_half_word_0_value & (PMBST_HALF0_CHECK_BITS + PMBST_BYTE0_RD_BYTE_COUNT)) == 0)
    	{//if no activity on PMBus, do nothing
    		return ;
    	}
    	// bard debug
    	if((pmbus_status_half_word_0_value & (PMBST_HALF0_CHECK_BITS + PMBST_BYTE0_RD_BYTE_COUNT)) ==
    				PMBST_BYTE0_EOM)
    	//if there is an end of message, no data ready, no data request, and no bytes recieved
    	//it must be an aborted message
    	{
    		PMBusRegs.PMBACK.byte.BYTE0 = 1;  //ACK?
    		pmbus_state = PMBUS_STATE_IDLE;
    		return ;
    	}
    	else if((pmbus_status_half_word_0_value & (PMBST_HALF0_CHECK_BITS + PMBST_BYTE0_RD_BYTE_COUNT)) ==
    				PMBST_BYTE0_DATA_REQUEST)
    	//Here we've got our data request, time to write to RXBUF
    	{
    		if(this_address == pmbus_address)
    		{
    			pmbus_read_message();
    		}
    		else if(this_address == (pmbus_address - 8))
    		{
    			eeprom_read_message();
    		}
    
    		read_message_without_ack();
    	}
    
    	else //here if something has happened on bus, not covered by anything above
    	{
    		PMBusRegs.PMBACK.byte.BYTE0 = 1;  //ack them
    		pmbus_state = PMBUS_STATE_IDLE; //pmbus_state_out();
    	//	_Status_CML_Register |= 0x40;;
    	//	_Status_CML_Register_BMC |= 0x40;
    	//	_Status_CML_Register_ME |= 0x40;
    	//	_Status_CML_Register |= 0x40;
    	//	_Status_CML_Register_BMC |= 0x40;
    	//	_Status_CML_Register_ME |= 0x40;
    		return;
    	}
    }
    
    void pmbus_read_process_wait_for_data_request_handler(void)
    {
    	int32 pmbus_status = PMBusRegs.PMBST.all;
    
    	pmbus_status_half_word_0_value = pmbus_status & 0xFFFF ; //assign to temporary value
    	pmbus_status_half_word_0_value_ored = pmbus_status_half_word_0_value_ored | pmbus_status_half_word_0_value;
    
    	if((pmbus_status_half_word_0_value & (PMBST_HALF0_CHECK_BITS + PMBST_BYTE0_RD_BYTE_COUNT)) == 0)
    	{//if no activity on PMBus, do nothing
    		return ;
    	}
    	// bard debug
    	if((pmbus_status_half_word_0_value & (PMBST_HALF0_CHECK_BITS + PMBST_BYTE0_RD_BYTE_COUNT)) ==
    				PMBST_BYTE0_EOM)
    	//if there is an end of message, no data ready, no data request, and no bytes recieved
    	//it must be an aborted message
    	{
    		PMBusRegs.PMBACK.byte.BYTE0 = 1;  //ACK?
    		pmbus_state = PMBUS_STATE_IDLE;
    		return ;
    	}
    	else if((pmbus_status_half_word_0_value & (PMBST_HALF0_CHECK_BITS + PMBST_BYTE0_RD_BYTE_COUNT)) ==
    				PMBST_BYTE0_DATA_REQUEST)
    	//Here we've got our data request, time to write to RXBUF
    	{
    		pmbus_read_message_block_process();
    		read_message_without_ack();
    	}
    }
    
    void pmbus_idle_handler()
    {
    	int32 pmbus_status = PMBusRegs.PMBST.all;
    
    	//ctrl_pin_status = (pmbus_status>>19) & 1;
    	pmbus_status_half_word_0_value = pmbus_status & 0xFFFF ; //assign to temporary value
    	pmbus_status_half_word_0_value_ored = pmbus_status_half_word_0_value_ored | pmbus_status_half_word_0_value;	
    
    	if(pmbus_status & 0x1000)
    	{
    		pmbus_start_flag = 1;
    	}
    	else
    	{
    		pmbus_start_flag = 0;
    	}
    
    	if((pmbus_status_half_word_0_value & (PMBST_HALF0_CHECK_BITS + PMBST_BYTE0_RD_BYTE_COUNT)) == 0)
    	{//if no activity on PMBus, do nothing
    		return ;
    	}
    	// bard debug
    	if((pmbus_status_half_word_0_value & (PMBST_HALF0_CHECK_BITS + PMBST_BYTE0_RD_BYTE_COUNT)) ==
    				PMBST_BYTE0_EOM)
    	//if there is an end of message, no data ready, no data request, and no bytes recieved
    	//it must be a quick command, which we do not support, so nack, go get the next one
    	{
    		PMBusRegs.PMBACK.byte.BYTE0 = 1;  //nack them
    		return ;
    	}
    	else if((pmbus_status_half_word_0_value & (PMBST_HALF0_CHECK_BITS + PMBST_BYTE0_RD_BYTE_COUNT)) ==
    				PMBST_BYTE0_DATA_REQUEST)
    	//for receive-byte command read of system bus scanning
    	{
    		// Bard debug
    //		PMBusRegs.PMBACK.byte.BYTE0 = 0;  //nack them
    		Uint32 receive_byte = 0xA0;
    		Uint8 pmbus_number_of_bytes = 1;
    		PMBusRegs.PMBCTRL2.byte.BYTE2 = PMBCTRL2_BYTE2_TX_PEC + pmbus_number_of_bytes + PMBCTRL2_BYTE2_RX_BYTE_ACK_CNT;
    
    		PMBusRegs.PMBTXBUF.all = receive_byte;
    		PMBusRegs.PMBACK.byte.BYTE0 = 1;  //nack them
    
    		return ;
    	}
    	else if((pmbus_status_half_word_0_value & (PMBST_HALF0_CHECK_BITS_Write)) ==
    			(PMBST_BYTE0_EOM + PMBST_BYTE0_DATA_READY))
    			//end of message, good data ready, pec valid, must be 2 to 4 bytes
    	{
    		//copy all 4 over just to make sure
    		pmbus_buffer[0] = PMBusRegs.PMBRXBUF.byte.BYTE0;
    		pmbus_buffer[1] = PMBusRegs.PMBRXBUF.byte.BYTE1;
    		pmbus_buffer[2] = PMBusRegs.PMBRXBUF.byte.BYTE2;
    		pmbus_buffer[3] = PMBusRegs.PMBRXBUF.byte.BYTE3;
    		pmbus_number_of_bytes = pmbus_status_half_word_0_value & PMBST_BYTE0_RD_BYTE_COUNT;
    
    		if((pmbus_status_half_word_0_value & PMBST_BYTE0_PEC_VALID) != 0)
    		//if pec_valid bit set
    		{
    			pmbus_pec_valid = 1;
    		}
    		else
    		{
    			pmbus_pec_valid = 0;
    		}
    
    		pmbus_watchdog_timer = 0; //something has happened, so pmbus is not locked up
    
    		if(this_address == pmbus_address)
    		{
    			pmbus_write_message();
    		}
    		else if(this_address == pmbus_address - 8)
    		{
    			fru_write();
    		}
    		PMBusRegs.PMBACK.byte.BYTE0 = 1;  //ack them
    		return;
    	}
    	else if((pmbus_status_half_word_0_value & (PMBST_HALF0_CHECK_BITS + PMBST_BYTE0_RD_BYTE_COUNT)) ==
    			(4 //4 is read byte count
    			 + PMBST_BYTE0_DATA_READY))
    			//no end of message, good data ready, 4 bytes of data - could be write block or process call
    	{
    		//copy data into buffer, set up to recieve more.
    		pmbus_buffer[0] = PMBusRegs.PMBRXBUF.byte.BYTE0;
    		pmbus_buffer[1] = PMBusRegs.PMBRXBUF.byte.BYTE1;
    		pmbus_buffer[2] = PMBusRegs.PMBRXBUF.byte.BYTE2;
    		pmbus_buffer[3] = PMBusRegs.PMBRXBUF.byte.BYTE3;
    		pmbus_number_of_bytes = 4 ; //start counting bytes.
    		
    		PMBusRegs.PMBACK.byte.BYTE0 = 1;  //ack first 4 bytes;
    
    
    
    		pmbus_state = PMBUS_STATE_BLOCK_WRITE_OR_PROCESS_CALL; //pmbus_state_out();
    		
    //		pmbus_state = PMBUS_STATE_WRITE_BLOCK;
    	}
    	else if((pmbus_status_half_word_0_value & (PMBST_HALF0_CHECK_BITS + PMBST_BYTE0_RD_BYTE_COUNT)) ==
    			(4 //4 is read byte count
    			 + PMBST_BYTE0_DATA_READY + PMBST_BYTE0_DATA_REQUEST))
    			//no end of message, good data ready, 4 bytes of data and data request - must be read with 4 bytes in write first
    	{
    		//copy data into buffer, set up to recieve more.
    		pmbus_buffer[0] = PMBusRegs.PMBRXBUF.byte.BYTE0;
    		pmbus_buffer[1] = PMBusRegs.PMBRXBUF.byte.BYTE1;
    		pmbus_buffer[2] = PMBusRegs.PMBRXBUF.byte.BYTE2;
    		pmbus_buffer[3] = PMBusRegs.PMBRXBUF.byte.BYTE3;
    		pmbus_number_of_bytes = 4 ; //start counting bytes.
    
    		PMBusRegs.PMBACK.byte.BYTE0 = 1;  //ack first 4 bytes;
    
    		pmbus_read_message_block_process();
    
    		read_message_without_ack();
    	}
    	else if((pmbus_status_half_word_0_value & (PMBST_HALF0_CHECK_BITS + PMBST_BYTE0_RD_BYTE_COUNT)) ==
     			(1 + PMBST_BYTE0_DATA_READY ))
    			//one byte, data ready, not EOM and/or PEC_VALID, for some reason, don't use data request
    			//all this means a read request.
    	{
    		pmbus_buffer[0] = PMBusRegs.PMBRXBUF.byte.BYTE0;
    		pmbus_number_of_bytes = 1;
    		PMBusRegs.PMBACK.byte.BYTE0 = 1;  //ack first 1 bytes;
    		pmbus_state = PMBUS_STATE_READ_WAIT_FOR_DATA_REQUEST;
    
    	}
    //**************added for handling long delay between polling
    	else if((pmbus_status_half_word_0_value & (PMBST_HALF0_CHECK_BITS + PMBST_BYTE0_RD_BYTE_COUNT)) ==
     			(1 + PMBST_BYTE0_DATA_READY + PMBST_BYTE0_DATA_REQUEST))
    			// or, if we're really slow, could it include a data request?
    //**************end of added for handling long delay between polling
    	{
    		pmbus_buffer[0] = PMBusRegs.PMBRXBUF.byte.BYTE0;
    
    		if(this_address == pmbus_address)
    		{
    			pmbus_read_message();
    		}
    		else if(this_address == (pmbus_address - 8))
    		{
    			eeprom_read_message();
    		}
    
    		read_message_with_ack();
    	}
    //**************added for handling query and smbus alert block process call
    	else if((pmbus_status_half_word_0_value & (PMBST_HALF0_CHECK_BITS + PMBST_BYTE0_RD_BYTE_COUNT)) ==
     			(3 + PMBST_BYTE0_DATA_READY ))
    			//3 bytes, data ready, not EOM and/or PEC_VALID, data request hasn't come in yet
    	{
    		pmbus_buffer[0] = PMBusRegs.PMBRXBUF.byte.BYTE0;
    		pmbus_buffer[1] = PMBusRegs.PMBRXBUF.byte.BYTE1;
    		pmbus_buffer[2] = PMBusRegs.PMBRXBUF.byte.BYTE2;
    
    		pmbus_number_of_bytes = 3;
    
    		PMBusRegs.PMBACK.byte.BYTE0 = 1;  //ack first 3 bytes;
    
    		pmbus_state = PMBUS_STATE_READ_PROCESS_WAIT_FOR_DATA_REQUEST;
    
    	}
    	else if((pmbus_status_half_word_0_value & (PMBST_HALF0_CHECK_BITS + PMBST_BYTE0_RD_BYTE_COUNT)) ==
     			(3 + PMBST_BYTE0_DATA_READY + PMBST_BYTE0_DATA_REQUEST))
    			// or, if we're really slow, could it include a data request?
    
    	{
    		pmbus_buffer[0] = PMBusRegs.PMBRXBUF.byte.BYTE0;
    		pmbus_buffer[1] = PMBusRegs.PMBRXBUF.byte.BYTE1;
    		pmbus_buffer[2] = PMBusRegs.PMBRXBUF.byte.BYTE2;
    
    		pmbus_number_of_bytes = 3;
    
    		pmbus_watchdog_timer = 0; //something has happened, so pmbus is not locked up
    
    		pmbus_read_message_block_process();
    
    		read_message_with_ack();
    	}
    	else //here if something has happened on bus, not covered by anything above
    	{
    		PMBusRegs.PMBACK.byte.BYTE0 = 1;  //ack them
    		pmbus_state = PMBUS_STATE_IDLE; //pmbus_state_out();
    	//	_Status_CML_Register |= 0x40;;
    	//	_Status_CML_Register_BMC |= 0x40;
    	//	_Status_CML_Register_ME |= 0x40;
    	//	_Status_CML_Register |= 0x40;
    	//	_Status_CML_Register_BMC |= 0x40;
    	//	_Status_CML_Register_ME |= 0x40;
    		return;
    	}
    }
    
    void pmbus_read_block_handler(void)
    {
    	union
    	{
    		Uint32 pmbus_transmit_load;
    		Uint8 pmbus_transmit_bytes[4];
    	}
    	 u;
    
    	pmbus_status_half_word_0_value = PMBusRegs.PMBST.half.HALF0 ; //assign to temporary value
    	pmbus_status_half_word_0_value_ored = pmbus_status_half_word_0_value_ored | pmbus_status_half_word_0_value;	
    
    	if((pmbus_status_half_word_0_value & (PMBST_HALF0_CHECK_BITS + PMBST_BYTE0_RD_BYTE_COUNT)) == 0) 
    	{//if no activity on PMBus, do nothing
    		return ; 
    	}
    	else if((pmbus_status_half_word_0_value & (PMBST_HALF0_CHECK_BITS + PMBST_BYTE0_RD_BYTE_COUNT)) ==
    				PMBST_BYTE0_DATA_REQUEST)
    
    	{
    		pmbus_watchdog_timer = 0; //something has happened, so pmbus is not locked up
    
    		u.pmbus_transmit_bytes[3] = pmbus_buffer[pmbus_buffer_position++] ; //put out byte 0
    		if(pmbus_buffer_position >= pmbus_number_of_bytes) //if last byte
    		{
    			PMBusRegs.PMBCTRL2.byte.BYTE2 = 1 /*+ PMBCTRL2_BYTE2_TX_PEC*/
    											+ PMBCTRL2_BYTE2_RX_BYTE_ACK_CNT;  //send byte and PEC;
    			PMBusRegs.PMBTXBUF.all = u.pmbus_transmit_load; //
    			pmbus_not_spec_flag = 0;
    			pmbus_state = PMBUS_STATE_READ_WAIT_FOR_EOM; //pmbus_state_out();
    			//PMBusRegs.PMBACK.byte.BYTE0 = 1;  //ack them
    			return  ;
    		}
    		u.pmbus_transmit_bytes[2] = pmbus_buffer[pmbus_buffer_position++] ; //put out byte 1
    		if(pmbus_buffer_position >= pmbus_number_of_bytes) //if last byte
    		{
    			PMBusRegs.PMBCTRL2.byte.BYTE2 = 2 /*+ PMBCTRL2_BYTE2_TX_PEC*/
    											+ PMBCTRL2_BYTE2_RX_BYTE_ACK_CNT;  //send bytes and PEC;
    			PMBusRegs.PMBTXBUF.all = u.pmbus_transmit_load; //
    			pmbus_not_spec_flag = 0;
    			pmbus_state = PMBUS_STATE_READ_WAIT_FOR_EOM; //pmbus_state_out();
    			//PMBusRegs.PMBACK.byte.BYTE0 = 1;  //ack them
    			return  ;
    		}
    		u.pmbus_transmit_bytes[1] = pmbus_buffer[pmbus_buffer_position++] ; //put out byte 2
    		if(pmbus_buffer_position >= pmbus_number_of_bytes) //if last byte
    		{
    			PMBusRegs.PMBCTRL2.byte.BYTE2 = 3 /*+ PMBCTRL2_BYTE2_TX_PEC*/
    											+ PMBCTRL2_BYTE2_RX_BYTE_ACK_CNT;  //send bytes and PEC;
    			PMBusRegs.PMBTXBUF.all = u.pmbus_transmit_load; //
    			pmbus_not_spec_flag = 0;
    			pmbus_state = PMBUS_STATE_READ_WAIT_FOR_EOM; //pmbus_state_out();
    			//PMBusRegs.PMBACK.byte.BYTE0 = 1;  //ack them
    			return  ;
    		}
    		u.pmbus_transmit_bytes[0] = pmbus_buffer[pmbus_buffer_position++] ; //put out byte 3
    		if(pmbus_buffer_position >= pmbus_number_of_bytes) //if last byte
    		{
    			PMBusRegs.PMBCTRL2.byte.BYTE2 = 4/* + PMBCTRL2_BYTE2_TX_PEC*/
    											+ PMBCTRL2_BYTE2_RX_BYTE_ACK_CNT;  //send bytes and PEC;
    			PMBusRegs.PMBTXBUF.all = u.pmbus_transmit_load; //
    			pmbus_not_spec_flag = 0;
    			pmbus_state = PMBUS_STATE_READ_WAIT_FOR_EOM; //pmbus_state_out();
    			//PMBusRegs.PMBACK.byte.BYTE0 = 1;  //ack them
    			return  ;
    		}
    		PMBusRegs.PMBCTRL2.byte.BYTE2 = 4 + PMBCTRL2_BYTE2_RX_BYTE_ACK_CNT ;  //send bytes, no PEC;
    		PMBusRegs.PMBTXBUF.all = u.pmbus_transmit_load; //
    //		oLED_Amber_ON = FALSE;
    		//PMBusRegs.PMBACK.byte.BYTE0 = 1;  //ack command;
    		return; //don't change status, we're not done yet.
    	}
    	// bard debug
    	else if((pmbus_status_half_word_0_value & (PMBST_HALF0_CHECK_BITS + PMBST_BYTE0_RD_BYTE_COUNT)) ==
    	PMBST_BYTE0_EOM)
    	{//if eom, done
    		pmbus_state = PMBUS_STATE_IDLE; //pmbus_state_out();
    		PMBusRegs.PMBACK.byte.BYTE0 = 1;  //ack them
    		return ;
    	}
    	else  //if we get something other than a data request
    	{
    		PMBusRegs.PMBACK.byte.BYTE0 = 1;  //nack them
    		return  ; //and return
    	}
    	
    }
    
    void pmbus_read_wait_for_eom_handler(void)
    {
    	Uint8 pmbus_status_half_word_0_value; //save pmbus status, since cleared on read.
    
    	pmbus_status_half_word_0_value = PMBusRegs.PMBST.half.HALF0 ; //assign to temporary value
    	pmbus_status_half_word_0_value_ored = pmbus_status_half_word_0_value_ored | pmbus_status_half_word_0_value;	
    
    	if((pmbus_status_half_word_0_value & (PMBST_HALF0_CHECK_BITS + PMBST_BYTE0_RD_BYTE_COUNT)) == 0)
    	{//if no activity on PMBus, do nothing
    		return ;
    	}
    
    	else if((pmbus_status_half_word_0_value & (PMBST_HALF0_CHECK_BITS + PMBST_BYTE0_RD_BYTE_COUNT)) == PMBST_BYTE0_EOM)
    	{//if eom, done
    		pmbus_state = PMBUS_STATE_IDLE; //pmbus_state_out();
    		PMBusRegs.PMBACK.byte.BYTE0 = 1;  //ack them
    //		oLED_Amber_ON = FALSE;
    		return ;
    	}
    	else if((pmbus_status_half_word_0_value & (PMBST_HALF0_CHECK_BITS + PMBST_BYTE0_RD_BYTE_COUNT)) == PMBST_BYTE0_DATA_REQUEST)
    	{//if master is asking for more bytes than we wanted to send
    
    
    		PMBusRegs.PMBCTRL2.byte.BYTE2 = 4 + PMBCTRL2_BYTE2_RX_BYTE_ACK_CNT ;  //send bytes;
    		PMBusRegs.PMBTXBUF.all = 0xFFFFFFFF; //all ffs	Azalea
    
    //		oLED_Amber_ON = TRUE;
    		return ;
    	}
    	else //some other error, still go back to idle.
    	{
    		pmbus_state = PMBUS_STATE_IDLE; //pmbus_state_out();
    //		oLED_Amber_ON = FALSE;
    		return;
    	}
    }
    
    
    

  • If the UCD is the slave, the issue is with whatever the master is. The UCD will only pull the clock low before the ACK, unless you are doing something with the raw PMBUS lines, which I don't think you are. Further, note that before the ACK clock rise, the clock line goes lower that it has been. That tells me that there is a little resistor between the master and the slave, and your scope probe is on the UCD side. the after the ACK, the clock is pulled down, but just as far as the clock is between the normal bits. This tells me that the clock is being pulled down by the master again.

    The reason this happens every 4 bytes is that is when the 4 byte RXBUF fills up on the UCD. The hardware stretches the clock until the software reads the RXBUF. So the master you are using is putting out a short ACK clock if there is clock stretching. At least that's the way it looks to me.