This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Tool/software: TI C/C++ Compiler
Hi Pals,
I set 10 I2C peripherals (I2C0~9) to read / write data, and met hard fault again.
If I disable or change to be FIFO on I2C3 & I2C4 &I2C7, the function is no problem.
Please kindly to review my code and provide your advise, thanks.
int main(void)
{
// uint16_t inVersion;
//uint32_t uiLoopTest=0;
volatile uint32_t ui32Boot = 0;
uint8_t nPntCnt=25,nPntCnt2=26,nMaxPntCnt=0;
uint8_t nPalmCnt=30,nPalmCnt2=31,nMaxPalmCnt=0;
uint8_t i;
g_ShotProtect=1;
#ifdef TI_Board
g_ui32SysClock = MAP_SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
SYSCTL_OSC_MAIN | SYSCTL_USE_PLL |
SYSCTL_CFG_VCO_480), 120000000);
#else
g_ui32SysClock = MAP_SysCtlClockFreqSet((SYSCTL_XTAL_12MHZ|
SYSCTL_OSC_MAIN | SYSCTL_USE_PLL |
SYSCTL_CFG_VCO_480), 120000000);
#endif
//gpio port function init
PortFunctionInit();
#ifdef TI_Board
ConfigureDBGUART(3,115200); //can't use port 0, uart0 conflict with I2C9
#else
ConfigureDBGUART(2,115200); //can't use port 0, uart0 conflict with I2C9
#endif
UARTprintf("Configure___________OK!!!\n");
PowerOnEnable();
I2C_InitialAll(I2C_EN);
I2C_DMAInitialAll(I2C_DMA_EN);
//#define SLAVE_0_EN 0x0001
//#define SLAVE_1_EN 0x0002
//#define SLAVE_2_EN 0x0004
//#define SLAVE_3_EN 0x0008
//#define SLAVE_4_EN 0x0010
//#define SLAVE_5_EN 0x0020
//#define SLAVE_6_EN 0x0040
//#define SLAVE_7_EN 0x0080
//#define SLAVE_8_EN 0x0100
//#define SLAVE_9_EN 0x0200
//#define I2C_EN (0x3FF) //-->Function is ok if defined 0x367
//#define I2C_DMA_EN (0x3FF) //-->Function is ok if defined 0x367
I2CMaster_Speed(I2C_SPEED_400K);
vfDelay_ms(1);
Flash_Test();
while(1){ };
}
void I2C_InitialAll(uint16_t u16MaskCH)
{
uint8_t i;
for (i=0; i<10; i++)
{
if(u16MaskCH & ( 1 << i ))
{
SysCtlPeripheralDisable(I2C_PERIPH[i]);
SysCtlPeripheralReset(I2C_PERIPH[i]);
SysCtlPeripheralEnable(I2C_PERIPH[i]);
while(!SysCtlPeripheralReady(I2C_PERIPH[i]));
GPIOPinTypeI2C(I2C_PIN_BASE[i], I2C_SDA_PIN[i]);
GPIOPinTypeI2CSCL(I2C_PIN_BASE[i], I2C_SCL_PIN[i]);
GPIOPinConfigure(I2C_SDA[i]);
GPIOPinConfigure(I2C_SCL[i]);
HWREG(I2C_PIN_BASE[i] + GPIO_O_PUR) = (I2C_SDA_PIN[i]|I2C_SCL_PIN[i]);
I2CRxFIFOConfigSet(I2C_BASE[i], (I2C_FIFO_CFG_RX_MASTER_DMA | I2C_FIFO_CFG_RX_TRIG_8));
I2CTxFIFOConfigSet(I2C_BASE[i], (I2C_FIFO_CFG_TX_MASTER_DMA));
I2CRxFIFOFlush(I2C_BASE[i]);
I2CTxFIFOFlush(I2C_BASE[i]);
I2CMInit(&g_sI2CMInst[i], I2C_BASE[i], I2C_INT[i], 0xff, 0xff, g_ui32SysClock, 1);
I2CIntRegister(I2C_BASE[i], pISRHandler[i]);
}
}
#if 0
if(SLAVE_3_EN & u16MaskCH)
{
I2CRxFIFOConfigSet(I2C_BASE[3], I2C_FIFO_CFG_RX_MASTER);
I2CTxFIFOConfigSet(I2C_BASE[3], I2C_FIFO_CFG_TX_MASTER);
}
if(SLAVE_4_EN & u16MaskCH)
{
I2CRxFIFOConfigSet(I2C_BASE[4], I2C_FIFO_CFG_RX_MASTER);
I2CTxFIFOConfigSet(I2C_BASE[4], I2C_FIFO_CFG_TX_MASTER);
}
if(SLAVE_5_EN & u16MaskCH)
{
I2CRxFIFOConfigSet(I2C_BASE[5], I2C_FIFO_CFG_RX_MASTER);
I2CTxFIFOConfigSet(I2C_BASE[5], I2C_FIFO_CFG_TX_MASTER);
}
if(SLAVE_7_EN & u16MaskCH)
{
I2CRxFIFOConfigSet(I2C_BASE[7], I2C_FIFO_CFG_RX_MASTER);
I2CTxFIFOConfigSet(I2C_BASE[7], I2C_FIFO_CFG_TX_MASTER);
}
#else
if(SLAVE_5_EN & u16MaskCH)
{
I2CRxFIFOConfigSet(I2C_BASE[5], I2C_FIFO_CFG_RX_MASTER);
I2CTxFIFOConfigSet(I2C_BASE[5], I2C_FIFO_CFG_TX_MASTER);
}
#endif
}
void I2C_DMAInitialAll(uint16_t u16MaskCH)
{
uint8_t i;
SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA);
SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_UDMA);
IntEnable(INT_UDMAERR);
uDMAEnable();
uDMAControlBaseSet(pui8ControlTable);
IntEnable(INT_UDMA);
for (i=0; i<10; i++)
{
#if 0
if(u16MaskCH & ( 1 << i ) && (i != 3)&&(i!=4)&&(i!=5)&&(i!=7))//if(u16MaskCH & ( 1 << i ) && (i != 5))
#else
if(u16MaskCH & ( 1 << i ) && (i != 5))
#endif
{
uDMAChannelAssign(DMA_I2CTX[i]);
uDMAChannelAttributeDisable(DMA_I2CTX[i],
UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST | UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK);
uDMAChannelControlSet(DMA_I2CTX[i] | UDMA_PRI_SELECT,
UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_4);
uDMAChannelAssign(DMA_I2CRX[i]);
uDMAChannelAttributeDisable(DMA_I2CRX[i],
UDMA_ATTR_USEBURST | UDMA_ATTR_ALTSELECT | (UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK));
uDMAChannelControlSet(DMA_I2CRX[i] | UDMA_PRI_SELECT,
UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_8 | UDMA_ARB_4);
//uDMAIntRegister
}
}
}
void I2C_DMAWriteAll(uint16_t u16MaskCH, uint8_t (*pu8TxBuffer)[200], uint16_t u16Len)
{
uint8_t u8CH;
uint16_t u16Free=0, u16Cnt=0;
// DMA setting ========================================================================
for(u8CH=0; u8CH<10; u8CH++)
{
#if 0
if(u16MaskCH & ( 1 << u8CH ) && (u8CH != 3)&&(u8CH!=4)&&(u8CH!=5)&&(u8CH!=7))
#else
if((u16MaskCH & (1<<u8CH)) && (u8CH != 5))
#endif
{
I2CMasterSlaveAddrSet(I2C_BASE[u8CH], I2C_SLAVE_ADDR, false);
uDMAChannelTransferSet(DMA_I2CTX[u8CH] | UDMA_PRI_SELECT, UDMA_MODE_BASIC,
pu8TxBuffer[u8CH], ((void *)(I2C_BASE[u8CH] + I2C_O_FIFODATA)), u16Len);
uDMAChannelEnable(DMA_I2CTX[u8CH]);
I2CMasterBurstLengthSet(I2C_BASE[u8CH], u16Len);
}
}
// DMA star ========================================================================
for(u8CH=0; u8CH<10; u8CH++)
{
#if 0
if(u16MaskCH & ( 1 << u8CH ) && ((u8CH != 3)&&(u8CH!=4)&&(u8CH!=5)&&(u8CH!=7)))//
#else
if((u16MaskCH & (1<<u8CH)) && (u8CH != 5))
#endif
I2CMasterControl(I2C_BASE[u8CH], I2C_MASTER_CMD_FIFO_SINGLE_SEND);
}
SysCtlDelay(1000);
// I2C5 start ========================================================================
#if 0
if((SLAVE_3_EN & u16MaskCH)|(SLAVE_4_EN & u16MaskCH)|(SLAVE_5_EN & u16MaskCH)|(SLAVE_7_EN & u16MaskCH))//if(SLAVE_5_EN & u16MaskCH)
{
// I2C_Write(I2C_SLAVE_ADDR, pu8TxBuffer[5], u16Len);
// //I2C0_FIFO_Write(pu8TxBuffer[5], u16Len);
// while(I2CMasterBusy(I2C_BASE[5]));
if(SLAVE_3_EN & u16MaskCH)
{
I2C_Write(3,I2C_SLAVE_ADDR, pu8TxBuffer[3], u16Len);
}
if(SLAVE_4_EN & u16MaskCH)
{
I2C_Write(4,I2C_SLAVE_ADDR, pu8TxBuffer[4], u16Len);
}
if(SLAVE_5_EN & u16MaskCH)
{
I2C_Write(5,I2C_SLAVE_ADDR, pu8TxBuffer[5], u16Len);
}
if(SLAVE_7_EN & u16MaskCH)
{
I2C_Write(7,I2C_SLAVE_ADDR, pu8TxBuffer[7], u16Len);
}
if(SLAVE_3_EN & u16MaskCH)
{
while(I2CMasterBusy(I2C_BASE[3]));
}
if(SLAVE_4_EN & u16MaskCH)
{
while(I2CMasterBusy(I2C_BASE[4]));
}
if(SLAVE_5_EN & u16MaskCH)
{
while(I2CMasterBusy(I2C_BASE[5]));
}
if(SLAVE_7_EN & u16MaskCH)
{
while(I2CMasterBusy(I2C_BASE[7]));
}
}
#else
if(SLAVE_5_EN & u16MaskCH)
{
I2C_Write(5,I2C_SLAVE_ADDR, pu8TxBuffer[5], u16Len); <-- *******Get stuck here in debug mode********
//I2C0_FIFO_Write(pu8TxBuffer[5], u16Len);
while(I2CMasterBusy(I2C_BASE[5]));
}
#endif
// Wait for bus free ========================================================================
while(u16Cnt<5000)
{
SysCtlDelay(1000);
u16Cnt++;
for(u8CH=0; u8CH<10; u8CH++)
{
if((u16MaskCH & (1<<u8CH)) && (I2CMasterBusy(I2C_BASE[u8CH]) == false))
u16Free |= (1 << u8CH);
}
if(u16MaskCH == u16Free)
break;
}
if(u16Cnt == 5000)
UARTprintf("\nWrite ERROR!!!");
}
void I2C_DMAReadAll(uint16_t u16MaskCH, uint8_t (*pu8RxBuffer)[200], uint16_t u16Len)
{
uint8_t u8CH;
uint16_t u16Free=0, u16Cnt=0;
// DMA setting ========================================================================
for(u8CH=0; u8CH<10; u8CH++)
{
if(u16MaskCH & (1<<u8CH) && (u8CH != 5))
{
I2CMasterSlaveAddrSet(I2C_BASE[u8CH], I2C_SLAVE_ADDR, true);
I2CMasterBurstLengthSet(I2C_BASE[u8CH], u16Len);
uDMAChannelTransferSet(DMA_I2CRX[u8CH] | UDMA_PRI_SELECT, UDMA_MODE_BASIC,
((void *)(I2C_BASE[u8CH] + I2C_O_FIFODATA)), pu8RxBuffer[u8CH], u16Len);
uDMAChannelEnable(DMA_I2CRX[u8CH]);
}
}
// DMA star ========================================================================
for(u8CH=0; u8CH<10; u8CH++)
{
#if 0
if(u16MaskCH & ( 1 << u8CH ) && ((u8CH != 3)&&(u8CH!=4)&&(u8CH!=5)&&(u8CH!=7)))
#else
if(u16MaskCH & (1<<u8CH) && (u8CH != 5))
#endif
I2CMasterControl(I2C_BASE[u8CH], I2C_MASTER_CMD_FIFO_SINGLE_RECEIVE);
}
// I2C5 start ========================================================================
// if(SLAVE_5_EN & u16MaskCH)
// {
// I2C_Read(I2C_SLAVE_ADDR, pu8RxBuffer[5], u16Len);
// while(I2CMasterBusy(I2C_BASE[5]));
// }
#if 0
if((SLAVE_3_EN & u16MaskCH)|(SLAVE_4_EN & u16MaskCH)|(SLAVE_5_EN & u16MaskCH)|(SLAVE_7_EN & u16MaskCH))//if(SLAVE_5_EN & u16MaskCH)
{
// I2C_Write(I2C_SLAVE_ADDR, pu8TxBuffer[5], u16Len);
// //I2C0_FIFO_Write(pu8TxBuffer[5], u16Len);
// while(I2CMasterBusy(I2C_BASE[5]));
if(SLAVE_3_EN & u16MaskCH)
{
I2C_Read(3,I2C_SLAVE_ADDR, pu8RxBuffer[3], u16Len);
}
if(SLAVE_4_EN & u16MaskCH)
{
I2C_Read(4,I2C_SLAVE_ADDR, pu8RxBuffer[4], u16Len);
}
if(SLAVE_5_EN & u16MaskCH)
{
I2C_Read(5,I2C_SLAVE_ADDR, pu8RxBuffer[5], u16Len);
}
if(SLAVE_7_EN & u16MaskCH)
{
I2C_Read(7,I2C_SLAVE_ADDR, pu8RxBuffer[7], u16Len);
}
if(SLAVE_3_EN & u16MaskCH)
{
while(I2CMasterBusy(I2C_BASE[3]));
}
if(SLAVE_4_EN & u16MaskCH)
{
while(I2CMasterBusy(I2C_BASE[4]));
}
if(SLAVE_5_EN & u16MaskCH)
{
while(I2CMasterBusy(I2C_BASE[5]));
}
if(SLAVE_7_EN & u16MaskCH)
{
while(I2CMasterBusy(I2C_BASE[7]));
}
}
#else
if(SLAVE_5_EN & u16MaskCH)
{
I2C_Read(5,I2C_SLAVE_ADDR, pu8RxBuffer[5], u16Len);
//I2C0_FIFO_Write(pu8TxBuffer[5], u16Len);
while(I2CMasterBusy(I2C_BASE[5]));
}
#endif
// Wait for bus free ========================================================================
while(u16Cnt<5000)
{
SysCtlDelay(1000);
u16Cnt++;
for(u8CH=0; u8CH<10; u8CH++)
{
if((u16MaskCH & (1<<u8CH)) && (I2CMasterBusy(I2C_BASE[u8CH]) == false))
u16Free |= (1 << u8CH);
}
if(u16MaskCH == u16Free)
break;
}
if(u16Cnt == 5000)
UARTprintf("\nRead ERROR!!!");
}
void Flash_Test(void)
{
uint8_t u8i;
uint8_t data[5];
// Enter the Serial Debug Mode
data[0] = 0x53;
data[1] = 0x45;
data[2] = 0x52;
data[3] = 0x44;
data[4] = 0x42;
for(u8i=0;u8i<10;u8i++)
{
if(I2C_EN&(1<<u8i))
{
memcpy(&(gau8TxBuf[u8i][0]),data,sizeof(data));
}
}
I2C_DMAWriteAll(I2C_EN, gau8TxBuf, 5);
delay_1ms();
}
Charles Tsai said:I will also suggest that you first try to limit the number of I2C and gradually increase one by one.
Or - to state this in two words, "employ KISS."
I (also) note a, "hard-coded" DELAY w/in the code - the "Cascade of I2C calls" may "so build" that a test for "I2C Peripheral Ready" (instead of a delay) - proves far more robust!
Hi,
I am QZboy's colleague.
QZboy said, only fail when do config both i2c6 and i2c7 using i2c+udma.
How to add a delay during transfer data via udma?
I think that is only hardware operation, is it right?
Greetings,
We note 3 occurrences of: "SysCtlDelay(1000); " w/in your program. You must determine if this value delay (always) proves proper - and/or - if a "Peripheral Ready" call proves superior.
Both the vendor (via many words) and I (via 2, "Use KISS") suggested that your program code be reduced to just those parts which (for now) result in Faults.
It is usual that, "Obtaining proper code operation" proves "faster & easier" when tasks are, "Reduced in Number." Only when each task has achieved great success - should another task be (then) "Added to the Mix." Your current method appears to, "Continue to attempt to "DO EVERYTHING" - which I have found to, "ADD UNNECESSARY COMPLICATIONS" - and make your "FIX" both "Harder and Longer to achieve!"
Again - I'd focus on your "failing functions ALONE" - I suspect you will (greatly) benefit by learning:
I must note that, "Even upon reading your thread's Subject/Title ... "TEN Sets i2C" - the "Rejection of KISS was most apparent" - and your "problems" were (almost) GUARANTEED! Simplify!
QZboy said:I want to use 10 sets I2C to read/write 10 devices in the same time
This (likely) is a, "language issue" - you don't (really) expect to "Read/Write 10 "I2C devices" (simultaneously) - do you? (such is what your writing suggests...And quite impossible!)
Vendor agents are most talented at, "Digging thru the datasheet" - should you seek a more "General Problem Solving Method" - I'll try to assist.
QZboy said:--> I2C3 and I2C4 can't use DMA, but it works in INTERRUPTmode.
I2C3 and I2C4 use different DMA channels according to the datasheet. Did it work for you if you only use I2C3 with uDMA or I2C4 with uDMA but not both of them together?
QZboy said:2. I2C5 & I2C8 is the same uDMA channel (refer to the Datasheet)
--> I set I2C5 to "INTERRUPT" mode, and set I2C8 to DMA mode; It seems work now.
You are correct that I2C5 and I2C8 share the same channels so you can use DMA on both of them at the same time.
QZboy said:3. I2C6/I2C7 works in INTERRUPT and DMA mode INDIVIDUALLY, but can't set both to DMA mode.
--> I guess that is the same uDMA channel, and need your confirm.
According to the datasheet, the I2C6 uses channel 26/27 while the I2C7 uses channel 28/29.
Will Wu said:We really need to use ten sets of i2c transfer at same time.
As noted previously - much depends upon your definition of, "at same time." (it is assumed that you intend, "simultaneously.")
While the use of the "MCU's µDMA" may (somewhat) automate the I2C transfer process - it is doubted that, "All ten I2C channels" can, "Operate w/out compromise" - at the standard I2C data rate. (commentary by Vendor Agents would prove (greatly) helpful - and is much invited - in this "Ten I2C channel, simultaneous operation's" regard!)
At some point - it is expected - that the MCU must "Deal w/the µDMA managed data" - and in that process - (any) simultaneous operation exceeds my recognition/understanding...
Hi Charles,
Thank you for so well noting that, "One and ONLY One - I2C Peripheral Module - may "transact" at any given time!" Poster has "Rejected or Over-Looked" that reality - my writings attempted to alert poster - hearing from you (the Vendor) ... (may) now bring about his "acceptance!" Maybe...