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.

CCS/F28M36P63C2: FFT on F28M36x

Part Number: F28M36P63C2
Other Parts Discussed in Thread: C2000WARE, CONTROLSUITE

Tool/software: Code Composer Studio

I am trying to implement FFT on the F28m36x board I am using. I have used the 2837x_vcu0_rfft_512 example as a template. I have configured vcu0 unit on my board properly I believe. After compilation, I looked at the memory and see functions defined in vcu0_cfft_utils.asm and vcu0_cfft_256.asm are written to memory. I took example input from rfft_512_data.asm and pointed the fft input pointer to the data and ran the code to see if the output from the fft matched the expected output. When I looked at the disassembly I see the function label is loaded into the working registers but I don't see the assembly code for the functions within the disassembly window. I continue to step through code and see the work buffer is filled with new data but after finishing the code I look at the contents of the input buffer and the data hasn't changed. It believe that the assembly functions are supposed to write back to the input buffer if the number of points are even, in which case they are. I'm a tad bit stumped

cfft16_t fft = rfft16_512P_DEFAULTS;

ComplexShort fft_work_buffer[256];

void rfft16(cfft16_t *fft_hnd);

void main(void){

fft.ipcbptr = (int *)RFFT16_512p_in_data + 0;
    fft.workptr = (int *)fft_work_buffer +  0;
    fft.init(&fft);
    rfft16(&fft);
    int k;
    int s,t,v;
    for (k = 0; k<DATA_LENGTH; k++){
        if(abs(RFFT16_512p_out_data[k] - RFFT16_512p_in_data[k]) > EPSILON){       
            s = RFFT16_512p_out_data[k];
            t = RFFT16_512p_in_data[k];
            v = abs(s-t);
            fail++;
        }
        else{
            pass++;
        }
    }

After iterating through the for loop I have 512 fails. the fft structure and functions are included in the vc0_fft.h/vcu_types.h files from the dsp library under v2_10_00_00/include/vcu0

  • Joshua,

    Please give me a day or so to review this and let me know.

    Thanks,
    Sira
  • Hi Sira,

    So I was able to figure out how to step through the assembly and look at assembly code. The problem now seems to be related to this section of code from the function _cfft16_flip_re_img found in vcu0_cfft_utils.asm

    RPTB        FLIP_LOOP, AR1
    MOV         AH, *+XAR2[0];
    MOV         AL, *+XAR2[1];
    MOVL        *XAR2++, ACC

    I can see in the registers the correct values from memory loaded into the accumulator, but on the store step the memory doesn't seem to change.

    For example:

    @0x0013250A 0xFA60

    @0x0013250B 0xF876

    AH: 0xFA60, AL: 0xF876, XAR2: 0x0013250A

    On write back to XAR2 the contents never change. I'm not sure what the problem is.

    Thanks,

    Josh

  • Hi Joshua,

    Before I get into the technical details of the issue you are experiencing, I would like to request/ask if you could switch from using the VCU FFT to the FPU FFT. C2000Ware v1_06_00_00 does have support for FPU as well as VCU libraries under the DSP libraries folder. However, moving forward, we will be removing support for the VCU FFT library. With this in mind, and since the F28M36x device contains an FPU, I am requesting the change.

    If this works, could you repeat your steps with the FPU FFT library and let me know how it turns out.
    Thanks,
    Sira
  • Hi Sira,
    Thanks for the response. So I believe I have the project setup correctly. I am using the 2833x_RFFT example as a template. I have the properties configured correctly(I hope) and the project compiles. I am stuck in the debugger at the moment. I call the RFFT_f32(&rfft) function and I step through the assembly:
    _RFFT_f32:
    ADDB SP,#2
    MOVL *-SP[2],XAR4
    LCR _rfft_f32_Stages1and2and3andBitReverse
    MOVL XAR4,*-SP[2]
    LCR _rfft_f32_Stages4andUp
    SUBB SP,#2
    LRETR
    everything runs smooth until the LRETR instruction. The debugger throws a message saying there is a break at the program instruction memory position. I believe this is the return instruction at the end of the function call?
  • Hi Sira,

    Sorry to keep hitting you with questions, but I'm curious about the disassembly window. Some of the code appears like:

    1293c5:    761F002B    MOVW         DP, #0x2b
    1293c7:    4A2F        TBIT         @0x2f, #0xa
    1293c8:    6C07        SB           C$L18, NTC
    1293c9:    482F        TBIT         @0x2f, #0x8
    1293ca:    6D03        SB           C$L17, TC
    1293cb:    492F        TBIT         @0x2f, #0x9
    1293cc:    6C03        SB           C$L18, NTC
    417              return(0);

    and other parts of it look like

    1293d2:    FE02        ADDB         SP, #2
    140             MOVL *-SP[2],XAR4
    1293d3:    A842        MOVL         *-SP[2], XAR4
    141             LCR  _rfft_f32_Stages1and2and3andBitReverse
    1293d4:    765293DB    LCR          $C:/ti/controlSUITE/libs/dsp/FPU/v131/source/C28x_FPU_LIB/RFFT_f32.asm:192:356$
    142             MOVL XAR4,*-SP[2]
    1293d6:    8A42        MOVL         XAR4, *-SP[2]
    143             LCR  _rfft_f32_Stages4andUp
    1293d7:    76529447    LCR          $C:/ti/controlSUITE/libs/dsp/FPU/v131/source/C28x_FPU_LIB/RFFT_f32.asm:363:590$
    144             SUBB SP,#2
    1293d9:    FE82        SUBB         SP, #2
    145             LRETR
    1293da:    0006        LRETR       
    192              PUSH     XAR1

    I can see that they are referring to the lines from the assembly file. Does the difference stem from assembly in an .asm file vs. assembly generated from the C code?

    Also some of the labels for the functions are written as a directory pathing and others are basic labels. Could that be the reason I'm hard faulting?

    ex:

    0x1293DB: $C:/ti/controlSUITE/libs/dsp/FPU/v131/source/C28x_FPU_LIB/RFFT_f32.asm:192:356$, rfft_f32_Stages1and2and3andBitReverse

    0x12943A: rfft_32_Last 

    Both functions are written in the same file so it seems weird that they are displayed differently.

    Thanks,

    Josh

  • Joshua,

    Since your questions more pertain to CCS debug (disassembly etc.) than to the FFT library instructions per se, I have asked a colleague for advice. So you may see some comments from Vamsi.

    Meanwhile, my assumption is that you are simply executing the example code and running into an issue?? This is surprising. You should be able to run the example on Control card hardware (for example) without issue. Or does the program run correctly in real-time, and you are debugging the program (for better understanding or other reasons) and running into these issues?

    Thanks,
    Sira
  • Hi Sira,
    I realized my problem was due to the fact that I never initialized the fft structure so fft.FFTSize was zero. Once I set with a value the function ran. Now the issue I'm running into is from this line of code

    RFFTin1Buff[i] = sin(Rad) + cos(Rad*2.3567);

    In the debugger the code seems to fail in this function
    float cosf(float x)
    {
    int sign; /* the sign of the result */
    float xn, f, g, rg, result;
    int n;

    /**************************************************************************/
    /* cos(x) = cos(-x) */
    /**************************************************************************/
    x = fabsf(x);

    /**************************************************************************/
    /* Treat zero as a special case. */
    /**************************************************************************/
    if (x == 0.0) return 1.0;

    /**************************************************************************/
    /* n = round(x/PI + 1/2) (can be rounded this way, since positive number) */
    /**************************************************************************/
    n = (int) (((x + HALFPI) * INVSPI) + 0.5f);
    xn = (float) n - 0.5;

    /**************************************************************************/
    /* if n is odd, negate the sign */
    /**************************************************************************/
    sign = n % 2;

    /**************************************************************************/
    /* f = x - xn * PI (but more mathematically stable) */
    /**************************************************************************/
    f = (x - xn * C1) - xn * C2;

    /**************************************************************************/
    /* determine polynomial expression */
    /**************************************************************************/
    g = f * f;

    rg = (((R4 * g + R3) * g + R2) * g + R1) * g;

    result = f + f * rg;
    return sign ? -result : result;
    }

    The disassembly:
    cos, cosf():
    12986a: FE02 ADDB SP, #2
    101 x = fabsf(x);
    12986b: E6950000 ABSF32 R0H, R0H
    106 if (x == 0.0) return 1.0;
    12986d: E5A0 CMPF32 R0H, #0.0
    12986e: AD14 MOVST0 NF,ZF
    12986f: 6004 SB C$L1, NEQ
    129870: E801FC00 MOVIZ R0, #0x3f80
    129872: 6F57 SB C$L2, UNC //the code jumps at this location
    129 rg = (((R4 * g + R3) * g + R2) * g + R1) * g;
    C$L1:
    129873: E801FE49 MOVIZ R1, #0x3fc9
    129875: E801F512 MOVIZ R2, #0x3ea2
    129877: E8087ED9 MOVXI R1H, #0xfdb
    129879: E7100009 ADDF32 R1H, R1H, R0H
    12987b: E80FCC1A MOVXI R2H, #0xf983
    12987d: E7000051 MPYF32 R1H, R2H, R1H
    12987f: 7700 NOP
    129880: E88FC009 ADDF32 R1H, #0x3f00, R1H
    129882: 7700 NOP
    129883: E68C0009 F32TOI16 R1H, R1H
    129885: 7700 NOP
    129886: 3B01 SETC SXM
    129887: BFA90F16 MOV32 @ACC, R1H
    129889: 85A9 MOV ACC, @AL
    12988a: BDA90F16 MOV32 R1H, @ACC
    12988c: 7700 NOP
    12988d: 7700 NOP
    12988e: 7700 NOP
    12988f: 7700 NOP
    129890: E689000A I32TOF32 R2H, R1H
    129892: 7700 NOP
    129893: E8AFC012 ADDF32 R2H, #0xbf00, R2H
    129895: E801D3E9 MOVIZ R1, #0x3a7d
    129897: E8501253 MPYF32 R3H, #0x4049, R2H
    129899: E80D5111 MOVXI R1H, #0xaa22
    12989b: E7518089 MPYF32 R1H, R1H, R2H
    || SUBF32 R0H, R0H, R3H
    12989d: E805CA7B MOVIZ R3, #0xb94f
    12989f: E7200041 SUBF32 R1H, R0H, R1H
    1298a1: E801B172 MOVIZ R2, #0x362e
    1298a3: E7000048 MPYF32 R0H, R1H, R1H
    1298a5: E80CE2DA MOVXI R2H, #0x9c5b
    1298a7: E7000012 MPYF32 R2H, R2H, R0H
    1298a9: E80D9113 MOVXI R3H, #0xb222
    1298ab: E710009B ADDF32 R3H, R3H, R2H
    1298ad: E801E042 MOVIZ R2, #0x3c08
    1298af: E70000C3 MPYF32 R3H, R0H, R3H
    1298b1: E80C39F2 MOVXI R2H, #0x873e
    1298b3: E710009B ADDF32 R3H, R3H, R2H
    1298b5: E805F152 MOVIZ R2, #0xbe2a
    1298b7: E70000C3 MPYF32 R3H, R0H, R3H
    1298b9: E80D5522 MOVXI R2H, #0xaaa4
    1298bb: E71000D2 ADDF32 R2H, R2H, R3H
    1298bd: 7700 NOP
    1298be: E7000080 MPYF32 R0H, R0H, R2H
    1298c0: 7700 NOP
    131 result = f + f * rg; //this is were it jumps to
    1298c1: E7000040 MPYF32 R0H, R0H, R1H
    132 return sign ? -result : result;
    1298c3: 40A9 TBIT @AL, #0x0
    131 result = f + f * rg;
    1298c4: E7100040 ADDF32 R0H, R0H, R1H
    132 return sign ? -result : result;
    1298c6: 6C03 SB C$L2, NTC
    1298c7: E6AF0000 NEGF32 R0H, R0H, UNCF
    132 return sign ? -result : result;
    C$L2:
    1298c9: FE82 SUBB SP, #2
    1298ca: 0006 LRETR

    the code reached x = fabsf(x); but never enters the function.
    Then it goes to if (x == 0.0) return 1.0;.
    After that it jumps to result = f + f * rg;
    Then it leaves the function altogether and my RFFTinBuf is never written to. I went through the 2833x_RFFT example project properties and compared them to mine and I believe I have my project configured properly but I'm not completely sure.
  • Joshua,

    Have you been able to successfully run the TI provided 2833x_RFFT example project from C2000Ware without any modifications? That would be the first step.

    Then we can discuss what is happening in your project. What's the difference between your project the 2833x_RFFT project? I presume your project is your specific application where you want to implement FFT functionality, and you are bringing in the pieces from the 2833x_RFFT project?

    Things to check in your project would be the Linker command file, libraries linked to in the project (see picture below), header files to include (math.h), and pay attention to any Warnings generated after the build.

  • Josh,

    Sira asked me to comment on the disassembly view related questions that you posted.

    Regarding the difference in between the two disassembly views that you copied: Yes, the difference between the two code snippets that you posted is due to the direct assembly Vs the generated assembly.

    Regarding the label display difference: I think it is based on global vs local function. I can check and confirm further if you want. But I don't think it has anything to do with the issue that you are facing.

    Thanks and regards,
    Vamsi
  • Hi,

    So what I ended up doing to test whether or not the functions were working I created a new function called float sinf_new(void)/cosf_new and copied over the code from sinf()/cosf() defined in s_cosf.c and s_sinf.c and ran my code. It appears to be working. So what I'm seeing is when I run the original code, I'm taken inside the function but the function background is greyed out and where I've seen that before is when I didn't have a preprocessor symbol defined. 

    #if __TI_HAS_F32_HARDWARE && !__TI_HAS_F64_HARDWARE is included above the function definition. Should I be placing this in my predefined symbols?

    Right now I removed all the 2833x_RFFT code and I'm replacing it with the 2837x_RFFT code and I'm inserting code sections one at a time to see where any errors occur, while using the redefinition of the sin and cos functions.

    Thanks

    Josh

  • Joshua,

    I think there is no real difference between the 2833x_RFFT or the 2837x_RFFT examples. It's just a different device so the linker command files are probably different.

    Since your target is the F28M36x, you could start with a F28M36x project, and ControlSUITE has these (e.g. C:\ti\controlSUITE\device_support\f28m36x\v200\F28M36x_examples_Dual - perhaps Internal_Loopback_Serial would be a good choice). Then it's a question of porting over the files (source and header - e.g. main.c), modifying the linker command files (to assign the right locations for the FFT buffers e.g. Input, Output, Coeff, .), and getting the libraries and linking to it in the project.

    If these are done, you shouldn't have to do much else, especially stuff like copying over sin and cos function contents into different functions etc.

    Thanks,
    Sira
  • Hi Sira,

    So I started with the adc_soc f28m36x project on the c28x side and the UART project on the arm side. I was able to correctly implement the functionality that I was looking to achieve. That's when I started trying to port over the fft algorithms from the examples provided in the control suite. Right now I have the FPU working and I'm populating the FFT arrays properly after calls to the sin cos function. I believe I have my linker properly setup because I ran what I have and looked at how the program executes in the disassembly and memory viewers. The only issue I'm seeing right now is in the call to the sin and cos in the sinf.c and cosf.c. The whole block defining both functions are grayed out so I believe that means that the functions aren't included during compilation, since the code executes when I remove it from the #ifdef FPU32 && !FPU64 block. The reason I believe its a preprocessor symbol issue is because when I add the USE_TABLES statement I see the sections of code that were greyed out under that label become white.

    Thanks,

    Josh

  • Josh,

    If I understand you correctly, you are saying the sin and cos calls are within a block of code that has the #ifdef FPU32 && !FPU64 condition?

    If this is correct:
    1. I am confused why this is present. Because if the device does contain an FPU, it should be able to generate native floating point instructions (For sin and cos), and if it doesn't, it should be able to emulate them anyway. Can you let me know which project and which file has this condition block?
    2. Regardless, since the F28M36x has an FPU32 and no FPU64, this condition should be true in your project. In project properties, under C2000 compiler - Processor options, --fpu_support should be set to FPU32.

    Thanks,
    Sira
  • Hi Sira,

    I was finally able to get the project running. The only remaining issue I have involves calls to sin and cos. As I was previously saying I've had to define a new function to implement the cos and sin functions. When I add the statement __TI_HAS_F32_HARDWARE && !__TI_HAS_F64_HARDWARE to my predefined symbols the compiler tells me that I have an error which states that there are no source codes and it has nothing to do. But outside that everything else works perfect.

    Thanks,

    Josh

  • Josh,

    Please answer the 2 questions I asked earlier, and another point of confusion for me is that you previously mentioned an #ifdef FPU32 && !FPU64 block, whereas now you mention a __TI_HAS_F32_HARDWARE && !__TI_HAS_F64_HARDWARE. I would like to know the files that mention these.

    Just to be sure, you are including <math.h>, correct?

    Thanks,
    Sira
  • Hi Sira,
    Sorry I didn't notice the response you had written earlier. I had miswrote in my previous reply. The exact wording is:
    #if __TI_HAS_F32_HARDWARE && !__TI_HAS_F64_HARDWARE
    /*---------------------------------------------------------------------------*/
    /* This hardware has fast 32-bit hardware, but not 64-bit hardware. We */
    /* don't want to sacrifice the O(100x) speedup of hardware computation for */
    /* the rather small extra precision of 64-bit computation. */
    /*---------------------------------------------------------------------------*/

    #define INVSPI 0.31830988618379067154f
    #define HALFPI 1.57079632679489661923f
    #define C1 3.140625f
    #define C2 9.67653589793e-4f
    #define R1 -0.1666665668e+0f
    #define R2 0.8333025139e-2f
    #define R3 -0.1980741872e-3f
    #define R4 0.2601903036e-5f

    /****************************************************************************/
    /* COS() - Cosine */
    /* */
    /* Based on the algorithm from "Software Manual for the Elementary */
    /* Functions", Cody and Waite, Prentice Hall 1980, chapter 8. */
    /* */
    /* N = round(x / PI + 1/2) - 0.5 */
    /* f = x - N * PI */
    /* g = f * f */
    /* R = polynomial expression */
    /* */
    /* result = f + f * R */
    /* if N is even, result = - result */
    /* */
    /* This will return the wrong result for x >= MAXINT * PI */
    /****************************************************************************/
    float cosf(float x)
    {
    int sign; /* the sign of the result */
    float xn, f, g, rg, result;
    int n;

    /**************************************************************************/
    /* cos(x) = cos(-x) */
    /**************************************************************************/
    x = fabsf(x);

    /**************************************************************************/
    /* Treat zero as a special case. */
    /**************************************************************************/
    if (x == 0.0) return 1.0;

    /**************************************************************************/
    /* n = round(x/PI + 1/2) (can be rounded this way, since positive number) */
    /**************************************************************************/
    n = (int) (((x + HALFPI) * INVSPI) + 0.5f);
    xn = (float) n - 0.5;

    /**************************************************************************/
    /* if n is odd, negate the sign */
    /**************************************************************************/
    sign = n % 2;

    /**************************************************************************/
    /* f = x - xn * PI (but more mathematically stable) */
    /**************************************************************************/
    f = (x - xn * C1) - xn * C2;

    /**************************************************************************/
    /* determine polynomial expression */
    /**************************************************************************/
    g = f * f;

    rg = (((R4 * g + R3) * g + R2) * g + R1) * g;

    result = f + f * rg;
    return sign ? -result : result;
    }

    #else....
    This is defined in s_cosf.c file. I did a search in the TI folder to see the pathing for the file to see where the file is located, but the search isn't returning the file. I'm guessing its apart of the c28x_fpu_dsp_library.lib or the rts2800_fpu32.lib, but I'm not certain.
    As to the other questions, yes I have fpu32 set in the "Specify floating point support (--float_support" option under C200->Processor Options and I have included <math.h>

    my include statements;
    #include "DSP28x_Project.h"
    #include "F28M36x_Ipc_drivers.h"
    #include <math.h>
    #include <string.h>

    //rfft includes
    //********************************************************************
    #include "fpu_rfft.h"
  • Josh,

    I ran the 2837x_RFFT project (which runs properly when I run it in real-time), and I stepped through it and found the following:
    1. s_cosf.c is in C:\ti\ccsv8\tools\compiler\ti-cgt-c2000_18.1.3.LTS\lib\src (depending on your CCS version and Compiler used by the project, this path change accordingly
    2. I found the #if section and as you mentioned, it is grayed out, but that is the portion that gets executed (the opposite of what we're used to i.e. gray means it won't execute. Not sure why, but this is good to know. I tried to place breakpoints in the #else portion but CCS wouldn't). It also executes the way you mentioned a few messages prior. So it seems your execution flow and my execution flow are very similar.
    3. Based on this, I believe your project will run properly in real-time. I don't see any issues with your sin or cos and you shouldn't have to create your own implementations. Have you tried running in real-time and checking if it passes?
    4. If it still fails, can you try the F2833x or F2837x example projects, if you have the corresponding hardware?
    5. If you don't have the hardware, and if your F28M36x project is failing in real-time, could you try the USE_TABLES macro and see if it runs well in real-time?

    Thanks,
    Sira
  • Hi Sira,

    Thanks for the response. I have a few things I need to work on before getting back to the project. I will try to run it in real time when I get the opportunity and I will let you know what happens. 

    Thanks, 

    Josh

  • Josh,

    Sounds good. Please revert once you've had the chance to try.

    We have metrics to close tickets in a timely manner, so your timely feedback would be appreciated.

    Thanks,
    Sira
  • Hi Sira,

    Is there a tool in code composer to measure the execution time of the fft?

    Thanks,

    Josh

  • Josh,

    Yes, when you are in debug mode, you can go to Run-Clock-Enable (also make sure Run-Clock-Show is checked), and then you'll see a clock symbol with cycle count at the bottom right corner of the CCS window. Double click there at any point of time to reset to 0. Then you can set breakpoints, Run and see the cycle count change.
    Thanks,
    Sira
  • Hi Sira,

    My issues have been resolved and just wanna say thanks for all the help.

    Thanks,

    Josh