I'm doing some code now to interface with I2C devices using freeRTOS. As the I2C communications are half duplex, I was wondering if I could safely use a single queue for incoming and outgoing data. That means, using the same queue to communicate with the ISR when transmitting and receiving.
Hope someone can help me.
Best wishes ;)
Queues are very flexible and can have any number of readers and any number of writers. Your only problem is going to be coordinating your multiple readers and writers. If a task wrote to a queue and then read from the queue they would just read out what they had just written.
You could use two queues? One in each direction if you have enough resources.
While I won't say you can't use one queue, it may make things more difficult, as you will need to do something to make the task that is taking data from the I2C input not grab the date being sent out. (And then it consumes all the data that has come in before sending data back out).
While the bus itself may be half duplex, making it a single queue says you will need to keep the concept of half duplex all the way to the program terminal task. I suspect that in most cases, the whole reason you are using a queue there at all, and not just a mailbox with a data ready flag, is that you want to allow for the data coming in to have the option of getting a bit ahead of the consuming task, and/or let what ever is producing data be able to get ahead of the actual bus. At this point the half-duplex assumption is no longer valid, and the standard model of an input and output queue is suggested.
Well richard, I've implemented a I2C routine that handles reading or writing a block of N bytes of data, it has the following prototype:
unsigned int iI2CDriverTransaction( xI2CHandle xI2CResources, unsigned int iDevAddress, unsigned int iMemAddress, unsigned int iBusDirection, unsigned int iBytesToTransfer, void * pvDataBuffer )
I don't know if that's what you mean with the mailbox. This function basically takes a mutex, writes data to a structure (which is used by a Finite State Machine running on the I2C ISR), and generates a interrupt which causes a FSM to start working. Then the function(task) blocks and waits for a message from the ISR on what I called a ''Control Queue''. This message contains a code indicating what happened inside the FSM. When the message arrives from the ISR, the function gives back the mutex and returns with the code received from the control Queue. If data was successfully read or written this function returns E_SUCCESS, other codes are also provided, for example E_ERROR_NACK indicates that master did not received ACK from the given slave address.
What I'm trying to do now is to implement a layer of compatibility that allows me to use the MPFS(microchip file system) that is used in the TCP/IP stack and other application notes from Microchip. The TCP/IP stack I'm using includes files for SPI and I2C interface with eeprom memories. In the i2ceeprom.c file I find functions like this:
static unsigned char getcI2C( void )
I2C2CONbits.RCEN = 1; // enable master for 1 byte reception
while(I2C2CONbits.RCEN); // wait until byte received
return I2C2RCV; // return with read byte
Here for example, I'm looking for a way to replace this with a function that uses the Rtos to do something usefull instead of just checking the RCEN bit (with the bus at 400 Khz this may be too much wasted time). As we intend to receive only a byte at a time, a large queue doesn't makes sense. But for TX a large queue would be, in theory OK. I'm still wondering how to do this and I thought that I could use a single queue for TX and RX, so the question.
Well, those are some random thoughts, of what I'm trying to do. If anyone has worked with anything similar or know about a embedded filesystem for use in small eeprom or flash memories, or have some comments, it would be cool. Meanwhile I'll be checking in detail the MPFS implementation.
Thank you guys, have a nice day!