cancel
Showing results for 
Search instead for 
Did you mean: 

PSoC 5, 3 & 1 MCU

MaGa_1759861
New Contributor II

I need to read more than 256 bytes from an I2C peripheral in a single transfer.

The standard component I2CM_0_MasterReadBuf() and associated ISR are limited to 256 bytes due to the cnt variable being uint8 instead of (a more useful) uint16. This is something that does not appear to be configurable at the build level.

I can create a copy of the API function to use locally but is there any way to override the ISR in the build with my own version where I can also change the counter size?

0 Likes
1 Solution
MaGa_1759861
New Contributor II

I have resolved this, the trick is in the mode parameter I2CM_MasterReadBuf().

I was able to split the transfer into two consecutive calls:

for the first mode = I2C_MODE_NO_STOP,

for the second mode = I2C_MODE_RESTART.

However it's not clear how you could do more than two blocks in a transfer without a STOP, I tried consecutive intermediate blocks with each  setting mode to:

I2C_MODE_REPEAT_START

I2C_MODE_NO_STOP

I2C_MODE_REPEAT_START | I2C_MODE_NO_STOP   /* this is really what you want to work */

The first of these puts a stop on the bus, the latter two end up at the CYASSERT() in the ISR

            case I2CM_0_SM_MSTR_RD_ADDR:  /* After address is sent, read data */

.........

                else

                {

                    /* Address phase is not set for some reason: error */

                    #if(I2CM_0_TIMEOUT_ENABLED)

                        /* Exit interrupt to take chance for timeout timer to handle this case */

                        I2CM_0_DisableInt();

                        I2CM_0_ClearPendingInt();

                    #else

                        /* Block execution flow: unexpected condition */

                        CYASSERT(0u != 0u);

                    #endif /* (I2CM_0_TIMEOUT_ENABLED) */

                }

                break;

Fortunately < 512 bytes is enough for my application!

View solution in original post

0 Likes
1 Reply
MaGa_1759861
New Contributor II

I have resolved this, the trick is in the mode parameter I2CM_MasterReadBuf().

I was able to split the transfer into two consecutive calls:

for the first mode = I2C_MODE_NO_STOP,

for the second mode = I2C_MODE_RESTART.

However it's not clear how you could do more than two blocks in a transfer without a STOP, I tried consecutive intermediate blocks with each  setting mode to:

I2C_MODE_REPEAT_START

I2C_MODE_NO_STOP

I2C_MODE_REPEAT_START | I2C_MODE_NO_STOP   /* this is really what you want to work */

The first of these puts a stop on the bus, the latter two end up at the CYASSERT() in the ISR

            case I2CM_0_SM_MSTR_RD_ADDR:  /* After address is sent, read data */

.........

                else

                {

                    /* Address phase is not set for some reason: error */

                    #if(I2CM_0_TIMEOUT_ENABLED)

                        /* Exit interrupt to take chance for timeout timer to handle this case */

                        I2CM_0_DisableInt();

                        I2CM_0_ClearPendingInt();

                    #else

                        /* Block execution flow: unexpected condition */

                        CYASSERT(0u != 0u);

                    #endif /* (I2CM_0_TIMEOUT_ENABLED) */

                }

                break;

Fortunately < 512 bytes is enough for my application!

View solution in original post

0 Likes