Add target tree files (lcd, tick timer, pcm, buttons and stubs).
[kugel-rb.git] / firmware / target / hosted / android / thread-android-arm.c
blob312a32d7460b36ae43f2cedb1a0b01cdfcd20981
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2005 by Thom Johansen
11 * Copyright (C) 2010 by Thomas Martitz (Android-suitable core_sleep())
13 * Generic ARM threading support
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
20 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
21 * KIND, either express or implied.
23 ****************************************************************************/
25 #include <jni.h>
26 /*---------------------------------------------------------------------------
27 * Start the thread running and terminate it if it returns
28 *---------------------------------------------------------------------------
30 static void __attribute__((naked,used)) start_thread(void)
32 /* r0 = context */
33 asm volatile (
34 "ldr sp, [r0, #32] \n" /* Load initial sp */
35 "ldr r4, [r0, #40] \n" /* start in r4 since it's non-volatile */
36 "mov r1, #0 \n" /* Mark thread as running */
37 "str r1, [r0, #40] \n"
38 "mov lr, pc \n" /* Call thread function */
39 "bx r4 \n"
40 ); /* No clobber list - new thread doesn't care */
41 thread_exit();
44 /* For startup, place context pointer in r4 slot, start_thread pointer in r5
45 * slot, and thread function pointer in context.start. See load_context for
46 * what happens when thread is initially going to run. */
47 #define THREAD_STARTUP_INIT(core, thread, function) \
48 ({ (thread)->context.r[0] = (uint32_t)&(thread)->context, \
49 (thread)->context.r[1] = (uint32_t)start_thread, \
50 (thread)->context.start = (uint32_t)function; })
53 /*---------------------------------------------------------------------------
54 * Store non-volatile context.
55 *---------------------------------------------------------------------------
57 static inline void store_context(void* addr)
59 asm volatile(
60 "stmia %0, { r4-r11, sp, lr } \n"
61 : : "r" (addr)
65 /*---------------------------------------------------------------------------
66 * Load non-volatile context.
67 *---------------------------------------------------------------------------
69 static inline void load_context(const void* addr)
71 asm volatile(
72 "ldr r0, [%0, #40] \n" /* Load start pointer */
73 "cmp r0, #0 \n" /* Check for NULL */
75 /* If not already running, jump to start */
76 "ldmneia %0, { r0, pc } \n"
77 "ldmia %0, { r4-r11, sp, lr } \n" /* Load regs r4 to r14 from context */
78 : : "r" (addr) : "r0" /* only! */
82 extern JNIEnv *env_ptr;
83 extern jclass RockboxActivity_class;
84 extern jobject RockboxActivity_instance;
87 * this core sleep suspends the thread rockbox runs under, which greatly
88 * reduces cpu usage (~100% to <10%)
90 * it returns when the RockboxTimer notified us, i.e. at each tick
91 **/
92 static inline void core_sleep(void)
94 static bool got_method_id = false;
95 static jmethodID java_core_sleep;
97 if (UNLIKELY(!got_method_id))
98 { /* cache method id */
99 java_core_sleep = (*env_ptr)->GetMethodID(env_ptr,
100 RockboxActivity_class,
101 "java_core_sleep",
102 "()V");
103 got_method_id = true;
105 (*env_ptr)->CallVoidMethod(env_ptr, RockboxActivity_instance, java_core_sleep);