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.

TIVA Launchpad direct ROM calls in workshop LAB 5

Other Parts Discussed in Thread: TM4C123GH6PM

Direct ROM calls in workshop LAB 5 run no error but does not produce a smaller code size as expected.

I am using TARGET_IS_BLIZZARD_RB1 and the device is TM4C123GH6PM on my launchpad.

Please help. Thanks

  • Vinh Dam Nguyen said:
    does not produce a smaller code size as expected.

    Might the issue be with your expectation?

    Realize that your specific code - the number & variety of peripherals "in play" - and your ability to devise code which makes repeat "calls" to large sized functions all will impact final code size.  And - there is the impact of the flash code making calls to the ROM - which opposes size savings.

    Be aware (as vendor's Dave W. past detailed) that a "single call" to a flash-based function block will require that, "all the code for that entire block" appends to your program size.  As one critical example - ROM code for I2C for Stellaris LX4F & some (perhaps all?) rebrand - did not encompass, GPIOPinTypeI2CSCL(). Thus - the entire flash version of I2C must be used.

    Note that ROM code will not always be, "latest/greatest" - as new features/functions are introduced - most often flash versions are required to gain this added capability... 

    ROM code has the advantage of being a stable, secure code-base - free from user's "undocumented" additions/changes - which may befall flash-based (user accessible) code.   Both have their place...

  • I should correct or clarify your statement about the entire flash version of a driver being pulled into the image if you use any one function from that driver. The code is all compiled (at least, when we compile it) such that every function is in a separate, linkable section so, if you call a function, the only code that gets included in your image is the code for that function and any dependent data it uses or downstream function calls it makes.

    I suspect in this case that the reason the application is not significantly smaller when using the ROM calls is that the calls being made are not particularly code-intensive and the ROM call overhead is about the same as the amount of code executed in the flash-based version of the function. Many DriverLib APIs set only one or two registers so the amount of code required to do that is pretty comparable with the amount of code used to perform the two level jump table lookup required to get into the ROM version of the function.

    The benefit of ROM comes when you use larger DriverLib functions such as some of those found in SysCtl. You will also likely see a performance benefit, especially when running at high system clock speeds because ROM always runs at the system clock rate without any wait states whereas flash can't run as quickly and you end up with stalls in some cases.

  • Re: correct or clarify - we copied/printed your past, referenced, "flash vs. ROM" post.  (Loved/benefitted)   Might your "update today" apply almost equally to that original post - as well as our interpretation?

    Your amplifying mention of "larger DriverLib functions" - and the mention of the ROM's likely faster execution - are very useful & appreciated...   Thank you...

    Oh - and can you report if "I2CSCL" has joined the ranks w/in ROM?

  • I'm afraid I can't find the post you reference so I can't check to see if I misled anyone there - sorry. If you have the URL or even the post title, I'll take a look at it and see what I told people earlier!

  • You must know - I've been looking.  (searched under ROM & Dave W)   Nothing reveals.

    Please do comment upon GPIOPinTypeI2CSCL()'s presence/absence w/in newest device's ROM...

  • As far as I can tell, looking at rom.h from the TivaWare 1.1 release, GPIOPinTypeI2CSCL should be present in the ROM on all the production TM4C devices.

  • Thanks for this "I2CSCL" report - seems some confusion/uncertainty persists.

    Multiple "official" postings here have stated/suggested that, "Rebrand MCU's are substantially similar (my words - seek to avoid "identical") to earlier LX4F devices - yet none of our multiple LX4F's have evidenced that I2CSCL ROM enhancement."

     

  • Rebranded MCUs are essentially identical to their replacements BUT there are several silicon revisions and the ROM is updated on each revision. The LX4F part you have is likely revision A1 of the Blizzard class of parts (which became TM4C123 parts after the rebranding). The GPIOPinTypeI2CSCL function appeared in the ROM at revision A3. Current TM4C parts are likely A3 or B1 (I can't remember which!) silicon revisions so will have the function present.

    On this specific function, you'll probably notice that it configures the pin in exactly the same way as for UART, SSI, PWM, Timer and USB digital outputs so you could alias ROM_GPIOPinTypeI2CSCL to ROM_GPIOPinTypeUART, ROM_GPIOPinTypePWM, ROM_GPIOPinTypeTimer, ROM_GPIOPinTypeSSI or ROM_GPIOPinTypeUSBDigital and call one of those instead if that would be helpful. All these functions appear in all shipped revisions of the Blizzard device ROM.

  • Bingo - once again - thank you, Dave W!

    Indeed our 1K+ LX4F are A1.

    Months past - clever poster here noted that, "ROM_GPIOPinTypePWM()" indeed duplicated, "I2CSCL" actions.  And you've now supplied even further options - raising the odds that we/others here may "escape" the requirement for that function's (unwanted) flash presence.

    Building upon poster's past "find" - and your neat expansion - this suggests that further such, "fortunate set-up/config overlaps" may exist - far beyond I2C - and thus enable additional, code-size reductions.

    To beat this (dying) horse - one last time - note that the referenced flash function, "GPIOPinTypeI2CSCL()" is not resident w/in the I2C driver - but instead w/in gpio.cThus - its singular use would not cause any portion of the flash version of I2C's driver to be added!  (which our group - long feared/expected...)

    To assist others in exploiting this, "Unwanted Flash code addition" note that the key part of "I2CSCL" is:

    GPIOPadConfigSet(ulPort, ucPins, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD);

    Thus a, "search in files" (via your IDE) for, "ulPort, ucPins, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD" very effectively/quickly automates this, "fortunate overlap discovery!"  (you choose a "hit" which appears in any of your ROM-based drivers - thus avoiding use of the more normal/direct flash driver...) 

  • Dave,

    as always thank you for the detailed explanations. I do have some additional questions based on an example I ran. You mentioned that simple functions may not render great benefit when running from ROM, but would actually add more memory than identical functions running from flash?

    In my experiment I compiled most of the GPIO functions with and without ROM_. The difference for each is 8 bytes in favor of the flash calls!? Is that correct or am I missing something? Could or should I adopt no ROM calls for those simple functions when I am pinching bits in flash?

    Example: GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_4) is 8 bytes smaller than its ROM_ counterpart.

    Thank you!

  • Hi,

    Realizing I made a mistake reading Dave's post,

    I only added

    #define TARGET_IS_BLIZZARD_RB1
    #include "driverlib/rom.h"


    but did not to add "ROM_ " to each function. 

    After the correction, the code below reduced from 5ECh to 3C0h, 36% smaller.

    #include <stdint.h>
    #include <stdbool.h>
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "driverlib/debug.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/adc.h"
    #define TARGET_IS_BLIZZARD_RB1
    #include "driverlib/rom.h"

    #ifdef DEBUG
    void__error__(char *pcFilename, uint32_t ui32Line)
    {
    }
    #endif

    int main(void)
    {
        uint32_t ui32ADC0Value[4];
        volatile uint32_t ui32TempAvg;
        volatile uint32_t ui32TempValueC;
        volatile uint32_t ui32TempValueF;
        ROM_SysCtlClockSet(SYSCTL_SYSDIV_5|SYSCTL_USE_PLL|SYSCTL_OSC_MAIN|SYSCTL_XTAL_16MHZ);
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
        ROM_ADCHardwareOversampleConfigure(ADC0_BASE, 64);
        ROM_ADCSequenceConfigure(ADC0_BASE, 1, ADC_TRIGGER_PROCESSOR, 0);
        ROM_ADCSequenceStepConfigure(ADC0_BASE, 1, 0, ADC_CTL_TS);
        ROM_ADCSequenceStepConfigure(ADC0_BASE, 1, 1, ADC_CTL_TS);
        ROM_ADCSequenceStepConfigure(ADC0_BASE, 1, 2, ADC_CTL_TS);
        ROM_ADCSequenceStepConfigure(ADC0_BASE,1,3,ADC_CTL_TS|ADC_CTL_IE|ADC_CTL_END);
        ROM_ADCSequenceEnable(ADC0_BASE, 1);
        while(1)
        {
            ROM_ADCIntClear(ADC0_BASE, 1);
            ROM_ADCProcessorTrigger(ADC0_BASE, 1);
            while(!ROM_ADCIntStatus(ADC0_BASE, 1, false))
            {
            }
            ROM_ADCSequenceDataGet(ADC0_BASE, 1, ui32ADC0Value);
            ui32TempAvg = (ui32ADC0Value[0] + ui32ADC0Value[1] + ui32ADC0Value[2] + ui32ADC0Value[3] + 2)/4;
            ui32TempValueC = (1475 - ((2475 * ui32TempAvg)) / 4096)/10;
            ui32TempValueF = ((ui32TempValueC * 9) + 160) / 5;
        }
    }

  • Vinh,

      That sounds a bit better. I suspect most of the size saving came from using ROM_SysCtlClockSet because this is a pretty large function. Some of the ADC functions are also 20 or so lines of code so are probably worthwhile calling in ROM too.

  • Armando,

      Looking at the assembly for an application that makes ROM calls, it seems that, with Keil tools at any rate, there is an additional overhead of between 3 and 7 instructions to call the ROM version of a function (in groups of ROM function calls, the first one incurs a longer penalty but the compiler is clever enough to hold on to the ROM table pointer so the following calls incur less of an overhead). If the target DriverLib function is very small and does something as simple as set a single register, this overhead may actually me larger than the function itself but for any function more than 3 or 4 lines long, I'm fairly sure that the ROM implementation will result in a smaller code image.

      Without looking at the actual code you are compiling and the specific DriverLib APIs that you are using, it's tricky to determine what type of improvement in size you will see. One option would be to use the MAP_ versions of all the DriverLib calls. Add rom_map.h to your C files then compile with TARGET_IS_BLIZZARD_RA3 (or whatever silicon revision you are targeting) and save the map file for the build. Next, remove the TARGET_IS_XXX definition, rebuild and see what difference you see. If no TARGET_IS_XXX is specified, the MAP_ versions of each call will call flash-based versions of the functions whereas, if the target is specified, it will call the ROM version. You can do all this without having to make source changes between each test so it's easy to switch back and forward between all-ROM and all-flash versions of your application.  To keep something in flash, just remove the MAP_ prefix from the relevant function call,

  • Excellent! Thank you very much!