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.

TMS320F280049C: Looking for proper linker cmd file for fft example code

Part Number: TMS320F280049C
Other Parts Discussed in Thread: C2000WARE,

My first try is to put most of my FFT and other processing code into RAM (for speed), so looking for proper linker file.

  1. Trying to add my code to one of the matching FFT example projects (seems to be a good fit) "rfft_adc_f32_windowed",
    but under project properties "General->Linker command file:", it references a file not available for my part.
        
    In directory "\ti\c2000\C2000Ware_4_03_00_00\device_support\f28004x\common\cmd", there doesn't appear to be an appropriate cmd file for this type of project.

    What is the proper cmd linker file for a proper FFT example?

  2. The TMS320F280049C is supposed to have 100KB RAM, but the generic linker file does not seem to reference enough RAM space in there.
    What am I misunderstanding?
    Even if looking at the "\ti\ccs1220\ccs\ccs_base\c2000\include\280049C_RAM_lnk.cmd",
    there isn't enough RAM listed:

PAGE 0 :
/* BEGIN is used for the "boot to SARAM" bootloader mode */

BEGIN : origin = 0x000000, length = 0x000002
RAMM0 : origin = 0x0000F5, length = 0x00030B

RAMLS0 : origin = 0x008000, length = 0x000800
RAMLS1 : origin = 0x008800, length = 0x000800
RAMLS2 : origin = 0x009000, length = 0x000800
RAMLS3 : origin = 0x009800, length = 0x000800
RAMLS4 : origin = 0x00A000, length = 0x000800
RESET : origin = 0x3FFFC0, length = 0x000002

PAGE 1 :

BOOT_RSVD : origin = 0x000002, length = 0x0000F3 /* Part of M0, BOOT rom will use this for stack */
RAMM1 : origin = 0x000400, length = 0x000400 /* on-chip RAM block M1 */

RAMLS5 : origin = 0x00A800, length = 0x000800
RAMLS6 : origin = 0x00B000, length = 0x000800
RAMLS7 : origin = 0x00B800, length = 0x000800

RAMGS0 : origin = 0x00C000, length = 0x002000
RAMGS1 : origin = 0x00E000, length = 0x002000
RAMGS2 : origin = 0x010000, length = 0x002000
RAMGS3 : origin = 0x012000, length = 0x002000
}

thanks, Dan

  • Hello Dan,

    1. I'm not sure what you're trying to do here; when you import an FPU DSP example such as rfft_adc_f32_windowed the proper linker file is automatically pulled in, there is no need to use your own or manually pull one in from driverlib. The reason this specific command linker file is pulled in is because it allocates a section for the FFT buffer and performs an error checking for the FFT alignment (in addition to allocating memory for the FPU tables). You should be able to view the dsp_examples_rfft_lnk.cmd file in the Project Explorer window:
    2. The RAM shown in the text provided is correct; keep in mind that each address stores 16-bit values, so a RAM unit that is 0x800 in length is 2K x 16, or 4KB. I did the math for the rest of the memory allocation above, it seems correct.

    Best regards,

    Omer Amir

  • Hello Omer,

    Thank you for your answers, and thanks for correcting me about the memory size. I thought it counted as bytes instead of 16-bit words.

    When one imports a fresh project example, the cmd linker file looks like you showed above, and under project properties (General), the linker command file setting also points to the one you showed. This file 

    But, this linker file does not list all the RAM available in my part .
       

    However, as soon as I change away from the generic part to select my proper part (C280049C), the linker file goes away.

    I assume I should use the linker file for my specific part, but then modify the cmd file for the FFT buffer alignment.

    So, there are a few questions.

    1) Which added statements are needed to make use of full RAM space? Just the ALIGN steps?

    2) The FFT routines say the input buffer must be "aligned" for proper function, but the routine description claims it swaps input/output buffers for the various stages of the FFT, so shouldn't BOTH input & output buffers be "aligned"? Since I will have multiple buffers for inputs/outputs/intermediate processing (see next statements below), do all have to be "aligned" or just the initial input buffer to FFT?

    3) Please correct any incorrect assumptions.
    - input data is 1024-pt real data, so planning following steps:
    - read in 1024-pts real data
    - setup FFT structure, hnd_cfft, for 512-pt
    - 512-pt CFFT_f32t(hnd_cfft);
    - 512-pt CFFT_f32_unpack(hnd_cfft);
    - 512-pt (or 1024-pts ?) RFFT_f32_mag_TMU0() (still trying to figure out which it needs, real or complex)
    - 512-pt CFFT_f32_phase_TMU0()
    - additional freq domain processing
    - CFFT_f32_pack() (in preparation for ICFFT)
    - 512-pt ICFFT(hnd_cfft);
    - now I expect to get 1024-pt real data out (or after some additional steps?)

    thanks, Dan
    p.s. If a call would be more efficient way to handle this, you can reach me at +1-719-359-5352 or email me your contact to dan.staver@tavetech.com

  • Hello Dan,

    To simplify, when you choose a new linker file it selects this new linker file as the one to set up the memory (hence modifying it in project properties makes the project ignore the previous .cmd file). I'm not sure why you're not modifying the existing linker file and adding in the memory configuration for the rest of the RAM, there should be no issue in doing this I would think.

    To address your questions:

    1. I believe everything in the MEMORY{} section of the .cmd file is needed for initializing the RAM sections, I'm not sure if this is what you mean by the ALIGN steps
    2. Yes, all buffers are required to be aligned (given 1 pair of input/output buffer, they can be stored sequentially to be aligned properly if the input buffer is already aligned)
    3. A few points on this:
      1. CFFT has its own magnitude function with TMU0, is there a reason that you're unpacking the CFFT to use the RFFT_f32_mag_TMU0?
      2. The rest of your assumptions look fine, although I'm unsure about sampling 1024 real data points if you're only doing a 512-point CFFT.
        1. If you were using a device with more memory you could instead use the RFFT to do the FFT and process the phase/magnitude, and then use the CFFT to convert back to the time domain (there is some additional processing required to go from RFFT to CFFT for the arrays).

    Best regards,

    Omer Amir

  • I think I have now figured out the linker file with no issues there. Slight smile

    Now, for my FFT questions. Many TI documents say it is computationally preferential to do N-point FFT for 2N-point real data, then do an unwrap after, so not sure why you say not to unwrap? See example project "c2000\C2000Ware_4_03_00_00\libraries\dsp\FPU\c28\examples\fft\dsp_rfft.c", where they have 256-point real but call 128-point complex FFT.

    (line-63) #define TEST_SIZE       (256U)
    (line-107) CFFT_f32_setFFTSize(hnd_cfft, (FFT_SIZE >> 1));  // so they're setting up to do 128-point complex FFT
    (line-112) CFFT_f32t(hnd_cfft);                             // do 128-point FFT here
    (line-122) 
    CFFT_f32_unpack(hnd_cfft);                       // now they explicitly call unwrap here so NOT built-in, no????

    The document for this "CFFT_f32t" says it swaps input and output buffers for each stage so you check for final output buffer before subsequent processing.

    5.4.2.18 void CFFT_f32t (CFFT_F32_STRUCT_Handle hndCFFT_F32)
    This routine computes the 32-bit floating-point FFT for an N-pt (N = 2n; n = 5 : 10) complex
    input. This function will reorder the input in bit-reversed format before proceeding with the FFT.
    The routine uses two buffers in ping-pong fashion i.e. after each FFT stage the output and input
    buffers become the input and output buffers respectively for the next stage. The CFFT_F32 object
    uses two pointers, CurrentInPtr and CurrentOutPtr to keep track of the switching. The user can
    determine the address of the final output by looking at the CurrentOutPtr.

    Yet, in the actual "fpu_cfft.h" file contradicts this:
        C:\ti\c2000\C2000Ware_4_03_00_00\libraries\dsp\FPU\c28\include\fpu32\fpu_cfft.h

    extern void CFFT_f32t(CFFT_F32_STRUCT_Handle hndCFFT_F32);
    //! \brief Complex Fast Fourier Transform (In-Place) using a Pre Generated
    //! Twiddle Factor Table
    //!
    //! This routine computes the 32-bit floating-point FFT for an N-pt
    //! (\f$ N = 2^{n}, n = 5 : 10\f$) complex input. The routine performs its
    //! computation in-place, i.e. it uses a single buffer as both input and output
    // for each FFT stage.
    //! \param hndCFFT_F32 Pointer to the CFFT_F32 object
    //! \attention
    //! -# This function does not reorder the input in bit-reversed format before
    //! proceeding with the FFT. It assumes the user has already bit reversed the
    //! input by calling CFFT_f32_brev() prior to calling this function
    //! -# The routine requires a single buffer of size 2N (32-bit float), for
    //! computation; the buffer must be aligned to a memory address of 4N words
    //! (16-bit).

    Which is correct? Is there an FFT-expert who can help?

  • Hello Daniel,

    Many TI documents say it is computationally preferential to do N-point FFT for 2N-point real data, then do an unwrap after, so not sure why you say not to unwrap?

    I did not say you should not use the unpack function, I was just confused why you were using it. It looked like you were using it just to use the RFFT magnitude function, but if you were following the provided example then that's fine.

    Yet, in the actual "fpu_cfft.h" file contradicts this:

    I believe you are looking at the incorrect comments for the CFFT_f32t function description in the header file. I double-checked, and the comments relating to each function are directly above the function's declaration (no space between the comments and function declaration). These are the comments for the CFFT_f32t function:

    //! \brief Complex Fast Fourier Transform using a Pre Generated Twiddle
    //! Factor Table
    //!
    //! This routine computes the 32-bit floating-point FFT for an N-pt
    //! (\f$ N = 2^{n}, n = 5 : 10\f$) complex input. This function will reorder
    //! the input in bit-reversed format before proceeding with the FFT. The
    //! routine uses two buffers in ping-pong fashion i.e. after each FFT stage the
    //! output and input buffers become the input and output buffers respectively
    //! for the next stage. The CFFT_F32 object uses two pointers, CurrentInPtr
    //! and CurrentOutPtr to keep track of the switching. The user can determine
    //! the address of the final output by looking at the CurrentOutPtr.
    //! \param hndCFFT_F32 Pointer to the CFFT_F32 object
    //! \attention
    //! -# The routine requires the use of two buffers, each of size 2N (32-bit
    //! float), for computation; the input buffer must be aligned to a memory
    //! address of 4N words (16-bit). Refer to the CFFT linker command file to see
    //! an example of this.
    //! -# If alignment is not possible the user can use the alternative, albeit
    //! slower, function CFFT_f32ut
    //! \warning This function is not re-entrant as it uses global variables to
    //! store certain parameters
    //!
    //! <table>
    //! <caption id="multi_row">Performance Data</caption>
    //! <tr><th> Samples <th> Cycles 
    //! <tr><td> 64      <td> 2334
    //! <tr><td> 128     <td> 5032
    //! <tr><td> 256     <td> 11026
    //! <tr><td> 512     <td> 24250
    //! <tr><td> 1024    <td> 53220
    //! </table>
    //
    extern void CFFT_f32t(CFFT_F32_STRUCT_Handle hndCFFT_F32);

    The comments you are citing from the fpu_cfft.h file seem to be for the CFFT_f32it function, which is why they are inconsistent.

    Best regards,

    Omer Amir

  • Oh Omer, You are good and I am an idiot. Grinning

    For some reason I was indeed looking at the wrong comment block.
    I think this should solve this thread. I'll open a different thread if something else comes up.

    thanks for your help!