This is an automated email from the ASF dual-hosted git repository. acassis pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 3cc65d5d35e779d64acc8a2a0f47fbe65b305c61 Author: Michal Lenc <[email protected]> AuthorDate: Tue May 28 11:01:40 2024 +0200 timers/mcp794xx: add option to digital trimming MCP794XX supports digital trimming that periodically adds or subtracts clock cycles, resulting in small adjustments in the internal timing. This way inaccuracies of clock source can be compensated. This commit adds option to set the trimming register for MCP794XX. Signed-off-by: Michal Lenc <[email protected]> --- drivers/timers/mcp794xx.c | 107 ++++++++++++++++++++++++++++++++++++++-- include/nuttx/timers/mcp794xx.h | 24 +++++++++ 2 files changed, 128 insertions(+), 3 deletions(-) diff --git a/drivers/timers/mcp794xx.c b/drivers/timers/mcp794xx.c index 54953a0c73..2734c87f5a 100644 --- a/drivers/timers/mcp794xx.c +++ b/drivers/timers/mcp794xx.c @@ -77,6 +77,7 @@ struct mcp794xx_dev_s { FAR struct i2c_master_s *i2c; /* Contained reference to the I2C bus driver. */ uint8_t addr; /* The I2C device address. */ + bool coarse_trim; /* Coarse trim mode */ }; /**************************************************************************** @@ -182,6 +183,105 @@ static int rtc_bcd2bin(uint8_t value) * Public Functions ****************************************************************************/ +/**************************************************************************** + * Name: mcp794xx_rtc_set_trim + * + * Description: + * Sets the digital trimming to correct for inaccuracies of clock source. + * Digital trimming consists of the MCP794XX periodically adding or + * subtracting clock cycles, resulting in small adjustments in the internal + * timing. + * + * Input Parameters: + * trim_val - Calculated trimming value, refer to MCP794XX reference + * manual. + * rtc_slow - True indicates RTC is behind real clock, false otherwise. + * This has to be set to ensure correct trimming direction. + * coarse_mode - MCP794XX allows coarse mode that trims every second + * instead of every minute. + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ****************************************************************************/ + +int mcp794xx_rtc_set_trim(uint8_t trim_val, bool rtc_slow, bool coarse_mode) +{ + struct i2c_msg_s msg[2]; + uint8_t buffer[2]; + uint8_t address; + uint8_t ctrl; + int ret; + + if (g_mcp794xx.coarse_trim != coarse_mode) + { + address = MCP794XX_REG_CONTROL; + msg[0].frequency = CONFIG_MCP794XX_I2C_FREQUENCY; + msg[0].addr = g_mcp794xx.addr; + msg[0].flags = I2C_M_NOSTOP; + msg[0].buffer = &address; + msg[0].length = 1; + + msg[1].frequency = CONFIG_MCP794XX_I2C_FREQUENCY; + msg[1].addr = g_mcp794xx.addr; + msg[1].flags = I2C_M_READ; + msg[1].buffer = &ctrl; + msg[1].length = 1; + + ret = I2C_TRANSFER(g_mcp794xx.i2c, msg, 2); + if (ret < 0) + { + rtcerr("ERROR: I2C_TRANSFER failed: %d\n", ret); + return ret; + } + + ctrl &= ~MCP794XX_CONTROL_CRSTRIM; + if (coarse_mode) + { + ctrl |= MCP794XX_CONTROL_CRSTRIM; + } + + buffer[0] = MCP794XX_REG_CONTROL; + buffer[1] = ctrl; + msg[0].frequency = CONFIG_MCP794XX_I2C_FREQUENCY; + msg[0].addr = g_mcp794xx.addr; + msg[0].flags = 0; + msg[0].buffer = buffer; + msg[0].length = 2; + + ret = I2C_TRANSFER(g_mcp794xx.i2c, msg, 1); + if (ret < 0) + { + rtcerr("ERROR: I2C_TRANSFER failed: %d\n", ret); + return ret; + } + + g_mcp794xx.coarse_trim = coarse_mode; + } + + buffer[0] = MCP794XX_REG_OSCTRIM; + buffer[1] = trim_val & 0x7; + if (rtc_slow) + { + buffer[1] |= MCP794XX_OSCTRIM_SIGN; + } + + msg[0].frequency = CONFIG_MCP794XX_I2C_FREQUENCY; + msg[0].addr = g_mcp794xx.addr; + msg[0].flags = 0; + msg[0].buffer = buffer; + msg[0].length = 2; + + ret = I2C_TRANSFER(g_mcp794xx.i2c, msg, 1); + if (ret < 0) + { + rtcerr("ERROR: I2C_TRANSFER failed: %d\n", ret); + return ret; + } + + return OK; +} + /**************************************************************************** * Name: mcp794xx_rtc_initialize * @@ -211,9 +311,10 @@ int mcp794xx_rtc_initialize(FAR struct i2c_master_s *i2c, uint8_t addr) { /* Remember the i2c device and claim that the RTC is enabled */ - g_mcp794xx.i2c = i2c; - g_mcp794xx.addr = addr; - g_rtc_enabled = true; + g_mcp794xx.i2c = i2c; + g_mcp794xx.addr = addr; + g_mcp794xx.coarse_trim = false; + g_rtc_enabled = true; return OK; } diff --git a/include/nuttx/timers/mcp794xx.h b/include/nuttx/timers/mcp794xx.h index 7b8abf1f9b..d75c63356c 100644 --- a/include/nuttx/timers/mcp794xx.h +++ b/include/nuttx/timers/mcp794xx.h @@ -41,6 +41,30 @@ extern "C" #define EXTERN extern #endif +/**************************************************************************** + * Name: mcp794xx_rtc_set_trim + * + * Description: + * Sets the digital trimming to correct for inaccuracies of clock source. + * Digital trimming consists of the MCP794XX periodically adding or + * subtracting clock cycles, resulting in small adjustments in the internal + * timing. + * + * Input Parameters: + * trim_val - Calculated trimming value, refer to MCP794XX reference + * manual. + * rtc_slow - True indicates RTC is behind real clock, false otherwise. + * This has to be set to ensure correct trimming direction. + * coarse_mode - MCP794XX allows coarse mode that trims every second + * instead of every minute. + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ****************************************************************************/ + +int mcp794xx_rtc_set_trim(uint8_t trim_val, bool rtc_slow, bool coarse_mode); + /**************************************************************************** * Name: mcp794xx_rtc_initialize *
