Overview
The UBM middleware provides the implementation of the Universal Backplane Management (UBM) - a common backplane management framework for a host, to determine the SAS/SATA/PCIe backplane capabilities, Drive Facing Connector (DFC) Status, and Control information, and to read the port routing of the Drive Facing Connectors to Host Facing Connectors (HFC) of the backplane.
Features:
- Status and Control over Drive Facing Connector I/O
- High speed lane port routing assignments to Host Facing Connectors
- Backplane capabilities including:
- PCIe Reference Clock expectations
- PCIe Reset expectations
- Power Disable support
- Dual Port support
- Controller programmable firmware update
General Description
Include mtb_ubm.h to get access to all the functions and other declarations in this middleware.
See the Basic UBM application with Update mode to start with the bootloader application and the UBM Controller Application for the main application.
Refer to the SFF-TA-1005 for the UBM specification. Refer to the release notes for limitations and compatibility information.
The control of the PCIe reset and clock routing
The PCIe reset signal is controlled directly by the UBM controller. The PCIe RefClk signal is driven by a specific chip. (e.g., https://www.renesas.com/tw/en/document/dst/9db403d-datasheet?r=73671). For more details, refer to the backplane schematic. The UBM Middleware simply provides the control signal for the specific multiplexer. The pins for the above signals are assigned via the configuration structure.
The requirements to Firmware Host Tool.
- Note
- The UBM Middleware does not provide any Firmware Host Tool. This is a vendor-specific application to be implemented by the vendor side.
As described later, the UBM middleware provides a transport layer for downloading a new firmware image. The Host update tool (software tool) is used for transfer. This instrument must meet the following requirements:
- The Host tool supports the 2WIRE interface for communication with the UBM controller.
- The update process complies with the procedure described in SFF-TA-1005 Rev 1.4, section 5.21.
- The Host tool calculates the flash memory parameters based on the data received by the "Get Non-Volatile Storage Geometry Subcommand".
- The Host tool can parse binary, hexadecimal files into packets for transmission. According to the UBM specification, the Host transmits sector indexes (flash memory lines) that can exceed the maximum length of the UBM command. Sector indexes are divided into packets. For more details, see the "Program Subcommand" description.
- To record data in flash memory, pauses of 30 and 16 milliseconds are set for "Program Subcommand" and "Erase Subcommand" respectively. For more details on the time parameters of operations with flash memory, see the manual for the target device.
- Note
- A pause for "Program Subcommand" is necessary only after the last data packet is received and the index sector is completely formed.
- The UBM specification contains "Verify Image Subcommand" but it does not define the verification method. A checksum check of the entire application, including additional areas of the MCUBoot bootloader, is applied in the middleware. The Host tool calculates the checksum of the binary file previously signed by MCUBoot. Write the calculated CRC bytes at address BASE ADDRESS + 0x200. The CRC endianness must be little. The following is the function for calculating the checksum on Python:
def calculate_checksum(ih, len):
i = 1
crc = 0xFFFFFFFF
crcTable =\
[
0x00000000, 0x105ec76f, 0x20bd8ede, 0x30e349b1,
0x417b1dbc, 0x5125dad3, 0x61c69362, 0x7198540d,
0x82f63b78, 0x92a8fc17, 0xa24bb5a6, 0xb21572c9,
0xc38d26c4, 0xd3d3e1ab, 0xe330a81a, 0xf36e6f75,
]
for i in range(len):
crc = crc ^ ih[i]
crc = (crc >> 4) ^ crcTable[crc & 0xF]
crc = (crc >> 4) ^ crcTable[crc & 0xF]
crc = ~crc
return crc & 0xffffffff
Quick Start Guide
Basic UBM application with Update mode
The UBM Middleware supports Update mode. This feature is based on the MCUBoot bootloader, and the transport layer, which provides the UBM Middleware for transferring a new application image to the slot.
- Note
- Strongly recommended - learn more about MCUBoot and multi-application projects from the following sources:
- MCUBoot documentation
- MCUBoot/Infineon
- MCUBoot basic application
- Dual application guide
Use this guide to create two applications:
- The bootloader - a program that checks the slots in the flash memory and downloads a new firmware image when it finds one.
- The blinky application - the user's main application that will be updated to run the UBM Middleware.
After creating a sample project:
- Apply the modifications described later in this section to update the "bootloader" and "blinky" application.
- Update the main.c file of the "blinky" application with the alterations outlined in the following section UBM Controller Application.
- Include the UBM middleware into the project using the ModusToolbox™ Library Manager.
- Copy the configuration file from mtb_shared/ubm/release[version]/ubm_flash_map/[config].json to the Bootloader application "flashmap" folder.
- Update the FLASH_MAP variable in "shared_config.mk" to the previously copied JSON file
# Flashmap JSON file name
FLASH_MAP=psoc62_swap_single_custom.json
- Update the configurational defines in the configurational file in [app_name]/blinky/imports/ubm/mtb_ubm_config.h:
- Note
- The configurational file mtb_ubm_config.h is added to the Blinky application in the folder "imports" after the UBM middleware is added using the Library Manager and the following values are auto-updated:
#define MTB_UBM_UPGRADE_AREA_START_ADDRESS (0x10018000U)
#define MTB_UBM_UPGRADE_AREA_SIZE (0x20000U)
Update these addresses when the JSON configuration file is changed.
- Update the main makefile of the Blinky application - modify the rule for the post-build processing:
POSTBUILD=\
cp -f $(BINARY_OUT_PATH).hex $(BINARY_OUT_PATH)_raw.hex;\
rm -f $(BINARY_OUT_PATH).hex;\
$(CY_ELF_TO_HEX_TOOL) --change-addresses=$(HEADER_OFFSET) --remove-section .cy_em_eeprom $(CY_ELF_TO_HEX_OPTIONS) $(BINARY_OUT_PATH).elf $(BINARY_OUT_PATH)_unsigned.hex;\
$(PYTHON_PATH) $(IMGTOOL_PATH) $(SIGN_ARGS) $(BINARY_OUT_PATH)_unsigned.hex $(BINARY_OUT_PATH).hex;
- Warning
- Delete the cy_em_eeprom section because it can break the signing process.
-
Known issue: The main Makefile of Blinky application has one incorrect path. Change this path:
ALL_FILES=*
# Correct path:
SOURCES+=$(wildcard $(SEARCH_mcuboot)/boot/bootutil/src/$(ALL_FILES).c)\
$(wildcard $(MCUBOOT_CY_PATH)/libs/watchdog/$(ALL_FILES).c)\
$(wildcard $(MCUBOOT_CY_PATH)/platforms/img_confirm/$(FAMILY)/$(ALL_FILES).c)
- Update the main.c file in the Blinky application as described in UBM Controller Application.
UBM Controller Application
- When the UBM middleware is added to the project, the configurational file mtb_ubm_config.h is added to the Blinky application to the "imports" folder. This file contains the main configurational defines, e.g. the number of the HFCs or the number of DFCs, etc. Update the necessary parameters according to your backplane configuration. An example for 2 HFCs, 2 DFCs, and 2 Routes:
#define MTB_UBM_HFC_MAX_NUM (8U)
#define MTB_UBM_DFC_MAX_NUM (8U)
#define MTB_UBM_ROUTES_MAX_NUM (32U)
- Include the UBM middleware header file in your main.c file:
- Add the mtb_ubm_init() function call in your main.c file, for example:
- The following parameters are required for the mtb_ubm_init() function:
- The first parameter mtb_stc_ubm_backplane_cfg_t contains the configurational values required to set up the UBM middleware, for example:
{
.num_of_dfc = 4U,
.num_of_routes = 4U,
.starting_slot = 0x00U,
.overview_area = &overview_area,
.fru_config = &eepromConfig,
.ses_event_handler = NULL,
.bifurcate_port = false,
.silicon_identity =
{
.pcie_vendor_id = 0xaa55U,
.device_code = 0xface8d00U,
.fw_version_minor = 0x12U,
.fw_version_major = 0x21U,
.vendor_specific = 0x1234U,
},
.backplane_info =
{
.backplane_type = 0x05U,
.backplane_number = 0x0AU,
},
.capabilities =
{
.clock_routing = true,
.slot_power_control = true,
.pcie_reset_control = true,
.dual_port = true,
.i2c_reset_operation = MTB_UBM_CAP_2WIRE_RESET_OP_FRU_CONTROLLER,
.change_detect_interrupt = true,
.dfc_change_count_supported = true,
.prsnt_reported = true,
.ifdet_reported = true,
.ifdet2_reported = true,
.perst_override_supported = true,
.smb_reset_supported = true,
},
.route_information =
{
{
.ubm_ctrl_slave_addr = 0x13U,
.drive_connector_idx = 0x0U,
.drive_types_supported =
{
.sff_ta_1001 = true,
.gen_z = false,
.sas_sata = true,
.quad_pcie = true,
.dfc_empty = true,
},
.hfc_starting_phy_lane = 0x0U,
.hfc_identifier = 0x0U,
.slot_offset = 0x00U,
},
{
.ubm_ctrl_slave_addr = 0x13U,
.drive_connector_idx = 0x1U,
.drive_types_supported =
{
.sff_ta_1001 = true,
.gen_z = false,
.sas_sata = true,
.quad_pcie = true,
.dfc_empty = true,
},
.hfc_starting_phy_lane = 0x0U,
.hfc_identifier = 0x1U,
.slot_offset = 0x01U,
},
{
.ubm_ctrl_slave_addr = 0x4DU,
.drive_connector_idx = 0x2U,
.drive_types_supported =
{
.sff_ta_1001 = true,
.gen_z = false,
.sas_sata = true,
.quad_pcie = true,
.dfc_empty = true,
},
.hfc_starting_phy_lane = 0x0U,
.hfc_identifier = 0x2U,
.slot_offset = 0x02U,
},
{
.ubm_ctrl_slave_addr = 0x4DU,
.drive_connector_idx = 0x3U,
.drive_types_supported =
{
.sff_ta_1001 = true,
.gen_z = false,
.sas_sata = true,
.quad_pcie = true,
.dfc_empty = true,
},
.hfc_starting_phy_lane = 0x0U,
.hfc_identifier = 0x3U,
.slot_offset = 0x03U,
}
}
};
The first parameter requires configuring the Emulated EEPROM as a storage for FRU data. For more details, refer to the Emulated EEPROM Middleware Library documentation. An example of the configuration: #define DATA_SIZE (256)
#define SIMPLE_MODE (1U)
#define WEAR_LEVELING (2U)
#define REDUNDANT_COPY (0U)
#define BLOCKING_WRITE (1U)
CY_ALIGN(CY_EM_EEPROM_FLASH_SIZEOF_ROW)
const uint8_t emEepromStorage[CY_EM_EEPROM_GET_PHYSICAL_SIZE(DATA_SIZE, SIMPLE_MODE, WEAR_LEVELING, REDUNDANT_COPY)] __attribute__((used, section(".cy_em_eeprom"))) = { 0U };
cy_stc_eeprom_config_t eepromConfig =
{
.eepromSize = DATA_SIZE,
.simpleMode = SIMPLE_MODE,
.wearLevelingFactor = WEAR_LEVELING,
.redundantCopy = REDUNDANT_COPY,
.blockingWrite = BLOCKING_WRITE,
.userFlashStartAddr = (uint32_t) & (emEepromStorage[0U]),
};
Then, set the the overview area parameters as desired. For the the parameters details, refer to the UBM Overview Area section in the SFF-TA-1005 specification. An example of the configuration: {
.two_wire_mux_address = 0x00U,
.ubm_max_time_limit = 0x04U,
.ubm_controller_features =
{
.read_checksum_creation = true,
.write_checksum_checking = true,
.cprsnt_legacy_mode = false,
.pcie_reset_change_count_mask = false,
.drive_type_installed_change_count_mask = false,
.operational_state_change_count_mask = false,
.perst_management_override = 0x00U,
.smbus_reset_control = false
},
.maximum_power_per_dfc = 0x00U,
};
For the explanation of the Silicon Identity, Backplane Info, and Capabilities parameters, refer to the corresponding section of the SFF-TA-1005 specification.
- The second parameter mtb_stc_ubm_backplane_control_signals_t contains the GPIO definition for HFC and DFC IO signals. The number of elements of this configurational array must match the number of HFCs and the number of DFCs configured. These signal definitions are a combination of SFF-TA-1005, SFF-8639, SFF-TA-1001, SFF-TA-1009, SAS and SATA standards. Change the pin settings to match your specification. An example of the configuration:
{
{
{.
ifdet = P0_2, .ifdet2 = P0_3, .prsnt = P1_2, .persta = P2_7, .perstb = P6_2, .pwrdis = P6_3, .refclken = P6_5, .dualporten = P8_0 },
{.ifdet = P12_7, .ifdet2 = P13_4, .prsnt = P13_5, .persta = P2_0, .perstb = P2_1, .pwrdis = P2_2, .refclken = P2_4, .dualporten = P2_5 },
},
.hfc_io =
{
{.sda = P9_1, .scl = P9_0, .i2c_reset = P3_0, .change_detect = P3_1, .bp_type = P3_2, .perst = P3_3 },
{.sda = P10_1, .scl = P10_0, .i2c_reset = P3_4, .change_detect = P3_5, .bp_type = P4_0, .perst = P4_1 },
}
};
- Warning
- Do not use the selected IO pins elsewhere in the application. Verify that the selected IO pins are not used in the ModusToolbox™ Device Configurator.
-
The mtb_ubm_init() function can detect if the IO pin was already initialized with the HAL function cyhal_gpio_init() and returned the appropriate return code, but it cannot detect if the IO pin was initialized by the Peripheral Driver Library directly.
- The third parameter mtb_stc_ubm_context_t contains internal middleware data structures and will not be changed by the application.
- Note
- Keep the context variable accessible during the whole application execution time.
- Your application configuration is complete for building and programmed using the ModusToolbox™ software. For the error codes returned by the mtb_ubm_init() function, refer to mtb_en_ubm_status_t.
LED indication
The current implementation of the UBM Middleware does not include the LED blinking algorithm but assumes it is implemented by the application itself.
The DFC Status and Control Descriptor command contains the SES Array Device Slot Element, which can be used as an input to an LED blinking algorithm. So, the UBM Middleware has an optional functionality to notify the application when a valid SES Array Device Slot Control Element was received.
To enable this feature:
- Set the related macro in mtb_ubm_config.h:
#define MTB_UBM_SES_CB_ACTIVE (1)
- Declare the application handler of the mtb_ubm_ses_app_cb_t type in your application:
- Configure the application handler in the mtb_stc_ubm_backplane_cfg_t configurational structure:
ubm_backplane_configuration.ses_event_handler = ubm_app_handler;
Now, the configured handler function will be called every time a valid SES Array Device Slot Control Element is received. The handler argument mtb_stc_ubm_ses_app_cb_context_t contains:
- The DFC index of the DFC Status and Control Descriptor command,
- The pointer to the received SES Array Device Slot Control Element,
- The pointer to the SES Array Device Slot Status Element.
If the application needs/updates the SES Array Device Slot Status Element for the following read back, the handler function will return true. The SES Array Device Slot Status is ignored and not saved if the handler function returns false.
For the implementation example of the applicaion handler, refer to a corresponding code example.
UBM Controller Commands
Each of added to the configuration Controllers supports the following commands:
UBM Controller Commands
Command code | Read/Write | Command name | Description |
Generic commands |
00h | Read only | Operational State | Returns the operating state of the UBM Controller. |
01h | Read only | Last Command Status | Returns the last command execution status of the UBM Controller. |
02h | Read only | Silicon Identity and Version | Returns UBM Controller identification data. |
03h | Read only | Programming Update Mode Capabilities | Returns the Programming Update Mode capabilities of the UBM Controller. |
Programmable Update Mode Commands |
20h | Read/Write | Enter Programmable Update Mode | Indicates the sequence to unlock and transfer to Programmable Update Mode. |
21h | Read/Write | Programmable Mode Data Transfer | Indicates the method to exchange multiple bytes of the command, status, and data. |
22h | Read/Write | Exit Programmable Update Mode | Indicates to transfer out of Programmable Update Mode. |
Backplane Management Commands |
30h | Read only | Host Facing Connector Info | Returns the Host Facing Connector information. |
31h | Read only | Backplane Info | Returns the backplane number and type, which are unique in the chassis. |
32h | Read only | Starting Slot | Returns the Starting Slot, which is applied to the Slot Offset found in the UBM Port Route Information of the UBM FRU. |
33h | Read only | Capabilities | Returns the backplane capabilities. |
34h | Read only | Features | Returns the backplane features. |
35h | Read/Write | Change Count | The counter used to manage UBM Controller interrupts. |
36h | Read/Write | DFC Status and Control Descriptor Index | Controls the DFC Status and Control Descriptor to access. |
40h | Read/Write | DFC Status and Control Descriptor | Indicates the DFC Status and Control Descriptor data for the current DFC Status and Control Descriptor Index. |
All commands implemented per SFF-TA-1005 Rev 1.4.