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.

C6678 Interrupt Service routine problems

Hi,

I am having trouble getting my ISR up and running on the CC678. I am trying to read back from the DSP over I2C but I am not registering an interrupt and the I2C lines are driven low.

I am sure I am missing something simple but if I post some of my interrupt initialisation code is it possible if someone could point me in the right direction?

#define CSL_INTC_EVENTID_I2CINT 59

/* Intc variable declaration */
CSL_IntcContext g_intcContext;
CSL_IntcEventHandlerRecord g_EventHandler[1];
CSL_IntcObj g_intcObji2c;
CSL_IntcHandle g_hIntci2c;
CSL_IntcGlobalEnableState g_state;
CSL_IntcEventHandlerRecord g_EventRecord;
CSL_IntcParam g_vectId;

/* For the register scheme */
Uint8 g_addr_reg = 0; /* Register address, actually index of a register in g_regs[] array */
Uint8 g_write_mask = 0x80; /* If address received by the master & this is not zero then we are dealing
with a write operation */
Uint8 g_machine_state = 0; /* The I2C protocol is driven by a "state machine" this variable hold the last state */
Uint8 g_regs[] = { /* The actual registers the master can write to and read from */
0x01,
0x05,
0x06,
0x40,
0x50,
0x60,
0x70,
0x71,
0x72,
0x73
};

void init_intc()
{
int status;
CSL_Status cslstatus;

/* Intc module initialization */
g_intcContext.eventhandlerRecord = g_EventHandler;
g_intcContext.numEvtEntries = 1;
status = CSL_intcInit(&g_intcContext);
if (status != CSL_SOK) {
printf("Intc initialization failed\n");
return;
}

/* Enable NMIs */
status = CSL_intcGlobalNmiEnable();
if (status != CSL_SOK) {
printf("Intc global NMI enable failed\n");
return;
}

/* Enable global interrupts */
status = CSL_intcGlobalEnable(&g_state);
if (status != CSL_SOK) {
printf ("Intc global enable failed\n");
return;
}

/* Opening intc module */
g_vectId = CSL_INTC_VECTID_4;
g_hIntci2c = CSL_intcOpen (&g_intcObji2c, CSL_INTC_EVENTID_I2CINT,
&g_vectId , NULL);
if (g_hIntci2c == NULL) {
printf("Intc open failed\n");
return;
}

if (cslstatus != CSL_SOK) {
printf("interrupt open failed!\n");
return;
}

g_EventRecord.handler = eventI2CHandler; /* the event−handler for i2c interrupt */
g_EventRecord.arg = (void *)NULL; /* an argument to be passed to the ISR */
CSL_intcPlugEventHandler(g_hIntci2c, &g_EventRecord);

}


/* The I2C interrupt handler, the CPU arrives here each time a byte is ready to be read from the
* input read register. */
void eventI2CHandler (void *handle)
{
Uint8 buf = 0x66;
Uint32 ivr;

/* Read the interrupt code */
ivr = getI2CIVR();

/* Process interrupt */
switch(ivr) {
case I2C_IVR_ICRRDY_INTERRUPT:
/*
* An i2c data has been received serially and is available in the ICDRR register
*
*/
switch(g_machine_state%ISR_STATE_MACHINE_NUMBER_STATE) {
case ISR_STATE_MACHINE_STATE_ADDRESS:

/* Read from ICDRR register */
buf = getICDRR();

/* Figure out if the next operation is read or write operation and setup state machine
* in consequence */
if(buf&g_write_mask) {
g_machine_state = ISR_STATE_MACHINE_STATE_DATA_WRITE;
} else {
g_machine_state = ISR_STATE_MACHINE_STATE_DATA_READ;
}

/* Get rid of the directon bit in the address value */
buf &= ~g_write_mask;

/* Finally update the address value */
g_addr_reg = buf; /* Read from I2C ICDRR register and configure
address */

/* If it was a read transaction we place read transaction in the output register */
if(g_machine_state==ISR_STATE_MACHINE_STATE_DATA_READ) {
setICDXR(g_regs[g_addr_reg%(sizeof(g_regs)/sizeof(Uint8))]);
g_machine_state = ISR_STATE_MACHINE_STATE_ADDRESS;
}
break;
case ISR_STATE_MACHINE_STATE_DATA_WRITE:

/* Read from ICDRR register */
buf = getICDRR();

/* Write to register */
g_regs[g_addr_reg%(sizeof(g_regs)/sizeof(Uint8))] = buf;


/* The next byte we receive will be the address */
g_machine_state = ISR_STATE_MACHINE_STATE_ADDRESS;

break;
}
break;
}

}


I can see that the that data is being stored in the I2C receive data register but code my interrupts just aren't working. Any help would be greatly appreciated,

Thank you

Fearghal

  • Hey Fearghal,

    I'm here to help you work this out. Okay, so you said that the I2C is receiving data, storing it, but not sending these data/interrupts to the CPU. I'm thinking there may be a problem in your I2C initalization that is keeping those lines driven low.

    Check your I2C registers, like the I2CDXR (data transmit register) and I2CIER (interrupt enable register). So basically look at your x00-0x30 offsets. What I think happened is that the transmit or interrupt is not enabled, and the DSP isn't receiving because of it. Maybe you forgot to init the PLL or something.

     

    Try that and see if that helps. By the way, does any of your printf errors you have in your code above show? If not then it's most likely the initization as I said.

     

    Good luck!

    Kat Kelsch

  • Hi Kat,

    I am not sure if the issue lies with the initialization of the I2C.

    I have run through a test to try and read back the value stored in the ICIMR register. These are the values I read in the key I2C registers after initialization:

    ICSTR: 0x00000410

    ICSAR: 0x000003FF

    ICEMDR: 0x00000001

    ICPSC: 0x0000000B

    ICOAR: 0x00000020

    ICIMR: 0x0000007F

    ICCLKL: 0x0000003F 

    ICCLKH: 0x0000003F

    ICMDR: 0x000040A0

    Then I write a value directly into the ICDXR register and get the following changes:

    ICSTR: 0x00000400

    ICDXR: 0x00000044

    After I send a I2C read command from my master device the following register changes occur:

    ICSTR: 0x00000438

    ICIVR: 0x00000004

    ICDRR: 0x00000004


    When I try to send another read command I get the failure where the I2C lines are held low. (This is due to no value written in the ICDXR register, this is undertaken in the interrupt event handler in my code. It did not initially fail as I wrote directly into the ICDXR register).

    The ICSTR register now reads: 0x00001E38

    To me it seem like I am receiving I2C communication and recognising it and setting the correct interrupt bits. I am not recognising these interrupts as I do not enter into my interrupt event handler function, where I should be able to read back the value in the ICDRR register and copy it to the ICDXR. This is why I am not sure that I have initialized my interrupt controller correctly. What do you think Kat? Thanks for your help with this.

    Best Regards,

    Fearghal

  • Hey Fearghal,

     Okay, so you wrote to the data transmit register and the status register changed from 410 to 400. You then send a read command you get 438. The 0x438 corresponds to the data being ready to send. This is right because this meant that data has been copied to ICDDR, and it shows it in your register. Okay, that means the I2C is following orders, so I think you're right that it is not the problem.

    You never enter your interrupt function? Then, yes let's focus on that. Does it even say "int open failed" on your console?  Or is it just never sending the interrupt?

    Here's a bit of code you posted:

    /* Opening intc module */
    g_vectId = CSL_INTC_VECTID_4;
    g_hIntci2c = CSL_intcOpen (&g_intcObji2c, CSL_INTC_EVENTID_I2CINT,
    &g_vectId , NULL);
    if (g_hIntci2c == NULL) {
    printf("Intc open failed\n");
    return;
    }

    if (cslstatus != CSL_SOK) {
    printf("interrupt open failed!\n");
    return;
    }

    g_EventRecord.handler = eventI2CHandler; /* the event−handler for i2c interrupt */
    g_EventRecord.arg = (void *)NULL; /* an argument to be passed to the ISR */
    CSL_intcPlugEventHandler(g_hIntci2c, &g_EventRecord);

    }

     

    Where exactly do you have the interrupt flagged high/sent? I don't see any code actually interruptting. I see the handler and the NULL agrument passed, but no interrupt. Is that included in the code where you didn't post it here?

     

    Kat

     

  • Hi Kat,

    I now have almost have my interrupt routine working. I am able to recognise one read cycle from I2C to a register in the DSP but when I try to read again, the I2C lines are again pulled low. I have a feeling it is to do with not clearing an interrupt after I have flagged it. Can I provide you with event handler routine and see if you can see what I am doing wrong?

    /* Read current value in the I2C's interrupt vector register. Note that this clears interrupt */
    Uint32 getI2CIVR(void)
    {
    return ((CSL_I2cRegs*)CSL_I2C_DATA_CONTROL_REGS)->ICIVR;
    }

    /* Read value from the I2C's read register, this clears RDRDY */
    Uint8 getICDRR(void)
    {
    return CSL_FEXT(((CSL_I2cRegs*)CSL_I2C_DATA_CONTROL_REGS)->ICDRR,I2C_ICDRR_D);
    }

    /* Write value to the I2C's write register, this clears TXRDY */
    void setICDXR(Uint8 val)
    {
    ((CSL_I2cRegs*)CSL_I2C_DATA_CONTROL_REGS)->ICDXR =
    ((CSL_I2cRegs*)CSL_I2C_DATA_CONTROL_REGS)->ICDXR&0xFF00 | (CSL_FMK(I2C_ICDXR_D, val));
    }

    /* For the register scheme */
    Uint8 g_addr_reg = 0; /* Register address, actually index of a register in g_regs[] array */
    Uint8 g_write_mask = 0x80; /* If address received by the master & this is not zero then we are dealing with a write operation */
    Uint8 g_machine_state = 0; /* The I2C protocol is driven by a "state machine" this variable hold the last state */
    Uint8 g_regs[] = { /* The actual registers the master can write to and read from */
    0x01,
    0x05,
    0x06,
    0x40,
    0x50,
    0x60,
    0x70,
    0x71,
    0x72,
    0x73
    };

    /* The I2C interrupt handler, the CPU arrives here each time a byte is ready to be read from the
    * input read register. */
    void eventI2CHandler (void *handle)
    {
    Uint8 buf = 0x66;
    Uint32 ivr;

    /* Read the interrupt code */
    ivr = getI2CIVR();

    /* Disable the CIC0 host interrupt output */
    CSL_CPINTC_disableHostInterrupt(hnd, 3);

    /* Clear the CIC0 system interrupt */
    CSL_CPINTC_clearSysInterrupt(hnd, 58);

    /* Process interrupt */
    switch(ivr) {
    case I2C_IVR_ICRRDY_INTERRUPT:
    /*
    * An i2c data has been received serially and is available in the ICDRR register
    *
    */
    switch(g_machine_state%ISR_STATE_MACHINE_NUMBER_STATE) {
    case ISR_STATE_MACHINE_STATE_ADDRESS:

    /* Read from ICDRR register */
    buf = getICDRR();

    /* Figure out if the next operation is read or write operation and setup state machine
    * in consequence */
    if(buf&g_write_mask) {
    g_machine_state = ISR_STATE_MACHINE_STATE_DATA_WRITE;
    } else {
    g_machine_state = ISR_STATE_MACHINE_STATE_DATA_READ;
    }

    /* Get rid of the directon bit in the address value */
    buf &= ~g_write_mask;

    /* Finally update the address value */
    g_addr_reg = buf; /* Read from I2C ICDRR register and configure
    address */

    /* If it was a read transaction we place read transaction in the output register */
    if(g_machine_state==ISR_STATE_MACHINE_STATE_DATA_READ) {
    setICDXR(g_regs[g_addr_reg%(sizeof(g_regs)/sizeof(Uint8))]);
    g_machine_state = ISR_STATE_MACHINE_STATE_ADDRESS;
    }
    break;
    case ISR_STATE_MACHINE_STATE_DATA_WRITE:

    /* Read from ICDRR register */
    buf = getICDRR();

    /* Write to register */
    g_regs[g_addr_reg%(sizeof(g_regs)/sizeof(Uint8))] = buf;


    /* The next byte we receive will be the address */
    g_machine_state = ISR_STATE_MACHINE_STATE_ADDRESS;

    break;
    }
    break;
    }

    /* Clear the event in case it is pending */
    CSL_intcHwControl(g_hIntci2c, CSL_INTC_CMD_EVTCLEAR, NULL);

    /* Enable the CIC0 host interrupt output */
    CSL_CPINTC_enableHostInterrupt(hnd, 3);

    }

    I am not sure if I am handling the system and host interrupt correctly for I2C. Thanks again for your help.

    Best Regards,

    Fearghal

  • Hi Kat,

    I was able to solve my problem.

    Initially I had not configured the both the CIC and CorePac INTC for I2C interrupt correctly. Upon correcting this, I was still seeing issues related to my I2C interrupts but this was due to the I2C stop bit interrupt causing an error in my ISR. Everything seems to be working now.

    Best Regards,

    Fearghal

  • That's great! Let me know if you need any other help.

     

    Kat