Hi Dialog,
I am attempting to use the DA1468x device as an I2C Slave device using the i2c adapters (ad_i2c_start_slave). For the most part it works but sometimes it doesn't.
The communication protocol is (more or less) as follows:
- wait for message header
ad_i2c_start_slave(ack, sizeof ack , msgHeader, sizeof msgHeader, callbacks, OS_EVENT_FOREVER);
... wait for data_sent and data_received callbacks
- wait for payload
ad_i2c_start_slave(ack, sizeof ack, msgPayload, sizeof msgPayload, callbacks, TIMEOUT);
- process and get result ready
ad_i2c_start_slave(ack, sizeof ack , waiting_for_result, sizeof waiting_for_result, callbacks, TIMEOUT);
- send result
ad_i2c_start_slave(ack, sizeof ack , result, sizeof result, callbacks, TIMEOUT);
The ad_i2c_start_slave() can generate 4 different callbacks depending on whether read and/or write buffers are provided. From my experience I am not able to properly handle the read request callback so I opted for always providing wbuf and rbuf for ad_i2c_start_slave() so that I am only concerned about data_sent and data_received callbacks.
So at every stage (above) it is expected that the i2c master sends data and reads data (say an acknowledgement). So basically I am waiting for data_sent and data_received events to be triggered in order to advance to the next stage of the protocol (see above).
However sometimes they i2c bus hangs (SCLK is held low). I am guessing this is because data is requested (or data sent to) which is not handled by the software. How can this happen? I think this can occur when during the switches of the buffer between each stage. However shouldn't the old buffers be used instead? or are these buffers used only one time?
Another issue that can occur I'm guess is that there's pending transactions that I do not know how to cancel in the case of timesouts. See my other post here :https://support.dialog-semiconductor.com/forums/post/dialog-smartbond-bl...
So my question is how can use the ad_i2c_start_slave() with timeouts the way how described in the protocol mentioned above and or do you have any suggestions on how I can implement this.
PS. The issue I was having before with read_request callback is that reading the data from the buffer didn't really stop the interrupt (RX_FULL) from continuously being triggered. Perhaps if you have suggestions how this can be done in combination with the protocol I'll be more than welcomed to hear it.
Hi rajames,
Unfortunatelly there are no example demo for using the 68x as a slave device. A few things regarding the I2C and how the driver operates. When the 68x is in i2c slave mode if there is a read or a write depends on the command sent from the master either read or write along with the slave's address and not from the available buffers. Depending on the command from the master the device will expose the proper buffer read or write. Regarding the clock line held low by the slave, this might occur when the slave doens't have data in its FIFO and there is a read request from the master, in this case the line will stay low until read data are provided to the slave I2C controller. Regarding the functions that you have supplied to the ad_i2c_start_slave(), i see that on the last parameter you have provided somekind of a timeout, there aren't parameters that will set a timeout, what you can do is implement your own timeout and then invoke the ad_i2c_stop_slave() in order to abort the interaction, if not the device will wait until the interaction completes. Also when interacting with the master you
should first set the buffer in your transaction in order to read the data from the master and then start a new transaction in order to write, and not at the same time as you have implemeneted on the code above.
Thanks MT_dialog
Hi Dialog,
Let me clarify, indeed the ad_i2c_start_slave doesn't have TIMEOUT argument I will explain below what I meant.
// prepare ack buffers for responding
// message header
ad_i2c_start_slave(ack, sizeof ack , msgHeader, sizeof msgHeader, callbacks);
... wait for data_sent and data_received callbacks
OS_EVENT_GROUP_WAIT(event, (DATA_RECEIVED | DATA_SENT), OS_EVENT_GROUP_FOREVER);
// payload
ad_i2c_start_slave(ack, sizeof ack, msgPayload, sizeof msgPayload, callbacks);
... wait for data_sent and data_received callbacks
OS_EVENT_GROUP_WAIT(event, (DATA_RECEIVED | DATA_SENT), TIMEOUT);
// waiting for result
ad_i2c_start_slave(ack, sizeof ack , waiting_for_result, sizeof waiting_for_result, callbacks);
... wait for data_sent and data_received callbacks
OS_EVENT_GROUP_WAIT(event, (DATA_RECEIVED | DATA_SENT), TIMEOUT);
// process and prepare result buffer (may take some time)
// send result
ad_i2c_start_slave(ack, sizeof ack , result, sizeof result, callbacks);
... wait for data_sent and data_received callbacks
OS_EVENT_GROUP_WAIT(event, (DATA_RECEIVED | DATA_SENT), TIMEOUT);
Secondly all thewbufused in ad_i2c_start_slave are prepared before calling ad_i2c_start_slave.
I expect that settingwbufandrbufand calling ad_i2c_start_slave will be able to handle both write and read asynchronously.
How else would I be able to synchronize with a master device (if just looking at the DATA_RECEIVED and DATA_SENT events)?
Example Scenarios.
1. If slave is expecting areadbut master did awriteinstead.
2. If slave is expecting awritebut master did areadinstead.
Should I handle all 4 events DATA_RECEIVED, DATA_READY, DATA_SENT, READ_REQUEST events ?? I prefer not to because this really complicates the state-machine seeing that
I might be waiting on events that might not occur and that I may have to handle some of logic in the callbacks (isr context). And if I recall it may not be a good idea to call ad_i2c routines in isr context.
劳尔
Hi rajames,
关于你看到设备控股的事实the SCK line low, this is in order to declare a busy state to the master device, this holding the line low is when the device accepts a read request from the master, when that occurs (so when the READ_REQ has occured) the sw will check if there are valid callbacks and buffers and if there are it will start filling the hw buffer in order for the I2C hw to send out the data, so while this procedure is executing the clock like is held low.
I suppose that you could provide both write and a read buffer in order to execute a standard read command (since the i2c performs a write and then a read). Also as mentioned if no buffers are available at the time the master sends a read or a write request (read_request and data_ready), you can manage what the device will do from those callbacks. What events you should handle and how you will handle them depends on your implementation, if you would like a system that will handle out of sync situations where the master and slave can access the bus then you should handle all the events.
Thanks MT_dialog