📄 power.c
字号:
#include "u.h"#include "../port/lib.h"#include "mem.h"#include "dat.h"#include "fns.h"#include "io.h"#include "ureg.h"#include "pool.h"/* Power management for the bitsy */#define TODFREQ 1000000000LL/* saved state during power down. * it's only used up to 164/4. * it's only used by routines in l.s */ulong power_state[200/4];ulong resumeaddr[1];Rendez powerr;ulong powerflag = 0; /* set to start power-off sequence */extern void power_resume(void);extern int setpowerlabel(void);extern void _start(void);extern Uart sa1110uart[];GPIOregs savedgpioregs;Intrregs savedintrregs;#define R(p) ((Uartregs*)((p)->regs))uchar *savedtext;static voidcheckflash(void){ ulong *p; ulong s; s = 0; for (p = (ulong*)FLASHZERO; p < (ulong*)(FLASHZERO+8*1024*1024); p++) s += *p; iprint("flash checksum is 0x%lux\n", s);}static voidcheckktext(void){ ulong *p; ulong s; s = 0; for (p = (ulong*)_start; p < (ulong*)etext; p++){ if(*p == 0) iprint("0x%lux->0\n", p); if (((ulong)p & 0x1fff) == 0){ iprint("page 0x%lux checksum 0x%lux\n", (ulong)(p-1)&~0x1fff, s); s = 0; } s += *p; } iprint("page 0x%lux checksum 0x%lux\n", (ulong)(p-1)&~0x1fff, s);}static voidcheckpagetab(void){ extern ulong l1table; ulong *p; ulong s; s = 0; for (p = (ulong*)l1table; p < (ulong*)(l1table+16*1024); p++) s += *p; iprint("page table checksum is 0x%lux\n", s);}static voiddumpitall(void){ extern ulong l1table; iprint("intr: icip %lux iclr %lux iccr %lux icmr %lux\n", intrregs->icip, intrregs->iclr, intrregs->iccr, intrregs->icmr ); iprint("gpio: lvl %lux dir %lux, re %lux, fe %lux sts %lux alt %lux\n", gpioregs->level, gpioregs->direction, gpioregs->rising, gpioregs->falling, gpioregs->edgestatus, gpioregs->altfunc); iprint("uart1: %lux %lux %lux \nuart3: %lux %lux %lux\n", R(&sa1110uart[0])->ctl[0], R(&sa1110uart[0])->status[0], R(&sa1110uart[0])->status[1], R(&sa1110uart[1])->ctl[0], R(&sa1110uart[1])->status[0], R(&sa1110uart[1])->status[1]); iprint("tmr: osmr %lux %lux %lux %lux oscr %lux ossr %lux oier %lux\n", timerregs->osmr[0], timerregs->osmr[1], timerregs->osmr[2], timerregs->osmr[3], timerregs->oscr, timerregs->ossr, timerregs->oier); iprint("dram: mdcnfg %lux mdrefr %lux cas %lux %lux %lux %lux %lux %lux\n", memconfregs->mdcnfg, memconfregs->mdrefr, memconfregs->mdcas00, memconfregs->mdcas01,memconfregs->mdcas02, memconfregs->mdcas20, memconfregs->mdcas21,memconfregs->mdcas22); iprint("dram: mdcnfg msc %lux %lux %lux mecr %lux\n", memconfregs->msc0, memconfregs->msc1,memconfregs->msc2, memconfregs->mecr); iprint("mmu: CpControl %lux CpTTB %lux CpDAC %lux l1table 0x%lux\n", getcontrol(), getttb(), getdac(), l1table); iprint("powerregs: pmcr %lux pssr %lux pcfr %lux ppcr %lux pwer %lux pspr %lux pgsr %lux posr %lux\n", powerregs->pmcr, powerregs->pssr, powerregs->pcfr, powerregs->ppcr, powerregs->pwer, powerregs->pspr, powerregs->pgsr, powerregs->posr); checkpagetab(); checkflash(); checkktext(); iprint("\n\n");}static voidintrcpy(Intrregs *to, Intrregs *from){ to->iclr = from->iclr; to->iccr = from->iccr; to->icmr = from->icmr; // interrupts enabled}static voidgpiosave(GPIOregs *to, GPIOregs *from){ to->level = from->level; to->rising = from->rising; // gpio intrs enabled to->falling= from->falling; // gpio intrs enabled to->altfunc = from->altfunc; to->direction = from->direction;}static voidgpiorestore(GPIOregs *to, GPIOregs *from){ to->direction = from->direction; to->altfunc = from->altfunc; to->set = from->level & 0x0fffffff; to->clear = ~from->level & 0x0fffffff; to->rising = from->rising; // gpio intrs enabled to->falling= from->falling; // gpio intrs enabled}void (*restart)(void) = nil;static intbitno(ulong x){ int i; for(i = 0; i < 8*sizeof(x); i++) if((1<<i) & x) break; return i;}intpowerdown(void *){ return powerflag;}voiddeepsleep(void) { static int power_pl; ulong xsp, xlink;// ulong mecr; ulong clkd; vlong savedtod; extern void power_resume(void); power_pl = splhi(); xlink = getcallerpc(&xlink); /* Power down */ pcmciapower(0); irpower(0); audiopower(0); screenpower(0); µcpower(0); iprint("entering suspend mode, sp = 0x%lux, pc = 0x%lux, psw = 0x%ux\n", &xsp, xlink, power_pl);// dumpitall(); delay(1000); uartpower(0); rs232power(0); clockpower(0); gpiosave(&savedgpioregs, gpioregs); intrcpy(&savedintrregs, intrregs); cacheflush(); delay(50); if(setpowerlabel()){ /* return here with mmu back on */ trapresume(); gpiorestore(gpioregs, &savedgpioregs); delay(50); intrcpy(intrregs, &savedintrregs); if(intrregs->icip & (1<<IRQgpio0)){ // don't want to sleep now. clear on/off irq. gpioregs->edgestatus = (1<<IRQgpio0); intrregs->icip = (1<<IRQgpio0); } clkd = clockpower(1); gpclkregs->r0 = 1<<0; todset(savedtod + clkd * TODFREQ, 0LL, 0); resetsuspendtimer(); rs232power(1); uartpower(1); delay(100); xlink = getcallerpc(&xlink); iprint("\nresuming execution, sp = 0x%lux, pc = 0x%lux, psw = 0x%ux\n", &xsp, xlink, splhi());// dumpitall(); delay(1000);// irpower(1); audiopower(1); µcpower(1); screenpower(1); pcmciapower(1); splx(power_pl); return; } cacheflush(); delay(100); savedtod = todget(nil); power_down(); /* no return */}voidpowerkproc(void*){ ulong xlink, xlink1; for(;;){ while(powerflag == 0) sleep(&powerr, powerdown, 0); xlink = getcallerpc(&xlink);// iprint("call deepsleep, pc = 0x%lux, sp = 0x%lux\n", xlink, &xlink); deepsleep(); xlink1 = getcallerpc(&xlink1); delay(2000);// iprint("deepsleep returned, pc = 0x%lux, sp = 0x%lux\n", xlink1, &xlink); powerflag = 0; }}voidonoffintr(Ureg* , void*){ int i; /* Power down interrupt comes on power button release. * Act only after button has been released a full 100 ms */ if (powerflag) return; for (i = 0; i < 100; i++) { delay(1); if ((gpioregs->level & GPIO_PWR_ON_i) == 0) return; /* bounced */ } powerflag = 1; wakeup(&powerr);}static voidblanktimer(void){ drawactive(0);}static ulong suspendtime = 120 * HZ;static int lastsuspend;voidresetsuspendtimer(void){ suspendtime = 60 * HZ;}static voidsuspendtimer(void){ uvlong now; return; // does not work well. if (suspendtime > 0) suspendtime--; if (suspendtime == 0){ now = seconds(); if (now < lastsuspend + 10){ resetsuspendtimer(); return; } lastsuspend = seconds(); deepsleep(); lastsuspend = seconds(); return; }}voidpowerinit(void){ extern ulong power_magic; extern ulong power_code; extern ulong doze_code; ulong *p, *q, i; p = (ulong*)(((ulong)&power_magic + 0x1f) & ~0x1f); q = &power_code; for (i = 0; i < 8; i++) *p++ = *q++; p = (ulong*)(((ulong)doze + 0x3f) & ~0x1f); q = &doze_code; for (i = 0; i < 3; i++) *p++ = *q++; *resumeaddr = (ulong) power_resume; addclock0link(blanktimer, 1000/HZ); addclock0link(suspendtimer, 1000/HZ); intrenable(GPIOrising, bitno(GPIO_PWR_ON_i), onoffintr, nil, "on/off");}voididlehands(void){ char *msgb = "idlehands called with splhi\n"; char *msga = "doze returns with splhi\n"; if(!islo()){ uartputs(msga, strlen(msga)); spllo(); } doze(); if(!islo()){ uartputs(msgb, strlen(msgb)); spllo(); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -