Hi,dialog
Problem:
I found a problem that when i use the IIC api ad_i2c_async_transact to write data (5 * 128byte) to the OLED display, there will lost some data . The IIC was change the state to "STOP" when the data haven't been completly transfer finished. if i turn off the ble advertise, the oled works well.
Project setting:
1,Project used: DA1468x_SDK_BTLE_v_1.0.6.968 for Pxp_reporter;
2,ble set as default;
3,IIC run in fast speed -- 400khz;
Want to konw:
1,how the ble affect the IIC transfer or there is something wrong with my iic configuration
2,In what way can both the iic and ble work well.
the accessory shows the iic signal waveform when writing the oled.
Thanks Kingwheat
Device:
Hi kingwheat,
If a BLE interrupt occurs when there is an ongoing I2C transaction, the BLE interrupt has greater priority and will interrupt the I2C transaction, so the module will issue a stop on the I2C bus. The proper way to do that is to use the DMA instead of directly using the I2C module. So are you using the DMA ?
Thanks MT_dialog
Hi MT_dialog,
I set the iic to use the dma,but it's dosen;t work in the dma mode.
First of all , I config the IIC as I2C_SLAVE_DEVICE_DMA(I2C2, SSD1306, 0x3c, HW_I2C_ADDRESSING_7B, HW_I2C_SPEED_FAST, 2);
if it's ok for the iic to use the dam channel or there still something i have to do to enable the dma?
after then use the hw_i2c_write_buffer_dma_ex(); to send the data.
I printf the device->dma_channel , the value is -1;
so ,how to enable the dam?
Hi kingwheat,
In order to use the DMA, you just have to configure your device in the platform_devices.h file like indicated below:
I2C_SLAVE_DEVICE_DMA(I2C1, MPU_6050, 0x68, HW_I2C_ADDRESSING_7B, HW_I2C_SPEED_STANDARD, 2);
Also please use the adapters in order to interact with the I2C and the DMA and not directly the hw drivers, like the example below,
i2c_device your_device_handle;
your_device_handle = ad_i2c_open (YOUR_DEVICE_NAME);
ad_i2c_transact(your_device_handle, i2c_internal_register, write_length, read_buffer, read_length);
ad_i2c_close(your_device_handle)
You can also have a look at the peripherals_demo project in order to check how the adapters are used with the DMA, and also the Doxygen documentation in the adapters section.
Thanks MT_dialog
Hi, MT_dialog
I have the test what you say before, i found that the ad_i2c_transact has the dam only in the received mode, if i want to write data,it use the
OS_ENTER_CRITICAL_SECTION();
OS_LEAVE_CRITICAL_SECTION();
to avoid the distraction of another intterupt,but not use the dam which i need. But in fact , the iic still be stop when the data is not finish.
I don;t know if I not use it in the correct way, could you give me some advice?
I use the ad_i2c_async_transact() ,the this function only has the receive mode with the dma, os i add the write mode myself...but i meet some problems:
I try to use the dam in this way:
ssd1306_dev = ad_i2c_open(SSD1306);
ad_i2c_async_transact(ssd1306_dev, I2C_SND(®ister_addr, 1),
I2C_SND_ST(register_data, wr_len),
I2C_CB1(ssd1306_done_cb, &error),
I2C_END);
ad_i2c_close(ssd1306_dev);
;******************************************************************************
void ad_i2c_async_transact(i2c_device dev, ...)
{
...some code here.....
ad_i2c_async_do(dev, 0);
}
;******************************************************************************
static void ad_i2c_async_do(i2c_device dev, HW_I2C_ABORT_SOURCE error)
{
...some code here.....
case I2C_TAG_SEND:
/* start write operation, next action executes from interrupt */
len = (uint16_t) data->transaction[data->transaction_ix++];
wbuf = (const uint8_t *) data->transaction[data->transaction_ix++];
if (device->dma_channel < 0 ) {
hw_i2c_write_buffer_async(device->bus_id, wbuf, len, ad_i2c_cb, device, HW_I2C_F_NONE);
} else {
hw_i2c_write_buffer_dma_ex(device->bus_id,
(uint8_t)device->dma_channel, wbuf, len,
ad_i2c_dma_cb, device ,HW_I2C_F_NONE); // here is the code i add in order to send data in the dma mode
}
return;
}
After that :
In this time , the iic is working in the dam mode which i know in the debug mode. The iic sequence is write--> Slave_address + destination address + data(128Byte)
但我found the destination addressis alwasy 0x00; and Slave_address and data is right ; I don't konw why the hardwear IIC set the destination address to zero;
I have debug for this problem ,but I can't find out where the problem is ???
the attachment show the iic problem.
Thanks !
data buffer elements are 16-bit wide, this high byte should be 0 for writing and discarded when reading.
/* my code */
static OS_EVENT i2c_event;
static volatile HW_I2C_ABORT_SOURCE i2c_err;
...some code here.....
static void i2c_init(void)
{
OS_EVENT_CREATE(i2c_event);
}
...some code here.....
static void i2c_wr(void)
{
i2c_device dev;
uint16_t wbuf[2] = {0x00,0xAE};
dev = ad_i2c_open(MY_DEVICE);
ad_i2c_async_write(dev, wbuf, sizeof(wbuf)/sizeof(uint16_t), i2c_wr_cb, NULL);
OS_EVENT_WAIT(i2c_event, OS_EVENT_FOREVER);
ASSERT_ERROR(i2c_err == HW_I2C_ABORT_NONE);
ad_i2c_close(dev);
}
static void i2c_wr_cb(void *user_data, HW_I2C_ABORT_SOURCE error)
{
i2c_err = error;
OS_EVENT_SIGNAL_FROM_ISR(i2c_event);
}