import ska_low_sps_tpm_api.boards.tpm_hw_definitions as tpm_hw_definitions
from ska_low_sps_tpm_api.base.definitions import *
from ska_low_sps_tpm_api.base.utils import *
from ska_low_sps_tpm_api.plugins.firmwareblock import FirmwareBlock
__author__ = "Gabriele Sorrenti"
FRAM_BA = 0x90000000 # MCU shadow RAM offset
[docs]
class McuRegisters(object):
FRAM_MCU_VERSION = 0x00000000
FRAM_MCU_COMPILE_DATE = 0x00000004
FRAM_MCU_GIT_HASH = 0x00000008
FRAM_MCU_GPR_0 = 0x0000000C
FRAM_MCU_GPR_1 = 0x00000010
FRAM_MCU_GPR_2 = 0x00000014
FRAM_MCU_GPR_3 = 0x00000018
FRAM_MCU_POOLING_INTERVAL = 0x0000001C
FRAM_MCU_INTERNAL_COMMAND = 0x00000020
FRAM_MCU_COUNTER = 0x00000024
FRAM_MCU_COMPLETE_ADC_COUNTER = 0x00000028
FRAM_MCU_BOOTLOADER_VERSION = 0x0000002C
FRAM_MCU_BOOTLOADER_COMMANDS = 0x00000030
FRAM_MCU_STEP = 0x000000038
FRAM_MCU_UART_DBG_DIS = 0x00000040
FRAM_MCU_FEATURES = 0x00000044
FRAM_BOARD_STATUS = 0x000000E0
FRAM_BOARD_ALARM = 0x000000E4
FRAM_BOARD_WARNING = 0x000000E8
FRAM_ALM_ERR_VALUE = 0x000000EC
FRAM_WARN_ERR_VALUE = 0x000000F0
FRAM_I2C_UNREACH_ERR = 0x000000F4
FRAM_POWERGOOD_ERR = 0x000000FA
FRAM_POWERGOOD = 0x000000FC
FRAM_ADC_SW_AVDD1 = 0x00000100
FRAM_ADC_SW_AVDD2 = 0x00000104
FRAM_ADC_AVDD3 = 0x00000108
FRAM_ADC_MAN_1V2 = 0x0000010C
FRAM_ADC_DDR0_VREF = 0x00000110
FRAM_ADC_DDR1_VREF = 0x00000114
FRAM_ADC_VM_DRVDD = 0x00000118
FRAM_ADC_VIN_SCALED = 0x0000011C
FRAM_ADC_VM_MAN3V3 = 0x00000120
FRAM_ADC_VM_MAN1V8 = 0x00000124
FRAM_ADC_MON_5V0 = 0x00000128
FRAM_ADC_MGT_AV = 0x0000012C
FRAM_ADC_MGT_AVTT = 0x00000130
FRAM_ADC_INTERNAL_MCU_TEMP = 0x00000134
FRAM_BOARD_TEMP = 0x00000138
FRAM_FPGA0_TEMP = 0x0000013C
FRAM_FPGA1_TEMP = 0x00000140
FRAM_FPGA0_FE_CURRENT = 0x00000144
FRAM_FPGA1_FE_CURRENT = 0x00000148
FRAM_WARN_ALARM_UPDATE = 0x00000190
FRAM_WARN_THR_SW_AVDD1 = 0x00000194
FRAM_WARN_THR_SW_AVDD2 = 0x00000198
FRAM_WARN_THR_AVDD3 = 0x0000019C
FRAM_WARN_THR_MAN_1V2 = 0x000001A0
FRAM_WARN_THR_DDR0_VREF = 0x000001A4
FRAM_WARN_THR_DDR1_VREF = 0x000001A8
FRAM_WARN_THR_VM_DRVDD = 0x000001AC
FRAM_WARN_THR_VIN_SCALED = 0x000001B0
FRAM_WARN_THR_VM_MAN3V3 = 0x000001B4
FRAM_WARN_THR_VM_MAN1V8 = 0x000001B8
FRAM_WARN_THR_MON_5V0 = 0x000001BC
FRAM_WARN_THR_MGT_AV = 0x000001C0
FRAM_WARN_THR_MGT_AVTT = 0x000001C4
FRAM_WARN_THR_INTERNAL_MCU_TEMP = 0x000001C8
FRAM_WARN_THR_BOARD_TEMP = 0x000001CC
FRAM_WARN_THR_FPGA0_TEMP = 0x000001D0
FRAM_WARN_THR_FPGA1_TEMP = 0x000001D4
FRAM_WARN_THR_FPGA0_FE_CURRENT = 0x000001D8
FRAM_WARN_THR_FPGA1_FE_CURRENT = 0x000001E0
FRAM_ALARM_THR_SW_AVDD1 = 0x00000220
FRAM_ALARM_THR_SW_AVDD2 = 0x00000224
FRAM_ALARM_THR_AVDD3 = 0x00000228
FRAM_ALARM_THR_MAN_1V2 = 0x0000022C
FRAM_ALARM_THR_DDR0_VREF = 0x00000230
FRAM_ALARM_THR_DDR1_VREF = 0x00000234
FRAM_ALARM_THR_VM_DRVDD = 0x00000238
FRAM_ALARM_THR_VIN_SCALED = 0x0000023C
FRAM_ALARM_THR_VM_MAN3V3 = 0x00000240
FRAM_ALARM_THR_VM_MAN1V8 = 0x00000244
FRAM_ALARM_THR_MON_5V0 = 0x00000248
FRAM_ALARM_THR_MGT_AV = 0x0000024C
FRAM_ALARM_THR_MGT_AVTT = 0x00000250
FRAM_ALARM_THR_INTERNAL_MCU_TEMP = 0x00000254
FRAM_ALARM_THR_BOARD_TEMP = 0x00000258
FRAM_ALARM_THR_FPGA0_TEMP = 0x0000025C
FRAM_ALARM_THR_FPGA1_TEMP = 0x00000260
FRAM_ALARM_THR_FPGA0_FE_CURRENT = 0x00000264
FRAM_ALARM_THR_FPGA1_FE_CURRENT = 0x00000268
MCU_ADC_OFFSET = FRAM_ADC_SW_AVDD1
ALARM_THR_OFFSET = FRAM_ALARM_THR_SW_AVDD1
TEMPS_OFFSET = FRAM_BOARD_TEMP
Mcu_Feature = {
"FIX_FEx_mAV_READ": 0x1,
}
McuADCs = {
"ADC_SW_AVDD1": {"add": McuRegisters.FRAM_ADC_SW_AVDD1, "status": 1, "divider": 0},
"ADC_SW_AVDD2": {"add": McuRegisters.FRAM_ADC_SW_AVDD2, "status": 2, "divider": 0},
"ADC_AVDD3": {"add": McuRegisters.FRAM_ADC_AVDD3, "status": 4, "divider": 0},
"ADC_MAN_1V2": {"add": McuRegisters.FRAM_ADC_MAN_1V2, "status": 8, "divider": 0},
"ADC_DDR0_VREF": {
"add": McuRegisters.FRAM_ADC_DDR0_VREF,
"status": 16,
"divider": 0,
},
"ADC_DDR1_VREF": {
"add": McuRegisters.FRAM_ADC_DDR1_VREF,
"status": 32,
"divider": 0,
},
"ADC_VM_DRVDD": {"add": McuRegisters.FRAM_ADC_VM_DRVDD, "status": 64, "divider": 0},
"ADC_VIN_SCALED": {
"add": McuRegisters.FRAM_ADC_VIN_SCALED,
"status": 128,
"divider": 12.5,
},
"ADC_VM_MAN3V3": {
"add": McuRegisters.FRAM_ADC_VM_MAN3V3,
"status": 256,
"divider": 3.74782,
},
"ADC_VM_MAN1V8": {
"add": McuRegisters.FRAM_ADC_VM_MAN1V8,
"status": 512,
"divider": 2.73914,
},
"ADC_MON_5V0": {
"add": McuRegisters.FRAM_ADC_MON_5V0,
"status": 1024,
"divider": 2.739276,
},
"ADC_MGT_AV": {"add": McuRegisters.FRAM_ADC_MGT_AV, "status": 2048, "divider": 0},
"ADC_MGT_AVTT": {
"add": McuRegisters.FRAM_ADC_MGT_AVTT,
"status": 4096,
"divider": 0,
},
"FE0_mVA": {
"add": McuRegisters.FRAM_FPGA0_FE_CURRENT,
"status": 4096,
"divider": 0,
},
"FE1_mVA": {
"add": McuRegisters.FRAM_FPGA1_FE_CURRENT,
"status": 4096,
"divider": 0,
},
}
Warn_Thresholds = {
"ADC_SW_AVDD1": {"add": McuRegisters.FRAM_WARN_THR_SW_AVDD1, "divider": 0},
"ADC_SW_AVDD2": {"add": McuRegisters.FRAM_WARN_THR_SW_AVDD2, "divider": 0},
"ADC_AVDD3": {"add": McuRegisters.FRAM_WARN_THR_AVDD3, "divider": 0},
"ADC_MAN_1V2": {"add": McuRegisters.FRAM_WARN_THR_MAN_1V2, "divider": 0},
"ADC_DDR0_VREF": {"add": McuRegisters.FRAM_WARN_THR_DDR0_VREF, "divider": 0},
"ADC_DDR1_VREF": {"add": McuRegisters.FRAM_WARN_THR_DDR1_VREF, "divider": 0},
"ADC_VM_DRVDD": {"add": McuRegisters.FRAM_WARN_THR_VM_DRVDD, "divider": 0},
"ADC_VIN_SCALED": {"add": McuRegisters.FRAM_WARN_THR_VIN_SCALED, "divider": 12.5},
"ADC_VM_MAN3V3": {"add": McuRegisters.FRAM_WARN_THR_VM_MAN3V3, "divider": 3.74782},
"ADC_VM_MAN1V8": {"add": McuRegisters.FRAM_WARN_THR_VM_MAN1V8, "divider": 2.73914},
"ADC_MON_5V0": {"add": McuRegisters.FRAM_WARN_THR_MON_5V0, "divider": 2.739276},
"ADC_MGT_AV": {"add": McuRegisters.FRAM_WARN_THR_MGT_AV, "divider": 0},
"ADC_MGT_AVTT": {"add": McuRegisters.FRAM_WARN_THR_MGT_AVTT, "divider": 0},
"FE0_mVA": {"add": McuRegisters.FRAM_WARN_THR_FPGA0_FE_CURRENT, "divider": 0},
"FE1_mVA": {"add": McuRegisters.FRAM_WARN_THR_FPGA1_FE_CURRENT, "divider": 0},
}
Alarm_Thresholds = {
"ADC_SW_AVDD1": {"add": McuRegisters.FRAM_ALARM_THR_SW_AVDD1, "divider": 0},
"ADC_SW_AVDD2": {"add": McuRegisters.FRAM_ALARM_THR_SW_AVDD2, "divider": 0},
"ADC_AVDD3": {"add": McuRegisters.FRAM_ALARM_THR_AVDD3, "divider": 0},
"ADC_MAN_1V2": {"add": McuRegisters.FRAM_ALARM_THR_MAN_1V2, "divider": 0},
"ADC_DDR0_VREF": {"add": McuRegisters.FRAM_ALARM_THR_DDR0_VREF, "divider": 0},
"ADC_DDR1_VREF": {"add": McuRegisters.FRAM_ALARM_THR_DDR1_VREF, "divider": 0},
"ADC_VM_DRVDD": {"add": McuRegisters.FRAM_ALARM_THR_VM_DRVDD, "divider": 0},
"ADC_VIN_SCALED": {"add": McuRegisters.FRAM_ALARM_THR_VIN_SCALED, "divider": 12.5},
"ADC_VM_MAN3V3": {"add": McuRegisters.FRAM_ALARM_THR_VM_MAN3V3, "divider": 3.74782},
"ADC_VM_MAN1V8": {"add": McuRegisters.FRAM_ALARM_THR_VM_MAN1V8, "divider": 2.73914},
"ADC_MON_5V0": {"add": McuRegisters.FRAM_ALARM_THR_MON_5V0, "divider": 2.739276},
"ADC_MGT_AV": {"add": McuRegisters.FRAM_ALARM_THR_MGT_AV, "divider": 0},
"ADC_MGT_AVTT": {"add": McuRegisters.FRAM_ALARM_THR_MGT_AVTT, "divider": 0},
"FE0_mVA": {"add": McuRegisters.FRAM_ALARM_THR_FPGA0_FE_CURRENT, "divider": 0},
"FE1_mVA": {"add": McuRegisters.FRAM_ALARM_THR_FPGA1_FE_CURRENT, "divider": 0},
}
VoltTemps = [
"SW_AVDD1",
"SW_AVDD2",
"AVDD3",
"MAN_1V2",
"DDR0_VREF",
"DDR1_VREF",
"VM_DRVDD",
"VIN",
"MON_3V3",
"MON_1V8",
"MON_5V0",
"MGT_AVCC",
"MGT_AVTT",
"TEMP_MCU",
"TEMP_BOARD",
"TEMP_FPGA0",
"TEMP_FPGA1",
"FE0_mVA",
"FE1_mVA",
]
mcu_exec_steps_t = [
"null",
"post_internal_periph_init",
"pre_startup_stuff",
"startup_stuff",
"eth_reg_init",
"checkpowergood",
"systemmonitorstart",
"startuploadsettings",
"post_startup_stuff",
"pre_main_loop",
"i2c_manage",
"adcreadsingle",
"alarmmanage",
"irqinternalcpldhandler",
"taskslow",
"irqinternalpghandler",
"twidatablock",
"exchangedatablock",
"exchangedatablockxilinx",
"smaplock",
"smapunlock",
"exchangedatablockxilinx2",
"exchangedatablockxilinx3",
"exchangedatablockxilinx4",
"exchangedatablockxilinx5",
"exchangedatablockxilinx6",
"taskslow1",
"taskslow2",
"taskslow3",
"exchangedatablockxilinx7",
"exchangedatablockxilinx8",
"exchangedatablockxilinx9",
"exchangedatablockxilinx10",
"xilaccessdbg",
"smaplockrenew",
"smaplock_1",
"i2c_manage_req",
"i2c_manage_deasserve",
"i2c_manage_check",
"i2c_manage_end",
"i2c_manage_rlow",
"check_bus",
]
[docs]
class TpmMcu(FirmwareBlock):
"""TpmMcu plugin"""
[docs]
@compatibleboards(BoardMake.TpmBoard)
@friendlyname("tpm_monitor")
@maxinstances(1)
def __init__(self, board, logger=None, **kwargs):
"""
TpmMcu initialiser.
:param board: Pointer to board instance
"""
super(TpmMcu, self).__init__(board, logger=logger)
self._board_type = kwargs.get("board_type", "XTPM")
self.voltage_dict_map = {
"MGT_AVCC": "ADC_MGT_AV",
"MGT_AVTT": "ADC_MGT_AVTT",
"SW_AVDD1": "ADC_SW_AVDD1",
"SW_AVDD2": "ADC_SW_AVDD2",
"AVDD3": "ADC_AVDD3",
"MAN_1V2": "ADC_MAN_1V2",
"DDR0_VREF": "ADC_DDR0_VREF",
"DDR1_VREF": "ADC_DDR1_VREF",
"VM_DRVDD": "ADC_VM_DRVDD",
"VIN": "ADC_VIN_SCALED",
"MON_3V3": "ADC_VM_MAN3V3",
"MON_1V8": "ADC_VM_MAN1V8",
"MON_5V0": "ADC_MON_5V0",
}
self.current_dict_map = {}
self.FRAM_MCU_FEATURES = self.board.read_address(
FRAM_BA + McuRegisters.FRAM_MCU_FEATURES
)
if Mcu_Feature["FIX_FEx_mAV_READ"] & self.FRAM_MCU_FEATURES != 0:
self.current_dict_map["FE0_mVA"] = "FE0_mVA"
self.current_dict_map["FE1_mVA"] = "FE1_mVA"
self._available_voltages = list(self.voltage_dict_map.keys())
self._available_currents = list(self.current_dict_map.keys())
self.set_voltage_warning_thresholds("VIN", 11.4, 12.6)
self.logger.info("Disable MCU UART debug output")
self.disable_uart_debug_output()
#######################################################################################
[docs]
def disable_uart_debug_output(self):
"""Disable debug trasmission on uart, default at poweron is enabled."""
self.board.write_address((FRAM_BA + McuRegisters.FRAM_MCU_UART_DBG_DIS), 0x1)
[docs]
def enable_uart_debug_output(self):
"""Enable debug trasmission on uart, default at poweron is enabled."""
self.board.write_address((FRAM_BA + McuRegisters.FRAM_MCU_UART_DBG_DIS), 0x0)
[docs]
def get_version(self):
"""
Get MCU FW Version.
:return: MCU FW Version (FW Version_Compile_date_InternalCommand)
"""
version = (
hex(self.board.read_address(FRAM_BA + McuRegisters.FRAM_MCU_VERSION)) + "_"
)
version += (
hex(self.board.read_address(FRAM_BA + McuRegisters.FRAM_MCU_COMPILE_DATE))
+ "_"
)
version += hex(
self.board.read_address(FRAM_BA + McuRegisters.FRAM_MCU_INTERNAL_COMMAND)
)
return version
[docs]
def get_available_mcu_adc(self):
"""
Get List of Supplies Measures Monitored with MCU ADCs, to be used in other methods
:return: List of MCU Measures Names available
"""
mcu_adc_names = []
for measure in McuADCs:
mcu_adc_names.append(measure)
print(mcu_adc_names)
return mcu_adc_names
[docs]
def get_adc_value(self, adc_measure=None, all_measure=None):
"""
Get single adc_measure current value, or all available measure values
and thresholds (mandatory set once of parameter).
:param adc_measure: use if want get only current value of selected measure
:param all_measure: set to True if want all available measure current value and
alarm and thresholds values
:return: single selected value, or dictionary with all available measure value and thresholds
"""
if adc_measure is not None:
if adc_measure in McuADCs:
measures = [adc_measure]
else:
self.logger.error(
"Error: measure not found, please use one in available"
)
op_status = -1
value = -1
return value, op_status
elif all_measure is not None:
measures = McuADCs
values = {}
op_status = 0
for meas in measures:
# print(meas)
value = self.board.read_address(FRAM_BA + McuADCs[meas]["add"])
# print(f"get_adc_value {hex(FRAM_BA+McuADCs[meas]['add'])} {value}")
w_tr_reg = self.board.read_address(FRAM_BA + Warn_Thresholds[meas]["add"])
min_w_tr = w_tr_reg & 0xFFFF
max_w_tr = (w_tr_reg & 0xFFFF0000) >> 16
a_tr_reg = self.board.read_address(FRAM_BA + Alarm_Thresholds[meas]["add"])
min_a_tr = a_tr_reg & 0xFFFF
max_a_tr = (a_tr_reg & 0xFFFF0000) >> 16
data = {
"value": value / 1000,
"unit": "V",
"max_alm": max_a_tr,
"min_alm": min_a_tr,
"max_wrn": max_w_tr,
"min_wrn": min_w_tr,
}
values[meas] = data
op_status = 0
# print(values)
if adc_measure is not None:
return values[adc_measure], op_status
return values, op_status
[docs]
def set_thresholds_update(self, message=""):
"""Update thresholds
:param message: message to be logged, default
"""
self.board.write_address((FRAM_BA + McuRegisters.FRAM_WARN_ALARM_UPDATE), 0x1)
self.board._poll_reg(
(FRAM_BA + McuRegisters.FRAM_WARN_ALARM_UPDATE),
0,
f"FRAM_WARN_ALARM_UPDATE ACK NOT Detected on set_thresholds_update {message}",
)
[docs]
def set_adc_warning_thresholds(self, adc_measure, min_thr, max_thr):
"""
Set slected MCU ADC measure Warning Max and Min thresholds values.
:param adc_measure: name of available measure to be configured
:param min_thr: minimun warning threshold value in Volt
:param max_thr: maximun warning threshold value in Volt
:return: operation status, 0 success, -1 failed
:note: this method not work properly with bios < v0.3.0
"""
if adc_measure is not None:
if adc_measure in McuADCs:
thr_warn_reg = ((int(max_thr * 1000) & 0xFFFF) << 16) | (
int(min_thr * 1000) & 0xFFFF
)
self.board.write_address(
FRAM_BA + Warn_Thresholds[adc_measure]["add"], thr_warn_reg
)
self.set_thresholds_update(f"set_adc_warning_thresholds {adc_measure}")
op_status = 0
else:
self.logger.error(
"Error: measure not found, please use one in available"
)
op_status = -1
return op_status
[docs]
def set_adc_alarm_thresholds(self, adc_measure, min_thr, max_thr):
"""
Set slected MCU ADC measure Alarrm Max and Min thresholds values.
:param adc_measure: name of available measure to be configured
:param min_thr: minimun alarm threshold value in Volt
:param max_thr: maximun alarm threshold value in Volt
:return: operation status, 0 success, -1 failed
:note: this method not work properly with bios < v0.3.0
"""
if adc_measure is not None:
if adc_measure in McuADCs:
thr_alm_reg = ((int(max_thr * 1000) & 0xFFFF) << 16) | (
int(min_thr * 1000) & 0xFFFF
)
self.board.write_address(
FRAM_BA + Alarm_Thresholds[adc_measure]["add"], thr_alm_reg
)
self.set_thresholds_update(f"set_adc_alarm_thresholds {adc_measure}")
op_status = 0
else:
self.logger.error(
"Error: measure not found, please use one in available"
)
op_status = -1
return op_status
[docs]
def get_rounded_adc_value(self, McuADCs_key):
value, op_status = self.get_adc_value(adc_measure=McuADCs_key)
return round(value["value"], 3)
[docs]
def get_temperature(self):
"""
Get Board temperature measured on PCB temperature sensor.
:return: temperature value, if I2C access error is detected a value of -273 will be returned
:note: until ADC PS is ON the returned value of temp is 0
:note: this method can not work properly with bios < v0.3.0
"""
step = 0.0625
temp = (
self.board.read_address(FRAM_BA + McuRegisters.FRAM_BOARD_TEMP)
) & 0xFFFF
temp_status = (temp & 0xC000) >> 12
if temp & 0x1000 == 0x1000:
temp = (temp & 0xFFF) - 4096
else:
temp = temp & 0xFFF
temp_f = temp * step
temp_f = round(temp_f, 2)
if (
self.board["board.regfile.date_code"]
> self.board.MCU_FW_VER_LOCK_I2C_CHANGE
):
if temp_status & 0x8 == 0x8:
self.logger.error(
"Board Temperature not updated for MCU I2C access error"
)
# temp_prev = temp_f
temp_upd = -273
elif temp_status & 0x4 == 0x4:
self.logger.error(
"Board Temperature not updated, ADC PS is Off for Temp Error"
)
# temp_prev = temp_f
temp_upd = -273
else:
# temp_prev = None
temp_upd = temp_f
else:
temp_upd = temp_f
return temp_upd
[docs]
def get_mcu_temperature(self):
"""
Get MCU temperature.
:return:MCU temperature value
"""
temp = self.board.read_address(
FRAM_BA + McuRegisters.FRAM_ADC_INTERNAL_MCU_TEMP
)
temp_f = float(temp / 10000)
temp_f = round(temp_f, 2)
return temp_f
[docs]
def set_board_warn_temp_thresholds(self, max_temp):
"""
Set board Warning temperature Max thresholds values.
:param max_temp: maximun temp threshold value in Celsius degree
:note: this method can not work properly with bios < v0.3.0
"""
tmax = int(max_temp / 0.0625)
regval = (tmax & 0xFFFF) << 16
self.board.write_address(
(FRAM_BA + McuRegisters.FRAM_WARN_THR_BOARD_TEMP), regval
)
self.set_thresholds_update(f"set_board_warn_temp_thresholds {max_temp}")
[docs]
def set_board_alm_temp_thresholds(self, max_temp):
"""
Set board Alarm temperature Max thresholds values.
:param max_temp: maximun temp threshold value in Celsius degree
:note: this method can not work properly with bios < v0.3.0
"""
tmax = int(max_temp / 0.0625)
regval = (tmax & 0xFFFF) << 16
self.board.write_address(
(FRAM_BA + McuRegisters.FRAM_ALARM_THR_BOARD_TEMP), regval
)
self.set_thresholds_update(f"set_board_alm_temp_thresholds {max_temp}")
[docs]
def set_fpga_warn_temp_thresholds(self, max_temp, fpga_id):
"""
Set selected FPGA Warning temperature Max thresholds values.
:param max_temp: maximun temp threshold value in Celsius degree
:param fpga_id: select which FPGA' temp thresholds will be configured (possible values:0,1)
:note: this method can not work properly with bios < v0.3.0
"""
max_value = int((max_temp + 273.67777) * 65536 / 501.3743)
regval = (max_value & 0xFFFF) << 16
if fpga_id == 0:
self.board.write_address(
(FRAM_BA + McuRegisters.FRAM_WARN_THR_FPGA0_TEMP), regval
)
else:
self.board.write_address(
(FRAM_BA + McuRegisters.FRAM_WARN_THR_FPGA1_TEMP), regval
)
self.set_thresholds_update(
f"set_fpga_warn_temp_thresholds {max_temp} {fpga_id}"
)
[docs]
def set_fpga_alm_temp_thresholds(self, max_temp, fpga_id):
"""
Set selected FPGA Alarm temperature Max thresholds values.
:param max_temp: maximun temp threshold value in Celsius degree
:param fpga_id: select which FPGA' temp thresholds will be configured (possible values:0,1)
:note: this method can not work properly with bios < v0.3.0
"""
max_value = int((max_temp + 273.67777) * 65536 / 501.3743)
regval = (max_value & 0xFFFF) << 16
if fpga_id == 0:
self.board.write_address(
(FRAM_BA + McuRegisters.FRAM_ALARM_THR_FPGA0_TEMP), regval
)
else:
self.board.write_address(
(FRAM_BA + McuRegisters.FRAM_ALARM_THR_FPGA1_TEMP), regval
)
self.set_thresholds_update(f"set_fpga_alm_temp_thresholds {max_temp} {fpga_id}")
[docs]
def get_fpga_alm_temp_thresholds(self, fpga_id):
"""
Get selected FPGA Alarm temperature Max thresholds values.
:param fpga_id: select which FPGA' temp thresholds will be returned (possible values:0,1)
:return: maximum temperature threshold value
:note: this method can not work properly with bios < v0.3.0
"""
if fpga_id == 0:
add = FRAM_BA + McuRegisters.FRAM_ALARM_THR_FPGA0_TEMP
else:
add = FRAM_BA + McuRegisters.FRAM_ALARM_THR_FPGA1_TEMP
fpga0_raw = self.board[add]
fpga_max = (fpga0_raw & 0xFFFF0000) >> 16
max_temp = (fpga_max * 501.3743 / 65536) - 273.67777
max_temp = round(max_temp, 2)
return max_temp
[docs]
def get_fpga_warn_temp_thresholds(self, fpga_id):
"""
Get selected FPGA Warning temperature Max thresholds values.
:param fpga_id: select which FPGA' temp thresholds will be returned(possible values:0,1)
:return: maximum temperature threshold value
:note: this method can not work properly with bios < v0.3.0
"""
if fpga_id == 0:
add = FRAM_BA + McuRegisters.FRAM_WARN_THR_FPGA0_TEMP
else:
add = FRAM_BA + McuRegisters.FRAM_WARN_THR_FPGA1_TEMP
fpga0_raw = self.board[add]
fpga_max = (fpga0_raw & 0xFFFF0000) >> 16
max_temp = (fpga_max * 501.3743 / 65536) - 273.67777
max_temp = round(max_temp, 2)
return max_temp
[docs]
def get_board_warn_temp_thresholds(self):
"""
Get board Warning temperature Max thresholds values
:note: this method can not work properly with bios < v0.3.0
"""
add = FRAM_BA + McuRegisters.FRAM_WARN_THR_BOARD_TEMP
temp_raw = self.board[add]
max_temp = ((temp_raw & 0xFFFF0000) >> 16) * 0.0625
max_temp = round(max_temp, 2)
return max_temp
[docs]
def get_board_alm_temp_thresholds(self):
"""
Get board Alarm temperature Max thresholds values.
:note: this method can not work properly with bios < v0.3.0
"""
add = FRAM_BA + McuRegisters.FRAM_ALARM_THR_BOARD_TEMP
temp_raw = self.board[add]
max_temp = ((temp_raw & 0xFFFF0000) >> 16) * 0.0625
max_temp = round(max_temp, 2)
return max_temp
[docs]
def get_mcu_last_exec_phase_id(self):
"""
Get mcu last execution phase id.
:return: last execution phase id
"""
add = FRAM_BA + McuRegisters.FRAM_MCU_STEP
exec_phaseid = self.board[add]
mcu_counter = self.board[FRAM_BA + McuRegisters.FRAM_MCU_COUNTER]
return [mcu_exec_steps_t[exec_phaseid], mcu_counter]
[docs]
def get_last_error(self):
"""
Get status of voltage or temp error detection by MCU, if error is detected the value
that has generated the error will be returned.
:return: dictionary with measure name as key and value (e.g. {'VIN': 11.2}), None if no errors detected
:note: this method not work properly with bios < v0.3.0
"""
add = FRAM_BA + McuRegisters.FRAM_BOARD_ALARM
error_status = self.board[add]
if error_status > 0:
error_status = VoltTemps[int(math.log(error_status, 2))]
else:
error_status = None
add = FRAM_BA + McuRegisters.FRAM_ALM_ERR_VALUE
error_value = self.board[add]
if error_status in ["TEMP_BOARD"]:
error_value = error_value * 0.0625
elif error_status in ["TEMP_FPGA0", "TEMP_FPGA1"]:
error_value = (error_value * 501.3743 / 65536) - 273.67777
else:
error_value = error_value / 1000
return {error_status: round(error_value, 2)}
[docs]
def get_last_warning(self):
"""
Get status of voltage or temp warning detection by MCU, if warning is detected the value
that has generated the warning will be returned.
:return: dictionary with measure name as key and value (e.g. {'VIN': 11.2}), None if no warnings detected
:note: this method not work properly with bios < v0.3.0
"""
add = FRAM_BA + McuRegisters.FRAM_BOARD_WARNING
warning_status = self.board[add]
if warning_status > 0:
warning_status = VoltTemps[int(math.log(warning_status, 2))]
else:
warning_status = None
add = FRAM_BA + McuRegisters.FRAM_WARN_ERR_VALUE
warning_value = self.board[add]
if warning_status in ["TEMP_BOARD"]:
warning_value = warning_value * 0.0625
elif warning_status in ["TEMP_FPGA0", "TEMP_FPGA1"]:
warning_value = (warning_value * 501.3743 / 65536) - 273.67777
else:
warning_value = warning_value / 1000
return {warning_status: round(warning_value, 2)}
[docs]
def get_pgood_err(self):
"""get status of power good error status.
:return: power good error value if not 0 an error was detetcted
:note: this method not work properly with bios < v0.3.0
"""
add = FRAM_BA + McuRegisters.FRAM_POWERGOOD_ERR
pgood_err = self.board[add]
return pgood_err
[docs]
def get_i2c_unreach_err(self):
"""
Get status of i2c unreachable error status.
:return: i2c unreachable error value if not 0 an error was detetcted
:note: this method not work properly with bios < v0.3.0
"""
add = FRAM_BA + McuRegisters.FRAM_I2C_UNREACH_ERR
i2cunreach_err = self.board[add]
return i2cunreach_err
[docs]
def get_voltage(self, voltage=None):
if voltage is None:
voltages = self._available_voltages
else:
if voltage not in self._available_voltages:
# raise PluginError(f"No voltage named '{voltage}' \n Options are {', '.join(self._available_voltages)}")
return {}
voltages = [voltage]
rt = {}
for v in voltages:
rt[v] = self.get_rounded_adc_value(self.voltage_dict_map[v])
return rt
[docs]
def get_voltage_warning_thresholds(self, voltage=None):
if voltage is not None:
if voltage in self._available_voltages:
measures = [voltage]
else:
self.logger.error(
"Error: measure not found, please use one in available"
)
return None
else:
measures = self._available_voltages
res = {}
for measure in measures:
adc_measure = self.voltage_dict_map[measure]
if adc_measure is not None:
thr_warn_reg = self.board.read_address(
FRAM_BA + Warn_Thresholds[adc_measure]["add"]
)
res[measure] = {
"min": ((thr_warn_reg & 0xFFFF)) / 1000,
"max": ((thr_warn_reg & 0xFFFF0000) >> 16) / 1000,
}
if voltage is not None:
return res[voltage]
return res
[docs]
def set_voltage_warning_thresholds(self, voltage, min_thr, max_thr):
if voltage not in self._available_voltages:
self.logger.error("Error: measure not found, please use one in available")
return None
adc_measure = self.voltage_dict_map[voltage]
if adc_measure is not None:
thr_warn_reg = ((int(max_thr * 1000) & 0xFFFF) << 16) | (
int(min_thr * 1000) & 0xFFFF
)
self.board.write_address(
FRAM_BA + Warn_Thresholds[adc_measure]["add"], thr_warn_reg
)
self.set_thresholds_update(
f"set_voltage_warning_thresholds {voltage} {min_thr} {max_thr}"
)
return True
[docs]
def get_current(self, current=None):
if current is None:
currents = self._available_currents
else:
if current not in self._available_currents:
# raise PluginError(f"No current named '{current}' \n Options are {', '.join(self._available_currents)}")
return {}
currents = [current]
rt = {}
for c in currents:
rt[c] = self.get_rounded_adc_value(self.current_dict_map[c])
return rt
[docs]
def get_current_warning_thresholds(self, current=None):
if current is not None:
if current in self._available_currents:
measures = [current]
else:
self.logger.error(
"Error: measure not found, please use one in available"
)
return None
else:
measures = self._available_currents
res = {}
for measure in measures:
adc_measure = self.current_dict_map[measure]
if adc_measure is not None:
thr_warn_reg = self.board.read_address(
FRAM_BA + Warn_Thresholds[adc_measure]["add"]
)
res[measure] = {
"min": ((thr_warn_reg & 0xFFFF)) / 1000,
"max": ((thr_warn_reg & 0xFFFF0000) >> 16) / 1000,
}
if current is not None:
return res[current]
return res
[docs]
def set_current_warning_thresholds(self, current, min_thr, max_thr):
if current not in self._available_currents:
self.logger.error("Error: measure not found, please use one in available")
return None
adc_measure = self.current_dict_map[current]
if adc_measure is not None:
thr_warn_reg = ((int(max_thr * 1000) & 0xFFFF) << 16) | (
int(min_thr * 1000) & 0xFFFF
)
self.board.write_address(
FRAM_BA + Warn_Thresholds[adc_measure]["add"], thr_warn_reg
)
self.set_thresholds_update(
f"set_current_warning_thresholds {current} {min_thr} {max_thr}"
)
return True
[docs]
def get_available_voltages(self):
return self._available_voltages
[docs]
def get_available_currents(self):
return self._available_currents
# #################### Superclass method implementations #################################
[docs]
def initialise(self):
"""Initialise TpmMcu"""
self.logger.info("TpmMcu has been initialised")
return True
[docs]
def status_check(self):
"""Perform status check.
:return: Status
"""
self.logger.info("TpmMcu : Checking status")
return Status.OK
[docs]
def clean_up(self):
"""Perform cleanup.
:return: Success
"""
self.logger.info("TpmMcu : Cleaning up")
return True