Non-blocking communications - Forums Re: Non-blocking communications Thanks Bob, that's not a bad idea.

Mon, 02 Jan 2012 11:51:14 -0600
Re: Non-blocking communications That looks like a complicatetd one:

The IDLE-State is set (of course) within the interrupt-routine of the I2C communication. To raise another interrupt within an interrupt-routine where a RTOS-function for task-switching is called looks a bit hazardous.

So let's try to bake smaller breads.

What, if you use an interrupt-driven polling? Ie. a timer that interrupts and just checks for the state of I2C and when it's IO is done releases the Semaphore? Due to the lengthy i/o of I2C (compared to the CPU) it won't matter much, if the semaphore release comes 1 to 10ms later than the end of transmission really was.

Well, I know that tis thing is not as easy as I just wrote, the interrupt-routine will have to know about started I/O and other things, but it can be an approach.

Happy coding, don't let you be interrupted


Mon, 02 Jan 2012 04:12:08 -0600
Re: Non-blocking communications I'm bumping this back up the forum because I have tried everything I can think of and I still can't find the appropriate place to put the xSemaphoreGiveFromISR.

Does anyone have any suggestions?

Sun, 01 Jan 2012 13:40:51 -0600
Re: Non-blocking communications Thanks dasq, that makes perfect sense.

Do you have any advice on the recommended way to get an interrupt at the end of the hardware- and cypress-generated-firmware- handled portion of an I2C transaction?

An optional irq output pin on the component might be a lot to ask, and would needlessly tie up another processor interrupt.

Perhaps a better approach would be just to add another section similar to this one (which I assume is maintained unmodified by the code generator):

                            /*  Place code to prepare read buffer here */
                            /* `#START SW_PREPARE_READ_BUF` */

                            /* `#END`  */

to I2C_INT.c?

Unfortunately it looks like there is no one line in the ISR where this could be added. If I understand properly, it would need to be each place where I2C_State is assigned the new value I2C_SM_IDLE? Maybe introduce a new local called I2C_State_Next, assign I2C_SM_IDLE to it, and then have one place after all the nested if/else logic but before assigning I2C_State_Next to I2C_State where the developer could add some custom logic to the ISR?

What I am trying to do is call the FreeRTOS function xSemaphoreGiveFromISR whenever the hardware-and-generated-firmware part of an I2C transaction is finished, so that the thread that requested it will be awoken by the scheduler.


Mon, 27 Jun 2011 14:32:05 -0600
Re: Non-blocking communications Hi Doug McClean,


In your previous post, you had used the API as follows:

status = I2C_MasterReadBuf(slaveAddress, &result, sizeof(uint16), I2C_MODE_REPEAT_START | I2C_MODE_COMPLETE_XFER);


The macro definition for



3) I2C_MODE_NO_STOP = 0x02.


Hence, it is the 2 least significant bits which determine whether STOP is generated and REPEAT START is issued.

When LSB is set (1), REPEAT START is sent, else START is sent.

When last but one LSB is set (1), STOP is not generated. Else, STOP is generated.


Hence, ORing with  I2C_MODE_COMPLETE_XFER is not really necessary as it is equivalent to ORing with 0x00.

Mon, 27 Jun 2011 01:54:42 -0600
Re: Non-blocking communications It does seem to work that way (up to endian-ness, which I had a little hiccup with since I hadn't had prior occasion to learn that the PSoC5 is little-endian).

Is there a better option than tinkering with the auto-generated ISR? It doesn't seem to include a block that the auto-generator won't overwrite, it doesn't seem to have a callback.

Maybe the component should include an option for an irq output that is pulsed when a transfer completes (successfully or otherwise), and I could hook my own ISR to that?

Tue, 21 Jun 2011 14:43:20 -0600
Re: Non-blocking communications Oh, and that it will NAK the 2nd byte of the read and then send a stop condition as well? (Since I2C_MODE_COMPLETE_XFER was specified.)

Tue, 21 Jun 2011 13:39:02 -0600
Re: Non-blocking communications Ahh, so they are.

So am I correct in thinking that code like this will be basically ok?


// this function should transfer one byte (the slave's register address) to the slave, then issue a restart, then read two bytes from the slave

uint16 ReadSlaveRegister(uint8 slaveAddress, uint8 slaveRegisterAddress)


uint16 result;

uint8 status;

status = I2C_MasterWriteBuf(slaveAddress, &slaveRegisterAddress, sizeof(uint8), I2C_MODE_NO_STOP);

// error handling

// call FreeRTOS to sleep this thread for a while until the I2C is done doing its thing, presumably by adding a line to the end of its ISR that will give our semaphore once the transfer is over or breaks

status = I2C_MasterReadBuf(slaveAddress, &result, sizeof(uint16), I2C_MODE_REPEAT_START | I2C_MODE_COMPLETE_XFER);

// error handling

// call FreeRTOS to sleep again in the same way

return result;


Tue, 21 Jun 2011 13:37:07 -0600
Re: Non-blocking communications Not all APIs are blocking APIs. It is possible to delegate the I2C data transfer job to the I2C hardware block while the CPU is busy with something else. This is possible with the two non-blocking statements,

  1. I2C_MasterWriteBuf(uint8 slaveAddress, uint8 * wrData, uint8 cnt, uint8 mode) 
  2. uint8 I2C_MasterReadBuf(uint8 slaveAddress, uint8 * rdData, uint8 cnt, uint8 mode)

The paraameter mode determines the nature of the transfer(Complete I2C transfer, No Stop bit, Starts with a repeat start and so on).

Note that there are other set of APIs which are clearly described as blocking statement in the datasheet:

Example: uint8 I2C_MasterSendStart(uint8 slaveAddress, uint8 R_nW)

uint8 I2C_MasterWriteByte(uint8 theByte)


Tue, 21 Jun 2011 11:17:28 -0600