mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2026-01-01 12:52:26 +00:00
Merge "Support warm reboot from one EC image to another."
This commit is contained in:
@@ -16,7 +16,7 @@
|
||||
|
||||
|
||||
/* 0-terminated list of GPIO bases */
|
||||
const uint32_t gpio_bases[] = {
|
||||
static const uint32_t gpio_bases[] = {
|
||||
LM4_GPIO_A, LM4_GPIO_B, LM4_GPIO_C, LM4_GPIO_D,
|
||||
LM4_GPIO_E, LM4_GPIO_F, LM4_GPIO_G, LM4_GPIO_H,
|
||||
LM4_GPIO_J, LM4_GPIO_K, LM4_GPIO_L, LM4_GPIO_M,
|
||||
@@ -45,12 +45,18 @@ int gpio_pre_init(void)
|
||||
{
|
||||
volatile uint32_t scratch __attribute__((unused));
|
||||
const struct gpio_info *g = gpio_list;
|
||||
int is_warm = 0;
|
||||
int i;
|
||||
|
||||
/* Enable clocks to all the GPIO blocks (since we use all of them as
|
||||
* GPIOs) */
|
||||
LM4_SYSTEM_RCGCGPIO |= 0x7fff;
|
||||
scratch = LM4_SYSTEM_RCGCGPIO; /* Delay a few clocks */
|
||||
if (LM4_SYSTEM_RCGCGPIO == 0x7fff) {
|
||||
/* This is a warm reboot */
|
||||
is_warm = 1;
|
||||
} else {
|
||||
/* Enable clocks to all the GPIO blocks (since we use all of
|
||||
* them as GPIOs) */
|
||||
LM4_SYSTEM_RCGCGPIO |= 0x7fff;
|
||||
scratch = LM4_SYSTEM_RCGCGPIO; /* Delay a few clocks */
|
||||
}
|
||||
|
||||
/* Disable GPIO commit control for PD7 and PF0, since we don't use the
|
||||
* NMI pin function. */
|
||||
@@ -64,6 +70,10 @@ int gpio_pre_init(void)
|
||||
/* Clear SSI0 alternate function on PA2:5 */
|
||||
LM4_GPIO_AFSEL(LM4_GPIO_A) &= ~0x3c;
|
||||
|
||||
/* Mask all GPIO interrupts */
|
||||
for (i = 0; gpio_bases[i]; i++)
|
||||
LM4_GPIO_IM(gpio_bases[i]) = 0;
|
||||
|
||||
/* Set all GPIOs to defaults */
|
||||
for (i = 0; i < GPIO_COUNT; i++, g++) {
|
||||
|
||||
@@ -76,7 +86,11 @@ int gpio_pre_init(void)
|
||||
LM4_GPIO_DIR(g->port) |= g->mask;
|
||||
/* Must set level after direction; writes to GPIO_DATA
|
||||
* before direction is output appear to be ignored. */
|
||||
gpio_set_level(i, g->flags & GPIO_HIGH);
|
||||
/* Only set level on a cold reboot; on a warm reboot we
|
||||
* want to leave things where they were or we'll shut
|
||||
* off the x86. */
|
||||
if (!is_warm)
|
||||
gpio_set_level(i, g->flags & GPIO_HIGH);
|
||||
} else {
|
||||
/* Input */
|
||||
if (g->flags & GPIO_PULL) {
|
||||
|
||||
@@ -97,6 +97,9 @@ int peci_init(void)
|
||||
/* Configure GPIOs */
|
||||
configure_gpios();
|
||||
|
||||
/* Disable polling while reconfiguring */
|
||||
LM4_PECI_CTL = 0;
|
||||
|
||||
/* Calculate baud setting from desired rate, compensating for internal
|
||||
* and external delays. */
|
||||
baud = CPU_CLOCK / (4 * PECI_BAUD_RATE) - 2;
|
||||
|
||||
@@ -61,7 +61,8 @@ static void check_reset_cause(void)
|
||||
} else if (raw_reset_cause) {
|
||||
reset_cause = SYSTEM_RESET_OTHER;
|
||||
} else {
|
||||
reset_cause = SYSTEM_RESET_UNKNOWN;
|
||||
/* Reset cause is still 0, so this is a warm reset. */
|
||||
reset_cause = SYSTEM_RESET_SOFT_WARM;
|
||||
}
|
||||
system_set_reset_cause(reset_cause);
|
||||
}
|
||||
|
||||
@@ -19,6 +19,15 @@
|
||||
/* Baud rate for UARTs */
|
||||
#define BAUD_RATE 115200
|
||||
|
||||
|
||||
static int init_done;
|
||||
|
||||
|
||||
int uart_init_done(void)
|
||||
{
|
||||
return init_done;
|
||||
}
|
||||
|
||||
void uart_tx_start(void)
|
||||
{
|
||||
/* Re-enable the transmit interrupt, then forcibly trigger the
|
||||
@@ -186,6 +195,8 @@ int uart_init(void)
|
||||
*/
|
||||
task_enable_irq(LM4_IRQ_UART0);
|
||||
|
||||
init_done = 1;
|
||||
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
@@ -114,10 +114,13 @@ int watchdog_init(int period_ms)
|
||||
|
||||
/* Enable watchdog 0 clock */
|
||||
LM4_SYSTEM_RCGCWD |= 0x1;
|
||||
/* wait 3 clock cycles before using the module */
|
||||
/* Wait 3 clock cycles before using the module */
|
||||
scratch = LM4_SYSTEM_RCGCWD;
|
||||
|
||||
/* set the time-out period */
|
||||
/* Unlock watchdog registers */
|
||||
LM4_WATCHDOG_LOCK(0) = LM4_WATCHDOG_MAGIC_WORD;
|
||||
|
||||
/* Set the time-out period */
|
||||
watchdog_period = period_ms * (CPU_CLOCK / 1000);
|
||||
LM4_WATCHDOG_LOAD(0) = watchdog_period;
|
||||
|
||||
@@ -129,7 +132,10 @@ int watchdog_init(int period_ms)
|
||||
*/
|
||||
LM4_WATCHDOG_CTL(0) = 0x3;
|
||||
|
||||
/* lock watchdog registers against unintended accesses */
|
||||
/* Reset watchdog interrupt bits */
|
||||
LM4_WATCHDOG_ICR(0) = LM4_WATCHDOG_RIS(0);
|
||||
|
||||
/* Lock watchdog registers against unintended accesses */
|
||||
LM4_WATCHDOG_LOCK(0) = 0xdeaddead;
|
||||
|
||||
/* Enable watchdog interrupt */
|
||||
|
||||
@@ -20,8 +20,14 @@
|
||||
/* Console USART index */
|
||||
#define UARTN CONFIG_CONSOLE_UART
|
||||
|
||||
/* record last TX control action */
|
||||
static int should_stop;
|
||||
static int init_done; /* Initialization done? */
|
||||
static int should_stop; /* Last TX control action */
|
||||
|
||||
|
||||
int uart_init_done(void)
|
||||
{
|
||||
return init_done;
|
||||
}
|
||||
|
||||
void uart_tx_start(void)
|
||||
{
|
||||
@@ -138,5 +144,7 @@ int uart_init(void)
|
||||
/* Enable interrupts */
|
||||
task_enable_irq(STM32L_IRQ_USART(UARTN));
|
||||
|
||||
init_done = 1;
|
||||
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -49,6 +49,10 @@ int main(void)
|
||||
jtag_pre_init();
|
||||
gpio_pre_init();
|
||||
|
||||
/* Initialize interrupts, but don't enable any of them. Note that
|
||||
* task scheduling is not enabled until task_start() below. */
|
||||
task_pre_init();
|
||||
|
||||
#ifdef CONFIG_FLASH
|
||||
flash_pre_init();
|
||||
#endif
|
||||
@@ -64,10 +68,6 @@ int main(void)
|
||||
/* Set the CPU clocks / PLLs. System is now running at full speed. */
|
||||
clock_init();
|
||||
|
||||
/* Initialize interrupts, but don't enable any of them. Note that
|
||||
* task scheduling is not enabled until task_start() below. */
|
||||
task_init();
|
||||
|
||||
/* Main initialization stage. Modules may enable interrupts here. */
|
||||
|
||||
/* Initialize UART. uart_printf(), etc. may now be used. */
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "host_command.h"
|
||||
#include "lpc_commands.h"
|
||||
#include "system.h"
|
||||
#include "task.h"
|
||||
#include "uart.h"
|
||||
#include "util.h"
|
||||
#include "version.h"
|
||||
@@ -64,39 +65,60 @@ const char *system_get_image_copy_string(void)
|
||||
}
|
||||
|
||||
|
||||
/* Jump to what we hope is the init address of an image. This function does
|
||||
* not return. */
|
||||
static void jump_to_image(uint32_t init_addr)
|
||||
{
|
||||
void (*resetvec)(void) = (void(*)(void))init_addr;
|
||||
|
||||
/* Flush UART output unless the UART hasn't been initialized yet */
|
||||
if (uart_init_done())
|
||||
uart_flush_output();
|
||||
|
||||
/* Disable interrupts before jump */
|
||||
interrupt_disable();
|
||||
|
||||
/* Jump to the reset vector */
|
||||
resetvec();
|
||||
}
|
||||
|
||||
|
||||
int system_run_image_copy(enum system_image_copy_t copy)
|
||||
{
|
||||
uint32_t base;
|
||||
uint32_t init_addr;
|
||||
void (*resetvec)(void);
|
||||
|
||||
/* Fail if we're not in RO firmware */
|
||||
if (system_get_image_copy() != SYSTEM_IMAGE_RO)
|
||||
return EC_ERROR_UNKNOWN;
|
||||
|
||||
/* Load the appropriate reset vector */
|
||||
if (copy == SYSTEM_IMAGE_RW_A)
|
||||
init_addr = *(uint32_t *)(CONFIG_FW_A_OFF + 4);
|
||||
#ifndef CONFIG_NO_RW_B
|
||||
else if (copy == SYSTEM_IMAGE_RW_B)
|
||||
init_addr = *(uint32_t *)(CONFIG_FW_B_OFF + 4);
|
||||
#endif
|
||||
else
|
||||
return EC_ERROR_UNKNOWN;
|
||||
|
||||
/* TODO: sanity checks (crosbug.com/p/7468)
|
||||
*
|
||||
* Fail if called outside of pre-init.
|
||||
*
|
||||
* Fail if reboot reason is not soft reboot. Power-on
|
||||
* reset cause must run RO firmware; if it wants to move to RW
|
||||
* firmware, it must go through a soft reboot first
|
||||
*
|
||||
* Sanity check reset vector; must be inside the appropriate
|
||||
* image. */
|
||||
* For this to be allowed either WP must be disabled, or ALL of the
|
||||
* following must be true:
|
||||
* - We must currently be running the RO image.
|
||||
* - We must still be in init (that is, before task_start().
|
||||
* - The target image must be A or B. */
|
||||
|
||||
/* Jump to the reset vector */
|
||||
resetvec = (void(*)(void))init_addr;
|
||||
resetvec();
|
||||
/* Load the appropriate reset vector */
|
||||
switch (copy) {
|
||||
case SYSTEM_IMAGE_RO:
|
||||
base = CONFIG_FW_RO_OFF;
|
||||
break;
|
||||
case SYSTEM_IMAGE_RW_A:
|
||||
base = CONFIG_FW_A_OFF;
|
||||
break;
|
||||
#ifndef CONFIG_NO_RW_B
|
||||
case SYSTEM_IMAGE_RW_B:
|
||||
base = CONFIG_FW_B_OFF;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return EC_ERROR_INVAL;
|
||||
}
|
||||
|
||||
/* Make sure the reset vector is inside the destination image */
|
||||
init_addr = *(uint32_t *)(base + 4);
|
||||
if (init_addr < base || init_addr >= base + CONFIG_FW_IMAGE_SIZE)
|
||||
return EC_ERROR_UNKNOWN;
|
||||
|
||||
jump_to_image(init_addr);
|
||||
|
||||
/* Should never get here */
|
||||
return EC_ERROR_UNIMPLEMENTED;
|
||||
@@ -215,6 +237,46 @@ static int command_version(int argc, char **argv)
|
||||
}
|
||||
DECLARE_CONSOLE_COMMAND(version, command_version);
|
||||
|
||||
|
||||
static int command_sysjump(int argc, char **argv)
|
||||
{
|
||||
uint32_t addr;
|
||||
char *e;
|
||||
|
||||
/* TODO: (crosbug.com/p/7468) For this command to be allowed, WP must
|
||||
* be disabled. */
|
||||
|
||||
if (argc < 2) {
|
||||
uart_puts("Usage: sysjump <RO | A | B | addr>\n");
|
||||
return EC_ERROR_INVAL;
|
||||
}
|
||||
|
||||
/* Handle named images */
|
||||
if (!strcasecmp(argv[1], "RO")) {
|
||||
uart_puts("Jumping directly to RO image...\n");
|
||||
return system_run_image_copy(SYSTEM_IMAGE_RO);
|
||||
} else if (!strcasecmp(argv[1], "A")) {
|
||||
uart_puts("Jumping directly to image A...\n");
|
||||
return system_run_image_copy(SYSTEM_IMAGE_RW_A);
|
||||
} else if (!strcasecmp(argv[1], "B")) {
|
||||
uart_puts("Jumping directly to image B...\n");
|
||||
return system_run_image_copy(SYSTEM_IMAGE_RW_B);
|
||||
}
|
||||
|
||||
/* Check for arbitrary address */
|
||||
addr = strtoi(argv[1], &e, 0);
|
||||
if (e && *e) {
|
||||
uart_puts("Invalid image address\n");
|
||||
return EC_ERROR_INVAL;
|
||||
}
|
||||
uart_printf("Jumping directly to 0x%08x...\n", addr);
|
||||
uart_flush_output();
|
||||
jump_to_image(addr);
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
DECLARE_CONSOLE_COMMAND(sysjump, command_sysjump);
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Host commands */
|
||||
|
||||
@@ -261,3 +323,41 @@ static enum lpc_status host_command_build_info(uint8_t *data)
|
||||
return EC_LPC_RESULT_SUCCESS;
|
||||
}
|
||||
DECLARE_HOST_COMMAND(EC_LPC_COMMAND_GET_BUILD_INFO, host_command_build_info);
|
||||
|
||||
|
||||
#ifdef CONFIG_REBOOT_EC
|
||||
enum lpc_status host_command_reboot(uint8_t *data)
|
||||
{
|
||||
struct lpc_params_reboot_ec *p =
|
||||
(struct lpc_params_reboot_ec *)data;
|
||||
|
||||
/* TODO: (crosbug.com/p/7468) For this command to be allowed, WP must
|
||||
* be disabled. */
|
||||
|
||||
switch (p->target) {
|
||||
case EC_LPC_IMAGE_RO:
|
||||
uart_puts("[Rebooting to image RO!\n]");
|
||||
system_run_image_copy(SYSTEM_IMAGE_RO);
|
||||
break;
|
||||
case EC_LPC_IMAGE_RW_A:
|
||||
uart_puts("[Rebooting to image A!]\n");
|
||||
system_run_image_copy(SYSTEM_IMAGE_RW_A);
|
||||
break;
|
||||
case EC_LPC_IMAGE_RW_B:
|
||||
uart_puts("[Rebooting to image B!]\n");
|
||||
system_run_image_copy(SYSTEM_IMAGE_RW_B);
|
||||
break;
|
||||
default:
|
||||
return EC_LPC_RESULT_ERROR;
|
||||
}
|
||||
|
||||
/* We normally never get down here, because we'll have jumped to
|
||||
* another image. To confirm this command worked, the host will need
|
||||
* to check what image is current using GET_VERSION.
|
||||
*
|
||||
* If we DO get down here, something went wrong in the reboot, so
|
||||
* return error. */
|
||||
return EC_LPC_RESULT_ERROR;
|
||||
}
|
||||
DECLARE_HOST_COMMAND(EC_LPC_COMMAND_REBOOT_EC, host_command_reboot);
|
||||
#endif /* CONFIG_REBOOT_EC */
|
||||
|
||||
@@ -90,35 +90,6 @@ static int command_reboot(int argc, char **argv)
|
||||
}
|
||||
DECLARE_CONSOLE_COMMAND(reboot, command_reboot);
|
||||
|
||||
#ifdef CONFIG_REBOOT_EC
|
||||
enum lpc_status vboot_command_reboot(uint8_t *data) {
|
||||
struct lpc_params_reboot_ec *p =
|
||||
(struct lpc_params_reboot_ec *)data;
|
||||
|
||||
switch (p->target) {
|
||||
case EC_LPC_IMAGE_RW_A:
|
||||
uart_puts("Rebooting to image A!\n\n\n");
|
||||
system_set_scratchpad(SCRATCHPAD_REQUEST_A);
|
||||
break;
|
||||
case EC_LPC_IMAGE_RW_B:
|
||||
uart_puts("Rebooting to image B!\n\n\n");
|
||||
system_set_scratchpad(SCRATCHPAD_REQUEST_B);
|
||||
break;
|
||||
case EC_LPC_IMAGE_RO: /* do nothing */
|
||||
uart_puts("Rebooting to image RO!\n\n\n");
|
||||
break;
|
||||
default:
|
||||
return EC_LPC_RESULT_ERROR;
|
||||
}
|
||||
|
||||
uart_flush_output();
|
||||
/* TODO - param to specify warm/cold */
|
||||
system_reset(1);
|
||||
return EC_LPC_RESULT_SUCCESS;
|
||||
}
|
||||
DECLARE_HOST_COMMAND(EC_LPC_COMMAND_REBOOT_EC, vboot_command_reboot);
|
||||
#endif /* CONFIG_REBOOT_EC */
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Initialization */
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "gpio.h"
|
||||
#include "lpc.h"
|
||||
#include "pwm.h"
|
||||
#include "system.h"
|
||||
#include "task.h"
|
||||
#include "timer.h"
|
||||
#include "uart.h"
|
||||
@@ -77,7 +78,9 @@ static const char * const state_names[] = {
|
||||
IN_PCH_SLP_S4n_DEASSERTED | \
|
||||
IN_PCH_SLP_S5n_DEASSERTED | \
|
||||
IN_PCH_SLP_An_DEASSERTED)
|
||||
|
||||
/* All inputs in the right state for S0 */
|
||||
#define IN_ALL_S0 (IN_PGOOD_ALWAYS_ON | IN_PGOOD_ALL_NONCORE | \
|
||||
IN_PGOOD_ALL_CORE | IN_ALL_PM_SLP_DEASSERTED)
|
||||
|
||||
static enum x86_state state; /* Current state */
|
||||
static uint32_t in_signals; /* Current input signal states (IN_PGOOD_*) */
|
||||
@@ -245,12 +248,35 @@ void x86_power_interrupt(enum gpio_signal signal)
|
||||
|
||||
int x86_power_init(void)
|
||||
{
|
||||
/* Default to G3 state unless proven otherwise */
|
||||
state = X86_G3;
|
||||
|
||||
/* Update input state */
|
||||
update_in_signals();
|
||||
in_want = 0;
|
||||
|
||||
/* If this is a warm reboot, see if the x86 is already powered on; if
|
||||
* so, leave it there instead of cycling through G3. */
|
||||
if (system_get_reset_cause() == SYSTEM_RESET_SOFT_WARM) {
|
||||
if ((in_signals & IN_ALL_S0) == IN_ALL_S0) {
|
||||
uart_puts("[x86 already in S0]\n");
|
||||
state = X86_S0;
|
||||
} else {
|
||||
/* Force all signals to their G3 states */
|
||||
uart_puts("[x86 forcing G3]\n");
|
||||
gpio_set_level(GPIO_PCH_PWROK, 0);
|
||||
gpio_set_level(GPIO_ENABLE_VCORE, 0);
|
||||
gpio_set_level(GPIO_PCH_RCINn, 0);
|
||||
gpio_set_level(GPIO_ENABLE_VS, 0);
|
||||
gpio_set_level(GPIO_ENABLE_TOUCHPAD, 0);
|
||||
gpio_set_level(GPIO_TOUCHSCREEN_RESETn, 0);
|
||||
gpio_set_level(GPIO_ENABLE_1_5V_DDR, 0);
|
||||
gpio_set_level(GPIO_SHUNT_1_5V_DDR, 1);
|
||||
gpio_set_level(GPIO_PCH_RSMRSTn, 0);
|
||||
gpio_set_level(GPIO_PCH_DPWROK, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Enable interrupts for our GPIOs */
|
||||
gpio_enable_interrupt(GPIO_PCH_BKLTEN);
|
||||
gpio_enable_interrupt(GPIO_PCH_SLP_An);
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
/* Nested Vectored Interrupt Controller */
|
||||
#define CPU_NVIC_EN(x) CPUREG(0xe000e100 + 4 * (x))
|
||||
#define CPU_NVIC_DIS(x) CPUREG(0xe000e180 + 4 * (x))
|
||||
#define CPU_NVIC_UNPEND(x) CPUREG(0xe000e280 + 4 * (x))
|
||||
#define CPU_NVIC_PRI(x) CPUREG(0xe000e400 + 4 * (x))
|
||||
#define CPU_NVIC_APINT CPUREG(0xe000ed0c)
|
||||
#define CPU_NVIC_SWTRIG CPUREG(0xe000ef00)
|
||||
|
||||
@@ -302,7 +302,13 @@ vector_irq 254 @ IRQ 254 handler
|
||||
.global reset
|
||||
.thumb_func
|
||||
reset:
|
||||
/* set the vector table on our current code */
|
||||
/* Ensure we're in privileged mode with main stack.
|
||||
* Necessary if we've jumped directly here from another image
|
||||
* after task_start(). */
|
||||
mov r0, #0
|
||||
msr control, r0 @ use : priv. mode / main stack / no floating point
|
||||
isb @ ensure the write is done
|
||||
/* Set the vector table on our current code */
|
||||
ldr r1, =vectors
|
||||
ldr r2, =0xE000ED08 /* VTABLE register in SCB*/
|
||||
str r1, [r2]
|
||||
|
||||
@@ -299,18 +299,28 @@ void task_trigger_irq(int irq)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Enable all used IRQ in the NVIC and set their priorities
|
||||
* as defined by the DECLARE_IRQ statements
|
||||
*/
|
||||
/* Initialize IRQs in the NVIC and set their priorities as defined by the
|
||||
* DECLARE_IRQ statements. */
|
||||
static void __nvic_init_irqs(void)
|
||||
{
|
||||
/* get the IRQ priorities section from the linker */
|
||||
/* Get the IRQ priorities section from the linker */
|
||||
extern struct irq_priority __irqprio[];
|
||||
extern struct irq_priority __irqprio_end[];
|
||||
int irq_count = __irqprio_end - __irqprio;
|
||||
int i;
|
||||
|
||||
/* Mask and clear all pending interrupts */
|
||||
for (i = 0; i < 5; i++) {
|
||||
CPU_NVIC_DIS(i) = 0xffffffff;
|
||||
CPU_NVIC_UNPEND(i) = 0xffffffff;
|
||||
}
|
||||
|
||||
/* Re-enable global interrupts in case they're disabled. On a reboot,
|
||||
* they're already enabled; if we've jumped here from another image,
|
||||
* they're not. */
|
||||
interrupt_enable();
|
||||
|
||||
/* Set priorities */
|
||||
for (i = 0; i < irq_count; i++) {
|
||||
uint8_t irq = __irqprio[i].irq;
|
||||
uint8_t prio = __irqprio[i].priority;
|
||||
@@ -405,7 +415,7 @@ DECLARE_CONSOLE_COMMAND(taskready, command_task_ready);
|
||||
#endif
|
||||
|
||||
|
||||
int task_init(void)
|
||||
int task_pre_init(void)
|
||||
{
|
||||
/* sanity checks about static task invariants */
|
||||
BUILD_ASSERT(TASK_ID_COUNT <= sizeof(unsigned) * 8);
|
||||
|
||||
@@ -74,7 +74,7 @@ uint32_t task_wait_msg(int timeout_us);
|
||||
void task_resched_if_needed(void *excep_return);
|
||||
|
||||
/* Initializes tasks and interrupt controller. */
|
||||
int task_init(void);
|
||||
int task_pre_init(void);
|
||||
|
||||
/* Starts task scheduling. */
|
||||
int task_start(void);
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
/* Initializes the UART module. */
|
||||
int uart_init(void);
|
||||
|
||||
/* Return non-zero if UART init has completed. */
|
||||
int uart_init_done(void);
|
||||
|
||||
/* Enables console mode if <enable>!=0. In console mode:
|
||||
* - Input is echoed
|
||||
|
||||
Reference in New Issue
Block a user