From dfd583180f96e5394b6d77264bd2e93000168e9a Mon Sep 17 00:00:00 2001 From: Christos Gentsos <christos.gentsos@cern.ch> Date: Tue, 12 Oct 2021 16:31:23 +0200 Subject: [PATCH] I2C: Clear error bit on bus error, add STATUS_BYTE and STATUS_CML When a bus error happened, the I2C peripheral's error bit remained set. This caused it to respond erroneously in future transactions. Now, when a bus error occurs, we're clearing the error bit and setting the error flags in the STATUS_BYTE and STATUS_CML PMBus registers. After the user reads those registers (using commands 0x78 and 0x7E), their error flags are cleared. --- bootloader/src/main.c | 2 ++ common/src/i2c_slave.c | 16 ++++++++++-- main_fw/src/i2c_impl.c | 59 ++++++++++++++++++++++++++++-------------- main_fw/src/main.c | 2 ++ 4 files changed, 57 insertions(+), 22 deletions(-) diff --git a/bootloader/src/main.c b/bootloader/src/main.c index d2a0944..253e0f9 100644 --- a/bootloader/src/main.c +++ b/bootloader/src/main.c @@ -12,6 +12,8 @@ extern cmd_space_t cmds; //! Our custom commmands structure extern cmd_space_t ext_cmds; +uint8_t status_b; + int main(void) { system_init(); diff --git a/common/src/i2c_slave.c b/common/src/i2c_slave.c index ef1eb75..3f07208 100644 --- a/common/src/i2c_slave.c +++ b/common/src/i2c_slave.c @@ -36,6 +36,9 @@ static uint16_t added_tx_pec __xMR = 0; static uint16_t sent_checksum __xMR = 0; static uint8_t tx_tmp; +extern uint8_t status_b; +uint8_t status_cml; + int16_t in_addr_space(cmd_space_t *addr_space, uint8_t addr) { for (uint8_t i = 0; i < addr_space->n_cmds; ++i) @@ -179,8 +182,11 @@ static void __xMR I2C_rx_complete(const struct i2c_s_async_descriptor *const des send_ack(descr); if (cmds->cmds[cmd_index].w_callback) cmds->cmds[cmd_index].w_callback(); - } else + } else { + status_b |= 0x01; + status_cml = 0x20; // PEC error send_nack(descr); + } set_cmd(descr, 2); rx_state = CMD; break; @@ -190,8 +196,11 @@ static void __xMR I2C_rx_complete(const struct i2c_s_async_descriptor *const des send_ack(descr); if (ext_cmds->cmds[cmd_index].w_callback) ext_cmds->cmds[cmd_index].w_callback(); - } else + } else { + status_b |= 0x01; + status_cml = 0x20; // PEC error send_nack(descr); + } set_cmd(descr, 2); rx_state = CMD; break; @@ -280,6 +289,9 @@ static void __xMR I2C_tx_complete(const struct i2c_s_async_descriptor *const des /*! we get here when something bad has happened */ static void __xMR I2C_error(const struct i2c_s_async_descriptor *const descr) { + status_b |= 0x01; + status_cml = 0x02; // Other comm fault + hri_sercomi2cs_clear_INTFLAG_ERROR_bit(descr->device.hw); set_cmd(descr, 2); } diff --git a/main_fw/src/i2c_impl.c b/main_fw/src/i2c_impl.c index 08a9947..b3e6caf 100644 --- a/main_fw/src/i2c_impl.c +++ b/main_fw/src/i2c_impl.c @@ -32,6 +32,11 @@ extern uint16_t use_pec __xMR; uint8_t use_pec_tmp; void set_pec(); +void read_status_b(); +void read_status_cml(); +extern uint8_t status_b; +extern uint8_t status_cml; + void accvolt(); void acccurr(); void accpowr(); @@ -85,6 +90,8 @@ extern uint16_t fan_ppr[3] __xMR; static const int8_t cmd_data_lengths[] = { 1, // 0x00 -1, // 0x1A + 1, // 0x78 + 1, // 0x7E 2, // 0x8B 2, // 0x8C 2, // 0x8D @@ -112,26 +119,28 @@ static int8_t cmd_data_length_query = -1; static cmd_t cmds_cmds[] = (cmd_t[]){ {0x00, (int8_t *)&cmd_data_lengths[0], (uint8_t *)&page_tmp, (fp_t)NULL, &page_chk, (fp_t)NULL, QUERY_WR | QUERY_RD | QUERY_FMT_8B, 0}, {0x1A, (int8_t *)&cmd_data_length_query, (uint8_t *)&query_r, (fp_t)NULL, &query_prp, (fp_t)NULL, QUERY_SUP, 1}, - {0x8B, (int8_t *)&cmd_data_lengths[2], (uint8_t *)&curpage_volt, &accvolt, (fp_t)NULL, (fp_t)NULL, QUERY_RD | QUERY_FMT_LIN, 0}, - {0x8C, (int8_t *)&cmd_data_lengths[3], (uint8_t *)&curpage_curr, &acccurr, (fp_t)NULL, (fp_t)NULL, QUERY_RD | QUERY_FMT_LIN, 0}, - {0x8D, (int8_t *)&cmd_data_lengths[4], (uint8_t *)&temps_lin[0], (fp_t)NULL, (fp_t)NULL, (fp_t)NULL, QUERY_RD | QUERY_FMT_LIN, 0}, - {0x8E, (int8_t *)&cmd_data_lengths[5], (uint8_t *)&temps_lin[1], (fp_t)NULL, (fp_t)NULL, (fp_t)NULL, QUERY_RD | QUERY_FMT_LIN, 0}, - {0x8F, (int8_t *)&cmd_data_lengths[6], (uint8_t *)&temps_lin[2], (fp_t)NULL, (fp_t)NULL, (fp_t)NULL, QUERY_RD | QUERY_FMT_LIN, 0}, - {0x90, (int8_t *)&cmd_data_lengths[7], (uint8_t *)&frpms_lin[0], (fp_t)NULL, (fp_t)NULL, (fp_t)NULL, QUERY_RD | QUERY_FMT_LIN, 0}, - {0x91, (int8_t *)&cmd_data_lengths[8], (uint8_t *)&frpms_lin[1], (fp_t)NULL, (fp_t)NULL, (fp_t)NULL, QUERY_RD | QUERY_FMT_LIN, 0}, - {0x92, (int8_t *)&cmd_data_lengths[9], (uint8_t *)&frpms_lin[2], (fp_t)NULL, (fp_t)NULL, (fp_t)NULL, QUERY_RD | QUERY_FMT_LIN, 0}, - {0x96, (int8_t *)&cmd_data_lengths[10], (uint8_t *)&curpage_powr, &accpowr, (fp_t)NULL, (fp_t)NULL, QUERY_RD | QUERY_FMT_LIN, 0}, - {0x99, (int8_t *)&cmd_data_lengths[11], (uint8_t *)&MFR_ID, (fp_t)NULL, (fp_t)NULL, (fp_t)NULL, QUERY_RD | QUERY_FMT_NAN, 0}, - {0x9A, (int8_t *)&cmd_data_lengths[12], (uint8_t *)&MFR_MDL, (fp_t)NULL, (fp_t)NULL, (fp_t)NULL, QUERY_RD | QUERY_FMT_NAN, 0}, - {0x9B, (int8_t *)&cmd_data_lengths[13], (uint8_t *)&MFR_REV, (fp_t)NULL, (fp_t)NULL, (fp_t)NULL, QUERY_RD | QUERY_FMT_NAN, 0}, - {0x9C, (int8_t *)&cmd_data_lengths[14], (uint8_t *)&MFR_LOC, (fp_t)NULL, (fp_t)NULL, (fp_t)NULL, QUERY_RD | QUERY_FMT_NAN, 0}, - {0x9D, (int8_t *)&cmd_data_lengths[15], (uint8_t *)&MFR_DAT, (fp_t)NULL, (fp_t)NULL, (fp_t)NULL, QUERY_RD | QUERY_FMT_NAN, 0}, - {0x9E, (int8_t *)&cmd_data_lengths[16], (uint8_t *)&MFR_SER, (fp_t)NULL, (fp_t)NULL, (fp_t)NULL, QUERY_RD | QUERY_FMT_NAN, 0}, - {0x3A, (int8_t *)&cmd_data_lengths[17], (uint8_t *)&fan_config_1_2, (fp_t)NULL, &fan_config, (fp_t)NULL, QUERY_WR | QUERY_FMT_NAN, 0}, - {0x3B, (int8_t *)&cmd_data_lengths[18], (uint8_t *)&setfrpms_lin[0], (fp_t)NULL, &set_frpms, (fp_t)NULL, QUERY_WR | QUERY_FMT_LIN, 0}, - {0x3C, (int8_t *)&cmd_data_lengths[19], (uint8_t *)&setfrpms_lin[1], (fp_t)NULL, &set_frpms, (fp_t)NULL, QUERY_WR | QUERY_FMT_LIN, 0}, - {0x3D, (int8_t *)&cmd_data_lengths[20], (uint8_t *)&fan_config_3_4, (fp_t)NULL, &fan_config, (fp_t)NULL, QUERY_WR | QUERY_FMT_NAN, 0}, - {0x3E, (int8_t *)&cmd_data_lengths[21], (uint8_t *)&setfrpms_lin[2], (fp_t)NULL, &set_frpms, (fp_t)NULL, QUERY_WR | QUERY_FMT_LIN, 0}}; + {0x78, (int8_t *)&cmd_data_lengths[2], (uint8_t *)&status_b, (fp_t)NULL, (fp_t)NULL, &read_status_b, QUERY_RD, 0}, + {0x7E, (int8_t *)&cmd_data_lengths[3], (uint8_t *)&status_cml, (fp_t)NULL, (fp_t)NULL, &read_status_cml, QUERY_RD, 0}, + {0x8B, (int8_t *)&cmd_data_lengths[4], (uint8_t *)&curpage_volt, &accvolt, (fp_t)NULL, (fp_t)NULL, QUERY_RD | QUERY_FMT_LIN, 0}, + {0x8C, (int8_t *)&cmd_data_lengths[5], (uint8_t *)&curpage_curr, &acccurr, (fp_t)NULL, (fp_t)NULL, QUERY_RD | QUERY_FMT_LIN, 0}, + {0x8D, (int8_t *)&cmd_data_lengths[6], (uint8_t *)&temps_lin[0], (fp_t)NULL, (fp_t)NULL, (fp_t)NULL, QUERY_RD | QUERY_FMT_LIN, 0}, + {0x8E, (int8_t *)&cmd_data_lengths[7], (uint8_t *)&temps_lin[1], (fp_t)NULL, (fp_t)NULL, (fp_t)NULL, QUERY_RD | QUERY_FMT_LIN, 0}, + {0x8F, (int8_t *)&cmd_data_lengths[8], (uint8_t *)&temps_lin[2], (fp_t)NULL, (fp_t)NULL, (fp_t)NULL, QUERY_RD | QUERY_FMT_LIN, 0}, + {0x90, (int8_t *)&cmd_data_lengths[9], (uint8_t *)&frpms_lin[0], (fp_t)NULL, (fp_t)NULL, (fp_t)NULL, QUERY_RD | QUERY_FMT_LIN, 0}, + {0x91, (int8_t *)&cmd_data_lengths[10], (uint8_t *)&frpms_lin[1], (fp_t)NULL, (fp_t)NULL, (fp_t)NULL, QUERY_RD | QUERY_FMT_LIN, 0}, + {0x92, (int8_t *)&cmd_data_lengths[11], (uint8_t *)&frpms_lin[2], (fp_t)NULL, (fp_t)NULL, (fp_t)NULL, QUERY_RD | QUERY_FMT_LIN, 0}, + {0x96, (int8_t *)&cmd_data_lengths[12], (uint8_t *)&curpage_powr, &accpowr, (fp_t)NULL, (fp_t)NULL, QUERY_RD | QUERY_FMT_LIN, 0}, + {0x99, (int8_t *)&cmd_data_lengths[13], (uint8_t *)&MFR_ID, (fp_t)NULL, (fp_t)NULL, (fp_t)NULL, QUERY_RD | QUERY_FMT_NAN, 0}, + {0x9A, (int8_t *)&cmd_data_lengths[14], (uint8_t *)&MFR_MDL, (fp_t)NULL, (fp_t)NULL, (fp_t)NULL, QUERY_RD | QUERY_FMT_NAN, 0}, + {0x9B, (int8_t *)&cmd_data_lengths[15], (uint8_t *)&MFR_REV, (fp_t)NULL, (fp_t)NULL, (fp_t)NULL, QUERY_RD | QUERY_FMT_NAN, 0}, + {0x9C, (int8_t *)&cmd_data_lengths[16], (uint8_t *)&MFR_LOC, (fp_t)NULL, (fp_t)NULL, (fp_t)NULL, QUERY_RD | QUERY_FMT_NAN, 0}, + {0x9D, (int8_t *)&cmd_data_lengths[17], (uint8_t *)&MFR_DAT, (fp_t)NULL, (fp_t)NULL, (fp_t)NULL, QUERY_RD | QUERY_FMT_NAN, 0}, + {0x9E, (int8_t *)&cmd_data_lengths[18], (uint8_t *)&MFR_SER, (fp_t)NULL, (fp_t)NULL, (fp_t)NULL, QUERY_RD | QUERY_FMT_NAN, 0}, + {0x3A, (int8_t *)&cmd_data_lengths[19], (uint8_t *)&fan_config_1_2, (fp_t)NULL, &fan_config, (fp_t)NULL, QUERY_WR | QUERY_FMT_NAN, 0}, + {0x3B, (int8_t *)&cmd_data_lengths[20], (uint8_t *)&setfrpms_lin[0], (fp_t)NULL, &set_frpms, (fp_t)NULL, QUERY_WR | QUERY_FMT_LIN, 0}, + {0x3C, (int8_t *)&cmd_data_lengths[21], (uint8_t *)&setfrpms_lin[1], (fp_t)NULL, &set_frpms, (fp_t)NULL, QUERY_WR | QUERY_FMT_LIN, 0}, + {0x3D, (int8_t *)&cmd_data_lengths[22], (uint8_t *)&fan_config_3_4, (fp_t)NULL, &fan_config, (fp_t)NULL, QUERY_WR | QUERY_FMT_NAN, 0}, + {0x3E, (int8_t *)&cmd_data_lengths[23], (uint8_t *)&setfrpms_lin[2], (fp_t)NULL, &set_frpms, (fp_t)NULL, QUERY_WR | QUERY_FMT_LIN, 0}}; cmd_space_t cmds = { sizeof(cmds_cmds)/sizeof(cmd_t), @@ -239,6 +248,16 @@ void __xMR set_pec() use_pec = use_pec_tmp; } +void read_status_b() +{ + status_b &= 0xFE; +} + +void read_status_cml() +{ + status_cml = 0; +} + #if defined(MMFANT) || defined(MMPROT) void __xMR fan_config() diff --git a/main_fw/src/main.c b/main_fw/src/main.c index 46bb4d3..9fff074 100644 --- a/main_fw/src/main.c +++ b/main_fw/src/main.c @@ -127,6 +127,8 @@ float temps[3]; float volts[4]; float currs[3]; +uint8_t status_b; + uint16_t trig_adc_next_second __xMR = 0; #if defined(MMFANT) || defined(MMPROT) -- GitLab