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.

DSPLIB FFT and the interrupts

Other Parts Discussed in Thread: MATHLIB

Dear TI,

In my APP the EDMA collects the data from the McAsp port of the codec using Ping-Pong buffers. When the ping buffer is full then I run DSP FFT and I process the FFT results. When I am ready then I switch to the pong buffer and do the same. (I am using the LDKC6748 dev. kit)

The APP works more or less for 25-30 seconds then it crashes. The crash means the program counter jumps out the SHRAM (0xc0000000) range and points to the unknown location in the 0x6000000 memory ranges where are NOPs only).

If I replace the DSP chip based FFT with my C language FFT function then there is no crash but the APP runs very slow.

I checked this forum for hours and I realized that – what a surprise! - I must disable the global interrupts while the DSPLIB FFT function is running. Is this true? (Not talking about the magic “interrupt tolerant but not interruptible statement”)

If I disable the interrupts the APP runs up to 1 minute but it crashes on the same way.
But, the most serious problem is: while the global interrupts are disabled the data collection part does not work. There is no display update, serial port handing, temperature and pressure measurement and other digital IO handling. Nice! This means 8-12 ms dropouts in my case.

If the above story is true then how can the C6748 processor be used for collecting data and processing it with the DSP chip? It is unbelievable, is not it?

I just can hope that this story is a bad dream only…
Louis

  • Hi,

    Thanks for your post.

    Preliminarily, you have to check the appropriate DSP FFT library's release notes first to be aware of the known issue on the particular library release you are using, but with past experience with the DSP library function usage referred on the E2E forum posts & based on the known issues on the appropriate DSP library releases, it would be recommended to disable the global interrupts before calling the DSP FFT library function whereever applicable in your code and resume it back once the code exit out from the desired DSP FFT library function which you are using the code.  I mean, disable the interrupts before entering into DSP library function and return it back like, re-enabling the interrupt once the control  gets out from the corresponding library function. Yes it is true and it is applicable to some DSP library releases.

    To my opinion, it shouldn't affect the data collection part since you are disabling the interrupt only at the place before it calls the DSP FFT library function and immediately re-enabling the same interrupt back once after the corresponding library function is called.

    Kindly search for the similar posts on E2E forum community and for sure, you would get the appropriate posts with the same scenario.

    Thanks & regards,

    Sivaraj K

    -------------------------------------------------------------------------------------------------------

    Please click the Verify Answer button on this post if it answers your question.

    -------------------------------------------------------------------------------------------------------

  • Hi Sivaraj K (again)
    Thanks for the reply but the point was not whether I checked the forum topics or not. (Yes, I did, for long hours and hours)

    Okay, so it is true, I have to disable the interrupt before calling the DSP FFT then I can re-enable it. My note: It is an important information so it must be in the DSPLIB documentation, and in the example program… but I found it among the forum topics only…

    Finally we have to use the FFT from DSPLIB this way:

    //+++++
    // Process A channel
    //-----
    	// Create complex array for A channel
    	FFTCreateInputArrayA(FFT_N);
    
    	// Do the FFT on A channel
    	IntGlobalDisable();
    	DSPF_sp_fftSPxSP(FFT_N, x_sp, w_sp, y_sp, brev, 4, 0, FFT_N);
    	IntGlobalEnable();
    	// Process A channel here
    ...
    ... //+++++ // Process B channel //----- // Create complex array for B channel FFTCreateInputArrayB(FFT_N); // Do the FFT on B channel IntGlobalDisable(); DSPF_sp_fftSPxSP(FFT_N, x_sp, w_sp, y_sp, brev, 4, 0, FFT_N); IntGlobalEnable();
    //Process B channel here

    Some analysis: The 1024 point FFT takes about 372000 clocks (Measured with CSS6 clock function). It means around 1.25ms @300Mz clock (which is very good result!!!!). I have to do it twice with the another channel. So anything which is interrupt based will be stop working for around 2.5ms. This means ¼ part of the 100 Hz input sine will not be sampled. The signal won’t be continuous and FFT hates this. This is why I have terrible standard deviation after processing the FFT results.

    The other question was: why the CPU jumps out from the normal PC range if I enable the FFT function call within one minute. The same program without calling the DSP FFT function runs forever. It does not matter whether the interrupt is disabled or enabled before calling the DSPLIB FFT function. The program crashes up after 30 (interrupts enabled) or 60 (interrupts disabled then re-enabled) seconds and the PC jumps out to 0x64fe4dee address (This address is random) The stack pointer is right, the stack is 4096 byte long.

    How can I use CCS6 debugger to determine what causes the crash?

    Thanks for your help.
    Best regards,
    Louis

  • Louis,

    Since I am not familiar with the specific issues that Sivaraj has experienced, I will cautiously say that you should not have to disable interrupts when using the DSPLIB functions. This would be a serious loss for the these functions to require that. I could not find documentation for this in the C674x DSPLIB document, but the older C64x DSPLIB had the following:

    SPRU565B 2.2.6 Interrupt Behavior of DSPLIB Functions said:

    All of the functions in this library are designed to be used in systems with interrupts. That is, it is not necessary to disable interrupts when calling any of these functions. The functions in the library will disable interrupts as needed to protect the execution of code in tight loops and so on.

    If a function is "Interrupt-tolerant", that means you do not have to disable interrupts before calling the function. It is okay for interrupts to be enabled and for them to become active during the function's execution.

    If a function is "interruptible", that means if an enabled interrupt becomes active during the execution, that interrupt will be serviced.

    Any interruptible code sequence is also interrupt-tolerant. But code that is interrupt-tolerant might not be interruptible. This may be the case for some DSPLIB functions, if they disable interrupts for some part or all of the code.

    You should assume, in my opinion, that the interruptibility of the code is not your problem. Especially since you disabled interrupts around the function calls and still have the crash. Something else is the problem.

    The most common problem is stack overflow. Otherwise, it would be some other pointer table overflow.

    You said "the stack pointer is right, the stack is 4096 byte long', but that is not evidence that the is okay. First, double the size of the stack and see if it changes the problem. Second, fill the stack with something like 0xaaaaaaaa then look at the end of the stack when the crash occurs.

    After that, you will have to start taking out parts of the program one-at-a-time until you find the part that quits causing the crash when that part is removed.

    Good luck.

    Regards,
    RandyP

  • Hi RandyP,

    Thank you for the very good analysis. Filling the stack with a pattern is a very good idea. I removed disabling interrupts which also sounds funny to me. Thanks for clarifying the difference between interruptible and interrupt tolerant.

    Yes, I though the same, taking out the suspicious parts of the code, like phase [atan(imag / real)] or magnitude [sqrt(imag*imag + real*real)] calculations dramatically decreased the crashes.

    Now I am checking for division by zero, do not call squaring and sqrt if the real and/or imag are null. But sometimes it still crashes. I need to speed up the post processing of the FFT results. It takes (including the 2x 1024 points FFT) more than 10 ms, which is fast processing but the CPU runs on near 100%. By the way it would be very nice to use the profiling for C6748 with XDS510 USB emulator but I could not.

    I found an atansp(imag, real, result, n) function in the MathLib which uses the DSP chip and very fast, even interruptible function. Unfortunately I could not find any magnitude - square root of square sums – DSP accelerated functions in the MathLib. Only 1/sqrt() or sqrt(1/x). Interesting. TI has HW accelerated FFT, and phase calculations but there is no DSP accelerated magnitude calculation?

    Thanks for your help.
    Best regards,
    Louis

  • Crash solved!
    There was no stack overflow, the stack did not go down more than 512 bytes. There was no division by zero or sqrt(-1) error. This was trickier.

    I wrote an GetElapsedTime() function using the low 32-bit of the first TIMER64. I created an elapsed time history array[512] and I automatically saved the elapsed time when the GetElapsedTime() was called. This way I could check time was necessary to complete any functions.

    I measured the elapsed time in the EDMA handler. The EDMA collects the left+right channel data from the codec. I set the EDMA to store 1024 samples from the CODEC. The EMDA update time @48kHz (20.83usec) sampling frequency was 10.67 ms.

    I also called the GetElapsedTime() function from the main() loop when I processed the collected samples. The 2x1024 point FFT (+ calculating and finding the magnitude max, and the phase at the magnitude max) needed more than 20ms!!!

    Obvious if the processing needs more time (2x) than collecting the data the soon or later the system collapses. I incremented the sample count to 4096. Now the EDMA update time is much longer, around ~40ms. The 20 ms long processing can easily run in the main loop. Even the UART/USB connection also became live. I can read the measured data from the dev. kit.

    Thanks for everybody for the valuable help. Good luck! (And keep the interrupts enabled)
    Louis