Cypress Perform

Home > Design Support > Cypress Developer CommunityTM > Cypress Forums > PSoC® 5 > Non-blocking communications

Bookmark and Share
Cypress Developer CommunityTM
Forums | Videos | Blogs | Training | Rewards Program | Community Components



Non-blocking communications
Moderator:
ANCY

Post Reply
Follow this topic



Non-blocking communications

Doug McClean posted on 20 Jun 2011 9:10 AM PST
Top Contributor
38 Forum Posts

I'm setting up some I2C communications (although, quickly perusing the datasheet for the UART and SPI components, I think that analogous issues may exist there too) and I'm confused by the API.

It seems that all the sending/receiving functions are blocking. Are there no functions for initiating a transfer, letting the hardware mess with it at the much slower I2C clock, and then have it trigger an interrupt?

I may just be confused. I thought the idea of the hardware I2C transceiver was to allow it to operate on the slow clock while the processor does other things on the fast clock? Or is this scenario supported through messing directly with the registers, but not supported through the API?




Re: Non-blocking communications

U2 posted on 21 Jun 2011 09:17 AM PST
Cypress Employee
589 Forum Posts

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)

 



Re: Non-blocking communications

Doug McClean posted on 21 Jun 2011 11:37 AM PST
Top Contributor
38 Forum Posts

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;

}



Re: Non-blocking communications

Doug McClean posted on 21 Jun 2011 11:39 AM PST
Top Contributor
38 Forum Posts

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.)



Re: Non-blocking communications

Doug McClean posted on 21 Jun 2011 12:43 PM PST
Top Contributor
38 Forum Posts

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?



Re: Non-blocking communications

Gautam Das posted on 27 Jun 2011 11:54 PM PST
Cypress Employee
742 Forum Posts

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

1) I2C_MODE_REPEAT_START = 0x01

2) I2C_MODE_COMPLETE_XFER = 0x00

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.



Re: Non-blocking communications

Doug McClean posted on 27 Jun 2011 12:32 PM PST
Top Contributor
38 Forum Posts

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.

 



Re: Non-blocking communications

Doug McClean posted on 01 Jan 2012 11:40 AM PST
Top Contributor
38 Forum Posts

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?



Re: Non-blocking communications

Bob Marlowe posted on 02 Jan 2012 02:12 AM PST
Top Contributor
1768 Forum Posts

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

Bob



Re: Non-blocking communications

Doug McClean posted on 02 Jan 2012 09:51 AM PST
Top Contributor
38 Forum Posts

Thanks Bob, that's not a bad idea.






ALL CONTENT AND MATERIALS ON THIS SITE ARE PROVIDED "AS IS". CYPRESS SEMICONDUCTOR AND ITS RESPECTIVE SUPPLIERS MAKE NO REPRESENTATIONS ABOUT THE SUITABILITY OF THESE MATERIALS FOR ANY PURPOSE AND DISCLAIM ALL WARRANTIES AND CONDITIONS WITH REGARD TO THESE MATERIALS, INCLUDING BUT NOT LIMITED TO, ALL IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT OF ANY THIRD PARTY INTELLECTUAL PROPERTY RIGHT. NO LICENSE, EITHER EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, IS GRANTED BY CYPRESS SEMICONDUCTOR. USE OF THE INFORMATION ON THIS SITE MAY REQUIRE A LICENSE FROM A THIRD PARTY, OR A LICENSE FROM CYPRESS SEMICONDUCTOR.

Content on this site may contain or be subject to specific guidelines or limitations on use. All postings and use of the content on this site are subject to the Terms and Conditions of the site; third parties using this content agree to abide by any limitations or guidelines and to comply with the Terms and Conditions of this site. Cypress Semiconductor and its suppliers reserve the right to make corrections, deletions, modifications, enhancements, improvements and other changes to the content and materials, its products, programs and services at any time or to move or discontinue any content, products, programs, or services without notice.

Spec No: None; Sunset Owner: KXP; Secondary Owner: VWA; Sunset Date: 01/01/20