I2C Slave mode support?
Moderators: RoccoMarco, lbednarz, tfAteba
Re: I2C Slave mode support?
I'm not certain that 'read zero bytes from this address' is a valid call, although there's no specific test for it. Are you using i2cMasterReceiveTimeout()?
On the slave, IIRC it should always respond with data - the source depends on the call type. The slave has no knowledge of how much data has been requested; it just keeps sending until a STOP is received. So I suspect the problem is at the master end.
It's a while since I tested all modes of the driver, so its possible that something has become broken outside my normal use case. However nothing substantive has been changed.
On the slave, IIRC it should always respond with data - the source depends on the call type. The slave has no knowledge of how much data has been requested; it just keeps sending until a STOP is received. So I suspect the problem is at the master end.
It's a while since I tested all modes of the driver, so its possible that something has become broken outside my normal use case. However nothing substantive has been changed.
Re: I2C Slave mode support?
Hi steved,
I do not think this issue comes from your updated code, but is part of the not-yet-handled use cases.
The master cannot do anything in this case: as clock stretching has been left activated by default, the slave leaves the clock at the low level so the master is no longer able to communicate with the slave anyway - at least until the timer times out on the slave and release the SCL line so the master gets a chance to initiate a STOP.
I do not think an I2C request requires to have at least one data byte, whatever the direction.
The master is not running ChibiOS in my current setup.
Thanks for your help, I still need to dig further into the code.
It would be really nice the "slave" modes get an official API in ChibiOS - I'm also thinking about SPI here
I do not think this issue comes from your updated code, but is part of the not-yet-handled use cases.
The master cannot do anything in this case: as clock stretching has been left activated by default, the slave leaves the clock at the low level so the master is no longer able to communicate with the slave anyway - at least until the timer times out on the slave and release the SCL line so the master gets a chance to initiate a STOP.
I do not think an I2C request requires to have at least one data byte, whatever the direction.
The master is not running ChibiOS in my current setup.
Thanks for your help, I still need to dig further into the code.
It would be really nice the "slave" modes get an official API in ChibiOS - I'm also thinking about SPI here
- Professor Tarantoga
- Posts: 3
- Joined: Thu Aug 20, 2020 1:30 pm
Re: I2C Slave mode support?
Hi folks.
I am really happy, that there is code for i2c slave mode available (thanks for that), but i do have some little problem, getting it to work properly. Maybe someone can give me a hint?
I am using the NUCLEO-F767ZI, OS is 20.3.1 and code compiles without any error.
DMA disabled.
From the given examples i use following code to get slave mode up:
[font=Courier New]i2cStart(&slaveI2cPort, &slaveI2Cconfig);
slaveI2cPort.slaveTimeout = TIME_MS2I(500);
initialReply.size = strlen((char *)initialReply.body) + 1;
i2cSlaveConfigure(&slaveI2cPort, &echoRx, &initialReply);[/font]
In [font=Courier New]i2cSlaveConfigure[/font] function [font=Courier New]i2c_lld_slaveReceive[/font] is called and [font=Courier New]i2cStartReceive[/font] should be called in order to activate rx interrupt (I2C_CR1_RXIE). But [font=Courier New]i2cp->mode[/font] is set to idle and because of [font=Courier New]if (i2cp->mode == i2cLockedRxing && rxMsg->body && rxMsg->size)[/font] function [font=Courier New]i2cStartReceive[/font] is never called.
Am I missing something?
Thanks in advance
I am really happy, that there is code for i2c slave mode available (thanks for that), but i do have some little problem, getting it to work properly. Maybe someone can give me a hint?
I am using the NUCLEO-F767ZI, OS is 20.3.1 and code compiles without any error.
DMA disabled.
From the given examples i use following code to get slave mode up:
[font=Courier New]i2cStart(&slaveI2cPort, &slaveI2Cconfig);
slaveI2cPort.slaveTimeout = TIME_MS2I(500);
initialReply.size = strlen((char *)initialReply.body) + 1;
i2cSlaveConfigure(&slaveI2cPort, &echoRx, &initialReply);[/font]
In [font=Courier New]i2cSlaveConfigure[/font] function [font=Courier New]i2c_lld_slaveReceive[/font] is called and [font=Courier New]i2cStartReceive[/font] should be called in order to activate rx interrupt (I2C_CR1_RXIE). But [font=Courier New]i2cp->mode[/font] is set to idle and because of [font=Courier New]if (i2cp->mode == i2cLockedRxing && rxMsg->body && rxMsg->size)[/font] function [font=Courier New]i2cStartReceive[/font] is never called.
Am I missing something?
Thanks in advance
Re: I2C Slave mode support?
Long time since I looked at the code in detail, but I think you'll find that i2cStartReceive() is called (maybe via a convoluted route) once the device has received a correct I2C address.
Looking at my code, I have this sequence:
You don't mention calling i2cMatchAddress(), so that could be the problem.
Note: I always regard I2C addresses as 8 bits, with bit 0 always zero; Chibi uses a 7-bit value.
If you look back in this thread, there should be some pointers to the test harnesses I used originally when making the code work. (I do have this feeling that the I2Cv2 code might be over-complicated, but have never had time to revisit it)
Looking at my code, I have this sequence:
Code: Select all
#if HAL_USE_I2C_SLAVE
slaveI2cPort.slaveTimeout = MS2ST(100); // Time for complete message
#endif
i2cMatchAddress(&slaveI2cPort, slaveI2Caddress/2);
i2cSlaveConfigure(&slaveI2cPort, &echoRx, &initialReply);
You don't mention calling i2cMatchAddress(), so that could be the problem.
Note: I always regard I2C addresses as 8 bits, with bit 0 always zero; Chibi uses a 7-bit value.
If you look back in this thread, there should be some pointers to the test harnesses I used originally when making the code work. (I do have this feeling that the I2Cv2 code might be over-complicated, but have never had time to revisit it)
- Professor Tarantoga
- Posts: 3
- Joined: Thu Aug 20, 2020 1:30 pm
Re: I2C Slave mode support?
Hej steved,
thanks for answering.
Indeed I overlooked i2cMatchAddress(). Beside that I was struggeling with some inconveniences in my test setup. Meanwhile I managed to get something working.
As I don't have any experience with DMA, I disabled DMA. i2c should now run in interrupt mode.
I can see the received data in the provided rx-buffer but data is not further handled in any way.
i2cp->slaveBytes is always 0
I found a function i2cEndSlaveRxDMA, but no end-function for interrupt driven mode.
Could it be that your code is only working with DMA?
I will try DMA-mode and see, although it would be nice if you can give me a short feedback on interrupt driven mode.
Thanks and best regards
PT
thanks for answering.
Indeed I overlooked i2cMatchAddress(). Beside that I was struggeling with some inconveniences in my test setup. Meanwhile I managed to get something working.
As I don't have any experience with DMA, I disabled DMA. i2c should now run in interrupt mode.
I can see the received data in the provided rx-buffer but data is not further handled in any way.
i2cp->slaveBytes is always 0
I found a function i2cEndSlaveRxDMA, but no end-function for interrupt driven mode.
Could it be that your code is only working with DMA?
I will try DMA-mode and see, although it would be nice if you can give me a short feedback on interrupt driven mode.
Thanks and best regards
PT
Re: I2C Slave mode support?
Does look as if my 'real' code was using the I2C in DMA driven mode, although the driver was tested with both DMA and interrupts for a range of message sizes up to 563 bytes.
My applications send a message to the device, and always expect a reply.
Last thing I do in initialisation is:
The key data block is:
Then the key parts of my message processor are:
Hope that helps
My applications send a message to the device, and always expect a reply.
Last thing I do in initialisation is:
Code: Select all
i2cSlaveConfigure(&slaveI2cPort, &echoRx, &initialReply);
The key data block is:
Code: Select all
const I2CSlaveMsg echoRx =
{
sizeof(rxBody), /* max sizeof received msg body */
rxBody, /* body of received msg */
NULL, /* do nothing on address match */
messageProcessor, /* Routine to process received messages */
catchError /* Error hook */
};
Then the key parts of my message processor are:
Code: Select all
void messageProcessor(I2CDriver *i2cp)
{
size_t len = i2cSlaveBytes(i2cp); // Number of bytes received
if (len >= sizeof(rxBody))
len = sizeof(rxBody)-1;
rxBody[len]=0;
/* Process received message, generate response */
uint8_t rxLen = checkRxMessage(rxBody);
if (rxLen == 0)
{
strcpy((char *)txBody, errorReplyBody);
echoReply.size = strlen(errorReplyBody);
}
else
{
uint8_t txLen = processMessage(&rxBody, rxLen, &txBody);
txBody[1 + txLen] = '\0'; // Null terminate for simplicity
echoReply.size = txLen;
}
i2cSlaveReplyI(i2cp, &echoReply);
}
Hope that helps
- Professor Tarantoga
- Posts: 3
- Joined: Thu Aug 20, 2020 1:30 pm
Re: I2C Slave mode support?
I am now running DMA-mode. The data is received correctly and put into the rx-buffer.
Unfortunately the messageProcessor is never called so I cannot handle the data.
debugging codes are: 0x82, 0x80, | : 0x04, 0x13, 0x14, 0x05 : |
I understand:
82&80 init transfer
04 address match
13 address match receive
14 receive
05 stop
But where is the data handled?
Maybe I am stuck on outdated code od still missing something?
Thanks
best regards
PT
Unfortunately the messageProcessor is never called so I cannot handle the data.
debugging codes are: 0x82, 0x80, | : 0x04, 0x13, 0x14, 0x05 : |
I understand:
82&80 init transfer
04 address match
13 address match receive
14 receive
05 stop
But where is the data handled?
Maybe I am stuck on outdated code od still missing something?
Thanks
best regards
PT
Re: I2C Slave mode support?
Professor Tarantoga wrote:But where is the data handled?
Maybe I am stuck on outdated code od still missing something?
PT
I've just started using I2C slave mode in a different way to previously, and found exactly the same as you. It's when the master just sends, without requiring a reply - as you say, the data isn't handled.
Did you ever fix the problem?
Re: I2C Slave mode support?
Well, this is how I fixed it for I2Cv2 - just update the LLD.
Works with and without DMA.
Code could still do with a serious tidy up, but at least it works.
Works with and without DMA.
Code could still do with a serious tidy up, but at least it works.
- Attachments
-
- I2Cv2.7z
- (16.35 KiB) Downloaded 660 times
Re: I2C Slave mode support?
Is there a working i2c-slave code for stm32f103? I'm trying many variants published in this topic, but no one working
Please help me!