- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I've a project with I2C (slave and fixed function) and an ADC_SAR_Seq with many differential inputs (about 20).
ADC works perfect without cpu work (only to get values after a complete conversión of the 20 inputs).
But I2C doesn't work, the master says BUSY. After a while of testing and retesting I've tested omit ADC_SAR_Seq_StartConvert(); and voilá, I2C works perfect.
First I thought about high SPS, so down it. but no improvement, only omiting StartConvert solves the I2C problem.
Also commenting code into ADC ISR solves the problem and I2C begin to work.
The code for the I2C is simple and it's into the for loop:
if(0u != (I2C_SlaveStatus() & I2C_SSTAT_WR_CMPLT))
{
/* Read the number of bytes transferred */
byteCnt = I2C_SlaveGetWriteBufSize();
/* Clear the write status bits*/
I2C_SlaveClearWriteStatus();
/* Move the data written by the master to the read buffer so that the master can read back the data */
for(indexCntr = 0; indexCntr < byteCnt; indexCntr++)
{
rdBuf [indexCntr] = wrBuf[indexCntr]; /* Loop back the data to the read buffer */
}
/* Clear the write buffer pointer so that the next write operation will start from index 0 */
I2C_SlaveClearWriteBuf();
/* Clear the read buffer pointer so that the next read operations starts from index 0 */
I2C_SlaveClearReadBuf();
}
/* If the master has read the data , reset the read buffer pointer to 0 and clear the read status */
if(0u != (I2C_SlaveStatus() & I2C_SSTAT_RD_CMPLT))
{
/* Clear the read buffer pointer so that the next read operations starts from index 0 */
I2C_SlaveClearReadBuf();
/* Clear the read status bits */
I2C_SlaveClearReadStatus();
}
Again the code into the isr is simple:
CY_ISR( ADC_SAR_Seq_ISR )
{
int i;
for( i=0;i<20;i++)
{
ichannels = ADC_SAR_Seq_GetResult16(i);
}
}
Best regards.
- Labels:
-
PSoC 5LP
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I woulkd re-think how ISR handled.
Normally in ISR you want to just set a flag and exit, and service the isr in main().
That prevents stack push due to f() calls, etcc. adding extra latency.
Regards, Dana.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
My thought was that I2C component doesn't need mcu to work, so no ISR prevents from doing his work, and use a DMA for input/output info.
I need the ISR, get values and compare with a limit with a good latency (under 1ms, or 100us as I achieve now). A flag doesn't guarantee doing thinks with a good timing and depends on what is mcu doing.
How can we continue?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
When looking into the datasheet of I2C master fixed function or UDB implementation you'll see under "Resources" thatz both of them need an interrupt. Your interrupt-handler may consume too much time within the loop to allow a continous communicatzion.
To avoid that situation you could try to re-arrange the interrupt priortties givint the I2C a higher (lower number!) priority, so it will interrupt the SAR-handler or, as Dana suggested and proved to be correct, shorten the SAR-handler and move the handling out of the interrupt routine.
Bob
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I use I2C Slave, and fixed function, so I don't see any interrupt.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I didn't tell that it's a PSOC5.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
believe me, there is an interrupt handler for fixed function block I2C slave.
Go to "Generated Source" in Workspace Explorer and look for your I2C_INT.c file which contains the interrupt code.
When opening the .cydwr-file and opening the "Interrupts" tab you'll see that your I2C-slave is assigned the lowest(default) interrupt priority. Here you may assign a higher priority (lower number) to I2C.
Bob
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hopefully a PSoC5 LP ???
Bob
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Sorry for that many posts, but
Are you using Creator 2 or Creator 3 ?
Are you working with a PSoC5 or a PSoC5 LP?
Bob
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Creator 3
PSOC5LP
I see the I2C interrupt, sorry.
The first try was slowing clock for ADC (about 1Mhz, I can't less) so there was lesser interrupts, but no improvement. I don't believe that 60.000SPS with 20 channels (about 3000interrupts/sec) can prevent I2C from working.
Best regards.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I2C is realized with a state-machine, so the miss of an edge transition coud get it out of sync. Did you already try to change the priority?
Bob
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
3000 interrupts/s is not few. Depending on the amount of time you spend in your handler it might disturb some time-critical processes.
Bob