Mercurial > ecos
diff packages/redboot/current/src/main.c @ 556:f2b5df359050
Support return to redboot from go
| author | msalter |
|---|---|
| date | Fri, 31 Jan 2003 16:45:57 +0000 |
| parents | 44f818173f96 |
| children | 17d4ac30ee71 |
line wrap: on
line diff
--- a/packages/redboot/current/src/main.c +++ b/packages/redboot/current/src/main.c @@ -8,7 +8,7 @@ //####ECOSGPLCOPYRIGHTBEGIN#### // ------------------------------------------- // This file is part of eCos, the Embedded Configurable Operating System. -// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Red Hat, Inc. // Copyright (C) 2002 Gary Thomas // // eCos is free software; you can redistribute it and/or modify it under @@ -76,6 +76,10 @@ extern void breakpoint(void); // Builtin Self Test (BIST) externC void bist(void); +// Return path for code run from a go command +static void return_to_redboot(int status); + + // CLI command processing (defined in this file) RedBoot_cmd("version", "Display RedBoot version information", @@ -185,6 +189,8 @@ cyg_start(void) // Export version information CYGACC_CALL_IF_MONITOR_VERSION_SET(RedBoot_version); + CYGACC_CALL_IF_MONITOR_RETURN_SET(return_to_redboot); + // Make sure the channels are properly initialized. diag_init_putc(_mon_write_char); hal_if_diag_init(); @@ -378,23 +384,53 @@ do_help(int argc, char *argv[]) return; } +static void * go_saved_context; +static int go_return_status; + +static void +go_trampoline(unsigned long entry) +{ + typedef void code_fun(void); + code_fun *fun = (code_fun *)entry; + unsigned long oldints; + + HAL_DISABLE_INTERRUPTS(oldints); + +#ifdef HAL_ARCH_PROGRAM_NEW_STACK + HAL_ARCH_PROGRAM_NEW_STACK(fun); +#else + (*fun)(); +#endif +} + +static void +return_to_redboot(int status) +{ + CYGARC_HAL_SAVE_GP(); + + go_return_status = status; + HAL_THREAD_LOAD_CONTEXT(&go_saved_context); + // never returns +} + void do_go(int argc, char *argv[]) { - typedef void code_fun(void); unsigned long entry; unsigned long oldints; - code_fun *fun; bool wait_time_set; int wait_time, res; - struct option_info opts[1]; + bool cache_enabled = false; + struct option_info opts[2]; char line[8]; hal_virtual_comm_table_t *__chan = CYGACC_CALL_IF_CONSOLE_PROCS(); entry = entry_address; // Default from last 'load' operation init_opts(&opts[0], 'w', true, OPTION_ARG_TYPE_NUM, (void **)&wait_time, (bool *)&wait_time_set, "wait timeout"); - if (!scan_opts(argc, argv, 1, opts, 1, (void *)&entry, OPTION_ARG_TYPE_NUM, "starting address")) + init_opts(&opts[1], 'c', false, OPTION_ARG_TYPE_FLG, + (void **)&cache_enabled, (bool *)0, "go with caches enabled"); + if (!scan_opts(argc, argv, 1, opts, 2, (void *)&entry, OPTION_ARG_TYPE_NUM, "starting address")) { return; } @@ -419,19 +455,35 @@ do_go(int argc, char *argv[]) } CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_ENABLE_LINE_FLUSH); - fun = (code_fun *)entry; HAL_DISABLE_INTERRUPTS(oldints); HAL_DCACHE_SYNC(); - HAL_ICACHE_DISABLE(); - HAL_DCACHE_DISABLE(); - HAL_DCACHE_SYNC(); + if (!cache_enabled) { + HAL_ICACHE_DISABLE(); + HAL_DCACHE_DISABLE(); + HAL_DCACHE_SYNC(); + } HAL_ICACHE_INVALIDATE_ALL(); HAL_DCACHE_INVALIDATE_ALL(); -#ifdef HAL_ARCH_PROGRAM_NEW_STACK - HAL_ARCH_PROGRAM_NEW_STACK(fun); -#else - (*fun)(); -#endif + + // set up a temporary context that will take us to the trampoline + HAL_THREAD_INIT_CONTEXT((CYG_ADDRESS)workspace_end, entry, go_trampoline, 0); + + // switch context to trampoline + HAL_THREAD_SWITCH_CONTEXT(&go_saved_context, &workspace_end); + + // we get back here by way of return_to_redboot() + + // undo the changes we made before switching context + if (!cache_enabled) { + HAL_ICACHE_ENABLE(); + HAL_DCACHE_ENABLE(); + } + + CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_DISABLE_LINE_FLUSH); + + HAL_RESTORE_INTERRUPTS(oldints); + + diag_printf("\nProgram completed with status %d\n", go_return_status); } #ifdef HAL_PLATFORM_RESET
