This section provides a step-by-step guide to quickly get started with the PMBus middleware. Namely: how to set up the PMBus middleware in your project, configure the necessary hardware, and implement the basic SMBus/PMBus target functionality.
1. Add mtb-pmbus middleware to your project

- If you work in the ModusToolbox IDE, use the ModusToolbox Library Manager to add the mtb-pmbus middleware to your project. Otherwise, ensure that mtb-pmbus middleware is included into your project.
Note: Middleware uses printf() for logging purposes. To use printf() for the terminal output, add retarget-io middleware from the Library Manager or in any other way.
2. Configure SCB blocks and GPIO pins
Note: The following SCB I2C configuration steps are simplified for quick start. They will not cover all required settings to support all middleware features. For a detailed description of the complete SCB I2C configuration, refer to the API Reference Guide.
- Open the Device Configurator and switch to the Peripherals tab (#1.0).
- Enable the SCB block under Communication (#1.1) and select the I2C Personality (#1.2). Select the desired name for the SCB (e.g., PMBUS_I2C).
- In the "General" section (#1.3), choose Slave mode and set the I2C Data Rate to the desired value (e.g., 100 kHz). Disable the "Use TX FIFO" option and enable the "Accept Matching Address" in RX FIFO option.
- In the "Slave" section (#1.4), set the Slave Address to the desired SMBus/PMBus device address (e.g., 0x18).
- In the "Connect" section (#1.5), select the desired Clock for the SCB block. Also, select the desired pins for SDA and SCL lines, the Device Configurator will automatically configure them to Open Drain mode.

- Enable another SCB block under Communication and select UART Personality (#2.0). Select the desired name for the SCB. This block will be used for the debug output.
- Select the desired pins and clock for the SCB (#2.1). The other UART options can be set by default, see the screenshot.

- Switch to the Pins tab (#3.0) and enable any User LED GPIO pin (#3.1). In the "General" section (#3.2) select the Strong Drive, input buffer off Drive mode.

- Select File->Save to generate initialization code.
3. Add SMBus/PMBus code to your project
This section describes the implementation of either an SMBus or PMBus target device. The implementation is similar for both protocols, with some differences in the command table and configuration. Both implementations support the Quick Command and Read 32 protocols, while the PMBus implementation additionally supports the PAGE command and Write/Read Word protocols with pages.
Step 1. Fill the mtb_pmbus_conf.h file with the desired compile-time configuration macros. This file will appear in the project import folder after adding the mtb-pmbus middleware.
Note: This file is intended only for PMBus configuration without using the Device Configurator and solution personality. To enable this possibility, add define MTB_PMBUS_MANUAL_CONFIG to project's Makefile:
DEFINES += MTB_PMBUS_MANUAL_CONFIG
#ifdef MTB_PMBUS_MANUAL_CONFIG
#ifndef MTB_PMBUS_CONF_H
#define MTB_PMBUS_CONF_H
#include "mtb_pmbus_log_level.h"
#define MTB_PMBUS_LOG_LEVEL (MTB_PMBUS_LOG_LEVEL_DEBUG)
#define MTB_PMBUS_ENABLE_TIMEOUT (0U)
#endif
#endif
Step 2. Include the necessary headers files in main.c file:
#include "mtb_pmbus.h"
#include "cybsp.h"
#include "cy_retarget_io.h"
Step 3. Set project defines:
For PMBus project:
#define PMBUS_DEVICE_ADDRESS (0x18U)
#define PMBUS_CMD_TABLE_SIZE (2U)
#define PMBUS_TOTAL_NUM_PAGES (2U)
#define PMBUS_TEST_CMD_1_CODE (0x10U)
#define PMBUS_TEST_CMD_1_SIZE (4U)
#define PMBUS_TEST_CMD_2_CODE (0x11U)
#define PMBUS_TEST_CMD_2_SIZE (2U)
#define PMBUS_TEST_CMD_2_PAGES (2U)
For SMBus project:
#define PMBUS_DEVICE_ADDRESS (0x18U)
#define PMBUS_CMD_TABLE_SIZE (1U)
#define PMBUS_TEST_CMD_1_CODE (0x10U)
#define PMBUS_TEST_CMD_1_SIZE (4U)
Step 4. Create variables for:
Debug UART HAL object and context:
static cy_stc_scb_uart_context_t DEBUG_UART_context;
static mtb_hal_uart_t DEBUG_UART_hal_obj;
I2C context:
static cy_stc_scb_i2c_context_t i2c_pdl_context;
SMBus/PMBus instance:
Instance structure.
Definition mtb_pmbus_trgt.h:858
Step 5. Implement General event callback function:
{
{
printf("Gen: MTB_PMBUS_QUICK_CMD_WR_EVENT\n\r");
Cy_GPIO_Inv(CYBSP_USER_LED_PORT, CYBSP_USER_LED_PIN);
user_led_toggled_cnt++;
printf("User LED toggled\n\r");
}
}
mtb_pmbus_events_t
General events for PMBus Middleware.
Definition mtb_pmbus_trgt.h:322
@ MTB_PMBUS_QUICK_CMD_WR_EVENT
Quick command event with Write bit.
Definition mtb_pmbus_trgt.h:327
Step 6. Create buffers for SMBus/PMBus test commands:
For PMBus project:
static uint8_t pmbus_cmd1_buffer[PMBUS_TEST_CMD_1_SIZE] = {0U};
volatile uint32_t user_led_toggled_cnt = 0U;
static uint8_t pmbus_cmd2_buffer[PMBUS_TEST_CMD_2_PAGES][PMBUS_TEST_CMD_2_SIZE] = {0U};
volatile uint16_t user_data = 0U;
For SMBus project:
static uint8_t pmbus_cmd1_buffer[PMBUS_TEST_CMD_1_SIZE] = {0U};
volatile uint32_t user_led_toggled_cnt = 0U;
Step 7. Implement the SMBus/PMBus command callback functions:
For PMBus project:
{
(void) page;
(void) phase;
(void) byte;
{
printf("\n\rCMD1 match\n\r");
}
{
printf("\n\rCMD1 read request\n\r");
uint32_t tmp = user_led_toggled_cnt;
printf("Data buffer for read: 0x%02X\n\r", pmbus_cmd1_buffer[0U]);
}
return true;
}
void mtb_pmbus_cmd_update_data_isr(mtb_pmbus_stc_t *inst, uint32_t code, uint8_t *data, uint32_t data_size)
Update the data buffer for the selected command with new data.
Definition mtb_pmbus_trgt_cmd.c:235
mtb_pmbus_cmd_events_t
Command specific events.
Definition mtb_pmbus_trgt.h:352
@ MTB_PMBUS_CMD_MATCH
Command match event.
Definition mtb_pmbus_trgt.h:359
@ MTB_PMBUS_CMD_READ_REQ
Read data is requested.
Definition mtb_pmbus_trgt.h:377
{
(void) byte;
(void) phase;
{
printf("\n\rCMD2 match\n\r");
uint16_t tmp = user_data;
printf("Data buffer for page %" PRId32 ": 0x%02X 0x%02X\n\r", page, pmbus_cmd2_buffer[page][0U], pmbus_cmd2_buffer[page][1U]);
}
{
printf("\n\rCMD2 write done\n\r");
printf("Data buffer after write for page %" PRId32 ": 0x%02X 0x%02X\n\r", page, pmbus_cmd2_buffer[page][0U], pmbus_cmd2_buffer[page][1U]);
uint16_t tmp;
user_data = tmp;
}
return true;
}
void mtb_pmbus_cmd_read_data_ext_isr(mtb_pmbus_stc_t *inst, uint32_t code, int32_t page, int32_t phase, uint8_t *data, uint32_t data_size)
Read the data from the buffer for the selected command, page and phase.
Definition mtb_pmbus_trgt_cmd.c:248
void mtb_pmbus_cmd_update_data_ext_isr(mtb_pmbus_stc_t *inst, uint32_t code, int32_t page, int32_t phase, uint8_t *data, uint32_t data_size)
Update the data buffer for the selected command, page and phase with the new data.
Definition mtb_pmbus_trgt_cmd.c:172
@ MTB_PMBUS_CMD_WRITE_DONE
Write is completed.
Definition mtb_pmbus_trgt.h:372
For SMBus project (only pmbus_cmd1_callback is needed).
Step 8. Implement the SMBus/PMBus command table:
For PMBus project:
{
{
.cmd_code = PMBUS_TEST_CMD_1_CODE,
.data_buf = pmbus_cmd1_buffer,
.callback = pmbus_cmd1_callback,
.data_size = PMBUS_TEST_CMD_1_SIZE,
},
{
.cmd_code = PMBUS_TEST_CMD_2_CODE,
.data_buf = pmbus_cmd2_buffer,
.callback = pmbus_cmd2_callback,
.data_size = PMBUS_TEST_CMD_2_SIZE,
}
};
#define MTB_PMBUS_CMD_CAP_FORMAT_8_BIT
The command uses 8 bit unsigned.
Definition mtb_pmbus_trgt.h:142
#define MTB_PMBUS_CMD_CAP_PAGE
The command is paged.
Definition mtb_pmbus_trgt.h:123
#define MTB_PMBUS_CMD_CAP_DIR_WR
The command supports write direction.
Definition mtb_pmbus_trgt.h:114
#define MTB_PMBUS_CMD_CAP_DIR_RD
The command supports read direction.
Definition mtb_pmbus_trgt.h:116
Command configuration structure.
Definition mtb_pmbus_trgt.h:650
For SMBus project:
{
{
.cmd_code = PMBUS_TEST_CMD_1_CODE,
.data_buf = pmbus_cmd1_buffer,
.callback = pmbus_cmd1_callback,
.data_size = PMBUS_TEST_CMD_1_SIZE,
}
};
Step 9. Implement I2C interrupt handler function:
void i2c_isr(void)
{
}
void mtb_pmbus_i2c_isr(mtb_pmbus_stc_t *inst)
PMBus Target interrupt service routine.
Definition mtb_pmbus_trgt_hal.c:68
Step 10. Implement callback functions for enabling and disabling the I2C and I2C interrupts:
{
{
Cy_SCB_I2C_Enable(PMBUS_I2C_HW);
}
{
Cy_SCB_I2C_Disable(PMBUS_I2C_HW, &i2c_pdl_context);
}
}
mtb_pmbus_hw_resources_ctrl_action_t
I2C HW actions.
Definition mtb_pmbus_trgt.h:527
@ MTB_PMBUS_HW_RESOURCES_ENABLE
Enable the I2C HW.
Definition mtb_pmbus_trgt.h:529
@ MTB_PMBUS_HW_RESOURCES_DISABLE
Disable the I2C HW.
Definition mtb_pmbus_trgt.h:531
void hw_isr_enable(void)
{
NVIC_EnableIRQ((IRQn_Type) PMBUS_I2C_IRQ);
}
void hw_isr_disable(void)
{
NVIC_DisableIRQ((IRQn_Type) PMBUS_I2C_IRQ);
}
Step 11. Implement the SMBus/PMBus hardware configuration structure:
{
.hw_ptr = PMBUS_I2C_HW,
.pdl_i2c_context = &i2c_pdl_context,
};
{
.hal_config = &pmbus_hal_cfg,
.hw_resource_ctrl_callback = hw_resource_enable_callback,
.enable_hw_irq_callback = hw_isr_enable,
.disable_hw_irq_callback = hw_isr_disable
};
Hardware configuration structure.
Definition mtb_pmbus_trgt.h:669
HAL Configuration structure.
Definition mtb_pmbus_trgt_hal.h:78
Step 12. Implement the SMBus/PMBus configuration structure:
For PMBus project:
{
.hw_config = &pmbus_hw_cfg,
.address = PMBUS_DEVICE_ADDRESS,
.enable_pec = false,
.enable_smbalert = false,
.enable_pmbus = true,
.num_pages = PMBUS_TOTAL_NUM_PAGES,
.num_phases = 0U,
.enable_zone = false,
.cmd_table = cmd_table,
.cmd_num = PMBUS_CMD_TABLE_SIZE,
.enable_gen_call_addr = false,
.gen_callback = pmbus_gen_callback,
.errors_callback = NULL,
.enable_ieee_format = false,
};
#define MTB_PMBUS_IMPL_CMD_PAGE_EN
Enable the PAGE (0x00) command.
Definition mtb_pmbus_trgt.h:239
Configuration structure.
Definition mtb_pmbus_trgt.h:682
@ MTB_PMBUS_REVISION_1_4
PMBus revision 1.4.
Definition mtb_pmbus_trgt.h:542
@ MTB_PMBUS_SPEED_100
The maximum supported bus speed is 100 kHz.
Definition mtb_pmbus_trgt.h:556
For SMBus project:
{
.hw_config = &pmbus_hw_cfg,
.address = PMBUS_DEVICE_ADDRESS,
.enable_pec = false,
.enable_smbalert = false,
.enable_pmbus = false,
.num_pages = 0U,
.num_phases = 0U,
.enable_zone = false,
.impl_cmd_mask = 0U,
.cmd_table = cmd_table,
.cmd_num = PMBUS_CMD_TABLE_SIZE,
.enable_gen_call_addr = false,
.gen_callback = pmbus_gen_callback,
.errors_callback = NULL,
.enable_ieee_format = false,
};
Step 13. (From this step add code to the main() function) Create variables for result statuses:
cy_rslt_t result;
cy_en_scb_uart_status_t init_status;
Step 14. Initialize the device and board peripherals:
result = cybsp_init();
if (result != CY_RSLT_SUCCESS)
{
CY_ASSERT(0);
}
Step 15. Initialize the UART for debug output:
init_status = Cy_SCB_UART_Init(DEBUG_UART_HW, &DEBUG_UART_config, &DEBUG_UART_context);
if (init_status!=CY_SCB_UART_SUCCESS)
{
CY_ASSERT(0);
}
Cy_SCB_UART_Enable(DEBUG_UART_HW);
result = mtb_hal_uart_setup(&DEBUG_UART_hal_obj, &DEBUG_UART_hal_config,
&DEBUG_UART_context, NULL);
if (result != CY_RSLT_SUCCESS)
{
CY_ASSERT(0);
}
result = cy_retarget_io_init(&DEBUG_UART_hal_obj);
if (result != CY_RSLT_SUCCESS)
{
CY_ASSERT(0);
}
printf("\x1b[2J\x1b[;H");
printf("************************************************************\r\n");
printf("PMBus Quick Start Guide CE\r\n");
printf("************************************************************\r\n\n");
Step 16. Enable irq:
Step 17. Initialize the I2C hardware:
Cy_SCB_I2C_Init(PMBUS_I2C_HW, &PMBUS_I2C_config, &i2c_pdl_context);
cy_stc_sysint_t i2c_isr_cfg =
{
.intrSrc = PMBUS_I2C_IRQ,
.intrPriority = 3U
};
Cy_SysInt_Init(&i2c_isr_cfg, i2c_isr);
#define MTB_PMBUS_LOG_INF(_fmt,...)
Logs an informational message.
Definition mtb_pmbus_log.h:108
Step 18. Initialize the SMBus/PMBus middleware instance:
{
}
else
{
{
}
}
mtb_pmbus_status_t mtb_pmbus_enable(mtb_pmbus_stc_t *inst)
Enable PMBus Middleware.
Definition mtb_pmbus_trgt.c:268
mtb_pmbus_status_t mtb_pmbus_init(mtb_pmbus_stc_t *inst, mtb_pmbus_stc_config_t const *config)
Initialize the PMBus Middleware.
Definition mtb_pmbus_trgt.c:58
#define MTB_PMBUS_LOG_DBG(_fmt,...)
Logs a debug message.
Definition mtb_pmbus_log.h:120
mtb_pmbus_status_t
Used to return the statuses of most PMBus APIs.
Definition mtb_pmbus_trgt.h:280
@ MTB_PMBUS_STATUS_SUCCESS
Correct status.
Definition mtb_pmbus_trgt.h:282
4. Verify Target Mode Workability
See Verify Target Mode Workability for verification steps.