Repository: tenstorrent/tt-zephyr-platforms
Pull request #248: lib: tenstorrent: support reading telemetry tags via SMBUS
Author: login: danieldegrasse
Created: 2025-05-19T21:23:46Z | Merged: 2025-05-20T19:18:06Z

This PR enables reading telemetry tags via SMBUS, using the following scheme:

| Register       | Address | Width   | Usage                                                                                                                             |
|----------------|---------|---------|-----------------------------------------------------------------------------------------------------------------------------------|
| TELEMETRY_TAG  | 0x26    | 8 bits  | Write only. Write with telemetry tag value to select which telemetry field will be read when reading from TELEMETRY_DATA register |
| TELEMETRY_DATA | 0x27    | 32 bits | Read only. Read to get the latest telemetry data for the tag programmed to TELEMETRY_TAG register                                 |

The `TELEMETRY_TAG` register is "sticky"- so a controller only needs to program it once, and then can poll the `TELEMETRY_DATA` register for new telemetry data for that tag.

This PR also includes two other notable changes:
- remove the `tag_table` definition- telemetry tags now map directly to their offset in the telemetry table. This way, we don't need to perform any remapping logic on the SMC to report telemetry values based on their tag. The tag table is still defined so existing tools like tt-smi will function, but it is now effectively a 1:1 map
- add an SMBUS test sequence to the DMFW. This sequence is only enabled for test builds, but it will allow us to test SMBUS messages from the controller side, with the SMC running as the peripheral. Currently it is only used to test the telemetry tags support, but we could also use this to test fan control or board power limits.


Diff:
diff --git a/app/dmc/Kconfig b/app/dmc/Kconfig
new file mode 100644
index 000000000..37e79fec3
--- /dev/null
+++ b/app/dmc/Kconfig
@@ -0,0 +1,10 @@
+# Copyright (c) 2025 Tenstorrent AI ULC
+# SPDX-License-Identifier: Apache-2.0
+
+config DMC_RUN_SMBUS_TESTS
+	bool "Run SMBUS Tests"
+	help
+	  Run SMBUS tests on the DMC at boot time. This can be used to verify
+	  functionality of the SMBUS interface.
+
+source "Kconfig.zephyr"
diff --git a/app/dmc/sample.yaml b/app/dmc/sample.yaml
index da8b692f8..5a2cd6143 100644
--- a/app/dmc/sample.yaml
+++ b/app/dmc/sample.yaml
@@ -5,6 +5,7 @@ tests:
     sysbuild: true
     extra_configs:
       - CONFIG_TT_FWUPDATE=n
+      - CONFIG_DMC_RUN_SMBUS_TESTS=y
     platform_allow:
       - tt_blackhole@p100/tt_blackhole/dmc
       - tt_blackhole@p100a/tt_blackhole/dmc
diff --git a/app/dmc/src/main.c b/app/dmc/src/main.c
index 63ceaf533..40cd07dbd 100644
--- a/app/dmc/src/main.c
+++ b/app/dmc/src/main.c
@@ -179,6 +179,50 @@ uint16_t detect_max_power(void)
 	return psu_power;
 }
 
+/*
+ * Runs a series of SMBUS tests when `CONFIG_DMC_RUN_SMBUS_TESTS` is enabled.
+ * These tests aren't intended to be run on production firmware.
+ */
+static int bh_chip_run_smbus_tests(struct bh_chip *chip)
+{
+#ifdef CONFIG_DMC_RUN_SMBUS_TESTS
+	int ret;
+	int pass_val = 0xFEEDFACE;
+	uint8_t count;
+	uint8_t data[32]; /* Max size of SMBUS block read */
+
+	/* Test SMBUS telemetry by selecting TAG_DM_APP_FW_VERSION and reading it back */
+	ret = bharc_smbus_byte_data_write(&chip->config.arc, 0x26, 26);
+	if (ret < 0) {
+		LOG_ERR("Failed to write to SMBUS telemetry register");
+		return ret;
+	}
+	ret = bharc_smbus_block_read(&chip->config.arc, 0x27, &count, data);
+	if (ret < 0) {
+		LOG_ERR("Failed to read from SMBUS telemetry register");
+		return ret;
+	}
+	if (count != 4) {
+		LOG_ERR("SMBUS telemetry read returned unexpected count: %d", count);
+		return -EIO;
+	}
+	if ((*(uint32_t *)data) != APPVERSION) {
+		LOG_ERR("SMBUS telemetry read returned unexpected value: %08x", *(uint32_t *)data);
+		return -EIO;
+	}
+
+	/* Record test status into scratch register */
+	ret = bharc_smbus_block_write(&chip->config.arc, 0xDD, sizeof(pass_val),
+				      (uint8_t *)&pass_val);
+	if (ret < 0) {
+		LOG_ERR("Failed to write to SMBUS scratch register");
+		return ret;
+	}
+	printk("SMBUS tests passed\n");
+#endif
+	return 0;
+}
+
 int main(void)
 {
 	int ret;
@@ -353,7 +397,8 @@ int main(void)
 		ARRAY_FOR_EACH_PTR(BH_CHIPS, chip) {
 			if (chip->data.arc_needs_init_msg) {
 				if (bh_chip_set_static_info(chip, &static_info) == 0 &&
-				    bh_chip_set_input_power_lim(chip, max_power) == 0) {
+				    bh_chip_set_input_power_lim(chip, max_power) == 0 &&
+				    bh_chip_run_smbus_tests(chip) == 0) {
 					chip->data.arc_needs_init_msg = false;
 				}
 			}
diff --git a/app/smc/pytest/e2e_smoke.py b/app/smc/pytest/e2e_smoke.py
index a76af33cf..44d081958 100644
--- a/app/smc/pytest/e2e_smoke.py
+++ b/app/smc/pytest/e2e_smoke.py
@@ -115,6 +115,19 @@ def test_boot_status(arc_chip):
     logger.info('SMC boot status "%d"', status)
 
 
+def test_smbus_status(arc_chip):
+    """
+    Validates that the SMBUS tests run from the DMC firmware passed
+    """
+    # We have limited visibility into the DMC firmware, so we read
+    # the ARC scratch register the DMC should have set within SMBUS
+    # tests to check that they passed
+    ARC_SCRATCH_63 = 0x80030400 + (63 * 4)
+    status = arc_chip.axi_read32(ARC_SCRATCH_63)
+    assert status == 0xFEEDFACE, "SMC firmware did not pass SMBUS tests"
+    logger.info('SMC SMBUS status: "0x%x"', status)
+
+
 def get_int_version_from_file(filename) -> int:
     with open(filename, "r") as f:
         version_data = f.readlines()
diff --git a/include/tenstorrent/bh_arc.h b/include/tenstorrent/bh_arc.h
index 082f00784..dd1d1162e 100644
--- a/include/tenstorrent/bh_arc.h
+++ b/include/tenstorrent/bh_arc.h
@@ -54,6 +54,7 @@ typedef struct cm2dmMessageRet {
 int bharc_smbus_block_read(const struct bh_arc *dev, uint8_t cmd, uint8_t *count, uint8_t *output);
 int bharc_smbus_block_write(const struct bh_arc *dev, uint8_t cmd, uint8_t count, uint8_t *input);
 int bharc_smbus_word_data_write(const struct bh_arc *dev, uint16_t cmd, uint16_t word);
+int bharc_smbus_byte_data_write(const struct bh_arc *dev, uint8_t cmd, uint8_t word);
 
 #define BH_ARC_INIT(n)                                                                             \
 	{.smbus = SMBUS_DT_SPEC_GET(n),                                                            \
diff --git a/lib/tenstorrent/bh_arc/cm2dm_msg.c b/lib/tenstorrent/bh_arc/cm2dm_msg.c
index 8c158a458..3af8fa3f1 100644
--- a/lib/tenstorrent/bh_arc/cm2dm_msg.c
+++ b/lib/tenstorrent/bh_arc/cm2dm_msg.c
@@ -30,6 +30,7 @@ typedef struct {
 static Cm2DmMsgState cm2dm_msg_state;
 static bool dmfw_ping_valid;
 static uint16_t power;
+static uint16_t telemetry_reg;
 K_MSGQ_DEFINE(cm2dm_msg_q, sizeof(Cm2DmMsg), 4, _Alignof(Cm2DmMsg));
 
 int32_t EnqueueCm2DmMsg(const Cm2DmMsg *msg)
@@ -263,3 +264,27 @@ int32_t Dm2CmSendFanRPMHandler(const uint8_t *data, uint8_t size)
 
 	return -1;
 }
+
+int32_t SMBusTelemRegHandler(const uint8_t *data, uint8_t size)
+{
+	if (size != 1) {
+		return -1;
+	}
+
+	/* Load telemetry register with data */
+	telemetry_reg = data[0];
+	return 0;
+}
+
+int32_t SMBusTelemDataHandler(uint8_t *data, uint8_t size)
+{
+	uint32_t telemetry_data;
+
+	if (size != sizeof(telemetry_data)) {
+		return -1;
+	}
+
+	telemetry_data = GetTelemetryTag(telemetry_reg);
+	memcpy(data, &telemetry_data, sizeof(telemetry_data));
+	return 0;
+}
diff --git a/lib/tenstorrent/bh_arc/cm2dm_msg.h b/lib/tenstorrent/bh_arc/cm2dm_msg.h
index 79ce089af..30167adf9 100644
--- a/lib/tenstorrent/bh_arc/cm2dm_msg.h
+++ b/lib/tenstorrent/bh_arc/cm2dm_msg.h
@@ -57,5 +57,7 @@ int32_t Dm2CmSendPowerHandler(const uint8_t *data, uint8_t size);
 int32_t GetInputCurrent(void);
 uint16_t GetInputPower(void);
 int32_t Dm2CmSendFanRPMHandler(const uint8_t *data, uint8_t size);
+int32_t SMBusTelemRegHandler(const uint8_t *data, uint8_t size);
+int32_t SMBusTelemDataHandler(uint8_t *data, uint8_t size);
 
 #endif
diff --git a/lib/tenstorrent/bh_arc/smbus_target.c b/lib/tenstorrent/bh_arc/smbus_target.c
index cd3c473c8..b0af60d25 100644
--- a/lib/tenstorrent/bh_arc/smbus_target.c
+++ b/lib/tenstorrent/bh_arc/smbus_target.c
@@ -178,6 +178,13 @@ static SmbusConfig smbus_config = {
 		[0x25] = {.valid = 1,
 			  .trans_type = kSmbusTransWriteWord,
 			  .handler = {.rcv_handler = &Dm2CmSendPowerHandler}},
+		[0x26] = {.valid = 1,
+			  .trans_type = kSmbusTransWriteByte,
+			  .handler = {.rcv_handler = &SMBusTelemRegHandler}},
+		[0x27] = {.valid = 1,
+			  .trans_type = kSmbusTransBlockRead,
+			  .expected_blocksize = sizeof(uint32_t),
+			  .handler = {.send_handler = &SMBusTelemDataHandler}},
 #endif
 		[0xD8] = {.valid = 1,
 			  .trans_type = kSmbusTransReadByte,
diff --git a/lib/tenstorrent/bh_arc/telemetry.c b/lib/tenstorrent/bh_arc/telemetry.c
index 8cd30db3b..1b7d6c907 100644
--- a/lib/tenstorrent/bh_arc/telemetry.c
+++ b/lib/tenstorrent/bh_arc/telemetry.c
@@ -39,19 +39,76 @@ struct telemetry_entry {
 struct telemetry_table {
 	uint32_t version;
 	uint32_t entry_count;
-	struct telemetry_entry tag_table[TELEM_ENUM_COUNT];
-	uint32_t telemetry[TELEM_ENUM_COUNT];
+	struct telemetry_entry tag_table[TAG_COUNT];
+	uint32_t telemetry[TAG_COUNT];
 };
 
 /* Global variables */
-static struct telemetry_table telemetry_table;
+static struct telemetry_table telemetry_table = {
+	.tag_table = {
+		[0] = {TAG_BOARD_ID_HIGH, TELEM_OFFSET(TAG_BOARD_ID_HIGH)},
+		[1] = {TAG_BOARD_ID_LOW, TELEM_OFFSET(TAG_BOARD_ID_LOW)},
+		[2] = {TAG_ASIC_ID, TELEM_OFFSET(TAG_ASIC_ID)},
+		[3] = {TAG_HARVESTING_STATE, TELEM_OFFSET(TAG_HARVESTING_STATE)},
+		[4] = {TAG_UPDATE_TELEM_SPEED, TELEM_OFFSET(TAG_UPDATE_TELEM_SPEED)},
+		[5] = {TAG_VCORE, TELEM_OFFSET(TAG_VCORE)},
+		[6] = {TAG_TDP, TELEM_OFFSET(TAG_TDP)},
+		[7] = {TAG_TDC, TELEM_OFFSET(TAG_TDC)},
+		[8] = {TAG_VDD_LIMITS, TELEM_OFFSET(TAG_VDD_LIMITS)},
+		[9] = {TAG_THM_LIMITS, TELEM_OFFSET(TAG_THM_LIMITS)},
+		[10] = {TAG_ASIC_TEMPERATURE, TELEM_OFFSET(TAG_ASIC_TEMPERATURE)},
+		[11] = {TAG_VREG_TEMPERATURE, TELEM_OFFSET(TAG_VREG_TEMPERATURE)},
+		[12] = {TAG_BOARD_TEMPERATURE, TELEM_OFFSET(TAG_BOARD_TEMPERATURE)},
+		[13] = {TAG_AICLK, TELEM_OFFSET(TAG_AICLK)},
+		[14] = {TAG_AXICLK, TELEM_OFFSET(TAG_AXICLK)},
+		[15] = {TAG_ARCCLK, TELEM_OFFSET(TAG_ARCCLK)},
+		[16] = {TAG_L2CPUCLK0, TELEM_OFFSET(TAG_L2CPUCLK0)},
+		[17] = {TAG_L2CPUCLK1, TELEM_OFFSET(TAG_L2CPUCLK1)},
+		[18] = {TAG_L2CPUCLK2, TELEM_OFFSET(TAG_L2CPUCLK2)},
+		[19] = {TAG_L2CPUCLK3, TELEM_OFFSET(TAG_L2CPUCLK3)},
+		[20] = {TAG_ETH_LIVE_STATUS, TELEM_OFFSET(TAG_ETH_LIVE_STATUS)},
+		[21] = {TAG_GDDR_STATUS, TELEM_OFFSET(TAG_GDDR_STATUS)},
+		[22] = {TAG_GDDR_SPEED, TELEM_OFFSET(TAG_GDDR_SPEED)},
+		[23] = {TAG_ETH_FW_VERSION, TELEM_OFFSET(TAG_ETH_FW_VERSION)},
+		[24] = {TAG_GDDR_FW_VERSION, TELEM_OFFSET(TAG_GDDR_FW_VERSION)},
+		[25] = {TAG_DM_APP_FW_VERSION, TELEM_OFFSET(TAG_DM_APP_FW_VERSION)},
+		[26] = {TAG_DM_BL_FW_VERSION, TELEM_OFFSET(TAG_DM_BL_FW_VERSION)},
+		[27] = {TAG_FLASH_BUNDLE_VERSION, TELEM_OFFSET(TAG_FLASH_BUNDLE_VERSION)},
+		[28] = {TAG_CM_FW_VERSION, TELEM_OFFSET(TAG_CM_FW_VERSION)},
+		[29] = {TAG_L2CPU_FW_VERSION, TELEM_OFFSET(TAG_L2CPU_FW_VERSION)},
+		[30] = {TAG_FAN_SPEED, TELEM_OFFSET(TAG_FAN_SPEED)},
+		[31] = {TAG_TIMER_HEARTBEAT, TELEM_OFFSET(TAG_TIMER_HEARTBEAT)},
+		[32] = {TAG_ENABLED_TENSIX_COL, TELEM_OFFSET(TAG_ENABLED_TENSIX_COL)},
+		[33] = {TAG_ENABLED_ETH, TELEM_OFFSET(TAG_ENABLED_ETH)},
+		[34] = {TAG_ENABLED_GDDR, TELEM_OFFSET(TAG_ENABLED_GDDR)},
+		[35] = {TAG_ENABLED_L2CPU, TELEM_OFFSET(TAG_ENABLED_L2CPU)},
+		[36] = {TAG_PCIE_USAGE, TELEM_OFFSET(TAG_PCIE_USAGE)},
+		[37] = {TAG_NOC_TRANSLATION, TELEM_OFFSET(TAG_NOC_TRANSLATION)},
+		[38] = {TAG_FAN_RPM, TELEM_OFFSET(TAG_FAN_RPM)},
+		[39] = {TAG_GDDR_0_1_TEMP, TELEM_OFFSET(TAG_GDDR_0_1_TEMP)},
+		[40] = {TAG_GDDR_2_3_TEMP, TELEM_OFFSET(TAG_GDDR_2_3_TEMP)},
+		[41] = {TAG_GDDR_4_5_TEMP, TELEM_OFFSET(TAG_GDDR_4_5_TEMP)},
+		[42] = {TAG_GDDR_6_7_TEMP, TELEM_OFFSET(TAG_GDDR_6_7_TEMP)},
+		[43] = {TAG_GDDR_0_1_CORR_ERRS, TELEM_OFFSET(TAG_GDDR_0_1_CORR_ERRS)},
+		[44] = {TAG_GDDR_2_3_CORR_ERRS, TELEM_OFFSET(TAG_GDDR_2_3_CORR_ERRS)},
+		[45] = {TAG_GDDR_4_5_CORR_ERRS, TELEM_OFFSET(TAG_GDDR_4_5_CORR_ERRS)},
+		[46] = {TAG_GDDR_6_7_CORR_ERRS, TELEM_OFFSET(TAG_GDDR_6_7_CORR_ERRS)},
+		[47] = {TAG_GDDR_UNCORR_ERRS, TELEM_OFFSET(TAG_GDDR_UNCORR_ERRS)},
+		[48] = {TAG_MAX_GDDR_TEMP, TELEM_OFFSET(TAG_MAX_GDDR_TEMP)},
+		[49] = {TAG_ASIC_LOCATION, TELEM_OFFSET(TAG_ASIC_LOCATION)},
+		[50] = {TAG_BOARD_POWER_LIMIT, TELEM_OFFSET(TAG_BOARD_POWER_LIMIT)},
+		[51] = {TAG_INPUT_POWER, TELEM_OFFSET(TAG_INPUT_POWER)},
+		[52] = {TAG_TELEM_ENUM_COUNT, TELEM_OFFSET(TAG_TELEM_ENUM_COUNT)},
+	},
+};
 static uint32_t *telemetry = &telemetry_table.telemetry[0];
-static struct telemetry_entry *tag_table = &telemetry_table.tag_table[0];
 
 static struct k_timer telem_update_timer;
 static struct k_work telem_update_worker;
 static int telem_update_interval = 100;
 
+
+
 uint32_t ConvertFloatToTelemetry(float value)
 {
 	/* Convert float to signed int 16.16 format */
@@ -86,12 +143,12 @@ static void UpdateGddrTelemetry(void)
 {
 	/* We pack multiple metrics into one field, so need to clear first. */
 	for (int i = 0; i < NUM_GDDR / 2; i++) {
-		telemetry[GDDR_0_1_TEMP + i] = 0;
-		telemetry[GDDR_0_1_CORR_ERRS + i] = 0;
+		telemetry[TAG_GDDR_0_1_TEMP + i] = 0;
+		telemetry[TAG_GDDR_0_1_CORR_ERRS + i] = 0;
 	}
 
-	telemetry[GDDR_UNCORR_ERRS] = 0;
-	telemetry[GDDR_STATUS] = 0;
+	telemetry[TAG_GDDR_UNCORR_ERRS] = 0;
+	telemetry[TAG_GDDR_STATUS] = 0;
 
 	for (int i = 0; i < NUM_GDDR; i++) {
 		gddr_telemetry_table_t gddr_telemetry;
@@ -111,7 +168,8 @@ static void UpdateGddrTelemetry(void)
 			 * [14] - Training Complete GDDR 7
 			 * [15] - Error GDDR 7
 			 */
-			telemetry[GDDR_STATUS] |= (gddr_telemetry.training_complete << (i * 2)) |
+			telemetry[TAG_GDDR_STATUS] |=
+						  (gddr_telemetry.training_complete << (i * 2)) |
 						  (gddr_telemetry.gddr_error << (i * 2 + 1));
 
 			/* DDR_x_y_TEMP:
@@ -122,7 +180,7 @@ static void UpdateGddrTelemetry(void)
 			 */
 			int shift_val = (i % 2) * 16;
 
-			telemetry[GDDR_0_1_TEMP + i / 2] |=
+			telemetry[TAG_GDDR_0_1_TEMP + i / 2] |=
 				((gddr_telemetry.dram_temperature_top & 0xff) << (8 + shift_val)) |
 				((gddr_telemetry.dram_temperature_bottom & 0xff) << shift_val);
 
@@ -132,7 +190,7 @@ static void UpdateGddrTelemetry(void)
 			 * [15:8]  GDDR x Corrected Write EDC errors
 			 * [7:0]   GDDR y Corrected Read EDC Errors
 			 */
-			telemetry[GDDR_0_1_CORR_ERRS + i / 2] |=
+			telemetry[TAG_GDDR_0_1_CORR_ERRS + i / 2] |=
 				((gddr_telemetry.corr_edc_wr_errors & 0xff) << (8 + shift_val)) |
 				((gddr_telemetry.corr_edc_rd_errors & 0xff) << shift_val);
 
@@ -143,11 +201,11 @@ static void UpdateGddrTelemetry(void)
 			 * ...
 			 * [15] GDDR 7 Uncorrected Write EDC error
 			 */
-			telemetry[GDDR_UNCORR_ERRS] |=
+			telemetry[TAG_GDDR_UNCORR_ERRS] |=
 				(gddr_telemetry.uncorr_edc_rd_error << (i * 2)) |
 				(gddr_telemetry.uncorr_edc_wr_error << (i * 2 + 1));
 			/* GDDR speed - in Mbps */
-			telemetry[GDDR_SPEED] = gddr_telemetry.dram_speed;
+			telemetry[TAG_GDDR_SPEED] = gddr_telemetry.dram_speed;
 		}
 	}
 }
@@ -158,11 +216,10 @@ int GetMaxGDDRTemp(void)
 
 	for (int i = 0; i < NUM_GDDR; i++) {
 		int shift_val = (i % 2) * 16;
+		int gddr_temp = telemetry[TAG_GDDR_0_1_TEMP + i / 2];
 
-		max_gddr_temp =
-			MAX(max_gddr_temp, (telemetry[GDDR_0_1_TEMP + i / 2] >> shift_val) & 0xFF);
-		max_gddr_temp = MAX(max_gddr_temp,
-				    (telemetry[GDDR_0_1_TEMP + i / 2] >> (shift_val + 8)) & 0xFF);
+		max_gddr_temp = MAX(max_gddr_temp, (gddr_temp >> shift_val) & 0xFF);
+		max_gddr_temp = MAX(max_gddr_temp, (gddr_temp >> (shift_val + 8)) & 0xFF);
 	}
 
 	return max_gddr_temp;
@@ -173,17 +230,19 @@ static void write_static_telemetry(uint32_t app_version)
 	telemetry_table.version = TELEMETRY_VERSION;    /* v0.1.0 - Only update when redefining the
 							 * meaning of an existing tag
 							 */
-	telemetry_table.entry_count = TELEM_ENUM_COUNT; /* Runtime count of telemetry entries */
+	telemetry_table.entry_count = TAG_COUNT; /* Runtime count of telemetry entries */
 
 	/* Get the static values */
-	telemetry[BOARD_ID_HIGH] = get_read_only_table()->board_id >> 32;
-	telemetry[BOARD_ID_LOW] = get_read_only_table()->board_id & 0xFFFFFFFF;
-	telemetry[ASIC_ID] = 0x00000000; /* Might be subject to redesign */
-	telemetry[HARVESTING_STATE] = 0x00000000;
-	telemetry[UPDATE_TELEM_SPEED] = telem_update_interval; /* Expected speed of update in ms */
+	telemetry[TAG_BOARD_ID_HIGH] = get_read_only_table()->board_id >> 32;
+	telemetry[TAG_BOARD_ID_LOW] = get_read_only_table()->board_id & 0xFFFFFFFF;
+	telemetry[TAG_ASIC_ID] = 0x00000000; /* Might be subject to redesign */
+	telemetry[TAG_HARVESTING_STATE] = 0x00000000;
+	telemetry[TAG_UPDATE_TELEM_SPEED] = telem_update_interval; /* Expected speed of
+								    * update in ms
+								    */
 
 	/* TODO: Gather FW versions from FW themselves */
-	telemetry[ETH_FW_VERSION] = 0x00000000;
+	telemetry[TAG_ETH_FW_VERSION] = 0x00000000;
 	if (tile_enable.gddr_enabled != 0) {
 		gddr_telemetry_table_t gddr_telemetry;
 		/* Use first available instance. */
@@ -193,33 +252,37 @@ static void write_static_telemetry(uint32_t app_version)
 			LOG_WRN_ONCE("Failed to read GDDR telemetry table while "
 				     "writing static telemetry");
 		} else {
-			telemetry[GDDR_FW_VERSION] = (gddr_telemetry.mrisc_fw_version_major << 16) |
-						     gddr_telemetry.mrisc_fw_version_minor;
+			telemetry[TAG_GDDR_FW_VERSION] =
+					(gddr_telemetry.mrisc_fw_version_major << 16) |
+					 gddr_telemetry.mrisc_fw_version_minor;
 		}
 	}
 	/* DM_APP_FW_VERSION and DM_BL_FW_VERSION assumes zero-init, it might be
 	 * initialized by bh_chip_set_static_info in dmfw already, must not clear.
 	 */
-	telemetry[FLASH_BUNDLE_VERSION] = get_fw_table()->fw_bundle_version;
-	telemetry[CM_FW_VERSION] = app_version;
-	telemetry[L2CPU_FW_VERSION] = 0x00000000;
+	telemetry[TAG_FLASH_BUNDLE_VERSION] = get_fw_table()->fw_bundle_version;
+	telemetry[TAG_CM_FW_VERSION] = app_version;
+	telemetry[TAG_L2CPU_FW_VERSION] = 0x00000000;
 
 	/* Tile enablement / harvesting information */
-	telemetry[ENABLED_TENSIX_COL] = tile_enable.tensix_col_enabled;
-	telemetry[ENABLED_ETH] = tile_enable.eth_enabled;
-	telemetry[ENABLED_GDDR] = tile_enable.gddr_enabled;
-	telemetry[ENABLED_L2CPU] = tile_enable.l2cpu_enabled;
-	telemetry[PCIE_USAGE] =
-		((tile_enable.pcie_usage[1] & 0x3) << 2) | (tile_enable.pcie_usage[0] & 0x3);
-	/* telemetry[NOC_TRANSLATION] assumes zero-init, see also UpdateTelemetryNocTranslation. */
+	telemetry[TAG_ENABLED_TENSIX_COL] = tile_enable.tensix_col_enabled;
+	telemetry[TAG_ENABLED_ETH] = tile_enable.eth_enabled;
+	telemetry[TAG_ENABLED_GDDR] = tile_enable.gddr_enabled;
+	telemetry[TAG_ENABLED_L2CPU] = tile_enable.l2cpu_enabled;
+	telemetry[TAG_PCIE_USAGE] =
+		((tile_enable.pcie_usage[1] & 0x3) << 2) |
+		(tile_enable.pcie_usage[0] & 0x3);
+	/* telemetry[TAG_NOC_TRANSLATION] assumes zero-init, see also
+	 * UpdateTelemetryNocTranslation.
+	 */
 
 	if (get_pcb_type() == PcbTypeP300) {
 		/* For the p300 a value of 1 is the left asic and 0 is the right */
-		telemetry[ASIC_LOCATION] =
+		telemetry[TAG_ASIC_LOCATION] =
 			FIELD_GET(BIT(6), ReadReg(RESET_UNIT_STRAP_REGISTERS_L_REG_ADDR));
 	} else {
 		/* For all other supported boards this value is 0 */
-		telemetry[ASIC_LOCATION] = 0;
+		telemetry[TAG_ASIC_LOCATION] = 0;
 	}
 }
 
@@ -231,100 +294,43 @@ static void update_telemetry(void)
 	ReadTelemetryInternal(telem_update_interval, &telemetry_internal_data);
 
 	/* Get all dynamically updated values */
-	telemetry[VCORE] =
+	telemetry[TAG_VCORE] =
 		telemetry_internal_data
 			.vcore_voltage; /* reported in mV, will be truncated to uint32_t */
-	telemetry[TDP] = telemetry_internal_data
+	telemetry[TAG_TDP] = telemetry_internal_data
 				 .vcore_power; /* reported in W, will be truncated to uint32_t */
-	telemetry[TDC] = telemetry_internal_data
+	telemetry[TAG_TDC] = telemetry_internal_data
 				 .vcore_current; /* reported in A, will be truncated to uint32_t */
-	telemetry[VDD_LIMITS] = 0x00000000;      /* VDD limits - Not Available yet */
-	telemetry[THM_LIMITS] = 0x00000000;      /* THM limits - Not Available yet */
-	telemetry[ASIC_TEMPERATURE] = ConvertFloatToTelemetry(
-		telemetry_internal_data.asic_temperature); /* ASIC temperature - reported in signed
-							    * int 16.16 format
+	telemetry[TAG_VDD_LIMITS] = 0x00000000;      /* VDD limits - Not Available yet */
+	telemetry[TAG_THM_LIMITS] = 0x00000000;      /* THM limits - Not Available yet */
+	telemetry[TAG_ASIC_TEMPERATURE] = ConvertFloatToTelemetry(
+		telemetry_internal_data.asic_temperature); /* ASIC temperature - reported in
+							    * signed int 16.16 format
 							    */
-	telemetry[VREG_TEMPERATURE] = 0x000000;            /* VREG temperature - need I2C line */
-	telemetry[BOARD_TEMPERATURE] = 0x000000;           /* Board temperature - need I2C line */
-	telemetry[AICLK] = GetAICLK(); /* first 16 bits - MAX ASIC FREQ (Not Available yet), lower
-					* 16 bits - current AICLK
-					*/
-	telemetry[AXICLK] = GetAXICLK();
-	telemetry[ARCCLK] = GetARCCLK();
-	telemetry[L2CPUCLK0] = GetL2CPUCLK(0);
-	telemetry[L2CPUCLK1] = GetL2CPUCLK(1);
-	telemetry[L2CPUCLK2] = GetL2CPUCLK(2);
-	telemetry[L2CPUCLK3] = GetL2CPUCLK(3);
-	telemetry[ETH_LIVE_STATUS] =
+	telemetry[TAG_VREG_TEMPERATURE] = 0x000000;  /* VREG temperature - need I2C line */
+	telemetry[TAG_BOARD_TEMPERATURE] = 0x000000; /* Board temperature - need I2C line */
+	telemetry[TAG_AICLK] = GetAICLK(); /* first 16 bits - MAX ASIC FREQ (Not Available yet),
+					    * lower 16 bits - current AICLK
+					    */
+	telemetry[TAG_AXICLK] = GetAXICLK();
+	telemetry[TAG_ARCCLK] = GetARCCLK();
+	telemetry[TAG_L2CPUCLK0] = GetL2CPUCLK(0);
+	telemetry[TAG_L2CPUCLK1] = GetL2CPUCLK(1);
+	telemetry[TAG_L2CPUCLK2] = GetL2CPUCLK(2);
+	telemetry[TAG_L2CPUCLK3] = GetL2CPUCLK(3);
+	telemetry[TAG_ETH_LIVE_STATUS] =
 		0x00000000; /* ETH live status lower 16 bits: heartbeat status, upper 16 bits:
 			     * retrain_status - Not Available yet
 			     */
-	telemetry[FAN_SPEED] = GetFanSpeed(); /* Target fan speed - reported in percentage */
-	telemetry[FAN_RPM] = GetFanRPM();     /* Actual fan RPM */
+	telemetry[TAG_FAN_SPEED] = GetFanSpeed(); /* Target fan speed - reported in percentage */
+	telemetry[TAG_FAN_RPM] = GetFanRPM();     /* Actual fan RPM */
 	UpdateGddrTelemetry();
-	telemetry[MAX_GDDR_TEMP] = GetMaxGDDRTemp();
-	telemetry[INPUT_POWER] = GetInputPower(); /* Input power - reported in W */
-	telemetry[TIMER_HEARTBEAT]++; /* Incremented every time the timer is called */
+	telemetry[TAG_MAX_GDDR_TEMP] = GetMaxGDDRTemp();
+	telemetry[TAG_INPUT_POWER] = GetInputPower(); /* Input power - reported in W */
+	telemetry[TAG_TIMER_HEARTBEAT]++; /* Incremented every time the timer is called */
 	SetPostCode(POST_CODE_SRC_CMFW, POST_CODE_TELEMETRY_END);
 }
 
-static void update_tag_table(void)
-{
-	tag_table[0] = (struct telemetry_entry){TAG_BOARD_ID_HIGH, BOARD_ID_HIGH};
-	tag_table[1] = (struct telemetry_entry){TAG_BOARD_ID_LOW, BOARD_ID_LOW};
-	tag_table[2] = (struct telemetry_entry){TAG_ASIC_ID, ASIC_ID};
-	tag_table[3] = (struct telemetry_entry){TAG_HARVESTING_STATE, HARVESTING_STATE};
-	tag_table[4] = (struct telemetry_entry){TAG_UPDATE_TELEM_SPEED, UPDATE_TELEM_SPEED};
-	tag_table[5] = (struct telemetry_entry){TAG_VCORE, VCORE};
-	tag_table[6] = (struct telemetry_entry){TAG_TDP, TDP};
-	tag_table[7] = (struct telemetry_entry){TAG_TDC, TDC};
-	tag_table[8] = (struct telemetry_entry){TAG_VDD_LIMITS, VDD_LIMITS};
-	tag_table[9] = (struct telemetry_entry){TAG_THM_LIMITS, THM_LIMITS};
-	tag_table[10] = (struct telemetry_entry){TAG_ASIC_TEMPERATURE, ASIC_TEMPERATURE};
-	tag_table[11] = (struct telemetry_entry){TAG_VREG_TEMPERATURE, VREG_TEMPERATURE};
-	tag_table[12] = (struct telemetry_entry){TAG_BOARD_TEMPERATURE, BOARD_TEMPERATURE};
-	tag_table[13] = (struct telemetry_entry){TAG_AICLK, AICLK};
-	tag_table[14] = (struct telemetry_entry){TAG_AXICLK, AXICLK};
-	tag_table[15] = (struct telemetry_entry){TAG_ARCCLK, ARCCLK};
-	tag_table[16] = (struct telemetry_entry){TAG_L2CPUCLK0, L2CPUCLK0};
-	tag_table[17] = (struct telemetry_entry){TAG_L2CPUCLK1, L2CPUCLK1};
-	tag_table[18] = (struct telemetry_entry){TAG_L2CPUCLK2, L2CPUCLK2};
-	tag_table[19] = (struct telemetry_entry){TAG_L2CPUCLK3, L2CPUCLK3};
-	tag_table[20] = (struct telemetry_entry){TAG_ETH_LIVE_STATUS, ETH_LIVE_STATUS};
-	tag_table[21] = (struct telemetry_entry){TAG_GDDR_STATUS, GDDR_STATUS};
-	tag_table[22] = (struct telemetry_entry){TAG_GDDR_SPEED, GDDR_SPEED};
-	tag_table[23] = (struct telemetry_entry){TAG_ETH_FW_VERSION, ETH_FW_VERSION};
-	tag_table[24] = (struct telemetry_entry){TAG_GDDR_FW_VERSION, GDDR_FW_VERSION};
-	tag_table[25] = (struct telemetry_entry){TAG_DM_APP_FW_VERSION, DM_APP_FW_VERSION};
-	tag_table[26] = (struct telemetry_entry){TAG_DM_BL_FW_VERSION, DM_BL_FW_VERSION};
-	tag_table[27] = (struct telemetry_entry){TAG_FLASH_BUNDLE_VERSION, FLASH_BUNDLE_VERSION};
-	tag_table[28] = (struct telemetry_entry){TAG_CM_FW_VERSION, CM_FW_VERSION};
-	tag_table[29] = (struct telemetry_entry){TAG_L2CPU_FW_VERSION, L2CPU_FW_VERSION};
-	tag_table[30] = (struct telemetry_entry){TAG_FAN_SPEED, FAN_SPEED};
-	tag_table[31] = (struct telemetry_entry){TAG_TIMER_HEARTBEAT, TIMER_HEARTBEAT};
-	tag_table[32] = (struct telemetry_entry){TAG_ENABLED_TENSIX_COL, ENABLED_TENSIX_COL};
-	tag_table[33] = (struct telemetry_entry){TAG_ENABLED_ETH, ENABLED_ETH};
-	tag_table[34] = (struct telemetry_entry){TAG_ENABLED_GDDR, ENABLED_GDDR};
-	tag_table[35] = (struct telemetry_entry){TAG_ENABLED_L2CPU, ENABLED_L2CPU};
-	tag_table[36] = (struct telemetry_entry){TAG_PCIE_USAGE, PCIE_USAGE};
-	tag_table[37] = (struct telemetry_entry){TAG_NOC_TRANSLATION, NOC_TRANSLATION};
-	tag_table[38] = (struct telemetry_entry){TAG_FAN_RPM, FAN_RPM};
-	tag_table[39] = (struct telemetry_entry){TAG_GDDR_0_1_TEMP, GDDR_0_1_TEMP};
-	tag_table[40] = (struct telemetry_entry){TAG_GDDR_2_3_TEMP, GDDR_2_3_TEMP};
-	tag_table[41] = (struct telemetry_entry){TAG_GDDR_4_5_TEMP, GDDR_4_5_TEMP};
-	tag_table[42] = (struct telemetry_entry){TAG_GDDR_6_7_TEMP, GDDR_6_7_TEMP};
-	tag_table[43] = (struct telemetry_entry){TAG_GDDR_0_1_CORR_ERRS, GDDR_0_1_CORR_ERRS};
-	tag_table[44] = (struct telemetry_entry){TAG_GDDR_2_3_CORR_ERRS, GDDR_2_3_CORR_ERRS};
-	tag_table[45] = (struct telemetry_entry){TAG_GDDR_4_5_CORR_ERRS, GDDR_4_5_CORR_ERRS};
-	tag_table[46] = (struct telemetry_entry){TAG_GDDR_6_7_CORR_ERRS, GDDR_6_7_CORR_ERRS};
-	tag_table[47] = (struct telemetry_entry){TAG_GDDR_UNCORR_ERRS, GDDR_UNCORR_ERRS};
-	tag_table[48] = (struct telemetry_entry){TAG_MAX_GDDR_TEMP, MAX_GDDR_TEMP};
-	tag_table[49] = (struct telemetry_entry){TAG_ASIC_LOCATION, ASIC_LOCATION};
-	tag_table[50] = (struct telemetry_entry){TAG_BOARD_POWER_LIMIT, BOARD_POWER_LIMIT};
-	tag_table[51] = (struct telemetry_entry){TAG_INPUT_POWER, INPUT_POWER};
-	tag_table[52] = (struct telemetry_entry){TAG_TELEM_ENUM_COUNT, TELEM_ENUM_COUNT};
-}
-
 /* Handler functions for zephyr timer and worker objects */
 static void telemetry_work_handler(struct k_work *work)
 {
@@ -347,7 +353,6 @@ static K_TIMER_DEFINE(telem_update_timer, telemetry_timer_handler, NULL);
 
 void init_telemetry(uint32_t app_version)
 {
-	update_tag_table();
 	write_static_telemetry(app_version);
 	/* fill the dynamic values once before starting timed updates */
 	update_telemetry();
@@ -370,17 +375,25 @@ void StartTelemetryTimer(void)
 
 void UpdateDmFwVersion(uint32_t bl_version, uint32_t app_version)
 {
-	telemetry[DM_BL_FW_VERSION] = bl_version;
-	telemetry[DM_APP_FW_VERSION] = app_version;
+	telemetry[TAG_DM_BL_FW_VERSION] = bl_version;
+	telemetry[TAG_DM_APP_FW_VERSION] = app_version;
 }
 
 void UpdateTelemetryNocTranslation(bool translation_enabled)
 {
 	/* Note that this may be called before init_telemetry. */
-	telemetry[NOC_TRANSLATION] = translation_enabled;
+	telemetry[TAG_NOC_TRANSLATION] = translation_enabled;
 }
 
 void UpdateTelemetryBoardPowerLimit(uint32_t power_limit)
 {
-	telemetry[BOARD_POWER_LIMIT] = power_limit;
+	telemetry[TAG_BOARD_POWER_LIMIT] = power_limit;
+}
+
+uint32_t GetTelemetryTag(uint16_t tag)
+{
+	if (tag >= TAG_COUNT) {
+		return -1;
+	}
+	return telemetry[tag];
 }
diff --git a/lib/tenstorrent/bh_arc/telemetry.h b/lib/tenstorrent/bh_arc/telemetry.h
index 9c5470eaf..678c6a5e8 100644
--- a/lib/tenstorrent/bh_arc/telemetry.h
+++ b/lib/tenstorrent/bh_arc/telemetry.h
@@ -69,89 +69,13 @@
 #define TAG_ASIC_LOCATION        52
 #define TAG_BOARD_POWER_LIMIT    53
 #define TAG_INPUT_POWER          54
+/* Not a real tag, signifies the last tag in the list.
+ * MUST be incremented if new tags are defined
+ */
+#define TAG_COUNT                55
 
-/* Enums are subject to updates */
-typedef enum {
-	/* Board static information */
-	BOARD_ID_HIGH,
-	BOARD_ID_LOW,
-	ASIC_ID,
-	HARVESTING_STATE,
-
-	/* Telemetry timing data */
-	UPDATE_TELEM_SPEED, /* Expected speed of update to telemetry in ms */
-
-	/* Regulator information */
-	VCORE,
-	TDP,
-	TDC,
-	VDD_LIMITS,
-	THM_LIMITS,
-
-	/* Temperature information */
-	ASIC_TEMPERATURE,
-	VREG_TEMPERATURE,
-	BOARD_TEMPERATURE,
-
-	/* Clock information */
-	AICLK,
-	AXICLK,
-	ARCCLK,
-	L2CPUCLK0,
-	L2CPUCLK1,
-	L2CPUCLK2,
-	L2CPUCLK3,
-
-	/* IO information */
-	ETH_LIVE_STATUS, /* Lower 16 bits - heartbeat status, upper 16 bits - retrain_status */
-	GDDR_STATUS,
-	GDDR_SPEED,
-
-	/* FW versions */
-	ETH_FW_VERSION,
-	GDDR_FW_VERSION,
-	/* Board manager fw versions */
-	DM_APP_FW_VERSION,
-	DM_BL_FW_VERSION,
-	FLASH_BUNDLE_VERSION,
-	CM_FW_VERSION,
-	L2CPU_FW_VERSION,
-
-	/* MISC */
-	TIMER_HEARTBEAT, /* Incremented every time the timer is called */
-
-	/* Board telemetry */
-	FAN_SPEED,
-	FAN_RPM,
-	BOARD_POWER_LIMIT,
-	INPUT_POWER,
-
-	/* Tile enablement/harvesting information */
-	ENABLED_TENSIX_COL,
-	ENABLED_ETH,
-	ENABLED_GDDR,
-	ENABLED_L2CPU,
-	PCIE_USAGE,
-	NOC_TRANSLATION,
-
-	/* DRAM Temperatures */
-	GDDR_0_1_TEMP,
-	GDDR_2_3_TEMP,
-	GDDR_4_5_TEMP,
-	GDDR_6_7_TEMP,
-	MAX_GDDR_TEMP,
-
-	/* DDR Errors */
-	GDDR_0_1_CORR_ERRS,
-	GDDR_2_3_CORR_ERRS,
-	GDDR_4_5_CORR_ERRS,
-	GDDR_6_7_CORR_ERRS,
-	GDDR_UNCORR_ERRS,
-
-	ASIC_LOCATION,
-
-	TELEM_ENUM_COUNT, /* Count to check how large the enum is */
-} Telemetry;
+/* Telemetry tags are at offset `tag` in the telemetry buffer */
+#define TELEM_OFFSET(tag) (tag)
 
 void init_telemetry(uint32_t app_version);
 uint32_t ConvertFloatToTelemetry(float value);
@@ -161,5 +85,6 @@ void StartTelemetryTimer(void);
 void UpdateDmFwVersion(uint32_t bl_version, uint32_t app_version);
 void UpdateTelemetryNocTranslation(bool translation_enabled);
 void UpdateTelemetryBoardPowerLimit(uint32_t power_limit);
+uint32_t GetTelemetryTag(uint16_t tag);
 
 #endif
diff --git a/lib/tenstorrent/bh_chip/bh_arc.c b/lib/tenstorrent/bh_chip/bh_arc.c
index 5c35b605a..76bf561b9 100644
--- a/lib/tenstorrent/bh_chip/bh_arc.c
+++ b/lib/tenstorrent/bh_chip/bh_arc.c
@@ -91,3 +91,24 @@ int bharc_smbus_word_data_write(const struct bh_arc *dev, uint16_t cmd, uint16_t
 
 	return ret;
 }
+
+int bharc_smbus_byte_data_write(const struct bh_arc *dev, uint8_t cmd, uint8_t word)
+{
+	int ret;
+
+	ret = bharc_enable_i2cbus(dev);
+	if (ret != 0) {
+		bharc_disable_i2cbus(dev);
+		return ret;
+	}
+
+	ret = smbus_byte_data_write(dev->smbus.bus, dev->smbus.addr, cmd, word);
+
+	int newret = bharc_disable_i2cbus(dev);
+
+	if (ret == 0) {
+		return newret;
+	}
+
+	return ret;
+}
diff --git a/zephyr/patches.yml b/zephyr/patches.yml
index 9715eb850..bab88ad7d 100644
--- a/zephyr/patches.yml
+++ b/zephyr/patches.yml
@@ -31,7 +31,7 @@ patches:
     comments: |
       This patch moves BSS and noinit sections to the end.
   - path: zephyr/check-compliance.patch
-    sha256sum: 1a5c4fda2f9eb6094fba1250813277e3f0887d5ad84bee49f5d7291254ea9dee
+    sha256sum: 01982421bc0cf4fdfac3f39f6aab58531ab9d0e92075548488400f74084be6e7
     module: zephyr
     author: Chris Friedt
     email: cfriedt@tenstorrent.com
diff --git a/zephyr/patches/zephyr/check-compliance.patch b/zephyr/patches/zephyr/check-compliance.patch
index 958b85e3d..a8e7e9a85 100644
--- a/zephyr/patches/zephyr/check-compliance.patch
+++ b/zephyr/patches/zephyr/check-compliance.patch
@@ -60,6 +60,14 @@ index fe56b715162..c575460db38 100755
  
          # Generate combined list of configs and choices from the main Kconfig tree.
          kconf_syms = kconf.unique_defined_syms + kconf.unique_choices
+@@ -1047,6 +1046,7 @@ flagged.
+         "CRC",  # Used in TI CC13x2 / CC26x2 SDK comment
+         "DEEP_SLEEP",  # #defined by RV32M1 in ext/
+         "DESCRIPTION",
++        "DMC_RUN_SMBUS_TESTS",
+         "ERR",
+         "ESP_DIF_LIBRARY",  # Referenced in CMake comment
+         "EXPERIMENTAL",
 @@ -1076,6 +1073,7 @@ flagged.
          "MCUBOOT_CLEANUP_ARM_CORE", # Used in (sysbuild-based) test
          "MCUBOOT_DOWNGRADE_PREVENTION", # but symbols are defined in MCUboot


Reviews:
user: login: cfriedt
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-20T00:06:00Z
user: login: cfriedt
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-20T19:17:41Z
user: login: cfriedt
state: APPROVED
author_association: NONE
submitted_at: 2025-05-20T19:17:53Z
user: login: TTDRosen
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-20T19:23:45Z

Review comments:
diff_hunk: @@ -39,19 +39,76 @@ struct telemetry_entry {
 struct telemetry_table {
 	uint32_t version;
 	uint32_t entry_count;
-	struct telemetry_entry tag_table[TELEM_ENUM_COUNT];
-	uint32_t telemetry[TELEM_ENUM_COUNT];
+	struct telemetry_entry tag_table[TAG_COUNT];
path: lib/tenstorrent/bh_arc/telemetry.c
user: login: cfriedt
body: We should be able to remove the table from this structure. It provides zero information gain, FWICT and was previously write-only in `update_tag_table()`
created_at: 2025-05-20T00:01:16Z
author_association: NONE
diff_hunk: @@ -39,19 +39,76 @@ struct telemetry_entry {
 struct telemetry_table {
 	uint32_t version;
 	uint32_t entry_count;
-	struct telemetry_entry tag_table[TELEM_ENUM_COUNT];
-	uint32_t telemetry[TELEM_ENUM_COUNT];
+	struct telemetry_entry tag_table[TAG_COUNT];
+	uint32_t telemetry[TAG_COUNT];
 };
 
 /* Global variables */
-static struct telemetry_table telemetry_table;
+static struct telemetry_table telemetry_table = {
+	.tag_table = {
+		[0] = {TAG_BOARD_ID_HIGH, TELEM_OFFSET(TAG_BOARD_ID_HIGH)},
+		[1] = {TAG_BOARD_ID_LOW, TELEM_OFFSET(TAG_BOARD_ID_LOW)},
+		[2] = {TAG_ASIC_ID, TELEM_OFFSET(TAG_ASIC_ID)},
+		[3] = {TAG_HARVESTING_STATE, TELEM_OFFSET(TAG_HARVESTING_STATE)},
+		[4] = {TAG_UPDATE_TELEM_SPEED, TELEM_OFFSET(TAG_UPDATE_TELEM_SPEED)},
+		[5] = {TAG_VCORE, TELEM_OFFSET(TAG_VCORE)},
+		[6] = {TAG_TDP, TELEM_OFFSET(TAG_TDP)},
+		[7] = {TAG_TDC, TELEM_OFFSET(TAG_TDC)},
+		[8] = {TAG_VDD_LIMITS, TELEM_OFFSET(TAG_VDD_LIMITS)},
+		[9] = {TAG_THM_LIMITS, TELEM_OFFSET(TAG_THM_LIMITS)},
+		[10] = {TAG_ASIC_TEMPERATURE, TELEM_OFFSET(TAG_ASIC_TEMPERATURE)},
+		[11] = {TAG_VREG_TEMPERATURE, TELEM_OFFSET(TAG_VREG_TEMPERATURE)},
+		[12] = {TAG_BOARD_TEMPERATURE, TELEM_OFFSET(TAG_BOARD_TEMPERATURE)},
+		[13] = {TAG_AICLK, TELEM_OFFSET(TAG_AICLK)},
+		[14] = {TAG_AXICLK, TELEM_OFFSET(TAG_AXICLK)},
+		[15] = {TAG_ARCCLK, TELEM_OFFSET(TAG_ARCCLK)},
+		[16] = {TAG_L2CPUCLK0, TELEM_OFFSET(TAG_L2CPUCLK0)},
+		[17] = {TAG_L2CPUCLK1, TELEM_OFFSET(TAG_L2CPUCLK1)},
+		[18] = {TAG_L2CPUCLK2, TELEM_OFFSET(TAG_L2CPUCLK2)},
+		[19] = {TAG_L2CPUCLK3, TELEM_OFFSET(TAG_L2CPUCLK3)},
+		[20] = {TAG_ETH_LIVE_STATUS, TELEM_OFFSET(TAG_ETH_LIVE_STATUS)},
+		[21] = {TAG_GDDR_STATUS, TELEM_OFFSET(TAG_GDDR_STATUS)},
+		[22] = {TAG_GDDR_SPEED, TELEM_OFFSET(TAG_GDDR_SPEED)},
+		[23] = {TAG_ETH_FW_VERSION, TELEM_OFFSET(TAG_ETH_FW_VERSION)},
+		[24] = {TAG_GDDR_FW_VERSION, TELEM_OFFSET(TAG_GDDR_FW_VERSION)},
+		[25] = {TAG_DM_APP_FW_VERSION, TELEM_OFFSET(TAG_DM_APP_FW_VERSION)},
+		[26] = {TAG_DM_BL_FW_VERSION, TELEM_OFFSET(TAG_DM_BL_FW_VERSION)},
+		[27] = {TAG_FLASH_BUNDLE_VERSION, TELEM_OFFSET(TAG_FLASH_BUNDLE_VERSION)},
+		[28] = {TAG_CM_FW_VERSION, TELEM_OFFSET(TAG_CM_FW_VERSION)},
+		[29] = {TAG_L2CPU_FW_VERSION, TELEM_OFFSET(TAG_L2CPU_FW_VERSION)},
+		[30] = {TAG_FAN_SPEED, TELEM_OFFSET(TAG_FAN_SPEED)},
+		[31] = {TAG_TIMER_HEARTBEAT, TELEM_OFFSET(TAG_TIMER_HEARTBEAT)},
+		[32] = {TAG_ENABLED_TENSIX_COL, TELEM_OFFSET(TAG_ENABLED_TENSIX_COL)},
+		[33] = {TAG_ENABLED_ETH, TELEM_OFFSET(TAG_ENABLED_ETH)},
+		[34] = {TAG_ENABLED_GDDR, TELEM_OFFSET(TAG_ENABLED_GDDR)},
+		[35] = {TAG_ENABLED_L2CPU, TELEM_OFFSET(TAG_ENABLED_L2CPU)},
+		[36] = {TAG_PCIE_USAGE, TELEM_OFFSET(TAG_PCIE_USAGE)},
+		[37] = {TAG_NOC_TRANSLATION, TELEM_OFFSET(TAG_NOC_TRANSLATION)},
+		[38] = {TAG_FAN_RPM, TELEM_OFFSET(TAG_FAN_RPM)},
+		[39] = {TAG_GDDR_0_1_TEMP, TELEM_OFFSET(TAG_GDDR_0_1_TEMP)},
+		[40] = {TAG_GDDR_2_3_TEMP, TELEM_OFFSET(TAG_GDDR_2_3_TEMP)},
+		[41] = {TAG_GDDR_4_5_TEMP, TELEM_OFFSET(TAG_GDDR_4_5_TEMP)},
+		[42] = {TAG_GDDR_6_7_TEMP, TELEM_OFFSET(TAG_GDDR_6_7_TEMP)},
+		[43] = {TAG_GDDR_0_1_CORR_ERRS, TELEM_OFFSET(TAG_GDDR_0_1_CORR_ERRS)},
+		[44] = {TAG_GDDR_2_3_CORR_ERRS, TELEM_OFFSET(TAG_GDDR_2_3_CORR_ERRS)},
+		[45] = {TAG_GDDR_4_5_CORR_ERRS, TELEM_OFFSET(TAG_GDDR_4_5_CORR_ERRS)},
+		[46] = {TAG_GDDR_6_7_CORR_ERRS, TELEM_OFFSET(TAG_GDDR_6_7_CORR_ERRS)},
+		[47] = {TAG_GDDR_UNCORR_ERRS, TELEM_OFFSET(TAG_GDDR_UNCORR_ERRS)},
+		[48] = {TAG_MAX_GDDR_TEMP, TELEM_OFFSET(TAG_MAX_GDDR_TEMP)},
+		[49] = {TAG_ASIC_LOCATION, TELEM_OFFSET(TAG_ASIC_LOCATION)},
+		[50] = {TAG_BOARD_POWER_LIMIT, TELEM_OFFSET(TAG_BOARD_POWER_LIMIT)},
+		[51] = {TAG_INPUT_POWER, TELEM_OFFSET(TAG_INPUT_POWER)},
+		[52] = {TAG_TELEM_ENUM_COUNT, TELEM_OFFSET(TAG_TELEM_ENUM_COUNT)},
+	},
+};
path: lib/tenstorrent/bh_arc/telemetry.c
user: login: cfriedt
body: Can this entire table be deleted?

Maybe I'm missing something here too, and I believe I've asked about it a long time ago, but there also seems to be zero information gain here.

```
[0] = {1, 1},
[1] = {2, 2},
...
```

created_at: 2025-05-20T00:05:54Z
author_association: NONE
diff_hunk: @@ -39,19 +39,76 @@ struct telemetry_entry {
 struct telemetry_table {
 	uint32_t version;
 	uint32_t entry_count;
-	struct telemetry_entry tag_table[TELEM_ENUM_COUNT];
-	uint32_t telemetry[TELEM_ENUM_COUNT];
+	struct telemetry_entry tag_table[TAG_COUNT];
+	uint32_t telemetry[TAG_COUNT];
 };
 
 /* Global variables */
-static struct telemetry_table telemetry_table;
+static struct telemetry_table telemetry_table = {
+	.tag_table = {
+		[0] = {TAG_BOARD_ID_HIGH, TELEM_OFFSET(TAG_BOARD_ID_HIGH)},
+		[1] = {TAG_BOARD_ID_LOW, TELEM_OFFSET(TAG_BOARD_ID_LOW)},
+		[2] = {TAG_ASIC_ID, TELEM_OFFSET(TAG_ASIC_ID)},
+		[3] = {TAG_HARVESTING_STATE, TELEM_OFFSET(TAG_HARVESTING_STATE)},
+		[4] = {TAG_UPDATE_TELEM_SPEED, TELEM_OFFSET(TAG_UPDATE_TELEM_SPEED)},
+		[5] = {TAG_VCORE, TELEM_OFFSET(TAG_VCORE)},
+		[6] = {TAG_TDP, TELEM_OFFSET(TAG_TDP)},
+		[7] = {TAG_TDC, TELEM_OFFSET(TAG_TDC)},
+		[8] = {TAG_VDD_LIMITS, TELEM_OFFSET(TAG_VDD_LIMITS)},
+		[9] = {TAG_THM_LIMITS, TELEM_OFFSET(TAG_THM_LIMITS)},
+		[10] = {TAG_ASIC_TEMPERATURE, TELEM_OFFSET(TAG_ASIC_TEMPERATURE)},
+		[11] = {TAG_VREG_TEMPERATURE, TELEM_OFFSET(TAG_VREG_TEMPERATURE)},
+		[12] = {TAG_BOARD_TEMPERATURE, TELEM_OFFSET(TAG_BOARD_TEMPERATURE)},
+		[13] = {TAG_AICLK, TELEM_OFFSET(TAG_AICLK)},
+		[14] = {TAG_AXICLK, TELEM_OFFSET(TAG_AXICLK)},
+		[15] = {TAG_ARCCLK, TELEM_OFFSET(TAG_ARCCLK)},
+		[16] = {TAG_L2CPUCLK0, TELEM_OFFSET(TAG_L2CPUCLK0)},
+		[17] = {TAG_L2CPUCLK1, TELEM_OFFSET(TAG_L2CPUCLK1)},
+		[18] = {TAG_L2CPUCLK2, TELEM_OFFSET(TAG_L2CPUCLK2)},
+		[19] = {TAG_L2CPUCLK3, TELEM_OFFSET(TAG_L2CPUCLK3)},
+		[20] = {TAG_ETH_LIVE_STATUS, TELEM_OFFSET(TAG_ETH_LIVE_STATUS)},
+		[21] = {TAG_GDDR_STATUS, TELEM_OFFSET(TAG_GDDR_STATUS)},
+		[22] = {TAG_GDDR_SPEED, TELEM_OFFSET(TAG_GDDR_SPEED)},
+		[23] = {TAG_ETH_FW_VERSION, TELEM_OFFSET(TAG_ETH_FW_VERSION)},
+		[24] = {TAG_GDDR_FW_VERSION, TELEM_OFFSET(TAG_GDDR_FW_VERSION)},
+		[25] = {TAG_DM_APP_FW_VERSION, TELEM_OFFSET(TAG_DM_APP_FW_VERSION)},
+		[26] = {TAG_DM_BL_FW_VERSION, TELEM_OFFSET(TAG_DM_BL_FW_VERSION)},
+		[27] = {TAG_FLASH_BUNDLE_VERSION, TELEM_OFFSET(TAG_FLASH_BUNDLE_VERSION)},
+		[28] = {TAG_CM_FW_VERSION, TELEM_OFFSET(TAG_CM_FW_VERSION)},
+		[29] = {TAG_L2CPU_FW_VERSION, TELEM_OFFSET(TAG_L2CPU_FW_VERSION)},
+		[30] = {TAG_FAN_SPEED, TELEM_OFFSET(TAG_FAN_SPEED)},
+		[31] = {TAG_TIMER_HEARTBEAT, TELEM_OFFSET(TAG_TIMER_HEARTBEAT)},
+		[32] = {TAG_ENABLED_TENSIX_COL, TELEM_OFFSET(TAG_ENABLED_TENSIX_COL)},
+		[33] = {TAG_ENABLED_ETH, TELEM_OFFSET(TAG_ENABLED_ETH)},
+		[34] = {TAG_ENABLED_GDDR, TELEM_OFFSET(TAG_ENABLED_GDDR)},
+		[35] = {TAG_ENABLED_L2CPU, TELEM_OFFSET(TAG_ENABLED_L2CPU)},
+		[36] = {TAG_PCIE_USAGE, TELEM_OFFSET(TAG_PCIE_USAGE)},
+		[37] = {TAG_NOC_TRANSLATION, TELEM_OFFSET(TAG_NOC_TRANSLATION)},
+		[38] = {TAG_FAN_RPM, TELEM_OFFSET(TAG_FAN_RPM)},
+		[39] = {TAG_GDDR_0_1_TEMP, TELEM_OFFSET(TAG_GDDR_0_1_TEMP)},
+		[40] = {TAG_GDDR_2_3_TEMP, TELEM_OFFSET(TAG_GDDR_2_3_TEMP)},
+		[41] = {TAG_GDDR_4_5_TEMP, TELEM_OFFSET(TAG_GDDR_4_5_TEMP)},
+		[42] = {TAG_GDDR_6_7_TEMP, TELEM_OFFSET(TAG_GDDR_6_7_TEMP)},
+		[43] = {TAG_GDDR_0_1_CORR_ERRS, TELEM_OFFSET(TAG_GDDR_0_1_CORR_ERRS)},
+		[44] = {TAG_GDDR_2_3_CORR_ERRS, TELEM_OFFSET(TAG_GDDR_2_3_CORR_ERRS)},
+		[45] = {TAG_GDDR_4_5_CORR_ERRS, TELEM_OFFSET(TAG_GDDR_4_5_CORR_ERRS)},
+		[46] = {TAG_GDDR_6_7_CORR_ERRS, TELEM_OFFSET(TAG_GDDR_6_7_CORR_ERRS)},
+		[47] = {TAG_GDDR_UNCORR_ERRS, TELEM_OFFSET(TAG_GDDR_UNCORR_ERRS)},
+		[48] = {TAG_MAX_GDDR_TEMP, TELEM_OFFSET(TAG_MAX_GDDR_TEMP)},
+		[49] = {TAG_ASIC_LOCATION, TELEM_OFFSET(TAG_ASIC_LOCATION)},
+		[50] = {TAG_BOARD_POWER_LIMIT, TELEM_OFFSET(TAG_BOARD_POWER_LIMIT)},
+		[51] = {TAG_INPUT_POWER, TELEM_OFFSET(TAG_INPUT_POWER)},
+		[52] = {TAG_TELEM_ENUM_COUNT, TELEM_OFFSET(TAG_TELEM_ENUM_COUNT)},
+	},
+};
path: lib/tenstorrent/bh_arc/telemetry.c
user: login: cfriedt
body: cc @DRvader 
created_at: 2025-05-20T19:17:41Z
author_association: NONE
diff_hunk: @@ -39,19 +39,76 @@ struct telemetry_entry {
 struct telemetry_table {
 	uint32_t version;
 	uint32_t entry_count;
-	struct telemetry_entry tag_table[TELEM_ENUM_COUNT];
-	uint32_t telemetry[TELEM_ENUM_COUNT];
+	struct telemetry_entry tag_table[TAG_COUNT];
+	uint32_t telemetry[TAG_COUNT];
 };
 
 /* Global variables */
-static struct telemetry_table telemetry_table;
+static struct telemetry_table telemetry_table = {
+	.tag_table = {
+		[0] = {TAG_BOARD_ID_HIGH, TELEM_OFFSET(TAG_BOARD_ID_HIGH)},
+		[1] = {TAG_BOARD_ID_LOW, TELEM_OFFSET(TAG_BOARD_ID_LOW)},
+		[2] = {TAG_ASIC_ID, TELEM_OFFSET(TAG_ASIC_ID)},
+		[3] = {TAG_HARVESTING_STATE, TELEM_OFFSET(TAG_HARVESTING_STATE)},
+		[4] = {TAG_UPDATE_TELEM_SPEED, TELEM_OFFSET(TAG_UPDATE_TELEM_SPEED)},
+		[5] = {TAG_VCORE, TELEM_OFFSET(TAG_VCORE)},
+		[6] = {TAG_TDP, TELEM_OFFSET(TAG_TDP)},
+		[7] = {TAG_TDC, TELEM_OFFSET(TAG_TDC)},
+		[8] = {TAG_VDD_LIMITS, TELEM_OFFSET(TAG_VDD_LIMITS)},
+		[9] = {TAG_THM_LIMITS, TELEM_OFFSET(TAG_THM_LIMITS)},
+		[10] = {TAG_ASIC_TEMPERATURE, TELEM_OFFSET(TAG_ASIC_TEMPERATURE)},
+		[11] = {TAG_VREG_TEMPERATURE, TELEM_OFFSET(TAG_VREG_TEMPERATURE)},
+		[12] = {TAG_BOARD_TEMPERATURE, TELEM_OFFSET(TAG_BOARD_TEMPERATURE)},
+		[13] = {TAG_AICLK, TELEM_OFFSET(TAG_AICLK)},
+		[14] = {TAG_AXICLK, TELEM_OFFSET(TAG_AXICLK)},
+		[15] = {TAG_ARCCLK, TELEM_OFFSET(TAG_ARCCLK)},
+		[16] = {TAG_L2CPUCLK0, TELEM_OFFSET(TAG_L2CPUCLK0)},
+		[17] = {TAG_L2CPUCLK1, TELEM_OFFSET(TAG_L2CPUCLK1)},
+		[18] = {TAG_L2CPUCLK2, TELEM_OFFSET(TAG_L2CPUCLK2)},
+		[19] = {TAG_L2CPUCLK3, TELEM_OFFSET(TAG_L2CPUCLK3)},
+		[20] = {TAG_ETH_LIVE_STATUS, TELEM_OFFSET(TAG_ETH_LIVE_STATUS)},
+		[21] = {TAG_GDDR_STATUS, TELEM_OFFSET(TAG_GDDR_STATUS)},
+		[22] = {TAG_GDDR_SPEED, TELEM_OFFSET(TAG_GDDR_SPEED)},
+		[23] = {TAG_ETH_FW_VERSION, TELEM_OFFSET(TAG_ETH_FW_VERSION)},
+		[24] = {TAG_GDDR_FW_VERSION, TELEM_OFFSET(TAG_GDDR_FW_VERSION)},
+		[25] = {TAG_DM_APP_FW_VERSION, TELEM_OFFSET(TAG_DM_APP_FW_VERSION)},
+		[26] = {TAG_DM_BL_FW_VERSION, TELEM_OFFSET(TAG_DM_BL_FW_VERSION)},
+		[27] = {TAG_FLASH_BUNDLE_VERSION, TELEM_OFFSET(TAG_FLASH_BUNDLE_VERSION)},
+		[28] = {TAG_CM_FW_VERSION, TELEM_OFFSET(TAG_CM_FW_VERSION)},
+		[29] = {TAG_L2CPU_FW_VERSION, TELEM_OFFSET(TAG_L2CPU_FW_VERSION)},
+		[30] = {TAG_FAN_SPEED, TELEM_OFFSET(TAG_FAN_SPEED)},
+		[31] = {TAG_TIMER_HEARTBEAT, TELEM_OFFSET(TAG_TIMER_HEARTBEAT)},
+		[32] = {TAG_ENABLED_TENSIX_COL, TELEM_OFFSET(TAG_ENABLED_TENSIX_COL)},
+		[33] = {TAG_ENABLED_ETH, TELEM_OFFSET(TAG_ENABLED_ETH)},
+		[34] = {TAG_ENABLED_GDDR, TELEM_OFFSET(TAG_ENABLED_GDDR)},
+		[35] = {TAG_ENABLED_L2CPU, TELEM_OFFSET(TAG_ENABLED_L2CPU)},
+		[36] = {TAG_PCIE_USAGE, TELEM_OFFSET(TAG_PCIE_USAGE)},
+		[37] = {TAG_NOC_TRANSLATION, TELEM_OFFSET(TAG_NOC_TRANSLATION)},
+		[38] = {TAG_FAN_RPM, TELEM_OFFSET(TAG_FAN_RPM)},
+		[39] = {TAG_GDDR_0_1_TEMP, TELEM_OFFSET(TAG_GDDR_0_1_TEMP)},
+		[40] = {TAG_GDDR_2_3_TEMP, TELEM_OFFSET(TAG_GDDR_2_3_TEMP)},
+		[41] = {TAG_GDDR_4_5_TEMP, TELEM_OFFSET(TAG_GDDR_4_5_TEMP)},
+		[42] = {TAG_GDDR_6_7_TEMP, TELEM_OFFSET(TAG_GDDR_6_7_TEMP)},
+		[43] = {TAG_GDDR_0_1_CORR_ERRS, TELEM_OFFSET(TAG_GDDR_0_1_CORR_ERRS)},
+		[44] = {TAG_GDDR_2_3_CORR_ERRS, TELEM_OFFSET(TAG_GDDR_2_3_CORR_ERRS)},
+		[45] = {TAG_GDDR_4_5_CORR_ERRS, TELEM_OFFSET(TAG_GDDR_4_5_CORR_ERRS)},
+		[46] = {TAG_GDDR_6_7_CORR_ERRS, TELEM_OFFSET(TAG_GDDR_6_7_CORR_ERRS)},
+		[47] = {TAG_GDDR_UNCORR_ERRS, TELEM_OFFSET(TAG_GDDR_UNCORR_ERRS)},
+		[48] = {TAG_MAX_GDDR_TEMP, TELEM_OFFSET(TAG_MAX_GDDR_TEMP)},
+		[49] = {TAG_ASIC_LOCATION, TELEM_OFFSET(TAG_ASIC_LOCATION)},
+		[50] = {TAG_BOARD_POWER_LIMIT, TELEM_OFFSET(TAG_BOARD_POWER_LIMIT)},
+		[51] = {TAG_INPUT_POWER, TELEM_OFFSET(TAG_INPUT_POWER)},
+		[52] = {TAG_TELEM_ENUM_COUNT, TELEM_OFFSET(TAG_TELEM_ENUM_COUNT)},
+	},
+};
path: lib/tenstorrent/bh_arc/telemetry.c
user: login: TTDRosen
body: The table, has the extra level of indirection to support explicit field deletion. And fields have already been removed so the mapping is slightly offset. I know that's the case because some code did assume the 1:1 mapping and broke when the fields were removed 😆 
created_at: 2025-05-20T19:23:45Z
author_association: NONE

PR comments:
user: login: cfriedt
created_at: 2025-05-20T05:08:45Z
body: This change looks fine to me - I think the table is maybe wasting space though, not sure.
author_association: NONE
user: login: danieldegrasse
created_at: 2025-05-20T18:25:27Z
body: > This change looks fine to me - I think the table is maybe wasting space though, not sure.

I *think* tt-smi relies on the existence of this table: https://github.com/tenstorrent/luwen/blob/a8357d0d2a747c9f0596401bf37ec81fa13ae1b2/crates/luwen-if/src/chip/blackhole.rs#L702. @DRvader, can you confirm if we could drop the table? We could also implement some sort of migration to drop the table long term
author_association: CONTRIBUTOR
user: login: cfriedt
created_at: 2025-05-20T19:17:42Z
body: > We could also implement some sort of migration to drop the table long term

That would be great @DRvader.

Specifically one of the reasons why RPC is kind of ideal for telemetry is to avoid bespoke artifacts / tech debt like this.
author_association: NONE
user: login: TTDRosen
created_at: 2025-05-20T19:34:18Z
body: Doesn't this break the tags? BOARD_ID_HIGH was one previously (because of a removed tag, and now it's zero again)? Am I reading the code wrong?
author_association: NONE
user: login: afongTT
created_at: 2025-05-20T20:22:37Z
body: Requesting to revert this in #250 to restore the layer of indirection we had for tag and telemetry.
author_association: CONTRIBUTOR
user: login: afongTT
created_at: 2025-05-20T20:29:09Z
body: > Specifically one of the reasons why RPC is kind of ideal for telemetry is to avoid bespoke artifacts / tech debt like this.

Could you link to an example of something like this? We can keep it in mind for future projects / features.
author_association: CONTRIBUTOR
user: login: cfriedt
created_at: 2025-05-20T21:26:13Z
body: > Doesn't this break the tags? BOARD_ID_HIGH was one previously (because of a removed tag, and now it's zero again)? Am I reading the code wrong?

TAG_BOARD_ID_HIGH := 1 [here](https://github.com/tenstorrent/tt-zephyr-platforms/blob/61a57b4ecb92e8b302e56938d995642aaf3f5ce5/lib/tenstorrent/bh_arc/telemetry.h#L18) which is unchanged before and after this commit.

The zero'th entry in the telemetry table is `[0] = { 1, 1 }` [here](https://github.com/tenstorrent/tt-zephyr-platforms/blob/61a57b4ecb92e8b302e56938d995642aaf3f5ce5/lib/tenstorrent/bh_arc/telemetry.c#L49) which is exactly the same as it was [before this change](https://github.com/tenstorrent/tt-zephyr-platforms/blob/c5a864e647fde9b6cade688eaf231b99564ddcf8/lib/tenstorrent/bh_arc/telemetry.c#L273).

And if I'm not mistaken, the entire table follows the pattern of `[n] = {n+1, n+1}`.

Ideally, we could just change luwen to simply subtract 1 from the tag to determine the table index (the offset in bytes is of course 4 * the index).
author_association: NONE
user: login: cfriedt
created_at: 2025-05-20T21:34:06Z
body: > > Specifically one of the reasons why RPC is kind of ideal for telemetry is to avoid bespoke artifacts / tech debt like this.
> 
> Could you link to an example of something like this? We can keep it in mind for future projects / features.

First step would be using a straight linear translation.

For examples of RPC, see

https://docs.zephyrproject.org/latest/samples/modules/nanopb/README.html#nanopb
https://github.com/zephyrproject-rtos/zephyr/tree/main/samples/modules/nanopb

https://docs.zephyrproject.org/latest/samples/modules/thrift/hello/README.html#thrift-hello
https://github.com/zephyrproject-rtos/zephyr/tree/main/samples/modules/thrift

There is also CBOR, but I can't seem to find a link to a sample.e
author_association: NONE