Communicating with I2C devices using an RTL8710

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

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?

• Could you include a minimum working example that shows the problem? In case someone wants to test this, they will struggle with above code. I can't find out where your i2c_* are from. Why is frequency 1kHz (datasheet lists 100kHz as min)? Why is there a 0xff as i8 (doesn't rustc warn about this)? – domen Nov 19 '18 at 8:57
• @domen sure thing. The code I posted is basically already the full code, but I'll expand it to a full example with some instructions on how to run it. The I2C API is located here: github.com/lupyuen/rustl8710/blob/master/component/common/mbed/… , 0xff as i8 is needed because the C type of i2c_write requires an array of chars, and chars are signed in C. 0xff is not interpreted as a i8 without that cast. – Size43 Nov 19 '18 at 10:59
• @domen I'm fairly sure the 100kHz is an upper limit, and not a minimum. I've tested the MCP23008 using bitbanged i2c which had an average frequency of around 50Hz and a clock all over the place and that still worked without issues. – Size43 Nov 19 '18 at 11:01
• Signedness of char in C is implementation defined, so it's definitely weird to see them used for non-string characters. Does I2C work for you with any other i2c devices on rtl8710? Have you got access to oscilloscope/logical probe? Might be worth opening a ticket for rtl8710 i2c code. – domen Nov 19 '18 at 13:38
• @domen that would indeed be what I'll probably have to do eventually, but I was just hoping someone had run into this issue before. I've tried to use a Raspberry Pi to print something if the SCL or SDA lines go low, which never seems to happen (or the pi isn't accurate enough) – Size43 Nov 20 '18 at 12:39

1 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.