You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by ja...@apache.org on 2017/04/26 22:41:07 UTC
[19/50] [abbrv] incubator-mynewt-core git commit: MYNEWT-728;
support native arch armv7.
MYNEWT-728; support native arch armv7.
Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/commit/6d3edb39
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/6d3edb39
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/6d3edb39
Branch: refs/heads/bluetooth5
Commit: 6d3edb39595ad958b04a24e21d854429857bea84
Parents: 31d00cb
Author: Marko Kiiskila <ma...@runtime.io>
Authored: Wed Apr 19 15:30:36 2017 -0700
Committer: Marko Kiiskila <ma...@runtime.io>
Committed: Wed Apr 19 15:30:36 2017 -0700
----------------------------------------------------------------------
compiler/sim-armv7/compiler.yml | 41 ++
compiler/sim-armv7/pkg.yml | 28 ++
.../os/include/os/arch/sim-armv7/os/os_arch.h | 82 ++++
kernel/os/src/arch/sim-armv7/os_arch_sim.c | 457 +++++++++++++++++++
.../os/src/arch/sim-armv7/os_arch_stack_frame.s | 47 ++
kernel/os/src/arch/sim-armv7/os_fault.c | 39 ++
6 files changed, 694 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6d3edb39/compiler/sim-armv7/compiler.yml
----------------------------------------------------------------------
diff --git a/compiler/sim-armv7/compiler.yml b/compiler/sim-armv7/compiler.yml
new file mode 100644
index 0000000..79a710f
--- /dev/null
+++ b/compiler/sim-armv7/compiler.yml
@@ -0,0 +1,41 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+# Default.
+compiler.path.cc: "gcc"
+compiler.path.cpp: "g++"
+compiler.path.as: "gcc"
+compiler.path.archive: "ar"
+compiler.path.objdump: "objdump"
+compiler.path.objsize: "size"
+compiler.path.objcopy: "objcopy"
+compiler.flags.base: >
+ -Wall -Werror -ggdb -DARCH_sim
+compiler.ld.resolve_circular_deps: true
+
+compiler.flags.default: [compiler.flags.base, -O1]
+compiler.flags.debug: [compiler.flags.base, -O0]
+compiler.as.flags: [-x, assembler-with-cpp]
+compiler.ld.mapfile: false
+compiler.ld.binfile: false
+
+# Linux.
+compiler.flags.base.LINUX: >
+ -DMN_LINUX
+compiler.ld.flags.LINUX: -lutil
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6d3edb39/compiler/sim-armv7/pkg.yml
----------------------------------------------------------------------
diff --git a/compiler/sim-armv7/pkg.yml b/compiler/sim-armv7/pkg.yml
new file mode 100644
index 0000000..d5a7ec7
--- /dev/null
+++ b/compiler/sim-armv7/pkg.yml
@@ -0,0 +1,28 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+pkg.name: compiler/sim-armv7
+pkg.type: compiler
+pkg.description: Compiler definition for native gcc compiler.
+pkg.author: "Apache Mynewt <de...@mynewt.incubator.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+ - sim
+ - compiler
+ - gcc
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6d3edb39/kernel/os/include/os/arch/sim-armv7/os/os_arch.h
----------------------------------------------------------------------
diff --git a/kernel/os/include/os/arch/sim-armv7/os/os_arch.h b/kernel/os/include/os/arch/sim-armv7/os/os_arch.h
new file mode 100644
index 0000000..80f886f
--- /dev/null
+++ b/kernel/os/include/os/arch/sim-armv7/os/os_arch.h
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef _OS_ARCH_SIM_H
+#define _OS_ARCH_SIM_H
+
+#include <mcu/mcu_sim.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct os_task;
+
+/* CPU status register */
+typedef unsigned int os_sr_t;
+/* Stack type, aligned to a 32-bit word. */
+#define OS_STACK_PATTERN (0xdeadbeef)
+
+typedef unsigned int os_stack_t;
+#define OS_ALIGNMENT (4)
+#define OS_STACK_ALIGNMENT (16)
+
+/*
+ * Stack sizes for common OS tasks
+ */
+#define OS_SANITY_STACK_SIZE (1024)
+#define OS_IDLE_STACK_SIZE (1024)
+
+/*
+ * The 'sim' architecture-specific code does not have as much control on
+ * stack usage as the real embedded architectures.
+ *
+ * For e.g. the space occupied by the signal handler frame on the task
+ * stack is entirely dependent on the host OS.
+ *
+ * Deal with this by scaling the stack size by a factor of 16. The scaling
+ * factor can be arbitrarily large because the stacks are allocated from
+ * BSS and thus don't add to either the executable size or resident
+ * memory.
+ */
+#define OS_STACK_ALIGN(__nmemb) \
+ (OS_ALIGN(((__nmemb) * 16), OS_STACK_ALIGNMENT))
+
+/* Enter a critical section, save processor state, and block interrupts */
+#define OS_ENTER_CRITICAL(__os_sr) (__os_sr = os_arch_save_sr())
+/* Exit a critical section, restore processor state and unblock interrupts */
+#define OS_EXIT_CRITICAL(__os_sr) (os_arch_restore_sr(__os_sr))
+#define OS_ASSERT_CRITICAL() (assert(os_arch_in_critical()))
+
+void _Die(char *file, int line);
+
+os_stack_t *os_arch_task_stack_init(struct os_task *, os_stack_t *, int);
+void os_arch_ctx_sw(struct os_task *);
+os_sr_t os_arch_save_sr(void);
+void os_arch_restore_sr(os_sr_t sr);
+int os_arch_in_critical(void);
+os_error_t os_arch_os_init(void);
+void os_arch_os_stop(void);
+os_error_t os_arch_os_start(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _OS_ARCH_SIM_H */
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6d3edb39/kernel/os/src/arch/sim-armv7/os_arch_sim.c
----------------------------------------------------------------------
diff --git a/kernel/os/src/arch/sim-armv7/os_arch_sim.c b/kernel/os/src/arch/sim-armv7/os_arch_sim.c
new file mode 100644
index 0000000..67d1a6e
--- /dev/null
+++ b/kernel/os/src/arch/sim-armv7/os_arch_sim.c
@@ -0,0 +1,457 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "os/os.h"
+#include "os_priv.h"
+
+#include <hal/hal_bsp.h>
+
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <sys/time.h>
+#include <assert.h>
+
+struct stack_frame {
+ int sf_mainsp; /* stack on which main() is executing */
+ sigjmp_buf sf_jb;
+ struct os_task *sf_task;
+};
+
+/*
+ * Assert that 'sf_mainsp' and 'sf_jb' are at the specific offsets where
+ * os_arch_frame_init() expects them to be.
+ */
+CTASSERT(offsetof(struct stack_frame, sf_mainsp) == 0);
+CTASSERT(offsetof(struct stack_frame, sf_jb) == 8);
+
+extern void os_arch_frame_init(struct stack_frame *sf);
+
+#define sim_setjmp(__jb) sigsetjmp(__jb, 0)
+#define sim_longjmp(__jb, __ret) siglongjmp(__jb, __ret)
+
+#define OS_USEC_PER_TICK (1000000 / OS_TICKS_PER_SEC)
+
+static pid_t mypid;
+static sigset_t allsigs, nosigs;
+static void timer_handler(int sig);
+
+static bool suspended; /* process is blocked in sigsuspend() */
+static sigset_t suspsigs; /* signals delivered in sigsuspend() */
+
+/*
+ * Called from 'os_arch_frame_init()' when setjmp returns indirectly via
+ * longjmp. The return value of setjmp is passed to this function as 'rc'.
+ */
+void
+os_arch_task_start(struct stack_frame *sf, int rc)
+{
+ struct os_task *task;
+
+ /*
+ * Interrupts are disabled when a task starts executing. This happens in
+ * two different ways:
+ * - via os_arch_os_start() for the first task.
+ * - via os_sched() for all other tasks.
+ *
+ * Enable interrupts before starting the task.
+ */
+ OS_EXIT_CRITICAL(0);
+
+ task = sf->sf_task;
+ task->t_func(task->t_arg);
+
+ /* This should never return */
+ assert(0);
+}
+
+os_stack_t *
+os_arch_task_stack_init(struct os_task *t, os_stack_t *stack_top, int size)
+{
+ struct stack_frame *sf;
+
+ sf = (struct stack_frame *) ((uint8_t *) stack_top - sizeof(*sf));
+ sf->sf_task = t;
+
+ os_arch_frame_init(sf);
+
+ return ((os_stack_t *)sf);
+}
+
+void
+os_arch_ctx_sw(struct os_task *next_t)
+{
+ /*
+ * gdb will stop execution of the program on most signals (e.g. SIGUSR1)
+ * whereas it passes SIGURG to the process without any special settings.
+ */
+ kill(mypid, SIGURG);
+}
+
+static void
+ctxsw_handler(int sig)
+{
+ struct os_task *t, *next_t;
+ struct stack_frame *sf;
+ int rc;
+
+ OS_ASSERT_CRITICAL();
+
+ /*
+ * Just record that this handler was called when the process was blocked.
+ * The handler will be called after sigsuspend() returns in the correct
+ * order.
+ */
+ if (suspended) {
+ sigaddset(&suspsigs, sig);
+ return;
+ }
+
+ t = os_sched_get_current_task();
+ next_t = os_sched_next_task();
+ if (t == next_t) {
+ /*
+ * Context switch not needed - just return.
+ */
+ return;
+ }
+
+ if (t) {
+ sf = (struct stack_frame *) t->t_stackptr;
+
+ rc = sim_setjmp(sf->sf_jb);
+ if (rc != 0) {
+ OS_ASSERT_CRITICAL();
+ return;
+ }
+ }
+
+ os_sched_ctx_sw_hook(next_t);
+
+ os_sched_set_current_task(next_t);
+
+ sf = (struct stack_frame *) next_t->t_stackptr;
+ sim_longjmp(sf->sf_jb, 1);
+}
+
+/*
+ * Disable signals and enter a critical section.
+ *
+ * Returns 1 if signals were already blocked and 0 otherwise.
+ */
+os_sr_t
+os_arch_save_sr(void)
+{
+ int error;
+ sigset_t omask;
+
+ error = sigprocmask(SIG_BLOCK, &allsigs, &omask);
+ assert(error == 0);
+
+ /*
+ * If any one of the signals in 'allsigs' is present in 'omask' then
+ * we are already inside a critical section.
+ */
+ return (sigismember(&omask, SIGALRM));
+}
+
+void
+os_arch_restore_sr(os_sr_t osr)
+{
+ int error;
+
+ OS_ASSERT_CRITICAL();
+ assert(osr == 0 || osr == 1);
+
+ if (osr == 1) {
+ /* Exiting a nested critical section */
+ return;
+ }
+
+ error = sigprocmask(SIG_UNBLOCK, &allsigs, NULL);
+ assert(error == 0);
+}
+
+int
+os_arch_in_critical(void)
+{
+ int error;
+ sigset_t omask;
+
+ error = sigprocmask(SIG_SETMASK, NULL, &omask);
+ assert(error == 0);
+
+ /*
+ * If any one of the signals in 'allsigs' is present in 'omask' then
+ * we are already inside a critical section.
+ */
+ return (sigismember(&omask, SIGALRM));
+}
+
+static struct {
+ int num;
+ void (*handler)(int sig);
+} signals[] = {
+ { SIGALRM, timer_handler },
+ { SIGURG, ctxsw_handler },
+};
+
+#define NUMSIGS (sizeof(signals)/sizeof(signals[0]))
+
+void
+os_tick_idle(os_time_t ticks)
+{
+ int i, rc, sig;
+ struct itimerval it;
+ void (*handler)(int sig);
+
+ OS_ASSERT_CRITICAL();
+
+ if (ticks > 0) {
+ /*
+ * Enter tickless regime and set the timer to fire after 'ticks'
+ * worth of time has elapsed.
+ */
+ it.it_value.tv_sec = ticks / OS_TICKS_PER_SEC;
+ it.it_value.tv_usec = (ticks % OS_TICKS_PER_SEC) * OS_USEC_PER_TICK;
+ it.it_interval.tv_sec = 0;
+ it.it_interval.tv_usec = OS_USEC_PER_TICK;
+ rc = setitimer(ITIMER_REAL, &it, NULL);
+ assert(rc == 0);
+ }
+
+ suspended = true;
+ sigemptyset(&suspsigs);
+ sigsuspend(&nosigs); /* Wait for a signal to wake us up */
+ suspended = false;
+
+ /*
+ * Call handlers for signals delivered to the process during sigsuspend().
+ * The SIGALRM handler is called before any other handlers to ensure that
+ * OS time is always correct.
+ */
+ if (sigismember(&suspsigs, SIGALRM)) {
+ timer_handler(SIGALRM);
+ }
+ for (i = 0; i < NUMSIGS; i++) {
+ sig = signals[i].num;
+ handler = signals[i].handler;
+ if (sig != SIGALRM && sigismember(&suspsigs, sig)) {
+ handler(sig);
+ }
+ }
+
+ if (ticks > 0) {
+ /*
+ * Enable the periodic timer interrupt.
+ */
+ it.it_value.tv_sec = 0;
+ it.it_value.tv_usec = OS_USEC_PER_TICK;
+ it.it_interval.tv_sec = 0;
+ it.it_interval.tv_usec = OS_USEC_PER_TICK;
+ rc = setitimer(ITIMER_REAL, &it, NULL);
+ assert(rc == 0);
+ }
+}
+
+static void
+signals_init(void)
+{
+ int i, error;
+ struct sigaction sa;
+
+ sigemptyset(&nosigs);
+ sigemptyset(&allsigs);
+ for (i = 0; i < NUMSIGS; i++) {
+ sigaddset(&allsigs, signals[i].num);
+ }
+
+ for (i = 0; i < NUMSIGS; i++) {
+ memset(&sa, 0, sizeof sa);
+ sa.sa_handler = signals[i].handler;
+ sa.sa_mask = allsigs;
+ sa.sa_flags = SA_RESTART;
+ error = sigaction(signals[i].num, &sa, NULL);
+ assert(error == 0);
+ }
+
+ /*
+ * We use SIGALRM as a proxy for 'allsigs' to check if we are inside
+ * a critical section (for e.g. see os_arch_in_critical()). Make sure
+ * that SIGALRM is indeed present in 'allsigs'.
+ */
+ assert(sigismember(&allsigs, SIGALRM));
+}
+
+static void
+signals_cleanup(void)
+{
+ int i, error;
+ struct sigaction sa;
+
+ for (i = 0; i < NUMSIGS; i++) {
+ memset(&sa, 0, sizeof sa);
+ sa.sa_handler = SIG_DFL;
+ error = sigaction(signals[i].num, &sa, NULL);
+ assert(error == 0);
+ }
+}
+
+static void
+timer_handler(int sig)
+{
+ struct timeval time_now, time_diff;
+ int ticks;
+
+ static struct timeval time_last;
+ static int time_inited;
+
+ OS_ASSERT_CRITICAL();
+
+ /*
+ * Just record that this handler was called when the process was blocked.
+ * The handler will be called after sigsuspend() returns in the proper
+ * order.
+ */
+ if (suspended) {
+ sigaddset(&suspsigs, sig);
+ return;
+ }
+
+ if (!time_inited) {
+ gettimeofday(&time_last, NULL);
+ time_inited = 1;
+ }
+
+ gettimeofday(&time_now, NULL);
+ if (timercmp(&time_now, &time_last, <)) {
+ /*
+ * System time going backwards.
+ */
+ time_last = time_now;
+ } else {
+ timersub(&time_now, &time_last, &time_diff);
+
+ ticks = time_diff.tv_sec * OS_TICKS_PER_SEC;
+ ticks += time_diff.tv_usec / OS_USEC_PER_TICK;
+
+ /*
+ * Update 'time_last' but account for the remainder usecs that did not
+ * contribute towards whole 'ticks'.
+ */
+ time_diff.tv_sec = 0;
+ time_diff.tv_usec %= OS_USEC_PER_TICK;
+ timersub(&time_now, &time_diff, &time_last);
+
+ os_time_advance(ticks);
+ }
+}
+
+static void
+start_timer(void)
+{
+ struct itimerval it;
+ int rc;
+
+ memset(&it, 0, sizeof(it));
+ it.it_value.tv_sec = 0;
+ it.it_value.tv_usec = OS_USEC_PER_TICK;
+ it.it_interval.tv_sec = 0;
+ it.it_interval.tv_usec = OS_USEC_PER_TICK;
+
+ rc = setitimer(ITIMER_REAL, &it, NULL);
+ assert(rc == 0);
+}
+
+static void
+stop_timer(void)
+{
+ struct itimerval it;
+ int rc;
+
+ memset(&it, 0, sizeof(it));
+
+ rc = setitimer(ITIMER_REAL, &it, NULL);
+ assert(rc == 0);
+}
+
+os_error_t
+os_arch_os_init(void)
+{
+ mypid = getpid();
+ g_current_task = NULL;
+
+ STAILQ_INIT(&g_os_task_list);
+ TAILQ_INIT(&g_os_run_list);
+ TAILQ_INIT(&g_os_sleep_list);
+
+ /*
+ * Setup all interrupt handlers.
+ *
+ * This must be done early because task initialization uses critical
+ * sections which function correctly only when 'allsigs' is initialized.
+ */
+ signals_init();
+
+ os_init_idle_task();
+
+ return OS_OK;
+}
+
+os_error_t
+os_arch_os_start(void)
+{
+ struct stack_frame *sf;
+ struct os_task *t;
+ os_sr_t sr;
+
+ /*
+ * Disable interrupts before enabling any interrupt sources. Pending
+ * interrupts will be recognized when the first task starts executing.
+ */
+ OS_ENTER_CRITICAL(sr);
+ assert(sr == 0);
+
+ /* Enable the interrupt sources */
+ start_timer();
+
+ t = os_sched_next_task();
+ os_sched_set_current_task(t);
+
+ g_os_started = 1;
+
+ sf = (struct stack_frame *) t->t_stackptr;
+ sim_longjmp(sf->sf_jb, 1);
+
+ return 0;
+}
+
+/**
+ * Stops the tick timer and clears the "started" flag. This function is only
+ * implemented for sim.
+ */
+void
+os_arch_os_stop(void)
+{
+ stop_timer();
+ signals_cleanup();
+ g_os_started = 0;
+}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6d3edb39/kernel/os/src/arch/sim-armv7/os_arch_stack_frame.s
----------------------------------------------------------------------
diff --git a/kernel/os/src/arch/sim-armv7/os_arch_stack_frame.s b/kernel/os/src/arch/sim-armv7/os_arch_stack_frame.s
new file mode 100644
index 0000000..460d54a
--- /dev/null
+++ b/kernel/os/src/arch/sim-armv7/os_arch_stack_frame.s
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#define sigsetjmp __sigsetjmp
+
+ .text
+ .p2align 4, 0x90 /* align on 16-byte boundary and fill with NOPs */
+
+ .globl os_arch_frame_init
+ /*
+ * void os_arch_frame_init(struct stack_frame *sf)
+ */
+os_arch_frame_init:
+ mov r1, sp
+ mov sp, r0 /* stack for the task starts from sf */
+ sub sp, sp, #20
+ str r1, [sp, #12]
+ str lr, [sp, #16] /* Store LR there */
+ str r0, [sp, #4] /* Store sf pointer to stack */
+ add r0, r0, #8 /* $r0 = sf->sf_jb */
+ mov r1, #0
+ bl __sigsetjmp
+ cmp r0, #0 /* If $r0 == 0 then return */
+ beq end
+ mov r1, r0
+ ldr r0, [sp, #4]
+ bl os_arch_task_start
+end:
+ ldr r1, [sp, #16] /* return $sp for the callee */
+ ldr sp, [sp, #12]
+ mov pc, r1
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6d3edb39/kernel/os/src/arch/sim-armv7/os_fault.c
----------------------------------------------------------------------
diff --git a/kernel/os/src/arch/sim-armv7/os_fault.c b/kernel/os/src/arch/sim-armv7/os_fault.c
new file mode 100644
index 0000000..964202e
--- /dev/null
+++ b/kernel/os/src/arch/sim-armv7/os_fault.c
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "os/os.h"
+#include "os_priv.h"
+
+void
+__assert_func(const char *file, int line, const char *func, const char *e)
+{
+ char msg[256];
+
+ if (file) {
+ snprintf(msg, sizeof(msg), "assert @ %s:%d\n", file, line);
+ } else {
+ snprintf(msg, sizeof(msg), "assert @ %p\n",
+ __builtin_return_address(0));
+ }
+ write(1, msg, strlen(msg));
+ _exit(1);
+}