Colour targets: Revert an optimisation from almost 18 months ago that actually turned...
[Rockbox.git] / firmware / system.c
blobada99e0b5672cbc0f80a6037b592ed95490f3f24
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2002 by Alan Korr
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
21 #include <stdio.h>
22 #include "config.h"
23 #include <stdbool.h>
24 #include "lcd.h"
25 #include "font.h"
26 #include "system.h"
27 #include "kernel.h"
28 #include "thread.h"
29 #include "timer.h"
30 #include "inttypes.h"
31 #include "string.h"
33 #ifndef SIMULATOR
34 long cpu_frequency SHAREDBSS_ATTR = CPU_FREQ;
35 #endif
37 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
38 static int boost_counter SHAREDBSS_ATTR = 0;
39 static bool cpu_idle SHAREDBSS_ATTR = false;
40 #if NUM_CORES > 1
41 struct spinlock boostctrl_spin SHAREDBSS_ATTR;
42 void cpu_boost_init(void)
44 spinlock_init(&boostctrl_spin);
46 #endif
48 int get_cpu_boost_counter(void)
50 return boost_counter;
52 #ifdef CPU_BOOST_LOGGING
53 #define MAX_BOOST_LOG 64
54 static char cpu_boost_calls[MAX_BOOST_LOG][MAX_PATH];
55 static int cpu_boost_first = 0;
56 static int cpu_boost_calls_count = 0;
57 static int cpu_boost_track_message = 0;
58 int cpu_boost_log_getcount(void)
60 return cpu_boost_calls_count;
62 char * cpu_boost_log_getlog_first(void)
64 char *first;
65 #if NUM_CORES > 1
66 spinlock_lock(&boostctrl_spin);
67 #endif
69 first = NULL;
71 if (cpu_boost_calls_count)
73 cpu_boost_track_message = 1;
74 first = cpu_boost_calls[cpu_boost_first];
77 #if NUM_CORES > 1
78 spinlock_unlock(&boostctrl_spin);
79 #endif
81 return first;
84 char * cpu_boost_log_getlog_next(void)
86 int message;
87 char *next;
89 #if NUM_CORES > 1
90 spinlock_lock(&boostctrl_spin);
91 #endif
93 message = (cpu_boost_track_message+cpu_boost_first)%MAX_BOOST_LOG;
94 next = NULL;
96 if (cpu_boost_track_message < cpu_boost_calls_count)
98 cpu_boost_track_message++;
99 next = cpu_boost_calls[message];
102 #if NUM_CORES > 1
103 spinlock_unlock(&boostctrl_spin);
104 #endif
106 return next;
109 void cpu_boost_(bool on_off, char* location, int line)
111 #if NUM_CORES > 1
112 spinlock_lock(&boostctrl_spin);
113 #endif
115 if (cpu_boost_calls_count == MAX_BOOST_LOG)
117 cpu_boost_first = (cpu_boost_first+1)%MAX_BOOST_LOG;
118 cpu_boost_calls_count--;
119 if (cpu_boost_calls_count < 0)
120 cpu_boost_calls_count = 0;
122 if (cpu_boost_calls_count < MAX_BOOST_LOG)
124 int message = (cpu_boost_first+cpu_boost_calls_count)%MAX_BOOST_LOG;
125 snprintf(cpu_boost_calls[message], MAX_PATH,
126 "%c %s:%d",on_off==true?'B':'U',location,line);
127 cpu_boost_calls_count++;
129 #else
130 void cpu_boost(bool on_off)
132 #if NUM_CORES > 1
133 spinlock_lock(&boostctrl_spin);
134 #endif
136 #endif /* CPU_BOOST_LOGGING */
137 if(on_off)
139 /* Boost the frequency if not already boosted */
140 if(++boost_counter == 1)
141 set_cpu_frequency(CPUFREQ_MAX);
143 else
145 /* Lower the frequency if the counter reaches 0 */
146 if(--boost_counter <= 0)
148 if(cpu_idle)
149 set_cpu_frequency(CPUFREQ_DEFAULT);
150 else
151 set_cpu_frequency(CPUFREQ_NORMAL);
153 /* Safety measure */
154 if (boost_counter < 0)
156 boost_counter = 0;
161 #if NUM_CORES > 1
162 spinlock_unlock(&boostctrl_spin);
163 #endif
166 void cpu_idle_mode(bool on_off)
168 #if NUM_CORES > 1
169 spinlock_lock(&boostctrl_spin);
170 #endif
172 cpu_idle = on_off;
174 /* We need to adjust the frequency immediately if the CPU
175 isn't boosted */
176 if(boost_counter == 0)
178 if(cpu_idle)
179 set_cpu_frequency(CPUFREQ_DEFAULT);
180 else
181 set_cpu_frequency(CPUFREQ_NORMAL);
184 #if NUM_CORES > 1
185 spinlock_unlock(&boostctrl_spin);
186 #endif
188 #endif /* HAVE_ADJUSTABLE_CPU_FREQ */
191 #ifdef HAVE_FLASHED_ROCKBOX
192 static bool detect_flash_header(uint8_t *addr)
194 #ifndef BOOTLOADER
195 int oldmode = system_memory_guard(MEMGUARD_NONE);
196 #endif
197 struct flash_header hdr;
198 memcpy(&hdr, addr, sizeof(struct flash_header));
199 #ifndef BOOTLOADER
200 system_memory_guard(oldmode);
201 #endif
202 return hdr.magic == FLASH_MAGIC;
204 #endif
206 bool detect_flashed_romimage(void)
208 #ifdef HAVE_FLASHED_ROCKBOX
209 return detect_flash_header((uint8_t *)FLASH_ROMIMAGE_ENTRY);
210 #else
211 return false;
212 #endif /* HAVE_FLASHED_ROCKBOX */
215 bool detect_flashed_ramimage(void)
217 #ifdef HAVE_FLASHED_ROCKBOX
218 return detect_flash_header((uint8_t *)FLASH_RAMIMAGE_ENTRY);
219 #else
220 return false;
221 #endif /* HAVE_FLASHED_ROCKBOX */
224 bool detect_original_firmware(void)
226 return !(detect_flashed_ramimage() || detect_flashed_romimage());
229 #if defined(CPU_ARM)
231 static const char* const uiename[] = {
232 "Undefined instruction",
233 "Prefetch abort",
234 "Data abort",
235 "Divide by zero"
238 /* Unexpected Interrupt or Exception handler. Currently only deals with
239 exceptions, but will deal with interrupts later.
241 void UIE(unsigned int pc, unsigned int num) __attribute__((noreturn));
242 void UIE(unsigned int pc, unsigned int num)
244 char str[32];
246 lcd_clear_display();
247 #ifdef HAVE_LCD_BITMAP
248 lcd_setfont(FONT_SYSFIXED);
249 #endif
250 lcd_puts(0, 0, uiename[num]);
251 snprintf(str, sizeof(str), "at %08x" IF_COP(" (%d)"), pc
252 IF_COP(, CURRENT_CORE));
253 lcd_puts(0, 1, str);
254 lcd_update();
256 while (1)
258 /* TODO: perhaps add button handling in here when we get a polling
259 driver some day.
261 core_idle();
265 #ifndef STUB
266 /* Needs to be here or gcc won't find it */
267 void __div0(void) __attribute__((naked));
268 void __div0(void)
270 asm volatile (
271 "ldr r0, [sp] \r\n"
272 "mov r1, #3 \r\n"
273 "b UIE \r\n"
276 #endif
278 #endif /* CPU_ARM */