bones23 wrote on Friday, December 28, 2007:
I am trying to get an i2c driver running in freeRTOS on an str912. All it does right now is send a message continuously from the arm9 to a test device I have hooked up to the i2c bus. The i2c thread will run several hundred times just fine but will then throw a Prefetch abort. After stepping through the program I found that this happens in the call to vTaskDelay() made after the call to I2C_WriteData() has finished. Any ideas on what could be causing this?
//i2c thread
void prvRunI2C(void){
u8 i2cmsg[] = "test";
for(;;){
I2C_WriteData(0x6e, i2cmsg, 4);
vTaskDelay( mainLCD_DELAY );
}
}
//I2C_WriteData()
void I2C_WriteData(u8 address, u8 *msg, u8 count)
{
portENTER_CRITICAL();
I2C0_Buffer_Tx= msg;
i2c_buffer_size=count;
i2c_slave_address = address;
Direction = I2C_MODE_TRANSMITTER;
Tx_Idx=0;
{
char hex1[3];
char hex2[3];
char hex3[3];
hex1[2] = hex2[2] = hex3[2] = 0;
byte2hex(I2C0_Buffer_Tx[0], hex1);
byte2hex(I2C0_Buffer_Tx[1], hex2);
byte2hex(I2C0_Buffer_Tx[2], hex3);
}
I2C_GenerateStart(I2C0, ENABLE);
/* Test on EV5 and clear it */
while( ! I2C_CheckEvent(I2C0, I2C_EVENT_MASTER_MODE_SELECT) ) // EV5
{;
}
/* Send I2C1 Address for write */
I2C_Send7bitAddress (I2C0, i2c_slave_address, I2C_MODE_TRANSMITTER);
/* Test on EV6 and clear it */
while( ! I2C_CheckEvent(I2C0, I2C_EVENT_MASTER_MODE_SELECTED) ); // EV6
/* Clear EV6 by set again the PE bit */
I2C_Cmd (I2C0, ENABLE);
/* Send Data to write on I2C1 slave */
while (Tx_Idx < i2c_buffer_size)// && !stop)
{
/*snprintf(out_buf, 80, "sending byte: %d\r\n", Tx_Idx);
send_data(DEBUG_UART, out_buf, strlen(out_buf) );
*/
/* Send Master data */
I2C_SendData(I2C0, I2C0_Buffer_Tx[Tx_Idx++]);
/* Test on EV8 and clear it */
while(!I2C_CheckEvent(I2C0, I2C_EVENT_MASTER_BYTE_TRANSMITTED))// && !stop) //EV8
{
u16 wLastEvent = I2C_GetLastEvent(I2C0);
switch (wLastEvent)
{
/* 16 means that the BUSY flag is set, but not the M/SL flag.
Since we mean to act only as a master, the M/SL flag should be
set anytime we are in the middle of transmission*/
/*case 16:
stop = 1;
snprintf(out_buf, 80, "I2C Error, wLastEvent==16\r\n");
send_data(DEBUG_UART, out_buf, strlen(out_buf));
if (wLastEvent == I2C_ARBITRATION_LOST)
{
snprintf(out_buf, 80, "I2C Arbitration Lost\r\n");
send_data(DEBUG_UART, out_buf, strlen(out_buf));
stop=1; //Leave the while loop
}
if (wLastEvent == I2C_BUS_ERROR_DETECTED)
{
snprintf(out_buf, 80, "I2C Bus Error\r\n");
send_data(DEBUG_UART, out_buf, strlen(out_buf));
stop=1; //Leave the while loop
}
break;
case 0:
snprintf(out_buf, 80, "I2C status of 0, stopping\r\n");
send_data(DEBUG_UART, out_buf, strlen(out_buf));
stop = 1;
break;*/
CASE_ERROR(I2C_EVENT_SLAVE_ADDRESS_MATCHED)
CASE_ERROR(I2C_EVENT_SLAVE_BYTE_RECEIVED)
CASE_ERROR(I2C_EVENT_SLAVE_BYTE_TRANSMITTED)
CASE_ERROR(I2C_EVENT_MASTER_MODE_SELECT)
CASE_ERROR(I2C_EVENT_MASTER_MODE_SELECTED)
CASE_ERROR(I2C_EVENT_MASTER_BYTE_RECEIVED)
//CASE_ERROR(I2C_EVENT_MASTER_BYTE_TRANSMITTED)
case I2C_EVENT_MASTER_BYTE_TRANSMITTED:
break;
CASE_ERROR(I2C_EVENT_MASTER_MODE_ADDRESS10)
CASE_ERROR(I2C_EVENT_SLAVE_STOP_DETECTED)
CASE_ERROR(I2C_EVENT_SLAVE_ACK_FAILURE)
case 18: /*This is the correct busy state, busy flag, plus m/sl flag*/
break;
default:
UART_printf(DEBUG_UART, "unknown event: %d on byte: %d\r\n", wLastEvent, Tx_Idx);
break;
}
}
}
/* Generate STOP condition to close communication */
I2C_GenerateSTOP (I2C0, ENABLE);
/* Disable I2C0 */
//I2C_Cmd(I2C0, DISABLE);
portEXIT_CRITICAL();
}