quick boot to other module

Moderators: lily.li, violet, jeremy882, crail.lyu969

gabonator1
Kindergarten
Kindergarten
Posts: 85
Joined: Thu Sep 15, 2011 7:54 pm
Are you a staff member of seeedstudio?: no
Which products/projects are your favorite?: dso quad
Location: Sered, Slovakia

quick boot to other module

Post by gabonator1 » Sat Jan 12, 2013 4:00 pm

It seems that many users install gabonators fw into APP1 slot and jpa's logic analyser and pawn into slots APP3&4. It would be a nice if it was possible to swap between these applications without needing to switch the device off/on.

I suggest following: Every DSO application should have some header for identifying whether something is installed in certain application slot. For example, we could place something like "DSO_APP: Gabonators alternative UI;Alter UI;Gabriel Valky 2013" right after the isr_vectors section. I put there three labes separated by semicolon. First part is full application name, second is short variant less than 10 characters long (for menus where there is only small space for displaying app name) and third is information about author.

The isr_vectors is always the same size and the application which want to swap between app slots could easily scan the memory for installed application (by checking if the 'DSO_APP' string is present at specific memory location) and then display their names.

And my question is - how to set the program counter to execute code of other slot, while resetting the stack to provide maximum possible RAM for the application being executed?

changes in code:

Code: Select all

__attribute__ ((section(".identify")))
__attribute__((__used__))
const static char strIdentification[] = "DSO_APP: Gabonators alternative UI;Alter UI;Gabriel Valky 2013";
changes in linker script:

Code: Select all

    .rom : {
	    . = ALIGN(4);
      _vectors = .;
      *(.isr_vectors)      /* Vector table */
      *(.identify)
............
............
............
    } >ROM

jpa
Elementary-2
Elementary-2
Posts: 215
Joined: Wed Nov 02, 2011 4:06 am
Are you a staff member of seeedstudio?: no
Which products/projects are your favorite?: DSO Quad

Re: quick boot to other module

Post by jpa » Sat Jan 12, 2013 6:14 pm

gabonator1 wrote:It seems that many users install gabonators fw into APP1 slot and jpa's logic analyser and pawn into slots APP3&4. It would be a nice if it was possible to swap between these applications without needing to switch the device off/on.
How do you suggest that the switching would be done? I'm running out of buttons as it is.
gabonator1 wrote: And my question is - how to set the program counter to execute code of other slot, while resetting the stack to provide maximum possible RAM for the application being executed?
This is how the BIOS does it:
https://github.com/neilstockbridge/dsoq ... ain.c#L109

gabonator1
Kindergarten
Kindergarten
Posts: 85
Joined: Thu Sep 15, 2011 7:54 pm
Are you a staff member of seeedstudio?: no
Which products/projects are your favorite?: dso quad
Location: Sered, Slovakia

Re: quick boot to other module

Post by gabonator1 » Sat Jan 12, 2013 7:49 pm

in my app there is application selection screen:
Image

By selecting "Frequency response" I would like to locate which slot contains this application and then execute it. In your PAWN app I saw nice screen with icons for each pawn program. You could scan the memory to find out whether there are any other applications and if any, create an icon for each of them.

by this simple code I was able to find the indentification in ROM:

Code: Select all

void* BIOS::SYS::IdentifyApplication( int nCode )
{
	u32 dwGotoAddr = 0;

	switch ( nCode )
	{
		case BIOS::SYS::EApp1: dwGotoAddr = APP1_BASE; break;
		case BIOS::SYS::EApp2: dwGotoAddr = APP2_BASE; break;
		case BIOS::SYS::EApp3: dwGotoAddr = APP3_BASE; break;
		case BIOS::SYS::EApp4: dwGotoAddr = APP4_BASE; break;
		case BIOS::SYS::ESys: dwGotoAddr = SYS_BASE; break;
		case BIOS::SYS::EDfu: dwGotoAddr = DFU_BASE; break;
	}
	ui32* pData = (ui32*)dwGotoAddr;
	for (int i=0; i<200; i++, pData++)
	{
		if ( *pData == ToDword('D', 'S', 'O', '_') )
			return pData;
	}
	return NULL;
}
Here is the result:
Image

JackTheVendicator
Pre-kindergarten
Pre-kindergarten
Posts: 42
Joined: Tue Oct 11, 2011 6:12 am
Are you a staff member of seeedstudio?: no
Which products/projects are your favorite?: DSO Quad

Re: quick boot to other module

Post by JackTheVendicator » Sat Jan 12, 2013 9:01 pm

gabonator1 wrote: And my question is - how to set the program counter to execute code of other slot, while resetting the stack to provide maximum possible RAM for the application being executed?
My idea is to see from the disassembled binaries if the APPs reset the stack pointer on start. If they do, a simple jump could be fine (provided every APP rewrites the interrupt vector table accordingly on start too). If they don't, I think it'll be necessary to replicate the stack state left from the bootloader...

jpa
Elementary-2
Elementary-2
Posts: 215
Joined: Wed Nov 02, 2011 4:06 am
Are you a staff member of seeedstudio?: no
Which products/projects are your favorite?: DSO Quad

Re: quick boot to other module

Post by jpa » Sat Jan 12, 2013 10:17 pm

Remember to also reset all the peripherals (there are reset bits for them).

I much prefer just restarting, it's less hassle. Better spend the time on more useful features, but that's just my opinion. I can add the metadata to my applications if wanted, but I won't spend time creating any menu for switching applications.

gabonator1
Kindergarten
Kindergarten
Posts: 85
Joined: Thu Sep 15, 2011 7:54 pm
Are you a staff member of seeedstudio?: no
Which products/projects are your favorite?: dso quad
Location: Sered, Slovakia

Re: quick boot to other module

Post by gabonator1 » Sat Jan 12, 2013 10:36 pm

jpa, please let me know when your builds with metadata will be available.

in the original DFU, the program flow is controlled with function __set_MSP, I dont have such function in my stm32 library, but I have found something very similar __MSR_MSP. But after calling __MSR_MSP(0x0800C000+4); to reset to the first app, the device freezes. It seems that it will be more complicated, but it would be a nice feature demonstrating the synergy of various applications.

If anyone more experienced will be reading this post, please let us know how to safely restart the device into desired application.

Code: Select all

__MRS_MSP:

  MRS r0, MSP
  BX r14

Code: Select all

/**
 * @brief  Set the Main Stack Pointer
 *
 * @param  topOfMainStack  Main Stack Pointer
 *
 * Assign the value mainStackPointer to the MSP 
 * (main stack pointer) Cortex processor register
 */
__ASM void __set_MSP(uint32_t mainStackPointer)
{
  msr msp, r0
  bx lr
}

JackTheVendicator
Pre-kindergarten
Pre-kindergarten
Posts: 42
Joined: Tue Oct 11, 2011 6:12 am
Are you a staff member of seeedstudio?: no
Which products/projects are your favorite?: DSO Quad

Re: quick boot to other module

Post by JackTheVendicator » Sun Jan 13, 2013 1:26 am

gabonator1 wrote:in the original DFU, the program flow is controlled with function __set_MSP, I dont have such function in my stm32 library, but I have found something very similar __MSR_MSP. But after calling __MSR_MSP(0x0800C000+4); to reset to the first app, the device freezes. It seems that it will be more complicated, but it would be a nice feature demonstrating the synergy of various applications.
That code sets the stack pointer, and setting the stack pointer to a location in flash probably makes the CPU "throw" an exception (fault interrupt) and go to a particular point of the code like the hard fault handler (see https://github.com/Seeed-Studio/DSOQuad ... nterrupt.c - it's an endless loop). The only way to know where the CPU has gone to is the JTAG.

I'd try a blind jump to the branch, but it takes an offset and you don't know where exactly that code will be. Can you place a function in a fixed position in flash with GCC?

Or program start on a software interrupt vector and generating a software interrupt.

-- IMPORTANT EDIT --
Looks like there's an absolute jump instruction in ARM :D just try this:

Code: Select all

mov r0, PUTJUMPADDRESSHERE
bx r0
I have a couple of other ideas I'd like to discuss. If you wish, you can send me a gtalk address in a PM.

tormod
Elementary-2
Elementary-2
Posts: 271
Joined: Mon Oct 18, 2010 1:18 am

Re: quick boot to other module

Post by tormod » Thu Jan 17, 2013 4:17 am

Application signature

I once brought up this topic for the Nano in http://www.seeedstudio.com/forum/viewto ... =22&t=3605 (there is not much activity there though). I suggest for your app signature/header that you use for instance:

1. A magic marker which is more unique than "DSO_APP", like some half-random four byte combination.
2. The version of this header format (so that it can be changed later and the application switcher code can parse different formats.)
3. The address of the next free page after this application. At some point you might want to break free from this "slot" restriction and pack applications more tightly. Then the scanning can be more efficient and avoid false positives if it can jump ahead to next possible location.
4. Zero-terminated string for application name. Come up with a reasonable limit (16?) for how many characters must be displayed in a application switcher, with longer titles shown at best effort (imagine horizontally scrolling text etc).

Instead of (4) you could have:
4. Pointer to short name string
5. Pointer to full name string

[To save space, (2) could be the fourth byte in (1), or in (3) since the page start will always have LSB zero. (1) and (3) should be word-aligned to optimize the scan, I believe. But it is most important to fix where (2) should be and make it independent from the rest (like 3) which you might want to change one day, rather than optimizing 3 bytes.]

Executing a new application

For executing the new application, doing it fresh from a software-triggered reset is the way to go. Then you will have no hassle with peripheral states etc. Put a magic marker and the start address in a fixed position in RAM before the reset and check for this in the early bootloader code. I implemented this in my extended bootloader: https://gitorious.org/dsonano/dso-bootl ... r.c#line42

To demonstrate this I also made a very simple application switcher that scans through the flash: https://gitorious.org/dsonano/dso-bootl ... .c#line107

App selection app

The application switcher can be a free-standing application like any other. So a lazy application writer just has to include the signature header and a menu entry which sets the magic and resets the unit into the application switcher. For this you will have to agree on what address should be set with the magic - a fixed address where the application switcher should always reside, or more indirectly, a flag that tells the bootloader to start whatever is the default application switcher.

Or you make it so the bootloader always runs the application switcher, which in turn should allow the user to define the default "real" application. With the current bootloader that would mean putting the app switcher in "slot 1", but you certainly don't want to waste a whole slot on it, so you should make a hook for it in the bootloader.

Tormod
Last edited by tormod on Tue Jan 22, 2013 4:45 am, edited 1 time in total.

gabonator1
Kindergarten
Kindergarten
Posts: 85
Joined: Thu Sep 15, 2011 7:54 pm
Are you a staff member of seeedstudio?: no
Which products/projects are your favorite?: dso quad
Location: Sered, Slovakia

Re: quick boot to other module

Post by gabonator1 » Mon Jan 21, 2013 7:25 am

Finally a soft reboot is working! Now it is possible to run applications in slots 2,3,4 directly from main menu, unfortunatelly there is no way how to go back to my fw... Big thanks goes to JackTheVendicator for these three lines of code:

Code: Select all

        u32 *vector_table = (u32 *) 0x08024000;
        __MSR_MSP(vector_table[0]);
        ((void (*)(void)) vector_table[1])();
Regarding the application signature, here is a excerpt from email I was sending to Jack:
Tormod suggested more complex application signature/metadata for identifying what is installed in the application slots, but I am still not satisfied even with his solution. What would you say if the metadata has the form of XML?

for example:
<dsoapp version="1.0">
<shortName>My app</shortName>
<fullName>My interesting application</shortName>
<author>Someone</author>
<built>20.1.2013</built>
<version>2.1</version>
<required id="bios">1.50</required>
<required id="dfu">3.10</required>
<icon format="bmp" encoding="base64" width="32" height="32">klsfgjsalkfjsd;lkjskf...</icon>
<memory id="rom-top">0x01C00230</required>
</dsoapp>

or in minimal form to save ROM:
<dsoapp><shortName>My app</shortName></dsoapp>

I think it is good idea to choose something robust that should be suitable also for further versions of DSO oscilloscopes. And I prefer something that I can quicky find when looking through binary builts or memory dumps.

I was also thinking on different BIOS model. Something more similar to linux/windows operating systems. Instead of 20 exported functions on fixed locations in ROM, I would export only single function "GetProcAddress" that would be used for importing the functions into client applications:

typedef (void* TDrawText)(int x, int y, const char* str);
TDrawText DrawText = NULL;
DrawText = GetProcAddress("BIOS::DrawText");
DrawText(20, 20, "Hello!");

The only disadvantage is probably the execution time - every call to DrawText the CPU needs to de-reference the pointer DrawText.

JackTheVendicator
Pre-kindergarten
Pre-kindergarten
Posts: 42
Joined: Tue Oct 11, 2011 6:12 am
Are you a staff member of seeedstudio?: no
Which products/projects are your favorite?: DSO Quad

Re: quick boot to other module

Post by JackTheVendicator » Mon Jan 21, 2013 7:17 pm

As I said in the email, that code is not mine, it's tormod's :)
Anyway, I'm still considering if it's a good idea to add some code to reset peripherals before jumping to another APP.

Post Reply