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.

TM4C1294KCPDT: Calling a function present in an application from another application

Part Number: TM4C1294KCPDT
Other Parts Discussed in Thread: CC2650

I have a boot loader and two applications in my controller. Can i call a function present in one application from another application when these applications are present in different locations in the same flash?

  • Naman,

    I assume that the function will reside on the bootloader part, correct? Otherwise, the bootloader would be dependent on the "main" application, which would be weird.

    Interesting question, and the answer is yes. But I can only think of theoretical steps on how to do it:

    - You need to know exactly where the function will reside. There certainly is some sort of linker directive to achieve that.

    - On the application that does not contain the function, you would need an extern declaration to organize the parameters and return type, and probably a macro to direct the call into that fixed address.

    While no one provides a more direct reply, two suggestions to look further:

    - The Tivaware functions contain ROM_ calls, which is basically the same story: running code located "somewhere else", in this case, in ROM instead of a different FLASH address. Try to see how the ROM_ calls work in Tivaware and part of the goal will be answered.

    - The examples for CC2650 Launchpad (the chip that has Bluetooth/Radio and a dedicated ARM MCU) are compiled with two separate projects in THE SAME MCU: one for the Bluetooth stack and one for the application itself. They use this cross-calling concept.

    Looking forward to seeing your further development here!

    Regards

    Bruno

  • Bruno,

    Thanks for the reply.

    I have implemented it successfully. I am able to use a function defined in the boot loader application by using the following code, Note that my boot loader app address is 0x00 and another application address is,say, 0x6000:

    // Set the vector table address to the beginning of the application.
    ldr r1, =0xe000ed08
    str r0, [r1]
    // Load the stack pointer from the application's vector table.
    ldr r1, [r0]
    mov sp, r1
    // Load the initial PC from the application's vector table and branch to
    // the application's entry point.
    ldr r0, [r0, #4]
    bx r0

    Here i have to call boot loader application as a whole i.e. change the vector table address, Load the stack pointer and Load the initial PC from the boot loader application's vector table and branch to its entry point.

    This takes a lot of cycles. I have to go to the reset handler of the boot loader application first, reach its main() and then go to the required function from there. The output of the function needs to be saved in the flash memory(as it may be lost when i switch to another application if i use SRAM) to recover it in the calling application.

    While returning from the boot loader app, I again have to use the above code to branch code to go back to the reset handler of my application. Is there a way out where i can just call that particular function in the boot loader app and then branch back to that specific point in the another app from where the branch instruction was executed for function call. Please advise.

    I am also looking at the linker directives in the meanwhile.
  • Is it possible that (sometimes) "simple minded" proves "simply best?"

    Depending upon the size - and number - of these (potentially) "shared" functions - it appears FAR: "Faster, Easier, Better" to place such functions w/in "both" applications - does it not?   (such eliminates ALL of the complexity you note - and (still, rightfully) question.)

    While you reported, "Successful implementation" has that "success" been (really, properly) test/verified across all potential operating conditions?     (even those thought to be "rare/unlikely?"  (until they occur))

    You have traded "code size reduction" for "slowed response" & "added complexity" - and the implementation described may be "vulnerable" under "certain" operating conditions.   (say multiple interrupts arriving (Live) from (each) separated function.)

    Note too - that even though a vendor has (appeared) to employ such a (shared function, code device) - we do NOT know their motivation - nor their constraints - nor (really) how comprehensively (they) have, Test/Verified!      Bug reports, errata, and even API "fixes" - all suggest that (even) a vendor may "stumble."

    "Risk-Reward" must play (some) role here - the "reward" seems (not) too compelling - and the risk(s) (beyond those identified) may await discovery...

  • Aha!!!

    Then THAT'S why I never tried to do it!

    Absolutely right! The function can't be that huge! Save some 100 bytes in a device that has 256K or more, and add all that complexity!

    Still, knowing how to do it truly won't hurt. Further revelations from Naman will be welcome.
  • Hi there,

    Note the "2nd to last" para. I've just edited/added.

    Knowing "HOW" to add complexity - while "inviting" risk - MAY very well hurt!     (VCs make special efforts to search out - identify - and then "cast out" most all such implementations!)

    I'd suggest that this thoughtful & talented poster may fare better by adding REAL functionality to his program/project - NOT by (attempting) to "save" a few KB!

  • Hi cb1,
    I like your recommendation to the poster!
  • Greetings (skilled) vendor friend Charles,

    Thank you - thank you very much!     (my best Elvis - except I "mean it.")

    I've observed that "not always" do poster questions/issues lead them (efficiently - or safely) to the "promised land."     As one w/(perhaps) more Tech Biz experience/success than most - I try to suggest "alternative means/methods" - which I know to have "succeeded."      (presented when I sense posters "nearing" a high cliff)

    Most always I "justify/support" those recommendations - so that the logic (hopefully) shines through - raising poster confidence & acceptance.      (such method aids firm's winning Sales & Growth...)

    May I use this moment to thank both you & Bob for the great effort & assistance you (daily) provide?      You two are - very much - appreciated...    Again, Thanks!

  • Hello,

    I understand your concern and the risks that i am inviting, but it is a requirement for us as of now. While branching from one application to another all the interrupts have also to be disabled. So there is issue with the interrupts as well. Again, I am trying to know about this thing as much as possible to reduce the risks.

    I have tested that the entry point from one application to another is the reset handler only. However we can try to use a branch operation in the reset handler itself to jump to the required address which would reduce the cycles to execute the whole code(between the reset_handler and the place from where the function was called). For that i would have to use linker derivatives and a lot more things.

    One more thing i got to know about this. I set the CPU frequency in the boot loader application. But when i jump to another application, there i have to set the CPU frequency again, otherwise the code just gets hung in the app code. This is not true for other things like enabling the GPIO pins and initializing peripherals. They just work perfectly without initializing them again in application code.

    My new questions are:
    1. In tiva, while implementing the boot loader for upgradation of software, the startup file copies all the boot loader code to SRAM first and then the code executes from SRAM. Why do they do that? Is that for increasing the speed execution??

    2. Let us assume that we assign different dedicated SRAM locations to the different applications and move the data from flash to SRAM for each application. Now when we jump from one application to another, would the SRAM data remain same for an application where we left(as it is dedicated). Like, could we execute directly from SRAM only instead of flash?

    I would again say that it`s a requirement and this may sound stupid. But please try to help me if you can.

    Regards,

    Naman
  • Hi cb1,
    I was thinking how to call a function that is compiled as part of another application even though residing in the same flash. While I was thinking, your recommendation just cleared my mind. If the function is not terribly long, why wouldn't just duplicate it?

    Also thank you to your complements!
  • My friend - I've guided & reported as best as I can - your proposed method is NOT one I can support nor recommend.

    Especially noted is, "It is a requirement!"      Why is that?      Who set, "Such a requirement?"      And - is he/she/the group sufficiently aware, skilled and "invested in the consequences" of such added complexity?

    Note that I have relayed the (highly) skilled guidance/advice of (very) capable, aware, achieving (others) - who are "unafraid to invest large sums" - but (only) when the Risk-Reward equation  tilts strongly towards "Reward."       Yours - unfortunately - does NOT! 

  • Thanks for your guidance cb1_mobile.

    I would better say that we are trying to develop a code like this. The risks are still to be analysed before deciding whether to do it or not. Would you please enlist the risks that can be there due to its implementation so that I can discuss the same with my group.?

    Regards,

    Naman
  • Indeed Charles - as I have noted - "far too often" poster issues/questions are "Accepted & Acted Upon" without the benefit of first asking, "Does the poster's (chosen/advocated) path MAKE SENSE?"

    Posters "wind up here" because (most always) they, "Do NOT Know!"     And yet - their "Suggested or Desired, "Methods of Attack" are (pardon) too often, "uncritically accepted - and acted upon."

    Firm/I are engaged to PREVENT JUST THAT - thus this is much like, "Shooting fish in a barrel." (and fish are big - barrel small - hard for cb1 to miss!)

  • Naman Kumar said:
    Would you please enlist the risks

    Quite simple: the risks are that the idea won't work at all, OR that it will require A LOT of time to be implemented, OR yet it will introduce unknown errors that might not be discovered during development, which will only come to bother later when a very rare combination of factors occur and the product is already on the market.

    The Pro's of that idea:
    - It will save some FLASH memory (but really, HOW MUCH flash do these functions take? Will that saving make a difference on a TM4C129x????)

    The Con's:
    - No matter how well you implement, it will slow down your execution
    - Things will get confusing
    - Things will get VERY DIFFICULT to debug

    Does your "owner" need more arguments? You used the word "requirement", which is too often confused... The REQUIREMENT is a functional and reliable product on the market. Many other choices during development are related to HOW this will be obtained, and more often than not, the routes taken are not mandatory for reaching the destiny.

  • As you (alone) know & control your application(s) - should not (your) "Test/Verification" continue - even expand - so that (most) risks may be identified?

    Yet (more) effort - spent in behalf of those "(still) unidentified" - who impose such "requirement" - seems w/out (any) merit - does it not?
  • Thank you guys for your guidance.

    We were just trying to implement this thing to see if this could be done. And ofcourse the employer didn`t know about the risks involved and asked me to try this out.

    I admit that requirement was a wrong word to be used, but I took it that way.

    Regards,

    Naman
  • Hello again Naman,

    Just another consideration that occurred to me: I assume you are aware that your function can be "created and maintained" just in one location, correct? It is a good idea to gather all your trusted/proven functions into one static library, and use them on your various applications just with the proper #include.

    Of course, both your projects would have its own assembly code in flash - but at least you are using "the same proven function". I avoid as much as possible to actually copy source files into my projects when they are common pieces of code - pretty much the same concept that works with Tivaware libraries.

    Bruno

  • Hi Bruno,

    You are right. But i have another question in my mind after reading your reply.

    We use ROM_FlashErase() etc. type of libraries so that our application can use the libraries which are already present in ROM and so those proven functions in ROM do not get compiled with the application. This we do to save flash ofcourse. How does that thing work? Like i have not compiled ROM libraries with my code,but still it can use the libraries of ROM.

    I was trying to do the same type of thing. Using functions from another location which are not compiled with my application. Could you please explain that?

    Or It may be possible that the ROM libraries have got special status to be used from anywhere.. But we cannot do the same in Flash..

    Regards,

    Naman

  • Naman,
    Yes, you can. Read my first reply to this thread once more - the one with the requirements for your goal. As long as you know where in flash the function is stored, you can surely call it. I don't know the exact settings for that, but I gave two possible paths for you to investigate.
    Program counter is just an address, and as long as it is a valid one, you can detour your code execution to the Maldives as far as I'm concern - and it will go back to the previous address stored in your stack when a return/end-of-function is met. Your post later on with assembly code appears to me as not the proper way of doing it - you were actually diverting the PC flow, not calling something stored in another location.
    It's good fun to investigate - but time consuming and prone to confusion - but again, if you do figure things out, let us know for the sake of curiosity.
    Regards
    Bruno
  • Hello All,

    I have set the address of a function, let's say, func1() as the initial entry point of an application image. But when i try to call that function from another application(using "blx <func1() address>" command), it doesn`t work. With these settings as well, i am only able to enter the application through reset handler and no other way.

    Is there any way to enter an application other than jumping to the reset handler and setting the SP and vector table register?

    Regards,

    Naman
  • Bruno,

    I read the working of ROM_ calls. It has a ROM_APITABLE(array of function pointers) which points to several function pointers and call them as per the parameters passed. If we are able to call this table directly, then it works as a library.

    Now the issue I am facing is I have a function pointer in one application,but i am not able to call it directly from another application. It only enters the application if I pass the reset handler address, set the vector table register and the SP.

    Can you help me with this?

    Regards,

    Naman
  • Sorry, Naman, don't count on me for such discovery! I have no clue and can't try to setup such test anytime soon.
    I'd still like to see if you succeed, please share your results - and again, still believe you should be able to divert the execution... But one question comes to my mind: don't you need to allocate separate RAM for the local variables of functions in one application to work without colliding to functions of the other?
  • Hi Bruno,

    It worked. Your advice of looking into the ROM_ calls was really helpful in this. Just set the flash address of the function you want to call from your application. Once you know the address, use the following format to call the function:

    suppose the function declaration is "int sum(int, int)", and its address is 0x00020005(Make sure the address is odd as it is for Thumb code), then call it with the following statement from anywhere in flash.

    ((int(*)(int,int))(0x00020005))(4,5); // (int(*)(int,int)) is necessary to use, it is for typecasting i think
  • Kudos, Naman!!!
    Thanks for the feedback.
    I am still curious to figure how is the RAM memory allocated on this condition... Assuming that there are variables inside your foreigner function, I wonder if they are temporarily stored on the same region as the main program - that's something I never thought of.
    Regards
    Bruno
  • As per my knowledge, the local variables are getting stored in the same region of RAM and getting destroyed after return. But we need to make sure that no function gets called from the foreigner function which is local to foreigner function`s project as the main program may not know the address of it and it will crash. However you can call any function from anywhere if you pass address of that function.

    You need to be very careful and make sure that the main program must not encounter anything it doesn`t know about.

    Regards,
    Naman
  • Naman Kumar said:
    You need to be very careful and make sure that the main program must not encounter anything it doesn`t know about.

    Believe those "two cautions" prove most wise.

    Can the "so limited" test/verify performed thus far (resulting in, "it works!") be fully/properly accepted/counted upon?      Especially in light of the 2nd restriction (above) and multiple others - not yet arrived/noted.

    Still silent - is the justification for (any) such need!     Risk elements have been introduced - program development (has) been slowed - such is (sure) to drive investors/benefactors, "Krazy!"

    There are UNLIMITED such, "Points of Interest" - how & when are such "diversions" to be admitted - and investigated/acted upon - as they (necessarily)  divert time/effort from the "central task."    (such (may) be the "real thrust" here - and but for the "Risk-Reward" analysis (suggested earlier) has remained masked!)

  • Yet, cb1, people often climb mountains - just because they're there! ;)
  • And Bruno - do not (some) fall from those mountains - (also) just because they were there?

    Steering to "true course" - no matter the "lure of the (for today - "more interesting") - best guarantees "timely & proper" (arrival in port) aka: (product/project delivery.)
  • Certainly they do fall!
    And truth be told, I prefer that such happens neither on my clock, nor with my funds!
  • Bruno Saraiva said:
    truth be told, I prefer that such happens neither on my clock, nor with my funds!

    Your "preferences" - as noted here Bruno - very well qualify you as tech manager and/or tech investor!    

    Assuming that "most all here" are (likely) to be: "understaffed, underfunded, and have under-estimated the demands of the project" does not, "FOCUS upon the project's ESSENCE" assume, "TOP PRIORITY?"

    Should we not note that the past, "Requirement" most likely sprang from an (overly) curious poster - not from some "phantom" boss/investor?     (Some) discipline IS required.    (boring as it is...)

  • Or sometimes the mountain falls around them.

    Robert

    As a recent unfortunate climber on Mount Logan discovered.
  • Say Robert - did I hear "correctly" - you are offering a "free" (yet slightly dinged/used) Launchpad (caused of course - by that mountain's falling) to the first 10 who "remain semi-ambulatory" - and (forever) "cured" of such, "desire to climb?"    

  • Naman Kumar said:
    Would you please enlist the risks that can be there due to its implementation so that I can discuss the same with my group.?

    Let's see (non-exhaustive)

    • Possible loss of compile time checking (depending on the method you use)
    • Possible loss of speed if used in tight loops again depending on the method used
    • Stale versions
      • Caller may need features not supported by the called version (note this can work in reverse as well)
      • Called application may have bugs so either
        • you must enforce an update to the called version or
        • the caller must contain patches for older versions and the called must make allowances for older callers
      • Which means in either case that there must be some sort of mechanism to determine the version and features of the called application
    • Environment mismatch between applications

    I can think of four ways of supporting this off-hand interrupts, function table, incomplete link and interpreter. In the past it was not uncommon for embedded compilers to directly support an incomplete link method. Given the amount of memory available I've not found so far that I even need to call the ROM functions (and reasons not to). There are legitimate reasons for doing this but unless this is an educational exercise you might not want to tackle this on a whim.

    Robert

  • The moving mountain managed to avoid the climber but she was cut off and had to wait out the weather to be rescued. Sorry no Launchpad.

    Robert
  • Robert Adsett said:
    ...moving mountain managed to avoid the climber but she was cut off and had to wait out the weather to be rescued.    Sorry no Launchpad.

    Rescuing those (similarly) "cut off" or otherwise "stricken/confused" well describes my "Staff Recruitment M.O."     (although joint search for the "never to be found' (lost) puppy - lands a close second...)

    Sorry to see you renege wrt the "dinged" Launchpad.     Staff/I were (especially) willing to accept those "rock assaulted" units which gratefully & (spontaneously) ejected their "devil" 0Ω (R9,10 "plague-istors")!  

    (if not mistaken - friend/poster/mountaineer Bruno was "at the scene" - and seen - asking for a "meter!" ... required to calculate dV/dt of "falling" rocks.)

    M.O.  Modus Operandi    (the normal (recognizable) techniques/methods employed (often) by those w/criminal intent - although not limited to (that) field of endeavor...)

  • I don't blame the crack staff, I'm afraid the board in question may now be acclimatized to cryogenic operations only.

    Robert 
  • Robert Adsett said:
    ...don't blame the crack staff, I'm afraid the board in question may now be acclimatized to cryogenic operations only.

    "Don't blame the crack staff?"    Is that not "Survival Lesson #1" - (i.e. "only one here claims total credit (for success) - while disclaiming any involvement in failure - always & only caused by motley crue"...)

    To your "cryo" board - we're told that one poster here - often reporting output signal "Voids" - grasped your (so cold) board for (too long) - and now sports a similar, "2 fingers departed" (right hand) void.