Other Parts Discussed in Thread: AM2634
Tool/software:
Hi Team,
I'm working with the AM2634 and interfacing it with a DS1307 RTC over I2C. I'm using the I2C driver in interrupt mode with a callback function.
Using the API:
void DS1307_writeTime(uint8_t hr, uint8_t min, uint8_t sec, uint8_t day, uint8_t date, uint8_t month, uint8_t year)
I'm successfully able to set the time on the RTC.
However, when I try to read the time using another API:
void ReadDateTime(void)
I attempt to read all 7 bytes starting from register address 0x00
(which corresponds to the seconds register). But in this case:
1. The output data is garbage or invalid.
2. The I2C interrupt is not triggered during the read operation.
On the other hand, I have another function:
void ReadSec(void)
In which I read the data one byte at a time by first writing the register address (e.g., 0x00
, 0x01
, 0x02
, etc.), and then reading a single byte. This approach works reliably, and the correct values are returned from the RTC.
My Question:
Why does reading a full 7-byte block starting from 0x00 in a single transaction fail (i.e., returns garbage and no interrupt), even though the AM2634 I2C driver supports repeated start conditions? Could this be a limitation or bug in the driver when using interrupt mode for combined write-read transfers?
Any guidance or suggestions would be appreciated.
Also attaching my code below please have a look
/* * DS1307.c * * Created on: Apr 20, 2025 * Author: Swati */ #include <drivers/i2c.h> #include <kernel/dpl/ClockP.h> #include <stdint.h> #include <string.h> #include "ti_drivers_config.h" #define DS1307_I2C_ADDR (0x68) #define DS1307_REG_SECONDS (0x00) #define DS1307_REG_MINUTES (0x01) #define DS1307_REG_HOURS (0x02) #define DS1307_REG_DAY (0x03) #define DS1307_REG_DATE (0x04) #define DS1307_REG_MONTH (0x05) #define DS1307_REG_YEAR (0x06) #define I2C_READ_LEN (7U) #define I2C_ADDR_START 0x03 #define I2C_ADDR_END 0x77 #define I2C_SCAN_LEN 1 extern I2C_Handle gI2cHandle[]; static uint8_t hr, min, sec, day, date, month, year; uint8_t bcdToDec(uint8_t val) { return ((val / 16 * 10) + (val % 16)); } uint8_t decToBcd(uint8_t val) { return ((val / 10 * 16) + (val % 10)); } void ERTC_CallBack(I2C_Transaction *msg, int32_t transferStatus) { DebugP_log("transferStatus %d\n", transferStatus); if (transferStatus == SystemP_SUCCESS) { DebugP_log("I2C transfer successful.\n"); } else { DebugP_log("I2C transfer failed.\n"); } } void DS1307_writeTime(uint8_t hr, uint8_t min, uint8_t sec, uint8_t day, uint8_t date, uint8_t month, uint8_t year) { I2C_Transaction i2cTransaction = {0U}; uint8_t txBuffer[8]; I2C_Handle i2cHandle; i2cHandle = gI2cHandle[CONFIG_I2C0]; int32_t transferStatus; I2C_Transaction_init(&i2cTransaction); txBuffer[0] = DS1307_REG_SECONDS; txBuffer[1] = decToBcd(sec); txBuffer[2] = decToBcd(min); txBuffer[3] = decToBcd(hr); txBuffer[4] = decToBcd(day); txBuffer[5] = decToBcd(date); txBuffer[6] = decToBcd(month); txBuffer[7] = decToBcd(year); DebugP_log("Writing to DS1307: %02x %02x %02x %02x %02x %02x %02x\n", txBuffer[1], txBuffer[2], txBuffer[3], txBuffer[4], txBuffer[5], txBuffer[6], txBuffer[7]); i2cTransaction.writeBuf = txBuffer; i2cTransaction.writeCount = 8; i2cTransaction.readBuf = NULL; i2cTransaction.readCount = 0; i2cTransaction.targetAddress = (DS1307_I2C_ADDR); transferStatus = I2C_transfer(i2cHandle, &i2cTransaction); if (transferStatus == SystemP_SUCCESS) { DebugP_log("DS1307 write successful\n"); } else { DebugP_log("DS1307 write failed\n"); DebugP_log("Target Address: 0x%x, Wrote %d bytes\n", i2cTransaction.targetAddress, i2cTransaction.writeCount); } } void i2c_read_error_handler(uint8_t addr, int32_t status) { switch (status) { case I2C_STS_ERR: DebugP_logError("[I2C] Addr 0x%02X: Generic error occurred", addr); break; case I2C_STS_ERR_TIMEOUT: DebugP_logError("[I2C] Addr 0x%02X: Timeout error occurred", addr); break; case I2C_STS_ERR_NO_ACK: DebugP_logError("[I2C] Addr 0x%02X: No ACK received", addr); break; case I2C_STS_ERR_ARBITRATION_LOST: DebugP_logError("[I2C] Addr 0x%02X: Arbitration lost", addr); break; case I2C_STS_ERR_BUS_BUSY: DebugP_logError("[I2C] Addr 0x%02X: Bus busy error", addr); break; default: DebugP_logError("[I2C] Addr 0x%02X: Unknown error %d", addr, status); break; } } void ReadDateTime(void) { uint8_t rxBuffer[7]; uint8_t txBuffer[1] = {0x00}; // Start reading from register 0x00 (Seconds) I2C_Handle i2cHandle = gI2cHandle[CONFIG_I2C0]; I2C_Transaction i2cTransaction; int32_t transferStatus; I2C_Transaction_init(&i2cTransaction); i2cTransaction.writeBuf = txBuffer; i2cTransaction.writeCount = 1; i2cTransaction.readBuf = rxBuffer; i2cTransaction.readCount = 7; // Read all registers in one shot i2cTransaction.targetAddress = 0x68; transferStatus = I2C_transfer(i2cHandle, &i2cTransaction); if (transferStatus == I2C_STS_SUCCESS) { sec = bcdToDec(rxBuffer[0] & 0x7F); min = bcdToDec(rxBuffer[1]); hr = bcdToDec(rxBuffer[2]); day = bcdToDec(rxBuffer[3]); date = bcdToDec(rxBuffer[4]); month = bcdToDec(rxBuffer[5]); year = bcdToDec(rxBuffer[6]); DebugP_log("Time from DS1307: %02d:%02d:%02d\n", hr, min, sec); DebugP_log("Date from DS1307: %02d/%02d/%04d\n", date, month, 2000 + year); } else { i2c_read_error_handler(i2cTransaction.targetAddress, i2cTransaction.status); } } void ReadSec(void) { uint8_t secrxBuffer[1]; uint8_t sectxBuffer[I2C_SCAN_LEN] = {0x00}; I2C_Handle i2cHandle; I2C_Transaction i2cTransaction; int32_t transferStatus; i2cHandle = gI2cHandle[CONFIG_I2C0]; DebugP_log("[I2C] Scanning for I2C devices...\r\n"); I2C_Transaction_init(&i2cTransaction); i2cTransaction.writeBuf = sectxBuffer; i2cTransaction.writeCount = 1; i2cTransaction.readBuf = secrxBuffer; i2cTransaction.readCount = 1; i2cTransaction.targetAddress = 0x68; transferStatus = I2C_transfer(i2cHandle, &i2cTransaction); if (transferStatus == I2C_STS_SUCCESS) { sec = bcdToDec(secrxBuffer[0] & 0x7F); DebugP_log("sec from DS1307: %02d\n", sec); ClockP_usleep(10000); uint8_t minrxBuffer[1]; uint8_t mintxBuffer[I2C_SCAN_LEN] = {0x01}; I2C_Transaction_init(&i2cTransaction); i2cTransaction.writeBuf = mintxBuffer; i2cTransaction.writeCount = 1; i2cTransaction.readBuf = minrxBuffer; i2cTransaction.readCount = 1; i2cTransaction.targetAddress = 0x68; transferStatus = I2C_transfer(i2cHandle, &i2cTransaction); if (transferStatus == I2C_STS_SUCCESS) { min = bcdToDec(minrxBuffer[0]); DebugP_log("min from DS1307: %02d\n", min); uint8_t hrrxBuffer[1]; uint8_t hrtxBuffer[I2C_SCAN_LEN] = {0x02}; I2C_Transaction_init(&i2cTransaction); i2cTransaction.writeBuf = hrtxBuffer; i2cTransaction.writeCount = 1; i2cTransaction.readBuf = hrrxBuffer; i2cTransaction.readCount = 1; i2cTransaction.targetAddress = 0x68; transferStatus = I2C_transfer(i2cHandle, &i2cTransaction); if (transferStatus == I2C_STS_SUCCESS) { hr = bcdToDec(hrrxBuffer[0]); DebugP_log("hr from DS1307: %02d\n", hr); } } DebugP_log("Date from DS1307: %02d:%02d:%04d\n", date, month, (2000 + year)); } else { i2c_read_error_handler(i2cTransaction.targetAddress, i2cTransaction.status); } }
Thank you!