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.
I'm having trouble using the I2C interface with the ROM boot loader active. I don't get the reponses I expect.
Code from my I2C master:
#define TIVA_DEVICEADDRESS (0x42<<1) uint8 status_cmd = COMMAND_GET_STATUS; uint8 ping_cmd = COMMAND_PING; void EeSetStart(void) { volatile uint16 x; // Start condition ACCESS2_CTRL_REG &= ~(EN_ACCESS_BUS); x++; // 624 ns ACCESS2_CTRL_REG |= (SCL_VAL | SDA_VAL); BusyWait1(); ACCESS2_CTRL_REG &= ~(SDA_VAL); BusyWait1(); ACCESS2_CTRL_REG &= ~(SCL_VAL); BusyWait1(); } void EeSetStop(void) { // stop condition ACCESS2_CTRL_REG &= ~(EN_ACCESS_BUS); ACCESS2_CTRL_REG &= ~(SCL_VAL | SDA_VAL); BusyWait1(); ACCESS2_CTRL_REG |= SCL_VAL; BusyWait1(); ACCESS2_CTRL_REG |= SDA_VAL; BusyWait1(); } void EeSendByte(BYTE a) { volatile WORD n; ACCESS2_CTRL_REG |= EN_ACCESS_BUS; // automatic control SDA/SCL-VAL n++; // this is neccesssary to delay following events ACCESS2_CLEAR_INT_REG = 0; ACCESS2_IN_OUT_REG=a; // Wait until transmission is done while (!(ACCESS2_CTRL_REG & ACCESSx_INT)) ; ACCESS2_CLEAR_INT_REG = 0; } BYTE ReadByte_Ack(UByte nextNoAck) { volatile uint16 Read = 0; ACCESS2_CTRL_REG &= ~ACKn; while (!(ACCESS2_CTRL_REG & ACCESSx_INT)); Read=ACCESS2_IN_OUT_REG; // Read received byte ACCESS2_CLEAR_INT_REG = 0; if (nextNoAck) { ACCESS2_CTRL_REG |= ACKn; // don't transmit Acknowledge } return(Read); } BYTE ReadByte_NoAck(void) { volatile uint16 Read = 0; ACCESS2_CTRL_REG |= ACKn; // don't transmit Acknowledge while (!(ACCESS2_CTRL_REG & ACCESSx_INT)); Read=ACCESS2_IN_OUT_REG; // Read received byte ACCESS2_CLEAR_INT_REG = 0; return(Read); } uint8 send_packet(uint8* data, uint8 size) { uint8 i, ack, checksum = 0; for (i = 0; i < size; i++) { checksum += data[i]; } do { EeSetStop(); EeSetStart(); EeSendByte(TIVA_DEVICEADDRESS); } while (ACCESS2_CTRL_REG & ACKn); EeSetStop(); EeSetStart(); EeSendByte(size +2); EeSendByte(checksum); for (i = 0; i < size; i++) { EeSendByte(data[i]); } EeSetStart(); // Set Device address for read EeSendByte(TIVA_DEVICEADDRESS|0x01); ack = ReadByte_NoAck(); debugf("-%02X-\n", ack); EeSetStop(); return ack; } uint8 get_packet(uint8* data, uint8* size) { uint8 i, psize, pchecksum, checksum = 0; do { EeSetStop(); EeSetStart(); EeSendByte(TIVA_DEVICEADDRESS); } while (ACCESS2_CTRL_REG & ACKn); EeSetStart(); EeSendByte(TIVA_DEVICEADDRESS|0x01); psize = ReadByte_Ack(0); debugf("psize = %02X\n", psize); if (psize < *size) *size = psize; pchecksum = ReadByte_Ack(0); debugf("pchecksum = %02X\n", pchecksum); for (i = 0; i < *size; i++) { if (i == (*size-1)) { data[i] = ReadByte_NoAck(); } else if (i == (*size-2)) { ReadByte_Ack(1); } else { data[i] = ReadByte_Ack(0); } } for (i = 0; i < *size; i++) { checksum = data[i]; } EeSetStart(); // Set Device address for write EeSendByte(TIVA_DEVICEADDRESS); if (checksum == pchecksum) { EeSendByte(COMMAND_ACK); EeSetStop(); return COMMAND_ACK; } else { EeSendByte(COMMAND_NAK); EeSetStop(); return COMMAND_NAK; } } uint8 send_command(uint8* cmd, uint8 size) { uint8 ret; uint8 status, ssize; ret = send_packet(cmd, size); ret = send_packet(&status_cmd, 1); ssize = sizeof(status); ret = get_packet(&status, &ssize); debugf("status: %02X\n", status); return ret; }
void tiva_main()
{
send_commnad(&ping_cmd, 1);
}
Output from my debug interface:
-c2- <-- expected 0xCC = COMMAND_ACK -c2- <-- expected 0xCC = COMMAND_ACK psize = c2 <-- expected 1 pchecksum = f0 <-- expected 0x40 status: fc <-- expected 0x40 = COMMAND_RET_SUCCESS
Any ideas?
Hello Thomas
The first command response 0xC2 is not defined in the bl_cmmands.h. Do you have the I2C Transaction captured on the scope for the PING Command?
Regards
Amit
I simplified my code to just send a ping, but I get different responses. On 1st run I get 0x00, 2nd run I get 0xCC and for the following runs I get 0xC2.
void EeSetStart(void) { volatile uint16 x; // Start condition ACCESS2_CTRL_REG &= ~(EN_ACCESS_BUS); // manual control SDA/SCL-VAL x++; // 624 ns ACCESS2_CTRL_REG |= (SCL_VAL | SDA_VAL); BusyWait1(); BusyWait1(); ACCESS2_CTRL_REG &= ~(SDA_VAL); BusyWait1(); BusyWait1(); ACCESS2_CTRL_REG &= ~(SCL_VAL); // 1200 ns (clock pulse width low) BusyWait1(); BusyWait1(); } void EeSetStop(void) { // stop condition ACCESS2_CTRL_REG &= ~(EN_ACCESS_BUS); // manual control SDA/SCL-VAL ACCESS2_CTRL_REG &= ~(SCL_VAL | SDA_VAL); BusyWait1(); BusyWait1(); ACCESS2_CTRL_REG |= SCL_VAL; BusyWait1(); BusyWait1(); ACCESS2_CTRL_REG |= SDA_VAL; BusyWait1(); BusyWait1(); } void EeSendByte(BYTE a) { volatile WORD n; ACCESS2_CTRL_REG |= EN_ACCESS_BUS; // automatic control SDA/SCL-VAL BusyWait1(); ACCESS2_CLEAR_INT_REG = 0; ACCESS2_IN_OUT_REG=a; BusyWait1(); // Wait until transmission is done while (!(ACCESS2_CTRL_REG & ACCESSx_INT)) ; ACCESS2_CLEAR_INT_REG = 0; } BYTE ReadByteTiva(void) { volatile uint16 Read = 0; while (!(ACCESS2_CTRL_REG & ACCESSx_INT)); Read=ACCESS2_IN_OUT_REG; // Read received byte ACCESS2_CLEAR_INT_REG = 0; return(Read); } uint8 send_packet(uint8* data, uint8 size) { uint8 i, ack, ack2, checksum = 0; for (i = 0; i < size; i++) { checksum += data[i]; } debugf("checksum: %02X\n", checksum); do { EeSetStart(); EeSendByte(TIVA_DEVICEADDRESS); } while (ACCESS2_CTRL_REG & ACKn); EeSendByte(size +2); EeSendByte(checksum); for (i = 0; i < size; i++) { EeSendByte(data[i]); } EeSetStart(); // Set Device address for read EeSendByte(TIVA_DEVICEADDRESS|0x01); while (ACCESS2_CTRL_REG & ACKn); ACCESS2_CTRL_REG |= ACKn; // don't transmit Acknowledge ack = ReceiveByte_NoAck(); EeSetStop(); ACCESS2_CTRL_REG &= ~ACKn; // transmit Acknowledge debugf("ack: %02X\n", ack); return ack; } uint8 send_command(uint8* cmd, uint8 size) { uint8 ret; ret = send_packet(cmd, size); return ret; }
I've attached captures from the scope on 3 runs.
Thanks!
Hello Thomas,
The PING command should be the next byte after the Address for the slave. However what I see is that it is the second byte after the address.
Secondly I do not see a Repeated Start so that the program receives an ACK
Regards
Amit
Hi Amit,
According to the ROM user's guide (spmu367.pdf), every packet starts with the length, then the check sum and finally the data. This is also what I understood from the boot loader sources in TivaWare_C_Series-2.1.0.12573\boot_loader.
So a ping packet would be:
0x03 0x20 0x20 length checksum command
Is this wrong?
It's receiving the ACK that's the problem. For the 1st run I get 0x00, the 2nd run (without resetting the Tiva) I get 0xCC, and the following runs I get 0xC2.
There's a repeated start:
Thanks!
Hello Thomas
It also mentions that the Master has to wait for the single byte ACK from the device. So as long as you get 0x00 from the device the Master should wait.
Regards
Amit
If I wait for the ACK byte to be non zero, I get 0xFF for the 1st run, 0xCC for the 2nd run and 0xC2 for the following runs.
If I wait for the ACK byte to be either COMMAND_ACK (0xCC) or COMMAND_NAK (0x33) the 1st run never returns...
Hello Thomas,
In the earlier waveform snapshot you had the 1st run showed 0x00 and then it showed 0xCC in the 2nd RUN. What I am mentioning here is that the 1st RUN should not be terminated till the non-zero byte is received.
Regards
Amit
Yes, and if I wait for the ACK byte to be non zero, I get 0xFF (read 0x00 then try and read again and get 0xFF) for the 1st run, 0xCC for the 2nd run and 0xC2 for the following runs.
uint8 send_packet(uint8* data, uint8 size)
{
uint8 i, ack = 0, checksum = 0;
for (i = 0; i < size; i++) {
checksum += data[i];
}
debugf("checksum: %02X\n", checksum);
do
{
EeSetStart();
EeSendByte(TIVA_DEVICEADDRESS);
} while (ACCESS2_CTRL_REG & ACKn);
EeSendByte(size +2);
EeSendByte(checksum);
for (i = 0; i < size; i++) {
EeSendByte(data[i]);
}
EeSetStart();
// Set Device address for read
EeSendByte(TIVA_DEVICEADDRESS|0x01);
while (ACCESS2_CTRL_REG & ACKn);
ACCESS2_CTRL_REG |= ACKn; // don't transmit Acknowledge
while ((ack = ReceiveByte_NoAck()) == 0x00)
__asm("nop");
EeSetStop();
ACCESS2_CTRL_REG &= ~ACKn; // transmit Acknowledge
debugf("ack: %02X\n", ack);
return ack;
}
EDIT: I tried to mark the changed line in red, but got "<span style=
"color:#ff0000;"
>
" instead.
Hello Thomas,
Give me a day or two to get the setup working to see what is happening.
Regards
Amit
Thanks!
I read an extra byte with the acknowledge bit before reading the actual ACK/NAK byte and now it works.