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.

Interruption within Interruption (DSP BIOS, RTI, C6727b)

Other Parts Discussed in Thread: TMS320C6727B

 

Hello,


I have some problem with DSP BIOS, RTI and interrupt 5

Actually i'm using timer 1 and compare 1,2 and 3 registers, and the interupt 5 to send a frame - via McASP1 in CPU polling mode – at specified dates

The frame is sent via the same McASP link for the 3 case, only the content change.

It work fine when compare register values are spaced enough.

But a problem appears when two compare register values are two close.

The first compare register active the interrupt properly ; So in the interrupt I clear the correponding interrupt flag in RTIINTFLAG register, the i send my frame via McASP1.

If during this interrupt the second compare register set the corresponding RTIINTFLAG the interrupt is not re-latch in the IFR even if it is latched in the RTIINTFLAG register (I checked with a modified version of my software) and I can't send the corresponding frame.

At the begining I thought it was a problem of my DSP BIOS setting.

I'm using the dispatcher for this Interrupt 5 and I checked also with Interrupt mask set to « all » or « no », but there is no difference.

I also thought about checking by myself the RTIINTFLAG register and use ISR register to set the interrupt 5.

It solved the probleme now, but It's not an option for us because if the RTIINTFLAG updated after the test we will got the same problem.


Is that a normal operation I mean the fact that the same interuption cannot be automaticly relatched if your are already in the interuption sub routine ?


I'm using.

DSP bios 5.41.9.34

Code generation tool 6.1.11

DSP TMS320C6727B


Here the code

Variable with first letter capital are global variables.

void INT5_real_time_timer (void)

{

//Use for later debuging

Int5_routine_execution_counter++;

//A

if (RTIINTFLAG & 0x00000002)

{

RTIINTFLAG = 0x00000002; // Release interrupt flag

RTICLEARINT = 0x00000002;

// Update frame content

Stage_1_order[Selected_channel] |= 0x001;

Stage_2_order[Selected_channel] |= 0x001;

 

//save sent date and update counter

Command_sent_counter[Selected_channel][A_INDEX]++;

Command_sent_dsp_timer[Algo_selected_channel][A_INDEX]

= TIME_dsp_timer_datation_correction(RTIFRC1);

}

 

//B

if (RTIINTFLAG & 0x00000004)

{

RTIINTFLAG = 0x00000004;

RTICLEARINT = 0x00000004;

 

// Update frame order

Stage_1_order[Selected_channel] |= 0x010;

Stage_2_order[Selected_channel] |= 0x010;

 

//save sent date and update counter

Command_sent_counter[Selected_channel][B_INDEX]++;

Command_sent_dsp_timer[Selected_channel][B_INDEX]

= TIME_dsp_timer_datation_correction(RTIFRC1);

}

 

//C

if (RTIINTFLAG & 0x00000008)

{

RTIINTFLAG = 0x00000008;

RTICLEARINT = 0x00000008;

 

// Update frame order

Stage_1_order[Selected_channel] |= 0x100;

Stage_2_order[Selected_channel] |= 0x100;

 

//save sent date and update counter

Command_sent_counter[Selected_channel][C_INDEX]++;

Command_sent_dsp_timer[Selected_channel][C_INDEX]

= TIME_dsp_timer_datation_correction(RTIFRC1);

}

 

// Send M4 frame with order(s)

Command_order_duration = Command_order_duration[Selected_channel]*100;

Send_McASP1_frame();

State_machine_updating ();

}

 

regards

 

Julien

  • Julien,

    If you go to the TI Wiki Pages and search on C6000 BIOS Workshop, you will find an excellent source of training material for C6000 devices operating under DSP/BIOS (workshop v5.93) or SYS/BIOS (workshop v6.00).

    The section on interrupts explains that you should not do lengthy work inside an ISR, but should use DSP/BIOS features to start this work outside the ISR. This way you will not spend too much time inside the ISR, where interrupts could be disabled.

    Your actions with the McASP, using CPU polling to perform the data operations, ties up the CPU for a long time. If you use the features of DSP/BIOS, either posting a SWI (Software Interrupt), or posting a SEM (Semaphore) to a TSK (Task), you will be able to enter and exit the ISR very quickly and still get the work done in the time required and in the right order.

    Finding hooks to force unusual behavior, such as the re-entrant ISR method you are discussing, will lead to more logic confusion and system problems that are much harder to figure out than the work you have already done to find this problem.

    Please look at the C6000 workshop material and post back here with questions on that material, if needed.

    Regards,
    RandyP

  • Randy,

    I still don't understand the purpose on the bitmask in the DISPATCHER. I looked in the DSP/BIOS documentation and it seems "self" or "no" have the same behavior, based on what I saw in my program.

    Actually I don't want a reentrant ISR, I just want to execute It a second time when it's over, if the RTIINTFLAG has been latched again during the interrupt. Because even if the interrupt is as short as possible it could happen, especially with RTI and compare register.

    This frame sending is the most critical part on my application, I can't take the risk to posponned it too much (more than 50us) or miss it.

    I will try to change some features in my program, based on what you told me, and let you know.

    Thanks,

    Julien

     

     

  • The BIOS "mask" field is related to what interrupts should be masked during an ISR.  I highly recommend setting this box to "ALL", which means to mask all other interrupts.  In other words, pre-empting of interrupts will NOT be possible.  Make sure you do this for all of your ISRs.  This is the setting you need to achieve your goal. Here's an example timeline to illustrate:

    1. RTI interrupt latched
    2. RTI interrupt processed, CPU branches to corresponding vector and automatically clears CPU IFR flag
    3. RTI ISR starts executing (all other interrupts are masked)
    4. During the RTI ISR, another RTI interrupt latches in IFR.  It will be not be processed because you are masking all interrupts.  (Note that for "none" this interrupt would immediately pre-empt your initial ISR which I think you do NOT want to happen.)
    5. RTI ISR completes.
    6. The pending RTI interrupt can now be processed.

    Brad

  • Hello Julien

    I don't believe the previous answers hit to the heart of the problem or provided a real solution.  Here's my two cents.

    We faced a similar situation.  The issue is :

    a) RTI Interrupts 1, 2, 3, and RTI Overflow Interrupts 0 and 1 all share the INT5 input on the CPU. 

    b) The CPU IFR register responds only to an edge on the incoming INTn lines.  A constant request level will not regenerate the IFR bit after one source is serviced.

    c) When two or more interrupt sources on the shared RTI interrupt line become set before one interrupt is serviced, the HW is inherently unable to get the CPU IFR bit set again.  The INT5 lines will not show another edge because it is the OR of all the sources.  Clearing one fails to generate another edge on the line.  As such, one or more of the RTI interrupt sources will remain pending and unserviced.

    The bottom line on the above is that the shared RTI interrupt sources mentioned in a) are inherently problematic with multiple coincident interrupts.

    We are attempting to solve this problem by using a path through the dMAX controller.  It has the ability to generate interrupts from various sources and map those interrupts to one of the six dMAX interrupt inputs on the CPU (INT9-INT13 and INT15).  Figure 1-1 in the RTI Peripheral app note shows the interrupts INT0-3 also being associated with DMAREQ0-3.  In the dMAX, you can associate these events with whatever of the six CPU interrupts you want.  We believe this gives one the ability to associated the various RTI interrupt sources with any of the INT9-13 or INT15 lines.  One can then have a unique CPU INT line for each RTI interrupt.

    Of course, one must only use resources in the dMAX that are not used by DMA transfers employed in the application. 

    I hope this helps and am happy for further feedback from anyone monitoring this as well.

    ... Richard

  • Richard,

    I think you are right that preemption is not the key issue. I believe you are correct that the shared interrupt is at the heart of the issue. In the ISR you must ensure that all enabled RTI interrupts are zero before exiting the ISR. That's the only way to guarantee that you will generate the required edge to the CPU IFR. 

  • We have solved the issue using the dMAX's ability to generate events from RTI sources.  In setting up the RTI, we set one interrupt source to generate its request on INT1 (which maps to CPU interrupt INT5) and a second to use DMA2REQ.  This was done using the RTI control register RTISETINT.  In the dMAX, we mapped the event generated on DMAREQ2 to one of the spare DMA interrupts to the CPU (i.e. INT13).  The end result is that we are now generating two non-shared RTI interrupts separately on INT5 and INT13.

    Brad, I'd like to expand on your comment.  To follow my comment, understanding how the CPU's interrupt controller works is important (which I finally found in the C67x instruction set reference, Spru733a) . The CPU's IFR bit for the interrupt being serviced is automatically cleared by the hardware on transfer to the ISR.  If multiple sources arrive at the CPU before entry to the ISR, the IFR bit that is set is associated with all of them.  Any sources that arrive after entry to the ISR will re-enable the IFR bit.

    In the ISR, one needs a loop to check all of the shared interrupt sources since the single IFR enable may be associated with more than one source.  Every one that is set should be acted on prior to exiting the ISR.  As each one is acted on, the respective interrupt source in the RTI should be cleared. 

    Note that it might happen that a source that arrived after entry to the ISR is actually serviced in the loop above.  Even though that RTI source is cleared by the ISR handling, it has already generated an additional IFR enable.  In this case, the ISR will be executed a second time very shortly after exiting the initial service request.  The ISR simply needs to be prepared to find that no interrupt source is unserviced, in which case the ISR simply exits having done nothing. 

    In hindsight, this subsequent thought is probably better than our dMAX solution which is a little indirect and messing with the dMAX is not trivial.

    ... Richard

  • Richard -- thank you for providing all this excellent detail. That is exactly what I meant in my previous post. (My last couple posts have been from my phone which is why they are so short!)

     

    Can the OP please provide an update?  Is your problem resolved?

  • One additional note.  My developer notes that he implemented the above strategy of testing and clearing each interrupt source in the ISR service routine and still had problems.  I believe this issue is that all set interrupt sources must be cleared simultaneously in one instruction.  If clearing them one-by-one as I suggest, it is possible that an earlier cleared one or another one become active again before all are cleared.  In this case, the INT5 line remains active without another edge to set the IFR bit again. 

    The revised suggestion is then to read and save the register containing all the interrupt source bits. Following that immediately clear all interrupt bits in one instruction.  Finally, act on the saved interrupt sources bits that are set.

    ... Richard

  • You had it right the first time. You need to loop until you read back RTIINTFLAG such that all enabled interrupts are zero. This will guarantee that the CPU sees an edge when the next interrupt is latched. 

  • Yes, I agree with your statement.  Writing all possible request sources after reading them has a small hole between reading and clearing that could cause one source that arrived in between to be missed. Your suggestion of looping until all enabled interrupts are zero should work.

    The only hole in the final design here is successive interrupts from one particular source, i.e. the time between finding a source bit set and clearing it is a hole where a second request from that source could arrive and be cleared without being serviced.  This is fundamental with the type of interrupt sources being handled here.  Whether this will be an issue is dependent on each application.  In our case, this will not be an issue.

    ... Richard

  • Julien B--

    This thread has become a discussion between me and Richard!  Is your problem solved?  I suspect Richard hit the nail on the head, but it would be great for you to confirm.

    Brad