Electronic – Communicating with I2C devices using an RTL8710

i2c

I've connected an RTL8710 (in "Rtlduino" form) to a MCP23008 (on a breadboard) via I2C as follows:

My setup

I'm using rustl8710 to program the RTL8710, which works fine and I've already hooked up a display via SPI without any issues.

I've got this code set up to test the MCP23008:

led1.write(DigitalValue::High);
let mut handle = i2c_t::default();
i2c_init(&mut handle as *mut i2c_t, PinName::PC_4, PinName::PC_5);
i2c_frequency(&mut handle as *mut i2c_t, 1000);
led2.write(DigitalValue::High);
if i2c_write(&mut handle as *mut i2c_t, 0x20, &[ 0x00, 0xff as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0 ][0] as *const i8, 11, 1) != 1
{
    panic!("Byte write failed!");
}

led3.write(DigitalValue::High);
loop { }

Feel free to ignore all lines starting with led*, those simply pull some GPIO pins high to light up the 3 internal LEDs on the device so I can see if it works without using gdb.

Alternatively, this C code demonstrates the same problem:

#include "i2c_api.h"
#include "PinNames.h"

void main(void)
{
    ConfigDebugInfo = 0xffffffff;

    char data[] = { 0x00, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
    i2c_t handle;
    i2c_init(&handle, PC_4, PC_5);
    i2c_frequency(&handle, 1000);
    i2c_write(&handle, 0x20, data, 11, 1);

    while(1) { }
}

Paste the code above in place of main in main.c and then flash and run the code using make && make flash && make debug. The code will never reach the while loop, and hang on i2c_write.

The code effectively does the same thing as this code in an Adafruit library for the MCP23008.

I2C set-up (first 5 lines) works, but when calling i2c_write the RTL8710 just hangs infinitely somewhere in a loop in RtkI2CSend_Patch () at component/soc/realtek/8195a/fwlib/src/hal_i2c.c:1324 (according to gdb)

The MCP23008 is working fine, I've successfully used that on an ATTiny85.

Other things that might be relevant:

  • PC_5 (aka GC5) is also connected to a button on the evaluation board, which pulls the pin high when it's not pressed.
  • The RTL8710 prints RTL8195A[HAL]: ISR 0 didb't bee register!!!␊ to the UART_LOG ports. This appears to be from a function that isn't available in source form so I'm not quite sure how I should interpret that.

What am I doing wrong?

Best Answer

As it turns out, I was indeed not the only one to notice this issue. In both the 3.5a and 4.0b SDKs (rustl8710 is using the 3.5a SDK), there is a bug in the I2C code. Realtek have released a fix for this bug, but this fix is not included in the SDK downloads, nor listed on the download page, nor listed in the release notes.

Instead, you have to download a fixed library from the FAQ page here: https://www.amebaiot.com/en/ameba-sdk-faq/. For rustl8710, which uses the 3.5a SDK, you'd click on 'Fix 3.5a GCC SDK I2C problem', then download the linked zip file (note: you might need to create an account before you can download the file). This zip file contains a single lib_platform.a, which you'll have to copy over the existing file in component/soc/realtek/8195a/misc/bsp/lib/common/GCC/lib_platform.a.

After this, use these make commands to rebuild everything:

make clean
make

For me, I2C still doesn't work the first time after flashing. This can be worked around by starting a debug session using make debug, then quitting using q and restarting the debug session using make debug again.