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.

TMS570LS0332 N2HET Edge Interrupt

Other Parts Discussed in Thread: HALCOGEN

I've generated the code using HalCoGen, to interrupt on both edges (rising an falling) of three HET input pins. Code works perfectly well as long the input signals are not changing at the same time.

If two input signals generating Edge 0 and Edge 2 interrupts are in phase, Edge 0 interrupt is still triggered while Edge 2 is not.

What needs to be changed in the HET setup to be able to trigger interrupts when Edge 0 and Edge 2 are changing at the same time?

Please advice.

  • Marek,

    In your notification routine, are you sure you are not clearing both flags?

    If you can share the edgeNotification routine, I can have a look.

    Remember that interrupt priority on HET are based on the instruction position in your HET code.
    So Edge0 has higher priority than Edge1, and so on and so forth. (In this specific Halcogen implementation)
    Even if 2 edges happen at the same time,(edge0 and edge2)  2 flags will be set.
    In the notification code, you may want to take care of the highest priority (edge0) one and leave the other one (edge2) untouched.
    After completion of the notification routine, the CPU will again jump in the edgeNotification, this time because of the other edge (edge2).

    Please let me know if this will help solving your problem.

  • Marek,

    I've attached a basic test using HalcoGen HET driver. The Halcogen project files are also included so you should be able to look what I've done.

    Driver in use: RTI, GIO, HET.

    HET9, HET11 and HET13 are used for falling/rising edge detection.

    GIOA_0, GIOA_1, GIOA_2 are used to generate the falling/rising edge. (external connection are necessary between HET and GIO.

    By placing a breakpoint in edgeNotification you should stop there 3 times for rising detection and 3 times for falling detection.


    Please have a try and let me know if this was helpful.

    2330.TMS570LS1224_HET_EDGE_INT.zip

  • Hi Jean-Marc,

    In my implementation, up to two quadrature speed sensors can be connected to four HET pins.
    Second speed sensor can be quadrature or just a single output sensor and then there is a conditional compile statement.

    For the test purposes, I’m feeding quadrature signal to Speed 1 pins and SPD2A_PIN gets its signal from SPD1B_PIN as it is directly connected to it.
    Test result: SPD1A_EDGE and SPD1B_EDGE are detected but SPD2A_EDGE is not.

    Here is my code:

    // Speed Input Definitions
    #define SPD_PORT (hetREG1)
    #define SPD1A_PIN (PIN_HET_19)
    #define SPD1B_PIN (PIN_HET_26)
    #define SPD2A_PIN (PIN_HET_22)
    #define SPD2B_PIN (PIN_HET_31)
    #define bSpdInpGet(p) ((tBoolean)((SPD_PORT->DIN & (1U << p)) ? 1:0))

    #define SPD1A_EDGE (edge0)
    #define SPD1B_EDGE (edge1)
    #define SPD2A_EDGE (edge2)
    #define SPD2B_EDGE (edge3)
    #define SPD_EDGE_INT_FLG (0x00020000U)
    #define bSpdInpIntGet(e) ((tBoolean)((SPD_PORT->FLG & (SPD_EDGE_INT_FLG << e)) ? 1:0))
    #define vSpdInpIntClr(e) (SPD_PORT->FLG |= (SPD_EDGE_INT_FLG << e))

    // Notification Routine
    void edgeNotification(hetBASE_t * hetREG,uint32 edge)
    {
    /* enter user code between the USER CODE BEGIN and USER CODE END. */
    /* USER CODE BEGIN (37) */
    //==============================================================================

    switch(edge) {
    case SPD1A_EDGE:
    if((bSpdInpGet(SPD1A_PIN)) != (bSpdInpGet(SPD1B_PIN))) {
    uiSpd1Cnt++;
    }
    else {
    uiSpd1Cnt--;
    }
    vSpdInpIntClr(SPD1A_EDGE);
    break;

    case SPD1B_EDGE:
    if(bSpdInpGet(SPD1A_PIN) == bSpdInpGet(SPD1B_PIN)) {
    uiSpd1Cnt++;
    }
    else {
    uiSpd1Cnt--;
    }
    vSpdInpIntClr(SPD1B_EDGE);
    break;

    case SPD2A_EDGE:
    #ifndef SPEED2_QUAD
    uiSpd2Cnt++; // Single output speed sensor
    vSpdInpIntClr(SPD2A_EDGE);
    break;
    #else
    if(bSpdInpGet(SPD2A_PIN) != bSpdInpGet(SPD2B_PIN)) {
    uiSpd2Cnt++;
    }
    else {
    uiSpd2Cnt--;
    }
    vSpdInpIntClr(SPD2A_EDGE);
    break;

    case SPD2B_EDGE:
    if(bSpdInpGet(SPD2A_PIN) == bSpdInpGet(SPD2B_PIN)) {
    uiSpd2Cnt++;
    }
    else {
    uiSpd2Cnt--;
    }
    vSpdInpIntClr(SPD2B_EDGE);
    break;
    #endif
    }

    //==============================================================================
    /* USER CODE END */
  • Hi Marek,


    Your code looks good to me but I want to remind you one point.

    The interrupt are prioritized, meaning that in you case we have the following:

    SPD1A_EDGE    (highest)
    SPD1B_EDGE
    SPD2A_EDGE
    SPD2B_EDGE   (lowest)

    If there is a pending SPD2x_EDGE and another SPD1x_EDGE happens, it will mask the SPD2x_EDGE.

    In the case of HET driver, HalcoGen only provides an example of how to use the module.
    Based on your real application specific requirement, you will have to write your own ISR.

    If you look the way the HET ISR is working, the edgeNotification only provides the offset of the highest pending edge.

    void het1HighLevelInterrupt(void)
    {
        uint32 vec = hetREG1->OFF1;

        if (vec < 18U)
        {
            if ((vec & 1U) != 0U)
            {
                pwmNotification(hetREG1,(vec >> 1U) - 1U, pwmEND_OF_PERIOD);
            }
            else
            {
                pwmNotification(hetREG1,(vec >> 1U) - 1U, pwmEND_OF_DUTY);
            }
        }
        else
        {
            edgeNotification(hetREG1,vec - 18U);
        }
    }

    A possible modification could be something like:

    void het1HighLevelInterrupt(void)
    {
        uint32 vec;

       do
        {
         vec = hetREG1->OFF1;

        if (vec < 18U)
        {
            if ((vec & 1U) != 0U)
            {
                pwmNotification(hetREG1,(vec >> 1U) - 1U, pwmEND_OF_PERIOD);
            }
            else
            {
                pwmNotification(hetREG1,(vec >> 1U) - 1U, pwmEND_OF_DUTY);
            }
        }
        else
        {
            edgeNotification(hetREG1,vec - 18U);
        }

       while(vec);
    }

    Please let me know if that makes sense.

  • Hi Jean-Marc,

    It doesn't work when interrupt flags are cleared in switch cases and code looks like this:

    void edgeNotification(hetBASE_t * hetREG,uint32 edge)
    {
    /* enter user code between the USER CODE BEGIN and USER CODE END. */
    /* USER CODE BEGIN (37) */
    //==============================================================================

    while(true) {
    switch(edge) {
    case SPD1A_EDGE:
    if((bSpdInpGet(SPD1A_PIN)) != (bSpdInpGet(SPD1B_PIN))) {
    uiSpd1Cnt++;
    }
    else {
    uiSpd1Cnt--;
    }
    vSpdInpIntClr(SPD1A_EDGE);
    break;
    ......
    }

    edge = hetREG1->OFF1;
    if(edge < 18U) break;
    edge -= 18U;
    }


    It does work when interrupt flags are cleared after all edge pending interrupts are served and then code looks like this:

    while(true) {
    switch(edge) {
    case SPD1A_EDGE:
    if((bSpdInpGet(SPD1A_PIN)) != (bSpdInpGet(SPD1B_PIN))) {
    uiSpd1Cnt++;
    }
    else {
    uiSpd1Cnt--;
    }
    vSpdInpIntClr(SPD1A_EDGE);
    break;
    ......
    }

    edge = hetREG1->OFF1;
    if(edge < 18U) {
    vSpdInpIntClr(SPD1A_EDGE);
    vSpdInpIntClr(SPD1B_EDGE);
    vSpdInpIntClr(SPD2A_EDGE);
    vSpdInpIntClr(SPD2B_EDGE);
    break;
    }
    edge -= 18U;
    }


    And it still works when code looks like this (note that SPD2B_EDGE is not triggered in my test setup as there is nothing connected to this input):

    edge = hetREG1->OFF1;
    if(edge < 18U) {
    // vSpdInpIntClr(SPD1A_EDGE);
    // vSpdInpIntClr(SPD1B_EDGE);
    // vSpdInpIntClr(SPD2A_EDGE);
    vSpdInpIntClr(SPD2B_EDGE);
    break;
    }
    edge -= 18U;
    }

    It seems that clearing of a single edge interrupt flag clears all pending interrupt flags.
  • Marek,

    The flag can be cleared individually by writing 1 to the corresponding bit.
    Other bit will stay un-changed.

  • Hi Jean-Marc,

    You are perfectly right.
    Flags can be cleared by writing 1's to the corresponding bits.

    Here is my original clear interrupt flag definition:
    #define vSpdInpIntClr(e) (SPD_PORT->FLG |= (SPD_EDGE_INT_FLG << e))
    It was clearing all pending interrupt flags at ones.

    I have changed it to:
    #define vSpdInpIntClr(e) (SPD_PORT->FLG = (SPD_EDGE_INT_FLG << e))
    and it woks perfectly now.

    Thank you,
    Marek