The power-saving SLEEP patch by Simon Elén.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@3259 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Björn Stenberg 2003-02-14 09:44:34 +00:00
parent 84706a4188
commit c4d8d970f6
15 changed files with 101 additions and 31 deletions

View file

@ -1376,3 +1376,8 @@ id: LANG_RECORDING_SIZE
desc: Display of recorded file size desc: Display of recorded file size
eng: "Size:" eng: "Size:"
new: new:
id: LANG_CPU_SLEEP
desc: in system_settings_menu()
eng: "Power Saving"
new:

View file

@ -103,12 +103,12 @@ void init(void)
font_init(); font_init();
show_logo(); show_logo();
set_irq_level(0);
#ifdef DEBUG #ifdef DEBUG
debug_init(); debug_init();
#else #else
serial_setup(); serial_setup();
#endif #endif
set_irq_level(0);
i2c_init(); i2c_init();

View file

@ -180,8 +180,7 @@ bool recording_screen(void)
while(!done) while(!done)
{ {
yield(); button = button_get_w_tmo(HZ / peak_meter_fps);
button = button_get(false);
switch(button) switch(button)
{ {
case BUTTON_OFF: case BUTTON_OFF:

View file

@ -21,6 +21,7 @@
#include <stdio.h> #include <stdio.h>
#include "config.h" #include "config.h"
#include "kernel.h" #include "kernel.h"
#include "thread.h"
#include "settings.h" #include "settings.h"
#include "disk.h" #include "disk.h"
#include "panic.h" #include "panic.h"
@ -102,7 +103,7 @@ offset abs
0x23 0x37 <rec. left gain (bit 0-3)> 0x23 0x37 <rec. left gain (bit 0-3)>
0x24 0x38 <rec. right gain (bit 0-3)> 0x24 0x38 <rec. right gain (bit 0-3)>
0x25 0x39 <disk poweroff flag (bit 0), MP3 buffer margin (bit 1-3), 0x25 0x39 <disk poweroff flag (bit 0), MP3 buffer margin (bit 1-3),
Trickle charge flag (bit 4)> Trickle charge flag (bit 4), CPU sleep flag (bit 5)>
0x26 0x40 <runtime low byte> 0x26 0x40 <runtime low byte>
0x27 0x41 <runtime high byte> 0x27 0x41 <runtime high byte>
0x28 0x42 <topruntime low byte> 0x28 0x42 <topruntime low byte>
@ -350,7 +351,8 @@ int settings_save( void )
config_block[0x25] = (unsigned char) config_block[0x25] = (unsigned char)
((global_settings.disk_poweroff & 1) | ((global_settings.disk_poweroff & 1) |
((global_settings.buffer_margin & 7) << 1) | ((global_settings.buffer_margin & 7) << 1) |
((global_settings.trickle_charge & 1) << 4)); ((global_settings.trickle_charge & 1) << 4) |
((global_settings.cpu_sleep & 1) << 5));
{ {
static long lasttime = 0; static long lasttime = 0;
@ -513,6 +515,8 @@ void settings_apply(void)
global_settings.lang_file); global_settings.lang_file);
lang_load(buf); lang_load(buf);
} }
cpu_sleep(global_settings.cpu_sleep);
} }
/* /*
@ -636,6 +640,7 @@ void settings_load(void)
global_settings.disk_poweroff = config_block[0x25] & 1; global_settings.disk_poweroff = config_block[0x25] & 1;
global_settings.buffer_margin = (config_block[0x25] >> 1) & 7; global_settings.buffer_margin = (config_block[0x25] >> 1) & 7;
global_settings.trickle_charge = (config_block[0x25] >> 4) & 1; global_settings.trickle_charge = (config_block[0x25] >> 4) & 1;
global_settings.cpu_sleep = (config_block[0x25] >> 5) & 1;
} }
if (config_block[0x27] != 0xff) if (config_block[0x27] != 0xff)
@ -881,6 +886,7 @@ void settings_reset(void) {
global_settings.lang_file[0] = 0; global_settings.lang_file[0] = 0;
global_settings.runtime = 0; global_settings.runtime = 0;
global_settings.topruntime = 0; global_settings.topruntime = 0;
global_settings.cpu_sleep = true;
} }

View file

@ -147,6 +147,8 @@ struct user_settings
int bidir_limit; /* bidir scroll length limit */ int bidir_limit; /* bidir scroll length limit */
int scroll_delay; /* delay (in 1/10s) before starting scroll */ int scroll_delay; /* delay (in 1/10s) before starting scroll */
int scroll_step; /* pixels to advance per update */ int scroll_step; /* pixels to advance per update */
bool cpu_sleep; /* Use sleep instruction when idle? */
}; };
/* prototypes */ /* prototypes */

View file

@ -27,6 +27,7 @@
#include "mpeg.h" #include "mpeg.h"
#include "button.h" #include "button.h"
#include "kernel.h" #include "kernel.h"
#include "thread.h"
#include "sprintf.h" #include "sprintf.h"
#include "settings.h" #include "settings.h"
#include "settings_menu.h" #include "settings_menu.h"
@ -539,6 +540,13 @@ static bool poweroff(void)
} }
#endif #endif
static bool cpu_sleep_set(void)
{
bool result = set_bool(str(LANG_CPU_SLEEP), &global_settings.cpu_sleep);
cpu_sleep(global_settings.cpu_sleep);
return result;
}
static bool buffer_margin(void) static bool buffer_margin(void)
{ {
return set_int(str(LANG_MP3BUFFER_MARGIN), "s", return set_int(str(LANG_MP3BUFFER_MARGIN), "s",
@ -731,6 +739,7 @@ static bool system_settings_menu(void)
#ifdef HAVE_ATA_POWER_OFF #ifdef HAVE_ATA_POWER_OFF
{ str(LANG_POWEROFF), poweroff }, { str(LANG_POWEROFF), poweroff },
#endif #endif
{ str(LANG_CPU_SLEEP), cpu_sleep_set },
#ifndef SIMULATOR #ifndef SIMULATOR
{ str(LANG_BATTERY_CAPACITY), battery_capacity }, { str(LANG_BATTERY_CAPACITY), battery_capacity },
#endif #endif

View file

@ -111,7 +111,8 @@ static int wait_for_bsy(void)
{ {
int timeout = current_tick + HZ*10; int timeout = current_tick + HZ*10;
while (TIME_BEFORE(current_tick, timeout) && (ATA_ALT_STATUS & STATUS_BSY)) while (TIME_BEFORE(current_tick, timeout) && (ATA_ALT_STATUS & STATUS_BSY))
yield(); sleep_thread();
wake_up_thread();
if (TIME_BEFORE(current_tick, timeout)) if (TIME_BEFORE(current_tick, timeout))
return 1; return 1;
@ -131,7 +132,8 @@ static int wait_for_rdy(void)
while (TIME_BEFORE(current_tick, timeout) && while (TIME_BEFORE(current_tick, timeout) &&
!(ATA_ALT_STATUS & STATUS_RDY)) !(ATA_ALT_STATUS & STATUS_RDY))
yield(); sleep_thread();
wake_up_thread();
if (TIME_BEFORE(current_tick, timeout)) if (TIME_BEFORE(current_tick, timeout))
return STATUS_RDY; return STATUS_RDY;

View file

@ -163,19 +163,8 @@ int button_get(bool block)
int button_get_w_tmo(int ticks) int button_get_w_tmo(int ticks)
{ {
struct event ev; struct event ev;
unsigned int timeout = current_tick + ticks; queue_wait_w_tmo(&button_queue, &ev, ticks);
return (ev.id != SYS_TIMEOUT)? ev.id: BUTTON_NONE;
while (TIME_BEFORE( current_tick, timeout ))
{
if(!queue_empty(&button_queue))
{
queue_wait(&button_queue, &ev);
return ev.id;
}
yield();
}
return BUTTON_NONE;
} }
#ifdef HAVE_RECORDER_KEYPAD #ifdef HAVE_RECORDER_KEYPAD

View file

@ -19,6 +19,7 @@
#include "lcd.h" #include "lcd.h"
#include "sh7034.h" #include "sh7034.h"
#include "kernel.h" #include "kernel.h"
#include "thread.h"
#include "debug.h" #include "debug.h"
#define PB13 0x2000 #define PB13 0x2000
@ -108,7 +109,8 @@ void i2c_ack(int bit)
SCL_INPUT; /* Set the clock to input */ SCL_INPUT; /* Set the clock to input */
while(!SCL) /* and wait for the MAS to release it */ while(!SCL) /* and wait for the MAS to release it */
yield(); sleep_thread();
wake_up_thread();
DELAY; DELAY;
SCL_OUTPUT; SCL_OUTPUT;
@ -130,7 +132,8 @@ int i2c_getack(void)
SDA_INPUT; /* And set to input */ SDA_INPUT; /* And set to input */
SCL_INPUT; /* Set the clock to input */ SCL_INPUT; /* Set the clock to input */
while(!SCL) /* and wait for the MAS to release it */ while(!SCL) /* and wait for the MAS to release it */
yield(); sleep_thread();
wake_up_thread();
if (SDA) if (SDA)
/* ack failed */ /* ack failed */

View file

@ -19,12 +19,17 @@
#ifndef THREAD_H #ifndef THREAD_H
#define THREAD_H #define THREAD_H
#include <stdbool.h>
#define MAXTHREADS 16 #define MAXTHREADS 16
#define DEFAULT_STACK_SIZE 0x400 /* Bytes */ #define DEFAULT_STACK_SIZE 0x400 /* Bytes */
int create_thread(void* function, void* stack, int stack_size, char *name); int create_thread(void* function, void* stack, int stack_size, char *name);
void switch_thread(void); void switch_thread(void);
void sleep_thread(void);
void wake_up_thread(void);
void init_threads(void); void init_threads(void);
int thread_stack_usage(int threadnum); int thread_stack_usage(int threadnum);
void cpu_sleep(bool enabled);
#endif #endif

View file

@ -59,13 +59,15 @@ void sleep(int ticks)
int timeout = current_tick + ticks + 1; int timeout = current_tick + ticks + 1;
while (TIME_BEFORE( current_tick, timeout )) { while (TIME_BEFORE( current_tick, timeout )) {
yield(); sleep_thread();
} }
wake_up_thread();
} }
void yield(void) void yield(void)
{ {
switch_thread(); switch_thread();
wake_up_thread();
} }
/**************************************************************************** /****************************************************************************
@ -96,8 +98,9 @@ void queue_wait(struct event_queue *q, struct event *ev)
{ {
while(q->read == q->write) while(q->read == q->write)
{ {
switch_thread(); sleep_thread();
} }
wake_up_thread();
*ev = q->events[(q->read++) & QUEUE_LENGTH_MASK]; *ev = q->events[(q->read++) & QUEUE_LENGTH_MASK];
} }
@ -108,8 +111,9 @@ void queue_wait_w_tmo(struct event_queue *q, struct event *ev, int ticks)
while(q->read == q->write && TIME_BEFORE( current_tick, timeout )) while(q->read == q->write && TIME_BEFORE( current_tick, timeout ))
{ {
switch_thread(); sleep_thread();
} }
wake_up_thread();
if(q->read != q->write) if(q->read != q->write)
{ {
@ -201,6 +205,7 @@ void IMIA0(void)
} }
current_tick++; current_tick++;
wake_up_thread();
TSR0 &= ~0x01; TSR0 &= ~0x01;
} }
@ -257,7 +262,8 @@ void mutex_lock(struct mutex *m)
{ {
/* Wait until the lock is open... */ /* Wait until the lock is open... */
while(m->locked) while(m->locked)
yield(); sleep_thread();
wake_up_thread();
/* ...and lock it */ /* ...and lock it */
m->locked = true; m->locked = true;

View file

@ -845,6 +845,7 @@ static void dma_tick(void)
{ {
saving = true; saving = true;
queue_post(&mpeg_queue, MPEG_SAVE_DATA, 0); queue_post(&mpeg_queue, MPEG_SAVE_DATA, 0);
wake_up_thread();
} }
} }
} }
@ -948,6 +949,7 @@ void DEI3(void)
} }
CHCR3 &= ~0x0002; /* Clear DMA interrupt */ CHCR3 &= ~0x0002; /* Clear DMA interrupt */
wake_up_thread();
} }
#ifdef HAVE_MAS3587F #ifdef HAVE_MAS3587F
@ -1791,9 +1793,10 @@ static void mpeg_thread(void)
} }
else else
{ {
/* This doesn't look neccessary...
yield(); yield();
if(!queue_empty(&mpeg_queue)) if(!queue_empty(&mpeg_queue))
{ {*/
queue_wait(&mpeg_queue, &ev); queue_wait(&mpeg_queue, &ev);
switch(ev.id) switch(ev.id)
{ {
@ -1897,7 +1900,7 @@ static void mpeg_thread(void)
init_playback_done = true; init_playback_done = true;
break; break;
} }
} /*}*/
} }
#endif #endif
} }
@ -1974,7 +1977,8 @@ void mpeg_init_recording(void)
queue_post(&mpeg_queue, MPEG_INIT_RECORDING, NULL); queue_post(&mpeg_queue, MPEG_INIT_RECORDING, NULL);
while(!init_recording_done) while(!init_recording_done)
yield(); sleep_thread();
wake_up_thread();
} }
void mpeg_init_playback(void) void mpeg_init_playback(void)
@ -1983,7 +1987,8 @@ void mpeg_init_playback(void)
queue_post(&mpeg_queue, MPEG_INIT_PLAYBACK, NULL); queue_post(&mpeg_queue, MPEG_INIT_PLAYBACK, NULL);
while(!init_playback_done) while(!init_playback_done)
yield(); sleep_thread();
wake_up_thread();
} }
static void init_recording(void) static void init_recording(void)

View file

@ -75,7 +75,6 @@ runtests() {
try mkfile /cpa.rock 0 try mkfile /cpa.rock 0
check check
try chkfile /cpa.rock try chkfile /cpa.rock
try chkfile /apa.rock
try chkfile /bpa.rock try chkfile /bpa.rock
LOOP=50 LOOP=50

View file

@ -16,8 +16,11 @@
* KIND, either express or implied. * KIND, either express or implied.
* *
****************************************************************************/ ****************************************************************************/
#include <stdbool.h>
#include "thread.h" #include "thread.h"
#include "panic.h" #include "panic.h"
#include "kernel.h"
#include "sh7034.h"
struct regs struct regs
{ {
@ -30,6 +33,8 @@ struct regs
}; };
int num_threads; int num_threads;
bool cpu_sleep_enabled;
static volatile int num_sleepers;
static int current_thread; static int current_thread;
static struct regs thread_contexts[MAXTHREADS] __attribute__ ((section(".idata"))); static struct regs thread_contexts[MAXTHREADS] __attribute__ ((section(".idata")));
char *thread_name[MAXTHREADS]; char *thread_name[MAXTHREADS];
@ -95,6 +100,18 @@ void switch_thread(void)
int next; int next;
unsigned int *stackptr; unsigned int *stackptr;
#ifdef SIMULATOR
/* Do nothing */
#else
while (cpu_sleep_enabled && num_sleepers == num_threads)
{
/* Enter sleep mode, woken up on interrupt */
SBYCR &= 0x7F;
asm volatile ("sleep");
}
#endif
next = current = current_thread; next = current = current_thread;
if (++next >= num_threads) if (++next >= num_threads)
next = 0; next = 0;
@ -108,6 +125,22 @@ void switch_thread(void)
panicf("Stkov %s", thread_name[next]); panicf("Stkov %s", thread_name[next]);
} }
void cpu_sleep(bool enabled)
{
cpu_sleep_enabled = enabled;
}
void sleep_thread(void)
{
++num_sleepers;
switch_thread();
}
void wake_up_thread(void)
{
num_sleepers = 0;
}
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
* Create thread. * Create thread.
* Return 0 if context area could be allocated, else -1. * Return 0 if context area could be allocated, else -1.
@ -144,6 +177,7 @@ int create_thread(void* function, void* stack, int stack_size, char *name)
regs->sr = 0; regs->sr = 0;
regs->pr = function; regs->pr = function;
} }
wake_up_thread();
return 0; return 0;
} }
@ -154,6 +188,7 @@ void init_threads(void)
thread_name[0] = main_thread_name; thread_name[0] = main_thread_name;
thread_stack[0] = stackbegin; thread_stack[0] = stackbegin;
thread_stack_size[0] = (int)stackend - (int)stackbegin; thread_stack_size[0] = (int)stackend - (int)stackbegin;
num_sleepers = 0;
} }
int thread_stack_usage(int threadnum) int thread_stack_usage(int threadnum)

View file

@ -221,3 +221,8 @@ void lcd_fillrect (int x, int y, int nx, int ny)
(void)ny; (void)ny;
} }
#endif #endif
void cpu_sleep(bool enabled)
{
(void)enabled;
}