📄 go.c
字号:
"a2 is set to the address of the environment table.\n"
"a3 is set to the memory size.\n"
"ra holds the return address to YAMON.\n"
"\n"
"The application may return to YAMON by jumping to the address\n"
"specified in ra or by calling the exit(rc) function supplied by YAMON.",
NULL,
0,
FALSE
};
/************************************************************************
* Implementation : Public functions
************************************************************************/
/************************************************************************
* shell_shift_to_user
************************************************************************/
/************************************************************************
*
* shell_shift_to_user
* Description :
* -------------
*
* Shift/return to user context
*
* Return values :
* ---------------
*
* TRUE -> application ended.
*
************************************************************************/
bool
shell_shift_to_user(
bool from_gdb, /* TRUE -> invoked from GDB */
t_gdb_regs *user_regs ) /* regs to be used (possibly NULL) */
{
bool return2user;
char msg[80];
char *s;
UINT32 i;
if( user_regs )
memcpy( &user_context, user_regs, sizeof(t_gdb_regs ) );
/* Store settings of exception handlers so that it may later
* be restored.
*/
EXCEP_toggle_handlers( TRUE );
/* Register BREAK exc handler */
EXCEP_register_esr( C0_CAUSE_CODE_BP,
FALSE,
shell_exception,
NULL,
NULL );
/* Stop DMA */
shell_arch_dma( FALSE );
/* Force exception in order to shift to user context */
shell_force_break();
return2user = FALSE; /* Default */
/* Deregister BREAK exc handler */
EXCEP_register_esr( C0_CAUSE_CODE_BP,
FALSE,
NULL,
NULL,
NULL );
/* Why did we return from the exception ? */
switch( (UINT32)SYS_CPUREG(&shell_context, SYS_CPUREG_V1) )
{
case SHELL_FUNC_COUNT :
/* Returned due to user exception */
if( !from_gdb )
{
/* Print context */
EXCEP_print_context(
&user_context,
NULL,
TRUE,
FALSE );
printf( "\n" );
}
else
{
memcpy( user_regs, &user_context, sizeof(t_gdb_regs ) );
}
break;
case SHELL_FUNC_EXIT_CODE :
/* Normal return / exit() function */
sprintf( msg, "User application returned with code = %08x\n",
(UINT32)SYS_CPUREG(&shell_context, SYS_CPUREG_V0) );
SHELL_PUTS( msg );
if( from_gdb )
memcpy( user_regs, &user_context, sizeof(t_gdb_regs ) );
break;
case SHELL_FUNC_PRINT_COUNT_CODE :
/* a0 = Output port (ignored).
* a1 = String pointer.
* a2 = Number of characters.
*/
s = (char *)((UINT32)SYS_CPUREG(&user_context, SYS_CPUREG_A1));
for( i=0; i< SYS_CPUREG(&user_context, SYS_CPUREG_A2); i++ )
{
sys_putchar( DEFAULT_PORT, *s );
s++;
}
return2user = TRUE;
break;
case SHELL_FUNC_PRINT_CODE :
/* a0 = Output port (ignored).
* a1 = Null terminated string.
*/
sys_puts( DEFAULT_PORT,
(char *)((UINT32)SYS_CPUREG(&user_context, SYS_CPUREG_A1)) );
return2user = TRUE;
break;
case SHELL_FUNC_GETCHAR_CODE :
/* a0 = Input port (ignored).
* a1 = Pointer to char.
*/
SYS_CPUREG(&user_context, SYS_CPUREG_V0) =
sys_getchar( DEFAULT_PORT,
(char *)((UINT32)SYS_CPUREG(&user_context, SYS_CPUREG_A1)) );
return2user = TRUE;
break;
case SHELL_FUNC_SYSCON_READ_CODE :
/* a0 = SYSCON id.
* a1 = Pointer to param.
* a2 = size of param.
*/
SYS_CPUREG(&user_context, SYS_CPUREG_V0) =
SYSCON_read(
(t_syscon_ids) ((UINT32)SYS_CPUREG(&user_context, SYS_CPUREG_A0)),
(void *) ((UINT32)SYS_CPUREG(&user_context, SYS_CPUREG_A1)),
((UINT32)SYS_CPUREG(&user_context, SYS_CPUREG_A2)) );
return2user = TRUE;
break;
case SHELL_FUNC_FLUSH_CODE :
/* a0 =
* YAMON_FLUSH_ICACHE : Flush ICACHE
* YAMON_FLUSH_DCACHE : Flush DCACHE
*/
if( SYS_CPUREG(&user_context, SYS_CPUREG_A0) == YAMON_FLUSH_ICACHE )
sys_icache_invalidate_all();
else
sys_dcache_flush_all();
return2user = TRUE;
break;
case SHELL_FUNC_REGISTER_CPU_ISR_CODE :
/* a0 = CPU interrupt number
* a1 = Pointer to ISR
* a2 = Pointer to data
* a3 = Pointer to ref
*/
EXCEP_register_cpu_isr(
(UINT32)SYS_CPUREG(&user_context, SYS_CPUREG_A0),
(t_EXCEP_isr)((UINT32)SYS_CPUREG(&user_context, SYS_CPUREG_A1)),
(void *)((UINT32)SYS_CPUREG(&user_context, SYS_CPUREG_A2)),
(t_EXCEP_ref *)((UINT32)SYS_CPUREG(&user_context, SYS_CPUREG_A3)) );
/* v0 is set to the contents of the STATUS register */
SYS_CPUREG(&user_context, SYS_CPUREG_V0) = CP0_status_read();
return2user = TRUE;
break;
case SHELL_FUNC_DEREGISTER_CPU_ISR_CODE :
/* a0 = ref */
EXCEP_deregister_cpu_isr(
(t_EXCEP_ref)((UINT32)SYS_CPUREG(&user_context, SYS_CPUREG_A0)) );
/* v0 is set to the contents of the STATUS register */
SYS_CPUREG(&user_context, SYS_CPUREG_V0) = CP0_status_read();
return2user = TRUE;
break;
case SHELL_FUNC_REGISTER_IC_ISR_CODE :
/* a0 = IC line number
* a1 = Pointer to ISR
* a2 = Pointer to data
* a3 = Pointer to ref
*/
EXCEP_register_ic_isr(
(UINT32)SYS_CPUREG(&user_context, SYS_CPUREG_A0),
(t_EXCEP_isr)((UINT32)SYS_CPUREG(&user_context, SYS_CPUREG_A1)),
(void *)((UINT32)SYS_CPUREG(&user_context, SYS_CPUREG_A2)),
(t_EXCEP_ref *)((UINT32)SYS_CPUREG(&user_context, SYS_CPUREG_A3)) );
return2user = TRUE;
break;
case SHELL_FUNC_DEREGISTER_IC_ISR_CODE :
/* a0 = ref */
EXCEP_deregister_ic_isr(
(t_EXCEP_ref)((UINT32)SYS_CPUREG(&user_context, SYS_CPUREG_A0)) );
return2user = TRUE;
break;
case SHELL_FUNC_REGISTER_ESR_CODE :
/* a0 = Exception code
* a1 = Pointer to ESR
* a2 = Pointer to ref
* a3 = Pointer to retfunc
*/
EXCEP_register_esr(
(UINT32)SYS_CPUREG(&user_context, SYS_CPUREG_A0),
TRUE,
(t_EXCEP_esr)((UINT32)SYS_CPUREG(&user_context, SYS_CPUREG_A1)),
(t_EXCEP_ref *)((UINT32)SYS_CPUREG(&user_context, SYS_CPUREG_A2)),
(t_EXCEP_retfunc *)((UINT32)SYS_CPUREG(&user_context, SYS_CPUREG_A3)) );
return2user = TRUE;
break;
case SHELL_FUNC_DEREGISTER_ESR_CODE :
/* a0 = ref */
EXCEP_deregister_esr(
(t_EXCEP_ref)((UINT32)SYS_CPUREG(&user_context, SYS_CPUREG_A0)) );
return2user = TRUE;
break;
default : /* Should not happen */
break;
}
if( return2user )
{
/* return to user application.
* We need to skip the instruction that caused
* the exception.
*/
update_epc( &user_context );
/* Register BREAK exc handler */
EXCEP_register_esr( C0_CAUSE_CODE_BP,
FALSE,
return_exception,
NULL,
NULL );
shell_force_break();
}
else
{
/* Restore setting as it was when 'go' was started */
EXCEP_toggle_handlers( FALSE );
/* Restart DMA */
shell_arch_dma( TRUE );
return ( SYS_CPUREG(&shell_context, SYS_CPUREG_V1) == SHELL_FUNC_EXIT_CODE ) ?
TRUE : FALSE;
}
}
/************************************************************************
* shell_get_epc
************************************************************************/
UINT64
*shell_get_epc(
t_gdb_regs *regs )
{
return
( (UINT32)regs->cp0_status & C0_STATUS_ERL_BIT ) ?
®s->cp0_errorepc :
®s->cp0_epc;
}
/************************************************************************
*
* shell_setup_default_cpu
* Description :
* -------------
*
* Setup CPU (incl. CP0) registers in context structure so that they
* contain values suiting an application.
*
* Return values :
* ---------------
*
* void
*
************************************************************************/
void
shell_setup_default_cpu(
t_gdb_regs *regs,
UINT32 epc )
{
/* Clear data */
memset( regs, 0, sizeof(t_gdb_regs) );
/* ra (make sure jr ra is handled the same way as exit()) */
SYS_CPUREG(regs, SYS_CPUREG_RA) = (UINT64)shell_return;
/* sp (4 words below top according to C-calling convention) */
SYS_CPUREG(regs, SYS_CPUREG_SP) = (UINT64)(sys_freemem - 4 * sizeof(UINT32));
/* fp (set equal to sp) */
SYS_CPUREG(regs, SYS_CPUREG_FP) = SYS_CPUREG(regs, SYS_CPUREG_SP);
/* frame_ptr field (Dummy GDB reg, should not be used) */
regs->frame_ptr = 0;
/* a0 */
SYS_CPUREG(regs, SYS_CPUREG_A0) = (UINT64)shell_argc_appl;
/* a1 */
SYS_CPUREG(regs, SYS_CPUREG_A1) = (UINT64)shell_argv_appl;
/* a2 points to environment variables */
SYS_CPUREG(regs, SYS_CPUREG_A2) = (UINT64)((UINT32)env_get_all());
/* a3 is set to the memory size */
SYS_CPUREG(regs, SYS_CPUREG_A3) = (UINT64)sys_ramsize;
/* Retrieve current setting of CP0 registers */
sys_store_cp0_regs( regs );
/* CP0 status :
* Clear ERL and set EXL so that EPC will be used upon eret.
* Disable interrupts.
*/
regs->cp0_status &= ~(C0_STATUS_ERL_BIT | C0_STATUS_IE_BIT);
regs->cp0_status |= C0_STATUS_EXL_BIT;
/* EPC (sign extended) */
regs->cp0_epc = (INT64)((INT32)epc);
}
/************************************************************************
*
* shell_go_init
* Description :
* -------------
*
* Initialise command
*
* Return values :
* ---------------
*
* void
*
************************************************************************/
t_cmd *
shell_go_init( void )
{
return &cmd_def;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -