DSPRelated.com
Forums

C6713: I2C master transmitter and NACK

Started by Bernhard 'Gustl' Bauer July 5, 2005
Hi,

I have a problem with I2C again :-)

I send some bytes to a slave transmitter and the last one is answered
with a NACK. When this happens I2C stops. If I send this to a slave
which answers the last byte with a ACK all is fine.

I have no EDMA, no IRQ and no csl for this. So I must do it by polling
the registers. Any idea how I should treat this situation?

AFAIK it is possible for an I2C slave to answer the last byte (if it
knew its the last one) with an NACK. The I2C module should be able to
deal with this.

TIA Gustl

This is my code:
----------------
far void pipe_data(unsigned char *typ_string)
{
unsigned char *hw_ptr;
unsigned int i,help;
unsigned char dest[10];
unsigned char address=typ_string[1];
unsigned char number=typ_string[2];
unsigned char ret_number=typ_string[3];
unsigned char *source;

source=&typ_string[4];
send_byte=(void(*)(unsigned char))(0x00000CC8); // I2C open/reset
I2C_RSET(I2COAR0,I2C_I2COAR_DEFAULT);
I2C_RSET(I2CIMR0,I2C_I2CIMR_DEFAULT);
I2C_RSET(I2CCLKL0,I2C_I2CCLKL_DEFAULT);
I2C_RSET(I2CCLKH0,I2C_I2CCLKH_DEFAULT);
I2C_RSET(I2CCNT0,I2C_I2CCNT_DEFAULT);
I2C_RSET(I2CSAR0,I2C_I2CSAR_DEFAULT);
I2C_RSET(I2CMDR0,I2C_I2CMDR_DEFAULT);
I2C_RSET(I2CPSC0,I2C_I2CPSC_DEFAULT);

// I2c_init
I2C_RSET(I2COAR0,I2C_I2COAR_RMK(I2C_I2COAR_A_OF(0)));
I2C_RSET(I2CIMR0,I2C_I2CIMR_RMK(I2C_I2CIMR_ICXRDY_MSK,
I2C_I2CIMR_ICRRDY_MSK,
I2C_I2CIMR_ARDY_MSK,
I2C_I2CIMR_NACK_MSK,
I2C_I2CIMR_AL_MSK));
I2C_RSET(I2CCLKL0,I2C_I2CCLKL_RMK(I2C_I2CCLKL_ICCL_OF(12-6)));
I2C_RSET(I2CCLKH0,I2C_I2CCLKH_RMK(I2C_I2CCLKH_ICCH_OF(12-6)));
I2C_RSET(I2CCNT0,I2C_I2CCNT_RMK(I2C_I2CCNT_ICDC_OF(0)));
I2C_RSET(I2CSAR0,I2C_I2CSAR_RMK(I2C_I2CSAR_A_OF(0)));
I2C_RSET(I2CMDR0,I2C_I2CMDR_RMK(I2C_I2CMDR_NACKMOD_ACK,
I2C_I2CMDR_FREE_BSTOP,
I2C_I2CMDR_STT_NONE,
I2C_I2CMDR_STP_NONE,
I2C_I2CMDR_MST_MASTER,
I2C_I2CMDR_TRX_XMT,
I2C_I2CMDR_XA_7BIT,
I2C_I2CMDR_RM_NONE,
I2C_I2CMDR_DLB_NONE,
I2C_I2CMDR_IRS_RST,
I2C_I2CMDR_STB_NONE,
I2C_I2CMDR_FDF_NONE,
I2C_I2CMDR_BC_BIT8FDF));
I2C_RSET(I2CPSC0,I2C_I2CPSC_RMK(I2C_I2CPSC_IPSC_OF(10-1)));
// I2C out of reset
I2C_RSET(I2CMDR0,I2C_RGET(I2CMDR0)|_I2C_I2CMDR_IRS_MASK);
// clear BB in case of malfunction slave device
I2C_RSET(I2CSTR0,_I2C_I2CSTR_BB_MASK);
// prepare send
I2C_RSET(I2CSAR0,I2C_I2CSAR_RMK(I2C_I2CSAR_A_OF(address)));
I2C_RSET(I2CCNT0,I2C_I2CCNT_RMK(I2C_I2CCNT_ICDC_OF(number)));
I2C_RSET(I2CDXR0,I2C_I2CDXR_RMK(I2C_I2CDXR_OF(*source)));
source++;
number--;
// starting I2C
I2C_RSET(I2CMDR0,I2C_I2CMDR_RMK(I2C_I2CMDR_NACKMOD_ACK,
I2C_I2CMDR_FREE_BSTOP,
I2C_I2CMDR_STT_NONE,
I2C_I2CMDR_STP_NONE,
I2C_I2CMDR_MST_MASTER,
I2C_I2CMDR_TRX_XMT,
I2C_I2CMDR_XA_7BIT,
I2C_I2CMDR_RM_NONE,
I2C_I2CMDR_DLB_NONE,
I2C_I2CMDR_IRS_NRST,
I2C_I2CMDR_STB_NONE,
I2C_I2CMDR_FDF_NONE,
I2C_I2CMDR_BC_BIT8FDF));
I2C_RSET(I2CMDR0,I2C_I2CMDR_RMK(I2C_I2CMDR_NACKMOD_ACK,
I2C_I2CMDR_FREE_BSTOP,
I2C_I2CMDR_STT_START,
I2C_I2CMDR_STP_STOP,
I2C_I2CMDR_MST_MASTER,
I2C_I2CMDR_TRX_XMT,
I2C_I2CMDR_XA_7BIT,
I2C_I2CMDR_RM_NONE,
I2C_I2CMDR_DLB_NONE,
I2C_I2CMDR_IRS_NRST,
I2C_I2CMDR_STB_NONE,
I2C_I2CMDR_FDF_NONE,
I2C_I2CMDR_BC_BIT8FDF));
while((I2C_RGET(I2CSTR0)&_I2C_I2CSTR_BB_MASK)==0);
// send all bytes
while (number>0) {
if ((I2C_RGET(I2CSTR0)&_I2C_I2CSTR_ICXRDY_MASK)!=0) {
2C_RSET(I2CDXR0,I2C_I2CDXR_RMK(I2C_I2CDXR_OF(*source)));
source++;
number--;
}
}/**/
// wait until all is sent
while((I2C_RGET(I2CSTR0)&_I2C_I2CSTR_BB_MASK)!=0);
while((I2C_RGET(I2CSTR0)&_I2C_I2CSTR_BB_MASK)!=0);
}


HI
As far as my knowledge goes, the I2C peripheral slave dont acknowledge
for the last transmitted byte. but as your saying that the slave is
sending a NACK, that means the slave is not able to receive the last
byte properly, that might be possible due to many reasons.

Regards
Raja

On 7/5/05, Bernhard 'Gustl' Bauer <gustl@gust...> wrote:
> Hi,
>
> I have a problem with I2C again :-)
>
> I send some bytes to a slave transmitter and the last one is answered
> with a NACK. When this happens I2C stops. If I send this to a slave
> which answers the last byte with a ACK all is fine.
>
> I have no EDMA, no IRQ and no csl for this. So I must do it by polling
> the registers. Any idea how I should treat this situation?
>
> AFAIK it is possible for an I2C slave to answer the last byte (if it
> knew its the last one) with an NACK. The I2C module should be able to
> deal with this.
>
> TIA Gustl
>
> This is my code:
> ----------------
> far void pipe_data(unsigned char *typ_string)
> {
> unsigned char *hw_ptr;
> unsigned int i,help;
> unsigned char dest[10];
> unsigned char address=typ_string[1];
> unsigned char number=typ_string[2];
> unsigned char ret_number=typ_string[3];
> unsigned char *source;
>
> source=&typ_string[4];
> send_byte=(void(*)(unsigned char))(0x00000CC8); > // I2C open/reset
> I2C_RSET(I2COAR0,I2C_I2COAR_DEFAULT);
> I2C_RSET(I2CIMR0,I2C_I2CIMR_DEFAULT);
> I2C_RSET(I2CCLKL0,I2C_I2CCLKL_DEFAULT);
> I2C_RSET(I2CCLKH0,I2C_I2CCLKH_DEFAULT);
> I2C_RSET(I2CCNT0,I2C_I2CCNT_DEFAULT);
> I2C_RSET(I2CSAR0,I2C_I2CSAR_DEFAULT);
> I2C_RSET(I2CMDR0,I2C_I2CMDR_DEFAULT);
> I2C_RSET(I2CPSC0,I2C_I2CPSC_DEFAULT);
>
> // I2c_init
> I2C_RSET(I2COAR0,I2C_I2COAR_RMK(I2C_I2COAR_A_OF(0)));
> I2C_RSET(I2CIMR0,I2C_I2CIMR_RMK(I2C_I2CIMR_ICXRDY_MSK,
> I2C_I2CIMR_ICRRDY_MSK,
> I2C_I2CIMR_ARDY_MSK,
> I2C_I2CIMR_NACK_MSK,
> I2C_I2CIMR_AL_MSK));
> I2C_RSET(I2CCLKL0,I2C_I2CCLKL_RMK(I2C_I2CCLKL_ICCL_OF(12-6)));
> I2C_RSET(I2CCLKH0,I2C_I2CCLKH_RMK(I2C_I2CCLKH_ICCH_OF(12-6)));
> I2C_RSET(I2CCNT0,I2C_I2CCNT_RMK(I2C_I2CCNT_ICDC_OF(0)));
> I2C_RSET(I2CSAR0,I2C_I2CSAR_RMK(I2C_I2CSAR_A_OF(0)));
> I2C_RSET(I2CMDR0,I2C_I2CMDR_RMK(I2C_I2CMDR_NACKMOD_ACK,
> I2C_I2CMDR_FREE_BSTOP,
> I2C_I2CMDR_STT_NONE,
> I2C_I2CMDR_STP_NONE,
> I2C_I2CMDR_MST_MASTER,
> I2C_I2CMDR_TRX_XMT,
> I2C_I2CMDR_XA_7BIT,
> I2C_I2CMDR_RM_NONE,
> I2C_I2CMDR_DLB_NONE,
> I2C_I2CMDR_IRS_RST,
> I2C_I2CMDR_STB_NONE,
> I2C_I2CMDR_FDF_NONE,
> I2C_I2CMDR_BC_BIT8FDF));
> I2C_RSET(I2CPSC0,I2C_I2CPSC_RMK(I2C_I2CPSC_IPSC_OF(10-1)));
> // I2C out of reset
> I2C_RSET(I2CMDR0,I2C_RGET(I2CMDR0)|_I2C_I2CMDR_IRS_MASK);
> // clear BB in case of malfunction slave device
> I2C_RSET(I2CSTR0,_I2C_I2CSTR_BB_MASK);
> // prepare send
> I2C_RSET(I2CSAR0,I2C_I2CSAR_RMK(I2C_I2CSAR_A_OF(address)));
> I2C_RSET(I2CCNT0,I2C_I2CCNT_RMK(I2C_I2CCNT_ICDC_OF(number)));
> I2C_RSET(I2CDXR0,I2C_I2CDXR_RMK(I2C_I2CDXR_OF(*source)));
> source++;
> number--;
> // starting I2C
> I2C_RSET(I2CMDR0,I2C_I2CMDR_RMK(I2C_I2CMDR_NACKMOD_ACK,
> I2C_I2CMDR_FREE_BSTOP,
> I2C_I2CMDR_STT_NONE,
> I2C_I2CMDR_STP_NONE,
> I2C_I2CMDR_MST_MASTER,
> I2C_I2CMDR_TRX_XMT,
> I2C_I2CMDR_XA_7BIT,
> I2C_I2CMDR_RM_NONE,
> I2C_I2CMDR_DLB_NONE,
> I2C_I2CMDR_IRS_NRST,
> I2C_I2CMDR_STB_NONE,
> I2C_I2CMDR_FDF_NONE,
> I2C_I2CMDR_BC_BIT8FDF));
> I2C_RSET(I2CMDR0,I2C_I2CMDR_RMK(I2C_I2CMDR_NACKMOD_ACK,
> I2C_I2CMDR_FREE_BSTOP,
> I2C_I2CMDR_STT_START,
> I2C_I2CMDR_STP_STOP,
> I2C_I2CMDR_MST_MASTER,
> I2C_I2CMDR_TRX_XMT,
> I2C_I2CMDR_XA_7BIT,
> I2C_I2CMDR_RM_NONE,
> I2C_I2CMDR_DLB_NONE,
> I2C_I2CMDR_IRS_NRST,
> I2C_I2CMDR_STB_NONE,
> I2C_I2CMDR_FDF_NONE,
> I2C_I2CMDR_BC_BIT8FDF));
> while((I2C_RGET(I2CSTR0)&_I2C_I2CSTR_BB_MASK)==0);
> // send all bytes
> while (number>0) {
> if ((I2C_RGET(I2CSTR0)&_I2C_I2CSTR_ICXRDY_MASK)!=0) {
> 2C_RSET(I2CDXR0,I2C_I2CDXR_RMK(I2C_I2CDXR_OF(*source)));
> source++;
> number--;
> }
> }/**/
> // wait until all is sent
> while((I2C_RGET(I2CSTR0)&_I2C_I2CSTR_BB_MASK)!=0);
> while((I2C_RGET(I2CSTR0)&_I2C_I2CSTR_BB_MASK)!=0);
> } >


--
Raja Das
Flextronics Software Systems


Hi Raja,

thanks for your quick answer.

Raja Das wrote:

> HI
> As far as my knowledge goes, the I2C peripheral slave dont acknowledge
> for the last transmitted byte. but as your saying that the slave is
> sending a NACK, that means the slave is not able to receive the last
> byte properly, that might be possible due to many reasons.

This is a bit confusing. Isn't a NACK the same as 'don't acknowledge'?

I see there is a problem in distinguishing whether it is a last byte or
e.g. a transmission error.

I've had a look at the specification of Philips. The only situation
where a NACK is used to terminate a data stream is when a master
receiver signals to a slave transmitter 'no more data'.

I think this answers my problem, or at least shifts it to the slave
receiver.

Thanks a lot

Gustl

>
> Regards
> Raja >
>
> On 7/5/05, Bernhard 'Gustl' Bauer <gustl@gust...> wrote:
>
>>Hi,
>>
>>I have a problem with I2C again :-)
>>
>>I send some bytes to a slave transmitter and the last one is answered
>>with a NACK. When this happens I2C stops. If I send this to a slave
>>which answers the last byte with a ACK all is fine.
>>
>>I have no EDMA, no IRQ and no csl for this. So I must do it by polling
>>the registers. Any idea how I should treat this situation?
>>
>>AFAIK it is possible for an I2C slave to answer the last byte (if it
>>knew its the last one) with an NACK. The I2C module should be able to
>>deal with this.
>>
>>TIA Gustl
>>
>>This is my code:
>>----------------
>>far void pipe_data(unsigned char *typ_string)
>>{
>> unsigned char *hw_ptr;
>> unsigned int i,help;
>> unsigned char dest[10];
>> unsigned char address=typ_string[1];
>> unsigned char number=typ_string[2];
>> unsigned char ret_number=typ_string[3];
>> unsigned char *source;
>>
>> source=&typ_string[4];
>> send_byte=(void(*)(unsigned char))(0x00000CC8);
>>
>>
>> // I2C open/reset
>> I2C_RSET(I2COAR0,I2C_I2COAR_DEFAULT);
>> I2C_RSET(I2CIMR0,I2C_I2CIMR_DEFAULT);
>> I2C_RSET(I2CCLKL0,I2C_I2CCLKL_DEFAULT);
>> I2C_RSET(I2CCLKH0,I2C_I2CCLKH_DEFAULT);
>> I2C_RSET(I2CCNT0,I2C_I2CCNT_DEFAULT);
>> I2C_RSET(I2CSAR0,I2C_I2CSAR_DEFAULT);
>> I2C_RSET(I2CMDR0,I2C_I2CMDR_DEFAULT);
>> I2C_RSET(I2CPSC0,I2C_I2CPSC_DEFAULT);
>>
>> // I2c_init
>> I2C_RSET(I2COAR0,I2C_I2COAR_RMK(I2C_I2COAR_A_OF(0)));
>> I2C_RSET(I2CIMR0,I2C_I2CIMR_RMK(I2C_I2CIMR_ICXRDY_MSK,
>> I2C_I2CIMR_ICRRDY_MSK,
>> I2C_I2CIMR_ARDY_MSK,
>> I2C_I2CIMR_NACK_MSK,
>> I2C_I2CIMR_AL_MSK));
>> I2C_RSET(I2CCLKL0,I2C_I2CCLKL_RMK(I2C_I2CCLKL_ICCL_OF(12-6)));
>> I2C_RSET(I2CCLKH0,I2C_I2CCLKH_RMK(I2C_I2CCLKH_ICCH_OF(12-6)));
>> I2C_RSET(I2CCNT0,I2C_I2CCNT_RMK(I2C_I2CCNT_ICDC_OF(0)));
>> I2C_RSET(I2CSAR0,I2C_I2CSAR_RMK(I2C_I2CSAR_A_OF(0)));
>> I2C_RSET(I2CMDR0,I2C_I2CMDR_RMK(I2C_I2CMDR_NACKMOD_ACK,
>> I2C_I2CMDR_FREE_BSTOP,
>> I2C_I2CMDR_STT_NONE,
>> I2C_I2CMDR_STP_NONE,
>> I2C_I2CMDR_MST_MASTER,
>> I2C_I2CMDR_TRX_XMT,
>> I2C_I2CMDR_XA_7BIT,
>> I2C_I2CMDR_RM_NONE,
>> I2C_I2CMDR_DLB_NONE,
>> I2C_I2CMDR_IRS_RST,
>> I2C_I2CMDR_STB_NONE,
>> I2C_I2CMDR_FDF_NONE,
>> I2C_I2CMDR_BC_BIT8FDF));
>> I2C_RSET(I2CPSC0,I2C_I2CPSC_RMK(I2C_I2CPSC_IPSC_OF(10-1)));
>> // I2C out of reset
>> I2C_RSET(I2CMDR0,I2C_RGET(I2CMDR0)|_I2C_I2CMDR_IRS_MASK);
>> // clear BB in case of malfunction slave device
>> I2C_RSET(I2CSTR0,_I2C_I2CSTR_BB_MASK);
>> // prepare send
>> I2C_RSET(I2CSAR0,I2C_I2CSAR_RMK(I2C_I2CSAR_A_OF(address)));
>> I2C_RSET(I2CCNT0,I2C_I2CCNT_RMK(I2C_I2CCNT_ICDC_OF(number)));
>> I2C_RSET(I2CDXR0,I2C_I2CDXR_RMK(I2C_I2CDXR_OF(*source)));
>> source++;
>> number--;
>> // starting I2C
>> I2C_RSET(I2CMDR0,I2C_I2CMDR_RMK(I2C_I2CMDR_NACKMOD_ACK,
>> I2C_I2CMDR_FREE_BSTOP,
>> I2C_I2CMDR_STT_NONE,
>> I2C_I2CMDR_STP_NONE,
>> I2C_I2CMDR_MST_MASTER,
>> I2C_I2CMDR_TRX_XMT,
>> I2C_I2CMDR_XA_7BIT,
>> I2C_I2CMDR_RM_NONE,
>> I2C_I2CMDR_DLB_NONE,
>> I2C_I2CMDR_IRS_NRST,
>> I2C_I2CMDR_STB_NONE,
>> I2C_I2CMDR_FDF_NONE,
>> I2C_I2CMDR_BC_BIT8FDF));
>> I2C_RSET(I2CMDR0,I2C_I2CMDR_RMK(I2C_I2CMDR_NACKMOD_ACK,
>> I2C_I2CMDR_FREE_BSTOP,
>> I2C_I2CMDR_STT_START,
>> I2C_I2CMDR_STP_STOP,
>> I2C_I2CMDR_MST_MASTER,
>> I2C_I2CMDR_TRX_XMT,
>> I2C_I2CMDR_XA_7BIT,
>> I2C_I2CMDR_RM_NONE,
>> I2C_I2CMDR_DLB_NONE,
>> I2C_I2CMDR_IRS_NRST,
>> I2C_I2CMDR_STB_NONE,
>> I2C_I2CMDR_FDF_NONE,
>> I2C_I2CMDR_BC_BIT8FDF));
>> while((I2C_RGET(I2CSTR0)&_I2C_I2CSTR_BB_MASK)==0);
>> // send all bytes
>> while (number>0) {
>> if ((I2C_RGET(I2CSTR0)&_I2C_I2CSTR_ICXRDY_MASK)!=0) {
>> 2C_RSET(I2CDXR0,I2C_I2CDXR_RMK(I2C_I2CDXR_OF(*source)));
>> source++;
>> number--;
>> }
>> }/**/
>> // wait until all is sent
>> while((I2C_RGET(I2CSTR0)&_I2C_I2CSTR_BB_MASK)!=0);
>> while((I2C_RGET(I2CSTR0)&_I2C_I2CSTR_BB_MASK)!=0);
>>}
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
> >