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.

Linking the C28x FPU fastRTS library

Other Parts Discussed in Thread: TMS320F28335, CONTROLSUITE, STRIKE

I have another question related to the use of the fastRTS library for the TMS320F28335 DSP:

I am trying to use the fastRTS library for one of my projects, and I'm having a hard time getting it to link correctly in my project.  I have been referencing the "C28x Floating Point Unit fastRTS Library - Module User's Guide V1.00 (August 6, 2008)" for my project.  The guide seems to have been written for CCSV4, while I am using CCSV5, but it looks pretty similar.  I found the library itself under the directory \ti\controlSUITE\libs\math\FPUfastRTS\V100\lib\ on my computer.

My project is a DSP/BIOS project, so in my .tcf file I have added a page 0 memory section named FPUTABLES, with a base address of 0x3febdc and length of 0x6a0.  In my short user defined linker cmd file, I defined a section named FPUmathTables using the following code:

FPUmathTables	:	LOAD = FPUTABLES,		PAGE = 0
			RUN = L03SARAM, 		PAGE = 0
			LOAD_START(_fputables_loadstart),
			LOAD_END(_fputables_loadend),
			RUN_START(_fputables_runstart)

My initialization code contains the following:

memcpy( 	&fputables_runstart,
	&fputables_loadstart,
	&fputables_loadend - &fputables_loadstart);

The project itself contains both the rts2800_fpu32_fast_supplement.lib and rts2800_fpu32.lib files.  I have tried to set the link order by going to the "link order" tab of the CCS Build options page, and putting the rts2800_fpu32_fast_supplement.lib file before the rts2800_fpu32.lib file.  I also have my user defined .cmd file (which contains the definition of the FPUmathTables section) set above both library files in the link order.  Under the C2000 Linker section, under "file search path," I have ensured that both .lib files are listed with rts2800_fpu32_fast_supplement.lib listed first, and the "search libraries in priority order" box is checked.  When building, no errors show up so it looks like everything worked correctly.

Unfortunately, if I check the .map file for my project, the FPUTABLES memory section is empty.  It shows 0 used space, so it looks like nothing was actually linked to reside in that location.  In the SECTION ALLOCATION MAP section, it shows the FPUmathTables section having origin 8000, length 0, and UNINITIALIZED attributes.  I have also additionally searched through the file for the location of the _isqrt function, and it is sitting at 0x301cc5, which is in FLASH.  So, what have I done wrong?  Why does it not seem like the fastRTS library is linked correctly?  Do I need to do something different to install it?  Please let me know if you need more information than what I have given.

Thank you,

Paul

  • As a side note, I did consider it good news that the FPUmathTables section showed an origin of 0x8000 in the .map file, since that is in fact the start of the L03SARAM section I set it to run from.  I just don't think it's right that the section is length 0!  Are there more include files I needed to provide which actually contain the #pragma CODE_SECTION(function_name, "FPUmathTables") directives to place the fastRTS functions in that section?  Or should that have been taken care of from within the .lib file?  Seems I don't fully understand the linking process.

  • Hi Paul,

    The FPU tables should already be in the bootrom at address 0x3febdc, which you cant write to. If you look at the sample cmd file in controlSUITE, you will see the "type=NOLOAD" designation for the section FPUmathTable. If you wish to copy it to RAM, load the section to one of the FLASH sectors instead.

    Paul Rancuret1 said:
    I have also additionally searched through the file for the location of the _isqrt function, and it is sitting at 0x301cc5, which is in FLASH

    The fastRTS routines are loaded to the ".text" section, which from the looks of it you have assigned to one of the FLASH sectors. If you want to copy these routines over to RAM, you can do the following in the cmd (replace FLASHA and RAML1L2 with whatever flash and ram sectors you want to use)

       .text            : {rts2800_fpu32_fast_supplement.lib},
                           LOAD =  FLASHA,        PAGE = 0
                        RUN = RAML1L2,         PAGE = 0
                        LOAD_START(_fastRTS_loadstart),
                        LOAD_END(_fastRTS_loadend),
                        RUN_START(_fastRTS_runstart)

    You can then memcpy this over using the variables defined. When you do this you should see something similar to the following in the map file:

    .text      0    00338000    0000078c     RUN ADDR = 00009000
                      00338000    000006a0     rts2800_fpu32_fast_supplement.lib : FPUmathTables.obj (FPUmathTables)
                      003386a0    0000004a                                       : atan_f32.obj (.text)
                      003386ea    00000034                                       : cos_f32.obj (.text)
                      0033871e    00000034                                       : sin_f32.obj (.text)
                      00338752    00000021                                       : sqrt_f32.obj (.text)
                      00338773    00000019                                       : div_f32.obj (.text)

  • Thank you for the response Vishal!  I think I may still have some issues with my linking, but I understand a bit better now.

    I have tried your suggestion, but do not see the same result in my .map file.  Instead, it looks like this:

    .text	0	00302929	0000001c	RUN ADDR = 00008428
    		00302929	0000001c	rts2800_fpu32_fast_supplement.lib : isqrt_f32.obj (.text)

    I do not actually see FPUmathTables.obj anywhere in the .map file at all.  I have used the sin, cos, atan2, isqrt, and sqrt functions in my code, but the only object which seems to show up there is the isqrt_f32.obj.  Could this be because that particular function is in a separate header file from the rest (C28x_FPU_FastRTS.h)?  I do have math.h included in the project as well - is there some other header I'm missing?

    If I look at the section of the .map file it shows each address, I found the following few lines where the supplemental library went:

    0030291d	_fastRTS_loadstart
    00302939	BIOS_init
    00302939	_BIOS_init
    00302939	_fastRTS_loadend

    Does it strike you as odd that the only things called out between _fastRTS_loadstart and _fastRTS_loadend are called BIOS_init?  Thank you again for your help,

    Paul

  • I have also noticed that within the .text section of the .map file, I can find the following line:

    00301af5	00000088	rts2800_fpu32.lib : fs_div.obj (.text)

    Shouldn't this have been replaced by the div_f32.obj (.text) function from the fastRTS library instead?  It looks like for some reason, the standard library is still being used.

  • Sorry I made a small mistake in my earlier post. In the linker command file you would define the section as:

       .text            : {rts2800_fpu32_fast_supplement.lib(.text)},
                           LOAD =  FLASHA,        PAGE = 0
                        RUN = RAML1L2,         PAGE = 0
                        LOAD_START(_fastRTS_loadstart),
                        LOAD_END(_fastRTS_loadend),
                        RUN_START(_fastRTS_runstart)

    What this does is tell the linker to take the .text sections of the fastRTS library and place it in FLASHA. When I did this I see the following in the map file:

    .text      0    00338000    000000ec     RUN ADDR = 000091b9
                      00338000    0000004a     rts2800_fpu32_fast_supplement.lib : atan_f32.obj (.text)
                      0033804a    00000034                                       : cos_f32.obj (.text)
                      0033807e    00000034                                       : sin_f32.obj (.text)
                      003380b2    00000021                                       : sqrt_f32.obj (.text)
                      003380d3    00000019                                       : div_f32.obj (.text)

    FPUmathTables
    *          0    003febdc    000006a0     NOLOAD SECTION
                      003febdc    000006a0     rts2800_fpu32_fast_supplement.lib : FPUmathTables.obj (FPUmathTables)

    Paul Rancuret1 said:
    I have tried your suggestion, but do not see the same result in my .map file.

    What you are seeing is correct. The linker will only link in the routines that are being called by you're code. So if you are calling isqrt then you should only see that routine in the map file

    Paul Rancuret1 said:
    Does it strike you as odd that the only things called out between _fastRTS_loadstart and _fastRTS_loadend are called BIOS_init?

    These are just labels, so the fastRTS routines will lie between 0x030291d and 0x302989 and the BIOS_init routines start at 0x0302939

  • yeah you're right. It should be calling FS$$DIV from the fastRTS since you have declared the link order correctly. Im not sure what is causing this.

    Can you trace which .c file is calling this routine and try calling the isqrt function there just to be sure it sees the fastRTS lib....what you can do is set the properties of the .c file to generate C-interlisted assembly(properties->compiler->assembler options->--keep_asm and under Source interlist choose --c_src_interlist) and then check the assembly to see which routine is being called

  • Vishal,

    In one of my source files, at line 88, in order to show both the division and isqrt functions used, I added the following line:

    pwm_deadtime_cnt = (Uint16)(1/isqrt(36));

    I would expect it to set pwm_deadtime_cnt to 6 in that line, but unfortunately I don't have my target DSP with me right now so I can't check until next week.  I had it generate and keep an assembly file as suggested, although I am pretty ignorant when it comes to reading assembly.  In the assembly file, I never found any instances of FS$$DIV or any kind of 'div' in general.  I did find several instances of isqrt.  Near the beginning of the file, it seems to declare a global variable named _isqrt with the following:

    ;**************************************************************
    ;* UNDEFINED EXTERNAL REFERENCES                              *
    ;**************************************************************
     .global _isqrt

    Later in the assembly file, it references that _isqrt symbol in the following set of code:

    $C$DW$4 .dwtag  DW_TAG_subprogram, DW_AT_name("isqrt")
     .dwattr $C$DW$4, DW_AT_TI_symbol_name("_isqrt")
     .dwattr $C$DW$4, DW_AT_type(*$C$DW$T$658)
     .dwattr $C$DW$4, DW_AT_declaration
     .dwattr $C$DW$4, DW_AT_external

    Finally, in the section of the code which seems to actually perform what I put on line 88 in my source file, the following bit of assembly was generated:

    ;----------------------------------------------------------------------
    ;  88 | pwm_deadtime_cnt = (Uint16)(1/isqrt(36));                             
    ;----------------------------------------------------------------------
            MOVIZ     R0H,#16912            ; [CPU_] |88|
    $C$DW$15 .dwtag  DW_TAG_TI_branch
     .dwattr $C$DW$15, DW_AT_low_pc(0x00)
     .dwattr $C$DW$15, DW_AT_name("_isqrt")
     .dwattr $C$DW$15, DW_AT_TI_call
            LCR       #_isqrt               ; [CPU_] |88|
            ; call occurs [#_isqrt] ; [] |88|
     .dwpsn file "../F2833x_ePWM.c",line 90,column 2,is_stmt

    I hope you can make sense of this, because it doesn't mean a lot to me! :)  Thank you again for your help,

    Paul

  • Paul,

    All that clutter you are seeing around the assembly is the DWARF debug information. In the properties of the .c file you can turn off the debug symbol generation from :

    compiler->basic options->debug model->--symdebug:none

    Once you rebuild we should be able to see the C and assembly properly.

  • Vishal,

    After rurning off the DWARF debug info, here is the section of code pertaining to the command I added in line 88:

    ;----------------------------------------------------------------------
    ;  88 | pwm_deadtime_cnt = (Uint16)(1/isqrt(36));                             
    ;----------------------------------------------------------------------
            MOVIZ     R0H,#16912            ; [CPU_] |88|
            MOVL      @_pwmfullduty,XAR4    ; [CPU_] |79|
            LCR       #_isqrt               ; [CPU_] |88|
            ; call occurs [#_isqrt] ; [] |88|
            MOVW      DP,#_pwm_deadtime_cnt ; [CPU_U]

    It still looks pretty much the same as before, without the extra chatter.  I'm not sure what the MOVIZ command is, but otherwise I don't even see where the divide is taking place.  I was still unable to find anything with the letters 'div' in the .asm file.  The isqrt() function is called by referencing an undefined external variable _isqrt.  At the bottom of the document, the following section defines _isqrt as an external global symbol:

    ;**************************************************************
    ;* UNDEFINED EXTERNAL REFERENCES                              *
    ;**************************************************************
     .global _isqrt

    Do you know where I can find the external definition of _isqrt?  I'm still not sure how to verify whether or not it is actually using the fastRTS library.

    Thanks for the help,

    Paul

  • Vishal,

    I found the problem with my linking.  Looking into the "Link Order" tab of the build settings interface, I found that there were multiple calls to the rts800_fpu32.lib which I had not selected and added to my link order list.  When I clicked "Add," I noticed that the rts2800_fpu32_fast_supplement.lib and the rts2800_fpu32.lib were each listed twice, but I had only selected each one and added it to the link order list once.  So, I made sure to add all four of those objects to the list and ensure the fastRTS libraries (both linkings) occurred before any rts2800_fpu32.lib linking.  I'm not sure how I ended up with them in the list twice, but it doesn't seem to hurt anything.  I'll just make sure to be more careful about finding all references to an object in the link order in the future. 

    I have also been able to verify that the rts2800_fpu32_fast_supplement.lib is being used for the appropriate functions.  Thank you for showing me how to set that up so they run from RAM!  The following excerpt from the .map file verifies that they are running from RAM, as you showed me how to do:

    .text	0	00301209	000000a5	RUN ADDR = 00008ac8
    		00301209	0000004f	rts2800_fpu32_fast_supplement.lib	: atan2_f32.obj (.text)
    		00301258	00000021				: sqrt_f32.obj (.text)
    		00301279	0000001c				: isqrt_f32.obj (.text)
    		00301295	00000019				: div_f32.obj (.text)

    I appreciate the help, and I now consider this issue solved! 

    Thank you,

    Paul

  • I am trying to move "fast_supplement" routines to RAM:
    My cmd-file:
    MEMORY
    {
    PAGE 0: /* Program Memory */
    RAML0123 : origin = 0x008000, length = 0x004000 /* on-chip RAM block L0 */
    FLASHA : origin = 0x338000, length = 0x007F80 /* on-chip FLASH */
    }
    SECTIONS
    {
    .fastRTS : {
    rts2800_fpu32_fast_supplement.lib<sin_f32.obj>(.text)
    rts2800_fpu32_fast_supplement.lib<cos_f32.obj>(.text)
    },
    LOAD = FLASHA, PAGE = 0
    RUN = RAML0123, PAGE = 0
    LOAD_START(_fastRTS_loadstart),
    LOAD_END(_fastRTS_loadend),
    RUN_START(_fastRTS_runstart)
    }
    My map-file:
    .fastRTS 0 0033baae 00000068 RUN ADDR = 00008f43
    0033baae 00000034 rts2800_fpu32_fast_supplement.lib : sin_f32.obj (.text)
    0033bae2 00000034 : cos_f32.obj (.text)

    At the beginning of my code:
    memcpy(&fastRTS_runstart, &fastRTS_loadstart, &fastRTS_loadend - &fastRTS_loadstart);
    Then I call sin/cos routines periodically in timer interrupt (at frequency 10 kHz):
    float f, f1 = 0.25;
    DINT; // as a precaution
    f = sin(f1);
    f = cos(f1);
    Everything almost works, routines sin/cos are called from RAM and calculate correct result.
    But after several calls CPU is resetting.
    If I move to RAM only one routine (sin or cos) then everything works fine, there is no CPU reset.
    What can be the problem?
    PS: excuse me for my bad english )
  • Sergey,

    At a glance I don't see anything wrong with how you are allocating the function calls, so I'm not really sure what would cause your CPU resets.

    Are you using the watchdog timer?  I notice that you are disabling interrupts while the interrupt is being serviced.  I wonder if you have another interrupt that is servicing the watchdog, perhaps that one is missing events because the sin() and cos() functions together are taking enough time and disabling the other interrupts for too long.  If that's the case, you could possibly service the watchdog in that same interrupt, instead of a separate routine.

    One other thing worth mentioning is that the fastRTS library does have a sincos() function, which calculates both the sin and cos of an angle simultaneously.  I believe it is faster than calling the sin() and cos() functions separately, so making that change may help.

    Hope this is helpful!

     

    Paul

  • I found the problem, it is not related with moving routines to RAM. Sorry for false alarm.
    Anyway, thanks for your advice about sincos function.