⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 romload.c

📁 dual-boot loader用来引导更新程序的例子
💻 C
字号:
/*******************************************************************************

File Name    : romload.c

Description  : ROM boot loader (phase 1)

(C)Copyright ST Microelectronics 1999

Reference to the origin of this file within the build system repository
\5500ref\flash\loader\romload.c

References to related design specifications, tools, required header files etc.

Date        Modification                                          Initials
----        ------------                                          --------
14-Jan-99   Modified for STi5500 DVB reference software :
            -> added InitPllFromRom and InitSdramInterfaceFromRom
            functions                                                 PL
1996        Creation

*******************************************************************************/
 
/* Includes ----------------------------------------------------------------- */

#include <string.h>

#include "bootdata.h"
#include "st5500.h"
#include "mpgiface.h"


/* Global Variables --------------------------------------------------------- */


/* Private Types ------------------------------------------------------------ */


/* Private Constants -------------------------------------------------------- */

#define STACK_BASE  (offsetof(bootdata_t, __stackptr) / sizeof(int))
#define STACK_SIZE  (offsetof(bootdata_t, __stacksize) / sizeof(int))
#define NUM_POKES   (offsetof(bootdata_t, __numpokes) / sizeof(int))
#define POKE_TABLE  (offsetof(bootdata_t, __poketable) / sizeof(int))
#define STATIC_LINK (offsetof(bootdata_t, __staticlink) / sizeof(int))
#define true 1
#define false 0

/* Stack checking *must* be disabled in the bootstrap code because
 * global data required by the stack checking code is not set up */
#pragma ST_off(stack_checking)


/* Private Variables -------------------------------------------------------- */


/* Private Macros ----------------------------------------------------------- */


/* Private Function prototypes ---------------------------------------------- */


/* Global Function prototypes ----------------------------------------------- */

/* declare ROM loader phase 2 */
extern void romload2(void);
#pragma ST_translate(romload2, "romload2%c")
#pragma ST_nolink(romload2)

void romload(void);
#pragma ST_nolink (romload)
#pragma ST_translate(romload, "romload%c")

/* Functions ---------------------------------------------------------------- */


/*------------------------------------------------------------------------------
 Name    : romload
 Purpose : ROM Loader phase1
 In      : -
 Out     : -
 Note    : This function is responsible for the following:
              1. Perform the pokes encoded in the boot data block.
              2. Set wptr to the user workspace.
            It does this using 3 words of workspace initially before moving
            to the user stack. The initial workspace pointer is passed to the
            loader and the first task is to use gajw to move into this stack.
            On the C4 a value of 1 for the passed workspace pointer signifies
            that the wptr value set up by the hardware is to be used and so
            no initial gajw is done in this case. The workspace map is as
            follows:

            offset       description
            ------       -----------
              0          Address of bootdata block/section table address pair
              1          Poke counter
              2          Current poke data pair address
------------------------------------------------------------------------------*/
void romload(void)
{
#ifdef DEVELOP
#if __CORE__ == 1

  /************
   * FOR TESTING ONLY - MOVES THE VALUE IN AREG TO C TO CORRECTLY SIMULATE
   * THE ENTRY TO THE ROM CODE. THE TEST HARNESS IS WRITTEN IS SUCH A WAY
   * THAT THE VALUE EXPECTED IN CREG IS ACTUALLY IN AREG.
   ***********/
  __asm { rot; }

#else

  /************
   * FOR TESTING ONLY - LOSES THE VALUE FROM AREG STORED BY GCALL FROM
   * HARNESS
   ***********/
  __asm { pop; }


#endif
#endif

  /* C4/C2 : Entry to here is via a gcall op, so the return address is now in
   * areg. This address also just happens to contain the base address of three
   * words which contain the base addresses of the boot data block, base
   * address of the section table and initial workspace pointer respectively. */

  /* C1 : Entry to here is via a jab op, so the return address is now in
   * creg. This address also just happens to contain the base address of three
   * words which contain the base addresses of the boot data block, base
   * address of the section table and initial workspace pointer respectively.
   * So we move it back to areg. */

#if __CORE__ == 1
  __asm
  {
    arot;                /* Move the address of the bootdata block/section
                            table/wptr address block into Areg */
  }
#endif

  /* Move into initial stack if required */
  __asm
  {
    dup;                 /* make a copy of the bootdata block/section
                            table/wptr address block address */
    ldnl 2;              /* load the initial workspace pointer value */

#if __CORE__ != 1
    dup;                 /* make a copy of the initial value */
    eqc 1;               /* is it equal to 1? */
    eqc 0;               /* flip the result for cj */
    cj  nogajw;          /* Jump if we dont need to gajw */
#endif

    gajw;                /* Use it as new wptr */
#if __CORE__ != 1
    ldc 0;               /* Match the zero left by the cj */
#endif
  }

  /* store address of bootdata block/section table/wptr address block
     which is in C reg at this point */
  __asm
  {
  nogajw:

#if __CORE__ == 1
    rot;                 /* throw away the old wptr value */
#else
    pop;                 /* throw away the 0 from the jump or dummy zero loaded
                            to match it */
    pop;                 /* throw away old wptr from gajw or original wptr
                            if it was 1 */
#endif

    dup;                 /* make a copy of the bootdata block/section table
                            address pair for use later */
    stl 0;               /* save address of bootdata block/section table
                            address pair */
  }

  /* Poke loop */
#if 1
  __asm
  {
    ldnl 0;              /* get address of bootdata block (via address
                            we duped above) */
    dup;                 /* make a copy of bootdata block address for use
                            later */
    ldnl NUM_POKES;      /* get number of pokes from bootdata block */
    stl 1;               /* store it for use as a counter */
    ldnlp POKE_TABLE;    /* get address of first poke pair from bootdata
                            block */
    stl 2;               /* store it for use later */
    ldl 1;               /* Get numpokes */
    cj loopend;          /* Nothing to poke so jump over loop */
  loop:;
    ldl 2;               /* get poke pair address */
    ldnl 1;              /* get value to poke */
    ldl 2;               /* get poke pair address */
    ldnl 0;              /* get address to poke into */
#if __CORE__ == 1
    swinc;               /* do the poke */
#else
    devsw;               /* do the poke */
#endif
    ldl 1;               /* get poke counter */
    adc -1;              /* decrement */
    dup;                 /* make a copy to test against */
    stl 1;               /* store updated poke counter */
    cj loopend;          /* test counter - if its zero then jump out of loop */
    ldl 2;               /* get poke pair address */
    adc sizeof(int) * 2; /* Update to point at next poke pair */
    stl 2;               /* store updated poke pair address */
    j loop;
  loopend:;
  }
#endif


{
	int i;
  	
	*(volatile unsigned long *)0x0000007b = 0;
	
  /*
    * RS - 20032003 - Added support for both CPU Frequency configuration.
    */
#if (GDEF_CPU_FREQ == 60)
     *(volatile unsigned long *)0x000001d4 = 0x10a0;
#else	
	*(volatile unsigned long *)0x000001d4 = 0x20a0;
#endif
   /*
     *  END
     */
	
	*(volatile unsigned long *)0x000001d0 = 0x10a0;
	
	*(volatile unsigned long *)0x00000000 = 0x7f00;

	MPEG_WRITE_VIDEO8(0x38, 0x00);
	for (i=0 ; i<300 ; i++);
	MPEG_WRITE_VIDEO8(0x38, 0x01);
	for (i=0 ; i<300 ; i++);
	MPEG_WRITE_VIDEO8(0x38, 0x21);
	for (i=0 ; i<300 ; i++);
	MPEG_WRITE_VIDEO8(0x38, 0x23);
	for (i=0 ; i<300 ; i++);
	MPEG_WRITE_VIDEO8(0x38, 0xa3);
	
	*(volatile unsigned long *)0x00000000 = 0x7f3e;
  
	for (i=0 ; i<32000 ; i++);

	*(volatile unsigned long *)0xc0000000 = 0x12345678;
	if(*(volatile unsigned long *)0xc0000000 != 0x12345678) {
		MPEG_WRITE_VIDEO8(0x38, 0xa7);
		*(volatile unsigned long *)0xc0000000 = 0x12345678;
		if(*(volatile unsigned long *)0xc0000000 != 0x12345678) {
			MPEG_WRITE_VIDEO8(0x38, 0xab);
			*(volatile unsigned long *)0xc0000000 = 0x12345678;
			if(*(volatile unsigned long *)0xc0000000 != 0x12345678) {
				MPEG_WRITE_VIDEO8(0x38, 0xaf);
			}
		}
	}
	*(volatile unsigned long *)0x0000007b = 1;
}

  /* Move to user workspace */
  __asm
  {
    /* load address of bootdata block */
    ldl 0;               /* load address of bootdata block/section table
                            address pair */
    dup;                 /* Make a copy for later */
    ldnl 0;              /* load address of bootdata block */
    dup;                 /* take a copy for getting stack size later */
    ldnl STACK_BASE;     /* get address of user stack base */
    rev;                 /* Areg = Address of Boot_Data_Block,
                            Breg = address of user stack base */
    ldnl STACK_SIZE;     /* get size of stack area */
    add;                 /* stack_base + stack_size, address one
                            word beyond the top of stack */
    adc -sizeof(int);    /* address of top word in stack */
    gajw;                /* use it to set user stack base */
#if __CORE__ == 1
    rot;                 /* throw away old (junk) wsp */
#else
    pop;                 /* throw away old (junk) wsp */
#endif

    ajw -2;              /* make room for two parameters which need saving
                            into workspace before the call to romload2 */

#if __CORE__ != 1        /* on C2, parameters passed to romload2 on stack */
    dup;                 /* copy address of bootdata block/section table
                            address / wptr tuple */
    ldnl 0 ;             /* load the bootdata table base */
    ldnl STATIC_LINK ;   /* load the static link */
    stl 1;               /* save the static, this will appear as the first parameter
                            to romload2 */
    stl 2;               /* Save pointer to bootdata block/section table
                            address pair, this will appear as the second parameter
                            to romload2 */
#else                    /* on C1, parameters passed to romload2 in A & B regs */
    dup;                 /* copy address of bootdata block/section table
                            address / wptr tuple */
    ldnl 0 ;             /* load the bootdata table base */
    ldnl STATIC_LINK ;   /* load the static link */
#endif
    ldc 0x80000000;      /* load mint */
    stl 0;               /* Store a fake return address. This stops the
                            debugger from trying to backtrace further */
  }

  /* Now call next phase of bootstrap.
     At this point we have built a fake function call in the workspace
     with the the address of the bootdata block/section table pair at
     offset 1 and a fake mint return address at offset 0. Note that it
     is because of the fake return address that we do this call by hand.
     A real call would overwrite the fake return address */

  __asm
  {
    ld romload2;
#if __CORE__ == 1
    jab;                 /* jump to romload2 */
#else
    gcall;               /* jump to romload2 */
#endif
  }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -