📄 romload.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 + -