This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

AM2634-Q1: Issue Reading Full 7 Bytes from DS1307 RTC Using I2C in Interrupt Mode on AM2634

Part Number: AM2634-Q1
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!