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.

I2C again



Hi, folks,

There are 7 meaningful IIC's interior interrupts and 2 extra undocumented interior interrupt's conditions, I listed it all:

        case I2C_NO_ISRC:   // =0
            break;

        case I2C_ARB_ISRC:  // =1
            break;

        case I2C_NACK_ISRC: // =2
            break;

        case I2C_ARDY_ISRC: // =3
            break;

        case I2C_RX_ISRC:   // =4
            break;

        case I2C_TX_ISRC:   // =5
            break;

        case I2C_SCD_ISRC:  // =6
            break;

        case I2C_AAS_ISRC:  // =7
            break;

        default: break;

 

I have found that       I2C_NO_ISRC   did occur!

I have to know, which conditions cause I2C_NO_ISRC   occurrence?

 

And, just an ask....never mind though........ when uses          switch (I2caRegs.I2CISRC.bit.INTCODE & 0x7)         , after that ,

and , is there possibility of cases other than the above 8 numbers (0 to 7) to occur? Because it's likely that I saw it happened before(the default case)?.......OK....never mind.......

 

So, I have to know, please, it's really serious. If there were no answers, then I have to know at least, please, the least answer is, "FIFO" can work around or actually, cannot (need promise)??? I mean, workable anything about IIC single master xor single slave communication. (And how?)

(Just my opinion, It might be hard to implement master+slave on the IIC module)

Appreciates & thanks in advance.

 

 

 

 

 

 

  • What does your interrupt service routine look like for the I2C interrupt?

    As for your other question, I don't quite understand what information you are looking for.

  • Hi,

    It looks like this. And I have 3 problems suspending for a long time.

    Thanks in advance for your answers.

    1. I have no idea how to write FIFO, why my FIFO code doesn't work.

    2. I have no idea why set macro PROOF to 1, it stuck.

    3. Why temporarily disable INT, IIC sometimes halted.

    Is such IIC module acceptable by public(because I just wonder that why others didn't raise such phenomena or the alike)?

    The test code can run as master or slave just only needs to modify where "xxxxx" indicates.

     

     

    ////////////////////// please configure the corresponding GPIOs for IIC use.

    //////////////////// and add this fraction of code into your example code, invoke IIC_Driver() in main().

    //----------- xxxxx
    #define IIC_FIFO 0 // (it doesn't work)
    #define PROOF 0
    #if 0 //(0: piccolo - master, 1: F2808 - slave)
    //--------------

     


    #ifndef F280x
    #define F280x
    #endif
    #else
    #ifndef F2802x
    #define F2802x
    #endif
    #endif

    #ifdef F280x
    #define ARBL AL
    #define CLK_VAR 9
    #define IIC_MASTER_ADDR 0x41
    #define IIC_SLAVE_ADDR 0x0C
    #else
    #define CLK_VAR 5
    #define IIC_MASTER_ADDR 0x0C
    #define IIC_SLAVE_ADDR 0x41
    #endif

    #define IT(x) ((x)&0xFF)
    //--------------


    void IIC_Init(void){ // Initialize IIC
        I2caRegs.I2CMDR.all=0x0000;

        I2caRegs.I2CPSC.all = CLK_VAR;                // Prescaler - need 7-12 Mhz on module clk

        I2caRegs.I2CCLKL = 10;                  // NOTE: must be non zero
        I2caRegs.I2CCLKH = 5;                   // NOTE: must be non zero

        I2caRegs.I2COAR = IIC_MASTER_ADDR;      // Own address
        I2caRegs.I2CSAR = IIC_SLAVE_ADDR;       // Slave address - Device control code

    #if IIC_FIFO
        I2caRegs.I2CIER.all=0x67;

        I2caRegs.I2CFFTX.all=0x0040;
        I2caRegs.I2CFFTX.all=0x6440;
        I2caRegs.I2CFFTX.bit.TXFFIENA=1;

        I2caRegs.I2CFFRX.all=0x0041;
        I2caRegs.I2CFFRX.all=0x2041;
        I2caRegs.I2CFFRX.bit.RXFFIENA=1;
    #else
        I2caRegs.I2CIER.all=0x7F;
    #endif

        I2caRegs.I2CMDR.all=0x0020;
    }

    unsigned char status_recorder[256]={0};

    unsigned char rcv_recorder[256]={0};

    unsigned char status_ptr=254;

    unsigned char rcv_ptr=254;

    unsigned char b=IIC_MASTER_ADDR;

    unsigned char comp_num=IIC_SLAVE_ADDR;


    #if PROOF
    // prove that whether or not the IIC module causes data inconsistency. (non-RM only)
    unsigned char error_flag=0;

    // When changing role(master <--> slave), reset this flag (on either the occasions of issue a command
    // or perform listening. In which cases, both master and slave have to do the same
    // CHANGE_ROLE and the corresponding behavior at the same time)
    #define CHANGE_ROLE (error_flag=0)
    #endif


    interrupt void iic_int1a_isr(void){         // I2C-1A
        status_recorder[IT(status_ptr)]=(I2caRegs.I2CISRC.bit.INTCODE & 0x7);
        switch (status_recorder[IT(status_ptr)]){

            case I2C_NO_ISRC:   // =0
                status_ptr++;
                asm("   ESTOP0"); // Halt on invalid number.
                break;

            case I2C_ARB_ISRC:  // =1
                status_ptr++;
                break;

            case I2C_NACK_ISRC: // =2
                status_ptr++;
                break;

            case I2C_ARDY_ISRC: // =3
                status_ptr++;
                break;

            case I2C_RX_ISRC:   // =4
                status_ptr++;

    #if PROOF
                if (error_flag){
                    comp_num++;
                    error_flag=0;
                }
    #endif

                rcv_recorder[IT(rcv_ptr)]=I2caRegs.I2CDRR;
                if (IT(comp_num)!=rcv_recorder[IT(rcv_ptr)])
                    while (1);
                comp_num++; // next time to send from opposite
                rcv_ptr++;
                break;

            case I2C_TX_ISRC:   // =5


                status_ptr++;
                ///////////if (!I2caRegs.I2CSTR.bit.SDIR) break;
    #if PROOF
                // prove wrong, where means:
                // The role: <<<Slave transmits here.>>>
                // Slave now transmits once, and Slave is preparing to tell himself in a note later that
                // next time transmitting, don't forget the agreement with Master about
                // transmitting the next of the next of the sequence number previously sent.
                // NOTE: The above statements are on a perspective of "Slave received a read command".
                // Got it?
                // Ok, now, change your point of view to "Slave received a write command, Tx from master",
                // here is now becomes to Master transmitting,
                // the settings also hold. The only thing has to do is add another flag-set
                // prior to all that Slave changes to Master and commences to send commands or
                // Master changes to Slave and commences to listening.
                if (error_flag){
                    b++;
                    error_flag=0;
                }
    #endif

                //if (I2caRegs.I2CSTR.bit.SDIR)
                I2caRegs.I2CDXR=IT(b++);
                break;

            case I2C_SCD_ISRC:  // =6
                status_ptr++;
    #if PROOF
                error_flag=1;
    #endif
                break;

            case I2C_AAS_ISRC:  // =7
                status_ptr++;
                break;

            default:
                status_ptr++;
                asm("   ESTOP0"); // Halt on invalid number.
                break;
        }
        // Enable future I2C (PIE Group 8) interrupts
        PieCtrlRegs.PIEACK.all=PIEACK_GROUP8;
    }


    interrupt void iic_int2a_isr(void){         // I2C-2A
        int a;

        status_recorder[IT(status_ptr)]=(I2caRegs.I2CISRC.bit.INTCODE & 0x7)+8;
        switch (status_recorder[IT(status_ptr)]-8){
            case 0:   // =0, transmit
                status_ptr++;
                for (a=0x10-I2caRegs.I2CFFTX.bit.TXFFST; a--;)
                    I2caRegs.I2CDXR=IT(b++);
                I2caRegs.I2CFFTX.bit.TXFFINTCLR=1;
                break;

            case 1:  // =1, receive
                status_ptr++;
                for (a=I2caRegs.I2CFFRX.bit.RXFFST; a--;){
                    rcv_recorder[IT(rcv_ptr)]=I2caRegs.I2CDRR;
                    if (IT(comp_num)!=rcv_recorder[IT(rcv_ptr)])
                        while (1);
                    comp_num++;
                    rcv_ptr++;
                }
                I2caRegs.I2CFFRX.bit.RXFFINTCLR=1;
                break;

            default:
                status_ptr++;
                asm("   ESTOP0"); // Halt on invalid number.
        }
        // Enable future I2C (PIE Group 8) interrupts
        PieCtrlRegs.PIEACK.all=PIEACK_GROUP8;
    }


    void IIC_Driver(void){

        for (status_ptr=0; status_ptr<255;) status_recorder[++status_ptr]=0xaa;
        status_recorder[status_ptr=0]=0xaa;

        for (rcv_ptr=0; rcv_ptr<255;) rcv_recorder[++rcv_ptr]=0x55;
        rcv_recorder[rcv_ptr=0]=0x55;

        status_ptr=254;
        rcv_ptr=254;

        IIC_Init();

        while (1){
    #if (IIC_MASTER_ADDR==0x0C) // master
            if (rand()%2){
                I2caRegs.I2CCNT=(rand()%31)+1;
                I2caRegs.I2CMDR.all=0x6C20;
                while(I2caRegs.I2CMDR.bit.STP||!I2caRegs.I2CIER.bit.ARDY);
            }
            if (rand()%2){
                I2caRegs.I2CCNT=(rand()%32)+1;
                I2caRegs.I2CMDR.all=0x6E20;
                while(I2caRegs.I2CMDR.bit.STP||!I2caRegs.I2CIER.bit.ARDY);
            }
            if (rand()%2){ // how to RM?
                I2caRegs.I2CCNT=(rand()%33)+1;
                I2caRegs.I2CMDR.all=0x6C20;
                while(I2caRegs.I2CMDR.bit.STP||!I2caRegs.I2CIER.bit.ARDY);
            }
    #elif PROOF
                DINT;
                DELAY_US((unsigned char)(rand()%2));
                EINT;
                DELAY_US((unsigned char)(rand()%2));
                DINT;
                DELAY_US((unsigned char)(rand()%1));
                EINT;
                DELAY_US((unsigned char)(rand()%2));
                DINT;
                DELAY_US(1);
                EINT;
                DELAY_US(7);
    #endif
        }
    }