No announcement yet.

Launching program from the SD

  • Filter
  • Time
  • Show
Clear All
new posts

  • Launching program from the SD

    In order to overtake the program size limit for a single program in FLASH, I am willing to store some programs on the SD card.
    The "main program" (stored in the flashbank 0) would just be launcher.
    This program will not have any UI. It will simply make a few actions (check for files on the SD card, ...), and launch a 1st "app" from the SD called Menu (.4XE / .4FN).

    Menu will offer the user several buttons to choose which app he wants to use.
    Menu will then launch the corresponding app selected by the user, from the SD (4XE or 4FN).
    When the user is done with this app, a return button will exit and go back to Menu.

    Click image for larger version

Name:	apps.PNG
Views:	113
Size:	7.8 KB
ID:	71275

    Since the apps are independant for each other, it does not really matter if the context is stored when launching an app.
    It is ok for me to re-initialize my Menu app when I return from another app. The most important data will be store in a txt file on the SD, so it's just a matter of reading it.
    So, at this point, both file_Run() or file_Exec() seem to do the job.

    Here is where it gets tricky : all app need to have access to the serial/UART.
    How should I process with that ? Can I initialise the UART buffers (RX and TX) in myLauncher, and then access then from any of my apps with some pointers ?

    At the moment, re-init the UART everytime I open an app. Since I need to be able to send/receive big frame, I am using some large buffers as global variables (> 1000 byte).
    I tried a few things with file_Exec(), file_Run(), mem_Free() and returns, but after several opening/closing app, the screen crashed because of stack overflow.
    I believe that the memory is not completely freed when I return from an app. Therefore, everytime I re-open an app, some more RAM get allocated, until a stack overflow occurs.

    In each of my app code, I have something like this :
    // Global var
    var TXRXbufffer[1000] ;
    var RXbuff[1000];
    func main()
       com_SetBaud(COM2, 39700); // Parameter for the function is Baud/10
       com2_TXbuffer(TXRXbufffer,TX_COM_BUFFER_SIZE_ENCODED_FRAME, PA8);
          // Some actions
          // Different for each app
          // Check if there is some data
    func get_serial_messages()
       var singleData ;
       singleData := serin2();
       if(singleData >= 0)
           // Some processing
    I think I understand the concept of parent and child program, but I haven't been able to find the application note (there are no more filters on the website ?!). Therefore, there are probably some details that I am missing.

    myLauncher is prety basic, and uses Designer
    The other program are coded in Visi.
    I am using the pro version.
    Attached Files

  • #2
    After some tests, I solved a first problem. In my APP program, I had the return instruction placed in a subroutine.
    I beleive that the compiler is getting confused wether the return instruction is to return from my subroutine, or exit the program.
    I updated my program to only exit an APP from its main().
    Basically, something like this (discare syntax, it is only meant to describe):

    // App
    var needExit := 0 ;
    func [B]main[/B]()
       [ Some Inits ]
       // Replaced the repeat/forever
          [ Some actions ]
          manageTouchButtons() ;
       mem_Free(hndl) ;
       return ; // Optionnal
    func [B]manageTouchButtons[/B]()
          needExit := 1 ;

    At the moment, I am using the following mechanism. So far, it does not seem to cause any error. I haven't looked at the UART though.
    Click image for larger version

Name:	app.PNG
Views:	99
Size:	6.1 KB
ID:	71287

    This means that the context of MENU is still in RAM when the APP is executed, which I don't really need. Replacing file_Exec() by file_Run() nohing seem to happen when returning from the APP.
    The file_Exec() is not in the main() of MENU. Is that an issue ?
    Attached Files


    • #3

      It might be best to use flash_Run and have the seperate programs in different flashbanks. flash_Run wil release all memory, like a reset so the comms settings will have to be re-initialized. When you want to return from a running program you can software reset that will restart the display from flashbank 0

      Looking at your diagram above, you could then have the Menu in flashbank 0 so that it will always start from the menu.

      flash_Run is explained on page 222 of the manual

      Best regards



      • #4
        Hi Paul,

        Thanks for your message.

        Using the other flashbank could be a good solution. However, I will probably have more than 6 apps.
        In that case, everytime I need to open an app, I would have to :
        - Erase the previous content of the Flashbank using flash_EraseBank()
        - C
        opy the 4FN/4XR program from the SD into the flashbank using flash_LoadFile()
        - Run the program from the flashbank using flash_Run()

        From datasheet, I can see that the FLASH is rated for 10000 write cycles.
        For this particular project, the end user will not change app very often (on average, less than once a day), so this could work.
        But this solution will not work for all cases : changing from App#1 to App#2 12 times a day will reach the flash endurance in 2 years.

        Is there a quick way to compare the content of a flashbank with a file on the SD ?
        Doing that would prevent re-copying a file in a flashbank in case it is already loaded.
        The only options I see so far are :
        - Compare byte per byte, using flash_GetByte() and file_GetC()
        - Keep track of what has been copied in each flashbank using a dedicated file on the SD card


        • #5
          Hi Vincent

          If you had this code in each program underneath the #platform

          byte porgNmae "PROGRAM1"

          Numbered from 1 to 6 then this name will be close to the beginning of the file, it started at byte position 23 when I looked at it with a hex editor. You would then only need to check for these 8 bytes to find out what is already in a flashbank using flash_GetByte(bank, ptr);It wouldn't be necessary to know the contents of the SD card as you can make the decision to load just based on what program is in flash.

          Best regards



          • #6
            Originally posted by pauleilio View Post
            If you had this code in each program underneath the #platform

            byte porgNmae "PROGRAM1"

            Numbered from 1 to 6 then this name will be close to the beginning of the file, it started at byte position 23 when I looked at it with a hex editor.[/FONT]
            This looks like a good option to me. Thanks.
            Will the position always be starting at 23, or could that be compiler dependant ?
            Let's say I compile the same program using an older version of the IDE, or a futur release. Will the position of the constant be the same ?


            • #7

              I'm not certain that it will always be at that position. It might be a good idea to start the serch at 0 until PROGRAM is found and the just translate the number at the end.

              var check[7] := ['P','R', 'O', 'G', 'R', 'A', 'M'];
              var n, o, chk, prgNum;
              prgNum := 0;
              for(n := 0; n < 100; n++)
                chk := 0;
                for(o := 0; o < 7; o++)
                  if(flash_GetByte(1, n + o) == check[o]) chk ++;
                if(chk == 7)
                  prgNum := flash_GetByte(1, n + 7) - 48;
                  print("\r\nProgram ", prgNum, " Found at position ", n);


              • #8

                It indeed sounds like a good idea.
                My backup plan was to try how long it would take to compare the entire program with the source file on the SD. If the execution time was reasonable, I would have gone that way.

                You suggestion is better :
                - In case the constant is always at the begining, I get a quick comparaisson
                - In case, because of a new compiler (or whatever reason), it is located further in the compiled code : worst case scenario is parsing the entire file, which is what I was going for anyway.