Apollo3 I2C Command Completion Issue: STATUS Register Not Indicating Idle

Hello SparkFun Forum,

I am working with the Apollo3 microcontroller and encountering an issue where both IDLEST and CMDACT bits in the IOM0_STATUS register are not behaving as expected after I/O operations. The IDLEST bit should indicate that the I/O state machine is idle, and CMDACT should clear when no command is processing. However, after operations, my status check for the idle state consistently fails.

Problem Summary

After sending data, I perform a check to confirm that the I/O operation has completed and the interface is idle. However, this check fails, indicating that the state machine is not idle and/or a command is still being processed, which should not be the case.

Current Implementation

Here’s the specific code snippet I use to check if the I/O module has returned to idle and is not processing any commands. This is inside the func am_hal_iom_blocking_transfer: Link to the file

    //
    // Make sure transfer is completed.
    //
    ui32Status = am_hal_flash_delay_status_check(AM_HAL_IOM_MAX_BLOCKING_WAIT,
                            (uint32_t)&IOMn(ui32Module)->STATUS,
                            (IOM0_STATUS_IDLEST_Msk | IOM0_STATUS_CMDACT_Msk),
                            IOM0_STATUS_IDLEST_Msk,
                            true);

am_util_stdio_printf("After am_hal_flash_delay_status_check: Status = %d\n", ui32Status);

if (ui32Status == AM_HAL_STATUS_SUCCESS)
{
    ui32Status = internal_iom_get_int_err(ui32Module, 0);
    am_util_stdio_printf("After internal_iom_get_int_err: Status = %d\n", ui32Status);

    if (ui32Status == AM_HAL_STATUS_SUCCESS)
    {
        if (ui32Bytes)
        {
            // Indicates transaction did not finish for some reason
            ui32Status = AM_HAL_STATUS_FAIL;
            am_util_stdio_printf("Transaction not finished, setting status to AM_HAL_STATUS_FAIL\n");
        }
    }
}

This is inside the func am_hal_flash_delay_status_check: Link to the file

uint32_t
am_hal_flash_delay_status_check(uint32_t ui32usMaxDelay, uint32_t ui32Address,
                                uint32_t ui32Mask, uint32_t ui32Value,
                                bool bIsEqual)
{
    while ( 1 )
    {
        uint32_t regVal = AM_REGVAL(ui32Address) & ui32Mask;

        //
        // Print which bitmask and value are being checked
        //
        am_util_stdio_printf("Checking register at address %lu with mask %lu for value %lu\n", ui32Address, ui32Mask, ui32Value);

        //
        // Check the status
        //
        if ( bIsEqual )
        {
            am_util_stdio_printf("Checking if register value %lu equals %lu (masked value: %lu)\n", regVal, ui32Value, regVal & ui32Mask);
            if ( regVal == ui32Value )
            {
                am_util_stdio_printf("Condition met. Returning SUCCESS.\n");
                return AM_HAL_STATUS_SUCCESS;
            }
        }
        else
        {
            am_util_stdio_printf("Checking if register value %lu does not equal %lu (masked value: %lu)\n", regVal, ui32Value, regVal & ui32Mask);
            if ( regVal != ui32Value )
            {
                am_util_stdio_printf("Condition met. Returning SUCCESS.\n");
                return AM_HAL_STATUS_SUCCESS;
            }
        }

        if ( ui32usMaxDelay-- )
        {
            am_util_stdio_printf("Delaying... Remaining delays: %lu\n", ui32usMaxDelay);
            //
            // Call the BOOTROM cycle function to delay for about 1 microsecond.
            //
            am_hal_flash_delay( FLASH_CYCLES_US(1) );
        }
        else
        {
            am_util_stdio_printf("Maximum delay exceeded. Returning TIMEOUT.\n");
            break;
        }
    }

    return AM_HAL_STATUS_TIMEOUT;
}

!!! Print Statements are from me !!!

In this scenario, the function am_hal_flash_delay_status_check is supposed to return success when IDLEST is set (indicating idle) and CMDACT is cleared (indicating no active command). However, it consistently indicates that the module is not idle or is still processing a command.

Troubleshooting Steps Taken

  • Updated Firmware and Libraries: Ensured everything is up-to-date.
  • Reviewed Hardware Configurations: Checked all related configurations and setups.
  • Added Debugging Logs: To monitor the status register changes more closely.

Debug Output:

I2C Testing

API Validation is enabled
Checking register at address 268440440 with mask 4294967295 for value 0
Checking if register value 0 equals 0 (masked value: 0)
Condition met. Returning SUCCESS.
Checking register at address 1342202548 with mask 6 for value 4
Checking if register value 4 equals 4 (mChecking register at address 1342202548 with mask 6 for value 4
Checking if register value 2 equals 4 (masked value: 2)
Delaying... Remaining delays: 499999

**More Information about the bits being checked in am_hal_iom_blocking_transfer function can be found on datasheet of apollo3 on page No 340 (:frowning: Sorry Couldn’t addd link due to restrictions)
**

Questions to the Community

  1. Has anyone experienced similar issues with the Apollo3 regarding the status register not accurately reflecting the idle state after operations?
  2. Are there specific conditions or configurations in Apollo3 that might affect the behavior of these status bits (IDLEST and CMDACT)?
  3. Any recommended debugging approaches or solutions to ensure the IDLEST and CMDACT bits accurately reflect the state of the I/O operations?

Any advice or insights would be greatly appreciated as I continue to troubleshoot this issue.

Thank you!